diff --git a/eternalcore-api/src/main/java/com/eternalcode/core/feature/warp/WarpService.java b/eternalcore-api/src/main/java/com/eternalcode/core/feature/warp/WarpService.java index 23a72fd3e..b2ab4d65d 100644 --- a/eternalcore-api/src/main/java/com/eternalcode/core/feature/warp/WarpService.java +++ b/eternalcore-api/src/main/java/com/eternalcode/core/feature/warp/WarpService.java @@ -5,6 +5,7 @@ import java.util.Collection; import java.util.Optional; +import java.util.concurrent.CompletableFuture; public interface WarpService { @@ -23,4 +24,12 @@ public interface WarpService { Optional findWarp(String warp); Collection getWarps(); + + /** + * Migrates warps from the old configuration to the new one. + * This includes both warp locations and GUI settings. + * + * @return A CompletableFuture that completes with true if migration was successful, false otherwise + */ + CompletableFuture migrateWarps(); } diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpInventory.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpInventory.java index c5c067d08..fe70f15c6 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpInventory.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpInventory.java @@ -2,30 +2,22 @@ import com.eternalcode.commons.adventure.AdventureUtil; import com.eternalcode.commons.scheduler.Scheduler; -import com.eternalcode.core.configuration.ConfigurationManager; import com.eternalcode.core.configuration.contextual.ConfigItem; -import com.eternalcode.core.configuration.implementation.PluginConfiguration; import com.eternalcode.core.feature.language.Language; import com.eternalcode.core.feature.language.LanguageService; -import com.eternalcode.core.feature.warp.messages.WarpMessages; -import com.eternalcode.core.feature.warp.messages.WarpMessages.WarpInventorySection; +import com.eternalcode.core.feature.warp.repository.WarpConfig; +import com.eternalcode.core.feature.warp.repository.WarpConfig.WarpGuiSettings; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Service; -import com.eternalcode.core.translation.AbstractTranslation; -import com.eternalcode.core.translation.Translation; -import com.eternalcode.core.translation.TranslationManager; + import static com.eternalcode.core.util.FutureHandler.whenSuccess; import dev.triumphteam.gui.builder.item.BaseItemBuilder; import dev.triumphteam.gui.builder.item.ItemBuilder; import dev.triumphteam.gui.guis.Gui; import dev.triumphteam.gui.guis.GuiItem; -import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.Optional; -import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; -import org.bukkit.Material; import org.bukkit.Server; import org.bukkit.entity.Player; @@ -43,37 +35,31 @@ public class WarpInventory { private static final int BORDER_ROW_COUNT = 2; private static final int UGLY_BORDER_ROW_COUNT = 1; - private final TranslationManager translationManager; private final LanguageService languageService; private final WarpService warpService; private final Server server; private final MiniMessage miniMessage; private final WarpTeleportService warpTeleportService; - private final ConfigurationManager configurationManager; - private final PluginConfiguration config; private final Scheduler scheduler; + private final WarpConfig warpConfig; @Inject WarpInventory( - TranslationManager translationManager, LanguageService languageService, WarpService warpService, Server server, MiniMessage miniMessage, WarpTeleportService warpTeleportService, - ConfigurationManager configurationManager, - PluginConfiguration config, - Scheduler scheduler + Scheduler scheduler, + WarpConfig warpConfig ) { - this.translationManager = translationManager; this.languageService = languageService; this.warpService = warpService; this.server = server; this.miniMessage = miniMessage; this.warpTeleportService = warpTeleportService; - this.configurationManager = configurationManager; - this.config = config; this.scheduler = scheduler; + this.warpConfig = warpConfig; } public void openInventory(Player player) { @@ -83,48 +69,50 @@ public void openInventory(Player player) { } private Gui createInventory(Player player, Language language) { - Translation translation = this.translationManager.getMessages(language); - WarpMessages.WarpInventorySection warpSection = translation.warp().warpInventory(); + WarpConfig.WarpGuiSettings guiSettings = this.warpConfig.guiSettings; - int rowsCount; - int size = warpSection.items().size(); - - if (!warpSection.border().enabled()) { - rowsCount = (size + 1) / GUI_ROW_SIZE_WITHOUT_BORDER + 1; - } - else { - switch (warpSection.border().fillType()) { - case BORDER, ALL -> rowsCount = (size - 1) / GUI_ROW_SIZE_WITH_BORDER + 1 + BORDER_ROW_COUNT; - case TOP, BOTTOM -> rowsCount = (size - 1) / GUI_ROW_SIZE_WITHOUT_BORDER + 1 + UGLY_BORDER_ROW_COUNT; - default -> throw new IllegalStateException("Unexpected value: " + warpSection.border().fillType()); - } - } + int rowsCount = createrBorder(guiSettings); Gui gui = Gui.gui() - .title(this.miniMessage.deserialize(warpSection.title())) + .title(this.miniMessage.deserialize(guiSettings.title)) .rows(rowsCount) .disableAllInteractions() .create(); - this.createWarpItems(player, warpSection, gui); - this.createBorder(warpSection, gui); - this.createDecorations(warpSection, gui); + this.createWarpItems(player, gui); + this.createBorder(guiSettings, gui); + this.createDecorations(guiSettings, gui); return gui; } - private void createBorder(WarpInventorySection warpSection, Gui gui) { - if (warpSection.border().enabled()) { - WarpInventorySection.BorderSection borderSection = warpSection.border(); + private int createrBorder(WarpGuiSettings guiSettings) { + int rowsCount; + int size = this.warpService.getWarps().size(); - ItemBuilder borderItem = ItemBuilder.from(borderSection.material()); + if (!guiSettings.borderEnabled) { + rowsCount = (size + 1) / GUI_ROW_SIZE_WITHOUT_BORDER + 1; + } + else { + switch (guiSettings.borderFillType) { + case BORDER, ALL -> rowsCount = (size - 1) / GUI_ROW_SIZE_WITH_BORDER + 1 + BORDER_ROW_COUNT; + case TOP, BOTTOM -> rowsCount = (size - 1) / GUI_ROW_SIZE_WITHOUT_BORDER + 1 + UGLY_BORDER_ROW_COUNT; + default -> throw new IllegalStateException("Unexpected value: " + guiSettings.borderFillType); + } + } + return rowsCount; + } - if (!borderSection.name().isBlank()) { - borderItem.name(AdventureUtil.resetItalic(this.miniMessage.deserialize(borderSection.name()))); + private void createBorder(WarpConfig.WarpGuiSettings guiSettings, Gui gui) { + if (guiSettings.borderEnabled) { + ItemBuilder borderItem = ItemBuilder.from(guiSettings.borderMaterial); + + if (!guiSettings.borderName.isBlank()) { + borderItem.name(AdventureUtil.resetItalic(this.miniMessage.deserialize(guiSettings.borderName))); } - if (!borderSection.lore().isEmpty()) { - borderItem.lore(borderSection.lore() + if (!guiSettings.borderLore.isEmpty()) { + borderItem.lore(guiSettings.borderLore .stream() .map(entry -> AdventureUtil.resetItalic(this.miniMessage.deserialize(entry))) .toList()); @@ -132,18 +120,18 @@ private void createBorder(WarpInventorySection warpSection, Gui gui) { GuiItem guiItem = new GuiItem(borderItem.build()); - switch (borderSection.fillType()) { + switch (guiSettings.borderFillType) { case BORDER -> gui.getFiller().fillBorder(guiItem); case ALL -> gui.getFiller().fill(guiItem); case TOP -> gui.getFiller().fillTop(guiItem); case BOTTOM -> gui.getFiller().fillBottom(guiItem); - default -> throw new IllegalStateException("Unexpected value: " + borderSection.fillType()); + default -> throw new IllegalStateException("Unexpected value: " + guiSettings.borderFillType); } } } - private void createDecorations(WarpInventorySection warpSection, Gui gui) { - for (ConfigItem item : warpSection.decorationItems().items()) { + private void createDecorations(WarpConfig.WarpGuiSettings guiSettings, Gui gui) { + for (ConfigItem item : guiSettings.decorationItems) { BaseItemBuilder baseItemBuilder = this.createItem(item); GuiItem guiItem = baseItemBuilder.asGuiItem(); @@ -165,25 +153,33 @@ private void createDecorations(WarpInventorySection warpSection, Gui gui) { } } - private void createWarpItems(Player player, WarpInventorySection warpSection, Gui gui) { - warpSection.items().values().forEach(item -> { - Optional warpOptional = this.warpService.findWarp(item.warpName()); - - if (warpOptional.isEmpty()) { - return; - } - - Warp warp = warpOptional.get(); - ConfigItem warpItem = item.warpItem(); - - if (!warp.hasPermissions(player)) { - return; - } - - BaseItemBuilder baseItemBuilder = this.createItem(warpItem); - GuiItem guiItem = baseItemBuilder.asGuiItem(); + private void createWarpItems(Player player, Gui gui) { + List warps = this.warpService.getWarps().stream() + .filter(warp -> warp.hasPermissions(player)) + .sorted(Comparator.comparing(Warp::getName)) + .toList(); - guiItem.setAction(event -> { + int slot = getStartingSlot(); + + for (Warp warp : warps) { + WarpConfig.WarpConfigEntry warpEntry = this.warpConfig.warps.get(warp.getName()); + if (warpEntry == null) continue; + + WarpConfig.WarpGuiItem guiItem = warpEntry.guiItem; + + ConfigItem configItem = ConfigItem.builder() + .withName(guiItem.name.replace("{WARP_NAME}", warp.getName())) + .withLore(guiItem.lore) + .withMaterial(guiItem.material) + .withTexture(guiItem.texture) + .withSlot(slot++) + .withGlow(guiItem.glow) + .build(); + + BaseItemBuilder baseItemBuilder = this.createItem(configItem); + GuiItem item = baseItemBuilder.asGuiItem(); + + item.setAction(event -> { if (!warp.hasPermissions(player)) { return; } @@ -192,104 +188,47 @@ private void createWarpItems(Player player, WarpInventorySection warpSection, Gu this.warpTeleportService.teleport(player, warp); }); - gui.setItem(warpItem.slot(), guiItem); - }); + gui.setItem(configItem.slot(), item); + } } - private BaseItemBuilder createItem(ConfigItem item) { - Component name = AdventureUtil.resetItalic(this.miniMessage.deserialize(item.name())); - - List lore = item.lore() - .stream() - .map(entry -> AdventureUtil.resetItalic(this.miniMessage.deserialize(entry))) - .toList(); - - if (item.material() == Material.PLAYER_HEAD && !item.texture().isEmpty()) { - return ItemBuilder.skull() - .name(name) - .lore(lore) - .texture(item.texture()) - .glow(item.glow()); + private int getStartingSlot() { + WarpConfig.WarpGuiSettings guiSettings = this.warpConfig.guiSettings; + + if (!guiSettings.borderEnabled) { + return GUI_ITEM_SLOT_WITHOUT_BORDER; } - - return ItemBuilder.from(item.material()) - .name(name) - .lore(lore) - .glow(item.glow()); + + return switch (guiSettings.borderFillType) { + case TOP -> GUI_ITEM_SLOT_WITH_TOP_BORDER; + case ALL -> GUI_ITEM_SLOT_WITH_ALL_BORDER; + case BORDER, BOTTOM -> GUI_ITEM_SLOT_WITH_BORDER; + }; } - public void addWarp(Warp warp) { - if (!this.warpService.exists(warp.getName())) { - return; - } + private BaseItemBuilder createItem(ConfigItem item) { + BaseItemBuilder baseItemBuilder = ItemBuilder.from(item.material()); - for (Language language : this.translationManager.getAvailableLanguages()) { - AbstractTranslation translation = (AbstractTranslation) this.translationManager.getMessages(language); - WarpMessages.WarpInventorySection warpSection = translation.warp().warpInventory(); - int slot = getSlot(warpSection); - - warpSection.addItem( - warp.getName(), - WarpInventoryItem.builder() - .withWarpName(warp.getName()) - .withWarpItem(ConfigItem.builder() - .withName(this.config.warp.itemNamePrefix + warp.getName()) - .withLore(Collections.singletonList(this.config.warp.itemLore)) - .withMaterial(this.config.warp.itemMaterial) - .withTexture(this.config.warp.itemTexture) - .withSlot(slot) - .withGlow(true) - .build()) - .build()); - - this.configurationManager.save(translation); + if (item.texture() != null && !item.texture().isBlank()) { + baseItemBuilder = ItemBuilder.skull() + .texture(item.texture()); } - } - private int getSlot(WarpMessages.WarpInventorySection warpSection) { - int size = warpSection.items().size(); - if (!warpSection.border().enabled()) { - return GUI_ITEM_SLOT_WITHOUT_BORDER + size; + if (item.name() != null && !item.name().isBlank()) { + baseItemBuilder.name(AdventureUtil.resetItalic(this.miniMessage.deserialize(item.name()))); } - return switch (warpSection.border().fillType()) { - case BORDER -> GUI_ITEM_SLOT_WITH_BORDER + size + ((size / WarpInventory.GUI_ROW_SIZE_WITH_BORDER) * 2); - case ALL -> GUI_ITEM_SLOT_WITH_ALL_BORDER + size + ((size / WarpInventory.GUI_ROW_SIZE_WITH_BORDER) * 2); - case TOP -> GUI_ITEM_SLOT_WITH_TOP_BORDER + size; - case BOTTOM -> size; - }; - } - - public void removeWarp(String warpName) { - if (!this.config.warp.autoAddNewWarps) { - return; + if (item.lore() != null && !item.lore().isEmpty()) { + baseItemBuilder.lore(item.lore() + .stream() + .map(entry -> AdventureUtil.resetItalic(this.miniMessage.deserialize(entry))) + .toList()); } - for (Language language : this.translationManager.getAvailableLanguages()) { - AbstractTranslation translation = (AbstractTranslation) this.translationManager.getMessages(language); - WarpMessages.WarpInventorySection warpSection = translation.warp().warpInventory(); - WarpInventoryItem removed = warpSection.removeItem(warpName); - - if (removed != null) { - this.shiftWarpItems(removed, warpSection); - } - - this.configurationManager.save(translation); + if (item.glow()) { + baseItemBuilder.glow(); } - } - private void shiftWarpItems(WarpInventoryItem removed, WarpMessages.WarpInventorySection warpSection) { - int removedSlot = removed.warpItem.slot; - List itemsToShift = warpSection.items().values().stream() - .filter(item -> item.warpItem.slot > removedSlot) - .sorted(Comparator.comparingInt(item -> item.warpItem.slot)) - .toList(); - - int currentShift = removedSlot; - for (WarpInventoryItem item : itemsToShift) { - int nextShift = item.warpItem.slot; - item.warpItem.slot = currentShift; - currentShift = nextShift; - } + return baseItemBuilder; } } diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpServiceImpl.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpServiceImpl.java index b76ed7549..074d883ab 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpServiceImpl.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpServiceImpl.java @@ -2,7 +2,9 @@ import com.eternalcode.annotations.scan.feature.FeatureDocs; import com.eternalcode.commons.bukkit.position.PositionAdapter; +import com.eternalcode.core.feature.warp.repository.WarpConfig; import com.eternalcode.core.feature.warp.repository.WarpRepository; +import com.eternalcode.core.feature.warp.repository.WarpRepositoryImpl; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Service; import org.bukkit.Location; @@ -13,8 +15,10 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; +import org.jetbrains.annotations.ApiStatus.ScheduledForRemoval; @FeatureDocs( name = "Warp System", @@ -25,10 +29,12 @@ class WarpServiceImpl implements WarpService { private final Map warps = new ConcurrentHashMap<>(); private final WarpRepository warpRepository; + private final WarpConfig warpConfig; @Inject - private WarpServiceImpl(WarpRepository warpRepository) { + private WarpServiceImpl(WarpRepository warpRepository, WarpConfig warpConfig) { this.warpRepository = warpRepository; + this.warpConfig = warpConfig; warpRepository.getWarps().thenAcceptAsync(warps -> { for (Warp warp : warps) { @@ -37,6 +43,26 @@ private WarpServiceImpl(WarpRepository warpRepository) { }); } + @Deprecated(since = "1.6.1", forRemoval = true) + public CompletableFuture migrateWarps() { + if (warpRepository instanceof WarpRepositoryImpl) { + return ((WarpRepositoryImpl) warpRepository).migrateWarps() + .thenApply(success -> { + if (success) { + // Reload warps after migration + warpRepository.getWarps().thenAcceptAsync(warps -> { + this.warps.clear(); + for (Warp warp : warps) { + this.warps.put(warp.getName(), warp); + } + }); + } + return success; + }); + } + return CompletableFuture.completedFuture(false); + } + @Override public Warp createWarp(String name, Location location) { Warp warp = new WarpImpl(name, PositionAdapter.convert(location), new ArrayList<>()); diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/command/DelWarpCommand.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/command/DelWarpCommand.java index 0fb497a29..7c01e8ef9 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/command/DelWarpCommand.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/command/DelWarpCommand.java @@ -47,9 +47,6 @@ private void removeWarp(Player player, String name) { return; } - this.warpService.removeWarp(name); - this.warpInventory.removeWarp(name); - this.noticeService.create() .player(player.getUniqueId()) .notice(translation -> translation.warp().remove()) diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/command/SetWarpCommand.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/command/SetWarpCommand.java index 92de010e5..c3e391041 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/command/SetWarpCommand.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/command/SetWarpCommand.java @@ -54,31 +54,12 @@ private void createWarp(Player player, String warp, UUID uniqueId) { return; } - Warp createdWarp = this.warpService.createWarp(warp, player.getLocation()); + this.warpService.createWarp(warp, player.getLocation()); this.noticeService.create() .player(uniqueId) .notice(translation -> translation.warp().create()) .placeholder("{WARP}", warp) .send(); - - if (this.config.warp.autoAddNewWarps) { - if (this.warpService.getWarps().size() <= MAX_WARPS_IN_GUI) { - this.warpInventory.addWarp(createdWarp); - - this.noticeService.create() - .player(uniqueId) - .notice(translation -> translation.warp().itemAdded()) - .send(); - - return; - } - - this.noticeService.create() - .player(uniqueId) - .notice(translation -> translation.warp().itemLimit()) - .placeholder("{LIMIT}", String.valueOf(MAX_WARPS_IN_GUI)) - .send(); - } } } diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/messages/ENWarpMessages.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/messages/ENWarpMessages.java index 0848c69d4..e70ded786 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/messages/ENWarpMessages.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/messages/ENWarpMessages.java @@ -42,16 +42,21 @@ public class ENWarpMessages implements WarpMessages { @Description({" ", "# {WARPS} - List of warps (separated by commas)"}) public Notice available = Notice.chat("Available warps: {WARPS}"); - @Description({" ", "# Settings for warp inventory"}) + @Description({" ", + "# DEPRECATED: These settings have been moved to warps.yml", + "# Settings for warp inventory"}) + @Deprecated public ENWarpInventory warpInventory = new ENWarpInventory(); @Getter @Accessors(fluent = true) @Contextual + @Deprecated public static class ENWarpInventory implements WarpInventorySection { public String title = "» Available warps:"; @Description({" ", + "# DEPRECATED: These settings have been moved to warps.yml", "# Warps located inside GUI inventory can be customized here. More warps will be added on creation with /setwarp command. "}) public Map items = new HashMap<>(); @@ -65,9 +70,11 @@ public void setItems(Map items) { @Getter @Contextual + @Deprecated public static class ENBorderSection implements BorderSection { @Description({" ", + "# DEPRECATED: These settings have been moved to warps.yml", "# Changes of border section may affect the appearance of the GUI inventory, after changes adjust slots of existing items."}) public boolean enabled = true; @@ -82,6 +89,7 @@ public static class ENBorderSection implements BorderSection { @Getter @Contextual + @Deprecated public static class ENDecorationItemsSection implements DecorationItemsSection { public List items = List.of(); } diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/messages/PLWarpMessages.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/messages/PLWarpMessages.java index 458f25eda..612d176a0 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/messages/PLWarpMessages.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/messages/PLWarpMessages.java @@ -40,17 +40,22 @@ public class PLWarpMessages implements WarpMessages { @Description({" ", "# {WARPS} - Lista dostępnych warpów"}) public Notice available = Notice.chat("Dostepne warpy: {WARPS}!"); - @Description({" ", "# Ustawienia gui listy dostępnych warpów"}) + @Description({" ", + "# PRZESTARZAŁE: Te ustawienia zostały przeniesione do pliku warps.yml", + "# Ustawienia gui listy dostępnych warpów"}) + @Deprecated public PLWarpInventory warpInventory = new PLWarpInventory(); @Getter @Accessors(fluent = true) @Contextual + @Deprecated public static class PLWarpInventory implements WarpInventorySection { public String title = "» Lista dostępnych warpów"; @Description({ " ", + "# PRZESTARZAŁE: Te ustawienia zostały przeniesione do pliku warps.yml", "# Poniższa lista określa przedmioty w GUI, które są wyświetlane w liście dostępnych warpów.", "# Możesz edytować przedmioty, a dodawanie kolejnych warpów następuje automatycznie za pomocą komendy /setwarp", }) @@ -66,8 +71,10 @@ public void setItems(Map items) { @Getter @Contextual + @Deprecated public static class PLBorderSection implements BorderSection { @Description({" ", + "# PRZESTARZAŁE: Te ustawienia zostały przeniesione do pliku warps.yml", "# Zmiany w tej sekcji mogą wpłynąć na wygląd GUI, zwróć uwagę na zmiany slotów przedmiotów w GUI."}) public boolean enabled = true; @@ -82,6 +89,7 @@ public static class PLBorderSection implements BorderSection { @Getter @Contextual + @Deprecated public static class PLDecorationItemsSection implements DecorationItemsSection { public List items = List.of(); } diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/messages/WarpMessages.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/messages/WarpMessages.java index 6c5f9f7f5..a652363dc 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/messages/WarpMessages.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/messages/WarpMessages.java @@ -26,8 +26,17 @@ public interface WarpMessages { Notice missingWarpArgument(); Notice missingPermissionArgument(); + /** + * @deprecated This method is deprecated. Warp inventory settings have been moved to warps.yml. + * @return The warp inventory section + */ + @Deprecated WarpInventorySection warpInventory(); + /** + * @deprecated This interface is deprecated. Warp inventory settings have been moved to warps.yml. + */ + @Deprecated interface WarpInventorySection { String title(); @@ -52,6 +61,10 @@ default WarpInventoryItem removeItem(String name) { BorderSection border(); DecorationItemsSection decorationItems(); + /** + * @deprecated This interface is deprecated. Warp inventory settings have been moved to warps.yml. + */ + @Deprecated interface BorderSection { boolean enabled(); @@ -68,6 +81,10 @@ enum FillType { } } + /** + * @deprecated This interface is deprecated. Warp inventory settings have been moved to warps.yml. + */ + @Deprecated interface DecorationItemsSection { List items(); } diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/repository/WarpConfig.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/repository/WarpConfig.java index 28ca28b80..f083cbdb7 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/repository/WarpConfig.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/repository/WarpConfig.java @@ -2,32 +2,56 @@ import com.eternalcode.commons.bukkit.position.Position; import com.eternalcode.core.configuration.ReloadableConfig; +import com.eternalcode.core.configuration.contextual.ConfigItem; import com.eternalcode.core.injector.annotations.component.ConfigurationFile; import java.io.File; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import lombok.Getter; +import lombok.experimental.Accessors; import net.dzikoysk.cdn.entity.Contextual; import net.dzikoysk.cdn.entity.Description; -import net.dzikoysk.cdn.entity.Exclude; import net.dzikoysk.cdn.source.Resource; import net.dzikoysk.cdn.source.Source; +import org.bukkit.Material; @ConfigurationFile -class WarpConfig implements ReloadableConfig { +@Getter +@Accessors(fluent = true) +public class WarpConfig implements ReloadableConfig { - @Description({"# Warps data", "# These are warp locations, for your own safety, please don't touch it."}) + @Description({ + "# Warp System Configuration", + "# This file contains all warp locations and their GUI settings.", + "# You can easily manage your warps here." + }) public Map warps = new HashMap<>(); + @Description({ + " ", + "# GUI Settings", + "# Configure the appearance of the warp inventory" + }) + public WarpGuiSettings guiSettings = new WarpGuiSettings(); + @Override public Resource resource(File folder) { - return Source.of(folder, "data" + File.separator + "warps.yml"); + return Source.of(folder, "warps.yml"); } @Contextual - static class WarpConfigEntry { + public static class WarpConfigEntry { + @Description("# The location of the warp") public Position position; - public List permissions; + + @Description("# Permissions required to use this warp (leave empty for no permissions)") + public List permissions = new ArrayList<>(); + + @Description("# GUI item settings for this warp") + public WarpGuiItem guiItem = new WarpGuiItem(); public WarpConfigEntry() { } @@ -37,4 +61,53 @@ public WarpConfigEntry(Position position, List permissions) { this.permissions = permissions; } } + + @Contextual + public static class WarpGuiItem { + @Description("# The name of the warp item in the GUI") + public String name = "&6Warp: &f{WARP_NAME}"; + + @Description("# The lore of the warp item in the GUI") + public List lore = Collections.singletonList("&7Click to teleport to warp"); + + @Description("# The material of the warp item in the GUI") + public Material material = Material.PLAYER_HEAD; + + @Description("# The texture of the warp item in the GUI (for player heads)") + public String texture = "ewogICJ0aW1lc3RhbXAiIDogMTY2NDAzNTM1MjUyNCwKICAicHJvZmlsZUlkIiA6ICJjYjIzZWZhOWY1N2U0ZTQyOGE0MDU2OTM4NDlhODAxZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJWMUdHTyIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS82MThhZjFiODNhZGZmNzM1MDA3ZmVkMjMwMTkxOWMwYjYzZWJmZTgwZTVkNjFiYTkzN2M5MmViMWVhY2Y2ZDI4IgogICAgfQogIH0KfQ=="; + + @Description("# The slot of the warp item in the GUI") + public int slot = 10; + + @Description("# Whether the warp item should glow in the GUI") + public boolean glow = true; + } + + @Contextual + public static class WarpGuiSettings { + @Description("# The title of the warp inventory") + public String title = "» Available warps"; + + @Description("# Whether to enable the border in the warp inventory") + public boolean borderEnabled = true; + + @Description("# The material of the border in the warp inventory") + public Material borderMaterial = Material.GRAY_STAINED_GLASS_PANE; + + @Description("# The fill type of the border in the warp inventory (TOP, BOTTOM, BORDER, ALL)") + public BorderFillType borderFillType = BorderFillType.BORDER; + + @Description("# The name of the border in the warp inventory") + public String borderName = ""; + + @Description("# The lore of the border in the warp inventory") + public List borderLore = Collections.emptyList(); + + @Description("# Decoration items in the warp inventory") + public List decorationItems = List.of(); + + public enum BorderFillType { + TOP, BOTTOM, BORDER, ALL + } + } } diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/repository/WarpMigrationUtil.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/repository/WarpMigrationUtil.java new file mode 100644 index 000000000..008407c61 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/repository/WarpMigrationUtil.java @@ -0,0 +1,143 @@ +package com.eternalcode.core.feature.warp.repository; + +import com.eternalcode.core.configuration.ConfigurationManager; +import com.eternalcode.core.configuration.contextual.ConfigItem; +import com.eternalcode.core.configuration.implementation.LocationsConfiguration; +import com.eternalcode.core.feature.warp.WarpInventoryItem; +import com.eternalcode.core.feature.warp.messages.WarpMessages; +import com.eternalcode.core.translation.Translation; +import com.eternalcode.core.translation.TranslationManager; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import org.bukkit.Material; + +/** + * Utility class to help migrate from the old warp configuration to the new one. + * This class is used to migrate warp locations and GUI settings to the new warps.yml file. + */ +public class WarpMigrationUtil { + + /** + * Migrates warp locations and GUI settings to the new warps.yml file. + * + * @param translationManager The translation manager + * @param warpConfig The new warp configuration + * @param configurationManager The configuration manager + * @param locationsConfiguration The old locations configuration + * @return true if migration was successful, false otherwise + */ + public static boolean migrateWarps( + TranslationManager translationManager, + WarpConfig warpConfig, + ConfigurationManager configurationManager, + LocationsConfiguration locationsConfiguration + ) { + boolean migrated = false; + + // Migrate warp locations from old configuration + if (locationsConfiguration != null && !locationsConfiguration.warps.isEmpty()) { + warpConfig.warps.putAll(locationsConfiguration.warps + .entrySet() + .stream() + .collect(Collectors.toMap( + entry -> entry.getKey(), + entry -> new WarpConfig.WarpConfigEntry(entry.getValue(), new ArrayList<>())) + ) + ); + + locationsConfiguration.warps.clear(); + configurationManager.save(locationsConfiguration); + migrated = true; + } + + // Migrate GUI settings from language files + boolean guiMigrated = migrateGuiSettings( + translationManager, + warpConfig, + configurationManager + ); + + migrated |= guiMigrated; + + // Save the updated warp configuration + if (migrated) { + configurationManager.save(warpConfig); + } + + return migrated; + } + + /** + * Migrates warp GUI settings from language files to the new warps.yml file. + * + * @param translationManager The translation manager + * @param warpConfig The new warp configuration + * @param configurationManager The configuration manager + * @return true if migration was successful, false otherwise + */ + public static boolean migrateGuiSettings( + TranslationManager translationManager, + WarpConfig warpConfig, + ConfigurationManager configurationManager + ) { + // Get the first available language to use as a base for GUI settings + Translation translation = translationManager.getAvailableLanguages().stream() + .findFirst() + .map(translationManager::getMessages) + .orElse(null); + + if (translation == null) { + return false; + } + + WarpMessages.WarpInventorySection warpSection = translation.warp().warpInventory(); + + // Migrate GUI settings + WarpConfig.WarpGuiSettings guiSettings = warpConfig.guiSettings; + guiSettings.title = warpSection.title(); + guiSettings.borderEnabled = warpSection.border().enabled(); + guiSettings.borderMaterial = Material.valueOf(warpSection.border().material().name()); + guiSettings.borderFillType = convertFillType(warpSection.border().fillType()); + guiSettings.borderName = warpSection.border().name(); + guiSettings.borderLore = warpSection.border().lore(); + guiSettings.decorationItems = warpSection.decorationItems().items(); + + // Migrate warp items + Map warps = new HashMap<>(warpConfig.warps); + final boolean[] itemsMigrated = {false}; + + warpSection.items().forEach((name, item) -> { + WarpConfig.WarpConfigEntry warpEntry = warps.get(name); + if (warpEntry == null) { + return; + } + + ConfigItem configItem = item.warpItem(); + WarpConfig.WarpGuiItem guiItem = warpEntry.guiItem; + + guiItem.name = configItem.name(); + guiItem.lore = configItem.lore(); + guiItem.material = configItem.material(); + guiItem.texture = configItem.texture(); + guiItem.slot = configItem.slot(); + guiItem.glow = configItem.glow(); + + itemsMigrated[0] = true; + }); + + warpConfig.warps = warps; + + return true; + } + + private static WarpConfig.WarpGuiSettings.BorderFillType convertFillType(WarpMessages.WarpInventorySection.BorderSection.FillType fillType) { + return switch (fillType) { + case TOP -> WarpConfig.WarpGuiSettings.BorderFillType.TOP; + case BOTTOM -> WarpConfig.WarpGuiSettings.BorderFillType.BOTTOM; + case BORDER -> WarpConfig.WarpGuiSettings.BorderFillType.BORDER; + case ALL -> WarpConfig.WarpGuiSettings.BorderFillType.ALL; + }; + } +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/repository/WarpRepositoryImpl.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/repository/WarpRepositoryImpl.java index 3a5317433..431397c71 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/repository/WarpRepositoryImpl.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/repository/WarpRepositoryImpl.java @@ -8,7 +8,7 @@ import com.eternalcode.core.feature.warp.WarpImpl; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Repository; -import java.util.ArrayList; +import com.eternalcode.core.translation.TranslationManager; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -19,27 +19,43 @@ import java.util.stream.Collectors; @Repository -class WarpRepositoryImpl implements WarpRepository { +public class WarpRepositoryImpl implements WarpRepository { private static final Object READ_WRITE_LOCK = new Object(); - private final LocationsConfiguration locationsConfiguration; private final WarpConfig warpConfig; private final ConfigurationManager configurationManager; private final Scheduler scheduler; + private final TranslationManager translationManager; + private final LocationsConfiguration locationsConfiguration; @Inject WarpRepositoryImpl( ConfigurationManager configurationManager, - LocationsConfiguration locationsConfiguration, - WarpConfig warpConfig, Scheduler scheduler + WarpConfig warpConfig, + Scheduler scheduler, + TranslationManager translationManager, + LocationsConfiguration locationsConfiguration ) { - this.locationsConfiguration = locationsConfiguration; this.configurationManager = configurationManager; this.warpConfig = warpConfig; this.scheduler = scheduler; + this.translationManager = translationManager; + this.locationsConfiguration = locationsConfiguration; + } - this.migrateWarps(); + @Deprecated(since = "1.6.1", forRemoval = true) + public CompletableFuture migrateWarps() { + return scheduler.completeAsync(() -> { + synchronized (READ_WRITE_LOCK) { + return WarpMigrationUtil.migrateWarps( + this.translationManager, + this.warpConfig, + this.configurationManager, + this.locationsConfiguration + ); + } + }); } @Override @@ -77,26 +93,6 @@ public CompletableFuture> getWarps() { .collect(Collectors.toList())); } - private void migrateWarps() { - synchronized (READ_WRITE_LOCK) { - if (this.locationsConfiguration.warps.isEmpty()) { - return; - } - - this.transactionalRun(warps -> warps.putAll(this.locationsConfiguration.warps - .entrySet() - .stream() - .collect(Collectors.toMap( - entry -> entry.getKey(), - entry -> new WarpConfig.WarpConfigEntry(entry.getValue(), new ArrayList<>())) - ) - )); - - this.locationsConfiguration.warps.clear(); - this.configurationManager.save(this.locationsConfiguration); - } - } - private CompletableFuture transactionalRun(Consumer> editor) { return transactionalSupply(warps -> { editor.accept(warps); @@ -115,5 +111,4 @@ private CompletableFuture transactionalSupply(Function