diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ac07fef0..60a4bcae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,7 +24,7 @@ jobs: uses: actions/setup-java@v4 with: java-version: ${{ matrix.java }} - distribution: 'microsoft' + distribution: 'temurin' - name: make gradle wrapper executable run: chmod +x ./gradlew - uses: actions/cache@v4 @@ -36,10 +36,10 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - name: build - run: ./gradlew remapJar + run: ./gradlew build - name: capture build artifacts if: ${{ matrix.java == '21' }} # Only upload artifacts built from latest java uses: actions/upload-artifact@v4 with: name: Artifacts - path: build/libs/ + path: build/artifacts/ diff --git a/.gitignore b/.gitignore index c476faf2..4ba18e75 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ hs_err_*.log replay_*.log *.hprof *.jfr +runs diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 00056ddf..00000000 --- a/build.gradle +++ /dev/null @@ -1,135 +0,0 @@ -import com.modrinth.minotaur.dependencies.ModDependency -plugins { - id 'fabric-loom' version '1.9-SNAPSHOT' - id 'maven-publish' - id "com.modrinth.minotaur" version "2.+" -} - -version = "${project.mod_version}+${project.minecraft_version}" -group = project.maven_group - -base { - archivesName = project.archives_base_name -} - -repositories { - mavenLocal() - - maven { - name = 'ParchmentMC' - url = 'https://maven.parchmentmc.org' - } - - maven { url 'https://maven.nucleoid.xyz' } - - maven { - name = "TerraformersMC" - url = "https://maven.terraformersmc.com/" - } - maven { - name = "Ladysnake Libs" - url = 'https://maven.ladysnake.org/releases' - } -} - -loom { - accessWidenerPath = file("src/main/resources/solstice.accesswidener") -} - -dependencies { - // To change the versions see the gradle.properties file - minecraft "com.mojang:minecraft:${project.minecraft_version}" - - mappings loom.layered() { - officialMojangMappings() - parchment("org.parchmentmc.data:parchment-${project.minecraft_version}:${project.parchment_mappings}@zip") - } - - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - - include implementation("org.spongepowered:configurate-core:${project.configurate_version}") - include implementation("org.spongepowered:configurate-hocon:${project.configurate_version}") - include implementation("org.spongepowered:configurate-gson:${project.configurate_version}") - include "com.typesafe:config:1.4.3" - include "io.leangen.geantyref:geantyref:1.3.16" - - include modImplementation("me.lucko:fabric-permissions-api:${project.permissions_api_version}") - - include modImplementation("eu.pb4:placeholder-api:${project.placeholderapi_version}") - include modImplementation("eu.pb4:sgui:${project.sgui_version}") - - modCompileOnly "dev.emi:trinkets:${project.trinkets_version}" - modRuntimeOnly "dev.emi:trinkets:${project.trinkets_version}" - - modCompileOnly "net.luckperms:api:5.4" - modRuntimeOnly "net.luckperms:api:5.4" -} - -processResources { - inputs.property "version", project.version - - filesMatching("fabric.mod.json") { - expand "version": project.version - } -} - -tasks.withType(JavaCompile).configureEach { - it.options.release = 21 -} - -java { - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. - withSourcesJar() - - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 -} - -jar { - from("LICENSE") { - rename { "${it}_${project.base.archivesName.get()}"} - } -} - -modrinth { - token = System.getenv("MODRINTH_TOKEN") - projectId = 'uIvrDZas' - uploadFile = remapJar - gameVersions = [project.minecraft_version] - loaders = ['fabric'] - dependencies = [ - new ModDependency('P7dR8mSH', 'required') // Fabric API - ] -} - -// configure the maven publication -publishing { - publications { - create("mavenJava", MavenPublication) { - artifactId = project.archives_base_name - from components.java - } - } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. - - - maven { - name = "AlexDevsRepo" - url = "https://maven.alexdevs.me/releases" - credentials { - username = System.getenv("MAVEN_USERNAME") - password = System.getenv("MAVEN_PASSWORD") - } - } - } -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 00000000..3a2fef1f --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + id("fabric-loom") version "1.8-SNAPSHOT" apply false + id("net.neoforged.moddev") version "2.0.88" apply false + id("com.gradleup.shadow") version "9.0.0-beta15" apply false +} + +tasks.register("build") { + group = "all" + + dependsOn(project(":fabric").tasks.named("build")) + dependsOn(project(":neoforge").tasks.named("build")) +} diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 00000000..876c922b --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + `kotlin-dsl` +} + +repositories { + mavenCentral() +} diff --git a/buildSrc/src/main/kotlin/multiloader-common.gradle.kts b/buildSrc/src/main/kotlin/multiloader-common.gradle.kts new file mode 100644 index 00000000..7def4b81 --- /dev/null +++ b/buildSrc/src/main/kotlin/multiloader-common.gradle.kts @@ -0,0 +1,103 @@ +plugins { + id("java-library") + id("maven-publish") +} + +base { + archivesName = "${"mod_id"()}-${project.name}-${"minecraft_version"()}" +} + +java { + toolchain.languageVersion = JavaLanguageVersion.of("java_version"()) + withSourcesJar() + withJavadocJar() +} + +repositories { + mavenCentral() + + maven("https://maven.fabricmc.net/") + maven("https://maven.parchmentmc.org/") + maven("https://maven.neoforged.net/releases") + maven("https://maven.blamejared.com") + maven("https://mvn.devos.one/snapshots") + maven("https://maven.ladysnake.org/releases") + maven("https://maven.terraformersmc.com/") + maven("https://maven.nucleoid.xyz") + maven("https://maven.alexdevs.me/releases") + maven("https://maven.stardustmodding.org/releases") +} + +tasks.named("sourcesJar") { + from(rootProject.file("LICENSE")) { + rename { "${it}_${"mod_id"()}" } + } +} + +tasks.named("jar") { + from(rootProject.file("LICENSE")) { + rename { "${it}_${"mod_id"()}" } + } + + manifest { + attributes( + mapOf( + "Specification-Title" to "mod_name"(), + "Specification-Vendor" to "mod_authors"(), + "Specification-Version" to "mod_version"(), + "Implementation-Title" to project.name, + "Implementation-Version" to "mod_version"(), + "Implementation-Vendor" to "mod_authors"(), + "Built-On-Minecraft" to "minecraft_version"() + ) + ) + } +} + +tasks.processResources { + var expandProps = mapOf( + "mod_version" to "mod_version"(), + "mod_group_id" to "mod_group_id"(), + "minecraft_version" to "minecraft_version"(), + "minecraft_version_range" to "minecraft_version_range"(), + "fabric_version" to "fabric_version"(), + "fabric_loader_version" to "fabric_loader_version"(), + "mod_name" to "mod_name"(), + "mod_authors" to "mod_authors"(), + "mod_id" to "mod_id"(), + "mod_license" to "mod_license"(), + "mod_description" to "mod_description"(), + "neo_version" to "neo_version"(), + "neo_version_range" to "neo_version_range"(), + "neo_loader_version_range" to "neo_loader_version_range"(), + "mod_credits" to "mod_credits"(), + "java_version" to "java_version"() + ) + + filesMatching( + listOf( + "pack.mcmeta", "fabric.mod.json", "META-INF/mods.toml", "META-INF/neoforge.mods.toml", "*.mixins.json" + ) + ) { + expand(expandProps) + } + + inputs.properties(expandProps) +} + +publishing { + publications { + register("mavenJava") { + artifactId = base.archivesName.get() + from(components["java"]) + } + } + + repositories { + maven { + mavenLocal() + } + } +} + +operator fun String.invoke(): String = rootProject.ext[this] as? String ?: error("No property \"$this\"") diff --git a/buildSrc/src/main/kotlin/multiloader-loader.gradle.kts b/buildSrc/src/main/kotlin/multiloader-loader.gradle.kts new file mode 100644 index 00000000..417adad0 --- /dev/null +++ b/buildSrc/src/main/kotlin/multiloader-loader.gradle.kts @@ -0,0 +1,9 @@ +plugins { + id("multiloader-common") +} + +dependencies { + compileOnly(project(":common")) +} + +operator fun String.invoke(): String = rootProject.ext[this] as? String ?: error("No property \"$this\"") diff --git a/common/build.gradle.kts b/common/build.gradle.kts new file mode 100644 index 00000000..ba60c20f --- /dev/null +++ b/common/build.gradle.kts @@ -0,0 +1,37 @@ +plugins { + id("multiloader-common") + id("net.neoforged.moddev") +} + +neoForge { + neoFormVersion = "neoform_version"() + + val at = file("src/main/resources/META-INF/accesstransformer.cfg") + + if (at.exists()) { + accessTransformers.from(at.absolutePath) + } + + parchment { + minecraftVersion = "parchment_minecraft"() + mappingsVersion = "parchment_version"() + } +} + +dependencies { + compileOnly("org.ow2.asm:asm-tree:9.8") + compileOnly("org.spongepowered:mixin:0.8.5") + compileOnly("io.github.llamalad7:mixinextras-common:0.3.5") + annotationProcessor("io.github.llamalad7:mixinextras-common:0.3.5") + + compileOnly("org.spongepowered:configurate-core:${"configurate_version"()}") + compileOnly("org.spongepowered:configurate-hocon:${"configurate_version"()}") + compileOnly("org.spongepowered:configurate-gson:${"configurate_version"()}") + compileOnly("com.typesafe:config:1.4.3") + compileOnly("io.leangen.geantyref:geantyref:1.3.16") + compileOnly("eu.pb4:placeholderapi:${"placeholderapi_nf_version"()}") + compileOnly("eu.pb4:sgui-neoforge:${"sgui_version"()}") + compileOnly("net.luckperms:api:5.4") +} + +operator fun String.invoke(): String = rootProject.ext[this] as? String ?: error("No property \"$this\"") diff --git a/common/src/main/java/me/alexdevs/solstice/Paths.java b/common/src/main/java/me/alexdevs/solstice/Paths.java new file mode 100644 index 00000000..b3f105ee --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/Paths.java @@ -0,0 +1,9 @@ +package me.alexdevs.solstice; + +import me.alexdevs.solstice.api.platform.PlatformHelper; + +import java.nio.file.Path; + +public class Paths { + public static final Path configDirectory = PlatformHelper.get().getConfigDir().resolve(Solstice.MOD_ID); +} diff --git a/src/main/java/me/alexdevs/solstice/Solstice.java b/common/src/main/java/me/alexdevs/solstice/Solstice.java similarity index 73% rename from src/main/java/me/alexdevs/solstice/Solstice.java rename to common/src/main/java/me/alexdevs/solstice/Solstice.java index 5cc90c3b..e9117f6d 100644 --- a/src/main/java/me/alexdevs/solstice/Solstice.java +++ b/common/src/main/java/me/alexdevs/solstice/Solstice.java @@ -3,16 +3,15 @@ import me.alexdevs.solstice.api.data.HoconDataManager; import me.alexdevs.solstice.api.events.SolsticeEvents; import me.alexdevs.solstice.api.events.WorldSaveCallback; +import me.alexdevs.solstice.api.events.proxy.ProxyServerLifecycleEvents; +import me.alexdevs.solstice.api.events.proxy.ProxyServerTickEvents; +import me.alexdevs.solstice.api.platform.PlatformHelper; import me.alexdevs.solstice.core.*; import me.alexdevs.solstice.data.PlayerDataManager; import me.alexdevs.solstice.data.ServerData; import me.alexdevs.solstice.integrations.ConnectorIntegration; import me.alexdevs.solstice.integrations.LuckPermsIntegration; import me.alexdevs.solstice.locale.LocaleManager; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; -import net.fabricmc.loader.api.FabricLoader; import net.minecraft.network.chat.Component; import net.minecraft.server.MinecraftServer; import net.minecraft.world.level.storage.LevelResource; @@ -22,45 +21,35 @@ import java.util.concurrent.ConcurrentLinkedQueue; - -public class Solstice implements ModInitializer { +public class Solstice { public static final String MOD_ID = "solstice"; public static final Logger LOGGER = LoggerFactory.getLogger(Solstice.class); - public static final HoconDataManager configManager = new HoconDataManager(Paths.configDirectory.resolve("config.conf")); + public static final HoconDataManager configManager = new HoconDataManager(Paths.configDirectory.resolve( + "config.conf")); + public static final LocaleManager localeManager = new LocaleManager(Paths.configDirectory.resolve("locale.json")); public static final ServerData serverData = new ServerData(); public static final PlayerDataManager playerData = new PlayerDataManager(); - public static final Modules modules = new Modules(); + public static Modules modules = new Modules(); private static final ConcurrentLinkedQueue nextTickRunnables = new ConcurrentLinkedQueue<>(); public static MinecraftServer server; public static Scheduler scheduler = new Scheduler(1, nextTickRunnables); - public static final CooldownManager cooldown = new CooldownManager(); + public static CooldownManager cooldown = new CooldownManager(); public static final WarmUpManager warmUp = new WarmUpManager(); private static Solstice INSTANCE; - private static final UserCache userCache = new UserCache(FabricLoader.getInstance().getGameDir().resolve("usercache.json").toFile()); - public Solstice() { - INSTANCE = this; - } + private static final UserCache userCache = new UserCache(PlatformHelper.get() + .getGameDir() + .resolve("usercache.json") + .toFile()); - public static Solstice getInstance() { - return INSTANCE; - } - - public static void nextTick(Runnable runnable) { - nextTickRunnables.add(runnable); - } - - public static UserCache getUserCache() { - return userCache; - } + public void init() { + INSTANCE = this; - @Override - public void onInitialize() { - var modMeta = FabricLoader.getInstance().getModContainer(MOD_ID).get().getMetadata(); - LOGGER.info("Initializing Solstice v{}...", modMeta.getVersion()); + LOGGER.info("Initializing Solstice v{}...", PlatformHelper.get().getModVersion()); + PlatformHelper.get().init(); ConnectorIntegration.register(); LuckPermsIntegration.register(); @@ -85,30 +74,47 @@ public void onInitialize() { LOGGER.error("Error while loading Solstice locale!", e); } - ServerLifecycleEvents.SERVER_STARTING.register(server -> { + ProxyServerLifecycleEvents.SERVER_STARTING.register(server -> { Solstice.server = server; + var path = server.getWorldPath(LevelResource.ROOT).resolve("data").resolve(MOD_ID); + if (!path.toFile().exists()) { path.toFile().mkdirs(); } + serverData.setDataPath(path.resolve("server.json")); playerData.setDataPath(path.resolve("players")); - serverData.loadData(false); }); - ServerLifecycleEvents.SERVER_STARTED.register(server -> SolsticeEvents.READY.invoker().onReady(INSTANCE, server)); - ServerLifecycleEvents.SERVER_STOPPED.register(server -> scheduler.shutdownNow()); + + ProxyServerLifecycleEvents.SERVER_STARTED.register(server -> SolsticeEvents.READY.invoker() + .onReady(INSTANCE, server)); + ProxyServerLifecycleEvents.SERVER_STOPPED.register(server -> scheduler.shutdownNow()); + WorldSaveCallback.EVENT.register((server1, suppressLogs, flush, force) -> { serverData.save(); playerData.saveAll(); }); - ServerTickEvents.START_SERVER_TICK.register(server -> { + ProxyServerTickEvents.START_SERVER_TICK.register(server -> { nextTickRunnables.forEach(Runnable::run); nextTickRunnables.clear(); }); } + public static Solstice getInstance() { + return INSTANCE; + } + + public static void nextTick(Runnable runnable) { + nextTickRunnables.add(runnable); + } + + public static UserCache getUserCache() { + return userCache; + } + public void broadcast(Component text) { server.getPlayerList().broadcastSystemMessage(text, false); } diff --git a/src/main/java/me/alexdevs/solstice/api/PlayerMail.java b/common/src/main/java/me/alexdevs/solstice/api/PlayerMail.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/PlayerMail.java rename to common/src/main/java/me/alexdevs/solstice/api/PlayerMail.java diff --git a/src/main/java/me/alexdevs/solstice/api/Raycast.java b/common/src/main/java/me/alexdevs/solstice/api/Raycast.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/Raycast.java rename to common/src/main/java/me/alexdevs/solstice/api/Raycast.java diff --git a/src/main/java/me/alexdevs/solstice/api/ServerLocation.java b/common/src/main/java/me/alexdevs/solstice/api/ServerLocation.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/ServerLocation.java rename to common/src/main/java/me/alexdevs/solstice/api/ServerLocation.java diff --git a/src/main/java/me/alexdevs/solstice/api/color/Gradient.java b/common/src/main/java/me/alexdevs/solstice/api/color/Gradient.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/color/Gradient.java rename to common/src/main/java/me/alexdevs/solstice/api/color/Gradient.java diff --git a/src/main/java/me/alexdevs/solstice/api/color/RGBColor.java b/common/src/main/java/me/alexdevs/solstice/api/color/RGBColor.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/color/RGBColor.java rename to common/src/main/java/me/alexdevs/solstice/api/color/RGBColor.java diff --git a/src/main/java/me/alexdevs/solstice/api/command/Flags.java b/common/src/main/java/me/alexdevs/solstice/api/command/Flags.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/command/Flags.java rename to common/src/main/java/me/alexdevs/solstice/api/command/Flags.java diff --git a/src/main/java/me/alexdevs/solstice/api/command/LocalGameProfile.java b/common/src/main/java/me/alexdevs/solstice/api/command/LocalGameProfile.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/command/LocalGameProfile.java rename to common/src/main/java/me/alexdevs/solstice/api/command/LocalGameProfile.java diff --git a/src/main/java/me/alexdevs/solstice/api/command/TimeSpan.java b/common/src/main/java/me/alexdevs/solstice/api/command/TimeSpan.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/command/TimeSpan.java rename to common/src/main/java/me/alexdevs/solstice/api/command/TimeSpan.java diff --git a/src/main/java/me/alexdevs/solstice/api/command/flags/ArgumentFlag.java b/common/src/main/java/me/alexdevs/solstice/api/command/flags/ArgumentFlag.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/command/flags/ArgumentFlag.java rename to common/src/main/java/me/alexdevs/solstice/api/command/flags/ArgumentFlag.java diff --git a/src/main/java/me/alexdevs/solstice/api/command/flags/DoubleFlag.java b/common/src/main/java/me/alexdevs/solstice/api/command/flags/DoubleFlag.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/command/flags/DoubleFlag.java rename to common/src/main/java/me/alexdevs/solstice/api/command/flags/DoubleFlag.java diff --git a/src/main/java/me/alexdevs/solstice/api/command/flags/Flag.java b/common/src/main/java/me/alexdevs/solstice/api/command/flags/Flag.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/command/flags/Flag.java rename to common/src/main/java/me/alexdevs/solstice/api/command/flags/Flag.java diff --git a/src/main/java/me/alexdevs/solstice/api/command/flags/FloatFlag.java b/common/src/main/java/me/alexdevs/solstice/api/command/flags/FloatFlag.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/command/flags/FloatFlag.java rename to common/src/main/java/me/alexdevs/solstice/api/command/flags/FloatFlag.java diff --git a/src/main/java/me/alexdevs/solstice/api/command/flags/StringFlag.java b/common/src/main/java/me/alexdevs/solstice/api/command/flags/StringFlag.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/command/flags/StringFlag.java rename to common/src/main/java/me/alexdevs/solstice/api/command/flags/StringFlag.java diff --git a/src/main/java/me/alexdevs/solstice/api/data/GsonDataManager.java b/common/src/main/java/me/alexdevs/solstice/api/data/GsonDataManager.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/data/GsonDataManager.java rename to common/src/main/java/me/alexdevs/solstice/api/data/GsonDataManager.java diff --git a/src/main/java/me/alexdevs/solstice/api/data/HoconDataManager.java b/common/src/main/java/me/alexdevs/solstice/api/data/HoconDataManager.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/data/HoconDataManager.java rename to common/src/main/java/me/alexdevs/solstice/api/data/HoconDataManager.java diff --git a/src/main/java/me/alexdevs/solstice/api/data/serializers/DateSerializer.java b/common/src/main/java/me/alexdevs/solstice/api/data/serializers/DateSerializer.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/data/serializers/DateSerializer.java rename to common/src/main/java/me/alexdevs/solstice/api/data/serializers/DateSerializer.java diff --git a/src/main/java/me/alexdevs/solstice/api/events/CommandEvents.java b/common/src/main/java/me/alexdevs/solstice/api/events/CommandEvents.java similarity index 64% rename from src/main/java/me/alexdevs/solstice/api/events/CommandEvents.java rename to common/src/main/java/me/alexdevs/solstice/api/events/CommandEvents.java index 39ad20e2..3747b4fd 100644 --- a/src/main/java/me/alexdevs/solstice/api/events/CommandEvents.java +++ b/common/src/main/java/me/alexdevs/solstice/api/events/CommandEvents.java @@ -1,25 +1,26 @@ package me.alexdevs.solstice.api.events; -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; import net.minecraft.commands.CommandSourceStack; public class CommandEvents { - public static final Event ALLOW_COMMAND = EventFactory.createArrayBacked(AllowCommand.class, callbacks -> - (source, command) -> { + public static final Event ALLOW_COMMAND = EventFactory.createArrayBacked( + AllowCommand.class, callbacks -> (source, command) -> { for (var callback : callbacks) { - if(!callback.allowCommand(source, command)) - return false; + if (!callback.allowCommand(source, command)) return false; } return true; - }); + } + ); - public static final Event COMMAND = EventFactory.createArrayBacked(Command.class, callbacks -> - (player, command) -> { + public static final Event COMMAND = EventFactory.createArrayBacked( + Command.class, callbacks -> (player, command) -> { for (var callback : callbacks) { callback.onCommand(player, command); } - }); + } + ); @FunctionalInterface public interface AllowCommand { diff --git a/src/main/java/me/alexdevs/solstice/api/events/PlayerActivityEvents.java b/common/src/main/java/me/alexdevs/solstice/api/events/PlayerActivityEvents.java similarity index 88% rename from src/main/java/me/alexdevs/solstice/api/events/PlayerActivityEvents.java rename to common/src/main/java/me/alexdevs/solstice/api/events/PlayerActivityEvents.java index f5a45ffc..7276935c 100644 --- a/src/main/java/me/alexdevs/solstice/api/events/PlayerActivityEvents.java +++ b/common/src/main/java/me/alexdevs/solstice/api/events/PlayerActivityEvents.java @@ -1,8 +1,8 @@ package me.alexdevs.solstice.api.events; +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; import me.alexdevs.solstice.modules.afk.AfkModule; -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; import net.minecraft.server.level.ServerPlayer; public final class PlayerActivityEvents { diff --git a/src/main/java/me/alexdevs/solstice/api/events/PlayerConnectionEvents.java b/common/src/main/java/me/alexdevs/solstice/api/events/PlayerConnectionEvents.java similarity index 90% rename from src/main/java/me/alexdevs/solstice/api/events/PlayerConnectionEvents.java rename to common/src/main/java/me/alexdevs/solstice/api/events/PlayerConnectionEvents.java index d232d3d7..2be06346 100644 --- a/src/main/java/me/alexdevs/solstice/api/events/PlayerConnectionEvents.java +++ b/common/src/main/java/me/alexdevs/solstice/api/events/PlayerConnectionEvents.java @@ -1,8 +1,8 @@ package me.alexdevs.solstice.api.events; import com.mojang.authlib.GameProfile; -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; public class PlayerConnectionEvents { public static final Event WHITELIST_BYPASS = EventFactory.createArrayBacked(WhitelistBypass.class, callbacks -> diff --git a/src/main/java/me/alexdevs/solstice/api/events/PlayerTeleportCallback.java b/common/src/main/java/me/alexdevs/solstice/api/events/PlayerTeleportCallback.java similarity index 84% rename from src/main/java/me/alexdevs/solstice/api/events/PlayerTeleportCallback.java rename to common/src/main/java/me/alexdevs/solstice/api/events/PlayerTeleportCallback.java index 9254304a..28611ddd 100644 --- a/src/main/java/me/alexdevs/solstice/api/events/PlayerTeleportCallback.java +++ b/common/src/main/java/me/alexdevs/solstice/api/events/PlayerTeleportCallback.java @@ -1,8 +1,8 @@ package me.alexdevs.solstice.api.events; import me.alexdevs.solstice.api.ServerLocation; -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; import net.minecraft.server.level.ServerPlayer; public interface PlayerTeleportCallback { diff --git a/src/main/java/me/alexdevs/solstice/api/events/RestartEvents.java b/common/src/main/java/me/alexdevs/solstice/api/events/RestartEvents.java similarity index 89% rename from src/main/java/me/alexdevs/solstice/api/events/RestartEvents.java rename to common/src/main/java/me/alexdevs/solstice/api/events/RestartEvents.java index 6d5a44be..a7061cca 100644 --- a/src/main/java/me/alexdevs/solstice/api/events/RestartEvents.java +++ b/common/src/main/java/me/alexdevs/solstice/api/events/RestartEvents.java @@ -1,8 +1,8 @@ package me.alexdevs.solstice.api.events; +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; import me.alexdevs.solstice.modules.timeBar.TimeBar; -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; public class RestartEvents { public static final Event SCHEDULED = EventFactory.createArrayBacked(Schedule.class, callbacks -> diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/SolsticeEvents.java b/common/src/main/java/me/alexdevs/solstice/api/events/SolsticeEvents.java new file mode 100644 index 00000000..c5abfd3c --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/SolsticeEvents.java @@ -0,0 +1,83 @@ +package me.alexdevs.solstice.api.events; + +import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; + +public final class SolsticeEvents { + public static final Event READY = EventFactory.createArrayBacked( + Ready.class, callbacks -> + (instance, server) -> { + for (Ready callback : callbacks) { + callback.onReady(instance, server); + } + } + ); + + public static final Event RELOAD = EventFactory.createArrayBacked( + Reload.class, callbacks -> + (instance) -> { + for (Reload callback : callbacks) { + callback.onReload(instance); + } + } + ); + + public static final Event WELCOME = EventFactory.createArrayBacked( + Welcome.class, callbacks -> + (player, server) -> { + for (Welcome callback : callbacks) { + callback.onWelcome(player, server); + } + } + ); + + public static final Event USERNAME_CHANGE = EventFactory.createArrayBacked( + UsernameChange.class, callbacks -> + (player, previousUsername) -> { + for (UsernameChange callback : callbacks) { + callback.onUsernameChange(player, previousUsername); + } + } + ); + + /** + * @deprecated Superseded by {@link me.alexdevs.solstice.api.events.CommandEvents} + */ + @Deprecated + public static final Event PLAYER_COMMAND = EventFactory.createArrayBacked( + PlayerCommand.class, callbacks -> + (player, command) -> { + for (PlayerCommand callback : callbacks) { + callback.onPlayerCommand(player, command); + } + } + ); + + @FunctionalInterface + public interface Ready { + void onReady(Solstice instance, MinecraftServer server); + } + + @FunctionalInterface + public interface Reload { + void onReload(Solstice instance); + } + + @FunctionalInterface + public interface Welcome { + void onWelcome(ServerPlayer player, MinecraftServer server); + } + + @FunctionalInterface + public interface UsernameChange { + void onUsernameChange(ServerPlayer player, String previousUsername); + } + + @FunctionalInterface + public interface PlayerCommand { + void onPlayerCommand(ServerPlayer player, String command); + } +} diff --git a/src/main/java/me/alexdevs/solstice/api/events/TimeBarEvents.java b/common/src/main/java/me/alexdevs/solstice/api/events/TimeBarEvents.java similarity index 93% rename from src/main/java/me/alexdevs/solstice/api/events/TimeBarEvents.java rename to common/src/main/java/me/alexdevs/solstice/api/events/TimeBarEvents.java index 91d648b0..6b626901 100644 --- a/src/main/java/me/alexdevs/solstice/api/events/TimeBarEvents.java +++ b/common/src/main/java/me/alexdevs/solstice/api/events/TimeBarEvents.java @@ -1,8 +1,8 @@ package me.alexdevs.solstice.api.events; +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; import me.alexdevs.solstice.modules.timeBar.TimeBar; -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; import net.minecraft.server.MinecraftServer; public class TimeBarEvents { diff --git a/src/main/java/me/alexdevs/solstice/api/events/WorldSaveCallback.java b/common/src/main/java/me/alexdevs/solstice/api/events/WorldSaveCallback.java similarity index 65% rename from src/main/java/me/alexdevs/solstice/api/events/WorldSaveCallback.java rename to common/src/main/java/me/alexdevs/solstice/api/events/WorldSaveCallback.java index c3c0c427..88bb1ff1 100644 --- a/src/main/java/me/alexdevs/solstice/api/events/WorldSaveCallback.java +++ b/common/src/main/java/me/alexdevs/solstice/api/events/WorldSaveCallback.java @@ -1,17 +1,17 @@ package me.alexdevs.solstice.api.events; -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; import net.minecraft.server.MinecraftServer; public interface WorldSaveCallback { - Event EVENT = EventFactory.createArrayBacked(WorldSaveCallback.class, (callbacks) -> - (server, suppressLogs, flush, force) -> { + Event EVENT = EventFactory.createArrayBacked( + WorldSaveCallback.class, (callbacks) -> (server, suppressLogs, flush, force) -> { for (WorldSaveCallback callback : callbacks) { callback.onSave(server, suppressLogs, flush, force); } - - }); + } + ); void onSave(MinecraftServer server, boolean suppressLogs, boolean flush, boolean force); } \ No newline at end of file diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/backend/ArrayBackedEvent.java b/common/src/main/java/me/alexdevs/solstice/api/events/backend/ArrayBackedEvent.java new file mode 100644 index 00000000..933cf5ab --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/backend/ArrayBackedEvent.java @@ -0,0 +1,105 @@ +package me.alexdevs.solstice.api.events.backend; + +import net.minecraft.resources.ResourceLocation; + +import java.lang.reflect.Array; +import java.util.*; +import java.util.function.Function; + +class ArrayBackedEvent extends Event { + private final Function invokerFactory; + private final Object lock = new Object(); + private T[] handlers; + /** + * Registered event phases. + */ + private final Map> phases = new LinkedHashMap<>(); + /** + * Phases sorted in the correct dependency order. + */ + private final List> sortedPhases = new ArrayList<>(); + + @SuppressWarnings("unchecked") + ArrayBackedEvent(Class type, Function invokerFactory) { + this.invokerFactory = invokerFactory; + this.handlers = (T[]) Array.newInstance(type, 0); + update(); + } + + void update() { + this.invoker = invokerFactory.apply(handlers); + } + + @Override + public void register(T listener) { + register(DEFAULT_PHASE, listener); + } + + @Override + public void register(ResourceLocation phaseIdentifier, T listener) { + Objects.requireNonNull(phaseIdentifier, "Tried to register a listener for a null phase!"); + Objects.requireNonNull(listener, "Tried to register a null listener!"); + + synchronized (lock) { + getOrCreatePhase(phaseIdentifier, true).addListener(listener); + rebuildInvoker(handlers.length + 1); + } + } + + private EventPhaseData getOrCreatePhase(ResourceLocation id, boolean sortIfCreate) { + EventPhaseData phase = phases.get(id); + + if (phase == null) { + phase = new EventPhaseData<>(id, handlers.getClass().getComponentType()); + phases.put(id, phase); + sortedPhases.add(phase); + + if (sortIfCreate) { + NodeSorting.sort(sortedPhases, "event phases", Comparator.comparing(data -> data.id)); + } + } + + return phase; + } + + private void rebuildInvoker(int newLength) { + // Rebuild handlers. + if (sortedPhases.size() == 1) { + // Special case with a single phase: use the array of the phase directly. + handlers = sortedPhases.get(0).listeners; + } else { + @SuppressWarnings("unchecked") T[] newHandlers = (T[]) Array.newInstance( + handlers.getClass() + .getComponentType(), newLength + ); + int newHandlersIndex = 0; + + for (EventPhaseData existingPhase : sortedPhases) { + int length = existingPhase.listeners.length; + System.arraycopy(existingPhase.listeners, 0, newHandlers, newHandlersIndex, length); + newHandlersIndex += length; + } + + handlers = newHandlers; + } + + // Rebuild invoker. + update(); + } + + @Override + public void addPhaseOrdering(ResourceLocation firstPhase, ResourceLocation secondPhase) { + Objects.requireNonNull(firstPhase, "Tried to add an ordering for a null phase."); + Objects.requireNonNull(secondPhase, "Tried to add an ordering for a null phase."); + if (firstPhase.equals(secondPhase)) + throw new IllegalArgumentException("Tried to add a phase that depends on itself."); + + synchronized (lock) { + EventPhaseData first = getOrCreatePhase(firstPhase, false); + EventPhaseData second = getOrCreatePhase(secondPhase, false); + EventPhaseData.link(first, second); + NodeSorting.sort(this.sortedPhases, "event phases", Comparator.comparing(data -> data.id)); + rebuildInvoker(handlers.length); + } + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/backend/Event.java b/common/src/main/java/me/alexdevs/solstice/api/events/backend/Event.java new file mode 100644 index 00000000..c611d57a --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/backend/Event.java @@ -0,0 +1,66 @@ +package me.alexdevs.solstice.api.events.backend; + +import net.minecraft.resources.ResourceLocation; + +public abstract class Event { + /** + * The invoker field. This should be updated by the implementation to + * always refer to an instance containing all code that should be + * executed upon event emission. + */ + protected volatile T invoker; + + /** + * Returns the invoker instance. + * + *

