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());