From 72611ed190c2b4d430d5dacb38bc64b4a279ae2e Mon Sep 17 00:00:00 2001 From: Westernat Date: Thu, 25 Jan 2024 21:37:35 +0800 Subject: [PATCH] 2.4.0 --- README.md | 40 +++--- gradle.properties | 2 +- .../java/org/mesdag/advjs/AdvJSPlugin.java | 9 +- .../org/mesdag/advjs/command/AdvCommand.java | 7 +- .../mesdag/advjs/configure/AdvBuilder.java | 21 +++- .../advjs/configure/AdvConfigureEvent.java | 16 +-- .../org/mesdag/advjs/configure/AdvGetter.java | 10 +- .../advjs/configure/DisplayBuilder.java | 6 +- .../advjs/mixin/AdvancementRewardsMixin.java | 12 +- .../mixin/PlayerAdvancementTrackerMixin.java | 39 +++++- .../advjs/mixin/ScreenHandlerMixin.java | 14 ++- .../mixin/ServerAdvancementLoaderMixin.java | 117 +++++++++--------- .../advjs/mixin/ServerPlayerEntityMixin.java | 18 +++ .../org/mesdag/advjs/trigger/Trigger.java | 22 ++-- .../custom/BlockDestroyedCriterion.java | 2 +- ...onditions.java => BossEventCriterion.java} | 6 +- .../trigger/custom/CriteriaTriggers.java | 10 +- .../custom/IncreasedKillScoreCriterion.java | 115 +++++++++++++++++ ...ditions.java => PlayerTouchCriterion.java} | 13 +- .../AdvRemoveFilter.java} | 45 ++++--- .../java/org/mesdag/advjs/util/Bounds.java | 48 +++++-- .../advjs/{configure => util}/Data.java | 9 +- src/main/resources/advjs.mixins.json | 5 +- .../resources/assets/advjs/lang/en_us.json | 5 +- .../resources/assets/advjs/lang/zh_cn.json | 5 +- 25 files changed, 414 insertions(+), 182 deletions(-) create mode 100644 src/main/java/org/mesdag/advjs/mixin/ServerPlayerEntityMixin.java rename src/main/java/org/mesdag/advjs/trigger/custom/{BossEventConditions.java => BossEventCriterion.java} (90%) create mode 100644 src/main/java/org/mesdag/advjs/trigger/custom/IncreasedKillScoreCriterion.java rename src/main/java/org/mesdag/advjs/trigger/custom/{PlayerTouchConditions.java => PlayerTouchCriterion.java} (70%) rename src/main/java/org/mesdag/advjs/{configure/RemoveFilter.java => util/AdvRemoveFilter.java} (64%) rename src/main/java/org/mesdag/advjs/{configure => util}/Data.java (64%) diff --git a/README.md b/README.md index 5a8fc74..94339e1 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,13 @@ Configure Advancements by KubeJS ```js ServerEvents.advancement((event) => { - const { BOUNDS, PREDICATE, TRIGGER } = event; + const { PREDICATE, TRIGGER } = event; // Define trigger const jump5times = TRIGGER.tick((triggerBuilder) => - triggerBuilder.addStat(Stats.JUMP, Stats.CUSTOM, BOUNDS.min$Integer(5))); + triggerBuilder.addStat(Stats.JUMP, Stats.CUSTOM, { min: 5 })); const bred_in_nether = TRIGGER.bredAnimals((triggerBuilder) => { - triggerBuilder.setChild(PREDICATE.entity({ + triggerBuilder.setChildByPredicate(PREDICATE.entityFromJson({ stepping_on: { dimension: "the_nether" } @@ -55,25 +55,29 @@ ServerEvents.advancement((event) => { // Check if parent done, else it will not be done .requireParentDone() }); - + // Remove an exist advancement by RemoveFilter, available filter was writen in doc. // you can also remove like this: 'event.remove("minecraft:story/lava_bucket");' event.remove({ icon: "minecraft:lava_bucket" }); - + // Modify an exist advancement event.get("minecraft:story/smelt_iron") + // Apply offset to display + .displayOffset(1, 1, true) .modifyDisplay((displayBuilder) => displayBuilder.setIcon("diamond_pickaxe")) .addChild("child2", (childBuilder) => { childBuilder .display((displayBuilder) => { displayBuilder.setTitle('A nice one!') displayBuilder.setDescription(Text.green("Good luck")) + // You can also apply offset at here + displayBuilder.offset(-1, 0) }) .criteria((criteriaBuilder) => criteriaBuilder.add("jump", jump5times)) }); - + // Lock recipe by advancement event.lock("stone_slab", "minecraft:story/smelt_iron"); }) @@ -84,16 +88,22 @@ Just use ```/reload``` # Features - Custom trigger - - blockDestroyed: triggers when the player breaks a block. - - playerTouch: triggers when the player touch an entity. - - bossEvent: triggers when the play joins a boss fight. - - More idea... + - blockDestroyed: triggers when the player breaks a block. + - playerTouch: triggers when the player touch an entity. + - bossEvent: triggers when the play joins a boss fight. + - increasedKillScore: triggers when the player killed an entity. + - More idea... - Custom reward - - addEffect: to give effect. - - More idea... -- Custom condition - - requireParentDone: check if parent done, else it will not be done - - More idea... + - addEffect: to give effect. + - More idea... +- Custom method + - displayOffset(offsetX: number, offsetY: number, modifyChildren?: boolean) + - apply offset to advancement display and its children + - requireParentDone() + - check if parent done, else it will not be done. + - requireOthersDone(requires[]: ResourceLocation...) + - check if advancements that you put in had done. + - More idea... # TODO - More non-vanilla triggers diff --git a/gradle.properties b/gradle.properties index 1824c59..5e0cf38 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ yarn_mappings=1.20.1+build.10 loader_version=0.15.3 # Mod Properties -mod_version=2001fabric-2.3.0 +mod_version=2001fabric-2.4.0 maven_group=org.mesdag.advjs archives_base_name=AdvJS diff --git a/src/main/java/org/mesdag/advjs/AdvJSPlugin.java b/src/main/java/org/mesdag/advjs/AdvJSPlugin.java index 4d91186..278c66a 100644 --- a/src/main/java/org/mesdag/advjs/AdvJSPlugin.java +++ b/src/main/java/org/mesdag/advjs/AdvJSPlugin.java @@ -7,14 +7,11 @@ import dev.latvian.mods.kubejs.util.ConsoleJS; import dev.latvian.mods.rhino.util.wrap.TypeWrappers; import org.mesdag.advjs.command.AdvCommand; -import org.mesdag.advjs.util.Bounds; -import org.mesdag.advjs.util.FrameTypeWrapper; -import org.mesdag.advjs.util.GameTypeWrapper; -import org.mesdag.advjs.util.RequirementsStrategyWrapper; +import org.mesdag.advjs.util.*; import java.nio.file.Files; -import static org.mesdag.advjs.configure.Data.*; +import static org.mesdag.advjs.util.Data.*; public class AdvJSPlugin extends KubeJSPlugin { public static boolean DEBUG; @@ -24,11 +21,13 @@ public void registerBindings(BindingsEvent event) { event.add("FrameType", FrameTypeWrapper.class); event.add("RequirementsStrategy", RequirementsStrategyWrapper.class); event.add("GameType", GameTypeWrapper.class); + event.add("Bounds", Bounds.class); } @Override public void registerTypeWrappers(ScriptType type, TypeWrappers typeWrappers) { typeWrappers.registerSimple(Bounds.class, Bounds::of); + typeWrappers.registerSimple(AdvRemoveFilter.class, AdvRemoveFilter::of); } @Override diff --git a/src/main/java/org/mesdag/advjs/command/AdvCommand.java b/src/main/java/org/mesdag/advjs/command/AdvCommand.java index 66f1007..0d426fd 100644 --- a/src/main/java/org/mesdag/advjs/command/AdvCommand.java +++ b/src/main/java/org/mesdag/advjs/command/AdvCommand.java @@ -19,7 +19,7 @@ public static void register(CommandDispatcher dispatcher, C .then(CommandManager.literal("adventure").executes(context -> run(context.getSource(), AdvJS.ADVENTURE, ADVENTURE))) .then(CommandManager.literal("nether").executes(context -> run(context.getSource(), AdvJS.NETHER, NETHER))) .then(CommandManager.literal("husbandry").executes(context -> run(context.getSource(), AdvJS.HUSBANDRY, HUSBANDRY))) - .then(CommandManager.literal("end").executes(context -> run(context.getSource(), AdvJS.END, END))) + .then(CommandManager.literal("end").executes(context -> run(context.getSource(), AdvJS.END, END))) .then(CommandManager.literal("all").executes(context -> { ServerCommandSource source = context.getSource(); run(source, AdvJS.EXAMPLE, EXAMPLE); @@ -1856,7 +1856,7 @@ function lookAtThroughSpyglass(entityType) { """; STORY = """ ServerEvents.advancement(event => { - const { PREDICATE, TRIGGER } = event; + const { TRIGGER } = event; const story = event .create("advjs:story") @@ -2160,9 +2160,10 @@ function lookAtThroughSpyglass(entityType) { .display((displayBuilder) => { displayBuilder.setTitle('A nice one!') displayBuilder.setDescription(Text.green("Good luck")) + // You can also apply offset at here + displayBuilder.offset(-1, 0) }) .criteria((criteriaBuilder) => criteriaBuilder.add("jump", jump5times)) - .displayOffset(-1, 0) }); // Lock recipe by advancement diff --git a/src/main/java/org/mesdag/advjs/configure/AdvBuilder.java b/src/main/java/org/mesdag/advjs/configure/AdvBuilder.java index 39497f1..3aa2bfd 100644 --- a/src/main/java/org/mesdag/advjs/configure/AdvBuilder.java +++ b/src/main/java/org/mesdag/advjs/configure/AdvBuilder.java @@ -15,7 +15,7 @@ import java.util.UUID; import java.util.function.Consumer; -import static org.mesdag.advjs.configure.Data.*; +import static org.mesdag.advjs.util.Data.*; public class AdvBuilder { @Nullable @@ -37,7 +37,7 @@ public AdvBuilder(@Nullable Identifier parent, String name, Identifier rootPath, this.name = name; this.rootPath = rootPath; this.warn = warn; - this.id = getSavePath(); + this.id = generateId(); } @Info("Add a nameless child to this advancement, just for test. Returns child.") @@ -89,7 +89,13 @@ public AdvBuilder sendsTelemetryEvent() { @Info("It will check if parent done. Defaults do not check.") public AdvBuilder requireParentDone() { - REQUIRE_DONE.add(id); + REQUIRE_DONE.put(id, new Identifier[0]); + return this; + } + + @Info("It will check if advancements that you put in had done.") + public AdvBuilder requireOthersDone(Identifier... requires) { + REQUIRE_DONE.put(id, requires); return this; } @@ -123,7 +129,7 @@ private void update() { return parent; } - private Identifier getSavePath() { + private Identifier generateId() { if (name.contains(":")) { return new Identifier(name); } @@ -166,13 +172,16 @@ public WarnType getWarn() { } @HideFromJS - public void setWarn(WarnType warn) { + public AdvBuilder setWarn(WarnType warn) { this.warn = warn; + return this; } public enum WarnType { NONE(Text.empty()), - NAMELESS(Text.translatable("advjs.attention.nameless")); + NAMELESS(Text.translatable("advjs.attention.nameless")), + NO_SPACE(Text.translatable("advjs.attention.no_space")), + NO_PARENT(Text.translatable("advjs.attention.no_parent")); public final Text msg; diff --git a/src/main/java/org/mesdag/advjs/configure/AdvConfigureEvent.java b/src/main/java/org/mesdag/advjs/configure/AdvConfigureEvent.java index 012e2a7..a61f2f1 100644 --- a/src/main/java/org/mesdag/advjs/configure/AdvConfigureEvent.java +++ b/src/main/java/org/mesdag/advjs/configure/AdvConfigureEvent.java @@ -1,6 +1,5 @@ package org.mesdag.advjs.configure; -import com.google.gson.JsonElement; import dev.latvian.mods.kubejs.event.EventJS; import dev.latvian.mods.kubejs.typings.Info; import dev.latvian.mods.kubejs.typings.Param; @@ -9,11 +8,12 @@ import net.minecraft.util.Identifier; import org.mesdag.advjs.predicate.Predicate; import org.mesdag.advjs.trigger.Trigger; +import org.mesdag.advjs.util.AdvRemoveFilter; import org.mesdag.advjs.util.Condition; import org.mesdag.advjs.util.Provider; -import static org.mesdag.advjs.configure.Data.FILTERS; -import static org.mesdag.advjs.configure.Data.LOCK_MAP; +import static org.mesdag.advjs.util.Data.FILTERS; +import static org.mesdag.advjs.util.Data.LOCK_MAP; public class AdvConfigureEvent extends EventJS { @Info(""" @@ -31,6 +31,9 @@ public class AdvConfigureEvent extends EventJS { @Info("Create a new advancement root") public AdvBuilder create(Identifier rootPath) { + if (rootPath.getNamespace().equals("minecraft")) { + new AdvBuilder(null, "root", rootPath, AdvBuilder.WarnType.NO_SPACE); + } return new AdvBuilder(null, "root", rootPath, AdvBuilder.WarnType.NONE); } @@ -46,10 +49,9 @@ public AdvBuilder create(Identifier rootPath) { frame: type of frame for the icon. Available value is 'challenge', 'goal' or 'task'. parent: the parent advancement path of this advancement. """) - public void remove(JsonElement jsonElement) { - RemoveFilter filter = RemoveFilter.of(jsonElement); + public void remove(AdvRemoveFilter filter) { if (filter.fail()) { - ConsoleJS.SERVER.warn("AdvJS/AdvConfigureEvent: Failed create a filter"); + ConsoleJS.SERVER.warn("AdvJS/remove: Failed create a filter"); } else { FILTERS.add(filter); } @@ -60,7 +62,7 @@ public AdvGetter get(Identifier path) { return new AdvGetter(path); } - @Info(value = "Lock recipe by advancement.", + @Info(value = "Lock recipe by advancement. It will only deny player take the result from GUI.", params = { @Param(name = "toLock"), @Param(name = "lockBy") diff --git a/src/main/java/org/mesdag/advjs/configure/AdvGetter.java b/src/main/java/org/mesdag/advjs/configure/AdvGetter.java index 76dc18a..57a5793 100644 --- a/src/main/java/org/mesdag/advjs/configure/AdvGetter.java +++ b/src/main/java/org/mesdag/advjs/configure/AdvGetter.java @@ -10,7 +10,7 @@ import java.util.UUID; import java.util.function.Consumer; -import static org.mesdag.advjs.configure.Data.*; +import static org.mesdag.advjs.util.Data.*; public class AdvGetter { private final Identifier id; @@ -77,7 +77,13 @@ private static Identifier getRootPath(Identifier savePath) { @Info("It will check if parent done. Defaults do not check.") public AdvGetter requireParentDone() { - REQUIRE_DONE.add(id); + REQUIRE_DONE.put(id, new Identifier[0]); + return this; + } + + @Info("It will check if advancements that you put in had done.") + public AdvGetter requireOthersDone(Identifier... requires) { + REQUIRE_DONE.put(id, requires); return this; } diff --git a/src/main/java/org/mesdag/advjs/configure/DisplayBuilder.java b/src/main/java/org/mesdag/advjs/configure/DisplayBuilder.java index 09bf70c..d5ff3df 100644 --- a/src/main/java/org/mesdag/advjs/configure/DisplayBuilder.java +++ b/src/main/java/org/mesdag/advjs/configure/DisplayBuilder.java @@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable; import org.mesdag.advjs.util.DisplayOffset; -import static org.mesdag.advjs.configure.Data.DISPLAY_OFFSET; +import static org.mesdag.advjs.util.Data.DISPLAY_OFFSET; public class DisplayBuilder { private ItemStack icon; @@ -104,7 +104,7 @@ public void setHidden(boolean hidden) { @Param(name = "offsetX", value = "The offset x of display."), @Param(name = "offsetY", value = "The offset y of display.") }) - public void displayOffset(float x, float y) { + public void offset(float x, float y) { DISPLAY_OFFSET.put(source, new DisplayOffset(x, y, false)); } @@ -114,7 +114,7 @@ public void displayOffset(float x, float y) { @Param(name = "offsetY", value = "The offset y of display."), @Param(name = "modifyChildren", value = "Determine should its children apply the same offset.") }) - public void displayOffset(float x, float y, boolean modifyChildren) { + public void offset(float x, float y, boolean modifyChildren) { DISPLAY_OFFSET.put(source, new DisplayOffset(x, y, modifyChildren)); } diff --git a/src/main/java/org/mesdag/advjs/mixin/AdvancementRewardsMixin.java b/src/main/java/org/mesdag/advjs/mixin/AdvancementRewardsMixin.java index 2f3830d..086bd9e 100644 --- a/src/main/java/org/mesdag/advjs/mixin/AdvancementRewardsMixin.java +++ b/src/main/java/org/mesdag/advjs/mixin/AdvancementRewardsMixin.java @@ -24,11 +24,13 @@ public abstract class AdvancementRewardsMixin implements RewardsAccessor { @Inject(method = "apply", at = @At("HEAD")) private void advJS$grant(ServerPlayerEntity serverPlayer, CallbackInfo ci) { - if (advJS$mobEffectInstances != null) { - for (StatusEffectInstance mobEffectInstance : advJS$mobEffectInstances) { - if (mobEffectInstance != null) { - serverPlayer.addStatusEffect(mobEffectInstance); - } + if (advJS$mobEffectInstances == null) { + return; + } + + for (StatusEffectInstance mobEffectInstance : advJS$mobEffectInstances) { + if (mobEffectInstance != null) { + serverPlayer.addStatusEffect(mobEffectInstance); } } } diff --git a/src/main/java/org/mesdag/advjs/mixin/PlayerAdvancementTrackerMixin.java b/src/main/java/org/mesdag/advjs/mixin/PlayerAdvancementTrackerMixin.java index e071f42..c9cb6bc 100644 --- a/src/main/java/org/mesdag/advjs/mixin/PlayerAdvancementTrackerMixin.java +++ b/src/main/java/org/mesdag/advjs/mixin/PlayerAdvancementTrackerMixin.java @@ -1,27 +1,60 @@ package org.mesdag.advjs.mixin; +import dev.latvian.mods.kubejs.util.ConsoleJS; import net.minecraft.advancement.Advancement; import net.minecraft.advancement.AdvancementProgress; import net.minecraft.advancement.PlayerAdvancementTracker; +import net.minecraft.server.ServerAdvancementLoader; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; 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; -import static org.mesdag.advjs.configure.Data.REQUIRE_DONE; +import static org.mesdag.advjs.util.Data.REQUIRE_DONE; @Mixin(PlayerAdvancementTracker.class) public abstract class PlayerAdvancementTrackerMixin { @Shadow public abstract AdvancementProgress getProgress(Advancement advancement); + @Shadow + private ServerPlayerEntity owner; + @Inject(method = "grantCriterion", at = @At("HEAD"), cancellable = true) private void advJS$checkParentDone(Advancement advancement, String criterionName, CallbackInfoReturnable cir) { - if (REQUIRE_DONE.contains(advancement.getId())) { + Identifier id = advancement.getId(); + if (!REQUIRE_DONE.containsKey(id)) { + return; + } + + Identifier[] requires = REQUIRE_DONE.get(id); + if (requires.length == 0) { Advancement parent = advancement.getParent(); - if (parent != null && !getProgress(parent).isDone()) { + if (parent == null) { + ConsoleJS.SERVER.warn("AdvJS/requireParentDone: Advancement '%s' is a root, so it can't check parent done".formatted(id)); + return; + } + + if (!getProgress(parent).isDone()) { + cir.setReturnValue(false); + } + return; + } + + ServerAdvancementLoader loader = owner.server.getAdvancementLoader(); + for (Identifier requireId : requires) { + Advancement required = loader.get(requireId); + if (required == null) { + ConsoleJS.SERVER.warn("AdvJS/requireParentDone: Advancement '%s' is not exist, so '%s' will not check it".formatted(requireId, id)); + continue; + } + + if (!getProgress(required).isDone()) { cir.setReturnValue(false); + return; } } } diff --git a/src/main/java/org/mesdag/advjs/mixin/ScreenHandlerMixin.java b/src/main/java/org/mesdag/advjs/mixin/ScreenHandlerMixin.java index 0e7d731..1e5207e 100644 --- a/src/main/java/org/mesdag/advjs/mixin/ScreenHandlerMixin.java +++ b/src/main/java/org/mesdag/advjs/mixin/ScreenHandlerMixin.java @@ -17,7 +17,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import static org.mesdag.advjs.configure.Data.LOCK_MAP; +import static org.mesdag.advjs.util.Data.LOCK_MAP; @Mixin(ScreenHandler.class) public abstract class ScreenHandlerMixin { @@ -39,11 +39,13 @@ public abstract class ScreenHandlerMixin { if (actionType == SlotActionType.PICKUP && player instanceof ServerPlayerEntity serverPlayer) { Item result = slot.getStack().getItem(); MinecraftServer server = serverPlayer.getServer(); - if (server != null && LOCK_MAP.containsKey(result)) { - Advancement advancement = server.getAdvancementLoader().get(LOCK_MAP.get(result)); - if (advancement != null && !serverPlayer.getAdvancementTracker().getProgress(advancement).isDone()) { - ci.cancel(); - } + if (server == null || !LOCK_MAP.containsKey(result)) { + return; + } + + Advancement advancement = server.getAdvancementLoader().get(LOCK_MAP.get(result)); + if (advancement != null && !serverPlayer.getAdvancementTracker().getProgress(advancement).isDone()) { + ci.cancel(); } } } diff --git a/src/main/java/org/mesdag/advjs/mixin/ServerAdvancementLoaderMixin.java b/src/main/java/org/mesdag/advjs/mixin/ServerAdvancementLoaderMixin.java index 464b7f4..58e6b8b 100644 --- a/src/main/java/org/mesdag/advjs/mixin/ServerAdvancementLoaderMixin.java +++ b/src/main/java/org/mesdag/advjs/mixin/ServerAdvancementLoaderMixin.java @@ -18,6 +18,7 @@ import org.mesdag.advjs.AdvJS; import org.mesdag.advjs.AdvJSPlugin; import org.mesdag.advjs.configure.*; +import org.mesdag.advjs.util.AdvRemoveFilter; import org.mesdag.advjs.util.DisplayOffset; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -25,12 +26,12 @@ import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import java.util.Map; -import static org.mesdag.advjs.configure.Data.*; +import static org.mesdag.advjs.util.Data.*; @Mixin(ServerAdvancementLoader.class) public abstract class ServerAdvancementLoaderMixin { @@ -41,45 +42,6 @@ public abstract class ServerAdvancementLoaderMixin { @Shadow private AdvancementManager manager; - @Inject(method = "apply(Ljava/util/Map;Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/util/profiler/Profiler;)V", at = @At("TAIL")) - private void advJS$setLocation(Map map, ResourceManager resourceManager, Profiler profiler, CallbackInfo ci) { - for (Map.Entry entry : DISPLAY_OFFSET.entrySet()) { - Identifier id = entry.getKey(); - Advancement advancement = manager.get(id); - if (advancement == null) { - ConsoleJS.SERVER.warn("AdvJS: Advancement '%s' is not exist".formatted(id)); - continue; - } - - DisplayOffset offset = entry.getValue(); - advJS$applyOffset(advancement, offset.x, offset.y, offset.modifyChildren); - } - } - - @Unique - private static void advJS$applyOffset(Advancement advancement, float x, float y, boolean modifyChildren) { - AdvancementDisplay displayInfo = advancement.getDisplay(); - if (displayInfo == null) { - ConsoleJS.SERVER.warn("AdvJS: Advancement '%s' dose not have display".formatted(advancement.getId())); - } else { - float rawX = displayInfo.getX(); - float neoX = rawX + x; - float rawY = displayInfo.getY(); - float neoY = rawY + y; - displayInfo.setPos(neoX, neoY); - if (modifyChildren) { - for (Advancement child : advancement.getChildren()) { - advJS$applyOffset(child, x, y, true); - } - } - - if (AdvJSPlugin.DEBUG) { - ConsoleJS.SERVER.debug("AdvJS: The display location of advancement '%s' has set from (%s, %s) to (%s, %s)" - .formatted(advancement.getId(), rawX, rawY, neoX, neoY)); - } - } - } - @Inject(method = "apply(Ljava/util/Map;Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/util/profiler/Profiler;)V", at = @At("HEAD")) private void advJS$remove(Map map, ResourceManager resourceManager, Profiler profiler, CallbackInfo ci) { AdvJS.ADVANCEMENT.post(new AdvConfigureEvent()); @@ -94,7 +56,7 @@ public abstract class ServerAdvancementLoaderMixin { } JsonObject advJson = entry.getValue().getAsJsonObject(); - for (RemoveFilter filter : FILTERS) { + for (AdvRemoveFilter filter : FILTERS) { if (filter.isResolved()) { continue; } @@ -121,20 +83,19 @@ public abstract class ServerAdvancementLoaderMixin { ConsoleJS.SERVER.info("AdvJS: Removed " + counter + " advancements"); } - @ModifyArg( - method = "apply(Ljava/util/Map;Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/util/profiler/Profiler;)V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/advancement/AdvancementManager;load(Ljava/util/Map;)V")) - private Map advjs$configure(Map map) { - advJS$modify(map, conditionManager); - advJS$add(map); + @Inject(method = "apply(Ljava/util/Map;Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/util/profiler/Profiler;)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/advancement/AdvancementManager;load(Ljava/util/Map;)V", shift = At.Shift.BEFORE), + locals = LocalCapture.CAPTURE_FAILSOFT) + private void advjs$configure(Map map, ResourceManager resourceManager, Profiler profiler, CallbackInfo ci, Map map2, AdvancementManager advancementManager) { + advJS$modify(map2, conditionManager); + advJS$add(map2); ConsoleJS.SERVER.info("AdvJS: Completely loaded!"); - return map; } @Unique private static void advJS$modify(Map map, LootManager predicateManager) { if (AdvJSPlugin.DEBUG) { - ConsoleJS.SERVER.debug("AdvJS: Modification details:"); + ConsoleJS.SERVER.info("AdvJS: Modification details:"); } int counter = 0; @@ -142,7 +103,7 @@ public abstract class ServerAdvancementLoaderMixin { Identifier id = entry.getKey(); Advancement.Builder builder = map.get(id); if (builder == null) { - ConsoleJS.SERVER.error("AdvJS: Advancement '" + id + "' is not exist"); + ConsoleJS.SERVER.error("AdvJS/modify: Advancement '%s' is not exist".formatted(id)); continue; } AdvGetter getter = entry.getValue(); @@ -181,7 +142,7 @@ public abstract class ServerAdvancementLoaderMixin { counter++; if (AdvJSPlugin.DEBUG) { - ConsoleJS.SERVER.debug(""" + ConsoleJS.SERVER.info(""" identifier: %s parent: %s display: @@ -215,7 +176,7 @@ public abstract class ServerAdvancementLoaderMixin { ); } } - ConsoleJS.SERVER.info("AdvJS: Modified " + counter + " advancements"); + ConsoleJS.SERVER.info("AdvJS: Modified %s advancements".formatted(counter)); } @Unique @@ -230,15 +191,17 @@ public abstract class ServerAdvancementLoaderMixin { continue; } + Identifier id = advBuilder.getId(); if (BUILDER_MAP.containsKey(parentId) || map.containsKey(parentId)) { Advancement.Builder builder = advJS$build(advBuilder); - map.put(advBuilder.getId(), builder.parent(parentId)); + map.put(id, builder.parent(parentId)); counter++; } else { - ConsoleJS.SERVER.error("AdvJS: Advancement '" + parentId + "' is not exist"); + map.put(id, advJS$build(advBuilder.setWarn(AdvBuilder.WarnType.NO_PARENT))); + ConsoleJS.SERVER.error("AdvJS/add: Advancement '%s' can't find parent '%s'".formatted(id, parentId)); } } - ConsoleJS.SERVER.info("AdvJS: Added " + counter + " advancements"); + ConsoleJS.SERVER.info("AdvJS: Added %s advancements".formatted(counter)); } @Unique @@ -248,7 +211,7 @@ public abstract class ServerAdvancementLoaderMixin { displayBuilder.setTitle(Text.translatable("advjs.attention").formatted(Formatting.RED)); displayBuilder.setDescription(advBuilder.getWarn().msg); }); - ConsoleJS.SERVER.warn("AdvJS: A warn advancement created, the parent is '" + advBuilder.getParent() + "'"); + ConsoleJS.SERVER.warn("AdvJS: A warn advancement created, the id is '%s'".formatted(advBuilder.getId())); } return new Advancement( advBuilder.getId(), @@ -260,4 +223,44 @@ public abstract class ServerAdvancementLoaderMixin { advBuilder.isSendsTelemetryEvent() ).createTask(); } + + @Inject(method = "apply(Ljava/util/Map;Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/util/profiler/Profiler;)V", at = @At("TAIL")) + private void advJS$setLocation(Map map, ResourceManager resourceManager, Profiler profiler, CallbackInfo ci) { + for (Map.Entry entry : DISPLAY_OFFSET.entrySet()) { + Identifier id = entry.getKey(); + Advancement advancement = manager.get(id); + if (advancement == null) { + ConsoleJS.SERVER.warn("AdvJS/displayOffset: Advancement '%s' is not exist".formatted(id)); + continue; + } + + DisplayOffset offset = entry.getValue(); + advJS$applyOffset(advancement, offset.x, offset.y, offset.modifyChildren); + } + } + + @Unique + private static void advJS$applyOffset(Advancement advancement, float x, float y, boolean modifyChildren) { + AdvancementDisplay displayInfo = advancement.getDisplay(); + if (displayInfo == null) { + ConsoleJS.SERVER.error("AdvJS/displayOffset: Advancement '%s' dose not have display".formatted(advancement.getId())); + return; + } + + float rawX = displayInfo.getX(); + float neoX = rawX + x; + float rawY = displayInfo.getY(); + float neoY = rawY + y; + displayInfo.setPos(neoX, neoY); + if (modifyChildren) { + for (Advancement child : advancement.getChildren()) { + advJS$applyOffset(child, x, y, true); + } + } + + if (AdvJSPlugin.DEBUG) { + ConsoleJS.SERVER.info("AdvJS: The display location of advancement '%s' has set from (%s, %s) to (%s, %s)" + .formatted(advancement.getId(), rawX, rawY, neoX, neoY)); + } + } } diff --git a/src/main/java/org/mesdag/advjs/mixin/ServerPlayerEntityMixin.java b/src/main/java/org/mesdag/advjs/mixin/ServerPlayerEntityMixin.java new file mode 100644 index 0000000..83059bc --- /dev/null +++ b/src/main/java/org/mesdag/advjs/mixin/ServerPlayerEntityMixin.java @@ -0,0 +1,18 @@ +package org.mesdag.advjs.mixin; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.server.network.ServerPlayerEntity; +import org.mesdag.advjs.trigger.custom.CriteriaTriggers; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ServerPlayerEntity.class) +public abstract class ServerPlayerEntityMixin { + @Inject(method = "updateKilledAdvancementCriterion", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;addScore(I)V")) + private void advJS$killScore(Entity killed, int score, DamageSource damageSource, CallbackInfo ci) { + CriteriaTriggers.INCREASED_KILL_SCORE.trigger((ServerPlayerEntity) (Object) this, killed, score, damageSource); + } +} diff --git a/src/main/java/org/mesdag/advjs/trigger/Trigger.java b/src/main/java/org/mesdag/advjs/trigger/Trigger.java index 7e656e0..e2ae2dd 100644 --- a/src/main/java/org/mesdag/advjs/trigger/Trigger.java +++ b/src/main/java/org/mesdag/advjs/trigger/Trigger.java @@ -10,8 +10,9 @@ import net.minecraft.util.Identifier; import org.mesdag.advjs.predicate.PlayerPredicateBuilder; import org.mesdag.advjs.trigger.custom.BlockDestroyedCriterion; -import org.mesdag.advjs.trigger.custom.BossEventConditions; -import org.mesdag.advjs.trigger.custom.PlayerTouchConditions; +import org.mesdag.advjs.trigger.custom.BossEventCriterion; +import org.mesdag.advjs.trigger.custom.IncreasedKillScoreCriterion; +import org.mesdag.advjs.trigger.custom.PlayerTouchCriterion; import org.mesdag.advjs.util.ItemSetter; import java.util.List; @@ -20,19 +21,24 @@ public class Trigger implements ItemSetter { @Info("Custom trigger, triggers when the player breaks a block.") public BlockDestroyedCriterion.Conditions blockDestroyed(Consumer consumer) { - return BlockDestroyedCriterion.blockDestroyed(consumer); + return BlockDestroyedCriterion.create(consumer); } @Info("Custom trigger, triggers when the player touch an entity.") - public PlayerTouchConditions.Conditions playerTouch(Consumer consumer) { + public PlayerTouchCriterion.Conditions playerTouch(Consumer consumer) { SingleEntityBuilder builder = new SingleEntityBuilder(); consumer.accept(builder); - return new PlayerTouchConditions.Conditions(builder.player, builder.entity); + return new PlayerTouchCriterion.Conditions(builder.player, builder.entity); } - @Info("Custom trigger, triggers when the play joins a boss fight.") - public BossEventConditions.Conditions bossEvent(Consumer consumer) { - return BossEventConditions.bossEvent(consumer); + @Info("Custom trigger, triggers when the player joins a boss fight.") + public BossEventCriterion.Conditions bossEvent(Consumer consumer) { + return BossEventCriterion.create(consumer); + } + + @Info("Custom trigger, triggers when the player killed an entity. It will match the score that player increased.") + public IncreasedKillScoreCriterion.Condition increasedKillScore(Consumer consumer) { + return IncreasedKillScoreCriterion.create(consumer); } @Info("Never triggers.") diff --git a/src/main/java/org/mesdag/advjs/trigger/custom/BlockDestroyedCriterion.java b/src/main/java/org/mesdag/advjs/trigger/custom/BlockDestroyedCriterion.java index 08d273c..38cfc9f 100644 --- a/src/main/java/org/mesdag/advjs/trigger/custom/BlockDestroyedCriterion.java +++ b/src/main/java/org/mesdag/advjs/trigger/custom/BlockDestroyedCriterion.java @@ -55,7 +55,7 @@ public void trigger(ServerPlayerEntity serverPlayer, BlockState state, ItemStack return ID; } - public static Conditions blockDestroyed(Consumer consumer) { + public static Conditions create(Consumer consumer) { Builder builder = new Builder(); consumer.accept(builder); return new Conditions(builder.player, builder.block, builder.statePredicate, builder.item); diff --git a/src/main/java/org/mesdag/advjs/trigger/custom/BossEventConditions.java b/src/main/java/org/mesdag/advjs/trigger/custom/BossEventCriterion.java similarity index 90% rename from src/main/java/org/mesdag/advjs/trigger/custom/BossEventConditions.java rename to src/main/java/org/mesdag/advjs/trigger/custom/BossEventCriterion.java index 9f4e703..07d743d 100644 --- a/src/main/java/org/mesdag/advjs/trigger/custom/BossEventConditions.java +++ b/src/main/java/org/mesdag/advjs/trigger/custom/BossEventCriterion.java @@ -13,11 +13,11 @@ import java.util.function.Consumer; -public class BossEventConditions extends AbstractCriterion { +public class BossEventCriterion extends AbstractCriterion { static final Identifier ID = new Identifier("advjs:boss_event"); @Override - public @NotNull BossEventConditions.Conditions conditionsFromJson(@NotNull JsonObject jsonObject, @NotNull LootContextPredicate composite, @NotNull AdvancementEntityPredicateDeserializer deserializationContext) { + public @NotNull BossEventCriterion.Conditions conditionsFromJson(@NotNull JsonObject jsonObject, @NotNull LootContextPredicate composite, @NotNull AdvancementEntityPredicateDeserializer deserializationContext) { boolean darkenScreen = jsonObject.has("darken_screen") && jsonObject.get("darken_screen").getAsBoolean(); boolean playBossMusic = jsonObject.has("play_boss_music") && jsonObject.get("play_boss_music").getAsBoolean(); boolean createWorldFog = jsonObject.has("create_world_fog") && jsonObject.get("create_world_fog").getAsBoolean(); @@ -34,7 +34,7 @@ public void trigger(ServerPlayerEntity serverPlayer, boolean darkenScreen, boole return ID; } - public static Conditions bossEvent(Consumer consumer) { + public static Conditions create(Consumer consumer) { Builder builder = new Builder(); consumer.accept(builder); return new Conditions(builder.player, builder.darkenScreen, builder.playBossMusic, builder.createWorldFog, builder.key); diff --git a/src/main/java/org/mesdag/advjs/trigger/custom/CriteriaTriggers.java b/src/main/java/org/mesdag/advjs/trigger/custom/CriteriaTriggers.java index 7d3ac6b..68f3ee0 100644 --- a/src/main/java/org/mesdag/advjs/trigger/custom/CriteriaTriggers.java +++ b/src/main/java/org/mesdag/advjs/trigger/custom/CriteriaTriggers.java @@ -4,12 +4,14 @@ public class CriteriaTriggers { public static BlockDestroyedCriterion BLOCK_DESTROYED; - public static PlayerTouchConditions PLAYER_TOUCH; - public static BossEventConditions BOSS_EVENT; + public static PlayerTouchCriterion PLAYER_TOUCH; + public static BossEventCriterion BOSS_EVENT; + public static IncreasedKillScoreCriterion INCREASED_KILL_SCORE; public static void initialize() { BLOCK_DESTROYED = Criteria.register(new BlockDestroyedCriterion()); - PLAYER_TOUCH = Criteria.register(new PlayerTouchConditions()); - BOSS_EVENT = Criteria.register(new BossEventConditions()); + PLAYER_TOUCH = Criteria.register(new PlayerTouchCriterion()); + BOSS_EVENT = Criteria.register(new BossEventCriterion()); + INCREASED_KILL_SCORE = Criteria.register(new IncreasedKillScoreCriterion()); } } diff --git a/src/main/java/org/mesdag/advjs/trigger/custom/IncreasedKillScoreCriterion.java b/src/main/java/org/mesdag/advjs/trigger/custom/IncreasedKillScoreCriterion.java new file mode 100644 index 0000000..8a6c9a0 --- /dev/null +++ b/src/main/java/org/mesdag/advjs/trigger/custom/IncreasedKillScoreCriterion.java @@ -0,0 +1,115 @@ +package org.mesdag.advjs.trigger.custom; + +import com.google.gson.JsonObject; +import dev.latvian.mods.kubejs.typings.Info; +import net.minecraft.advancement.criterion.AbstractCriterion; +import net.minecraft.advancement.criterion.AbstractCriterionConditions; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.loot.context.LootContext; +import net.minecraft.predicate.NumberRange; +import net.minecraft.predicate.entity.AdvancementEntityPredicateDeserializer; +import net.minecraft.predicate.entity.DamageSourcePredicate; +import net.minecraft.predicate.entity.EntityPredicate; +import net.minecraft.predicate.entity.LootContextPredicate; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.NotNull; +import org.mesdag.advjs.predicate.DamageSourcePredicateBuilder; +import org.mesdag.advjs.predicate.EntityPredicateBuilder; +import org.mesdag.advjs.predicate.condition.ICondition; +import org.mesdag.advjs.trigger.AbstractTriggerBuilder; +import org.mesdag.advjs.util.Bounds; + +import java.util.function.Consumer; + +public class IncreasedKillScoreCriterion extends AbstractCriterion { + static final Identifier ID = new Identifier("advjs:increased_kill_score"); + + @Override + public @NotNull IncreasedKillScoreCriterion.Condition conditionsFromJson(@NotNull JsonObject jsonObject, @NotNull LootContextPredicate playerPredicate, @NotNull AdvancementEntityPredicateDeserializer deserializationContext) { + LootContextPredicate killedPredicate = EntityPredicate.contextPredicateFromJson(jsonObject, "entity", deserializationContext); + NumberRange.IntRange scoreBounds = NumberRange.IntRange.fromJson(jsonObject.get("score")); + DamageSourcePredicate damageSourcePredicate = DamageSourcePredicate.fromJson(jsonObject.get("killing_below")); + return new Condition(playerPredicate, killedPredicate, scoreBounds, damageSourcePredicate); + } + + public void trigger(ServerPlayerEntity serverPlayer, Entity entity, int score, DamageSource damageSource) { + LootContext killed = EntityPredicate.createAdvancementEntityLootContext(serverPlayer, entity); + this.trigger(serverPlayer, instance -> instance.matches(serverPlayer, killed, score, damageSource)); + } + + @Override + public @NotNull Identifier getId() { + return ID; + } + + public static Condition create(Consumer consumer) { + Builder builder = new Builder(); + consumer.accept(builder); + return new Condition(builder.player, builder.killedPredicate, builder.scoreBounds, builder.damageSourcePredicate); + } + + public static class Builder extends AbstractTriggerBuilder { + LootContextPredicate killedPredicate = LootContextPredicate.EMPTY; + NumberRange.IntRange scoreBounds = NumberRange.IntRange.ANY; + DamageSourcePredicate damageSourcePredicate = DamageSourcePredicate.EMPTY; + + @Info("The entity that was killed.") + public void setKilledByPredicate(EntityPredicate killedPredicate) { + this.killedPredicate = wrapEntity(killedPredicate); + } + + @Info("The entity that was killed.") + public void setKilledByType(EntityType entityType) { + this.killedPredicate = wrapEntity(entityType); + } + + @Info("The entity that was killed.") + public void setKilled(Consumer consumer) { + EntityPredicateBuilder builder = new EntityPredicateBuilder(); + consumer.accept(builder); + this.killedPredicate = wrapEntity(builder.build()); + } + + @Info("The entity that was killed.") + public void setKilledByCondition(ICondition... conditions) { + this.killedPredicate = wrapEntity(conditions); + } + + @Info("The score that player increased.") + public void setScore(Bounds bounds) { + this.scoreBounds = bounds.toIntegerBounds(); + } + + @Info("The type of damage that killed an entity.") + public void setKillingBelowByPredicate(DamageSourcePredicate damageSourcePredicate) { + this.damageSourcePredicate = damageSourcePredicate; + } + + @Info("The type of damage that killed an entity.") + public void setKillingBelow(Consumer consumer) { + DamageSourcePredicateBuilder builder = new DamageSourcePredicateBuilder(); + consumer.accept(builder); + this.damageSourcePredicate = builder.build(); + } + } + + public static class Condition extends AbstractCriterionConditions { + private final LootContextPredicate killedPredicate; + private final NumberRange.IntRange scoreBounds; + private final DamageSourcePredicate damageSourcePredicate; + + public Condition(LootContextPredicate playerPredicate, LootContextPredicate killedPredicate, NumberRange.IntRange scoreBounds, DamageSourcePredicate damageSourcePredicate) { + super(ID, playerPredicate); + this.killedPredicate = killedPredicate; + this.scoreBounds = scoreBounds; + this.damageSourcePredicate = damageSourcePredicate; + } + + public boolean matches(ServerPlayerEntity serverPlayer, LootContext killed, int score, DamageSource damageSource) { + return killedPredicate.test(killed) && scoreBounds.test(score) && damageSourcePredicate.test(serverPlayer, damageSource); + } + } +} diff --git a/src/main/java/org/mesdag/advjs/trigger/custom/PlayerTouchConditions.java b/src/main/java/org/mesdag/advjs/trigger/custom/PlayerTouchCriterion.java similarity index 70% rename from src/main/java/org/mesdag/advjs/trigger/custom/PlayerTouchConditions.java rename to src/main/java/org/mesdag/advjs/trigger/custom/PlayerTouchCriterion.java index 7e05ac0..aa18e4a 100644 --- a/src/main/java/org/mesdag/advjs/trigger/custom/PlayerTouchConditions.java +++ b/src/main/java/org/mesdag/advjs/trigger/custom/PlayerTouchCriterion.java @@ -1,6 +1,5 @@ package org.mesdag.advjs.trigger.custom; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import net.minecraft.advancement.criterion.AbstractCriterion; import net.minecraft.advancement.criterion.AbstractCriterionConditions; @@ -13,18 +12,12 @@ import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; -public class PlayerTouchConditions extends AbstractCriterion { +public class PlayerTouchCriterion extends AbstractCriterion { static final Identifier ID = new Identifier("advjs:player_touch"); @Override - public @NotNull PlayerTouchConditions.Conditions conditionsFromJson(@NotNull JsonObject jsonObject, @NotNull LootContextPredicate composite, @NotNull AdvancementEntityPredicateDeserializer deserializationContext) { - JsonElement entity = jsonObject.get("entity"); - LootContextPredicate touched; - if (entity.isJsonNull()) { - touched = LootContextPredicate.EMPTY; - } else { - touched = EntityPredicate.asLootContextPredicate(EntityPredicate.fromJson(entity)); - } + public @NotNull PlayerTouchCriterion.Conditions conditionsFromJson(@NotNull JsonObject jsonObject, @NotNull LootContextPredicate composite, @NotNull AdvancementEntityPredicateDeserializer deserializationContext) { + LootContextPredicate touched = EntityPredicate.contextPredicateFromJson(jsonObject, "entity", deserializationContext); return new Conditions(composite, touched); } diff --git a/src/main/java/org/mesdag/advjs/configure/RemoveFilter.java b/src/main/java/org/mesdag/advjs/util/AdvRemoveFilter.java similarity index 64% rename from src/main/java/org/mesdag/advjs/configure/RemoveFilter.java rename to src/main/java/org/mesdag/advjs/util/AdvRemoveFilter.java index 5aab9cc..d64df20 100644 --- a/src/main/java/org/mesdag/advjs/configure/RemoveFilter.java +++ b/src/main/java/org/mesdag/advjs/util/AdvRemoveFilter.java @@ -1,8 +1,8 @@ -package org.mesdag.advjs.configure; +package org.mesdag.advjs.util; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import dev.latvian.mods.kubejs.util.ConsoleJS; +import dev.latvian.mods.kubejs.util.MapJS; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.item.Item; import net.minecraft.item.Items; @@ -10,8 +10,10 @@ import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; +import java.util.Map; -public class RemoveFilter { + +public class AdvRemoveFilter { @Nullable Identifier path; @Nullable String modid; @Nullable Item icon; @@ -19,39 +21,42 @@ public class RemoveFilter { @Nullable String parent; private boolean resolved = false; - public static RemoveFilter of(JsonElement jsonElement) { - RemoveFilter filter = new RemoveFilter(); - if (jsonElement.isJsonObject()) { - JsonObject object = jsonElement.getAsJsonObject(); - if (object.has("mod")) { - String modid = object.get("mod").getAsString(); + public static AdvRemoveFilter of(Object o) { + AdvRemoveFilter filter = new AdvRemoveFilter(); + if (o instanceof CharSequence charSequence) { + filter.path = new Identifier(charSequence.toString()); + } else if (o instanceof Map) { + JsonObject jsonObject = MapJS.json(o); + if (jsonObject == null) { + return filter; + } + + if (jsonObject.has("mod")) { + String modid = jsonObject.get("mod").getAsString(); if (FabricLoader.getInstance().isModLoaded(modid)) { filter.modid = modid; } else { - ConsoleJS.SERVER.warn("AdvJS/RemoveFilter: Mod '" + modid + "' not found"); + ConsoleJS.SERVER.warn("AdvJS/RemoveFilter: Mod '%s' not found".formatted(modid)); } } - if (object.has("icon")) { - String icon = object.get("icon").getAsString(); - Identifier id = new Identifier(icon); + if (jsonObject.has("icon")) { + Identifier id = new Identifier(jsonObject.get("icon").getAsString()); Item item = Registries.ITEM.containsId(id) ? Registries.ITEM.get(id) : Items.AIR; if (item != Items.AIR) { filter.icon = item; } else { - ConsoleJS.SERVER.warn("AdvJS/RemoveFilter: Icon '" + icon + "' not found"); + ConsoleJS.SERVER.warn("AdvJS/RemoveFilter: Icon '%s' not found".formatted(id)); } } - if (object.has("frame")) { - filter.frame = object.get("frame").getAsString(); + if (jsonObject.has("frame")) { + filter.frame = jsonObject.get("frame").getAsString(); } - if (object.has("parent")) { - filter.parent = object.get("parent").getAsString(); + if (jsonObject.has("parent")) { + filter.parent = jsonObject.get("parent").getAsString(); } - } else if (jsonElement.isJsonPrimitive()) { - filter.path = new Identifier(jsonElement.getAsString()); } return filter; } diff --git a/src/main/java/org/mesdag/advjs/util/Bounds.java b/src/main/java/org/mesdag/advjs/util/Bounds.java index 4e3e729..2c2d084 100644 --- a/src/main/java/org/mesdag/advjs/util/Bounds.java +++ b/src/main/java/org/mesdag/advjs/util/Bounds.java @@ -52,28 +52,50 @@ public NumberRange.IntRange toIntegerBounds() { } @Info(""" - A number like A will wrap to an exactly bounds. - - A list like [A, B] will wrap to an between bounds. - - A map like {min: A} will wrap to an atLeast bounds. - - A map like {max: B} will wrap to an atMost bounds. - """) + A number like A will wrap to an exactly bounds. + + A list like [A, B] will wrap to an between bounds. + + A map like {min: A} will wrap to an atLeast bounds. + + A map like {max: B} will wrap to an atMost bounds. + """) @SuppressWarnings("unchecked") public static Bounds of(Object o) { - if (o instanceof Number n) { - var d = n.doubleValue(); + if (o instanceof Bounds bounds) { + return bounds; + } else if (o instanceof Number n) { + double d = n.doubleValue(); return new Bounds(d, d); } else if (o instanceof List l && !l.isEmpty()) { - var min = (Number) l.get(0); - var max = l.size() >= 2 ? (Number) l.get(1) : min; + Number min = (Number) l.get(0); + Number max = l.size() >= 2 ? (Number) l.get(1) : min; return new Bounds(min.doubleValue(), max.doubleValue()); } else if (o instanceof Map) { - var m = (Map) o; + Map m = (Map) o; return new Bounds(m.containsKey("min") ? (Number) m.get("min") : null, m.containsKey("max") ? (Number) m.get("max") : null); } return ANY; } + + public static Bounds exactly(double a) { + return new Bounds(a, a); + } + + public static Bounds between(double a, double b) { + return new Bounds(a, b); + } + + public static Bounds atLeast(double a) { + return new Bounds(a, null); + } + + public static Bounds atMost(double b) { + return new Bounds(null, b); + } + + public static Bounds any() { + return ANY; + } } diff --git a/src/main/java/org/mesdag/advjs/configure/Data.java b/src/main/java/org/mesdag/advjs/util/Data.java similarity index 64% rename from src/main/java/org/mesdag/advjs/configure/Data.java rename to src/main/java/org/mesdag/advjs/util/Data.java index ba49c79..cce5ad0 100644 --- a/src/main/java/org/mesdag/advjs/configure/Data.java +++ b/src/main/java/org/mesdag/advjs/util/Data.java @@ -1,17 +1,18 @@ -package org.mesdag.advjs.configure; +package org.mesdag.advjs.util; import net.minecraft.item.Item; import net.minecraft.util.Identifier; -import org.mesdag.advjs.util.DisplayOffset; +import org.mesdag.advjs.configure.AdvBuilder; +import org.mesdag.advjs.configure.AdvGetter; import java.util.HashMap; import java.util.HashSet; public class Data { - public static final HashSet FILTERS = new HashSet<>(); + public static final HashSet FILTERS = new HashSet<>(); public static final HashMap GETTER_MAP = new HashMap<>(); public static final HashMap BUILDER_MAP = new HashMap<>(); public static final HashMap LOCK_MAP = new HashMap<>(); - public static final HashSet REQUIRE_DONE = new HashSet<>(); + public static final HashMap REQUIRE_DONE = new HashMap<>(); public static final HashMap DISPLAY_OFFSET = new HashMap<>(); } diff --git a/src/main/resources/advjs.mixins.json b/src/main/resources/advjs.mixins.json index 0ab5051..9b2c05e 100644 --- a/src/main/resources/advjs.mixins.json +++ b/src/main/resources/advjs.mixins.json @@ -9,9 +9,10 @@ "PlayerEntityMixin", "ScreenHandlerMixin", "ServerAdvancementLoaderMixin", - "ServerBossBarMixin" + "ServerBossBarMixin", + "ServerPlayerEntityMixin" ], "injectors": { "defaultRequire": 1 - } + } } \ No newline at end of file diff --git a/src/main/resources/assets/advjs/lang/en_us.json b/src/main/resources/assets/advjs/lang/en_us.json index 3232f44..fff8ec0 100644 --- a/src/main/resources/assets/advjs/lang/en_us.json +++ b/src/main/resources/assets/advjs/lang/en_us.json @@ -1,6 +1,7 @@ { "advjs.attention": "Attention", - "advjs.attention.desc": "Your custom advancement doesn't have a name", - "advjs.command.success": "Successfully generated %s", + "advjs.attention.nameless": "Your custom advancement doesn't have a name", + "advjs.attention.no_space": "Your custom advancement is using namespace 'minecraft'", + "advjs.attention.no_parent": "Your custom advancement doesn't have parent", "advjs.command.failed": "Failed to generate %s" } \ No newline at end of file diff --git a/src/main/resources/assets/advjs/lang/zh_cn.json b/src/main/resources/assets/advjs/lang/zh_cn.json index d646859..4469591 100644 --- a/src/main/resources/assets/advjs/lang/zh_cn.json +++ b/src/main/resources/assets/advjs/lang/zh_cn.json @@ -1,6 +1,7 @@ { "advjs.attention": "警告", - "advjs.attention.desc": "你的自定义进度没有名字", - "advjs.command.success": "成功生成了:%s", + "advjs.attention.nameless": "你的自定义进度没有名字", + "advjs.attention.no_space": "你的自定义进度正在使用命名空间 'minecraft'", + "advjs.attention.no_parent": "你的自定义进度没有父进度", "advjs.command.failed": "生成失败了:%s" } \ No newline at end of file