An "invoker" is an object which hides multiple registered + * listeners of type T under one instance of type T, executing + * them and leaving early as necessary. + * + * @return The invoker instance. + */ + public final T invoker() { + return invoker; + } + + /** + * Register a listener to the event, in the default phase. + * Have a look at {@link #addPhaseOrdering} for an explanation of event phases. + * + * @param listener The desired listener. + */ + public abstract void register(T listener); + + /** + * The identifier of the default phase. + * Have a look at {@link EventFactory#createWithPhases} for an explanation of event phases. + */ + public static final ResourceLocation DEFAULT_PHASE = ResourceLocation.fromNamespaceAndPath("fabric", "default"); + + /** + * Register a listener to the event for the specified phase. + * Have a look at {@link EventFactory#createWithPhases} for an explanation of event phases. + * + * @param phase Identifier of the phase this listener should be registered for. It will be created if it didn't exist yet. + * @param listener The desired listener. + */ + public void register(ResourceLocation phase, T listener) { + // This is done to keep compatibility with existing Event subclasses, but they should really not be subclassing Event. + register(listener); + } + + /** + * Request that listeners registered for one phase be executed before listeners registered for another phase. + * Relying on the default phases supplied to {@link EventFactory#createWithPhases} should be preferred over manually + * registering phase ordering dependencies. + * + *

Incompatible ordering constraints such as cycles will lead to inconsistent behavior: + * some constraints will be respected and some will be ignored. If this happens, a warning will be logged. + * + * @param firstPhase The identifier of the phase that should run before the other. It will be created if it didn't exist yet. + * @param secondPhase The identifier of the phase that should run after the other. It will be created if it didn't exist yet. + */ + public void addPhaseOrdering(ResourceLocation firstPhase, ResourceLocation secondPhase) { + // This is not abstract to avoid breaking existing Event subclasses, but they should really not be subclassing Event. + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/backend/EventFactory.java b/common/src/main/java/me/alexdevs/solstice/api/events/backend/EventFactory.java new file mode 100644 index 00000000..1607f208 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/backend/EventFactory.java @@ -0,0 +1,128 @@ +package me.alexdevs.solstice.api.events.backend; + +import net.minecraft.resources.ResourceLocation; + +import java.util.function.Function; + +public final class EventFactory { + private EventFactory() { + } + + /** + * Create an "array-backed" Event instance. + * + *

If your factory simply delegates to the listeners without adding custom behavior, + * consider using {@linkplain #createArrayBacked(Class, Object, Function) the other overload} + * if performance of this event is critical. + * + * @param type The listener class type. + * @param invokerFactory The invoker factory, combining multiple listeners into one instance. + * @param The listener type. + * + * @return The Event instance. + */ + public static Event createArrayBacked(Class type, Function invokerFactory) { + return EventFactoryImpl.createArrayBacked(type, invokerFactory); + } + + /** + * Create an "array-backed" Event instance with a custom empty invoker, + * for an event whose {@code invokerFactory} only delegates to the listeners. + *

    + *
  • If there is no listener, the custom empty invoker will be used.
  • + *
  • If there is only one listener, that one will be used as the invoker + * and the factory will not be called.
  • + *
  • Only when there are at least two listeners will the factory be used.
  • + *
+ * + *

Having a custom empty invoker (of type (...) -> {}) increases performance + * relative to iterating over an empty array; however, it only really matters + * if the event is executed thousands of times a second. + * + * @param type The listener class type. + * @param emptyInvoker The custom empty invoker. + * @param invokerFactory The invoker factory, combining multiple listeners into one instance. + * @param The listener type. + * + * @return The Event instance. + */ + public static Event createArrayBacked(Class type, T emptyInvoker, Function invokerFactory) { + return createArrayBacked( + type, listeners -> { + if (listeners.length == 0) { + return emptyInvoker; + } else if (listeners.length == 1) { + return listeners[0]; + } else { + return invokerFactory.apply(listeners); + } + } + ); + } + + /** + * Create an array-backed event with a list of default phases that get invoked in order. + * Exposing the identifiers of the default phases as {@code public static final} constants is encouraged. + * + *

An event phase is a named group of listeners, which may be ordered before or after other groups of listeners. + * This allows some listeners to take priority over other listeners. + * Adding separate events should be considered before making use of multiple event phases. + * + *

Phases may be freely added to events created with any of the factory functions, + * however using this function is preferred for widely used event phases. + * If more phases are necessary, discussion with the author of the Event is encouraged. + * + *

Refer to {@link Event#addPhaseOrdering} for an explanation of event phases. + * + * @param type The listener class type. + * @param invokerFactory The invoker factory, combining multiple listeners into one instance. + * @param defaultPhases The default phases of this event, in the correct order. Must contain {@link Event#DEFAULT_PHASE}. + * @param The listener type. + * + * @return The Event instance. + */ + public static Event createWithPhases( + Class type, + Function invokerFactory, + ResourceLocation... defaultPhases + ) { + EventFactoryImpl.ensureContainsDefault(defaultPhases); + EventFactoryImpl.ensureNoDuplicates(defaultPhases); + + Event event = createArrayBacked(type, invokerFactory); + + for (int i = 1; i < defaultPhases.length; ++i) { + event.addPhaseOrdering(defaultPhases[i - 1], defaultPhases[i]); + } + + return event; + } + + /** + * @deprecated This is not to be used in events anymore. + */ + @Deprecated + public static String getHandlerName(Object handler) { + return handler.getClass().getName(); + } + + /** + * @deprecated Always returns {@code false}, do not use. This is not to be used in events anymore, standard Java profilers will do fine. + */ + @Deprecated + public static boolean isProfilingEnabled() { + return false; + } + + /** + * Invalidate and re-create all existing "invoker" instances across + * events created by this EventFactory. Use this if, for instance, + * the profilingEnabled field changes. + * + * @deprecated Do not use, will be removed in a future release. + */ + @Deprecated(forRemoval = true) + public static void invalidate() { + EventFactoryImpl.invalidate(); + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/backend/EventFactoryImpl.java b/common/src/main/java/me/alexdevs/solstice/api/events/backend/EventFactoryImpl.java new file mode 100644 index 00000000..efef8330 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/backend/EventFactoryImpl.java @@ -0,0 +1,114 @@ +package me.alexdevs.solstice.api.events.backend; + +import com.google.common.collect.MapMaker; +import net.minecraft.resources.ResourceLocation; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; +import java.util.Collections; +import java.util.Set; +import java.util.function.Function; + +public final class EventFactoryImpl { + private static final Set> ARRAY_BACKED_EVENTS = Collections.newSetFromMap(new MapMaker().weakKeys() + .makeMap()); + + private EventFactoryImpl() { + } + + public static void invalidate() { + ARRAY_BACKED_EVENTS.forEach(ArrayBackedEvent::update); + } + + public static Event createArrayBacked(Class type, Function invokerFactory) { + ArrayBackedEvent event = new ArrayBackedEvent<>(type, invokerFactory); + ARRAY_BACKED_EVENTS.add(event); + return event; + } + + public static void ensureContainsDefault(ResourceLocation[] defaultPhases) { + for (ResourceLocation id : defaultPhases) { + if (id.equals(Event.DEFAULT_PHASE)) { + return; + } + } + + throw new IllegalArgumentException("The event phases must contain Event.DEFAULT_PHASE."); + } + + public static void ensureNoDuplicates(ResourceLocation[] defaultPhases) { + for (int i = 0; i < defaultPhases.length; ++i) { + for (int j = i + 1; j < defaultPhases.length; ++j) { + if (defaultPhases[i].equals(defaultPhases[j])) { + throw new IllegalArgumentException("Duplicate event phase: " + defaultPhases[i]); + } + } + } + } + + // Code originally by sfPlayer1. + // Unfortunately, it's slightly slower than just passing an empty array in the first place. + private static T buildEmptyInvoker(Class handlerClass, Function invokerSetup) { + // find the functional interface method + Method funcIfMethod = null; + + for (Method m : handlerClass.getMethods()) { + if ((m.getModifiers() & (Modifier.STRICT | Modifier.PRIVATE)) == 0) { + if (funcIfMethod != null) { + throw new IllegalStateException("Multiple virtual methods in " + + handlerClass + + "; cannot build empty invoker!"); + } + + funcIfMethod = m; + } + } + + if (funcIfMethod == null) { + throw new IllegalStateException("No virtual methods in " + handlerClass + "; cannot build empty invoker!"); + } + + Object defValue = null; + + try { + // concert to mh, determine its type without the "this" reference + MethodHandle target = MethodHandles.lookup().unreflect(funcIfMethod); + MethodType type = target.type().dropParameterTypes(0, 1); + + if (type.returnType() != void.class) { + // determine default return value by invoking invokerSetup.apply(T[0]) with all-jvm-default args (null for refs, false for boolean, etc.) + // explicitCastArguments is being used to cast Object=null to the jvm default value for the correct type + + // construct method desc (TLjava/lang/Object;Ljava/lang/Object;...)R where T = invoker ref ("this"), R = invoker ret type and args 1+ are Object for each non-"this" invoker arg + MethodType objTargetType = MethodType.genericMethodType(type.parameterCount()) + .changeReturnType(type.returnType()) + .insertParameterTypes(0, target.type().parameterType(0)); + // explicit cast to translate to the invoker args from Object to their real type, inferring jvm default values + MethodHandle objTarget = MethodHandles.explicitCastArguments(target, objTargetType); + + // build invocation args with 0 = "this", 1+ = null + Object[] args = new Object[target.type().parameterCount()]; + //noinspection unchecked + args[0] = invokerSetup.apply((T[]) Array.newInstance(handlerClass, 0)); + + // retrieve default by invoking invokerSetup.apply(T[0]).targetName(def,def,...) + defValue = objTarget.invokeWithArguments(args); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + + final Object returnValue = defValue; + //noinspection unchecked + return (T) Proxy.newProxyInstance( + EventFactoryImpl.class.getClassLoader(), + new Class[] { handlerClass }, + (proxy, method, args) -> returnValue + ); + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/backend/EventPhaseData.java b/common/src/main/java/me/alexdevs/solstice/api/events/backend/EventPhaseData.java new file mode 100644 index 00000000..e86389d3 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/backend/EventPhaseData.java @@ -0,0 +1,28 @@ +package me.alexdevs.solstice.api.events.backend; + +import net.minecraft.resources.ResourceLocation; + +import java.lang.reflect.Array; +import java.util.Arrays; + +class EventPhaseData extends SortableNode> { + final ResourceLocation id; + T[] listeners; + + @SuppressWarnings("unchecked") + EventPhaseData(ResourceLocation id, Class listenerClass) { + this.id = id; + this.listeners = (T[]) Array.newInstance(listenerClass, 0); + } + + void addListener(T listener) { + int oldLength = listeners.length; + listeners = Arrays.copyOf(listeners, oldLength + 1); + listeners[oldLength] = listener; + } + + @Override + protected String getDescription() { + return id.toString(); + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/backend/NodeSorting.java b/common/src/main/java/me/alexdevs/solstice/api/events/backend/NodeSorting.java new file mode 100644 index 00000000..0260fd88 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/backend/NodeSorting.java @@ -0,0 +1,159 @@ +package me.alexdevs.solstice.api.events.backend; + +import com.google.common.annotations.VisibleForTesting; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +public class NodeSorting { + private static final Logger LOGGER = LoggerFactory.getLogger("fabric-api-base"); + + @VisibleForTesting public static boolean ENABLE_CYCLE_WARNING = true; + + /** + * Sort a list of nodes. + * + * @param sortedNodes The list of nodes to sort. Will be modified in-place. + * @param elementDescription A description of the elements, used for logging in the presence of cycles. + * @param comparator The comparator to break ties and to order elements within a cycle. + * + * @return {@code true} if all the constraints were satisfied, {@code false} if there was at least one cycle. + */ + public static > boolean sort( + List sortedNodes, + String elementDescription, + Comparator comparator + ) { + // FIRST KOSARAJU SCC VISIT + List toposort = new ArrayList<>(sortedNodes.size()); + + for (N node : sortedNodes) { + forwardVisit(node, null, toposort); + } + + clearStatus(toposort); + Collections.reverse(toposort); + + // SECOND KOSARAJU SCC VISIT + Map> nodeToScc = new IdentityHashMap<>(); + + for (N node : toposort) { + if (!node.visited) { + List sccNodes = new ArrayList<>(); + // Collect nodes in SCC. + backwardVisit(node, sccNodes); + // Sort nodes by id. + sccNodes.sort(comparator); + // Mark nodes as belonging to this SCC. + NodeScc scc = new NodeScc<>(sccNodes); + + for (N nodeInScc : sccNodes) { + nodeToScc.put(nodeInScc, scc); + } + } + } + + clearStatus(toposort); + + // Build SCC graph + for (NodeScc scc : nodeToScc.values()) { + for (N node : scc.nodes) { + for (N subsequentNode : node.subsequentNodes) { + NodeScc subsequentScc = nodeToScc.get(subsequentNode); + + if (subsequentScc != scc) { + scc.subsequentSccs.add(subsequentScc); + subsequentScc.inDegree++; + } + } + } + } + + // Order SCCs according to priorities. When there is a choice, use the SCC with the lowest id. + // The priority queue contains all SCCs that currently have 0 in-degree. + PriorityQueue> pq = new PriorityQueue<>(Comparator.comparing(scc -> scc.nodes.get(0), comparator)); + sortedNodes.clear(); + + for (NodeScc scc : nodeToScc.values()) { + if (scc.inDegree == 0) { + pq.add(scc); + // Prevent adding the same SCC multiple times, as nodeToScc may contain the same value multiple times. + scc.inDegree = -1; + } + } + + boolean noCycle = true; + + while (!pq.isEmpty()) { + NodeScc scc = pq.poll(); + sortedNodes.addAll(scc.nodes); + + if (scc.nodes.size() > 1) { + noCycle = false; + + if (ENABLE_CYCLE_WARNING) { + // Print cycle warning + StringBuilder builder = new StringBuilder(); + builder.append("Found cycle while sorting ").append(elementDescription).append(":\n"); + + for (N node : scc.nodes) { + builder.append("\t").append(node.getDescription()).append("\n"); + } + + LOGGER.warn(builder.toString()); + } + } + + for (NodeScc subsequentScc : scc.subsequentSccs) { + subsequentScc.inDegree--; + + if (subsequentScc.inDegree == 0) { + pq.add(subsequentScc); + } + } + } + + return noCycle; + } + + private static > void forwardVisit(N node, N parent, List toposort) { + if (!node.visited) { + // Not yet visited. + node.visited = true; + + for (N data : node.subsequentNodes) { + forwardVisit(data, node, toposort); + } + + toposort.add(node); + } + } + + private static > void clearStatus(List nodes) { + for (N node : nodes) { + node.visited = false; + } + } + + private static > void backwardVisit(N node, List sccNodes) { + if (!node.visited) { + node.visited = true; + sccNodes.add(node); + + for (N data : node.previousNodes) { + backwardVisit(data, sccNodes); + } + } + } + + private static class NodeScc> { + final List nodes; + final List> subsequentSccs = new ArrayList<>(); + int inDegree = 0; + + private NodeScc(List nodes) { + this.nodes = nodes; + } + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/backend/SortableNode.java b/common/src/main/java/me/alexdevs/solstice/api/events/backend/SortableNode.java new file mode 100644 index 00000000..2e1eb8ee --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/backend/SortableNode.java @@ -0,0 +1,24 @@ +package me.alexdevs.solstice.api.events.backend; + +import java.util.ArrayList; +import java.util.List; + +public abstract class SortableNode> { + final List subsequentNodes = new ArrayList<>(); + final List previousNodes = new ArrayList<>(); + boolean visited = false; + + /** + * @return Description of this node, used to print the cycle warning. + */ + protected abstract String getDescription(); + + public static > void link(N first, N second) { + if (first == second) { + throw new IllegalArgumentException("Cannot link a node to itself!"); + } + + first.subsequentNodes.add(second); + second.previousNodes.add(first); + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyAttackBlockCallback.java b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyAttackBlockCallback.java new file mode 100644 index 00000000..3236fc42 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyAttackBlockCallback.java @@ -0,0 +1,46 @@ +package me.alexdevs.solstice.api.events.proxy; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; + +/** + * Callback for left-clicking ("attacking") a block. + * Is hooked in before the spectator check, so make sure to check for the player's game mode as well! + * + *

On the logical client, the return values have the following meaning: + *

    + *
  • SUCCESS cancels further processing, causes a hand swing, and sends a packet to the server.
  • + *
  • CONSUME cancels further processing, and sends a packet to the server. It does NOT cause a hand swing.
  • + *
  • PASS falls back to further processing.
  • + *
  • FAIL cancels further processing and does not send a packet to the server.
  • + *
+ * + *

On the logical server, the return values have the following meaning: + *

    + *
  • PASS falls back to further processing.
  • + *
  • Any other value cancels further processing.
  • + *
+ */ +public interface ProxyAttackBlockCallback { + Event EVENT = EventFactory.createArrayBacked( + ProxyAttackBlockCallback.class, (listeners) -> (player, level, hand, pos, direction) -> { + for (ProxyAttackBlockCallback event : listeners) { + InteractionResult result = event.interact(player, level, hand, pos, direction); + + if (result != InteractionResult.PASS) { + return result; + } + } + + return InteractionResult.PASS; + } + ); + + InteractionResult interact(Player player, Level level, InteractionHand hand, BlockPos pos, Direction direction); +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyAttackEntityCallback.java b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyAttackEntityCallback.java new file mode 100644 index 00000000..1f97cc31 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyAttackEntityCallback.java @@ -0,0 +1,44 @@ +package me.alexdevs.solstice.api.events.proxy; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.EntityHitResult; +import org.jetbrains.annotations.Nullable; + +/** + * Callback for left-clicking ("attacking") an entity. + * Is hooked in before the spectator check, so make sure to check for the player's game mode as well! + * + *

Upon return: + *

  • SUCCESS cancels further processing and, on the client, sends a packet to the server. + *
  • PASS falls back to further processing. + *
  • FAIL cancels further processing and does not send a packet to the server.
+ */ +public interface ProxyAttackEntityCallback { + Event EVENT = EventFactory.createArrayBacked( + ProxyAttackEntityCallback.class, (listeners) -> (player, level, hand, entity, hitResult) -> { + for (ProxyAttackEntityCallback event : listeners) { + InteractionResult result = event.interact(player, level, hand, entity, hitResult); + + if (result != InteractionResult.PASS) { + return result; + } + } + + return InteractionResult.PASS; + } + ); + + InteractionResult interact( + Player player, + Level level, + InteractionHand hand, + Entity entity, + @Nullable EntityHitResult hitResult + ); +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyCommandRegistrationCallback.java b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyCommandRegistrationCallback.java new file mode 100644 index 00000000..06cd8b65 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyCommandRegistrationCallback.java @@ -0,0 +1,25 @@ +package me.alexdevs.solstice.api.events.proxy; + +import com.mojang.brigadier.CommandDispatcher; +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.commands.CommandBuildContext; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; + +public interface ProxyCommandRegistrationCallback { + Event EVENT = EventFactory.createArrayBacked( + ProxyCommandRegistrationCallback.class, callbacks -> (dispatcher, buildContext, selection) -> { + for (var callback : callbacks) { + callback.onRegister(dispatcher, buildContext, selection); + } + } + ); + + void onRegister( + CommandDispatcher dispatcher, + CommandBuildContext buildContext, + Commands.CommandSelection selection + ); +} + diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyEntitySleepEvents.java b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyEntitySleepEvents.java new file mode 100644 index 00000000..32070a7c --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyEntitySleepEvents.java @@ -0,0 +1,99 @@ +package me.alexdevs.solstice.api.events.proxy; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; + +public class ProxyEntitySleepEvents { + /** + * An event that is called when an entity stops sleeping and wakes up. + */ + public static final Event STOP_SLEEPING = EventFactory.createArrayBacked( + StopSleeping.class, callbacks -> (entity, sleepingPos) -> { + for (StopSleeping callback : callbacks) { + callback.onStopSleeping(entity, sleepingPos); + } + } + ); + + /** + * An event that checks whether the current time of day is valid for sleeping. + * + *

Note that if sleeping during day time is allowed, the game will still reset the time to 0 if the usual + * conditions are met, unless forbidden with {@link #ALLOW_RESETTING_TIME}. + */ + public static final Event ALLOW_SLEEP_TIME = EventFactory.createArrayBacked( + AllowSleepTime.class, callbacks -> (player, sleepingPos, vanillaResult) -> { + for (AllowSleepTime callback : callbacks) { + InteractionResult result = callback.allowSleepTime(player, sleepingPos, vanillaResult); + + if (result != InteractionResult.PASS) { + return result; + } + } + + return InteractionResult.PASS; + } + ); + + /** + * An event that checks whether a sleeping player counts into skipping the current day and resetting the time to 0. + * + *

When this event is called, all vanilla time resetting checks have already succeeded, i.e. this event + * is used in addition to vanilla checks. + */ + public static final Event ALLOW_RESETTING_TIME = EventFactory.createArrayBacked( + AllowResettingTime.class, callbacks -> player -> { + for (AllowResettingTime callback : callbacks) { + if (!callback.allowResettingTime(player)) { + return false; + } + } + + return true; + } + ); + + @FunctionalInterface + public interface StopSleeping { + /** + * Called when an entity stops sleeping and wakes up. + * + * @param entity the sleeping entity + * @param sleepingPos the {@linkplain LivingEntity#getSleepingPos() sleeping position} of the entity + */ + void onStopSleeping(LivingEntity entity, BlockPos sleepingPos); + } + + @FunctionalInterface + public interface AllowSleepTime { + /** + * Checks whether the current time of day is valid for sleeping. + * + *

Non-{@linkplain InteractionResult#PASS passing} return values cancel further callbacks. + * + * @param player the sleeping player + * @param sleepingPos the (possibly still unset) {@linkplain LivingEntity#getSleepingPos() sleeping position} of the player + * @param vanillaResult {@code true} if vanilla allows the time, {@code false} otherwise + * + * @return {@link InteractionResult#SUCCESS} if the time is valid, {@link InteractionResult#FAIL} if it's not, + * {@link InteractionResult#PASS} to fall back to other callbacks + */ + InteractionResult allowSleepTime(Player player, BlockPos sleepingPos, boolean vanillaResult); + } + + @FunctionalInterface + public interface AllowResettingTime { + /** + * Checks whether a sleeping player counts into skipping the current day and resetting the time to 0. + * + * @param player the sleeping player + * + * @return {@code true} if allowed, {@code false} otherwise + */ + boolean allowResettingTime(Player player); + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyPlayerBlockBreakEvents.java b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyPlayerBlockBreakEvents.java new file mode 100644 index 00000000..b34c6fe3 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyPlayerBlockBreakEvents.java @@ -0,0 +1,64 @@ +package me.alexdevs.solstice.api.events.proxy; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; + +/** + * Contains server side events triggered by block breaking. + */ +public final class ProxyPlayerBlockBreakEvents { + private ProxyPlayerBlockBreakEvents() { + } + + /** + * Callback before a block is broken. + * Only called on the server; however, updates are synced with the client. + * + *

If any listener cancels a block breaking action, that block breaking + * action is canceled and CANCELED event is fired. Otherwise, the + * AFTER event is fired.

+ */ + public static final Event BEFORE = EventFactory.createArrayBacked( + Before.class, (listeners) -> (level, player, pos, state, entity) -> { + for (Before event : listeners) { + boolean result = event.beforeBlockBreak(level, player, pos, state, entity); + + if (!result) { + return false; + } + } + + return true; + } + ); + + @FunctionalInterface + public interface Before { + /** + * Called before a block is broken and allows cancelling the block breaking. + * + *

Implementations should not modify the level or assume the block break has completed or failed.

+ * + * @param level the level in which the block is broken + * @param player the player breaking the block + * @param pos the position at which the block is broken + * @param state the block state before the block is broken + * @param blockEntity the block entity before the block is broken, can be {@code null} + * + * @return {@code false} to cancel block breaking action, or {@code true} to pass to next listener + */ + boolean beforeBlockBreak( + Level level, + Player player, + BlockPos pos, + BlockState state, + @Nullable BlockEntity blockEntity + ); + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerLifecycleEvents.java b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerLifecycleEvents.java new file mode 100644 index 00000000..136bfb8a --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerLifecycleEvents.java @@ -0,0 +1,59 @@ +package me.alexdevs.solstice.api.events.proxy; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.server.MinecraftServer; + +public class ProxyServerLifecycleEvents { + public static final Event SERVER_STARTING = EventFactory.createArrayBacked( + Starting.class, callbacks -> (server) -> { + for (var callback : callbacks) { + callback.onServerStarting(server); + } + } + ); + + public static final Event SERVER_STARTED = EventFactory.createArrayBacked( + Started.class, callbacks -> (server) -> { + for (var callback : callbacks) { + callback.onServerStarted(server); + } + } + ); + + public static final Event SERVER_STOPPING = EventFactory.createArrayBacked( + Stopping.class, callbacks -> (server) -> { + for (var callback : callbacks) { + callback.onServerStopping(server); + } + } + ); + + public static final Event SERVER_STOPPED = EventFactory.createArrayBacked( + Stopped.class, callbacks -> (server) -> { + for (var callback : callbacks) { + callback.onServerStopped(server); + } + } + ); + + @FunctionalInterface + public interface Starting { + void onServerStarting(MinecraftServer server); + } + + @FunctionalInterface + public interface Started { + void onServerStarted(MinecraftServer server); + } + + @FunctionalInterface + public interface Stopping { + void onServerStopping(MinecraftServer server); + } + + @FunctionalInterface + public interface Stopped { + void onServerStopped(MinecraftServer server); + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerLivingEntityEvents.java b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerLivingEntityEvents.java new file mode 100644 index 00000000..eba7fc51 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerLivingEntityEvents.java @@ -0,0 +1,30 @@ +package me.alexdevs.solstice.api.events.proxy; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.LivingEntity; + +public class ProxyServerLivingEntityEvents { + /** + * An event that is called when a living entity dies. + */ + public static final Event AFTER_DEATH = EventFactory.createArrayBacked( + AfterDeath.class, callbacks -> (entity, damageSource) -> { + for (AfterDeath callback : callbacks) { + callback.afterDeath(entity, damageSource); + } + } + ); + + @FunctionalInterface + public interface AfterDeath { + /** + * Called when a living entity dies. The death cannot be canceled at this point. + * + * @param entity the entity + * @param damageSource the source of the fatal damage + */ + void afterDeath(LivingEntity entity, DamageSource damageSource); + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerMessageEvents.java b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerMessageEvents.java new file mode 100644 index 00000000..323b021b --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerMessageEvents.java @@ -0,0 +1,72 @@ +package me.alexdevs.solstice.api.events.proxy; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.network.chat.ChatType; +import net.minecraft.network.chat.PlayerChatMessage; +import net.minecraft.server.level.ServerPlayer; + +public class ProxyServerMessageEvents { + /** + * An event triggered when the server broadcasts a chat message sent by a player, + * typically from a client GUI or a player-executed command. Mods can use this to block + * the message. + * + *

If a listener returned {@code false}, the message will not be broadcast, + * the remaining listeners will not be called (if any), and {@link #CHAT_MESSAGE} + * event will not be triggered. + */ + public static final Event ALLOW_CHAT_MESSAGE = EventFactory.createArrayBacked( + AllowChatMessage.class, handlers -> (message, sender, params) -> { + for (AllowChatMessage handler : handlers) { + if (!handler.allowChatMessage(message, sender, params)) return false; + } + + return true; + } + ); + + /** + * An event triggered when the server broadcasts a chat message sent by a player, typically + * from a client GUI or a player-executed command. Is not called when {@linkplain + * #ALLOW_CHAT_MESSAGE chat messages are blocked}. + */ + public static final Event CHAT_MESSAGE = EventFactory.createArrayBacked( + ChatMessage.class, handlers -> (message, sender, params) -> { + for (ChatMessage handler : handlers) { + handler.onChatMessage(message, sender, params); + } + } + ); + + @FunctionalInterface + public interface AllowChatMessage { + /** + * Called when the server broadcasts a chat message sent by a player, typically + * from a client GUI or a player-executed command. Returning {@code false} + * prevents the message from being broadcast and the {@link #CHAT_MESSAGE} event + * from triggering. + * + * @param message the broadcast message with message decorators applied; use {@code message.getContent()} to get the text + * @param sender the player that sent the message + * @param params the {@link ChatType.Bound} + * + * @return {@code true} if the message should be broadcast, otherwise {@code false} + */ + boolean allowChatMessage(PlayerChatMessage message, ServerPlayer sender, ChatType.Bound params); + } + + @FunctionalInterface + public interface ChatMessage { + /** + * Called when the server broadcasts a chat message sent by a player, typically + * from a client GUI or a player-executed command. Is not called when {@linkplain + * #ALLOW_CHAT_MESSAGE chat messages are blocked}. + * + * @param message the broadcast message with message decorators applied; use {@code message.getContent()} to get the text + * @param sender the player that sent the message + * @param params the {@link ChatType.Bound} + */ + void onChatMessage(PlayerChatMessage message, ServerPlayer sender, ChatType.Bound params); + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerPlayConnectionEvents.java b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerPlayConnectionEvents.java new file mode 100644 index 00000000..f9c38bb5 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerPlayConnectionEvents.java @@ -0,0 +1,34 @@ +package me.alexdevs.solstice.api.events.proxy; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; + +public class ProxyServerPlayConnectionEvents { + public static final Event JOIN = EventFactory.createArrayBacked( + Join.class, callbacks -> (player, server) -> { + for (Join callback : callbacks) { + callback.onJoin(player, server); + } + } + ); + + public static final Event DISCONNECT = EventFactory.createArrayBacked( + Disconnect.class, callbacks -> (player, server) -> { + for (Disconnect callback : callbacks) { + callback.onDisconnect(player, server); + } + } + ); + + @FunctionalInterface + public interface Join { + void onJoin(ServerPlayer player, MinecraftServer server); + } + + @FunctionalInterface + public interface Disconnect { + void onDisconnect(ServerPlayer player, MinecraftServer server); + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerPlayerEvents.java b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerPlayerEvents.java new file mode 100644 index 00000000..72396fe2 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerPlayerEvents.java @@ -0,0 +1,32 @@ +package me.alexdevs.solstice.api.events.proxy; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.server.level.ServerPlayer; + +public class ProxyServerPlayerEvents { + /** + * An event that is called after a player has been respawned. + * + *

Mods may use this event for reference clean up on the old player. + */ + public static final Event AFTER_RESPAWN = EventFactory.createArrayBacked( + ProxyServerPlayerEvents.AfterRespawn.class, callbacks -> (oldPlayer, newPlayer, alive) -> { + for (AfterRespawn callback : callbacks) { + callback.afterRespawn(oldPlayer, newPlayer, alive); + } + } + ); + + @FunctionalInterface + public interface AfterRespawn { + /** + * Called after player a has been respawned. + * + * @param oldPlayer the old player + * @param newPlayer the new player + * @param alive whether the old player is still alive + */ + void afterRespawn(ServerPlayer oldPlayer, ServerPlayer newPlayer, boolean alive); + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerTickEvents.java b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerTickEvents.java new file mode 100644 index 00000000..a2b5d184 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyServerTickEvents.java @@ -0,0 +1,33 @@ +package me.alexdevs.solstice.api.events.proxy; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.server.MinecraftServer; + +public class ProxyServerTickEvents { + public static final Event START_SERVER_TICK = EventFactory.createArrayBacked( + Begin.class, callbacks -> (server) -> { + for (var callback : callbacks) { + callback.onStartTick(server); + } + } + ); + + public static final Event END_SERVER_TICK = EventFactory.createArrayBacked( + End.class, callbacks -> (server) -> { + for (var callback : callbacks) { + callback.onEndTick(server); + } + } + ); + + @FunctionalInterface + public interface Begin { + void onStartTick(MinecraftServer server); + } + + @FunctionalInterface + public interface End { + void onEndTick(MinecraftServer server); + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyUseBlockCallback.java b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyUseBlockCallback.java new file mode 100644 index 00000000..1ef4549f --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyUseBlockCallback.java @@ -0,0 +1,36 @@ +package me.alexdevs.solstice.api.events.proxy; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.BlockHitResult; + +/** + * Callback for right-clicking ("using") a block. + * Is hooked in before the spectator check, so make sure to check for the player's game mode as well! + * + *

Upon return: + *

  • SUCCESS cancels further processing and, on the client, sends a packet to the server. + *
  • PASS falls back to further processing. + *
  • FAIL cancels further processing and does not send a packet to the server.
+ */ +public interface ProxyUseBlockCallback { + Event EVENT = EventFactory.createArrayBacked( + ProxyUseBlockCallback.class, (listeners) -> (player, level, hand, hitResult) -> { + for (ProxyUseBlockCallback event : listeners) { + InteractionResult result = event.interact(player, level, hand, hitResult); + + if (result != InteractionResult.PASS) { + return result; + } + } + + return InteractionResult.PASS; + } + ); + + InteractionResult interact(Player player, Level level, InteractionHand hand, BlockHitResult hitResult); +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyUseEntityCallback.java b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyUseEntityCallback.java new file mode 100644 index 00000000..e223ff80 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyUseEntityCallback.java @@ -0,0 +1,57 @@ +package me.alexdevs.solstice.api.events.proxy; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.EntityHitResult; +import org.jetbrains.annotations.Nullable; + +/** + * Callback for right-clicking ("using") an entity. + * Is hooked in before the spectator check, so make sure to check for the player's game mode as well! + * + *

On the logical client, the return values have the following meaning: + *

    + *
  • SUCCESS cancels further processing, causes a hand swing, and sends a packet to the server.
  • + *
  • CONSUME cancels further processing, and sends a packet to the server. It does NOT cause a hand swing.
  • + *
  • PASS falls back to further processing.
  • + *
  • FAIL cancels further processing and does not send a packet to the server.
  • + *
+ * + *

On the logical server, the return values have the following meaning: + *

    + *
  • PASS falls back to further processing.
  • + *
  • Any other value cancels further processing.
  • + *
+ * + *

Note that on the server, the {@link EntityHitResult} may be {@code null} if the client successfully interacted using + * the {@linkplain Player#interactOn(Entity, InteractionHand) position-less overload}. + * On the client, the {@link EntityHitResult} will never be null. + */ +public interface ProxyUseEntityCallback { + Event EVENT = EventFactory.createArrayBacked( + ProxyUseEntityCallback.class, (listeners) -> (player, level, hand, entity, hitResult) -> { + for (ProxyUseEntityCallback event : listeners) { + InteractionResult result = event.interact(player, level, hand, entity, hitResult); + + if (result != InteractionResult.PASS) { + return result; + } + } + + return InteractionResult.PASS; + } + ); + + InteractionResult interact( + Player player, + Level level, + InteractionHand hand, + Entity entity, + @Nullable EntityHitResult hitResult + ); +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyUseItemCallback.java b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyUseItemCallback.java new file mode 100644 index 00000000..6a981f80 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/events/proxy/ProxyUseItemCallback.java @@ -0,0 +1,37 @@ +package me.alexdevs.solstice.api.events.proxy; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +/** + * Callback for right-clicking ("using") an item. + * Is hooked in before the spectator check, so make sure to check for the player's game mode as well! + * + *

Upon return: + *

  • SUCCESS cancels further processing and, on the client, sends a packet to the server. + *
  • PASS falls back to further processing. + *
  • FAIL cancels further processing and does not send a packet to the server.
+ */ +public interface ProxyUseItemCallback { + Event EVENT = EventFactory.createArrayBacked( + ProxyUseItemCallback.class, listeners -> (player, level, hand) -> { + for (ProxyUseItemCallback event : listeners) { + InteractionResultHolder result = event.interact(player, level, hand); + + if (result.getResult() != InteractionResult.PASS) { + return result; + } + } + + return InteractionResultHolder.pass(ItemStack.EMPTY); + } + ); + + InteractionResultHolder interact(Player player, Level level, InteractionHand hand); +} diff --git a/src/main/java/me/alexdevs/solstice/api/module/Debug.java b/common/src/main/java/me/alexdevs/solstice/api/module/Debug.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/module/Debug.java rename to common/src/main/java/me/alexdevs/solstice/api/module/Debug.java diff --git a/src/main/java/me/alexdevs/solstice/api/module/ModCommand.java b/common/src/main/java/me/alexdevs/solstice/api/module/ModCommand.java similarity index 93% rename from src/main/java/me/alexdevs/solstice/api/module/ModCommand.java rename to common/src/main/java/me/alexdevs/solstice/api/module/ModCommand.java index 9cf30731..39b81b81 100644 --- a/src/main/java/me/alexdevs/solstice/api/module/ModCommand.java +++ b/common/src/main/java/me/alexdevs/solstice/api/module/ModCommand.java @@ -3,10 +3,11 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.tree.LiteralCommandNode; -import me.lucko.fabric.api.permissions.v0.Permissions; +import me.alexdevs.solstice.api.permissions.Permissions; import net.minecraft.commands.CommandBuildContext; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; + import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; @@ -25,7 +26,11 @@ public ModCommand(T module) { this.module = module; } - public void register(CommandDispatcher dispatcher, CommandBuildContext commandRegistry, Commands.CommandSelection environment) { + public void register( + CommandDispatcher dispatcher, + CommandBuildContext commandRegistry, + Commands.CommandSelection environment + ) { this.dispatcher = dispatcher; this.commandRegistry = commandRegistry; this.environment = environment; @@ -97,6 +102,7 @@ public Predicate require(String subNode, boolean defaultValu * Generate the command node, this method gets called for every name. * * @param name Command name + * * @return Command node */ public abstract LiteralArgumentBuilder command(String name); diff --git a/src/main/java/me/alexdevs/solstice/api/module/ModuleBase.java b/common/src/main/java/me/alexdevs/solstice/api/module/ModuleBase.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/module/ModuleBase.java rename to common/src/main/java/me/alexdevs/solstice/api/module/ModuleBase.java diff --git a/src/main/java/me/alexdevs/solstice/api/module/ModuleEntrypoint.java b/common/src/main/java/me/alexdevs/solstice/api/module/ModuleEntrypoint.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/module/ModuleEntrypoint.java rename to common/src/main/java/me/alexdevs/solstice/api/module/ModuleEntrypoint.java diff --git a/src/main/java/me/alexdevs/solstice/api/module/Utils.java b/common/src/main/java/me/alexdevs/solstice/api/module/Utils.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/module/Utils.java rename to common/src/main/java/me/alexdevs/solstice/api/module/Utils.java diff --git a/common/src/main/java/me/alexdevs/solstice/api/permissions/BooleanFunction.java b/common/src/main/java/me/alexdevs/solstice/api/permissions/BooleanFunction.java new file mode 100644 index 00000000..17205f7e --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/permissions/BooleanFunction.java @@ -0,0 +1,18 @@ +package me.alexdevs.solstice.api.permissions; + +/** + * Represents a function that accepts a boolean-valued argument and produces a result. + * + *

This is the {@code boolean}-consuming primitive specialization for {@link java.util.function.Function}. + */ +@FunctionalInterface +public interface BooleanFunction { + /** + * Applies this function to the given argument. + * + * @param value the function argument + * @return the function result + */ + R apply(boolean value); +} + diff --git a/common/src/main/java/me/alexdevs/solstice/api/permissions/OfflineOptionRequestEvent.java b/common/src/main/java/me/alexdevs/solstice/api/permissions/OfflineOptionRequestEvent.java new file mode 100644 index 00000000..c5194bb6 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/permissions/OfflineOptionRequestEvent.java @@ -0,0 +1,33 @@ +package me.alexdevs.solstice.api.permissions; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +/** + * Simple option request event for (potentially) offline players. + */ +public interface OfflineOptionRequestEvent { + + Event EVENT = EventFactory.createArrayBacked( + OfflineOptionRequestEvent.class, (callbacks) -> (uuid, key) -> { + CompletableFuture> res = CompletableFuture.completedFuture(null); + for (OfflineOptionRequestEvent callback : callbacks) { + res = res.thenCompose(value -> { + if (value.isPresent()) { + return CompletableFuture.completedFuture(value); + } + return callback.onOptionRequest(uuid, key); + }); + } + return res; + } + ); + + @NotNull CompletableFuture> onOptionRequest(@NotNull UUID uuid, @NotNull String key); + +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/permissions/OfflinePermissionCheckEvent.java b/common/src/main/java/me/alexdevs/solstice/api/permissions/OfflinePermissionCheckEvent.java new file mode 100644 index 00000000..500df5bd --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/permissions/OfflinePermissionCheckEvent.java @@ -0,0 +1,33 @@ +package me.alexdevs.solstice.api.permissions; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +/** + * Simple permissions check event for (potentially) offline players. + */ +public interface OfflinePermissionCheckEvent { + + Event EVENT = EventFactory.createArrayBacked( + OfflinePermissionCheckEvent.class, (callbacks) -> (uuid, permission) -> { + CompletableFuture res = CompletableFuture.completedFuture(TriState.DEFAULT); + for (OfflinePermissionCheckEvent callback : callbacks) { + res = res.thenCompose(triState -> { + if (triState != TriState.DEFAULT) { + return CompletableFuture.completedFuture(triState); + } + return callback.onPermissionCheck(uuid, permission); + }); + } + return res; + } + ); + + @NotNull CompletableFuture onPermissionCheck(@NotNull UUID uuid, @NotNull String permission); + +} + diff --git a/common/src/main/java/me/alexdevs/solstice/api/permissions/OptionRequestEvent.java b/common/src/main/java/me/alexdevs/solstice/api/permissions/OptionRequestEvent.java new file mode 100644 index 00000000..475f5eed --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/permissions/OptionRequestEvent.java @@ -0,0 +1,30 @@ +package me.alexdevs.solstice.api.permissions; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.commands.CommandSource; +import net.minecraft.commands.SharedSuggestionProvider; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +/** + * Simple option request event for {@link CommandSource}s. + */ +public interface OptionRequestEvent { + + Event EVENT = EventFactory.createArrayBacked( + OptionRequestEvent.class, (callbacks) -> (source, key) -> { + for (OptionRequestEvent callback : callbacks) { + Optional value = callback.onOptionRequest(source, key); + if (value.isPresent()) { + return value; + } + } + return Optional.empty(); + } + ); + + @NotNull Optional onOptionRequest(@NotNull SharedSuggestionProvider source, @NotNull String key); +} + diff --git a/common/src/main/java/me/alexdevs/solstice/api/permissions/Options.java b/common/src/main/java/me/alexdevs/solstice/api/permissions/Options.java new file mode 100644 index 00000000..6ad14065 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/permissions/Options.java @@ -0,0 +1,400 @@ +package me.alexdevs.solstice.api.permissions; + +import com.mojang.authlib.GameProfile; +import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.world.entity.Entity; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; + +/** + * A simple options (metadata) API. + */ +public interface Options { + + /** + * Gets the value of an option for the given source. + * + * @param source the source + * @param key the option key + * + * @return the option value + */ + static @NotNull Optional get(@NotNull SharedSuggestionProvider source, @NotNull String key) { + Objects.requireNonNull(source, "source"); + Objects.requireNonNull(key, "key"); + return OptionRequestEvent.EVENT.invoker().onOptionRequest(source, key); + } + + /** + * Gets the value of an option for the given source, falling back to the {@code defaultValue} + * if nothing is returned from the provider. + * + * @param source the source + * @param key the option key + * @param defaultValue the default value to use if nothing is returned + * + * @return the option value + */ + @Contract("_, _, !null -> !null") + static String get(@NotNull SharedSuggestionProvider source, @NotNull String key, String defaultValue) { + return get(source, key).orElse(defaultValue); + } + + /** + * Gets the value of an option for the given source, and runs it through the given {@code valueTransformer}. + * + *

If nothing is returned from the provider, an {@link Optional#empty() empty optional} is returned. + * (the transformer will never be passed a null argument)

+ * + *

The transformer is allowed to throw {@link IllegalArgumentException} or return null. This + * will also result in an {@link Optional#empty() empty optional} being returned.

+ * + *

For example, to parse and return an integer meta value, use:

+ *

+     *     get(source, "my-int-value", Integer::parseInt).orElse(0);
+     * 
+ * + * @param source the source + * @param key the option key + * @param valueTransformer the transformer used to transform the value + * @param the type of the transformed result + * + * @return the transformed option value + */ + static @NotNull Optional get( + @NotNull SharedSuggestionProvider source, + @NotNull String key, + @NotNull Function valueTransformer + ) { + return get(source, key).flatMap(value -> { + try { + return Optional.ofNullable(valueTransformer.apply(value)); + } catch (IllegalArgumentException e) { + return Optional.empty(); + } + }); + } + + /** + * Gets the value of an option for the given source, runs it through the given {@code valueTransformer}, + * and falls back to the {@code defaultValue} if nothing is returned. + * + *

If nothing is returned from the provider, the {@code defaultValue} is returned. + * (the transformer will never be passed a null argument)

+ * + *

The transformer is allowed to throw {@link IllegalArgumentException} or return null. This + * will also result in the {@code defaultValue} being returned.

+ * + *

For example, to parse and return an integer meta value, use:

+ *

+     *     get(source, "my-int-value", 0, Integer::parseInt);
+     * 
+ * + * @param source the source + * @param key the option key + * @param defaultValue the default value + * @param valueTransformer the transformer used to transform the value + * @param the type of the transformed result + * + * @return the transformed option value + */ + @Contract("_, _, !null, _ -> !null") + static T get( + @NotNull SharedSuggestionProvider source, + @NotNull String key, + T defaultValue, + @NotNull Function valueTransformer + ) { + return Options.get(source, key, valueTransformer).orElse(defaultValue); + } + + /** + * Gets the value of an option for the given entity. + * + * @param entity the entity + * @param key the option key + * + * @return the option value + */ + static @NotNull Optional get(@NotNull Entity entity, @NotNull String key) { + Objects.requireNonNull(entity, "entity"); + return get(Util.commandSourceFromEntity(entity), key); + } + + /** + * Gets the value of an option for the given entity, falling back to the {@code defaultValue} + * if nothing is returned from the provider. + * + * @param entity the entity + * @param key the option key + * @param defaultValue the default value to use if nothing is returned + * + * @return the option value + */ + @Contract("_, _, !null -> !null") + static String get(@NotNull Entity entity, @NotNull String key, String defaultValue) { + Objects.requireNonNull(entity, "entity"); + return get(Util.commandSourceFromEntity(entity), key, defaultValue); + } + + /** + * Gets the value of an option for the given entity, and runs it through the given {@code valueTransformer}. + * + *

If nothing is returned from the provider, an {@link Optional#empty() empty optional} is returned. + * (the transformer will never be passed a null argument)

+ * + *

The transformer is allowed to throw {@link IllegalArgumentException} or return null. This + * will also result in an {@link Optional#empty() empty optional} being returned.

+ * + *

For example, to parse and return an integer meta value, use:

+ *

+     *     get(entity, "my-int-value", Integer::parseInt).orElse(0);
+     * 
+ * + * @param entity the entity + * @param key the option key + * @param valueTransformer the transformer used to transform the value + * @param the type of the transformed result + * + * @return the transformed option value + */ + static @NotNull Optional get( + @NotNull Entity entity, + @NotNull String key, + @NotNull Function valueTransformer + ) { + Objects.requireNonNull(entity, "entity"); + return get(Util.commandSourceFromEntity(entity), key, valueTransformer); + } + + /** + * Gets the value of an option for the given entity, runs it through the given {@code valueTransformer}, + * and falls back to the {@code defaultValue} if nothing is returned. + * + *

If nothing is returned from the provider, the {@code defaultValue} is returned. + * (the transformer will never be passed a null argument)

+ * + *

The transformer is allowed to throw {@link IllegalArgumentException} or return null. This + * will also result in the {@code defaultValue} being returned.

+ * + *

For example, to parse and return an integer meta value, use:

+ *

+     *     get(entity, "my-int-value", 0, Integer::parseInt);
+     * 
+ * + * @param entity the entity + * @param key the option key + * @param defaultValue the default value + * @param valueTransformer the transformer used to transform the value + * @param the type of the transformed result + * + * @return the transformed option value + */ + @Contract("_, _, !null, _ -> !null") + static T get( + @NotNull Entity entity, + @NotNull String key, + T defaultValue, + @NotNull Function valueTransformer + ) { + Objects.requireNonNull(entity, "entity"); + return get(Util.commandSourceFromEntity(entity), key, defaultValue, valueTransformer); + } + + /** + * Gets the value of an option for the given (potentially) offline player. + * + * @param uuid the uuid of the player + * @param key the option key + * + * @return the option value + */ + static @NotNull CompletableFuture> get(@NotNull UUID uuid, @NotNull String key) { + Objects.requireNonNull(uuid, "uuid"); + Objects.requireNonNull(key, "key"); + return OfflineOptionRequestEvent.EVENT.invoker().onOptionRequest(uuid, key); + } + + /** + * Gets the value of an option for the given player, falling back to the {@code defaultValue} + * if nothing is returned from the provider. + * + * @param uuid the uuid of the player + * @param key the option key + * @param defaultValue the default value to use if nothing is returned + * + * @return the option value + */ + @Contract("_, _, !null -> !null") + static CompletableFuture get(@NotNull UUID uuid, @NotNull String key, String defaultValue) { + return get(uuid, key).thenApply(opt -> opt.orElse(defaultValue)); + } + + /** + * Gets the value of an option for the given player, and runs it through the given {@code valueTransformer}. + * + *

If nothing is returned from the provider, an {@link Optional#empty() empty optional} is returned. + * (the transformer will never be passed a null argument)

+ * + *

The transformer is allowed to throw {@link IllegalArgumentException} or return null. This + * will also result in an {@link Optional#empty() empty optional} being returned.

+ * + *

For example, to parse and return an integer meta value, use:

+ *

+     *     get(uuid, "my-int-value", Integer::parseInt).orElse(0);
+     * 
+ * + * @param uuid the uuid of the player + * @param key the option key + * @param valueTransformer the transformer used to transform the value + * @param the type of the transformed result + * + * @return the transformed option value + */ + static @NotNull CompletableFuture> get( + @NotNull UUID uuid, + @NotNull String key, + @NotNull Function valueTransformer + ) { + return get(uuid, key).thenApply(opt -> opt.flatMap(value -> { + try { + return Optional.ofNullable(valueTransformer.apply(value)); + } catch (IllegalArgumentException e) { + return Optional.empty(); + } + })); + } + + /** + * Gets the value of an option for the given player, runs it through the given {@code valueTransformer}, + * and falls back to the {@code defaultValue} if nothing is returned. + * + *

If nothing is returned from the provider, the {@code defaultValue} is returned. + * (the transformer will never be passed a null argument)

+ * + *

The transformer is allowed to throw {@link IllegalArgumentException} or return null. This + * will also result in the {@code defaultValue} being returned.

+ * + *

For example, to parse and return an integer meta value, use:

+ *

+     *     get(uuid, "my-int-value", 0, Integer::parseInt);
+     * 
+ * + * @param uuid the uuid of the player + * @param key the option key + * @param defaultValue the default value + * @param valueTransformer the transformer used to transform the value + * @param the type of the transformed result + * + * @return the transformed option value + */ + @Contract("_, _, !null, _ -> !null") + static CompletableFuture get( + @NotNull UUID uuid, + @NotNull String key, + T defaultValue, + @NotNull Function valueTransformer + ) { + return Options.get(uuid, key, valueTransformer).thenApply(opt -> opt.orElse(defaultValue)); + } + + /** + * Gets the value of an option for the given (potentially) offline player. + * + * @param profile the player profile + * @param key the option key + * + * @return the option value + */ + static @NotNull CompletableFuture> get(@NotNull GameProfile profile, @NotNull String key) { + Objects.requireNonNull(profile, "profile"); + return get(profile.getId(), key); + } + + /** + * Gets the value of an option for the given player, falling back to the {@code defaultValue} + * if nothing is returned from the provider. + * + * @param profile the player profile + * @param key the option key + * @param defaultValue the default value to use if nothing is returned + * + * @return the option value + */ + @Contract("_, _, !null -> !null") + static CompletableFuture get(@NotNull GameProfile profile, @NotNull String key, String defaultValue) { + Objects.requireNonNull(profile, "profile"); + return get(profile.getId(), key, defaultValue); + } + + /** + * Gets the value of an option for the given player, and runs it through the given {@code valueTransformer}. + * + *

If nothing is returned from the provider, an {@link Optional#empty() empty optional} is returned. + * (the transformer will never be passed a null argument)

+ * + *

The transformer is allowed to throw {@link IllegalArgumentException} or return null. This + * will also result in an {@link Optional#empty() empty optional} being returned.

+ * + *

For example, to parse and return an integer meta value, use:

+ *

+     *     get(uuid, "my-int-value", Integer::parseInt).orElse(0);
+     * 
+ * + * @param profile the player profile + * @param key the option key + * @param valueTransformer the transformer used to transform the value + * @param the type of the transformed result + * + * @return the transformed option value + */ + static @NotNull CompletableFuture> get( + @NotNull GameProfile profile, + @NotNull String key, + @NotNull Function valueTransformer + ) { + Objects.requireNonNull(profile, "profile"); + return get(profile.getId(), key, valueTransformer); + } + + /** + * Gets the value of an option for the given player, runs it through the given {@code valueTransformer}, + * and falls back to the {@code defaultValue} if nothing is returned. + * + *

If nothing is returned from the provider, the {@code defaultValue} is returned. + * (the transformer will never be passed a null argument)

+ * + *

The transformer is allowed to throw {@link IllegalArgumentException} or return null. This + * will also result in the {@code defaultValue} being returned.

+ * + *

For example, to parse and return an integer meta value, use:

+ *

+     *     get(uuid, "my-int-value", 0, Integer::parseInt);
+     * 
+ * + * @param profile the player profile + * @param key the option key + * @param defaultValue the default value + * @param valueTransformer the transformer used to transform the value + * @param the type of the transformed result + * + * @return the transformed option value + */ + @Contract("_, _, !null, _ -> !null") + static CompletableFuture get( + @NotNull GameProfile profile, + @NotNull String key, + T defaultValue, + @NotNull Function valueTransformer + ) { + Objects.requireNonNull(profile, "profile"); + return get(profile.getId(), key, defaultValue, valueTransformer); + } + +} \ No newline at end of file diff --git a/common/src/main/java/me/alexdevs/solstice/api/permissions/PermissionCheckEvent.java b/common/src/main/java/me/alexdevs/solstice/api/permissions/PermissionCheckEvent.java new file mode 100644 index 00000000..99e1655c --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/permissions/PermissionCheckEvent.java @@ -0,0 +1,28 @@ +package me.alexdevs.solstice.api.permissions; + +import me.alexdevs.solstice.api.events.backend.Event; +import me.alexdevs.solstice.api.events.backend.EventFactory; +import net.minecraft.commands.CommandSource; +import net.minecraft.commands.SharedSuggestionProvider; +import org.jetbrains.annotations.NotNull; + +/** + * Simple permissions check event for {@link CommandSource}s. + */ +public interface PermissionCheckEvent { + + Event EVENT = EventFactory.createArrayBacked( + PermissionCheckEvent.class, (callbacks) -> (source, permission) -> { + for (PermissionCheckEvent callback : callbacks) { + TriState state = callback.onPermissionCheck(source, permission); + if (state != TriState.DEFAULT) { + return state; + } + } + return TriState.DEFAULT; + } + ); + + @NotNull TriState onPermissionCheck(@NotNull SharedSuggestionProvider source, @NotNull String permission); + +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/permissions/Permissions.java b/common/src/main/java/me/alexdevs/solstice/api/permissions/Permissions.java new file mode 100644 index 00000000..76d73a61 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/permissions/Permissions.java @@ -0,0 +1,277 @@ +package me.alexdevs.solstice.api.permissions; + +import com.mojang.authlib.GameProfile; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.entity.Entity; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.function.BooleanSupplier; +import java.util.function.Predicate; + +/** + * A simple permissions API. + */ +public interface Permissions { + + /** + * Gets the {@link TriState state} of a {@code permission} for the given source. + * + * @param source the source + * @param permission the permission + * + * @return the state of the permission + */ + static @NotNull TriState getPermissionValue(@NotNull SharedSuggestionProvider source, @NotNull String permission) { + Objects.requireNonNull(source, "source"); + Objects.requireNonNull(permission, "permission"); + return PermissionCheckEvent.EVENT.invoker().onPermissionCheck(source, permission); + } + + /** + * Performs a permission check, falling back to the {@code defaultValue} if the resultant + * state is {@link TriState#DEFAULT}. + * + * @param source the source to perform the check for + * @param permission the permission to check + * @param defaultValue the default value to use if nothing has been set + * + * @return the result of the permission check + */ + static boolean check(@NotNull SharedSuggestionProvider source, @NotNull String permission, boolean defaultValue) { + return getPermissionValue(source, permission).orElse(defaultValue); + } + + /** + * Performs a permission check, falling back to requiring the {@code defaultRequiredLevel} + * if the resultant state is {@link TriState#DEFAULT}. + * + * @param source the source to perform the check for + * @param permission the permission to check + * @param defaultRequiredLevel the required permission level to check for as a fallback + * + * @return the result of the permission check + */ + static boolean check( + @NotNull SharedSuggestionProvider source, + @NotNull String permission, + int defaultRequiredLevel + ) { + return getPermissionValue(source, permission).orElseGet(() -> source.hasPermission(defaultRequiredLevel)); + } + + /** + * Performs a permission check, falling back to {@code false} if the resultant state + * is {@link TriState#DEFAULT}. + * + * @param source the source to perform the check for + * @param permission the permission to check + * + * @return the result of the permission check + */ + static boolean check(@NotNull SharedSuggestionProvider source, @NotNull String permission) { + return getPermissionValue(source, permission).orElse(false); + } + + /** + * Creates a predicate which returns the result of performing a permission check, + * falling back to the {@code defaultValue} if the resultant state is {@link TriState#DEFAULT}. + * + * @param permission the permission to check + * @param defaultValue the default value to use if nothing has been set + * + * @return a predicate that will perform the permission check + */ + static @NotNull Predicate require(@NotNull String permission, boolean defaultValue) { + Objects.requireNonNull(permission, "permission"); + return player -> check(player, permission, defaultValue); + } + + /** + * Creates a predicate which returns the result of performing a permission check, + * falling back to requiring the {@code defaultRequiredLevel} if the resultant state is + * {@link TriState#DEFAULT}. + * + * @param permission the permission to check + * @param defaultRequiredLevel the required permission level to check for as a fallback + * + * @return a predicate that will perform the permission check + */ + static @NotNull Predicate require(@NotNull String permission, int defaultRequiredLevel) { + Objects.requireNonNull(permission, "permission"); + return player -> check(player, permission, defaultRequiredLevel); + } + + /** + * Creates a predicate which returns the result of performing a permission check, + * falling back to {@code false} if the resultant state is {@link TriState#DEFAULT}. + * + * @param permission the permission to check + * + * @return a predicate that will perform the permission check + */ + static @NotNull Predicate require(@NotNull String permission) { + Objects.requireNonNull(permission, "permission"); + return player -> check(player, permission); + } + + /** + * Gets the {@link TriState state} of a {@code permission} for the given entity. + * + * @param entity the entity + * @param permission the permission + * + * @return the state of the permission + */ + static @NotNull TriState getPermissionValue(@NotNull Entity entity, @NotNull String permission) { + Objects.requireNonNull(entity, "entity"); + return getPermissionValue(Util.commandSourceFromEntity(entity), permission); + } + + /** + * Performs a permission check, falling back to the {@code defaultValue} if the resultant + * state is {@link TriState#DEFAULT}. + * + * @param entity the entity to perform the check for + * @param permission the permission to check + * @param defaultValue the default value to use if nothing has been set + * + * @return the result of the permission check + */ + static boolean check(@NotNull Entity entity, @NotNull String permission, boolean defaultValue) { + Objects.requireNonNull(entity, "entity"); + return check(Util.commandSourceFromEntity(entity), permission, defaultValue); + } + + /** + * Performs a permission check, falling back to requiring the {@code defaultRequiredLevel} + * if the resultant state is {@link TriState#DEFAULT}. + * + * @param entity the entity to perform the check for + * @param permission the permission to check + * @param defaultRequiredLevel the required permission level to check for as a fallback + * + * @return the result of the permission check + */ + static boolean check(@NotNull Entity entity, @NotNull String permission, int defaultRequiredLevel) { + Objects.requireNonNull(entity, "entity"); + return check(Util.commandSourceFromEntity(entity), permission, defaultRequiredLevel); + } + + /** + * Performs a permission check, falling back to {@code false} if the resultant state + * is {@link TriState#DEFAULT}. + * + * @param entity the entity to perform the check for + * @param permission the permission to check + * + * @return the result of the permission check + */ + static boolean check(@NotNull Entity entity, @NotNull String permission) { + Objects.requireNonNull(entity, "entity"); + return check(Util.commandSourceFromEntity(entity), permission); + } + + /** + * Gets the {@link TriState state} of a {@code permission} for the given (potentially) offline player. + * + * @param uuid the uuid of the player + * @param permission the permission + * + * @return the state of the permission + */ + static @NotNull CompletableFuture getPermissionValue(@NotNull UUID uuid, @NotNull String permission) { + Objects.requireNonNull(uuid, "uuid"); + Objects.requireNonNull(permission, "permission"); + return OfflinePermissionCheckEvent.EVENT.invoker().onPermissionCheck(uuid, permission); + } + + /** + * Performs a permission check, falling back to the {@code defaultValue} if the resultant + * state is {@link TriState#DEFAULT}. + * + * @param uuid the uuid of the player to perform the check for + * @param permission the permission to check + * @param defaultValue the default value to use if nothing has been set + * + * @return the result of the permission check + */ + static CompletableFuture check(@NotNull UUID uuid, @NotNull String permission, boolean defaultValue) { + return getPermissionValue(uuid, permission).thenApplyAsync(state -> state.orElse(defaultValue)); + } + + /** + * Performs a permission check, falling back to {@code false} if the resultant state + * is {@link TriState#DEFAULT}. + * + * @param uuid the uuid of the player to perform the check for + * @param permission the permission to check + * + * @return the result of the permission check + */ + static CompletableFuture check(@NotNull UUID uuid, @NotNull String permission) { + return getPermissionValue(uuid, permission).thenApplyAsync(state -> state.orElse(false)); + } + + /** + * Performs a permission check, falling back to {@code false} if the resultant state + * is {@link TriState#DEFAULT}. + * + * @param profile the player profile to perform the check for + * @param permission the permission to check + * @param defaultValue the default value to use if nothing has been set + * + * @return the result of the permission check + */ + static CompletableFuture check( + @NotNull GameProfile profile, + @NotNull String permission, + boolean defaultValue + ) { + Objects.requireNonNull(profile, "profile"); + return check(profile.getId(), permission, defaultValue); + } + + /** + * Performs a permission check, falling back to {@code false} if the resultant state + * is {@link TriState#DEFAULT}. + * + * @param profile the player profile to perform the check for + * @param permission the permission to check + * + * @return the result of the permission check + */ + static CompletableFuture check(@NotNull GameProfile profile, @NotNull String permission) { + Objects.requireNonNull(profile, "profile"); + return check(profile.getId(), permission); + } + + /** + * Performs a permission check, falling back to requiring the {@code defaultRequiredLevel} + * if the resultant state is {@link TriState#DEFAULT}. + * + * @param profile the player profile to perform the check for + * @param permission the permission to check + * @param defaultRequiredLevel the required permission level to check for as a fallback + * @param server instance to check permission level + * + * @return the result of the permission check + */ + static CompletableFuture check( + @NotNull GameProfile profile, + @NotNull String permission, + int defaultRequiredLevel, + @NotNull MinecraftServer server + ) { + Objects.requireNonNull(profile, "profile"); + Objects.requireNonNull(server, "server"); + BooleanSupplier permissionLevelCheck = () -> server.getProfilePermissions(profile) >= defaultRequiredLevel; + return getPermissionValue(profile.getId(), permission).thenApplyAsync(state -> state.orElseGet( + permissionLevelCheck)); + } + +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/permissions/TriState.java b/common/src/main/java/me/alexdevs/solstice/api/permissions/TriState.java new file mode 100644 index 00000000..7f030519 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/permissions/TriState.java @@ -0,0 +1,130 @@ +package me.alexdevs.solstice.api.permissions; + +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; +import java.util.Optional; +import java.util.function.BooleanSupplier; +import java.util.function.Supplier; + +/** + * Represents a boolean value which can be true, false or refer to a default value. + */ +public enum TriState { + /** + * Represents the boolean value of {@code false}. + */ + FALSE, + /** + * Represents a value that refers to a "default" value, often as a fallback. + */ + DEFAULT, + /** + * Represents the boolean value of {@code true}. + */ + TRUE; + + /** + * Gets the corresponding tri-state from a boolean value. + * + * @param bool the boolean value + * + * @return {@link TriState#TRUE} or {@link TriState#FALSE} depending on the value of the boolean. + */ + public static TriState of(boolean bool) { + return bool ? TRUE : FALSE; + } + + /** + * Gets a tri-state from a nullable boxed boolean. + * + * @param bool the boolean value + * + * @return {@link TriState#DEFAULT} if {@code null}. + * Otherwise {@link TriState#TRUE} or {@link TriState#FALSE} depending on the value of the boolean. + */ + public static TriState of(@Nullable Boolean bool) { + return bool == null ? DEFAULT : of(bool.booleanValue()); + } + + /** + * Gets the value of the tri-state. + * + * @return true if the tri-state is {@link TriState#TRUE}, + * otherwise false. + */ + public boolean get() { + return this == TRUE; + } + + /** + * Gets the value of the tri-state as a boxed, nullable boolean. + * + * @return {@code null} if {@link TriState#DEFAULT}. + * Otherwise {@code true} if {@link TriState#TRUE} or {@code false} if {@link TriState#FALSE}. + */ + @Nullable + public Boolean getBoxed() { + return this == DEFAULT ? null : this.get(); + } + + /** + * Gets the value of this tri-state. + * If the value is {@link TriState#DEFAULT} then use the supplied value. + * + * @param value the value to fall back to + * + * @return the value of the tri-state or the supplied value if {@link TriState#DEFAULT}. + */ + public boolean orElse(boolean value) { + return this == DEFAULT ? value : this.get(); + } + + /** + * Gets the value of this tri-state. + * If the value is {@link TriState#DEFAULT} then use the supplied value. + * + * @param supplier the supplier used to get the value to fall back to + * + * @return the value of the tri-state or the value of the supplier if the tri-state is {@link TriState#DEFAULT}. + */ + public boolean orElseGet(BooleanSupplier supplier) { + return this == DEFAULT ? supplier.getAsBoolean() : this.get(); + } + + /** + * Maps the boolean value of this tri-state if it is {@link TriState#TRUE} or {@link TriState#FALSE}. + * + * @param mapper the mapper to use + * @param the type of object being supplier by the mapper + * + * @return an optional containing the mapped value; {@link Optional#empty()} if the tri-state is {@link TriState#DEFAULT} or the value provided by the mapper is {@code null}. + */ + public Optional map(BooleanFunction<@Nullable ? extends T> mapper) { + Objects.requireNonNull(mapper, "Mapper function cannot be null"); + + if (this == DEFAULT) { + return Optional.empty(); + } + + return Optional.ofNullable(mapper.apply(this.get())); + } + + /** + * Gets the value of this tri-state, or throws an exception if this tri-state's value is {@link TriState#DEFAULT}. + * + * @param exceptionSupplier the supplying function that produces an exception to be thrown + * @param Type of the exception to be thrown + * + * @return the value + * + * @throws X if the value is {@link TriState#DEFAULT} + */ + public boolean orElseThrow(Supplier exceptionSupplier) throws X { + if (this != DEFAULT) { + return this.get(); + } + + throw exceptionSupplier.get(); + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/permissions/Util.java b/common/src/main/java/me/alexdevs/solstice/api/permissions/Util.java new file mode 100644 index 00000000..d81c005a --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/permissions/Util.java @@ -0,0 +1,24 @@ +package me.alexdevs.solstice.api.permissions; + +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; + +class Util { + static CommandSourceStack commandSourceFromEntity(Entity entity) { + if (entity instanceof ServerPlayer) { + return entity.createCommandSourceStack(); + } + Level world = entity.level(); + if (world instanceof ServerLevel) { +// return entity.createCommandSourceStack((ServerLevel) world); + return entity.createCommandSourceStack(); + } else { + throw new IllegalArgumentException("Entity '" + + entity + + "' is not a server entity. Try passing a CommandSource directly instead."); + } + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/platform/ModInfo.java b/common/src/main/java/me/alexdevs/solstice/api/platform/ModInfo.java new file mode 100644 index 00000000..acae1d9a --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/platform/ModInfo.java @@ -0,0 +1,4 @@ +package me.alexdevs.solstice.api.platform; + +public record ModInfo(String displayName, String version) { +} diff --git a/common/src/main/java/me/alexdevs/solstice/api/platform/PlatformHelper.java b/common/src/main/java/me/alexdevs/solstice/api/platform/PlatformHelper.java new file mode 100644 index 00000000..e1b7c947 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/api/platform/PlatformHelper.java @@ -0,0 +1,28 @@ +package me.alexdevs.solstice.api.platform; + +import java.nio.file.Path; +import java.util.ServiceLoader; + +public abstract class PlatformHelper { + private static final PlatformHelper INSTANCE = ServiceLoader.load(PlatformHelper.class).findFirst().orElseThrow(); + + public static PlatformHelper get() { + return INSTANCE; + } + + public abstract void init(); + + public abstract Path getGameDir(); + + public abstract Path getConfigDir(); + + public abstract boolean isModLoaded(String id); + + public abstract boolean isNativeForge(); + + public abstract Object getModContainer(); + + public abstract String getModVersion(); + + public abstract ModInfo getModInfo(String id); +} diff --git a/src/main/java/me/alexdevs/solstice/api/text/Components.java b/common/src/main/java/me/alexdevs/solstice/api/text/Components.java similarity index 98% rename from src/main/java/me/alexdevs/solstice/api/text/Components.java rename to common/src/main/java/me/alexdevs/solstice/api/text/Components.java index f8f5d528..cd2eb326 100644 --- a/src/main/java/me/alexdevs/solstice/api/text/Components.java +++ b/common/src/main/java/me/alexdevs/solstice/api/text/Components.java @@ -3,11 +3,11 @@ import eu.pb4.placeholders.api.TextParserUtils; import eu.pb4.placeholders.api.parsers.NodeParser; import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.api.text.parser.MarkdownParser; import me.alexdevs.solstice.core.coreModule.CoreModule; import me.alexdevs.solstice.modules.styling.StylingModule; import me.alexdevs.solstice.modules.styling.data.StylingConfig; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.PlayerChatMessage; diff --git a/src/main/java/me/alexdevs/solstice/api/text/Format.java b/common/src/main/java/me/alexdevs/solstice/api/text/Format.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/text/Format.java rename to common/src/main/java/me/alexdevs/solstice/api/text/Format.java diff --git a/src/main/java/me/alexdevs/solstice/api/text/RawPlaceholder.java b/common/src/main/java/me/alexdevs/solstice/api/text/RawPlaceholder.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/text/RawPlaceholder.java rename to common/src/main/java/me/alexdevs/solstice/api/text/RawPlaceholder.java diff --git a/src/main/java/me/alexdevs/solstice/api/text/parser/CodeParser.java b/common/src/main/java/me/alexdevs/solstice/api/text/parser/CodeParser.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/text/parser/CodeParser.java rename to common/src/main/java/me/alexdevs/solstice/api/text/parser/CodeParser.java diff --git a/src/main/java/me/alexdevs/solstice/api/text/parser/LinkParser.java b/common/src/main/java/me/alexdevs/solstice/api/text/parser/LinkParser.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/text/parser/LinkParser.java rename to common/src/main/java/me/alexdevs/solstice/api/text/parser/LinkParser.java diff --git a/src/main/java/me/alexdevs/solstice/api/text/parser/MarkdownComponentParser.java b/common/src/main/java/me/alexdevs/solstice/api/text/parser/MarkdownComponentParser.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/text/parser/MarkdownComponentParser.java rename to common/src/main/java/me/alexdevs/solstice/api/text/parser/MarkdownComponentParser.java diff --git a/src/main/java/me/alexdevs/solstice/api/text/parser/MarkdownParser.java b/common/src/main/java/me/alexdevs/solstice/api/text/parser/MarkdownParser.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/text/parser/MarkdownParser.java rename to common/src/main/java/me/alexdevs/solstice/api/text/parser/MarkdownParser.java diff --git a/src/main/java/me/alexdevs/solstice/api/text/tag/PhaseGradientTag.java b/common/src/main/java/me/alexdevs/solstice/api/text/tag/PhaseGradientTag.java similarity index 99% rename from src/main/java/me/alexdevs/solstice/api/text/tag/PhaseGradientTag.java rename to common/src/main/java/me/alexdevs/solstice/api/text/tag/PhaseGradientTag.java index 813b317c..3f77c5b9 100644 --- a/src/main/java/me/alexdevs/solstice/api/text/tag/PhaseGradientTag.java +++ b/common/src/main/java/me/alexdevs/solstice/api/text/tag/PhaseGradientTag.java @@ -16,7 +16,6 @@ /** * Implement an improved gradient that can also take in the phase. - *

* Most of the code is from Kyori Adventure. * * @see Kyori Adventure GradientTag diff --git a/src/main/java/me/alexdevs/solstice/api/utils/MathUtils.java b/common/src/main/java/me/alexdevs/solstice/api/utils/MathUtils.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/utils/MathUtils.java rename to common/src/main/java/me/alexdevs/solstice/api/utils/MathUtils.java diff --git a/src/main/java/me/alexdevs/solstice/api/utils/PlayerUtils.java b/common/src/main/java/me/alexdevs/solstice/api/utils/PlayerUtils.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/utils/PlayerUtils.java rename to common/src/main/java/me/alexdevs/solstice/api/utils/PlayerUtils.java diff --git a/src/main/java/me/alexdevs/solstice/api/utils/RegistryUtils.java b/common/src/main/java/me/alexdevs/solstice/api/utils/RegistryUtils.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/api/utils/RegistryUtils.java rename to common/src/main/java/me/alexdevs/solstice/api/utils/RegistryUtils.java diff --git a/src/main/java/me/alexdevs/solstice/core/CooldownManager.java b/common/src/main/java/me/alexdevs/solstice/core/CooldownManager.java similarity index 80% rename from src/main/java/me/alexdevs/solstice/core/CooldownManager.java rename to common/src/main/java/me/alexdevs/solstice/core/CooldownManager.java index 47efd4da..db5c5d99 100644 --- a/src/main/java/me/alexdevs/solstice/core/CooldownManager.java +++ b/common/src/main/java/me/alexdevs/solstice/core/CooldownManager.java @@ -2,11 +2,12 @@ import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.command.TimeSpan; +import me.alexdevs.solstice.api.events.proxy.ProxyServerPlayConnectionEvents; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.core.coreModule.CoreModule; -import me.lucko.fabric.api.permissions.v0.Permissions; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; + import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -16,10 +17,10 @@ public class CooldownManager { private final Map> cooldowns = new ConcurrentHashMap<>(); public CooldownManager() { - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - var playerUuid = handler.getPlayer().getUUID(); - cooldowns.computeIfAbsent(playerUuid, k -> new ConcurrentHashMap<>()); - }); + ProxyServerPlayConnectionEvents.JOIN.register((player, server) -> cooldowns.computeIfAbsent( + player.getUUID(), + k -> new ConcurrentHashMap<>() + )); Solstice.scheduler.scheduleAtFixedRate(this::tickDown, 0, 1, TimeUnit.SECONDS); } @@ -42,8 +43,7 @@ public boolean isExempt(ServerPlayer player, String node) { } public boolean onCooldown(ServerPlayer player, String node) { - if (isExempt(player, node)) - return false; + if (isExempt(player, node)) return false; var uuid = player.getUUID(); var cooldown = cooldowns.computeIfAbsent(uuid, k -> new ConcurrentHashMap<>()); return cooldown.getOrDefault(node, 0) > 0; @@ -54,16 +54,16 @@ public Component getMessage(ServerPlayer player, String node) { var cooldown = cooldowns.computeIfAbsent(uuid, k -> new ConcurrentHashMap<>()); var value = cooldown.getOrDefault(node, 0); var locale = Solstice.localeManager.getLocale(CoreModule.ID); - return locale.get("~cooldown", Map.of( - "timespan", Component.nullToEmpty(TimeSpan.toShortString(value)) - )); + return locale.get("~cooldown", Map.of("timespan", Component.nullToEmpty(TimeSpan.toShortString(value)))); } /** * Check and start cooldown if the player is not on cooldown. - * @param player Player - * @param node Permission node + * + * @param player Player + * @param node Permission node * @param seconds Cooldown seconds + * * @return Whether to execute */ public boolean trigger(ServerPlayer player, String node, int seconds) { diff --git a/src/main/java/me/alexdevs/solstice/core/Modules.java b/common/src/main/java/me/alexdevs/solstice/core/Modules.java similarity index 51% rename from src/main/java/me/alexdevs/solstice/core/Modules.java rename to common/src/main/java/me/alexdevs/solstice/core/Modules.java index f76aa2fc..b933d654 100644 --- a/src/main/java/me/alexdevs/solstice/core/Modules.java +++ b/common/src/main/java/me/alexdevs/solstice/core/Modules.java @@ -1,51 +1,56 @@ package me.alexdevs.solstice.core; -import com.mojang.brigadier.CommandDispatcher; import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.proxy.ProxyCommandRegistrationCallback; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.api.module.ModuleEntrypoint; import me.alexdevs.solstice.core.coreModule.CoreModule; -import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.commands.CommandBuildContext; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; + import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.ServiceLoader; public class Modules { private final HashSet modules = new HashSet<>(); public Modules() { - CommandRegistrationCallback.EVENT.register(this::registerCommands); + ProxyCommandRegistrationCallback.EVENT.register((dispatcher, buildCtx, selection) -> { + for (var module : modules) { + for (var command : module.getCommands()) { + command.register(dispatcher, buildCtx, selection); + } + } + }); } public void register() { modules.add(new CoreModule()); - var fabric = FabricLoader.getInstance(); - var moduleContainers = fabric.getEntrypointContainers("solstice", ModuleEntrypoint.class); - for (var container : moduleContainers) { - var mod = container.getProvider(); - var modMeta = mod.getMetadata(); - Solstice.LOGGER.info("Registering module provider '{}' ({}) v{}", modMeta.getName(), modMeta.getId(), modMeta.getVersion()); - try { - var provider = container.getEntrypoint(); - var providerModules = provider.register(); - for (var entry : providerModules) { - var moduleId = entry.getId(); - if (modules.stream().anyMatch(m -> m.getId().equals(moduleId))) { - Solstice.LOGGER.warn("Module ID conflict: {}", entry.getId()); - continue; - } - - modules.add(entry); + for (var provider : ServiceLoader.load(ModuleEntrypoint.class)) { + registerModule(provider); + } + } + + private void registerModule(ModuleEntrypoint provider) { + Solstice.LOGGER.info("Registering module provider '{}'", provider.getClass().getName()); + + try { + var providerModules = provider.register(); + + for (var entry : providerModules) { + var moduleId = entry.getId(); + + if (modules.stream().anyMatch(m -> m.getId().equals(moduleId))) { + Solstice.LOGGER.warn("Module ID conflict: {}", entry.getId()); + continue; } - } catch (Exception e) { - Solstice.LOGGER.error("Error registering a module from {}", modMeta.getId(), e); + + modules.add(entry); } + } catch (Exception e) { + Solstice.LOGGER.error("Error registering a module from {}", provider.getClass().getName(), e); } } @@ -88,12 +93,4 @@ public void initModules() { } } } - - private void registerCommands(CommandDispatcher dispatcher, CommandBuildContext commandRegistry, Commands.CommandSelection environment) { - for (var module : modules) { - for (var command : module.getCommands()) { - command.register(dispatcher, commandRegistry, environment); - } - } - } } diff --git a/src/main/java/me/alexdevs/solstice/core/Scheduler.java b/common/src/main/java/me/alexdevs/solstice/core/Scheduler.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/core/Scheduler.java rename to common/src/main/java/me/alexdevs/solstice/core/Scheduler.java diff --git a/src/main/java/me/alexdevs/solstice/core/ToggleableConfig.java b/common/src/main/java/me/alexdevs/solstice/core/ToggleableConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/core/ToggleableConfig.java rename to common/src/main/java/me/alexdevs/solstice/core/ToggleableConfig.java diff --git a/src/main/java/me/alexdevs/solstice/core/UserCache.java b/common/src/main/java/me/alexdevs/solstice/core/UserCache.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/core/UserCache.java rename to common/src/main/java/me/alexdevs/solstice/core/UserCache.java diff --git a/src/main/java/me/alexdevs/solstice/core/WarmUpManager.java b/common/src/main/java/me/alexdevs/solstice/core/WarmUpManager.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/core/WarmUpManager.java rename to common/src/main/java/me/alexdevs/solstice/core/WarmUpManager.java diff --git a/src/main/java/me/alexdevs/solstice/core/coreModule/CoreModule.java b/common/src/main/java/me/alexdevs/solstice/core/coreModule/CoreModule.java similarity index 74% rename from src/main/java/me/alexdevs/solstice/core/coreModule/CoreModule.java rename to common/src/main/java/me/alexdevs/solstice/core/coreModule/CoreModule.java index 20588a70..f70c478c 100644 --- a/src/main/java/me/alexdevs/solstice/core/coreModule/CoreModule.java +++ b/common/src/main/java/me/alexdevs/solstice/core/coreModule/CoreModule.java @@ -4,6 +4,7 @@ import me.alexdevs.solstice.api.ServerLocation; import me.alexdevs.solstice.api.events.SolsticeEvents; import me.alexdevs.solstice.api.events.WorldSaveCallback; +import me.alexdevs.solstice.api.events.proxy.ProxyServerPlayConnectionEvents; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.core.coreModule.commands.PingCommand; import me.alexdevs.solstice.core.coreModule.commands.ServerStatCommand; @@ -11,8 +12,8 @@ import me.alexdevs.solstice.core.coreModule.data.CoreConfig; import me.alexdevs.solstice.core.coreModule.data.CoreLocale; import me.alexdevs.solstice.core.coreModule.data.CorePlayerData; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.world.entity.Entity; + import java.util.Date; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -29,20 +30,20 @@ public void init() { Solstice.configManager.registerData(ID, CoreConfig.class, CoreConfig::new); Solstice.localeManager.registerShared(CoreLocale.SHARED); Solstice.localeManager.registerModule(ID, CoreLocale.MODULE); - Solstice.playerData.registerData(ID, CorePlayerData.class, CorePlayerData::new); commands.add(new SolsticeCommand(this)); commands.add(new ServerStatCommand(this)); commands.add(new PingCommand(this)); - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - Solstice.getUserCache().add(handler.getPlayer().getGameProfile()); - var player = handler.getPlayer(); + ProxyServerPlayConnectionEvents.JOIN.register((player, server) -> { + Solstice.getUserCache().add(player.getGameProfile()); + var playerData = Solstice.playerData.get(player).getData(CorePlayerData.class); + playerData.username = player.getGameProfile().getName(); playerData.lastSeenDate = new Date(); - playerData.ipAddress = handler.getPlayer().getIpAddress(); + playerData.ipAddress = player.getIpAddress(); if (playerData.firstJoinedDate == null) { Solstice.LOGGER.info("Player {} joined for the first time!", player.getGameProfile().getName()); @@ -51,22 +52,28 @@ public void init() { } if (playerData.username != null && !playerData.username.equals(player.getGameProfile().getName())) { - Solstice.LOGGER.info("Player {} has changed their username from {}", player.getGameProfile().getName(), playerData.username); + Solstice.LOGGER.info( + "Player {} has changed their username from {}", + player.getGameProfile().getName(), + playerData.username + ); + SolsticeEvents.USERNAME_CHANGE.invoker().onUsernameChange(player, playerData.username); } }); - ServerPlayConnectionEvents.DISCONNECT.register((handler, client) -> { - var playerData = Solstice.playerData.get(handler.getPlayer()).getData(CorePlayerData.class); + ProxyServerPlayConnectionEvents.DISCONNECT.register((player, client) -> { + var playerData = Solstice.playerData.get(player).getData(CorePlayerData.class); + playerData.lastSeenDate = new Date(); - playerData.logoffPosition = new ServerLocation(handler.getPlayer()); - Solstice.scheduler.schedule(() -> { - Solstice.playerData.dispose(handler.getPlayer().getUUID()); - }, 1, TimeUnit.SECONDS); + playerData.logoffPosition = new ServerLocation(player); + + Solstice.scheduler.schedule(() -> Solstice.playerData.dispose(player.getUUID()), 1, TimeUnit.SECONDS); }); WorldSaveCallback.EVENT.register((server, suppressLogs, flush, force) -> { var uuids = server.getPlayerList().getPlayers().stream().map(Entity::getUUID).toList(); + Solstice.playerData.disposeMissing(uuids); }); } @@ -81,8 +88,8 @@ public static CorePlayerData getPlayerData(UUID uuid) { public static String getUsername(UUID uuid) { var profile = Solstice.server.getProfileCache().get(uuid); - if(profile.isPresent()) - return profile.get().getName(); + + if (profile.isPresent()) return profile.get().getName(); return uuid.toString(); } diff --git a/src/main/java/me/alexdevs/solstice/core/coreModule/commands/PingCommand.java b/common/src/main/java/me/alexdevs/solstice/core/coreModule/commands/PingCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/core/coreModule/commands/PingCommand.java rename to common/src/main/java/me/alexdevs/solstice/core/coreModule/commands/PingCommand.java diff --git a/src/main/java/me/alexdevs/solstice/core/coreModule/commands/ServerStatCommand.java b/common/src/main/java/me/alexdevs/solstice/core/coreModule/commands/ServerStatCommand.java similarity index 99% rename from src/main/java/me/alexdevs/solstice/core/coreModule/commands/ServerStatCommand.java rename to common/src/main/java/me/alexdevs/solstice/core/coreModule/commands/ServerStatCommand.java index 0305d72a..e4c255c0 100644 --- a/src/main/java/me/alexdevs/solstice/core/coreModule/commands/ServerStatCommand.java +++ b/common/src/main/java/me/alexdevs/solstice/core/coreModule/commands/ServerStatCommand.java @@ -31,13 +31,13 @@ public LiteralArgumentBuilder command(String name) { .executes(context -> { var locale = module.locale(); var placeholderContext = PlaceholderContext.of(context.getSource()); - var messages = new ArrayList(); messages.add(locale.get("stat.tps", placeholderContext)); var uptime = Duration.ofMillis(ManagementFactory.getRuntimeMXBean().getUptime()); var uptimeFormatted = TimeSpan.toShortString((int)uptime.getSeconds()); + messages.add(locale.get("stat.uptime", placeholderContext, Map.of( "uptime", Component.nullToEmpty(uptimeFormatted) ))); @@ -63,6 +63,7 @@ public LiteralArgumentBuilder command(String name) { ))); var text = Component.empty(); + text.append(locale.get("stat.title")); for(var message : messages) { diff --git a/common/src/main/java/me/alexdevs/solstice/core/coreModule/commands/SolsticeCommand.java b/common/src/main/java/me/alexdevs/solstice/core/coreModule/commands/SolsticeCommand.java new file mode 100644 index 00000000..c9a39f26 --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/core/coreModule/commands/SolsticeCommand.java @@ -0,0 +1,139 @@ +package me.alexdevs.solstice.core.coreModule.commands; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.SolsticeEvents; +import me.alexdevs.solstice.api.module.Debug; +import me.alexdevs.solstice.api.module.ModCommand; +import me.alexdevs.solstice.api.platform.PlatformHelper; +import me.alexdevs.solstice.api.text.Format; +import me.alexdevs.solstice.core.coreModule.CoreModule; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; +import net.minecraft.network.chat.Style; + +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +import static net.minecraft.commands.Commands.literal; + +public class SolsticeCommand extends ModCommand { + public SolsticeCommand(CoreModule module) { + super(module); + } + + @Override + public List getNames() { + return List.of("solstice", "sol"); + } + + @Override + public LiteralArgumentBuilder command(String name) { + return literal(name).requires(require(true)).executes(context -> { + var modInfo = PlatformHelper.get().getModInfo(Solstice.MOD_ID); + + if (modInfo == null) { + context.getSource() + .sendSuccess(() -> Component.nullToEmpty("Could not find self in mod list???"), false); + return 1; + } + + var placeholders = Map.of( + "name", + Component.nullToEmpty(modInfo.displayName()), + "version", + Component.nullToEmpty(modInfo.version()) + ); + + var text = Format.parse("${name} v${version}", placeholders); + context.getSource().sendSuccess(() -> text, false); + + return 1; + }).then(literal("reload").requires(require("reload", 3)).executes(context -> { + try { + Solstice.configManager.loadData(true); + Solstice.localeManager.reload(); + } catch (Exception e) { + Solstice.LOGGER.error("Failed to reload Solstice", e); + context.getSource().sendSuccess( + () -> Component.nullToEmpty("Failed to load Solstice config. Check console for more info."), + true + ); + return 1; + } + + SolsticeEvents.RELOAD.invoker().onReload(Solstice.getInstance()); + + context.getSource().sendSuccess(() -> Component.nullToEmpty("Reloaded Solstice config"), true); + + return 1; + })).then(literal("debug").requires(require("debug", 4)).then(literal("gen-command-list").executes(context -> { + var builder = new StringBuilder(); + + var list = new ArrayList<>(Debug.commandDebugList); + + list.sort(Comparator.comparing(Debug.CommandDebug::module)); + + builder.append(String.format("| %s | %s | %s | %s |\n", "Module", "Command", "Aliases", "Permission")); + builder.append("|---|---|---|---|\n"); + for (var command : list) { + builder.append(String.format( + "| %s | %s | %s | %s |\n", + command.module(), + command.command(), + String.join(" ", command.commands()), + command.permission() + )); + } + + var output = builder.toString(); + var file = PlatformHelper.get().getGameDir().resolve("solstice-commands.md").toFile(); + + try (var fw = new FileWriter(file)) { + fw.write(output); + } catch (IOException e) { + throw new SimpleCommandExceptionType(Component.nullToEmpty(e.getMessage())).create(); + } + + context.getSource().sendSuccess(() -> Component.nullToEmpty("Generated 'solstice-commands.md'"), true); + + return 1; + })).then(literal("tags").executes(context -> { + var player = context.getSource().getPlayerOrException(); + + var hand = player.getUsedItemHand(); + var itemStack = player.getItemInHand(hand); + + var entry = itemStack.getItemHolder().unwrapKey().get(); + var entryString = String.format("Tags for [%s / %s]:", entry.registry(), entry.location()); + + var text = Component.empty(); + text.append(Component.nullToEmpty(entryString)); + var tags = itemStack.getTags().iterator(); + while (tags.hasNext()) { + var tag = tags.next(); + text.append(Component.nullToEmpty("\n")); + text.append(Component.literal(" #" + tag.location()) + .setStyle(Style.EMPTY.withHoverEvent(new HoverEvent( + HoverEvent.Action.SHOW_TEXT, + Component.nullToEmpty("Click to copy") + )) + .withClickEvent(new ClickEvent( + ClickEvent.Action.COPY_TO_CLIPBOARD, + "#" + tag.location() + )))); + } + + context.getSource().sendSuccess(() -> text, false); + + return 1; + }))); + } +} diff --git a/src/main/java/me/alexdevs/solstice/core/coreModule/data/CoreConfig.java b/common/src/main/java/me/alexdevs/solstice/core/coreModule/data/CoreConfig.java similarity index 88% rename from src/main/java/me/alexdevs/solstice/core/coreModule/data/CoreConfig.java rename to common/src/main/java/me/alexdevs/solstice/core/coreModule/data/CoreConfig.java index 1f866dd1..955dd10d 100644 --- a/src/main/java/me/alexdevs/solstice/core/coreModule/data/CoreConfig.java +++ b/common/src/main/java/me/alexdevs/solstice/core/coreModule/data/CoreConfig.java @@ -19,4 +19,7 @@ public class CoreConfig { @Comment("Format to use when hovering over the link in chat.") public String linkHover = "${url}"; + + @Comment("Force Minecraft to display the real ping numbers.") + public boolean useRealPing = true; } diff --git a/src/main/java/me/alexdevs/solstice/core/coreModule/data/CoreLocale.java b/common/src/main/java/me/alexdevs/solstice/core/coreModule/data/CoreLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/core/coreModule/data/CoreLocale.java rename to common/src/main/java/me/alexdevs/solstice/core/coreModule/data/CoreLocale.java diff --git a/src/main/java/me/alexdevs/solstice/core/coreModule/data/CorePlayerData.java b/common/src/main/java/me/alexdevs/solstice/core/coreModule/data/CorePlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/core/coreModule/data/CorePlayerData.java rename to common/src/main/java/me/alexdevs/solstice/core/coreModule/data/CorePlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/data/PlayerData.java b/common/src/main/java/me/alexdevs/solstice/data/PlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/data/PlayerData.java rename to common/src/main/java/me/alexdevs/solstice/data/PlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/data/PlayerDataManager.java b/common/src/main/java/me/alexdevs/solstice/data/PlayerDataManager.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/data/PlayerDataManager.java rename to common/src/main/java/me/alexdevs/solstice/data/PlayerDataManager.java diff --git a/src/main/java/me/alexdevs/solstice/data/ServerData.java b/common/src/main/java/me/alexdevs/solstice/data/ServerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/data/ServerData.java rename to common/src/main/java/me/alexdevs/solstice/data/ServerData.java diff --git a/src/main/java/me/alexdevs/solstice/integrations/ConnectorIntegration.java b/common/src/main/java/me/alexdevs/solstice/integrations/ConnectorIntegration.java similarity index 53% rename from src/main/java/me/alexdevs/solstice/integrations/ConnectorIntegration.java rename to common/src/main/java/me/alexdevs/solstice/integrations/ConnectorIntegration.java index 26df3947..5ebeb5ee 100644 --- a/src/main/java/me/alexdevs/solstice/integrations/ConnectorIntegration.java +++ b/common/src/main/java/me/alexdevs/solstice/integrations/ConnectorIntegration.java @@ -1,17 +1,20 @@ package me.alexdevs.solstice.integrations; import me.alexdevs.solstice.Solstice; -import net.fabricmc.loader.api.FabricLoader; +import me.alexdevs.solstice.api.platform.PlatformHelper; public class ConnectorIntegration { public static final String CONNECTOR_ID = "connector"; private static boolean isForge = false; public static void register() { - var optContainer = FabricLoader.getInstance().getModContainer(CONNECTOR_ID); - if (optContainer.isPresent()) { + if (PlatformHelper.get().isNativeForge()) { isForge = true; - Solstice.LOGGER.warn("Sinytra connector detected. Support may be limited!"); + } else { + if (PlatformHelper.get().isModLoaded(CONNECTOR_ID)) { + isForge = true; + Solstice.LOGGER.warn("Sinytra connector detected. Support may be limited!"); + } } } diff --git a/src/main/java/me/alexdevs/solstice/integrations/LuckPermsIntegration.java b/common/src/main/java/me/alexdevs/solstice/integrations/LuckPermsIntegration.java similarity index 62% rename from src/main/java/me/alexdevs/solstice/integrations/LuckPermsIntegration.java rename to common/src/main/java/me/alexdevs/solstice/integrations/LuckPermsIntegration.java index 96d56ee2..ba855c45 100644 --- a/src/main/java/me/alexdevs/solstice/integrations/LuckPermsIntegration.java +++ b/common/src/main/java/me/alexdevs/solstice/integrations/LuckPermsIntegration.java @@ -1,12 +1,12 @@ package me.alexdevs.solstice.integrations; import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.proxy.ProxyServerLifecycleEvents; import me.alexdevs.solstice.api.events.SolsticeEvents; -import me.lucko.fabric.api.permissions.v0.OfflinePermissionCheckEvent; -import me.lucko.fabric.api.permissions.v0.PermissionCheckEvent; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.util.TriState; -import net.fabricmc.loader.api.FabricLoader; +import me.alexdevs.solstice.api.permissions.OfflinePermissionCheckEvent; +import me.alexdevs.solstice.api.permissions.PermissionCheckEvent; +import me.alexdevs.solstice.api.permissions.TriState; +import me.alexdevs.solstice.api.platform.PlatformHelper; import net.luckperms.api.LuckPerms; import net.luckperms.api.LuckPermsProvider; import net.luckperms.api.event.node.NodeAddEvent; @@ -37,18 +37,20 @@ public class LuckPermsIntegration { public static void register() { if (!isAvailable()) { - Solstice.LOGGER.warn("LuckPerms not available! It is recommended to install LuckPerms to configure permissions and groups."); + Solstice.LOGGER.warn( + "LuckPerms not available! It is recommended to install LuckPerms to configure permissions and groups."); return; } - var container = FabricLoader.getInstance().getModContainer(Solstice.MOD_ID).get(); - - ServerLifecycleEvents.SERVER_STARTED.register(server -> { + ProxyServerLifecycleEvents.SERVER_STARTED.register(server -> { luckPerms = LuckPermsProvider.get(); available = true; + var eventBus = luckPerms.getEventBus(); if (!ConnectorIntegration.isForge()) { + var container = PlatformHelper.get().getModContainer(); + eventBus.subscribe(container, UserDataRecalculateEvent.class, Listeners::onDataRecalculate); eventBus.subscribe(container, NodeAddEvent.class, Listeners::onNodeAdded); eventBus.subscribe(container, NodeRemoveEvent.class, Listeners::onNodeRemoved); @@ -59,7 +61,7 @@ public static void register() { eventBus.subscribe(NodeRemoveEvent.class, Listeners::onNodeRemoved); eventBus.subscribe(NodeClearEvent.class, Listeners::onNodeCleared); - Solstice.LOGGER.warn("Permissions API is not available. Solstice is now taking over!"); + Solstice.LOGGER.warn("Fabric Permissions API is not available. Solstice is now taking over!"); // become the permissions api PermissionCheckEvent.EVENT.register((suggestion, permission) -> { @@ -76,15 +78,15 @@ public static void register() { OfflinePermissionCheckEvent.EVENT.register((uuid, permission) -> { var future = new CompletableFuture(); + checkPermission(uuid, permission).thenAcceptAsync(result -> { - future.complete( - switch (result) { - case TRUE -> TriState.TRUE; - case FALSE -> TriState.FALSE; - case UNDEFINED -> TriState.DEFAULT; - } - ); + future.complete(switch (result) { + case TRUE -> TriState.TRUE; + case FALSE -> TriState.FALSE; + case UNDEFINED -> TriState.DEFAULT; + }); }); + return future; }); } @@ -97,7 +99,7 @@ public static void register() { } public static boolean isAvailable() { - return FabricLoader.getInstance().isModLoaded("luckperms"); + return PlatformHelper.get().isModLoaded("luckperms"); } public static @Nullable String getPrefix(ServerPlayer player) { @@ -105,15 +107,17 @@ public static boolean isAvailable() { return null; } - return prefixMap.computeIfAbsent(player.getUUID(), uuid -> { - try { - var playerMeta = luckPerms.getPlayerAdapter(ServerPlayer.class).getMetaData(player); - return Optional.ofNullable(playerMeta.getPrefix()); - } catch (IllegalStateException e) { - // Fake player may throw with IllegalStateException - return Optional.empty(); - } - }).orElse(null); + return prefixMap.computeIfAbsent( + player.getUUID(), uuid -> { + try { + var playerMeta = luckPerms.getPlayerAdapter(ServerPlayer.class).getMetaData(player); + return Optional.ofNullable(playerMeta.getPrefix()); + } catch (IllegalStateException e) { + // Fake player may throw with IllegalStateException + return Optional.empty(); + } + } + ).orElse(null); } public static @Nullable String getSuffix(ServerPlayer player) { @@ -121,15 +125,17 @@ public static boolean isAvailable() { return null; } - return suffixMap.computeIfAbsent(player.getUUID(), uuid -> { - try { - var playerMeta = luckPerms.getPlayerAdapter(ServerPlayer.class).getMetaData(player); - return Optional.ofNullable(playerMeta.getSuffix()); - } catch (IllegalStateException e) { - // Fake player may throw with IllegalStateException - return Optional.empty(); - } - }).orElse(null); + return suffixMap.computeIfAbsent( + player.getUUID(), uuid -> { + try { + var playerMeta = luckPerms.getPlayerAdapter(ServerPlayer.class).getMetaData(player); + return Optional.ofNullable(playerMeta.getSuffix()); + } catch (IllegalStateException e) { + // Fake player may throw with IllegalStateException + return Optional.empty(); + } + } + ).orElse(null); } public static boolean isInGroup(ServerPlayer player, String group) { @@ -162,15 +168,12 @@ public static CompletableFuture checkPermission(UUID uuid, String perm if (user == null) { future.complete(Tristate.UNDEFINED); } else { - future.complete(user - .getCachedData() - .getPermissionData() - .checkPermission(permission)); + future.complete(user.getCachedData().getPermissionData().checkPermission(permission)); } } else { - luckPerms.getUserManager().loadUser(uuid).thenAccept(user -> future - .complete(user - .getCachedData() + luckPerms.getUserManager() + .loadUser(uuid) + .thenAccept(user -> future.complete(user.getCachedData() .getPermissionData() .checkPermission(permission))); } @@ -199,40 +202,46 @@ public static void onDataRecalculate(UserDataRecalculateEvent event) { public static void onNodeAdded(NodeAddEvent event) { if (event.isGroup()) { - Solstice.scheduler.scheduleSync(() -> { - if (event.getNode().getType() == NodeType.PREFIX) { - prefixMap.clear(); - } else if (event.getNode().getType() == NodeType.SUFFIX) { - suffixMap.clear(); - } - - recalculateUsersCache(); - }, 50, TimeUnit.MILLISECONDS); + Solstice.scheduler.scheduleSync( + () -> { + if (event.getNode().getType() == NodeType.PREFIX) { + prefixMap.clear(); + } else if (event.getNode().getType() == NodeType.SUFFIX) { + suffixMap.clear(); + } + + recalculateUsersCache(); + }, 50, TimeUnit.MILLISECONDS + ); } } public static void onNodeRemoved(NodeRemoveEvent event) { if (event.isGroup()) { - Solstice.scheduler.scheduleSync(() -> { - if (event.getNode().getType() == NodeType.PREFIX) { - prefixMap.clear(); - } else if (event.getNode().getType() == NodeType.SUFFIX) { - suffixMap.clear(); - } - - recalculateUsersCache(); - }, 50, TimeUnit.MILLISECONDS); + Solstice.scheduler.scheduleSync( + () -> { + if (event.getNode().getType() == NodeType.PREFIX) { + prefixMap.clear(); + } else if (event.getNode().getType() == NodeType.SUFFIX) { + suffixMap.clear(); + } + + recalculateUsersCache(); + }, 50, TimeUnit.MILLISECONDS + ); } } public static void onNodeCleared(NodeClearEvent event) { if (event.isGroup()) { - Solstice.scheduler.scheduleSync(() -> { - prefixMap.clear(); - suffixMap.clear(); - - recalculateUsersCache(); - }, 50, TimeUnit.MILLISECONDS); + Solstice.scheduler.scheduleSync( + () -> { + prefixMap.clear(); + suffixMap.clear(); + + recalculateUsersCache(); + }, 50, TimeUnit.MILLISECONDS + ); } } } diff --git a/common/src/main/java/me/alexdevs/solstice/integrations/TrinketsApiProxy.java b/common/src/main/java/me/alexdevs/solstice/integrations/TrinketsApiProxy.java new file mode 100644 index 00000000..585a1e4c --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/integrations/TrinketsApiProxy.java @@ -0,0 +1,21 @@ +package me.alexdevs.solstice.integrations; + +import net.minecraft.world.Container; +import net.minecraft.world.entity.LivingEntity; + +import java.util.Map; +import java.util.Optional; +import java.util.ServiceLoader; + +public abstract class TrinketsApiProxy { + private static final TrinketsApiProxy INSTANCE = ServiceLoader.load(TrinketsApiProxy.class) + .findFirst() + .orElseThrow(); + + public static TrinketsApiProxy get() { + return INSTANCE; + } + + // Basically, this does getTrinketComponent(target).getInventory().mapValues((map) -> map.mapValues(inv -> inv.values())) + public abstract Optional>> getTrinketComponentInventory(LivingEntity target); +} diff --git a/src/main/java/me/alexdevs/solstice/integrations/TrinketsIntegration.java b/common/src/main/java/me/alexdevs/solstice/integrations/TrinketsIntegration.java similarity index 52% rename from src/main/java/me/alexdevs/solstice/integrations/TrinketsIntegration.java rename to common/src/main/java/me/alexdevs/solstice/integrations/TrinketsIntegration.java index 20130fc9..c598241a 100644 --- a/src/main/java/me/alexdevs/solstice/integrations/TrinketsIntegration.java +++ b/common/src/main/java/me/alexdevs/solstice/integrations/TrinketsIntegration.java @@ -1,9 +1,9 @@ package me.alexdevs.solstice.integrations; -import net.fabricmc.loader.api.FabricLoader; +import me.alexdevs.solstice.api.platform.PlatformHelper; public class TrinketsIntegration { public static boolean isAvailable() { - return FabricLoader.getInstance().isModLoaded("trinkets"); + return PlatformHelper.get().isModLoaded("trinkets"); } } diff --git a/src/main/java/me/alexdevs/solstice/locale/Locale.java b/common/src/main/java/me/alexdevs/solstice/locale/Locale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/locale/Locale.java rename to common/src/main/java/me/alexdevs/solstice/locale/Locale.java diff --git a/src/main/java/me/alexdevs/solstice/locale/LocaleManager.java b/common/src/main/java/me/alexdevs/solstice/locale/LocaleManager.java similarity index 99% rename from src/main/java/me/alexdevs/solstice/locale/LocaleManager.java rename to common/src/main/java/me/alexdevs/solstice/locale/LocaleManager.java index 6fb73040..a7dfadc8 100644 --- a/src/main/java/me/alexdevs/solstice/locale/LocaleManager.java +++ b/common/src/main/java/me/alexdevs/solstice/locale/LocaleManager.java @@ -24,6 +24,7 @@ public class LocaleManager { .setPrettyPrinting() .setDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX") .create(); + private static final Pattern sharedRegex = Pattern.compile("^shared\\.(.+)$"); private static final Pattern moduleRegex = Pattern.compile("^module\\.(\\w+)\\.(.+)$"); private final Path path; diff --git a/src/main/java/me/alexdevs/solstice/mixin/SolsticeMixinConfigPlugin.java b/common/src/main/java/me/alexdevs/solstice/mixin/SolsticeMixinConfigPlugin.java similarity index 99% rename from src/main/java/me/alexdevs/solstice/mixin/SolsticeMixinConfigPlugin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/SolsticeMixinConfigPlugin.java index cf2cc0df..8987a30c 100644 --- a/src/main/java/me/alexdevs/solstice/mixin/SolsticeMixinConfigPlugin.java +++ b/common/src/main/java/me/alexdevs/solstice/mixin/SolsticeMixinConfigPlugin.java @@ -22,8 +22,10 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { var moduleMixin = mixinClassName.replace(packageBase, ""); var parts = moduleMixin.split("\\."); var module = parts[0].toLowerCase(); + return config.isEnabled(module); } + return true; } diff --git a/src/main/java/me/alexdevs/solstice/mixin/events/CommandEventsMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/events/CommandEventsMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/events/CommandEventsMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/events/CommandEventsMixin.java diff --git a/common/src/main/java/me/alexdevs/solstice/mixin/events/LivingEntityMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/events/LivingEntityMixin.java new file mode 100644 index 00000000..17d92fff --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/mixin/events/LivingEntityMixin.java @@ -0,0 +1,40 @@ +package me.alexdevs.solstice.mixin.events; + +import me.alexdevs.solstice.api.events.proxy.ProxyEntitySleepEvents; +import me.alexdevs.solstice.api.events.proxy.ProxyServerLivingEntityEvents; +import net.minecraft.core.BlockPos; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.LivingEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Optional; + +@Mixin(LivingEntity.class) +public abstract class LivingEntityMixin { + @Shadow + public abstract Optional getSleepingPos(); + + @Inject( + method = "die", at = @At( + value = "INVOKE", + target = "net/minecraft/world/level/Level.broadcastEntityEvent(Lnet/minecraft/world/entity/Entity;B)V" + ) + ) + private void notifyDeath(DamageSource source, CallbackInfo ci) { + ProxyServerLivingEntityEvents.AFTER_DEATH.invoker().afterDeath((LivingEntity) (Object) this, source); + } + + @Inject(method = "stopSleeping", at = @At("HEAD")) + private void onWakeUp(CallbackInfo info) { + BlockPos sleepingPos = getSleepingPos().orElse(null); + + // If actually asleep - this method is often called with data loading, syncing etc. "just to be sure" + if (sleepingPos != null) { + ProxyEntitySleepEvents.STOP_SLEEPING.invoker().onStopSleeping((LivingEntity) (Object) this, sleepingPos); + } + } +} diff --git a/common/src/main/java/me/alexdevs/solstice/mixin/events/PlayerListMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/events/PlayerListMixin.java new file mode 100644 index 00000000..332e824f --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/mixin/events/PlayerListMixin.java @@ -0,0 +1,46 @@ +package me.alexdevs.solstice.mixin.events; + +import me.alexdevs.solstice.api.events.proxy.ProxyServerMessageEvents; +import me.alexdevs.solstice.api.events.proxy.ProxyServerPlayerEvents; +import net.minecraft.network.chat.ChatType; +import net.minecraft.network.chat.PlayerChatMessage; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.players.PlayerList; +import net.minecraft.world.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(PlayerList.class) +public class PlayerListMixin { + @Inject( + method = "broadcastChatMessage(Lnet/minecraft/network/chat/PlayerChatMessage;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/network/chat/ChatType$Bound;)V", + at = @At("HEAD"), + cancellable = true + ) + private void onSendChatMessage( + PlayerChatMessage message, + ServerPlayer sender, + ChatType.Bound params, + CallbackInfo ci + ) { + if (!ProxyServerMessageEvents.ALLOW_CHAT_MESSAGE.invoker().allowChatMessage(message, sender, params)) { + ci.cancel(); + return; + } + + ProxyServerMessageEvents.CHAT_MESSAGE.invoker().onChatMessage(message, sender, params); + } + + @Inject(method = "respawn", at = @At("TAIL")) + private void afterRespawn( + ServerPlayer oldPlayer, + boolean alive, + Entity.RemovalReason removalReason, + CallbackInfoReturnable cir + ) { + ProxyServerPlayerEvents.AFTER_RESPAWN.invoker().afterRespawn(oldPlayer, cir.getReturnValue(), alive); + } +} diff --git a/src/main/java/me/alexdevs/solstice/mixin/events/WorldSaveEventMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/events/WorldSaveEventMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/events/WorldSaveEventMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/events/WorldSaveEventMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/admin/ConnectionBypassMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/admin/ConnectionBypassMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/admin/ConnectionBypassMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/admin/ConnectionBypassMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/afk/FixPlayerSleepPercentageMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/afk/FixPlayerSleepPercentageMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/afk/FixPlayerSleepPercentageMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/afk/FixPlayerSleepPercentageMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/back/PreTeleportMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/back/PreTeleportMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/back/PreTeleportMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/back/PreTeleportMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/ban/CustomBanMessageMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/ban/CustomBanMessageMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/ban/CustomBanMessageMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/ban/CustomBanMessageMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/core/RealPingMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/core/RealPingMixin.java similarity index 60% rename from src/main/java/me/alexdevs/solstice/mixin/modules/core/RealPingMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/core/RealPingMixin.java index d42ca265..3def5a19 100644 --- a/src/main/java/me/alexdevs/solstice/mixin/modules/core/RealPingMixin.java +++ b/common/src/main/java/me/alexdevs/solstice/mixin/modules/core/RealPingMixin.java @@ -1,6 +1,7 @@ package me.alexdevs.solstice.mixin.modules.core; import com.llamalad7.mixinextras.sugar.Local; +import me.alexdevs.solstice.core.coreModule.CoreModule; import net.minecraft.server.network.ServerCommonPacketListenerImpl; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; @@ -10,11 +11,18 @@ @Mixin(ServerCommonPacketListenerImpl.class) public abstract class RealPingMixin { - @Shadow - private int latency; + @Shadow private int latency; - @Redirect(method = "handleKeepAlive", at = @At(value = "FIELD", target = "Lnet/minecraft/server/network/ServerCommonPacketListenerImpl;latency:I", opcode = Opcodes.PUTFIELD)) + @Redirect( + method = "handleKeepAlive", at = @At( + value = "FIELD", + target = "Lnet/minecraft/server/network/ServerCommonPacketListenerImpl;latency:I", + opcode = Opcodes.PUTFIELD + ) + ) public void solstice$realPing(ServerCommonPacketListenerImpl instance, int value, @Local int i) { + if (!CoreModule.getConfig().useRealPing) return; + latency = i; } } diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/customname/CustomDisplayNameMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/customname/CustomDisplayNameMixin.java similarity index 81% rename from src/main/java/me/alexdevs/solstice/mixin/modules/customname/CustomDisplayNameMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/customname/CustomDisplayNameMixin.java index 28222c79..549c1276 100644 --- a/src/main/java/me/alexdevs/solstice/mixin/modules/customname/CustomDisplayNameMixin.java +++ b/common/src/main/java/me/alexdevs/solstice/mixin/modules/customname/CustomDisplayNameMixin.java @@ -2,6 +2,7 @@ import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.modules.customName.CustomNameModule; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; @@ -14,12 +15,10 @@ @Mixin(Player.class) public abstract class CustomDisplayNameMixin { @Shadow - private MutableComponent decorateDisplayNameComponent(MutableComponent component) { - return null; - } + protected abstract MutableComponent decorateDisplayNameComponent(MutableComponent component); @Inject(method = "getDisplayName", at = @At("HEAD"), cancellable = true) - public void solstice$getDisplayName(CallbackInfoReturnable cir) { + public void solstice$getDisplayName(CallbackInfoReturnable cir) { var customNameModule = Solstice.modules.getModule(CustomNameModule.class); var name = customNameModule.getNameForPlayer((ServerPlayer) (Object) this); cir.setReturnValue(decorateDisplayNameComponent(name)); diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/miscellaneous/BypassSleepingInBedCheckMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/miscellaneous/BypassSleepingInBedCheckMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/miscellaneous/BypassSleepingInBedCheckMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/miscellaneous/BypassSleepingInBedCheckMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/sign/FormatSignMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/sign/FormatSignMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/sign/FormatSignMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/sign/FormatSignMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/spawn/OverrideSpawnPointMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/spawn/OverrideSpawnPointMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/spawn/OverrideSpawnPointMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/spawn/OverrideSpawnPointMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomAdvancementMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomAdvancementMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomAdvancementMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomAdvancementMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomChatMessageMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomChatMessageMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomChatMessageMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomChatMessageMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomConnectionMessagesMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomConnectionMessagesMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomConnectionMessagesMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomConnectionMessagesMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomDeathMessageMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomDeathMessageMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomDeathMessageMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomDeathMessageMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomSentMessageMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomSentMessageMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomSentMessageMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/styling/CustomSentMessageMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/styling/InjectCustomChatMessageMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/styling/InjectCustomChatMessageMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/styling/InjectCustomChatMessageMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/styling/InjectCustomChatMessageMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/styling/PlayerDisconnectMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/styling/PlayerDisconnectMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/styling/PlayerDisconnectMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/styling/PlayerDisconnectMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/tablist/CustomPlayerListNameMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/tablist/CustomPlayerListNameMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/tablist/CustomPlayerListNameMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/tablist/CustomPlayerListNameMixin.java diff --git a/src/main/java/me/alexdevs/solstice/mixin/modules/tablist/UpdatePlayerListMixin.java b/common/src/main/java/me/alexdevs/solstice/mixin/modules/tablist/UpdatePlayerListMixin.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/mixin/modules/tablist/UpdatePlayerListMixin.java rename to common/src/main/java/me/alexdevs/solstice/mixin/modules/tablist/UpdatePlayerListMixin.java diff --git a/src/main/java/me/alexdevs/solstice/modules/ModuleProvider.java b/common/src/main/java/me/alexdevs/solstice/modules/ModuleProvider.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/ModuleProvider.java rename to common/src/main/java/me/alexdevs/solstice/modules/ModuleProvider.java diff --git a/src/main/java/me/alexdevs/solstice/modules/admin/AdminModule.java b/common/src/main/java/me/alexdevs/solstice/modules/admin/AdminModule.java similarity index 96% rename from src/main/java/me/alexdevs/solstice/modules/admin/AdminModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/admin/AdminModule.java index 06b37daf..b44e0037 100644 --- a/src/main/java/me/alexdevs/solstice/modules/admin/AdminModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/admin/AdminModule.java @@ -3,7 +3,7 @@ import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.events.PlayerConnectionEvents; import me.alexdevs.solstice.api.module.ModuleBase; -import me.lucko.fabric.api.permissions.v0.Permissions; +import me.alexdevs.solstice.api.permissions.Permissions; public class AdminModule extends ModuleBase { public static final String ID = "admin"; diff --git a/src/main/java/me/alexdevs/solstice/modules/afk/AfkModule.java b/common/src/main/java/me/alexdevs/solstice/modules/afk/AfkModule.java similarity index 78% rename from src/main/java/me/alexdevs/solstice/modules/afk/AfkModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/afk/AfkModule.java index 52af7249..5ff43c73 100644 --- a/src/main/java/me/alexdevs/solstice/modules/afk/AfkModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/afk/AfkModule.java @@ -8,15 +8,12 @@ import me.alexdevs.solstice.api.events.CommandEvents; import me.alexdevs.solstice.api.events.PlayerActivityEvents; import me.alexdevs.solstice.api.events.SolsticeEvents; +import me.alexdevs.solstice.api.events.proxy.*; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.api.text.Format; import me.alexdevs.solstice.modules.afk.commands.ActiveTimeCommand; import me.alexdevs.solstice.modules.afk.commands.AfkCommand; import me.alexdevs.solstice.modules.afk.data.*; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; -import net.fabricmc.fabric.api.event.player.*; -import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; @@ -24,6 +21,7 @@ import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec3; + import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -66,32 +64,31 @@ public void init() { this.commands.add(new AfkCommand(this)); this.commands.add(new ActiveTimeCommand(this)); - Placeholders.register(ResourceLocation.fromNamespaceAndPath(Solstice.MOD_ID, "afk"), (context, arg) -> { - if (!context.hasPlayer()) - return PlaceholderResult.invalid("No player!"); + Placeholders.register( + ResourceLocation.fromNamespaceAndPath(Solstice.MOD_ID, "afk"), (context, arg) -> { + if (!context.hasPlayer()) return PlaceholderResult.invalid("No player!"); - var player = context.player(); + var player = context.player(); - if (isPlayerAfk(player)) - return PlaceholderResult.value(Format.parse(getConfig().tag)); - else - return PlaceholderResult.value(""); - }); + if (isPlayerAfk(player)) return PlaceholderResult.value(Format.parse(getConfig().tag)); + else return PlaceholderResult.value(""); + } + ); SolsticeEvents.READY.register((instance, server) -> { Solstice.scheduler.scheduleAtFixedRate(this::updateActiveTime, 0, 1, TimeUnit.SECONDS); calculateLeaderboard(); }); - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - activities.put(handler.getPlayer().getUUID(), new PlayerActivityState(handler.getPlayer(), server.getTickCount())); + ProxyServerPlayConnectionEvents.JOIN.register((player, server) -> { + activities.put(player.getUUID(), new PlayerActivityState(player, server.getTickCount())); }); - ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> { - activities.remove(handler.getPlayer().getUUID()); + ProxyServerPlayConnectionEvents.DISCONNECT.register((player, server) -> { + activities.remove(player.getUUID()); }); - ServerTickEvents.END_SERVER_TICK.register(this::tick); + ProxyServerTickEvents.END_SERVER_TICK.register(this::tick); PlayerActivityEvents.AFK.register((player) -> { var config = getConfig(); @@ -100,9 +97,12 @@ public void init() { player.serverLevel().updateSleepingPlayerList(); } - Solstice.LOGGER.info("{} is AFK. Active time: {} seconds.", player.getGameProfile().getName(), getActiveTime(player.getUUID())); - if (!config.announce) - return; + Solstice.LOGGER.info( + "{} is AFK. Active time: {} seconds.", + player.getGameProfile().getName(), + getActiveTime(player.getUUID()) + ); + if (!config.announce) return; var playerContext = PlaceholderContext.of(player); @@ -116,9 +116,13 @@ public void init() { player.serverLevel().updateSleepingPlayerList(); } - Solstice.LOGGER.info("{} is no longer AFK due to {}. Active time: {} seconds.", player.getGameProfile().getName(), reason.name(), getActiveTime(player.getUUID())); - if (!config.announce) - return; + Solstice.LOGGER.info( + "{} is no longer AFK due to {}. Active time: {} seconds.", + player.getGameProfile().getName(), + reason.name(), + getActiveTime(player.getUUID()) + ); + if (!config.announce) return; var playerContext = PlaceholderContext.of(player); @@ -133,13 +137,17 @@ public AfkServerData getServerData() { } private void updateActiveTime() { - var activePlayers = Solstice.server.getPlayerList().getPlayers() - .stream().filter(player -> !isPlayerAfk(player)); + var activePlayers = Solstice.server.getPlayerList() + .getPlayers() + .stream() + .filter(player -> !isPlayerAfk(player)); activePlayers.forEach(player -> { - var activity = activities.computeIfAbsent(player.getUUID(), uuid -> new PlayerActivityState(player, player.getServer().getTickCount())); - if (!activity.activeTimeEnabled) - return; + var activity = activities.computeIfAbsent( + player.getUUID(), + uuid -> new PlayerActivityState(player, player.getServer().getTickCount()) + ); + if (!activity.activeTimeEnabled) return; var playerData = getPlayerData(player.getUUID()); playerData.activeTime++; @@ -175,11 +183,13 @@ private void tryInsertLeaderboard(ServerPlayer player, int activeTime) { private void tick(MinecraftServer server) { var config = getConfig(); - if (!config.enable) - return; + if (!config.enable) return; server.getPlayerList().getPlayers().forEach(player -> { - var activity = activities.computeIfAbsent(player.getUUID(), uuid -> new PlayerActivityState(player, server.getTickCount())); + var activity = activities.computeIfAbsent( + player.getUUID(), + uuid -> new PlayerActivityState(player, server.getTickCount()) + ); var curLocation = new ServerLocation(player); var oldLocation = activity.location; @@ -193,7 +203,9 @@ private void tick(MinecraftServer server) { // Suppose the player in a vehicle will look around, so we only check for movement when not in a vehicle. if (player.getVehicle() == null) { // Defeats some anti-afk stuff, like pools. Works best when no lag. - if ((player.isShiftKeyDown() && speed >= sneakSpeed) || (player.isSprinting() && speed >= sprintSpeed) || (speed >= walkSpeed)) { + if ((player.isShiftKeyDown() && speed >= sneakSpeed) || + (player.isSprinting() && speed >= sprintSpeed) || + (speed >= walkSpeed)) { if (getConfig().triggers.onMovement) { clearAfk(player, AfkTriggerReason.MOVEMENT); } @@ -230,8 +242,7 @@ public boolean isPlayerAfk(ServerPlayer player) { } public void setPlayerAfk(ServerPlayer player, boolean isAfk) { - if (!activities.containsKey(player.getUUID())) - return; + if (!activities.containsKey(player.getUUID())) return; var config = getConfig(); var activity = activities.get(player.getUUID()); @@ -253,8 +264,7 @@ public void forceRecalculateLeaderboard() { private void calculateLeaderboard() { var serverData = getServerData(); - if (!serverData.forceCalculateLeaderboard) - return; + if (!serverData.forceCalculateLeaderboard) return; serverData.forceCalculateLeaderboard = false; @@ -262,8 +272,7 @@ private void calculateLeaderboard() { var temp = new ArrayList(); for (var name : userCache.getAllNames()) { var profile = userCache.getByName(name); - if (profile.isEmpty()) - continue; + if (profile.isEmpty()) continue; var playerData = Solstice.playerData.get(profile.get().getId()).getData(AfkPlayerData.class); if (playerData.activeTime > 0) { @@ -294,14 +303,12 @@ public List getCurrentActivePlayers() { } private void clearAfk(ServerPlayer player, AfkTriggerReason reason) { - if (!activities.containsKey(player.getUUID())) - return; + if (!activities.containsKey(player.getUUID())) return; var activity = activities.get(player.getUUID()); activity.lastUpdate = Solstice.server.getTickCount(); - if (!activity.afkEnabled) - return; + if (!activity.afkEnabled) return; if (activity.isAfk) { activity.isAfk = false; @@ -311,42 +318,42 @@ private void clearAfk(ServerPlayer player, AfkTriggerReason reason) { } private void registerTriggers() { - AttackBlockCallback.EVENT.register((player, world, hand, pos, direction) -> { + ProxyAttackBlockCallback.EVENT.register((player, world, hand, pos, direction) -> { if (getConfig().triggers.onBlockAttack) { clearAfk((ServerPlayer) player, AfkTriggerReason.BLOCK_ATTACK); } return InteractionResult.PASS; }); - AttackEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> { + ProxyAttackEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> { if (getConfig().triggers.onEntityAttack) { clearAfk((ServerPlayer) player, AfkTriggerReason.ENTITY_ATTACK); } return InteractionResult.PASS; }); - UseBlockCallback.EVENT.register((player, world, hand, hitResult) -> { + ProxyUseBlockCallback.EVENT.register((player, world, hand, hitResult) -> { if (getConfig().triggers.onBlockInteract) { clearAfk((ServerPlayer) player, AfkTriggerReason.BLOCK_INTERACT); } return InteractionResult.PASS; }); - UseEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> { + ProxyUseEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> { if (getConfig().triggers.onEntityInteract) { clearAfk((ServerPlayer) player, AfkTriggerReason.ENTITY_INTERACT); } return InteractionResult.PASS; }); - UseItemCallback.EVENT.register((player, world, hand) -> { + ProxyUseItemCallback.EVENT.register((player, world, hand) -> { if (getConfig().triggers.onItemUse) { clearAfk((ServerPlayer) player, AfkTriggerReason.ITEM_USE); } return InteractionResultHolder.pass(player.getItemInHand(hand)); }); - ServerMessageEvents.ALLOW_CHAT_MESSAGE.register((message, sender, params) -> { + ProxyServerMessageEvents.ALLOW_CHAT_MESSAGE.register((message, sender, params) -> { if (getConfig().triggers.onChat) { clearAfk(sender, AfkTriggerReason.CHAT_MESSAGE); } @@ -354,8 +361,7 @@ private void registerTriggers() { }); CommandEvents.ALLOW_COMMAND.register((source, command) -> { - if (!source.isPlayer()) - return true; + if (!source.isPlayer()) return true; if (getConfig().triggers.onCommand) { clearAfk(source.getPlayer(), AfkTriggerReason.COMMAND); diff --git a/src/main/java/me/alexdevs/solstice/modules/afk/commands/ActiveTimeCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/afk/commands/ActiveTimeCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/afk/commands/ActiveTimeCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/afk/commands/ActiveTimeCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/afk/commands/AfkCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/afk/commands/AfkCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/afk/commands/AfkCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/afk/commands/AfkCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/afk/data/AfkConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/afk/data/AfkConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/afk/data/AfkConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/afk/data/AfkConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/afk/data/AfkLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/afk/data/AfkLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/afk/data/AfkLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/afk/data/AfkLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/afk/data/AfkPlayerData.java b/common/src/main/java/me/alexdevs/solstice/modules/afk/data/AfkPlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/afk/data/AfkPlayerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/afk/data/AfkPlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/afk/data/AfkServerData.java b/common/src/main/java/me/alexdevs/solstice/modules/afk/data/AfkServerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/afk/data/AfkServerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/afk/data/AfkServerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/afk/data/LeaderboardEntry.java b/common/src/main/java/me/alexdevs/solstice/modules/afk/data/LeaderboardEntry.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/afk/data/LeaderboardEntry.java rename to common/src/main/java/me/alexdevs/solstice/modules/afk/data/LeaderboardEntry.java diff --git a/src/main/java/me/alexdevs/solstice/modules/afk/data/PlayerActivityState.java b/common/src/main/java/me/alexdevs/solstice/modules/afk/data/PlayerActivityState.java similarity index 93% rename from src/main/java/me/alexdevs/solstice/modules/afk/data/PlayerActivityState.java rename to common/src/main/java/me/alexdevs/solstice/modules/afk/data/PlayerActivityState.java index 23830230..b1dee4ce 100644 --- a/src/main/java/me/alexdevs/solstice/modules/afk/data/PlayerActivityState.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/afk/data/PlayerActivityState.java @@ -2,8 +2,8 @@ import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.ServerLocation; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.modules.afk.AfkModule; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.server.level.ServerPlayer; public class PlayerActivityState { diff --git a/src/main/java/me/alexdevs/solstice/modules/autoAnnouncement/AutoAnnouncementModule.java b/common/src/main/java/me/alexdevs/solstice/modules/autoAnnouncement/AutoAnnouncementModule.java similarity index 97% rename from src/main/java/me/alexdevs/solstice/modules/autoAnnouncement/AutoAnnouncementModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/autoAnnouncement/AutoAnnouncementModule.java index 652e0bc8..16f11a39 100644 --- a/src/main/java/me/alexdevs/solstice/modules/autoAnnouncement/AutoAnnouncementModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/autoAnnouncement/AutoAnnouncementModule.java @@ -4,9 +4,9 @@ import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.events.SolsticeEvents; import me.alexdevs.solstice.api.module.ModuleBase; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.api.text.Format; import me.alexdevs.solstice.modules.autoAnnouncement.data.AutoAnnouncementConfig; -import me.lucko.fabric.api.permissions.v0.Permissions; import java.util.Random; import java.util.concurrent.ScheduledFuture; diff --git a/src/main/java/me/alexdevs/solstice/modules/autoAnnouncement/data/AutoAnnouncementConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/autoAnnouncement/data/AutoAnnouncementConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/autoAnnouncement/data/AutoAnnouncementConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/autoAnnouncement/data/AutoAnnouncementConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/back/BackModule.java b/common/src/main/java/me/alexdevs/solstice/modules/back/BackModule.java similarity index 73% rename from src/main/java/me/alexdevs/solstice/modules/back/BackModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/back/BackModule.java index 6ce96c94..b3247a92 100644 --- a/src/main/java/me/alexdevs/solstice/modules/back/BackModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/back/BackModule.java @@ -3,12 +3,13 @@ import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.ServerLocation; import me.alexdevs.solstice.api.events.PlayerTeleportCallback; +import me.alexdevs.solstice.api.events.proxy.ProxyServerLivingEntityEvents; +import me.alexdevs.solstice.api.events.proxy.ProxyServerPlayConnectionEvents; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.modules.back.commands.BackCommand; import me.alexdevs.solstice.modules.back.data.BackLocale; -import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.server.level.ServerPlayer; + import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -26,14 +27,18 @@ public void init() { commands.add(new BackCommand(this)); - ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> lastPlayerPositions.remove(handler.getPlayer().getUUID())); + ProxyServerPlayConnectionEvents.DISCONNECT.register((player, server) -> lastPlayerPositions.remove(player.getUUID())); - PlayerTeleportCallback.EVENT.register((player, origin, destination) -> lastPlayerPositions.put(player.getUUID(), origin)); + PlayerTeleportCallback.EVENT.register((player, origin, destination) -> lastPlayerPositions.put( + player.getUUID(), + origin + )); - ServerLivingEntityEvents.AFTER_DEATH.register((entity, damageSource) -> { + ProxyServerLivingEntityEvents.AFTER_DEATH.register((entity, damageSource) -> { if (entity.isAlwaysTicking()) { try { var player = (ServerPlayer) entity; + lastPlayerPositions.put(entity.getUUID(), new ServerLocation(player)); } catch (ClassCastException e) { // They were, in fact, not a player. diff --git a/src/main/java/me/alexdevs/solstice/modules/back/commands/BackCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/back/commands/BackCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/back/commands/BackCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/back/commands/BackCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/back/data/BackLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/back/data/BackLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/back/data/BackLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/back/data/BackLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/ban/BanModule.java b/common/src/main/java/me/alexdevs/solstice/modules/ban/BanModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/ban/BanModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/ban/BanModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/ban/commands/BanCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/ban/commands/BanCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/ban/commands/BanCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/ban/commands/BanCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/ban/commands/TempBanCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/ban/commands/TempBanCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/ban/commands/TempBanCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/ban/commands/TempBanCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/ban/commands/UnbanCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/ban/commands/UnbanCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/ban/commands/UnbanCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/ban/commands/UnbanCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/ban/data/BanLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/ban/data/BanLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/ban/data/BanLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/ban/data/BanLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/ban/formatters/BanMessageFormatter.java b/common/src/main/java/me/alexdevs/solstice/modules/ban/formatters/BanMessageFormatter.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/ban/formatters/BanMessageFormatter.java rename to common/src/main/java/me/alexdevs/solstice/modules/ban/formatters/BanMessageFormatter.java diff --git a/src/main/java/me/alexdevs/solstice/modules/broadcast/BroadcastModule.java b/common/src/main/java/me/alexdevs/solstice/modules/broadcast/BroadcastModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/broadcast/BroadcastModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/broadcast/BroadcastModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/broadcast/commands/BroadcastCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/broadcast/commands/BroadcastCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/broadcast/commands/BroadcastCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/broadcast/commands/BroadcastCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/broadcast/commands/PlainBroadcastCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/broadcast/commands/PlainBroadcastCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/broadcast/commands/PlainBroadcastCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/broadcast/commands/PlainBroadcastCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/broadcast/data/BroadcastConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/broadcast/data/BroadcastConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/broadcast/data/BroadcastConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/broadcast/data/BroadcastConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/commandSpy/CommandSpyModule.java b/common/src/main/java/me/alexdevs/solstice/modules/commandSpy/CommandSpyModule.java similarity index 97% rename from src/main/java/me/alexdevs/solstice/modules/commandSpy/CommandSpyModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/commandSpy/CommandSpyModule.java index 76114183..8413a98e 100644 --- a/src/main/java/me/alexdevs/solstice/modules/commandSpy/CommandSpyModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/commandSpy/CommandSpyModule.java @@ -3,10 +3,11 @@ import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.events.CommandEvents; import me.alexdevs.solstice.api.module.ModuleBase; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.modules.commandSpy.data.CommandSpyConfig; import me.alexdevs.solstice.modules.commandSpy.data.CommandSpyLocale; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.network.chat.Component; + import java.util.Map; public class CommandSpyModule extends ModuleBase.Toggleable { diff --git a/src/main/java/me/alexdevs/solstice/modules/commandSpy/data/CommandSpyConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/commandSpy/data/CommandSpyConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/commandSpy/data/CommandSpyConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/commandSpy/data/CommandSpyConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/commandSpy/data/CommandSpyLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/commandSpy/data/CommandSpyLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/commandSpy/data/CommandSpyLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/commandSpy/data/CommandSpyLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/customName/CustomNameModule.java b/common/src/main/java/me/alexdevs/solstice/modules/customName/CustomNameModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/customName/CustomNameModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/customName/CustomNameModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/customName/commands/NicknameCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/customName/commands/NicknameCommand.java similarity index 98% rename from src/main/java/me/alexdevs/solstice/modules/customName/commands/NicknameCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/customName/commands/NicknameCommand.java index f3443b2f..0a9cdfa7 100644 --- a/src/main/java/me/alexdevs/solstice/modules/customName/commands/NicknameCommand.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/customName/commands/NicknameCommand.java @@ -6,8 +6,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import me.alexdevs.solstice.api.command.LocalGameProfile; import me.alexdevs.solstice.api.module.ModCommand; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.modules.customName.CustomNameModule; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; diff --git a/src/main/java/me/alexdevs/solstice/modules/customName/data/CustomNameConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/customName/data/CustomNameConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/customName/data/CustomNameConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/customName/data/CustomNameConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/customName/data/CustomNameLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/customName/data/CustomNameLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/customName/data/CustomNameLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/customName/data/CustomNameLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/customName/data/CustomNamePlayerData.java b/common/src/main/java/me/alexdevs/solstice/modules/customName/data/CustomNamePlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/customName/data/CustomNamePlayerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/customName/data/CustomNamePlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/enderchest/EnderChestModule.java b/common/src/main/java/me/alexdevs/solstice/modules/enderchest/EnderChestModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/enderchest/EnderChestModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/enderchest/EnderChestModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/enderchest/commands/EnderChestCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/enderchest/commands/EnderChestCommand.java similarity index 98% rename from src/main/java/me/alexdevs/solstice/modules/enderchest/commands/EnderChestCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/enderchest/commands/EnderChestCommand.java index 0ba56713..50464068 100644 --- a/src/main/java/me/alexdevs/solstice/modules/enderchest/commands/EnderChestCommand.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/enderchest/commands/EnderChestCommand.java @@ -5,10 +5,10 @@ import eu.pb4.sgui.api.gui.SimpleGui; import me.alexdevs.solstice.api.command.LocalGameProfile; import me.alexdevs.solstice.api.module.ModCommand; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.api.utils.PlayerUtils; import me.alexdevs.solstice.modules.enderchest.EnderChestModule; import me.alexdevs.solstice.modules.inventorySee.ImmutableSlot; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; @@ -114,7 +114,6 @@ public void onClose() { } container.setTitle(title); - container.open(); } } diff --git a/src/main/java/me/alexdevs/solstice/modules/enderchest/data/EnderChestLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/enderchest/data/EnderChestLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/enderchest/data/EnderChestLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/enderchest/data/EnderChestLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/experiments/ExperimentsModule.java b/common/src/main/java/me/alexdevs/solstice/modules/experiments/ExperimentsModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/experiments/ExperimentsModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/experiments/ExperimentsModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/experiments/commands/FlagsCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/experiments/commands/FlagsCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/experiments/commands/FlagsCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/experiments/commands/FlagsCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/experiments/commands/TimeSpanCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/experiments/commands/TimeSpanCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/experiments/commands/TimeSpanCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/experiments/commands/TimeSpanCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/extinguish/ExtinguishModule.java b/common/src/main/java/me/alexdevs/solstice/modules/extinguish/ExtinguishModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/extinguish/ExtinguishModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/extinguish/ExtinguishModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/extinguish/commands/ExtinguishCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/extinguish/commands/ExtinguishCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/extinguish/commands/ExtinguishCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/extinguish/commands/ExtinguishCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/feed/FeedModule.java b/common/src/main/java/me/alexdevs/solstice/modules/feed/FeedModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/feed/FeedModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/feed/FeedModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/feed/commands/FeedCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/feed/commands/FeedCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/feed/commands/FeedCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/feed/commands/FeedCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/fly/FlyModule.java b/common/src/main/java/me/alexdevs/solstice/modules/fly/FlyModule.java similarity index 80% rename from src/main/java/me/alexdevs/solstice/modules/fly/FlyModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/fly/FlyModule.java index ce31848a..e40e836e 100644 --- a/src/main/java/me/alexdevs/solstice/modules/fly/FlyModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/fly/FlyModule.java @@ -1,11 +1,11 @@ package me.alexdevs.solstice.modules.fly; import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.proxy.ProxyServerPlayConnectionEvents; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.modules.fly.commands.FlyCommand; import me.alexdevs.solstice.modules.fly.data.FlyLocale; import me.alexdevs.solstice.modules.fly.data.FlyPlayerData; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; public class FlyModule extends ModuleBase.Toggleable { public static final String ID = "fly"; @@ -21,11 +21,10 @@ public void init() { commands.add(new FlyCommand(this)); - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - var player = handler.getPlayer(); - + ProxyServerPlayConnectionEvents.JOIN.register((player, server) -> { var data = Solstice.playerData.get(player).getData(FlyPlayerData.class); - if(data.flightEnabled) { + + if (data.flightEnabled) { var abilities = player.getAbilities(); abilities.mayfly = true; player.onUpdateAbilities(); diff --git a/src/main/java/me/alexdevs/solstice/modules/fly/commands/FlyCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/fly/commands/FlyCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/fly/commands/FlyCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/fly/commands/FlyCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/fly/data/FlyLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/fly/data/FlyLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/fly/data/FlyLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/fly/data/FlyLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/fly/data/FlyPlayerData.java b/common/src/main/java/me/alexdevs/solstice/modules/fly/data/FlyPlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/fly/data/FlyPlayerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/fly/data/FlyPlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/god/GodModule.java b/common/src/main/java/me/alexdevs/solstice/modules/god/GodModule.java similarity index 79% rename from src/main/java/me/alexdevs/solstice/modules/god/GodModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/god/GodModule.java index cdc0b5d3..fe56e8e3 100644 --- a/src/main/java/me/alexdevs/solstice/modules/god/GodModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/god/GodModule.java @@ -1,11 +1,11 @@ package me.alexdevs.solstice.modules.god; import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.proxy.ProxyServerPlayConnectionEvents; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.modules.god.commands.GodCommand; import me.alexdevs.solstice.modules.god.data.GodLocale; import me.alexdevs.solstice.modules.god.data.GodPlayerData; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; public class GodModule extends ModuleBase.Toggleable { public static final String ID = "god"; @@ -21,11 +21,10 @@ public void init() { commands.add(new GodCommand(this)); - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - var player = handler.getPlayer(); - + ProxyServerPlayConnectionEvents.JOIN.register((player, server) -> { var data = Solstice.playerData.get(player).getData(GodPlayerData.class); - if(data.invulnerabilityEnabled) { + + if (data.invulnerabilityEnabled) { var abilities = player.getAbilities(); abilities.invulnerable = true; player.onUpdateAbilities(); diff --git a/src/main/java/me/alexdevs/solstice/modules/god/commands/GodCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/god/commands/GodCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/god/commands/GodCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/god/commands/GodCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/god/data/GodLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/god/data/GodLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/god/data/GodLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/god/data/GodLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/god/data/GodPlayerData.java b/common/src/main/java/me/alexdevs/solstice/modules/god/data/GodPlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/god/data/GodPlayerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/god/data/GodPlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/hat/HatModule.java b/common/src/main/java/me/alexdevs/solstice/modules/hat/HatModule.java similarity index 99% rename from src/main/java/me/alexdevs/solstice/modules/hat/HatModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/hat/HatModule.java index 200f3c3b..57c23f0e 100644 --- a/src/main/java/me/alexdevs/solstice/modules/hat/HatModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/hat/HatModule.java @@ -7,6 +7,7 @@ import me.alexdevs.solstice.modules.hat.data.HatLocale; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; + import java.util.List; import java.util.stream.Stream; diff --git a/src/main/java/me/alexdevs/solstice/modules/hat/commands/HatCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/hat/commands/HatCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/hat/commands/HatCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/hat/commands/HatCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/hat/data/HatConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/hat/data/HatConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/hat/data/HatConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/hat/data/HatConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/hat/data/HatLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/hat/data/HatLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/hat/data/HatLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/hat/data/HatLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/heal/HealModule.java b/common/src/main/java/me/alexdevs/solstice/modules/heal/HealModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/heal/HealModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/heal/HealModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/heal/commands/HealCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/heal/commands/HealCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/heal/commands/HealCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/heal/commands/HealCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/helpOp/HelpOpModule.java b/common/src/main/java/me/alexdevs/solstice/modules/helpOp/HelpOpModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/helpOp/HelpOpModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/helpOp/HelpOpModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/helpOp/commands/HelpOpCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/helpOp/commands/HelpOpCommand.java similarity index 97% rename from src/main/java/me/alexdevs/solstice/modules/helpOp/commands/HelpOpCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/helpOp/commands/HelpOpCommand.java index 67a756f5..b0f4999c 100644 --- a/src/main/java/me/alexdevs/solstice/modules/helpOp/commands/HelpOpCommand.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/helpOp/commands/HelpOpCommand.java @@ -5,9 +5,9 @@ import eu.pb4.placeholders.api.PlaceholderContext; import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.module.ModCommand; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.locale.Locale; import me.alexdevs.solstice.modules.helpOp.HelpOpModule; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; import java.util.List; diff --git a/src/main/java/me/alexdevs/solstice/modules/helpOp/data/HelpOpLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/helpOp/data/HelpOpLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/helpOp/data/HelpOpLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/helpOp/data/HelpOpLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/home/HomeModule.java b/common/src/main/java/me/alexdevs/solstice/modules/home/HomeModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/home/HomeModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/home/HomeModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/home/commands/DeleteHomeCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/home/commands/DeleteHomeCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/home/commands/DeleteHomeCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/home/commands/DeleteHomeCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/home/commands/HomeCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/home/commands/HomeCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/home/commands/HomeCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/home/commands/HomeCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/home/commands/HomeOtherCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/home/commands/HomeOtherCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/home/commands/HomeOtherCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/home/commands/HomeOtherCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/home/commands/HomesCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/home/commands/HomesCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/home/commands/HomesCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/home/commands/HomesCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/home/commands/SetHomeCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/home/commands/SetHomeCommand.java similarity index 98% rename from src/main/java/me/alexdevs/solstice/modules/home/commands/SetHomeCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/home/commands/SetHomeCommand.java index a92b33c8..e2fb780a 100644 --- a/src/main/java/me/alexdevs/solstice/modules/home/commands/SetHomeCommand.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/home/commands/SetHomeCommand.java @@ -7,9 +7,9 @@ import eu.pb4.placeholders.api.PlaceholderContext; import me.alexdevs.solstice.api.ServerLocation; import me.alexdevs.solstice.api.module.ModCommand; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.modules.home.HomeModule; import me.alexdevs.solstice.api.text.Components; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; import java.util.List; diff --git a/src/main/java/me/alexdevs/solstice/modules/home/data/HomeConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/home/data/HomeConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/home/data/HomeConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/home/data/HomeConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/home/data/HomeLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/home/data/HomeLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/home/data/HomeLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/home/data/HomeLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/home/data/HomePlayerData.java b/common/src/main/java/me/alexdevs/solstice/modules/home/data/HomePlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/home/data/HomePlayerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/home/data/HomePlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/ignite/IgniteModule.java b/common/src/main/java/me/alexdevs/solstice/modules/ignite/IgniteModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/ignite/IgniteModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/ignite/IgniteModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/ignite/commands/IgniteCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/ignite/commands/IgniteCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/ignite/commands/IgniteCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/ignite/commands/IgniteCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/ignore/IgnoreModule.java b/common/src/main/java/me/alexdevs/solstice/modules/ignore/IgnoreModule.java similarity index 96% rename from src/main/java/me/alexdevs/solstice/modules/ignore/IgnoreModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/ignore/IgnoreModule.java index 20f5a5c7..8864d76e 100644 --- a/src/main/java/me/alexdevs/solstice/modules/ignore/IgnoreModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/ignore/IgnoreModule.java @@ -2,13 +2,14 @@ import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.module.ModuleBase; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.modules.ignore.commands.IgnoreCommand; import me.alexdevs.solstice.modules.ignore.commands.IgnoreListCommand; import me.alexdevs.solstice.modules.ignore.data.IgnoreLocale; import me.alexdevs.solstice.modules.ignore.data.IgnorePlayerData; import me.alexdevs.solstice.modules.styling.StylingModule; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.server.level.ServerPlayer; + import java.util.UUID; public class IgnoreModule extends ModuleBase.Toggleable { diff --git a/src/main/java/me/alexdevs/solstice/modules/ignore/commands/IgnoreCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/ignore/commands/IgnoreCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/ignore/commands/IgnoreCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/ignore/commands/IgnoreCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/ignore/commands/IgnoreListCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/ignore/commands/IgnoreListCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/ignore/commands/IgnoreListCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/ignore/commands/IgnoreListCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/ignore/data/IgnoreLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/ignore/data/IgnoreLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/ignore/data/IgnoreLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/ignore/data/IgnoreLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/ignore/data/IgnorePlayerData.java b/common/src/main/java/me/alexdevs/solstice/modules/ignore/data/IgnorePlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/ignore/data/IgnorePlayerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/ignore/data/IgnorePlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/info/InfoModule.java b/common/src/main/java/me/alexdevs/solstice/modules/info/InfoModule.java similarity index 86% rename from src/main/java/me/alexdevs/solstice/modules/info/InfoModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/info/InfoModule.java index 33225d2c..f0246ed1 100644 --- a/src/main/java/me/alexdevs/solstice/modules/info/InfoModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/info/InfoModule.java @@ -3,6 +3,7 @@ import eu.pb4.placeholders.api.PlaceholderContext; import me.alexdevs.solstice.Paths; import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.proxy.ProxyServerPlayConnectionEvents; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.api.text.Format; import me.alexdevs.solstice.modules.info.commands.InfoCommand; @@ -10,7 +11,6 @@ import me.alexdevs.solstice.modules.info.commands.RulesCommand; import me.alexdevs.solstice.modules.info.data.InfoConfig; import me.alexdevs.solstice.modules.info.data.InfoLocale; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.network.chat.Component; import org.jetbrains.annotations.Nullable; @@ -25,10 +25,8 @@ public class InfoModule extends ModuleBase.Toggleable { public static final String ID = "info"; - private static final String[] startingPages = new String[]{ - "motd.txt", - "rules.txt", - "formatting.txt" + private static final String[] startingPages = new String[] { + "motd.txt", "rules.txt", "formatting.txt" }; public final String nameFilterRegex = "[^a-z0-9-]"; private final Path infoDir; @@ -70,15 +68,16 @@ public void init() { } } - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { + ProxyServerPlayConnectionEvents.JOIN.register((player, server) -> { if (getConfig().enableMotd) { if (!exists("motd")) { Solstice.LOGGER.warn("Could not send MOTD because info/motd.txt does not exist!"); return; } + Solstice.nextTick(() -> { - var motd = buildMotd(PlaceholderContext.of(handler.getPlayer())); - handler.getPlayer().sendSystemMessage(motd); + var motd = buildMotd(PlaceholderContext.of(player)); + player.sendSystemMessage(motd); }); } }); @@ -98,7 +97,8 @@ private String sanitize(String name) { public Collection enumerate() { return Arrays.stream(Objects.requireNonNull(infoDir.toFile().listFiles())) - .map(f -> f.getName().replace(".txt", "")).toList(); + .map(f -> f.getName().replace(".txt", "")) + .toList(); } public boolean exists(String name) { @@ -123,10 +123,8 @@ public Component getPage(String name, @Nullable PlaceholderContext context) { content.append(line).append("\n"); } var output = content.toString().trim(); - if (context != null) - return Format.parse(output, context); - else - return Component.nullToEmpty(output); + if (context != null) return Format.parse(output, context); + else return Component.nullToEmpty(output); } catch (IOException e) { Solstice.LOGGER.error("Could not read info file", e); return locale().get("pageError"); diff --git a/src/main/java/me/alexdevs/solstice/modules/info/commands/InfoCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/info/commands/InfoCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/info/commands/InfoCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/info/commands/InfoCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/info/commands/MotdCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/info/commands/MotdCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/info/commands/MotdCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/info/commands/MotdCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/info/commands/RulesCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/info/commands/RulesCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/info/commands/RulesCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/info/commands/RulesCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/info/data/InfoConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/info/data/InfoConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/info/data/InfoConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/info/data/InfoConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/info/data/InfoLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/info/data/InfoLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/info/data/InfoLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/info/data/InfoLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/inventorySee/ImmutableSlot.java b/common/src/main/java/me/alexdevs/solstice/modules/inventorySee/ImmutableSlot.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/inventorySee/ImmutableSlot.java rename to common/src/main/java/me/alexdevs/solstice/modules/inventorySee/ImmutableSlot.java diff --git a/src/main/java/me/alexdevs/solstice/modules/inventorySee/InventorySeeModule.java b/common/src/main/java/me/alexdevs/solstice/modules/inventorySee/InventorySeeModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/inventorySee/InventorySeeModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/inventorySee/InventorySeeModule.java diff --git a/common/src/main/java/me/alexdevs/solstice/modules/inventorySee/commands/InventorySeeCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/inventorySee/commands/InventorySeeCommand.java new file mode 100644 index 00000000..d07b09cc --- /dev/null +++ b/common/src/main/java/me/alexdevs/solstice/modules/inventorySee/commands/InventorySeeCommand.java @@ -0,0 +1,218 @@ +package me.alexdevs.solstice.modules.inventorySee.commands; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import eu.pb4.sgui.api.gui.SimpleGui; +import me.alexdevs.solstice.api.command.LocalGameProfile; +import me.alexdevs.solstice.api.module.ModCommand; +import me.alexdevs.solstice.api.permissions.Permissions; +import me.alexdevs.solstice.api.utils.PlayerUtils; +import me.alexdevs.solstice.integrations.TrinketsApiProxy; +import me.alexdevs.solstice.integrations.TrinketsIntegration; +import me.alexdevs.solstice.modules.inventorySee.ImmutableSlot; +import me.alexdevs.solstice.modules.inventorySee.InventorySeeModule; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.core.component.DataComponents; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.inventory.ChestMenu; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static net.minecraft.commands.Commands.argument; +import static net.minecraft.commands.Commands.literal; + +public class InventorySeeCommand extends ModCommand { + public InventorySeeCommand(InventorySeeModule module) { + super(module); + } + + @Override + public List getNames() { + return List.of("invsee", "inventorysee"); + } + + private static final LinkedHashMap> invSizes = new LinkedHashMap<>(); + + static { + invSizes.put(9, MenuType.GENERIC_9x1); + invSizes.put(18, MenuType.GENERIC_9x2); + invSizes.put(27, MenuType.GENERIC_9x3); + invSizes.put(36, MenuType.GENERIC_9x4); + invSizes.put(45, MenuType.GENERIC_9x5); + invSizes.put(54, MenuType.GENERIC_9x6); + } + + @Override + public LiteralArgumentBuilder command(String name) { + return literal(name).requires(require(2)) + .then(argument("player", StringArgumentType.word()).suggests(LocalGameProfile::suggest) + .executes(context -> { + var source = context.getSource(); + var player = source.getPlayerOrException(); + var targetProfile = LocalGameProfile.getProfile(context, "player"); + var targetOnline = PlayerUtils.isOnline(targetProfile.getId()); + + if (!targetOnline && !Permissions.check(player, getPermissionNode("offline"), 3)) { + source.sendSuccess(() -> module.locale().get("offlineNotAllowed"), false); + return 0; + } + + ServerPlayer target; + if (targetOnline) { + target = context.getSource() + .getServer() + .getPlayerList() + .getPlayer(targetProfile.getId()); + if (Permissions.check(target, getPermissionNode("exempt"), 3)) { + source.sendSuccess(() -> module.locale().get("exempt"), false); + return 0; + } + } else { + target = PlayerUtils.loadOfflinePlayer(targetProfile); + if (Permissions.check(targetProfile, getPermissionNode("exempt"), 3, source.getServer()) + .getNow(false)) { + source.sendSuccess(() -> module.locale().get("exempt"), false); + return 0; + } + } + + var canEdit = Permissions.check(player, getPermissionNode("edit"), 3); + + var targetInventory = target.getInventory(); + + var container = new SimpleGui(MenuType.GENERIC_9x5, player, false) { + @Override + public void onClose() { + if (!targetOnline) { + PlayerUtils.saveOfflinePlayer(target); + } + } + }; + + for (var i = 0; i < targetInventory.getContainerSize(); i++) { + Slot slot; + if (canEdit) { + slot = new Slot(targetInventory, i, 0, 0); + } else { + slot = new ImmutableSlot(targetInventory, i, 0, 0); + } + container.setSlotRedirect(i, slot); + } + + var barrier = new ItemStack(Items.BLACK_STAINED_GLASS_PANE); + barrier.set(DataComponents.CUSTOM_NAME, Component.literal("")); + for (var i = targetInventory.getContainerSize(); i < container.getSize(); i++) { + container.setSlot(i, barrier); + } + + container.setTitle(target.getName()); + + container.open(); + + var map = Map.of("user", Component.nullToEmpty(target.getGameProfile().getName())); + source.sendSuccess(() -> module.locale().get("openedInventory", map), true); + + return 1; + }) + .then(literal("trinkets").executes(context -> { + var source = context.getSource(); + var player = source.getPlayerOrException(); + var targetProfile = LocalGameProfile.getProfile(context, "player"); + var targetOnline = PlayerUtils.isOnline(targetProfile.getId()); + + if (!targetOnline && !Permissions.check(player, getPermissionNode("offline"), 3)) { + source.sendSuccess(() -> module.locale().get("offlineNotAllowed"), false); + return 0; + } + + ServerPlayer target; + if (targetOnline) { + target = context.getSource() + .getServer() + .getPlayerList() + .getPlayer(targetProfile.getId()); + if (Permissions.check(target, getPermissionNode("exempt"), 3)) { + source.sendSuccess(() -> module.locale().get("exempt"), false); + return 0; + } + } else { + target = PlayerUtils.loadOfflinePlayer(targetProfile); + if (Permissions.check(targetProfile, getPermissionNode("exempt"), 3, source.getServer()) + .getNow(false)) { + source.sendSuccess(() -> module.locale().get("exempt"), false); + return 0; + } + } + + if (!TrinketsIntegration.isAvailable()) { + source.sendSuccess(() -> module.locale().get("trinketsNotInstalled"), false); + return 0; + } + + var canEdit = Permissions.check(player, getPermissionNode("edit"), 3); + var trinkets = TrinketsApiProxy.get().getTrinketComponentInventory(target).orElse(null); + var slots = new ArrayList(); + + for (var group : trinkets.values()) { + for (var inventory : group.values()) { + for (var i = 0; i < inventory.getContainerSize(); i++) { + Slot slot; + + if (canEdit) { + slot = new Slot(inventory, i, 0, 0); + } else { + slot = new ImmutableSlot(inventory, i, 0, 0); + } + + slots.add(slot); + } + } + } + + var size = slots.size(); + MenuType handlerType = null; + for (var entry : invSizes.entrySet()) { + handlerType = entry.getValue(); + if (size <= entry.getKey()) { + break; + } + } + + var container = new SimpleGui(handlerType, player, false) { + @Override + public void onClose() { + if (!targetOnline) { + PlayerUtils.saveOfflinePlayer(target); + } + } + }; + + for (var i = 0; i < slots.size(); i++) { + var slot = slots.get(i); + container.setSlotRedirect(i, slot); + } + + var barrier = new ItemStack(Items.BLACK_STAINED_GLASS_PANE); + barrier.set(DataComponents.CUSTOM_NAME, Component.literal("")); + for (var i = size; i < container.getSize(); i++) { + container.setSlot(i, barrier); + } + + container.setTitle(target.getName()); + container.open(); + + var map = Map.of("user", Component.nullToEmpty(target.getGameProfile().getName())); + source.sendSuccess(() -> module.locale().get("openedTrinkets", map), true); + + return 1; + }))); + } +} diff --git a/src/main/java/me/alexdevs/solstice/modules/inventorySee/data/InventorySeeLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/inventorySee/data/InventorySeeLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/inventorySee/data/InventorySeeLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/inventorySee/data/InventorySeeLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/item/ItemModule.java b/common/src/main/java/me/alexdevs/solstice/modules/item/ItemModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/item/ItemModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/item/ItemModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/item/commands/ItemLoreCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/item/commands/ItemLoreCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/item/commands/ItemLoreCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/item/commands/ItemLoreCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/item/commands/ItemNameCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/item/commands/ItemNameCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/item/commands/ItemNameCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/item/commands/ItemNameCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/item/commands/MoreCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/item/commands/MoreCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/item/commands/MoreCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/item/commands/MoreCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/item/commands/RepairCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/item/commands/RepairCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/item/commands/RepairCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/item/commands/RepairCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/item/data/ItemLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/item/data/ItemLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/item/data/ItemLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/item/data/ItemLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/jail/JailModule.java b/common/src/main/java/me/alexdevs/solstice/modules/jail/JailModule.java similarity index 79% rename from src/main/java/me/alexdevs/solstice/modules/jail/JailModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/jail/JailModule.java index 7146214b..c36837b2 100644 --- a/src/main/java/me/alexdevs/solstice/modules/jail/JailModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/jail/JailModule.java @@ -4,6 +4,7 @@ import me.alexdevs.solstice.api.ServerLocation; import me.alexdevs.solstice.api.command.TimeSpan; import me.alexdevs.solstice.api.events.CommandEvents; +import me.alexdevs.solstice.api.events.proxy.*; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.modules.jail.commands.CheckJailCommand; import me.alexdevs.solstice.modules.jail.commands.JailCommand; @@ -14,15 +15,11 @@ import me.alexdevs.solstice.modules.jail.data.JailPlayerData; import me.alexdevs.solstice.modules.jail.data.JailServerData; import me.alexdevs.solstice.modules.spawn.SpawnModule; -import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.player.*; -import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; + import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -46,24 +43,25 @@ public void init() { commands.add(new UnjailCommand(this)); commands.add(new CheckJailCommand(this)); - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { + ProxyServerPlayConnectionEvents.JOIN.register((player, server) -> { Solstice.nextTick(() -> { - var data = getPlayer(handler.getPlayer().getUUID()); + var data = getPlayer(player.getUUID()); + if (data.jailed) { - sendToJail(handler.getPlayer()); + sendToJail(player); } else if (data.teleportToPreviousLocation) { - unjailPlayer(handler.getPlayer().getUUID()); + unjailPlayer(player.getUUID()); } }); }); - ServerPlayerEvents.AFTER_RESPAWN.register((oldPlayer, player, alive) -> { + ProxyServerPlayerEvents.AFTER_RESPAWN.register((oldPlayer, player, alive) -> { if (isPlayerJailed(player.getUUID())) { sendToJail(player); } }); - ServerLifecycleEvents.SERVER_STARTED.register((server) -> { + ProxyServerLifecycleEvents.SERVER_STARTED.register((server) -> { Solstice.scheduler.scheduleAtFixedRate(this::checkJailedPlayers, 0, 1, TimeUnit.SECONDS); }); @@ -84,7 +82,7 @@ public void init() { return true; }); - AttackBlockCallback.EVENT.register((player, world, hand, blockPos, direction) -> { + ProxyAttackBlockCallback.EVENT.register((player, world, hand, blockPos, direction) -> { if (isPlayerJailed(player.getUUID())) { player.sendSystemMessage(locale().get("cannotBreakBlocks")); return InteractionResult.FAIL; @@ -92,7 +90,7 @@ public void init() { return InteractionResult.PASS; }); - AttackEntityCallback.EVENT.register((player, world, hand, entity, entityHitResult) -> { + ProxyAttackEntityCallback.EVENT.register((player, world, hand, entity, entityHitResult) -> { if (isPlayerJailed(player.getUUID())) { player.sendSystemMessage(locale().get("cannotAttackEntities")); return InteractionResult.FAIL; @@ -100,7 +98,7 @@ public void init() { return InteractionResult.PASS; }); - PlayerBlockBreakEvents.BEFORE.register((world, player, blockPos, blockState, blockEntity) -> { + ProxyPlayerBlockBreakEvents.BEFORE.register((world, player, blockPos, blockState, blockEntity) -> { if (isPlayerJailed(player.getUUID())) { player.sendSystemMessage(locale().get("cannotBreakBlocks")); return false; @@ -109,7 +107,7 @@ public void init() { return true; }); - UseBlockCallback.EVENT.register((player, world, hand, blockHitResult) -> { + ProxyUseBlockCallback.EVENT.register((player, world, hand, blockHitResult) -> { if (isPlayerJailed(player.getUUID())) { player.sendSystemMessage(locale().get("cannotUseBlocks")); return InteractionResult.FAIL; @@ -117,7 +115,7 @@ public void init() { return InteractionResult.PASS; }); - UseEntityCallback.EVENT.register((player, world, hand, entity, entityHitResult) -> { + ProxyUseEntityCallback.EVENT.register((player, world, hand, entity, entityHitResult) -> { if (isPlayerJailed(player.getUUID())) { player.sendSystemMessage(locale().get("cannotUseEntities")); return InteractionResult.FAIL; @@ -125,7 +123,7 @@ public void init() { return InteractionResult.PASS; }); - UseItemCallback.EVENT.register((player, world, hand) -> { + ProxyUseItemCallback.EVENT.register((player, world, hand) -> { var stack = player.getItemInHand(hand); if (isPlayerJailed(player.getUUID())) { player.sendSystemMessage(locale().get("cannotUseItems")); @@ -134,10 +132,10 @@ public void init() { return InteractionResultHolder.pass(stack); }); - ServerMessageEvents.ALLOW_CHAT_MESSAGE.register((signedMessage, player, parameters) -> { + ProxyServerMessageEvents.ALLOW_CHAT_MESSAGE.register((signedMessage, player, parameters) -> { if (isPlayerJailed(player.getUUID())) { var config = getConfig(); - if(config.mute) { + if (config.mute) { player.sendSystemMessage(locale().get("cannotSpeak")); return false; } @@ -153,7 +151,8 @@ private void checkJailedPlayers() { for (var player : players) { var data = getPlayer(player.getUUID()); if (isPlayerJailed(player.getUUID()) && data.jailTime > 0) { - if (data.jailedOn != null && data.jailedOn.getTime() + (data.jailTime * 1000L) < System.currentTimeMillis()) { + if (data.jailedOn != null && + data.jailedOn.getTime() + (data.jailTime * 1000L) < System.currentTimeMillis()) { unjailPlayer(player.getUUID()); } } @@ -187,10 +186,14 @@ public void sendToJail(ServerPlayer player) { jail.teleport(player); var map = Map.of( - "player", player.getName(), - "jail", Component.nullToEmpty(data.jailName), - "duration", Component.nullToEmpty(TimeSpan.toLongString(data.jailTime)), - "reason", Component.nullToEmpty(data.jailReason) + "player", + player.getName(), + "jail", + Component.nullToEmpty(data.jailName), + "duration", + Component.nullToEmpty(TimeSpan.toLongString(data.jailTime)), + "reason", + Component.nullToEmpty(data.jailReason) ); Component text; diff --git a/src/main/java/me/alexdevs/solstice/modules/jail/commands/CheckJailCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/jail/commands/CheckJailCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/jail/commands/CheckJailCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/jail/commands/CheckJailCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/jail/commands/JailCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/jail/commands/JailCommand.java similarity index 98% rename from src/main/java/me/alexdevs/solstice/modules/jail/commands/JailCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/jail/commands/JailCommand.java index ca7159e2..5e37b245 100644 --- a/src/main/java/me/alexdevs/solstice/modules/jail/commands/JailCommand.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/jail/commands/JailCommand.java @@ -11,9 +11,9 @@ import me.alexdevs.solstice.api.command.LocalGameProfile; import me.alexdevs.solstice.api.command.TimeSpan; import me.alexdevs.solstice.api.module.ModCommand; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.core.coreModule.data.CorePlayerData; import me.alexdevs.solstice.modules.jail.JailModule; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.SharedSuggestionProvider; diff --git a/src/main/java/me/alexdevs/solstice/modules/jail/commands/JailsCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/jail/commands/JailsCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/jail/commands/JailsCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/jail/commands/JailsCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/jail/commands/UnjailCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/jail/commands/UnjailCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/jail/commands/UnjailCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/jail/commands/UnjailCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/jail/data/JailConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/jail/data/JailConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/jail/data/JailConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/jail/data/JailConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/jail/data/JailLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/jail/data/JailLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/jail/data/JailLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/jail/data/JailLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/jail/data/JailPlayerData.java b/common/src/main/java/me/alexdevs/solstice/modules/jail/data/JailPlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/jail/data/JailPlayerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/jail/data/JailPlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/jail/data/JailServerData.java b/common/src/main/java/me/alexdevs/solstice/modules/jail/data/JailServerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/jail/data/JailServerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/jail/data/JailServerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/kick/KickModule.java b/common/src/main/java/me/alexdevs/solstice/modules/kick/KickModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/kick/KickModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/kick/KickModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/kick/commands/KickCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/kick/commands/KickCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/kick/commands/KickCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/kick/commands/KickCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/kit/KitInventory.java b/common/src/main/java/me/alexdevs/solstice/modules/kit/KitInventory.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/kit/KitInventory.java rename to common/src/main/java/me/alexdevs/solstice/modules/kit/KitInventory.java diff --git a/src/main/java/me/alexdevs/solstice/modules/kit/KitModule.java b/common/src/main/java/me/alexdevs/solstice/modules/kit/KitModule.java similarity index 98% rename from src/main/java/me/alexdevs/solstice/modules/kit/KitModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/kit/KitModule.java index de1046e2..3f9d79a0 100644 --- a/src/main/java/me/alexdevs/solstice/modules/kit/KitModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/kit/KitModule.java @@ -3,12 +3,13 @@ import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.events.SolsticeEvents; import me.alexdevs.solstice.api.module.ModuleBase; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.modules.kit.commands.KitCommand; import me.alexdevs.solstice.modules.kit.commands.KitsCommand; import me.alexdevs.solstice.modules.kit.data.*; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; + import java.util.Date; import java.util.List; import java.util.Map; diff --git a/src/main/java/me/alexdevs/solstice/modules/kit/Utils.java b/common/src/main/java/me/alexdevs/solstice/modules/kit/Utils.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/kit/Utils.java rename to common/src/main/java/me/alexdevs/solstice/modules/kit/Utils.java diff --git a/src/main/java/me/alexdevs/solstice/modules/kit/commands/KitCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/kit/commands/KitCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/kit/commands/KitCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/kit/commands/KitCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/kit/commands/KitsCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/kit/commands/KitsCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/kit/commands/KitsCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/kit/commands/KitsCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/kit/data/Kit.java b/common/src/main/java/me/alexdevs/solstice/modules/kit/data/Kit.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/kit/data/Kit.java rename to common/src/main/java/me/alexdevs/solstice/modules/kit/data/Kit.java diff --git a/src/main/java/me/alexdevs/solstice/modules/kit/data/KitConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/kit/data/KitConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/kit/data/KitConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/kit/data/KitConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/kit/data/KitLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/kit/data/KitLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/kit/data/KitLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/kit/data/KitLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/kit/data/KitPlayerData.java b/common/src/main/java/me/alexdevs/solstice/modules/kit/data/KitPlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/kit/data/KitPlayerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/kit/data/KitPlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/kit/data/KitServerData.java b/common/src/main/java/me/alexdevs/solstice/modules/kit/data/KitServerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/kit/data/KitServerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/kit/data/KitServerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/mail/MailModule.java b/common/src/main/java/me/alexdevs/solstice/modules/mail/MailModule.java similarity index 81% rename from src/main/java/me/alexdevs/solstice/modules/mail/MailModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/mail/MailModule.java index 82946319..7b774817 100644 --- a/src/main/java/me/alexdevs/solstice/modules/mail/MailModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/mail/MailModule.java @@ -3,12 +3,12 @@ import eu.pb4.placeholders.api.PlaceholderContext; import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.PlayerMail; +import me.alexdevs.solstice.api.events.proxy.ProxyServerPlayConnectionEvents; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.modules.ignore.IgnoreModule; import me.alexdevs.solstice.modules.mail.commands.MailCommand; import me.alexdevs.solstice.modules.mail.data.MailLocale; import me.alexdevs.solstice.modules.mail.data.MailPlayerData; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import java.util.List; import java.util.UUID; @@ -28,15 +28,16 @@ public void init() { commands.add(new MailCommand(this)); - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - var player = handler.getPlayer(); + ProxyServerPlayConnectionEvents.JOIN.register((player, server) -> { var playerContext = PlaceholderContext.of(player); - Solstice.scheduler.schedule(() -> { - if (!getMailData(player.getUUID()).mails.isEmpty()) { - player.sendSystemMessage(locale().get("mailPending", playerContext)); - } - }, 1, TimeUnit.SECONDS); + Solstice.scheduler.schedule( + () -> { + if (!getMailData(player.getUUID()).mails.isEmpty()) { + player.sendSystemMessage(locale().get("mailPending", playerContext)); + } + }, 1, TimeUnit.SECONDS + ); }); } diff --git a/src/main/java/me/alexdevs/solstice/modules/mail/commands/MailCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/mail/commands/MailCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/mail/commands/MailCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/mail/commands/MailCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/mail/data/MailLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/mail/data/MailLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/mail/data/MailLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/mail/data/MailLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/mail/data/MailPlayerData.java b/common/src/main/java/me/alexdevs/solstice/modules/mail/data/MailPlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/mail/data/MailPlayerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/mail/data/MailPlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/miscellaneous/DummyExplosion.java b/common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/DummyExplosion.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/miscellaneous/DummyExplosion.java rename to common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/DummyExplosion.java diff --git a/src/main/java/me/alexdevs/solstice/modules/miscellaneous/MiscellaneousModule.java b/common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/MiscellaneousModule.java similarity index 68% rename from src/main/java/me/alexdevs/solstice/modules/miscellaneous/MiscellaneousModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/MiscellaneousModule.java index 4b651d92..4ed9b160 100644 --- a/src/main/java/me/alexdevs/solstice/modules/miscellaneous/MiscellaneousModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/MiscellaneousModule.java @@ -1,14 +1,18 @@ package me.alexdevs.solstice.modules.miscellaneous; import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.proxy.ProxyEntitySleepEvents; +import me.alexdevs.solstice.api.events.proxy.ProxyServerPlayConnectionEvents; import me.alexdevs.solstice.api.module.ModuleBase; -import me.alexdevs.solstice.modules.miscellaneous.commands.*; +import me.alexdevs.solstice.modules.miscellaneous.commands.EffectsCommand; +import me.alexdevs.solstice.modules.miscellaneous.commands.NudgeCommand; +import me.alexdevs.solstice.modules.miscellaneous.commands.SleepCommand; +import me.alexdevs.solstice.modules.miscellaneous.commands.TopCommand; import me.alexdevs.solstice.modules.miscellaneous.data.MiscellaneousLocale; -import net.fabricmc.fabric.api.entity.event.v1.EntitySleepEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.LivingEntity; + import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -30,13 +34,13 @@ public void init() { commands.add(new SleepCommand(this)); commands.add(new NudgeCommand(this)); commands.add(new TopCommand(this)); - //commands.add(new KittyCannonCommand(this)); - //commands.add(new RocketCommand(this)); + // commands.add(new KittyCannonCommand(this)); + // commands.add(new RocketCommand(this)); - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> commandSleeping.remove(handler.getPlayer().getUUID())); - EntitySleepEvents.STOP_SLEEPING.register((entity, pos) -> commandSleeping.remove(entity.getUUID())); + ProxyServerPlayConnectionEvents.JOIN.register((player, server) -> commandSleeping.remove(player.getUUID())); + ProxyEntitySleepEvents.STOP_SLEEPING.register((entity, pos) -> commandSleeping.remove(entity.getUUID())); - EntitySleepEvents.ALLOW_SLEEP_TIME.register((player, pos, vanillaResult) -> { + ProxyEntitySleepEvents.ALLOW_SLEEP_TIME.register((player, pos, vanillaResult) -> { if (commandSleeping.getOrDefault(player.getUUID(), false)) { return InteractionResult.SUCCESS; } @@ -44,7 +48,7 @@ public void init() { return InteractionResult.PASS; }); - EntitySleepEvents.ALLOW_RESETTING_TIME.register(player -> { + ProxyEntitySleepEvents.ALLOW_RESETTING_TIME.register(player -> { if (commandSleeping.getOrDefault(player.getUUID(), false)) { return !player.level().isDay(); } diff --git a/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/EffectsCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/EffectsCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/EffectsCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/EffectsCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/KittyCannonCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/KittyCannonCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/KittyCannonCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/KittyCannonCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/NudgeCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/NudgeCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/NudgeCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/NudgeCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/RocketCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/RocketCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/RocketCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/RocketCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/SleepCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/SleepCommand.java similarity index 97% rename from src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/SleepCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/SleepCommand.java index afae492b..9a4b5d8d 100644 --- a/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/SleepCommand.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/SleepCommand.java @@ -7,6 +7,7 @@ import net.minecraft.commands.Commands; import net.minecraft.commands.arguments.EntityArgument; import net.minecraft.world.entity.LivingEntity; + import java.util.List; public class SleepCommand extends ModCommand { @@ -40,7 +41,6 @@ public LiteralArgumentBuilder command(String name) { } } return count; - }) - ); + })); } } diff --git a/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/TopCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/TopCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/TopCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/commands/TopCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/miscellaneous/data/MiscellaneousLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/data/MiscellaneousLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/miscellaneous/data/MiscellaneousLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/miscellaneous/data/MiscellaneousLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/mute/MuteModule.java b/common/src/main/java/me/alexdevs/solstice/modules/mute/MuteModule.java similarity index 88% rename from src/main/java/me/alexdevs/solstice/modules/mute/MuteModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/mute/MuteModule.java index 40a412a5..7bac3f07 100644 --- a/src/main/java/me/alexdevs/solstice/modules/mute/MuteModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/mute/MuteModule.java @@ -1,12 +1,12 @@ package me.alexdevs.solstice.modules.mute; import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.proxy.ProxyServerMessageEvents; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.modules.mute.commands.MuteCommand; import me.alexdevs.solstice.modules.mute.commands.UnmuteCommand; import me.alexdevs.solstice.modules.mute.data.MuteLocale; import me.alexdevs.solstice.modules.mute.data.MutePlayerData; -import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; import java.util.UUID; @@ -25,11 +25,12 @@ public void init() { commands.add(new MuteCommand(this)); commands.add(new UnmuteCommand(this)); - ServerMessageEvents.ALLOW_CHAT_MESSAGE.register((signedMessage, player, parameters) -> { + ProxyServerMessageEvents.ALLOW_CHAT_MESSAGE.register((signedMessage, player, parameters) -> { if (isMuted(player.getUUID())) { player.sendSystemMessage(locale().get("youAreMuted")); return false; } + return true; }); } diff --git a/src/main/java/me/alexdevs/solstice/modules/mute/commands/MuteCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/mute/commands/MuteCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/mute/commands/MuteCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/mute/commands/MuteCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/mute/commands/UnmuteCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/mute/commands/UnmuteCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/mute/commands/UnmuteCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/mute/commands/UnmuteCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/mute/data/MuteLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/mute/data/MuteLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/mute/data/MuteLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/mute/data/MuteLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/mute/data/MutePlayerData.java b/common/src/main/java/me/alexdevs/solstice/modules/mute/data/MutePlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/mute/data/MutePlayerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/mute/data/MutePlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/near/NearModule.java b/common/src/main/java/me/alexdevs/solstice/modules/near/NearModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/near/NearModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/near/NearModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/near/commands/NearCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/near/commands/NearCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/near/commands/NearCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/near/commands/NearCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/near/data/NearConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/near/data/NearConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/near/data/NearConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/near/data/NearConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/near/data/NearLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/near/data/NearLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/near/data/NearLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/near/data/NearLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/note/NoteModule.java b/common/src/main/java/me/alexdevs/solstice/modules/note/NoteModule.java similarity index 79% rename from src/main/java/me/alexdevs/solstice/modules/note/NoteModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/note/NoteModule.java index 4521a788..c0d3f1be 100644 --- a/src/main/java/me/alexdevs/solstice/modules/note/NoteModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/note/NoteModule.java @@ -2,16 +2,17 @@ import eu.pb4.placeholders.api.PlaceholderContext; import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.proxy.ProxyServerPlayConnectionEvents; import me.alexdevs.solstice.api.module.ModuleBase; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.api.text.Components; import me.alexdevs.solstice.modules.note.commands.NotesCommand; import me.alexdevs.solstice.modules.note.data.Note; import me.alexdevs.solstice.modules.note.data.NoteConfig; import me.alexdevs.solstice.modules.note.data.NoteLocale; import me.alexdevs.solstice.modules.note.data.NotePlayerData; -import me.lucko.fabric.api.permissions.v0.Permissions; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.network.chat.Component; + import java.util.List; import java.util.Map; import java.util.UUID; @@ -31,12 +32,12 @@ public void init() { commands.add(new NotesCommand(this)); - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { + ProxyServerPlayConnectionEvents.JOIN.register((player, server) -> { var config = Solstice.configManager.getData(NoteConfig.class); + if (!config.showLogin) return; - var player = handler.getPlayer(); var notes = getNotes(player.getUUID()); if (notes.isEmpty()) @@ -49,11 +50,13 @@ public void init() { locale().raw("hoverCheck"), "/notes " + player.getGameProfile().getName() ); - final var text = locale().get("loginInfo", context, Map.of( - "user", Component.nullToEmpty(player.getGameProfile().getName()), - "notes", Component.nullToEmpty(String.valueOf(notes.size())), - "checkButton", checkButton - )); + final var text = locale().get( + "loginInfo", context, Map.of( + "user", Component.nullToEmpty(player.getGameProfile().getName()), + "notes", Component.nullToEmpty(String.valueOf(notes.size())), + "checkButton", checkButton + ) + ); Solstice.nextTick(() -> server.getPlayerList().getPlayers().forEach(pl -> { diff --git a/src/main/java/me/alexdevs/solstice/modules/note/commands/NotesCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/note/commands/NotesCommand.java similarity index 99% rename from src/main/java/me/alexdevs/solstice/modules/note/commands/NotesCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/note/commands/NotesCommand.java index 98771570..9914dcd2 100644 --- a/src/main/java/me/alexdevs/solstice/modules/note/commands/NotesCommand.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/note/commands/NotesCommand.java @@ -7,12 +7,12 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import me.alexdevs.solstice.api.command.LocalGameProfile; import me.alexdevs.solstice.api.module.ModCommand; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.api.text.Components; import me.alexdevs.solstice.api.text.Format; import me.alexdevs.solstice.core.coreModule.CoreModule; import me.alexdevs.solstice.modules.note.NoteModule; import me.alexdevs.solstice.modules.note.data.Note; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; import java.text.SimpleDateFormat; diff --git a/src/main/java/me/alexdevs/solstice/modules/note/data/Note.java b/common/src/main/java/me/alexdevs/solstice/modules/note/data/Note.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/note/data/Note.java rename to common/src/main/java/me/alexdevs/solstice/modules/note/data/Note.java diff --git a/src/main/java/me/alexdevs/solstice/modules/note/data/NoteConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/note/data/NoteConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/note/data/NoteConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/note/data/NoteConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/note/data/NoteLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/note/data/NoteLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/note/data/NoteLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/note/data/NoteLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/note/data/NotePlayerData.java b/common/src/main/java/me/alexdevs/solstice/modules/note/data/NotePlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/note/data/NotePlayerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/note/data/NotePlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/notifications/NotificationsModule.java b/common/src/main/java/me/alexdevs/solstice/modules/notifications/NotificationsModule.java similarity index 86% rename from src/main/java/me/alexdevs/solstice/modules/notifications/NotificationsModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/notifications/NotificationsModule.java index 1e895936..a94b6d17 100644 --- a/src/main/java/me/alexdevs/solstice/modules/notifications/NotificationsModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/notifications/NotificationsModule.java @@ -1,6 +1,7 @@ package me.alexdevs.solstice.modules.notifications; import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.proxy.ProxyServerMessageEvents; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.modules.afk.AfkModule; import me.alexdevs.solstice.modules.notifications.commands.NotificationsCommand; @@ -8,7 +9,6 @@ import me.alexdevs.solstice.modules.notifications.data.NotificationsLocale; import me.alexdevs.solstice.modules.notifications.data.NotificationsPlayerData; import me.alexdevs.solstice.modules.notifications.data.PlayerNotificationSettings; -import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; @@ -29,11 +29,11 @@ public void init() { commands.add(new NotificationsCommand(this)); - ServerMessageEvents.CHAT_MESSAGE.register((message, sender, parameters) -> { + ProxyServerMessageEvents.CHAT_MESSAGE.register((message, sender, parameters) -> { var content = message.decoratedContent().getString().toLowerCase(); sender.getServer().getPlayerList().getPlayers().forEach(player -> { - if(player.equals(sender)) { + if (player.equals(sender)) { return; } @@ -50,8 +50,7 @@ public void init() { public static void notify(ServerPlayer player) { var module = Solstice.modules.getModule(NotificationsModule.class); - if (!module.isEnabled()) - return; + if (!module.isEnabled()) return; module.notifyPlayer(player); } @@ -78,14 +77,12 @@ public PlayerNotificationSettings getPlayerSettings(ServerPlayer player) { } public boolean shouldNotify(ServerPlayer player) { - if (!isEnabled()) - return false; + if (!isEnabled()) return false; var data = getPlayerData(player); var settings = getPlayerSettings(player); - if (!data.enable) - return false; + if (!data.enable) return false; var afkModule = Solstice.modules.getModule(AfkModule.class); if (afkModule.isEnabled()) { @@ -96,8 +93,7 @@ public boolean shouldNotify(ServerPlayer player) { } public void notifyPlayer(ServerPlayer player) { - if (!shouldNotify(player)) - return; + if (!shouldNotify(player)) return; var settings = getPlayerSettings(player); var id = ResourceLocation.tryParse(settings.soundId()); @@ -105,6 +101,11 @@ public void notifyPlayer(ServerPlayer player) { return; } - player.playNotifySound(SoundEvent.createVariableRangeEvent(id), SoundSource.MASTER, settings.volume(), settings.pitch()); + player.playNotifySound( + SoundEvent.createVariableRangeEvent(id), + SoundSource.MASTER, + settings.volume(), + settings.pitch() + ); } } diff --git a/src/main/java/me/alexdevs/solstice/modules/notifications/commands/NotificationsCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/notifications/commands/NotificationsCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/notifications/commands/NotificationsCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/notifications/commands/NotificationsCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/notifications/data/NotificationsConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/notifications/data/NotificationsConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/notifications/data/NotificationsConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/notifications/data/NotificationsConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/notifications/data/NotificationsLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/notifications/data/NotificationsLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/notifications/data/NotificationsLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/notifications/data/NotificationsLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/notifications/data/NotificationsPlayerData.java b/common/src/main/java/me/alexdevs/solstice/modules/notifications/data/NotificationsPlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/notifications/data/NotificationsPlayerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/notifications/data/NotificationsPlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/notifications/data/PlayerNotificationSettings.java b/common/src/main/java/me/alexdevs/solstice/modules/notifications/data/PlayerNotificationSettings.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/notifications/data/PlayerNotificationSettings.java rename to common/src/main/java/me/alexdevs/solstice/modules/notifications/data/PlayerNotificationSettings.java diff --git a/src/main/java/me/alexdevs/solstice/modules/placeholders/PlaceholdersModule.java b/common/src/main/java/me/alexdevs/solstice/modules/placeholders/PlaceholdersModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/placeholders/PlaceholdersModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/placeholders/PlaceholdersModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/powertool/Action.java b/common/src/main/java/me/alexdevs/solstice/modules/powertool/Action.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/powertool/Action.java rename to common/src/main/java/me/alexdevs/solstice/modules/powertool/Action.java diff --git a/src/main/java/me/alexdevs/solstice/modules/powertool/PowerToolModule.java b/common/src/main/java/me/alexdevs/solstice/modules/powertool/PowerToolModule.java similarity index 89% rename from src/main/java/me/alexdevs/solstice/modules/powertool/PowerToolModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/powertool/PowerToolModule.java index 83948df4..e000d8f0 100644 --- a/src/main/java/me/alexdevs/solstice/modules/powertool/PowerToolModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/powertool/PowerToolModule.java @@ -5,17 +5,17 @@ import eu.pb4.placeholders.api.PlaceholderContext; import eu.pb4.placeholders.api.Placeholders; import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.proxy.*; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.modules.powertool.commands.PowerToolCommand; import me.alexdevs.solstice.modules.powertool.data.PowerToolLocale; import me.alexdevs.solstice.modules.powertool.data.PowerToolPlayerData; -import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.player.*; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.item.ItemStack; + import java.util.UUID; public class PowerToolModule extends ModuleBase.Toggleable { @@ -34,10 +34,10 @@ public void init() { commands.add(new PowerToolCommand(this)); - CommandRegistrationCallback.EVENT.register((dispatcher, registry, environment) -> this.dispatcher = dispatcher); + ProxyCommandRegistrationCallback.EVENT.register((dispatcher, registry, environment) -> this.dispatcher = dispatcher); // USE - UseItemCallback.EVENT.register((player, world, hand) -> { + ProxyUseItemCallback.EVENT.register((player, world, hand) -> { var stack = player.getItemInHand(hand); if (!stack.isEmpty()) { var data = getData(player.getUUID()); @@ -56,7 +56,7 @@ public void init() { }); // ATTACK_BLOCK - AttackBlockCallback.EVENT.register((player, world, hand, blockPos, direction) -> { + ProxyAttackBlockCallback.EVENT.register((player, world, hand, blockPos, direction) -> { var stack = player.getItemInHand(hand); if (!stack.isEmpty()) { var data = getData(player.getUUID()); @@ -75,7 +75,7 @@ public void init() { }); // ATTACK_ENTITY - AttackEntityCallback.EVENT.register((player, world, hand, entity, entityHitResult) -> { + ProxyAttackEntityCallback.EVENT.register((player, world, hand, entity, entityHitResult) -> { var stack = player.getItemInHand(hand); if (!stack.isEmpty()) { var data = getData(player.getUUID()); @@ -94,7 +94,7 @@ public void init() { }); // INTERACT_BLOCK - UseBlockCallback.EVENT.register((player, world, hand, blockHitResult) -> { + ProxyUseBlockCallback.EVENT.register((player, world, hand, blockHitResult) -> { var stack = player.getItemInHand(hand); if (!stack.isEmpty()) { var data = getData(player.getUUID()); @@ -113,7 +113,7 @@ public void init() { }); // INTERACT_ENTITY - UseEntityCallback.EVENT.register((player, world, hand, entity, hit) -> { + ProxyUseEntityCallback.EVENT.register((player, world, hand, entity, hit) -> { var stack = player.getItemInHand(hand); if (!stack.isEmpty()) { var data = getData(player.getUUID()); diff --git a/src/main/java/me/alexdevs/solstice/modules/powertool/commands/PowerToolCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/powertool/commands/PowerToolCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/powertool/commands/PowerToolCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/powertool/commands/PowerToolCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/powertool/data/PowerToolLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/powertool/data/PowerToolLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/powertool/data/PowerToolLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/powertool/data/PowerToolLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/powertool/data/PowerToolPlayerData.java b/common/src/main/java/me/alexdevs/solstice/modules/powertool/data/PowerToolPlayerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/powertool/data/PowerToolPlayerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/powertool/data/PowerToolPlayerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/restart/RestartModule.java b/common/src/main/java/me/alexdevs/solstice/modules/restart/RestartModule.java similarity index 83% rename from src/main/java/me/alexdevs/solstice/modules/restart/RestartModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/restart/RestartModule.java index ccbae3dd..99982a0b 100644 --- a/src/main/java/me/alexdevs/solstice/modules/restart/RestartModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/restart/RestartModule.java @@ -5,7 +5,6 @@ import me.alexdevs.solstice.api.events.SolsticeEvents; import me.alexdevs.solstice.api.events.TimeBarEvents; import me.alexdevs.solstice.api.module.ModuleBase; -import me.alexdevs.solstice.integrations.ConnectorIntegration; import me.alexdevs.solstice.modules.restart.commands.RestartCommand; import me.alexdevs.solstice.modules.restart.data.RestartConfig; import me.alexdevs.solstice.modules.restart.data.RestartLocale; @@ -54,8 +53,7 @@ public void init() { }); TimeBarEvents.PROGRESS.register((timeBar, server) -> { - if (restartBar == null || !timeBar.getUuid().equals(restartBar.getUuid())) - return; + if (restartBar == null || !timeBar.getUuid().equals(restartBar.getUuid())) return; var notificationTimes = getConfig().restartNotifications; @@ -68,8 +66,7 @@ public void init() { // Shutdown TimeBarEvents.END.register((timeBar, server) -> { - if (restartBar == null || !timeBar.getUuid().equals(restartBar.getUuid())) - return; + if (restartBar == null || !timeBar.getUuid().equals(restartBar.getUuid())) return; restart(); }); @@ -79,8 +76,7 @@ public void init() { @Override public boolean isEnabled() { - if (!Solstice.modules.getModule(TimeBarModule.class).isEnabled()) - return false; + if (!Solstice.modules.getModule(TimeBarModule.class).isEnabled()) return false; return super.isEnabled(); } @@ -110,17 +106,14 @@ public BossEvent.BossBarColor getBarColor() { } public void restart() { - if (!ConnectorIntegration.isForge()) { - var kickMessage = locale().get("kickMessage"); - for (var player : Solstice.server.getPlayerList().getPlayers()) { - try { - player.connection.disconnect(kickMessage); - } catch (Exception e) { - Solstice.LOGGER.error("An error occurred while disconnecting player {}", player, e); - } + var kickMessage = locale().get("kickMessage"); + + for (var player : Solstice.server.getPlayerList().getPlayers()) { + try { + player.connection.disconnect(kickMessage); + } catch (Exception e) { + Solstice.LOGGER.error("An error occurred while disconnecting player {}", player, e); } - } else { - Solstice.LOGGER.warn("Kicking players with restart message is not compatible with Forge at the moment."); } Solstice.server.halt(false); @@ -129,6 +122,7 @@ public void restart() { private void setup() { var soundName = getConfig().restartSound; var id = ResourceLocation.tryParse(soundName); + if (id == null) { Solstice.LOGGER.error("Invalid restart notification sound name {}", soundName); sound = SoundEvents.NOTE_BLOCK_BELL.value(); @@ -144,13 +138,7 @@ public void schedule(int seconds, String message, RestartEvents.RestartType rest } var timeBar = Solstice.modules.getModule(TimeBarModule.class); - restartBar = timeBar.startTimeBar( - message, - seconds, - getBarColor(), - getBarStyle(), - true - ); + restartBar = timeBar.startTimeBar(message, seconds, getBarColor(), getBarStyle(), true); RestartEvents.SCHEDULED.invoker().onSchedule(restartBar, restartType); } @@ -183,19 +171,24 @@ private void notifyRestart(MinecraftServer server, TimeBar bar) { solstice.broadcast(text); var pitch = getConfig().restartSoundPitch; - server.getPlayerList().getPlayers().forEach(player -> player.playNotifySound(sound, SoundSource.MASTER, 1f, pitch)); + server.getPlayerList() + .getPlayers() + .forEach(player -> player.playNotifySound(sound, SoundSource.MASTER, 1f, pitch)); } @Nullable public Long scheduleNextRestart() { var delay = getNextDelay(); - if (delay == null) - return null; + if (delay == null) return null; var barTime = getConfig().restartNotifications.stream().max(Integer::compareTo).orElse(600); var barStartTime = delay - barTime; - currentSchedule = Solstice.scheduler.schedule(() -> schedule(barTime, locale().raw("barLabel"), RestartEvents.RestartType.AUTOMATIC), barStartTime, TimeUnit.SECONDS); + currentSchedule = Solstice.scheduler.schedule( + () -> schedule(barTime, locale().raw("barLabel"), RestartEvents.RestartType.AUTOMATIC), + barStartTime, + TimeUnit.SECONDS + ); Solstice.LOGGER.info("Restart scheduled for in {} seconds", delay); return delay; diff --git a/src/main/java/me/alexdevs/solstice/modules/restart/commands/RestartCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/restart/commands/RestartCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/restart/commands/RestartCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/restart/commands/RestartCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/restart/data/RestartConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/restart/data/RestartConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/restart/data/RestartConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/restart/data/RestartConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/restart/data/RestartLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/restart/data/RestartLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/restart/data/RestartLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/restart/data/RestartLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/rtp/RTPModule.java b/common/src/main/java/me/alexdevs/solstice/modules/rtp/RTPModule.java similarity index 90% rename from src/main/java/me/alexdevs/solstice/modules/rtp/RTPModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/rtp/RTPModule.java index b1a869de..9d02aaab 100644 --- a/src/main/java/me/alexdevs/solstice/modules/rtp/RTPModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/rtp/RTPModule.java @@ -1,15 +1,16 @@ package me.alexdevs.solstice.modules.rtp; import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.proxy.ProxyServerTickEvents; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.modules.rtp.commands.RTPCommand; import me.alexdevs.solstice.modules.rtp.core.Locator; import me.alexdevs.solstice.modules.rtp.data.RTPConfig; import me.alexdevs.solstice.modules.rtp.data.RTPLocale; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.biome.Biome; + import java.util.ArrayList; public class RTPModule extends ModuleBase.Toggleable { @@ -28,7 +29,7 @@ public void init() { commands.add(new RTPCommand(this)); - ServerTickEvents.END_SERVER_TICK.register(server -> locators.removeIf(Locator::tick)); + ProxyServerTickEvents.END_SERVER_TICK.register(server -> locators.removeIf(Locator::tick)); } public RTPConfig getConfig() { diff --git a/src/main/java/me/alexdevs/solstice/modules/rtp/commands/RTPCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/rtp/commands/RTPCommand.java similarity index 99% rename from src/main/java/me/alexdevs/solstice/modules/rtp/commands/RTPCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/rtp/commands/RTPCommand.java index 34fa8c1d..79c5d243 100644 --- a/src/main/java/me/alexdevs/solstice/modules/rtp/commands/RTPCommand.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/rtp/commands/RTPCommand.java @@ -5,10 +5,10 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.module.ModCommand; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.api.utils.RegistryUtils; import me.alexdevs.solstice.modules.rtp.RTPModule; import me.alexdevs.solstice.modules.rtp.core.Locator; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.arguments.ResourceArgument; diff --git a/src/main/java/me/alexdevs/solstice/modules/rtp/core/Locator.java b/common/src/main/java/me/alexdevs/solstice/modules/rtp/core/Locator.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/rtp/core/Locator.java rename to common/src/main/java/me/alexdevs/solstice/modules/rtp/core/Locator.java diff --git a/src/main/java/me/alexdevs/solstice/modules/rtp/data/RTPConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/rtp/data/RTPConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/rtp/data/RTPConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/rtp/data/RTPConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/rtp/data/RTPLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/rtp/data/RTPLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/rtp/data/RTPLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/rtp/data/RTPLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/seen/SeenModule.java b/common/src/main/java/me/alexdevs/solstice/modules/seen/SeenModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/seen/SeenModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/seen/SeenModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/seen/commands/SeenCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/seen/commands/SeenCommand.java similarity index 98% rename from src/main/java/me/alexdevs/solstice/modules/seen/commands/SeenCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/seen/commands/SeenCommand.java index 0d5389a7..55fd0202 100644 --- a/src/main/java/me/alexdevs/solstice/modules/seen/commands/SeenCommand.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/seen/commands/SeenCommand.java @@ -6,10 +6,10 @@ import me.alexdevs.solstice.api.ServerLocation; import me.alexdevs.solstice.api.command.LocalGameProfile; import me.alexdevs.solstice.api.module.ModCommand; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.core.coreModule.CoreModule; import me.alexdevs.solstice.modules.seen.SeenModule; import me.alexdevs.solstice.api.text.Format; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/me/alexdevs/solstice/modules/seen/data/SeenLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/seen/data/SeenLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/seen/data/SeenLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/seen/data/SeenLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/sign/SignModule.java b/common/src/main/java/me/alexdevs/solstice/modules/sign/SignModule.java similarity index 94% rename from src/main/java/me/alexdevs/solstice/modules/sign/SignModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/sign/SignModule.java index 94443edf..a303cf7f 100644 --- a/src/main/java/me/alexdevs/solstice/modules/sign/SignModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/sign/SignModule.java @@ -2,10 +2,11 @@ import eu.pb4.placeholders.api.parsers.LegacyFormattingParser; import me.alexdevs.solstice.api.module.ModuleBase; -import me.lucko.fabric.api.permissions.v0.Permissions; +import me.alexdevs.solstice.api.permissions.Permissions; import net.minecraft.server.network.FilteredText; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.block.entity.SignText; + import java.util.List; public class SignModule extends ModuleBase.Toggleable { diff --git a/src/main/java/me/alexdevs/solstice/modules/skull/SkullModule.java b/common/src/main/java/me/alexdevs/solstice/modules/skull/SkullModule.java similarity index 94% rename from src/main/java/me/alexdevs/solstice/modules/skull/SkullModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/skull/SkullModule.java index 036f2513..716cc666 100644 --- a/src/main/java/me/alexdevs/solstice/modules/skull/SkullModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/skull/SkullModule.java @@ -5,10 +5,8 @@ import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.modules.skull.commands.SkullCommand; import net.minecraft.core.component.DataComponents; -import net.minecraft.nbt.StringTag; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.item.PlayerHeadItem; import net.minecraft.world.item.component.ResolvableProfile; import java.util.Optional; diff --git a/src/main/java/me/alexdevs/solstice/modules/skull/commands/SkullCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/skull/commands/SkullCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/skull/commands/SkullCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/skull/commands/SkullCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/smite/SmiteModule.java b/common/src/main/java/me/alexdevs/solstice/modules/smite/SmiteModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/smite/SmiteModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/smite/SmiteModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/smite/commands/SmiteCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/smite/commands/SmiteCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/smite/commands/SmiteCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/smite/commands/SmiteCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/spawn/SpawnModule.java b/common/src/main/java/me/alexdevs/solstice/modules/spawn/SpawnModule.java similarity index 83% rename from src/main/java/me/alexdevs/solstice/modules/spawn/SpawnModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/spawn/SpawnModule.java index 03765ae0..bfb5e2c4 100644 --- a/src/main/java/me/alexdevs/solstice/modules/spawn/SpawnModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/spawn/SpawnModule.java @@ -3,6 +3,7 @@ import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.ServerLocation; import me.alexdevs.solstice.api.events.SolsticeEvents; +import me.alexdevs.solstice.api.events.proxy.ProxyServerPlayConnectionEvents; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.modules.spawn.commands.FirstSpawnCommand; import me.alexdevs.solstice.modules.spawn.commands.SetFirstSpawnCommand; @@ -11,7 +12,6 @@ import me.alexdevs.solstice.modules.spawn.data.SpawnConfig; import me.alexdevs.solstice.modules.spawn.data.SpawnLocale; import me.alexdevs.solstice.modules.spawn.data.SpawnServerData; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; @@ -48,21 +48,25 @@ public void init() { } }); - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { + ProxyServerPlayConnectionEvents.JOIN.register((player, server) -> { var config = getConfig(); if (config.globalSpawn.onLogin) { Solstice.nextTick(() -> { - getGlobalSpawnPosition().teleport(handler.getPlayer(), false); + getGlobalSpawnPosition().teleport(player, false); }); } }); SolsticeEvents.READY.register((instance, server) -> { var spawnData = getServerData(); + if (spawnData.spawn != null) { var legacy = spawnData.spawn; var world = legacy.getWorld(server); - world.setDefaultSpawnPos(new BlockPos((int) legacy.getX(), (int) legacy.getY(), (int) legacy.getZ()), legacy.getYaw()); + world.setDefaultSpawnPos( + new BlockPos((int) legacy.getX(), (int) legacy.getY(), (int) legacy.getZ()), + legacy.getYaw() + ); spawnData.spawn = null; } }); @@ -75,7 +79,14 @@ public ServerLocation getSpawn() { if (spawnPosition == null) { var server = Solstice.server; var spawnPos = server.overworld().getSharedSpawnPos(); - spawnPosition = new ServerLocation(spawnPos.getX(), spawnPos.getY(), spawnPos.getZ(), 0, 0, server.overworld()); + spawnPosition = new ServerLocation( + spawnPos.getX(), + spawnPos.getY(), + spawnPos.getZ(), + 0, + 0, + server.overworld() + ); } return spawnPosition; } @@ -104,8 +115,12 @@ public ServerLocation getWorldSpawn(ServerLevel world) { } return new ServerLocation( - worldSpawnPosition.x(), worldSpawnPosition.y(), worldSpawnPosition.z(), - worldSpawnYaw, 0, world + worldSpawnPosition.x(), + worldSpawnPosition.y(), + worldSpawnPosition.z(), + worldSpawnYaw, + 0, + world ); } diff --git a/src/main/java/me/alexdevs/solstice/modules/spawn/commands/FirstSpawnCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/spawn/commands/FirstSpawnCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/spawn/commands/FirstSpawnCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/spawn/commands/FirstSpawnCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/spawn/commands/SetFirstSpawnCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/spawn/commands/SetFirstSpawnCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/spawn/commands/SetFirstSpawnCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/spawn/commands/SetFirstSpawnCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/spawn/commands/SetSpawnCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/spawn/commands/SetSpawnCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/spawn/commands/SetSpawnCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/spawn/commands/SetSpawnCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/spawn/commands/SpawnCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/spawn/commands/SpawnCommand.java similarity index 98% rename from src/main/java/me/alexdevs/solstice/modules/spawn/commands/SpawnCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/spawn/commands/SpawnCommand.java index f4f77dee..46fcf88b 100644 --- a/src/main/java/me/alexdevs/solstice/modules/spawn/commands/SpawnCommand.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/spawn/commands/SpawnCommand.java @@ -5,8 +5,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import eu.pb4.placeholders.api.PlaceholderContext; import me.alexdevs.solstice.api.module.ModCommand; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.modules.spawn.SpawnModule; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.arguments.DimensionArgument; import net.minecraft.commands.arguments.EntityArgument; diff --git a/src/main/java/me/alexdevs/solstice/modules/spawn/data/SpawnConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/spawn/data/SpawnConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/spawn/data/SpawnConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/spawn/data/SpawnConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/spawn/data/SpawnLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/spawn/data/SpawnLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/spawn/data/SpawnLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/spawn/data/SpawnLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/spawn/data/SpawnServerData.java b/common/src/main/java/me/alexdevs/solstice/modules/spawn/data/SpawnServerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/spawn/data/SpawnServerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/spawn/data/SpawnServerData.java diff --git a/src/main/java/me/alexdevs/solstice/modules/staffChat/StaffChatModule.java b/common/src/main/java/me/alexdevs/solstice/modules/staffChat/StaffChatModule.java similarity index 82% rename from src/main/java/me/alexdevs/solstice/modules/staffChat/StaffChatModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/staffChat/StaffChatModule.java index c856a8b6..b49c15a0 100644 --- a/src/main/java/me/alexdevs/solstice/modules/staffChat/StaffChatModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/staffChat/StaffChatModule.java @@ -2,14 +2,15 @@ import eu.pb4.placeholders.api.node.TextNode; import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.proxy.ProxyServerMessageEvents; import me.alexdevs.solstice.api.module.ModuleBase; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.api.text.parser.MarkdownParser; import me.alexdevs.solstice.modules.staffChat.commands.StaffChatCommand; import me.alexdevs.solstice.modules.staffChat.data.StaffChatLocale; -import me.lucko.fabric.api.permissions.v0.Permissions; -import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; + import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -28,14 +29,12 @@ public void init() { commands.add(new StaffChatCommand(this)); - ServerMessageEvents.ALLOW_CHAT_MESSAGE.register((message, player, pars) -> { - if (stickyStaffChat.getOrDefault(player.getUUID(), false) - && canUseStaffChat(player)) { - + ProxyServerMessageEvents.ALLOW_CHAT_MESSAGE.register((message, player, pars) -> { + if (stickyStaffChat.getOrDefault(player.getUUID(), false) && canUseStaffChat(player)) { sendStaffChatMessage(player.getDisplayName(), message.decoratedContent()); - return false; } + return true; }); } @@ -48,10 +47,8 @@ public void sendStaffChatMessage(Component sourceName, final Component message) var formattedMessage = MarkdownParser.defaultParser.parseNode(TextNode.convert(message)).toText(); - var text = Solstice.localeManager.getLocale(ID).get("message", Map.of( - "name", sourceName, - "message", formattedMessage - )); + var text = Solstice.localeManager.getLocale(ID) + .get("message", Map.of("name", sourceName, "message", formattedMessage)); Solstice.server.sendSystemMessage(text); Solstice.server.getPlayerList().getPlayers().forEach(player -> { diff --git a/src/main/java/me/alexdevs/solstice/modules/staffChat/commands/StaffChatCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/staffChat/commands/StaffChatCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/staffChat/commands/StaffChatCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/staffChat/commands/StaffChatCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/staffChat/data/StaffChatLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/staffChat/data/StaffChatLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/staffChat/data/StaffChatLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/staffChat/data/StaffChatLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/styling/CustomSentMessage.java b/common/src/main/java/me/alexdevs/solstice/modules/styling/CustomSentMessage.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/styling/CustomSentMessage.java rename to common/src/main/java/me/alexdevs/solstice/modules/styling/CustomSentMessage.java diff --git a/src/main/java/me/alexdevs/solstice/modules/styling/StylingModule.java b/common/src/main/java/me/alexdevs/solstice/modules/styling/StylingModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/styling/StylingModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/styling/StylingModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/styling/data/StylingConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/styling/data/StylingConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/styling/data/StylingConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/styling/data/StylingConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/styling/formatters/AdvancementFormatter.java b/common/src/main/java/me/alexdevs/solstice/modules/styling/formatters/AdvancementFormatter.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/styling/formatters/AdvancementFormatter.java rename to common/src/main/java/me/alexdevs/solstice/modules/styling/formatters/AdvancementFormatter.java diff --git a/src/main/java/me/alexdevs/solstice/modules/styling/formatters/ChatFormatter.java b/common/src/main/java/me/alexdevs/solstice/modules/styling/formatters/ChatFormatter.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/styling/formatters/ChatFormatter.java rename to common/src/main/java/me/alexdevs/solstice/modules/styling/formatters/ChatFormatter.java diff --git a/src/main/java/me/alexdevs/solstice/modules/styling/formatters/ConnectionActivityFormatter.java b/common/src/main/java/me/alexdevs/solstice/modules/styling/formatters/ConnectionActivityFormatter.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/styling/formatters/ConnectionActivityFormatter.java rename to common/src/main/java/me/alexdevs/solstice/modules/styling/formatters/ConnectionActivityFormatter.java diff --git a/src/main/java/me/alexdevs/solstice/modules/styling/formatters/DeathFormatter.java b/common/src/main/java/me/alexdevs/solstice/modules/styling/formatters/DeathFormatter.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/styling/formatters/DeathFormatter.java rename to common/src/main/java/me/alexdevs/solstice/modules/styling/formatters/DeathFormatter.java diff --git a/src/main/java/me/alexdevs/solstice/modules/styling/formatters/EmoteFormatter.java b/common/src/main/java/me/alexdevs/solstice/modules/styling/formatters/EmoteFormatter.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/styling/formatters/EmoteFormatter.java rename to common/src/main/java/me/alexdevs/solstice/modules/styling/formatters/EmoteFormatter.java diff --git a/src/main/java/me/alexdevs/solstice/modules/sudo/SudoModule.java b/common/src/main/java/me/alexdevs/solstice/modules/sudo/SudoModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/sudo/SudoModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/sudo/SudoModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/sudo/commands/DoAsCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/sudo/commands/DoAsCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/sudo/commands/DoAsCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/sudo/commands/DoAsCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/sudo/commands/SudoCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/sudo/commands/SudoCommand.java similarity index 98% rename from src/main/java/me/alexdevs/solstice/modules/sudo/commands/SudoCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/sudo/commands/SudoCommand.java index da8f1c48..4befb8db 100644 --- a/src/main/java/me/alexdevs/solstice/modules/sudo/commands/SudoCommand.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/sudo/commands/SudoCommand.java @@ -4,8 +4,8 @@ import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import me.alexdevs.solstice.api.module.ModCommand; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.modules.sudo.SudoModule; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.commands.CommandSource; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.ClickEvent; diff --git a/src/main/java/me/alexdevs/solstice/modules/suicide/SuicideModule.java b/common/src/main/java/me/alexdevs/solstice/modules/suicide/SuicideModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/suicide/SuicideModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/suicide/SuicideModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/suicide/commands/SuicideCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/suicide/commands/SuicideCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/suicide/commands/SuicideCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/suicide/commands/SuicideCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/tablist/TabListModule.java b/common/src/main/java/me/alexdevs/solstice/modules/tablist/TabListModule.java similarity index 89% rename from src/main/java/me/alexdevs/solstice/modules/tablist/TabListModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/tablist/TabListModule.java index 4067cbc9..51f8e514 100644 --- a/src/main/java/me/alexdevs/solstice/modules/tablist/TabListModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/tablist/TabListModule.java @@ -3,11 +3,11 @@ import eu.pb4.placeholders.api.PlaceholderContext; import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.events.SolsticeEvents; +import me.alexdevs.solstice.api.events.proxy.ProxyServerLifecycleEvents; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.api.text.Format; import me.alexdevs.solstice.api.text.RawPlaceholder; import me.alexdevs.solstice.modules.tablist.data.TabListConfig; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.minecraft.network.protocol.game.ClientboundTabListPacket; import net.minecraft.server.MinecraftServer; @@ -29,8 +29,9 @@ public TabListModule() { public void init() { Solstice.configManager.registerData(ID, TabListConfig.class, TabListConfig::new); - ServerLifecycleEvents.SERVER_STARTED.register(server -> { + ProxyServerLifecycleEvents.SERVER_STARTED.register(server -> { this.server = server; + schedule(); }); @@ -38,6 +39,7 @@ public void init() { if (scheduledFuture != null) { scheduledFuture.cancel(false); } + schedule(); }); } @@ -47,7 +49,12 @@ private void schedule() { if (!config.enable) return; - scheduledFuture = Solstice.scheduler.scheduleAtFixedRate(this::updateTab, 0, config.delay, TimeUnit.MILLISECONDS); + scheduledFuture = Solstice.scheduler.scheduleAtFixedRate( + this::updateTab, + 0, + config.delay, + TimeUnit.MILLISECONDS + ); } public void updateTab() { diff --git a/src/main/java/me/alexdevs/solstice/modules/tablist/data/TabListConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/tablist/data/TabListConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/tablist/data/TabListConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/tablist/data/TabListConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/teleportHere/TeleportHereModule.java b/common/src/main/java/me/alexdevs/solstice/modules/teleportHere/TeleportHereModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/teleportHere/TeleportHereModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/teleportHere/TeleportHereModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/teleportHere/commands/TeleportHereCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/teleportHere/commands/TeleportHereCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/teleportHere/commands/TeleportHereCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/teleportHere/commands/TeleportHereCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/teleportOffline/TeleportOfflineModule.java b/common/src/main/java/me/alexdevs/solstice/modules/teleportOffline/TeleportOfflineModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/teleportOffline/TeleportOfflineModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/teleportOffline/TeleportOfflineModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/teleportOffline/commands/TeleportOfflineCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/teleportOffline/commands/TeleportOfflineCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/teleportOffline/commands/TeleportOfflineCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/teleportOffline/commands/TeleportOfflineCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/teleportPosition/TeleportPositionModule.java b/common/src/main/java/me/alexdevs/solstice/modules/teleportPosition/TeleportPositionModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/teleportPosition/TeleportPositionModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/teleportPosition/TeleportPositionModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/teleportPosition/commands/TeleportPositionCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/teleportPosition/commands/TeleportPositionCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/teleportPosition/commands/TeleportPositionCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/teleportPosition/commands/TeleportPositionCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/teleportRequest/TeleportRequestModule.java b/common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/TeleportRequestModule.java similarity index 77% rename from src/main/java/me/alexdevs/solstice/modules/teleportRequest/TeleportRequestModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/TeleportRequestModule.java index 6768ac0c..2070adc1 100644 --- a/src/main/java/me/alexdevs/solstice/modules/teleportRequest/TeleportRequestModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/TeleportRequestModule.java @@ -3,6 +3,7 @@ import eu.pb4.placeholders.api.PlaceholderContext; import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.ServerLocation; +import me.alexdevs.solstice.api.events.proxy.ProxyServerPlayConnectionEvents; import me.alexdevs.solstice.api.module.ModuleBase; import me.alexdevs.solstice.api.text.Components; import me.alexdevs.solstice.modules.notifications.NotificationsModule; @@ -13,8 +14,8 @@ import me.alexdevs.solstice.modules.teleportRequest.data.Request; import me.alexdevs.solstice.modules.teleportRequest.data.TeleportConfig; import me.alexdevs.solstice.modules.teleportRequest.data.TeleportLocale; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.server.level.ServerPlayer; + import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -42,8 +43,13 @@ public void init() { Solstice.scheduler.scheduleAtFixedRate(this::tickDown, 0, 1, TimeUnit.SECONDS); - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> requests.put(handler.getPlayer().getUUID(), new ConcurrentLinkedDeque<>())); - ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> Solstice.nextTick(() -> requests.remove(handler.getPlayer().getUUID()))); + ProxyServerPlayConnectionEvents.JOIN.register((player, server) -> requests.put( + player.getUUID(), + new ConcurrentLinkedDeque<>() + )); + + ProxyServerPlayConnectionEvents.DISCONNECT.register((player, server) -> Solstice.nextTick(() -> requests.remove( + player.getUUID()))); } private void tickDown() { @@ -66,8 +72,7 @@ public Request getRequestFromSource(ServerPlayer player, ServerPlayer source) { public Request getLatestRequest(ServerPlayer player) { var reqs = requests.get(player.getUUID()); - if (reqs.isEmpty()) - return null; + if (reqs.isEmpty()) return null; return reqs.getLast(); } @@ -77,9 +82,7 @@ public void acceptRequest(ServerPlayer player, Request request) { var source = request.getSource(); var direction = request.getDirection(); - var map = Map.of( - "player", player.getDisplayName() - ); + var map = Map.of("player", player.getDisplayName()); player.sendSystemMessage(locale().get("targetAccepted")); source.sendSystemMessage(locale().get("sourceAccepted", map)); @@ -97,9 +100,7 @@ public void refuseRequest(ServerPlayer player, Request request) { requests.get(player.getUUID()).remove(request); var source = request.getSource(); - var map = Map.of( - "player", player.getDisplayName() - ); + var map = Map.of("player", player.getDisplayName()); player.sendSystemMessage(locale().get("targetRefused")); source.sendSystemMessage(locale().get("sourceRefused", map)); @@ -113,27 +114,20 @@ public void requestTo(ServerPlayer source, ServerPlayer target) { var targetContext = PlaceholderContext.of(target); var placeholders = Map.of( - "requesterPlayer", source.getDisplayName(), - "acceptButton", Components.button( + "requesterPlayer", source.getDisplayName(), "acceptButton", Components.button( locale().raw("~accept"), locale().raw("~accept.hover"), - "/tpaccept " + source.getGameProfile().getName()), - "refuseButton", Components.button( + "/tpaccept " + source.getGameProfile().getName() + ), "refuseButton", Components.button( locale().raw("~refuse"), locale().raw("~refuse.hover"), - "/tpdeny " + source.getGameProfile().getName()) + "/tpdeny " + source.getGameProfile().getName() + ) ); - target.sendSystemMessage(locale().get( - "pendingTeleport", - targetContext, - placeholders - )); + target.sendSystemMessage(locale().get("pendingTeleport", targetContext, placeholders)); - source.sendSystemMessage(locale().get( - "requestSent", - sourceContext - )); + source.sendSystemMessage(locale().get("requestSent", sourceContext)); NotificationsModule.notify(target); } @@ -145,27 +139,20 @@ public void requestToHere(ServerPlayer source, ServerPlayer target) { var sourceContext = PlaceholderContext.of(source); var targetContext = PlaceholderContext.of(target); var placeholders = Map.of( - "requesterPlayer", source.getDisplayName(), - "acceptButton", Components.button( + "requesterPlayer", source.getDisplayName(), "acceptButton", Components.button( locale().raw("~accept"), locale().raw("~accept.hover"), - "/tpaccept " + source.getGameProfile().getName()), - "refuseButton", Components.button( + "/tpaccept " + source.getGameProfile().getName() + ), "refuseButton", Components.button( locale().raw("~refuse"), locale().raw("~refuse.hover"), - "/tpdeny " + source.getGameProfile().getName()) + "/tpdeny " + source.getGameProfile().getName() + ) ); - target.sendSystemMessage(locale().get( - "pendingTeleportHere", - targetContext, - placeholders - )); + target.sendSystemMessage(locale().get("pendingTeleportHere", targetContext, placeholders)); - source.sendSystemMessage(locale().get( - "requestSent", - sourceContext - )); + source.sendSystemMessage(locale().get("requestSent", sourceContext)); NotificationsModule.notify(target); } diff --git a/src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportAcceptCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportAcceptCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportAcceptCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportAcceptCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportAskCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportAskCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportAskCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportAskCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportAskHereCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportAskHereCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportAskHereCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportAskHereCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportDenyCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportDenyCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportDenyCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/commands/TeleportDenyCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/teleportRequest/data/Request.java b/common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/data/Request.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/teleportRequest/data/Request.java rename to common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/data/Request.java diff --git a/src/main/java/me/alexdevs/solstice/modules/teleportRequest/data/TeleportConfig.java b/common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/data/TeleportConfig.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/teleportRequest/data/TeleportConfig.java rename to common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/data/TeleportConfig.java diff --git a/src/main/java/me/alexdevs/solstice/modules/teleportRequest/data/TeleportLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/data/TeleportLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/teleportRequest/data/TeleportLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/teleportRequest/data/TeleportLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/tell/TellModule.java b/common/src/main/java/me/alexdevs/solstice/modules/tell/TellModule.java similarity index 98% rename from src/main/java/me/alexdevs/solstice/modules/tell/TellModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/tell/TellModule.java index b09b0423..0b40011c 100644 --- a/src/main/java/me/alexdevs/solstice/modules/tell/TellModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/tell/TellModule.java @@ -3,16 +3,17 @@ import eu.pb4.placeholders.api.PlaceholderContext; import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.module.ModuleBase; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.modules.ignore.IgnoreModule; import me.alexdevs.solstice.modules.notifications.NotificationsModule; import me.alexdevs.solstice.modules.tell.commands.ReplyCommand; import me.alexdevs.solstice.modules.tell.commands.TellCommand; import me.alexdevs.solstice.modules.tell.data.TellLocale; import me.alexdevs.solstice.api.text.Components; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; + import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/me/alexdevs/solstice/modules/tell/commands/ReplyCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/tell/commands/ReplyCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/tell/commands/ReplyCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/tell/commands/ReplyCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/tell/commands/TellCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/tell/commands/TellCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/tell/commands/TellCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/tell/commands/TellCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/tell/data/TellLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/tell/data/TellLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/tell/data/TellLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/tell/data/TellLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/timeBar/TimeBar.java b/common/src/main/java/me/alexdevs/solstice/modules/timeBar/TimeBar.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/timeBar/TimeBar.java rename to common/src/main/java/me/alexdevs/solstice/modules/timeBar/TimeBar.java diff --git a/src/main/java/me/alexdevs/solstice/modules/timeBar/TimeBarModule.java b/common/src/main/java/me/alexdevs/solstice/modules/timeBar/TimeBarModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/timeBar/TimeBarModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/timeBar/TimeBarModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/timeBar/commands/TimeBarCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/timeBar/commands/TimeBarCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/timeBar/commands/TimeBarCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/timeBar/commands/TimeBarCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/trash/TrashModule.java b/common/src/main/java/me/alexdevs/solstice/modules/trash/TrashModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/trash/TrashModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/trash/TrashModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/trash/commands/TrashCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/trash/commands/TrashCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/trash/commands/TrashCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/trash/commands/TrashCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/trash/data/TrashLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/trash/data/TrashLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/trash/data/TrashLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/trash/data/TrashLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/UtilitiesModule.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/UtilitiesModule.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/UtilitiesModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/UtilitiesModule.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/commands/AnvilCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/commands/AnvilCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/commands/AnvilCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/commands/AnvilCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/commands/CartographyCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/commands/CartographyCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/commands/CartographyCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/commands/CartographyCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/commands/GrindstoneCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/commands/GrindstoneCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/commands/GrindstoneCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/commands/GrindstoneCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/commands/LoomCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/commands/LoomCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/commands/LoomCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/commands/LoomCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/commands/SmithingCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/commands/SmithingCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/commands/SmithingCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/commands/SmithingCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/commands/StonecutterCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/commands/StonecutterCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/commands/StonecutterCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/commands/StonecutterCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/commands/WorkbenchCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/commands/WorkbenchCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/commands/WorkbenchCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/commands/WorkbenchCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualAnvilScreenHandler.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualAnvilScreenHandler.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualAnvilScreenHandler.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualAnvilScreenHandler.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualCartographyTableScreenHandler.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualCartographyTableScreenHandler.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualCartographyTableScreenHandler.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualCartographyTableScreenHandler.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualCraftingScreenHandler.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualCraftingScreenHandler.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualCraftingScreenHandler.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualCraftingScreenHandler.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualGrindstoneScreenHandler.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualGrindstoneScreenHandler.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualGrindstoneScreenHandler.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualGrindstoneScreenHandler.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualLoomScreenHandler.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualLoomScreenHandler.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualLoomScreenHandler.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualLoomScreenHandler.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualSmithingScreenHandler.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualSmithingScreenHandler.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualSmithingScreenHandler.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualSmithingScreenHandler.java diff --git a/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualStonecutterScreenHandler.java b/common/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualStonecutterScreenHandler.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualStonecutterScreenHandler.java rename to common/src/main/java/me/alexdevs/solstice/modules/utilities/virtualScreenHandlers/VirtualStonecutterScreenHandler.java diff --git a/src/main/java/me/alexdevs/solstice/modules/warp/WarpModule.java b/common/src/main/java/me/alexdevs/solstice/modules/warp/WarpModule.java similarity index 95% rename from src/main/java/me/alexdevs/solstice/modules/warp/WarpModule.java rename to common/src/main/java/me/alexdevs/solstice/modules/warp/WarpModule.java index 87b16841..6ee9fed6 100644 --- a/src/main/java/me/alexdevs/solstice/modules/warp/WarpModule.java +++ b/common/src/main/java/me/alexdevs/solstice/modules/warp/WarpModule.java @@ -2,13 +2,13 @@ import me.alexdevs.solstice.Solstice; import me.alexdevs.solstice.api.module.ModuleBase; +import me.alexdevs.solstice.api.permissions.Permissions; import me.alexdevs.solstice.modules.warp.commands.DeleteWarpCommand; import me.alexdevs.solstice.modules.warp.commands.SetWarpCommand; import me.alexdevs.solstice.modules.warp.commands.WarpCommand; import me.alexdevs.solstice.modules.warp.commands.WarpsCommand; import me.alexdevs.solstice.modules.warp.data.WarpLocale; import me.alexdevs.solstice.modules.warp.data.WarpServerData; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.server.level.ServerPlayer; public class WarpModule extends ModuleBase.Toggleable { diff --git a/src/main/java/me/alexdevs/solstice/modules/warp/commands/DeleteWarpCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/warp/commands/DeleteWarpCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/warp/commands/DeleteWarpCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/warp/commands/DeleteWarpCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/warp/commands/SetWarpCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/warp/commands/SetWarpCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/warp/commands/SetWarpCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/warp/commands/SetWarpCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/warp/commands/WarpCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/warp/commands/WarpCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/warp/commands/WarpCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/warp/commands/WarpCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/warp/commands/WarpsCommand.java b/common/src/main/java/me/alexdevs/solstice/modules/warp/commands/WarpsCommand.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/warp/commands/WarpsCommand.java rename to common/src/main/java/me/alexdevs/solstice/modules/warp/commands/WarpsCommand.java diff --git a/src/main/java/me/alexdevs/solstice/modules/warp/data/WarpLocale.java b/common/src/main/java/me/alexdevs/solstice/modules/warp/data/WarpLocale.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/warp/data/WarpLocale.java rename to common/src/main/java/me/alexdevs/solstice/modules/warp/data/WarpLocale.java diff --git a/src/main/java/me/alexdevs/solstice/modules/warp/data/WarpServerData.java b/common/src/main/java/me/alexdevs/solstice/modules/warp/data/WarpServerData.java similarity index 100% rename from src/main/java/me/alexdevs/solstice/modules/warp/data/WarpServerData.java rename to common/src/main/java/me/alexdevs/solstice/modules/warp/data/WarpServerData.java diff --git a/common/src/main/resources/META-INF/accesstransformer.cfg b/common/src/main/resources/META-INF/accesstransformer.cfg new file mode 100644 index 00000000..d21ee3ba --- /dev/null +++ b/common/src/main/resources/META-INF/accesstransformer.cfg @@ -0,0 +1,2 @@ +public net.minecraft.server.MinecraftServer playerDataStorage +public net.minecraft.server.level.ServerChunkCache getVisibleChunkIfPresent(J)Lnet/minecraft/server/level/ChunkHolder; diff --git a/common/src/main/resources/META-INF/services/me.alexdevs.solstice.api.module.ModuleEntrypoint b/common/src/main/resources/META-INF/services/me.alexdevs.solstice.api.module.ModuleEntrypoint new file mode 100644 index 00000000..c1f441a3 --- /dev/null +++ b/common/src/main/resources/META-INF/services/me.alexdevs.solstice.api.module.ModuleEntrypoint @@ -0,0 +1 @@ +me.alexdevs.solstice.modules.ModuleProvider \ No newline at end of file diff --git a/src/main/resources/assets/solstice/info/formatting.txt b/common/src/main/resources/assets/solstice/info/formatting.txt similarity index 100% rename from src/main/resources/assets/solstice/info/formatting.txt rename to common/src/main/resources/assets/solstice/info/formatting.txt diff --git a/src/main/resources/assets/solstice/info/motd.txt b/common/src/main/resources/assets/solstice/info/motd.txt similarity index 100% rename from src/main/resources/assets/solstice/info/motd.txt rename to common/src/main/resources/assets/solstice/info/motd.txt diff --git a/src/main/resources/assets/solstice/info/rules.txt b/common/src/main/resources/assets/solstice/info/rules.txt similarity index 100% rename from src/main/resources/assets/solstice/info/rules.txt rename to common/src/main/resources/assets/solstice/info/rules.txt diff --git a/src/main/resources/solstice.accesswidener b/common/src/main/resources/solstice.accesswidener similarity index 79% rename from src/main/resources/solstice.accesswidener rename to common/src/main/resources/solstice.accesswidener index 8c2bc47d..ef43e334 100644 --- a/src/main/resources/solstice.accesswidener +++ b/common/src/main/resources/solstice.accesswidener @@ -3,4 +3,4 @@ accessWidener v2 named accessible method net/minecraft/server/level/ServerChunkCache getVisibleChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder; # Inventory see -accessible field net/minecraft/server/MinecraftServer playerDataStorage Lnet/minecraft/world/level/storage/PlayerDataStorage; \ No newline at end of file +accessible field net/minecraft/server/MinecraftServer playerDataStorage Lnet/minecraft/world/level/storage/PlayerDataStorage; diff --git a/src/main/resources/solstice.mixins.json b/common/src/main/resources/solstice.mixins.json similarity index 91% rename from src/main/resources/solstice.mixins.json rename to common/src/main/resources/solstice.mixins.json index 11fef50a..2c4d1282 100644 --- a/src/main/resources/solstice.mixins.json +++ b/common/src/main/resources/solstice.mixins.json @@ -2,15 +2,13 @@ "required": true, "minVersion": "0.8", "package": "me.alexdevs.solstice.mixin", - "compatibilityLevel": "JAVA_21", + "refmap": "${mod_id}.mixins.json", "plugin": "me.alexdevs.solstice.mixin.SolsticeMixinConfigPlugin", - "client": [], - "server": [], - "injectors": { - "defaultRequire": 1 - }, + "compatibilityLevel": "JAVA_21", "mixins": [ "events.CommandEventsMixin", + "events.LivingEntityMixin", + "events.PlayerListMixin", "events.WorldSaveEventMixin", "modules.admin.ConnectionBypassMixin", "modules.afk.FixPlayerSleepPercentageMixin", @@ -30,5 +28,8 @@ "modules.styling.PlayerDisconnectMixin", "modules.tablist.CustomPlayerListNameMixin", "modules.tablist.UpdatePlayerListMixin" - ] + ], + "injectors": { + "defaultRequire": 1 + } } \ No newline at end of file diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts new file mode 100644 index 00000000..ebe3bb54 --- /dev/null +++ b/fabric/build.gradle.kts @@ -0,0 +1,78 @@ +plugins { + id("multiloader-loader") + id("fabric-loom") +} + +dependencies { + minecraft("com.mojang:minecraft:${"minecraft_version"()}") + + @Suppress("UnstableApiUsage") mappings(loom.layered { + officialMojangMappings() + parchment("org.parchmentmc.data:parchment-${"parchment_minecraft"()}:${"parchment_version"()}@zip") + }) + + modImplementation("net.fabricmc:fabric-loader:${"fabric_loader_version"()}") + modImplementation("net.fabricmc.fabric-api:fabric-api:${"fabric_version"()}") + + include(implementation("org.spongepowered:configurate-core:${"configurate_version"()}")!!) + include(implementation("org.spongepowered:configurate-hocon:${"configurate_version"()}")!!) + include(implementation("org.spongepowered:configurate-gson:${"configurate_version"()}")!!) + include(implementation("com.typesafe:config:1.4.3")!!) + include(implementation("io.leangen.geantyref:geantyref:1.3.16")!!) + + include(modImplementation("eu.pb4:placeholder-api:${"placeholderapi_fabric_version"()}")!!) + include(modImplementation("eu.pb4:sgui-fabric:${"sgui_version"()}")!!) + + modCompileOnly("dev.emi:trinkets:${"trinkets_version"()}") + modLocalRuntime("dev.emi:trinkets:${"trinkets_version"()}") + + modCompileOnly("net.luckperms:api:5.4") + modLocalRuntime("net.luckperms:api:5.4") + + include("net.kyori:option:1.1.0") +} + +loom { + val aw = project(":common").file("src/main/resources/${"mod_id"()}.accesswidener") + + if (aw.exists()) { + accessWidenerPath.set(aw) + } + + @Suppress("UnstableApiUsage") mixin { + defaultRefmapName.set("${"mod_id"()}.refmap.json") + useLegacyMixinAp = false + } + + runs { + maybeCreate("client").apply { + client() + configName = "Fabric Client" + ideConfigGenerated(true) + runDir("runs/client") + property("mixin.debug.export", "true") + } + + maybeCreate("server").apply { + server() + configName = "Fabric Server" + ideConfigGenerated(true) + runDir("runs/server") + property("mixin.debug.export", "true") + } + } +} + +tasks.compileJava { + source(project(":common").sourceSets["main"].java) +} + +tasks.processResources { + from(project(":common").sourceSets["main"].resources) +} + +tasks.remapJar { + destinationDirectory.set(rootProject.layout.buildDirectory.dir("artifacts")) +} + +operator fun String.invoke(): String = rootProject.ext[this] as? String ?: error("No property \"$this\"") diff --git a/fabric/src/main/java/me/alexdevs/solstice/fabric/FabricPlatform.java b/fabric/src/main/java/me/alexdevs/solstice/fabric/FabricPlatform.java new file mode 100644 index 00000000..a44971d9 --- /dev/null +++ b/fabric/src/main/java/me/alexdevs/solstice/fabric/FabricPlatform.java @@ -0,0 +1,85 @@ +package me.alexdevs.solstice.fabric; + +import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.proxy.*; +import me.alexdevs.solstice.api.platform.ModInfo; +import me.alexdevs.solstice.api.platform.PlatformHelper; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.fabricmc.fabric.api.entity.event.v1.EntitySleepEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.event.player.*; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.loader.api.FabricLoader; + +import java.nio.file.Path; + +public class FabricPlatform extends PlatformHelper { + public void init() { + CommandRegistrationCallback.EVENT.register(ProxyCommandRegistrationCallback.EVENT.invoker()::onRegister); + ServerLifecycleEvents.SERVER_STARTING.register(ProxyServerLifecycleEvents.SERVER_STARTING.invoker()::onServerStarting); + ServerLifecycleEvents.SERVER_STARTED.register(ProxyServerLifecycleEvents.SERVER_STARTED.invoker()::onServerStarted); + ServerLifecycleEvents.SERVER_STOPPING.register(ProxyServerLifecycleEvents.SERVER_STOPPING.invoker()::onServerStopping); + ServerLifecycleEvents.SERVER_STOPPED.register(ProxyServerLifecycleEvents.SERVER_STOPPED.invoker()::onServerStopped); + ServerTickEvents.START_SERVER_TICK.register(ProxyServerTickEvents.START_SERVER_TICK.invoker()::onStartTick); + ServerTickEvents.END_SERVER_TICK.register(ProxyServerTickEvents.END_SERVER_TICK.invoker()::onEndTick); + UseItemCallback.EVENT.register(ProxyUseItemCallback.EVENT.invoker()::interact); + UseBlockCallback.EVENT.register(ProxyUseBlockCallback.EVENT.invoker()::interact); + UseEntityCallback.EVENT.register(ProxyUseEntityCallback.EVENT.invoker()::interact); + PlayerBlockBreakEvents.BEFORE.register(ProxyPlayerBlockBreakEvents.BEFORE.invoker()::beforeBlockBreak); + AttackBlockCallback.EVENT.register(ProxyAttackBlockCallback.EVENT.invoker()::interact); + AttackEntityCallback.EVENT.register(ProxyAttackEntityCallback.EVENT.invoker()::interact); + + ServerPlayConnectionEvents.JOIN.register((handler, _sender, server) -> ProxyServerPlayConnectionEvents.JOIN.invoker() + .onJoin(handler.getPlayer(), server)); + + ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> ProxyServerPlayConnectionEvents.DISCONNECT.invoker() + .onDisconnect(handler.getPlayer(), server)); + + EntitySleepEvents.ALLOW_SLEEP_TIME.register(ProxyEntitySleepEvents.ALLOW_SLEEP_TIME.invoker()::allowSleepTime); + EntitySleepEvents.ALLOW_RESETTING_TIME.register(ProxyEntitySleepEvents.ALLOW_RESETTING_TIME.invoker()::allowResettingTime); + } + + @Override + public Path getGameDir() { + return FabricLoader.getInstance().getGameDir(); + } + + @Override + public Path getConfigDir() { + return FabricLoader.getInstance().getConfigDir(); + } + + @Override + public boolean isModLoaded(String id) { + return FabricLoader.getInstance().isModLoaded(id); + } + + @Override + public boolean isNativeForge() { + return false; + } + + @Override + public Object getModContainer() { + return FabricLoader.getInstance().getModContainer(Solstice.MOD_ID).orElseThrow(); + } + + @Override + public String getModVersion() { + return FabricLoader.getInstance() + .getModContainer(Solstice.MOD_ID) + .orElseThrow() + .getMetadata() + .getVersion() + .toString(); + } + + @Override + public ModInfo getModInfo(String id) { + return FabricLoader.getInstance() + .getModContainer(id) + .map(it -> new ModInfo(it.getMetadata().getName(), it.getMetadata().getVersion().toString())) + .orElse(null); + } +} diff --git a/fabric/src/main/java/me/alexdevs/solstice/fabric/FabricTrinketsApi.java b/fabric/src/main/java/me/alexdevs/solstice/fabric/FabricTrinketsApi.java new file mode 100644 index 00000000..5e30e829 --- /dev/null +++ b/fabric/src/main/java/me/alexdevs/solstice/fabric/FabricTrinketsApi.java @@ -0,0 +1,26 @@ +package me.alexdevs.solstice.fabric; + +import dev.emi.trinkets.api.TrinketsApi; +import me.alexdevs.solstice.integrations.TrinketsApiProxy; +import net.minecraft.world.Container; +import net.minecraft.world.entity.LivingEntity; + +import java.util.Map; +import java.util.Optional; + +public class FabricTrinketsApi extends TrinketsApiProxy { + // Basically, this does getTrinketComponent(target).getInventory().mapValues((map) -> map.mapValues(inv -> inv.values())) + @SuppressWarnings("unchecked") + @Override + public Optional>> getTrinketComponentInventory(LivingEntity target) { + return TrinketsApi.getTrinketComponent(target) + .map(comp -> Map.ofEntries(comp.getInventory().entrySet().stream().map(entry -> Map.entry( + entry.getKey(), + Map.ofEntries(entry.getValue() + .entrySet() + .stream() + .map(it -> Map.entry(it.getKey(), (Container) it.getValue())) + .toArray(Map.Entry[]::new)) + )).toArray(Map.Entry[]::new))); + } +} diff --git a/fabric/src/main/java/me/alexdevs/solstice/fabric/SolsticeFabric.java b/fabric/src/main/java/me/alexdevs/solstice/fabric/SolsticeFabric.java new file mode 100644 index 00000000..a71b4165 --- /dev/null +++ b/fabric/src/main/java/me/alexdevs/solstice/fabric/SolsticeFabric.java @@ -0,0 +1,11 @@ +package me.alexdevs.solstice.fabric; + +import me.alexdevs.solstice.Solstice; +import net.fabricmc.api.ModInitializer; + +public class SolsticeFabric implements ModInitializer { + @Override + public void onInitialize() { + new Solstice().init(); + } +} diff --git a/fabric/src/main/resources/META-INF/services/me.alexdevs.solstice.api.platform.PlatformHelper b/fabric/src/main/resources/META-INF/services/me.alexdevs.solstice.api.platform.PlatformHelper new file mode 100644 index 00000000..7f1ed3d0 --- /dev/null +++ b/fabric/src/main/resources/META-INF/services/me.alexdevs.solstice.api.platform.PlatformHelper @@ -0,0 +1 @@ +me.alexdevs.solstice.fabric.FabricPlatform \ No newline at end of file diff --git a/fabric/src/main/resources/META-INF/services/me.alexdevs.solstice.integrations.TrinketsApiProxy b/fabric/src/main/resources/META-INF/services/me.alexdevs.solstice.integrations.TrinketsApiProxy new file mode 100644 index 00000000..13e7ce22 --- /dev/null +++ b/fabric/src/main/resources/META-INF/services/me.alexdevs.solstice.integrations.TrinketsApiProxy @@ -0,0 +1 @@ +me.alexdevs.solstice.fabric.FabricTrinketsApi \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json similarity index 68% rename from src/main/resources/fabric.mod.json rename to fabric/src/main/resources/fabric.mod.json index eb6dcbec..b73f3d46 100644 --- a/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -1,9 +1,9 @@ { "schemaVersion": 1, - "id": "solstice", - "version": "${version}", - "name": "Solstice Essentials", - "description": "Server commands, custom chat formats and more", + "id": "${mod_id}", + "version": "${mod_version}", + "name": "${mod_name}", + "description": "${mod_description}", "authors": [ { "name": "AlexDevs", @@ -19,14 +19,11 @@ "homepage": "https://solstice.alexdevs.me", "email": "solstice@alexdevs.me" }, - "license": "MIT", + "license": "${mod_license}", "environment": "*", "entrypoints": { "main": [ - "me.alexdevs.solstice.Solstice" - ], - "solstice": [ - "me.alexdevs.solstice.modules.ModuleProvider" + "me.alexdevs.solstice.fabric.SolsticeFabric" ] }, "mixins": [ @@ -41,5 +38,5 @@ "recommends": { "luckperms": "*" }, - "accessWidener": "solstice.accesswidener" -} \ No newline at end of file + "accessWidener": "${mod_id}.accesswidener" +} diff --git a/gradle.properties b/gradle.properties index 3cfae2ee..31765261 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,26 +1,48 @@ # Done to increase the memory available to gradle. -org.gradle.jvmargs=-Xmx1G + +org.gradle.jvmargs=-Xmx4G +org.gradle.daemon=true org.gradle.parallel=true +org.gradle.caching=true +#org.gradle.configuration-cache=true + +## Environment + +java_version=21 +neoform_version=1.21.1-20240808.144430 -# Fabric Properties -# check these on https://fabricmc.net/develop minecraft_version=1.21.1 -yarn_mappings=1.21.1+build.3 -loader_version=0.16.9 +minecraft_version_range=[1.21.1] + +parchment_minecraft=1.21.1 +parchment_version=2024.11.17 + +## NeoForge + +neo_version=21.1.169 +neo_version_range=[21.1.100,) +neo_loader_version_range=[4,) + +## Fabric -parchment_mappings=2024.11.17 +fabric_version=0.116.1+1.21.1 +fabric_loader_version=0.16.0 -# Mod Properties -mod_version=1.8.1 -maven_group=me.alexdevs -archives_base_name=solstice +## Mod Properties -# Dependencies -fabric_version=0.110.0+1.21.1 +mod_id=solstice +mod_name=Solstice Essentials +mod_license=MIT +mod_version=1.9.0 +mod_authors=AlexDevs +mod_credits= +mod_group_id=me.alexdevs +mod_description=Server commands, custom chat formats, and more! -configurate_version=4.1.2 -permissions_api_version=0.2-SNAPSHOT -placeholderapi_version=2.4.2+1.21 -sgui_version=1.6.1+1.21.1 +## Dependencies -trinkets_version=3.10.0 \ No newline at end of file +configurate_version=4.2.0 +placeholderapi_nf_version=2.4.2+1.21.1-nf +placeholderapi_fabric_version=2.4.2+1.21 +sgui_version=1.9.1+1.21.1 +trinkets_version=3.10.0 diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts new file mode 100644 index 00000000..e28c3429 --- /dev/null +++ b/neoforge/build.gradle.kts @@ -0,0 +1,98 @@ +plugins { + id("multiloader-loader") + id("net.neoforged.moddev") + id("com.gradleup.shadow") +} + +val localRuntime: Configuration by configurations.creating { + isCanBeResolved = true + isCanBeConsumed = false +} + +val shadowDep: Configuration by configurations.creating { + isCanBeResolved = true + isCanBeConsumed = true +} + +neoForge { + version = "neo_version"() + + val at = project(":common").file("src/main/resources/META-INF/accesstransformer.cfg") + + if (at.exists()) { + accessTransformers.from(at.absolutePath) + } + + parchment { + minecraftVersion = "parchment_minecraft"() + mappingsVersion = "parchment_version"() + } + + runs { + configureEach { + val capitalized = name.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() } + + systemProperty("neoforge.enabledGameTestNamespaces", "mod_id"()) + ideName = "NeoForge $capitalized (${project.path})" + } + + maybeCreate("client").apply { + client() + devLogin = true + } + + maybeCreate("data").apply { + data() + } + + maybeCreate("server").apply { + server() + programArgument("nogui") + } + } + + mods { + maybeCreate("mod_id"()).apply { + sourceSet(sourceSets.main.get()) + } + } +} + +dependencies { + jarJar(implementation("org.spongepowered:configurate-core:${"configurate_version"()}")!!) + jarJar(implementation("org.spongepowered:configurate-hocon:${"configurate_version"()}")!!) + jarJar(implementation("org.spongepowered:configurate-gson:${"configurate_version"()}")!!) + jarJar(implementation("com.typesafe:config:1.4.3")!!) + jarJar(implementation("io.leangen.geantyref:geantyref:1.3.16")!!) + jarJar(implementation("eu.pb4:placeholderapi:${"placeholderapi_nf_version"()}")!!) + jarJar(implementation("eu.pb4:sgui-neoforge:${"sgui_version"()}")!!) + + "additionalRuntimeClasspath"("org.spongepowered:configurate-core:${"configurate_version"()}") + "additionalRuntimeClasspath"("org.spongepowered:configurate-hocon:${"configurate_version"()}") + "additionalRuntimeClasspath"("org.spongepowered:configurate-gson:${"configurate_version"()}") + "additionalRuntimeClasspath"("com.typesafe:config:1.4.3") + "additionalRuntimeClasspath"("io.leangen.geantyref:geantyref:1.3.16") + + compileOnly("net.luckperms:api:5.4") + localRuntime("net.luckperms:api:5.4") + + jarJar("net.kyori:option:1.1.0") + shadowDep(project(":common")) +} + +tasks.jar { + archiveClassifier = "dev" +} + +tasks.shadowJar { + archiveClassifier = "" + from(tasks.jarJar) + configurations.set(listOf(shadowDep)) + destinationDirectory.set(rootProject.layout.buildDirectory.dir("artifacts")) +} + +tasks.build.get().finalizedBy(tasks.shadowJar) +sourceSets.main.get().resources { srcDir("src/generated/resources") } +configurations.runtimeClasspath.get().extendsFrom(localRuntime) + +operator fun String.invoke(): String = rootProject.ext[this] as? String ?: error("No property \"$this\"") diff --git a/neoforge/src/main/java/me/alexdevs/solstice/neoforge/EmptyTrinketsApi.java b/neoforge/src/main/java/me/alexdevs/solstice/neoforge/EmptyTrinketsApi.java new file mode 100644 index 00000000..4fc1ad56 --- /dev/null +++ b/neoforge/src/main/java/me/alexdevs/solstice/neoforge/EmptyTrinketsApi.java @@ -0,0 +1,15 @@ +package me.alexdevs.solstice.neoforge; + +import me.alexdevs.solstice.integrations.TrinketsApiProxy; +import net.minecraft.world.Container; +import net.minecraft.world.entity.LivingEntity; + +import java.util.Map; +import java.util.Optional; + +public class EmptyTrinketsApi extends TrinketsApiProxy { + @Override + public Optional>> getTrinketComponentInventory(LivingEntity target) { + throw new UnsupportedOperationException("Cannot use Trinkets on Forge!"); + } +} diff --git a/neoforge/src/main/java/me/alexdevs/solstice/neoforge/NeoForgePlatform.java b/neoforge/src/main/java/me/alexdevs/solstice/neoforge/NeoForgePlatform.java new file mode 100644 index 00000000..2ff17103 --- /dev/null +++ b/neoforge/src/main/java/me/alexdevs/solstice/neoforge/NeoForgePlatform.java @@ -0,0 +1,240 @@ +package me.alexdevs.solstice.neoforge; + +import me.alexdevs.solstice.Solstice; +import me.alexdevs.solstice.api.events.proxy.*; +import me.alexdevs.solstice.api.platform.ModInfo; +import me.alexdevs.solstice.api.platform.PlatformHelper; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.EntityHitResult; +import net.neoforged.fml.ModList; +import net.neoforged.fml.loading.FMLPaths; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.common.util.TriState; +import net.neoforged.neoforge.event.RegisterCommandsEvent; +import net.neoforged.neoforge.event.entity.player.AttackEntityEvent; +import net.neoforged.neoforge.event.entity.player.CanContinueSleepingEvent; +import net.neoforged.neoforge.event.entity.player.PlayerEvent; +import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent; +import net.neoforged.neoforge.event.level.BlockEvent; +import net.neoforged.neoforge.event.server.ServerStartedEvent; +import net.neoforged.neoforge.event.server.ServerStartingEvent; +import net.neoforged.neoforge.event.server.ServerStoppedEvent; +import net.neoforged.neoforge.event.server.ServerStoppingEvent; +import net.neoforged.neoforge.event.tick.ServerTickEvent; + +import java.nio.file.Path; + +public class NeoForgePlatform extends PlatformHelper { + public void init() { + NeoForge.EVENT_BUS.addListener( + RegisterCommandsEvent.class, + (ev) -> ProxyCommandRegistrationCallback.EVENT.invoker() + .onRegister(ev.getDispatcher(), ev.getBuildContext(), ev.getCommandSelection()) + ); + + NeoForge.EVENT_BUS.addListener( + ServerStartingEvent.class, + (ev) -> ProxyServerLifecycleEvents.SERVER_STARTING.invoker().onServerStarting(ev.getServer()) + ); + + NeoForge.EVENT_BUS.addListener( + ServerStartedEvent.class, + (ev) -> ProxyServerLifecycleEvents.SERVER_STARTED.invoker().onServerStarted(ev.getServer()) + ); + + NeoForge.EVENT_BUS.addListener( + ServerStoppingEvent.class, + (ev) -> ProxyServerLifecycleEvents.SERVER_STOPPING.invoker().onServerStopping(ev.getServer()) + ); + + NeoForge.EVENT_BUS.addListener( + ServerStoppedEvent.class, + (ev) -> ProxyServerLifecycleEvents.SERVER_STOPPED.invoker().onServerStopped(ev.getServer()) + ); + + NeoForge.EVENT_BUS.addListener( + ServerTickEvent.Pre.class, + (ev) -> ProxyServerTickEvents.START_SERVER_TICK.invoker().onStartTick(ev.getServer()) + ); + + NeoForge.EVENT_BUS.addListener( + ServerTickEvent.Post.class, + (ev) -> ProxyServerTickEvents.END_SERVER_TICK.invoker().onEndTick(ev.getServer()) + ); + + NeoForge.EVENT_BUS.addListener( + PlayerInteractEvent.RightClickItem.class, (ev) -> { + var result = ProxyUseItemCallback.EVENT.invoker() + .interact(ev.getEntity(), ev.getLevel(), ev.getHand()) + .getResult(); + + if (result != InteractionResult.PASS) { + ev.setCanceled(true); + ev.setCancellationResult(result); + } + } + ); + + NeoForge.EVENT_BUS.addListener( + PlayerInteractEvent.RightClickBlock.class, (ev) -> { + var result = ProxyUseBlockCallback.EVENT.invoker() + .interact(ev.getEntity(), ev.getLevel(), ev.getHand(), ev.getHitVec()); + + if (result != InteractionResult.PASS) { + ev.setCanceled(true); + ev.setCancellationResult(result); + } + } + ); + + NeoForge.EVENT_BUS.addListener( + PlayerInteractEvent.EntityInteract.class, (ev) -> { + var result = ProxyUseEntityCallback.EVENT.invoker() + .interact(ev.getEntity(), ev.getLevel(), ev.getHand(), ev.getTarget(), null); + + if (result != InteractionResult.PASS) { + ev.setCanceled(true); + ev.setCancellationResult(result); + } + } + ); + + NeoForge.EVENT_BUS.addListener( + PlayerInteractEvent.EntityInteractSpecific.class, (ev) -> { + var result = ProxyUseEntityCallback.EVENT.invoker().interact( + ev.getEntity(), + ev.getLevel(), + ev.getHand(), + ev.getTarget(), + new EntityHitResult(ev.getTarget(), ev.getLocalPos().add(ev.getTarget().position())) + ); + + if (result != InteractionResult.PASS) { + ev.setCanceled(true); + ev.setCancellationResult(result); + } + } + ); + + NeoForge.EVENT_BUS.addListener( + BlockEvent.BreakEvent.class, (ev) -> { + var player = ev.getPlayer(); + var level = player.level(); + + var result = ProxyPlayerBlockBreakEvents.BEFORE.invoker().beforeBlockBreak( + level, + player, + ev.getPos(), + level.getBlockState(ev.getPos()), + level.getBlockEntity(ev.getPos()) + ); + + if (!result) { + ev.setCanceled(true); + } + } + ); + + NeoForge.EVENT_BUS.addListener( + PlayerInteractEvent.LeftClickBlock.class, (ev) -> { + if (ev.getAction() == PlayerInteractEvent.LeftClickBlock.Action.START) { + var result = ProxyAttackBlockCallback.EVENT.invoker() + .interact(ev.getEntity(), ev.getLevel(), ev.getHand(), ev.getPos(), ev.getFace()); + + if (result != InteractionResult.PASS) { + ev.setUseBlock(result == InteractionResult.SUCCESS ? TriState.TRUE : TriState.FALSE); + ev.setUseItem(result == InteractionResult.SUCCESS ? TriState.TRUE : TriState.FALSE); + } + } + } + ); + + NeoForge.EVENT_BUS.addListener( + AttackEntityEvent.class, (ev) -> { + var result = ProxyAttackEntityCallback.EVENT.invoker() + .interact( + ev.getEntity(), + ev.getEntity().level(), + InteractionHand.MAIN_HAND, + ev.getTarget(), + null + ); + + if (result != InteractionResult.PASS) { + ev.setCanceled(true); + } + } + ); + + NeoForge.EVENT_BUS.addListener( + PlayerEvent.PlayerLoggedInEvent.class, (ev) -> { + if (ev.getEntity() instanceof ServerPlayer player) { + ProxyServerPlayConnectionEvents.JOIN.invoker().onJoin(player, player.server); + } + } + ); + + NeoForge.EVENT_BUS.addListener( + PlayerEvent.PlayerLoggedOutEvent.class, (ev) -> { + if (ev.getEntity() instanceof ServerPlayer player) { + ProxyServerPlayConnectionEvents.DISCONNECT.invoker().onDisconnect(player, player.server); + } + } + ); + + NeoForge.EVENT_BUS.addListener( + CanContinueSleepingEvent.class, (ev) -> { + ev.getEntity().getSleepingPos().ifPresent(sleepingPos -> { + if (ev.getEntity() instanceof Player player) { + InteractionResult result = ProxyEntitySleepEvents.ALLOW_SLEEP_TIME.invoker() + .allowSleepTime(player, sleepingPos, !player.level().isDay()); + if (result != InteractionResult.PASS) { + ev.setContinueSleeping(result.consumesAction()); + } + } + }); + } + ); + } + + @Override + public Path getGameDir() { + return FMLPaths.GAMEDIR.get(); + } + + @Override + public Path getConfigDir() { + return FMLPaths.CONFIGDIR.get(); + } + + @Override + public boolean isModLoaded(String id) { + return ModList.get().isLoaded(id); + } + + @Override + public boolean isNativeForge() { + return true; + } + + @Override + public Object getModContainer() { + return ModList.get().getModContainerById(Solstice.MOD_ID).orElseThrow(); + } + + @Override + public String getModVersion() { + return ModList.get().getModContainerById(Solstice.MOD_ID).orElseThrow().getModInfo().getVersion().toString(); + } + + @Override + public ModInfo getModInfo(String id) { + return ModList.get() + .getModContainerById(id) + .map(it -> new ModInfo(it.getModInfo().getDisplayName(), it.getModInfo().getVersion().toString())) + .orElse(null); + } +} diff --git a/neoforge/src/main/java/me/alexdevs/solstice/neoforge/SolsticeNeoForge.java b/neoforge/src/main/java/me/alexdevs/solstice/neoforge/SolsticeNeoForge.java new file mode 100644 index 00000000..ac556343 --- /dev/null +++ b/neoforge/src/main/java/me/alexdevs/solstice/neoforge/SolsticeNeoForge.java @@ -0,0 +1,13 @@ +package me.alexdevs.solstice.neoforge; + +import me.alexdevs.solstice.Solstice; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.common.Mod; + +@Mod(Solstice.MOD_ID) +public class SolsticeNeoForge { + public SolsticeNeoForge(ModContainer mod, IEventBus bus) { + new Solstice().init(); + } +} diff --git a/neoforge/src/main/java/me/alexdevs/solstice/neoforge/mixin/PlayerMixin.java b/neoforge/src/main/java/me/alexdevs/solstice/neoforge/mixin/PlayerMixin.java new file mode 100644 index 00000000..c16c049b --- /dev/null +++ b/neoforge/src/main/java/me/alexdevs/solstice/neoforge/mixin/PlayerMixin.java @@ -0,0 +1,18 @@ +package me.alexdevs.solstice.neoforge.mixin; + +import me.alexdevs.solstice.api.events.proxy.ProxyEntitySleepEvents; +import net.minecraft.world.entity.player.Player; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(Player.class) +public class PlayerMixin { + @Inject(method = "isSleepingLongEnough", at = @At("RETURN"), cancellable = true) + private void onIsSleepingLongEnough(CallbackInfoReturnable info) { + if (info.getReturnValueZ()) { + info.setReturnValue(ProxyEntitySleepEvents.ALLOW_RESETTING_TIME.invoker().allowResettingTime((Player) (Object) this)); + } + } +} diff --git a/neoforge/src/main/java/me/alexdevs/solstice/neoforge/mixin/ServerPlayerMixin.java b/neoforge/src/main/java/me/alexdevs/solstice/neoforge/mixin/ServerPlayerMixin.java new file mode 100644 index 00000000..90ad9a8f --- /dev/null +++ b/neoforge/src/main/java/me/alexdevs/solstice/neoforge/mixin/ServerPlayerMixin.java @@ -0,0 +1,31 @@ +package me.alexdevs.solstice.neoforge.mixin; + +import me.alexdevs.solstice.api.events.proxy.ProxyEntitySleepEvents; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ServerPlayer.class) +public class ServerPlayerMixin { + @Redirect( + method = "lambda$startSleepInBed$13", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;isDay()Z") + ) + private boolean redirectDaySleepCheck(Level world, BlockPos pos) { + boolean day = world.isDay(); + + InteractionResult result = ProxyEntitySleepEvents.ALLOW_SLEEP_TIME.invoker() + .allowSleepTime((Player) (Object) this, pos, !day); + + if (result != InteractionResult.PASS) { + return !result.consumesAction(); // true from the event = night-like conditions, so we have to invert + } + + return day; + } +} diff --git a/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/neoforge/src/main/resources/META-INF/neoforge.mods.toml new file mode 100644 index 00000000..1d15a251 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -0,0 +1,31 @@ +modLoader="javafml" +loaderVersion="${neo_loader_version_range}" +license="${mod_license}" + +[[mods]] +modId="${mod_id}" +version="${mod_version}" +displayName="${mod_name}" +credits="${mod_credits}" +authors="${mod_authors}" +description='''${mod_description}''' + +[[mixins]] +config="${mod_id}.mixins.json" + +[[accessTransformers]] +file="META-INF/accesstransformer.cfg" + +[[dependencies.${mod_id}]] +modId="neoforge" +type="required" +versionRange="${neo_version_range}" +ordering="NONE" +side="BOTH" + +[[dependencies.${mod_id}]] +modId="minecraft" +type="required" +versionRange="${minecraft_version_range}" +ordering="NONE" +side="BOTH" diff --git a/neoforge/src/main/resources/META-INF/services/me.alexdevs.solstice.api.platform.PlatformHelper b/neoforge/src/main/resources/META-INF/services/me.alexdevs.solstice.api.platform.PlatformHelper new file mode 100644 index 00000000..28ac0ae3 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/services/me.alexdevs.solstice.api.platform.PlatformHelper @@ -0,0 +1 @@ +me.alexdevs.solstice.neoforge.NeoForgePlatform \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/services/me.alexdevs.solstice.integrations.TrinketsApiProxy b/neoforge/src/main/resources/META-INF/services/me.alexdevs.solstice.integrations.TrinketsApiProxy new file mode 100644 index 00000000..b03769d1 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/services/me.alexdevs.solstice.integrations.TrinketsApiProxy @@ -0,0 +1 @@ +me.alexdevs.solstice.neoforge.EmptyTrinketsApi \ No newline at end of file diff --git a/neoforge/src/main/resources/solstice-neoforge.mixins.json b/neoforge/src/main/resources/solstice-neoforge.mixins.json new file mode 100644 index 00000000..236e6d64 --- /dev/null +++ b/neoforge/src/main/resources/solstice-neoforge.mixins.json @@ -0,0 +1,15 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "me.alexdevs.solstice.neoforge.mixin", + "compatibilityLevel": "JAVA_21", + "client": [], + "server": [], + "injectors": { + "defaultRequire": 1 + }, + "mixins": [ + "ServerPlayerMixin", + "PlayerMixin" + ] +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 75c4d726..00000000 --- a/settings.gradle +++ /dev/null @@ -1,10 +0,0 @@ -pluginManagement { - repositories { - maven { - name = 'Fabric' - url = 'https://maven.fabricmc.net/' - } - mavenCentral() - gradlePluginPortal() - } -} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 00000000..1d3338c7 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,17 @@ +pluginManagement { + repositories { + maven("https://maven.fabricmc.net/") + maven("https://maven.neoforged.net/releases") + maven("https://repo.spongepowered.org/repository/maven-public") + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "0.9.0" +} + +include("common") +include("fabric") +include("neoforge") diff --git a/src/main/java/me/alexdevs/solstice/Paths.java b/src/main/java/me/alexdevs/solstice/Paths.java deleted file mode 100644 index e766f79f..00000000 --- a/src/main/java/me/alexdevs/solstice/Paths.java +++ /dev/null @@ -1,9 +0,0 @@ -package me.alexdevs.solstice; - -import net.fabricmc.loader.api.FabricLoader; - -import java.nio.file.Path; - -public class Paths { - public static final Path configDirectory = FabricLoader.getInstance().getConfigDir().resolve(Solstice.MOD_ID); -} diff --git a/src/main/java/me/alexdevs/solstice/api/events/SolsticeEvents.java b/src/main/java/me/alexdevs/solstice/api/events/SolsticeEvents.java deleted file mode 100644 index d499963a..00000000 --- a/src/main/java/me/alexdevs/solstice/api/events/SolsticeEvents.java +++ /dev/null @@ -1,73 +0,0 @@ -package me.alexdevs.solstice.api.events; - -import me.alexdevs.solstice.Solstice; -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerPlayer; - -public final class SolsticeEvents { - public static final Event READY = EventFactory.createArrayBacked(Ready.class, callbacks -> - (instance, server) -> { - for (Ready callback : callbacks) { - callback.onReady(instance, server); - } - }); - - public static final Event RELOAD = EventFactory.createArrayBacked(Reload.class, callbacks -> - (instance) -> { - for (Reload callback : callbacks) { - callback.onReload(instance); - } - }); - - public static final Event WELCOME = EventFactory.createArrayBacked(Welcome.class, callbacks -> - (player, server) -> { - for (Welcome callback : callbacks) { - callback.onWelcome(player, server); - } - }); - - public static final Event USERNAME_CHANGE = EventFactory.createArrayBacked(UsernameChange.class, callbacks -> - (player, previousUsername) -> { - for (UsernameChange callback : callbacks) { - callback.onUsernameChange(player, previousUsername); - } - }); - - /** - * @deprecated Superseded by {@link me.alexdevs.solstice.api.events.CommandEvents} - */ - @Deprecated - public static final Event PLAYER_COMMAND = EventFactory.createArrayBacked(PlayerCommand.class, callbacks -> - (player, command) -> { - for (PlayerCommand callback : callbacks) { - callback.onPlayerCommand(player, command); - } - }); - - @FunctionalInterface - public interface Ready { - void onReady(Solstice instance, MinecraftServer server); - } - - @FunctionalInterface - public interface Reload { - void onReload(Solstice instance); - } - - @FunctionalInterface - public interface Welcome { - void onWelcome(ServerPlayer player, MinecraftServer server); - } - - @FunctionalInterface - public interface UsernameChange { - void onUsernameChange(ServerPlayer player, String previousUsername); - } - - @FunctionalInterface - public interface PlayerCommand { - void onPlayerCommand(ServerPlayer player, String command); - } -} diff --git a/src/main/java/me/alexdevs/solstice/core/coreModule/commands/SolsticeCommand.java b/src/main/java/me/alexdevs/solstice/core/coreModule/commands/SolsticeCommand.java deleted file mode 100644 index e351465e..00000000 --- a/src/main/java/me/alexdevs/solstice/core/coreModule/commands/SolsticeCommand.java +++ /dev/null @@ -1,138 +0,0 @@ -package me.alexdevs.solstice.core.coreModule.commands; - -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import me.alexdevs.solstice.Solstice; -import me.alexdevs.solstice.api.events.SolsticeEvents; -import me.alexdevs.solstice.api.module.Debug; -import me.alexdevs.solstice.api.module.ModCommand; -import me.alexdevs.solstice.core.coreModule.CoreModule; -import me.alexdevs.solstice.api.text.Format; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.network.chat.ClickEvent; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.HoverEvent; -import net.minecraft.network.chat.Style; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Map; - -import static net.minecraft.commands.Commands.literal; - -public class SolsticeCommand extends ModCommand { - public SolsticeCommand(CoreModule module) { - super(module); - } - - @Override - public List getNames() { - return List.of("solstice", "sol"); - } - - @Override - public LiteralArgumentBuilder command(String name) { - return literal(name) - .requires(require(true)) - .executes(context -> { - var modContainer = FabricLoader.getInstance().getModContainer(Solstice.MOD_ID).orElse(null); - if (modContainer == null) { - context.getSource().sendSuccess(() -> Component.nullToEmpty("Could not find self in mod list???"), false); - return 1; - } - - var metadata = modContainer.getMetadata(); - var placeholders = Map.of( - "name", Component.nullToEmpty(metadata.getName()), - "version", Component.nullToEmpty(metadata.getVersion().getFriendlyString()) - ); - - var text = Format.parse( - "${name} v${version}", - placeholders); - context.getSource().sendSuccess(() -> text, false); - - return 1; - }) - .then(literal("reload") - .requires(require("reload", 3)) - .executes(context -> { - try { - Solstice.configManager.loadData(true); - Solstice.localeManager.reload(); - } catch (Exception e) { - Solstice.LOGGER.error("Failed to reload Solstice", e); - context.getSource().sendSuccess(() -> Component.nullToEmpty("Failed to load Solstice config. Check console for more info."), true); - return 1; - } - - SolsticeEvents.RELOAD.invoker().onReload(Solstice.getInstance()); - - context.getSource().sendSuccess(() -> Component.nullToEmpty("Reloaded Solstice config"), true); - - return 1; - })) - .then(literal("debug") - .requires(require("debug", 4)) - .then(literal("gen-command-list") - .executes(context -> { - var builder = new StringBuilder(); - - var list = new ArrayList<>(Debug.commandDebugList); - - list.sort(Comparator.comparing(Debug.CommandDebug::module)); - - builder.append(String.format("| %s | %s | %s | %s |\n", "Module", "Command", "Aliases", "Permission")); - builder.append("|---|---|---|---|\n"); - for (var command : list) { - builder.append(String.format("| %s | %s | %s | %s |\n", command.module(), command.command(), String.join(" ", command.commands()), command.permission())); - } - - var output = builder.toString(); - - var file = FabricLoader.getInstance().getGameDir().resolve("solstice-commands.md").toFile(); - try (var fw = new FileWriter(file)) { - fw.write(output); - } catch (IOException e) { - throw new SimpleCommandExceptionType(Component.nullToEmpty(e.getMessage())).create(); - } - - context.getSource().sendSuccess(() -> Component.nullToEmpty("Generated 'solstice-commands.md'"), true); - - return 1; - })) - .then(literal("tags") - .executes(context -> { - var player = context.getSource().getPlayerOrException(); - - var hand = player.getUsedItemHand(); - var itemStack = player.getItemInHand(hand); - - var entry = itemStack.getItemHolder().unwrapKey().get(); - var entryString = String.format("Tags for [%s / %s]:", entry.registry(), entry.location()); - - var text = Component.empty(); - text.append(Component.nullToEmpty(entryString)); - var tags = itemStack.getTags().iterator(); - while(tags.hasNext()) { - var tag = tags.next(); - text.append(Component.nullToEmpty("\n")); - text.append( - Component.literal(" #" + tag.location()) - .setStyle(Style.EMPTY - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.nullToEmpty("Click to copy"))) - .withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, "#" + tag.location())) - ) - ); - } - - context.getSource().sendSuccess(() -> text, false); - - return 1; - })) - ); - } -} diff --git a/src/main/java/me/alexdevs/solstice/modules/inventorySee/commands/InventorySeeCommand.java b/src/main/java/me/alexdevs/solstice/modules/inventorySee/commands/InventorySeeCommand.java deleted file mode 100644 index 319851d1..00000000 --- a/src/main/java/me/alexdevs/solstice/modules/inventorySee/commands/InventorySeeCommand.java +++ /dev/null @@ -1,215 +0,0 @@ -package me.alexdevs.solstice.modules.inventorySee.commands; - -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import dev.emi.trinkets.api.TrinketsApi; -import eu.pb4.sgui.api.gui.SimpleGui; -import me.alexdevs.solstice.api.command.LocalGameProfile; -import me.alexdevs.solstice.api.module.ModCommand; -import me.alexdevs.solstice.api.utils.PlayerUtils; -import me.alexdevs.solstice.integrations.TrinketsIntegration; -import me.alexdevs.solstice.modules.inventorySee.ImmutableSlot; -import me.alexdevs.solstice.modules.inventorySee.InventorySeeModule; -import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.core.component.DataComponents; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.inventory.ChestMenu; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import static net.minecraft.commands.Commands.argument; -import static net.minecraft.commands.Commands.literal; - -public class InventorySeeCommand extends ModCommand { - public InventorySeeCommand(InventorySeeModule module) { - super(module); - } - - @Override - public List getNames() { - return List.of("invsee", "inventorysee"); - } - - private static final LinkedHashMap> invSizes = new LinkedHashMap<>(); - - static { - invSizes.put(9, MenuType.GENERIC_9x1); - invSizes.put(18, MenuType.GENERIC_9x2); - invSizes.put(27, MenuType.GENERIC_9x3); - invSizes.put(36, MenuType.GENERIC_9x4); - invSizes.put(45, MenuType.GENERIC_9x5); - invSizes.put(54, MenuType.GENERIC_9x6); - } - - @Override - public LiteralArgumentBuilder command(String name) { - return literal(name) - .requires(require(2)) - .then(argument("player", StringArgumentType.word()) - .suggests(LocalGameProfile::suggest) - .executes(context -> { - var source = context.getSource(); - var player = source.getPlayerOrException(); - var targetProfile = LocalGameProfile.getProfile(context, "player"); - var targetOnline = PlayerUtils.isOnline(targetProfile.getId()); - - if (!targetOnline && !Permissions.check(player, getPermissionNode("offline"), 3)) { - source.sendSuccess(() -> module.locale().get("offlineNotAllowed"), false); - return 0; - } - - ServerPlayer target; - if (targetOnline) { - target = context.getSource().getServer().getPlayerList().getPlayer(targetProfile.getId()); - if (Permissions.check(target, getPermissionNode("exempt"), 3)) { - source.sendSuccess(() -> module.locale().get("exempt"), false); - return 0; - } - } else { - target = PlayerUtils.loadOfflinePlayer(targetProfile); - if (Permissions.check(targetProfile, getPermissionNode("exempt"), 3, source.getServer()).getNow(false)) { - source.sendSuccess(() -> module.locale().get("exempt"), false); - return 0; - } - } - - var canEdit = Permissions.check(player, getPermissionNode("edit"), 3); - - var targetInventory = target.getInventory(); - - var container = new SimpleGui(MenuType.GENERIC_9x5, player, false) { - @Override - public void onClose() { - if (!targetOnline) { - PlayerUtils.saveOfflinePlayer(target); - } - } - }; - - for (var i = 0; i < targetInventory.getContainerSize(); i++) { - Slot slot; - if (canEdit) { - slot = new Slot(targetInventory, i, 0, 0); - } else { - slot = new ImmutableSlot(targetInventory, i, 0, 0); - } - container.setSlotRedirect(i, slot); - } - - var barrier = new ItemStack(Items.BLACK_STAINED_GLASS_PANE); - barrier.set(DataComponents.CUSTOM_NAME, Component.literal("")); - for (var i = targetInventory.getContainerSize(); i < container.getSize(); i++) { - container.setSlot(i, barrier); - } - - container.setTitle(target.getName()); - - container.open(); - - var map = Map.of( - "user", Component.nullToEmpty(target.getGameProfile().getName()) - ); - source.sendSuccess(() -> module.locale().get("openedInventory", map), true); - - return 1; - }) - .then(literal("trinkets") - .executes(context -> { - var source = context.getSource(); - var player = source.getPlayerOrException(); - var targetProfile = LocalGameProfile.getProfile(context, "player"); - var targetOnline = PlayerUtils.isOnline(targetProfile.getId()); - - if (!targetOnline && !Permissions.check(player, getPermissionNode("offline"), 3)) { - source.sendSuccess(() -> module.locale().get("offlineNotAllowed"), false); - return 0; - } - - ServerPlayer target; - if (targetOnline) { - target = context.getSource().getServer().getPlayerList().getPlayer(targetProfile.getId()); - if (Permissions.check(target, getPermissionNode("exempt"), 3)) { - source.sendSuccess(() -> module.locale().get("exempt"), false); - return 0; - } - } else { - target = PlayerUtils.loadOfflinePlayer(targetProfile); - if (Permissions.check(targetProfile, getPermissionNode("exempt"), 3, source.getServer()).getNow(false)) { - source.sendSuccess(() -> module.locale().get("exempt"), false); - return 0; - } - } - - if (!TrinketsIntegration.isAvailable()) { - source.sendSuccess(() -> module.locale().get("trinketsNotInstalled"), false); - return 0; - } - - var canEdit = Permissions.check(player, getPermissionNode("edit"), 3); - - var trinkets = TrinketsApi.getTrinketComponent(target).orElse(null); - var slots = new ArrayList(); - for (var group : trinkets.getInventory().values()) { - for (var inventory : group.values()) { - for (var i = 0; i < inventory.getContainerSize(); i++) { - Slot slot; - if (canEdit) { - slot = new Slot(inventory, i, 0, 0); - } else { - slot = new ImmutableSlot(inventory, i, 0, 0); - } - slots.add(slot); - } - } - } - - var size = slots.size(); - MenuType handlerType = null; - for (var entry : invSizes.entrySet()) { - handlerType = entry.getValue(); - if (size <= entry.getKey()) { - break; - } - } - - var container = new SimpleGui(handlerType, player, false) { - @Override - public void onClose() { - if (!targetOnline) { - PlayerUtils.saveOfflinePlayer(target); - } - } - }; - - for (var i = 0; i < slots.size(); i++) { - var slot = slots.get(i); - container.setSlotRedirect(i, slot); - } - - var barrier = new ItemStack(Items.BLACK_STAINED_GLASS_PANE); - barrier.set(DataComponents.CUSTOM_NAME, Component.literal("")); - for (var i = size; i < container.getSize(); i++) { - container.setSlot(i, barrier); - } - - container.setTitle(target.getName()); - container.open(); - - var map = Map.of( - "user", Component.nullToEmpty(target.getGameProfile().getName()) - ); - source.sendSuccess(() -> module.locale().get("openedTrinkets", map), true); - - return 1; - })) - ); - } -} diff --git a/src/main/resources/META-INF/neoforge.mods.toml b/src/main/resources/META-INF/neoforge.mods.toml deleted file mode 100644 index 4641cd68..00000000 --- a/src/main/resources/META-INF/neoforge.mods.toml +++ /dev/null @@ -1,34 +0,0 @@ -modLoader="javafml" -loaderVersion="[1,)" -license="MIT" - -[properties] -"connector:placeholder"=true - -[[mods]] -modId="solstice" -version="0.0.1" -displayName="Solstice Essentials" -authors="AlexDevs" -description='''Server commands, custom chat formats and more''' - -[[dependencies.solstice]] -modId="forge" -mandatory=true -versionRange="[47,)" -ordering="NONE" -side="SERVER" - -[[dependencies.solstice]] -modId="minecraft" -mandatory=true -versionRange="[1.21.1]" -ordering="NONE" -side="SERVER" - -[[dependencies.solstice]] -modId="connector" -mandatory=true -versionRange="*" -ordering="NONE" -side="BOTH" \ No newline at end of file