diff --git a/.github/workflows/gradlepublish.yml b/.github/workflows/gradlepublish.yml new file mode 100644 index 0000000..e0a483d --- /dev/null +++ b/.github/workflows/gradlepublish.yml @@ -0,0 +1,34 @@ +# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created +# For more information see: https://github.com/actions/setup-java#publishing-using-gradle + +name: Gradle Package + +on: push + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + server-id: github # Value of the distributionManagement/repository/id field of the pom.xml + settings-path: ${{ github.workspace }} # location for the settings.xml file + + - name: Build with Gradle + run: gradle build + + # The USERNAME and PASSWORD need to correspond to the credentials environment variables used in + # the publishing section of your build.gradle + - name: Publish to GitHub Packages + run: gradle publish + env: + BRANCH_NAME: ${{ github.ref }} + RUN_COUNT: ${{ github.run_number }} + REPO_NAME: ${{ github.repository }} + USERNAME: ${{ github.actor }} + PASSWORD: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 1b74810..ffd34e2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,29 @@ -.idea/ -build/ -run/ -.gradle/ +# Compiled nonsense that does not belong in *source* control +/build +/bin +/.gradle +/minecraft +/out +/run +/classes + +# IDE nonsense that could go in source control but really shouldn't +.classpath +.project +.metadata +.settings +*.launch +*.iml +.idea +*.ipr +*.iws + +# Sekrit files +private.properties +private.gradle + +# Files from bad operating systems :^) +Thumbs.db +.DS_Store +local.properties +.directory \ No newline at end of file diff --git a/LICENSE b/LICENSE index ad1f48d..0352c66 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,14 @@ -Copyright 2019 Martmists +Copyright 2020 FabLabsMC -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/build.gradle b/build.gradle index f0dce44..59b8456 100644 --- a/build.gradle +++ b/build.gradle @@ -1,25 +1,128 @@ -buildscript { - dependencies { - classpath "net.fabricmc:fabric-loom:0.2.7-SNAPSHOT" +plugins { + id "java" + id "eclipse" + id "idea" + id "fabric-loom" version "0.2.7-SNAPSHOT" + id "maven-publish" + id "checkstyle" +} + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +// Elytra version format - notes branch, commit count, and dirty in version string +def branch +if (System.env.BRANCH_NAME) { + // CI support + branch = System.env.BRANCH_NAME + branch = branch.substring(branch.lastIndexOf("/")+1) +} else { + branch = "git rev-parse --abbrev-ref HEAD".execute().in.text.trim() +} +if (branch == "HEAD") { + branch = "git rev-parse --short HEAD".execute().in.text.trim() +} +def commits +if (System.env.RUN_COUNT) { + //CI support, for some reason github actions doesn't like getting the rev-list count + commits = System.env.RUN_COUNT +} else { + commits = "git rev-list --count HEAD".execute().in.text.trim() +} +def dirty = !"git diff-index HEAD".execute().in.text.trim().isEmpty() + +def libName = "${project.library_name}" +def libVer = "${project.library_version}" +archivesBaseName = "fablabs-" + libName + "-v" + libVer +group = "${project.maven_group}" +version = branch + "-${project.mod_version}" + "." + commits + (dirty ? "-dirty" : "") + "+${project.minecraft_version}" +def modVersion = "${project.mod_version}" + "-" + commits + "+${project.minecraft_version}" // semver-compatible version string for use in fabric.mod.json +def modRepo +if (System.env.REPO_NAME) { + modRepo = System.env.REPO_NAME +} else { + modRepo = "FabLabsMC/${project.library_name}" +} + +minecraft { + accessWidener = file("src/main/resources/libgamerule.accesswidener") +} + +repositories { + mavenCentral() + maven { url "http://maven.fabricmc.net/" } // Fabric maven - home of Fabric API and ModMenu +} + +dependencies { + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.minecraft_version}+build.${project.yarn_build}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + // compileOnly "com.google.code.findbugs:jsr305:3.0.2" //TODO: what are we going to do for annotations? +} + +checkstyle { + configFile = rootProject.file("checkstyle.xml") + toolVersion = '8.25' +} + +processResources { + inputs.property "version", modVersion + inputs.property "id", project.archivesBaseName + inputs.property "repo", modRepo + inputs.property "libname", libName + inputs.property "libver", libVer + from(sourceSets.main.resources.srcDirs) { + include "fabric.mod.json" + expand version: modVersion, id: project.archivesBaseName, repo: modRepo, libname: libName, libver: libVer } - repositories { - maven { - name = 'Fabric' - url = 'https://maven.fabricmc.net/' - } - gradlePluginPortal() + from(sourceSets.main.resources.srcDirs) { + exclude "fabric.mod.json" } } -apply plugin: "idea" - +// ensure that the encoding is set to UTF-8, no matter what the system default is +// this fixes some edge cases with special characters not displaying correctly +// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html tasks.withType(JavaCompile) { options.encoding = "UTF-8" } -repositories { - mavenCentral() - maven { - url 'https://jitpack.io' +// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task +// if it is present. +// If you remove this task, sources will not be generated. +task sourcesJar(type: Jar, dependsOn: classes) { + classifier = "sources" + from sourceSets.main.allSource +} + +jar { + from "LICENSE" +} + +// configure the maven publication +publishing { + repositories { + maven { + name = "GitHubPackages" + url = uri("https://maven.pkg.github.com/" + modRepo.toLowerCase()) + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("USERNAME") + password = project.findProperty("gpr.key") ?: System.getenv("PASSWORD") + } + } + // uncomment to publish to the local maven + // mavenLocal() + } + publications { + mavenJava(MavenPublication) { + // add all the jars that should be included when publishing to maven + artifact(remapJar) { + builtBy remapJar + } + artifact(sourcesJar) { + builtBy remapSourcesJar + } + } } } diff --git a/checkstyle.xml b/checkstyle.xml new file mode 100644 index 0000000..42dca1a --- /dev/null +++ b/checkstyle.xml @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index c6bbd48..17f0e31 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,19 @@ # Done to increase the memory available to gradle. org.gradle.jvmargs=-Xmx4G -mod_name=libgamerule -mod_version=0.0.4 + +# Fabric Properties +# check these on https://fabricmc.net/use +minecraft_version=1.15.2 +yarn_build=15 +loader_version=0.8.2+build.194 + +# Mod Properties +# library_name may also be used for maven publishing +mod_version = 1.0.0 +maven_group = io.github.fablabsmc +library_name = libgamerule +library_version=1 + +# Dependencies +# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api +fabric_version=0.5.1+build.294-1.15 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 87b738c..deedc7f 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 192468f..b9e1d2c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Oct 15 13:15:02 CEST 2019 -distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip +#Mon Aug 22 17:36:22 EDT 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..8cea0b6 Binary files /dev/null and b/icon.png differ diff --git a/settings.gradle b/settings.gradle index 3cbfa50..89fa615 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,10 @@ -include "versions:1.15.2" -include "versions:1.16" - -rootProject.name = 'libgamerule' \ No newline at end of file +pluginManagement { + repositories { + jcenter() + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + gradlePluginPortal() + } +} \ No newline at end of file diff --git a/src/main/java/com/martmists/libgamerule/Gamerule.java b/src/main/java/com/martmists/libgamerule/Gamerule.java deleted file mode 100644 index cf49d7f..0000000 --- a/src/main/java/com/martmists/libgamerule/Gamerule.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.martmists.libgamerule; - -import blue.endless.jankson.annotation.Nullable; -import com.martmists.libgamerule.entities.ValueGetter; -import com.martmists.libgamerule.mixin.GameRuleCommandAccessor; -import com.martmists.libgamerule.mixin.GameRulesAccessor; -import com.martmists.libgamerule.mixin.RuleTypeAccessor; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.tree.CommandNode; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.registry.CommandRegistry; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.command.CommandManager; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.world.GameRules; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.Supplier; - -public class Gamerule implements ModInitializer { - public static Supplier SERVER_SUPPLIER; - public static boolean dirty = false; - public static CommandDispatcher DISPATCHER; - public static List> unregistered = new ArrayList<>(); - - public static > GameRules.RuleKey register(String name, GameRules.RuleType type) { - dirty = true; - GameRules.RuleKey key = GameRulesAccessor.invokeRegister(name, type); - - CommandNode node = CommandManager.literal(name).executes((commandContext) -> { - return GameRuleCommandAccessor.invokeExecuteQuery(commandContext.getSource(), key); - }).then(type.argument("value").executes((commandContext) -> { - return GameRuleCommandAccessor.invokeExecuteSet(commandContext, key); - })).build(); - - if (DISPATCHER == null){ - unregistered.add(node); - } else { - DISPATCHER.getRoot().getChild("gamerule").addChild(node); - } - return key; - } - - @Nullable - public static & ValueGetter, V> V get(GameRules.RuleKey key) { - return SERVER_SUPPLIER.get().getGameRules().get(key).get(); - } - - public static > GameRules.RuleType createRuleType(Supplier> argumentType, Function, T> factory) { - return createRuleType(argumentType, factory, (s, r) -> { - }); - } - - public static > GameRules.RuleType createRuleType(Supplier> argumentType, Function, T> factory, BiConsumer notifier) { - return RuleTypeAccessor.invokeNew(argumentType, factory, notifier); - } - - @Override - public void onInitialize() { - CommandRegistry.INSTANCE.register(false, (dispatcher)-> { - DISPATCHER = dispatcher; - unregistered.forEach((n)->{ - DISPATCHER.getRoot().getChild("gamerule").addChild(n); - }); - unregistered.clear(); - }); - } -} diff --git a/src/main/java/com/martmists/libgamerule/GameruleClientMod.java b/src/main/java/com/martmists/libgamerule/GameruleClientMod.java deleted file mode 100644 index d29e0c2..0000000 --- a/src/main/java/com/martmists/libgamerule/GameruleClientMod.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.martmists.libgamerule; - -import net.fabricmc.api.ClientModInitializer; -import net.minecraft.client.MinecraftClient; - -public class GameruleClientMod implements ClientModInitializer { - @Override - public void onInitializeClient() { - Gamerule.SERVER_SUPPLIER = () -> MinecraftClient.getInstance().getServer(); - } -} diff --git a/src/main/java/com/martmists/libgamerule/GameruleServerMod.java b/src/main/java/com/martmists/libgamerule/GameruleServerMod.java deleted file mode 100644 index c212985..0000000 --- a/src/main/java/com/martmists/libgamerule/GameruleServerMod.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.martmists.libgamerule; - -import net.fabricmc.api.DedicatedServerModInitializer; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.server.MinecraftServer; - -public class GameruleServerMod implements DedicatedServerModInitializer { - @Override - public void onInitializeServer() { - Gamerule.SERVER_SUPPLIER = () -> (MinecraftServer) FabricLoader.getInstance().getGameInstance(); - } -} diff --git a/src/main/java/com/martmists/libgamerule/arguments/EnumArgumentType.java b/src/main/java/com/martmists/libgamerule/arguments/EnumArgumentType.java deleted file mode 100644 index 6aefb29..0000000 --- a/src/main/java/com/martmists/libgamerule/arguments/EnumArgumentType.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.martmists.libgamerule.arguments; - -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import net.minecraft.server.command.CommandSource; -import net.minecraft.text.LiteralText; - -import java.util.Arrays; -import java.util.Collection; -import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; - -public class EnumArgumentType> implements ArgumentType { - Class clazz; - - public EnumArgumentType(Class enumClass) { - this.clazz = enumClass; - } - - @Override - public E parse(StringReader reader) throws CommandSyntaxException { - StringBuilder param = new StringBuilder(); - - if (reader.canRead() && Character.isJavaIdentifierStart(reader.peek())) { - do { - param.append(reader.read()); - } while (reader.canRead() && Character.isJavaIdentifierPart(reader.peek())); - } - - try { - return Enum.valueOf(clazz, param.toString().toUpperCase()); - } catch (IllegalArgumentException e) { - throw new SimpleCommandExceptionType(new LiteralText("Invalid enum value!")).createWithContext(reader); - } - } - - @Override - public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { - return CommandSource.suggestMatching( - Arrays.stream(clazz.getEnumConstants()) - .map(Enum::toString) - .toArray(String[]::new), - builder - ); - } - - @Override - public Collection getExamples() { - return Arrays.stream(clazz.getEnumConstants()) - .map(Enum::toString) - .limit(2) - .collect(Collectors.toList()); - } -} diff --git a/src/main/java/com/martmists/libgamerule/compat/libcd/GameruleTweaker.java b/src/main/java/com/martmists/libgamerule/compat/libcd/GameruleTweaker.java deleted file mode 100644 index 6e7a3fc..0000000 --- a/src/main/java/com/martmists/libgamerule/compat/libcd/GameruleTweaker.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.martmists.libgamerule.compat.libcd; - -import com.martmists.libgamerule.Gamerule; -import com.martmists.libgamerule.rules.BooleanRule; -import com.martmists.libgamerule.rules.DoubleRule; -import com.martmists.libgamerule.rules.IntRule; -import com.martmists.libgamerule.rules.StringRule; -import net.minecraft.world.GameRules; - -public class GameruleTweaker { - public void addGamerule(String name, String type, Object defaultValue) { - try { - GameRules.RuleType t; - switch (type) { - case "int": - case "integer": - t = IntRule.create((Integer) defaultValue); - break; - case "bool": - case "boolean": - t = BooleanRule.create((Boolean) defaultValue); - break; - case "double": - t = DoubleRule.create((Double) defaultValue); - break; - case "string": - t = StringRule.create((String) defaultValue); - break; - case "enum": - throw new Exception("Enums are not yet supported in libcd scripts"); - default: - throw new Exception("Unknown rule type!"); - } - Gamerule.register(name, t); - } catch (Exception e) { - System.out.println("Error parsing gamerule - " + e.getMessage()); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/martmists/libgamerule/compat/libcd/GameruleTweakerEP.java b/src/main/java/com/martmists/libgamerule/compat/libcd/GameruleTweakerEP.java deleted file mode 100644 index dae4e78..0000000 --- a/src/main/java/com/martmists/libgamerule/compat/libcd/GameruleTweakerEP.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.martmists.libgamerule.compat.libcd; - -import blue.endless.jankson.JsonObject; -import blue.endless.jankson.JsonPrimitive; -import com.martmists.libgamerule.Gamerule; -import com.martmists.libgamerule.rules.BooleanRule; -import com.martmists.libgamerule.rules.DoubleRule; -import com.martmists.libgamerule.rules.IntRule; -import com.martmists.libgamerule.rules.StringRule; -import io.github.cottonmc.libcd.api.CDSyntaxError; -import io.github.cottonmc.libcd.api.LibCDInitializer; -import io.github.cottonmc.libcd.api.condition.ConditionManager; -import io.github.cottonmc.libcd.api.tweaker.TweakerManager; -import net.minecraft.util.Identifier; -import net.minecraft.world.GameRules; - -public class GameruleTweakerEP implements LibCDInitializer { - public void initTweakers(TweakerManager p0) { - p0.addAssistant("libgamerule.GameruleTweaker", GameruleTweaker.class); - } - - @Override - public void initConditions(ConditionManager conditionManager) { - conditionManager.registerCondition(new Identifier("libgamerule:gamerule_has_value"), (value) -> { - if (value instanceof String) { - // assume booleanrule - return Gamerule.get(new GameRules.RuleKey((String) value)); - } else if (value instanceof JsonObject) { - JsonObject jo = (JsonObject) value; - String ruleName = ((JsonPrimitive) jo.get("name")).asString(); - String ruleType = ((JsonPrimitive) jo.get("type")).asString(); - switch (ruleType) { - case "string": - return Gamerule.get(new GameRules.RuleKey(ruleName)).equals(((JsonPrimitive) jo.get("value")).asString()); - case "double": - return Gamerule.get(new GameRules.RuleKey(ruleName)) == ((JsonPrimitive) jo.get("value")).asDouble(0.0); - case "int": - case "integer": - return Gamerule.get(new GameRules.RuleKey(ruleName)) == ((JsonPrimitive) jo.get("value")).asInt(0); - case "boolean": - return Gamerule.get(new GameRules.RuleKey(ruleName)); - default: - throw new CDSyntaxError("Invalid rule type: " + ruleType); - } - } - return false; - }); - } -} diff --git a/src/main/java/com/martmists/libgamerule/entities/UpdateGameRules.java b/src/main/java/com/martmists/libgamerule/entities/UpdateGameRules.java deleted file mode 100644 index 2386c2d..0000000 --- a/src/main/java/com/martmists/libgamerule/entities/UpdateGameRules.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.martmists.libgamerule.entities; - -public interface UpdateGameRules { - void updateGamerules(); -} diff --git a/src/main/java/com/martmists/libgamerule/entities/ValueGetter.java b/src/main/java/com/martmists/libgamerule/entities/ValueGetter.java deleted file mode 100644 index 2b4154c..0000000 --- a/src/main/java/com/martmists/libgamerule/entities/ValueGetter.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.martmists.libgamerule.entities; - -public interface ValueGetter { - T get(); -} diff --git a/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandAccessor.java b/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandAccessor.java deleted file mode 100644 index 5eef973..0000000 --- a/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandAccessor.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.martmists.libgamerule.mixin; - -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.server.command.GameRuleCommand; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.world.GameRules; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(GameRuleCommand.class) -public interface GameRuleCommandAccessor { - @Invoker - @SuppressWarnings("PublicStaticMixinMember") - static > int invokeExecuteSet(CommandContext commandContext, GameRules.RuleKey ruleKey) { - throw new AssertionError("This shouldn't happen!"); - } - - @Invoker - @SuppressWarnings("PublicStaticMixinMember") - static > int invokeExecuteQuery(ServerCommandSource serverCommandSource, GameRules.RuleKey ruleKey) { - throw new AssertionError("This shouldn't happen!"); - } -} diff --git a/src/main/java/com/martmists/libgamerule/mixin/GameRulesAccessor.java b/src/main/java/com/martmists/libgamerule/mixin/GameRulesAccessor.java deleted file mode 100644 index 4f2163c..0000000 --- a/src/main/java/com/martmists/libgamerule/mixin/GameRulesAccessor.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.martmists.libgamerule.mixin; - -import net.minecraft.world.GameRules; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(GameRules.class) -public interface GameRulesAccessor { - @Invoker - @SuppressWarnings("PublicStaticMixinMember") - static > GameRules.RuleKey invokeRegister(String name, GameRules.RuleType type) { - throw new AssertionError("This shouldn't happen!"); - } -} diff --git a/src/main/java/com/martmists/libgamerule/mixin/GameRulesMixin.java b/src/main/java/com/martmists/libgamerule/mixin/GameRulesMixin.java deleted file mode 100644 index 64ea31a..0000000 --- a/src/main/java/com/martmists/libgamerule/mixin/GameRulesMixin.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.martmists.libgamerule.mixin; - -import com.google.common.collect.ImmutableMap; -import com.martmists.libgamerule.Gamerule; -import com.martmists.libgamerule.entities.UpdateGameRules; -import net.minecraft.world.GameRules; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Map; - -@Mixin(GameRules.class) -public class GameRulesMixin implements UpdateGameRules { - @Final - @Shadow - private static Map, GameRules.RuleType> RULE_TYPES; - - @Shadow - private Map, GameRules.Rule> rules; - - public void updateGamerules() { - // In case new Gamerules were added late by e.g. libcd - if (Gamerule.dirty) { - Gamerule.dirty = false; - this.rules = RULE_TYPES.entrySet() - .stream() - .collect(ImmutableMap.toImmutableMap( - Map.Entry::getKey, - (e) -> ((GameRules.RuleType) e.getValue()).createRule() - )); - } - } -} diff --git a/src/main/java/com/martmists/libgamerule/mixin/LevelPropertiesMixin.java b/src/main/java/com/martmists/libgamerule/mixin/LevelPropertiesMixin.java deleted file mode 100644 index 3bbcab5..0000000 --- a/src/main/java/com/martmists/libgamerule/mixin/LevelPropertiesMixin.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.martmists.libgamerule.mixin; - -import com.martmists.libgamerule.entities.UpdateGameRules; -import net.minecraft.world.GameRules; -import net.minecraft.world.level.LevelProperties; -import org.spongepowered.asm.mixin.Final; -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.CallbackInfoReturnable; - -@Mixin(LevelProperties.class) -public class LevelPropertiesMixin { - @Shadow - @Final - private GameRules gameRules; - - @Inject(method = "getGameRules", at = @At("HEAD")) - void preUpdate(CallbackInfoReturnable cir) { - // We refresh the gamerules in case any were added after the world was initialized. - ((UpdateGameRules) gameRules).updateGamerules(); - } -} diff --git a/src/main/java/com/martmists/libgamerule/mixin/RuleTypeAccessor.java b/src/main/java/com/martmists/libgamerule/mixin/RuleTypeAccessor.java deleted file mode 100644 index 23f4ca8..0000000 --- a/src/main/java/com/martmists/libgamerule/mixin/RuleTypeAccessor.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.martmists.libgamerule.mixin; - -import com.mojang.brigadier.arguments.ArgumentType; -import net.minecraft.world.GameRules; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.Supplier; - -@Mixin(GameRules.RuleType.class) -public interface RuleTypeAccessor { - @Invoker("") - @SuppressWarnings("PublicStaticMixinMember") - static GameRules.RuleType invokeNew(Supplier> argumentType, Function factory, BiConsumer notifier) { - throw new AssertionError("This shouldn't happen!"); - } -} diff --git a/src/main/java/com/martmists/libgamerule/rules/BooleanRule.java b/src/main/java/com/martmists/libgamerule/rules/BooleanRule.java deleted file mode 100644 index 15f3fb1..0000000 --- a/src/main/java/com/martmists/libgamerule/rules/BooleanRule.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.martmists.libgamerule.rules; - -import com.martmists.libgamerule.Gamerule; -import com.martmists.libgamerule.entities.ValueGetter; -import com.mojang.brigadier.arguments.BoolArgumentType; -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.world.GameRules; - -public class BooleanRule extends GameRules.Rule implements ValueGetter { - // Using this instead of GameRules.BooleanRule for ease of use - boolean value; - - public BooleanRule(GameRules.RuleType ruleType, boolean value) { - super(ruleType); - this.value = value; - } - - public static GameRules.RuleType create(boolean defaultValue) { - return Gamerule.createRuleType( - BoolArgumentType::bool, - (GameRules.RuleType t) -> new BooleanRule(t, defaultValue) - ); - } - - @Override - protected void setFromArgument(CommandContext commandContext, String string) { - value = BoolArgumentType.getBool(commandContext, string); - } - - @Override - protected void deserialize(String string) { - value = string.equals("true"); - } - - @Override - protected String serialize() { - return Boolean.toString(value); - } - - @Override - public int getCommandResult() { - return 0; - } - - @Override - protected BooleanRule getThis() { - return this; - } - - @Override - public Boolean get() { - return value; - } -} diff --git a/src/main/java/com/martmists/libgamerule/rules/DoubleRule.java b/src/main/java/com/martmists/libgamerule/rules/DoubleRule.java deleted file mode 100644 index ff632b4..0000000 --- a/src/main/java/com/martmists/libgamerule/rules/DoubleRule.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.martmists.libgamerule.rules; - -import com.martmists.libgamerule.Gamerule; -import com.martmists.libgamerule.entities.ValueGetter; -import com.mojang.brigadier.arguments.DoubleArgumentType; -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.world.GameRules; - -public class DoubleRule extends GameRules.Rule implements ValueGetter { - double value; - - public DoubleRule(GameRules.RuleType ruleType, double value) { - super(ruleType); - this.value = value; - } - - public static GameRules.RuleType create(double defaultValue) { - return Gamerule.createRuleType( - DoubleArgumentType::doubleArg, - (GameRules.RuleType t) -> new DoubleRule(t, defaultValue) - ); - } - - public static GameRules.RuleType create(double defaultValue, double minValue) { - return Gamerule.createRuleType( - () -> DoubleArgumentType.doubleArg(minValue), - (GameRules.RuleType t) -> new DoubleRule(t, defaultValue) - ); - } - - public static GameRules.RuleType create(double defaultValue, double minValue, double maxValue) { - return Gamerule.createRuleType( - () -> DoubleArgumentType.doubleArg(minValue, maxValue), - (GameRules.RuleType t) -> new DoubleRule(t, defaultValue) - ); - } - - @Override - protected void setFromArgument(CommandContext commandContext, String string) { - value = DoubleArgumentType.getDouble(commandContext, string); - } - - @Override - protected void deserialize(String string) { - value = Double.parseDouble(string); - } - - @Override - protected String serialize() { - return Double.toString(value); - } - - @Override - public int getCommandResult() { - return 0; - } - - @Override - protected DoubleRule getThis() { - return this; - } - - @Override - public Double get() { - return value; - } -} diff --git a/src/main/java/com/martmists/libgamerule/rules/EnumRule.java b/src/main/java/com/martmists/libgamerule/rules/EnumRule.java deleted file mode 100644 index 21aa3ce..0000000 --- a/src/main/java/com/martmists/libgamerule/rules/EnumRule.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.martmists.libgamerule.rules; - -import com.martmists.libgamerule.Gamerule; -import com.martmists.libgamerule.arguments.EnumArgumentType; -import com.martmists.libgamerule.entities.ValueGetter; -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.world.GameRules; - -public class EnumRule> extends GameRules.Rule> implements ValueGetter { - Class clazz; - E value; - - public EnumRule(GameRules.RuleType> ruleType, E value) { - super(ruleType); - this.value = value; - this.clazz = value.getDeclaringClass(); - } - - public static > GameRules.RuleType> create(E defaultValue) { - return Gamerule.createRuleType( - () -> new EnumArgumentType<>(defaultValue.getDeclaringClass()), - (GameRules.RuleType> t) -> new EnumRule<>(t, defaultValue) - ); - } - - @Override - protected void setFromArgument(CommandContext context, String name) { - value = context.getArgument(name, clazz); - } - - @Override - protected void deserialize(String string) { - value = Enum.valueOf(clazz, string); - } - - @Override - protected String serialize() { - return value.toString(); - } - - @Override - public int getCommandResult() { - return 0; - } - - @Override - protected EnumRule getThis() { - return this; - } - - @Override - public E get() { - return value; - } -} diff --git a/src/main/java/com/martmists/libgamerule/rules/IntRule.java b/src/main/java/com/martmists/libgamerule/rules/IntRule.java deleted file mode 100644 index 016bfe6..0000000 --- a/src/main/java/com/martmists/libgamerule/rules/IntRule.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.martmists.libgamerule.rules; - -import com.martmists.libgamerule.Gamerule; -import com.martmists.libgamerule.entities.ValueGetter; -import com.mojang.brigadier.arguments.IntegerArgumentType; -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.world.GameRules; - -public class IntRule extends GameRules.Rule implements ValueGetter { - // Not using GameRules.IntRule for flexibility in create() - - int value; - - public IntRule(GameRules.RuleType ruleType, int value) { - super(ruleType); - this.value = value; - } - - public static GameRules.RuleType create(int defaultValue) { - return Gamerule.createRuleType( - IntegerArgumentType::integer, - (GameRules.RuleType t) -> new IntRule(t, defaultValue) - ); - } - - public static GameRules.RuleType create(int defaultValue, int minValue) { - return Gamerule.createRuleType( - () -> IntegerArgumentType.integer(minValue), - (GameRules.RuleType t) -> new IntRule(t, defaultValue) - ); - } - - public static GameRules.RuleType create(int defaultValue, int minValue, int maxValue) { - return Gamerule.createRuleType( - () -> IntegerArgumentType.integer(minValue, maxValue), - (GameRules.RuleType t) -> new IntRule(t, defaultValue) - ); - } - - @Override - protected void setFromArgument(CommandContext commandContext, String string) { - value = IntegerArgumentType.getInteger(commandContext, string); - } - - @Override - protected void deserialize(String string) { - value = Integer.parseInt(string); - } - - @Override - protected String serialize() { - return Integer.toString(value); - } - - @Override - public int getCommandResult() { - return 0; - } - - @Override - protected IntRule getThis() { - return this; - } - - @Override - public Integer get() { - return value; - } -} diff --git a/src/main/java/com/martmists/libgamerule/rules/StringRule.java b/src/main/java/com/martmists/libgamerule/rules/StringRule.java deleted file mode 100644 index 510f1f1..0000000 --- a/src/main/java/com/martmists/libgamerule/rules/StringRule.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.martmists.libgamerule.rules; - -import com.martmists.libgamerule.Gamerule; -import com.martmists.libgamerule.entities.ValueGetter; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.world.GameRules; - -public class StringRule extends GameRules.Rule implements ValueGetter { - String value; - - public StringRule(GameRules.RuleType ruleType, String value) { - super(ruleType); - this.value = value; - } - - public static GameRules.RuleType create(String defaultValue) { - return Gamerule.createRuleType( - StringArgumentType::greedyString, - (GameRules.RuleType t) -> new StringRule(t, defaultValue) - ); - } - - @Override - protected void setFromArgument(CommandContext commandContext, String string) { - value = StringArgumentType.getString(commandContext, string); - } - - @Override - protected void deserialize(String string) { - value = string; - } - - @Override - protected String serialize() { - return value; - } - - @Override - public int getCommandResult() { - return 0; - } - - @Override - protected StringRule getThis() { - return this; - } - - @Override - public String get() { - return value; - } -} diff --git a/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/FloatSupplier.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/FloatSupplier.java new file mode 100644 index 0000000..9a7a99f --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/FloatSupplier.java @@ -0,0 +1,16 @@ +package io.github.fablabsmc.fablabs.api.gamerule.v1; + +/** + * Represents a supplier of {@code float}-valued results. This is the + * {@code float}-producing primitive specialization of {@link java.util.function.Supplier}. + */ +// TODO: This probably belongs in `fabric-base-api` when merged +@FunctionalInterface +public interface FloatSupplier { + /** + * Gets a result. + * + * @return a result + */ + float getAsFloat(); +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/GameRuleRegistry.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/GameRuleRegistry.java new file mode 100644 index 0000000..87f5489 --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/GameRuleRegistry.java @@ -0,0 +1,21 @@ +package io.github.fablabsmc.fablabs.api.gamerule.v1; + +import io.github.fablabsmc.fablabs.impl.gamerule.GameRuleRegistryImpl; + +import net.minecraft.util.Identifier; +import net.minecraft.world.GameRules; + +public interface GameRuleRegistry { + GameRuleRegistry INSTANCE = GameRuleRegistryImpl.INSTANCE; + + /** + * Registers a {@link GameRules.Rule}. + * + * @param id the id this rule will be named + * @param type the rule type + * @param the type of rule + * @return a rule key which can be used to query the value of the rule + * @throws IllegalStateException if a rule of the same name already exists. + */ + > GameRules.RuleKey register(Identifier id, GameRules.RuleType type); +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/RuleFactory.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/RuleFactory.java new file mode 100644 index 0000000..967638e --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/RuleFactory.java @@ -0,0 +1,131 @@ +package io.github.fablabsmc.fablabs.api.gamerule.v1; + +import java.util.function.BiConsumer; + +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.DoubleRule; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.EnumRule; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.FloatRule; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.StringRule; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.TextRule; +import io.github.fablabsmc.fablabs.impl.gamerule.RuleFactoryImpl; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.text.Text; +import net.minecraft.world.GameRules; + +public interface RuleFactory { + RuleFactory INSTANCE = RuleFactoryImpl.INSTANCE; + + default GameRules.RuleType createBooleanType(boolean defaultValue) { + return this.createBooleanType(defaultValue, (server, rule) -> { + }); + } + + GameRules.RuleType createBooleanType(boolean defaultValue, BiConsumer notifier); + + default GameRules.RuleType createIntType(int defaultValue) { + return this.createIntType(defaultValue, (server, rule) -> { + }); + } + + default GameRules.RuleType createBoundedIntType(int defaultValue, int lowerBound) { + return this.createBoundedIntType(defaultValue, lowerBound, Integer.MAX_VALUE, (server, rule) -> { + }); + } + + default GameRules.RuleType createBoundedIntType(int defaultValue, int lowerBound, BiConsumer notifier) { + return this.createBoundedIntType(defaultValue, lowerBound, Integer.MAX_VALUE, notifier); + } + + default GameRules.RuleType createBoundedIntType(int defaultValue, int lowerBound, int upperBound) { + return this.createBoundedIntType(defaultValue, lowerBound, upperBound, (server, rule) -> { + }); + } + + GameRules.RuleType createIntType(int defaultValue, BiConsumer notifier); + + GameRules.RuleType createBoundedIntType(int defaultValue, int lowerBound, int upperBound, BiConsumer notifier); + + default GameRules.RuleType createDoubleType(double defaultValue) { + return this.createDoubleType(defaultValue, (server, rule) -> { + }); + } + + default GameRules.RuleType createBoundedDoubleType(double defaultValue, double lowerBound) { + return this.createBoundedDoubleType(defaultValue, lowerBound, Integer.MAX_VALUE, (server, rule) -> { + }); + } + + default GameRules.RuleType createBoundedDoubleType(double defaultValue, double lowerBound, BiConsumer notifier) { + return this.createBoundedDoubleType(defaultValue, lowerBound, Integer.MAX_VALUE, notifier); + } + + default GameRules.RuleType createBoundedDoubleType(double defaultValue, double lowerBound, double upperBound) { + return this.createBoundedDoubleType(defaultValue, lowerBound, upperBound, (server, rule) -> { + }); + } + + GameRules.RuleType createDoubleType(double defaultValue, BiConsumer notifier); + + GameRules.RuleType createBoundedDoubleType(double defaultValue, double lowerBound, double upperBound, BiConsumer notifier); + + default GameRules.RuleType createFloatType(float defaultValue) { + return this.createFloatType(defaultValue, (server, rule) -> { + }); + } + + default GameRules.RuleType createBoundedFloatType(float defaultValue, float lowerBound) { + return this.createBoundedFloatType(defaultValue, lowerBound, Integer.MAX_VALUE, (server, rule) -> { + }); + } + + default GameRules.RuleType createBoundedFloatType(float defaultValue, float lowerBound, BiConsumer notifier) { + return this.createBoundedFloatType(defaultValue, lowerBound, Integer.MAX_VALUE, notifier); + } + + default GameRules.RuleType createBoundedFloatType(float defaultValue, float lowerBound, float upperBound) { + return this.createBoundedFloatType(defaultValue, lowerBound, upperBound, (server, rule) -> { + }); + } + + GameRules.RuleType createFloatType(float defaultValue, BiConsumer notifier); + + GameRules.RuleType createBoundedFloatType(float defaultValue, float lowerBound, float upperBound, BiConsumer notifier); + + default GameRules.RuleType createTextType(Text defaultValue) { + return this.createTextType(defaultValue, (server, rule) -> { + }); + } + + GameRules.RuleType createTextType(Text defaultValue, BiConsumer notifier); + + default GameRules.RuleType createWordType(String defaultValue) { + return this.createWordType(defaultValue, (server, rule) -> { + }); + } + + GameRules.RuleType createWordType(String defaultValue, BiConsumer notifier); + + default GameRules.RuleType createStringType(String defaultValue) { + return this.createStringType(defaultValue, (server, rule) -> { + }); + } + + GameRules.RuleType createStringType(String defaultValue, BiConsumer notifier); + + default > GameRules.RuleType> createEnumRule(E defaultValue) { + return this.createEnumRule(defaultValue, (server, rule) -> { + }); + } + + default > GameRules.RuleType> createEnumRule(E defaultValue, BiConsumer> notifier) { + return this.createEnumRule(defaultValue, defaultValue.getDeclaringClass().getEnumConstants(), notifier); + } + + default > GameRules.RuleType> createEnumRule(E defaultValue, E[] supportedValues) { + return this.createEnumRule(defaultValue, supportedValues, (server, rule) -> { + }); + } + + > GameRules.RuleType> createEnumRule(E defaultValue, E[] supportedValues, BiConsumer> notifier); +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/DoubleRule.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/DoubleRule.java new file mode 100644 index 0000000..5a07ee6 --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/DoubleRule.java @@ -0,0 +1,67 @@ +package io.github.fablabsmc.fablabs.api.gamerule.v1.rule; + +import java.util.function.DoubleSupplier; + +import com.mojang.brigadier.context.CommandContext; +import io.github.fablabsmc.fablabs.api.gamerule.v1.RuleFactory; +import io.github.fablabsmc.fablabs.impl.gamerule.GameRuleRegistryImpl; + +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.GameRules; + +public class DoubleRule extends GameRules.Rule implements DoubleSupplier { + private double value; + + // TODO: i509VCB - Should we make these constructors private since people are not supposed to be able to invoke these, and then use some invokers to create these internally within the api? + + /** + * @deprecated Please use {@link RuleFactory} instead. + */ + @Deprecated + public DoubleRule(GameRules.RuleType type, double value) { + super(type); + this.value = value; + } + + @Override + protected void setFromArgument(CommandContext context, String name) { + this.value = context.getArgument(name, Double.class); + } + + @Override + protected void deserialize(String value) { + this.value = DoubleRule.parseDouble(value); + } + + private static double parseDouble(String string) { + if (!string.isEmpty()) { + try { + return Double.parseDouble(string); + } catch (NumberFormatException e) { + GameRuleRegistryImpl.LOGGER.warn("Failed to parse double {}", string); + } + } + + return 0.0D; + } + + @Override + protected String serialize() { + return Double.toString(this.value); + } + + @Override + public int getCommandResult() { + return 0; + } + + @Override + protected DoubleRule getThis() { + return this; + } + + @Override + public double getAsDouble() { + return this.value; + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/EnumRule.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/EnumRule.java new file mode 100644 index 0000000..d6d76fb --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/EnumRule.java @@ -0,0 +1,100 @@ +package io.github.fablabsmc.fablabs.api.gamerule.v1.rule; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.function.Supplier; + +import io.github.fablabsmc.fablabs.api.gamerule.v1.RuleFactory; +import io.github.fablabsmc.fablabs.impl.gamerule.GameRuleRegistryImpl; + +import net.minecraft.world.GameRules; + +public class EnumRule> extends LiteralRule> implements Supplier { + private final Class classType; + private final E[] supportedValues; + private E value; + + // TODO: i509VCB - Should we make these constructors private since people are not supposed to be able to invoke these, and then use some invokers to create these internally within the api? + /** + * @deprecated Please use {@link RuleFactory} instead. + */ + @Deprecated + public EnumRule(GameRules.RuleType> type, E value, E[] supportedValues) { + super(type); + this.classType = value.getDeclaringClass(); + this.value = value; + this.supportedValues = supportedValues; + } + + // TODO: This should not be public, maybe use mixin to hide it? + public void setValue(E value) throws IllegalArgumentException { + checkNotNull(value); + + for (E supportedValue : this.supportedValues) { + if (supportedValue.equals(value)) { + this.value = value; + return; + } + } + + throw new IllegalArgumentException("Tried to set an unsupported value: " + value.toString()); + } + + @Override + protected void deserialize(String value) { + int ordinal = parseInt(value); + E[] possibleValues = this.classType.getEnumConstants(); + + if (possibleValues.length <= ordinal + 1) { // Our ordinal doesn't exist, log the issue + GameRuleRegistryImpl.LOGGER.warn("Failed to parse int {} for rule of type {}. Since it's ordinal is not present", ordinal, this.classType); + return; + } + + try { + this.setValue(possibleValues[ordinal]); + } catch (IllegalArgumentException e) { // Not a supported value + GameRuleRegistryImpl.LOGGER.warn("Failed to parse int {} for rule of type {}. {}", ordinal, this.classType, e); + } + } + + private int parseInt(String string) { + if (!string.isEmpty()) { + try { + return Integer.parseInt(string); + } catch (NumberFormatException e) { + GameRuleRegistryImpl.LOGGER.warn("Failed to parse int {} for rule of type {}", string, this.classType); + } + } + + return 0; + } + + @Override + protected String serialize() { + return Integer.toString(this.value.ordinal()); + } + + @Override + public int getCommandResult() { + return 0; + } + + @Override + protected EnumRule getThis() { + return this; + } + + public Class getEnumClass() { + return this.classType; + } + + @Override + public String toString() { + return this.value.toString(); + } + + @Override + public E get() { + return this.value; + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/FloatRule.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/FloatRule.java new file mode 100644 index 0000000..cf68858 --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/FloatRule.java @@ -0,0 +1,66 @@ +package io.github.fablabsmc.fablabs.api.gamerule.v1.rule; + +import com.mojang.brigadier.context.CommandContext; +import io.github.fablabsmc.fablabs.api.gamerule.v1.FloatSupplier; +import io.github.fablabsmc.fablabs.api.gamerule.v1.RuleFactory; +import io.github.fablabsmc.fablabs.impl.gamerule.GameRuleRegistryImpl; + +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.GameRules; + +public class FloatRule extends GameRules.Rule implements FloatSupplier { + private float value; + + // TODO: i509VCB - Should we make these constructors private since people are not supposed to be able to invoke these, and then use some invokers to create these internally within the api? + + /** + * @deprecated Please use {@link RuleFactory} instead. + */ + @Deprecated + public FloatRule(GameRules.RuleType type, float value) { + super(type); + this.value = value; + } + + @Override + protected void setFromArgument(CommandContext context, String name) { + this.value = context.getArgument(name, Float.class); + } + + @Override + protected void deserialize(String value) { + this.value = FloatRule.parseFloat(value); + } + + private static float parseFloat(String string) { + if (!string.isEmpty()) { + try { + return Float.parseFloat(string); + } catch (NumberFormatException e) { + GameRuleRegistryImpl.LOGGER.warn("Failed to parse float {}", string); + } + } + + return 0.0F; + } + + @Override + protected String serialize() { + return Float.toString(this.value); + } + + @Override + public int getCommandResult() { + return 0; + } + + @Override + protected FloatRule getThis() { + return this; + } + + @Override + public float getAsFloat() { + return this.value; + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/LiteralRule.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/LiteralRule.java new file mode 100644 index 0000000..42e3a11 --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/LiteralRule.java @@ -0,0 +1,17 @@ +package io.github.fablabsmc.fablabs.api.gamerule.v1.rule; + +import com.mojang.brigadier.context.CommandContext; + +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.GameRules; + +public abstract class LiteralRule> extends GameRules.Rule { + protected LiteralRule(GameRules.RuleType type) { + super(type); + } + + @Override + protected final void setFromArgument(CommandContext context, String name) { + // Do nothing. We use a different system for application + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/StringRule.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/StringRule.java new file mode 100644 index 0000000..73e3425 --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/StringRule.java @@ -0,0 +1,54 @@ +package io.github.fablabsmc.fablabs.api.gamerule.v1.rule; + +import java.util.function.Supplier; + +import com.mojang.brigadier.context.CommandContext; +import io.github.fablabsmc.fablabs.api.gamerule.v1.RuleFactory; + +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.GameRules; + +public class StringRule extends GameRules.Rule implements Supplier { + private String value; + + // TODO: i509VCB - Should we make these constructors private since people are not supposed to be able to invoke these, and then use some invokers to create these internally within the api? + + /** + * @deprecated Please use {@link RuleFactory} instead. + */ + @Deprecated + public StringRule(GameRules.RuleType type, String value) { + super(type); + this.value = value; + } + + @Override + protected void setFromArgument(CommandContext context, String name) { + this.value = context.getArgument(name, String.class); + } + + @Override + protected void deserialize(String value) { + this.value = value; + } + + @Override + protected String serialize() { + return this.value; + } + + @Override + public int getCommandResult() { + return 0; + } + + @Override + protected StringRule getThis() { + return this; + } + + @Override + public String get() { + return this.value; + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/TextRule.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/TextRule.java new file mode 100644 index 0000000..e132777 --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/TextRule.java @@ -0,0 +1,55 @@ +package io.github.fablabsmc.fablabs.api.gamerule.v1.rule; + +import java.util.function.Supplier; + +import com.mojang.brigadier.context.CommandContext; +import io.github.fablabsmc.fablabs.api.gamerule.v1.RuleFactory; + +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.Text; +import net.minecraft.world.GameRules; + +public class TextRule extends GameRules.Rule implements Supplier { + private Text value; + + // TODO: i509VCB - Should we make these constructors private since people are not supposed to be able to invoke these, and then use some invokers to create these internally within the api? + + /** + * @deprecated Please use {@link RuleFactory} instead. + */ + @Deprecated + public TextRule(GameRules.RuleType type, Text defaultValue) { + super(type); + this.value = defaultValue; + } + + @Override + protected void setFromArgument(CommandContext context, String name) { + this.value = context.getArgument(name, Text.class); + } + + @Override + protected void deserialize(String value) { + this.value = Text.Serializer.fromJson(value); + } + + @Override + protected String serialize() { + return Text.Serializer.toJson(this.value); + } + + @Override + public int getCommandResult() { + return 0; + } + + @Override + protected TextRule getThis() { + return this; + } + + @Override + public Text get() { + return this.value; + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumArgumentType.java b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumArgumentType.java new file mode 100644 index 0000000..d845954 --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumArgumentType.java @@ -0,0 +1,60 @@ +package io.github.fablabsmc.fablabs.impl.gamerule; + +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; + +import net.minecraft.server.command.CommandSource; +import net.minecraft.text.LiteralText; + +public class EnumArgumentType> implements ArgumentType { + Class clazz; + + public EnumArgumentType(Class enumClass) { + this.clazz = enumClass; + } + + @Override + public E parse(StringReader reader) throws CommandSyntaxException { + StringBuilder param = new StringBuilder(); + + if (reader.canRead() && Character.isJavaIdentifierStart(reader.peek())) { + do { + param.append(reader.read()); + } while (reader.canRead() && Character.isJavaIdentifierPart(reader.peek())); + } + + try { + return Enum.valueOf(clazz, param.toString().toUpperCase()); + } catch (IllegalArgumentException e) { + throw new SimpleCommandExceptionType(new LiteralText("Invalid enum value!")).createWithContext(reader); + } + } + + @Override + public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { + return CommandSource.suggestMatching( + Arrays.stream(clazz.getEnumConstants()) + .map(Enum::toString) + .toArray(String[]::new), + builder + ); + } + + @Override + public Collection getExamples() { + return Arrays.stream(clazz.getEnumConstants()) + .map(Enum::toString) + .limit(2) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumRuleCommand.java b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumRuleCommand.java new file mode 100644 index 0000000..d71d0a7 --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumRuleCommand.java @@ -0,0 +1,21 @@ +package io.github.fablabsmc.fablabs.impl.gamerule; + +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.EnumRule; + +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.TranslatableText; +import net.minecraft.world.GameRules; + +final class EnumRuleCommand { + public static > int executeEnumSet(CommandContext context, int ordinal, GameRules.RuleKey> key) throws CommandSyntaxException { + // Mostly copied from vanilla, but tweaked so we can use literals + ServerCommandSource serverCommandSource = context.getSource(); + EnumRule rule = serverCommandSource.getMinecraftServer().getGameRules().get(key); + + rule.setValue(rule.getEnumClass().getEnumConstants()[ordinal]); + serverCommandSource.sendFeedback(new TranslatableText("commands.gamerule.set", key.getName(), rule.toString()), true); + return rule.getCommandResult(); + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumRuleType.java b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumRuleType.java new file mode 100644 index 0000000..8379de8 --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumRuleType.java @@ -0,0 +1,38 @@ +package io.github.fablabsmc.fablabs.impl.gamerule; + +import static net.minecraft.server.command.CommandManager.literal; + +import java.util.function.BiConsumer; +import java.util.function.Function; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.tree.LiteralCommandNode; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.EnumRule; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.GameRules; + +class EnumRuleType> extends LiteralRuleType> { + private final E[] supportedValues; + + EnumRuleType(Function>, EnumRule> ruleFactory, BiConsumer> changeCallback, E[] supportedValues) { + super(null, ruleFactory, changeCallback); + this.supportedValues = supportedValues; + } + + @Override + public void register(LiteralArgumentBuilder literalArgumentBuilder, GameRules.RuleKey> key) { + LiteralCommandNode ruleNode = literal(key.getName()).build(); + + for (E supportedValue : this.supportedValues) { + ruleNode.addChild( + literal(supportedValue.toString()) + .executes(context -> EnumRuleCommand.executeEnumSet(context, supportedValue.ordinal(), key)) + .build() + ); + } + + literalArgumentBuilder.then(ruleNode); + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/GameRuleRegistryImpl.java b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/GameRuleRegistryImpl.java new file mode 100644 index 0000000..b1ac2a1 --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/GameRuleRegistryImpl.java @@ -0,0 +1,22 @@ +package io.github.fablabsmc.fablabs.impl.gamerule; + +import io.github.fablabsmc.fablabs.api.gamerule.v1.GameRuleRegistry; +import io.github.fablabsmc.fablabs.mixin.gamerule.GameRulesAccessor; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import net.minecraft.util.Identifier; +import net.minecraft.world.GameRules; + +public class GameRuleRegistryImpl implements GameRuleRegistry { + public static final GameRuleRegistryImpl INSTANCE = new GameRuleRegistryImpl(); + public static final Logger LOGGER = LogManager.getLogger(GameRuleRegistry.class); + + private GameRuleRegistryImpl() { + } + + @Override + public > GameRules.RuleKey register(Identifier id, GameRules.RuleType type) { + return GameRulesAccessor.invokeRegister(id.toString(), type); + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleCommand.java b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleCommand.java new file mode 100644 index 0000000..75ebef0 --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleCommand.java @@ -0,0 +1,24 @@ +package io.github.fablabsmc.fablabs.impl.gamerule; + +import static net.minecraft.server.command.CommandManager.literal; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.LiteralRule; +import io.github.fablabsmc.fablabs.mixin.gamerule.GameRuleCommandAccessor; + +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.GameRules; + +public final class LiteralRuleCommand { + public static > void register(LiteralArgumentBuilder literalArgumentBuilder, GameRules.RuleKey key, LiteralRuleType type) { + literalArgumentBuilder.then(literal(key.getName()) + .executes(context -> { + // We can use the vanilla query method + return GameRuleCommandAccessor.invokeExecuteQuery(context.getSource(), key); + } + )); + + // The LiteralRuleType handles the executeSet + type.register(literalArgumentBuilder, key); + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleType.java b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleType.java new file mode 100644 index 0000000..07b5bcf --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleType.java @@ -0,0 +1,28 @@ +package io.github.fablabsmc.fablabs.impl.gamerule; + +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.LiteralRule; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.GameRules; + +public abstract class LiteralRuleType> extends GameRules.RuleType { + public LiteralRuleType(Supplier> argumentType, Function, T> ruleFactory, BiConsumer changeCallback) { + super(argumentType, ruleFactory, changeCallback); + } + + @Override + @Deprecated + public final RequiredArgumentBuilder argument(String name) { + return super.argument(name); + } + + public abstract void register(LiteralArgumentBuilder literalArgumentBuilder, GameRules.RuleKey key); +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/RuleFactoryImpl.java b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/RuleFactoryImpl.java new file mode 100644 index 0000000..1911b0d --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/RuleFactoryImpl.java @@ -0,0 +1,139 @@ +package io.github.fablabsmc.fablabs.impl.gamerule; + +import java.util.function.BiConsumer; + +import com.mojang.brigadier.arguments.DoubleArgumentType; +import com.mojang.brigadier.arguments.FloatArgumentType; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import io.github.fablabsmc.fablabs.api.gamerule.v1.RuleFactory; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.DoubleRule; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.EnumRule; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.FloatRule; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.StringRule; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.TextRule; +import io.github.fablabsmc.fablabs.mixin.gamerule.GameRules$BooleanRuleAccessor; +import io.github.fablabsmc.fablabs.mixin.gamerule.GameRules$IntRuleAccessor; + +import net.minecraft.command.arguments.TextArgumentType; +import net.minecraft.server.MinecraftServer; +import net.minecraft.text.Text; +import net.minecraft.world.GameRules; + +public class RuleFactoryImpl implements RuleFactory { + public static final RuleFactoryImpl INSTANCE = new RuleFactoryImpl(); + + private RuleFactoryImpl() { + } + + @Override + public GameRules.RuleType createBooleanType(boolean defaultValue, BiConsumer notifier) { + return GameRules$BooleanRuleAccessor.invokeCreate(defaultValue, notifier); + } + + @Override + public GameRules.RuleType createIntType(int defaultValue, BiConsumer notifier) { + return GameRules$IntRuleAccessor.invokeCreate(defaultValue, notifier); + } + + @Override + public GameRules.RuleType createBoundedIntType(int defaultValue, int lowerBound, int upperBound, BiConsumer notifier) { + // fixme: use Invoker when issue is fixed: https://github.com/FabricMC/fabric-loom/issues/193 + return new GameRules.RuleType<>( + //return GameRules$RuleTypeAccessor.invokeNew( + () -> IntegerArgumentType.integer(lowerBound, upperBound), + type -> new GameRules.IntRule(type, defaultValue), + notifier + ); + } + + @Override + public GameRules.RuleType createDoubleType(double defaultValue, BiConsumer notifier) { + // fixme: use Invoker when issue is fixed: https://github.com/FabricMC/fabric-loom/issues/193 + return new GameRules.RuleType<>( + //return GameRules$RuleTypeAccessor.invokeNew( + DoubleArgumentType::doubleArg, + type -> new DoubleRule(type, defaultValue), + notifier + ); + } + + @Override + public GameRules.RuleType createBoundedDoubleType(double defaultValue, double lowerBound, double upperBound, BiConsumer notifier) { + // fixme: use Invoker when issue is fixed: https://github.com/FabricMC/fabric-loom/issues/193 + return new GameRules.RuleType<>( + //return GameRules$RuleTypeAccessor.invokeNew( + () -> DoubleArgumentType.doubleArg(lowerBound, upperBound), + type -> new DoubleRule(type, defaultValue), + notifier + ); + } + + @Override + public GameRules.RuleType createFloatType(float defaultValue, BiConsumer notifier) { + // fixme: use Invoker when issue is fixed: https://github.com/FabricMC/fabric-loom/issues/193 + return new GameRules.RuleType<>( + //return GameRules$RuleTypeAccessor.invokeNew( + FloatArgumentType::floatArg, + type -> new FloatRule(type, defaultValue), + notifier + ); + } + + @Override + public GameRules.RuleType createBoundedFloatType(float defaultValue, float lowerBound, float upperBound, BiConsumer notifier) { + // fixme: use Invoker when issue is fixed: https://github.com/FabricMC/fabric-loom/issues/193 + return new GameRules.RuleType<>( + //return GameRules$RuleTypeAccessor.invokeNew( + () -> FloatArgumentType.floatArg(lowerBound, upperBound), + type -> new FloatRule(type, defaultValue), + notifier + ); + } + + @Override + public GameRules.RuleType createTextType(Text defaultValue, BiConsumer notifier) { + // fixme: use Invoker when issue is fixed: https://github.com/FabricMC/fabric-loom/issues/193 + return new GameRules.RuleType<>( + //return GameRules$RuleTypeAccessor.invokeNew( + TextArgumentType::text, + type -> new TextRule(type, defaultValue), + notifier + ); + } + + @Override + public GameRules.RuleType createWordType(String defaultValue, BiConsumer notifier) { + // fixme: use Invoker when issue is fixed: https://github.com/FabricMC/fabric-loom/issues/193 + return new GameRules.RuleType<>( + //return GameRules$RuleTypeAccessor.invokeNew( + StringArgumentType::word, + type -> new StringRule(type, defaultValue), + notifier + ); + } + + @Override + public GameRules.RuleType createStringType(String defaultValue, BiConsumer notifier) { + // fixme: use Invoker when issue is fixed: https://github.com/FabricMC/fabric-loom/issues/193 + return new GameRules.RuleType<>( + //return GameRules$RuleTypeAccessor.invokeNew( + StringArgumentType::string, + type -> new StringRule(type, defaultValue), + notifier + ); + } + + @Override + public > GameRules.RuleType> createEnumRule(E defaultValue, E[] supportedValues, BiConsumer> notifier) { + if (supportedValues.length == 0) { + throw new IllegalArgumentException("Cannot register an enum rule where no values are supported"); + } + + return new EnumRuleType<>( + type -> new EnumRule<>(type, defaultValue, supportedValues), + notifier, + supportedValues + ); + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/test/GameRuleTest.java b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/test/GameRuleTest.java new file mode 100644 index 0000000..fe715dc --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/test/GameRuleTest.java @@ -0,0 +1,27 @@ +package io.github.fablabsmc.fablabs.impl.gamerule.test; + +import io.github.fablabsmc.fablabs.api.gamerule.v1.GameRuleRegistry; +import io.github.fablabsmc.fablabs.api.gamerule.v1.RuleFactory; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.EnumRule; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.TextRule; + +import net.minecraft.text.LiteralText; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.Direction; +import net.minecraft.world.GameRules; + +import net.fabricmc.api.ModInitializer; + +public class GameRuleTest implements ModInitializer { + public static final GameRules.RuleKey> TEST_DIR = register("test_dir", RuleFactory.INSTANCE.createEnumRule(Direction.NORTH)); + public static final GameRules.RuleKey TEST = register("test2", RuleFactory.INSTANCE.createBoundedIntType(0, 0)); + public static final GameRules.RuleKey TEXT = register("tesx", RuleFactory.INSTANCE.createTextType(new LiteralText("Yeet"))); + + @Override + public void onInitialize() { + } + + private static > GameRules.RuleKey register(String id, GameRules.RuleType type) { + return GameRuleRegistry.INSTANCE.register(new Identifier("test", id), type); + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRuleCommandAccessor.java b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRuleCommandAccessor.java new file mode 100644 index 0000000..fbebba5 --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRuleCommandAccessor.java @@ -0,0 +1,22 @@ +package io.github.fablabsmc.fablabs.mixin.gamerule; + +import com.mojang.brigadier.context.CommandContext; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.server.command.GameRuleCommand; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.GameRules; + +@Mixin(GameRuleCommand.class) +public interface GameRuleCommandAccessor { + @Invoker + static > int invokeExecuteSet(CommandContext commandContext, GameRules.RuleKey ruleKey) { + throw new AssertionError("This shouldn't happen!"); + } + + @Invoker + static > int invokeExecuteQuery(ServerCommandSource serverCommandSource, GameRules.RuleKey ruleKey) { + throw new AssertionError("This shouldn't happen!"); + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRuleCommandMixin$RuleConsumer.java b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRuleCommandMixin$RuleConsumer.java new file mode 100644 index 0000000..cb2973f --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRuleCommandMixin$RuleConsumer.java @@ -0,0 +1,30 @@ +package io.github.fablabsmc.fablabs.mixin.gamerule; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import io.github.fablabsmc.fablabs.impl.gamerule.LiteralRuleCommand; +import io.github.fablabsmc.fablabs.impl.gamerule.LiteralRuleType; +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 net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.GameRules; + +@Mixin(targets = "net/minecraft/server/command/GameRuleCommand$1") +public abstract class GameRuleCommandMixin$RuleConsumer { + @Shadow + private LiteralArgumentBuilder field_19419; + + @SuppressWarnings("UnresolvedMixinReference") + @Inject(at = @At("HEAD"), method = "accept(Lnet/minecraft/world/GameRules$RuleKey;Lnet/minecraft/world/GameRules$RuleType;)V", cancellable = true) + private > void lgb_onRegisterCommand(GameRules.RuleKey key, GameRules.RuleType type, CallbackInfo ci) { + // Check if our type is a LiteralRuleType + if (type instanceof LiteralRuleType) { + //noinspection rawtypes,unchecked + LiteralRuleCommand.register(this.field_19419, (GameRules.RuleKey) key, (LiteralRuleType) type); + ci.cancel(); + } + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$BooleanRuleAccessor.java b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$BooleanRuleAccessor.java new file mode 100644 index 0000000..632ac79 --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$BooleanRuleAccessor.java @@ -0,0 +1,17 @@ +package io.github.fablabsmc.fablabs.mixin.gamerule; + +import java.util.function.BiConsumer; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.GameRules; + +@Mixin(GameRules.BooleanRule.class) +public interface GameRules$BooleanRuleAccessor { + @Invoker + static GameRules.RuleType invokeCreate(boolean initialValue, BiConsumer changeCallback) { + throw new AssertionError("Untransformed accessor"); + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$IntRuleAccessor.java b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$IntRuleAccessor.java new file mode 100644 index 0000000..5f43faa --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$IntRuleAccessor.java @@ -0,0 +1,17 @@ +package io.github.fablabsmc.fablabs.mixin.gamerule; + +import java.util.function.BiConsumer; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.GameRules; + +@Mixin(GameRules.IntRule.class) +public interface GameRules$IntRuleAccessor { + @Invoker + static GameRules.RuleType invokeCreate(int initialValue, BiConsumer changeCallback) { + throw new AssertionError("Untransformed accessor"); + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$RuleTypeAccessor.java b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$RuleTypeAccessor.java new file mode 100644 index 0000000..a88a044 --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$RuleTypeAccessor.java @@ -0,0 +1,20 @@ +package io.github.fablabsmc.fablabs.mixin.gamerule; + +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; + +import com.mojang.brigadier.arguments.ArgumentType; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.GameRules; + +// i509VCB -> fixme: AW conflicts during compile due to mixin AP and loom: https://github.com/FabricMC/fabric-loom/issues/193 +//@Mixin(GameRules.RuleType.class) +public interface GameRules$RuleTypeAccessor { + // i509VCB -> fixme: AW conflicts during compile due to mixin AP and loom: https://github.com/FabricMC/fabric-loom/issues/193 + //@Invoker("") + static > GameRules.RuleType invokeNew(Supplier> argumentType, Function, T> ruleFactory, BiConsumer notifier) { + throw new AssertionError("Untransformed accessor"); + } +} diff --git a/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRulesAccessor.java b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRulesAccessor.java new file mode 100644 index 0000000..3bf44aa --- /dev/null +++ b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRulesAccessor.java @@ -0,0 +1,14 @@ +package io.github.fablabsmc.fablabs.mixin.gamerule; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.world.GameRules; + +@Mixin(GameRules.class) +public interface GameRulesAccessor { + @Invoker + static > GameRules.RuleKey invokeRegister(String name, GameRules.RuleType type) { + throw new AssertionError("This shouldn't happen!"); + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 6be4ac5..50b1827 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,35 +1,28 @@ { "schemaVersion": 1, - "id": "libgamerule", + "id": "${id}", "version": "${version}", - "name": "LibGamerule", - "description": "A library for creating and using gamerules", - "authors": [ - "Martmists" - ], + "name": "FabLabs ${libname} version ${libver}", + "icon": "assets/blueprint/icon.png", + "description": "An API draft for GameRules", + "license": "MIT", "contact": { - "sources": "https://dilaton.martmists.com/martmists/libgamerule" + "sources": "https://github.com/${repo}" }, - "license": "MIT", - "icon": "assets/lgr/icon.png", + "environment": "*", "entrypoints": { - "libcd": [ - "com.martmists.libgamerule.compat.libcd.GameruleTweakerEP" - ], - "main": ["com.martmists.libgamerule.Gamerule"], - "client": ["com.martmists.libgamerule.GameruleClientMod"], - "server": ["com.martmists.libgamerule.GameruleServerMod"] + "main": [ + "io.github.fablabsmc.fablabs.impl.gamerule.test.GameRuleTest" + ] }, + "accessWidener": "libgamerule.accesswidener", "mixins": [ - "lgr.mixins.json" + "mixins.${libname}.json" ], - "custom": { - "modmenu:api": true - }, "depends": { - "fabricloader": ">=0.4.0" + "fabricloader": ">=0.8.0" }, - "suggests": { - "libcd": "*" + "custom": { + "modmenu:api": true } } \ No newline at end of file diff --git a/src/main/resources/lgr.mixins.json b/src/main/resources/lgr.mixins.json deleted file mode 100644 index d63e878..0000000 --- a/src/main/resources/lgr.mixins.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "required": true, - "package": "com.martmists.libgamerule.mixin", - "compatibilityLevel": "JAVA_8", - "mixins": [ - "GameRuleCommandAccessor", - "RuleTypeAccessor", - "GameRulesAccessor", - "LevelPropertiesMixin", - "GameRulesMixin" - ], - "injectors": { - "defaultRequire": 1 - } -} \ No newline at end of file diff --git a/src/main/resources/libgamerule.accesswidener b/src/main/resources/libgamerule.accesswidener new file mode 100644 index 0000000..3542ffa --- /dev/null +++ b/src/main/resources/libgamerule.accesswidener @@ -0,0 +1,4 @@ +accessWidener v1 named +extendable method net/minecraft/world/GameRules$RuleType (Ljava/util/function/Supplier;Ljava/util/function/Function;Ljava/util/function/BiConsumer;)V +# fixme: Remove accessible issue when issue is fixed: https://github.com/FabricMC/fabric-loom/issues/193 +accessible method net/minecraft/world/GameRules$RuleType (Ljava/util/function/Supplier;Ljava/util/function/Function;Ljava/util/function/BiConsumer;)V diff --git a/src/main/resources/mixins.libgamerule.json b/src/main/resources/mixins.libgamerule.json new file mode 100644 index 0000000..1a84f4a --- /dev/null +++ b/src/main/resources/mixins.libgamerule.json @@ -0,0 +1,15 @@ +{ + "required": true, + "package": "io.github.fablabsmc.fablabs.mixin.gamerule", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "GameRuleCommandAccessor", + "GameRuleCommandMixin$RuleConsumer", + "GameRules$BooleanRuleAccessor", + "GameRules$IntRuleAccessor", + "GameRulesAccessor" + ], + "injectors": { + "defaultRequire": 1 + } +} \ No newline at end of file diff --git a/versions/1.15.2/build.gradle b/versions/1.15.2/build.gradle deleted file mode 100644 index 131e7dc..0000000 --- a/versions/1.15.2/build.gradle +++ /dev/null @@ -1 +0,0 @@ -apply from: '../common.gradle' \ No newline at end of file diff --git a/versions/1.15.2/gradle.properties b/versions/1.15.2/gradle.properties deleted file mode 100644 index 66e2259..0000000 --- a/versions/1.15.2/gradle.properties +++ /dev/null @@ -1,5 +0,0 @@ -minecraft_version=1.15.2 -yarn_mappings=1.15.2+build.14 -loader_version=0.7.8+build.184 -fabric_version=0.4.32+build.292-1.15 -libcd_version = 2.3.0+1.15.2 diff --git a/versions/1.16/build.gradle b/versions/1.16/build.gradle deleted file mode 100644 index 131e7dc..0000000 --- a/versions/1.16/build.gradle +++ /dev/null @@ -1 +0,0 @@ -apply from: '../common.gradle' \ No newline at end of file diff --git a/versions/1.16/gradle.properties b/versions/1.16/gradle.properties deleted file mode 100644 index 590e995..0000000 --- a/versions/1.16/gradle.properties +++ /dev/null @@ -1,5 +0,0 @@ -minecraft_version=20w08a -yarn_mappings=20w08a+build.5 -loader_version=0.7.8+build.184 -fabric_version=0.4.33+build.299-1.16 -libcd_version = 2.3.0+20w06a \ No newline at end of file diff --git a/versions/common.gradle b/versions/common.gradle deleted file mode 100644 index 5e7f44c..0000000 --- a/versions/common.gradle +++ /dev/null @@ -1,58 +0,0 @@ -apply plugin: 'fabric-loom' -apply plugin: 'java' - -sourceCompatibility = 1.8 -targetCompatibility = 1.8 -archivesBaseName = "${project.mod_name}-${project.mod_version}-${project.minecraft_version}" - -dependencies { - // Base dependencies - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - modCompileOnly "io.github.cottonmc:LibCD:${project.libcd_version}" -} - -repositories { - maven { - url "http://server.bbkr.space:8081/artifactory/libs-release/" - } -} - -processResources { - inputs.property "version", project.version - - from(sourceSets.main.resources.srcDirs) { - include "fabric.mod.json" - expand "version": project.version - } - - from(sourceSets.main.resources.srcDirs) { - exclude "fabric.mod.json" - } -} - -setBuildDir("../../build") - -sourceSets { - main { - java { - srcDirs = ["../../src/main/java"] - } - resources { - srcDirs = ["../../src/main/resources"] - } - } -} - -jar { - from "LICENSE" -} - -task sourcesJar(type: Jar, dependsOn: classes) { - archiveClassifier.set("sources") - from sourceSets.main.allSource -} - -jar.dependsOn sourcesJar -build.dependsOn jar