diff --git a/src/main/java/com/lovetropics/minigames/LoveTropics.java b/src/main/java/com/lovetropics/minigames/LoveTropics.java index 90f56375b..185be553b 100644 --- a/src/main/java/com/lovetropics/minigames/LoveTropics.java +++ b/src/main/java/com/lovetropics/minigames/LoveTropics.java @@ -170,6 +170,7 @@ public LoveTropics(IEventBus modBus, ModContainer modContainer) { SoundRegistry.REGISTER.register(modBus); MinigameDataComponents.REGISTER.register(modBus); BiodiversityBlitz.DATA_COMPONENTS.register(modBus); + RiverRace.DATA_COMPONENTS.register(modBus); VoidChunkGenerator.REGISTER.register(modBus); LoveTropicsEntityOptions.register(); diff --git a/src/main/java/com/lovetropics/minigames/common/content/river_race/RiverRace.java b/src/main/java/com/lovetropics/minigames/common/content/river_race/RiverRace.java index fdc8876d5..123be6777 100644 --- a/src/main/java/com/lovetropics/minigames/common/content/river_race/RiverRace.java +++ b/src/main/java/com/lovetropics/minigames/common/content/river_race/RiverRace.java @@ -12,12 +12,19 @@ import com.tterrag.registrate.providers.ProviderType; import com.tterrag.registrate.util.entry.BlockEntityEntry; import com.tterrag.registrate.util.entry.BlockEntry; +import net.minecraft.core.component.DataComponentType; import net.minecraft.core.registries.Registries; +import net.minecraft.util.Unit; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockBehaviour; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; public class RiverRace { private static final LoveTropicsRegistrate REGISTRATE = LoveTropics.registrate(); + + public static final DeferredRegister.DataComponents DATA_COMPONENTS = DeferredRegister.createDataComponents(LoveTropics.ID); + public static final GameBehaviorEntry TRIVIA_BEHAVIOUR = REGISTRATE.object("trivia").behavior(TriviaBehaviour.CODEC).register(); public static final GameBehaviorEntry START_MICROGAMES_ACTION = REGISTRATE.object("start_microgames").behavior(StartMicrogamesAction.CODEC).register(); public static final GameBehaviorEntry VICTORY_POINTS_BEHAVIOR = REGISTRATE.object("victory_points").behavior(VictoryPointsBehavior.CODEC).register(); @@ -27,7 +34,6 @@ public class RiverRace { public static final GameBehaviorEntry COLLECTABLES_BEHAVIOUR = REGISTRATE.object("river_race_collectables").behavior(CollectablesBehaviour.CODEC).register(); public static final GameBehaviorEntry PREVENT_BREAK_BEHAVIOUR = REGISTRATE.object("prevent_break").behavior(PreventBreakBehaviour.CODEC).register(); - public static final BlockEntry TRIVIA_GATE = REGISTRATE .block("trivia_gate", TriviaBlock.GateTriviaBlock::new) .initialProperties(() -> Blocks.BEDROCK) @@ -79,6 +85,10 @@ public class RiverRace { .validBlocks(TRIVIA_GATE, TRIVIA_COLLECTABLE, TRIVIA_VICTORY).register(); public static final BlockEntityEntry TRIVIA_CHEST_BLOCK_ENTITY = BlockEntityEntry.cast(REGISTRATE.get("trivia_chest", Registries.BLOCK_ENTITY_TYPE)); + public static final DeferredHolder, DataComponentType> COLLECTABLE_MARKER = DATA_COMPONENTS.registerComponentType( + "river_race_collectable_marker", + builder -> builder.persistent(Unit.CODEC) + ); public static void init() { } diff --git a/src/main/java/com/lovetropics/minigames/common/core/game/behavior/GameBehaviorTypes.java b/src/main/java/com/lovetropics/minigames/common/core/game/behavior/GameBehaviorTypes.java index 3bf139c4c..4c5ab1f45 100644 --- a/src/main/java/com/lovetropics/minigames/common/core/game/behavior/GameBehaviorTypes.java +++ b/src/main/java/com/lovetropics/minigames/common/core/game/behavior/GameBehaviorTypes.java @@ -106,6 +106,7 @@ import com.lovetropics.minigames.common.core.game.behavior.instances.trigger.SetRoleTrigger; import com.lovetropics.minigames.common.core.game.behavior.instances.trigger.TopPlayerTrigger; import com.lovetropics.minigames.common.core.game.behavior.instances.trigger.WeatherChangeTrigger; +import com.lovetropics.minigames.common.core.game.behavior.instances.trigger.WhileInInventoryTrigger; import com.lovetropics.minigames.common.core.game.behavior.instances.trigger.WhileInRegionTrigger; import com.lovetropics.minigames.common.core.game.behavior.instances.trigger.phase.GameReadyTrigger; import com.lovetropics.minigames.common.core.game.behavior.instances.trigger.phase.GameTickTrigger; @@ -271,6 +272,7 @@ public class GameBehaviorTypes { public static final GameBehaviorEntry GIVE_ITEMS_TO_KILLER = register("give_items_to_killer", GiveItemsToKillerBehavior.CODEC); public static final GameBehaviorEntry COUNTDOWN_EFFECTS = register("countdown_effects", CountdownEffectsBehavior.CODEC); public static final GameBehaviorEntry TRIGGER_EVERY_PACKAGE = register("trigger_every_package", TriggerEveryPackageBehavior.CODEC); + public static final GameBehaviorEntry WHILE_IN_INVENTORY = register("while_in_inventory", WhileInInventoryTrigger.CODEC); public static final GameBehaviorEntry SETUP_INTEGRATIONS = register("setup_integrations", SetupIntegrationsBehavior.CODEC); public static final GameBehaviorEntry ASSIGN_PLAYER_ROLES = register("assign_player_roles", AssignPlayerRolesBehavior.CODEC); diff --git a/src/main/java/com/lovetropics/minigames/common/core/game/behavior/instances/trigger/WhileInInventoryTrigger.java b/src/main/java/com/lovetropics/minigames/common/core/game/behavior/instances/trigger/WhileInInventoryTrigger.java new file mode 100644 index 000000000..4dcdaa7ce --- /dev/null +++ b/src/main/java/com/lovetropics/minigames/common/core/game/behavior/instances/trigger/WhileInInventoryTrigger.java @@ -0,0 +1,78 @@ +package com.lovetropics.minigames.common.core.game.behavior.instances.trigger; + +import com.lovetropics.minigames.common.core.game.IGamePhase; +import com.lovetropics.minigames.common.core.game.behavior.GameBehaviorType; +import com.lovetropics.minigames.common.core.game.behavior.GameBehaviorTypes; +import com.lovetropics.minigames.common.core.game.behavior.IGameBehavior; +import com.lovetropics.minigames.common.core.game.behavior.action.GameActionContext; +import com.lovetropics.minigames.common.core.game.behavior.action.GameActionList; +import com.lovetropics.minigames.common.core.game.behavior.event.EventRegistrar; +import com.lovetropics.minigames.common.core.game.behavior.event.GamePlayerEvents; +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import net.minecraft.advancements.critereon.ItemPredicate; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.inventory.CraftingContainer; + +import java.util.UUID; +import java.util.function.Supplier; + +public record WhileInInventoryTrigger( + ItemPredicate itemPredicate, + GameActionList apply, + GameActionList clear, + boolean stack +) implements IGameBehavior { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(i -> i.group( + ItemPredicate.CODEC.fieldOf("item").forGetter(WhileInInventoryTrigger::itemPredicate), + GameActionList.PLAYER_CODEC.optionalFieldOf("apply", GameActionList.EMPTY).forGetter(WhileInInventoryTrigger::apply), + GameActionList.PLAYER_CODEC.optionalFieldOf("clear", GameActionList.EMPTY).forGetter(WhileInInventoryTrigger::clear), + Codec.BOOL.optionalFieldOf("stack", false).forGetter(WhileInInventoryTrigger::stack) + ).apply(i, WhileInInventoryTrigger::new)); + + @Override + public void register(IGamePhase game, EventRegistrar events) { + apply.register(game, events); + clear.register(game, events); + + Object2IntMap countByPlayer = new Object2IntOpenHashMap<>(); + events.listen(GamePlayerEvents.TICK, player -> { + int oldCount = countByPlayer.getInt(player.getUUID()); + int newCount = countInInventory(player); + if (newCount != oldCount) { + countByPlayer.put(player.getUUID(), newCount); + onItemCountChanged(game, player, oldCount, newCount); + } + }); + } + + private void onItemCountChanged(IGamePhase game, ServerPlayer player, int oldCount, int newCount) { + if (!stack) { + oldCount = Math.min(oldCount, 1); + newCount = Math.min(newCount, 1); + } + + if (newCount > oldCount) { + for (int i = 0; i < newCount - oldCount; i++) { + apply.apply(game, GameActionContext.EMPTY, player); + } + } else { + for (int i = 0; i < oldCount - newCount; i++) { + clear.apply(game, GameActionContext.EMPTY, player); + } + } + } + + private int countInInventory(ServerPlayer player) { + CraftingContainer craftSlots = player.inventoryMenu.getCraftSlots(); + return player.getInventory().clearOrCountMatchingItems(itemPredicate, 0, craftSlots); + } + + @Override + public Supplier> behaviorType() { + return GameBehaviorTypes.WHILE_IN_INVENTORY; + } +}