diff --git a/settings.gradle.kts b/settings.gradle.kts index 56a9e34..b5fd539 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -38,6 +38,7 @@ dependencyResolutionManagement { version("luckperms-minestom-loader", "5.6-SNAPSHOT") version("minestom-extensions", "2.1.1") version("guava", "33.7.1-jre") + version("pica", "0.1.0") library("aonyx.bom", "net.onelitefeather", "aonyx-bom").versionRef("aonyx") @@ -64,6 +65,7 @@ dependencyResolutionManagement { library("minestom-extensions-bom", "net.onelitefeather", "minestom-extensions-bom").versionRef("minestom-extensions") library("minestom-extensions", "net.onelitefeather", "minestom-extensions").withoutVersion() library("minestom-extensions-processor", "net.onelitefeather", "minestom-extensions-processor").withoutVersion() + library("pica", "net.onelitefeather", "pica").versionRef("pica") library("cloudnet-bom", "eu.cloudnetservice.cloudnet", "bom").versionRef("cloudnet") library("cloudnet-driver-api", "eu.cloudnetservice.cloudnet", "driver-api").withoutVersion() diff --git a/setup/build.gradle.kts b/setup/build.gradle.kts index c90f354..b5aa3ba 100644 --- a/setup/build.gradle.kts +++ b/setup/build.gradle.kts @@ -23,6 +23,7 @@ dependencies { runtimeOnly(libs.slf4j.simple) implementation(libs.xerus) implementation(libs.guira) + implementation(libs.pica) implementation(platform(libs.minestom.extensions.bom)) implementation(libs.minestom.extensions) diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/BounceSetup.java b/setup/src/main/java/net/theevilreaper/bounce/setup/BounceSetup.java index 48375f9..6a151b9 100644 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/BounceSetup.java +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/BounceSetup.java @@ -14,8 +14,6 @@ import net.theevilreaper.bounce.common.bootstrap.ServiceBootstrap; import net.theevilreaper.bounce.setup.command.GameModeCommand; import net.theevilreaper.bounce.setup.command.SetupCommand; -import net.theevilreaper.bounce.setup.dialog.DialogRegistry; -import net.theevilreaper.bounce.setup.dialog.SetupDialogRegistry; import net.theevilreaper.bounce.setup.dialog.event.PlayerDialogRequestEvent; import net.theevilreaper.bounce.setup.event.map.MapSetupSelectEvent; import net.theevilreaper.bounce.setup.event.ground.PlayerGroundBlockSelectEvent; @@ -30,7 +28,7 @@ import net.theevilreaper.bounce.setup.listener.PlayerDisconnectListener; import net.theevilreaper.bounce.setup.listener.PlayerItemListener; import net.theevilreaper.bounce.setup.listener.PlayerSpawnListener; -import net.theevilreaper.bounce.setup.listener.dialog.PlayerCustomClickEventListener; +import net.theevilreaper.bounce.setup.listener.dialog.DialogPayloadListener; import net.theevilreaper.bounce.setup.listener.dialog.PlayerDeletePromptListener; import net.theevilreaper.bounce.setup.listener.dialog.PlayerDialogRequestListener; import net.theevilreaper.bounce.setup.listener.dialog.SaveValidationPromptListener; @@ -58,14 +56,12 @@ public final class BounceSetup implements ListenerHandling { private final SetupMapProvider mapProvider; private final SetupDataService setupDataService; private final InventoryService inventoryService; - private final DialogRegistry dialogRegistry; public BounceSetup() { Path path = ServiceBootstrap.resolveWorkingDirectory(); this.mapProvider = new SetupMapProvider(path); this.setupDataService = SetupDataService.create(); this.inventoryService = new InventoryService(this.mapProvider::getEntries); - this.dialogRegistry = new SetupDialogRegistry(); MinecraftServer.getSchedulerManager().buildShutdownTask(this::onShutdown); MinecraftServer.getConnectionManager().setPlayerProvider(SetupPlayer::new); } @@ -101,15 +97,15 @@ private void registerListener(@NotNull EventNode node) { node.addListener(SetupFinishEvent.class, new SetupFinishListener(instanceSwitcher, this.setupDataService::remove)); node.addListener(SetupDiscardEvent.class, new SetupDiscardListener(instanceSwitcher, this.setupDataService::remove)); - node.addListener(SaveValidationPromptEvent.class, new SaveValidationPromptListener(dialogRegistry)); + node.addListener(SaveValidationPromptEvent.class, new SaveValidationPromptListener()); node.addListener(PlayerGroundBlockSelectEvent.class, new PlayerBlockSelectListener(this.setupDataService::get)); node.addListener(SetupInventorySwitchEvent.class, new SetupInventorySwitchListener(this.inventoryService, this.setupDataService::get)); node.addListener(GameMapBuilderStateNotifyEvent.class, new GameMapBuilderStateNotifyListener()); node.addListener(PlayerPushBlockSelectEvent.class, new PlayerPushBlockSelectListener(this.setupDataService::get)); node.addListener(PlayerPushIndexChangeEvent.class, new PlayerPushIndexChangeListener(this.setupDataService::get)); - node.addListener(PlayerDeletePromptEvent.class, new PlayerDeletePromptListener(dialogRegistry)); - node.addListener(PlayerCustomClickEvent.class, new PlayerCustomClickEventListener(this.dialogRegistry, this.setupDataService::get)); - node.addListener(PlayerDialogRequestEvent.class, new PlayerDialogRequestListener(this.dialogRegistry)); + node.addListener(PlayerDeletePromptEvent.class, new PlayerDeletePromptListener()); + node.addListener(PlayerCustomClickEvent.class, new DialogPayloadListener(this.setupDataService::get)); + node.addListener(PlayerDialogRequestEvent.class, new PlayerDialogRequestListener()); node.addListener(AddEntityToInstanceEvent.class, new EntityAddToInstanceListener(instanceSupplier)); } diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/AbstractDialogTemplate.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/AbstractDialogTemplate.java deleted file mode 100644 index bd3c803..0000000 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/AbstractDialogTemplate.java +++ /dev/null @@ -1,22 +0,0 @@ -package net.theevilreaper.bounce.setup.dialog; - - -import net.kyori.adventure.text.Component; -import org.jetbrains.annotations.NotNull; - -public abstract class AbstractDialogTemplate implements DialogTemplate { - - protected final Component header; - protected final Component submitComponent; - protected final Component cancelComponent; - - protected AbstractDialogTemplate( - @NotNull Component header, - @NotNull Component submitComponent, - @NotNull Component cancelComponent - ) { - this.header = header; - this.submitComponent = submitComponent; - this.cancelComponent = cancelComponent; - } -} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/AuthorDialogs.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/AuthorDialogs.java new file mode 100644 index 0000000..899937d --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/AuthorDialogs.java @@ -0,0 +1,75 @@ +package net.theevilreaper.bounce.setup.dialog; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.minestom.server.dialog.DialogAction; +import net.minestom.server.dialog.DialogAfterAction; +import net.minestom.server.entity.Player; +import net.onelitefeather.pica.dialog.DialogTemplate; +import net.onelitefeather.pica.dialog.type.DialogType; +import org.jetbrains.annotations.NotNull; + +public final class AuthorDialogs extends DialogBase { + + public static final Key AUTHOR_AMOUNT_KEY = create("author_amount_dialog"); + public static final Key AUTHOR_INPUT_KEY = create("bounce_author_setup"); + + public static void openAuthorAmountDialog(@NotNull Player player) { + DialogTemplate dialogTemplate = DialogType.confirm(AUTHOR_AMOUNT_KEY) + .meta(dialogMeta -> { + dialogMeta.closeWithEscape(false); + dialogMeta.pause(false); + dialogMeta.afterAction(DialogAfterAction.CLOSE); + dialogMeta.title(Component.text("Request Author(s)")); + dialogMeta.messageBody(template -> + template.contents(Component.text("How many builders should the map have?"))); + dialogMeta.range("amount", range -> range + .label(Component.text("Amount")) + .start(1) + .initial(1) + .end(10) + .step(1)); + }) + .yesButton(button -> button.width(100).label(Component.text("Save")).tooltip(Component.text("Click to confirm", NamedTextColor.GREEN)) + .action(new DialogAction.DynamicCustom(AUTHOR_AMOUNT_KEY, getEmptyPayload())) + ) + .noButton(button -> button.width(101).label(Component.text("Cancel")).tooltip(Component.text("Click to cancel", NamedTextColor.RED))) + .build(); + dialogTemplate.open(player); + } + + public static void openAuthorInputDialog(@NotNull Player player, int amount) { + DialogTemplate dialogTemplate = DialogType.confirm(AUTHOR_INPUT_KEY) + .meta(dialogMeta -> { + dialogMeta.closeWithEscape(false); + dialogMeta.pause(false); + dialogMeta.afterAction(DialogAfterAction.CLOSE); + dialogMeta.title(Component.text("Setup Author(s)")); + dialogMeta.messageBody(template -> + template.contents(Component.text("Please enter the builder(s)"))); + + for (int i = 0; i < amount; i++) { + String key = "author" + i; + Component label = Component.text("Author " + i); + dialogMeta.text(key, textInputTemplate -> + textInputTemplate.activeLabel(false).label(label).maxLength(32).initial("")); + } + }) + .yesButton(button -> button.width(100).label(Component.text("Save")).tooltip(Component.text("Click to confirm", NamedTextColor.GREEN)) + .action(new DialogAction.DynamicCustom(AUTHOR_INPUT_KEY, getAmountPayload(amount))) + ) + .noButton(button -> button.width(101).label(Component.text("Cancel")).tooltip(Component.text("Click to cancel", NamedTextColor.RED))) + .build(); + dialogTemplate.open(player); + } + + private AuthorDialogs() { + // Nothing to do here + } + + private static CompoundBinaryTag getAmountPayload(int amount) { + return CompoundBinaryTag.builder().putInt("amount", amount).build(); + } +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/DialogBase.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/DialogBase.java new file mode 100644 index 0000000..9b0d1ee --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/DialogBase.java @@ -0,0 +1,31 @@ +package net.theevilreaper.bounce.setup.dialog; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.Contract; + +public abstract class DialogBase { + + protected static final Component NO_COMPONENT = Component.text("No"); + + /** + * Creates a new instance of a {@link Key} in the bounce namespace. + * + * @param value the value of the key + * @return the created instance + */ + protected static Key create(String value) { + return Key.key("bounce", value); + } + + /** + * Creates a new {@link CompoundBinaryTag} with no data for the dialog. + * + * @return the created tag + */ + @Contract(pure = true) + protected static CompoundBinaryTag getEmptyPayload() { + return CompoundBinaryTag.builder().build(); + } +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/DialogRegistry.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/DialogRegistry.java deleted file mode 100644 index cd54e9f..0000000 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/DialogRegistry.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.theevilreaper.bounce.setup.dialog; - -import net.kyori.adventure.key.Key; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public interface DialogRegistry { - - @Nullable DialogTemplate get(@Nullable Key key); - - boolean contains(@NotNull Key key); -} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/DialogTemplate.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/DialogTemplate.java deleted file mode 100644 index a53241a..0000000 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/DialogTemplate.java +++ /dev/null @@ -1,23 +0,0 @@ -package net.theevilreaper.bounce.setup.dialog; - -import net.kyori.adventure.key.Key; -import net.minestom.server.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public interface DialogTemplate { - - default void open(@NotNull Player player) { - this.open(player, null); - } - - void open(@NotNull Player player, @Nullable K data); - - /** - * Gets the key of this dialog template. - * - * @return the given key - */ - @NotNull Key key(); - -} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/MapDialogs.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/MapDialogs.java new file mode 100644 index 0000000..55490af --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/MapDialogs.java @@ -0,0 +1,105 @@ +package net.theevilreaper.bounce.setup.dialog; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.minestom.server.dialog.DialogAction; +import net.minestom.server.dialog.DialogAfterAction; +import net.minestom.server.entity.Player; +import net.onelitefeather.pica.dialog.DialogTemplate; +import net.onelitefeather.pica.dialog.type.DialogType; +import net.theevilreaper.bounce.setup.inventory.overview.OverviewType; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public final class MapDialogs extends DialogBase { + + public static final Key NAME_KEY = create("name_setup_dialog"); + public static final Key DELETE_KEY = create("delete_dialog"); + public static final Key SAVE_VALIDATION_KEY = create("save_validation_dialog"); + + public static void openNameDialog(@NotNull Player player) { + DialogTemplate dialogTemplate = DialogType.confirm(NAME_KEY) + .meta(dialogMeta -> { + dialogMeta.closeWithEscape(false); + dialogMeta.pause(false); + dialogMeta.afterAction(DialogAfterAction.CLOSE); + dialogMeta.title(Component.text("Setup Map Name")); + dialogMeta.messageBody(template -> + template.contents(Component.text("How the name of the map should be?"))); + dialogMeta.text("name", textInputTemplate -> + textInputTemplate.activeLabel(true).label(Component.text("Name")).maxLength(32).initial("")); + }) + .yesButton(button -> button.width(100).label(Component.text("Save")).tooltip(Component.text("§7Click to submit")) + .action(new DialogAction.DynamicCustom(NAME_KEY, getEmptyPayload())) + ) + .noButton(button -> button.width(101).label(Component.text("Cancel")).tooltip(Component.text("§7Click to cancel"))) + .build(); + dialogTemplate.open(player); + } + + public static void openDeleteDialog(@NotNull Player player, @NotNull OverviewType overviewType) { + DialogTemplate dialogTemplate = DialogType.confirm(DELETE_KEY) + .meta(dialogMeta -> { + dialogMeta.closeWithEscape(false); + dialogMeta.pause(false); + dialogMeta.afterAction(DialogAfterAction.CLOSE); + dialogMeta.title(Component.text("Confirm data deletion")); + dialogMeta.messageBody(template -> + template.contents(Component.text("The following map data would be deleted:")).width(150)); + dialogMeta.messageBody(template -> template.contents(Component.empty()).width(1)); + dialogMeta.messageBody(template -> template.contents(Component.text(overviewType.getName())).width(100)); + }) + .yesButton(button -> button.width(100).label(Component.text("Yes")).tooltip(Component.text("Click to confirm", NamedTextColor.GREEN)) + .action(new DialogAction.DynamicCustom(DELETE_KEY, getTypePayload(overviewType))) + ) + .noButton(button -> button.width(101).label(NO_COMPONENT).tooltip(Component.text("Click to cancel", NamedTextColor.RED))) + .build(); + dialogTemplate.open(player); + } + + public static void openSaveValidationDialog(@NotNull Player player, @NotNull List missingFields) { + DialogTemplate dialogTemplate = DialogType.confirm(SAVE_VALIDATION_KEY) + .meta(dialogMeta -> { + dialogMeta.closeWithEscape(false); + dialogMeta.pause(false); + dialogMeta.afterAction(DialogAfterAction.CLOSE); + dialogMeta.title(Component.text("This map isn't ready yet")); + dialogMeta.messageBody(template -> + template.contents(Component.text("The following data is still missing:")).width(200)); + dialogMeta.messageBody(template -> template.contents(Component.empty()).width(1)); + + if (missingFields.isEmpty()) { + dialogMeta.messageBody(template -> + template.contents(Component.text("Unknown", NamedTextColor.RED)).width(200)); + } else { + for (String missingField : missingFields) { + dialogMeta.messageBody(template -> + template.contents(Component.text("- " + missingField, NamedTextColor.RED)).width(200)); + } + } + + dialogMeta.messageBody(template -> template.contents(Component.empty()).width(1)); + dialogMeta.messageBody(template -> + template.contents(Component.text("Go back and fill them in, or delete this setup.")).width(200)); + }) + .yesButton(button -> button.width(155).label(Component.text("Delete data")).tooltip(Component.text("Click to confirm", NamedTextColor.GREEN)) + .action(new DialogAction.DynamicCustom(SAVE_VALIDATION_KEY, getEmptyPayload())) + ) + .noButton(button -> button.width(155).label(Component.text("Back")).tooltip(Component.text("Click to cancel", NamedTextColor.RED))) + .build(); + dialogTemplate.open(player); + } + + private MapDialogs() { + // Nothing to do here + } + + @Contract(pure = true) + private static CompoundBinaryTag getTypePayload(@NotNull OverviewType overviewType) { + return CompoundBinaryTag.builder().putInt("type", overviewType.ordinal()).build(); + } +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/SetupDialogRegistry.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/SetupDialogRegistry.java deleted file mode 100644 index 92615d0..0000000 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/SetupDialogRegistry.java +++ /dev/null @@ -1,61 +0,0 @@ -package net.theevilreaper.bounce.setup.dialog; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.text.Component; -import net.theevilreaper.bounce.setup.dialog.type.*; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.Map; - -public class SetupDialogRegistry implements DialogRegistry { - - private final Map> dialogMap; - - public SetupDialogRegistry() { - this.dialogMap = new HashMap<>(); - - Component saveButton = Component.text("Save"); - Component cancelButton = Component.text("Cancel"); - - this.registerDialog( - new NameInputDialog( - Component.text("Setup Map Name"), - saveButton, - cancelButton - ) - ); - this.registerDialog(new AuthorRequestDialog( - Component.text("Request Author(s)"), - saveButton, - cancelButton - )); - this.registerDialog(new AuthorInputDialog( - Component.text("Setup Author(s)"), - saveButton, - cancelButton - // Default to 1 author - )); - this.registerDialog(new DeleteDialog()); - this.registerDialog(new ValueInputDialog()); - this.registerDialog(new WeightInputDialog()); - this.registerDialog(new ShuffleIntervalInputDialog()); - this.registerDialog(new ReshufflePercentageInputDialog()); - this.registerDialog(new SaveValidationDialog()); - } - - private void registerDialog(@NotNull DialogTemplate dialog) { - dialogMap.put(dialog.key(), dialog); - } - - @Override - public @Nullable DialogTemplate get(@Nullable Key key) { - return this.dialogMap.getOrDefault(key, null); - } - - @Override - public boolean contains(@NotNull Key key) { - return false; - } -} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/ValueDialogs.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/ValueDialogs.java new file mode 100644 index 0000000..3369a5d --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/ValueDialogs.java @@ -0,0 +1,84 @@ +package net.theevilreaper.bounce.setup.dialog; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.minestom.server.dialog.DialogAction; +import net.minestom.server.dialog.DialogAfterAction; +import net.minestom.server.entity.Player; +import net.onelitefeather.pica.dialog.DialogTemplate; +import net.onelitefeather.pica.dialog.type.DialogType; +import org.jetbrains.annotations.NotNull; + +/** + * Groups the simple "one range input, confirm or cancel" dialogs used to change a single numeric map value. + */ +public final class ValueDialogs extends DialogBase { + + public static final Key VALUE_KEY = create("value_setup_dialog"); + public static final Key WEIGHT_KEY = create("weight_setup_dialog"); + public static final Key SHUFFLE_INTERVAL_KEY = create("shuffle_interval_setup_dialog"); + public static final Key RESHUFFLE_PERCENTAGE_KEY = create("reshuffle_percentage_setup_dialog"); + + public static void openBounceValue(@NotNull Player player) { + open(player, VALUE_KEY, "Change block boost", "How much the block should bounce?", + "bounce_amount", "Amount", "options.generic_value", 1, 10, 1, 1, 200); + } + + public static void openWeight(@NotNull Player player) { + open(player, WEIGHT_KEY, "Change spawn chance", "Spawn probability in percent (0 - 100%):", + "weight_percentage", "Chance", "options.percent_value", 0, 100, 5, 0.1f, 320); + } + + public static void openShuffleInterval(@NotNull Player player) { + open(player, SHUFFLE_INTERVAL_KEY, "Change shuffle interval", "Reshuffle interval in ticks (20 ticks = 1 second):", + "interval_ticks", "Interval", "options.generic_value", 20, 600, 100, 10, 320); + } + + public static void openReshufflePercentage(@NotNull Player player) { + open(player, RESHUFFLE_PERCENTAGE_KEY, "Change reshuffle percentage", "Percentage of the area re-rolled\non each reshuffle (0 - 100%):", + "reshuffle_percentage", "Percentage", "options.percent_value", 0, 100, 10, 0.1f, 320); + } + + private static void open( + @NotNull Player player, + @NotNull Key key, + @NotNull String title, + @NotNull String message, + @NotNull String inputKey, + @NotNull String inputLabel, + @NotNull String labelFormat, + float start, + float end, + float initial, + float step, + int width + ) { + DialogTemplate dialogTemplate = DialogType.confirm(key) + .meta(dialogMeta -> { + dialogMeta.closeWithEscape(false); + dialogMeta.pause(false); + dialogMeta.afterAction(DialogAfterAction.CLOSE); + dialogMeta.title(Component.text(title)); + dialogMeta.messageBody(template -> template.contents(Component.text(message)).width(width)); + dialogMeta.range(inputKey, range -> range + .label(Component.text(inputLabel)) + .labelFormat(labelFormat) + .width(width) + .start(start) + .end(end) + .initial(initial) + .step(step)); + }) + .yesButton(button -> button.width(155).label(Component.text("Click to confirm")).tooltip(Component.text("Click to confirm", NamedTextColor.GREEN)) + .action(new DialogAction.DynamicCustom(key, getEmptyPayload())) + ) + .noButton(button -> button.width(155).label(Component.text("Click to cancel")).tooltip(Component.text("Click to cancel", NamedTextColor.RED))) + .build(); + dialogTemplate.open(player); + } + + private ValueDialogs() { + // Nothing to do here + } +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/event/PlayerDialogRequestEvent.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/event/PlayerDialogRequestEvent.java index 63ea1b4..c17b2b6 100644 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/event/PlayerDialogRequestEvent.java +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/event/PlayerDialogRequestEvent.java @@ -51,10 +51,6 @@ public enum Target { * The target for the dialog request is to define the amount of authors to set up. */ SETUP_REQUEST_AUTHOR, - /** - * The target for the dialog request is to define the author of the setup. - */ - SETUP_AUTHOR, /** * The target for the dialog request is to set up the block bounce. */ diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/AuthorAmountHandler.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/AuthorAmountHandler.java new file mode 100644 index 0000000..6cefbce --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/AuthorAmountHandler.java @@ -0,0 +1,19 @@ +package net.theevilreaper.bounce.setup.dialog.handler; + +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.minestom.server.event.player.PlayerCustomClickEvent; +import net.theevilreaper.bounce.setup.dialog.AuthorDialogs; + +public final class AuthorAmountHandler implements DialogHandler { + + /** + * {@inheritDoc} + */ + @Override + public void handle(PlayerCustomClickEvent event, CompoundBinaryTag payload) { + int amount = payload.getInt("amount", 1); + if (amount <= 0) return; + + AuthorDialogs.openAuthorInputDialog(event.getPlayer(), amount); + } +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/AuthorInputHandler.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/AuthorInputHandler.java new file mode 100644 index 0000000..79fb625 --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/AuthorInputHandler.java @@ -0,0 +1,35 @@ +package net.theevilreaper.bounce.setup.dialog.handler; + +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.minestom.server.event.player.PlayerCustomClickEvent; +import net.onelitefeather.guira.functional.OptionalSetupDataGetter; +import net.theevilreaper.bounce.setup.data.BounceData; +import org.jetbrains.annotations.NotNull; + +public final class AuthorInputHandler implements DialogHandler { + + private final OptionalSetupDataGetter setupDataGetter; + + public AuthorInputHandler(@NotNull OptionalSetupDataGetter setupDataGetter) { + this.setupDataGetter = setupDataGetter; + } + + /** + * {@inheritDoc} + */ + @Override + public void handle(PlayerCustomClickEvent event, CompoundBinaryTag payload) { + int amount = payload.getInt("amount", 1); + + setupDataGetter.get(event.getPlayer().getUuid()).ifPresent(setupData -> { + BounceData data = (BounceData) setupData; + + for (int i = 0; i < amount; i++) { + String author = payload.getString("author" + i); + if (author.trim().isEmpty()) continue; + data.getMapBuilder().builder(author); + } + data.triggerUpdate(); + }); + } +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/DeleteHandler.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/DeleteHandler.java new file mode 100644 index 0000000..8064cc5 --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/DeleteHandler.java @@ -0,0 +1,42 @@ +package net.theevilreaper.bounce.setup.dialog.handler; + +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.minestom.server.event.player.PlayerCustomClickEvent; +import net.onelitefeather.guira.functional.OptionalSetupDataGetter; +import net.theevilreaper.bounce.setup.data.BounceData; +import net.theevilreaper.bounce.setup.inventory.overview.OverviewType; +import org.jetbrains.annotations.NotNull; + +public final class DeleteHandler implements DialogHandler { + + private final OptionalSetupDataGetter setupDataGetter; + + public DeleteHandler(@NotNull OptionalSetupDataGetter setupDataGetter) { + this.setupDataGetter = setupDataGetter; + } + + /** + * {@inheritDoc} + */ + @Override + public void handle(PlayerCustomClickEvent event, CompoundBinaryTag payload) { + int type = payload.getInt("type"); + OverviewType overviewType = OverviewType.fromOrdinal(type); + + setupDataGetter.get(event.getPlayer().getUuid()).ifPresent(setupData -> { + BounceData data = (BounceData) setupData; + + switch (overviewType) { + case NAME -> data.getMapBuilder().name(null); + case BUILDER -> data.getMapBuilder().clearBuilders(); + case GAME_SPAWN -> data.getMapBuilder().gameSpawn(null); + case SPAWN -> data.getMapBuilder().spawn(null); + default -> { + // Nothing to do here + } + } + + data.triggerUpdate(); + }); + } +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/DialogHandler.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/DialogHandler.java new file mode 100644 index 0000000..2750ef4 --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/DialogHandler.java @@ -0,0 +1,19 @@ +package net.theevilreaper.bounce.setup.dialog.handler; + +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.minestom.server.event.player.PlayerCustomClickEvent; + +/** + * Represents a handler which reacts to the payload of a single dialog key. + */ +@FunctionalInterface +public interface DialogHandler { + + /** + * Handles the payload logic for a specific dialog key. + * + * @param event which is involved + * @param payload of the dialog + */ + void handle(PlayerCustomClickEvent event, CompoundBinaryTag payload); +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/NameHandler.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/NameHandler.java new file mode 100644 index 0000000..e7e471b --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/NameHandler.java @@ -0,0 +1,31 @@ +package net.theevilreaper.bounce.setup.dialog.handler; + +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.minestom.server.event.player.PlayerCustomClickEvent; +import net.onelitefeather.guira.functional.OptionalSetupDataGetter; +import net.theevilreaper.bounce.setup.data.BounceData; +import org.jetbrains.annotations.NotNull; + +public final class NameHandler implements DialogHandler { + + private final OptionalSetupDataGetter setupDataGetter; + + public NameHandler(@NotNull OptionalSetupDataGetter setupDataGetter) { + this.setupDataGetter = setupDataGetter; + } + + /** + * {@inheritDoc} + */ + @Override + public void handle(PlayerCustomClickEvent event, CompoundBinaryTag payload) { + String name = payload.getString("name"); + if (name.trim().isEmpty()) return; + + setupDataGetter.get(event.getPlayer().getUuid()).ifPresent(setupData -> { + BounceData data = (BounceData) setupData; + data.getMapBuilder().name(name); + data.triggerUpdate(); + }); + } +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/ReshufflePercentageHandler.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/ReshufflePercentageHandler.java new file mode 100644 index 0000000..0736418 --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/ReshufflePercentageHandler.java @@ -0,0 +1,31 @@ +package net.theevilreaper.bounce.setup.dialog.handler; + +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.minestom.server.event.player.PlayerCustomClickEvent; +import net.onelitefeather.guira.functional.OptionalSetupDataGetter; +import net.theevilreaper.bounce.setup.data.BounceData; +import org.jetbrains.annotations.NotNull; + +public final class ReshufflePercentageHandler implements DialogHandler { + + private final OptionalSetupDataGetter setupDataGetter; + + public ReshufflePercentageHandler(@NotNull OptionalSetupDataGetter setupDataGetter) { + this.setupDataGetter = setupDataGetter; + } + + /** + * {@inheritDoc} + */ + @Override + public void handle(PlayerCustomClickEvent event, CompoundBinaryTag payload) { + float percentage = payload.getFloat("reshuffle_percentage", 10.0f); + double reshufflePercentage = Math.max(0.0, Math.min(1.0, percentage / 100.0)); + + setupDataGetter.get(event.getPlayer().getUuid()).ifPresent(setupData -> { + BounceData data = (BounceData) setupData; + data.getMapBuilder().reshufflePercentage(reshufflePercentage); + data.triggerAreaViewUpdate(); + }); + } +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/SaveValidationHandler.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/SaveValidationHandler.java new file mode 100644 index 0000000..be53e31 --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/SaveValidationHandler.java @@ -0,0 +1,27 @@ +package net.theevilreaper.bounce.setup.dialog.handler; + +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.minestom.server.event.EventDispatcher; +import net.minestom.server.event.player.PlayerCustomClickEvent; +import net.onelitefeather.guira.functional.OptionalSetupDataGetter; +import net.theevilreaper.bounce.setup.data.BounceData; +import net.theevilreaper.bounce.setup.event.map.SetupDiscardEvent; +import org.jetbrains.annotations.NotNull; + +public final class SaveValidationHandler implements DialogHandler { + + private final OptionalSetupDataGetter setupDataGetter; + + public SaveValidationHandler(@NotNull OptionalSetupDataGetter setupDataGetter) { + this.setupDataGetter = setupDataGetter; + } + + /** + * {@inheritDoc} + */ + @Override + public void handle(PlayerCustomClickEvent event, CompoundBinaryTag payload) { + setupDataGetter.get(event.getPlayer().getUuid()).ifPresent(setupData -> + EventDispatcher.call(new SetupDiscardEvent((BounceData) setupData))); + } +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/ShuffleIntervalHandler.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/ShuffleIntervalHandler.java new file mode 100644 index 0000000..65a3e49 --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/ShuffleIntervalHandler.java @@ -0,0 +1,32 @@ +package net.theevilreaper.bounce.setup.dialog.handler; + +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.minestom.server.event.player.PlayerCustomClickEvent; +import net.onelitefeather.guira.functional.OptionalSetupDataGetter; +import net.theevilreaper.bounce.setup.data.BounceData; +import org.jetbrains.annotations.NotNull; + +public final class ShuffleIntervalHandler implements DialogHandler { + + private final OptionalSetupDataGetter setupDataGetter; + + public ShuffleIntervalHandler(@NotNull OptionalSetupDataGetter setupDataGetter) { + this.setupDataGetter = setupDataGetter; + } + + /** + * {@inheritDoc} + */ + @Override + public void handle(PlayerCustomClickEvent event, CompoundBinaryTag payload) { + int ticks = (int) payload.getFloat("interval_ticks", 100f); + if (ticks < 20) ticks = 20; + int finalTicks = ticks; + + setupDataGetter.get(event.getPlayer().getUuid()).ifPresent(setupData -> { + BounceData data = (BounceData) setupData; + data.getMapBuilder().shuffleIntervalTicks(finalTicks); + data.triggerAreaViewUpdate(); + }); + } +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/ValueHandler.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/ValueHandler.java new file mode 100644 index 0000000..cabde2a --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/ValueHandler.java @@ -0,0 +1,35 @@ +package net.theevilreaper.bounce.setup.dialog.handler; + +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.minestom.server.entity.Player; +import net.minestom.server.event.player.PlayerCustomClickEvent; +import net.onelitefeather.guira.functional.OptionalSetupDataGetter; +import net.theevilreaper.bounce.setup.data.BounceData; +import net.theevilreaper.bounce.setup.util.SetupTags; +import org.jetbrains.annotations.NotNull; + +public final class ValueHandler implements DialogHandler { + + private final OptionalSetupDataGetter setupDataGetter; + + public ValueHandler(@NotNull OptionalSetupDataGetter setupDataGetter) { + this.setupDataGetter = setupDataGetter; + } + + /** + * {@inheritDoc} + */ + @Override + public void handle(PlayerCustomClickEvent event, CompoundBinaryTag payload) { + Player player = event.getPlayer(); + int amount = payload.getInt("bounce_amount", 0); + int valueIndex = player.getTag(SetupTags.PUSH_SLOT_INDEX); + player.removeTag(SetupTags.PUSH_SLOT_INDEX); + + setupDataGetter.get(player.getUuid()).ifPresent(setupData -> { + BounceData data = (BounceData) setupData; + data.getMapBuilder().getPushDataBuilder().getPushValues().get(valueIndex).setValue(amount); + data.triggerPushValueUpdate(valueIndex); + }); + } +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/WeightHandler.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/WeightHandler.java new file mode 100644 index 0000000..7bc13d7 --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/handler/WeightHandler.java @@ -0,0 +1,40 @@ +package net.theevilreaper.bounce.setup.dialog.handler; + +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.minestom.server.entity.Player; +import net.minestom.server.event.player.PlayerCustomClickEvent; +import net.onelitefeather.guira.functional.OptionalSetupDataGetter; +import net.theevilreaper.bounce.setup.data.BounceData; +import net.theevilreaper.bounce.setup.util.SetupTags; +import org.jetbrains.annotations.NotNull; + +public final class WeightHandler implements DialogHandler { + + private final OptionalSetupDataGetter setupDataGetter; + + public WeightHandler(@NotNull OptionalSetupDataGetter setupDataGetter) { + this.setupDataGetter = setupDataGetter; + } + + /** + * {@inheritDoc} + */ + @Override + public void handle(PlayerCustomClickEvent event, CompoundBinaryTag payload) { + Player player = event.getPlayer(); + float percentage = payload.getFloat("weight_percentage", 5.0f); + double weight = Math.max(0.0, Math.min(1.0, Math.round((percentage / 100.0) * 1000.0) / 1000.0)); + int valueIndex = player.hasTag(SetupTags.PUSH_SLOT_INDEX) ? player.getTag(SetupTags.PUSH_SLOT_INDEX) : 0; + player.removeTag(SetupTags.PUSH_SLOT_INDEX); + + setupDataGetter.get(player.getUuid()).ifPresent(setupData -> { + BounceData data = (BounceData) setupData; + data.getMapBuilder().getPushDataBuilder().getPushValues().get(valueIndex).setWeight(weight); + if (valueIndex == 0) { + data.triggerGroundViewUpdate(); + } else { + data.triggerPushValueUpdate(valueIndex); + } + }); + } +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/AuthorInputDialog.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/AuthorInputDialog.java deleted file mode 100644 index 569dd9e..0000000 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/AuthorInputDialog.java +++ /dev/null @@ -1,85 +0,0 @@ -package net.theevilreaper.bounce.setup.dialog.type; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.minestom.server.dialog.*; -import net.minestom.server.entity.Player; -import net.minestom.server.network.packet.server.common.ShowDialogPacket; -import net.theevilreaper.bounce.setup.dialog.DialogTemplate; -import net.theevilreaper.bounce.setup.util.SetupTags; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -public class AuthorInputDialog implements DialogTemplate> { - - public static final Key DIALOG_KEY = Key.key("bounce", "bounce_author_setup"); - - private final Component header; - private final Component submitComponent; - private final Component cancelComponent; - - public AuthorInputDialog(@NotNull Component header, @NotNull Component submitComponent, @NotNull Component cancelComponent) { - this.header = header; - this.submitComponent = submitComponent; - this.cancelComponent = cancelComponent; - } - - @Override - public void open(@NotNull Player player, @Nullable List data) { - int amount = player.getTag(SetupTags.AUTHOR_AMOUNT_TAG); - List inputFields = new ArrayList<>(); - for (int i = 0; i < amount; i++) { - inputFields.add( - new DialogInput.Text( - "author" + i, - 200, - Component.text("Author " + i), - false, - "", - 32, - null - ) - ); - } - var packet = new ShowDialogPacket(new Dialog.Confirmation( - new DialogMetadata( - header, - null, - false, - false, - DialogAfterAction.CLOSE, - List.of( - new DialogBody.PlainMessage(Component.text("Please enter the builder(s)"), 200) - ), - inputFields - ), - new DialogActionButton( - submitComponent, - Component.text("Click to confirm", NamedTextColor.GREEN), - 100, - new DialogAction.DynamicCustom(DIALOG_KEY, - CompoundBinaryTag.builder() - .putInt("amount", amount) - .build() - ) - ), - new DialogActionButton( - cancelComponent, - Component.text("Click to cancel", NamedTextColor.RED), - 101, - null - ) - )); - player.sendPacket(packet); - } - - @Override - public @NotNull Key key() { - return DIALOG_KEY; - } -} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/AuthorRequestDialog.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/AuthorRequestDialog.java deleted file mode 100644 index 9445f1c..0000000 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/AuthorRequestDialog.java +++ /dev/null @@ -1,65 +0,0 @@ -package net.theevilreaper.bounce.setup.dialog.type; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.minestom.server.dialog.*; -import net.minestom.server.entity.Player; -import net.minestom.server.network.packet.server.common.ShowDialogPacket; -import net.theevilreaper.bounce.setup.dialog.DialogTemplate; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -public class AuthorRequestDialog implements DialogTemplate { - - public static final Key DIALOG_KEY = Key.key("bounce", "author_amount_dialog"); - - private final Component header; - private final Component submitComponent; - private final Component cancelComponent; - - public AuthorRequestDialog(@NotNull Component header, @NotNull Component submitComponent, @NotNull Component cancelComponent) { - this.header = header; - this.submitComponent = submitComponent; - this.cancelComponent = cancelComponent; - } - - @Override - public void open(@NotNull Player player, Void test) { - var packet = new ShowDialogPacket(new Dialog.Confirmation( - new DialogMetadata( - header, - null, - false, - false, - DialogAfterAction.CLOSE, - List.of( - new DialogBody.PlainMessage(Component.text("How many builders should the map have?"), 200) - ), - List.of( - new DialogInput.NumberRange("amount", 200, Component.text("Amount"), "options.generic_value", 1, 10, 1f, 1f) - ) - ), - new DialogActionButton( - submitComponent, - Component.text("Click to confirm", NamedTextColor.GREEN), - 100, - new DialogAction.DynamicCustom(DIALOG_KEY, CompoundBinaryTag.builder().build()) - ), - new DialogActionButton( - cancelComponent, - Component.text("Click to cancel", NamedTextColor.RED), - 101, - null - ) - )); - player.sendPacket(packet); - } - - @Override - public @NotNull Key key() { - return DIALOG_KEY; - } -} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/DeleteDialog.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/DeleteDialog.java deleted file mode 100644 index 692b432..0000000 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/DeleteDialog.java +++ /dev/null @@ -1,65 +0,0 @@ -package net.theevilreaper.bounce.setup.dialog.type; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.minestom.server.dialog.*; -import net.minestom.server.entity.Player; -import net.minestom.server.network.packet.server.common.ShowDialogPacket; -import net.theevilreaper.bounce.setup.dialog.AbstractDialogTemplate; -import net.theevilreaper.bounce.setup.inventory.overview.OverviewType; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class DeleteDialog extends AbstractDialogTemplate { - - public static final Key DIALOG_KEY = Key.key("bounce", "delete_dialog"); - - public DeleteDialog() { - super(Component.text("Confirm data deletion"), Component.text("Yes"), Component.text("No")); - } - - @Override - public void open(@NotNull Player player, @Nullable OverviewType data) { - var packet = new ShowDialogPacket(new Dialog.Confirmation( - new DialogMetadata( - header, - null, - false, - false, - DialogAfterAction.CLOSE, - List.of( - new DialogBody.PlainMessage(Component.text("The following map data would be deleted:"), 150), - new DialogBody.PlainMessage(Component.empty(), 1), - new DialogBody.PlainMessage(Component.text(data == null ? "No data provided" : data.getName()), 100) - ), - List.of() - ), - new DialogActionButton( - submitComponent, - Component.text("Click to confirm", NamedTextColor.GREEN), - 100, - new DialogAction.DynamicCustom(DIALOG_KEY, CompoundBinaryTag - .builder() - .putInt("type", data.ordinal()) - .build() - ) - ), - new DialogActionButton( - cancelComponent, - Component.text("Click to cancel", NamedTextColor.RED), - 101, - null - ) - )); - player.sendPacket(packet); - } - - @Override - public @NotNull Key key() { - return DIALOG_KEY; - } -} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/NameInputDialog.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/NameInputDialog.java deleted file mode 100644 index 1f70280..0000000 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/NameInputDialog.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.theevilreaper.bounce.setup.dialog.type; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.kyori.adventure.text.Component; -import net.minestom.server.dialog.*; -import net.minestom.server.entity.Player; -import net.minestom.server.network.packet.server.common.ShowDialogPacket; -import net.theevilreaper.bounce.setup.dialog.DialogTemplate; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public final class NameInputDialog implements DialogTemplate { - - public static final Key DIALOG_KEY = Key.key("bounce", "name_setup_dialog"); - - private final Component header; - private final Component submitComponent; - private final Component cancelComponent; - - public NameInputDialog(@NotNull Component header, @NotNull Component submitComponent, @NotNull Component cancelComponent) { - this.header = header; - this.submitComponent = submitComponent; - this.cancelComponent = cancelComponent; - } - - /** - * Opens the name input dialog for the given player with the provided data. - * @param player the player to open the dialog for - * @param data the initial data to pre-fill the input field, can be null - */ - public void open(@NotNull Player player, @Nullable String data) { - String initialName = data == null ? "" : data; - var packet = new ShowDialogPacket(new Dialog.Confirmation( - new DialogMetadata( - header, - null, - false, - false, - DialogAfterAction.CLOSE, - List.of( - new DialogBody.PlainMessage(Component.text("How the name of the map should be?"), 200) - ), - List.of( - new DialogInput.Text("name", 200, Component.text("Name"), true, initialName, 32, null) - ) - ), - new DialogActionButton( - submitComponent, - Component.text("§7Click to submit"), - 100, - new DialogAction.DynamicCustom(DIALOG_KEY, CompoundBinaryTag.builder().build()) - ), - new DialogActionButton( - cancelComponent, - Component.text("§7Click to cancel"), - 101, - null - ) - )); - player.sendPacket(packet); - } - - @Override - public @NotNull Key key() { - return DIALOG_KEY; - } -} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/ReshufflePercentageInputDialog.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/ReshufflePercentageInputDialog.java deleted file mode 100644 index fc3f945..0000000 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/ReshufflePercentageInputDialog.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.theevilreaper.bounce.setup.dialog.type; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.minestom.server.dialog.*; -import net.minestom.server.entity.Player; -import net.minestom.server.network.packet.server.common.ShowDialogPacket; -import net.theevilreaper.bounce.setup.dialog.AbstractDialogTemplate; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public final class ReshufflePercentageInputDialog extends AbstractDialogTemplate { - - public static final Key DIALOG_KEY = Key.key("bounce", "reshuffle_percentage_setup_dialog"); - - public ReshufflePercentageInputDialog() { - super( - Component.text("Change reshuffle percentage"), - Component.text("Click to confirm"), - Component.text("Click to cancel") - ); - } - - @Override - public void open(@NotNull Player player) { - this.open(player, 10.0f); - } - - @Override - public void open(@NotNull Player player, @Nullable Float data) { - float initial = data != null ? data : 10.0f; - ShowDialogPacket packet = new ShowDialogPacket(new Dialog.Confirmation( - new DialogMetadata( - header, - null, - false, - false, - DialogAfterAction.CLOSE, - List.of( - new DialogBody.PlainMessage(Component.text("Percentage of the area re-rolled\non each reshuffle (0 - 100%):"), 320) - ), - List.of( - new DialogInput.NumberRange("reshuffle_percentage", 320, Component.text("Percentage"), "options.percent_value", 0f, 100f, initial, 0.1f) - ) - ), - new DialogActionButton( - submitComponent, - Component.text("Click to confirm", NamedTextColor.GREEN), - 155, - new DialogAction.DynamicCustom(DIALOG_KEY, CompoundBinaryTag.builder().build()) - ), - new DialogActionButton( - cancelComponent, - Component.text("Click to cancel", NamedTextColor.RED), - 155, - null - ) - )); - player.sendPacket(packet); - } - - @Override - public @NotNull Key key() { - return DIALOG_KEY; - } -} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/SaveValidationDialog.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/SaveValidationDialog.java deleted file mode 100644 index ffca4b2..0000000 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/SaveValidationDialog.java +++ /dev/null @@ -1,80 +0,0 @@ -package net.theevilreaper.bounce.setup.dialog.type; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.minestom.server.dialog.*; -import net.minestom.server.entity.Player; -import net.minestom.server.network.packet.server.common.ShowDialogPacket; -import net.theevilreaper.bounce.setup.dialog.AbstractDialogTemplate; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -/** - * Shown when a player tries to save a map which is still missing required data. Offers to either go back and - * finish it, or to discard the whole setup process. - */ -public final class SaveValidationDialog extends AbstractDialogTemplate> { - - public static final Key DIALOG_KEY = Key.key("bounce", "save_validation_dialog"); - - public SaveValidationDialog() { - super( - Component.text("This map isn't ready yet"), - Component.text("Delete data"), - Component.text("Back") - ); - } - - @Override - public void open(@NotNull Player player, @Nullable List missingFields) { - List body = new ArrayList<>(); - body.add(new DialogBody.PlainMessage(Component.text("The following data is still missing:"), 200)); - body.add(new DialogBody.PlainMessage(Component.empty(), 1)); - - if (missingFields == null || missingFields.isEmpty()) { - body.add(new DialogBody.PlainMessage(Component.text("Unknown", NamedTextColor.RED), 200)); - } else { - for (String missingField : missingFields) { - body.add(new DialogBody.PlainMessage(Component.text("- " + missingField, NamedTextColor.RED), 200)); - } - } - - body.add(new DialogBody.PlainMessage(Component.empty(), 1)); - body.add(new DialogBody.PlainMessage(Component.text("Go back and fill them in, or delete this setup."), 200)); - - ShowDialogPacket packet = new ShowDialogPacket(new Dialog.Confirmation( - new DialogMetadata( - header, - null, - false, - false, - DialogAfterAction.CLOSE, - body, - List.of() - ), - new DialogActionButton( - submitComponent, - Component.text("Click to confirm", NamedTextColor.GREEN), - 155, - new DialogAction.DynamicCustom(DIALOG_KEY, CompoundBinaryTag.builder().build()) - ), - new DialogActionButton( - cancelComponent, - Component.text("Click to cancel", NamedTextColor.RED), - 155, - null - ) - )); - player.sendPacket(packet); - } - - @Override - public @NotNull Key key() { - return DIALOG_KEY; - } -} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/ShuffleIntervalInputDialog.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/ShuffleIntervalInputDialog.java deleted file mode 100644 index 7ef8852..0000000 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/ShuffleIntervalInputDialog.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.theevilreaper.bounce.setup.dialog.type; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.minestom.server.dialog.*; -import net.minestom.server.entity.Player; -import net.minestom.server.network.packet.server.common.ShowDialogPacket; -import net.theevilreaper.bounce.setup.dialog.AbstractDialogTemplate; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public final class ShuffleIntervalInputDialog extends AbstractDialogTemplate { - - public static final Key DIALOG_KEY = Key.key("bounce", "shuffle_interval_setup_dialog"); - - public ShuffleIntervalInputDialog() { - super( - Component.text("Change shuffle interval"), - Component.text("Click to confirm"), - Component.text("Click to cancel") - ); - } - - @Override - public void open(@NotNull Player player) { - this.open(player, 100.0f); - } - - @Override - public void open(@NotNull Player player, @Nullable Float data) { - float initial = data != null ? data : 100.0f; - ShowDialogPacket packet = new ShowDialogPacket(new Dialog.Confirmation( - new DialogMetadata( - header, - null, - false, - false, - DialogAfterAction.CLOSE, - List.of( - new DialogBody.PlainMessage(Component.text("Reshuffle interval in ticks (20 ticks = 1 second):"), 320) - ), - List.of( - new DialogInput.NumberRange("interval_ticks", 320, Component.text("Interval"), "options.generic_value", 20f, 600f, initial, 10f) - ) - ), - new DialogActionButton( - submitComponent, - Component.text("Click to confirm", NamedTextColor.GREEN), - 155, - new DialogAction.DynamicCustom(DIALOG_KEY, CompoundBinaryTag.builder().build()) - ), - new DialogActionButton( - cancelComponent, - Component.text("Click to cancel", NamedTextColor.RED), - 155, - null - ) - )); - player.sendPacket(packet); - } - - @Override - public @NotNull Key key() { - return DIALOG_KEY; - } -} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/ValueInputDialog.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/ValueInputDialog.java deleted file mode 100644 index 68319b7..0000000 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/ValueInputDialog.java +++ /dev/null @@ -1,69 +0,0 @@ -package net.theevilreaper.bounce.setup.dialog.type; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.minestom.server.dialog.*; -import net.minestom.server.entity.Player; -import net.minestom.server.network.packet.server.common.ShowDialogPacket; -import net.theevilreaper.bounce.setup.dialog.AbstractDialogTemplate; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public final class ValueInputDialog extends AbstractDialogTemplate { - - public static final Key DIALOG_KEY = Key.key("bounce", "value_setup_dialog"); - - public ValueInputDialog() { - super( - Component.text("Change block boost"), - Component.text("Click to confirm"), - Component.text("Click to cancel") - ); - } - - @Override - public void open(@NotNull Player player) { - this.open(player, 1); - } - - @Override - public void open(@NotNull Player player, @Nullable Integer data) { - ShowDialogPacket packet = new ShowDialogPacket(new Dialog.Confirmation( - new DialogMetadata( - header, - null, - false, - false, - DialogAfterAction.CLOSE, - List.of( - new DialogBody.PlainMessage(Component.text("How much the block should bounce?"), 200) - ), - List.of( - new DialogInput.NumberRange("bounce_amount", 200, Component.text("Amount"), "options.generic_value", 1, 10, 1f, 1f) - ) - ), - new DialogActionButton( - submitComponent, - Component.text("Click to confirm", NamedTextColor.GREEN), - 100, - new DialogAction.DynamicCustom(DIALOG_KEY, CompoundBinaryTag.builder().build()) - ), - new DialogActionButton( - cancelComponent, - Component.text("Click to cancel", NamedTextColor.RED), - 101, - null - ) - )); - player.sendPacket(packet); - } - - @Override - public @NotNull Key key() { - return DIALOG_KEY; - } -} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/WeightInputDialog.java b/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/WeightInputDialog.java deleted file mode 100644 index a71c499..0000000 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/dialog/type/WeightInputDialog.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.theevilreaper.bounce.setup.dialog.type; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.minestom.server.dialog.*; -import net.minestom.server.entity.Player; -import net.minestom.server.network.packet.server.common.ShowDialogPacket; -import net.theevilreaper.bounce.setup.dialog.AbstractDialogTemplate; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public final class WeightInputDialog extends AbstractDialogTemplate { - - public static final Key DIALOG_KEY = Key.key("bounce", "weight_setup_dialog"); - - public WeightInputDialog() { - super( - Component.text("Change spawn chance"), - Component.text("Click to confirm"), - Component.text("Click to cancel") - ); - } - - @Override - public void open(@NotNull Player player) { - this.open(player, 5.0f); - } - - @Override - public void open(@NotNull Player player, @Nullable Float data) { - float initial = data != null ? data : 5.0f; - ShowDialogPacket packet = new ShowDialogPacket(new Dialog.Confirmation( - new DialogMetadata( - header, - null, - false, - false, - DialogAfterAction.CLOSE, - List.of( - new DialogBody.PlainMessage(Component.text("Spawn probability in percent (0 - 100%):"), 320) - ), - List.of( - new DialogInput.NumberRange("weight_percentage", 320, Component.text("Chance"), "options.percent_value", 0f, 100f, initial, 0.1f) - ) - ), - new DialogActionButton( - submitComponent, - Component.text("Click to confirm", NamedTextColor.GREEN), - 155, - new DialogAction.DynamicCustom(DIALOG_KEY, CompoundBinaryTag.builder().build()) - ), - new DialogActionButton( - cancelComponent, - Component.text("Click to cancel", NamedTextColor.RED), - 155, - null - ) - )); - player.sendPacket(packet); - } - - @Override - public @NotNull Key key() { - return DIALOG_KEY; - } -} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/event/map/SetupDiscardEvent.java b/setup/src/main/java/net/theevilreaper/bounce/setup/event/map/SetupDiscardEvent.java index b8cef5f..be1267a 100644 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/event/map/SetupDiscardEvent.java +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/event/map/SetupDiscardEvent.java @@ -6,7 +6,7 @@ /** * Fired when a player discards an in-progress setup instead of saving it, e.g. after confirming a - * {@link net.theevilreaper.bounce.setup.dialog.type.SaveValidationDialog}. + * {@link net.theevilreaper.bounce.setup.dialog.MapDialogs#openSaveValidationDialog}. */ public class SetupDiscardEvent implements Event { diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/inventory/slot/StringSlot.java b/setup/src/main/java/net/theevilreaper/bounce/setup/inventory/slot/StringSlot.java index 90254f5..544a7a6 100644 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/inventory/slot/StringSlot.java +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/inventory/slot/StringSlot.java @@ -6,6 +6,7 @@ import net.minestom.server.inventory.click.Click; import net.minestom.server.item.ItemStack; import net.theevilreaper.aves.inventory.click.ClickHolder; +import net.theevilreaper.aves.map.BaseMapBuilder; import net.theevilreaper.bounce.setup.dialog.event.PlayerDialogRequestEvent; import net.theevilreaper.bounce.setup.event.map.PlayerDeletePromptEvent; import net.theevilreaper.bounce.setup.inventory.overview.OverviewType; @@ -32,7 +33,7 @@ public StringSlot(OverviewType overviewType, @Nullable String data) { public ItemStack getItem() { ItemStack overviewItem = this.type.getItem(); - if (data == null) { + if (data == null || data.equals(BaseMapBuilder.DEFAULT_NAME)) { return overviewItem; } return asBuilder(overviewItem).lore( @@ -52,7 +53,7 @@ public ItemStack getItem() { protected void click(Player player, int slot, Click click, ItemStack stack, Consumer result) { result.accept(ClickHolder.cancelClick()); - if (data == null || data.isEmpty()) { + if (data == null || data.isEmpty() || data.equals(BaseMapBuilder.DEFAULT_NAME)) { EventDispatcher.call(new PlayerDialogRequestEvent(player, PlayerDialogRequestEvent.Target.SETUP_NAME)); return; } diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/DialogPayloadListener.java b/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/DialogPayloadListener.java new file mode 100644 index 0000000..63cbb43 --- /dev/null +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/DialogPayloadListener.java @@ -0,0 +1,60 @@ +package net.theevilreaper.bounce.setup.listener.dialog; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.nbt.BinaryTag; +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.minestom.server.entity.Player; +import net.minestom.server.event.player.PlayerCustomClickEvent; +import net.onelitefeather.guira.functional.OptionalSetupDataGetter; +import net.theevilreaper.bounce.setup.dialog.AuthorDialogs; +import net.theevilreaper.bounce.setup.dialog.MapDialogs; +import net.theevilreaper.bounce.setup.dialog.ValueDialogs; +import net.theevilreaper.bounce.setup.dialog.handler.AuthorAmountHandler; +import net.theevilreaper.bounce.setup.dialog.handler.AuthorInputHandler; +import net.theevilreaper.bounce.setup.dialog.handler.DeleteHandler; +import net.theevilreaper.bounce.setup.dialog.handler.DialogHandler; +import net.theevilreaper.bounce.setup.dialog.handler.NameHandler; +import net.theevilreaper.bounce.setup.dialog.handler.ReshufflePercentageHandler; +import net.theevilreaper.bounce.setup.dialog.handler.SaveValidationHandler; +import net.theevilreaper.bounce.setup.dialog.handler.ShuffleIntervalHandler; +import net.theevilreaper.bounce.setup.dialog.handler.ValueHandler; +import net.theevilreaper.bounce.setup.dialog.handler.WeightHandler; +import net.theevilreaper.bounce.setup.util.SetupTags; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.function.Consumer; + +public final class DialogPayloadListener implements Consumer { + + private final Map handlers; + + public DialogPayloadListener(@NotNull OptionalSetupDataGetter setupDataGetter) { + this.handlers = Map.ofEntries( + Map.entry(MapDialogs.NAME_KEY, new NameHandler(setupDataGetter)), + Map.entry(MapDialogs.DELETE_KEY, new DeleteHandler(setupDataGetter)), + Map.entry(MapDialogs.SAVE_VALIDATION_KEY, new SaveValidationHandler(setupDataGetter)), + Map.entry(AuthorDialogs.AUTHOR_AMOUNT_KEY, new AuthorAmountHandler()), + Map.entry(AuthorDialogs.AUTHOR_INPUT_KEY, new AuthorInputHandler(setupDataGetter)), + Map.entry(ValueDialogs.VALUE_KEY, new ValueHandler(setupDataGetter)), + Map.entry(ValueDialogs.WEIGHT_KEY, new WeightHandler(setupDataGetter)), + Map.entry(ValueDialogs.SHUFFLE_INTERVAL_KEY, new ShuffleIntervalHandler(setupDataGetter)), + Map.entry(ValueDialogs.RESHUFFLE_PERCENTAGE_KEY, new ReshufflePercentageHandler(setupDataGetter)) + ); + } + + @Override + public void accept(@NotNull PlayerCustomClickEvent event) { + Player player = event.getPlayer(); + if (!player.hasTag(SetupTags.SETUP_TAG)) return; + + Key key = event.getKey(); + BinaryTag payload = event.getPayload(); + if (payload == null) return; + + DialogHandler handler = this.handlers.get(key); + if (handler == null) return; + + handler.handle(event, (CompoundBinaryTag) payload); + } +} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/PlayerCustomClickEventListener.java b/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/PlayerCustomClickEventListener.java deleted file mode 100644 index e47146c..0000000 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/PlayerCustomClickEventListener.java +++ /dev/null @@ -1,181 +0,0 @@ -package net.theevilreaper.bounce.setup.listener.dialog; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.nbt.BinaryTag; -import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.minestom.server.entity.Player; -import net.minestom.server.event.EventDispatcher; -import net.minestom.server.event.player.PlayerCustomClickEvent; -import net.onelitefeather.guira.functional.OptionalSetupDataGetter; -import net.theevilreaper.bounce.setup.data.BounceData; -import net.theevilreaper.bounce.setup.dialog.*; -import net.theevilreaper.bounce.setup.dialog.type.*; -import net.theevilreaper.bounce.setup.event.map.SetupDiscardEvent; -import net.theevilreaper.bounce.setup.inventory.overview.OverviewType; -import net.theevilreaper.bounce.setup.util.SetupTags; -import org.jetbrains.annotations.NotNull; - -import java.util.function.Consumer; - -public class PlayerCustomClickEventListener implements Consumer { - - private final DialogRegistry dialogRegistry; - private final OptionalSetupDataGetter setupDataGetter; - - public PlayerCustomClickEventListener( - @NotNull DialogRegistry dialogRegistry, - @NotNull OptionalSetupDataGetter setupDataGetter - ) { - this.dialogRegistry = dialogRegistry; - this.setupDataGetter = setupDataGetter; - } - - @Override - public void accept(@NotNull PlayerCustomClickEvent event) { - Player player = event.getPlayer(); - - if (!player.hasTag(SetupTags.SETUP_TAG)) return; - - Key key = event.getKey(); - BinaryTag payload = event.getPayload(); - - if (payload == null) return; - - DialogTemplate dialogTemplate = dialogRegistry.get(key); - - if (dialogTemplate == null) return; - - CompoundBinaryTag dialogData = (CompoundBinaryTag) payload; - - if (dialogTemplate instanceof AuthorRequestDialog) { - int amount = dialogData.getInt("amount", 1); - player.setTag(SetupTags.AUTHOR_AMOUNT_TAG, amount); - dialogRegistry.get(AuthorInputDialog.DIALOG_KEY).open(player); - return; - } - - setupDataGetter.get(player.getUuid()).ifPresent(setupData -> { - BounceData data = (BounceData) setupData; - - switch (dialogTemplate) { - case NameInputDialog ignored -> this.handleNameSet(data, dialogData); - case AuthorInputDialog ignored -> handleAuthorSet(data, dialogData); - case DeleteDialog ignored -> this.handleDataDelete(data, dialogData); - case ValueInputDialog ignored -> this.handleValueUpdate(player, data, dialogData); - case WeightInputDialog ignored -> this.handleWeightUpdate(player, data, dialogData); - case ShuffleIntervalInputDialog ignored -> this.handleShuffleIntervalSet(data, dialogData); - case ReshufflePercentageInputDialog ignored -> this.handleReshufflePercentageSet(data, dialogData); - case SaveValidationDialog ignored -> EventDispatcher.call(new SetupDiscardEvent(data)); - default -> - throw new IllegalStateException("Unexpected dialog type: " + dialogTemplate.getClass().getCanonicalName()); - } - }); - } - - /** - * Handles setting the reshuffle interval based on the dialog data provided. - * @param data the BounceData instance containing the map builder - * @param dialogData the dialog data containing the interval ticks to set - */ - private void handleShuffleIntervalSet(@NotNull BounceData data, @NotNull CompoundBinaryTag dialogData) { - int ticks = (int) dialogData.getFloat("interval_ticks", 100f); - if (ticks < 20) ticks = 20; - data.getMapBuilder().shuffleIntervalTicks(ticks); - data.triggerAreaViewUpdate(); - } - - /** - * Handles setting the reshuffle percentage based on the dialog data provided. - * @param data the BounceData instance containing the map builder - * @param dialogData the dialog data containing the reshuffle percentage to set - */ - private void handleReshufflePercentageSet(@NotNull BounceData data, @NotNull CompoundBinaryTag dialogData) { - float percentage = dialogData.getFloat("reshuffle_percentage", 10.0f); - double reshufflePercentage = Math.max(0.0, Math.min(1.0, percentage / 100.0)); - data.getMapBuilder().reshufflePercentage(reshufflePercentage); - data.triggerAreaViewUpdate(); - } - - /** - * Handles the update of a weight/chance based on the dialog data provided. - * @param player the player who triggered the dialog - * @param data the BounceData instance containing the map builder - * @param dialogData the dialog data containing the weight percentage to update - */ - private void handleWeightUpdate(@NotNull Player player, @NotNull BounceData data, @NotNull CompoundBinaryTag dialogData) { - float percentage = dialogData.getFloat("weight_percentage", 5.0f); - double weight = Math.max(0.0, Math.min(1.0, Math.round((percentage / 100.0) * 1000.0) / 1000.0)); - int valueIndex = player.hasTag(SetupTags.PUSH_SLOT_INDEX) ? player.getTag(SetupTags.PUSH_SLOT_INDEX) : 0; - player.removeTag(SetupTags.PUSH_SLOT_INDEX); - data.getMapBuilder().getPushDataBuilder().getPushValues().get(valueIndex).setWeight(weight); - if (valueIndex == 0) { - data.triggerGroundViewUpdate(); - } else { - data.triggerPushValueUpdate(valueIndex); - } - } - - /** - * Handles the update of a value based on the dialog data provided. - * @param player the player who triggered the dialog - * @param data the BounceData instance containing the map builder - * @param dialogData the dialog data containing the value to update - */ - private void handleValueUpdate(@NotNull Player player, @NotNull BounceData data, @NotNull CompoundBinaryTag dialogData) { - int amount = dialogData.getInt("bounce_amount", 0); - int valueIndex = player.getTag(SetupTags.PUSH_SLOT_INDEX); - player.removeTag(SetupTags.PUSH_SLOT_INDEX); - data.getMapBuilder().getPushDataBuilder().getPushValues().get(valueIndex).setValue(amount); - data.triggerPushValueUpdate(valueIndex); - } - - /** - * Handles the setting of authors based on the dialog data provided. - * - * @param data the BounceData instance containing the map builder - * @param dialogData the dialog data containing the authors to set - */ - private void handleNameSet(@NotNull BounceData data, @NotNull CompoundBinaryTag dialogData) { - String name = dialogData.getString("name"); - if (name.trim().isEmpty()) return; - data.getMapBuilder().name(name); - data.triggerUpdate(); - } - - /** - * Handles the setting of authors based on the dialog data provided. - * - * @param data the BounceData instance containing the map builder - * @param dialogData the dialog data containing the authors to set - */ - private void handleAuthorSet(@NotNull BounceData data, @NotNull CompoundBinaryTag dialogData) { - int amount = dialogData.getInt("amount", 1); - - for (int i = 0; i < amount; i++) { - String author = dialogData.getString("author" + i); - if (author.trim().isEmpty()) continue; - data.getMapBuilder().builder(author); - } - data.triggerUpdate(); - } - - /** - * Handles the deletion of data based on the dialog data provided. - * - * @param data the BounceData instance containing the map builder - * @param dialogData the dialog data containing the type of data to delete - */ - private void handleDataDelete(@NotNull BounceData data, @NotNull CompoundBinaryTag dialogData) { - int type = dialogData.getInt("type"); - OverviewType mappedType = OverviewType.fromOrdinal(type); - - switch (mappedType) { - case NAME -> data.getMapBuilder().name(null); - case BUILDER -> data.getMapBuilder().clearBuilders(); - case GAME_SPAWN -> data.getMapBuilder().gameSpawn(null); - case SPAWN -> data.getMapBuilder().spawn(null); - } - - data.triggerUpdate(); - } -} diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/PlayerDeletePromptListener.java b/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/PlayerDeletePromptListener.java index 69357f8..a4e5f2e 100644 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/PlayerDeletePromptListener.java +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/PlayerDeletePromptListener.java @@ -1,32 +1,15 @@ package net.theevilreaper.bounce.setup.listener.dialog; -import net.theevilreaper.bounce.setup.dialog.DialogRegistry; -import net.theevilreaper.bounce.setup.dialog.DialogTemplate; -import net.theevilreaper.bounce.setup.dialog.type.DeleteDialog; +import net.theevilreaper.bounce.setup.dialog.MapDialogs; import net.theevilreaper.bounce.setup.event.map.PlayerDeletePromptEvent; import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; -public class PlayerDeletePromptListener implements Consumer { - - private final DialogRegistry dialogRegistry; - - public PlayerDeletePromptListener(@NotNull DialogRegistry dialogRegistry) { - this.dialogRegistry = dialogRegistry; - } +public final class PlayerDeletePromptListener implements Consumer { @Override public void accept(@NotNull PlayerDeletePromptEvent event) { - DialogTemplate dialog = dialogRegistry.get(DeleteDialog.DIALOG_KEY); - - if (dialog == null) { - throw new IllegalStateException("Dialog with key " + DeleteDialog.DIALOG_KEY + " not found in registry."); - } - - switch (dialog) { - case DeleteDialog deleteDialog -> deleteDialog.open(event.getPlayer(), event.getType()); - default -> throw new IllegalStateException("Unexpected dialog type: " + dialog.getClass().getCanonicalName()); - } + MapDialogs.openDeleteDialog(event.getPlayer(), event.getType()); } } diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/PlayerDialogRequestListener.java b/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/PlayerDialogRequestListener.java index 97f9767..3e73be8 100644 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/PlayerDialogRequestListener.java +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/PlayerDialogRequestListener.java @@ -1,48 +1,27 @@ package net.theevilreaper.bounce.setup.listener.dialog; import net.minestom.server.entity.Player; -import net.theevilreaper.bounce.setup.dialog.DialogRegistry; -import net.theevilreaper.bounce.setup.dialog.DialogTemplate; +import net.theevilreaper.bounce.setup.dialog.AuthorDialogs; +import net.theevilreaper.bounce.setup.dialog.MapDialogs; +import net.theevilreaper.bounce.setup.dialog.ValueDialogs; import net.theevilreaper.bounce.setup.dialog.event.PlayerDialogRequestEvent; -import net.theevilreaper.bounce.setup.dialog.type.AuthorInputDialog; -import net.theevilreaper.bounce.setup.dialog.type.AuthorRequestDialog; -import net.theevilreaper.bounce.setup.dialog.type.NameInputDialog; -import net.theevilreaper.bounce.setup.dialog.type.ValueInputDialog; import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; -import static net.theevilreaper.bounce.setup.dialog.event.PlayerDialogRequestEvent.*; - public final class PlayerDialogRequestListener implements Consumer { - private final DialogRegistry dialogRegistry; - - public PlayerDialogRequestListener(@NotNull DialogRegistry dialogRegistry) { - this.dialogRegistry = dialogRegistry; - } - @Override public void accept(@NotNull PlayerDialogRequestEvent event) { Player player = event.getPlayer(); - Target target = event.getTarget(); - DialogTemplate dialogTemplate; - switch (target) { - case Target.SETUP_NAME -> dialogTemplate = dialogRegistry.get(NameInputDialog.DIALOG_KEY); - case Target.SETUP_AUTHOR -> dialogTemplate = dialogRegistry.get(AuthorInputDialog.DIALOG_KEY); - case Target.SETUP_REQUEST_AUTHOR -> dialogTemplate = dialogRegistry.get(AuthorRequestDialog.DIALOG_KEY); - case Target.SETUP_BLOCK_BOUNCE -> dialogTemplate = dialogRegistry.get(ValueInputDialog.DIALOG_KEY); - case Target.SETUP_BLOCK_WEIGHT -> dialogTemplate = dialogRegistry.get(net.theevilreaper.bounce.setup.dialog.type.WeightInputDialog.DIALOG_KEY); - case Target.SETUP_SHUFFLE_INTERVAL -> dialogTemplate = dialogRegistry.get(net.theevilreaper.bounce.setup.dialog.type.ShuffleIntervalInputDialog.DIALOG_KEY); - case Target.SETUP_RESHUFFLE_PERCENTAGE -> dialogTemplate = dialogRegistry.get(net.theevilreaper.bounce.setup.dialog.type.ReshufflePercentageInputDialog.DIALOG_KEY); - default -> throw new IllegalArgumentException("Unknown target: " + target); + switch (event.getTarget()) { + case SETUP_NAME -> MapDialogs.openNameDialog(player); + case SETUP_REQUEST_AUTHOR -> AuthorDialogs.openAuthorAmountDialog(player); + case SETUP_BLOCK_BOUNCE -> ValueDialogs.openBounceValue(player); + case SETUP_BLOCK_WEIGHT -> ValueDialogs.openWeight(player); + case SETUP_SHUFFLE_INTERVAL -> ValueDialogs.openShuffleInterval(player); + case SETUP_RESHUFFLE_PERCENTAGE -> ValueDialogs.openReshufflePercentage(player); } - - if (dialogTemplate == null) { - throw new IllegalStateException("Dialog with key " + dialogTemplate.key() + " not found in registry."); - } - - dialogTemplate.open(player); } } diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/SaveValidationPromptListener.java b/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/SaveValidationPromptListener.java index 6332a8d..baf5808 100644 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/SaveValidationPromptListener.java +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/listener/dialog/SaveValidationPromptListener.java @@ -1,32 +1,15 @@ package net.theevilreaper.bounce.setup.listener.dialog; -import net.theevilreaper.bounce.setup.dialog.DialogRegistry; -import net.theevilreaper.bounce.setup.dialog.DialogTemplate; -import net.theevilreaper.bounce.setup.dialog.type.SaveValidationDialog; +import net.theevilreaper.bounce.setup.dialog.MapDialogs; import net.theevilreaper.bounce.setup.event.map.SaveValidationPromptEvent; import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; -public class SaveValidationPromptListener implements Consumer { - - private final DialogRegistry dialogRegistry; - - public SaveValidationPromptListener(@NotNull DialogRegistry dialogRegistry) { - this.dialogRegistry = dialogRegistry; - } +public final class SaveValidationPromptListener implements Consumer { @Override public void accept(@NotNull SaveValidationPromptEvent event) { - DialogTemplate dialog = dialogRegistry.get(SaveValidationDialog.DIALOG_KEY); - - if (dialog == null) { - throw new IllegalStateException("Dialog with key " + SaveValidationDialog.DIALOG_KEY + " not found in registry."); - } - - switch (dialog) { - case SaveValidationDialog saveValidationDialog -> saveValidationDialog.open(event.getPlayer(), event.getMissingFields()); - default -> throw new IllegalStateException("Unexpected dialog type: " + dialog.getClass().getCanonicalName()); - } + MapDialogs.openSaveValidationDialog(event.getPlayer(), event.getMissingFields()); } } diff --git a/setup/src/main/java/net/theevilreaper/bounce/setup/util/SetupTags.java b/setup/src/main/java/net/theevilreaper/bounce/setup/util/SetupTags.java index 3e92b8d..e003693 100644 --- a/setup/src/main/java/net/theevilreaper/bounce/setup/util/SetupTags.java +++ b/setup/src/main/java/net/theevilreaper/bounce/setup/util/SetupTags.java @@ -7,7 +7,6 @@ public final class SetupTags { public static final Tag SETUP_TAG = Tag.Transient("bounce.setup"); - public static final Tag AUTHOR_AMOUNT_TAG = Tag.Transient("bounce.author_amount"); public static final Tag PUSH_SLOT_INDEX = Tag.Integer("push_slot_index"); private SetupTags() { diff --git a/setup/src/test/java/net/theevilreaper/bounce/setup/inventory/area/AreaViewInventoryIntegrationTest.java b/setup/src/test/java/net/theevilreaper/bounce/setup/inventory/area/AreaViewInventoryIntegrationTest.java index bfea540..801f2d0 100644 --- a/setup/src/test/java/net/theevilreaper/bounce/setup/inventory/area/AreaViewInventoryIntegrationTest.java +++ b/setup/src/test/java/net/theevilreaper/bounce/setup/inventory/area/AreaViewInventoryIntegrationTest.java @@ -18,9 +18,9 @@ @ExtendWith(MicrotusExtension.class) class AreaViewInventoryIntegrationTest { - private static final int SHUFFLE_INTERVAL_SLOT = 10; - private static final int POS1_SLOT = 11; - private static final int POS2_SLOT = 13; + private static final int SHUFFLE_INTERVAL_SLOT = 14; + private static final int POS1_SLOT = 10; + private static final int POS2_SLOT = 12; private static final int RESHUFFLE_PERCENTAGE_SLOT = 16; @Test diff --git a/setup/src/test/java/net/theevilreaper/bounce/setup/inventory/slot/StringSlotTest.java b/setup/src/test/java/net/theevilreaper/bounce/setup/inventory/slot/StringSlotTest.java new file mode 100644 index 0000000..0caa181 --- /dev/null +++ b/setup/src/test/java/net/theevilreaper/bounce/setup/inventory/slot/StringSlotTest.java @@ -0,0 +1,39 @@ +package net.theevilreaper.bounce.setup.inventory.slot; + +import net.minestom.server.component.DataComponents; +import net.minestom.server.item.ItemStack; +import net.minestom.testing.Env; +import net.minestom.testing.extension.MicrotusExtension; +import net.theevilreaper.aves.map.BaseMapBuilder; +import net.theevilreaper.bounce.setup.inventory.overview.OverviewType; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@ExtendWith(MicrotusExtension.class) +class StringSlotTest { + + @Test + void testDefaultNameHasNoLore(@NotNull Env env) { + StringSlot slot = new StringSlot(OverviewType.NAME, BaseMapBuilder.DEFAULT_NAME); + ItemStack item = slot.getItem(); + assertEquals(OverviewType.NAME.getItem(), item, "The default map name should not be rendered as a set value"); + } + + @Test + void testUnsetNameHasNoLore(@NotNull Env env) { + StringSlot slot = new StringSlot(OverviewType.NAME, null); + ItemStack item = slot.getItem(); + assertEquals(OverviewType.NAME.getItem(), item); + } + + @Test + void testCustomNameHasLore(@NotNull Env env) { + StringSlot slot = new StringSlot(OverviewType.NAME, "My Map"); + ItemStack item = slot.getItem(); + assertTrue(item.has(DataComponents.LORE)); + } +}