From d006160696974f189348f6a2615902b840d037da Mon Sep 17 00:00:00 2001 From: i509VCB Date: Thu, 16 Apr 2020 22:20:53 -0500 Subject: [PATCH 1/5] Not ready, just testing --- .github/workflows/gradlepublish.yml | 34 +++ .gitignore | 33 ++- LICENSE | 15 +- build.gradle | 133 ++++++++++-- checkstyle.xml | 196 ++++++++++++++++++ gradle.properties | 19 +- icon.png | Bin 0 -> 4220 bytes settings.gradle | 14 +- .../com/martmists/libgamerule/Gamerule.java | 72 ------- .../libgamerule/GameruleClientMod.java | 11 - .../libgamerule/GameruleServerMod.java | 12 -- .../libgamerule/api/FloatSupplier.java | 16 ++ .../libgamerule/api/GameRuleRegistry.java | 20 ++ .../libgamerule/api/RuleFactory.java | 130 ++++++++++++ .../libgamerule/api/rule/DoubleRule.java | 66 ++++++ .../libgamerule/api/rule/EnumRule.java | 69 ++++++ .../libgamerule/api/rule/FloatRule.java | 65 ++++++ .../libgamerule/api/rule/LiteralRule.java | 16 ++ .../libgamerule/api/rule/StringRule.java | 53 +++++ .../libgamerule/api/rule/TextRule.java | 55 +++++ .../compat/libcd/GameruleTweaker.java | 39 ---- .../compat/libcd/GameruleTweakerEP.java | 49 ----- .../libgamerule/entities/UpdateGameRules.java | 5 - .../libgamerule/entities/ValueGetter.java | 5 - .../libgamerule/impl/EnumRuleType.java | 37 ++++ .../impl/GameRuleRegistryImpl.java | 20 ++ .../libgamerule/impl/LiteralRuleCommand.java | 45 ++++ .../libgamerule/impl/LiteralRuleType.java | 26 +++ .../libgamerule/impl/RuleFactoryImpl.java | 119 +++++++++++ .../mixin/GameRuleCommandAccessor.java | 2 - .../GameRuleCommandMixin$RuleConsumer.java | 28 +++ .../mixin/GameRules$BooleanRuleAccessor.java | 16 ++ .../mixin/GameRules$IntRuleAccessor.java | 16 ++ .../libgamerule/mixin/GameRulesAccessor.java | 1 - .../libgamerule/mixin/GameRulesMixin.java | 34 --- .../mixin/LevelPropertiesMixin.java | 24 --- .../libgamerule/mixin/RuleTypeAccessor.java | 6 +- .../libgamerule/rules/BooleanRule.java | 55 ----- .../libgamerule/rules/DoubleRule.java | 68 ------ .../martmists/libgamerule/rules/EnumRule.java | 56 ----- .../martmists/libgamerule/rules/IntRule.java | 70 ------- .../libgamerule/rules/StringRule.java | 54 ----- src/main/resources/fabric.mod.json | 35 ++-- src/main/resources/libgamerule.accesswidener | 2 + ...gr.mixins.json => mixins.libgamerule.json} | 7 +- versions/1.15.2/build.gradle | 1 - versions/1.15.2/gradle.properties | 5 - versions/1.16/build.gradle | 1 - versions/1.16/gradle.properties | 5 - versions/common.gradle | 58 ------ 50 files changed, 1234 insertions(+), 684 deletions(-) create mode 100644 .github/workflows/gradlepublish.yml create mode 100644 checkstyle.xml create mode 100644 icon.png delete mode 100644 src/main/java/com/martmists/libgamerule/Gamerule.java delete mode 100644 src/main/java/com/martmists/libgamerule/GameruleClientMod.java delete mode 100644 src/main/java/com/martmists/libgamerule/GameruleServerMod.java create mode 100644 src/main/java/com/martmists/libgamerule/api/FloatSupplier.java create mode 100644 src/main/java/com/martmists/libgamerule/api/GameRuleRegistry.java create mode 100644 src/main/java/com/martmists/libgamerule/api/RuleFactory.java create mode 100644 src/main/java/com/martmists/libgamerule/api/rule/DoubleRule.java create mode 100644 src/main/java/com/martmists/libgamerule/api/rule/EnumRule.java create mode 100644 src/main/java/com/martmists/libgamerule/api/rule/FloatRule.java create mode 100644 src/main/java/com/martmists/libgamerule/api/rule/LiteralRule.java create mode 100644 src/main/java/com/martmists/libgamerule/api/rule/StringRule.java create mode 100644 src/main/java/com/martmists/libgamerule/api/rule/TextRule.java delete mode 100644 src/main/java/com/martmists/libgamerule/compat/libcd/GameruleTweaker.java delete mode 100644 src/main/java/com/martmists/libgamerule/compat/libcd/GameruleTweakerEP.java delete mode 100644 src/main/java/com/martmists/libgamerule/entities/UpdateGameRules.java delete mode 100644 src/main/java/com/martmists/libgamerule/entities/ValueGetter.java create mode 100644 src/main/java/com/martmists/libgamerule/impl/EnumRuleType.java create mode 100644 src/main/java/com/martmists/libgamerule/impl/GameRuleRegistryImpl.java create mode 100644 src/main/java/com/martmists/libgamerule/impl/LiteralRuleCommand.java create mode 100644 src/main/java/com/martmists/libgamerule/impl/LiteralRuleType.java create mode 100644 src/main/java/com/martmists/libgamerule/impl/RuleFactoryImpl.java create mode 100644 src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandMixin$RuleConsumer.java create mode 100644 src/main/java/com/martmists/libgamerule/mixin/GameRules$BooleanRuleAccessor.java create mode 100644 src/main/java/com/martmists/libgamerule/mixin/GameRules$IntRuleAccessor.java delete mode 100644 src/main/java/com/martmists/libgamerule/mixin/GameRulesMixin.java delete mode 100644 src/main/java/com/martmists/libgamerule/mixin/LevelPropertiesMixin.java delete mode 100644 src/main/java/com/martmists/libgamerule/rules/BooleanRule.java delete mode 100644 src/main/java/com/martmists/libgamerule/rules/DoubleRule.java delete mode 100644 src/main/java/com/martmists/libgamerule/rules/EnumRule.java delete mode 100644 src/main/java/com/martmists/libgamerule/rules/IntRule.java delete mode 100644 src/main/java/com/martmists/libgamerule/rules/StringRule.java create mode 100644 src/main/resources/libgamerule.accesswidener rename src/main/resources/{lgr.mixins.json => mixins.libgamerule.json} (62%) delete mode 100644 versions/1.15.2/build.gradle delete mode 100644 versions/1.15.2/gradle.properties delete mode 100644 versions/1.16/build.gradle delete mode 100644 versions/1.16/gradle.properties delete mode 100644 versions/common.gradle 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..9df8fe5 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=14 +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/icon.png b/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8cea0b66d073a8c493b61721b463937d203b765b GIT binary patch literal 4220 zcmdT`c}!Dx9RHP5L_kL}ROB$~x{XU<69h{^*_h*~feq0qAX6bL+9C?&EC?uOV;b>5 z&N)Y!$|Z+5u0oj{DlM@b0@4VhpX>X%u+PIq zYxTy}006DMUpadMpcIFER;j^n*0i>4fj3O3r^{|o$lSySVC{~*&Q9M@G6g+&lEF~S zxg({yitQ!ANh(LNznk=Y+@`kSPOBF-+=_Rv6tkdvy4ic*cKV)pb1NRp*s=MN+l^`! z&PHXY-J6{PbdAjpth>@<{wy~^+cl@no6p@@SwxItiQ=|uld35>k;pr}lPm7W5=$J2 zQ^jrxwf7x|Km`zF0zG_2`^sOVvl3s%>@ zHaai<@`|wTN%)v z<7%yON9sFsvyy}j>Mna+nZqK^w+j(Uek}9^9H4Xz%T_i#GvCUc>Eaq5Jmp{%BdPyd zCS?{+jr2d7Ex&CLSh>(H7bOmA&(ieB@y}P-ya;z_4oY|805E4P4&OImzsJ>o<^g6Y zWyimd1e5E-#CdwAGt$B9kZlQDMj%j6TiqL|j-6xYxDk9tv-Hoib+65jH0aQ<(rucG zgrZ=-jGhqMRjPGFu}zJC!5^qI(XX)lGC*KC9t!7tIS*&c!^K(Uw(qK;o720;lXt(A|ds}Ps^Mel-s zxhNmcO%hV&^X!}3>IQlc#A>6W1A{d5>e05*XDcW7_T~5%x5J4cOqo+^!w5#Q={)?6 z?BaHN8|^%7e)&ZQsedHHlT63( z0s%$Lt+K-%xgCCTlLx_vh@=e!g%ds22gTJ_dnPoJQTbi4DG3H?+SX-HQrg>?C>NQJ?n zPK=5Y%V$Z7SSZ2Uy%i@RETan+vIYo?!-8l(TUUPhVWZtM{q&F>HY;`Oyum5hLx&g8 z_xAb$zdS}8hyxsGk1gb_qC{2kgiQW=(=z!s)Gj}2R8UK5zf4?+;INp&ojrFH(pX9d z{Svl2Fh~9av=p^w?s?;_VTF8@<>l3R8LhxwJODb8!wC4Oh@h74TB*bjX4OhdqwY+@ z;xOo#X8v(8Ol~H_$S( z{T;0k62ZS{Bq>4`(J0COuNpIeSpx{au}N}YdHr43mS$UwsP?${?Pv~GP|I8DH;PiQ zn+~O&%{t_3s~ESz<2R(AGB2v0ZA4<_Z$K(z#)e>?_)v& zYeEfQH4)ur8ujZ)qwN_f1xAXdwo9eBXtFI1lWZ#+niw>ywkvxXY$6`g@lHnDZdq&Z z8$i$`!DWv!5KZb?}DOP&Kv8T{>nuZRxnc09i0DURQx_b=pM~+ki1n?dtgPRVhjYrre+(+00Tn*Gq fgLie+DN+@fc;OZ;q35t2@{qk>csLjC_CNa<#(S+f literal 0 HcmV?d00001 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/api/FloatSupplier.java b/src/main/java/com/martmists/libgamerule/api/FloatSupplier.java new file mode 100644 index 0000000..ac791c7 --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/api/FloatSupplier.java @@ -0,0 +1,16 @@ +package com.martmists.libgamerule.api; + +/** + * 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/com/martmists/libgamerule/api/GameRuleRegistry.java b/src/main/java/com/martmists/libgamerule/api/GameRuleRegistry.java new file mode 100644 index 0000000..add757e --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/api/GameRuleRegistry.java @@ -0,0 +1,20 @@ +package com.martmists.libgamerule.api; + +import com.martmists.libgamerule.impl.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/com/martmists/libgamerule/api/RuleFactory.java b/src/main/java/com/martmists/libgamerule/api/RuleFactory.java new file mode 100644 index 0000000..8cacc96 --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/api/RuleFactory.java @@ -0,0 +1,130 @@ +package com.martmists.libgamerule.api; + +import com.martmists.libgamerule.api.rule.DoubleRule; +import com.martmists.libgamerule.api.rule.EnumRule; +import com.martmists.libgamerule.api.rule.FloatRule; +import com.martmists.libgamerule.api.rule.StringRule; +import com.martmists.libgamerule.api.rule.TextRule; +import com.martmists.libgamerule.impl.RuleFactoryImpl; +import net.minecraft.server.MinecraftServer; +import net.minecraft.text.Text; +import net.minecraft.world.GameRules; + +import java.util.function.BiConsumer; + +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/com/martmists/libgamerule/api/rule/DoubleRule.java b/src/main/java/com/martmists/libgamerule/api/rule/DoubleRule.java new file mode 100644 index 0000000..b0f96c8 --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/api/rule/DoubleRule.java @@ -0,0 +1,66 @@ +package com.martmists.libgamerule.api.rule; + +import com.martmists.libgamerule.api.RuleFactory; +import com.martmists.libgamerule.impl.GameRuleRegistryImpl; +import com.mojang.brigadier.context.CommandContext; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.GameRules; + +import java.util.function.DoubleSupplier; + +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. + * @param type the rule type + */ + @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/com/martmists/libgamerule/api/rule/EnumRule.java b/src/main/java/com/martmists/libgamerule/api/rule/EnumRule.java new file mode 100644 index 0000000..964a509 --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/api/rule/EnumRule.java @@ -0,0 +1,69 @@ +package com.martmists.libgamerule.api.rule; + +import com.martmists.libgamerule.api.RuleFactory; +import net.minecraft.world.GameRules; + +import java.util.function.Supplier; + +import static com.google.common.base.Preconditions.checkNotNull; + +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. + * @param type the rule type + */ + @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 == value) { + this.value = value; + break; + } + } + + throw new IllegalArgumentException("Tried to set an unsupported value: " + value.toString()); + } + + @Override + protected void deserialize(String value) { + this.value = E.valueOf(this.classType, value); + } + + @Override + protected String serialize() { + return this.value.toString(); + } + + @Override + public int getCommandResult() { + return 0; + } + + @Override + protected EnumRule getThis() { + return this; + } + + public Class getEnumClass() { + return this.classType; + } + + @Override + public E get() { + return this.value; + } +} diff --git a/src/main/java/com/martmists/libgamerule/api/rule/FloatRule.java b/src/main/java/com/martmists/libgamerule/api/rule/FloatRule.java new file mode 100644 index 0000000..2d801a6 --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/api/rule/FloatRule.java @@ -0,0 +1,65 @@ +package com.martmists.libgamerule.api.rule; + +import com.martmists.libgamerule.api.FloatSupplier; +import com.martmists.libgamerule.api.RuleFactory; +import com.martmists.libgamerule.impl.GameRuleRegistryImpl; +import com.mojang.brigadier.context.CommandContext; +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. + * @param type the rule type + */ + @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/com/martmists/libgamerule/api/rule/LiteralRule.java b/src/main/java/com/martmists/libgamerule/api/rule/LiteralRule.java new file mode 100644 index 0000000..445c68c --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/api/rule/LiteralRule.java @@ -0,0 +1,16 @@ +package com.martmists.libgamerule.api.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 { + public 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/com/martmists/libgamerule/api/rule/StringRule.java b/src/main/java/com/martmists/libgamerule/api/rule/StringRule.java new file mode 100644 index 0000000..bd02c8c --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/api/rule/StringRule.java @@ -0,0 +1,53 @@ +package com.martmists.libgamerule.api.rule; + +import com.martmists.libgamerule.api.RuleFactory; +import com.mojang.brigadier.context.CommandContext; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.GameRules; + +import java.util.function.Supplier; + +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. + * @param type the rule type + */ + @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/com/martmists/libgamerule/api/rule/TextRule.java b/src/main/java/com/martmists/libgamerule/api/rule/TextRule.java new file mode 100644 index 0000000..72c8e78 --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/api/rule/TextRule.java @@ -0,0 +1,55 @@ +package com.martmists.libgamerule.api.rule; + +import com.martmists.libgamerule.api.RuleFactory; +import com.mojang.brigadier.context.CommandContext; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.Text; +import net.minecraft.world.GameRules; + +import java.util.function.Supplier; + +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. + * @param type the rule type + * @param defaultValue + */ + @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/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/impl/EnumRuleType.java b/src/main/java/com/martmists/libgamerule/impl/EnumRuleType.java new file mode 100644 index 0000000..1b9cdc9 --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/impl/EnumRuleType.java @@ -0,0 +1,37 @@ +package com.martmists.libgamerule.impl; + +import com.martmists.libgamerule.api.rule.EnumRule; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.tree.LiteralCommandNode; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.GameRules; + +import java.util.function.BiConsumer; +import java.util.function.Function; + +import static net.minecraft.server.command.CommandManager.literal; + +public class EnumRuleType> extends LiteralRuleType> { + private final E[] supportedValues; + + public 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 -> LiteralRuleCommand.executeEnumSet(context, supportedValue.toString(), key)) + .build() + ); + } + + literalArgumentBuilder.then(ruleNode); + } +} diff --git a/src/main/java/com/martmists/libgamerule/impl/GameRuleRegistryImpl.java b/src/main/java/com/martmists/libgamerule/impl/GameRuleRegistryImpl.java new file mode 100644 index 0000000..a4f591e --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/impl/GameRuleRegistryImpl.java @@ -0,0 +1,20 @@ +package com.martmists.libgamerule.impl; + +import com.martmists.libgamerule.api.GameRuleRegistry; +import net.minecraft.util.Identifier; +import net.minecraft.world.GameRules; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +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 null; + } +} diff --git a/src/main/java/com/martmists/libgamerule/impl/LiteralRuleCommand.java b/src/main/java/com/martmists/libgamerule/impl/LiteralRuleCommand.java new file mode 100644 index 0000000..337c5b5 --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/impl/LiteralRuleCommand.java @@ -0,0 +1,45 @@ +package com.martmists.libgamerule.impl; + +import com.martmists.libgamerule.api.rule.EnumRule; +import com.martmists.libgamerule.mixin.GameRuleCommandAccessor; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import net.minecraft.text.TranslatableText; +import net.minecraft.world.GameRules; + +import static net.minecraft.server.command.CommandManager.literal; + +public final class LiteralRuleCommand { + public static > int executeEnumSet(CommandContext context, String literal, 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); + E value; + + try { + value = E.valueOf(rule.getEnumClass(), literal); + } catch (Throwable t) { + throw new SimpleCommandExceptionType(new LiteralText(t.getMessage())).create(); + } + + rule.setValue(value); + serverCommandSource.sendFeedback(new TranslatableText("commands.gamerule.set", key.getName(), rule.toString()), true); + return rule.getCommandResult(); + } + + 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); + }) + ); + + type.register(literalArgumentBuilder, key); + } +} diff --git a/src/main/java/com/martmists/libgamerule/impl/LiteralRuleType.java b/src/main/java/com/martmists/libgamerule/impl/LiteralRuleType.java new file mode 100644 index 0000000..fd2d0e8 --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/impl/LiteralRuleType.java @@ -0,0 +1,26 @@ +package com.martmists.libgamerule.impl; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.GameRules; + +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; + +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/com/martmists/libgamerule/impl/RuleFactoryImpl.java b/src/main/java/com/martmists/libgamerule/impl/RuleFactoryImpl.java new file mode 100644 index 0000000..7adc7fd --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/impl/RuleFactoryImpl.java @@ -0,0 +1,119 @@ +package com.martmists.libgamerule.impl; + +import com.martmists.libgamerule.api.RuleFactory; +import com.martmists.libgamerule.api.rule.DoubleRule; +import com.martmists.libgamerule.api.rule.EnumRule; +import com.martmists.libgamerule.api.rule.FloatRule; +import com.martmists.libgamerule.api.rule.StringRule; +import com.martmists.libgamerule.api.rule.TextRule; +import com.martmists.libgamerule.mixin.GameRules$BooleanRuleAccessor; +import com.martmists.libgamerule.mixin.GameRules$IntRuleAccessor; +import com.martmists.libgamerule.mixin.RuleTypeAccessor; +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 net.minecraft.command.arguments.TextArgumentType; +import net.minecraft.server.MinecraftServer; +import net.minecraft.text.Text; +import net.minecraft.world.GameRules; + +import java.util.function.BiConsumer; + +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) { + return RuleTypeAccessor.invokeNew( + () -> IntegerArgumentType.integer(lowerBound, upperBound), + type -> new GameRules.IntRule(type, defaultValue), + notifier + ); + } + + @Override + public GameRules.RuleType createDoubleType(double defaultValue, BiConsumer notifier) { + return RuleTypeAccessor.invokeNew( + DoubleArgumentType::doubleArg, + type -> new DoubleRule(type, defaultValue), + notifier + ); + } + + @Override + public GameRules.RuleType createBoundedDoubleType(double defaultValue, double lowerBound, double upperBound, BiConsumer notifier) { + return RuleTypeAccessor.invokeNew( + () -> DoubleArgumentType.doubleArg(lowerBound, upperBound), + type -> new DoubleRule(type, defaultValue), + notifier + ); + } + + @Override + public GameRules.RuleType createFloatType(float defaultValue, BiConsumer notifier) { + return RuleTypeAccessor.invokeNew( + FloatArgumentType::floatArg, + type -> new FloatRule(type, defaultValue), + notifier + ); + } + + @Override + public GameRules.RuleType createBoundedFloatType(float defaultValue, float lowerBound, float upperBound, BiConsumer notifier) { + return RuleTypeAccessor.invokeNew( + () -> FloatArgumentType.floatArg(lowerBound, upperBound), + type -> new FloatRule(type, defaultValue), + notifier + ); + } + + @Override + public GameRules.RuleType createTextType(Text defaultValue, BiConsumer notifier) { + return RuleTypeAccessor.invokeNew( + TextArgumentType::text, + type -> new TextRule(type, defaultValue), + notifier + ); + } + + @Override + public GameRules.RuleType createWordType(String defaultValue, BiConsumer notifier) { + return RuleTypeAccessor.invokeNew( + StringArgumentType::word, + type -> new StringRule(type, defaultValue), + notifier + ); + } + + @Override + public GameRules.RuleType createStringType(String defaultValue, BiConsumer notifier) { + return RuleTypeAccessor.invokeNew( + StringArgumentType::string, + type -> new StringRule(type, defaultValue), + notifier + ); + } + + @Override + public > GameRules.RuleType> createEnumRule(E defaultValue, E[] supportedValues, BiConsumer> notifier) { + return new EnumRuleType<>( + type -> new EnumRule<>(type, defaultValue, supportedValues), + notifier, + supportedValues + ); + } +} diff --git a/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandAccessor.java b/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandAccessor.java index 5eef973..42ee024 100644 --- a/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandAccessor.java +++ b/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandAccessor.java @@ -10,13 +10,11 @@ @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/GameRuleCommandMixin$RuleConsumer.java b/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandMixin$RuleConsumer.java new file mode 100644 index 0000000..a2f4011 --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandMixin$RuleConsumer.java @@ -0,0 +1,28 @@ +package com.martmists.libgamerule.mixin; + +import com.martmists.libgamerule.impl.LiteralRuleCommand; +import com.martmists.libgamerule.impl.LiteralRuleType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.GameRules; +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; + +@Mixin(targets = "net/minecraft/server/command/GameRuleCommand$1") +public abstract class GameRuleCommandMixin$RuleConsumer implements GameRules.RuleTypeConsumer { + @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) { + LiteralRuleCommand.register(this.field_19419, key, (LiteralRuleType) type); + ci.cancel(); + } + } +} diff --git a/src/main/java/com/martmists/libgamerule/mixin/GameRules$BooleanRuleAccessor.java b/src/main/java/com/martmists/libgamerule/mixin/GameRules$BooleanRuleAccessor.java new file mode 100644 index 0000000..6f97b21 --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/mixin/GameRules$BooleanRuleAccessor.java @@ -0,0 +1,16 @@ +package com.martmists.libgamerule.mixin; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.GameRules; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.function.BiConsumer; + +@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/com/martmists/libgamerule/mixin/GameRules$IntRuleAccessor.java b/src/main/java/com/martmists/libgamerule/mixin/GameRules$IntRuleAccessor.java new file mode 100644 index 0000000..7fc35da --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/mixin/GameRules$IntRuleAccessor.java @@ -0,0 +1,16 @@ +package com.martmists.libgamerule.mixin; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.GameRules; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.function.BiConsumer; + +@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/com/martmists/libgamerule/mixin/GameRulesAccessor.java b/src/main/java/com/martmists/libgamerule/mixin/GameRulesAccessor.java index 4f2163c..047e7e8 100644 --- a/src/main/java/com/martmists/libgamerule/mixin/GameRulesAccessor.java +++ b/src/main/java/com/martmists/libgamerule/mixin/GameRulesAccessor.java @@ -7,7 +7,6 @@ @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 index 23f4ca8..4abd06a 100644 --- a/src/main/java/com/martmists/libgamerule/mixin/RuleTypeAccessor.java +++ b/src/main/java/com/martmists/libgamerule/mixin/RuleTypeAccessor.java @@ -1,6 +1,7 @@ package com.martmists.libgamerule.mixin; import com.mojang.brigadier.arguments.ArgumentType; +import net.minecraft.server.MinecraftServer; import net.minecraft.world.GameRules; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; @@ -12,8 +13,7 @@ @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!"); + static > GameRules.RuleType invokeNew(Supplier> argumentType, Function, T> ruleFactory, BiConsumer notifier) { + throw new AssertionError("Untransformed accessor"); } } 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/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 6be4ac5..28584ec 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,35 +1,26 @@ { "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"] }, + "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/libgamerule.accesswidener b/src/main/resources/libgamerule.accesswidener new file mode 100644 index 0000000..8c3f731 --- /dev/null +++ b/src/main/resources/libgamerule.accesswidener @@ -0,0 +1,2 @@ +accessWidener v1 named +extendable 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/lgr.mixins.json b/src/main/resources/mixins.libgamerule.json similarity index 62% rename from src/main/resources/lgr.mixins.json rename to src/main/resources/mixins.libgamerule.json index d63e878..43c7ebe 100644 --- a/src/main/resources/lgr.mixins.json +++ b/src/main/resources/mixins.libgamerule.json @@ -4,10 +4,11 @@ "compatibilityLevel": "JAVA_8", "mixins": [ "GameRuleCommandAccessor", - "RuleTypeAccessor", + "GameRuleCommandMixin$RuleConsumer", + "GameRules$BooleanRuleAccessor", + "GameRules$IntRuleAccessor", "GameRulesAccessor", - "LevelPropertiesMixin", - "GameRulesMixin" + "RuleTypeAccessor" ], "injectors": { "defaultRequire": 1 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 From d96cb82abf7a81604afd6755fc6bd7aa003ff744 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Thu, 16 Apr 2020 23:11:56 -0500 Subject: [PATCH 2/5] Allow registration of rules --- gradle/wrapper/gradle-wrapper.jar | Bin 55190 -> 52818 bytes gradle/wrapper/gradle-wrapper.properties | 6 +++--- .../impl/GameRuleRegistryImpl.java | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 87b738cbd051603d91cc39de6cb000dd98fe6b02..deedc7fa5e6310eac3148a7dd0b1f069b07364cb 100644 GIT binary patch delta 47733 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 G#s2{UCS}q9 literal 55190 zcmafaW0WS*vSoFbZQHhO+s0S6%`V%vZQJa!ZQHKus_B{g-pt%P_q|ywBQt-*Stldc z$+IJ3?^KWm27v+sf`9-50uuadKtMnL*BJ;1^6ynvR7H?hQcjE>7)art9Bu0Pcm@7C z@c%WG|JzYkP)<@zR9S^iR_sA`azaL$mTnGKnwDyMa;8yL_0^>Ba^)phg0L5rOPTbm7g*YIRLg-2^{qe^`rb!2KqS zk~5wEJtTdD?)3+}=eby3x6%i)sb+m??NHC^u=tcG8p$TzB<;FL(WrZGV&cDQb?O0GMe6PBV=V z?tTO*5_HTW$xea!nkc~Cnx#cL_rrUGWPRa6l+A{aiMY=<0@8y5OC#UcGeE#I>nWh}`#M#kIn-$A;q@u-p71b#hcSItS!IPw?>8 zvzb|?@Ahb22L(O4#2Sre&l9H(@TGT>#Py)D&eW-LNb!=S;I`ZQ{w;MaHW z#to!~TVLgho_Pm%zq@o{K3Xq?I|MVuVSl^QHnT~sHlrVxgsqD-+YD?Nz9@HA<;x2AQjxP)r6Femg+LJ-*)k%EZ}TTRw->5xOY z9#zKJqjZgC47@AFdk1$W+KhTQJKn7e>A&?@-YOy!v_(}GyV@9G#I?bsuto4JEp;5|N{orxi_?vTI4UF0HYcA( zKyGZ4<7Fk?&LZMQb6k10N%E*$gr#T&HsY4SPQ?yerqRz5c?5P$@6dlD6UQwZJ*Je9 z7n-@7!(OVdU-mg@5$D+R%gt82Lt%&n6Yr4=|q>XT%&^z_D*f*ug8N6w$`woqeS-+#RAOfSY&Rz z?1qYa5xi(7eTCrzCFJfCxc%j{J}6#)3^*VRKF;w+`|1n;Xaojr2DI{!<3CaP`#tXs z*`pBQ5k@JLKuCmovFDqh_`Q;+^@t_;SDm29 zCNSdWXbV?9;D4VcoV`FZ9Ggrr$i<&#Dx3W=8>bSQIU_%vf)#(M2Kd3=rN@^d=QAtC zI-iQ;;GMk|&A++W5#hK28W(YqN%?!yuW8(|Cf`@FOW5QbX|`97fxmV;uXvPCqxBD zJ9iI37iV)5TW1R+fV16y;6}2tt~|0J3U4E=wQh@sx{c_eu)t=4Yoz|%Vp<#)Qlh1V z0@C2ZtlT>5gdB6W)_bhXtcZS)`9A!uIOa`K04$5>3&8An+i9BD&GvZZ=7#^r=BN=k za+=Go;qr(M)B~KYAz|<^O3LJON}$Q6Yuqn8qu~+UkUKK~&iM%pB!BO49L+?AL7N7o z(OpM(C-EY753=G=WwJHE`h*lNLMNP^c^bBk@5MyP5{v7x>GNWH>QSgTe5 z!*GPkQ(lcbEs~)4ovCu!Zt&$${9$u(<4@9%@{U<-ksAqB?6F`bQ;o-mvjr)Jn7F&j$@`il1Mf+-HdBs<-`1FahTxmPMMI)@OtI&^mtijW6zGZ67O$UOv1Jj z;a3gmw~t|LjPkW3!EZ=)lLUhFzvO;Yvj9g`8hm%6u`;cuek_b-c$wS_0M4-N<@3l|88 z@V{Sd|M;4+H6guqMm4|v=C6B7mlpP(+It%0E;W`dxMOf9!jYwWj3*MRk`KpS_jx4c z=hrKBkFK;gq@;wUV2eqE3R$M+iUc+UD0iEl#-rECK+XmH9hLKrC={j@uF=f3UiceB zU5l$FF7#RKjx+6!JHMG5-!@zI-eG=a-!Bs^AFKqN_M26%cIIcSs61R$yuq@5a3c3& z4%zLs!g}+C5%`ja?F`?5-og0lv-;(^e<`r~p$x%&*89_Aye1N)9LNVk?9BwY$Y$$F^!JQAjBJvywXAesj7lTZ)rXuxv(FFNZVknJha99lN=^h`J2> zl5=~(tKwvHHvh|9-41@OV`c;Ws--PE%{7d2sLNbDp;A6_Ka6epzOSFdqb zBa0m3j~bT*q1lslHsHqaHIP%DF&-XMpCRL(v;MV#*>mB^&)a=HfLI7efblG z(@hzN`|n+oH9;qBklb=d^S0joHCsArnR1-h{*dIUThik>ot^!6YCNjg;J_i3h6Rl0ji)* zo(tQ~>xB!rUJ(nZjCA^%X;)H{@>uhR5|xBDA=d21p@iJ!cH?+%U|VSh2S4@gv`^)^ zNKD6YlVo$%b4W^}Rw>P1YJ|fTb$_(7C;hH+ z1XAMPb6*p^h8)e5nNPKfeAO}Ik+ZN_`NrADeeJOq4Ak;sD~ zTe77no{Ztdox56Xi4UE6S7wRVxJzWxKj;B%v7|FZ3cV9MdfFp7lWCi+W{}UqekdpH zdO#eoOuB3Fu!DU`ErfeoZWJbWtRXUeBzi zBTF-AI7yMC^ntG+8%mn(I6Dw}3xK8v#Ly{3w3_E?J4(Q5JBq~I>u3!CNp~Ekk&YH` z#383VO4O42NNtcGkr*K<+wYZ>@|sP?`AQcs5oqX@-EIqgK@Pmp5~p6O6qy4ml~N{D z{=jQ7k(9!CM3N3Vt|u@%ssTw~r~Z(}QvlROAkQQ?r8OQ3F0D$aGLh zny+uGnH5muJ<67Z=8uilKvGuANrg@s3Vu_lU2ajb?rIhuOd^E@l!Kl0hYIxOP1B~Q zggUmXbh$bKL~YQ#!4fos9UUVG#}HN$lIkM<1OkU@r>$7DYYe37cXYwfK@vrHwm;pg zbh(hEU|8{*d$q7LUm+x&`S@VbW*&p-sWrplWnRM|I{P;I;%U`WmYUCeJhYc|>5?&& zj}@n}w~Oo=l}iwvi7K6)osqa;M8>fRe}>^;bLBrgA;r^ZGgY@IC^ioRmnE&H4)UV5 zO{7egQ7sBAdoqGsso5q4R(4$4Tjm&&C|7Huz&5B0wXoJzZzNc5Bt)=SOI|H}+fbit z-PiF5(NHSy>4HPMrNc@SuEMDuKYMQ--G+qeUPqO_9mOsg%1EHpqoX^yNd~~kbo`cH zlV0iAkBFTn;rVb>EK^V6?T~t~3vm;csx+lUh_%ROFPy0(omy7+_wYjN!VRDtwDu^h4n|xpAMsLepm% zggvs;v8+isCW`>BckRz1MQ=l>K6k^DdT`~sDXTWQ<~+JtY;I~I>8XsAq3yXgxe>`O zZdF*{9@Z|YtS$QrVaB!8&`&^W->_O&-JXn1n&~}o3Z7FL1QE5R*W2W@=u|w~7%EeC1aRfGtJWxImfY-D3t!!nBkWM> zafu>^Lz-ONgT6ExjV4WhN!v~u{lt2-QBN&UxwnvdH|I%LS|J-D;o>@@sA62@&yew0 z)58~JSZP!(lX;da!3`d)D1+;K9!lyNlkF|n(UduR-%g>#{`pvrD^ClddhJyfL7C-(x+J+9&7EsC~^O`&}V%)Ut8^O_7YAXPDpzv8ir4 zl`d)(;imc6r16k_d^)PJZ+QPxxVJS5e^4wX9D=V2zH&wW0-p&OJe=}rX`*->XT=;_qI&)=WHkYnZx6bLoUh_)n-A}SF_ z9z7agNTM5W6}}ui=&Qs@pO5$zHsOWIbd_&%j^Ok5PJ3yUWQw*i4*iKO)_er2CDUME ztt+{Egod~W-fn^aLe)aBz)MOc_?i-stTj}~iFk7u^-gGSbU;Iem06SDP=AEw9SzuF zeZ|hKCG3MV(z_PJg0(JbqTRf4T{NUt%kz&}4S`)0I%}ZrG!jgW2GwP=WTtkWS?DOs znI9LY!dK+1_H0h+i-_~URb^M;4&AMrEO_UlDV8o?E>^3x%ZJyh$JuDMrtYL8|G3If zPf2_Qb_W+V?$#O; zydKFv*%O;Y@o_T_UAYuaqx1isMKZ^32JtgeceA$0Z@Ck0;lHbS%N5)zzAW9iz; z8tTKeK7&qw!8XVz-+pz>z-BeIzr*#r0nB^cntjQ9@Y-N0=e&ZK72vlzX>f3RT@i7@ z=z`m7jNk!9%^xD0ug%ptZnM>F;Qu$rlwo}vRGBIymPL)L|x}nan3uFUw(&N z24gdkcb7!Q56{0<+zu zEtc5WzG2xf%1<@vo$ZsuOK{v9gx^0`gw>@h>ZMLy*h+6ueoie{D#}}` zK2@6Xxq(uZaLFC%M!2}FX}ab%GQ8A0QJ?&!vaI8Gv=vMhd);6kGguDmtuOElru()) zuRk&Z{?Vp!G~F<1#s&6io1`poBqpRHyM^p;7!+L??_DzJ8s9mYFMQ0^%_3ft7g{PD zZd}8E4EV}D!>F?bzcX=2hHR_P`Xy6?FOK)mCj)Ym4s2hh z0OlOdQa@I;^-3bhB6mpw*X5=0kJv8?#XP~9){G-+0ST@1Roz1qi8PhIXp1D$XNqVG zMl>WxwT+K`SdO1RCt4FWTNy3!i?N>*-lbnn#OxFJrswgD7HjuKpWh*o@QvgF&j+CT z{55~ZsUeR1aB}lv#s_7~+9dCix!5(KR#c?K?e2B%P$fvrsZxy@GP#R#jwL{y#Ld$} z7sF>QT6m|}?V;msb?Nlohj7a5W_D$y+4O6eI;Zt$jVGymlzLKscqer9#+p2$0It&u zWY!dCeM6^B^Z;ddEmhi?8`scl=Lhi7W%2|pT6X6^%-=q90DS(hQ-%c+E*ywPvmoF(KqDoW4!*gmQIklm zk#!GLqv|cs(JRF3G?=AYY19{w@~`G3pa z@xR9S-Hquh*&5Yas*VI};(%9%PADn`kzm zeWMJVW=>>wap*9|R7n#!&&J>gq04>DTCMtj{P^d12|2wXTEKvSf?$AvnE!peqV7i4 zE>0G%CSn%WCW1yre?yi9*aFP{GvZ|R4JT}M%x_%Hztz2qw?&28l&qW<6?c6ym{f$d z5YCF+k#yEbjCN|AGi~-NcCG8MCF1!MXBFL{#7q z)HO+WW173?kuI}^Xat;Q^gb4Hi0RGyB}%|~j8>`6X4CPo+|okMbKy9PHkr58V4bX6<&ERU)QlF8%%huUz&f+dwTN|tk+C&&o@Q1RtG`}6&6;ncQuAcfHoxd5AgD7`s zXynq41Y`zRSiOY@*;&1%1z>oNcWTV|)sjLg1X8ijg1Y zbIGL0X*Sd}EXSQ2BXCKbJmlckY(@EWn~Ut2lYeuw1wg?hhj@K?XB@V_ZP`fyL~Yd3n3SyHU-RwMBr6t-QWE5TinN9VD4XVPU; zonIIR!&pGqrLQK)=#kj40Im%V@ij0&Dh0*s!lnTw+D`Dt-xmk-jmpJv$1-E-vfYL4 zqKr#}Gm}~GPE+&$PI@4ag@=M}NYi7Y&HW82Q`@Y=W&PE31D110@yy(1vddLt`P%N^ z>Yz195A%tnt~tvsSR2{m!~7HUc@x<&`lGX1nYeQUE(%sphTi>JsVqSw8xql*Ys@9B z>RIOH*rFi*C`ohwXjyeRBDt8p)-u{O+KWP;$4gg||%*u{$~yEj+Al zE(hAQRQ1k7MkCq9s4^N3ep*$h^L%2Vq?f?{+cicpS8lo)$Cb69b98au+m2J_e7nYwID0@`M9XIo1H~|eZFc8Hl!qly612ADCVpU zY8^*RTMX(CgehD{9v|^9vZ6Rab`VeZ2m*gOR)Mw~73QEBiktViBhR!_&3l$|be|d6 zupC`{g89Y|V3uxl2!6CM(RNpdtynaiJ~*DqSTq9Mh`ohZnb%^3G{k;6%n18$4nAqR zjPOrP#-^Y9;iw{J@XH9=g5J+yEVh|e=4UeY<^65`%gWtdQ=-aqSgtywM(1nKXh`R4 zzPP&7r)kv_uC7X9n=h=!Zrf<>X=B5f<9~Q>h#jYRD#CT7D~@6@RGNyO-#0iq0uHV1 zPJr2O4d_xLmg2^TmG7|dpfJ?GGa`0|YE+`2Rata9!?$j#e9KfGYuLL(*^z z!SxFA`$qm)q-YKh)WRJZ@S+-sD_1E$V?;(?^+F3tVcK6 z2fE=8hV*2mgiAbefU^uvcM?&+Y&E}vG=Iz!%jBF7iv){lyC`)*yyS~D8k+Mx|N3bm zI~L~Z$=W9&`x)JnO;8c>3LSDw!fzN#X3qi|0`sXY4?cz{*#xz!kvZ9bO=K3XbN z5KrgN=&(JbXH{Wsu9EdmQ-W`i!JWEmfI;yVTT^a-8Ch#D8xf2dtyi?7p z%#)W3n*a#ndFpd{qN|+9Jz++AJQO#-Y7Z6%*%oyEP5zs}d&kKIr`FVEY z;S}@d?UU=tCdw~EJ{b}=9x}S2iv!!8<$?d7VKDA8h{oeD#S-$DV)-vPdGY@x08n)@ zag?yLF_E#evvRTj4^CcrLvBL=fft&@HOhZ6Ng4`8ijt&h2y}fOTC~7GfJi4vpomA5 zOcOM)o_I9BKz}I`q)fu+Qnfy*W`|mY%LO>eF^a z;$)?T4F-(X#Q-m}!-k8L_rNPf`Mr<9IWu)f&dvt=EL+ESYmCvErd@8B9hd)afc(ZL94S z?rp#h&{7Ah5IJftK4VjATklo7@hm?8BX*~oBiz)jyc9FuRw!-V;Uo>p!CWpLaIQyt zAs5WN)1CCeux-qiGdmbIk8LR`gM+Qg=&Ve}w?zA6+sTL)abU=-cvU`3E?p5$Hpkxw znu0N659qR=IKnde*AEz_7z2pdi_Bh-sb3b=PdGO1Pdf_q2;+*Cx9YN7p_>rl``knY zRn%aVkcv1(W;`Mtp_DNOIECtgq%ufk-mu_<+Fu3Q17Tq4Rr(oeq)Yqk_CHA7LR@7@ zIZIDxxhS&=F2IQfusQ+Nsr%*zFK7S4g!U0y@3H^Yln|i;0a5+?RPG;ZSp6Tul>ezM z`40+516&719qT)mW|ArDSENle5hE2e8qY+zfeZoy12u&xoMgcP)4=&P-1Ib*-bAy` zlT?>w&B|ei-rCXO;sxo7*G;!)_p#%PAM-?m$JP(R%x1Hfas@KeaG%LO?R=lmkXc_MKZW}3f%KZ*rAN?HYvbu2L$ zRt_uv7~-IejlD1x;_AhwGXjB94Q=%+PbxuYzta*jw?S&%|qb=(JfJ?&6P=R7X zV%HP_!@-zO*zS}46g=J}#AMJ}rtWBr21e6hOn&tEmaM%hALH7nlm2@LP4rZ>2 zebe5aH@k!e?ij4Zwak#30|}>;`bquDQK*xmR=zc6vj0yuyC6+U=LusGnO3ZKFRpen z#pwzh!<+WBVp-!$MAc<0i~I%fW=8IO6K}bJ<-Scq>e+)951R~HKB?Mx2H}pxPHE@} zvqpq5j81_jtb_WneAvp<5kgdPKm|u2BdQx9%EzcCN&U{l+kbkhmV<1}yCTDv%&K^> zg;KCjwh*R1f_`6`si$h6`jyIKT7rTv5#k~x$mUyIw)_>Vr)D4fwIs@}{FSX|5GB1l z4vv;@oS@>Bu7~{KgUa_8eg#Lk6IDT2IY$41$*06{>>V;Bwa(-@N;ex4;D`(QK*b}{ z{#4$Hmt)FLqERgKz=3zXiV<{YX6V)lvYBr3V>N6ajeI~~hGR5Oe>W9r@sg)Na(a4- zxm%|1OKPN6^%JaD^^O~HbLSu=f`1px>RawOxLr+1b2^28U*2#h*W^=lSpSY4(@*^l z{!@9RSLG8Me&RJYLi|?$c!B0fP=4xAM4rerxX{xy{&i6=AqXueQAIBqO+pmuxy8Ib z4X^}r!NN3-upC6B#lt7&x0J;)nb9O~xjJMemm$_fHuP{DgtlU3xiW0UesTzS30L+U zQzDI3p&3dpONhd5I8-fGk^}@unluzu%nJ$9pzoO~Kk!>dLxw@M)M9?pNH1CQhvA`z zV;uacUtnBTdvT`M$1cm9`JrT3BMW!MNVBy%?@ZX%;(%(vqQAz<7I!hlDe|J3cn9=} zF7B;V4xE{Ss76s$W~%*$JviK?w8^vqCp#_G^jN0j>~Xq#Zru26e#l3H^{GCLEXI#n z?n~F-Lv#hU(bZS`EI9(xGV*jT=8R?CaK)t8oHc9XJ;UPY0Hz$XWt#QyLBaaz5+}xM zXk(!L_*PTt7gwWH*HLWC$h3Ho!SQ-(I||nn_iEC{WT3S{3V{8IN6tZ1C+DiFM{xlI zeMMk{o5;I6UvaC)@WKp9D+o?2Vd@4)Ue-nYci()hCCsKR`VD;hr9=vA!cgGL%3k^b(jADGyPi2TKr(JNh8mzlIR>n(F_hgiV(3@Ds(tjbNM7GoZ;T|3 zWzs8S`5PrA!9){jBJuX4y`f<4;>9*&NY=2Sq2Bp`M2(fox7ZhIDe!BaQUb@P(ub9D zlP8!p(AN&CwW!V&>H?yPFMJ)d5x#HKfwx;nS{Rr@oHqpktOg)%F+%1#tsPtq7zI$r zBo-Kflhq-=7_eW9B2OQv=@?|y0CKN77)N;z@tcg;heyW{wlpJ1t`Ap!O0`Xz{YHqO zI1${8Hag^r!kA<2_~bYtM=<1YzQ#GGP+q?3T7zYbIjN6Ee^V^b&9en$8FI*NIFg9G zPG$OXjT0Ku?%L7fat8Mqbl1`azf1ltmKTa(HH$Dqlav|rU{zP;Tbnk-XkGFQ6d+gi z-PXh?_kEJl+K98&OrmzgPIijB4!Pozbxd0H1;Usy!;V>Yn6&pu*zW8aYx`SC!$*ti zSn+G9p=~w6V(fZZHc>m|PPfjK6IN4(o=IFu?pC?+`UZAUTw!e`052{P=8vqT^(VeG z=psASIhCv28Y(;7;TuYAe>}BPk5Qg=8$?wZj9lj>h2kwEfF_CpK=+O6Rq9pLn4W)# zeXCKCpi~jsfqw7Taa0;!B5_C;B}e56W1s8@p*)SPzA;Fd$Slsn^=!_&!mRHV*Lmt| zBGIDPuR>CgS4%cQ4wKdEyO&Z>2aHmja;Pz+n|7(#l%^2ZLCix%>@_mbnyPEbyrHaz z>j^4SIv;ZXF-Ftzz>*t4wyq)ng8%0d;(Z_ExZ-cxwei=8{(br-`JYO(f23Wae_MqE z3@{Mlf^%M5G1SIN&en1*| zH~ANY1h3&WNsBy$G9{T=`kcxI#-X|>zLX2r*^-FUF+m0{k)n#GTG_mhG&fJfLj~K& zU~~6othMlvMm9<*SUD2?RD+R17|Z4mgR$L*R3;nBbo&Vm@39&3xIg;^aSxHS>}gwR zmzs?h8oPnNVgET&dx5^7APYx6Vv6eou07Zveyd+^V6_LzI$>ic+pxD_8s~ zC<}ucul>UH<@$KM zT4oI=62M%7qQO{}re-jTFqo9Z;rJKD5!X5$iwUsh*+kcHVhID08MB5cQD4TBWB(rI zuWc%CA}}v|iH=9gQ?D$1#Gu!y3o~p7416n54&Hif`U-cV?VrUMJyEqo_NC4#{puzU zzXEE@UppeeRlS9W*^N$zS`SBBi<@tT+<%3l@KhOy^%MWB9(A#*J~DQ;+MK*$rxo6f zcx3$3mcx{tly!q(p2DQrxcih|)0do_ZY77pyHGE#Q(0k*t!HUmmMcYFq%l$-o6%lS zDb49W-E?rQ#Hl``C3YTEdGZjFi3R<>t)+NAda(r~f1cT5jY}s7-2^&Kvo&2DLTPYP zhVVo-HLwo*vl83mtQ9)PR#VBg)FN}+*8c-p8j`LnNUU*Olm1O1Qqe62D#$CF#?HrM zy(zkX|1oF}Z=T#3XMLWDrm(|m+{1&BMxHY7X@hM_+cV$5-t!8HT(dJi6m9{ja53Yw z3f^`yb6Q;(e|#JQIz~B*=!-GbQ4nNL-NL z@^NWF_#w-Cox@h62;r^;Y`NX8cs?l^LU;5IWE~yvU8TqIHij!X8ydbLlT0gwmzS9} z@5BccG?vO;rvCs$mse1*ANi-cYE6Iauz$Fbn3#|ToAt5v7IlYnt6RMQEYLldva{~s zvr>1L##zmeoYgvIXJ#>bbuCVuEv2ZvZ8I~PQUN3wjP0UC)!U+wn|&`V*8?)` zMSCuvnuGec>QL+i1nCPGDAm@XSMIo?A9~C?g2&G8aNKjWd2pDX{qZ?04+2 zeyLw}iEd4vkCAWwa$ zbrHlEf3hfN7^1g~aW^XwldSmx1v~1z(s=1az4-wl} z`mM+G95*N*&1EP#u3}*KwNrPIgw8Kpp((rdEOO;bT1;6ea~>>sK+?!;{hpJ3rR<6UJb`O8P4@{XGgV%63_fs%cG8L zk9Fszbdo4tS$g0IWP1>t@0)E%-&9yj%Q!fiL2vcuL;90fPm}M==<>}Q)&sp@STFCY z^p!RzmN+uXGdtPJj1Y-khNyCb6Y$Vs>eZyW zPaOV=HY_T@FwAlleZCFYl@5X<<7%5DoO(7S%Lbl55?{2vIr_;SXBCbPZ(up;pC6Wx={AZL?shYOuFxLx1*>62;2rP}g`UT5+BHg(ju z&7n5QSvSyXbioB9CJTB#x;pexicV|9oaOpiJ9VK6EvKhl4^Vsa(p6cIi$*Zr0UxQ z;$MPOZnNae2Duuce~7|2MCfhNg*hZ9{+8H3?ts9C8#xGaM&sN;2lriYkn9W>&Gry! z3b(Xx1x*FhQkD-~V+s~KBfr4M_#0{`=Yrh90yj}Ph~)Nx;1Y^8<418tu!$1<3?T*~ z7Dl0P3Uok-7w0MPFQexNG1P5;y~E8zEvE49>$(f|XWtkW2Mj`udPn)pb%} zrA%wRFp*xvDgC767w!9`0vx1=q!)w!G+9(-w&p*a@WXg{?T&%;qaVcHo>7ca%KX$B z^7|KBPo<2;kM{2mRnF8vKm`9qGV%|I{y!pKm8B(q^2V;;x2r!1VJ^Zz8bWa)!-7a8 zSRf@dqEPlsj!7}oNvFFAA)75})vTJUwQ03hD$I*j6_5xbtd_JkE2`IJD_fQ;a$EkO z{fQ{~e%PKgPJsD&PyEvDmg+Qf&p*-qu!#;1k2r_(H72{^(Z)htgh@F?VIgK#_&eS- z$~(qInec>)XIkv@+{o6^DJLpAb>!d}l1DK^(l%#OdD9tKK6#|_R?-%0V!`<9Hj z3w3chDwG*SFte@>Iqwq`J4M&{aHXzyigT620+Vf$X?3RFfeTcvx_e+(&Q*z)t>c0e zpZH$1Z3X%{^_vylHVOWT6tno=l&$3 z9^eQ@TwU#%WMQaFvaYp_we%_2-9=o{+ck zF{cKJCOjpW&qKQquyp2BXCAP920dcrZ}T1@piukx_NY;%2W>@Wca%=Ch~x5Oj58Hv z;D-_ALOZBF(Mqbcqjd}P3iDbek#Dwzu`WRs`;hRIr*n0PV7vT+%Io(t}8KZ zpp?uc2eW!v28ipep0XNDPZt7H2HJ6oey|J3z!ng#1H~x_k%35P+Cp%mqXJ~cV0xdd z^4m5^K_dQ^Sg?$P`))ccV=O>C{Ds(C2WxX$LMC5vy=*44pP&)X5DOPYfqE${)hDg< z3hcG%U%HZ39=`#Ko4Uctg&@PQLf>?0^D|4J(_1*TFMOMB!Vv1_mnOq$BzXQdOGqgy zOp#LBZ!c>bPjY1NTXksZmbAl0A^Y&(%a3W-k>bE&>K?px5Cm%AT2E<&)Y?O*?d80d zgI5l~&Mve;iXm88Q+Fw7{+`PtN4G7~mJWR^z7XmYQ>uoiV!{tL)hp|= zS(M)813PM`d<501>{NqaPo6BZ^T{KBaqEVH(2^Vjeq zgeMeMpd*1tE@@);hGjuoVzF>Cj;5dNNwh40CnU+0DSKb~GEMb_# zT8Z&gz%SkHq6!;_6dQFYE`+b`v4NT7&@P>cA1Z1xmXy<2htaDhm@XXMp!g($ zw(7iFoH2}WR`UjqjaqOQ$ecNt@c|K1H1kyBArTTjLp%-M`4nzOhkfE#}dOpcd;b#suq8cPJ&bf5`6Tq>ND(l zib{VrPZ>{KuaIg}Y$W>A+nrvMg+l4)-@2jpAQ5h(Tii%Ni^-UPVg{<1KGU2EIUNGaXcEkOedJOusFT9X3%Pz$R+-+W+LlRaY-a$5r?4V zbPzgQl22IPG+N*iBRDH%l{Zh$fv9$RN1sU@Hp3m=M}{rX%y#;4(x1KR2yCO7Pzo>rw(67E{^{yUR`91nX^&MxY@FwmJJbyPAoWZ9Z zcBS$r)&ogYBn{DOtD~tIVJUiq|1foX^*F~O4hlLp-g;Y2wKLLM=?(r3GDqsPmUo*? zwKMEi*%f)C_@?(&&hk>;m07F$X7&i?DEK|jdRK=CaaNu-)pX>n3}@%byPKVkpLzBq z{+Py&!`MZ^4@-;iY`I4#6G@aWMv{^2VTH7|WF^u?3vsB|jU3LgdX$}=v7#EHRN(im zI(3q-eU$s~r=S#EWqa_2!G?b~ z<&brq1vvUTJH380=gcNntZw%7UT8tLAr-W49;9y^=>TDaTC|cKA<(gah#2M|l~j)w zY8goo28gj$n&zcNgqX1Qn6=<8?R0`FVO)g4&QtJAbW3G#D)uNeac-7cH5W#6i!%BH z=}9}-f+FrtEkkrQ?nkoMQ1o-9_b+&=&C2^h!&mWFga#MCrm85hW;)1pDt;-uvQG^D zntSB?XA*0%TIhtWDS!KcI}kp3LT>!(Nlc(lQN?k^bS8Q^GGMfo}^|%7s;#r+pybl@?KA++|FJ zr%se9(B|g*ERQU96az%@4gYrxRRxaM2*b}jNsG|0dQi;Rw{0WM0E>rko!{QYAJJKY z)|sX0N$!8d9E|kND~v|f>3YE|uiAnqbkMn)hu$if4kUkzKqoNoh8v|S>VY1EKmgO} zR$0UU2o)4i4yc1inx3}brso+sio{)gfbLaEgLahj8(_Z#4R-v) zglqwI%`dsY+589a8$Mu7#7_%kN*ekHupQ#48DIN^uhDxblDg3R1yXMr^NmkR z7J_NWCY~fhg}h!_aXJ#?wsZF$q`JH>JWQ9`jbZzOBpS`}-A$Vgkq7+|=lPx9H7QZG z8i8guMN+yc4*H*ANr$Q-3I{FQ-^;8ezWS2b8rERp9TMOLBxiG9J*g5=?h)mIm3#CGi4JSq1ohFrcrxx@`**K5%T}qbaCGldV!t zVeM)!U3vbf5FOy;(h08JnhSGxm)8Kqxr9PsMeWi=b8b|m_&^@#A3lL;bVKTBx+0v8 zLZeWAxJ~N27lsOT2b|qyp$(CqzqgW@tyy?CgwOe~^i;ZH zlL``i4r!>i#EGBNxV_P@KpYFQLz4Bdq{#zA&sc)*@7Mxsh9u%e6Ke`?5Yz1jkTdND zR8!u_yw_$weBOU}24(&^Bm|(dSJ(v(cBct}87a^X(v>nVLIr%%D8r|&)mi+iBc;B;x;rKq zd8*X`r?SZsTNCPQqoFOrUz8nZO?225Z#z(B!4mEp#ZJBzwd7jW1!`sg*?hPMJ$o`T zR?KrN6OZA1H{9pA;p0cSSu;@6->8aJm1rrO-yDJ7)lxuk#npUk7WNER1Wwnpy%u zF=t6iHzWU(L&=vVSSc^&D_eYP3TM?HN!Tgq$SYC;pSIPWW;zeNm7Pgub#yZ@7WPw#f#Kl)W4%B>)+8%gpfoH1qZ;kZ*RqfXYeGXJ_ zk>2otbp+1By`x^1V!>6k5v8NAK@T;89$`hE0{Pc@Q$KhG0jOoKk--Qx!vS~lAiypV zCIJ&6B@24`!TxhJ4_QS*S5;;Pk#!f(qIR7*(c3dN*POKtQe)QvR{O2@QsM%ujEAWEm) z+PM=G9hSR>gQ`Bv2(k}RAv2+$7qq(mU`fQ+&}*i%-RtSUAha>70?G!>?w%F(b4k!$ zvm;E!)2`I?etmSUFW7WflJ@8Nx`m_vE2HF#)_BiD#FaNT|IY@!uUbd4v$wTglIbIX zblRy5=wp)VQzsn0_;KdM%g<8@>#;E?vypTf=F?3f@SSdZ;XpX~J@l1;p#}_veWHp>@Iq_T z@^7|h;EivPYv1&u0~l9(a~>dV9Uw10QqB6Dzu1G~-l{*7IktljpK<_L8m0|7VV_!S zRiE{u97(%R-<8oYJ{molUd>vlGaE-C|^<`hppdDz<7OS13$#J zZ+)(*rZIDSt^Q$}CRk0?pqT5PN5TT`Ya{q(BUg#&nAsg6apPMhLTno!SRq1e60fl6GvpnwDD4N> z9B=RrufY8+g3_`@PRg+(+gs2(bd;5#{uTZk96CWz#{=&h9+!{_m60xJxC%r&gd_N! z>h5UzVX%_7@CUeAA1XFg_AF%(uS&^1WD*VPS^jcC!M2v@RHZML;e(H-=(4(3O&bX- zI6>usJOS+?W&^S&DL{l|>51ZvCXUKlH2XKJPXnHjs*oMkNM#ZDLx!oaM5(%^)5XaP zk6&+P16sA>vyFe9v`Cp5qnbE#r#ltR5E+O3!WnKn`56Grs2;sqr3r# zp@Zp<^q`5iq8OqOlJ`pIuyK@3zPz&iJ0Jcc`hDQ1bqos2;}O|$i#}e@ua*x5VCSx zJAp}+?Hz++tm9dh3Fvm_bO6mQo38al#>^O0g)Lh^&l82+&x)*<n7^Sw-AJo9tEzZDwyJ7L^i7|BGqHu+ea6(&7jKpBq>~V z8CJxurD)WZ{5D0?s|KMi=e7A^JVNM6sdwg@1Eg_+Bw=9j&=+KO1PG|y(mP1@5~x>d z=@c{EWU_jTSjiJl)d(>`qEJ;@iOBm}alq8;OK;p(1AdH$)I9qHNmxxUArdzBW0t+Qeyl)m3?D09770g z)hzXEOy>2_{?o%2B%k%z4d23!pZcoxyW1Ik{|m7Q1>fm4`wsRrl)~h z_=Z*zYL+EG@DV1{6@5@(Ndu!Q$l_6Qlfoz@79q)Kmsf~J7t1)tl#`MD<;1&CAA zH8;i+oBm89dTTDl{aH`cmTPTt@^K-%*sV+t4X9q0Z{A~vEEa!&rRRr=0Rbz4NFCJr zLg2u=0QK@w9XGE=6(-JgeP}G#WG|R&tfHRA3a9*zh5wNTBAD;@YYGx%#E4{C#Wlfo z%-JuW9=FA_T6mR2-Vugk1uGZvJbFvVVWT@QOWz$;?u6+CbyQsbK$>O1APk|xgnh_8 zc)s@Mw7#0^wP6qTtyNq2G#s?5j~REyoU6^lT7dpX{T-rhZWHD%dik*=EA7bIJgOVf_Ga!yC8V^tkTOEHe+JK@Fh|$kfNxO^= z#lpV^(ZQ-3!^_BhV>aXY~GC9{8%1lOJ}6vzXDvPhC>JrtXwFBC+!3a*Z-%#9}i z#<5&0LLIa{q!rEIFSFc9)>{-_2^qbOg5;_A9 ztQ))C6#hxSA{f9R3Eh^`_f${pBJNe~pIQ`tZVR^wyp}=gLK}e5_vG@w+-mp#Fu>e| z*?qBp5CQ5zu+Fi}xAs)YY1;bKG!htqR~)DB$ILN6GaChoiy%Bq@i+1ZnANC0U&D z_4k$=YP47ng+0NhuEt}6C;9-JDd8i5S>`Ml==9wHDQFOsAlmtrVwurYDw_)Ihfk35 zJDBbe!*LUpg%4n>BExWz>KIQ9vexUu^d!7rc_kg#Bf= z7TLz|l*y*3d2vi@c|pX*@ybf!+Xk|2*z$@F4K#MT8Dt4zM_EcFmNp31#7qT6(@GG? zdd;sSY9HHuDb=w&|K%sm`bYX#%UHKY%R`3aLMO?{T#EI@FNNFNO>p@?W*i0z(g2dt z{=9Ofh80Oxv&)i35AQN>TPMjR^UID-T7H5A?GI{MD_VeXZ%;uo41dVm=uT&ne2h0i zv*xI%9vPtdEK@~1&V%p1sFc2AA`9?H)gPnRdlO~URx!fiSV)j?Tf5=5F>hnO=$d$x zzaIfr*wiIc!U1K*$JO@)gP4%xp!<*DvJSv7p}(uTLUb=MSb@7_yO+IsCj^`PsxEl& zIxsi}s3L?t+p+3FXYqujGhGwTx^WXgJ1}a@Yq5mwP0PvGEr*qu7@R$9j>@-q1rz5T zriz;B^(ex?=3Th6h;7U`8u2sDlfS{0YyydK=*>-(NOm9>S_{U|eg(J~C7O zIe{|LK=Y`hXiF_%jOM8Haw3UtaE{hWdzo3BbD6ud7br4cODBtN(~Hl+odP0SSWPw;I&^m)yLw+nd#}3#z}?UIcX3=SssI}`QwY=% zAEXTODk|MqTx}2DVG<|~(CxgLyi*A{m>M@1h^wiC)4Hy>1K7@|Z&_VPJsaQoS8=ex zDL&+AZdQa>ylxhT_Q$q=60D5&%pi6+qlY3$3c(~rsITX?>b;({FhU!7HOOhSP7>bmTkC8KM%!LRGI^~y3Ug+gh!QM=+NZXznM)?L3G=4=IMvFgX3BAlyJ z`~jjA;2z+65D$j5xbv9=IWQ^&-K3Yh`vC(1Qz2h2`o$>Cej@XRGff!it$n{@WEJ^N z41qk%Wm=}mA*iwCqU_6}Id!SQd13aFER3unXaJJXIsSnxvG2(hSCP{i&QH$tL&TPx zDYJsuk+%laN&OvKb-FHK$R4dy%M7hSB*yj#-nJy?S9tVoxAuDei{s}@+pNT!vLOIC z8g`-QQW8FKp3cPsX%{)0B+x+OhZ1=L7F-jizt|{+f1Ga7%+!BXqjCjH&x|3%?UbN# zh?$I1^YokvG$qFz5ySK+Ja5=mkR&p{F}ev**rWdKMko+Gj^?Or=UH?SCg#0F(&a_y zXOh}dPv0D9l0RVedq1~jCNV=8?vZfU-Xi|nkeE->;ohG3U7z+^0+HV17~-_Mv#mV` zzvwUJJ15v5wwKPv-)i@dsEo@#WEO9zie7mdRAbgL2kjbW4&lk$vxkbq=w5mGKZK6@ zjXWctDkCRx58NJD_Q7e}HX`SiV)TZMJ}~zY6P1(LWo`;yDynY_5_L?N-P`>ALfmyl z8C$a~FDkcwtzK9m$tof>(`Vu3#6r#+v8RGy#1D2)F;vnsiL&P-c^PO)^B-4VeJteLlT@25sPa z%W~q5>YMjj!mhN})p$47VA^v$Jo6_s{!y?}`+h+VM_SN`!11`|;C;B};B&Z<@%FOG z_YQVN+zFF|q5zKab&e4GH|B;sBbKimHt;K@tCH+S{7Ry~88`si7}S)1E{21nldiu5 z_4>;XTJa~Yd$m4A9{Qbd)KUAm7XNbZ4xHbg3a8-+1uf*$1PegabbmCzgC~1WB2F(W zYj5XhVos!X!QHuZXCatkRsdEsSCc+D2?*S7a+(v%toqyxhjz|`zdrUvsxQS{J>?c& zvx*rHw^8b|v^7wq8KWVofj&VUitbm*a&RU_ln#ZFA^3AKEf<#T%8I!Lg3XEsdH(A5 zlgh&M_XEoal)i#0tcq8c%Gs6`xu;vvP2u)D9p!&XNt z!TdF_H~;`g@fNXkO-*t<9~;iEv?)Nee%hVe!aW`N%$cFJ(Dy9+Xk*odyFj72T!(b%Vo5zvCGZ%3tkt$@Wcx8BWEkefI1-~C_3y*LjlQ5%WEz9WD8i^ z2MV$BHD$gdPJV4IaV)G9CIFwiV=ca0cfXdTdK7oRf@lgyPx;_7*RRFk=?@EOb9Gcz zg~VZrzo*Snp&EE{$CWr)JZW)Gr;{B2ka6B!&?aknM-FENcl%45#y?oq9QY z3^1Y5yn&^D67Da4lI}ljDcphaEZw2;tlYuzq?uB4b9Mt6!KTW&ptxd^vF;NbX=00T z@nE1lIBGgjqs?ES#P{ZfRb6f!At51vk%<0X%d_~NL5b8UyfQMPDtfU@>ijA0NP3UU zh{lCf`Wu7cX!go`kUG`1K=7NN@SRGjUKuo<^;@GS!%iDXbJs`o6e`v3O8-+7vRkFm z)nEa$sD#-v)*Jb>&Me+YIW3PsR1)h=-Su)))>-`aRcFJG-8icomO4J@60 zw10l}BYxi{eL+Uu0xJYk-Vc~BcR49Qyyq!7)PR27D`cqGrik=?k1Of>gY7q@&d&Ds zt7&WixP`9~jjHO`Cog~RA4Q%uMg+$z^Gt&vn+d3&>Ux{_c zm|bc;k|GKbhZLr-%p_f%dq$eiZ;n^NxoS-Nu*^Nx5vm46)*)=-Bf<;X#?`YC4tLK; z?;u?shFbXeks+dJ?^o$l#tg*1NA?(1iFff@I&j^<74S!o;SWR^Xi);DM%8XiWpLi0 zQE2dL9^a36|L5qC5+&Pf0%>l&qQ&)OU4vjd)%I6{|H+pw<0(a``9w(gKD&+o$8hOC zNAiShtc}e~ob2`gyVZx59y<6Fpl*$J41VJ-H*e-yECWaDMmPQi-N8XI3 z%iI@ljc+d}_okL1CGWffeaejlxWFVDWu%e=>H)XeZ|4{HlbgC-Uvof4ISYQzZ0Um> z#Ov{k1c*VoN^f(gfiueuag)`TbjL$XVq$)aCUBL_M`5>0>6Ska^*Knk__pw{0I>jA zzh}Kzg{@PNi)fcAk7jMAdi-_RO%x#LQszDMS@_>iFoB+zJ0Q#CQJzFGa8;pHFdi`^ zxnTC`G$7Rctm3G8t8!SY`GwFi4gF|+dAk7rh^rA{NXzc%39+xSYM~($L(pJ(8Zjs* zYdN_R^%~LiGHm9|ElV4kVZGA*T$o@YY4qpJOxGHlUi*S*A(MrgQ{&xoZQo+#PuYRs zv3a$*qoe9gBqbN|y|eaH=w^LE{>kpL!;$wRahY(hhzRY;d33W)m*dfem@)>pR54Qy z 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 GameRules.RuleKey register(Identifier id, GameRules.RuleType type) { - return null; + return GameRulesAccessor.invokeRegister(id.toString(), type); } } From 51b4821753d8542593138ba6e705eaca55f48cf4 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Fri, 17 Apr 2020 00:20:51 -0500 Subject: [PATCH 3/5] Temporary workaround for loom bug --- gradle.properties | 2 +- .../libgamerule/api/GameRuleRegistry.java | 4 +- .../libgamerule/api/rule/DoubleRule.java | 3 +- .../libgamerule/api/rule/EnumRule.java | 3 +- .../libgamerule/api/rule/FloatRule.java | 3 +- .../libgamerule/api/rule/StringRule.java | 3 +- .../libgamerule/api/rule/TextRule.java | 5 +- .../arguments/EnumArgumentType.java | 80 +++++++++---------- .../libgamerule/impl/EnumRuleType.java | 4 +- .../libgamerule/impl/RuleFactoryImpl.java | 34 +++++--- .../mixin/GameRuleCommandAccessor.java | 16 ++-- .../GameRuleCommandMixin$RuleConsumer.java | 2 +- .../mixin/GameRules$RuleTypeAccessor.java | 21 +++++ .../libgamerule/mixin/GameRulesAccessor.java | 8 +- .../libgamerule/mixin/RuleTypeAccessor.java | 19 ----- src/main/resources/fabric.mod.json | 1 - src/main/resources/libgamerule.accesswidener | 2 + src/main/resources/mixins.libgamerule.json | 3 +- 18 files changed, 118 insertions(+), 95 deletions(-) create mode 100644 src/main/java/com/martmists/libgamerule/mixin/GameRules$RuleTypeAccessor.java delete mode 100644 src/main/java/com/martmists/libgamerule/mixin/RuleTypeAccessor.java diff --git a/gradle.properties b/gradle.properties index 9df8fe5..17f0e31 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ org.gradle.jvmargs=-Xmx4G # Fabric Properties # check these on https://fabricmc.net/use minecraft_version=1.15.2 -yarn_build=14 +yarn_build=15 loader_version=0.8.2+build.194 # Mod Properties diff --git a/src/main/java/com/martmists/libgamerule/api/GameRuleRegistry.java b/src/main/java/com/martmists/libgamerule/api/GameRuleRegistry.java index add757e..207dc58 100644 --- a/src/main/java/com/martmists/libgamerule/api/GameRuleRegistry.java +++ b/src/main/java/com/martmists/libgamerule/api/GameRuleRegistry.java @@ -10,9 +10,9 @@ public interface GameRuleRegistry { /** * Registers a {@link GameRules.Rule}. * - * @param id the id this rule will be named + * @param id the id this rule will be named * @param type the rule type - * @param the type of rule + * @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. */ diff --git a/src/main/java/com/martmists/libgamerule/api/rule/DoubleRule.java b/src/main/java/com/martmists/libgamerule/api/rule/DoubleRule.java index b0f96c8..824bd63 100644 --- a/src/main/java/com/martmists/libgamerule/api/rule/DoubleRule.java +++ b/src/main/java/com/martmists/libgamerule/api/rule/DoubleRule.java @@ -12,9 +12,10 @@ public class DoubleRule extends GameRules.Rule implements DoubleSupp 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. * @param type the rule type + * @deprecated Please use {@link RuleFactory} instead. */ @Deprecated public DoubleRule(GameRules.RuleType type, double value) { diff --git a/src/main/java/com/martmists/libgamerule/api/rule/EnumRule.java b/src/main/java/com/martmists/libgamerule/api/rule/EnumRule.java index 964a509..6b4b15f 100644 --- a/src/main/java/com/martmists/libgamerule/api/rule/EnumRule.java +++ b/src/main/java/com/martmists/libgamerule/api/rule/EnumRule.java @@ -13,9 +13,10 @@ public class EnumRule> extends LiteralRule> implem 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. * @param type the rule type + * @deprecated Please use {@link RuleFactory} instead. */ @Deprecated public EnumRule(GameRules.RuleType> type, E value, E[] supportedValues) { diff --git a/src/main/java/com/martmists/libgamerule/api/rule/FloatRule.java b/src/main/java/com/martmists/libgamerule/api/rule/FloatRule.java index 2d801a6..84de9b1 100644 --- a/src/main/java/com/martmists/libgamerule/api/rule/FloatRule.java +++ b/src/main/java/com/martmists/libgamerule/api/rule/FloatRule.java @@ -11,9 +11,10 @@ public class FloatRule extends GameRules.Rule implements FloatSupplie 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. * @param type the rule type + * @deprecated Please use {@link RuleFactory} instead. */ @Deprecated public FloatRule(GameRules.RuleType type, float value) { diff --git a/src/main/java/com/martmists/libgamerule/api/rule/StringRule.java b/src/main/java/com/martmists/libgamerule/api/rule/StringRule.java index bd02c8c..cdbbd6b 100644 --- a/src/main/java/com/martmists/libgamerule/api/rule/StringRule.java +++ b/src/main/java/com/martmists/libgamerule/api/rule/StringRule.java @@ -11,9 +11,10 @@ public class StringRule extends GameRules.Rule implements Supplier type, String value) { diff --git a/src/main/java/com/martmists/libgamerule/api/rule/TextRule.java b/src/main/java/com/martmists/libgamerule/api/rule/TextRule.java index 72c8e78..0f5339b 100644 --- a/src/main/java/com/martmists/libgamerule/api/rule/TextRule.java +++ b/src/main/java/com/martmists/libgamerule/api/rule/TextRule.java @@ -12,10 +12,11 @@ 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. - * @param type the rule type + * @param type the rule type * @param defaultValue + * @deprecated Please use {@link RuleFactory} instead. */ @Deprecated public TextRule(GameRules.RuleType type, Text defaultValue) { diff --git a/src/main/java/com/martmists/libgamerule/arguments/EnumArgumentType.java b/src/main/java/com/martmists/libgamerule/arguments/EnumArgumentType.java index 6aefb29..861fc0b 100644 --- a/src/main/java/com/martmists/libgamerule/arguments/EnumArgumentType.java +++ b/src/main/java/com/martmists/libgamerule/arguments/EnumArgumentType.java @@ -16,44 +16,44 @@ 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()); - } + 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/impl/EnumRuleType.java b/src/main/java/com/martmists/libgamerule/impl/EnumRuleType.java index 1b9cdc9..c689484 100644 --- a/src/main/java/com/martmists/libgamerule/impl/EnumRuleType.java +++ b/src/main/java/com/martmists/libgamerule/impl/EnumRuleType.java @@ -27,8 +27,8 @@ public void register(LiteralArgumentBuilder literalArgument for (E supportedValue : this.supportedValues) { ruleNode.addChild( literal(supportedValue.toString()) - .executes(context -> LiteralRuleCommand.executeEnumSet(context, supportedValue.toString(), key)) - .build() + .executes(context -> LiteralRuleCommand.executeEnumSet(context, supportedValue.toString(), key)) + .build() ); } diff --git a/src/main/java/com/martmists/libgamerule/impl/RuleFactoryImpl.java b/src/main/java/com/martmists/libgamerule/impl/RuleFactoryImpl.java index 7adc7fd..147b529 100644 --- a/src/main/java/com/martmists/libgamerule/impl/RuleFactoryImpl.java +++ b/src/main/java/com/martmists/libgamerule/impl/RuleFactoryImpl.java @@ -8,7 +8,7 @@ import com.martmists.libgamerule.api.rule.TextRule; import com.martmists.libgamerule.mixin.GameRules$BooleanRuleAccessor; import com.martmists.libgamerule.mixin.GameRules$IntRuleAccessor; -import com.martmists.libgamerule.mixin.RuleTypeAccessor; +import com.martmists.libgamerule.mixin.GameRules$RuleTypeAccessor; import com.mojang.brigadier.arguments.DoubleArgumentType; import com.mojang.brigadier.arguments.FloatArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType; @@ -38,7 +38,9 @@ public GameRules.RuleType createIntType(int defaultValue, BiC @Override public GameRules.RuleType createBoundedIntType(int defaultValue, int lowerBound, int upperBound, BiConsumer notifier) { - return RuleTypeAccessor.invokeNew( + // 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 @@ -47,7 +49,9 @@ public GameRules.RuleType createBoundedIntType(int defaultVal @Override public GameRules.RuleType createDoubleType(double defaultValue, BiConsumer notifier) { - return RuleTypeAccessor.invokeNew( + // 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 @@ -56,7 +60,9 @@ public GameRules.RuleType createDoubleType(double defaultValue, BiCo @Override public GameRules.RuleType createBoundedDoubleType(double defaultValue, double lowerBound, double upperBound, BiConsumer notifier) { - return RuleTypeAccessor.invokeNew( + // 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 @@ -65,7 +71,9 @@ public GameRules.RuleType createBoundedDoubleType(double defaultValu @Override public GameRules.RuleType createFloatType(float defaultValue, BiConsumer notifier) { - return RuleTypeAccessor.invokeNew( + // 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 @@ -74,7 +82,9 @@ public GameRules.RuleType createFloatType(float defaultValue, BiConsu @Override public GameRules.RuleType createBoundedFloatType(float defaultValue, float lowerBound, float upperBound, BiConsumer notifier) { - return RuleTypeAccessor.invokeNew( + // 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 @@ -83,7 +93,9 @@ public GameRules.RuleType createBoundedFloatType(float defaultValue, @Override public GameRules.RuleType createTextType(Text defaultValue, BiConsumer notifier) { - return RuleTypeAccessor.invokeNew( + // 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 @@ -92,7 +104,9 @@ public GameRules.RuleType createTextType(Text defaultValue, BiConsumer @Override public GameRules.RuleType createWordType(String defaultValue, BiConsumer notifier) { - return RuleTypeAccessor.invokeNew( + // 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 @@ -101,7 +115,9 @@ public GameRules.RuleType createWordType(String defaultValue, BiCons @Override public GameRules.RuleType createStringType(String defaultValue, BiConsumer notifier) { - return RuleTypeAccessor.invokeNew( + // 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 diff --git a/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandAccessor.java b/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandAccessor.java index 42ee024..3d7e6d9 100644 --- a/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandAccessor.java +++ b/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandAccessor.java @@ -9,13 +9,13 @@ @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 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!"); - } + @Invoker + 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/GameRuleCommandMixin$RuleConsumer.java b/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandMixin$RuleConsumer.java index a2f4011..45e520f 100644 --- a/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandMixin$RuleConsumer.java +++ b/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandMixin$RuleConsumer.java @@ -12,7 +12,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(targets = "net/minecraft/server/command/GameRuleCommand$1") -public abstract class GameRuleCommandMixin$RuleConsumer implements GameRules.RuleTypeConsumer { +public abstract class GameRuleCommandMixin$RuleConsumer { @Shadow private LiteralArgumentBuilder field_19419; diff --git a/src/main/java/com/martmists/libgamerule/mixin/GameRules$RuleTypeAccessor.java b/src/main/java/com/martmists/libgamerule/mixin/GameRules$RuleTypeAccessor.java new file mode 100644 index 0000000..9c9aa2b --- /dev/null +++ b/src/main/java/com/martmists/libgamerule/mixin/GameRules$RuleTypeAccessor.java @@ -0,0 +1,21 @@ +package com.martmists.libgamerule.mixin; + +import com.mojang.brigadier.arguments.ArgumentType; +import net.minecraft.server.MinecraftServer; +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; + +// 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/com/martmists/libgamerule/mixin/GameRulesAccessor.java b/src/main/java/com/martmists/libgamerule/mixin/GameRulesAccessor.java index 047e7e8..959f2a5 100644 --- a/src/main/java/com/martmists/libgamerule/mixin/GameRulesAccessor.java +++ b/src/main/java/com/martmists/libgamerule/mixin/GameRulesAccessor.java @@ -6,8 +6,8 @@ @Mixin(GameRules.class) public interface GameRulesAccessor { - @Invoker - static > GameRules.RuleKey invokeRegister(String name, GameRules.RuleType type) { - throw new AssertionError("This shouldn't happen!"); - } + @Invoker + 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/RuleTypeAccessor.java b/src/main/java/com/martmists/libgamerule/mixin/RuleTypeAccessor.java deleted file mode 100644 index 4abd06a..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.server.MinecraftServer; -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("") - static > GameRules.RuleType invokeNew(Supplier> argumentType, Function, T> ruleFactory, BiConsumer notifier) { - throw new AssertionError("Untransformed accessor"); - } -} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 28584ec..ac054d2 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -2,7 +2,6 @@ "schemaVersion": 1, "id": "${id}", "version": "${version}", - "name": "FabLabs ${libname} version ${libver}", "icon": "assets/blueprint/icon.png", "description": "An API draft for GameRules", diff --git a/src/main/resources/libgamerule.accesswidener b/src/main/resources/libgamerule.accesswidener index 8c3f731..3542ffa 100644 --- a/src/main/resources/libgamerule.accesswidener +++ b/src/main/resources/libgamerule.accesswidener @@ -1,2 +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 index 43c7ebe..7d69eb2 100644 --- a/src/main/resources/mixins.libgamerule.json +++ b/src/main/resources/mixins.libgamerule.json @@ -7,8 +7,7 @@ "GameRuleCommandMixin$RuleConsumer", "GameRules$BooleanRuleAccessor", "GameRules$IntRuleAccessor", - "GameRulesAccessor", - "RuleTypeAccessor" + "GameRulesAccessor" ], "injectors": { "defaultRequire": 1 From 8f28a00a992bb1aa797a53e0e9d2f910e5969ae6 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Fri, 17 Apr 2020 01:03:12 -0500 Subject: [PATCH 4/5] Workaround and checkstyle complaint --- .../api/gamerule/v1}/FloatSupplier.java | 2 +- .../api/gamerule/v1}/GameRuleRegistry.java | 5 ++-- .../fablabs/api/gamerule/v1}/RuleFactory.java | 21 ++++++++------- .../api/gamerule/v1}/rule/DoubleRule.java | 12 ++++----- .../api/gamerule/v1}/rule/EnumRule.java | 11 ++++---- .../api/gamerule/v1}/rule/FloatRule.java | 10 +++---- .../api/gamerule/v1}/rule/LiteralRule.java | 5 ++-- .../api/gamerule/v1}/rule/StringRule.java | 10 +++---- .../api/gamerule/v1}/rule/TextRule.java | 11 ++++---- .../impl/gamerule}/EnumArgumentType.java | 13 +++++----- .../fablabs/impl/gamerule}/EnumRuleType.java | 15 ++++++----- .../impl/gamerule}/GameRuleRegistryImpl.java | 11 ++++---- .../impl/gamerule}/LiteralRuleCommand.java | 15 ++++++----- .../impl/gamerule}/LiteralRuleType.java | 11 ++++---- .../impl/gamerule}/RuleFactoryImpl.java | 26 +++++++++---------- .../gamerule}/GameRuleCommandAccessor.java | 7 ++--- .../GameRuleCommandMixin$RuleConsumer.java | 11 ++++---- .../GameRules$BooleanRuleAccessor.java | 9 ++++--- .../gamerule}/GameRules$IntRuleAccessor.java | 9 ++++--- .../gamerule}/GameRules$RuleTypeAccessor.java | 13 +++++----- .../mixin/gamerule}/GameRulesAccessor.java | 5 ++-- src/main/resources/mixins.libgamerule.json | 2 +- 22 files changed, 123 insertions(+), 111 deletions(-) rename src/main/java/{com/martmists/libgamerule/api => io/github/fablabsmc/fablabs/api/gamerule/v1}/FloatSupplier.java (87%) rename src/main/java/{com/martmists/libgamerule/api => io/github/fablabsmc/fablabs/api/gamerule/v1}/GameRuleRegistry.java (82%) rename src/main/java/{com/martmists/libgamerule/api => io/github/fablabsmc/fablabs/api/gamerule/v1}/RuleFactory.java (92%) rename src/main/java/{com/martmists/libgamerule/api => io/github/fablabsmc/fablabs/api/gamerule/v1}/rule/DoubleRule.java (88%) rename src/main/java/{com/martmists/libgamerule/api => io/github/fablabsmc/fablabs/api/gamerule/v1}/rule/EnumRule.java (92%) rename src/main/java/{com/martmists/libgamerule/api => io/github/fablabsmc/fablabs/api/gamerule/v1}/rule/FloatRule.java (84%) rename src/main/java/{com/martmists/libgamerule/api => io/github/fablabsmc/fablabs/api/gamerule/v1}/rule/LiteralRule.java (79%) rename src/main/java/{com/martmists/libgamerule/api => io/github/fablabsmc/fablabs/api/gamerule/v1}/rule/StringRule.java (90%) rename src/main/java/{com/martmists/libgamerule/api => io/github/fablabsmc/fablabs/api/gamerule/v1}/rule/TextRule.java (88%) rename src/main/java/{com/martmists/libgamerule/arguments => io/github/fablabsmc/fablabs/impl/gamerule}/EnumArgumentType.java (97%) rename src/main/java/{com/martmists/libgamerule/impl => io/github/fablabsmc/fablabs/impl/gamerule}/EnumRuleType.java (91%) rename src/main/java/{com/martmists/libgamerule/impl => io/github/fablabsmc/fablabs/impl/gamerule}/GameRuleRegistryImpl.java (76%) rename src/main/java/{com/martmists/libgamerule/impl => io/github/fablabsmc/fablabs/impl/gamerule}/LiteralRuleCommand.java (89%) rename src/main/java/{com/martmists/libgamerule/impl => io/github/fablabsmc/fablabs/impl/gamerule}/LiteralRuleType.java (95%) rename src/main/java/{com/martmists/libgamerule/impl => io/github/fablabsmc/fablabs/impl/gamerule}/RuleFactoryImpl.java (89%) rename src/main/java/{com/martmists/libgamerule/mixin => io/github/fablabsmc/fablabs/mixin/gamerule}/GameRuleCommandAccessor.java (93%) rename src/main/java/{com/martmists/libgamerule/mixin => io/github/fablabsmc/fablabs/mixin/gamerule}/GameRuleCommandMixin$RuleConsumer.java (85%) rename src/main/java/{com/martmists/libgamerule/mixin => io/github/fablabsmc/fablabs/mixin/gamerule}/GameRules$BooleanRuleAccessor.java (90%) rename src/main/java/{com/martmists/libgamerule/mixin => io/github/fablabsmc/fablabs/mixin/gamerule}/GameRules$IntRuleAccessor.java (90%) rename src/main/java/{com/martmists/libgamerule/mixin => io/github/fablabsmc/fablabs/mixin/gamerule}/GameRules$RuleTypeAccessor.java (86%) rename src/main/java/{com/martmists/libgamerule/mixin => io/github/fablabsmc/fablabs/mixin/gamerule}/GameRulesAccessor.java (87%) diff --git a/src/main/java/com/martmists/libgamerule/api/FloatSupplier.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/FloatSupplier.java similarity index 87% rename from src/main/java/com/martmists/libgamerule/api/FloatSupplier.java rename to src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/FloatSupplier.java index ac791c7..9a7a99f 100644 --- a/src/main/java/com/martmists/libgamerule/api/FloatSupplier.java +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/FloatSupplier.java @@ -1,4 +1,4 @@ -package com.martmists.libgamerule.api; +package io.github.fablabsmc.fablabs.api.gamerule.v1; /** * Represents a supplier of {@code float}-valued results. This is the diff --git a/src/main/java/com/martmists/libgamerule/api/GameRuleRegistry.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/GameRuleRegistry.java similarity index 82% rename from src/main/java/com/martmists/libgamerule/api/GameRuleRegistry.java rename to src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/GameRuleRegistry.java index 207dc58..87f5489 100644 --- a/src/main/java/com/martmists/libgamerule/api/GameRuleRegistry.java +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/GameRuleRegistry.java @@ -1,6 +1,7 @@ -package com.martmists.libgamerule.api; +package io.github.fablabsmc.fablabs.api.gamerule.v1; + +import io.github.fablabsmc.fablabs.impl.gamerule.GameRuleRegistryImpl; -import com.martmists.libgamerule.impl.GameRuleRegistryImpl; import net.minecraft.util.Identifier; import net.minecraft.world.GameRules; diff --git a/src/main/java/com/martmists/libgamerule/api/RuleFactory.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/RuleFactory.java similarity index 92% rename from src/main/java/com/martmists/libgamerule/api/RuleFactory.java rename to src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/RuleFactory.java index 8cacc96..967638e 100644 --- a/src/main/java/com/martmists/libgamerule/api/RuleFactory.java +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/RuleFactory.java @@ -1,17 +1,18 @@ -package com.martmists.libgamerule.api; - -import com.martmists.libgamerule.api.rule.DoubleRule; -import com.martmists.libgamerule.api.rule.EnumRule; -import com.martmists.libgamerule.api.rule.FloatRule; -import com.martmists.libgamerule.api.rule.StringRule; -import com.martmists.libgamerule.api.rule.TextRule; -import com.martmists.libgamerule.impl.RuleFactoryImpl; +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; -import java.util.function.BiConsumer; - public interface RuleFactory { RuleFactory INSTANCE = RuleFactoryImpl.INSTANCE; diff --git a/src/main/java/com/martmists/libgamerule/api/rule/DoubleRule.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/DoubleRule.java similarity index 88% rename from src/main/java/com/martmists/libgamerule/api/rule/DoubleRule.java rename to src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/DoubleRule.java index 824bd63..5a07ee6 100644 --- a/src/main/java/com/martmists/libgamerule/api/rule/DoubleRule.java +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/DoubleRule.java @@ -1,20 +1,20 @@ -package com.martmists.libgamerule.api.rule; +package io.github.fablabsmc.fablabs.api.gamerule.v1.rule; + +import java.util.function.DoubleSupplier; -import com.martmists.libgamerule.api.RuleFactory; -import com.martmists.libgamerule.impl.GameRuleRegistryImpl; 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; -import java.util.function.DoubleSupplier; - 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? /** - * @param type the rule type * @deprecated Please use {@link RuleFactory} instead. */ @Deprecated diff --git a/src/main/java/com/martmists/libgamerule/api/rule/EnumRule.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/EnumRule.java similarity index 92% rename from src/main/java/com/martmists/libgamerule/api/rule/EnumRule.java rename to src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/EnumRule.java index 6b4b15f..c9d1db2 100644 --- a/src/main/java/com/martmists/libgamerule/api/rule/EnumRule.java +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/EnumRule.java @@ -1,11 +1,12 @@ -package com.martmists.libgamerule.api.rule; +package io.github.fablabsmc.fablabs.api.gamerule.v1.rule; -import com.martmists.libgamerule.api.RuleFactory; -import net.minecraft.world.GameRules; +import static com.google.common.base.Preconditions.checkNotNull; import java.util.function.Supplier; -import static com.google.common.base.Preconditions.checkNotNull; +import io.github.fablabsmc.fablabs.api.gamerule.v1.RuleFactory; + +import net.minecraft.world.GameRules; public class EnumRule> extends LiteralRule> implements Supplier { private final Class classType; @@ -15,7 +16,6 @@ public class EnumRule> extends LiteralRule> implem // 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? /** - * @param type the rule type * @deprecated Please use {@link RuleFactory} instead. */ @Deprecated @@ -29,6 +29,7 @@ public EnumRule(GameRules.RuleType> type, E value, E[] supportedValu // 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 == value) { this.value = value; diff --git a/src/main/java/com/martmists/libgamerule/api/rule/FloatRule.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/FloatRule.java similarity index 84% rename from src/main/java/com/martmists/libgamerule/api/rule/FloatRule.java rename to src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/FloatRule.java index 84de9b1..cf68858 100644 --- a/src/main/java/com/martmists/libgamerule/api/rule/FloatRule.java +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/FloatRule.java @@ -1,9 +1,10 @@ -package com.martmists.libgamerule.api.rule; +package io.github.fablabsmc.fablabs.api.gamerule.v1.rule; -import com.martmists.libgamerule.api.FloatSupplier; -import com.martmists.libgamerule.api.RuleFactory; -import com.martmists.libgamerule.impl.GameRuleRegistryImpl; 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; @@ -13,7 +14,6 @@ public class FloatRule extends GameRules.Rule implements FloatSupplie // 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? /** - * @param type the rule type * @deprecated Please use {@link RuleFactory} instead. */ @Deprecated diff --git a/src/main/java/com/martmists/libgamerule/api/rule/LiteralRule.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/LiteralRule.java similarity index 79% rename from src/main/java/com/martmists/libgamerule/api/rule/LiteralRule.java rename to src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/LiteralRule.java index 445c68c..42e3a11 100644 --- a/src/main/java/com/martmists/libgamerule/api/rule/LiteralRule.java +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/LiteralRule.java @@ -1,11 +1,12 @@ -package com.martmists.libgamerule.api.rule; +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 { - public LiteralRule(GameRules.RuleType type) { + protected LiteralRule(GameRules.RuleType type) { super(type); } diff --git a/src/main/java/com/martmists/libgamerule/api/rule/StringRule.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/StringRule.java similarity index 90% rename from src/main/java/com/martmists/libgamerule/api/rule/StringRule.java rename to src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/StringRule.java index cdbbd6b..73e3425 100644 --- a/src/main/java/com/martmists/libgamerule/api/rule/StringRule.java +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/StringRule.java @@ -1,19 +1,19 @@ -package com.martmists.libgamerule.api.rule; +package io.github.fablabsmc.fablabs.api.gamerule.v1.rule; + +import java.util.function.Supplier; -import com.martmists.libgamerule.api.RuleFactory; 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; -import java.util.function.Supplier; - 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? /** - * @param type the rule type * @deprecated Please use {@link RuleFactory} instead. */ @Deprecated diff --git a/src/main/java/com/martmists/libgamerule/api/rule/TextRule.java b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/TextRule.java similarity index 88% rename from src/main/java/com/martmists/libgamerule/api/rule/TextRule.java rename to src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/TextRule.java index 0f5339b..e132777 100644 --- a/src/main/java/com/martmists/libgamerule/api/rule/TextRule.java +++ b/src/main/java/io/github/fablabsmc/fablabs/api/gamerule/v1/rule/TextRule.java @@ -1,21 +1,20 @@ -package com.martmists.libgamerule.api.rule; +package io.github.fablabsmc.fablabs.api.gamerule.v1.rule; + +import java.util.function.Supplier; -import com.martmists.libgamerule.api.RuleFactory; 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; -import java.util.function.Supplier; - 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? /** - * @param type the rule type - * @param defaultValue * @deprecated Please use {@link RuleFactory} instead. */ @Deprecated diff --git a/src/main/java/com/martmists/libgamerule/arguments/EnumArgumentType.java b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumArgumentType.java similarity index 97% rename from src/main/java/com/martmists/libgamerule/arguments/EnumArgumentType.java rename to src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumArgumentType.java index 861fc0b..d845954 100644 --- a/src/main/java/com/martmists/libgamerule/arguments/EnumArgumentType.java +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumArgumentType.java @@ -1,4 +1,9 @@ -package com.martmists.libgamerule.arguments; +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; @@ -7,14 +12,10 @@ 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; diff --git a/src/main/java/com/martmists/libgamerule/impl/EnumRuleType.java b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumRuleType.java similarity index 91% rename from src/main/java/com/martmists/libgamerule/impl/EnumRuleType.java rename to src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumRuleType.java index c689484..86515db 100644 --- a/src/main/java/com/martmists/libgamerule/impl/EnumRuleType.java +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumRuleType.java @@ -1,17 +1,18 @@ -package com.martmists.libgamerule.impl; +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.martmists.libgamerule.api.rule.EnumRule; 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; -import java.util.function.BiConsumer; -import java.util.function.Function; - -import static net.minecraft.server.command.CommandManager.literal; - public class EnumRuleType> extends LiteralRuleType> { private final E[] supportedValues; diff --git a/src/main/java/com/martmists/libgamerule/impl/GameRuleRegistryImpl.java b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/GameRuleRegistryImpl.java similarity index 76% rename from src/main/java/com/martmists/libgamerule/impl/GameRuleRegistryImpl.java rename to src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/GameRuleRegistryImpl.java index b344a22..b1ac2a1 100644 --- a/src/main/java/com/martmists/libgamerule/impl/GameRuleRegistryImpl.java +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/GameRuleRegistryImpl.java @@ -1,12 +1,13 @@ -package com.martmists.libgamerule.impl; +package io.github.fablabsmc.fablabs.impl.gamerule; -import com.martmists.libgamerule.api.GameRuleRegistry; -import com.martmists.libgamerule.mixin.GameRulesAccessor; -import net.minecraft.util.Identifier; -import net.minecraft.world.GameRules; +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); diff --git a/src/main/java/com/martmists/libgamerule/impl/LiteralRuleCommand.java b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleCommand.java similarity index 89% rename from src/main/java/com/martmists/libgamerule/impl/LiteralRuleCommand.java rename to src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleCommand.java index 337c5b5..3763070 100644 --- a/src/main/java/com/martmists/libgamerule/impl/LiteralRuleCommand.java +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleCommand.java @@ -1,18 +1,19 @@ -package com.martmists.libgamerule.impl; +package io.github.fablabsmc.fablabs.impl.gamerule; + +import static net.minecraft.server.command.CommandManager.literal; -import com.martmists.libgamerule.api.rule.EnumRule; -import com.martmists.libgamerule.mixin.GameRuleCommandAccessor; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.EnumRule; +import io.github.fablabsmc.fablabs.mixin.gamerule.GameRuleCommandAccessor; + import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.LiteralText; import net.minecraft.text.TranslatableText; import net.minecraft.world.GameRules; -import static net.minecraft.server.command.CommandManager.literal; - public final class LiteralRuleCommand { public static > int executeEnumSet(CommandContext context, String literal, GameRules.RuleKey> key) throws CommandSyntaxException { // Mostly copied from vanilla, but tweaked so we can use literals @@ -37,8 +38,8 @@ public static > void register(LiteralArgumentBuilder .executes(context -> { // We can use the vanilla query method return GameRuleCommandAccessor.invokeExecuteQuery(context.getSource(), key); - }) - ); + } + )); type.register(literalArgumentBuilder, key); } diff --git a/src/main/java/com/martmists/libgamerule/impl/LiteralRuleType.java b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleType.java similarity index 95% rename from src/main/java/com/martmists/libgamerule/impl/LiteralRuleType.java rename to src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleType.java index fd2d0e8..6d70f43 100644 --- a/src/main/java/com/martmists/libgamerule/impl/LiteralRuleType.java +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleType.java @@ -1,16 +1,17 @@ -package com.martmists.libgamerule.impl; +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 net.minecraft.server.MinecraftServer; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.world.GameRules; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.Supplier; - public abstract class LiteralRuleType> extends GameRules.RuleType { public LiteralRuleType(Supplier> argumentType, Function, T> ruleFactory, BiConsumer changeCallback) { super(argumentType, ruleFactory, changeCallback); diff --git a/src/main/java/com/martmists/libgamerule/impl/RuleFactoryImpl.java b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/RuleFactoryImpl.java similarity index 89% rename from src/main/java/com/martmists/libgamerule/impl/RuleFactoryImpl.java rename to src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/RuleFactoryImpl.java index 147b529..2c7d391 100644 --- a/src/main/java/com/martmists/libgamerule/impl/RuleFactoryImpl.java +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/RuleFactoryImpl.java @@ -1,25 +1,25 @@ -package com.martmists.libgamerule.impl; - -import com.martmists.libgamerule.api.RuleFactory; -import com.martmists.libgamerule.api.rule.DoubleRule; -import com.martmists.libgamerule.api.rule.EnumRule; -import com.martmists.libgamerule.api.rule.FloatRule; -import com.martmists.libgamerule.api.rule.StringRule; -import com.martmists.libgamerule.api.rule.TextRule; -import com.martmists.libgamerule.mixin.GameRules$BooleanRuleAccessor; -import com.martmists.libgamerule.mixin.GameRules$IntRuleAccessor; -import com.martmists.libgamerule.mixin.GameRules$RuleTypeAccessor; +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; -import java.util.function.BiConsumer; - public class RuleFactoryImpl implements RuleFactory { public static final RuleFactoryImpl INSTANCE = new RuleFactoryImpl(); diff --git a/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandAccessor.java b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRuleCommandAccessor.java similarity index 93% rename from src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandAccessor.java rename to src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRuleCommandAccessor.java index 3d7e6d9..fbebba5 100644 --- a/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandAccessor.java +++ b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRuleCommandAccessor.java @@ -1,11 +1,12 @@ -package com.martmists.libgamerule.mixin; +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; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(GameRuleCommand.class) public interface GameRuleCommandAccessor { diff --git a/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandMixin$RuleConsumer.java b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRuleCommandMixin$RuleConsumer.java similarity index 85% rename from src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandMixin$RuleConsumer.java rename to src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRuleCommandMixin$RuleConsumer.java index 45e520f..88d9fde 100644 --- a/src/main/java/com/martmists/libgamerule/mixin/GameRuleCommandMixin$RuleConsumer.java +++ b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRuleCommandMixin$RuleConsumer.java @@ -1,16 +1,17 @@ -package com.martmists.libgamerule.mixin; +package io.github.fablabsmc.fablabs.mixin.gamerule; -import com.martmists.libgamerule.impl.LiteralRuleCommand; -import com.martmists.libgamerule.impl.LiteralRuleType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.world.GameRules; +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 diff --git a/src/main/java/com/martmists/libgamerule/mixin/GameRules$BooleanRuleAccessor.java b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$BooleanRuleAccessor.java similarity index 90% rename from src/main/java/com/martmists/libgamerule/mixin/GameRules$BooleanRuleAccessor.java rename to src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$BooleanRuleAccessor.java index 6f97b21..632ac79 100644 --- a/src/main/java/com/martmists/libgamerule/mixin/GameRules$BooleanRuleAccessor.java +++ b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$BooleanRuleAccessor.java @@ -1,11 +1,12 @@ -package com.martmists.libgamerule.mixin; +package io.github.fablabsmc.fablabs.mixin.gamerule; + +import java.util.function.BiConsumer; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.GameRules; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; -import java.util.function.BiConsumer; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.GameRules; @Mixin(GameRules.BooleanRule.class) public interface GameRules$BooleanRuleAccessor { diff --git a/src/main/java/com/martmists/libgamerule/mixin/GameRules$IntRuleAccessor.java b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$IntRuleAccessor.java similarity index 90% rename from src/main/java/com/martmists/libgamerule/mixin/GameRules$IntRuleAccessor.java rename to src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$IntRuleAccessor.java index 7fc35da..5f43faa 100644 --- a/src/main/java/com/martmists/libgamerule/mixin/GameRules$IntRuleAccessor.java +++ b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$IntRuleAccessor.java @@ -1,11 +1,12 @@ -package com.martmists.libgamerule.mixin; +package io.github.fablabsmc.fablabs.mixin.gamerule; + +import java.util.function.BiConsumer; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.GameRules; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; -import java.util.function.BiConsumer; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.GameRules; @Mixin(GameRules.IntRule.class) public interface GameRules$IntRuleAccessor { diff --git a/src/main/java/com/martmists/libgamerule/mixin/GameRules$RuleTypeAccessor.java b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$RuleTypeAccessor.java similarity index 86% rename from src/main/java/com/martmists/libgamerule/mixin/GameRules$RuleTypeAccessor.java rename to src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$RuleTypeAccessor.java index 9c9aa2b..a88a044 100644 --- a/src/main/java/com/martmists/libgamerule/mixin/GameRules$RuleTypeAccessor.java +++ b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRules$RuleTypeAccessor.java @@ -1,15 +1,14 @@ -package com.martmists.libgamerule.mixin; - -import com.mojang.brigadier.arguments.ArgumentType; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.GameRules; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; +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 { diff --git a/src/main/java/com/martmists/libgamerule/mixin/GameRulesAccessor.java b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRulesAccessor.java similarity index 87% rename from src/main/java/com/martmists/libgamerule/mixin/GameRulesAccessor.java rename to src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRulesAccessor.java index 959f2a5..3bf44aa 100644 --- a/src/main/java/com/martmists/libgamerule/mixin/GameRulesAccessor.java +++ b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRulesAccessor.java @@ -1,9 +1,10 @@ -package com.martmists.libgamerule.mixin; +package io.github.fablabsmc.fablabs.mixin.gamerule; -import net.minecraft.world.GameRules; 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 diff --git a/src/main/resources/mixins.libgamerule.json b/src/main/resources/mixins.libgamerule.json index 7d69eb2..1a84f4a 100644 --- a/src/main/resources/mixins.libgamerule.json +++ b/src/main/resources/mixins.libgamerule.json @@ -1,6 +1,6 @@ { "required": true, - "package": "com.martmists.libgamerule.mixin", + "package": "io.github.fablabsmc.fablabs.mixin.gamerule", "compatibilityLevel": "JAVA_8", "mixins": [ "GameRuleCommandAccessor", From 3f2a1cc9c8b1a2a1ea8e842551918eedb8c709dc Mon Sep 17 00:00:00 2001 From: i509VCB Date: Fri, 17 Apr 2020 02:13:46 -0500 Subject: [PATCH 5/5] Make enum rules use ordinals for saving. --- .../api/gamerule/v1/rule/EnumRule.java | 39 ++++++++++++++--- .../impl/gamerule/EnumRuleCommand.java | 21 ++++++++++ .../fablabs/impl/gamerule/EnumRuleType.java | 6 +-- .../impl/gamerule/LiteralRuleCommand.java | 42 +++++-------------- .../impl/gamerule/LiteralRuleType.java | 3 +- .../impl/gamerule/RuleFactoryImpl.java | 4 ++ .../impl/gamerule/test/GameRuleTest.java | 27 ++++++++++++ .../GameRuleCommandMixin$RuleConsumer.java | 3 +- src/main/resources/fabric.mod.json | 3 ++ 9 files changed, 106 insertions(+), 42 deletions(-) create mode 100644 src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumRuleCommand.java create mode 100644 src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/test/GameRuleTest.java 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 index c9d1db2..d6d76fb 100644 --- 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 @@ -5,6 +5,7 @@ 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; @@ -14,7 +15,6 @@ public class EnumRule> extends LiteralRule> implem 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. */ @@ -31,9 +31,9 @@ public void setValue(E value) throws IllegalArgumentException { checkNotNull(value); for (E supportedValue : this.supportedValues) { - if (supportedValue == value) { + if (supportedValue.equals(value)) { this.value = value; - break; + return; } } @@ -42,12 +42,36 @@ public void setValue(E value) throws IllegalArgumentException { @Override protected void deserialize(String value) { - this.value = E.valueOf(this.classType, 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 this.value.toString(); + return Integer.toString(this.value.ordinal()); } @Override @@ -64,6 +88,11 @@ 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/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 index 86515db..8379de8 100644 --- a/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumRuleType.java +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/EnumRuleType.java @@ -13,10 +13,10 @@ import net.minecraft.server.command.ServerCommandSource; import net.minecraft.world.GameRules; -public class EnumRuleType> extends LiteralRuleType> { +class EnumRuleType> extends LiteralRuleType> { private final E[] supportedValues; - public EnumRuleType(Function>, EnumRule> ruleFactory, BiConsumer> changeCallback, E[] supportedValues) { + EnumRuleType(Function>, EnumRule> ruleFactory, BiConsumer> changeCallback, E[] supportedValues) { super(null, ruleFactory, changeCallback); this.supportedValues = supportedValues; } @@ -28,7 +28,7 @@ public void register(LiteralArgumentBuilder literalArgument for (E supportedValue : this.supportedValues) { ruleNode.addChild( literal(supportedValue.toString()) - .executes(context -> LiteralRuleCommand.executeEnumSet(context, supportedValue.toString(), key)) + .executes(context -> EnumRuleCommand.executeEnumSet(context, supportedValue.ordinal(), key)) .build() ); } 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 index 3763070..75ebef0 100644 --- a/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleCommand.java +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleCommand.java @@ -3,44 +3,22 @@ import static net.minecraft.server.command.CommandManager.literal; import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import io.github.fablabsmc.fablabs.api.gamerule.v1.rule.EnumRule; +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.text.LiteralText; -import net.minecraft.text.TranslatableText; import net.minecraft.world.GameRules; public final class LiteralRuleCommand { - public static > int executeEnumSet(CommandContext context, String literal, 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); - E value; - - try { - value = E.valueOf(rule.getEnumClass(), literal); - } catch (Throwable t) { - throw new SimpleCommandExceptionType(new LiteralText(t.getMessage())).create(); - } - - rule.setValue(value); - serverCommandSource.sendFeedback(new TranslatableText("commands.gamerule.set", key.getName(), rule.toString()), true); - return rule.getCommandResult(); - } - - 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); - } - )); - + 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 index 6d70f43..07b5bcf 100644 --- a/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleType.java +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/LiteralRuleType.java @@ -7,12 +7,13 @@ 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 abstract class LiteralRuleType> extends GameRules.RuleType { public LiteralRuleType(Supplier> argumentType, Function, T> ruleFactory, BiConsumer changeCallback) { super(argumentType, ruleFactory, changeCallback); } 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 index 2c7d391..1911b0d 100644 --- a/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/RuleFactoryImpl.java +++ b/src/main/java/io/github/fablabsmc/fablabs/impl/gamerule/RuleFactoryImpl.java @@ -126,6 +126,10 @@ public GameRules.RuleType createStringType(String defaultValue, BiCo @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, 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/GameRuleCommandMixin$RuleConsumer.java b/src/main/java/io/github/fablabsmc/fablabs/mixin/gamerule/GameRuleCommandMixin$RuleConsumer.java index 88d9fde..cb2973f 100644 --- 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 @@ -22,7 +22,8 @@ public abstract class GameRuleCommandMixin$RuleConsumer { private > void lgb_onRegisterCommand(GameRules.RuleKey key, GameRules.RuleType type, CallbackInfo ci) { // Check if our type is a LiteralRuleType if (type instanceof LiteralRuleType) { - LiteralRuleCommand.register(this.field_19419, key, (LiteralRuleType) type); + //noinspection rawtypes,unchecked + LiteralRuleCommand.register(this.field_19419, (GameRules.RuleKey) key, (LiteralRuleType) type); ci.cancel(); } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index ac054d2..50b1827 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -11,6 +11,9 @@ }, "environment": "*", "entrypoints": { + "main": [ + "io.github.fablabsmc.fablabs.impl.gamerule.test.GameRuleTest" + ] }, "accessWidener": "libgamerule.accesswidener", "mixins": [