From d9052a869fb44a47ffff141c8a0b4382bc160838 Mon Sep 17 00:00:00 2001 From: Hugman Date: Mon, 18 Nov 2024 20:13:40 +0100 Subject: [PATCH 01/13] Move and data-drive UHCConfig --- src/main/java/com/hugman/uhc/UHC.java | 4 +- .../hugman/uhc/command/ModulesCommand.java | 6 +-- .../hugman/uhc/config/UHCChapterConfig.java | 18 ------- .../java/com/hugman/uhc/config/UHCConfig.java | 41 +++------------- .../com/hugman/uhc/config/UHCGameConfig.java | 48 +++++++++++++++++++ .../com/hugman/uhc/config/UHCMapConfig.java | 9 +++- .../hugman/uhc/config/UHCTimersConfig.java | 23 +++++++++ .../java/com/hugman/uhc/game/UHCLogic.java | 20 ++++---- .../com/hugman/uhc/game/phase/UHCActive.java | 22 ++++----- .../hugman/uhc/game/phase/UHCGamePhase.java | 28 +++++++++++ .../com/hugman/uhc/game/phase/UHCWaiting.java | 11 +++-- .../hugman/uhc/map/ModuledChunkGenerator.java | 12 ++--- src/main/java/com/hugman/uhc/map/UHCMap.java | 10 ++-- .../hugman/uhc/registry/UHCRegistryKeys.java | 3 ++ .../data/doublerunner/plasmid/game/duos.json | 28 +---------- .../data/doublerunner/plasmid/game/solo.json | 29 +---------- .../doublerunner/plasmid/game/squads.json | 28 +---------- .../data/doublerunner/plasmid/game/test.json | 17 +++++++ .../data/doublerunner/plasmid/game/trios.json | 28 +---------- .../doublerunner/uhc/config/standard.json | 24 ++++++++++ .../uhc/module/faster_resources_plus.json | 2 +- .../resources/data/uhc/plasmid/game/duos.json | 30 ++---------- .../resources/data/uhc/plasmid/game/solo.json | 29 +---------- .../data/uhc/plasmid/game/squads.json | 30 ++---------- .../data/uhc/plasmid/game/trios.json | 30 ++---------- .../data/uhc/uhc/config/standard.json | 20 ++++++++ .../resources/data/uhcrun/lang/en_us.json | 2 +- .../data/uhcrun/plasmid/game/duos.json | 31 ++---------- .../data/uhcrun/plasmid/game/solo.json | 32 ++----------- .../data/uhcrun/plasmid/game/squads.json | 31 ++---------- .../data/uhcrun/plasmid/game/trios.json | 31 ++---------- .../data/uhcrun/uhc/config/standard.json | 24 ++++++++++ 32 files changed, 277 insertions(+), 424 deletions(-) delete mode 100644 src/main/java/com/hugman/uhc/config/UHCChapterConfig.java create mode 100644 src/main/java/com/hugman/uhc/config/UHCGameConfig.java create mode 100644 src/main/java/com/hugman/uhc/config/UHCTimersConfig.java create mode 100644 src/main/java/com/hugman/uhc/game/phase/UHCGamePhase.java create mode 100644 src/main/resources/data/doublerunner/plasmid/game/test.json create mode 100644 src/main/resources/data/doublerunner/uhc/config/standard.json create mode 100644 src/main/resources/data/uhc/uhc/config/standard.json create mode 100644 src/main/resources/data/uhcrun/uhc/config/standard.json diff --git a/src/main/java/com/hugman/uhc/UHC.java b/src/main/java/com/hugman/uhc/UHC.java index df9d48d..1b86baf 100644 --- a/src/main/java/com/hugman/uhc/UHC.java +++ b/src/main/java/com/hugman/uhc/UHC.java @@ -2,7 +2,7 @@ import com.google.common.reflect.Reflection; import com.hugman.uhc.command.ModulesCommand; -import com.hugman.uhc.config.UHCConfig; +import com.hugman.uhc.config.UHCGameConfig; import com.hugman.uhc.game.phase.UHCWaiting; import com.hugman.uhc.modifier.ModifierType; import com.hugman.uhc.module.Module; @@ -26,7 +26,7 @@ public void onInitialize() { UHCRegistryKeys.registerDynamics(); CommandRegistrationCallback.EVENT.register((dispatcher, dedicated, environment) -> ModulesCommand.register(dispatcher)); - GameType.register(UHC.id("standard"), UHCConfig.CODEC, UHCWaiting::open); + GameType.register(UHC.id("standard"), UHCGameConfig.CODEC, UHCWaiting::open); } public static Identifier id(String path) { diff --git a/src/main/java/com/hugman/uhc/command/ModulesCommand.java b/src/main/java/com/hugman/uhc/command/ModulesCommand.java index 0e5a660..ac87e81 100644 --- a/src/main/java/com/hugman/uhc/command/ModulesCommand.java +++ b/src/main/java/com/hugman/uhc/command/ModulesCommand.java @@ -1,6 +1,6 @@ package com.hugman.uhc.command; -import com.hugman.uhc.config.UHCConfig; +import com.hugman.uhc.config.UHCGameConfig; import com.hugman.uhc.module.Module; import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; @@ -37,14 +37,14 @@ public static void register(CommandDispatcher dispatcher) { public static boolean isSourceInUHC(ServerCommandSource source) { GameSpace gameSpace = GameSpaceManager.get().byWorld(source.getWorld()); if (gameSpace != null) { - return gameSpace.getMetadata().sourceConfig().value().config() instanceof UHCConfig; + return gameSpace.getMetadata().sourceConfig().value().config() instanceof UHCGameConfig; } return false; } private static int displayModules(CommandContext context) throws CommandSyntaxException { ServerCommandSource source = context.getSource(); - RegistryEntryList moduleEntries = ((UHCConfig) Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())).getMetadata().sourceConfig().value().config()).modules(); + RegistryEntryList moduleEntries = ((UHCGameConfig) Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())).getMetadata().sourceConfig().value().config()).uhcConfig().value().modules(); if (moduleEntries.size() != 0) { ScreenHandlerType type = Registries.SCREEN_HANDLER.get(Identifier.of("generic_9x" + MathHelper.clamp(1, MathHelper.ceil((float) moduleEntries.size() / 9), 6))); SimpleGui gui = new SimpleGui(type, source.getPlayer(), false); diff --git a/src/main/java/com/hugman/uhc/config/UHCChapterConfig.java b/src/main/java/com/hugman/uhc/config/UHCChapterConfig.java deleted file mode 100644 index ffc5fc1..0000000 --- a/src/main/java/com/hugman/uhc/config/UHCChapterConfig.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.hugman.uhc.config; - -import com.hugman.uhc.util.DoubleRange; -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; - -public record UHCChapterConfig(DoubleRange inCagesTime, DoubleRange invulnerabilityTime, DoubleRange warmupTime, - DoubleRange deathmatchTime) { - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - DoubleRange.CODEC.optionalFieldOf("in_cages", new DoubleRange(30, 75)).forGetter(UHCChapterConfig::inCagesTime), - DoubleRange.CODEC.optionalFieldOf("invulnerability", new DoubleRange(60, 60)).forGetter(UHCChapterConfig::invulnerabilityTime), - DoubleRange.CODEC.fieldOf("warmup").forGetter(UHCChapterConfig::warmupTime), - DoubleRange.CODEC.optionalFieldOf("deathmatch", new DoubleRange(2400, 2400)).forGetter(UHCChapterConfig::deathmatchTime) - ).apply(instance, UHCChapterConfig::new)); - - -} - diff --git a/src/main/java/com/hugman/uhc/config/UHCConfig.java b/src/main/java/com/hugman/uhc/config/UHCConfig.java index eb5373e..2932fd7 100644 --- a/src/main/java/com/hugman/uhc/config/UHCConfig.java +++ b/src/main/java/com/hugman/uhc/config/UHCConfig.java @@ -1,50 +1,23 @@ package com.hugman.uhc.config; -import com.hugman.uhc.modifier.Modifier; -import com.hugman.uhc.modifier.ModifierType; import com.hugman.uhc.module.Module; +import com.hugman.uhc.registry.UHCRegistryKeys; import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.registry.entry.RegistryElementCodec; +import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryEntryList; -import xyz.nucleoid.plasmid.api.game.common.config.WaitingLobbyConfig; - -import java.util.ArrayList; -import java.util.List; public record UHCConfig( - WaitingLobbyConfig players, - int teamSize, UHCMapConfig mapConfig, - UHCChapterConfig chapterConfig, + UHCTimersConfig chapterConfig, RegistryEntryList modules ) { - public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( - WaitingLobbyConfig.CODEC.fieldOf("players").forGetter(UHCConfig::players), - Codec.INT.fieldOf("team_size").forGetter(UHCConfig::teamSize), + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( UHCMapConfig.CODEC.fieldOf("map").forGetter(UHCConfig::mapConfig), - UHCChapterConfig.CODEC.fieldOf("chapters").forGetter(UHCConfig::chapterConfig), + UHCTimersConfig.CODEC.optionalFieldOf("chapters", UHCTimersConfig.DEFAULT).forGetter(UHCConfig::chapterConfig), Module.ENTRY_LIST_CODEC.optionalFieldOf("modules", RegistryEntryList.of()).forGetter(UHCConfig::modules) ).apply(instance, UHCConfig::new)); - public List getModifiers() { - List modifiers = new ArrayList<>(); - for (var moduleEntry : modules) { - modifiers.addAll(moduleEntry.value().modifiers()); - } - return modifiers; - } - - public List getModifiers(ModifierType type) { - //TODO: cache modules so it's quicker to sort by type - List modifiers = new ArrayList<>(); - for (var moduleEntry : modules) { - for (Modifier modifier : moduleEntry.value().modifiers()) { - if (modifier.getType() == type) { - modifiers.add((V) modifier); - } - } - } - return modifiers; - } + public static final Codec> ENTRY_CODEC = RegistryElementCodec.of(UHCRegistryKeys.UHC_CONFIG, CODEC); } diff --git a/src/main/java/com/hugman/uhc/config/UHCGameConfig.java b/src/main/java/com/hugman/uhc/config/UHCGameConfig.java new file mode 100644 index 0000000..c045488 --- /dev/null +++ b/src/main/java/com/hugman/uhc/config/UHCGameConfig.java @@ -0,0 +1,48 @@ +package com.hugman.uhc.config; + +import com.hugman.uhc.modifier.Modifier; +import com.hugman.uhc.modifier.ModifierType; +import com.hugman.uhc.module.Module; +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.registry.entry.RegistryEntryList; +import net.minecraft.util.dynamic.Codecs; +import xyz.nucleoid.plasmid.api.game.common.config.WaitingLobbyConfig; + +import java.util.ArrayList; +import java.util.List; + +public record UHCGameConfig( + WaitingLobbyConfig players, + int teamSize, + RegistryEntry uhcConfig +) { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + WaitingLobbyConfig.CODEC.fieldOf("players").forGetter(UHCGameConfig::players), + Codecs.POSITIVE_INT.optionalFieldOf("team_size", 1).forGetter(UHCGameConfig::teamSize), + UHCConfig.ENTRY_CODEC.fieldOf("config").forGetter(UHCGameConfig::uhcConfig) + ).apply(instance, UHCGameConfig::new)); + + public List getModifiers() { + List modifiers = new ArrayList<>(); + for (var moduleEntry : uhcConfig.value().modules()) { + modifiers.addAll(moduleEntry.value().modifiers()); + } + return modifiers; + } + + public List getModifiers(ModifierType type) { + //TODO: cache modules so it's quicker to sort by type + List modifiers = new ArrayList<>(); + for (var moduleEntry : uhcConfig.value().modules()) { + for (Modifier modifier : moduleEntry.value().modifiers()) { + if (modifier.getType() == type) { + modifiers.add((V) modifier); + } + } + } + return modifiers; + } +} diff --git a/src/main/java/com/hugman/uhc/config/UHCMapConfig.java b/src/main/java/com/hugman/uhc/config/UHCMapConfig.java index 117a4f4..809fe2d 100644 --- a/src/main/java/com/hugman/uhc/config/UHCMapConfig.java +++ b/src/main/java/com/hugman/uhc/config/UHCMapConfig.java @@ -6,8 +6,13 @@ import net.minecraft.world.dimension.DimensionOptions; -public record UHCMapConfig(DimensionOptions dimension, DoubleRange startSize, DoubleRange endSize, - double shrinkingSpeed, int spawnOffset) { +public record UHCMapConfig( + DimensionOptions dimension, + DoubleRange startSize, + DoubleRange endSize, + double shrinkingSpeed, + int spawnOffset +) { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( DimensionOptions.CODEC.fieldOf("dimension").forGetter(UHCMapConfig::dimension), DoubleRange.CODEC.fieldOf("start_size").forGetter(UHCMapConfig::startSize), diff --git a/src/main/java/com/hugman/uhc/config/UHCTimersConfig.java b/src/main/java/com/hugman/uhc/config/UHCTimersConfig.java new file mode 100644 index 0000000..58fe0b7 --- /dev/null +++ b/src/main/java/com/hugman/uhc/config/UHCTimersConfig.java @@ -0,0 +1,23 @@ +package com.hugman.uhc.config; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +public record UHCTimersConfig( + double cages, + double invulnerability, + double warmup, + double deathmatch +) { + public static final UHCTimersConfig DEFAULT = new UHCTimersConfig(30.0D, 60.0D, 3600.0D, 2400.0D); + + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + Codec.DOUBLE.optionalFieldOf("in_cages", DEFAULT.cages()).forGetter(UHCTimersConfig::cages), + Codec.DOUBLE.optionalFieldOf("invulnerability", DEFAULT.invulnerability()).forGetter(UHCTimersConfig::invulnerability), + Codec.DOUBLE.optionalFieldOf("warmup", DEFAULT.warmup()).forGetter(UHCTimersConfig::warmup), + Codec.DOUBLE.optionalFieldOf("deathmatch", DEFAULT.deathmatch()).forGetter(UHCTimersConfig::deathmatch) + ).apply(instance, UHCTimersConfig::new)); + + +} + diff --git a/src/main/java/com/hugman/uhc/game/UHCLogic.java b/src/main/java/com/hugman/uhc/game/UHCLogic.java index 76d45ce..b0cfecb 100644 --- a/src/main/java/com/hugman/uhc/game/UHCLogic.java +++ b/src/main/java/com/hugman/uhc/game/UHCLogic.java @@ -1,43 +1,43 @@ package com.hugman.uhc.game; -import com.hugman.uhc.config.UHCConfig; +import com.hugman.uhc.config.UHCGameConfig; public class UHCLogic { private static final int HIGH_PLAYER_COUNT = 100; - private final UHCConfig config; + private final UHCGameConfig config; private final float playerDose; - public UHCLogic(UHCConfig config, int playerAmount) { + public UHCLogic(UHCGameConfig config, int playerAmount) { this.config = config; this.playerDose = (playerAmount - (float) config.players().minPlayers()) / ((float) Math.max(config.players().minPlayers(), HIGH_PLAYER_COUNT) - (float) config.players().minPlayers()); } public double getStartMapSize() { - return config.mapConfig().startSize().crossProduct(playerDose); + return config.uhcConfig().value().mapConfig().startSize().crossProduct(playerDose); } public double getEndMapSize() { - return config.mapConfig().endSize().crossProduct(playerDose); + return config.uhcConfig().value().mapConfig().endSize().crossProduct(playerDose); } public long getInCagesTime() { - return (long) (config.chapterConfig().inCagesTime().crossProduct(playerDose) * 20L); + return (long) (config.uhcConfig().value().chapterConfig().cages() * 20L); } public long getInvulnerabilityTime() { - return (long) (config.chapterConfig().invulnerabilityTime().crossProduct(playerDose) * 20L); + return (long) (config.uhcConfig().value().chapterConfig().invulnerability() * 20L); } public long getWarmupTime() { - return (long) (config.chapterConfig().warmupTime().crossProduct(playerDose) * 20L); + return (long) (config.uhcConfig().value().chapterConfig().warmup() * 20L); } public long getDeathmatchTime() { - return (long) (config.chapterConfig().deathmatchTime().crossProduct(playerDose) * 20L); + return (long) (config.uhcConfig().value().chapterConfig().deathmatch() * 20L); } public long getShrinkingTime() { - return (long) ((getStartMapSize() - getEndMapSize()) / config.mapConfig().shrinkingSpeed() * 10L); + return (long) ((getStartMapSize() - getEndMapSize()) / config.uhcConfig().value().mapConfig().shrinkingSpeed() * 10L); } } diff --git a/src/main/java/com/hugman/uhc/game/phase/UHCActive.java b/src/main/java/com/hugman/uhc/game/phase/UHCActive.java index 9666a1b..c7dc6fc 100644 --- a/src/main/java/com/hugman/uhc/game/phase/UHCActive.java +++ b/src/main/java/com/hugman/uhc/game/phase/UHCActive.java @@ -1,7 +1,7 @@ package com.hugman.uhc.game.phase; import com.hugman.uhc.UHC; -import com.hugman.uhc.config.UHCConfig; +import com.hugman.uhc.config.UHCGameConfig; import com.hugman.uhc.game.*; import com.hugman.uhc.modifier.*; import com.hugman.uhc.util.TickUtil; @@ -38,16 +38,12 @@ import xyz.nucleoid.plasmid.api.game.common.team.*; import xyz.nucleoid.plasmid.api.game.event.GameActivityEvents; import xyz.nucleoid.plasmid.api.game.event.GamePlayerEvents; -import xyz.nucleoid.plasmid.api.game.player.JoinAcceptor; -import xyz.nucleoid.plasmid.api.game.player.JoinAcceptorResult; -import xyz.nucleoid.plasmid.api.game.player.JoinIntent; -import xyz.nucleoid.plasmid.api.game.player.PlayerSet; +import xyz.nucleoid.plasmid.api.game.player.*; import xyz.nucleoid.plasmid.api.game.rule.GameRuleType; import xyz.nucleoid.stimuli.event.DroppedItemsResult; import xyz.nucleoid.stimuli.event.EventResult; import xyz.nucleoid.stimuli.event.block.BlockBreakEvent; import xyz.nucleoid.stimuli.event.block.BlockDropItemsEvent; -import xyz.nucleoid.stimuli.event.entity.EntityDamageEvent; import xyz.nucleoid.stimuli.event.entity.EntityDropItemsEvent; import xyz.nucleoid.stimuli.event.player.PlayerDamageEvent; import xyz.nucleoid.stimuli.event.player.PlayerDeathEvent; @@ -60,7 +56,7 @@ public class UHCActive { private final GameSpace gameSpace; private final ServerWorld world; private final GameActivity activity; - private final UHCConfig config; + private final UHCGameConfig config; private Object2ObjectMap participants; private List teamsAlive; @@ -84,7 +80,7 @@ public class UHCActive { private boolean invulnerable; private boolean isFinished = false; - private UHCActive(GameActivity activity, GameSpace gameSpace, ServerWorld world, UHCConfig config, GlobalWidgets widgets) { + private UHCActive(GameActivity activity, GameSpace gameSpace, ServerWorld world, UHCGameConfig config, GlobalWidgets widgets) { this.activity = activity; this.gameSpace = gameSpace; this.world = world; @@ -135,7 +131,7 @@ private void fillTeams() { }); } - public static void start(GameSpace gameSpace, ServerWorld world, UHCConfig config) { + public static void start(GameSpace gameSpace, ServerWorld world, UHCGameConfig config) { gameSpace.setActivity(activity -> { GlobalWidgets widgets = GlobalWidgets.addTo(activity); UHCActive active = new UHCActive(activity, gameSpace, world, config, widgets); @@ -149,7 +145,7 @@ public static void start(GameSpace gameSpace, ServerWorld world, UHCConfig confi activity.listen(GameActivityEvents.ENABLE, active::enable); - activity.listen(GamePlayerEvents.OFFER, offer -> offer.intent() == JoinIntent.SPECTATE ? offer.accept() : offer.pass()); + activity.listen(GamePlayerEvents.OFFER, JoinOffer::acceptSpectators); activity.listen(GamePlayerEvents.ACCEPT, active::acceptPlayer); activity.listen(GamePlayerEvents.LEAVE, active::playerLeave); @@ -405,8 +401,8 @@ private void tpToCages() { for (GameTeam team : teamsAlive) { double theta = ((double) index++ / teamsAlive.size()) * 2 * Math.PI; - int x = MathHelper.floor(Math.cos(theta) * (this.logic.getStartMapSize() / 2 - this.config.mapConfig().spawnOffset())); - int z = MathHelper.floor(Math.sin(theta) * (this.logic.getStartMapSize() / 2 - this.config.mapConfig().spawnOffset())); + int x = MathHelper.floor(Math.cos(theta) * (this.logic.getStartMapSize() / 2 - this.config.uhcConfig().value().mapConfig().spawnOffset())); + int z = MathHelper.floor(Math.sin(theta) * (this.logic.getStartMapSize() / 2 - this.config.uhcConfig().value().mapConfig().spawnOffset())); this.spawnLogic.summonCage(team, x, z); teamManager.playersIn(team.key()).forEach(player -> this.spawnLogic.putParticipantInCage(team, player)); @@ -449,7 +445,7 @@ private void sendWarning(String s, Object... args) { } public void sendModuleListToChat() { - var moduleEntries = this.config.modules(); + var moduleEntries = this.config.uhcConfig().value().modules(); if (moduleEntries.size() > 0) { MutableText text = Text.literal("\n").append(Text.translatable("text.uhc.enabled_modules").formatted(Formatting.GOLD)); moduleEntries.forEach(moduleEntry -> { diff --git a/src/main/java/com/hugman/uhc/game/phase/UHCGamePhase.java b/src/main/java/com/hugman/uhc/game/phase/UHCGamePhase.java new file mode 100644 index 0000000..c156caf --- /dev/null +++ b/src/main/java/com/hugman/uhc/game/phase/UHCGamePhase.java @@ -0,0 +1,28 @@ +package com.hugman.uhc.game.phase; + +import net.minecraft.util.StringIdentifiable; + +public enum UHCGamePhase implements StringIdentifiable { + WARMUP("warmup"), + FIGHT("fight"); + + public static final StringIdentifiable.EnumCodec CODEC = StringIdentifiable.createCodec(UHCGamePhase::values); + private final String id; + + UHCGamePhase(final String id) { + this.id = id; + } + + public String getId() { + return this.id; + } + + public static UHCGamePhase getFromId(String id) { + return CODEC.byId(id); + } + + @Override + public String asString() { + return this.id; + } +} diff --git a/src/main/java/com/hugman/uhc/game/phase/UHCWaiting.java b/src/main/java/com/hugman/uhc/game/phase/UHCWaiting.java index 589c46a..c0dca2c 100644 --- a/src/main/java/com/hugman/uhc/game/phase/UHCWaiting.java +++ b/src/main/java/com/hugman/uhc/game/phase/UHCWaiting.java @@ -1,6 +1,6 @@ package com.hugman.uhc.game.phase; -import com.hugman.uhc.config.UHCConfig; +import com.hugman.uhc.config.UHCGameConfig; import com.hugman.uhc.game.UHCSpawner; import com.hugman.uhc.map.UHCMap; import net.minecraft.server.world.ServerWorld; @@ -21,8 +21,13 @@ import xyz.nucleoid.stimuli.event.player.PlayerDamageEvent; import xyz.nucleoid.stimuli.event.player.PlayerDeathEvent; -public record UHCWaiting(GameSpace gameSpace, ServerWorld world, UHCConfig config, TeamManager teamManager) { - public static GameOpenProcedure open(GameOpenContext context) { +public record UHCWaiting( + GameSpace gameSpace, + ServerWorld world, + UHCGameConfig config, + TeamManager teamManager +) { + public static GameOpenProcedure open(GameOpenContext context) { UHCMap map = UHCMap.of(context.config()); return context.openWithWorld(map.createRuntimeWorldConfig(), (activity, world) -> { diff --git a/src/main/java/com/hugman/uhc/map/ModuledChunkGenerator.java b/src/main/java/com/hugman/uhc/map/ModuledChunkGenerator.java index 1ca7484..8ffbef3 100644 --- a/src/main/java/com/hugman/uhc/map/ModuledChunkGenerator.java +++ b/src/main/java/com/hugman/uhc/map/ModuledChunkGenerator.java @@ -1,6 +1,6 @@ package com.hugman.uhc.map; -import com.hugman.uhc.config.UHCConfig; +import com.hugman.uhc.config.UHCGameConfig; import com.hugman.uhc.modifier.ModifierType; import com.hugman.uhc.modifier.PlacedFeaturesModifier; import com.mojang.datafixers.util.Pair; @@ -40,12 +40,12 @@ import java.util.function.Supplier; public class ModuledChunkGenerator extends GameChunkGenerator implements ChunkGeneratorSettingsProvider { - private final UHCConfig config; + private final UHCGameConfig config; private final long seed; private final ChunkGenerator subGenerator; private final ChunkGeneratorSettings settings; - public ModuledChunkGenerator(BiomeSource biomeSource, UHCConfig config, long seed, ChunkGenerator subGenerator, ChunkGeneratorSettings settings) { + public ModuledChunkGenerator(BiomeSource biomeSource, UHCGameConfig config, long seed, ChunkGenerator subGenerator, ChunkGeneratorSettings settings) { super(biomeSource); this.config = config; this.seed = seed; @@ -53,9 +53,9 @@ public ModuledChunkGenerator(BiomeSource biomeSource, UHCConfig config, long see this.settings = settings; } - public static ModuledChunkGenerator of(UHCConfig config, long seed) { - BiomeSource biomeSource = config.mapConfig().dimension().chunkGenerator().getBiomeSource(); - ChunkGenerator subGenerator = config.mapConfig().dimension().chunkGenerator(); + public static ModuledChunkGenerator of(UHCGameConfig config, long seed) { + BiomeSource biomeSource = config.uhcConfig().value().mapConfig().dimension().chunkGenerator().getBiomeSource(); + ChunkGenerator subGenerator = config.uhcConfig().value().mapConfig().dimension().chunkGenerator(); ChunkGeneratorSettings settings = null; if (subGenerator instanceof NoiseChunkGenerator generator) { settings = generator.getSettings().value(); diff --git a/src/main/java/com/hugman/uhc/map/UHCMap.java b/src/main/java/com/hugman/uhc/map/UHCMap.java index 6062eaf..d75ec45 100644 --- a/src/main/java/com/hugman/uhc/map/UHCMap.java +++ b/src/main/java/com/hugman/uhc/map/UHCMap.java @@ -1,23 +1,23 @@ package com.hugman.uhc.map; -import com.hugman.uhc.config.UHCConfig; +import com.hugman.uhc.config.UHCGameConfig; import net.minecraft.world.GameRules; import net.minecraft.world.gen.GeneratorOptions; import net.minecraft.world.gen.chunk.ChunkGenerator; import xyz.nucleoid.fantasy.RuntimeWorldConfig; public class UHCMap { - private final UHCConfig config; + private final UHCGameConfig config; private final ChunkGenerator chunkGenerator; private final long seed; - public UHCMap(UHCConfig config, ChunkGenerator chunkGenerator, long seed) { + public UHCMap(UHCGameConfig config, ChunkGenerator chunkGenerator, long seed) { this.config = config; this.chunkGenerator = chunkGenerator; this.seed = seed; } - public static UHCMap of(UHCConfig config) { + public static UHCMap of(UHCGameConfig config) { long seed = GeneratorOptions.getRandomSeed(); return new UHCMap(config, ModuledChunkGenerator.of(config, seed), seed); } @@ -29,6 +29,6 @@ public RuntimeWorldConfig createRuntimeWorldConfig() { .setGameRule(GameRules.NATURAL_REGENERATION, false) .setGameRule(GameRules.DO_MOB_SPAWNING, true) .setGameRule(GameRules.DO_DAYLIGHT_CYCLE, true) - .setDimensionType(this.config.mapConfig().dimension().dimensionTypeEntry()); + .setDimensionType(this.config.uhcConfig().value().mapConfig().dimension().dimensionTypeEntry()); } } diff --git a/src/main/java/com/hugman/uhc/registry/UHCRegistryKeys.java b/src/main/java/com/hugman/uhc/registry/UHCRegistryKeys.java index f50e658..64eaed0 100644 --- a/src/main/java/com/hugman/uhc/registry/UHCRegistryKeys.java +++ b/src/main/java/com/hugman/uhc/registry/UHCRegistryKeys.java @@ -1,6 +1,7 @@ package com.hugman.uhc.registry; import com.hugman.uhc.UHC; +import com.hugman.uhc.config.UHCConfig; import com.hugman.uhc.modifier.ModifierType; import com.hugman.uhc.module.Module; import net.fabricmc.fabric.api.event.registry.DynamicRegistries; @@ -10,8 +11,10 @@ public class UHCRegistryKeys { public static final RegistryKey> MODULE = RegistryKey.ofRegistry(UHC.id("module")); public static final RegistryKey>> MODIFIER_TYPE = RegistryKey.ofRegistry(UHC.id("modifier_type")); + public static final RegistryKey> UHC_CONFIG = RegistryKey.ofRegistry(UHC.id("config")); public static void registerDynamics() { DynamicRegistries.register(MODULE, Module.CODEC); + DynamicRegistries.register(UHC_CONFIG, UHCConfig.CODEC); } } diff --git a/src/main/resources/data/doublerunner/plasmid/game/duos.json b/src/main/resources/data/doublerunner/plasmid/game/duos.json index 33f8207..2b0255b 100644 --- a/src/main/resources/data/doublerunner/plasmid/game/duos.json +++ b/src/main/resources/data/doublerunner/plasmid/game/duos.json @@ -1,5 +1,6 @@ { "type": "uhc:standard", + "config": "doublerunner:standard", "name": { "translate": "game.generic.mode", "with": [ @@ -11,34 +12,9 @@ } ] }, - "team_size": 2, "players": { "min": 4, "threshold": 16 }, - "map": { - "dimension": { - "type": "minecraft:overworld", - "generator": { - "type": "minecraft:noise", - "settings": "minecraft:overworld", - "biome_source": { - "type": "minecraft:multi_noise", - "preset": "minecraft:overworld" - } - } - }, - "shrinking_speed": 0.6, - "start_size": { - "min": 200, - "max": 8000 - } - }, - "chapters": { - "warmup": { - "min": 600, - "max": 800 - } - }, - "modules": "#doublerunner:standard" + "team_size": 2 } diff --git a/src/main/resources/data/doublerunner/plasmid/game/solo.json b/src/main/resources/data/doublerunner/plasmid/game/solo.json index 026ff0e..32388e7 100644 --- a/src/main/resources/data/doublerunner/plasmid/game/solo.json +++ b/src/main/resources/data/doublerunner/plasmid/game/solo.json @@ -1,5 +1,6 @@ { "type": "uhc:standard", + "config": "doublerunner:standard", "name": { "translate": "game.generic.mode", "with": [ @@ -11,34 +12,8 @@ } ] }, - "team_size": 1, "players": { "min": 2, "threshold": 8 - }, - "map": { - "dimension": { - "type": "minecraft:overworld", - "generator": { - "type": "minecraft:noise", - "settings": "minecraft:overworld", - "biome_source": { - "type": "minecraft:multi_noise", - "preset": "minecraft:overworld" - } - } - }, - "shrinking_speed": 0.6, - "start_size": { - "min": 200, - "max": 8000 - } - }, - "chapters": { - "warmup": { - "min": 600, - "max": 800 - } - }, - "modules": "#doublerunner:standard" + } } diff --git a/src/main/resources/data/doublerunner/plasmid/game/squads.json b/src/main/resources/data/doublerunner/plasmid/game/squads.json index 54d97fd..8c5379c 100644 --- a/src/main/resources/data/doublerunner/plasmid/game/squads.json +++ b/src/main/resources/data/doublerunner/plasmid/game/squads.json @@ -1,5 +1,6 @@ { "type": "uhc:standard", + "config": "doublerunner:standard", "name": { "translate": "game.generic.mode", "with": [ @@ -11,34 +12,9 @@ } ] }, - "team_size": 4, "players": { "min": 8, "threshold": 32 }, - "map": { - "dimension": { - "type": "minecraft:overworld", - "generator": { - "type": "minecraft:noise", - "settings": "minecraft:overworld", - "biome_source": { - "type": "minecraft:multi_noise", - "preset": "minecraft:overworld" - } - } - }, - "shrinking_speed": 0.6, - "start_size": { - "min": 200, - "max": 8000 - } - }, - "chapters": { - "warmup": { - "min": 600, - "max": 800 - } - }, - "modules": "#doublerunner:standard" + "team_size": 4 } diff --git a/src/main/resources/data/doublerunner/plasmid/game/test.json b/src/main/resources/data/doublerunner/plasmid/game/test.json new file mode 100644 index 0000000..145617e --- /dev/null +++ b/src/main/resources/data/doublerunner/plasmid/game/test.json @@ -0,0 +1,17 @@ +{ + "type": "uhc:standard", + "config": "doublerunner:standard", + "name": { + "translate": "game.generic.mode", + "with": [ + { + "translate": "game.doublerunner" + }, + "test" + ] + }, + "players": { + "min": 1, + "threshold": 1 + } +} diff --git a/src/main/resources/data/doublerunner/plasmid/game/trios.json b/src/main/resources/data/doublerunner/plasmid/game/trios.json index 68e5d86..81254b1 100644 --- a/src/main/resources/data/doublerunner/plasmid/game/trios.json +++ b/src/main/resources/data/doublerunner/plasmid/game/trios.json @@ -1,5 +1,6 @@ { "type": "uhc:standard", + "config": "doublerunner:standard", "name": { "translate": "game.generic.mode", "with": [ @@ -11,34 +12,9 @@ } ] }, - "team_size": 3, "players": { "min": 6, "threshold": 24 }, - "map": { - "dimension": { - "type": "minecraft:overworld", - "generator": { - "type": "minecraft:noise", - "settings": "minecraft:overworld", - "biome_source": { - "type": "minecraft:multi_noise", - "preset": "minecraft:overworld" - } - } - }, - "shrinking_speed": 0.6, - "start_size": { - "min": 200, - "max": 8000 - } - }, - "chapters": { - "warmup": { - "min": 600, - "max": 800 - } - }, - "modules": "#doublerunner:standard" + "team_size": 3 } diff --git a/src/main/resources/data/doublerunner/uhc/config/standard.json b/src/main/resources/data/doublerunner/uhc/config/standard.json new file mode 100644 index 0000000..03eed01 --- /dev/null +++ b/src/main/resources/data/doublerunner/uhc/config/standard.json @@ -0,0 +1,24 @@ +{ + "modules": "#doublerunner:standard", + "map": { + "dimension": { + "type": "minecraft:overworld", + "generator": { + "type": "minecraft:noise", + "settings": "minecraft:overworld", + "biome_source": { + "type": "minecraft:multi_noise", + "preset": "minecraft:overworld" + } + } + }, + "shrinking_speed": 0.6, + "start_size": { + "min": 200, + "max": 8000 + } + }, + "chapters": { + "warmup": 600 + } +} \ No newline at end of file diff --git a/src/main/resources/data/doublerunner/uhc/module/faster_resources_plus.json b/src/main/resources/data/doublerunner/uhc/module/faster_resources_plus.json index cae2784..ade5d1b 100644 --- a/src/main/resources/data/doublerunner/uhc/module/faster_resources_plus.json +++ b/src/main/resources/data/doublerunner/uhc/module/faster_resources_plus.json @@ -31,7 +31,7 @@ "translate": "module_description.uhcrun.animals_and_zombies_drop_books" }, { - "translate": "module_description.uhcrun.sheep_drop_bows" + "translate": "module_description.uhcrun.sheep_drop_bow" }, { "translate": "module_description.uhcrun.chickens_drop_arrows" diff --git a/src/main/resources/data/uhc/plasmid/game/duos.json b/src/main/resources/data/uhc/plasmid/game/duos.json index 8452b95..5b92231 100644 --- a/src/main/resources/data/uhc/plasmid/game/duos.json +++ b/src/main/resources/data/uhc/plasmid/game/duos.json @@ -1,5 +1,6 @@ { "type": "uhc:standard", + "config": "uhc:standard", "name": { "translate": "game.generic.mode", "with": [ @@ -11,34 +12,9 @@ } ] }, - "map": { - "dimension": { - "type": "minecraft:overworld", - "generator": { - "type": "minecraft:noise", - "settings": "minecraft:overworld", - "biome_source": { - "type": "minecraft:multi_noise", - "preset": "minecraft:overworld" - } - } - }, - "shrinking_speed": 0.5, - "start_size": { - "min": 400, - "max": 10000 - } - }, - "team_size": 2, "players": { "min": 4, - "threshold": 16, - "max": 100 + "threshold": 16 }, - "chapters": { - "warmup": { - "min": 2700, - "max": 4200 - } - } + "team_size": 2 } diff --git a/src/main/resources/data/uhc/plasmid/game/solo.json b/src/main/resources/data/uhc/plasmid/game/solo.json index 84457a1..31659bf 100644 --- a/src/main/resources/data/uhc/plasmid/game/solo.json +++ b/src/main/resources/data/uhc/plasmid/game/solo.json @@ -1,5 +1,6 @@ { "type": "uhc:standard", + "config": "uhc:standard", "name": { "translate": "game.generic.mode", "with": [ @@ -11,34 +12,8 @@ } ] }, - "map": { - "dimension": { - "type": "minecraft:overworld", - "generator": { - "type": "minecraft:noise", - "settings": "minecraft:overworld", - "biome_source": { - "type": "minecraft:multi_noise", - "preset": "minecraft:overworld" - } - } - }, - "shrinking_speed": 0.5, - "start_size": { - "min": 400, - "max": 10000 - } - }, - "team_size": 1, "players": { "min": 2, - "threshold": 8, - "max": 100 - }, - "chapters": { - "warmup": { - "min": 2700, - "max": 4200 - } + "threshold": 8 } } diff --git a/src/main/resources/data/uhc/plasmid/game/squads.json b/src/main/resources/data/uhc/plasmid/game/squads.json index 2ae6137..935546b 100644 --- a/src/main/resources/data/uhc/plasmid/game/squads.json +++ b/src/main/resources/data/uhc/plasmid/game/squads.json @@ -1,5 +1,6 @@ { "type": "uhc:standard", + "config": "uhc:standard", "name": { "translate": "game.generic.mode", "with": [ @@ -11,34 +12,9 @@ } ] }, - "team_size": 4, "players": { "min": 8, - "threshold": 32, - "max": 100 + "threshold": 32 }, - "map": { - "dimension": { - "type": "minecraft:overworld", - "generator": { - "type": "minecraft:noise", - "settings": "minecraft:overworld", - "biome_source": { - "type": "minecraft:multi_noise", - "preset": "minecraft:overworld" - } - } - }, - "shrinking_speed": 0.5, - "start_size": { - "min": 400, - "max": 10000 - } - }, - "chapters": { - "warmup": { - "min": 2700, - "max": 4200 - } - } + "team_size": 4 } diff --git a/src/main/resources/data/uhc/plasmid/game/trios.json b/src/main/resources/data/uhc/plasmid/game/trios.json index eed47f8..7917aa2 100644 --- a/src/main/resources/data/uhc/plasmid/game/trios.json +++ b/src/main/resources/data/uhc/plasmid/game/trios.json @@ -1,5 +1,6 @@ { "type": "uhc:standard", + "config": "uhc:standard", "name": { "translate": "game.generic.mode", "with": [ @@ -11,34 +12,9 @@ } ] }, - "team_size": 3, "players": { "min": 6, - "threshold": 24, - "max": 100 + "threshold": 24 }, - "map": { - "dimension": { - "type": "minecraft:overworld", - "generator": { - "type": "minecraft:noise", - "settings": "minecraft:overworld", - "biome_source": { - "type": "minecraft:multi_noise", - "preset": "minecraft:overworld" - } - } - }, - "shrinking_speed": 0.5, - "start_size": { - "min": 400, - "max": 10000 - } - }, - "chapters": { - "warmup": { - "min": 2700, - "max": 4200 - } - } + "team_size": 3 } diff --git a/src/main/resources/data/uhc/uhc/config/standard.json b/src/main/resources/data/uhc/uhc/config/standard.json new file mode 100644 index 0000000..da4c874 --- /dev/null +++ b/src/main/resources/data/uhc/uhc/config/standard.json @@ -0,0 +1,20 @@ +{ + "map": { + "dimension": { + "type": "minecraft:overworld", + "generator": { + "type": "minecraft:noise", + "settings": "minecraft:overworld", + "biome_source": { + "type": "minecraft:multi_noise", + "preset": "minecraft:overworld" + } + } + }, + "shrinking_speed": 0.5, + "start_size": { + "min": 400, + "max": 10000 + } + } +} \ No newline at end of file diff --git a/src/main/resources/data/uhcrun/lang/en_us.json b/src/main/resources/data/uhcrun/lang/en_us.json index b45e702..649e73d 100644 --- a/src/main/resources/data/uhcrun/lang/en_us.json +++ b/src/main/resources/data/uhcrun/lang/en_us.json @@ -28,7 +28,7 @@ "module_description.uhcrun.animals_and_zombies_drop_leather": "Most animals and zombies drop leather", "module_description.uhcrun.animals_and_zombies_drop_books": "Most animals and zombies drop books", "module_description.uhcrun.sheep_drop_strings": "Sheep drop strings", - "module_description.uhcrun.sheep_drop_bow": "Sheep drop bows", + "module_description.uhcrun.sheep_drop_bow": "Sheep drop a bow", "module_description.uhcrun.sugar_cane_drop_paper": "Sugar cane drop paper", "module_description.uhcrun.sugar_cane_drop_enchanting_tables_and_books": "Sugar cane drop enchanting tables and books", "module_description.uhcrun.chickens_drop_arrows": "Chickens drop arrows", diff --git a/src/main/resources/data/uhcrun/plasmid/game/duos.json b/src/main/resources/data/uhcrun/plasmid/game/duos.json index 42d10e8..a405c46 100644 --- a/src/main/resources/data/uhcrun/plasmid/game/duos.json +++ b/src/main/resources/data/uhcrun/plasmid/game/duos.json @@ -1,5 +1,6 @@ { "type": "uhc:standard", + "config": "uhcrun:standard", "name": { "translate": "game.generic.mode", "with": [ @@ -11,35 +12,9 @@ } ] }, - "team_size": 2, "players": { "min": 4, - "threshold": 16, - "max": 100 + "threshold": 16 }, - "map": { - "dimension": { - "type": "minecraft:overworld", - "generator": { - "type": "minecraft:noise", - "settings": "minecraft:overworld", - "biome_source": { - "type": "minecraft:multi_noise", - "preset": "minecraft:overworld" - } - } - }, - "shrinking_speed": 0.6, - "start_size": { - "min": 200, - "max": 8000 - } - }, - "chapters": { - "warmup": { - "min": 1200, - "max": 1400 - } - }, - "modules": "#uhcrun:standard" + "team_size": 2 } diff --git a/src/main/resources/data/uhcrun/plasmid/game/solo.json b/src/main/resources/data/uhcrun/plasmid/game/solo.json index a217d7f..770516f 100644 --- a/src/main/resources/data/uhcrun/plasmid/game/solo.json +++ b/src/main/resources/data/uhcrun/plasmid/game/solo.json @@ -1,5 +1,6 @@ { "type": "uhc:standard", + "config": "uhcrun:standard", "name": { "translate": "game.generic.mode", "with": [ @@ -11,35 +12,8 @@ } ] }, - "team_size": 1, "players": { "min": 2, - "threshold": 8, - "max": 100 - }, - "map": { - "dimension": { - "type": "minecraft:overworld", - "generator": { - "type": "minecraft:noise", - "settings": "minecraft:overworld", - "biome_source": { - "type": "minecraft:multi_noise", - "preset": "minecraft:overworld" - } - } - }, - "shrinking_speed": 0.6, - "start_size": { - "min": 200, - "max": 8000 - } - }, - "chapters": { - "warmup": { - "min": 1200, - "max": 1400 - } - }, - "modules": "#uhcrun:standard" + "threshold": 8 + } } diff --git a/src/main/resources/data/uhcrun/plasmid/game/squads.json b/src/main/resources/data/uhcrun/plasmid/game/squads.json index c7093ee..8e3758b 100644 --- a/src/main/resources/data/uhcrun/plasmid/game/squads.json +++ b/src/main/resources/data/uhcrun/plasmid/game/squads.json @@ -1,5 +1,6 @@ { "type": "uhc:standard", + "config": "uhcrun:standard", "name": { "translate": "game.generic.mode", "with": [ @@ -11,35 +12,9 @@ } ] }, - "team_size": 4, "players": { "min": 8, - "threshold": 32, - "max": 100 + "threshold": 32 }, - "map": { - "dimension": { - "type": "minecraft:overworld", - "generator": { - "type": "minecraft:noise", - "settings": "minecraft:overworld", - "biome_source": { - "type": "minecraft:multi_noise", - "preset": "minecraft:overworld" - } - } - }, - "shrinking_speed": 0.6, - "start_size": { - "min": 200, - "max": 8000 - } - }, - "chapters": { - "warmup": { - "min": 1200, - "max": 1400 - } - }, - "modules": "#uhcrun:standard" + "team_size": 4 } diff --git a/src/main/resources/data/uhcrun/plasmid/game/trios.json b/src/main/resources/data/uhcrun/plasmid/game/trios.json index e1ac9b2..f1ae361 100644 --- a/src/main/resources/data/uhcrun/plasmid/game/trios.json +++ b/src/main/resources/data/uhcrun/plasmid/game/trios.json @@ -1,5 +1,6 @@ { "type": "uhc:standard", + "config": "uhcrun:standard", "name": { "translate": "game.generic.mode", "with": [ @@ -11,35 +12,9 @@ } ] }, - "team_size": 3, "players": { "min": 6, - "threshold": 24, - "max": 100 + "threshold": 24 }, - "map": { - "dimension": { - "type": "minecraft:overworld", - "generator": { - "type": "minecraft:noise", - "settings": "minecraft:overworld", - "biome_source": { - "type": "minecraft:multi_noise", - "preset": "minecraft:overworld" - } - } - }, - "shrinking_speed": 0.6, - "start_size": { - "min": 200, - "max": 8000 - } - }, - "chapters": { - "warmup": { - "min": 1200, - "max": 1400 - } - }, - "modules": "#uhcrun:standard" + "team_size": 3 } diff --git a/src/main/resources/data/uhcrun/uhc/config/standard.json b/src/main/resources/data/uhcrun/uhc/config/standard.json new file mode 100644 index 0000000..87a9f22 --- /dev/null +++ b/src/main/resources/data/uhcrun/uhc/config/standard.json @@ -0,0 +1,24 @@ +{ + "modules": "#uhcrun:standard", + "map": { + "dimension": { + "type": "minecraft:overworld", + "generator": { + "type": "minecraft:noise", + "settings": "minecraft:overworld", + "biome_source": { + "type": "minecraft:multi_noise", + "preset": "minecraft:overworld" + } + } + }, + "shrinking_speed": 0.6, + "start_size": { + "min": 200, + "max": 8000 + } + }, + "chapters": { + "warmup": 1200 + } +} \ No newline at end of file From 8fd8d9ccaba506ab1fa3432f61c0bad5053ec481 Mon Sep 17 00:00:00 2001 From: Hugman Date: Wed, 4 Dec 2024 00:31:28 +0100 Subject: [PATCH 02/13] Bind modules to the game space --- .../hugman/uhc/command/ModulesCommand.java | 13 ++++++- .../com/hugman/uhc/config/UHCGameConfig.java | 29 -------------- .../com/hugman/uhc/game/ModuleManager.java | 38 +++++++++++++++++++ .../com/hugman/uhc/game/UHCAttachments.java | 8 ++++ .../com/hugman/uhc/game/phase/UHCActive.java | 18 +++++---- .../hugman/uhc/map/ModuledChunkGenerator.java | 30 +++++++++------ .../uhc/modifier/BlockLootModifier.java | 8 +++- .../uhc/modifier/EntityLootModifier.java | 7 +++- .../uhc/modifier/PermanentEffectModifier.java | 5 ++- .../uhc/modifier/TraversalBreakModifier.java | 6 ++- 10 files changed, 107 insertions(+), 55 deletions(-) create mode 100644 src/main/java/com/hugman/uhc/game/ModuleManager.java create mode 100644 src/main/java/com/hugman/uhc/game/UHCAttachments.java diff --git a/src/main/java/com/hugman/uhc/command/ModulesCommand.java b/src/main/java/com/hugman/uhc/command/ModulesCommand.java index ac87e81..fa5a79f 100644 --- a/src/main/java/com/hugman/uhc/command/ModulesCommand.java +++ b/src/main/java/com/hugman/uhc/command/ModulesCommand.java @@ -1,6 +1,8 @@ package com.hugman.uhc.command; import com.hugman.uhc.config.UHCGameConfig; +import com.hugman.uhc.game.ModuleManager; +import com.hugman.uhc.game.UHCAttachments; import com.hugman.uhc.module.Module; import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; @@ -19,6 +21,7 @@ import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; +import xyz.nucleoid.plasmid.api.game.GameAttachment; import xyz.nucleoid.plasmid.api.game.GameSpace; import xyz.nucleoid.plasmid.api.game.GameSpaceManager; @@ -44,7 +47,15 @@ public static boolean isSourceInUHC(ServerCommandSource source) { private static int displayModules(CommandContext context) throws CommandSyntaxException { ServerCommandSource source = context.getSource(); - RegistryEntryList moduleEntries = ((UHCGameConfig) Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())).getMetadata().sourceConfig().value().config()).uhcConfig().value().modules(); + // TODO: get modules by the current game space instead + + var attachment = Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())).getAttachment(UHCAttachments.MODULE_MANAGER); + + if(attachment == null) { + throw NO_MODULES_ACTIVATED.create(); + } + + RegistryEntryList moduleEntries = attachment.modules(); if (moduleEntries.size() != 0) { ScreenHandlerType type = Registries.SCREEN_HANDLER.get(Identifier.of("generic_9x" + MathHelper.clamp(1, MathHelper.ceil((float) moduleEntries.size() / 9), 6))); SimpleGui gui = new SimpleGui(type, source.getPlayer(), false); diff --git a/src/main/java/com/hugman/uhc/config/UHCGameConfig.java b/src/main/java/com/hugman/uhc/config/UHCGameConfig.java index c045488..a44e7be 100644 --- a/src/main/java/com/hugman/uhc/config/UHCGameConfig.java +++ b/src/main/java/com/hugman/uhc/config/UHCGameConfig.java @@ -1,19 +1,11 @@ package com.hugman.uhc.config; -import com.hugman.uhc.modifier.Modifier; -import com.hugman.uhc.modifier.ModifierType; -import com.hugman.uhc.module.Module; -import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.registry.entry.RegistryEntryList; import net.minecraft.util.dynamic.Codecs; import xyz.nucleoid.plasmid.api.game.common.config.WaitingLobbyConfig; -import java.util.ArrayList; -import java.util.List; - public record UHCGameConfig( WaitingLobbyConfig players, int teamSize, @@ -24,25 +16,4 @@ public record UHCGameConfig( Codecs.POSITIVE_INT.optionalFieldOf("team_size", 1).forGetter(UHCGameConfig::teamSize), UHCConfig.ENTRY_CODEC.fieldOf("config").forGetter(UHCGameConfig::uhcConfig) ).apply(instance, UHCGameConfig::new)); - - public List getModifiers() { - List modifiers = new ArrayList<>(); - for (var moduleEntry : uhcConfig.value().modules()) { - modifiers.addAll(moduleEntry.value().modifiers()); - } - return modifiers; - } - - public List getModifiers(ModifierType type) { - //TODO: cache modules so it's quicker to sort by type - List modifiers = new ArrayList<>(); - for (var moduleEntry : uhcConfig.value().modules()) { - for (Modifier modifier : moduleEntry.value().modifiers()) { - if (modifier.getType() == type) { - modifiers.add((V) modifier); - } - } - } - return modifiers; - } } diff --git a/src/main/java/com/hugman/uhc/game/ModuleManager.java b/src/main/java/com/hugman/uhc/game/ModuleManager.java new file mode 100644 index 0000000..bf7a994 --- /dev/null +++ b/src/main/java/com/hugman/uhc/game/ModuleManager.java @@ -0,0 +1,38 @@ +package com.hugman.uhc.game; + +import com.hugman.uhc.modifier.Modifier; +import com.hugman.uhc.modifier.ModifierType; +import com.hugman.uhc.module.Module; +import net.minecraft.registry.entry.RegistryEntryList; + +import java.util.ArrayList; +import java.util.List; + +public record ModuleManager( + RegistryEntryList modules +) { + public List getModifiers() { + List modifiers = new ArrayList<>(); + for (var moduleEntry : modules) { + modifiers.addAll(moduleEntry.value().modifiers()); + } + return modifiers; + } + + public List getModifiers(ModifierType type) { + //TODO: cache modules so it's quicker to sort by type + return filter(modules, type); + } + + public static List filter(RegistryEntryList modules, ModifierType type) { + List modifiers = new ArrayList<>(); + for (var moduleEntry : modules) { + for (Modifier modifier : moduleEntry.value().modifiers()) { + if (modifier.getType() == type) { + modifiers.add((V) modifier); + } + } + } + return modifiers; + } +} diff --git a/src/main/java/com/hugman/uhc/game/UHCAttachments.java b/src/main/java/com/hugman/uhc/game/UHCAttachments.java new file mode 100644 index 0000000..b2dac6a --- /dev/null +++ b/src/main/java/com/hugman/uhc/game/UHCAttachments.java @@ -0,0 +1,8 @@ +package com.hugman.uhc.game; + +import com.hugman.uhc.UHC; +import xyz.nucleoid.plasmid.api.game.GameAttachment; + +public class UHCAttachments { + public static final GameAttachment MODULE_MANAGER = GameAttachment.create(UHC.id("module_manager")); +} diff --git a/src/main/java/com/hugman/uhc/game/phase/UHCActive.java b/src/main/java/com/hugman/uhc/game/phase/UHCActive.java index c7dc6fc..d13e020 100644 --- a/src/main/java/com/hugman/uhc/game/phase/UHCActive.java +++ b/src/main/java/com/hugman/uhc/game/phase/UHCActive.java @@ -66,6 +66,7 @@ public class UHCActive { private final UHCSpawner spawnLogic; private final UHCBar bar; private final UHCSideBar sideBar; + private final ModuleManager moduleManager; private long gameStartTick; private long startInvulnerableTick; @@ -93,6 +94,7 @@ private UHCActive(GameActivity activity, GameSpace gameSpace, ServerWorld world, this.spawnLogic = new UHCSpawner(this.world); this.bar = UHCBar.create(widgets, this.gameSpace); this.sideBar = UHCSideBar.create(widgets, gameSpace); + this.moduleManager = new ModuleManager(config.uhcConfig().value().modules()); } private void fillTeams() { @@ -136,6 +138,8 @@ public static void start(GameSpace gameSpace, ServerWorld world, UHCGameConfig c GlobalWidgets widgets = GlobalWidgets.addTo(activity); UHCActive active = new UHCActive(activity, gameSpace, world, config, widgets); + gameSpace.setAttachment(UHCAttachments.MODULE_MANAGER, active.moduleManager); + activity.allow(GameRuleType.CRAFTING); activity.deny(GameRuleType.PORTALS); activity.deny(GameRuleType.PVP); @@ -328,14 +332,14 @@ public void clearPlayer(ServerPlayerEntity player) { } public void refreshPlayerAttributes(ServerPlayerEntity player) { - for (PlayerAttributeModifier piece : this.config.getModifiers(ModifierType.PLAYER_ATTRIBUTE)) { + for (PlayerAttributeModifier piece : this.moduleManager.getModifiers(ModifierType.PLAYER_ATTRIBUTE)) { piece.refreshAttribute(player); } player.networkHandler.sendPacket(new EntityAttributesS2CPacket(player.getId(), player.getAttributes().getTracked())); } public void applyPlayerEffects(ServerPlayerEntity player) { - for (PermanentEffectModifier piece : this.config.getModifiers(ModifierType.PERMANENT_EFFECT)) { + for (PermanentEffectModifier piece : this.moduleManager.getModifiers(ModifierType.PERMANENT_EFFECT)) { piece.setEffect(player); } } @@ -445,7 +449,7 @@ private void sendWarning(String s, Object... args) { } public void sendModuleListToChat() { - var moduleEntries = this.config.uhcConfig().value().modules(); + var moduleEntries = this.moduleManager.modules(); if (moduleEntries.size() > 0) { MutableText text = Text.literal("\n").append(Text.translatable("text.uhc.enabled_modules").formatted(Formatting.GOLD)); moduleEntries.forEach(moduleEntry -> { @@ -487,7 +491,7 @@ private EventResult onPlayerDeath(ServerPlayerEntity player, DamageSource source } private EventResult onBlockBroken(ServerPlayerEntity playerEntity, ServerWorld world, BlockPos pos) { - for (TraversalBreakModifier piece : this.config.getModifiers(ModifierType.TRAVERSAL_BREAK)) { + for (TraversalBreakModifier piece : this.moduleManager.getModifiers(ModifierType.TRAVERSAL_BREAK)) { piece.breakBlock(this.world, playerEntity, pos); } return EventResult.ALLOW; @@ -495,7 +499,7 @@ private EventResult onBlockBroken(ServerPlayerEntity playerEntity, ServerWorld w private EventResult onExplosion(Explosion explosion, List positions) { positions.forEach(pos -> { - for (TraversalBreakModifier piece : this.config.getModifiers(ModifierType.TRAVERSAL_BREAK)) { + for (TraversalBreakModifier piece : this.moduleManager.getModifiers(ModifierType.TRAVERSAL_BREAK)) { piece.breakBlock(this.world, explosion.getCausingEntity(), pos); } }); @@ -505,7 +509,7 @@ private EventResult onExplosion(Explosion explosion, List positions) { private DroppedItemsResult onMobLoot(LivingEntity livingEntity, List itemStacks) { boolean keepOld = true; List stacks = new ArrayList<>(); - for (EntityLootModifier piece : this.config.getModifiers(ModifierType.ENTITY_LOOT)) { + for (EntityLootModifier piece : this.moduleManager.getModifiers(ModifierType.ENTITY_LOOT)) { if (piece.test(livingEntity)) { stacks.addAll(piece.getLoots(this.world, livingEntity)); if (piece.shouldReplace()) keepOld = false; @@ -518,7 +522,7 @@ private DroppedItemsResult onMobLoot(LivingEntity livingEntity, List private DroppedItemsResult onBlockDrop(@Nullable Entity entity, ServerWorld world, BlockPos pos, BlockState state, List itemStacks) { boolean keepOld = true; List stacks = new ArrayList<>(); - for (BlockLootModifier piece : this.config.getModifiers(ModifierType.BLOCK_LOOT)) { + for (BlockLootModifier piece : this.moduleManager.getModifiers(ModifierType.BLOCK_LOOT)) { if (piece.test(state, world.getRandom())) { piece.spawnExperience(world, pos); stacks.addAll(piece.getLoots(world, pos, entity, entity instanceof LivingEntity ? ((LivingEntity) entity).getActiveItem() : ItemStack.EMPTY)); diff --git a/src/main/java/com/hugman/uhc/map/ModuledChunkGenerator.java b/src/main/java/com/hugman/uhc/map/ModuledChunkGenerator.java index 8ffbef3..04661db 100644 --- a/src/main/java/com/hugman/uhc/map/ModuledChunkGenerator.java +++ b/src/main/java/com/hugman/uhc/map/ModuledChunkGenerator.java @@ -1,6 +1,7 @@ package com.hugman.uhc.map; import com.hugman.uhc.config.UHCGameConfig; +import com.hugman.uhc.game.ModuleManager; import com.hugman.uhc.modifier.ModifierType; import com.hugman.uhc.modifier.PlacedFeaturesModifier; import com.mojang.datafixers.util.Pair; @@ -29,25 +30,28 @@ import net.minecraft.world.gen.StructureAccessor; import net.minecraft.world.gen.chunk.*; import net.minecraft.world.gen.chunk.placement.StructurePlacementCalculator; +import net.minecraft.world.gen.feature.PlacedFeature; import net.minecraft.world.gen.noise.NoiseConfig; import net.minecraft.world.gen.structure.Structure; import org.jetbrains.annotations.Nullable; import xyz.nucleoid.fantasy.util.ChunkGeneratorSettingsProvider; import xyz.nucleoid.plasmid.api.game.world.generator.GameChunkGenerator; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; +import java.util.stream.Collectors; public class ModuledChunkGenerator extends GameChunkGenerator implements ChunkGeneratorSettingsProvider { - private final UHCGameConfig config; + private final List placedFeatures; private final long seed; private final ChunkGenerator subGenerator; private final ChunkGeneratorSettings settings; - public ModuledChunkGenerator(BiomeSource biomeSource, UHCGameConfig config, long seed, ChunkGenerator subGenerator, ChunkGeneratorSettings settings) { + public ModuledChunkGenerator(BiomeSource biomeSource, List placedFeatures, long seed, ChunkGenerator subGenerator, ChunkGeneratorSettings settings) { super(biomeSource); - this.config = config; + this.placedFeatures = placedFeatures; this.seed = seed; this.subGenerator = subGenerator; this.settings = settings; @@ -60,7 +64,13 @@ public static ModuledChunkGenerator of(UHCGameConfig config, long seed) { if (subGenerator instanceof NoiseChunkGenerator generator) { settings = generator.getSettings().value(); } - return new ModuledChunkGenerator(biomeSource, config, seed, subGenerator, settings); + + List placedFeatures = ModuleManager.filter(config.uhcConfig().value().modules(), ModifierType.PLACED_FEATURES).stream() + .flatMap(modifier -> modifier.features().stream()) + .map(RegistryEntry::value) + .collect(Collectors.toList()); + + return new ModuledChunkGenerator(biomeSource, placedFeatures, seed, subGenerator, settings); } @Override @@ -74,15 +84,11 @@ public void generateFeatures(StructureWorldAccess world, Chunk chunk, StructureA ChunkRandom chunkRandom = new ChunkRandom(new Xoroshiro128PlusPlusRandom(this.seed)); long popSeed = chunkRandom.setPopulationSeed(world.getSeed(), blockPos.getX(), blockPos.getZ()); - List placedFeaturesModifiers = this.config.getModifiers(ModifierType.PLACED_FEATURES); int i = 0; - for (var modifier : placedFeaturesModifiers) { - for (var entry : modifier.features()) { - chunkRandom.setDecoratorSeed(popSeed, i++, 0); - Supplier s = () -> entry.getKey().map(Object::toString).orElseGet(entry::toString); - world.setCurrentlyGeneratingStructureName(s); - entry.value().generate(world, this, chunkRandom, blockPos); - } + for (var placedFeature : this.placedFeatures) { + chunkRandom.setDecoratorSeed(popSeed, i++, 0); + world.setCurrentlyGeneratingStructureName(() -> "custom UHC feature"); + placedFeature.generate(world, this, chunkRandom, blockPos); } world.setCurrentlyGeneratingStructureName(null); this.subGenerator.generateFeatures(world, chunk, structureAccessor); diff --git a/src/main/java/com/hugman/uhc/modifier/BlockLootModifier.java b/src/main/java/com/hugman/uhc/modifier/BlockLootModifier.java index 1c076f0..2426ff7 100644 --- a/src/main/java/com/hugman/uhc/modifier/BlockLootModifier.java +++ b/src/main/java/com/hugman/uhc/modifier/BlockLootModifier.java @@ -24,8 +24,12 @@ import java.util.List; import java.util.Optional; -public record BlockLootModifier(boolean replace, RuleTest predicate, Optional> lootTable, - int experience) implements Modifier { +public record BlockLootModifier( + boolean replace, + RuleTest predicate, + Optional> lootTable, + int experience +) implements Modifier { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( Codec.BOOL.optionalFieldOf("replace", true).forGetter(BlockLootModifier::replace), RuleTest.TYPE_CODEC.fieldOf("target").forGetter(BlockLootModifier::predicate), diff --git a/src/main/java/com/hugman/uhc/modifier/EntityLootModifier.java b/src/main/java/com/hugman/uhc/modifier/EntityLootModifier.java index ab430ab..73d5b40 100644 --- a/src/main/java/com/hugman/uhc/modifier/EntityLootModifier.java +++ b/src/main/java/com/hugman/uhc/modifier/EntityLootModifier.java @@ -20,8 +20,11 @@ import java.util.List; import java.util.Optional; -public record EntityLootModifier(boolean replace, RegistryEntryList> entities, - Optional> lootTable) implements Modifier { +public record EntityLootModifier( + boolean replace, + RegistryEntryList> entities, + Optional> lootTable +) implements Modifier { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( Codec.BOOL.optionalFieldOf("replace", true).forGetter(EntityLootModifier::replace), RegistryCodecs.entryList(RegistryKeys.ENTITY_TYPE).optionalFieldOf("entities", RegistryEntryList.empty()).forGetter(EntityLootModifier::entities), diff --git a/src/main/java/com/hugman/uhc/modifier/PermanentEffectModifier.java b/src/main/java/com/hugman/uhc/modifier/PermanentEffectModifier.java index 14e235d..1f32078 100644 --- a/src/main/java/com/hugman/uhc/modifier/PermanentEffectModifier.java +++ b/src/main/java/com/hugman/uhc/modifier/PermanentEffectModifier.java @@ -8,7 +8,10 @@ import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.server.network.ServerPlayerEntity; -public record PermanentEffectModifier(RegistryEntry effect, int amplifier) implements Modifier { +public record PermanentEffectModifier( + RegistryEntry effect, + int amplifier +) implements Modifier { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( StatusEffect.ENTRY_CODEC.fieldOf("effect").forGetter(PermanentEffectModifier::effect), Codec.intRange(0, Integer.MAX_VALUE).optionalFieldOf("amplifier", 0).forGetter(PermanentEffectModifier::amplifier) diff --git a/src/main/java/com/hugman/uhc/modifier/TraversalBreakModifier.java b/src/main/java/com/hugman/uhc/modifier/TraversalBreakModifier.java index b96b12f..205be90 100644 --- a/src/main/java/com/hugman/uhc/modifier/TraversalBreakModifier.java +++ b/src/main/java/com/hugman/uhc/modifier/TraversalBreakModifier.java @@ -15,7 +15,11 @@ import org.jetbrains.annotations.Nullable; import xyz.nucleoid.plasmid.api.util.BlockTraversal; -public record TraversalBreakModifier(RuleTest predicate, int amount, boolean includeLeaves) implements Modifier { +public record TraversalBreakModifier( + RuleTest predicate, + int amount, + boolean includeLeaves +) implements Modifier { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( RuleTest.TYPE_CODEC.fieldOf("target").forGetter(module -> module.predicate), Codec.intRange(0, Integer.MAX_VALUE).optionalFieldOf("amount", 128).forGetter(module -> module.amount), From 8a946e64970f077b933b2de2821ffd0fb894b9de Mon Sep 17 00:00:00 2001 From: Hugman Date: Thu, 5 Dec 2024 01:14:14 +0100 Subject: [PATCH 03/13] Make UHC modules toggleable mid-game --- src/main/java/com/hugman/uhc/UHC.java | 4 +- .../hugman/uhc/command/ModulesCommand.java | 85 ------------- .../com/hugman/uhc/command/UHCCommand.java | 104 ++++++++++++++++ .../command/argument/UHCModuleArgument.java | 39 ++++++ .../com/hugman/uhc/game/ModuleManager.java | 112 +++++++++++++++++- .../com/hugman/uhc/game/phase/UHCActive.java | 16 +-- .../hugman/uhc/map/ModuledChunkGenerator.java | 5 +- 7 files changed, 255 insertions(+), 110 deletions(-) delete mode 100644 src/main/java/com/hugman/uhc/command/ModulesCommand.java create mode 100644 src/main/java/com/hugman/uhc/command/UHCCommand.java create mode 100644 src/main/java/com/hugman/uhc/command/argument/UHCModuleArgument.java diff --git a/src/main/java/com/hugman/uhc/UHC.java b/src/main/java/com/hugman/uhc/UHC.java index 1b86baf..86860d7 100644 --- a/src/main/java/com/hugman/uhc/UHC.java +++ b/src/main/java/com/hugman/uhc/UHC.java @@ -1,7 +1,7 @@ package com.hugman.uhc; import com.google.common.reflect.Reflection; -import com.hugman.uhc.command.ModulesCommand; +import com.hugman.uhc.command.UHCCommand; import com.hugman.uhc.config.UHCGameConfig; import com.hugman.uhc.game.phase.UHCWaiting; import com.hugman.uhc.modifier.ModifierType; @@ -25,7 +25,7 @@ public void onInitialize() { UHCRegistryKeys.registerDynamics(); - CommandRegistrationCallback.EVENT.register((dispatcher, dedicated, environment) -> ModulesCommand.register(dispatcher)); + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> UHCCommand.register(dispatcher, registryAccess)); GameType.register(UHC.id("standard"), UHCGameConfig.CODEC, UHCWaiting::open); } diff --git a/src/main/java/com/hugman/uhc/command/ModulesCommand.java b/src/main/java/com/hugman/uhc/command/ModulesCommand.java deleted file mode 100644 index fa5a79f..0000000 --- a/src/main/java/com/hugman/uhc/command/ModulesCommand.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.hugman.uhc.command; - -import com.hugman.uhc.config.UHCGameConfig; -import com.hugman.uhc.game.ModuleManager; -import com.hugman.uhc.game.UHCAttachments; -import com.hugman.uhc.module.Module; -import com.mojang.brigadier.Command; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import eu.pb4.sgui.api.elements.GuiElementBuilder; -import eu.pb4.sgui.api.gui.SimpleGui; -import net.minecraft.registry.Registries; -import net.minecraft.registry.entry.RegistryEntryList; -import net.minecraft.screen.ScreenHandlerType; -import net.minecraft.server.command.CommandManager; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.Style; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.MathHelper; -import xyz.nucleoid.plasmid.api.game.GameAttachment; -import xyz.nucleoid.plasmid.api.game.GameSpace; -import xyz.nucleoid.plasmid.api.game.GameSpaceManager; - -import java.util.Objects; - -public class ModulesCommand { - public static final SimpleCommandExceptionType NO_MODULES_ACTIVATED = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.no_modules_activated")); - - public static void register(CommandDispatcher dispatcher) { - dispatcher.register( - CommandManager.literal("modules") - .requires(ModulesCommand::isSourceInUHC) - .executes(ModulesCommand::displayModules)); - } - - public static boolean isSourceInUHC(ServerCommandSource source) { - GameSpace gameSpace = GameSpaceManager.get().byWorld(source.getWorld()); - if (gameSpace != null) { - return gameSpace.getMetadata().sourceConfig().value().config() instanceof UHCGameConfig; - } - return false; - } - - private static int displayModules(CommandContext context) throws CommandSyntaxException { - ServerCommandSource source = context.getSource(); - // TODO: get modules by the current game space instead - - var attachment = Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())).getAttachment(UHCAttachments.MODULE_MANAGER); - - if(attachment == null) { - throw NO_MODULES_ACTIVATED.create(); - } - - RegistryEntryList moduleEntries = attachment.modules(); - if (moduleEntries.size() != 0) { - ScreenHandlerType type = Registries.SCREEN_HANDLER.get(Identifier.of("generic_9x" + MathHelper.clamp(1, MathHelper.ceil((float) moduleEntries.size() / 9), 6))); - SimpleGui gui = new SimpleGui(type, source.getPlayer(), false); - gui.setTitle(Text.translatable("ui.uhc.modules.title")); - int i = 0; - for (var moduleEntry : moduleEntries) { - var module = moduleEntry.value(); - GuiElementBuilder elementBuilder = new GuiElementBuilder(module.icon()) - .setName(module.name().copy().formatted(Formatting.BOLD).setStyle(Style.EMPTY.withColor(module.color()))) - .hideDefaultTooltip(); - if(module.longDescription().isPresent()) { - for (Text line : module.longDescription().get()) { - elementBuilder.addLoreLine(Text.literal("- ").append(line).formatted(Formatting.GRAY)); - } - } - else if(module.description().isPresent()){ - elementBuilder.addLoreLine(Text.literal("- ").append(module.description().get()).formatted(Formatting.GRAY)); - } - gui.setSlot(i++, elementBuilder); - } - gui.open(); - return Command.SINGLE_SUCCESS; - } else { - throw NO_MODULES_ACTIVATED.create(); - } - } -} diff --git a/src/main/java/com/hugman/uhc/command/UHCCommand.java b/src/main/java/com/hugman/uhc/command/UHCCommand.java new file mode 100644 index 0000000..78a9698 --- /dev/null +++ b/src/main/java/com/hugman/uhc/command/UHCCommand.java @@ -0,0 +1,104 @@ +package com.hugman.uhc.command; + +import com.hugman.uhc.command.argument.UHCModuleArgument; +import com.hugman.uhc.config.UHCGameConfig; +import com.hugman.uhc.game.UHCAttachments; +import com.hugman.uhc.module.Module; +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.server.command.CommandManager; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.Text; +import xyz.nucleoid.plasmid.api.game.GameSpace; +import xyz.nucleoid.plasmid.api.game.GameSpaceManager; + +import java.util.Objects; + +public class UHCCommand { + private static final SimpleCommandExceptionType NO_MANAGER_ACTIVATED = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.no_manager")); + private static final SimpleCommandExceptionType NO_MODULES_ACTIVATED = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.no_modules_activated")); + private static final SimpleCommandExceptionType COULD_NOT_ACTIVATE_MODULE = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.enable.error")); + + private static final String MODULE_ARG = "module"; + + public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess) { + dispatcher.register( + CommandManager.literal("uhc") + .then(CommandManager.literal("create") + .requires(UHCCommand::isSourceNotInUHC) + .executes(context -> 0)) + .then(CommandManager.literal("modules") + .requires(UHCCommand::isSourceInUHC) //TODO: check if there is a module manager + .executes(UHCCommand::displayModules) + .then(CommandManager.literal("enable") + .then(UHCModuleArgument.argument("module") + .executes(context -> enableModule(context, UHCModuleArgument.get(context, MODULE_ARG))))) + .then(CommandManager.literal("disable") + .then(UHCModuleArgument.argument("module") //TODO: only suggest enabled modules + .executes(context -> disableModule(context, UHCModuleArgument.get(context, MODULE_ARG)))))) + + ); + } + + public static boolean isSourceInUHC(ServerCommandSource source) { + GameSpace gameSpace = GameSpaceManager.get().byWorld(source.getWorld()); + if (gameSpace != null) { + return gameSpace.getMetadata().sourceConfig().value().config() instanceof UHCGameConfig; + } + return false; + } + + public static boolean isSourceNotInUHC(ServerCommandSource source) { + return !isSourceInUHC(source); + } + + private static int displayModules(CommandContext context) throws CommandSyntaxException { + ServerCommandSource source = context.getSource(); + var manager = Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())).getAttachment(UHCAttachments.MODULE_MANAGER); + if (manager == null) { + throw NO_MANAGER_ACTIVATED.create(); + } + + if (!manager.isEmpty()) { + manager.buildGui(source.getPlayer()).open(); + return Command.SINGLE_SUCCESS; + } else { + throw NO_MODULES_ACTIVATED.create(); + } + } + + private static int enableModule(CommandContext context, RegistryEntry module) throws CommandSyntaxException { + ServerCommandSource source = context.getSource(); + var manager = Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())).getAttachment(UHCAttachments.MODULE_MANAGER); + if (manager == null) { + throw NO_MANAGER_ACTIVATED.create(); + } + + if (manager.enableModule(module)) { + source.sendFeedback(() -> Text.translatable("command.uhc.modules.enable.success", module.value().name()), true); + return Command.SINGLE_SUCCESS; + } else { + throw COULD_NOT_ACTIVATE_MODULE.create(); + } + } + + private static int disableModule(CommandContext context, RegistryEntry module) throws CommandSyntaxException { + ServerCommandSource source = context.getSource(); + var manager = Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())).getAttachment(UHCAttachments.MODULE_MANAGER); + if (manager == null) { + throw NO_MANAGER_ACTIVATED.create(); + } + + if (manager.disableModule(module)) { + source.sendFeedback(() -> Text.translatable("command.uhc.modules.enable.success", module.value().name()), true); + return Command.SINGLE_SUCCESS; + } else { + throw COULD_NOT_ACTIVATE_MODULE.create(); + } + } +} diff --git a/src/main/java/com/hugman/uhc/command/argument/UHCModuleArgument.java b/src/main/java/com/hugman/uhc/command/argument/UHCModuleArgument.java new file mode 100644 index 0000000..b874e46 --- /dev/null +++ b/src/main/java/com/hugman/uhc/command/argument/UHCModuleArgument.java @@ -0,0 +1,39 @@ +package com.hugman.uhc.command.argument; + +import com.hugman.uhc.module.Module; +import com.hugman.uhc.registry.UHCRegistryKeys; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; +import net.minecraft.command.CommandSource; +import net.minecraft.command.argument.IdentifierArgumentType; +import net.minecraft.registry.Registry; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.server.command.CommandManager; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +import java.util.Locale; + +public final class UHCModuleArgument { + private static final DynamicCommandExceptionType MODULE_NOT_FOUND = new DynamicCommandExceptionType((id) -> Text.stringifiedTranslatable("text.plasmid.game_config.game_not_found", id)); //TODO: change + + public static RequiredArgumentBuilder argument(String name) { + return CommandManager.argument(name, IdentifierArgumentType.identifier()).suggests((ctx, builder) -> { + Registry registry = ctx.getSource().getRegistryManager().getOrThrow(UHCRegistryKeys.MODULE); + String remaining = builder.getRemaining().toLowerCase(Locale.ROOT); + CommandSource.forEachMatching(registry.getKeys(), remaining, RegistryKey::getValue, (key) -> registry.getOptional(key) + .ifPresent((entry) -> builder.suggest(key.getValue().toString(), entry.value().name()))); + return builder.buildFuture(); + }); + } + + public static RegistryEntry.Reference get(CommandContext context, String name) throws CommandSyntaxException { + RegistryKey key = RegistryKey.of(UHCRegistryKeys.MODULE, IdentifierArgumentType.getIdentifier(context, name)); + Registry registry = context.getSource().getRegistryManager().getOrThrow(UHCRegistryKeys.MODULE); + return registry.getOptional(key).orElseThrow(() -> MODULE_NOT_FOUND.create(key.getValue())); + } +} diff --git a/src/main/java/com/hugman/uhc/game/ModuleManager.java b/src/main/java/com/hugman/uhc/game/ModuleManager.java index bf7a994..813de94 100644 --- a/src/main/java/com/hugman/uhc/game/ModuleManager.java +++ b/src/main/java/com/hugman/uhc/game/ModuleManager.java @@ -3,14 +3,37 @@ import com.hugman.uhc.modifier.Modifier; import com.hugman.uhc.modifier.ModifierType; import com.hugman.uhc.module.Module; +import eu.pb4.sgui.api.elements.GuiElementBuilder; +import eu.pb4.sgui.api.gui.SimpleGui; +import net.minecraft.registry.Registries; +import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryEntryList; +import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.*; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; import java.util.ArrayList; import java.util.List; +import java.util.stream.Stream; + +public final class ModuleManager { + private final List> modules; + + public ModuleManager(List> modules) { + this.modules = new ArrayList<>(modules); + } + + public ModuleManager(RegistryEntryList modules) { + this(modules.stream().toList()); + } + + public boolean isEmpty() { + return modules.isEmpty(); + } -public record ModuleManager( - RegistryEntryList modules -) { public List getModifiers() { List modifiers = new ArrayList<>(); for (var moduleEntry : modules) { @@ -21,10 +44,74 @@ public List getModifiers() { public List getModifiers(ModifierType type) { //TODO: cache modules so it's quicker to sort by type - return filter(modules, type); + return ModuleManager.getModifiers(modules, type); + } + + public boolean enableModule(RegistryEntry module) { + if (modules.contains(module)) { + return false; + } + //TODO: trigger the modifier (they may have something to do when enabled) + return modules.add(module); + } + + public boolean disableModule(RegistryEntry module) { + if (!modules.contains(module)) { + return false; + } + + //TODO: trigger the modifier (they may have something to do when disabled) + return modules.remove(module); } - public static List filter(RegistryEntryList modules, ModifierType type) { + /** + * Builds a GUI for the player to check the list of currently active modules + * + * @param player The player to build the GUI for + * @return The GUI + */ + public SimpleGui buildGui(ServerPlayerEntity player) { + ScreenHandlerType type = Registries.SCREEN_HANDLER.get(Identifier.of("generic_9x" + MathHelper.clamp(1, MathHelper.ceil((float) modules.size() / 9), 6))); + SimpleGui gui = new SimpleGui(type, player, false); + gui.setTitle(Text.translatable("ui.uhc.modules.title")); + int i = 0; + for (var moduleEntry : modules) { + var module = moduleEntry.value(); + GuiElementBuilder elementBuilder = new GuiElementBuilder(module.icon()) + .setName(module.name().copy().formatted(Formatting.BOLD).setStyle(Style.EMPTY.withColor(module.color()))) + .hideDefaultTooltip(); + if (module.longDescription().isPresent()) { + for (Text line : module.longDescription().get()) { + elementBuilder.addLoreLine(Text.literal("- ").append(line).formatted(Formatting.GRAY)); + } + } else if (module.description().isPresent()) { + elementBuilder.addLoreLine(Text.literal("- ").append(module.description().get()).formatted(Formatting.GRAY)); + } + gui.setSlot(i++, elementBuilder); + } + return gui; + } + + public MutableText buildChatMessage() { + var text = Text.literal("\n").append(Text.translatable("text.uhc.enabled_modules").formatted(Formatting.GOLD)); + this.modules.forEach(moduleEntry -> { + var module = moduleEntry.value(); + var style = Style.EMPTY; + if (module.description().isPresent()) { + style = style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, module.description().get().copy())); + } + text.append(Text.literal("\n - ").formatted(Formatting.WHITE)).append(Texts.bracketed(module.name()).setStyle(style.withColor(module.color()))); + }); + text.append("\n"); + return text; + } + + /** + * Filters a registry entry list of modules by type + * + * @return A list of modifiers of the specified type + */ + public static List getModifiers(List> modules, ModifierType type) { List modifiers = new ArrayList<>(); for (var moduleEntry : modules) { for (Modifier modifier : moduleEntry.value().modifiers()) { @@ -35,4 +122,19 @@ public static List filter(RegistryEntryList modu } return modifiers; } + + + public static Stream streamModifiers(Stream> modules, ModifierType type) { + return modules + .map(RegistryEntry::value) + .flatMap(module -> module.modifiers().stream()) + .filter(modifier -> modifier.getType() == type) + .map(modifier -> (V) modifier); + } + + @Override + public String toString() { + return "ModuleManager[" + + "modules=" + modules + ']'; + } } diff --git a/src/main/java/com/hugman/uhc/game/phase/UHCActive.java b/src/main/java/com/hugman/uhc/game/phase/UHCActive.java index d13e020..c59b369 100644 --- a/src/main/java/com/hugman/uhc/game/phase/UHCActive.java +++ b/src/main/java/com/hugman/uhc/game/phase/UHCActive.java @@ -449,20 +449,8 @@ private void sendWarning(String s, Object... args) { } public void sendModuleListToChat() { - var moduleEntries = this.moduleManager.modules(); - if (moduleEntries.size() > 0) { - MutableText text = Text.literal("\n").append(Text.translatable("text.uhc.enabled_modules").formatted(Formatting.GOLD)); - moduleEntries.forEach(moduleEntry -> { - var module = moduleEntry.value(); - Style style = Style.EMPTY; - if(module.description().isPresent()) - { - style = style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, module.description().get().copy())); - } - text.append(Text.literal("\n - ").formatted(Formatting.WHITE)).append(Texts.bracketed(module.name()).setStyle(style.withColor(module.color()))); - }); - text.append("\n"); - this.gameSpace.getPlayers().sendMessage(text); + if (!this.moduleManager.isEmpty()) { + this.gameSpace.getPlayers().sendMessage(this.moduleManager.buildChatMessage()); this.gameSpace.getPlayers().playSound(SoundEvents.ENTITY_ITEM_PICKUP); } } diff --git a/src/main/java/com/hugman/uhc/map/ModuledChunkGenerator.java b/src/main/java/com/hugman/uhc/map/ModuledChunkGenerator.java index 04661db..7bf197e 100644 --- a/src/main/java/com/hugman/uhc/map/ModuledChunkGenerator.java +++ b/src/main/java/com/hugman/uhc/map/ModuledChunkGenerator.java @@ -3,7 +3,6 @@ import com.hugman.uhc.config.UHCGameConfig; import com.hugman.uhc.game.ModuleManager; import com.hugman.uhc.modifier.ModifierType; -import com.hugman.uhc.modifier.PlacedFeaturesModifier; import com.mojang.datafixers.util.Pair; import net.minecraft.SharedConstants; import net.minecraft.entity.SpawnGroup; @@ -37,10 +36,8 @@ import xyz.nucleoid.fantasy.util.ChunkGeneratorSettingsProvider; import xyz.nucleoid.plasmid.api.game.world.generator.GameChunkGenerator; -import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.function.Supplier; import java.util.stream.Collectors; public class ModuledChunkGenerator extends GameChunkGenerator implements ChunkGeneratorSettingsProvider { @@ -65,7 +62,7 @@ public static ModuledChunkGenerator of(UHCGameConfig config, long seed) { settings = generator.getSettings().value(); } - List placedFeatures = ModuleManager.filter(config.uhcConfig().value().modules(), ModifierType.PLACED_FEATURES).stream() + List placedFeatures = ModuleManager.streamModifiers(config.uhcConfig().value().modules().stream(), ModifierType.PLACED_FEATURES) .flatMap(modifier -> modifier.features().stream()) .map(RegistryEntry::value) .collect(Collectors.toList()); From 3b470bf4447485e46ceb629d4c4533b82179a7a1 Mon Sep 17 00:00:00 2001 From: Hugman Date: Fri, 6 Dec 2024 00:31:27 +0100 Subject: [PATCH 04/13] Several refactors --- src/main/java/com/hugman/uhc/UHC.java | 2 +- .../com/hugman/uhc/command/UHCCommand.java | 55 ++++---- .../command/argument/UHCModuleArgument.java | 28 +++- .../com/hugman/uhc/game/ModuleManager.java | 9 ++ .../com/hugman/uhc/game/UHCPlayerManager.java | 124 ++++++++++++++++++ .../java/com/hugman/uhc/game/UHCSideBar.java | 8 +- .../com/hugman/uhc/game/phase/UHCActive.java | 113 +++++----------- .../com/hugman/uhc/game/phase/UHCWaiting.java | 13 +- .../com/hugman/uhc/modifier/Modifier.java | 6 + .../java/com/hugman/uhc/module/Module.java | 2 - 10 files changed, 243 insertions(+), 117 deletions(-) create mode 100644 src/main/java/com/hugman/uhc/game/UHCPlayerManager.java diff --git a/src/main/java/com/hugman/uhc/UHC.java b/src/main/java/com/hugman/uhc/UHC.java index 86860d7..f6f9206 100644 --- a/src/main/java/com/hugman/uhc/UHC.java +++ b/src/main/java/com/hugman/uhc/UHC.java @@ -25,7 +25,7 @@ public void onInitialize() { UHCRegistryKeys.registerDynamics(); - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> UHCCommand.register(dispatcher, registryAccess)); + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> UHCCommand.register(dispatcher)); GameType.register(UHC.id("standard"), UHCGameConfig.CODEC, UHCWaiting::open); } diff --git a/src/main/java/com/hugman/uhc/command/UHCCommand.java b/src/main/java/com/hugman/uhc/command/UHCCommand.java index 78a9698..3d80273 100644 --- a/src/main/java/com/hugman/uhc/command/UHCCommand.java +++ b/src/main/java/com/hugman/uhc/command/UHCCommand.java @@ -9,7 +9,6 @@ import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import net.minecraft.command.CommandRegistryAccess; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; @@ -20,41 +19,45 @@ import java.util.Objects; public class UHCCommand { - private static final SimpleCommandExceptionType NO_MANAGER_ACTIVATED = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.no_manager")); - private static final SimpleCommandExceptionType NO_MODULES_ACTIVATED = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.no_modules_activated")); - private static final SimpleCommandExceptionType COULD_NOT_ACTIVATE_MODULE = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.enable.error")); + private static final SimpleCommandExceptionType NO_MANAGER_ACTIVATED = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.no_manager")); //TODO: translate this + private static final SimpleCommandExceptionType NO_MODULES_ACTIVATED = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.no_modules_activated")); //TODO: translate this + private static final SimpleCommandExceptionType COULD_NOT_ENABLE_MODULE = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.enable.error")); //TODO: translate this + private static final SimpleCommandExceptionType COULD_NOT_DISABLE_MODULE = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.disable.error")); //TODO: translate this private static final String MODULE_ARG = "module"; - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess) { + public static void register(CommandDispatcher dispatcher) { dispatcher.register( CommandManager.literal("uhc") .then(CommandManager.literal("create") - .requires(UHCCommand::isSourceNotInUHC) - .executes(context -> 0)) + .requires(UHCCommand::isNotUHC) + .executes(UHCCommand::createUHC)) .then(CommandManager.literal("modules") - .requires(UHCCommand::isSourceInUHC) //TODO: check if there is a module manager + .requires(UHCCommand::isUHC) .executes(UHCCommand::displayModules) .then(CommandManager.literal("enable") - .then(UHCModuleArgument.argument("module") - .executes(context -> enableModule(context, UHCModuleArgument.get(context, MODULE_ARG))))) + .then(UHCModuleArgument.argumentFromDisabled("module") + .executes(context -> enableModule(context, UHCModuleArgument.get(context, MODULE_ARG))))) .then(CommandManager.literal("disable") - .then(UHCModuleArgument.argument("module") //TODO: only suggest enabled modules - .executes(context -> disableModule(context, UHCModuleArgument.get(context, MODULE_ARG)))))) - + .then(UHCModuleArgument.argumentFromEnabled("module") + .executes(context -> disableModule(context, UHCModuleArgument.get(context, MODULE_ARG))))) + ) ); } - public static boolean isSourceInUHC(ServerCommandSource source) { + public static boolean isUHC(ServerCommandSource source) { GameSpace gameSpace = GameSpaceManager.get().byWorld(source.getWorld()); - if (gameSpace != null) { - return gameSpace.getMetadata().sourceConfig().value().config() instanceof UHCGameConfig; + if (gameSpace == null) { + return false; + } + if (!(gameSpace.getMetadata().sourceConfig().value().config() instanceof UHCGameConfig)) { + return false; } - return false; + return true; } - public static boolean isSourceNotInUHC(ServerCommandSource source) { - return !isSourceInUHC(source); + public static boolean isNotUHC(ServerCommandSource source) { + return !isUHC(source); } private static int displayModules(CommandContext context) throws CommandSyntaxException { @@ -80,10 +83,10 @@ private static int enableModule(CommandContext context, Reg } if (manager.enableModule(module)) { - source.sendFeedback(() -> Text.translatable("command.uhc.modules.enable.success", module.value().name()), true); + source.sendFeedback(() -> Text.translatable("command.uhc.modules.enable.success", module.value().name()), true); //TODO: translate this return Command.SINGLE_SUCCESS; } else { - throw COULD_NOT_ACTIVATE_MODULE.create(); + throw COULD_NOT_ENABLE_MODULE.create(); } } @@ -95,10 +98,16 @@ private static int disableModule(CommandContext context, Re } if (manager.disableModule(module)) { - source.sendFeedback(() -> Text.translatable("command.uhc.modules.enable.success", module.value().name()), true); + source.sendFeedback(() -> Text.translatable("command.uhc.modules.disable.success", module.value().name()), true); //TODO: translate this return Command.SINGLE_SUCCESS; } else { - throw COULD_NOT_ACTIVATE_MODULE.create(); + throw COULD_NOT_DISABLE_MODULE.create(); } } + + + private static int createUHC(CommandContext context) { + context.getSource().sendFeedback(() -> Text.of("Available soon... :)"), true); + return Command.SINGLE_SUCCESS; + } } diff --git a/src/main/java/com/hugman/uhc/command/argument/UHCModuleArgument.java b/src/main/java/com/hugman/uhc/command/argument/UHCModuleArgument.java index b874e46..b9a107d 100644 --- a/src/main/java/com/hugman/uhc/command/argument/UHCModuleArgument.java +++ b/src/main/java/com/hugman/uhc/command/argument/UHCModuleArgument.java @@ -1,5 +1,6 @@ package com.hugman.uhc.command.argument; +import com.hugman.uhc.game.UHCAttachments; import com.hugman.uhc.module.Module; import com.hugman.uhc.registry.UHCRegistryKeys; import com.mojang.brigadier.builder.RequiredArgumentBuilder; @@ -15,17 +16,40 @@ import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import xyz.nucleoid.plasmid.api.game.GameSpaceManager; +import java.util.ArrayList; import java.util.Locale; +import java.util.Objects; public final class UHCModuleArgument { private static final DynamicCommandExceptionType MODULE_NOT_FOUND = new DynamicCommandExceptionType((id) -> Text.stringifiedTranslatable("text.plasmid.game_config.game_not_found", id)); //TODO: change - public static RequiredArgumentBuilder argument(String name) { + public static RequiredArgumentBuilder argumentFromEnabled(String name) { return CommandManager.argument(name, IdentifierArgumentType.identifier()).suggests((ctx, builder) -> { Registry registry = ctx.getSource().getRegistryManager().getOrThrow(UHCRegistryKeys.MODULE); String remaining = builder.getRemaining().toLowerCase(Locale.ROOT); - CommandSource.forEachMatching(registry.getKeys(), remaining, RegistryKey::getValue, (key) -> registry.getOptional(key) + var manager = Objects.requireNonNull(GameSpaceManager.get().byWorld(ctx.getSource().getWorld())).getAttachment(UHCAttachments.MODULE_MANAGER); + if (manager == null) { + return builder.buildFuture(); + } + var enabledKeys = manager.getKeys(); + CommandSource.forEachMatching(enabledKeys, remaining, RegistryKey::getValue, (key) -> registry.getOptional(key) + .ifPresent((entry) -> builder.suggest(key.getValue().toString(), entry.value().name()))); + return builder.buildFuture(); + }); + } + + public static RequiredArgumentBuilder argumentFromDisabled(String name) { + return CommandManager.argument(name, IdentifierArgumentType.identifier()).suggests((ctx, builder) -> { + Registry registry = ctx.getSource().getRegistryManager().getOrThrow(UHCRegistryKeys.MODULE); + String remaining = builder.getRemaining().toLowerCase(Locale.ROOT); + var manager = Objects.requireNonNull(GameSpaceManager.get().byWorld(ctx.getSource().getWorld())).getAttachment(UHCAttachments.MODULE_MANAGER); + var candidates = new ArrayList<>(registry.getKeys()); + if (manager != null) { + candidates.removeAll(manager.getKeys()); + } + CommandSource.forEachMatching(candidates, remaining, RegistryKey::getValue, (key) -> registry.getOptional(key) .ifPresent((entry) -> builder.suggest(key.getValue().toString(), entry.value().name()))); return builder.buildFuture(); }); diff --git a/src/main/java/com/hugman/uhc/game/ModuleManager.java b/src/main/java/com/hugman/uhc/game/ModuleManager.java index 813de94..039f0cd 100644 --- a/src/main/java/com/hugman/uhc/game/ModuleManager.java +++ b/src/main/java/com/hugman/uhc/game/ModuleManager.java @@ -6,6 +6,7 @@ import eu.pb4.sgui.api.elements.GuiElementBuilder; import eu.pb4.sgui.api.gui.SimpleGui; import net.minecraft.registry.Registries; +import net.minecraft.registry.RegistryKey; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryEntryList; import net.minecraft.screen.ScreenHandlerType; @@ -17,6 +18,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.stream.Stream; public final class ModuleManager { @@ -42,6 +44,10 @@ public List getModifiers() { return modifiers; } + public List> getKeys() { + return modules.stream().map(moduleRegistryEntry -> moduleRegistryEntry.getKey().orElse(null)).filter(Objects::nonNull).toList(); + } + public List getModifiers(ModifierType type) { //TODO: cache modules so it's quicker to sort by type return ModuleManager.getModifiers(modules, type); @@ -52,6 +58,8 @@ public boolean enableModule(RegistryEntry module) { return false; } //TODO: trigger the modifier (they may have something to do when enabled) + //TODO: send feedback to all players in game (chat + title) + return modules.add(module); } @@ -61,6 +69,7 @@ public boolean disableModule(RegistryEntry module) { } //TODO: trigger the modifier (they may have something to do when disabled) + //TODO: send feedback to all players in game (chat + title) return modules.remove(module); } diff --git a/src/main/java/com/hugman/uhc/game/UHCPlayerManager.java b/src/main/java/com/hugman/uhc/game/UHCPlayerManager.java new file mode 100644 index 0000000..73bfc11 --- /dev/null +++ b/src/main/java/com/hugman/uhc/game/UHCPlayerManager.java @@ -0,0 +1,124 @@ +package com.hugman.uhc.game; + +import com.hugman.uhc.config.UHCGameConfig; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.minecraft.scoreboard.AbstractTeam; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.util.DyeColor; +import org.apache.commons.lang3.RandomStringUtils; +import xyz.nucleoid.plasmid.api.game.GameActivity; +import xyz.nucleoid.plasmid.api.game.GameSpace; +import xyz.nucleoid.plasmid.api.game.common.team.*; +import xyz.nucleoid.plasmid.api.game.player.PlayerSet; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.stream.Collectors; + +public class UHCPlayerManager { + private final Object2ObjectMap participants; + private final TeamManager teamManager; + private final List aliveTeams; + + public UHCPlayerManager(Object2ObjectMap participants, TeamManager teamManager, List aliveTeams) { + this.participants = participants; + this.teamManager = teamManager; + this.aliveTeams = aliveTeams; + } + + public static UHCPlayerManager of(GameActivity activity, GameSpace gameSpace, UHCGameConfig config) { + Object2ObjectMap participants = new Object2ObjectOpenHashMap<>(); + TeamManager teamManager = TeamManager.addTo(activity); + List teamsAlive = new ArrayList<>(); + + List teamColors = Arrays.stream(DyeColor.values()).collect(Collectors.toList()); + teamColors.remove(DyeColor.WHITE); + teamColors.remove(DyeColor.BLACK); + teamColors.remove(DyeColor.MAGENTA); + Collections.shuffle(teamColors); + + for (int i = 0; i < Math.round(gameSpace.getPlayers().size() / (float) config.teamSize()); i++) { + GameTeam team = new GameTeam(new GameTeamKey(RandomStringUtils.randomAlphabetic(16)), + GameTeamConfig.builder() + .setFriendlyFire(false) + .setCollision(AbstractTeam.CollisionRule.PUSH_OTHER_TEAMS) + .setName(Text.literal("UHC Team")) //TODO: Add correct team name + .setColors(GameTeamConfig.Colors.from(teamColors.get(i))) + .build()); + + teamManager.addTeam(team); + teamsAlive.add(team); + } + + + TeamAllocator allocator = new TeamAllocator<>(teamsAlive); + for (ServerPlayerEntity playerEntity : gameSpace.getPlayers()) { + allocator.add(playerEntity, null); + } + allocator.allocate((team, player) -> { + participants.put(player, new UHCParticipant()); + teamManager.addPlayerTo(player, team.key()); + }); + + TeamChat.addTo(activity, teamManager); + + return new UHCPlayerManager(participants, teamManager, teamsAlive); + } + + public void clear() { + participants.clear(); + } + + // PARTICIPANTS + + public UHCParticipant getParticipant(ServerPlayerEntity player) { + return participants.get(player); + } + + public boolean isParticipant(ServerPlayerEntity player) { + return participants.containsKey(player); + } + + public int participantCount() { + return participants.size(); + } + + public int aliveParticipantCount() { + return (int) participants.values().stream().filter(participant -> !participant.isEliminated()).count(); + } + + public void forEachParticipant(final BiConsumer consumer) { + participants.forEach(consumer); + } + + // TEAMS + + public PlayerSet teamPlayers(GameTeamKey team) { + return teamManager.playersIn(team); + } + + public int aliveTeamCount() { + return aliveTeams.size(); + } + + public boolean noTeamsAlive() { + return aliveTeams.isEmpty(); + } + + public void refreshAliveTeams() { + aliveTeams.removeIf(team -> teamManager.playersIn(team.key()).stream().allMatch(playerEntity -> getParticipant(playerEntity).isEliminated())); + } + + public GameTeam getLastTeam() { + return aliveTeams.getFirst(); + } + + public List aliveTeams() { + return aliveTeams; + } +} diff --git a/src/main/java/com/hugman/uhc/game/UHCSideBar.java b/src/main/java/com/hugman/uhc/game/UHCSideBar.java index 1a96240..13b19be 100644 --- a/src/main/java/com/hugman/uhc/game/UHCSideBar.java +++ b/src/main/java/com/hugman/uhc/game/UHCSideBar.java @@ -1,8 +1,6 @@ package com.hugman.uhc.game; import com.hugman.uhc.util.TickUtil; -import it.unimi.dsi.fastutil.objects.Object2ObjectMap; -import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import xyz.nucleoid.plasmid.api.game.GameSpace; @@ -16,12 +14,10 @@ public static UHCSideBar create(GlobalWidgets widgets, GameSpace gameSpace) { return new UHCSideBar(widgets.addSidebar(name.copy().formatted(Formatting.BOLD, Formatting.GOLD))); } - public void update(long ticks, int worldSize, Object2ObjectMap participantMap) { + public void update(long ticks, int worldSize, UHCPlayerManager playerManager) { sidebarWidget.set(content -> { - long count = participantMap.values().stream().filter(participant -> !participant.isEliminated()).count(); - content.add(Text.literal("")); - content.add(Text.translatable("text.uhc.players", Text.literal(String.valueOf(count)).formatted(Formatting.GREEN)).formatted(Formatting.WHITE)); + content.add(Text.translatable("text.uhc.players", Text.literal(String.valueOf(playerManager.aliveParticipantCount())).formatted(Formatting.GREEN)).formatted(Formatting.WHITE)); //TODO: write kills content.add(Text.literal("")); content.add(Text.translatable("text.uhc.world", Text.literal(worldSize + "x" + worldSize).formatted(Formatting.GREEN)).formatted(Formatting.WHITE)); diff --git a/src/main/java/com/hugman/uhc/game/phase/UHCActive.java b/src/main/java/com/hugman/uhc/game/phase/UHCActive.java index c59b369..bda55ff 100644 --- a/src/main/java/com/hugman/uhc/game/phase/UHCActive.java +++ b/src/main/java/com/hugman/uhc/game/phase/UHCActive.java @@ -5,8 +5,6 @@ import com.hugman.uhc.game.*; import com.hugman.uhc.modifier.*; import com.hugman.uhc.util.TickUtil; -import it.unimi.dsi.fastutil.objects.Object2ObjectMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; @@ -17,28 +15,29 @@ import net.minecraft.network.packet.s2c.play.EntityAttributesS2CPacket; import net.minecraft.network.packet.s2c.play.WorldBorderInitializeS2CPacket; import net.minecraft.network.packet.s2c.play.WorldBorderInterpolateSizeS2CPacket; -import net.minecraft.scoreboard.AbstractTeam; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundEvents; -import net.minecraft.text.*; -import net.minecraft.util.DyeColor; +import net.minecraft.text.Text; +import net.minecraft.text.Texts; import net.minecraft.util.Formatting; import net.minecraft.util.ItemScatterer; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.GameMode; import net.minecraft.world.explosion.Explosion; -import org.apache.commons.lang3.RandomStringUtils; import org.jetbrains.annotations.Nullable; import xyz.nucleoid.plasmid.api.game.GameActivity; import xyz.nucleoid.plasmid.api.game.GameCloseReason; import xyz.nucleoid.plasmid.api.game.GameSpace; import xyz.nucleoid.plasmid.api.game.common.GlobalWidgets; -import xyz.nucleoid.plasmid.api.game.common.team.*; +import xyz.nucleoid.plasmid.api.game.common.team.GameTeam; import xyz.nucleoid.plasmid.api.game.event.GameActivityEvents; import xyz.nucleoid.plasmid.api.game.event.GamePlayerEvents; -import xyz.nucleoid.plasmid.api.game.player.*; +import xyz.nucleoid.plasmid.api.game.player.JoinAcceptor; +import xyz.nucleoid.plasmid.api.game.player.JoinAcceptorResult; +import xyz.nucleoid.plasmid.api.game.player.JoinOffer; +import xyz.nucleoid.plasmid.api.game.player.PlayerSet; import xyz.nucleoid.plasmid.api.game.rule.GameRuleType; import xyz.nucleoid.stimuli.event.DroppedItemsResult; import xyz.nucleoid.stimuli.event.EventResult; @@ -49,8 +48,9 @@ import xyz.nucleoid.stimuli.event.player.PlayerDeathEvent; import xyz.nucleoid.stimuli.event.world.ExplosionDetonatedEvent; -import java.util.*; -import java.util.stream.Collectors; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; public class UHCActive { private final GameSpace gameSpace; @@ -58,10 +58,7 @@ public class UHCActive { private final GameActivity activity; private final UHCGameConfig config; - private Object2ObjectMap participants; - private List teamsAlive; - private TeamManager teamManager; - + private final UHCPlayerManager playerManager; private final UHCLogic logic; private final UHCSpawner spawnLogic; private final UHCBar bar; @@ -87,50 +84,12 @@ private UHCActive(GameActivity activity, GameSpace gameSpace, ServerWorld world, this.world = world; this.config = config; - fillTeams(); - TeamChat.addTo(activity, teamManager); - - this.logic = new UHCLogic(config, this.participants.size()); + this.playerManager = UHCPlayerManager.of(activity, gameSpace, config); + this.logic = new UHCLogic(config, this.playerManager.participantCount()); this.spawnLogic = new UHCSpawner(this.world); this.bar = UHCBar.create(widgets, this.gameSpace); this.sideBar = UHCSideBar.create(widgets, gameSpace); - this.moduleManager = new ModuleManager(config.uhcConfig().value().modules()); - } - - private void fillTeams() { - this.teamManager = TeamManager.addTo(activity); - this.teamsAlive = new ArrayList<>(); - - List teamColors = Arrays.stream(DyeColor.values()).collect(Collectors.toList()); - teamColors.remove(DyeColor.WHITE); - teamColors.remove(DyeColor.BLACK); - teamColors.remove(DyeColor.MAGENTA); - Collections.shuffle(teamColors); - - for (int i = 0; i < Math.round(this.gameSpace.getPlayers().size() / (float) config.teamSize()); i++) { - GameTeam gameTeam = new GameTeam(new GameTeamKey(RandomStringUtils.randomAlphabetic(16)), - GameTeamConfig.builder() - .setFriendlyFire(false) - .setCollision(AbstractTeam.CollisionRule.PUSH_OTHER_TEAMS) - .setName(Text.literal("UHC Team")) - .setColors(GameTeamConfig.Colors.from(teamColors.get(i))) - .build()); - - teamManager.addTeam(gameTeam); - teamsAlive.add(gameTeam); - } - - TeamAllocator allocator = new TeamAllocator<>(this.teamsAlive); - this.participants = new Object2ObjectOpenHashMap<>(); - - for (ServerPlayerEntity playerEntity : gameSpace.getPlayers()) { - allocator.add(playerEntity, null); - } - allocator.allocate((gameTeam, playerEntity) -> { - teamManager.addPlayerTo(playerEntity, gameTeam.key()); - UHCParticipant participant = new UHCParticipant(); - participants.put(playerEntity, participant); - }); + this.moduleManager = gameSpace.getAttachment(UHCAttachments.MODULE_MANAGER); } public static void start(GameSpace gameSpace, ServerWorld world, UHCGameConfig config) { @@ -138,8 +97,6 @@ public static void start(GameSpace gameSpace, ServerWorld world, UHCGameConfig c GlobalWidgets widgets = GlobalWidgets.addTo(activity); UHCActive active = new UHCActive(activity, gameSpace, world, config, widgets); - gameSpace.setAttachment(UHCAttachments.MODULE_MANAGER, active.moduleManager); - activity.allow(GameRuleType.CRAFTING); activity.deny(GameRuleType.PORTALS); activity.deny(GameRuleType.PVP); @@ -186,7 +143,7 @@ private void enable() { this.gameCloseTick = this.gameEndTick + 600; // Start - Cage chapter - this.participants.forEach((player, participant) -> { + this.playerManager.forEachParticipant((player, participant) -> { if (!participant.isEliminated()) { this.resetPlayer(player); this.refreshPlayerAttributes(player); @@ -202,7 +159,7 @@ private void tick() { long worldTime = world.getTime(); this.bar.tick(world); - this.sideBar.update(worldTime - this.gameStartTick, (int) world.getWorldBorder().getSize(), this.participants); + this.sideBar.update(worldTime - this.gameStartTick, (int) world.getWorldBorder().getSize(), this.playerManager); // Game ends if (isFinished) { @@ -235,7 +192,7 @@ else if (worldTime == this.startWarmupTick) { // Finale - Cages chapter else if (worldTime == this.finaleCagesTick) { - this.participants.forEach((player, participant) -> { + this.playerManager.forEachParticipant((player, participant) -> { if (!participant.isEliminated()) { this.clearPlayer(player); this.refreshPlayerAttributes(player); @@ -282,10 +239,6 @@ else if (worldTime == this.deathMatchTick) { } // GENERAL PLAYER MANAGEMENT - private UHCParticipant getParticipant(ServerPlayerEntity player) { - return participants.get(player); - } - private JoinAcceptorResult acceptPlayer(JoinAcceptor joinAcceptor) { return joinAcceptor .teleport(this.world, UHCSpawner.getSurfaceBlock(world, 0, 0)) @@ -296,9 +249,9 @@ private JoinAcceptorResult acceptPlayer(JoinAcceptor joinAcceptor) { } private void playerLeave(ServerPlayerEntity player) { - if (participants.containsKey(player)) { - if (!getParticipant(player).isEliminated()) { - PlayerSet players = this.gameSpace.getPlayers(); + if (playerManager.isParticipant(player)) { + if (!playerManager.getParticipant(player).isEliminated()) { + var players = this.gameSpace.getPlayers(); players.sendMessage(Text.literal("\nā˜  ").append(Text.translatable("text.uhc.player_eliminated", player.getDisplayName())).append("\n").formatted(Formatting.DARK_RED)); players.playSound(SoundEvents.ENTITY_WITHER_SPAWN); this.eliminateParticipant(player); @@ -311,7 +264,7 @@ private void eliminateParticipant(ServerPlayerEntity player) { player.changeGameMode(GameMode.SPECTATOR); this.resetPlayer(player); this.spawnLogic.spawnPlayerAtCenter(player); - getParticipant(player).eliminate(); + playerManager.getParticipant(player).eliminate(); this.checkForWinner(); } @@ -348,15 +301,15 @@ private void checkForWinner() { PlayerSet players = this.gameSpace.getPlayers(); // Remove empty teams - teamsAlive.removeIf(team -> teamManager.playersIn(team.key()).stream().allMatch(playerEntity -> getParticipant(playerEntity).isEliminated())); + this.playerManager.refreshAliveTeams(); // Only one team is left, so they win - if (teamsAlive.size() <= 1) { - if (teamsAlive.isEmpty()) { + if (this.playerManager.aliveTeamCount() <= 1) { + if (this.playerManager.noTeamsAlive()) { players.sendMessage(Text.literal("\n").append(Text.translatable("text.uhc.none_win").formatted(Formatting.BOLD, Formatting.GOLD)).append("\n")); UHC.LOGGER.warn("There are no teams left! Consider reviewing the minimum amount of players needed to start a game, so that there are at least 2 teams in the game."); } else { - GameTeam lastTeam = teamsAlive.getFirst(); - PlayerSet teamMembers = teamManager.playersIn(lastTeam.key()); + GameTeam lastTeam = this.playerManager.getLastTeam(); + PlayerSet teamMembers = this.playerManager.teamPlayers(lastTeam.key()); if (teamMembers.size() <= 0) { players.sendMessage(Text.literal("\n").append(Text.translatable("text.uhc.none_win").formatted(Formatting.BOLD, Formatting.GOLD)).append("\n")); UHC.LOGGER.warn("There is only one team left, but there are no players in it!"); @@ -374,7 +327,7 @@ private void checkForWinner() { this.gameCloseTick = this.world.getTime() + 200; this.bar.close(); this.isFinished = true; - this.participants.clear(); + this.playerManager.clear(); } } @@ -402,14 +355,14 @@ private void tpToCages() { this.setInteractWithWorld(false); int index = 0; - for (GameTeam team : teamsAlive) { - double theta = ((double) index++ / teamsAlive.size()) * 2 * Math.PI; + for (GameTeam team : this.playerManager.aliveTeams()) { + double theta = ((double) index++ / this.playerManager.aliveTeamCount()) * 2 * Math.PI; int x = MathHelper.floor(Math.cos(theta) * (this.logic.getStartMapSize() / 2 - this.config.uhcConfig().value().mapConfig().spawnOffset())); int z = MathHelper.floor(Math.sin(theta) * (this.logic.getStartMapSize() / 2 - this.config.uhcConfig().value().mapConfig().spawnOffset())); this.spawnLogic.summonCage(team, x, z); - teamManager.playersIn(team.key()).forEach(player -> this.spawnLogic.putParticipantInCage(team, player)); + this.playerManager.teamPlayers(team.key()).forEach(player -> this.spawnLogic.putParticipantInCage(team, player)); } } @@ -417,7 +370,7 @@ private void dropCages() { this.spawnLogic.clearCages(); this.setInteractWithWorld(true); - this.participants.forEach((player, participant) -> { + this.playerManager.forEachParticipant((player, participant) -> { if (!participant.isEliminated()) { player.changeGameMode(GameMode.SURVIVAL); this.refreshPlayerAttributes(player); @@ -465,8 +418,8 @@ private EventResult onPlayerDamage(ServerPlayerEntity entity, DamageSource damag } private EventResult onPlayerDeath(ServerPlayerEntity player, DamageSource source) { - if (participants.containsKey(player)) { - if (!getParticipant(player).isEliminated()) { + if (playerManager.isParticipant(player)) { + if (!playerManager.getParticipant(player).isEliminated()) { PlayerSet players = this.gameSpace.getPlayers(); players.sendMessage(Text.literal("\nā˜  ").append(source.getDeathMessage(player).copy()).append("!\n").formatted(Formatting.DARK_RED)); players.playSound(SoundEvents.ENTITY_WITHER_SPAWN); diff --git a/src/main/java/com/hugman/uhc/game/phase/UHCWaiting.java b/src/main/java/com/hugman/uhc/game/phase/UHCWaiting.java index c0dca2c..6501dac 100644 --- a/src/main/java/com/hugman/uhc/game/phase/UHCWaiting.java +++ b/src/main/java/com/hugman/uhc/game/phase/UHCWaiting.java @@ -1,6 +1,8 @@ package com.hugman.uhc.game.phase; import com.hugman.uhc.config.UHCGameConfig; +import com.hugman.uhc.game.ModuleManager; +import com.hugman.uhc.game.UHCAttachments; import com.hugman.uhc.game.UHCSpawner; import com.hugman.uhc.map.UHCMap; import net.minecraft.server.world.ServerWorld; @@ -28,13 +30,18 @@ public record UHCWaiting( TeamManager teamManager ) { public static GameOpenProcedure open(GameOpenContext context) { - UHCMap map = UHCMap.of(context.config()); + var config = context.config(); + var map = UHCMap.of(config); + var moduleManager = new ModuleManager(config.uhcConfig().value().modules()); return context.openWithWorld(map.createRuntimeWorldConfig(), (activity, world) -> { - GameWaitingLobby.addTo(activity, context.config().players()); + GameWaitingLobby.addTo(activity, config.players()); TeamManager teamManager = TeamManager.addTo(activity); - UHCWaiting waiting = new UHCWaiting(activity.getGameSpace(), world, context.config(), teamManager); + var gameSpace = activity.getGameSpace(); + UHCWaiting waiting = new UHCWaiting(gameSpace, world, config, teamManager); + + gameSpace.setAttachment(UHCAttachments.MODULE_MANAGER, moduleManager); activity.listen(GamePlayerEvents.OFFER, JoinOffer::accept); activity.listen(GamePlayerEvents.ACCEPT, waiting::acceptPlayer); diff --git a/src/main/java/com/hugman/uhc/modifier/Modifier.java b/src/main/java/com/hugman/uhc/modifier/Modifier.java index 5b5f080..6762852 100644 --- a/src/main/java/com/hugman/uhc/modifier/Modifier.java +++ b/src/main/java/com/hugman/uhc/modifier/Modifier.java @@ -7,4 +7,10 @@ public interface Modifier { Codec TYPE_CODEC = UHCRegistries.MODIFIER_TYPE.getCodec().dispatch(Modifier::getType, ModifierType::codec); ModifierType getType(); + + default void enable() { + } + + default void disable() { + } } diff --git a/src/main/java/com/hugman/uhc/module/Module.java b/src/main/java/com/hugman/uhc/module/Module.java index 0a1a705..1dc6bdb 100644 --- a/src/main/java/com/hugman/uhc/module/Module.java +++ b/src/main/java/com/hugman/uhc/module/Module.java @@ -4,10 +4,8 @@ import com.hugman.uhc.registry.UHCRegistryKeys; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.registry.Registries; import net.minecraft.registry.RegistryCodecs; import net.minecraft.registry.entry.RegistryElementCodec; import net.minecraft.registry.entry.RegistryEntry; From e2b29d37e647818720e4d43f1b75585897fdb35b Mon Sep 17 00:00:00 2001 From: Hugo Landrin Date: Sat, 7 Dec 2024 00:15:35 +0100 Subject: [PATCH 05/13] Add module enabling/disabling events --- .../com/hugman/uhc/command/UHCCommand.java | 14 +- .../com/hugman/uhc/game/ModuleManager.java | 76 ++++++- .../com/hugman/uhc/game/UHCPlayerManager.java | 14 +- .../game/{UHCLogic.java => UHCTimers.java} | 4 +- .../com/hugman/uhc/game/phase/UHCActive.java | 191 ++++++++---------- .../com/hugman/uhc/modifier/Modifier.java | 7 +- .../uhc/modifier/PermanentEffectModifier.java | 12 ++ .../uhc/modifier/PlayerAttributeModifier.java | 18 ++ .../com/hugman/uhc/module/ModuleEvents.java | 34 ++++ 9 files changed, 252 insertions(+), 118 deletions(-) rename src/main/java/com/hugman/uhc/game/{UHCLogic.java => UHCTimers.java} (94%) create mode 100644 src/main/java/com/hugman/uhc/module/ModuleEvents.java diff --git a/src/main/java/com/hugman/uhc/command/UHCCommand.java b/src/main/java/com/hugman/uhc/command/UHCCommand.java index 3d80273..0fab2f7 100644 --- a/src/main/java/com/hugman/uhc/command/UHCCommand.java +++ b/src/main/java/com/hugman/uhc/command/UHCCommand.java @@ -4,6 +4,7 @@ import com.hugman.uhc.config.UHCGameConfig; import com.hugman.uhc.game.UHCAttachments; import com.hugman.uhc.module.Module; +import com.hugman.uhc.module.ModuleEvents; import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.context.CommandContext; @@ -15,6 +16,8 @@ import net.minecraft.text.Text; import xyz.nucleoid.plasmid.api.game.GameSpace; import xyz.nucleoid.plasmid.api.game.GameSpaceManager; +import xyz.nucleoid.stimuli.EventInvokers; +import xyz.nucleoid.stimuli.Stimuli; import java.util.Objects; @@ -77,12 +80,17 @@ private static int displayModules(CommandContext context) t private static int enableModule(CommandContext context, RegistryEntry module) throws CommandSyntaxException { ServerCommandSource source = context.getSource(); - var manager = Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())).getAttachment(UHCAttachments.MODULE_MANAGER); + var space = Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())); + var manager = space.getAttachment(UHCAttachments.MODULE_MANAGER); if (manager == null) { throw NO_MANAGER_ACTIVATED.create(); } if (manager.enableModule(module)) { + try (EventInvokers invokers = Stimuli.select().forCommandSource(context.getSource())) { + (invokers.get(ModuleEvents.ENABLE)).onEnable(module); + } + source.sendFeedback(() -> Text.translatable("command.uhc.modules.enable.success", module.value().name()), true); //TODO: translate this return Command.SINGLE_SUCCESS; } else { @@ -98,6 +106,10 @@ private static int disableModule(CommandContext context, Re } if (manager.disableModule(module)) { + try (EventInvokers invokers = Stimuli.select().forCommandSource(context.getSource())) { + (invokers.get(ModuleEvents.DISABLE)).onDisable(module); + } + source.sendFeedback(() -> Text.translatable("command.uhc.modules.disable.success", module.value().name()), true); //TODO: translate this return Command.SINGLE_SUCCESS; } else { diff --git a/src/main/java/com/hugman/uhc/game/ModuleManager.java b/src/main/java/com/hugman/uhc/game/ModuleManager.java index 039f0cd..6a05ced 100644 --- a/src/main/java/com/hugman/uhc/game/ModuleManager.java +++ b/src/main/java/com/hugman/uhc/game/ModuleManager.java @@ -1,20 +1,38 @@ package com.hugman.uhc.game; -import com.hugman.uhc.modifier.Modifier; -import com.hugman.uhc.modifier.ModifierType; +import com.hugman.uhc.modifier.*; import com.hugman.uhc.module.Module; +import com.hugman.uhc.module.ModuleEvents; import eu.pb4.sgui.api.elements.GuiElementBuilder; import eu.pb4.sgui.api.gui.SimpleGui; +import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemStack; import net.minecraft.registry.Registries; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryEntryList; import net.minecraft.screen.ScreenHandlerType; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; import net.minecraft.text.*; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; +import net.minecraft.world.explosion.Explosion; +import org.jetbrains.annotations.Nullable; +import xyz.nucleoid.plasmid.api.game.GameActivity; +import xyz.nucleoid.plasmid.api.game.event.GamePlayerEvents; +import xyz.nucleoid.stimuli.EventInvokers; +import xyz.nucleoid.stimuli.Stimuli; +import xyz.nucleoid.stimuli.event.DroppedItemsResult; +import xyz.nucleoid.stimuli.event.EventResult; +import xyz.nucleoid.stimuli.event.block.BlockBreakEvent; +import xyz.nucleoid.stimuli.event.block.BlockDropItemsEvent; +import xyz.nucleoid.stimuli.event.entity.EntityDropItemsEvent; +import xyz.nucleoid.stimuli.event.world.ExplosionDetonatedEvent; import java.util.ArrayList; import java.util.List; @@ -57,6 +75,7 @@ public boolean enableModule(RegistryEntry module) { if (modules.contains(module)) { return false; } + //TODO: trigger the modifier (they may have something to do when enabled) //TODO: send feedback to all players in game (chat + title) @@ -141,6 +160,59 @@ public static Stream streamModifiers(Stream (V) modifier); } + // LISTENERS + public void setupListeners(GameActivity activity) { + activity.listen(EntityDropItemsEvent.EVENT, this::onMobLoot); + activity.listen(BlockBreakEvent.EVENT, this::onBlockBroken); + activity.listen(BlockDropItemsEvent.EVENT, this::onBlockDrop); + activity.listen(ExplosionDetonatedEvent.EVENT, this::onExplosion); + } + + private EventResult onBlockBroken(ServerPlayerEntity playerEntity, ServerWorld world, BlockPos pos) { + for (TraversalBreakModifier piece : this.getModifiers(ModifierType.TRAVERSAL_BREAK)) { + piece.breakBlock(world, playerEntity, pos); + } + return EventResult.ALLOW; + } + + private EventResult onExplosion(Explosion explosion, List positions) { + positions.forEach(pos -> { + for (TraversalBreakModifier piece : this.getModifiers(ModifierType.TRAVERSAL_BREAK)) { + piece.breakBlock(explosion.getWorld(), explosion.getCausingEntity(), pos); + } + }); + return EventResult.ALLOW; + } + + + private DroppedItemsResult onMobLoot(LivingEntity livingEntity, List itemStacks) { + boolean keepOld = true; + List stacks = new ArrayList<>(); + for (EntityLootModifier piece : this.getModifiers(ModifierType.ENTITY_LOOT)) { + if (piece.test(livingEntity)) { + stacks.addAll(piece.getLoots((ServerWorld) livingEntity.getWorld(), livingEntity)); + if (piece.shouldReplace()) keepOld = false; + } + } + if (keepOld) stacks.addAll(itemStacks); + return DroppedItemsResult.pass(stacks); + } + + private DroppedItemsResult onBlockDrop(@Nullable Entity entity, ServerWorld world, BlockPos pos, BlockState state, List itemStacks) { + boolean keepOld = true; + List stacks = new ArrayList<>(); + for (BlockLootModifier piece : this.getModifiers(ModifierType.BLOCK_LOOT)) { + if (piece.test(state, world.getRandom())) { + piece.spawnExperience(world, pos); + stacks.addAll(piece.getLoots(world, pos, entity, entity instanceof LivingEntity ? ((LivingEntity) entity).getActiveItem() : ItemStack.EMPTY)); + if (piece.shouldReplace()) keepOld = false; + } + } + if (keepOld) stacks.addAll(itemStacks); + return DroppedItemsResult.pass(stacks); + } + + @Override public String toString() { return "ModuleManager[" + diff --git a/src/main/java/com/hugman/uhc/game/UHCPlayerManager.java b/src/main/java/com/hugman/uhc/game/UHCPlayerManager.java index 73bfc11..1592a25 100644 --- a/src/main/java/com/hugman/uhc/game/UHCPlayerManager.java +++ b/src/main/java/com/hugman/uhc/game/UHCPlayerManager.java @@ -17,7 +17,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.function.BiConsumer; +import java.util.function.Consumer; import java.util.stream.Collectors; public class UHCPlayerManager { @@ -92,8 +92,16 @@ public int aliveParticipantCount() { return (int) participants.values().stream().filter(participant -> !participant.isEliminated()).count(); } - public void forEachParticipant(final BiConsumer consumer) { - participants.forEach(consumer); + public void forEachAliveParticipant(final Consumer consumer) { + participants.forEach((player, participant) -> { + if (!participant.isEliminated()) { + consumer.accept(player); + } + }); + } + + public void forEachParticipant(final Consumer consumer) { + participants.keySet().forEach(consumer); } // TEAMS diff --git a/src/main/java/com/hugman/uhc/game/UHCLogic.java b/src/main/java/com/hugman/uhc/game/UHCTimers.java similarity index 94% rename from src/main/java/com/hugman/uhc/game/UHCLogic.java rename to src/main/java/com/hugman/uhc/game/UHCTimers.java index b0cfecb..fb0a78e 100644 --- a/src/main/java/com/hugman/uhc/game/UHCLogic.java +++ b/src/main/java/com/hugman/uhc/game/UHCTimers.java @@ -2,13 +2,13 @@ import com.hugman.uhc.config.UHCGameConfig; -public class UHCLogic { +public class UHCTimers { private static final int HIGH_PLAYER_COUNT = 100; private final UHCGameConfig config; private final float playerDose; - public UHCLogic(UHCGameConfig config, int playerAmount) { + public UHCTimers(UHCGameConfig config, int playerAmount) { this.config = config; this.playerDose = (playerAmount - (float) config.players().minPlayers()) / ((float) Math.max(config.players().minPlayers(), HIGH_PLAYER_COUNT) - (float) config.players().minPlayers()); } diff --git a/src/main/java/com/hugman/uhc/game/phase/UHCActive.java b/src/main/java/com/hugman/uhc/game/phase/UHCActive.java index bda55ff..fcbc69d 100644 --- a/src/main/java/com/hugman/uhc/game/phase/UHCActive.java +++ b/src/main/java/com/hugman/uhc/game/phase/UHCActive.java @@ -3,18 +3,20 @@ import com.hugman.uhc.UHC; import com.hugman.uhc.config.UHCGameConfig; import com.hugman.uhc.game.*; -import com.hugman.uhc.modifier.*; +import com.hugman.uhc.modifier.Modifier; +import com.hugman.uhc.modifier.ModifierType; +import com.hugman.uhc.modifier.PermanentEffectModifier; +import com.hugman.uhc.modifier.PlayerAttributeModifier; +import com.hugman.uhc.module.Module; +import com.hugman.uhc.module.ModuleEvents; import com.hugman.uhc.util.TickUtil; -import net.minecraft.block.BlockState; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.boss.BossBar; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.network.packet.s2c.play.EntityAttributesS2CPacket; import net.minecraft.network.packet.s2c.play.WorldBorderInitializeS2CPacket; import net.minecraft.network.packet.s2c.play.WorldBorderInterpolateSizeS2CPacket; +import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundEvents; @@ -22,11 +24,8 @@ import net.minecraft.text.Texts; import net.minecraft.util.Formatting; import net.minecraft.util.ItemScatterer; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.GameMode; -import net.minecraft.world.explosion.Explosion; -import org.jetbrains.annotations.Nullable; import xyz.nucleoid.plasmid.api.game.GameActivity; import xyz.nucleoid.plasmid.api.game.GameCloseReason; import xyz.nucleoid.plasmid.api.game.GameSpace; @@ -39,27 +38,20 @@ import xyz.nucleoid.plasmid.api.game.player.JoinOffer; import xyz.nucleoid.plasmid.api.game.player.PlayerSet; import xyz.nucleoid.plasmid.api.game.rule.GameRuleType; -import xyz.nucleoid.stimuli.event.DroppedItemsResult; import xyz.nucleoid.stimuli.event.EventResult; -import xyz.nucleoid.stimuli.event.block.BlockBreakEvent; -import xyz.nucleoid.stimuli.event.block.BlockDropItemsEvent; -import xyz.nucleoid.stimuli.event.entity.EntityDropItemsEvent; import xyz.nucleoid.stimuli.event.player.PlayerDamageEvent; import xyz.nucleoid.stimuli.event.player.PlayerDeathEvent; -import xyz.nucleoid.stimuli.event.world.ExplosionDetonatedEvent; -import java.util.ArrayList; -import java.util.List; import java.util.Optional; public class UHCActive { private final GameSpace gameSpace; private final ServerWorld world; private final GameActivity activity; - private final UHCGameConfig config; + private final int spawnOffset; private final UHCPlayerManager playerManager; - private final UHCLogic logic; + private final UHCTimers timers; private final UHCSpawner spawnLogic; private final UHCBar bar; private final UHCSideBar sideBar; @@ -78,24 +70,43 @@ public class UHCActive { private boolean invulnerable; private boolean isFinished = false; - private UHCActive(GameActivity activity, GameSpace gameSpace, ServerWorld world, UHCGameConfig config, GlobalWidgets widgets) { + private UHCActive( + GameActivity activity, + GameSpace gameSpace, + ServerWorld world, + UHCGameConfig config, + GlobalWidgets widgets, + UHCPlayerManager playerManager, + ModuleManager moduleManager + ) { this.activity = activity; this.gameSpace = gameSpace; this.world = world; - this.config = config; + this.playerManager = playerManager; + this.moduleManager = moduleManager; - this.playerManager = UHCPlayerManager.of(activity, gameSpace, config); - this.logic = new UHCLogic(config, this.playerManager.participantCount()); + this.spawnOffset = config.uhcConfig().value().mapConfig().spawnOffset(); + this.timers = new UHCTimers(config, this.playerManager.participantCount()); this.spawnLogic = new UHCSpawner(this.world); this.bar = UHCBar.create(widgets, this.gameSpace); this.sideBar = UHCSideBar.create(widgets, gameSpace); - this.moduleManager = gameSpace.getAttachment(UHCAttachments.MODULE_MANAGER); } public static void start(GameSpace gameSpace, ServerWorld world, UHCGameConfig config) { gameSpace.setActivity(activity -> { GlobalWidgets widgets = GlobalWidgets.addTo(activity); - UHCActive active = new UHCActive(activity, gameSpace, world, config, widgets); + var moduleManager = gameSpace.getAttachment(UHCAttachments.MODULE_MANAGER); + assert moduleManager != null; + var playerManager = UHCPlayerManager.of(activity, gameSpace, config); + UHCActive active = new UHCActive( + activity, + gameSpace, + world, + config, + widgets, + playerManager, + moduleManager + ); activity.allow(GameRuleType.CRAFTING); activity.deny(GameRuleType.PORTALS); @@ -111,14 +122,13 @@ public static void start(GameSpace gameSpace, ServerWorld world, UHCGameConfig c activity.listen(GamePlayerEvents.LEAVE, active::playerLeave); activity.listen(GameActivityEvents.TICK, active::tick); + activity.listen(ModuleEvents.ENABLE, active::enableModule); + activity.listen(ModuleEvents.DISABLE, active::disableModule); activity.listen(PlayerDamageEvent.EVENT, active::onPlayerDamage); activity.listen(PlayerDeathEvent.EVENT, active::onPlayerDeath); - activity.listen(EntityDropItemsEvent.EVENT, active::onMobLoot); - activity.listen(BlockBreakEvent.EVENT, active::onBlockBroken); - activity.listen(BlockDropItemsEvent.EVENT, active::onBlockDrop); - activity.listen(ExplosionDetonatedEvent.EVENT, active::onExplosion); + moduleManager.setupListeners(activity); }); } @@ -128,30 +138,28 @@ private void enable() { // Setup world.getWorldBorder().setCenter(0, 0); - world.getWorldBorder().setSize(this.logic.getStartMapSize()); + world.getWorldBorder().setSize(this.timers.getStartMapSize()); world.getWorldBorder().setDamagePerBlock(0.5); this.gameSpace.getPlayers().forEach(player -> player.networkHandler.sendPacket(new WorldBorderInitializeS2CPacket(world.getWorldBorder()))); this.gameStartTick = world.getTime(); - this.startInvulnerableTick = world.getTime() + this.logic.getInCagesTime(); - this.startWarmupTick = this.startInvulnerableTick + this.logic.getInvulnerabilityTime(); - this.finaleCagesTick = this.startWarmupTick + this.logic.getWarmupTime(); - this.finaleInvulnerabilityTick = this.finaleCagesTick + this.logic.getInCagesTime(); - this.reducingTick = this.finaleInvulnerabilityTick + this.logic.getInvulnerabilityTime(); - this.deathMatchTick = this.reducingTick + this.logic.getShrinkingTime(); - this.gameEndTick = this.deathMatchTick + this.logic.getDeathmatchTime(); + this.startInvulnerableTick = world.getTime() + this.timers.getInCagesTime(); + this.startWarmupTick = this.startInvulnerableTick + this.timers.getInvulnerabilityTime(); + this.finaleCagesTick = this.startWarmupTick + this.timers.getWarmupTime(); + this.finaleInvulnerabilityTick = this.finaleCagesTick + this.timers.getInCagesTime(); + this.reducingTick = this.finaleInvulnerabilityTick + this.timers.getInvulnerabilityTime(); + this.deathMatchTick = this.reducingTick + this.timers.getShrinkingTime(); + this.gameEndTick = this.deathMatchTick + this.timers.getDeathmatchTime(); this.gameCloseTick = this.gameEndTick + 600; // Start - Cage chapter - this.playerManager.forEachParticipant((player, participant) -> { - if (!participant.isEliminated()) { - this.resetPlayer(player); - this.refreshPlayerAttributes(player); - player.changeGameMode(GameMode.ADVENTURE); - } + this.playerManager.forEachAliveParticipant(player -> { + this.resetPlayer(player); + this.refreshPlayerAttributes(player); + player.changeGameMode(GameMode.ADVENTURE); }); this.tpToCages(); - this.bar.set("text.uhc.dropping", this.logic.getInCagesTime(), this.startInvulnerableTick, BossBar.Color.PURPLE); + this.bar.set("text.uhc.dropping", this.timers.getInCagesTime(), this.startInvulnerableTick, BossBar.Color.PURPLE); } private void tick() { @@ -170,7 +178,7 @@ private void tick() { } // Start - Cage chapter (@ 80%) - if (worldTime == this.startInvulnerableTick - (logic.getInCagesTime() * 0.8)) { + if (worldTime == this.startInvulnerableTick - (timers.getInCagesTime() * 0.8)) { this.sendModuleListToChat(); } // Start - Invulnerable chapter @@ -179,7 +187,7 @@ else if (worldTime == this.startInvulnerableTick) { this.sendInfo("text.uhc.dropped_players"); this.sendInfo("text.uhc.world_will_shrink", TickUtil.formatPretty(this.finaleCagesTick - worldTime)); - this.bar.set("šŸ›”", "text.uhc.vulnerable", this.logic.getInvulnerabilityTime(), this.startWarmupTick, BossBar.Color.YELLOW); + this.bar.set("šŸ›”", "text.uhc.vulnerable", this.timers.getInvulnerabilityTime(), this.startWarmupTick, BossBar.Color.YELLOW); } // Start - Warmup chapter @@ -187,22 +195,20 @@ else if (worldTime == this.startWarmupTick) { this.setInvulnerable(false); this.sendWarning("šŸ›”", "text.uhc.no_longer_immune"); - this.bar.set("text.uhc.tp", this.logic.getWarmupTime(), this.finaleCagesTick, BossBar.Color.BLUE); + this.bar.set("text.uhc.tp", this.timers.getWarmupTime(), this.finaleCagesTick, BossBar.Color.BLUE); } // Finale - Cages chapter else if (worldTime == this.finaleCagesTick) { - this.playerManager.forEachParticipant((player, participant) -> { - if (!participant.isEliminated()) { - this.clearPlayer(player); - this.refreshPlayerAttributes(player); - player.changeGameMode(GameMode.ADVENTURE); - } + this.playerManager.forEachAliveParticipant(player -> { + this.clearPlayer(player); + this.refreshPlayerAttributes(player); + player.changeGameMode(GameMode.ADVENTURE); }); this.tpToCages(); this.sendInfo("text.uhc.shrinking_when_pvp"); - this.bar.set("text.uhc.dropping", this.logic.getInCagesTime(), this.finaleInvulnerabilityTick, BossBar.Color.PURPLE); + this.bar.set("text.uhc.dropping", this.timers.getInCagesTime(), this.finaleInvulnerabilityTick, BossBar.Color.PURPLE); } // Finale - Invulnerability chapter @@ -210,7 +216,7 @@ else if (worldTime == this.finaleInvulnerabilityTick) { this.dropCages(); this.sendInfo("text.uhc.dropped_players"); - this.bar.set("šŸ—”", "text.uhc.pvp", this.logic.getInvulnerabilityTime(), this.reducingTick, BossBar.Color.YELLOW); + this.bar.set("šŸ—”", "text.uhc.pvp", this.timers.getInvulnerabilityTime(), this.reducingTick, BossBar.Color.YELLOW); } // Finale - Reducing chapter @@ -221,11 +227,11 @@ else if (worldTime == this.reducingTick) { this.setPvp(true); this.sendWarning("šŸ—”", "text.uhc.pvp_enabled"); - world.getWorldBorder().interpolateSize(this.logic.getStartMapSize(), this.logic.getEndMapSize(), this.logic.getShrinkingTime() * 50L); + world.getWorldBorder().interpolateSize(this.timers.getStartMapSize(), this.timers.getEndMapSize(), this.timers.getShrinkingTime() * 50L); this.gameSpace.getPlayers().forEach(player -> player.networkHandler.sendPacket(new WorldBorderInterpolateSizeS2CPacket(world.getWorldBorder()))); this.sendWarning("text.uhc.shrinking_start"); - this.bar.set("text.uhc.shrinking_finish", this.logic.getShrinkingTime(), this.deathMatchTick, BossBar.Color.RED); + this.bar.set("text.uhc.shrinking_finish", this.timers.getShrinkingTime(), this.deathMatchTick, BossBar.Color.RED); } // Finale - Deathmatch chapter @@ -358,8 +364,8 @@ private void tpToCages() { for (GameTeam team : this.playerManager.aliveTeams()) { double theta = ((double) index++ / this.playerManager.aliveTeamCount()) * 2 * Math.PI; - int x = MathHelper.floor(Math.cos(theta) * (this.logic.getStartMapSize() / 2 - this.config.uhcConfig().value().mapConfig().spawnOffset())); - int z = MathHelper.floor(Math.sin(theta) * (this.logic.getStartMapSize() / 2 - this.config.uhcConfig().value().mapConfig().spawnOffset())); + int x = MathHelper.floor(Math.cos(theta) * (this.timers.getStartMapSize() / 2 - this.spawnOffset)); + int z = MathHelper.floor(Math.sin(theta) * (this.timers.getStartMapSize() / 2 - this.spawnOffset)); this.spawnLogic.summonCage(team, x, z); this.playerManager.teamPlayers(team.key()).forEach(player -> this.spawnLogic.putParticipantInCage(team, player)); @@ -370,14 +376,12 @@ private void dropCages() { this.spawnLogic.clearCages(); this.setInteractWithWorld(true); - this.playerManager.forEachParticipant((player, participant) -> { - if (!participant.isEliminated()) { - player.changeGameMode(GameMode.SURVIVAL); - this.refreshPlayerAttributes(player); - this.clearPlayer(player); - this.applyPlayerEffects(player); - } - }); + this.playerManager.forEachAliveParticipant((player -> { + player.changeGameMode(GameMode.SURVIVAL); + this.refreshPlayerAttributes(player); + this.clearPlayer(player); + this.applyPlayerEffects(player); + })); } // MESSAGES @@ -409,6 +413,20 @@ public void sendModuleListToChat() { } // GENERAL LISTENERS + private void enableModule(RegistryEntry moduleRegistryEntry) { + Module module = moduleRegistryEntry.value(); + for (Modifier modifier : module.modifiers()) { + modifier.enable(this.playerManager); + } + } + + private void disableModule(RegistryEntry moduleRegistryEntry) { + Module module = moduleRegistryEntry.value(); + for (Modifier modifier : module.modifiers()) { + modifier.disable(this.playerManager); + } + } + private EventResult onPlayerDamage(ServerPlayerEntity entity, DamageSource damageSource, float v) { if (this.invulnerable) { return EventResult.DENY; @@ -430,47 +448,4 @@ private EventResult onPlayerDeath(ServerPlayerEntity player, DamageSource source this.spawnLogic.spawnPlayerAtCenter(player); return EventResult.DENY; } - - private EventResult onBlockBroken(ServerPlayerEntity playerEntity, ServerWorld world, BlockPos pos) { - for (TraversalBreakModifier piece : this.moduleManager.getModifiers(ModifierType.TRAVERSAL_BREAK)) { - piece.breakBlock(this.world, playerEntity, pos); - } - return EventResult.ALLOW; - } - - private EventResult onExplosion(Explosion explosion, List positions) { - positions.forEach(pos -> { - for (TraversalBreakModifier piece : this.moduleManager.getModifiers(ModifierType.TRAVERSAL_BREAK)) { - piece.breakBlock(this.world, explosion.getCausingEntity(), pos); - } - }); - return EventResult.ALLOW; - } - - private DroppedItemsResult onMobLoot(LivingEntity livingEntity, List itemStacks) { - boolean keepOld = true; - List stacks = new ArrayList<>(); - for (EntityLootModifier piece : this.moduleManager.getModifiers(ModifierType.ENTITY_LOOT)) { - if (piece.test(livingEntity)) { - stacks.addAll(piece.getLoots(this.world, livingEntity)); - if (piece.shouldReplace()) keepOld = false; - } - } - if (keepOld) stacks.addAll(itemStacks); - return DroppedItemsResult.pass(stacks); - } - - private DroppedItemsResult onBlockDrop(@Nullable Entity entity, ServerWorld world, BlockPos pos, BlockState state, List itemStacks) { - boolean keepOld = true; - List stacks = new ArrayList<>(); - for (BlockLootModifier piece : this.moduleManager.getModifiers(ModifierType.BLOCK_LOOT)) { - if (piece.test(state, world.getRandom())) { - piece.spawnExperience(world, pos); - stacks.addAll(piece.getLoots(world, pos, entity, entity instanceof LivingEntity ? ((LivingEntity) entity).getActiveItem() : ItemStack.EMPTY)); - if (piece.shouldReplace()) keepOld = false; - } - } - if (keepOld) stacks.addAll(itemStacks); - return DroppedItemsResult.pass(stacks); - } } diff --git a/src/main/java/com/hugman/uhc/modifier/Modifier.java b/src/main/java/com/hugman/uhc/modifier/Modifier.java index 6762852..38e306b 100644 --- a/src/main/java/com/hugman/uhc/modifier/Modifier.java +++ b/src/main/java/com/hugman/uhc/modifier/Modifier.java @@ -1,16 +1,19 @@ package com.hugman.uhc.modifier; +import com.hugman.uhc.game.UHCPlayerManager; import com.hugman.uhc.registry.UHCRegistries; import com.mojang.serialization.Codec; +import net.minecraft.server.PlayerManager; public interface Modifier { Codec TYPE_CODEC = UHCRegistries.MODIFIER_TYPE.getCodec().dispatch(Modifier::getType, ModifierType::codec); ModifierType getType(); - default void enable() { + //TODO: make them fire events instead + default void enable(UHCPlayerManager playerManager) { } - default void disable() { + default void disable(UHCPlayerManager playerManager) { } } diff --git a/src/main/java/com/hugman/uhc/modifier/PermanentEffectModifier.java b/src/main/java/com/hugman/uhc/modifier/PermanentEffectModifier.java index 1f32078..1de7a37 100644 --- a/src/main/java/com/hugman/uhc/modifier/PermanentEffectModifier.java +++ b/src/main/java/com/hugman/uhc/modifier/PermanentEffectModifier.java @@ -1,11 +1,13 @@ package com.hugman.uhc.modifier; +import com.hugman.uhc.game.UHCPlayerManager; import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.server.PlayerManager; import net.minecraft.server.network.ServerPlayerEntity; public record PermanentEffectModifier( @@ -25,4 +27,14 @@ public ModifierType getType() { public void setEffect(ServerPlayerEntity player) { player.addStatusEffect(new StatusEffectInstance(this.effect, -1, this.amplifier, false, false, true)); } + + @Override + public void enable(UHCPlayerManager playerManager) { + playerManager.forEachAliveParticipant(this::setEffect); + } + + @Override + public void disable(UHCPlayerManager playerManager) { + playerManager.forEachAliveParticipant(player -> player.removeStatusEffect(this.effect)); + } } diff --git a/src/main/java/com/hugman/uhc/modifier/PlayerAttributeModifier.java b/src/main/java/com/hugman/uhc/modifier/PlayerAttributeModifier.java index bd45666..c3a2aa0 100644 --- a/src/main/java/com/hugman/uhc/modifier/PlayerAttributeModifier.java +++ b/src/main/java/com/hugman/uhc/modifier/PlayerAttributeModifier.java @@ -1,11 +1,14 @@ package com.hugman.uhc.modifier; +import com.hugman.uhc.UHC; +import com.hugman.uhc.game.UHCPlayerManager; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.entity.attribute.EntityAttribute; import net.minecraft.entity.attribute.EntityAttributeInstance; import net.minecraft.entity.attribute.EntityAttributeModifier; import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.server.PlayerManager; import net.minecraft.server.network.ServerPlayerEntity; public record PlayerAttributeModifier( @@ -29,4 +32,19 @@ public void refreshAttribute(ServerPlayerEntity player) { instance.addPersistentModifier(modifier); } } + + @Override + public void enable(UHCPlayerManager playerManager) { + playerManager.forEachAliveParticipant(this::refreshAttribute); + } + + @Override + public void disable(UHCPlayerManager playerManager) { + playerManager.forEachAliveParticipant(player -> { + EntityAttributeInstance instance = player.getAttributes().getCustomInstance(this.attribute); + if (instance != null) { + instance.removeModifier(modifier); + } + }); + } } diff --git a/src/main/java/com/hugman/uhc/module/ModuleEvents.java b/src/main/java/com/hugman/uhc/module/ModuleEvents.java new file mode 100644 index 0000000..1ee770c --- /dev/null +++ b/src/main/java/com/hugman/uhc/module/ModuleEvents.java @@ -0,0 +1,34 @@ +package com.hugman.uhc.module; + +import com.hugman.uhc.game.UHCPlayerManager; +import net.minecraft.registry.entry.RegistryEntry; +import xyz.nucleoid.stimuli.event.StimulusEvent; + +public class ModuleEvents { + public static final StimulusEvent ENABLE = StimulusEvent.create(Enable.class, (ctx) -> (module) -> { + try { + for (Enable listener : ctx.getListeners()) { + listener.onEnable(module); + } + } catch (Throwable throwable) { + ctx.handleException(throwable); + } + }); + public static final StimulusEvent DISABLE = StimulusEvent.create(Disable.class, (ctx) -> (module) -> { + try { + for (Disable listener : ctx.getListeners()) { + listener.onDisable(module); + } + } catch (Throwable throwable) { + ctx.handleException(throwable); + } + }); + + public interface Enable { + void onEnable(RegistryEntry moduleEntry); + } + + public interface Disable { + void onDisable(RegistryEntry moduleEntry); + } +} From c280d33af0d578569ac719e7043c1d18f6719c5c Mon Sep 17 00:00:00 2001 From: Hugman Date: Sat, 7 Dec 2024 13:32:36 +0100 Subject: [PATCH 06/13] Refactor messages --- src/main/java/com/hugman/text/Messenger.java | 109 ++++++++++++++ src/main/java/com/hugman/uhc/UHC.java | 4 +- .../{UHCCommand.java => ModulesCommand.java} | 64 ++++----- .../command/argument/UHCModuleArgument.java | 12 +- .../com/hugman/uhc/game/ModuleManager.java | 47 +++--- .../com/hugman/uhc/game/UHCAttachments.java | 8 -- src/main/java/com/hugman/uhc/game/UHCBar.java | 33 +++-- .../com/hugman/uhc/game/UHCPlayerManager.java | 4 - .../com/hugman/uhc/game/phase/UHCActive.java | 134 ++++++++---------- .../com/hugman/uhc/game/phase/UHCWaiting.java | 3 +- .../java/com/hugman/uhc/util/TickUtil.java | 4 - src/main/resources/data/uhc/lang/en_us.json | 13 +- 12 files changed, 250 insertions(+), 185 deletions(-) create mode 100644 src/main/java/com/hugman/text/Messenger.java rename src/main/java/com/hugman/uhc/command/{UHCCommand.java => ModulesCommand.java} (57%) delete mode 100644 src/main/java/com/hugman/uhc/game/UHCAttachments.java diff --git a/src/main/java/com/hugman/text/Messenger.java b/src/main/java/com/hugman/text/Messenger.java new file mode 100644 index 0000000..bb15b32 --- /dev/null +++ b/src/main/java/com/hugman/text/Messenger.java @@ -0,0 +1,109 @@ +package com.hugman.text; + +import com.hugman.uhc.game.ModuleManager; +import com.hugman.uhc.module.Module; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvent; +import net.minecraft.sound.SoundEvents; +import net.minecraft.text.HoverEvent; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.text.Texts; +import net.minecraft.util.Formatting; +import xyz.nucleoid.plasmid.api.game.GameSpacePlayers; + +/** + * Sends messages to players in a game. + */ +public class Messenger { + public static final String SYMBOL_SKULL = "ā˜ "; + public static final String SYMBOL_MODULE = "āœØ"; + public static final String SYMBOL_SHIELD = "šŸ›”"; + public static final String SYMBOL_SWORD = "šŸ—”"; + + private final GameSpacePlayers players; + + public Messenger(GameSpacePlayers players) { + this.players = players; + } + + public void sound(SoundEvent sound, float volume, float pitch) { + players.playSound(sound, SoundCategory.PLAYERS, volume, pitch); + } + + public void info(String symbol, String s, Object... args) { + players.sendMessage(build(symbol, s, Formatting.YELLOW, args)); + } + + public void info(String s, Object... args) { + players.sendMessage(build(s, Formatting.YELLOW, args)); + } + + public void danger(String symbol, String s, Object... args) { + players.sendMessage(build(symbol, s, Formatting.RED, args)); + } + + public void danger(String s, Object... args) { + players.sendMessage(build(s, Formatting.RED, args)); + } + + public void elimination(ServerPlayerEntity player) { + players.sendMessage(buildElimination(player)); + players.playSound(SoundEvents.ENTITY_WITHER_SPAWN); + } + + public void death(DamageSource source, ServerPlayerEntity player) { + players.sendMessage(buildDeath(source, player)); + players.playSound(SoundEvents.ENTITY_WITHER_SPAWN); + } + + public void moduleAnnouncement(String message, RegistryEntry module, Formatting formatting) { + players.sendMessage(buildModuleAnnouncement(message, module, formatting)); + } + + public void moduleList(ModuleManager moduleManager) { + if (!moduleManager.isEmpty()) { + players.sendMessage(buildModuleList(moduleManager)); + players.playSound(SoundEvents.ENTITY_ITEM_PICKUP); + } + } + + private static Text build(String symbol, String s, Formatting f, Object... args) { + return Text.literal(symbol).append(" ").append(Text.translatable(s, args)).formatted(f); + } + + private static Text build(String s, Formatting f, Object... args) { + return Text.translatable(s, args).formatted(f); + } + + private static Text buildDeath(DamageSource source, ServerPlayerEntity player) { + return Text.literal("\n").append(SYMBOL_SKULL).append(" ").append(source.getDeathMessage(player).copy()).append("!\n").formatted(Formatting.DARK_RED); + } + + private static Text buildElimination(ServerPlayerEntity player) { + return Text.literal("\n").append(SYMBOL_SKULL).append(" ").append(Text.translatable("text.uhc.player_eliminated", player.getDisplayName())).append("\n").formatted(Formatting.DARK_RED); + } + + private static Text buildModuleAnnouncement(String message, RegistryEntry module, Formatting formatting) { + return Text.literal("\n\n").append(SYMBOL_MODULE).append(" ").append(Text.translatable(message, moduleSnippet(module.value())).formatted(formatting)).append("\n\n"); + } + + private static Text buildModuleList(ModuleManager manager) { + var text = Text.literal("\n").append(Text.translatable("text.uhc.enabled_modules").formatted(Formatting.GOLD)); + manager.forEach(module -> text.append(Text.literal("\n - ").formatted(Formatting.WHITE)).append(moduleSnippet(module))); + text.append("\n"); + return text; + } + + + private static Text moduleSnippet(Module module) { + var style = Style.EMPTY; + if (module.description().isPresent()) { + style = style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, module.description().get().copy())); + } + return Texts.bracketed(module.name()).setStyle(style.withColor(module.color())); + } +} diff --git a/src/main/java/com/hugman/uhc/UHC.java b/src/main/java/com/hugman/uhc/UHC.java index f6f9206..28daa6a 100644 --- a/src/main/java/com/hugman/uhc/UHC.java +++ b/src/main/java/com/hugman/uhc/UHC.java @@ -1,7 +1,7 @@ package com.hugman.uhc; import com.google.common.reflect.Reflection; -import com.hugman.uhc.command.UHCCommand; +import com.hugman.uhc.command.ModulesCommand; import com.hugman.uhc.config.UHCGameConfig; import com.hugman.uhc.game.phase.UHCWaiting; import com.hugman.uhc.modifier.ModifierType; @@ -25,7 +25,7 @@ public void onInitialize() { UHCRegistryKeys.registerDynamics(); - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> UHCCommand.register(dispatcher)); + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> ModulesCommand.register(dispatcher)); GameType.register(UHC.id("standard"), UHCGameConfig.CODEC, UHCWaiting::open); } diff --git a/src/main/java/com/hugman/uhc/command/UHCCommand.java b/src/main/java/com/hugman/uhc/command/ModulesCommand.java similarity index 57% rename from src/main/java/com/hugman/uhc/command/UHCCommand.java rename to src/main/java/com/hugman/uhc/command/ModulesCommand.java index 0fab2f7..31320b2 100644 --- a/src/main/java/com/hugman/uhc/command/UHCCommand.java +++ b/src/main/java/com/hugman/uhc/command/ModulesCommand.java @@ -1,8 +1,7 @@ package com.hugman.uhc.command; import com.hugman.uhc.command.argument.UHCModuleArgument; -import com.hugman.uhc.config.UHCGameConfig; -import com.hugman.uhc.game.UHCAttachments; +import com.hugman.uhc.game.ModuleManager; import com.hugman.uhc.module.Module; import com.hugman.uhc.module.ModuleEvents; import com.mojang.brigadier.Command; @@ -21,51 +20,42 @@ import java.util.Objects; -public class UHCCommand { - private static final SimpleCommandExceptionType NO_MANAGER_ACTIVATED = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.no_manager")); //TODO: translate this - private static final SimpleCommandExceptionType NO_MODULES_ACTIVATED = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.no_modules_activated")); //TODO: translate this - private static final SimpleCommandExceptionType COULD_NOT_ENABLE_MODULE = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.enable.error")); //TODO: translate this - private static final SimpleCommandExceptionType COULD_NOT_DISABLE_MODULE = new SimpleCommandExceptionType(Text.translatable("command.uhc.modules.disable.error")); //TODO: translate this +public class ModulesCommand { + private static final SimpleCommandExceptionType NO_MANAGER_ACTIVATED = new SimpleCommandExceptionType(Text.translatable("command.modules.no_manager")); + private static final SimpleCommandExceptionType NO_MODULES_ACTIVATED = new SimpleCommandExceptionType(Text.translatable("command.modules.no_modules_activated")); + private static final SimpleCommandExceptionType ALREADY_ENABLED = new SimpleCommandExceptionType(Text.translatable("command.modules.already_enabled")); + private static final SimpleCommandExceptionType ALREADY_DISABLED = new SimpleCommandExceptionType(Text.translatable("command.modules.already_disabled")); private static final String MODULE_ARG = "module"; public static void register(CommandDispatcher dispatcher) { dispatcher.register( - CommandManager.literal("uhc") - .then(CommandManager.literal("create") - .requires(UHCCommand::isNotUHC) - .executes(UHCCommand::createUHC)) - .then(CommandManager.literal("modules") - .requires(UHCCommand::isUHC) - .executes(UHCCommand::displayModules) - .then(CommandManager.literal("enable") - .then(UHCModuleArgument.argumentFromDisabled("module") - .executes(context -> enableModule(context, UHCModuleArgument.get(context, MODULE_ARG))))) - .then(CommandManager.literal("disable") - .then(UHCModuleArgument.argumentFromEnabled("module") - .executes(context -> disableModule(context, UHCModuleArgument.get(context, MODULE_ARG))))) - ) + CommandManager.literal("modules") + .requires(ModulesCommand::supportsModules) + .executes(ModulesCommand::displayModules) + .then(CommandManager.literal("enable") + .then(UHCModuleArgument.argumentFromDisabled("module") + .executes(context -> enableModule(context, UHCModuleArgument.get(context, MODULE_ARG))))) + .then(CommandManager.literal("disable") + .then(UHCModuleArgument.argumentFromEnabled("module") + .executes(context -> disableModule(context, UHCModuleArgument.get(context, MODULE_ARG))))) ); } - public static boolean isUHC(ServerCommandSource source) { + public static boolean supportsModules(ServerCommandSource source) { GameSpace gameSpace = GameSpaceManager.get().byWorld(source.getWorld()); if (gameSpace == null) { return false; } - if (!(gameSpace.getMetadata().sourceConfig().value().config() instanceof UHCGameConfig)) { + if (!(gameSpace.getAttachment(ModuleManager.ATTACHMENT) instanceof ModuleManager)) { return false; } return true; } - public static boolean isNotUHC(ServerCommandSource source) { - return !isUHC(source); - } - private static int displayModules(CommandContext context) throws CommandSyntaxException { ServerCommandSource source = context.getSource(); - var manager = Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())).getAttachment(UHCAttachments.MODULE_MANAGER); + var manager = Objects.requireNonNull(GameSpaceManager.get().byPlayer(source.getPlayer())).getAttachment(ModuleManager.ATTACHMENT); if (manager == null) { throw NO_MANAGER_ACTIVATED.create(); } @@ -81,7 +71,7 @@ private static int displayModules(CommandContext context) t private static int enableModule(CommandContext context, RegistryEntry module) throws CommandSyntaxException { ServerCommandSource source = context.getSource(); var space = Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())); - var manager = space.getAttachment(UHCAttachments.MODULE_MANAGER); + var manager = space.getAttachment(ModuleManager.ATTACHMENT); if (manager == null) { throw NO_MANAGER_ACTIVATED.create(); } @@ -91,16 +81,16 @@ private static int enableModule(CommandContext context, Reg (invokers.get(ModuleEvents.ENABLE)).onEnable(module); } - source.sendFeedback(() -> Text.translatable("command.uhc.modules.enable.success", module.value().name()), true); //TODO: translate this + source.sendFeedback(() -> Text.translatable("command.modules.enable.success", module.value().name()), true); return Command.SINGLE_SUCCESS; } else { - throw COULD_NOT_ENABLE_MODULE.create(); + throw ALREADY_ENABLED.create(); } } private static int disableModule(CommandContext context, RegistryEntry module) throws CommandSyntaxException { ServerCommandSource source = context.getSource(); - var manager = Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())).getAttachment(UHCAttachments.MODULE_MANAGER); + var manager = Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())).getAttachment(ModuleManager.ATTACHMENT); if (manager == null) { throw NO_MANAGER_ACTIVATED.create(); } @@ -110,16 +100,10 @@ private static int disableModule(CommandContext context, Re (invokers.get(ModuleEvents.DISABLE)).onDisable(module); } - source.sendFeedback(() -> Text.translatable("command.uhc.modules.disable.success", module.value().name()), true); //TODO: translate this + source.sendFeedback(() -> Text.translatable("command.modules.disable.success", module.value().name()), true); return Command.SINGLE_SUCCESS; } else { - throw COULD_NOT_DISABLE_MODULE.create(); + throw ALREADY_DISABLED.create(); } } - - - private static int createUHC(CommandContext context) { - context.getSource().sendFeedback(() -> Text.of("Available soon... :)"), true); - return Command.SINGLE_SUCCESS; - } } diff --git a/src/main/java/com/hugman/uhc/command/argument/UHCModuleArgument.java b/src/main/java/com/hugman/uhc/command/argument/UHCModuleArgument.java index b9a107d..b041e06 100644 --- a/src/main/java/com/hugman/uhc/command/argument/UHCModuleArgument.java +++ b/src/main/java/com/hugman/uhc/command/argument/UHCModuleArgument.java @@ -1,6 +1,6 @@ package com.hugman.uhc.command.argument; -import com.hugman.uhc.game.UHCAttachments; +import com.hugman.uhc.game.ModuleManager; import com.hugman.uhc.module.Module; import com.hugman.uhc.registry.UHCRegistryKeys; import com.mojang.brigadier.builder.RequiredArgumentBuilder; @@ -23,17 +23,17 @@ import java.util.Objects; public final class UHCModuleArgument { - private static final DynamicCommandExceptionType MODULE_NOT_FOUND = new DynamicCommandExceptionType((id) -> Text.stringifiedTranslatable("text.plasmid.game_config.game_not_found", id)); //TODO: change + private static final DynamicCommandExceptionType MODULE_NOT_FOUND = new DynamicCommandExceptionType((id) -> Text.stringifiedTranslatable("text.module.not_found", id)); //TODO: change public static RequiredArgumentBuilder argumentFromEnabled(String name) { return CommandManager.argument(name, IdentifierArgumentType.identifier()).suggests((ctx, builder) -> { Registry registry = ctx.getSource().getRegistryManager().getOrThrow(UHCRegistryKeys.MODULE); String remaining = builder.getRemaining().toLowerCase(Locale.ROOT); - var manager = Objects.requireNonNull(GameSpaceManager.get().byWorld(ctx.getSource().getWorld())).getAttachment(UHCAttachments.MODULE_MANAGER); + var manager = Objects.requireNonNull(GameSpaceManager.get().byWorld(ctx.getSource().getWorld())).getAttachment(ModuleManager.ATTACHMENT); if (manager == null) { return builder.buildFuture(); } - var enabledKeys = manager.getKeys(); + var enabledKeys = manager.keys(); CommandSource.forEachMatching(enabledKeys, remaining, RegistryKey::getValue, (key) -> registry.getOptional(key) .ifPresent((entry) -> builder.suggest(key.getValue().toString(), entry.value().name()))); return builder.buildFuture(); @@ -44,10 +44,10 @@ public static RequiredArgumentBuilder argumentF return CommandManager.argument(name, IdentifierArgumentType.identifier()).suggests((ctx, builder) -> { Registry registry = ctx.getSource().getRegistryManager().getOrThrow(UHCRegistryKeys.MODULE); String remaining = builder.getRemaining().toLowerCase(Locale.ROOT); - var manager = Objects.requireNonNull(GameSpaceManager.get().byWorld(ctx.getSource().getWorld())).getAttachment(UHCAttachments.MODULE_MANAGER); + var manager = Objects.requireNonNull(GameSpaceManager.get().byWorld(ctx.getSource().getWorld())).getAttachment(ModuleManager.ATTACHMENT); var candidates = new ArrayList<>(registry.getKeys()); if (manager != null) { - candidates.removeAll(manager.getKeys()); + candidates.removeAll(manager.keys()); } CommandSource.forEachMatching(candidates, remaining, RegistryKey::getValue, (key) -> registry.getOptional(key) .ifPresent((entry) -> builder.suggest(key.getValue().toString(), entry.value().name()))); diff --git a/src/main/java/com/hugman/uhc/game/ModuleManager.java b/src/main/java/com/hugman/uhc/game/ModuleManager.java index 6a05ced..4d94162 100644 --- a/src/main/java/com/hugman/uhc/game/ModuleManager.java +++ b/src/main/java/com/hugman/uhc/game/ModuleManager.java @@ -1,8 +1,8 @@ package com.hugman.uhc.game; +import com.hugman.uhc.UHC; import com.hugman.uhc.modifier.*; import com.hugman.uhc.module.Module; -import com.hugman.uhc.module.ModuleEvents; import eu.pb4.sgui.api.elements.GuiElementBuilder; import eu.pb4.sgui.api.gui.SimpleGui; import net.minecraft.block.BlockState; @@ -24,9 +24,7 @@ import net.minecraft.world.explosion.Explosion; import org.jetbrains.annotations.Nullable; import xyz.nucleoid.plasmid.api.game.GameActivity; -import xyz.nucleoid.plasmid.api.game.event.GamePlayerEvents; -import xyz.nucleoid.stimuli.EventInvokers; -import xyz.nucleoid.stimuli.Stimuli; +import xyz.nucleoid.plasmid.api.game.GameAttachment; import xyz.nucleoid.stimuli.event.DroppedItemsResult; import xyz.nucleoid.stimuli.event.EventResult; import xyz.nucleoid.stimuli.event.block.BlockBreakEvent; @@ -37,9 +35,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.function.Consumer; import java.util.stream.Stream; public final class ModuleManager { + public static final GameAttachment ATTACHMENT = GameAttachment.create(UHC.id("module_manager")); + private final List> modules; public ModuleManager(List> modules) { @@ -54,7 +55,7 @@ public boolean isEmpty() { return modules.isEmpty(); } - public List getModifiers() { + public List modifiers() { List modifiers = new ArrayList<>(); for (var moduleEntry : modules) { modifiers.addAll(moduleEntry.value().modifiers()); @@ -62,13 +63,17 @@ public List getModifiers() { return modifiers; } - public List> getKeys() { + public List> keys() { return modules.stream().map(moduleRegistryEntry -> moduleRegistryEntry.getKey().orElse(null)).filter(Objects::nonNull).toList(); } - public List getModifiers(ModifierType type) { + public void forEach(Consumer action) { + modules.forEach(moduleEntry -> action.accept(moduleEntry.value())); + } + + public List modifiers(ModifierType type) { //TODO: cache modules so it's quicker to sort by type - return ModuleManager.getModifiers(modules, type); + return ModuleManager.modifiers(modules, type); } public boolean enableModule(RegistryEntry module) { @@ -76,7 +81,6 @@ public boolean enableModule(RegistryEntry module) { return false; } - //TODO: trigger the modifier (they may have something to do when enabled) //TODO: send feedback to all players in game (chat + title) return modules.add(module); @@ -87,7 +91,6 @@ public boolean disableModule(RegistryEntry module) { return false; } - //TODO: trigger the modifier (they may have something to do when disabled) //TODO: send feedback to all players in game (chat + title) return modules.remove(module); } @@ -120,26 +123,12 @@ public SimpleGui buildGui(ServerPlayerEntity player) { return gui; } - public MutableText buildChatMessage() { - var text = Text.literal("\n").append(Text.translatable("text.uhc.enabled_modules").formatted(Formatting.GOLD)); - this.modules.forEach(moduleEntry -> { - var module = moduleEntry.value(); - var style = Style.EMPTY; - if (module.description().isPresent()) { - style = style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, module.description().get().copy())); - } - text.append(Text.literal("\n - ").formatted(Formatting.WHITE)).append(Texts.bracketed(module.name()).setStyle(style.withColor(module.color()))); - }); - text.append("\n"); - return text; - } - /** * Filters a registry entry list of modules by type * * @return A list of modifiers of the specified type */ - public static List getModifiers(List> modules, ModifierType type) { + public static List modifiers(List> modules, ModifierType type) { List modifiers = new ArrayList<>(); for (var moduleEntry : modules) { for (Modifier modifier : moduleEntry.value().modifiers()) { @@ -169,7 +158,7 @@ public void setupListeners(GameActivity activity) { } private EventResult onBlockBroken(ServerPlayerEntity playerEntity, ServerWorld world, BlockPos pos) { - for (TraversalBreakModifier piece : this.getModifiers(ModifierType.TRAVERSAL_BREAK)) { + for (TraversalBreakModifier piece : this.modifiers(ModifierType.TRAVERSAL_BREAK)) { piece.breakBlock(world, playerEntity, pos); } return EventResult.ALLOW; @@ -177,7 +166,7 @@ private EventResult onBlockBroken(ServerPlayerEntity playerEntity, ServerWorld w private EventResult onExplosion(Explosion explosion, List positions) { positions.forEach(pos -> { - for (TraversalBreakModifier piece : this.getModifiers(ModifierType.TRAVERSAL_BREAK)) { + for (TraversalBreakModifier piece : this.modifiers(ModifierType.TRAVERSAL_BREAK)) { piece.breakBlock(explosion.getWorld(), explosion.getCausingEntity(), pos); } }); @@ -188,7 +177,7 @@ private EventResult onExplosion(Explosion explosion, List positions) { private DroppedItemsResult onMobLoot(LivingEntity livingEntity, List itemStacks) { boolean keepOld = true; List stacks = new ArrayList<>(); - for (EntityLootModifier piece : this.getModifiers(ModifierType.ENTITY_LOOT)) { + for (EntityLootModifier piece : this.modifiers(ModifierType.ENTITY_LOOT)) { if (piece.test(livingEntity)) { stacks.addAll(piece.getLoots((ServerWorld) livingEntity.getWorld(), livingEntity)); if (piece.shouldReplace()) keepOld = false; @@ -201,7 +190,7 @@ private DroppedItemsResult onMobLoot(LivingEntity livingEntity, List private DroppedItemsResult onBlockDrop(@Nullable Entity entity, ServerWorld world, BlockPos pos, BlockState state, List itemStacks) { boolean keepOld = true; List stacks = new ArrayList<>(); - for (BlockLootModifier piece : this.getModifiers(ModifierType.BLOCK_LOOT)) { + for (BlockLootModifier piece : this.modifiers(ModifierType.BLOCK_LOOT)) { if (piece.test(state, world.getRandom())) { piece.spawnExperience(world, pos); stacks.addAll(piece.getLoots(world, pos, entity, entity instanceof LivingEntity ? ((LivingEntity) entity).getActiveItem() : ItemStack.EMPTY)); diff --git a/src/main/java/com/hugman/uhc/game/UHCAttachments.java b/src/main/java/com/hugman/uhc/game/UHCAttachments.java deleted file mode 100644 index b2dac6a..0000000 --- a/src/main/java/com/hugman/uhc/game/UHCAttachments.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.hugman.uhc.game; - -import com.hugman.uhc.UHC; -import xyz.nucleoid.plasmid.api.game.GameAttachment; - -public class UHCAttachments { - public static final GameAttachment MODULE_MANAGER = GameAttachment.create(UHC.id("module_manager")); -} diff --git a/src/main/java/com/hugman/uhc/game/UHCBar.java b/src/main/java/com/hugman/uhc/game/UHCBar.java index 895b9f6..ffd5d01 100644 --- a/src/main/java/com/hugman/uhc/game/UHCBar.java +++ b/src/main/java/com/hugman/uhc/game/UHCBar.java @@ -1,5 +1,6 @@ package com.hugman.uhc.game; +import com.hugman.text.Messenger; import com.hugman.uhc.util.TickUtil; import net.minecraft.entity.boss.BossBar; import net.minecraft.server.world.ServerWorld; @@ -12,7 +13,7 @@ public class UHCBar { private final BossBarWidget widget; - private final GameSpace gameSpace; + private final Messenger messenger; private String symbol; private String name; private String message; @@ -21,17 +22,17 @@ public class UHCBar { private long totalTicks = 0; private boolean canTick = false; - private UHCBar(BossBarWidget widget, GameSpace gameSpace) { + private UHCBar(BossBarWidget widget, Messenger messenger) { this.widget = widget; - this.gameSpace = gameSpace; + this.messenger = messenger; } - public static UHCBar create(GlobalWidgets widgets, GameSpace gameSpace) { - return new UHCBar(widgets.addBossBar(gameSpace.getMetadata().sourceConfig().value().name(), BossBar.Color.BLUE, BossBar.Style.PROGRESS), gameSpace); + public static UHCBar create(GlobalWidgets widgets, GameSpace gameSpace, Messenger messenger) { + return new UHCBar(widgets.addBossBar(gameSpace.getMetadata().sourceConfig().value().name(), BossBar.Color.BLUE, BossBar.Style.PROGRESS), messenger); } public void set(String symbol, String name, long totalTicks, long endTick, BossBar.Color color) { - this.symbol = symbol.equals("") ? "" : symbol + " "; + this.symbol = symbol; this.name = name + ".countdown_bar"; this.message = name + ".countdown_text"; this.totalTicks = totalTicks; @@ -41,11 +42,7 @@ public void set(String symbol, String name, long totalTicks, long endTick, BossB } public void set(String name, long totalTicks, long endTick, BossBar.Color color) { - this.set("", name, totalTicks, endTick, color); - } - - public void setMessage(String message) { - this.message = message; + this.set(null, name, totalTicks, endTick, color); } public void setFull(Text title) { @@ -71,7 +68,7 @@ public void tick(ServerWorld world) { sendMessage(seconds); newColor = BossBar.Color.RED; } - this.widget.setTitle(Text.literal(symbol).append(Text.translatable(name, TickUtil.format(ticks)))); + this.widget.setTitle(symbol == null ? Text.translatable(name, TickUtil.format(ticks)) : Text.literal(symbol).append(" ").append(Text.translatable(name, TickUtil.format(ticks)))); this.widget.setStyle(newColor, BossBar.Style.NOTCHED_10); this.widget.setProgress((float) seconds / totalSeconds); } @@ -79,11 +76,13 @@ public void tick(ServerWorld world) { private void sendMessage(long seconds) { float pitch = seconds == 0 ? 1.5F : 1.0F; - gameSpace.getPlayers().forEach(entity -> { - if (this.message != null && seconds != 0) { - entity.sendMessage(Text.literal(symbol).append(Text.translatable(this.message, TickUtil.formatPretty(seconds * 20).formatted(Formatting.RED))).formatted(Formatting.GOLD), false); + if (this.message != null && seconds != 0) { + if (symbol != null) { + messenger.info(symbol, message, TickUtil.formatPretty(seconds * 20).formatted(Formatting.RED)); + } else { + messenger.info(message, TickUtil.formatPretty(seconds * 20).formatted(Formatting.RED)); } - entity.playSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0F, pitch); - }); + } + messenger.sound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0F, pitch); } } diff --git a/src/main/java/com/hugman/uhc/game/UHCPlayerManager.java b/src/main/java/com/hugman/uhc/game/UHCPlayerManager.java index 1592a25..e45281c 100644 --- a/src/main/java/com/hugman/uhc/game/UHCPlayerManager.java +++ b/src/main/java/com/hugman/uhc/game/UHCPlayerManager.java @@ -100,10 +100,6 @@ public void forEachAliveParticipant(final Consumer consumer) }); } - public void forEachParticipant(final Consumer consumer) { - participants.keySet().forEach(consumer); - } - // TEAMS public PlayerSet teamPlayers(GameTeamKey team) { diff --git a/src/main/java/com/hugman/uhc/game/phase/UHCActive.java b/src/main/java/com/hugman/uhc/game/phase/UHCActive.java index fcbc69d..3516c06 100644 --- a/src/main/java/com/hugman/uhc/game/phase/UHCActive.java +++ b/src/main/java/com/hugman/uhc/game/phase/UHCActive.java @@ -1,5 +1,6 @@ package com.hugman.uhc.game.phase; +import com.hugman.text.Messenger; import com.hugman.uhc.UHC; import com.hugman.uhc.config.UHCGameConfig; import com.hugman.uhc.game.*; @@ -56,6 +57,7 @@ public class UHCActive { private final UHCBar bar; private final UHCSideBar sideBar; private final ModuleManager moduleManager; + private final Messenger msg; private long gameStartTick; private long startInvulnerableTick; @@ -71,42 +73,60 @@ public class UHCActive { private boolean isFinished = false; private UHCActive( - GameActivity activity, GameSpace gameSpace, ServerWorld world, - UHCGameConfig config, - GlobalWidgets widgets, + GameActivity activity, + int spawnOffset, UHCPlayerManager playerManager, - ModuleManager moduleManager + UHCTimers timers, + UHCSpawner spawnLogic, + UHCBar bar, + UHCSideBar sideBar, + ModuleManager moduleManager, + Messenger msg ) { - this.activity = activity; this.gameSpace = gameSpace; this.world = world; + this.activity = activity; + this.spawnOffset = spawnOffset; this.playerManager = playerManager; + this.timers = timers; + this.spawnLogic = spawnLogic; + this.bar = bar; + this.sideBar = sideBar; this.moduleManager = moduleManager; + this.msg = msg; + } - this.spawnOffset = config.uhcConfig().value().mapConfig().spawnOffset(); - this.timers = new UHCTimers(config, this.playerManager.participantCount()); - this.spawnLogic = new UHCSpawner(this.world); - this.bar = UHCBar.create(widgets, this.gameSpace); - this.sideBar = UHCSideBar.create(widgets, gameSpace); + private static UHCActive of( + GameActivity activity, + GameSpace gameSpace, + ServerWorld world, + UHCGameConfig config + ) { + var moduleManager = gameSpace.getAttachment(ModuleManager.ATTACHMENT); + assert moduleManager != null; + var playerManager = UHCPlayerManager.of(activity, gameSpace, config); + var widgets = GlobalWidgets.addTo(activity); + var messenger = new Messenger(gameSpace.getPlayers()); + return new UHCActive( + gameSpace, + world, + activity, + config.uhcConfig().value().mapConfig().spawnOffset(), + playerManager, + new UHCTimers(config, playerManager.participantCount()), + new UHCSpawner(world), + UHCBar.create(widgets, gameSpace, messenger), + UHCSideBar.create(widgets, gameSpace), + moduleManager, + messenger + ); } public static void start(GameSpace gameSpace, ServerWorld world, UHCGameConfig config) { gameSpace.setActivity(activity -> { - GlobalWidgets widgets = GlobalWidgets.addTo(activity); - var moduleManager = gameSpace.getAttachment(UHCAttachments.MODULE_MANAGER); - assert moduleManager != null; - var playerManager = UHCPlayerManager.of(activity, gameSpace, config); - UHCActive active = new UHCActive( - activity, - gameSpace, - world, - config, - widgets, - playerManager, - moduleManager - ); + UHCActive active = UHCActive.of(activity, gameSpace, world, config); activity.allow(GameRuleType.CRAFTING); activity.deny(GameRuleType.PORTALS); @@ -128,7 +148,7 @@ public static void start(GameSpace gameSpace, ServerWorld world, UHCGameConfig c activity.listen(PlayerDamageEvent.EVENT, active::onPlayerDamage); activity.listen(PlayerDeathEvent.EVENT, active::onPlayerDeath); - moduleManager.setupListeners(activity); + active.moduleManager.setupListeners(activity); }); } @@ -179,21 +199,21 @@ private void tick() { // Start - Cage chapter (@ 80%) if (worldTime == this.startInvulnerableTick - (timers.getInCagesTime() * 0.8)) { - this.sendModuleListToChat(); + msg.moduleList(this.moduleManager); } // Start - Invulnerable chapter else if (worldTime == this.startInvulnerableTick) { this.dropCages(); - this.sendInfo("text.uhc.dropped_players"); - this.sendInfo("text.uhc.world_will_shrink", TickUtil.formatPretty(this.finaleCagesTick - worldTime)); + msg.info("text.uhc.dropped_players"); + msg.info("text.uhc.world_will_shrink", TickUtil.formatPretty(this.finaleCagesTick - worldTime)); - this.bar.set("šŸ›”", "text.uhc.vulnerable", this.timers.getInvulnerabilityTime(), this.startWarmupTick, BossBar.Color.YELLOW); + this.bar.set(Messenger.SYMBOL_SHIELD, "text.uhc.vulnerable", this.timers.getInvulnerabilityTime(), this.startWarmupTick, BossBar.Color.YELLOW); } // Start - Warmup chapter else if (worldTime == this.startWarmupTick) { this.setInvulnerable(false); - this.sendWarning("šŸ›”", "text.uhc.no_longer_immune"); + msg.danger(Messenger.SYMBOL_SHIELD, "text.uhc.no_longer_immune"); this.bar.set("text.uhc.tp", this.timers.getWarmupTime(), this.finaleCagesTick, BossBar.Color.BLUE); } @@ -206,7 +226,7 @@ else if (worldTime == this.finaleCagesTick) { player.changeGameMode(GameMode.ADVENTURE); }); this.tpToCages(); - this.sendInfo("text.uhc.shrinking_when_pvp"); + msg.info("text.uhc.shrinking_when_pvp"); this.bar.set("text.uhc.dropping", this.timers.getInCagesTime(), this.finaleInvulnerabilityTick, BossBar.Color.PURPLE); } @@ -214,22 +234,22 @@ else if (worldTime == this.finaleCagesTick) { // Finale - Invulnerability chapter else if (worldTime == this.finaleInvulnerabilityTick) { this.dropCages(); - this.sendInfo("text.uhc.dropped_players"); + msg.info("text.uhc.dropped_players"); - this.bar.set("šŸ—”", "text.uhc.pvp", this.timers.getInvulnerabilityTime(), this.reducingTick, BossBar.Color.YELLOW); + this.bar.set(Messenger.SYMBOL_SWORD, "text.uhc.pvp", this.timers.getInvulnerabilityTime(), this.reducingTick, BossBar.Color.YELLOW); } // Finale - Reducing chapter else if (worldTime == this.reducingTick) { this.setInvulnerable(false); - this.sendWarning("šŸ›”", "text.uhc.no_longer_immune"); + msg.danger(Messenger.SYMBOL_SHIELD, "text.uhc.no_longer_immune"); this.setPvp(true); - this.sendWarning("šŸ—”", "text.uhc.pvp_enabled"); + msg.danger(Messenger.SYMBOL_SKULL, "text.uhc.pvp_enabled"); world.getWorldBorder().interpolateSize(this.timers.getStartMapSize(), this.timers.getEndMapSize(), this.timers.getShrinkingTime() * 50L); this.gameSpace.getPlayers().forEach(player -> player.networkHandler.sendPacket(new WorldBorderInterpolateSizeS2CPacket(world.getWorldBorder()))); - this.sendWarning("text.uhc.shrinking_start"); + msg.danger("text.uhc.shrinking_start"); this.bar.set("text.uhc.shrinking_finish", this.timers.getShrinkingTime(), this.deathMatchTick, BossBar.Color.RED); } @@ -239,7 +259,7 @@ else if (worldTime == this.deathMatchTick) { this.bar.setFull(Text.literal("šŸ—”").append(Text.translatable("text.uhc.deathmatchTime")).append("šŸ—”")); world.getWorldBorder().setDamagePerBlock(2.5); world.getWorldBorder().setSafeZone(0.125); - this.sendInfo("šŸ—”", "text.uhc.last_one_wins"); + msg.info(Messenger.SYMBOL_SWORD, "text.uhc.last_one_wins"); this.checkForWinner(); } } @@ -257,9 +277,7 @@ private JoinAcceptorResult acceptPlayer(JoinAcceptor joinAcceptor) { private void playerLeave(ServerPlayerEntity player) { if (playerManager.isParticipant(player)) { if (!playerManager.getParticipant(player).isEliminated()) { - var players = this.gameSpace.getPlayers(); - players.sendMessage(Text.literal("\nā˜  ").append(Text.translatable("text.uhc.player_eliminated", player.getDisplayName())).append("\n").formatted(Formatting.DARK_RED)); - players.playSound(SoundEvents.ENTITY_WITHER_SPAWN); + msg.elimination(player); this.eliminateParticipant(player); } } @@ -291,14 +309,14 @@ public void clearPlayer(ServerPlayerEntity player) { } public void refreshPlayerAttributes(ServerPlayerEntity player) { - for (PlayerAttributeModifier piece : this.moduleManager.getModifiers(ModifierType.PLAYER_ATTRIBUTE)) { + for (PlayerAttributeModifier piece : this.moduleManager.modifiers(ModifierType.PLAYER_ATTRIBUTE)) { piece.refreshAttribute(player); } player.networkHandler.sendPacket(new EntityAttributesS2CPacket(player.getId(), player.getAttributes().getTracked())); } public void applyPlayerEffects(ServerPlayerEntity player) { - for (PermanentEffectModifier piece : this.moduleManager.getModifiers(ModifierType.PERMANENT_EFFECT)) { + for (PermanentEffectModifier piece : this.moduleManager.modifiers(ModifierType.PERMANENT_EFFECT)) { piece.setEffect(player); } } @@ -384,40 +402,13 @@ private void dropCages() { })); } - // MESSAGES - private void sendMessage(String symbol, String s, Formatting f, Object... args) { - this.gameSpace.getPlayers().sendMessage(Text.literal(symbol).append(Text.translatable(s, args)).formatted(f)); - } - - public void sendInfo(String symbol, String s, Object... args) { - this.sendMessage(symbol + " ", s, Formatting.YELLOW, args); - } - - public void sendInfo(String s, Object... args) { - this.sendMessage("", s, Formatting.YELLOW, args); - } - - private void sendWarning(String symbol, String s, Object... args) { - this.sendMessage(symbol + " ", s, Formatting.RED, args); - } - - private void sendWarning(String s, Object... args) { - this.sendMessage("", s, Formatting.RED, args); - } - - public void sendModuleListToChat() { - if (!this.moduleManager.isEmpty()) { - this.gameSpace.getPlayers().sendMessage(this.moduleManager.buildChatMessage()); - this.gameSpace.getPlayers().playSound(SoundEvents.ENTITY_ITEM_PICKUP); - } - } - // GENERAL LISTENERS private void enableModule(RegistryEntry moduleRegistryEntry) { Module module = moduleRegistryEntry.value(); for (Modifier modifier : module.modifiers()) { modifier.enable(this.playerManager); } + msg.moduleAnnouncement("text.module.enabled", moduleRegistryEntry, Formatting.GREEN); } private void disableModule(RegistryEntry moduleRegistryEntry) { @@ -425,6 +416,7 @@ private void disableModule(RegistryEntry moduleRegistryEntry) { for (Modifier modifier : module.modifiers()) { modifier.disable(this.playerManager); } + msg.moduleAnnouncement("text.module.disabled", moduleRegistryEntry, Formatting.RED); } private EventResult onPlayerDamage(ServerPlayerEntity entity, DamageSource damageSource, float v) { @@ -438,9 +430,7 @@ private EventResult onPlayerDamage(ServerPlayerEntity entity, DamageSource damag private EventResult onPlayerDeath(ServerPlayerEntity player, DamageSource source) { if (playerManager.isParticipant(player)) { if (!playerManager.getParticipant(player).isEliminated()) { - PlayerSet players = this.gameSpace.getPlayers(); - players.sendMessage(Text.literal("\nā˜  ").append(source.getDeathMessage(player).copy()).append("!\n").formatted(Formatting.DARK_RED)); - players.playSound(SoundEvents.ENTITY_WITHER_SPAWN); + msg.death(source, player); this.eliminateParticipant(player); return EventResult.DENY; } diff --git a/src/main/java/com/hugman/uhc/game/phase/UHCWaiting.java b/src/main/java/com/hugman/uhc/game/phase/UHCWaiting.java index 6501dac..fe7f742 100644 --- a/src/main/java/com/hugman/uhc/game/phase/UHCWaiting.java +++ b/src/main/java/com/hugman/uhc/game/phase/UHCWaiting.java @@ -2,7 +2,6 @@ import com.hugman.uhc.config.UHCGameConfig; import com.hugman.uhc.game.ModuleManager; -import com.hugman.uhc.game.UHCAttachments; import com.hugman.uhc.game.UHCSpawner; import com.hugman.uhc.map.UHCMap; import net.minecraft.server.world.ServerWorld; @@ -41,7 +40,7 @@ public static GameOpenProcedure open(GameOpenContext context) { var gameSpace = activity.getGameSpace(); UHCWaiting waiting = new UHCWaiting(gameSpace, world, config, teamManager); - gameSpace.setAttachment(UHCAttachments.MODULE_MANAGER, moduleManager); + gameSpace.setAttachment(ModuleManager.ATTACHMENT, moduleManager); activity.listen(GamePlayerEvents.OFFER, JoinOffer::accept); activity.listen(GamePlayerEvents.ACCEPT, waiting::acceptPlayer); diff --git a/src/main/java/com/hugman/uhc/util/TickUtil.java b/src/main/java/com/hugman/uhc/util/TickUtil.java index 803a561..f0a630b 100644 --- a/src/main/java/com/hugman/uhc/util/TickUtil.java +++ b/src/main/java/com/hugman/uhc/util/TickUtil.java @@ -29,10 +29,6 @@ public static int getHours(long t) { return (int) asHours(t) % 24; } - public static boolean blink(long l, int max, int each) { - return l <= max && l % each == 0; - } - public static MutableText format(long t) { if (getHours(t) > 0) { return Text.literal(String.format("%02d:%02d:%02d", getHours(t), getMinutes(t), getSeconds(t))); diff --git a/src/main/resources/data/uhc/lang/en_us.json b/src/main/resources/data/uhc/lang/en_us.json index f5084a4..961be2b 100644 --- a/src/main/resources/data/uhc/lang/en_us.json +++ b/src/main/resources/data/uhc/lang/en_us.json @@ -43,5 +43,16 @@ "text.uhc.world_will_shrink": "You will get teleported in %s. The world will then start shrinking and PvP will get enabled.", "ui.uhc.modules.title": "Active Modules", - "command.uhc.modules.no_modules_activated": "This game has no modules activated!" + "command.uhc.modules.no_modules_activated": "This game has no modules activated!", + + "text.module.enabled": "The %s module has been enabled!", + "text.module.disabled": "The %s module has been disabled!", + "text.module.not_found": "Module with id \"%s\", not found!", + + "command.modules.no_manager": "The module manager is not available! (please contact the developer)", + "command.modules.no_modules_activated": "There are not active modules!", + "command.modules.already_enabled": "The %s module is already enabled!", + "command.modules.already_disabled": "The %s module is already disabled!", + "command.modules.enable.success": "The %s module has been successfully enabled.", + "command.modules.disable.success": "The %s module has been successfully disabled." } \ No newline at end of file From c71d36820437ecab8c409e5a5f47bceb55fbda41 Mon Sep 17 00:00:00 2001 From: Hugman Date: Sat, 7 Dec 2024 14:57:24 +0100 Subject: [PATCH 07/13] Update to 1.21.4 --- gradle.properties | 10 +++++----- src/main/java/com/hugman/uhc/game/UHCSpawner.java | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gradle.properties b/gradle.properties index c7ab736..534d93d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,16 +2,16 @@ org.gradle.jvmargs=-Xmx1G # Mod Properties -mod_version=2.4.0 +mod_version=3.0.0 maven_group=com.hugman archives_base_name=uhc # Fabric Properties # check these on https://fabricmc.net/develop/ -minecraft_version=1.21.3 -yarn_mappings=1.21.3+build.2 +minecraft_version=1.21.4 +yarn_mappings=1.21.4+build.1 loader_version=0.16.9 -fabric_version=0.108.0+1.21.3 +fabric_version=0.111.0+1.21.4 # check this on https://nucleoid.xyz/use/ -plasmid_version=0.6.0+1.21.3 \ No newline at end of file +plasmid_version=0.6.3-SNAPSHOT+1.21.4 \ No newline at end of file diff --git a/src/main/java/com/hugman/uhc/game/UHCSpawner.java b/src/main/java/com/hugman/uhc/game/UHCSpawner.java index b7ac276..cfa743f 100644 --- a/src/main/java/com/hugman/uhc/game/UHCSpawner.java +++ b/src/main/java/com/hugman/uhc/game/UHCSpawner.java @@ -36,7 +36,7 @@ public void spawnPlayerAtCenter(ServerPlayerEntity player) { public void spawnPlayerAt(ServerPlayerEntity player, BlockPos pos) { ChunkPos chunkPos = new ChunkPos(pos.getX() >> 4, pos.getZ() >> 4); - this.world.getChunkManager().addTicket(ChunkTicketType.POST_TELEPORT, chunkPos, 1, player.getId()); + this.world.getChunkManager().addTicket(ChunkTicketType.PLAYER, chunkPos, 1, chunkPos); player.refreshPositionAndAngles(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 0.0F, 0.0F); } From 082f8c796d2a7c4181fa30375aa3a31c82eb4240 Mon Sep 17 00:00:00 2001 From: Hugman Date: Sat, 7 Dec 2024 16:31:37 +0100 Subject: [PATCH 08/13] Small tweaks + CS --- .../com/hugman/uhc/command/ModulesCommand.java | 2 ++ .../java/com/hugman/uhc/game/ModuleManager.java | 3 ++- .../java/com/hugman/uhc/modifier/Modifier.java | 1 - .../uhc/modifier/PermanentEffectModifier.java | 3 +-- .../uhc/modifier/PlayerAttributeModifier.java | 2 -- .../com/hugman/uhc/module/ModuleEvents.java | 1 - .../data/doublerunner/plasmid/game/test.json | 17 ----------------- 7 files changed, 5 insertions(+), 24 deletions(-) delete mode 100644 src/main/resources/data/doublerunner/plasmid/game/test.json diff --git a/src/main/java/com/hugman/uhc/command/ModulesCommand.java b/src/main/java/com/hugman/uhc/command/ModulesCommand.java index 31320b2..87f3397 100644 --- a/src/main/java/com/hugman/uhc/command/ModulesCommand.java +++ b/src/main/java/com/hugman/uhc/command/ModulesCommand.java @@ -34,9 +34,11 @@ public static void register(CommandDispatcher dispatcher) { .requires(ModulesCommand::supportsModules) .executes(ModulesCommand::displayModules) .then(CommandManager.literal("enable") + .requires(source -> source.hasPermissionLevel(2)) .then(UHCModuleArgument.argumentFromDisabled("module") .executes(context -> enableModule(context, UHCModuleArgument.get(context, MODULE_ARG))))) .then(CommandManager.literal("disable") + .requires(source -> source.hasPermissionLevel(2)) .then(UHCModuleArgument.argumentFromEnabled("module") .executes(context -> disableModule(context, UHCModuleArgument.get(context, MODULE_ARG))))) ); diff --git a/src/main/java/com/hugman/uhc/game/ModuleManager.java b/src/main/java/com/hugman/uhc/game/ModuleManager.java index 4d94162..29c1ae3 100644 --- a/src/main/java/com/hugman/uhc/game/ModuleManager.java +++ b/src/main/java/com/hugman/uhc/game/ModuleManager.java @@ -16,7 +16,8 @@ import net.minecraft.screen.ScreenHandlerType; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; -import net.minecraft.text.*; +import net.minecraft.text.Style; +import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/com/hugman/uhc/modifier/Modifier.java b/src/main/java/com/hugman/uhc/modifier/Modifier.java index 38e306b..a06ce6d 100644 --- a/src/main/java/com/hugman/uhc/modifier/Modifier.java +++ b/src/main/java/com/hugman/uhc/modifier/Modifier.java @@ -3,7 +3,6 @@ import com.hugman.uhc.game.UHCPlayerManager; import com.hugman.uhc.registry.UHCRegistries; import com.mojang.serialization.Codec; -import net.minecraft.server.PlayerManager; public interface Modifier { Codec TYPE_CODEC = UHCRegistries.MODIFIER_TYPE.getCodec().dispatch(Modifier::getType, ModifierType::codec); diff --git a/src/main/java/com/hugman/uhc/modifier/PermanentEffectModifier.java b/src/main/java/com/hugman/uhc/modifier/PermanentEffectModifier.java index 1de7a37..c69fe45 100644 --- a/src/main/java/com/hugman/uhc/modifier/PermanentEffectModifier.java +++ b/src/main/java/com/hugman/uhc/modifier/PermanentEffectModifier.java @@ -7,7 +7,6 @@ import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.server.PlayerManager; import net.minecraft.server.network.ServerPlayerEntity; public record PermanentEffectModifier( @@ -34,7 +33,7 @@ public void enable(UHCPlayerManager playerManager) { } @Override - public void disable(UHCPlayerManager playerManager) { + public void disable(UHCPlayerManager playerManager) { playerManager.forEachAliveParticipant(player -> player.removeStatusEffect(this.effect)); } } diff --git a/src/main/java/com/hugman/uhc/modifier/PlayerAttributeModifier.java b/src/main/java/com/hugman/uhc/modifier/PlayerAttributeModifier.java index c3a2aa0..2f61082 100644 --- a/src/main/java/com/hugman/uhc/modifier/PlayerAttributeModifier.java +++ b/src/main/java/com/hugman/uhc/modifier/PlayerAttributeModifier.java @@ -1,6 +1,5 @@ package com.hugman.uhc.modifier; -import com.hugman.uhc.UHC; import com.hugman.uhc.game.UHCPlayerManager; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; @@ -8,7 +7,6 @@ import net.minecraft.entity.attribute.EntityAttributeInstance; import net.minecraft.entity.attribute.EntityAttributeModifier; import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.server.PlayerManager; import net.minecraft.server.network.ServerPlayerEntity; public record PlayerAttributeModifier( diff --git a/src/main/java/com/hugman/uhc/module/ModuleEvents.java b/src/main/java/com/hugman/uhc/module/ModuleEvents.java index 1ee770c..4592e6e 100644 --- a/src/main/java/com/hugman/uhc/module/ModuleEvents.java +++ b/src/main/java/com/hugman/uhc/module/ModuleEvents.java @@ -1,6 +1,5 @@ package com.hugman.uhc.module; -import com.hugman.uhc.game.UHCPlayerManager; import net.minecraft.registry.entry.RegistryEntry; import xyz.nucleoid.stimuli.event.StimulusEvent; diff --git a/src/main/resources/data/doublerunner/plasmid/game/test.json b/src/main/resources/data/doublerunner/plasmid/game/test.json deleted file mode 100644 index 145617e..0000000 --- a/src/main/resources/data/doublerunner/plasmid/game/test.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "type": "uhc:standard", - "config": "doublerunner:standard", - "name": { - "translate": "game.generic.mode", - "with": [ - { - "translate": "game.doublerunner" - }, - "test" - ] - }, - "players": { - "min": 1, - "threshold": 1 - } -} From f2dedbe12c5abe3b0f17d647a3a1e4293d472fb4 Mon Sep 17 00:00:00 2001 From: Hugman Date: Sun, 8 Dec 2024 12:06:06 +0100 Subject: [PATCH 09/13] Add the Better Tools modules --- .gitignore | 3 + .../com/hugman/uhc/game/ModuleManager.java | 15 ++++- .../com/hugman/uhc/game/phase/UHCActive.java | 2 +- .../com/hugman/uhc/modifier/ModifierType.java | 1 + .../uhc/modifier/ReplaceStackModifier.java | 20 +++++++ .../data/doublerunner/lang/en_us.json | 2 + .../tags/uhc/module/standard.json | 1 + .../uhc/module/better_tools_plus.json | 56 +++++++++++++++++++ .../resources/data/uhcrun/lang/en_us.json | 2 + .../data/uhcrun/tags/uhc/module/standard.json | 3 +- .../data/uhcrun/uhc/module/better_tools.json | 56 +++++++++++++++++++ 11 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/hugman/uhc/modifier/ReplaceStackModifier.java create mode 100644 src/main/resources/data/doublerunner/uhc/module/better_tools_plus.json create mode 100644 src/main/resources/data/uhcrun/uhc/module/better_tools.json diff --git a/.gitignore b/.gitignore index 3c37caf..4a73677 100644 --- a/.gitignore +++ b/.gitignore @@ -116,3 +116,6 @@ run/ # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) !gradle-wrapper.jar + +# Test game configs +*plasmid/game/test.json \ No newline at end of file diff --git a/src/main/java/com/hugman/uhc/game/ModuleManager.java b/src/main/java/com/hugman/uhc/game/ModuleManager.java index 29c1ae3..d3f4e71 100644 --- a/src/main/java/com/hugman/uhc/game/ModuleManager.java +++ b/src/main/java/com/hugman/uhc/game/ModuleManager.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable; import xyz.nucleoid.plasmid.api.game.GameActivity; import xyz.nucleoid.plasmid.api.game.GameAttachment; +import xyz.nucleoid.plasmid.api.game.event.GameActivityEvents; import xyz.nucleoid.stimuli.event.DroppedItemsResult; import xyz.nucleoid.stimuli.event.EventResult; import xyz.nucleoid.stimuli.event.block.BlockBreakEvent; @@ -151,11 +152,23 @@ public static Stream streamModifiers(Stream this.tick(playerManager)); + } + + private void tick(UHCPlayerManager playerManager) { + playerManager.forEachAliveParticipant(player -> { + for (ReplaceStackModifier piece : this.modifiers(ModifierType.REPLACE_STACK)) { + int slot = player.getInventory().getSlotWithStack(piece.target()); + if(slot != -1) { + player.getInventory().setStack(slot, piece.replacement()); + } + } + }); } private EventResult onBlockBroken(ServerPlayerEntity playerEntity, ServerWorld world, BlockPos pos) { diff --git a/src/main/java/com/hugman/uhc/game/phase/UHCActive.java b/src/main/java/com/hugman/uhc/game/phase/UHCActive.java index 3516c06..f87da62 100644 --- a/src/main/java/com/hugman/uhc/game/phase/UHCActive.java +++ b/src/main/java/com/hugman/uhc/game/phase/UHCActive.java @@ -148,7 +148,7 @@ public static void start(GameSpace gameSpace, ServerWorld world, UHCGameConfig c activity.listen(PlayerDamageEvent.EVENT, active::onPlayerDamage); activity.listen(PlayerDeathEvent.EVENT, active::onPlayerDeath); - active.moduleManager.setupListeners(activity); + active.moduleManager.setupListeners(activity, active.playerManager); }); } diff --git a/src/main/java/com/hugman/uhc/modifier/ModifierType.java b/src/main/java/com/hugman/uhc/modifier/ModifierType.java index 933043d..a25cf55 100644 --- a/src/main/java/com/hugman/uhc/modifier/ModifierType.java +++ b/src/main/java/com/hugman/uhc/modifier/ModifierType.java @@ -13,6 +13,7 @@ public record ModifierType(MapCodec codec) { public static final ModifierType PLAYER_ATTRIBUTE = register("player_attribute", PlayerAttributeModifier.CODEC); public static final ModifierType PERMANENT_EFFECT = register("permanent_effect", PermanentEffectModifier.CODEC); public static final ModifierType PLACED_FEATURES = register("placed_features", PlacedFeaturesModifier.CODEC); + public static final ModifierType REPLACE_STACK = register("replace_stack", ReplaceStackModifier.CODEC); private static ModifierType register(String name, MapCodec codec) { return register(UHC.id(name), codec); diff --git a/src/main/java/com/hugman/uhc/modifier/ReplaceStackModifier.java b/src/main/java/com/hugman/uhc/modifier/ReplaceStackModifier.java new file mode 100644 index 0000000..7aa8627 --- /dev/null +++ b/src/main/java/com/hugman/uhc/modifier/ReplaceStackModifier.java @@ -0,0 +1,20 @@ +package com.hugman.uhc.modifier; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.item.ItemStack; + +public record ReplaceStackModifier( + ItemStack target, + ItemStack replacement +) implements Modifier { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + ItemStack.VALIDATED_UNCOUNTED_CODEC.fieldOf("target").forGetter(ReplaceStackModifier::target), + ItemStack.VALIDATED_CODEC.fieldOf("replacement").forGetter(ReplaceStackModifier::replacement) + ).apply(instance, ReplaceStackModifier::new)); + + @Override + public ModifierType getType() { + return ModifierType.REPLACE_STACK; + } +} diff --git a/src/main/resources/data/doublerunner/lang/en_us.json b/src/main/resources/data/doublerunner/lang/en_us.json index a9cd466..344f752 100644 --- a/src/main/resources/data/doublerunner/lang/en_us.json +++ b/src/main/resources/data/doublerunner/lang/en_us.json @@ -11,6 +11,8 @@ "module.doublerunner.potion_drops": "Potion Drops", "module.doublerunner.potion_drops.description": "Some entities drop potions", "module.doublerunner.timberman.description": "Trees get cut instantly and drop oak planks", + "module.doublerunner.better_tools_plus": "Better Tools+", + "module.doublerunner.better_tools_plus.description": "Wooden tools are replaced with iron tools", "module_description.doublerunner.zombies_drop_strength_potions": "Zombies drops potions of Strength", "module_description.doublerunner.spiders_drop_poison_potions": "Spiders drops potions of Poison", diff --git a/src/main/resources/data/doublerunner/tags/uhc/module/standard.json b/src/main/resources/data/doublerunner/tags/uhc/module/standard.json index eaf40f0..d8c3d50 100644 --- a/src/main/resources/data/doublerunner/tags/uhc/module/standard.json +++ b/src/main/resources/data/doublerunner/tags/uhc/module/standard.json @@ -8,6 +8,7 @@ "doublerunner:blasted_ores_plus", "doublerunner:potion_drops", "doublerunner:faster_resources_plus", + "doublerunner:better_tools_plus", "uhcrun:animal_cooked_food", "uhcrun:mob_cooked_food" ] diff --git a/src/main/resources/data/doublerunner/uhc/module/better_tools_plus.json b/src/main/resources/data/doublerunner/uhc/module/better_tools_plus.json new file mode 100644 index 0000000..dffaa63 --- /dev/null +++ b/src/main/resources/data/doublerunner/uhc/module/better_tools_plus.json @@ -0,0 +1,56 @@ +{ + "name": { + "translate": "module.doublerunner.better_tools_plus" + }, + "description": { + "translate": "module.doublerunner.better_tools_plus.description" + }, + "icon": "minecraft:iron_pickaxe", + "modifiers": [ + { + "type": "uhc:replace_stack", + "target": { + "id": "minecraft:wooden_sword" + }, + "replacement": { + "id": "minecraft:iron_sword" + } + }, + { + "type": "uhc:replace_stack", + "target": { + "id": "minecraft:wooden_pickaxe" + }, + "replacement": { + "id": "minecraft:iron_pickaxe" + } + }, + { + "type": "uhc:replace_stack", + "target": { + "id": "minecraft:wooden_axe" + }, + "replacement": { + "id": "minecraft:iron_axe" + } + }, + { + "type": "uhc:replace_stack", + "target": { + "id": "minecraft:wooden_shovel" + }, + "replacement": { + "id": "minecraft:iron_shovel" + } + }, + { + "type": "uhc:replace_stack", + "target": { + "id": "minecraft:wooden_hoe" + }, + "replacement": { + "id": "minecraft:iron_hoe" + } + } + ] +} diff --git a/src/main/resources/data/uhcrun/lang/en_us.json b/src/main/resources/data/uhcrun/lang/en_us.json index 649e73d..a9d8292 100644 --- a/src/main/resources/data/uhcrun/lang/en_us.json +++ b/src/main/resources/data/uhcrun/lang/en_us.json @@ -17,6 +17,8 @@ "module.uhcrun.ore_boost.description": "Lapis, gold and diamond ores are more frequent", "module.uhcrun.timberman": "Timberman", "module.uhcrun.timberman.description": "Trees get cut instantly and drop oak planks", + "module.uhcrun.better_tools": "Better Tools", + "module.uhcrun.better_tools.description": "Wooden tools are replaced with stone tools", "module_description.uhcrun.stones_drop_cobblestone": "All stones types drop cobblestone", "module_description.uhcrun.gravel_drops_arrows_and_flint_and_steel": "Gravel drop arrows and flint and steel", diff --git a/src/main/resources/data/uhcrun/tags/uhc/module/standard.json b/src/main/resources/data/uhcrun/tags/uhc/module/standard.json index 4e6ea14..1979611 100644 --- a/src/main/resources/data/uhcrun/tags/uhc/module/standard.json +++ b/src/main/resources/data/uhcrun/tags/uhc/module/standard.json @@ -8,6 +8,7 @@ "uhcrun:blasted_ores", "uhcrun:faster_resources", "uhcrun:animal_cooked_food", - "uhcrun:mob_cooked_food" + "uhcrun:mob_cooked_food", + "uhcrun:better_tools" ] } diff --git a/src/main/resources/data/uhcrun/uhc/module/better_tools.json b/src/main/resources/data/uhcrun/uhc/module/better_tools.json new file mode 100644 index 0000000..82f985f --- /dev/null +++ b/src/main/resources/data/uhcrun/uhc/module/better_tools.json @@ -0,0 +1,56 @@ +{ + "name": { + "translate": "module.uhcrun.better_tools" + }, + "description": { + "translate": "module.uhcrun.better_tools.description" + }, + "icon": "minecraft:stone_pickaxe", + "modifiers": [ + { + "type": "uhc:replace_stack", + "target": { + "id": "minecraft:wooden_sword" + }, + "replacement": { + "id": "minecraft:stone_sword" + } + }, + { + "type": "uhc:replace_stack", + "target": { + "id": "minecraft:wooden_pickaxe" + }, + "replacement": { + "id": "minecraft:stone_pickaxe" + } + }, + { + "type": "uhc:replace_stack", + "target": { + "id": "minecraft:wooden_axe" + }, + "replacement": { + "id": "minecraft:stone_axe" + } + }, + { + "type": "uhc:replace_stack", + "target": { + "id": "minecraft:wooden_shovel" + }, + "replacement": { + "id": "minecraft:stone_shovel" + } + }, + { + "type": "uhc:replace_stack", + "target": { + "id": "minecraft:wooden_hoe" + }, + "replacement": { + "id": "minecraft:stone_hoe" + } + } + ] +} From d0eee099731f3d09f1c152e9dae01df92d4f1091 Mon Sep 17 00:00:00 2001 From: Hugman Date: Sun, 8 Dec 2024 12:08:59 +0100 Subject: [PATCH 10/13] Fix .gitinore? --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4a73677..596841b 100644 --- a/.gitignore +++ b/.gitignore @@ -118,4 +118,4 @@ run/ !gradle-wrapper.jar # Test game configs -*plasmid/game/test.json \ No newline at end of file +*/plasmid/game/test.json \ No newline at end of file From 169752d7a38254b2ae2efed8b8e87f0b08d3ac57 Mon Sep 17 00:00:00 2001 From: Hugman Date: Sun, 8 Dec 2024 12:09:16 +0100 Subject: [PATCH 11/13] nope ok --- .gitignore | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 596841b..1656c12 100644 --- a/.gitignore +++ b/.gitignore @@ -115,7 +115,4 @@ gradle-app.setting run/ # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar - -# Test game configs -*/plasmid/game/test.json \ No newline at end of file +!gradle-wrapper.jar \ No newline at end of file From 6577a7fa4e1ebf214cd0376412c56a153b8ce83d Mon Sep 17 00:00:00 2001 From: Hugman Date: Sun, 8 Dec 2024 12:27:27 +0100 Subject: [PATCH 12/13] Fixes --- .gitignore | 4 +- .../com/hugman/uhc/game/ModuleManager.java | 2 +- .../data/doublerunner/lang/en_us.json | 2 +- .../uhc/module/better_tools_plus.json | 56 +++++++++++++++++++ .../uhcrun/loot_table/gold_ingots/four.json | 25 +++++++++ 5 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 src/main/resources/data/uhcrun/loot_table/gold_ingots/four.json diff --git a/.gitignore b/.gitignore index 1656c12..f24d986 100644 --- a/.gitignore +++ b/.gitignore @@ -115,4 +115,6 @@ gradle-app.setting run/ # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar \ No newline at end of file +!gradle-wrapper.jar + +/src/main/resources/data/*/plasmid/game/test.json diff --git a/src/main/java/com/hugman/uhc/game/ModuleManager.java b/src/main/java/com/hugman/uhc/game/ModuleManager.java index d3f4e71..dc2d7f9 100644 --- a/src/main/java/com/hugman/uhc/game/ModuleManager.java +++ b/src/main/java/com/hugman/uhc/game/ModuleManager.java @@ -165,7 +165,7 @@ private void tick(UHCPlayerManager playerManager) { for (ReplaceStackModifier piece : this.modifiers(ModifierType.REPLACE_STACK)) { int slot = player.getInventory().getSlotWithStack(piece.target()); if(slot != -1) { - player.getInventory().setStack(slot, piece.replacement()); + player.getInventory().setStack(slot, piece.replacement().copy()); } } }); diff --git a/src/main/resources/data/doublerunner/lang/en_us.json b/src/main/resources/data/doublerunner/lang/en_us.json index 344f752..6905917 100644 --- a/src/main/resources/data/doublerunner/lang/en_us.json +++ b/src/main/resources/data/doublerunner/lang/en_us.json @@ -12,7 +12,7 @@ "module.doublerunner.potion_drops.description": "Some entities drop potions", "module.doublerunner.timberman.description": "Trees get cut instantly and drop oak planks", "module.doublerunner.better_tools_plus": "Better Tools+", - "module.doublerunner.better_tools_plus.description": "Wooden tools are replaced with iron tools", + "module.doublerunner.better_tools_plus.description": "Wooden tools are replaced with iron tools and diamond tools are enchanted with Efficiency III", "module_description.doublerunner.zombies_drop_strength_potions": "Zombies drops potions of Strength", "module_description.doublerunner.spiders_drop_poison_potions": "Spiders drops potions of Poison", diff --git a/src/main/resources/data/doublerunner/uhc/module/better_tools_plus.json b/src/main/resources/data/doublerunner/uhc/module/better_tools_plus.json index dffaa63..2c8976e 100644 --- a/src/main/resources/data/doublerunner/uhc/module/better_tools_plus.json +++ b/src/main/resources/data/doublerunner/uhc/module/better_tools_plus.json @@ -51,6 +51,62 @@ "replacement": { "id": "minecraft:iron_hoe" } + }, + { + "type": "uhc:replace_stack", + "target": { + "id": "minecraft:diamond_pickaxe" + }, + "replacement": { + "id": "minecraft:diamond_pickaxe", + "components": { + "minecraft:enchantments": { + "minecraft:efficiency": 3 + } + } + } + }, + { + "type": "uhc:replace_stack", + "target": { + "id": "minecraft:diamond_axe" + }, + "replacement": { + "id": "minecraft:diamond_axe", + "components": { + "minecraft:enchantments": { + "minecraft:efficiency": 3 + } + } + } + }, + { + "type": "uhc:replace_stack", + "target": { + "id": "minecraft:diamond_shovel" + }, + "replacement": { + "id": "minecraft:diamond_shovel", + "components": { + "minecraft:enchantments": { + "minecraft:efficiency": 3 + } + } + } + }, + { + "type": "uhc:replace_stack", + "target": { + "id": "minecraft:diamond_hoe" + }, + "replacement": { + "id": "minecraft:diamond_hoe", + "components": { + "minecraft:enchantments": { + "minecraft:efficiency": 3 + } + } + } } ] } diff --git a/src/main/resources/data/uhcrun/loot_table/gold_ingots/four.json b/src/main/resources/data/uhcrun/loot_table/gold_ingots/four.json new file mode 100644 index 0000000..ec3266f --- /dev/null +++ b/src/main/resources/data/uhcrun/loot_table/gold_ingots/four.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:gold_ingot", + "functions": [ + { + "function": "minecraft:set_count", + "count": 3 + }, + { + "function": "minecraft:apply_bonus", + "enchantment": "minecraft:fortune", + "formula": "minecraft:ore_drops" + } + ] + } + ] + } + ] +} \ No newline at end of file From e2c3240b651bbf938d65c34635726823dc21fc1e Mon Sep 17 00:00:00 2001 From: Hugman Date: Sun, 8 Dec 2024 12:30:09 +0100 Subject: [PATCH 13/13] Bump fabric.mod.json --- src/main/resources/fabric.mod.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 5e7fd6d..5ef2644 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -21,8 +21,8 @@ ] }, "depends": { - "java": ">=17", - "minecraft": ">=1.21.3", + "java": ">=21", + "minecraft": ">=1.21.4", "plasmid": "0.6.x", "fabricloader": ">=0.16.0", "fabric-api": ">=0.86.1"