diff --git a/setup/build.gradle.kts b/setup/build.gradle.kts index d68eb43..b3dd5b0 100644 --- a/setup/build.gradle.kts +++ b/setup/build.gradle.kts @@ -18,6 +18,7 @@ dependencies { implementation(libs.xerus) implementation(libs.adventure) implementation(libs.pica) + implementation(libs.guira) testImplementation(libs.minestom) testImplementation(libs.cyano) diff --git a/setup/src/main/java/net/onelitefeather/cygnus/setup/SetupExtension.java b/setup/src/main/java/net/onelitefeather/cygnus/setup/SetupExtension.java index 29989be..c3c7654 100644 --- a/setup/src/main/java/net/onelitefeather/cygnus/setup/SetupExtension.java +++ b/setup/src/main/java/net/onelitefeather/cygnus/setup/SetupExtension.java @@ -27,12 +27,14 @@ import net.onelitefeather.cygnus.setup.listener.SetupItemListener; import net.onelitefeather.cygnus.setup.listener.map.MapSetupSaveListener; import net.onelitefeather.cygnus.setup.util.SetupData; +import net.onelitefeather.guira.SetupDataService; import org.jetbrains.annotations.NotNull; import java.nio.file.Paths; public class SetupExtension implements ListenerHandling { + private final SetupDataService dataService; private final SetupData setupData; private final InstanceContainer instanceContainer; private final PageProvider pageProvider; @@ -41,6 +43,7 @@ public class SetupExtension implements ListenerHandling { public SetupExtension() { this.setupData = new SetupData(); + this.dataService = SetupDataService.create(); this.instanceContainer = MinecraftServer.getInstanceManager().createInstanceContainer(); MinecraftServer.getInstanceManager().registerInstance(instanceContainer); this.pageProvider = new PageProvider(() -> { diff --git a/setup/src/main/java/net/onelitefeather/cygnus/setup/data/GameData.java b/setup/src/main/java/net/onelitefeather/cygnus/setup/data/GameData.java new file mode 100644 index 0000000..190c342 --- /dev/null +++ b/setup/src/main/java/net/onelitefeather/cygnus/setup/data/GameData.java @@ -0,0 +1,135 @@ +package net.onelitefeather.cygnus.setup.data; + +import net.kyori.adventure.bossbar.BossBar; +import net.minestom.server.MinecraftServer; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.Player; +import net.minestom.server.instance.anvil.AnvilLoader; +import net.onelitefeather.cygnus.common.map.GameMap; +import net.onelitefeather.cygnus.common.map.GameMapBuilder; +import net.theevilreaper.aves.file.FileHandler; +import net.theevilreaper.aves.map.BaseMapBuilder; +import net.theevilreaper.aves.map.MapEntry; + +import java.nio.file.Files; +import java.util.Optional; +import java.util.UUID; + +public class GameData extends InstanceSetupData { + + private final FileHandler fileHandler; + //TODO: Implement inventory + private Object inventory; + private GameMapBuilder gameMapBuilder; + private boolean areaMode; + + /** + * Constructs a new GameData instance. + * + * @param uuid the UUID of the player + * @param mapEntry the map entry associated with this game data + * @param fileHandler the file handler for saving and loading game data + */ + public GameData(UUID uuid, MapEntry mapEntry, FileHandler fileHandler) { + super(uuid, mapEntry, BossBar.Color.RED); + this.fileHandler = fileHandler; + Player player = MinecraftServer.getConnectionManager().getOnlinePlayerByUuid(uuid); + this.loadData(); + if (player == null) { + throw new IllegalArgumentException("Player with UUID " + uuid + " is not online."); + } + } + + /** + * Swaps between area mode and normal mode. + */ + public void swapAreaMode() { + this.areaMode = !this.areaMode; + } + + /** + * {@inheritDoc} + */ + @Override + public void openInventory(Player player) { + //player.openInventory(this.inventory.getInventory()); + } + + /** + * {@inheritDoc} + */ + @Override + public void triggerUpdate() { + // this.inventory.invalidateDataLayout(); + } + + /** + * {@inheritDoc} + */ + @Override + public void save() { + if (!Files.exists(mapEntry.getMapFile())) { + this.mapEntry.createFile(); + } + //this.fileHandler.save(mapEntry.getMapFile(), BaseMap.class); + } + + @Override + public void teleport(Player player) { + super.teleport(player); + Pos spawnPoint = this.gameMapBuilder.getSpawn() == null + ? SPAWN_POINT + : this.gameMapBuilder.getSpawn(); + player.setInstance(this.instance, spawnPoint); + } + + /** + * {@inheritDoc} + */ + @Override + public void reset() { + super.reset(); + // this.inventory.unregister(); + } + + /** + * {@inheritDoc} + */ + @Override + public void loadData() { + if (!this.mapEntry.hasMapFile()) { + this.gameMapBuilder = new GameMapBuilder(); + } else { + Optional mapData = fileHandler.load(mapEntry.getMapFile(), GameMap.class); + mapData.ifPresentOrElse(gameMap -> + this.gameMapBuilder = new GameMapBuilder(gameMap), + () -> this.gameMapBuilder = new GameMapBuilder() + ); + } + // this.inventory = new LobbyViewInventory(this.gameMapBuilder); + this.instance = MinecraftServer.getInstanceManager().createInstanceContainer(); + AnvilLoader anvilLoader = new AnvilLoader(this.mapEntry.getDirectoryRoot()); + this.instance.setChunkLoader(anvilLoader); + this.updateTitle(); + MinecraftServer.getInstanceManager().registerInstance(this.instance); + } + + /** + * Returns an indication if the area mode is active or not. + * + * @return true if area mode is active, false otherwise + */ + public boolean hasAreaMode() { + return areaMode; + } + + /** + * Returns the GameMapBuilder instance used for building the game map. + * + * @return the builder instance + */ + @Override + public BaseMapBuilder getMapBuilder() { + return this.gameMapBuilder; + } +} diff --git a/setup/src/main/java/net/onelitefeather/cygnus/setup/data/InstanceSetupData.java b/setup/src/main/java/net/onelitefeather/cygnus/setup/data/InstanceSetupData.java new file mode 100644 index 0000000..a288d18 --- /dev/null +++ b/setup/src/main/java/net/onelitefeather/cygnus/setup/data/InstanceSetupData.java @@ -0,0 +1,118 @@ +package net.onelitefeather.cygnus.setup.data; + +import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.minestom.server.MinecraftServer; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.Player; +import net.minestom.server.instance.InstanceContainer; +import net.onelitefeather.guira.data.SetupData; +import net.theevilreaper.aves.map.BaseMapBuilder; +import net.theevilreaper.aves.map.MapEntry; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +/** + * Base implementation for setup data working with a temporary map instance. + * + *

Provides shared functionality for managing setup state, boss bar updates, + * instance lifecycle handling and map-related access. Subclasses implement + * setup-specific interaction and update logic.

+ * + * @author theEvilReaper + * @version 1.0.0 + * @since 2.1.0 + */ +public abstract class InstanceSetupData implements SetupData { + + protected static final Pos SPAWN_POINT = new Pos(0, 100, 0); + + protected UUID uuid; + protected MapEntry mapEntry; + protected @Nullable InstanceContainer instance; + protected BossBar bossBar; + protected @Nullable Component title; + + /** + * Creates a new setup data container. + * + * @param uuid unique identifier of this setup session + * @param mapEntry map entry associated with the setup + * @param color boss bar color used for setup feedback + */ + protected InstanceSetupData(UUID uuid, MapEntry mapEntry, BossBar.Color color) { + this.uuid = uuid; + this.mapEntry = mapEntry; + this.bossBar = BossBar.bossBar(Component.empty(), 1, color, BossBar.Overlay.PROGRESS); + } + + /** + * Updates the boss bar title. + * + *

If no title is set, a fallback title is used.

+ */ + public void updateTitle() { + if (this.title == null) { + this.title = Component.text("Please set a title", NamedTextColor.RED); + } + this.bossBar.name(title); + } + + /** + * Displays setup-related information to the given player. + * + * @param player target player + */ + public void teleport(Player player) { + player.showBossBar(this.bossBar); + } + + /** + * Opens the setup inventory for the given player. + * + * @param player target player + */ + public abstract void openInventory(Player player); + + /** + * Triggers an update of the setup state and related visual feedback. + */ + public abstract void triggerUpdate(); + + /** + * Checks whether a map file is available for this setup. + * + * @return true if a map file exists, otherwise false + */ + public boolean hasMapFile() { + return this.mapEntry.hasMapFile(); + } + + /** + * Resets this setup and unregisters its instance if present. + */ + @Override + public void reset() { + if (instance == null) return; + MinecraftServer.getInstanceManager().unregisterInstance(instance); + } + + /** + * Returns the unique identifier of this setup. + * + * @return setup id + */ + @Override + public UUID getId() { + return this.uuid; + } + + /** + * Returns the map builder used by this setup. + * + * @return associated map builder + */ + public abstract BaseMapBuilder getMapBuilder(); +} \ No newline at end of file diff --git a/setup/src/main/java/net/onelitefeather/cygnus/setup/data/LobbyData.java b/setup/src/main/java/net/onelitefeather/cygnus/setup/data/LobbyData.java new file mode 100644 index 0000000..1afd89c --- /dev/null +++ b/setup/src/main/java/net/onelitefeather/cygnus/setup/data/LobbyData.java @@ -0,0 +1,93 @@ +package net.onelitefeather.cygnus.setup.data; + +import net.kyori.adventure.bossbar.BossBar; +import net.minestom.server.MinecraftServer; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.Player; +import net.minestom.server.instance.anvil.AnvilLoader; +import net.theevilreaper.aves.file.FileHandler; +import net.theevilreaper.aves.map.BaseMap; +import net.theevilreaper.aves.map.BaseMapBuilder; +import net.theevilreaper.aves.map.MapEntry; + +import java.nio.file.Files; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; + +public final class LobbyData extends InstanceSetupData { + + private final FileHandler fileHandler; + private Objects viewInventory; + private BaseMapBuilder mapBuilder; + + public LobbyData(UUID uuid, MapEntry mapEntry, FileHandler fileHandler) { + super(uuid, mapEntry, BossBar.Color.GREEN); + this.fileHandler = fileHandler; + this.loadData(); + Player player = MinecraftServer.getConnectionManager().getOnlinePlayerByUuid(uuid); + + if (player == null) { + throw new IllegalArgumentException("Player with UUID " + uuid + " is not online."); + } + } + + @Override + public void openInventory(Player player) { + //player.openInventory(this.viewInventory.getInventory()); + } + + @Override + public void triggerUpdate() { + // this.viewInventory.invalidateDataLayout(); + } + + @Override + public void save() { + if (!Files.exists(mapEntry.getMapFile())) { + this.mapEntry.createFile(); + } + this.fileHandler.save(mapEntry.getMapFile(), BaseMap.class); + } + + @Override + public void teleport(Player player) { + super.teleport(player); + Pos spawnPoint = this.mapBuilder.getSpawn() == null + ? SPAWN_POINT + : this.mapBuilder.getSpawn(); + player.setInstance(this.instance, spawnPoint); + } + + @Override + public void reset() { + super.reset(); + //this.viewInventory.unregister(); + } + + @Override + public void loadData() { + if (this.mapEntry == null) { + this.mapBuilder = BaseMap.builder(); + } else { + Optional mapData = fileHandler.load(mapEntry.getMapFile(), BaseMap.class); + + mapData.ifPresentOrElse(baseMap -> { + this.mapBuilder = BaseMap.builder(baseMap); + }, () -> this.mapBuilder = BaseMap.builder()); + } + + //this.viewInventory = new LobbyViewInventory(this.mapBuilder); + + this.instance = MinecraftServer.getInstanceManager().createInstanceContainer(); + AnvilLoader anvilLoader = new AnvilLoader(this.mapEntry.getDirectoryRoot()); + this.instance.setChunkLoader(anvilLoader); + this.updateTitle(); + MinecraftServer.getInstanceManager().registerInstance(this.instance); + } + + @Override + public BaseMapBuilder getMapBuilder() { + return mapBuilder; + } +} diff --git a/setup/src/main/java/net/onelitefeather/cygnus/setup/data/package-info.java b/setup/src/main/java/net/onelitefeather/cygnus/setup/data/package-info.java new file mode 100644 index 0000000..1d2028c --- /dev/null +++ b/setup/src/main/java/net/onelitefeather/cygnus/setup/data/package-info.java @@ -0,0 +1,4 @@ +@NotNullByDefault +package net.onelitefeather.cygnus.setup.data; + +import org.jetbrains.annotations.NotNullByDefault; \ No newline at end of file diff --git a/setup/src/main/java/net/onelitefeather/cygnus/setup/util/SetupData.java b/setup/src/main/java/net/onelitefeather/cygnus/setup/util/SetupData.java index ff0d69f..6f0bf4f 100644 --- a/setup/src/main/java/net/onelitefeather/cygnus/setup/util/SetupData.java +++ b/setup/src/main/java/net/onelitefeather/cygnus/setup/util/SetupData.java @@ -27,6 +27,7 @@ * @version 1.0.0 * @since 1.0.0 */ +@Deprecated(forRemoval = true) public final class SetupData { private static final Pos SPAWN_POINT = new Pos(0, 100, 0);