diff --git a/.changelog/6.2.0.11.md b/.changelog/6.2.0.11.md
index a19b452621..dfc902a4c8 100644
--- a/.changelog/6.2.0.11.md
+++ b/.changelog/6.2.0.11.md
@@ -47,6 +47,16 @@
- Wildcard patterns like *_AXE and *_SPAWN_EGG now work in blacklist configuration
- Supports * for any characters and ? for single character matching
- Case-insensitive pattern matching
+- Overhauled GUI system(thanks to Yusakidev)
+ - Implemented gui.yml configuration file for customizing the GUI.
+ - Implemented better filtering for qs browse
+ - Implement GUI system to be more stable, and less error prone.
+ - Added gui.yml for fully configurable GUI layouts and text
+ - Browse menu: search, sort (price/name/stock), and filter (all/buying/selling/in-stock)
+ - Staff menu: search functionality for player/staff selection
+ - Grouped item pages for better shop browsing
+ - Refactored all menu pages to use configurable display/lore
+ - Moved GUI messages from messages.yml to gui.yml
## Addons/Compats Changes
- Added UltimateClaims compat
@@ -84,10 +94,14 @@
manager.interaction(new MyTradeInteraction());
manager.behavior(new MyTradeBehavior());
```
-- Replaced some apache commons calls that could be easily replaced with built-in java methods, reduces some calls by ~ 1100ms/method call
-- Deprecated the ShopType enum, and the ShopTypeEvent. These are replaced with the new IShopType interface, and implementing classes.
+- Replaced some Apache Commons calls that could be easily replaced with built-in java methods, reduces some calls by ~ 1100ms/method call
+- Deprecated the ShopType enum, and the ShopTypeEvent. These are replaced with the new IShopType interface and implementing classes.
- The new event is ShopTypeEnhancedEvent.
- This allows for third-party addons to add their own shop types, and simplifies code checks for translations.
+- Updated config system to use Boosted-yaml
+ - this allows for auto-updating of config files without complex update scripts
+ - this also allows for the config system to not be minecraft-dependent.
+- Replaced logical PaperLib calls with native PaperAPI calls.
## Minor Changes
- Bump Java version up to 21
@@ -97,6 +111,9 @@
- Bumped Residence version for the compat(thanks to YuanYuanOwO)
- add world whitelist support(thanks to wling-art)
- added /qs database save command, which saves all currently dirty-marked shops to the database.
+- Split up interactions _SHOPBLOCK into _SHOPBLOCK and _CONTAINER.
+ - _SHOPBLOCK relates to shops, where _CONTAINER relates to shop-valid containers that are not currently shops.
+- Added inventory as an option for command panel, this is useful for adding a secondary option for players to open a shop's inventory.
## Fixes
- Fixes issue with item price restrictions(thanks to maxcom1)
@@ -114,4 +131,9 @@
- Fixed issue with 1.20.4 packetevents virtual displays not staying put.
- Fixes critical issue in GriefPrevention compatibility plugin.
- Fixes issue with shop owner not getting money when benefits active.
-- Fixes for lands addon on folia, Use regionThread for Folia compatibility(thanks to YusakiDev)
\ No newline at end of file
+- Fixes for lands addon on folia, Use regionThread for Folia compatibility(thanks to YusakiDev)
+- Fixes for TRADE_DIRECT on stacking shops
+- Fixes issue for protocollib 5.4.0 with undocumented packet changes.
+- Fixes issue where item stacks could be used on creation above the max stack size.
+- Fixes issue with BukkitAudiences-related crashes on 1.21.11.
+- Fix issue with shop deletion when getting too impatient.
\ No newline at end of file
diff --git a/addon/betonquest/pom.xml b/addon/betonquest/pom.xml
index 4f3f221160..14749f5b4c 100644
--- a/addon/betonquest/pom.xml
+++ b/addon/betonquest/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/addon/bluemap/pom.xml b/addon/bluemap/pom.xml
index 0e465a5624..784d065501 100644
--- a/addon/bluemap/pom.xml
+++ b/addon/bluemap/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.addon
diff --git a/addon/discordsrv/pom.xml b/addon/discordsrv/pom.xml
index 86d0fb5d46..9c90f7db28 100644
--- a/addon/discordsrv/pom.xml
+++ b/addon/discordsrv/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.addon
diff --git a/addon/discount/pom.xml b/addon/discount/pom.xml
index c1e1124459..adcbb38395 100644
--- a/addon/discount/pom.xml
+++ b/addon/discount/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.addon
diff --git a/addon/displaycontrol/pom.xml b/addon/displaycontrol/pom.xml
index 74065a8155..6e8e55573e 100644
--- a/addon/displaycontrol/pom.xml
+++ b/addon/displaycontrol/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.addon
diff --git a/addon/displaycontrol/src/main/java/com/ghostchu/quickshop/addon/displaycontrol/Main.java b/addon/displaycontrol/src/main/java/com/ghostchu/quickshop/addon/displaycontrol/Main.java
index 016f90969e..16154a22b8 100644
--- a/addon/displaycontrol/src/main/java/com/ghostchu/quickshop/addon/displaycontrol/Main.java
+++ b/addon/displaycontrol/src/main/java/com/ghostchu/quickshop/addon/displaycontrol/Main.java
@@ -122,7 +122,7 @@ public DisplayControlDatabaseHelper getDatabaseHelper() {
}
@Override
- public void onPluginMessageReceived(@NotNull final String channel, @NotNull final Player player, final byte @NotNull [] message) {
+ public void onPluginMessageReceived(@NotNull final String channel, @NotNull final Player player, final @NotNull byte[] message) {
if(!channel.equalsIgnoreCase(BUNGEE_CHANNEL)) {
return;
diff --git a/addon/dynmap/pom.xml b/addon/dynmap/pom.xml
index 00227c85ff..86bf390185 100644
--- a/addon/dynmap/pom.xml
+++ b/addon/dynmap/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.addon
diff --git a/addon/limited/pom.xml b/addon/limited/pom.xml
index d3341874d0..8391a6ce54 100644
--- a/addon/limited/pom.xml
+++ b/addon/limited/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.addon
diff --git a/addon/list/pom.xml b/addon/list/pom.xml
index 087ee46b8d..566d4fd2a7 100644
--- a/addon/list/pom.xml
+++ b/addon/list/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.addon
diff --git a/addon/pl3xmap/pom.xml b/addon/pl3xmap/pom.xml
index b301751cc2..bc78eec3c7 100644
--- a/addon/pl3xmap/pom.xml
+++ b/addon/pl3xmap/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.addon
diff --git a/addon/plan/pom.xml b/addon/plan/pom.xml
index 52711c5100..de5047d65d 100644
--- a/addon/plan/pom.xml
+++ b/addon/plan/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.addon
diff --git a/addon/quests/pom.xml b/addon/quests/pom.xml
index 874dce33d6..fc30f977aa 100644
--- a/addon/quests/pom.xml
+++ b/addon/quests/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/addon/reremake-migrator/pom.xml b/addon/reremake-migrator/pom.xml
index f890a9815a..47dceeb6f1 100644
--- a/addon/reremake-migrator/pom.xml
+++ b/addon/reremake-migrator/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.addon
diff --git a/addon/shopitemonly/pom.xml b/addon/shopitemonly/pom.xml
index 4aa876429e..8c6462b652 100644
--- a/addon/shopitemonly/pom.xml
+++ b/addon/shopitemonly/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.addon
diff --git a/addon/squaremap/pom.xml b/addon/squaremap/pom.xml
index f8b9443c76..b494f187fa 100644
--- a/addon/squaremap/pom.xml
+++ b/addon/squaremap/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.addon
diff --git a/addon/squaremap/src/main/java/com/ghostchu/quickshop/addon/squaremap/Main.java b/addon/squaremap/src/main/java/com/ghostchu/quickshop/addon/squaremap/Main.java
index 0e8431a0cd..4956149de9 100644
--- a/addon/squaremap/src/main/java/com/ghostchu/quickshop/addon/squaremap/Main.java
+++ b/addon/squaremap/src/main/java/com/ghostchu/quickshop/addon/squaremap/Main.java
@@ -1,10 +1,6 @@
package com.ghostchu.quickshop.addon.squaremap;
import com.ghostchu.quickshop.QuickShop;
-import xyz.jpenilla.squaremap.api.BukkitAdapter;
-import xyz.jpenilla.squaremap.api.Key;
-import xyz.jpenilla.squaremap.api.Squaremap;
-import xyz.jpenilla.squaremap.api.SquaremapProvider;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
@@ -14,6 +10,10 @@
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
+import xyz.jpenilla.squaremap.api.BukkitAdapter;
+import xyz.jpenilla.squaremap.api.Key;
+import xyz.jpenilla.squaremap.api.Squaremap;
+import xyz.jpenilla.squaremap.api.SquaremapProvider;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
diff --git a/addon/squaremap/src/main/java/com/ghostchu/quickshop/addon/squaremap/ShopLayerProvider.java b/addon/squaremap/src/main/java/com/ghostchu/quickshop/addon/squaremap/ShopLayerProvider.java
index 61bb7fdcd2..501fe8b00c 100644
--- a/addon/squaremap/src/main/java/com/ghostchu/quickshop/addon/squaremap/ShopLayerProvider.java
+++ b/addon/squaremap/src/main/java/com/ghostchu/quickshop/addon/squaremap/ShopLayerProvider.java
@@ -5,15 +5,15 @@
import lombok.Getter;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.jetbrains.annotations.NotNull;
import xyz.jpenilla.squaremap.api.Key;
import xyz.jpenilla.squaremap.api.Point;
import xyz.jpenilla.squaremap.api.SimpleLayerProvider;
import xyz.jpenilla.squaremap.api.marker.Icon;
import xyz.jpenilla.squaremap.api.marker.Marker;
import xyz.jpenilla.squaremap.api.marker.MarkerOptions;
-import org.bukkit.Bukkit;
-import org.bukkit.Location;
-import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Map;
diff --git a/compatibility/advancedregionmarket/pom.xml b/compatibility/advancedregionmarket/pom.xml
index 866b51ea85..67bc7b214e 100644
--- a/compatibility/advancedregionmarket/pom.xml
+++ b/compatibility/advancedregionmarket/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/angelchest/pom.xml b/compatibility/angelchest/pom.xml
index d8c8e3ac4d..0dc4899e72 100644
--- a/compatibility/angelchest/pom.xml
+++ b/compatibility/angelchest/pom.xml
@@ -6,7 +6,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/bentobox/pom.xml b/compatibility/bentobox/pom.xml
index ad9202d161..573bd97fa0 100644
--- a/compatibility/bentobox/pom.xml
+++ b/compatibility/bentobox/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/bungeecord-geyser/pom.xml b/compatibility/bungeecord-geyser/pom.xml
index b533d7eeb3..a8fc928deb 100644
--- a/compatibility/bungeecord-geyser/pom.xml
+++ b/compatibility/bungeecord-geyser/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/bungeecord/pom.xml b/compatibility/bungeecord/pom.xml
index d170148dfb..fec9aaab49 100644
--- a/compatibility/bungeecord/pom.xml
+++ b/compatibility/bungeecord/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/chestprotect/pom.xml b/compatibility/chestprotect/pom.xml
index ee9f8beff8..fb368cdd2b 100644
--- a/compatibility/chestprotect/pom.xml
+++ b/compatibility/chestprotect/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/clearlag/pom.xml b/compatibility/clearlag/pom.xml
index 5333cb89ca..6a3d49a9a0 100644
--- a/compatibility/clearlag/pom.xml
+++ b/compatibility/clearlag/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/common/pom.xml b/compatibility/common/pom.xml
index 57a003c554..4b0adea6d3 100644
--- a/compatibility/common/pom.xml
+++ b/compatibility/common/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/common/src/main/java/com/ghostchu/quickshop/compatibility/CompatibilityModule.java b/compatibility/common/src/main/java/com/ghostchu/quickshop/compatibility/CompatibilityModule.java
index b0fd5a211d..ee658060d1 100644
--- a/compatibility/common/src/main/java/com/ghostchu/quickshop/compatibility/CompatibilityModule.java
+++ b/compatibility/common/src/main/java/com/ghostchu/quickshop/compatibility/CompatibilityModule.java
@@ -66,7 +66,7 @@ public void onLoad() {
try {
saveDefaultConfig();
- } catch(IllegalArgumentException ignored) {
+ } catch(final IllegalArgumentException ignored) {
}
this.api = QuickShopAPI.getInstance();
getLogger().info("Loading up...");
@@ -84,7 +84,7 @@ public void onEnable() {
// Plugin startup logic
try {
saveDefaultConfig();
- } catch(IllegalArgumentException ignored) {
+ } catch(final IllegalArgumentException ignored) {
}
this.api = QuickShopAPI.getInstance();
Bukkit.getPluginManager().registerEvents(this, this);
diff --git a/compatibility/dominion/pom.xml b/compatibility/dominion/pom.xml
index cafed504c7..65591d90b7 100644
--- a/compatibility/dominion/pom.xml
+++ b/compatibility/dominion/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/ecoenchants/pom.xml b/compatibility/ecoenchants/pom.xml
index 02f45f9513..e43813753b 100644
--- a/compatibility/ecoenchants/pom.xml
+++ b/compatibility/ecoenchants/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/elitemobs/pom.xml b/compatibility/elitemobs/pom.xml
index f07e0e2e20..f5c2a9ca04 100644
--- a/compatibility/elitemobs/pom.xml
+++ b/compatibility/elitemobs/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/fabledskyblock/pom.xml b/compatibility/fabledskyblock/pom.xml
index 1024007f90..589ce19e3f 100644
--- a/compatibility/fabledskyblock/pom.xml
+++ b/compatibility/fabledskyblock/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/griefprevention/pom.xml b/compatibility/griefprevention/pom.xml
index ca30d20375..3059699ddb 100644
--- a/compatibility/griefprevention/pom.xml
+++ b/compatibility/griefprevention/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/husktowns/pom.xml b/compatibility/husktowns/pom.xml
index 314515b032..b7a91ba18e 100644
--- a/compatibility/husktowns/pom.xml
+++ b/compatibility/husktowns/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/iridiumskyblock/pom.xml b/compatibility/iridiumskyblock/pom.xml
index 96fa9a2ecb..c07fbda0de 100644
--- a/compatibility/iridiumskyblock/pom.xml
+++ b/compatibility/iridiumskyblock/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/itemsadder/pom.xml b/compatibility/itemsadder/pom.xml
index 508a1e093d..d2e1cfcbd0 100644
--- a/compatibility/itemsadder/pom.xml
+++ b/compatibility/itemsadder/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/lands/pom.xml b/compatibility/lands/pom.xml
index 51a2960c06..a28d2667db 100644
--- a/compatibility/lands/pom.xml
+++ b/compatibility/lands/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/matcherplus/pom.xml b/compatibility/matcherplus/pom.xml
index e058bb7f1a..09e77056d2 100644
--- a/compatibility/matcherplus/pom.xml
+++ b/compatibility/matcherplus/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/openinv/pom.xml b/compatibility/openinv/pom.xml
index 218a72ed03..2469e9ed9f 100644
--- a/compatibility/openinv/pom.xml
+++ b/compatibility/openinv/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/plotsquared/pom.xml b/compatibility/plotsquared/pom.xml
index b96ea19afe..2b73e730ea 100644
--- a/compatibility/plotsquared/pom.xml
+++ b/compatibility/plotsquared/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/reforges/pom.xml b/compatibility/reforges/pom.xml
index 0c899a8c2f..624122684b 100644
--- a/compatibility/reforges/pom.xml
+++ b/compatibility/reforges/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/residence/pom.xml b/compatibility/residence/pom.xml
index 2362d04287..f6dc679659 100644
--- a/compatibility/residence/pom.xml
+++ b/compatibility/residence/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/simpleclaimsystem/pom.xml b/compatibility/simpleclaimsystem/pom.xml
index 1de176e77f..eed2dbfe2a 100644
--- a/compatibility/simpleclaimsystem/pom.xml
+++ b/compatibility/simpleclaimsystem/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/slimefun/pom.xml b/compatibility/slimefun/pom.xml
index e286d467bf..0e0ae8c8a9 100644
--- a/compatibility/slimefun/pom.xml
+++ b/compatibility/slimefun/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/superiorskyblock/pom.xml b/compatibility/superiorskyblock/pom.xml
index 42f26f0588..ac2838d7da 100644
--- a/compatibility/superiorskyblock/pom.xml
+++ b/compatibility/superiorskyblock/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/towny/pom.xml b/compatibility/towny/pom.xml
index 156be005fe..34a2c92218 100644
--- a/compatibility/towny/pom.xml
+++ b/compatibility/towny/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/ultimateclaims/pom.xml b/compatibility/ultimateclaims/pom.xml
index 6e5eeb3946..a3491cf651 100644
--- a/compatibility/ultimateclaims/pom.xml
+++ b/compatibility/ultimateclaims/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/velocity/pom.xml b/compatibility/velocity/pom.xml
index 5d05e2e8c6..b3290b3f23 100644
--- a/compatibility/velocity/pom.xml
+++ b/compatibility/velocity/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/voidchest/pom.xml b/compatibility/voidchest/pom.xml
index 51f0f70f61..0ea4b1e215 100644
--- a/compatibility/voidchest/pom.xml
+++ b/compatibility/voidchest/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/worldedit/pom.xml b/compatibility/worldedit/pom.xml
index b963a5f9a3..8d0e43b976 100644
--- a/compatibility/worldedit/pom.xml
+++ b/compatibility/worldedit/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/compatibility/worldguard/pom.xml b/compatibility/worldguard/pom.xml
index 1221f03f9d..d292afb03b 100644
--- a/compatibility/worldguard/pom.xml
+++ b/compatibility/worldguard/pom.xml
@@ -7,7 +7,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
com.ghostchu.quickshop.compatibility
diff --git a/downloads.json b/downloads.json
index b85380dbcf..e63d4fa0f2 100644
--- a/downloads.json
+++ b/downloads.json
@@ -10,6 +10,11 @@
"snapshots": [
{
+ "version": "6.2.0.11-SNAPSHOT-13",
+ "downloadUrl": "https://cdn.discordapp.com/attachments/1457411929550229557/1457411929982107802/QuickShop-Hikari-6.2.0.11-SNAPSHOT-13.jar?ex=695be821&is=695a96a1&hm=a78b56041d7ee2efdfdf44ad9b0f25109f378878cd973f75a57fae53158358d7&"
+ },
+ {
+
"version": "6.2.0.11-SNAPSHOT-12",
"downloadUrl": "https://cdn.discordapp.com/attachments/1447773525803925614/1447774048154292264/QuickShop-Hikari-6.2.0.11-SNAPSHOT-12.jar?ex=6938d827&is=693786a7&hm=e83923c019d519526ab82ceab7b576af8c66093f18893a56a3fb58ca70b0fef8&"
},
diff --git a/platform/quickshop-platform-interface/pom.xml b/platform/quickshop-platform-interface/pom.xml
index f096525fa3..a6fab20d38 100644
--- a/platform/quickshop-platform-interface/pom.xml
+++ b/platform/quickshop-platform-interface/pom.xml
@@ -8,7 +8,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
diff --git a/platform/quickshop-platform-paper/pom.xml b/platform/quickshop-platform-paper/pom.xml
index 21478728e6..453608dff1 100644
--- a/platform/quickshop-platform-paper/pom.xml
+++ b/platform/quickshop-platform-paper/pom.xml
@@ -8,7 +8,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
../../pom.xml
diff --git a/pom.xml b/pom.xml
index 069001f172..b7bbf41832 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
pom
quickshop-hikari
Another QuickShop fork
@@ -34,6 +34,7 @@
4.3.4
4.3.4
4.3.4
+ 1.3.7
3.18.0
0.4.7
1.3.0
@@ -41,7 +42,7 @@
2.15.0
2.9.0-SNAPSHOT
1.21-R0.1-SNAPSHOT
- 5.3.0
+ 5.4.0
1.7.1
2.13
@@ -213,6 +214,7 @@
io.vertx:vertx-core:*
io.vertx:vertx-web:*
org.eclipse.aether:*:*
+ dev.dejvokep:boosted-yaml
org.slf4j:slf4j-jdk14:*
cc.carm.lib:*
com.rollbar:*
@@ -427,12 +429,6 @@
1.18.38
provided
-
- org.jetbrains
- annotations
- 26.0.2
- provided
-
org.slf4j
@@ -457,6 +453,8 @@
org.jetbrains
annotations
+ 26.0.2-1
+ provided
diff --git a/quickshop-api/pom.xml b/quickshop-api/pom.xml
index 8e4a53a0b1..2cb1997e3b 100644
--- a/quickshop-api/pom.xml
+++ b/quickshop-api/pom.xml
@@ -5,7 +5,7 @@
quickshop-hikari
com.ghostchu
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
4.0.0
@@ -13,6 +13,12 @@
takari-jar
+
+ org.jetbrains
+ annotations
+ 26.0.2-1
+ provided
+
com.ghostchu
quickshop-common
@@ -23,6 +29,24 @@
io.papermc.paper
paper-api
${depend.paper}
+
+
+ org.jetbrains
+ annotations
+
+
+
+
+ dev.dejvokep
+ boosted-yaml
+ 1.3.7
+ compile
+
+
+ org.jetbrains
+ annotations-java5
+
+
\ No newline at end of file
diff --git a/quickshop-api/src/main/java/com/ghostchu/quickshop/api/config/QSConfig.java b/quickshop-api/src/main/java/com/ghostchu/quickshop/api/config/QSConfig.java
new file mode 100644
index 0000000000..4b25971f37
--- /dev/null
+++ b/quickshop-api/src/main/java/com/ghostchu/quickshop/api/config/QSConfig.java
@@ -0,0 +1,147 @@
+package com.ghostchu.quickshop.api.config;
+
+/*
+ * QuickShop-Hikari
+ * Copyright (C) 2025 Daniel "creatorfromhell" Vidmar
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import com.ghostchu.quickshop.api.QuickShopAPI;
+import com.ghostchu.simplereloadlib.ReloadResult;
+import com.ghostchu.simplereloadlib.ReloadStatus;
+import com.ghostchu.simplereloadlib.Reloadable;
+import dev.dejvokep.boostedyaml.YamlDocument;
+import dev.dejvokep.boostedyaml.settings.Settings;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * QSConfig
+ *
+ * @author creatorfromhell
+ * @since 6.2.0.11
+ */
+public class QSConfig implements Reloadable {
+
+ protected final String fileName;
+ protected final File file;
+ protected final String defaults;
+ protected final List nodes = new ArrayList<>();
+ protected YamlDocument yaml;
+ protected Settings[] settings;
+
+ public QSConfig(final String fileName, final String defaults, final List nodes, final Settings... settings) {
+
+ this.defaults = defaults;
+ this.fileName = fileName;
+ this.nodes.addAll(nodes);
+ file = new File(QuickShopAPI.getPluginInstance().getDataFolder(), fileName);
+
+ this.settings = settings;
+
+ if(!file.exists()) {
+ QuickShopAPI.getPluginInstance().getLogger().warning("Configuration doesn't exist! File Name:" + fileName);
+ }
+ }
+
+ public boolean load() {
+
+ try(final InputStream in = getResource(defaults)) {
+
+ if(in != null) {
+ this.yaml = YamlDocument.create(file, in, settings);
+
+ return true;
+ }
+ } catch(final IOException ignore) {
+
+ QuickShopAPI.getPluginInstance().getLogger().warning("Error while creating config \"" + file.getName() + "\".");
+ return false;
+ }
+ return false;
+ }
+
+ public YamlDocument getYaml() {
+
+ return yaml;
+ }
+
+ public void setYaml(final YamlDocument yaml) {
+
+ this.yaml = yaml;
+ }
+
+ public boolean save() {
+
+ try {
+
+ yaml.save(file);
+ return true;
+ } catch(final IOException ignore) {
+
+ QuickShopAPI.getPluginInstance().getLogger().warning("Error while saving config \"" + nodes.get(0) + "\".");
+ return false;
+ }
+ }
+
+ public void setComment(final String route, final List comments) {
+
+ if(yaml.contains(route)) {
+ yaml.getBlock(route).setComments(comments);
+ }
+ }
+
+ public void setComment(final String route, final String comment) {
+
+ setComment(route, Collections.singletonList(comment));
+ }
+
+ public @Nullable InputStream getResource(@NotNull final String filename) {
+
+ try {
+ final URL url = this.getClass().getClassLoader().getResource(filename);
+ if(url == null) {
+ return null;
+ } else {
+
+ final URLConnection connection = url.openConnection();
+ connection.setUseCaches(false);
+
+ return connection.getInputStream();
+ }
+ } catch(final IOException ignore) {
+ return null;
+ }
+ }
+
+ @Override
+ public ReloadResult reloadModule() throws Exception {
+
+ load();
+
+ QuickShopAPI.getPluginInstance().getLogger().info("Configuration reloaded successfully. File Name:" + fileName);
+
+ return ReloadResult.builder().status(ReloadStatus.SUCCESS).build();
+ }
+}
\ No newline at end of file
diff --git a/quickshop-api/src/main/java/com/ghostchu/quickshop/api/shop/Locatable.java b/quickshop-api/src/main/java/com/ghostchu/quickshop/api/shop/Locatable.java
new file mode 100644
index 0000000000..46ef11c79a
--- /dev/null
+++ b/quickshop-api/src/main/java/com/ghostchu/quickshop/api/shop/Locatable.java
@@ -0,0 +1,36 @@
+package com.ghostchu.quickshop.api.shop;
+
+
+/*
+ * QuickShop-Hikari
+ * Copyright (C) 2025 Daniel "creatorfromhell" Vidmar
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+/**
+ * Locatable
+ *
+ * @author creatorfromhell
+ * @since 6.2.0.11
+ */
+public interface Locatable {
+
+ /**
+ * Retrieves the location associated with this object.
+ *
+ * @return the location of type T associated with this object.
+ */
+ T getLocation();
+}
\ No newline at end of file
diff --git a/quickshop-api/src/main/java/com/ghostchu/quickshop/api/shop/Shop.java b/quickshop-api/src/main/java/com/ghostchu/quickshop/api/shop/Shop.java
index 4fa86c68d4..445223e6bb 100644
--- a/quickshop-api/src/main/java/com/ghostchu/quickshop/api/shop/Shop.java
+++ b/quickshop-api/src/main/java/com/ghostchu/quickshop/api/shop/Shop.java
@@ -29,7 +29,7 @@
/**
* A shop
*/
-public interface Shop {
+public interface Shop extends Locatable {
NamespacedKey SHOP_NAMESPACED_KEY = new NamespacedKey(QuickShopAPI.getPluginInstance(), "shopsign");
@@ -130,14 +130,6 @@ public interface Shop {
*/
void setItem(@NotNull ItemStack item);
- /**
- * Get shop's location
- *
- * @return Shop's location
- */
- @NotNull
- Location getLocation();
-
/**
* Get shop's owner QUser
@@ -678,5 +670,4 @@ default List getSignText(@NotNull final ProxiedLocale locale) {
* Sets the benefit in this shop
*/
void setShopBenefit(@NotNull BenefitProvider benefit);
-
-}
+}
\ No newline at end of file
diff --git a/quickshop-bukkit/pom.xml b/quickshop-bukkit/pom.xml
index 7e0708d6c1..c410c0f0fa 100644
--- a/quickshop-bukkit/pom.xml
+++ b/quickshop-bukkit/pom.xml
@@ -8,7 +8,7 @@
com.ghostchu
quickshop-hikari
- 6.2.0.11-SNAPSHOT-12
+ 6.2.0.11-SNAPSHOT-13
@@ -71,6 +71,12 @@
+
+ org.jetbrains
+ annotations
+ 26.0.2-1
+ provided
+
io.papermc.paper
paper-api
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/QuickShop.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/QuickShop.java
index c523b3a474..c2b2366e62 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/QuickShop.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/QuickShop.java
@@ -31,6 +31,8 @@
import com.ghostchu.quickshop.common.util.CommonUtil;
import com.ghostchu.quickshop.common.util.JsonUtil;
import com.ghostchu.quickshop.common.util.QuickExecutor;
+import com.ghostchu.quickshop.config.GuiConfig;
+import com.ghostchu.quickshop.config.MainConfig;
import com.ghostchu.quickshop.database.DatabaseIOUtil;
import com.ghostchu.quickshop.database.HikariUtil;
import com.ghostchu.quickshop.database.SimpleDatabaseHelperV2;
@@ -84,8 +86,6 @@
import com.ghostchu.quickshop.util.ReflectFactory;
import com.ghostchu.quickshop.util.ShopUtil;
import com.ghostchu.quickshop.util.Util;
-import com.ghostchu.quickshop.util.config.ConfigUpdateScript;
-import com.ghostchu.quickshop.util.config.ConfigurationUpdater;
import com.ghostchu.quickshop.util.envcheck.CheckResult;
import com.ghostchu.quickshop.util.envcheck.EnvCheckEntry;
import com.ghostchu.quickshop.util.envcheck.EnvironmentChecker;
@@ -115,6 +115,8 @@
import com.google.common.cache.CacheBuilder;
import com.tcoded.folialib.FoliaLib;
import com.vdurmont.semver4j.Semver;
+import dev.dejvokep.boostedyaml.YamlDocument;
+import dev.dejvokep.boostedyaml.block.implementation.Section;
import io.papermc.lib.PaperLib;
import lombok.Getter;
import lombok.Setter;
@@ -145,8 +147,6 @@
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.PluginCommand;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.event.HandlerList;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.ServicePriority;
@@ -172,7 +172,6 @@
import java.util.concurrent.CompletionException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
public class QuickShop implements QuickShopAPI, Reloadable {
@@ -193,6 +192,7 @@ public class QuickShop implements QuickShopAPI, Reloadable {
*/
@ApiStatus.Internal
private static QuickShop instance;
+ private MainConfig config;
/**
* The manager to check permissions.
*/
@@ -218,7 +218,7 @@ public class QuickShop implements QuickShopAPI, Reloadable {
protected HelperMethods helperMethods;
private QuickShopInteractionManager interactionManager;
@Getter
- private com.ghostchu.quickshop.menu.config.GuiConfig guiConfig;
+ private GuiConfig guiConfig;
private FoliaLib folia;
/* Public QuickShop API End */
private GameVersion gameVersion;
@@ -255,6 +255,8 @@ public class QuickShop implements QuickShopAPI, Reloadable {
@Getter
private LogWatcher logWatcher;
+ private boolean onFolia = false;
+
/**
* The plugin PlaceHolderAPI(null if not present)
*/
@@ -469,15 +471,19 @@ private void initConfiguration() {
/* Process the config */
//noinspection ResultOfMethodCallIgnored
javaPlugin.getDataFolder().mkdirs();
- try {
+
+ this.config = new MainConfig(this);
+ if(!this.config.load()) {
+ logger.error("Failed to load config.yml, The binary file of QuickShop may be corrupted. Please re-download from our website.");
+ }
+
+ /*try {
javaPlugin.saveDefaultConfig();
} catch(final IllegalArgumentException resourceNotFoundException) {
logger.error("Failed to save config.yml from jar, The binary file of QuickShop may be corrupted. Please re-download from our website.");
}
- javaPlugin.reloadConfig();
- if(getConfig().getInt("config-version", 0) == 0) {
- getConfig().set("config-version", 1);
- }
+ javaPlugin.reloadConfig();*/
+
/* It will generate a new UUID above updateConfig */
this.serverUniqueID = UUID.fromString(Objects.requireNonNull(getConfig().getString("server-uuid", String.valueOf(UUID.randomUUID()))));
updateConfig();
@@ -549,15 +555,19 @@ public void reloadConfigSubModule() {
//Util.mainThreadRun(() -> new QSConfigurationReloadEvent(javaPlugin).callEvent());
}
+ public MainConfig mainConfig() {
+ return this.config;
+ }
+
@NotNull
- public FileConfiguration getConfig() {
+ public YamlDocument getConfig() {
- return javaPlugin.getConfig();
+ return this.config.getYaml();
}
private void updateConfig() {
- new ConfigurationUpdater(this).update(new ConfigUpdateScript(getConfig(), this));
+ //new ConfigurationUpdater(this).update(new ConfigUpdateScript(getConfig(), this));
}
@NotNull
@@ -715,6 +725,7 @@ public final void onEnable() {
if(this.folia.isFolia()) {
+ this.onFolia = true;
Bukkit.getPluginManager().registerEvents(new FoliaChatListener(javaPlugin), javaPlugin);
Bukkit.getPluginManager().registerEvents(new FoliaInventoryClickListener(javaPlugin), javaPlugin);
Bukkit.getPluginManager().registerEvents(new FoliaInventoryCloseListener(javaPlugin), javaPlugin);
@@ -734,7 +745,7 @@ public final void onEnable() {
}
// Initialize GuiConfig before menus that depend on it
- this.guiConfig = new com.ghostchu.quickshop.menu.config.GuiConfig(this);
+ this.guiConfig = new GuiConfig(this);
MenuManager.instance().addMenu(new ShopHistoryMenu());
MenuManager.instance().addMenu(new ShopKeeperMenu());
@@ -1078,7 +1089,7 @@ public boolean setupDatabase() {
logger.info("Setting up database...");
final HikariConfig config = HikariUtil.createHikariConfig();
try {
- final ConfigurationSection dbCfg = getConfig().getConfigurationSection("database");
+ final Section dbCfg = getConfig().getSection("database");
if(Objects.requireNonNull(dbCfg).getBoolean("mysql")) {
databaseDriverType = DatabaseDriverType.MYSQL;
// MySQL database - Required database be created first.
@@ -1265,6 +1276,11 @@ public Platform platform() {
return platform;
}
+ public boolean onFolia() {
+
+ return onFolia;
+ }
+
@NotNull
public File getDataFolder() {
@@ -1341,7 +1357,7 @@ public String getMainCommand() {
public String getCommandPrefix(final String commandLabel) {
- final ConfigurationSection section = getConfig().getConfigurationSection("custom-subcommands");
+ final Section section = getConfig().getSection("custom-subcommands");
if(section == null) return commandLabel;
final String prefix = section.getString(commandLabel);
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/QuickShopBukkit.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/QuickShopBukkit.java
index 20ee3f2b23..df4068c37d 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/QuickShopBukkit.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/QuickShopBukkit.java
@@ -43,10 +43,15 @@ public class QuickShopBukkit extends JavaPlugin {
@Override
public void reloadConfig() {
- super.reloadConfig();
this.quickShop.reloadConfigSubModule();
}
+ @Override
+ public void saveConfig() {
+
+ this.quickShop.mainConfig().save();
+ }
+
@Override
public void onLoad() {
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/SimpleCommandManager.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/SimpleCommandManager.java
index 94b0f30af2..83a24277d2 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/SimpleCommandManager.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/SimpleCommandManager.java
@@ -55,6 +55,7 @@
import com.ghostchu.quickshop.command.subcommand.silent.SubCommand_SilentEmpty;
import com.ghostchu.quickshop.command.subcommand.silent.SubCommand_SilentFreeze;
import com.ghostchu.quickshop.command.subcommand.silent.SubCommand_SilentHistory;
+import com.ghostchu.quickshop.command.subcommand.silent.SubCommand_SilentInventory;
import com.ghostchu.quickshop.command.subcommand.silent.SubCommand_SilentPreview;
import com.ghostchu.quickshop.command.subcommand.silent.SubCommand_SilentRemove;
import com.ghostchu.quickshop.command.subcommand.silent.SubCommand_SilentSell;
@@ -240,6 +241,13 @@ public SimpleCommandManager(final QuickShop plugin) {
.permission("quickshop.empty")
.executor(new SubCommand_SilentEmpty(plugin))
.build());
+ registerCmd(
+ CommandContainer.builder()
+ .prefix("silentinventory")
+ .hidden(true)
+ .permission("quickshop.inventory")
+ .executor(new SubCommand_SilentInventory(plugin))
+ .build());
registerCmd(
CommandContainer.builder()
.prefix("silentpreview")
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Clean.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Clean.java
index 196208f647..3df37daddc 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Clean.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Clean.java
@@ -46,7 +46,7 @@ public void onCommand(@NotNull final CommandSender sender, @NotNull final String
pendingRemoval.add(shop);
i++;
}
- } catch(IllegalStateException e) {
+ } catch(final IllegalStateException e) {
pendingRemoval.add(shop); // The shop is not there anymore, remove it
}
}
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_CleanGhost.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_CleanGhost.java
index fd7d416580..bfe40ae215 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_CleanGhost.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_CleanGhost.java
@@ -84,4 +84,4 @@ public void onCommand(@NotNull final CommandSender sender, @NotNull final String
}
-}
+}
\ No newline at end of file
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Create.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Create.java
index 253758d796..4ee46d43f3 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Create.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Create.java
@@ -56,6 +56,12 @@ public void onCommand(@NotNull final Player sender, @NotNull final String comman
if(amount < 1) {
amount = 1;
}
+
+ final int maxSize = Util.getItemMaxStackSize(material);
+ if(amount > maxSize) {
+ amount = maxSize;
+ }
+
item = new ItemStack(material, amount);
} catch(final NumberFormatException e) {
item = new ItemStack(material, 1);
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Debug.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Debug.java
index e04379539e..7c51f5b1d6 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Debug.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Debug.java
@@ -87,12 +87,12 @@ private void handleDisplayEntities(final CommandSender sender, final List entities = new ArrayList<>();
for(final World world : Bukkit.getWorlds()) {
for(final Entity entity : world.getEntities()) {
- if(entity instanceof Item itemEntity) {
+ if(entity instanceof final Item itemEntity) {
if(AbstractDisplayItem.checkIsGuardItemStack(itemEntity.getItemStack())) {
entities.add(entity);
}
}
- if(entity instanceof ItemDisplay itemDisplay) {
+ if(entity instanceof final ItemDisplay itemDisplay) {
if(AbstractDisplayItem.checkIsGuardItemStack(itemDisplay.getItemStack())) {
entities.add(entity);
}
@@ -131,7 +131,7 @@ private void handleShopsDirtyAndSave(final CommandSender sender, final List subParams) {
- if(!(sender instanceof Player player)) {
+ if(!(sender instanceof final Player player)) {
return;
}
if(player.getInventory().getItemInMainHand().getType().isAir()) {
@@ -164,21 +164,21 @@ private void handleDbConnectionTest(final CommandSender sender, final List{
- try(Connection connection = plugin.getSqlManager().getConnection()) {
+ try(final Connection connection = plugin.getSqlManager().getConnection()) {
if(connection.isValid(1000)) {
plugin.text().of(sender, "debug.hikari-cp-working").send();
} else {
plugin.text().of(sender, "debug.hikari-cp-not-working");
}
- } catch(SQLException e) {
+ } catch(final SQLException e) {
plugin.text().of(sender, "internal-error").send();
e.printStackTrace();
}
return null;
}).get(5, TimeUnit.SECONDS);
- } catch(TimeoutException e) {
+ } catch(final TimeoutException e) {
plugin.text().of(sender, "debug.hikari-cp-timeout").send();
- } catch(ExecutionException | InterruptedException e) {
+ } catch(final ExecutionException | InterruptedException e) {
plugin.text().of(sender, "internal-error").send();
e.printStackTrace();
}
@@ -212,7 +212,7 @@ private void handleDumpHikariCPStatus(final CommandSender sender, final List{
try {
- databaseIOUtil.exportTables(file);
+ TableZipCsvBackup.exportTables(file);
+
plugin.text().of(sender, "exported-database", file.toString()).send();
- } catch(SQLException | IOException e) {
+ } catch(final SQLException | IOException e) {
plugin.logger().warn("Exporting database failed.", e);
plugin.text().of(sender, "exporting-failed", e.getMessage()).send();
}
});
}
-
-}
+}
\ No newline at end of file
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Find.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Find.java
index d0942ce9b3..1d2478835e 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Find.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Find.java
@@ -8,7 +8,6 @@
import com.ghostchu.quickshop.api.shop.permission.BuiltInShopPermission;
import com.ghostchu.quickshop.util.MsgUtil;
import com.ghostchu.quickshop.util.Util;
-import io.papermc.lib.PaperLib;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.ChatColor;
@@ -120,10 +119,11 @@ public void onCommand(@NotNull final Player sender, @NotNull final String comman
//Function
if(usingOldLogic) {
+
final Map.Entry closest = sortedShops.getFirst();
final Location lookAt = closest.getKey().getLocation().clone().add(0.5, 0.5, 0.5);
- PaperLib.teleportAsync(sender, Util.lookAt(sender.getEyeLocation(), lookAt).add(0, -1.62, 0),
- PlayerTeleportEvent.TeleportCause.UNKNOWN);
+ sender.teleportAsync(Util.lookAt(sender.getEyeLocation(), lookAt).add(0, -1.62, 0), PlayerTeleportEvent.TeleportCause.UNKNOWN);
+
plugin.text().of(sender, "nearby-shop-this-way", closest.getValue().intValue()).send();
} else {
plugin.text().of(sender, "nearby-shop-header", lookFor).send();
@@ -132,10 +132,12 @@ public void onCommand(@NotNull final Player sender, @NotNull final String comman
final Shop shop = shopDoubleEntry.getKey();
final Location location = shop.getLocation();
ItemStack previewItemStack = shop.getItem().clone();
+
final ItemPreviewComponentPrePopulateEvent previewComponentPrePopulateEvent = new ItemPreviewComponentPrePopulateEvent(previewItemStack, sender);
+
previewComponentPrePopulateEvent.callEvent();
previewItemStack = previewComponentPrePopulateEvent.getItemStack();
- // "nearby-shop-entry": "&a- Info:{0} &aPrice:&b{1} &ax:&b{2} &ay:&b{3} &az:&b{4} &adistance: &b{5} &ablock(s)"
+
Component entryComponent = plugin.text().of(sender, "nearby-shop-entry",
shop.getSignText(plugin.text().findRelativeLanguages(sender)).get(1),
shop.getSignText(plugin.text().findRelativeLanguages(sender)).get(3),
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Name.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Name.java
index f8ecdf6619..8d84117d8e 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Name.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Name.java
@@ -71,7 +71,7 @@ public void onCommand(@NotNull final Player sender, @NotNull final String comman
return;
}
- final double fee = plugin.getConfig().getDouble("shop.name-fee", 0);
+ final double fee = plugin.getConfig().getDouble("shop.name-fee", 0.0);
QSEconomyTransaction transaction = null;
if(fee > 0) {
if(!plugin.perm().hasPermission(sender, "quickshop.bypass.namefee")) {
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Recovery.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Recovery.java
index 8778afc1af..0f03a5c0b0 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Recovery.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Recovery.java
@@ -5,12 +5,14 @@
import com.ghostchu.quickshop.api.command.CommandParser;
import com.ghostchu.quickshop.database.DatabaseIOUtil;
import com.ghostchu.quickshop.database.SimpleDatabaseHelperV2;
+import com.ghostchu.quickshop.database.TableZipCsvBackup;
import com.ghostchu.quickshop.util.Util;
import com.ghostchu.quickshop.util.logger.Log;
import org.bukkit.command.ConsoleCommandSender;
import org.jetbrains.annotations.NotNull;
import java.io.File;
+import java.io.IOException;
import java.sql.SQLException;
public class SubCommand_Recovery implements CommandHandler {
@@ -47,17 +49,17 @@ public void onCommand(@NotNull final ConsoleCommandSender sender, @NotNull final
Util.asyncThreadRun(()->{
try {
databaseIOUtil.performBackup("recovery");
- databaseIOUtil.importTables(file);
+ TableZipCsvBackup.importTables(file);
Log.debug("Re-loading shop from database...");
Util.mainThreadRun(()->{
plugin.getShopLoader().loadShops();
plugin.text().of(sender, "imported-database", "recovery.zip").send();
});
- } catch(SQLException | ClassNotFoundException e) {
+ } catch(final SQLException | IOException | ClassNotFoundException e) {
plugin.text().of(sender, "importing-failed", e.getMessage()).send();
plugin.logger().warn("Failed to import the database from backup file.", e);
}
});
}
-}
+}
\ No newline at end of file
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Size.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Size.java
index 3ce2313ce3..b8a4e9ef98 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Size.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/SubCommand_Size.java
@@ -37,7 +37,7 @@ public void onCommand(@NotNull final Player sender, @NotNull final String comman
final int amount;
try {
amount = Integer.parseInt(parser.getArgs().getFirst());
- } catch(NumberFormatException e) {
+ } catch(final NumberFormatException e) {
plugin.text().of(sender, "not-a-integer", parser.getArgs().getFirst()).send();
return;
}
@@ -49,6 +49,7 @@ public void onCommand(@NotNull final Player sender, @NotNull final String comman
plugin.text().of(sender, "command.invalid-bulk-amount", amount).send();
return;
}
+
if(amount > Util.getItemMaxStackSize(shop.getItem().getType()) && !plugin.getConfig().getBoolean("shop.disable-max-size-check-for-size-command", false)) {
plugin.text().of(sender, "command.invalid-bulk-amount", amount).send();
return;
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/silent/SubCommand_SilentInventory.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/silent/SubCommand_SilentInventory.java
new file mode 100644
index 0000000000..2f55eb773d
--- /dev/null
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/silent/SubCommand_SilentInventory.java
@@ -0,0 +1,53 @@
+package com.ghostchu.quickshop.command.subcommand.silent;
+
+import com.ghostchu.quickshop.QuickShop;
+import com.ghostchu.quickshop.api.command.CommandParser;
+import com.ghostchu.quickshop.api.inventory.InventoryWrapper;
+import com.ghostchu.quickshop.api.shop.Shop;
+import com.ghostchu.quickshop.api.shop.permission.BuiltInShopPermission;
+import com.ghostchu.quickshop.listener.LockListener;
+import com.ghostchu.quickshop.shop.ContainerShop;
+import com.ghostchu.quickshop.util.MsgUtil;
+import com.ghostchu.quickshop.util.logger.Log;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+
+public class SubCommand_SilentInventory extends SubCommand_SilentBase {
+
+ public SubCommand_SilentInventory(final QuickShop plugin) {
+
+ super(plugin);
+ }
+
+ @Override
+ protected void doSilentCommand(final Player sender, @NotNull final Shop shop, @NotNull final CommandParser parser) {
+
+ if(!(shop instanceof final ContainerShop cs)) {
+ plugin.text().of(sender, "not-looking-at-shop").send();
+ return;
+ }
+
+ final InventoryWrapper inventory = cs.getInventory();
+
+ if(inventory == null || inventory.getHolder() == null) {
+ Log.debug("Inventory is empty! " + cs);
+ return;
+ }
+
+ if(plugin.getConfig().getBoolean("shop.lock") && !shop.playerAuthorize(sender.getUniqueId(), BuiltInShopPermission.ACCESS_INVENTORY)) {
+ if(plugin.perm().hasPermission(sender, "quickshop.other.open")) {
+ if(LockListener.lockCoolDown.getIfPresent(sender.getUniqueId()) == null) {
+ plugin.text().of(sender, "bypassing-lock").send();
+ LockListener.lockCoolDown.put(sender.getUniqueId(), LockListener.EMPTY_OBJECT);
+ }
+ return;
+ }
+ plugin.text().of(sender, "that-is-locked").send();
+ return;
+ }
+
+ sender.openInventory(inventory.getHolder().getInventory());
+ QuickShop.inShop.add(sender.getUniqueId());
+ }
+}
\ No newline at end of file
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/silent/SubCommand_SilentSell.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/silent/SubCommand_SilentSell.java
index 51b39ae682..2761653046 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/silent/SubCommand_SilentSell.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/command/subcommand/silent/SubCommand_SilentSell.java
@@ -38,4 +38,4 @@ protected void doSilentCommand(final Player sender, @NotNull final Shop shop, @N
"command.now-selling", Util.getItemStackName(shop.getItem())).send();
}
-}
+}
\ No newline at end of file
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/config/GuiConfig.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/config/GuiConfig.java
similarity index 71%
rename from quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/config/GuiConfig.java
rename to quickshop-bukkit/src/main/java/com/ghostchu/quickshop/config/GuiConfig.java
index 6aa38d5a1f..b1687fe077 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/config/GuiConfig.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/config/GuiConfig.java
@@ -1,4 +1,4 @@
-package com.ghostchu.quickshop.menu.config;
+package com.ghostchu.quickshop.config;
/*
* QuickShop-Hikari
* Copyright (C) 2024 Daniel "creatorfromhell" Vidmar
@@ -18,20 +18,20 @@
*/
import com.ghostchu.quickshop.QuickShop;
+import com.ghostchu.quickshop.api.config.QSConfig;
import com.ghostchu.quickshop.util.logger.Log;
import com.ghostchu.simplereloadlib.ReloadResult;
import com.ghostchu.simplereloadlib.ReloadStatus;
-import com.ghostchu.simplereloadlib.Reloadable;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.file.FileConfiguration;
-import org.bukkit.configuration.file.YamlConfiguration;
+import dev.dejvokep.boostedyaml.YamlDocument;
+import dev.dejvokep.boostedyaml.block.implementation.Section;
+import dev.dejvokep.boostedyaml.dvs.versioning.BasicVersioning;
+import dev.dejvokep.boostedyaml.settings.loader.LoaderSettings;
+import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -42,32 +42,33 @@
* @author creatorfromhell
* @since 6.2.0.11
*/
-public class GuiConfig implements Reloadable {
+public class GuiConfig extends QSConfig {
private final QuickShop plugin;
- private FileConfiguration config;
+ private static GuiConfig instance;
private final Map menuConfigs = new HashMap<>();
public GuiConfig(@NotNull final QuickShop plugin) {
+
+ super("gui.yml", "gui.yml", Collections.emptyList(),
+ LoaderSettings.builder().setAutoUpdate(true).build(),
+ UpdaterSettings.builder().setAutoSave(true)
+ .setVersioning(new BasicVersioning("version")).build());
+
+ instance = this;
this.plugin = plugin;
+
loadConfig();
plugin.getReloadManager().register(this);
}
public void loadConfig() {
- Log.debug("GUI Config Loading.");
- final File configFile = new File(plugin.getDataFolder(), "gui.yml");
- if(!configFile.exists()) {
- try {
- Files.copy(plugin.getJavaPlugin().getResource("gui.yml"), configFile.toPath());
- } catch(final IOException e) {
- plugin.logger().warn("Failed to copy gui.yml to plugin folder!", e);
- }
- }
- config = YamlConfiguration.loadConfiguration(configFile);
+ Log.debug("GUI Config Loading.");
menuConfigs.clear();
+ this.load();
+
// Load menu configurations
loadMenuConfig("trade");
loadMenuConfig("keeper");
@@ -79,7 +80,8 @@ public void loadConfig() {
}
private void loadMenuConfig(final String menuName) {
- final ConfigurationSection section = config.getConfigurationSection(menuName);
+
+ final Section section = this.yaml.getSection(menuName);
if(section != null) {
menuConfigs.put(menuName, new MenuConfig(section));
}
@@ -87,39 +89,45 @@ private void loadMenuConfig(final String menuName) {
@Nullable
public MenuConfig getMenuConfig(final String menuName) {
+
return menuConfigs.get(menuName);
}
- @NotNull
- public FileConfiguration getConfig() {
- return config;
+ public static YamlDocument yaml() {
+
+ return instance.getYaml();
}
/**
* Gets a chat message from the gui.yml messages section.
*
- * @param path The path under "messages" section (e.g., "keeper.confirm-delete")
+ * @param path The path under "messages" section (e.g., "keeper.confirm-delete")
* @param defaultValue The default value if not found
+ *
* @return The message string
*/
@NotNull
public String getMessage(@NotNull final String path, @NotNull final String defaultValue) {
- return config.getString("messages." + path, defaultValue);
+
+ return yaml.getString("messages." + path, defaultValue);
}
/**
* Gets a chat message from the gui.yml messages section.
*
* @param path The path under "messages" section (e.g., "keeper.confirm-delete")
+ *
* @return The message string, or the path if not found
*/
@NotNull
public String getMessage(@NotNull final String path) {
- return config.getString("messages." + path, path);
+
+ return yaml.getString("messages." + path, path);
}
@Override
public ReloadResult reloadModule() throws Exception {
+
loadConfig();
plugin.logger().info("GUI configuration reloaded successfully. Menus loaded: " + menuConfigs.keySet());
plugin.logger().info("Note: Changes to menu row counts require a server restart to take effect.");
@@ -130,40 +138,49 @@ public ReloadResult reloadModule() throws Exception {
* Represents configuration for a single menu
*/
public static class MenuConfig {
- private final ConfigurationSection section;
+
+ private final Section section;
private final Map icons = new HashMap<>();
- public MenuConfig(final ConfigurationSection section) {
+ public MenuConfig(final Section section) {
+
this.section = section;
loadIcons();
}
private void loadIcons() {
- for(final String key : section.getKeys(false)) {
+
+ for(final Object keyObj : section.getKeys()) {
+
+ final String key = String.valueOf(keyObj);
if(key.equals("title") || key.equals("rows")) continue;
-
+
final Object value = section.get(key);
- if(value instanceof ConfigurationSection iconSection) {
+ if(value instanceof final Section iconSection) {
icons.put(key, new IconConfig(iconSection));
}
}
}
public String getTitle() {
+
return section.getString("title", "Menu");
}
public int getRows() {
+
return section.getInt("rows", 6);
}
@Nullable
public IconConfig getIcon(final String iconName) {
+
return icons.get(iconName);
}
@NotNull
- public ConfigurationSection getSection() {
+ public Section getSection() {
+
return section;
}
}
@@ -171,29 +188,27 @@ public ConfigurationSection getSection() {
/**
* Represents configuration for a single icon/button
*/
- public static class IconConfig {
- private final ConfigurationSection section;
-
- public IconConfig(final ConfigurationSection section) {
- this.section = section;
- }
+ public record IconConfig(Section section) {
@NotNull
public String getMaterial() {
+
return section.getString("material", "STONE");
}
@Nullable
public String getName() {
+
return section.getString("name");
}
@NotNull
public List getLore() {
+
final Object loreObj = section.get("lore");
if(loreObj instanceof List>) {
final List result = new ArrayList<>();
- for(final Object item : (List>) loreObj) {
+ for(final Object item : (List>)loreObj) {
if(item != null) {
result.add(item.toString());
}
@@ -201,52 +216,62 @@ public List getLore() {
return result;
} else if(loreObj instanceof String) {
final List result = new ArrayList<>();
- result.add((String) loreObj);
+ result.add((String)loreObj);
return result;
}
return new ArrayList<>();
}
public int getCustomModelData() {
+
return section.getInt("custom-model-data", 0);
}
public int getSlot() {
+
return section.getInt("slot", 0);
}
public int getAmount() {
+
return section.getInt("amount", 1);
}
@NotNull
public List getSlots() {
- return section.getIntegerList("slots");
+
+ return section.getIntList("slots");
}
@NotNull
public List getQuantities() {
- return section.getIntegerList("quantities");
+
+ return section.getIntList("quantities");
}
@NotNull
public List getRows() {
- return section.getIntegerList("rows");
+
+ return section.getIntList("rows");
}
public boolean hasCustomModelData() {
+
return section.contains("custom-model-data") && getCustomModelData() != 0;
}
+ @Override
@Nullable
- public ConfigurationSection getSection() {
+ public Section section() {
+
return section;
}
@Nullable
public IconConfig getSubIcon(final String name) {
- final ConfigurationSection sub = section.getConfigurationSection(name);
- return sub != null?new IconConfig(sub) : null;
+
+ final Section sub = section.getSection(name);
+ return sub != null? new IconConfig(sub) : null;
}
}
}
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/config/GuiIconBuilder.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/config/GuiIconBuilder.java
similarity index 85%
rename from quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/config/GuiIconBuilder.java
rename to quickshop-bukkit/src/main/java/com/ghostchu/quickshop/config/GuiIconBuilder.java
index 1418115e7b..8123515450 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/config/GuiIconBuilder.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/config/GuiIconBuilder.java
@@ -1,4 +1,4 @@
-package com.ghostchu.quickshop.menu.config;
+package com.ghostchu.quickshop.config;
/*
* QuickShop-Hikari
* Copyright (C) 2024 Daniel "creatorfromhell" Vidmar
@@ -40,10 +40,12 @@ public class GuiIconBuilder {
* Creates an AbstractItemStack from IconConfig
*
* @param config The icon configuration
+ *
* @return The configured AbstractItemStack
*/
@NotNull
public static AbstractItemStack> createStack(@NotNull final GuiConfig.IconConfig config) {
+
AbstractItemStack> stack = QuickShop.getInstance().stack()
.of(config.getMaterial(), config.getAmount());
@@ -77,10 +79,12 @@ public static AbstractItemStack> createStack(@NotNull final GuiConfig.IconConf
* Creates an IconBuilder from IconConfig with slot
*
* @param config The icon configuration
+ *
* @return The configured IconBuilder
*/
@NotNull
public static IconBuilder createIconBuilder(@NotNull final GuiConfig.IconConfig config) {
+
return new IconBuilder(createStack(config))
.withSlot(config.getSlot());
}
@@ -90,11 +94,13 @@ public static IconBuilder createIconBuilder(@NotNull final GuiConfig.IconConfig
*
* @param config The icon configuration
* @param slot The slot to use
+ *
* @return The configured IconBuilder
*/
@NotNull
public static IconBuilder createIconBuilder(@NotNull final GuiConfig.IconConfig config,
- final int slot) {
+ final int slot) {
+
return new IconBuilder(createStack(config))
.withSlot(slot);
}
@@ -102,18 +108,20 @@ public static IconBuilder createIconBuilder(@NotNull final GuiConfig.IconConfig
/**
* Creates an IconBuilder with custom display name and lore
*
- * @param config The icon configuration (for material and custom model data)
- * @param slot The slot to use
- * @param name The display name component
- * @param lore The lore components
+ * @param config The icon configuration (for material and custom model data)
+ * @param slot The slot to use
+ * @param name The display name component
+ * @param lore The lore components
+ *
* @return The configured IconBuilder
*/
@NotNull
public static IconBuilder createIconBuilder(@NotNull final GuiConfig.IconConfig config,
- final int slot,
- @NotNull final Component name,
- @NotNull final List lore) {
- AbstractItemStack> stack = QuickShop.getInstance().stack()
+ final int slot,
+ @NotNull final Component name,
+ @NotNull final List lore) {
+
+ final AbstractItemStack> stack = QuickShop.getInstance().stack()
.of(config.getMaterial(), config.getAmount())
.display(name)
.lore(lore);
@@ -127,13 +135,15 @@ public static IconBuilder createIconBuilder(@NotNull final GuiConfig.IconConfig
* @param config The icon configuration
* @param slot The slot to use
* @param name The display name component
+ *
* @return The configured IconBuilder
*/
@NotNull
public static IconBuilder createIconBuilder(@NotNull final GuiConfig.IconConfig config,
- final int slot,
- @NotNull final Component name) {
- AbstractItemStack> stack = QuickShop.getInstance().stack()
+ final int slot,
+ @NotNull final Component name) {
+
+ final AbstractItemStack> stack = QuickShop.getInstance().stack()
.of(config.getMaterial(), config.getAmount())
.display(name);
@@ -144,10 +154,12 @@ public static IconBuilder createIconBuilder(@NotNull final GuiConfig.IconConfig
* Creates a border IconBuilder
*
* @param config The border icon configuration
+ *
* @return The configured IconBuilder for borders
*/
@NotNull
public static IconBuilder createBorderBuilder(@NotNull final GuiConfig.IconConfig config) {
+
AbstractItemStack> stack = QuickShop.getInstance().stack()
.of(config.getMaterial(), 1);
@@ -166,11 +178,13 @@ public static IconBuilder createBorderBuilder(@NotNull final GuiConfig.IconConfi
*
* @param item The ItemStack to modify
* @param config The icon configuration
+ *
* @return The modified ItemStack
*/
@NotNull
public static ItemStack applyCustomModelData(@NotNull final ItemStack item,
- @NotNull final GuiConfig.IconConfig config) {
+ @NotNull final GuiConfig.IconConfig config) {
+
if(config.hasCustomModelData()) {
final ItemMeta meta = item.getItemMeta();
if(meta != null) {
@@ -185,10 +199,12 @@ public static ItemStack applyCustomModelData(@NotNull final ItemStack item,
* Parses a string as MiniMessage format directly.
*
* @param text The MiniMessage formatted text (e.g., "Buy Items")
+ *
* @return The parsed Component
*/
@NotNull
private static Component parseMiniMessage(@NotNull final String text) {
+
return QuickShop.getInstance().platform().miniMessage().deserialize(text);
}
}
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/config/InteractionConfig.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/config/InteractionConfig.java
new file mode 100644
index 0000000000..5229444e36
--- /dev/null
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/config/InteractionConfig.java
@@ -0,0 +1,53 @@
+package com.ghostchu.quickshop.config;
+
+
+/*
+ * QuickShop-Hikari
+ * Copyright (C) 2025 Daniel "creatorfromhell" Vidmar
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import com.ghostchu.quickshop.api.config.QSConfig;
+import dev.dejvokep.boostedyaml.YamlDocument;
+import dev.dejvokep.boostedyaml.dvs.versioning.BasicVersioning;
+import dev.dejvokep.boostedyaml.settings.loader.LoaderSettings;
+import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings;
+
+import java.util.Collections;
+
+/**
+ * InteractionConfig
+ *
+ * @author creatorfromhell
+ * @since 6.2.0.11
+ */
+public class InteractionConfig extends QSConfig {
+
+ private static InteractionConfig instance;
+
+ public InteractionConfig() {
+
+ super("interaction.yml", "interaction.yml", Collections.emptyList(),
+ LoaderSettings.builder().setAutoUpdate(true).build(),
+ UpdaterSettings.builder().setAutoSave(true).setVersioning(new BasicVersioning("version")).build());
+
+ instance = this;
+ }
+
+ public static YamlDocument yaml() {
+
+ return instance.getYaml();
+ }
+}
\ No newline at end of file
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/config/MainConfig.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/config/MainConfig.java
new file mode 100644
index 0000000000..80132149fe
--- /dev/null
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/config/MainConfig.java
@@ -0,0 +1,58 @@
+package com.ghostchu.quickshop.config;
+
+/*
+ * QuickShop-Hikari
+ * Copyright (C) 2025 Daniel "creatorfromhell" Vidmar
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import com.ghostchu.quickshop.QuickShop;
+import com.ghostchu.quickshop.api.config.QSConfig;
+import dev.dejvokep.boostedyaml.YamlDocument;
+import dev.dejvokep.boostedyaml.dvs.versioning.BasicVersioning;
+import dev.dejvokep.boostedyaml.settings.loader.LoaderSettings;
+import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings;
+
+import java.util.Collections;
+
+/**
+ * MainConfig
+ *
+ * @author creatorfromhell
+ * @since 6.2.0.11
+ */
+public class MainConfig extends QSConfig {
+
+ private static MainConfig instance;
+
+ public MainConfig(final QuickShop plugin) {
+
+ super("config.yml", "config.yml", Collections.emptyList(),
+ LoaderSettings.builder().setAutoUpdate(true).build(),
+ UpdaterSettings.builder().setAutoSave(true)
+ .setVersioning(new BasicVersioning("config-version"))
+ .addIgnoredRoute("1032", "limits.ranks", '.')
+ .addIgnoredRoute("1033", "limits.ranks", '.')
+ .addIgnoredRoute("1034", "limits.ranks", '.').build());
+
+ instance = this;
+ plugin.getReloadManager().register(this);
+ }
+
+ public static YamlDocument yaml() {
+
+ return instance.getYaml();
+ }
+}
\ No newline at end of file
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/DataTables.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/DataTables.java
index 1e584e766f..0f2aa99d41 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/DataTables.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/DataTables.java
@@ -218,6 +218,10 @@ private void create(@NotNull final SQLManager sqlManager, @NotNull final String
return this.prefix + this.name;
}
+ @NotNull String logicalName() {
+ return this.name;
+ }
+
public @NotNull DeleteBuilder createDelete() {
return this.createDelete(this.manager);
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/DatabaseIOUtil.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/DatabaseIOUtil.java
index a985b4a636..775c6588c4 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/DatabaseIOUtil.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/DatabaseIOUtil.java
@@ -60,11 +60,11 @@ public boolean performBackup(final String reason) {
try {
exportTables(backupFile);
return true;
- } catch(SQLException | IOException e) {
+ } catch(final SQLException | IOException e) {
QuickShop.getInstance().logger().warn("[DB Backup] Failed to create backup", e);
return false;
}
- } catch(Throwable throwable) {
+ } catch(final Throwable throwable) {
QuickShop.getInstance().logger().warn("[DB Backup] Unexpected error", throwable);
return false;
}
@@ -73,12 +73,12 @@ public boolean performBackup(final String reason) {
public void exportTables(@NotNull final File zipFile) throws SQLException, IOException {
// zipFile.getParentFile().mkdirs();
zipFile.createNewFile();
- try(ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile))) {
+ try(final ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile))) {
for(final DataTables table : DataTables.values()) {
Log.debug("Exporting table " + table.name());
final File tableCsv = new File(Util.getCacheFolder(), table.getName() + ".csv");
tableCsv.deleteOnExit();
- try(SQLQuery query = table.createQuery().build().execute()) {
+ try(final SQLQuery query = table.createQuery().build().execute()) {
final ResultSet result = query.getResultSet();
writeToCSV(result, tableCsv);
Log.debug("Exported table " + table.name() + " to " + tableCsv.getAbsolutePath());
@@ -107,10 +107,11 @@ public void importFromCSV(@NotNull final File zipFile, @NotNull final DataTables
Log.debug("Loading CsvDriver...");
Class.forName("org.relique.jdbc.csv.CsvDriver");
- try(Connection conn = DriverManager.getConnection("jdbc:relique:csv:zip:" + zipFile);
- Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
- ResultSet.CONCUR_READ_ONLY);
- ResultSet results = stmt.executeQuery("SELECT * FROM " + table.getName())) {
+ try(final Connection conn = DriverManager.getConnection("jdbc:relique:csv:zip:" + zipFile);
+ final Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
+ ResultSet.CONCUR_READ_ONLY);
+ final ResultSet results = stmt.executeQuery("SELECT * FROM " + table.logicalName())) {
+
final ResultSetMetaData metaData = results.getMetaData();
final String[] columns = new String[metaData.getColumnCount()];
for(int i = 0; i < columns.length; i++) {
@@ -121,6 +122,8 @@ public void importFromCSV(@NotNull final File zipFile, @NotNull final DataTables
final Object[] values = new String[columns.length];
for(int i = 0; i < values.length; i++) {
Log.debug("Copying column: " + columns[i]);
+
+
values[i] = results.getObject(columns[i]);
}
Log.debug("Inserting row: " + CommonUtil.array2String(Arrays.stream(values).map(Object::toString).toArray(String[]::new)));
@@ -140,7 +143,7 @@ public void writeToCSV(@NotNull final ResultSet set, @NotNull final File csvFile
if(!csvFile.exists()) {
csvFile.createNewFile();
}
- try(PrintStream stream = new PrintStream(csvFile)) {
+ try(final PrintStream stream = new PrintStream(csvFile)) {
Log.debug("Writing to CSV file: " + csvFile.getAbsolutePath());
CsvDriver.writeToCsv(set, stream, true);
}
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/HikariUtil.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/HikariUtil.java
index 5dddc7a700..7a822da77e 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/HikariUtil.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/HikariUtil.java
@@ -2,7 +2,7 @@
import com.ghostchu.quickshop.QuickShop;
import com.ghostchu.quickshop.util.logger.Log;
-import org.bukkit.configuration.ConfigurationSection;
+import dev.dejvokep.boostedyaml.block.implementation.Section;
public class HikariUtil {
@@ -13,15 +13,17 @@ private HikariUtil() {
public static cc.carm.lib.easysql.hikari.HikariConfig createHikariConfig() {
final cc.carm.lib.easysql.hikari.HikariConfig config = new cc.carm.lib.easysql.hikari.HikariConfig();
- ConfigurationSection section = QuickShop.getInstance().getConfig().getConfigurationSection("database");
+ Section section = QuickShop.getInstance().getConfig().getSection("database");
if(section == null) {
throw new IllegalArgumentException("database section in configuration not found");
}
- section = section.getConfigurationSection("properties");
+ section = section.getSection("properties");
if(section == null) {
throw new IllegalArgumentException("database.properties section in configuration not found");
}
- for(final String key : section.getKeys(false)) {
+ for(final Object keyObj : section.getKeys()) {
+
+ final String key = String.valueOf(keyObj);
config.addDataSourceProperty(key, String.valueOf(section.get(key)));
}
Log.debug("HikariCP Config created with properties: " + config.getDataSourceProperties());
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/TableZipCsvBackup.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/TableZipCsvBackup.java
new file mode 100644
index 0000000000..541e16a562
--- /dev/null
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/TableZipCsvBackup.java
@@ -0,0 +1,309 @@
+package com.ghostchu.quickshop.database;
+
+import cc.carm.lib.easysql.api.SQLQuery;
+import com.ghostchu.quickshop.common.util.CommonUtil;
+import com.ghostchu.quickshop.util.Util;
+import com.ghostchu.quickshop.util.logger.Log;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import org.jetbrains.annotations.NotNull;
+import org.relique.jdbc.csv.CsvDriver;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+/*
+ * QuickShop-Hikari
+ * Copyright (C) 2025 Daniel "creatorfromhell" Vidmar
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+/**
+ * TableZipCsvBackup
+ *
+ * @author creatorfromhell
+ * @since 6.2.0.11
+ */
+public final class TableZipCsvBackup {
+
+ private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
+
+ private static TableSchema readSchemaFromZip(@NotNull final File zipFile, @NotNull final String tableName)
+ throws IOException {
+
+ final String entryName = tableName + ".schema.json";
+ try(final ZipFile zf = new ZipFile(zipFile)) {
+ final ZipEntry entry = zf.getEntry(entryName);
+ if(entry == null) return null;
+
+ try(final InputStream in = zf.getInputStream(entry);
+ final InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8)) {
+ return GSON.fromJson(reader, TableSchema.class);
+ }
+ }
+ }
+
+ private static Object convertCsvString(final String raw, final ColumnSchema col) throws SQLException {
+
+ if(raw == null) return null;
+ final String s = raw.trim();
+ if(s.isEmpty()) return null;
+
+ try {
+ switch(col.sqlType) {
+ case Types.TINYINT:
+ case Types.SMALLINT:
+ case Types.INTEGER:
+ return Integer.valueOf(s);
+
+ case Types.BIGINT:
+ return Long.valueOf(s);
+
+ case Types.FLOAT:
+ case Types.REAL:
+ case Types.DOUBLE:
+ return Double.valueOf(s);
+
+ case Types.DECIMAL:
+ case Types.NUMERIC:
+ return new BigDecimal(s);
+
+ case Types.BIT:
+ case Types.BOOLEAN:
+ if(s.equalsIgnoreCase("true") || s.equalsIgnoreCase("yes")) return true;
+ if(s.equalsIgnoreCase("false") || s.equalsIgnoreCase("no")) return false;
+ if(s.equals("1")) return true;
+ if(s.equals("0")) return false;
+ return Boolean.valueOf(s);
+
+ case Types.DATE:
+ return Date.valueOf(s);
+
+ case Types.TIME:
+ return Time.valueOf(s);
+
+ case Types.TIMESTAMP:
+ case Types.TIMESTAMP_WITH_TIMEZONE:
+ return parseTimestampFlexible(s);
+
+ case Types.CHAR:
+ case Types.VARCHAR:
+ case Types.LONGVARCHAR:
+ case Types.NCHAR:
+ case Types.NVARCHAR:
+ case Types.LONGNVARCHAR:
+ default:
+ return s;
+ }
+ } catch(final Exception ex) {
+
+ throw new SQLException("Failed to convert CSV value '" + s + "' for column '" + col.name
+ + "' (sqlType=" + col.sqlType + ", typeName=" + col.typeName + ")", ex);
+ }
+ }
+
+ private static Timestamp parseTimestampFlexible(final String s) {
+ try {
+ final Instant inst = Instant.parse(s);
+ return Timestamp.from(inst);
+ } catch(final Exception ignored) { }
+
+ try {
+ final OffsetDateTime odt = OffsetDateTime.parse(s);
+ return Timestamp.from(odt.toInstant());
+ } catch(final Exception ignored) { }
+
+ try {
+ final LocalDateTime ldt = LocalDateTime.parse(s);
+ return Timestamp.valueOf(ldt);
+ } catch(final Exception ignored) { }
+
+ return Timestamp.valueOf(s);
+ }
+
+ public static void exportTables(@NotNull final File zipFile) throws SQLException, IOException {
+
+ zipFile.getParentFile().mkdirs();
+ if(!zipFile.exists()) zipFile.createNewFile();
+
+ try(final ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile))) {
+ for(final DataTables table : DataTables.values()) {
+ Log.debug("Exporting table " + table.name());
+
+ final File tableCsv = new File(Util.getCacheFolder(), table.getName() + ".csv");
+ tableCsv.getParentFile().mkdirs();
+ if(tableCsv.exists()) tableCsv.delete();
+ tableCsv.deleteOnExit();
+
+ final TableSchema schema;
+ try(final SQLQuery query = table.createQuery().build().execute()) {
+ final ResultSet rs = query.getResultSet();
+
+ writeToCSV(rs, tableCsv);
+
+ schema = TableSchema.from(table.getName(), rs.getMetaData());
+
+ Log.debug("Exported table " + table.name() + " to " + tableCsv.getAbsolutePath());
+ }
+
+ Log.debug("Adding CSV for " + table.name() + " to zip file");
+ out.putNextEntry(new ZipEntry(table.getName() + ".csv"));
+ Files.copy(tableCsv.toPath(), out);
+ out.closeEntry();
+
+ Log.debug("Adding schema for " + table.name() + " to zip file");
+ out.putNextEntry(new ZipEntry(table.getName() + ".schema.json"));
+ final byte[] schemaBytes = GSON.toJson(schema).getBytes(StandardCharsets.UTF_8);
+ out.write(schemaBytes);
+ out.closeEntry();
+
+ Log.debug("Added table " + table.name() + " to zip file");
+ }
+ }
+ }
+
+ public static void importTables(@NotNull final File zipFile) throws SQLException, ClassNotFoundException, IOException {
+
+ for(final DataTables table : DataTables.values()) {
+ Log.debug("Purging table " + table.getName());
+ table.purgeTable();
+
+ Log.debug("Importing table " + table.getName() + " from " + zipFile.getAbsolutePath());
+ importFromCSV(zipFile, table);
+ Log.debug("Imported table " + table.getName() + " from " + zipFile.getAbsolutePath());
+ }
+ }
+
+ public static void importFromCSV(@NotNull final File zipFile, @NotNull final DataTables table)
+ throws SQLException, ClassNotFoundException, IOException {
+
+ final TableSchema schema = readSchemaFromZip(zipFile, table.getName());
+ if(schema == null) {
+ throw new IllegalStateException("Missing schema sidecar for table " + table.getName()
+ + " (expected " + table.getName() + ".schema.json in zip)");
+ }
+
+ Log.debug("Loading CsvDriver...");
+ Class.forName("org.relique.jdbc.csv.CsvDriver");
+
+ final String csvTableName = table.getName();
+
+ try(final Connection conn = DriverManager.getConnection("jdbc:relique:csv:zip:" + zipFile);
+ final Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
+ final ResultSet results = stmt.executeQuery("SELECT * FROM " + csvTableName)) {
+
+ final String[] columnNames = schema.columnNames();
+ Log.debug("Schema columns (" + columnNames.length + "): " + CommonUtil.array2String(columnNames));
+
+ while(results.next()) {
+ final Object[] values = new Object[columnNames.length];
+
+ for(int i = 0; i < columnNames.length; i++) {
+ final ColumnSchema col = schema.columns.get(i);
+
+ final String raw = results.getString(col.name);
+ values[i] = convertCsvString(raw, col);
+ }
+
+ Log.debug("Inserting row: " + CommonUtil.array2String(
+ Arrays.stream(values).map(v->v == null? "null" : String.valueOf(v)).toArray(String[]::new)
+ ));
+
+ table.createInsert()
+ .setColumnNames(columnNames)
+ .setParams(values)
+ .execute();
+ }
+ }
+ }
+
+ public static void writeToCSV(@NotNull final ResultSet set, @NotNull final File csvFile) throws SQLException, IOException {
+
+ if(!csvFile.getParentFile().exists()) csvFile.getParentFile().mkdirs();
+ if(!csvFile.exists()) csvFile.createNewFile();
+
+ try(final PrintStream stream = new PrintStream(csvFile)) {
+ Log.debug("Writing to CSV file: " + csvFile.getAbsolutePath());
+ CsvDriver.writeToCsv(set, stream, true);
+ }
+ }
+
+ public static final class TableSchema {
+
+ public String table;
+ public List columns = new ArrayList<>();
+
+ public static TableSchema from(final String tableName, final ResultSetMetaData md) throws SQLException {
+
+ final TableSchema schema = new TableSchema();
+ schema.table = tableName;
+
+ for(int i = 1; i <= md.getColumnCount(); i++) {
+ final ColumnSchema col = new ColumnSchema();
+ col.name = md.getColumnLabel(i); // label respects aliases; use getColumnName if you prefer
+ col.sqlType = md.getColumnType(i);
+ col.typeName = md.getColumnTypeName(i);
+ col.nullable = (md.isNullable(i) != ResultSetMetaData.columnNoNulls);
+ col.precision = md.getPrecision(i);
+ col.scale = md.getScale(i);
+ schema.columns.add(col);
+ }
+ return schema;
+ }
+
+ public String[] columnNames() {
+
+ final String[] arr = new String[columns.size()];
+ for(int i = 0; i < columns.size(); i++) arr[i] = columns.get(i).name;
+ return arr;
+ }
+ }
+
+ public static final class ColumnSchema {
+
+ public String name;
+ public int sqlType;
+ public String typeName;
+ public boolean nullable;
+ public int precision;
+ public int scale;
+ }
+}
\ No newline at end of file
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/localization/text/SimpleTextManager.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/localization/text/SimpleTextManager.java
index fb58a62600..797393291b 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/localization/text/SimpleTextManager.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/localization/text/SimpleTextManager.java
@@ -739,7 +739,7 @@ public List getAvailableLanguages() {
}
@Override
- public com.ghostchu.quickshop.api.localization.text.@NotNull TextList ofList(@Nullable final QUser sender, @NotNull final String path, @Nullable final Object... args) {
+ public @NotNull com.ghostchu.quickshop.api.localization.text.TextList ofList(@Nullable final QUser sender, @NotNull final String path, @Nullable final Object... args) {
return new TextList(this, sender, languageFilesManager.getDistributions(), path, tagResolvers, convert(args));
}
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopBrowseMenu.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopBrowseMenu.java
index 2ff9179b17..21580cd7a4 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopBrowseMenu.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopBrowseMenu.java
@@ -18,9 +18,9 @@
*/
import com.ghostchu.quickshop.QuickShop;
+import com.ghostchu.quickshop.config.GuiConfig;
import com.ghostchu.quickshop.menu.browse.GroupedItemPage;
import com.ghostchu.quickshop.menu.browse.ShopListPage;
-import com.ghostchu.quickshop.menu.config.GuiConfig;
import net.tnemc.menu.core.Menu;
import net.tnemc.menu.core.Page;
@@ -40,7 +40,7 @@ public class ShopBrowseMenu extends Menu {
public static final String BROWSE_SEARCH = "BROWSE_SEARCH";
public static final String BROWSE_STOCK_ONLY = "BROWSE_STOCK_ONLY";
public static final String BROWSE_WORLD_ONLY = "BROWSE_WORLD_ONLY";
-
+
// Data keys for shop list page (when viewing shops for a specific item)
public static final String SELECTED_ITEM_SHOPS = "SELECTED_ITEM_SHOPS";
public static final String SHOP_LIST_PAGE = "SHOP_LIST_PAGE";
@@ -49,7 +49,7 @@ public ShopBrowseMenu() {
// Load rows from GUI config
final GuiConfig.MenuConfig menuConfig = QuickShop.getInstance().getGuiConfig().getMenuConfig("browse");
- this.rows = (menuConfig != null?menuConfig.getRows() : 6);
+ this.rows = (menuConfig != null? menuConfig.getRows() : 6);
this.name = "qs:browse";
setOpen((open)->open.getMenu().setTitle(QuickShop.getInstance().text().of(open.getPlayer().identifier(), "gui.browse.title").legacy()));
@@ -59,7 +59,7 @@ public ShopBrowseMenu() {
final GroupedItemPage groupedPageHandler = new GroupedItemPage(this.name, this.rows);
groupedPage.setOpen(groupedPageHandler::handle);
addPage(groupedPage);
-
+
// Page 2: Shop list view (all shops for a specific item)
final Page shopListPage = new Page(2);
final ShopListPage shopListPageHandler = new ShopListPage(this.name, this.rows);
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopHistoryMenu.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopHistoryMenu.java
index b4e81c1576..59dd7ec036 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopHistoryMenu.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopHistoryMenu.java
@@ -18,7 +18,7 @@
*/
import com.ghostchu.quickshop.QuickShop;
-import com.ghostchu.quickshop.menu.config.GuiConfig;
+import com.ghostchu.quickshop.config.GuiConfig;
import com.ghostchu.quickshop.menu.history.MainPage;
import net.tnemc.menu.core.Menu;
import net.tnemc.menu.core.Page;
@@ -40,7 +40,7 @@ public ShopHistoryMenu() {
// Load rows from GUI config
final GuiConfig.MenuConfig menuConfig = QuickShop.getInstance().getGuiConfig().getMenuConfig("history");
- this.rows = (menuConfig != null?menuConfig.getRows() : 6);
+ this.rows = (menuConfig != null? menuConfig.getRows() : 6);
this.name = "qs:history";
setOpen((open)->open.getMenu().setTitle(QuickShop.getInstance().text().of(open.getPlayer().identifier(), "history.shop.gui-title").legacy()));
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopKeeperMenu.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopKeeperMenu.java
index 4f9888af25..adb5d97ae5 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopKeeperMenu.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopKeeperMenu.java
@@ -18,7 +18,7 @@
*/
import com.ghostchu.quickshop.QuickShop;
-import com.ghostchu.quickshop.menu.config.GuiConfig;
+import com.ghostchu.quickshop.config.GuiConfig;
import com.ghostchu.quickshop.menu.keeper.MainPage;
import com.ghostchu.quickshop.menu.shared.QuickShopMenu;
@@ -38,7 +38,7 @@ public ShopKeeperMenu() {
// Load rows from config or use default (4 rows for modern layout)
final GuiConfig.MenuConfig menuConfig = QuickShop.getInstance().getGuiConfig().getMenuConfig("keeper");
- this.rows = (menuConfig != null?menuConfig.getRows() : 4);
+ this.rows = (menuConfig != null? menuConfig.getRows() : 4);
this.name = "qs:keeper";
setOpen((open)->open.getMenu().setTitle(legacy(open.getPlayer().identifier(), "gui.keeper.title")));
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopStaffMenu.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopStaffMenu.java
index 77f554fe1f..a4f21947e7 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopStaffMenu.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopStaffMenu.java
@@ -18,7 +18,7 @@
*/
import com.ghostchu.quickshop.QuickShop;
-import com.ghostchu.quickshop.menu.config.GuiConfig;
+import com.ghostchu.quickshop.config.GuiConfig;
import com.ghostchu.quickshop.menu.shared.QuickShopMenu;
import com.ghostchu.quickshop.menu.staff.PlayerSelectionPage;
import com.ghostchu.quickshop.menu.staff.StaffSelectionPage;
@@ -47,7 +47,7 @@ public ShopStaffMenu() {
// Load rows from config or use default (6 rows for modern layout)
final GuiConfig.MenuConfig menuConfig = QuickShop.getInstance().getGuiConfig().getMenuConfig("staff");
- this.rows = (menuConfig != null?menuConfig.getRows() : 6);
+ this.rows = (menuConfig != null? menuConfig.getRows() : 6);
this.name = "qs:staff";
this.title = "Shop Staff";
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopTradeMenu.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopTradeMenu.java
index ee42eada10..09637a3e2a 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopTradeMenu.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/ShopTradeMenu.java
@@ -18,7 +18,7 @@
*/
import com.ghostchu.quickshop.QuickShop;
-import com.ghostchu.quickshop.menu.config.GuiConfig;
+import com.ghostchu.quickshop.config.GuiConfig;
import com.ghostchu.quickshop.menu.shared.QuickShopMenu;
import com.ghostchu.quickshop.menu.trade.MainPage;
@@ -34,7 +34,7 @@ public ShopTradeMenu() {
// Load rows from config or use default (6 rows for modern layout)
final GuiConfig.MenuConfig menuConfig = QuickShop.getInstance().getGuiConfig().getMenuConfig("trade");
- this.rows = (menuConfig != null?menuConfig.getRows() : 6);
+ this.rows = (menuConfig != null? menuConfig.getRows() : 6);
this.name = "qs:trade";
setOpen((open)->open.getMenu().setTitle(legacy(open.getPlayer().identifier(), "gui.trade.title")));
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/browse/BrowseFilterMode.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/browse/BrowseFilterMode.java
index fff77d6bee..d734961de4 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/browse/BrowseFilterMode.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/browse/BrowseFilterMode.java
@@ -24,58 +24,66 @@
* @since 6.2.0.8
*/
public enum BrowseFilterMode {
-
+
/**
* Show all shops
*/
ALL("all", "gui.browse.filter.all"),
-
+
/**
* Show only buying shops (shops that buy from players)
*/
BUYING("buying", "gui.browse.filter.buying"),
-
+
/**
* Show only selling shops (shops that sell to players)
*/
SELLING("selling", "gui.browse.filter.selling");
-
+
private final String id;
private final String translationKey;
-
+
BrowseFilterMode(final String id, final String translationKey) {
+
this.id = id;
this.translationKey = translationKey;
}
-
+
+ /**
+ * Get filter mode from id string
+ *
+ * @param id The id string
+ *
+ * @return The filter mode, or ALL if not found
+ */
+ public static BrowseFilterMode fromId(final String id) {
+
+ for(final BrowseFilterMode mode : values()) {
+ if(mode.getId().equalsIgnoreCase(id)) {
+ return mode;
+ }
+ }
+ return ALL;
+ }
+
public String getId() {
+
return id;
}
-
+
public String getTranslationKey() {
+
return translationKey;
}
-
+
/**
* Get the next filter mode in the cycle
+ *
* @return The next filter mode
*/
public BrowseFilterMode next() {
+
final BrowseFilterMode[] values = values();
return values[(this.ordinal() + 1) % values.length];
}
-
- /**
- * Get filter mode from id string
- * @param id The id string
- * @return The filter mode, or ALL if not found
- */
- public static BrowseFilterMode fromId(final String id) {
- for(final BrowseFilterMode mode : values()) {
- if(mode.getId().equalsIgnoreCase(id)) {
- return mode;
- }
- }
- return ALL;
- }
}
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/browse/BrowseSortMode.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/browse/BrowseSortMode.java
index 448843172e..5eb638d4b2 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/browse/BrowseSortMode.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/browse/BrowseSortMode.java
@@ -24,63 +24,71 @@
* @since 6.2.0.8
*/
public enum BrowseSortMode {
-
+
/**
* Sort by price, lowest first
*/
PRICE_ASC("price-low-high", "gui.browse.sort.price-asc"),
-
+
/**
* Sort by price, highest first
*/
PRICE_DESC("price-high-low", "gui.browse.sort.price-desc"),
-
+
/**
* Sort by stock amount, highest first
*/
STOCK("stock", "gui.browse.sort.stock"),
-
+
/**
* Sort by item name alphabetically
*/
NAME("name", "gui.browse.sort.name");
-
+
private final String id;
private final String translationKey;
-
+
BrowseSortMode(final String id, final String translationKey) {
+
this.id = id;
this.translationKey = translationKey;
}
-
+
+ /**
+ * Get sort mode from id string
+ *
+ * @param id The id string
+ *
+ * @return The sort mode, or PRICE_ASC if not found
+ */
+ public static BrowseSortMode fromId(final String id) {
+
+ for(final BrowseSortMode mode : values()) {
+ if(mode.getId().equalsIgnoreCase(id)) {
+ return mode;
+ }
+ }
+ return PRICE_ASC;
+ }
+
public String getId() {
+
return id;
}
-
+
public String getTranslationKey() {
+
return translationKey;
}
-
+
/**
* Get the next sort mode in the cycle
+ *
* @return The next sort mode
*/
public BrowseSortMode next() {
+
final BrowseSortMode[] values = values();
return values[(this.ordinal() + 1) % values.length];
}
-
- /**
- * Get sort mode from id string
- * @param id The id string
- * @return The sort mode, or PRICE_ASC if not found
- */
- public static BrowseSortMode fromId(final String id) {
- for(final BrowseSortMode mode : values()) {
- if(mode.getId().equalsIgnoreCase(id)) {
- return mode;
- }
- }
- return PRICE_ASC;
- }
}
diff --git a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/browse/GroupedItemPage.java b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/browse/GroupedItemPage.java
index be14a09abb..1add06dff0 100644
--- a/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/browse/GroupedItemPage.java
+++ b/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/menu/browse/GroupedItemPage.java
@@ -20,10 +20,9 @@
import com.ghostchu.quickshop.QuickShop;
import com.ghostchu.quickshop.api.shop.Shop;
import com.ghostchu.quickshop.common.util.CommonUtil;
-import com.ghostchu.quickshop.menu.config.GuiConfig;
+import com.ghostchu.quickshop.config.GuiConfig;
import com.ghostchu.quickshop.menu.shared.ClearSearchAction;
import com.ghostchu.quickshop.menu.shared.GuiChatAction;
-import net.tnemc.menu.core.icon.action.ActionType;
import net.kyori.adventure.text.Component;
import net.tnemc.item.AbstractItemStack;
import net.tnemc.item.bukkit.BukkitItemStack;
@@ -31,6 +30,7 @@
import net.tnemc.menu.core.builder.IconBuilder;
import net.tnemc.menu.core.callbacks.page.PageOpenCallback;
import net.tnemc.menu.core.compatibility.MenuPlayer;
+import net.tnemc.menu.core.icon.action.ActionType;
import net.tnemc.menu.core.icon.action.impl.DataAction;
import net.tnemc.menu.core.icon.action.impl.RunnableAction;
import net.tnemc.menu.core.icon.action.impl.SwitchPageAction;
@@ -59,8 +59,8 @@
import static com.ghostchu.quickshop.menu.shared.QuickShopPage.guiMessage;
/**
- * GroupedItemPage - Market overview page showing items grouped by type
- * with price statistics and the ability to drill down into specific items
+ * GroupedItemPage - Market overview page showing items grouped by type with price statistics and
+ * the ability to drill down into specific items
*
* @author creatorfromhell
* @since 6.2.0.8
@@ -71,48 +71,49 @@ public class GroupedItemPage {
private final int menuRows;
public GroupedItemPage(final String menuName, final int menuRows) {
+
this.menuName = menuName;
this.menuRows = Math.max(menuRows, 3); // Minimum 3 rows
}
public void handle(final PageOpenCallback callback) {
+
final Optional viewerOpt = callback.getPlayer().viewer();
if(viewerOpt.isEmpty()) return;
-
+
final MenuViewer viewer = viewerOpt.get();
final Page menuPage = callback.getPage();
final Optional
@@ -116,6 +120,10 @@
net.kyori
examination-string
+
+ org.jetbrains
+ annotations
+
@@ -132,6 +140,10 @@
org.slf4j
slf4j-api
+
+ org.jetbrains
+ annotations
+
@@ -144,6 +156,10 @@
net.kyori
adventure-api
+
+ org.jetbrains
+ annotations
+
@@ -156,6 +172,10 @@
net.kyori
adventure-api
+
+ org.jetbrains
+ annotations
+
@@ -172,6 +192,10 @@
net.kyori
option
+
+ org.jetbrains
+ annotations
+
@@ -184,6 +208,10 @@
net.kyori
adventure-api
+
+ org.jetbrains
+ annotations
+
@@ -196,6 +224,10 @@
net.kyori
adventure-api
+
+ org.jetbrains
+ annotations
+
@@ -203,6 +235,16 @@
examination-api
provided
${depend.examination-api}
+
+
+ net.kyori
+ examination-api
+
+
+ org.jetbrains
+ annotations
+
+
net.kyori
@@ -214,6 +256,10 @@
net.kyori
examination-api
+
+ org.jetbrains
+ annotations
+
diff --git a/quickshop-common/src/main/java/com/ghostchu/quickshop/common/util/mirror/MavenCentralMirror.java b/quickshop-common/src/main/java/com/ghostchu/quickshop/common/util/mirror/MavenCentralMirror.java
index 946091cbdf..4018456308 100644
--- a/quickshop-common/src/main/java/com/ghostchu/quickshop/common/util/mirror/MavenCentralMirror.java
+++ b/quickshop-common/src/main/java/com/ghostchu/quickshop/common/util/mirror/MavenCentralMirror.java
@@ -3,6 +3,7 @@
public enum MavenCentralMirror {
CENTRAL("US", "https://repo1.maven.org/maven2", "https://repo1.maven.org/maven2/net/kyori/adventure-api/4.9.1/adventure-api-4.9.1.pom"),
APACHE("US", "https://repo.maven.apache.org/maven2", "https://repo.maven.apache.org/maven2/net/kyori/adventure-api/4.9.1/adventure-api-4.9.1.pom"),
+ GOOGLE("EU", "https://maven-central-eu.storage-download.googleapis.com", "https://maven-central-eu.storage-download.googleapis.com/maven2/net/kyori/adventure-api/4.9.1/adventure-api-4.9.1.pom"),
ALIYUN("CN", "https://maven.aliyun.com/repository/public", "https://maven.aliyun.com/repository/central/net/kyori/adventure-api/4.9.1/adventure-api-4.9.1.pom"),
TENCENT("CN", "https://mirrors.cloud.tencent.com/nexus/repository/maven-public", "https://mirrors.cloud.tencent.com/nexus/repository/maven-public/net/kyori/adventure-api/4.9.1/adventure-api-4.9.1.pom"),
HUAWEI("CN", "https://repo.huaweicloud.com/repository/maven", "https://repo.huaweicloud.com/repository/maven/net/kyori/adventure-api/4.9.1/adventure-api-4.9.1.pom");