From 933d6c974aed96008f45812409105a24ce635b37 Mon Sep 17 00:00:00 2001
From: YuTian <2953516620@qq.com>
Date: Tue, 16 Jul 2024 23:05:14 +0800
Subject: [PATCH] 0.1-beta
---
 .gitignore                                    |  40 ++++++
 pom.xml                                       |  55 ++++++++
 .../io/yutian/auchestshop/AuChestShop.java    |  48 +++++++
 .../auchestshop/command/CommandManager.java   |  13 ++
 .../auchestshop/database/SQLExecutor.java     |  12 ++
 .../io/yutian/auchestshop/database/SQLIO.java |  71 ++++++++++
 .../auchestshop/listener/ShopListener.java    |  14 ++
 .../auchestshop/manager/ShopManager.java      | 132 ++++++++++++++++++
 .../com/io/yutian/auchestshop/shop/Shop.java  |  84 +++++++++++
 .../io/yutian/auchestshop/shop/ShopChunk.java |  63 +++++++++
 .../yutian/auchestshop/shop/ShopLoader.java   |  10 ++
 .../io/yutian/auchestshop/shop/ShopType.java  |   8 ++
 .../io/yutian/auchestshop/util/ShopUtil.java  |  25 ++++
 src/main/resources/plugin.yml                 |   7 +
 14 files changed, 582 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 pom.xml
 create mode 100644 src/main/java/com/io/yutian/auchestshop/AuChestShop.java
 create mode 100644 src/main/java/com/io/yutian/auchestshop/command/CommandManager.java
 create mode 100644 src/main/java/com/io/yutian/auchestshop/database/SQLExecutor.java
 create mode 100644 src/main/java/com/io/yutian/auchestshop/database/SQLIO.java
 create mode 100644 src/main/java/com/io/yutian/auchestshop/listener/ShopListener.java
 create mode 100644 src/main/java/com/io/yutian/auchestshop/manager/ShopManager.java
 create mode 100644 src/main/java/com/io/yutian/auchestshop/shop/Shop.java
 create mode 100644 src/main/java/com/io/yutian/auchestshop/shop/ShopChunk.java
 create mode 100644 src/main/java/com/io/yutian/auchestshop/shop/ShopLoader.java
 create mode 100644 src/main/java/com/io/yutian/auchestshop/shop/ShopType.java
 create mode 100644 src/main/java/com/io/yutian/auchestshop/util/ShopUtil.java
 create mode 100644 src/main/resources/plugin.yml
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..977d1fd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,40 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
+/.idea/
+/target/
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..4a6421f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,55 @@
+
+
+    4.0.0
+
+    com.io.yutian.auchestshop
+    AuChestShop
+    1.0-SNAPSHOT
+    jar
+
+    
+        17
+        17
+        UTF-8
+    
+
+    
+        
+            papermc-repo
+            https://repo.papermc.io/repository/maven-public/
+        
+        
+            sonatype
+            https://oss.sonatype.org/content/groups/public/
+        
+        
+            public-rpg
+            https://repo.aurora-pixels.com/repository/public-rpg/
+        
+    
+
+    
+        
+            io.papermc.paper
+            paper-api
+            1.18.2-R0.1-SNAPSHOT
+            provided
+        
+        
+            com.io.yutian.pixelpaper
+            pixelpaper-api
+            1.18.2
+            provided
+        
+        
+            com.io.yutian
+            AuLib
+            1.2.2
+            provided
+        
+    
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/io/yutian/auchestshop/AuChestShop.java b/src/main/java/com/io/yutian/auchestshop/AuChestShop.java
new file mode 100644
index 0000000..6ed98ce
--- /dev/null
+++ b/src/main/java/com/io/yutian/auchestshop/AuChestShop.java
@@ -0,0 +1,48 @@
+package com.io.yutian.auchestshop;
+
+import com.io.yutian.auchestshop.database.SQLIO;
+import com.io.yutian.auchestshop.manager.ShopManager;
+import com.io.yutian.aulib.lang.Lang;
+import org.bukkit.plugin.java.JavaPlugin;
+
+public class AuChestShop extends JavaPlugin {
+
+    private static AuChestShop instance;
+
+    private static SQLIO sqlIO;
+    private static ShopManager shopManager;
+
+    @Override
+    public void onEnable() {
+        instance = this;
+
+        sqlIO = new SQLIO();
+        shopManager = new ShopManager();
+
+        Lang.reload(this);
+
+        try {
+            sqlIO.init();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void onDisable() {
+        sqlIO.close();
+    }
+
+    public static SQLIO getSQLIO() {
+        return sqlIO;
+    }
+
+    public static ShopManager getShopManager() {
+        return shopManager;
+    }
+
+    public static AuChestShop inst() {
+        return instance;
+    }
+
+}
diff --git a/src/main/java/com/io/yutian/auchestshop/command/CommandManager.java b/src/main/java/com/io/yutian/auchestshop/command/CommandManager.java
new file mode 100644
index 0000000..94e1784
--- /dev/null
+++ b/src/main/java/com/io/yutian/auchestshop/command/CommandManager.java
@@ -0,0 +1,13 @@
+package com.io.yutian.auchestshop.command;
+
+import com.io.yutian.aulib.command.SimpleCommandManager;
+import com.io.yutian.aulib.command.list.CommandHelp;
+
+public class CommandManager extends SimpleCommandManager {
+
+    public CommandManager() {
+        super("chestshop");
+        register(new CommandHelp(this));
+    }
+
+}
diff --git a/src/main/java/com/io/yutian/auchestshop/database/SQLExecutor.java b/src/main/java/com/io/yutian/auchestshop/database/SQLExecutor.java
new file mode 100644
index 0000000..5499dbb
--- /dev/null
+++ b/src/main/java/com/io/yutian/auchestshop/database/SQLExecutor.java
@@ -0,0 +1,12 @@
+package com.io.yutian.auchestshop.database;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+public class SQLExecutor {
+
+    public static ExecutorService HIKARICP_EXECUTOR = new ThreadPoolExecutor(2, 8, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
+
+}
diff --git a/src/main/java/com/io/yutian/auchestshop/database/SQLIO.java b/src/main/java/com/io/yutian/auchestshop/database/SQLIO.java
new file mode 100644
index 0000000..4e698f2
--- /dev/null
+++ b/src/main/java/com/io/yutian/auchestshop/database/SQLIO.java
@@ -0,0 +1,71 @@
+package com.io.yutian.auchestshop.database;
+
+import com.io.yutian.auchestshop.AuChestShop;
+import com.io.yutian.aulib.sql.SQLHelper;
+import com.io.yutian.aulib.sql.api.SQLManager;
+import com.io.yutian.aulib.sql.api.SQLQuery;
+import com.io.yutian.aulib.sql.api.enums.IndexType;
+import com.io.yutian.aulib.sql.manager.SQLManagerImpl;
+import com.io.yutian.aulib.sql.util.DatabaseDriverType;
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+
+import java.io.File;
+import java.io.IOException;
+import java.sql.ResultSet;
+import java.util.UUID;
+
+public class SQLIO {
+
+    private SQLManager sqlManager;
+
+    public void init() throws IOException {
+        HikariConfig config = new HikariConfig();
+        config.setDriverClassName(DatabaseDriverType.H2.getDriverClassName());
+        config.setJdbcUrl("jdbc:h2:"+new File(AuChestShop.inst().getDataFolder(), "shops").getCanonicalFile().getAbsolutePath() + ";MODE=MYSQL");
+        sqlManager = new SQLManagerImpl(new HikariDataSource(config), "AuChestShop-Hikari-SQLManager");
+        sqlManager.executeSQL("SET MODE=MYSQL;");
+        sqlManager.setExecutorPool(SQLExecutor.HIKARICP_EXECUTOR);
+
+        createTables();
+    }
+
+    private void createTables() {
+        sqlManager.createTable("shops")
+                .addColumn("uuid", "VARCHAR(32) NOT NULL")
+                .addColumn("owner", "VARCHAR(32) NOT NULL")
+                .addColumn("item", "TEXT NOT NULL")
+                .addColumn("type", "INT NOT NULL DEFAULT 0")
+                .addColumn("price", "DECIMAL(32,2) NOT NULL")
+                .addColumn("unlimited", "BIT NOT NULL DEFAULT 0")
+                .addColumn("log", "TEXT NOT NULL")
+                .addColumn("create_time", "LONG NOT NULL")
+                .setIndex("uuid", IndexType.UNIQUE_KEY)
+                .build().execute(null);
+    }
+
+    private void query(UUID uuid) {
+        try (SQLQuery query = sqlManager.createQuery()
+                .inTable("shops")
+                .selectColumns("uuid", "name", "item", "type", "price", "unlimited", "create_time")
+                .addCondition("uuid", uuid.toString())
+                .build().execute(null)) {
+            try (ResultSet resultSet = query.getResultSet()) {
+                while (resultSet.next()) {
+                    String name = resultSet.getString("name");
+
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void close() {
+        if (sqlManager == null) {
+            return;
+        }
+        SQLHelper.shutdownManager(sqlManager);
+    }
+
+}
diff --git a/src/main/java/com/io/yutian/auchestshop/listener/ShopListener.java b/src/main/java/com/io/yutian/auchestshop/listener/ShopListener.java
new file mode 100644
index 0000000..b435ba0
--- /dev/null
+++ b/src/main/java/com/io/yutian/auchestshop/listener/ShopListener.java
@@ -0,0 +1,14 @@
+package com.io.yutian.auchestshop.listener;
+
+import com.io.yutian.aulib.listener.IListener;
+import org.bukkit.plugin.Plugin;
+
+public class ShopListener extends IListener {
+
+    public ShopListener(Plugin plugin) {
+        super(plugin);
+    }
+
+
+
+}
diff --git a/src/main/java/com/io/yutian/auchestshop/manager/ShopManager.java b/src/main/java/com/io/yutian/auchestshop/manager/ShopManager.java
new file mode 100644
index 0000000..f829ae5
--- /dev/null
+++ b/src/main/java/com/io/yutian/auchestshop/manager/ShopManager.java
@@ -0,0 +1,132 @@
+package com.io.yutian.auchestshop.manager;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.io.yutian.auchestshop.shop.Shop;
+import com.io.yutian.auchestshop.shop.ShopChunk;
+import com.io.yutian.auchestshop.shop.ShopLoader;
+import com.io.yutian.auchestshop.util.ShopUtil;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.Chunk;
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+public class ShopManager {
+
+    private final Map>> shops = Maps.newConcurrentMap();
+    private final Set loadedShops = Sets.newConcurrentHashSet();
+
+    public void loadAll(ShopLoader shopLoader) {
+
+    }
+
+    public @NotNull List getAllShops() {
+        List shopsCollected = new ArrayList<>();
+        for (Map> shopMapData : getShops().values()) {
+            for (Map shopData : shopMapData.values()) {
+                shopsCollected.addAll(shopData.values());
+            }
+        }
+        return shopsCollected;
+    }
+
+    public @NotNull List getAllShops(@NotNull UUID playerUUID) {
+        List playerShops = new ArrayList<>();
+        for (Shop shop : getAllShops()) {
+            UUID shopUuid = shop.getOwner();
+            if (playerUUID.equals(shopUuid)) {
+                playerShops.add(shop);
+            }
+        }
+        return playerShops;
+    }
+
+
+    public @Nullable Shop getShop(UUID shopId) {
+        for (Shop shop : getAllShops()) {
+            if (shop.getUUID().equals(shopId)) {
+                return shop;
+            }
+        }
+        return null;
+    }
+
+    public @Nullable Shop getShop(@NotNull Location location) {
+        if (!ShopUtil.isShoppables(location.getBlock().getType())) {
+            return null;
+        }
+        ShopChunk shopChunk = ShopChunk.fromLocation(location);
+        final Map inChunk = getShops(shopChunk);
+        if (inChunk == null) {
+            return null;
+        }
+        location = location.clone();
+        location.setX(location.getBlockX());
+        location.setY(location.getBlockY());
+        location.setZ(location.getBlockZ());
+        return inChunk.get(location);
+    }
+
+    public Map>> getShops() {
+        return this.shops;
+    }
+
+    public Map getShops(@NotNull Chunk chunk) {
+        return getShops(chunk.getWorld().getName(), chunk.getX(), chunk.getZ());
+    }
+
+    public Map getShops(@NotNull String world, int chunkX, int chunkZ) {
+        final Map> inWorld = this.getShops(world);
+        if (inWorld == null) {
+            return null;
+        }
+        return inWorld.get(new ShopChunk(world, chunkX, chunkZ));
+    }
+
+    public Map getShops(@NotNull ShopChunk shopChunk) {
+        return getShops(shopChunk.getWorld(), shopChunk.getX(), shopChunk.getZ());
+    }
+
+    public Map> getShops(@NotNull String world) {
+        return this.shops.get(world);
+    }
+
+    public @NotNull List getShopsInWorld(@NotNull World world) {
+        final List worldShops = new ArrayList<>();
+        for (final Shop shop : getAllShops()) {
+            Location location = shop.getLocation();
+            if (location.isWorldLoaded() && Objects.equals(location.getWorld(), world)) {
+                worldShops.add(shop);
+            }
+        }
+        return worldShops;
+    }
+
+    public @NotNull List getShopsInWorld(@NotNull String worldName) {
+        final List worldShops = new ArrayList<>();
+        for (final Shop shop : getAllShops()) {
+            Location location = shop.getLocation();
+            if (location.isWorldLoaded() && StringUtils.equals(worldName, location.getWorld().getName())) {
+                worldShops.add(shop);
+            }
+        }
+        return worldShops;
+    }
+
+    public void loadShop(@NotNull Shop shop) {
+        loadedShops.add(shop);
+    }
+
+    public void unloadShop(@NotNull Shop shop) {
+        this.loadedShops.remove(shop);
+    }
+
+    public Set getLoadedShops() {
+        return loadedShops;
+    }
+
+}
diff --git a/src/main/java/com/io/yutian/auchestshop/shop/Shop.java b/src/main/java/com/io/yutian/auchestshop/shop/Shop.java
new file mode 100644
index 0000000..9b1a780
--- /dev/null
+++ b/src/main/java/com/io/yutian/auchestshop/shop/Shop.java
@@ -0,0 +1,84 @@
+package com.io.yutian.auchestshop.shop;
+
+import org.bukkit.Location;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.Objects;
+import java.util.UUID;
+
+public class Shop {
+
+    private final UUID uuid;
+    private final Location location;
+    private final UUID owner;
+    private double price;
+    private ShopType shopType;
+    private boolean unlimited;
+    private ItemStack item;
+    private ItemStack originalItem;
+    private ItemStack displayItem;
+
+    public Shop(UUID uuid, Location location, UUID owner, double price, ShopType shopType, boolean unlimited, ItemStack item, ItemStack originalItem, ItemStack displayItem) {
+        this.uuid = uuid;
+        this.location = location;
+        this.owner = owner;
+        this.price = price;
+        this.shopType = shopType;
+        this.unlimited = unlimited;
+        this.item = item;
+        this.originalItem = originalItem;
+        this.displayItem = displayItem;
+    }
+
+    public UUID getUUID() {
+        return uuid;
+    }
+
+    public Location getLocation() {
+        return location;
+    }
+
+    public UUID getOwner() {
+        return owner;
+    }
+
+    public double getPrice() {
+        return price;
+    }
+
+    public ShopType getShopType() {
+        return shopType;
+    }
+
+    public boolean isUnlimited() {
+        return unlimited;
+    }
+
+    public ItemStack getItem() {
+        return item;
+    }
+
+    public ItemStack getOriginalItem() {
+        return originalItem;
+    }
+
+    public ItemStack getDisplayItem() {
+        return displayItem;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Shop shop = (Shop) o;
+        return Objects.equals(uuid, shop.uuid) && Objects.equals(getOwner(), shop.getOwner());
+    }
+
+    @Override
+    public int hashCode() {
+        int result = Objects.hashCode(uuid);
+        result = 31 * result + Objects.hashCode(getOwner());
+        return result;
+    }
+}
diff --git a/src/main/java/com/io/yutian/auchestshop/shop/ShopChunk.java b/src/main/java/com/io/yutian/auchestshop/shop/ShopChunk.java
new file mode 100644
index 0000000..cf7545f
--- /dev/null
+++ b/src/main/java/com/io/yutian/auchestshop/shop/ShopChunk.java
@@ -0,0 +1,63 @@
+package com.io.yutian.auchestshop.shop;
+
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+
+public class ShopChunk {
+
+    private final String world;
+    private final int x;
+    private final int z;
+
+    public ShopChunk(String world, int x, int z) {
+        this.world = world;
+        this.x = x;
+        this.z = z;
+    }
+
+    public String getWorld() {
+        return world;
+    }
+
+    public int getX() {
+        return x;
+    }
+
+    public int getZ() {
+        return z;
+    }
+
+    public boolean equals(@NotNull String world, int x, int z) {
+        return this.x == x && this.z == z && this.world.equals(world);
+    }
+
+    public boolean equals(@NotNull World world, int x, int z) {
+        return equals(world.getName(), x, z);
+    }
+
+
+    public static ShopChunk fromLocation(@NotNull Location location) {
+        return new ShopChunk(location.getWorld().getName(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ShopChunk shopChunk = (ShopChunk) o;
+        return getX() == shopChunk.getX() && getZ() == shopChunk.getZ() && Objects.equals(getWorld(), shopChunk.getWorld());
+    }
+
+    @Override
+    public int hashCode() {
+        int result = Objects.hashCode(getWorld());
+        result = 31 * result + getX();
+        result = 31 * result + getZ();
+        return result;
+    }
+
+}
diff --git a/src/main/java/com/io/yutian/auchestshop/shop/ShopLoader.java b/src/main/java/com/io/yutian/auchestshop/shop/ShopLoader.java
new file mode 100644
index 0000000..aaa4bff
--- /dev/null
+++ b/src/main/java/com/io/yutian/auchestshop/shop/ShopLoader.java
@@ -0,0 +1,10 @@
+package com.io.yutian.auchestshop.shop;
+
+public class ShopLoader {
+
+    public void load() {
+
+    }
+
+
+}
diff --git a/src/main/java/com/io/yutian/auchestshop/shop/ShopType.java b/src/main/java/com/io/yutian/auchestshop/shop/ShopType.java
new file mode 100644
index 0000000..472d176
--- /dev/null
+++ b/src/main/java/com/io/yutian/auchestshop/shop/ShopType.java
@@ -0,0 +1,8 @@
+package com.io.yutian.auchestshop.shop;
+
+public enum ShopType {
+
+    SELLING,
+    BUYING
+
+}
diff --git a/src/main/java/com/io/yutian/auchestshop/util/ShopUtil.java b/src/main/java/com/io/yutian/auchestshop/util/ShopUtil.java
new file mode 100644
index 0000000..a0dd313
--- /dev/null
+++ b/src/main/java/com/io/yutian/auchestshop/util/ShopUtil.java
@@ -0,0 +1,25 @@
+package com.io.yutian.auchestshop.util;
+
+import org.bukkit.Material;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.EnumSet;
+
+public class ShopUtil {
+
+    private static final EnumSet SHOPABLES = EnumSet.noneOf(Material.class);
+
+    static {
+        SHOPABLES.add(Material.CHEST);
+        SHOPABLES.add(Material.TRAPPED_CHEST);
+    }
+
+    public static boolean isShoppables(@NotNull Material material) {
+        return SHOPABLES.contains(material);
+    }
+
+    public static EnumSet getShopables() {
+        return SHOPABLES;
+    }
+
+}
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
new file mode 100644
index 0000000..c496b99
--- /dev/null
+++ b/src/main/resources/plugin.yml
@@ -0,0 +1,7 @@
+name: AuChestShop
+main: com.io.yutian.auchestshop.AuChestShop
+version: 1.0
+api-version: 1.18
+author: SuperYuTian
+depend:
+  - AuLib
\ No newline at end of file