diff --git a/.gitignore b/.gitignore index 9563893..b81f660 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ # gradle +remapped/ + .gradle/ build/ out/ diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..bd09074 --- /dev/null +++ b/build.gradle @@ -0,0 +1,27 @@ +plugins { + id "architectury-plugin" version "1.3.44" + id "forgified-fabric-loom" version "0.5.25" apply false +} + +architect { + minecraft = rootProject.minecraft_version +} + +subprojects { + apply plugin: "forgified-fabric-loom" + apply plugin: "architectury-plugin" + +} + +allprojects { + apply plugin: "java" + apply plugin: "architectury-plugin" + + archivesBaseName = rootProject.archives_base_name + version = rootProject.mod_version + group = rootProject.maven_group + + tasks.withType(JavaCompile) { + options.encoding = "UTF-8" + } +} \ No newline at end of file diff --git a/common/build.gradle b/common/build.gradle new file mode 100644 index 0000000..853c879 --- /dev/null +++ b/common/build.gradle @@ -0,0 +1,46 @@ +repositories { + maven { + url = "https://jitpack.io" + } +} + +dependencies { + minecraft "com.mojang:minecraft:${rootProject.architect.minecraft}" + mappings("net.fabricmc:yarn:${rootProject.yarn_mappings}:v2") + // We depend on fabric loader here to use the fabric @Environment annotations + // Do NOT use other classes from fabric loader + modCompile "net.fabricmc:fabric-loader:${rootProject.loader_version}" + + modCompile("me.shedaniel:architectury:${rootProject.architectury_version}") { + exclude(module: "fabric-api") + } + + // Password hashing + // Argon2 + implementation "de.mkammerer:argon2-jvm:${argon2_version}" + include "de.mkammerer:argon2-jvm:${argon2_version}" + + // BCrypt + implementation "at.favre.lib:bcrypt:${bcrypt_version}" + implementation "at.favre.lib:bytes:${bytes_version}" + include "at.favre.lib:bcrypt:${bcrypt_version}" + include "at.favre.lib:bytes:${bytes_version}" + + // Storage + // LevelDB database + implementation group: 'org.iq80.leveldb', name: 'leveldb', version: '0.12' + implementation group: 'org.iq80.leveldb', name: 'leveldb-api', version: '0.12' + include group: 'org.iq80.leveldb', name: 'leveldb', version: '0.12' + include group: 'org.iq80.leveldb', name: 'leveldb-api', version: '0.12' + + // MongoDB driver + implementation 'org.mongodb:mongodb-driver-sync:4.1.0' + include 'org.mongodb:mongodb-driver-sync:4.1.0' + + // JNA lib + include 'net.java.dev.jna:jna:5.5.0' +} + +architect { + common() +} \ No newline at end of file diff --git a/common/src/main/java/org/samo_lego/simpleauth/SimpleAuth.java b/common/src/main/java/org/samo_lego/simpleauth/SimpleAuth.java new file mode 100644 index 0000000..1cf60ca --- /dev/null +++ b/common/src/main/java/org/samo_lego/simpleauth/SimpleAuth.java @@ -0,0 +1,99 @@ +package org.samo_lego.simpleauth; + +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.server.MinecraftServer; +import org.samo_lego.simpleauth.storage.AuthConfig; +import org.samo_lego.simpleauth.storage.DBHelper; +import org.samo_lego.simpleauth.storage.PlayerCache; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Properties; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import static org.samo_lego.simpleauth.utils.SimpleLogger.logError; +import static org.samo_lego.simpleauth.utils.SimpleLogger.logInfo; + +public class SimpleAuth { + public static final String MOD_ID = "simpleauth"; + + + public static DBHelper DB = new DBHelper(); + + public static final ExecutorService THREADPOOL = Executors.newCachedThreadPool(); + + /** + * HashMap of players that have joined the server. + * It's cleared on server stop in order to save some interactions with database during runtime. + * Stores their data as {@link org.samo_lego.simpleauth.storage.PlayerCache PlayerCache} object. + */ + public static final HashMap playerCacheMap = new HashMap<>(); + + /** + * HashSet of player names that have Mojang accounts. + * If player is saved in here, they will be treated as online-mode ones. + */ + public static final HashSet mojangAccountNamesCache = new HashSet<>(); + + // Getting game directory + public static Path gameDirectory; + + // Server properties + public static final Properties serverProp = new Properties(); + + /** + * Config of the SimpleAuth mod. + */ + public static AuthConfig config; + + + public static void init(Path gameDir) { + gameDirectory = gameDir; + logInfo("SimpleAuth mod by samo_lego."); + // The support on discord was great! I really appreciate your help. + logInfo("This mod wouldn't exist without the awesome Fabric Community. TYSM guys!"); + + try { + serverProp.load(new FileReader(gameDirectory + "/server.properties")); + } catch (IOException e) { + logError("Error while reading server properties: " + e.getMessage()); + } + + // Creating data directory (database and config files are stored there) + File file = new File(gameDirectory + "/mods/SimpleAuth/leveldbStore"); + if (!file.exists() && !file.mkdirs()) + throw new RuntimeException("[SimpleAuth] Error creating directory!"); + // Loading config + config = AuthConfig.load(new File(gameDirectory + "/mods/SimpleAuth/config.json")); + // Connecting to db + DB.openConnection(); + } + + /** + * Called on server stop. + */ + public static void stop() { + logInfo("Shutting down SimpleAuth."); + DB.saveAll(playerCacheMap); + + // Closing threads + try { + THREADPOOL.shutdownNow(); + if (!THREADPOOL.awaitTermination(500, TimeUnit.MILLISECONDS)) { + Thread.currentThread().interrupt(); + } + } catch (InterruptedException e) { + logError(e.getMessage()); + THREADPOOL.shutdownNow(); + } + + // Closing DB connection + DB.close(); + } +} diff --git a/forge/build.gradle b/forge/build.gradle new file mode 100644 index 0000000..7eb945b --- /dev/null +++ b/forge/build.gradle @@ -0,0 +1,54 @@ +plugins { + id "com.github.johnrengelman.shadow" version "5.0.0" +} + +configurations { + shadow +} + +architectury { + platformSetupLoomIde() +} + +loom { + // Enable this for yarn to work + //useFabricMixin = true + mixinConfigs = ["simpleauth.mixins.json"] +} + +dependencies { + minecraft("com.mojang:minecraft:${rootProject.architect.minecraft}") + mappings("net.fabricmc:yarn:${rootProject.yarn_mappings}:v2") + forge("net.minecraftforge:forge:${rootProject.architect.minecraft}-${rootProject.forge_version}") + + compileOnly(project(path: ":common")) { + transitive = false + } + runtimeOnly(project(path: ":common", configuration: "transformForgeFakeMod")) { + transitive = false + } + shadow(project(path: ":common", configuration: "transformForge")) { + transitive = false + } +} + +shadowJar { + exclude "fabric.mod.json" + + configurations = [project.configurations.shadow] + classifier "shadow" +} + +remapJar { + dependsOn(shadowJar) + input.set(shadowJar.archivePath) + archiveClassifier = "forge" +} + +jar { + manifest { + attributes([ + "MixinConfigs": "simpleauth.mixins.json", + ]) + } +} \ No newline at end of file diff --git a/forge/src/main/java/org/samo_lego/simpleauth/SimpleAuthForge.java b/forge/src/main/java/org/samo_lego/simpleauth/SimpleAuthForge.java new file mode 100644 index 0000000..e215f75 --- /dev/null +++ b/forge/src/main/java/org/samo_lego/simpleauth/SimpleAuthForge.java @@ -0,0 +1,41 @@ +package org.samo_lego.simpleauth; + +import com.mojang.brigadier.CommandDispatcher; +import me.shedaniel.architectury.platform.forge.EventBuses; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.server.FMLServerStoppedEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.fml.loading.FMLPaths; +import org.samo_lego.simpleauth.commands.*; + +@Mod(SimpleAuth.MOD_ID) +public class SimpleAuthForge { + public SimpleAuthForge() { + // Submit our event bus to let architectury register our content on the right time + EventBuses.registerModEventBus(SimpleAuth.MOD_ID, FMLJavaModLoadingContext.get().getModEventBus()); + SimpleAuth.init(FMLPaths.GAMEDIR.get()); + } + + // Registering the commands + @SubscribeEvent + public void registerCommands(RegisterCommandsEvent event) { + CommandDispatcher dispatcher = event.getDispatcher(); + + RegisterCommand.registerCommand(dispatcher); + LoginCommand.registerCommand(dispatcher); + LogoutCommand.registerCommand(dispatcher); + AccountCommand.registerCommand(dispatcher); + AuthCommand.registerCommand(dispatcher); + } + + /** + * Called on server stop. + */ + @SubscribeEvent + public void onStopServer(FMLServerStoppedEvent event) { + SimpleAuth.stop(); + } +} diff --git a/forge/src/main/resources/META-INF/mods.toml b/forge/src/main/resources/META-INF/mods.toml new file mode 100644 index 0000000..edf0f06 --- /dev/null +++ b/forge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,45 @@ +modLoader="javafml" #mandatory +# A version range to match for said mod loader - for regular FML @Mod it will be the forge version +loaderVersion="[34,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. + +license="MIT" + +# A URL to refer people to when problems occur with this mod +issueTrackerURL="https://github.com/samolego/SimpleAuth/issues/" + +# A list of mods - how many allowed here is determined by the individual mod loader +[[mods]] #mandatory + +# The modid of the mod +modId="simpleauth" + +version="${file.jarVersion}" + + # A display name for the mod +displayName="Simple Auth" + +# A URL for the "homepage" for this mod, displayed in the mod UI +displayURL="https://samolego.github.io/" + +# A text field displayed in the mod UI +credits="Fabric community" + +# A text field displayed in the mod UI +authors="samo_lego" + +description=''' +A mod that tries to keep authentication for players simple via commands. +''' + +# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. +[[dependencies.simpleauth]] #optional + # the modid of the dependency + modId="forge" #mandatory + # Does this dependency have to exist - if not, ordering below must be specified + mandatory=true #mandatory + # The version range of the dependency + versionRange="[32,)" #mandatory + # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory + ordering="NONE" + # Side this dependency is applied on - BOTH, CLIENT or SERVER + side="SERVER" \ No newline at end of file diff --git a/forge/src/main/resources/pack.mcmeta b/forge/src/main/resources/pack.mcmeta new file mode 100644 index 0000000..06ca035 --- /dev/null +++ b/forge/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "Example Mod", + "pack_format": 6 + } +}