From aa89c068498ed5e23482996cd03270551d66918c Mon Sep 17 00:00:00 2001 From: Brian Date: Sat, 13 Jan 2024 15:58:00 -0500 Subject: [PATCH] Add advancement triggers and some new advancements (#96) * Start custom advancement triggers * Add advancement triggers and some new advancements --- .../assets/allomancy/lang/en_us.json | 2 + .../advancements/main/consequences.json | 55 +++++++++++++++++++ .../advancements/main/tin_foil_hat.json | 47 +++++++++++++--- .../legobmw99/allomancy/api/enums/Metal.java | 11 ++++ .../allomancy/datagen/Advancements.java | 25 ++++++++- .../allomancy/datagen/Languages.java | 2 + .../modules/combat/item/CoinBagItem.java | 2 - .../allomancy/modules/extras/ExtrasSetup.java | 10 ++++ .../advancement/MetalUsedOnEntityTrigger.java | 54 ++++++++++++++++++ .../advancement/MetalUsedOnPlayerTrigger.java | 52 ++++++++++++++++++ .../modules/powers/CommonEventHandler.java | 11 ++-- .../powers/network/EntityPushPullPayload.java | 4 ++ .../powers/network/ServerPayloadHandler.java | 48 ++++++++++------ 13 files changed, 291 insertions(+), 32 deletions(-) create mode 100644 src/generated/resources/data/allomancy/advancements/main/consequences.json create mode 100644 src/main/java/com/legobmw99/allomancy/modules/extras/advancement/MetalUsedOnEntityTrigger.java create mode 100644 src/main/java/com/legobmw99/allomancy/modules/extras/advancement/MetalUsedOnPlayerTrigger.java diff --git a/src/generated/resources/assets/allomancy/lang/en_us.json b/src/generated/resources/assets/allomancy/lang/en_us.json index c017fc68..a3688143 100644 --- a/src/generated/resources/assets/allomancy/lang/en_us.json +++ b/src/generated/resources/assets/allomancy/lang/en_us.json @@ -3,6 +3,8 @@ "advancements.become_mistborn.title": "Become Mistborn!", "advancements.coinshot.desc": "Kill a mob with the bag of coins.", "advancements.coinshot.title": "Coinshot", + "advancements.consequences.desc": "Learn what happens when you push on a much heavier target.", + "advancements.consequences.title": "Consequences, Vin", "advancements.dna_entangled.desc": "Your DNA is too entangled with the spiritual realm to use Lerasium", "advancements.dna_entangled.title": "Spiritual DNA Entanglement", "advancements.local_metallurgist.desc": "Craft a grinder to begin mixing metals", diff --git a/src/generated/resources/data/allomancy/advancements/main/consequences.json b/src/generated/resources/data/allomancy/advancements/main/consequences.json new file mode 100644 index 00000000..7e6a8a17 --- /dev/null +++ b/src/generated/resources/data/allomancy/advancements/main/consequences.json @@ -0,0 +1,55 @@ +{ + "parent": "allomancy:main/metallurgist", + "criteria": { + "pulled_iron_golem": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:iron_golem" + } + } + ], + "metal": "iron" + }, + "trigger": "allomancy:metal_used_on_entity" + }, + "pushed_iron_golem": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:iron_golem" + } + } + ], + "metal": "steel" + }, + "trigger": "allomancy:metal_used_on_entity" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "translate": "advancements.consequences.desc" + }, + "hidden": true, + "icon": { + "item": "minecraft:iron_block" + }, + "title": { + "translate": "advancements.consequences.title" + } + }, + "requirements": [ + [ + "pushed_iron_golem", + "pulled_iron_golem" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/allomancy/advancements/main/tin_foil_hat.json b/src/generated/resources/data/allomancy/advancements/main/tin_foil_hat.json index 4b0a9ca1..94de2c43 100644 --- a/src/generated/resources/data/allomancy/advancements/main/tin_foil_hat.json +++ b/src/generated/resources/data/allomancy/advancements/main/tin_foil_hat.json @@ -1,17 +1,49 @@ { "parent": "allomancy:main/metallurgist", "criteria": { - "tin_foil_hat": { + "attempted_chromium_manipulation": { "conditions": { - "items": [ + "enhanced": false, + "metal": "chromium", + "player": [ { - "items": [ - "allomancy:aluminum_helmet" - ] + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "equipment": { + "head": { + "items": [ + "allomancy:aluminum_helmet" + ] + } + } + } } ] }, - "trigger": "minecraft:inventory_changed" + "trigger": "allomancy:metal_used_on_player" + }, + "attempted_nicrosil_manipulation": { + "conditions": { + "enhanced": false, + "metal": "nicrosil", + "player": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "equipment": { + "head": { + "items": [ + "allomancy:aluminum_helmet" + ] + } + } + } + } + ] + }, + "trigger": "allomancy:metal_used_on_player" } }, "display": { @@ -30,7 +62,8 @@ }, "requirements": [ [ - "tin_foil_hat" + "attempted_nicrosil_manipulation", + "attempted_chromium_manipulation" ] ], "sends_telemetry_event": true diff --git a/src/main/java/com/legobmw99/allomancy/api/enums/Metal.java b/src/main/java/com/legobmw99/allomancy/api/enums/Metal.java index 790a71af..f72035ed 100644 --- a/src/main/java/com/legobmw99/allomancy/api/enums/Metal.java +++ b/src/main/java/com/legobmw99/allomancy/api/enums/Metal.java @@ -1,5 +1,8 @@ package com.legobmw99.allomancy.api.enums; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; + import java.util.Locale; public enum Metal { @@ -61,5 +64,13 @@ public int getIndex() { return ordinal(); } + public static final Codec CODEC = Codec.STRING.comapFlatMap(s -> { + for (Metal mt : Metal.values()) { + if (mt.getName().equals(s)) { + return DataResult.success(mt); + } + } + return DataResult.error(() -> s + " is not a valid Metal"); + }, Metal::getName); } \ No newline at end of file diff --git a/src/main/java/com/legobmw99/allomancy/datagen/Advancements.java b/src/main/java/com/legobmw99/allomancy/datagen/Advancements.java index db0e28bd..e3774895 100644 --- a/src/main/java/com/legobmw99/allomancy/datagen/Advancements.java +++ b/src/main/java/com/legobmw99/allomancy/datagen/Advancements.java @@ -1,8 +1,11 @@ package com.legobmw99.allomancy.datagen; import com.legobmw99.allomancy.Allomancy; +import com.legobmw99.allomancy.api.enums.Metal; import com.legobmw99.allomancy.modules.combat.CombatSetup; import com.legobmw99.allomancy.modules.consumables.ConsumeSetup; +import com.legobmw99.allomancy.modules.extras.advancement.MetalUsedOnEntityTrigger; +import com.legobmw99.allomancy.modules.extras.advancement.MetalUsedOnPlayerTrigger; import com.legobmw99.allomancy.modules.materials.MaterialsSetup; import net.minecraft.advancements.*; import net.minecraft.advancements.critereon.*; @@ -10,7 +13,9 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Blocks; import net.neoforged.neoforge.common.data.AdvancementProvider; import net.neoforged.neoforge.common.data.ExistingFileHelper; @@ -74,13 +79,29 @@ public void generate(HolderLookup.Provider registries, Consumer> CT = DeferredRegister.create(Registries.TRIGGER_TYPE, Allomancy.MODID); + public static final Supplier METAL_USED_ON_ENTITY_TRIGGER = CT.register("metal_used_on_entity", MetalUsedOnEntityTrigger::new); + public static final Supplier METAL_USED_ON_PLAYER_TRIGGER = CT.register("metal_used_on_player", MetalUsedOnPlayerTrigger::new); + public static void register(IEventBus bus) { BLOCKS.register(bus); ITEMS.register(bus); BP.register(bus); + CT.register(bus); } + } diff --git a/src/main/java/com/legobmw99/allomancy/modules/extras/advancement/MetalUsedOnEntityTrigger.java b/src/main/java/com/legobmw99/allomancy/modules/extras/advancement/MetalUsedOnEntityTrigger.java new file mode 100644 index 00000000..574a6135 --- /dev/null +++ b/src/main/java/com/legobmw99/allomancy/modules/extras/advancement/MetalUsedOnEntityTrigger.java @@ -0,0 +1,54 @@ +package com.legobmw99.allomancy.modules.extras.advancement; + +import com.legobmw99.allomancy.api.enums.Metal; +import com.legobmw99.allomancy.modules.extras.ExtrasSetup; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.advancements.Criterion; +import net.minecraft.advancements.critereon.ContextAwarePredicate; +import net.minecraft.advancements.critereon.EntityPredicate; +import net.minecraft.advancements.critereon.SimpleCriterionTrigger; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.storage.loot.LootContext; + +import java.util.Optional; + +/** + * Triggered when a player affects a mob with Allomancy + * This currently only means: zinc, brass, iron, steel + */ +public class MetalUsedOnEntityTrigger extends SimpleCriterionTrigger { + @Override + public Codec codec() { + return TriggerInstance.CODEC; + } + + public void trigger(ServerPlayer player, Entity entity, Metal mt, boolean enhanced) { + LootContext lootcontext = EntityPredicate.createContext(player, entity); + this.trigger(player, p_48112_ -> p_48112_.matches(lootcontext, mt, enhanced)); + } + + public record TriggerInstance(Optional player, Optional entityPredicate, Metal mt, + Optional enhanced) implements SimpleCriterionTrigger.SimpleInstance { + public static final Codec CODEC = RecordCodecBuilder.create(builder -> builder + .group(ExtraCodecs.strictOptionalField(EntityPredicate.ADVANCEMENT_CODEC, "player").forGetter(TriggerInstance::player), + ExtraCodecs.strictOptionalField(EntityPredicate.ADVANCEMENT_CODEC, "entity").forGetter(TriggerInstance::entityPredicate), + Metal.CODEC.fieldOf("metal").forGetter(TriggerInstance::mt), Codec.BOOL.optionalFieldOf("enhanced").forGetter(TriggerInstance::enhanced)) + .apply(builder, TriggerInstance::new)); + + public static Criterion instance(Optional player, Optional entityPredicate, Metal mt) { + return ExtrasSetup.METAL_USED_ON_ENTITY_TRIGGER.get().createCriterion(new TriggerInstance(player, entityPredicate, mt, Optional.empty())); + } + + public static Criterion instance(Optional player, Optional entityPredicate, Metal mt, boolean enhanced) { + return ExtrasSetup.METAL_USED_ON_ENTITY_TRIGGER.get().createCriterion(new TriggerInstance(player, entityPredicate, mt, Optional.of(enhanced))); + } + + boolean matches(LootContext entity, Metal mt, boolean enhanced) { + return this.mt == mt && (this.entityPredicate.isEmpty() || this.entityPredicate.get().matches(entity)) && + (this.enhanced().isEmpty() || this.enhanced().get() == enhanced); + } + } +} diff --git a/src/main/java/com/legobmw99/allomancy/modules/extras/advancement/MetalUsedOnPlayerTrigger.java b/src/main/java/com/legobmw99/allomancy/modules/extras/advancement/MetalUsedOnPlayerTrigger.java new file mode 100644 index 00000000..6841638d --- /dev/null +++ b/src/main/java/com/legobmw99/allomancy/modules/extras/advancement/MetalUsedOnPlayerTrigger.java @@ -0,0 +1,52 @@ +package com.legobmw99.allomancy.modules.extras.advancement; + +import com.legobmw99.allomancy.api.enums.Metal; +import com.legobmw99.allomancy.modules.extras.ExtrasSetup; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.advancements.Criterion; +import net.minecraft.advancements.critereon.ContextAwarePredicate; +import net.minecraft.advancements.critereon.EntityPredicate; +import net.minecraft.advancements.critereon.SimpleCriterionTrigger; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.ExtraCodecs; + +import java.util.Optional; + +/** + * Triggered when a player is affected by Allomancy from another player + * This currently only means: chromium, nicrosil, iron, steel + */ +public class MetalUsedOnPlayerTrigger extends SimpleCriterionTrigger { + @Override + public Codec codec() { + return TriggerInstance.CODEC; + } + + public void trigger(ServerPlayer player, Metal mt, boolean enhanced) { + this.trigger(player, p_48112_ -> p_48112_.matches(mt, enhanced)); + } + + public record TriggerInstance(Optional player, Metal mt, Optional enhanced) implements SimpleInstance { + public static final Codec CODEC = RecordCodecBuilder.create(builder -> builder + .group(ExtraCodecs.strictOptionalField(EntityPredicate.ADVANCEMENT_CODEC, "player").forGetter(TriggerInstance::player), + Metal.CODEC.fieldOf("metal").forGetter(TriggerInstance::mt), Codec.BOOL.optionalFieldOf("enhanced").forGetter(TriggerInstance::enhanced)) + .apply(builder, TriggerInstance::new)); + + + public static Criterion instance(Optional player, Metal mt) { + return ExtrasSetup.METAL_USED_ON_PLAYER_TRIGGER.get().createCriterion(new TriggerInstance(player, mt, Optional.empty())); + } + + public static Criterion instance(Optional player, Metal mt, boolean enhanced) { + return ExtrasSetup.METAL_USED_ON_PLAYER_TRIGGER.get().createCriterion(new TriggerInstance(player, mt, Optional.of(enhanced))); + } + + + boolean matches(Metal mt, boolean enhanced) { + return this.mt == mt && (this.enhanced().isEmpty() || this.enhanced().get() == enhanced); + } + + + } +} diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/CommonEventHandler.java b/src/main/java/com/legobmw99/allomancy/modules/powers/CommonEventHandler.java index 320ac407..bc744d3d 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/CommonEventHandler.java +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/CommonEventHandler.java @@ -4,6 +4,7 @@ import com.legobmw99.allomancy.api.data.IAllomancerData; import com.legobmw99.allomancy.api.enums.Metal; import com.legobmw99.allomancy.modules.combat.item.KolossBladeItem; +import com.legobmw99.allomancy.modules.extras.ExtrasSetup; import com.legobmw99.allomancy.modules.materials.MaterialsSetup; import com.legobmw99.allomancy.modules.powers.data.AllomancerAttachment; import com.legobmw99.allomancy.modules.powers.data.AllomancerData; @@ -187,8 +188,12 @@ public static void onDamage(final LivingHurtEvent event) { } if (data.isBurning(Metal.CHROMIUM)) { - if (event.getEntity() instanceof Player player && !PowerUtils.hasTinFoilHat(player)) { - PowerUtils.wipePlayer(player); + ExtrasSetup.METAL_USED_ON_ENTITY_TRIGGER.get().trigger(source, event.getEntity(), Metal.CHROMIUM, data.isEnhanced()); + if (event.getEntity() instanceof ServerPlayer player) { + ExtrasSetup.METAL_USED_ON_PLAYER_TRIGGER.get().trigger(player, Metal.CHROMIUM, data.isEnhanced()); + if (!PowerUtils.hasTinFoilHat(player)) { + PowerUtils.wipePlayer(player); + } } } } @@ -260,7 +265,6 @@ private static void playerPowerTick(Player curPlayer, Level level) { data.tickBurning(player); } - /********************************************* * CHROMIUM (enhanced) * *********************************************/ @@ -275,7 +279,6 @@ private static void playerPowerTick(Player curPlayer, Level level) { } } - /********************************************* * GOLD AND ELECTRUM (enhanced) * *********************************************/ diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/network/EntityPushPullPayload.java b/src/main/java/com/legobmw99/allomancy/modules/powers/network/EntityPushPullPayload.java index 1089aac6..9cf59d0a 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/network/EntityPushPullPayload.java +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/network/EntityPushPullPayload.java @@ -19,6 +19,10 @@ public void write(FriendlyByteBuf buf) { buf.writeInt(this.direction); } + public boolean isPush() { + return this.direction > 0; + } + @Override public ResourceLocation id() { return ID; diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/network/ServerPayloadHandler.java b/src/main/java/com/legobmw99/allomancy/modules/powers/network/ServerPayloadHandler.java index a8ab9ea9..b3ab1401 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/network/ServerPayloadHandler.java +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/network/ServerPayloadHandler.java @@ -2,8 +2,10 @@ import com.legobmw99.allomancy.Allomancy; import com.legobmw99.allomancy.api.block.IAllomanticallyUsableBlock; +import com.legobmw99.allomancy.api.data.IAllomancerData; import com.legobmw99.allomancy.api.enums.Metal; import com.legobmw99.allomancy.modules.combat.CombatSetup; +import com.legobmw99.allomancy.modules.extras.ExtrasSetup; import com.legobmw99.allomancy.modules.powers.PowerUtils; import com.legobmw99.allomancy.modules.powers.data.AllomancerAttachment; import com.legobmw99.allomancy.network.Network; @@ -29,12 +31,13 @@ public class ServerPayloadHandler { public static void handleEmotionChange(final EmotionPayload data, final PlayPayloadContext ctx) { ctx.workHandler().submitAsync(() -> { - Player allomancer = ctx.player().get(); + ServerPlayer allomancer = (ServerPlayer) ctx.player().get(); PathfinderMob target = (PathfinderMob) ctx.level().get().getEntity(data.entityID()); if (target == null) { return; } boolean enhanced = allomancer.getData(AllomancerAttachment.ALLOMANCY_DATA).isEnhanced(); + ExtrasSetup.METAL_USED_ON_ENTITY_TRIGGER.get().trigger(allomancer, target, data.makeAggressive() ? Metal.ZINC : Metal.BRASS, enhanced); if (data.makeAggressive()) { PowerUtils.riotEntity(target, allomancer, enhanced); } else { @@ -70,25 +73,32 @@ public static void tryPushPullBlock(final BlockPushPullPayload data, final PlayP }); } - public static void tryPushPullEntity(final EntityPushPullPayload data, final PlayPayloadContext ctx) { + public static void tryPushPullEntity(final EntityPushPullPayload payload, final PlayPayloadContext ctx) { ctx.workHandler().execute(() -> { - Player player = ctx.player().get(); + ServerPlayer player = (ServerPlayer) ctx.player().get(); Level level = ctx.level().get(); - Entity target = level.getEntity(data.entityID()); + Entity target = level.getEntity(payload.entityID()); + IAllomancerData data = player.getData(AllomancerAttachment.ALLOMANCY_DATA.get()); + Metal which = payload.isPush() ? Metal.STEEL : Metal.IRON; if (target != null) { if (PowerUtils.isEntityMetal(target)) { + ExtrasSetup.METAL_USED_ON_ENTITY_TRIGGER.get().trigger(player, target, which, data.isEnhanced()); + // The player moves if (target instanceof IronGolem || target instanceof ItemFrame) { - PowerUtils.move(data.direction(), player, target.blockPosition()); + PowerUtils.move(payload.direction(), player, target.blockPosition()); } else if (target instanceof ItemEntity || target instanceof FallingBlockEntity || target instanceof ArmorStand || (target instanceof AbstractMinecart && !target.isVehicle())) { - PowerUtils.move(data.direction() / 2.0, target, player.blockPosition()); + PowerUtils.move(payload.direction() / 2.0, target, player.blockPosition()); // Split the difference } else if (!(target instanceof ThrowableItemProjectile)) { - PowerUtils.move(data.direction() / 2.0, target, player.blockPosition()); - PowerUtils.move(data.direction() / 2.0, player, target.blockPosition()); + if (target instanceof ServerPlayer targetPlayer) { + ExtrasSetup.METAL_USED_ON_PLAYER_TRIGGER.get().trigger(targetPlayer, which, data.isEnhanced()); + } + PowerUtils.move(payload.direction() / 2.0, target, player.blockPosition()); + PowerUtils.move(payload.direction() / 2.0, player, target.blockPosition()); } } } @@ -101,7 +111,7 @@ public static void toggleBurnRequest(final ToggleBurnPayload payload, final Play ctx.workHandler().submitAsync(() -> { ServerPlayer player = (ServerPlayer) ctx.player().get(); Metal mt = payload.metal(); - var data = player.getData(AllomancerAttachment.ALLOMANCY_DATA); + IAllomancerData data = player.getData(AllomancerAttachment.ALLOMANCY_DATA); boolean value = payload.on(); @@ -128,21 +138,25 @@ public static void toggleBurnRequest(final ToggleBurnPayload payload, final Play public static void updateEnhanced(final EnhanceTimePayload payload, final PlayPayloadContext ctx) { ctx.workHandler().submitAsync(() -> { - Player source = ctx.player().get(); - - if (!source.getData(AllomancerAttachment.ALLOMANCY_DATA).isBurning(Metal.NICROSIL)) { + ServerPlayer source = (ServerPlayer) ctx.player().get(); + var data = source.getData(AllomancerAttachment.ALLOMANCY_DATA); + if (!data.isBurning(Metal.NICROSIL)) { Allomancy.LOGGER.warn("Illegal use of Nicrosil by player: {}!", source); ctx.packetHandler().disconnect(Component.translatable("allomancy.networking.kicked", "Tried to mark other player as enhanced while not burning Nicrosil!")); return; } Entity e = ctx.level().get().getEntity(payload.entityID()); - if (e instanceof ServerPlayer player && !PowerUtils.hasTinFoilHat(player)) { - var target_data = player.getData(AllomancerAttachment.ALLOMANCY_DATA); - target_data.setEnhanced(payload.enhanceTime()); - // broadcast back to player and tracking - Network.sync(payload, player); + ExtrasSetup.METAL_USED_ON_ENTITY_TRIGGER.get().trigger(source, e, Metal.NICROSIL, data.isEnhanced()); + if (e instanceof ServerPlayer player) { + ExtrasSetup.METAL_USED_ON_PLAYER_TRIGGER.get().trigger(player, Metal.NICROSIL, data.isEnhanced()); + if (!PowerUtils.hasTinFoilHat(player)) { + var target_data = player.getData(AllomancerAttachment.ALLOMANCY_DATA); + target_data.setEnhanced(payload.enhanceTime()); + // broadcast back to player and tracking + Network.sync(payload, player); + } } }).exceptionally(e -> { Allomancy.LOGGER.error("Failed to handle sever updateEnhanced", e);