diff --git a/pom.xml b/pom.xml index d66f709..c3abade 100644 --- a/pom.xml +++ b/pom.xml @@ -32,16 +32,9 @@ - io.papermc.paper - paper-api - 1.18.2-R0.1-SNAPSHOT - provided - - - com.io.yutian.pixelpaper - pixelpaper-api + com.io.yutian + pixelpaper 1.18.2 - provided com.io.yutian diff --git a/src/main/java/com/io/yutian/auchestshop/AuChestShop.java b/src/main/java/com/io/yutian/auchestshop/AuChestShop.java index 4791a54..49b2091 100644 --- a/src/main/java/com/io/yutian/auchestshop/AuChestShop.java +++ b/src/main/java/com/io/yutian/auchestshop/AuChestShop.java @@ -2,6 +2,8 @@ package com.io.yutian.auchestshop; import com.io.yutian.auchestshop.command.CommandManager; import com.io.yutian.auchestshop.database.SQLIO; +import com.io.yutian.auchestshop.listener.ShopListener; +import com.io.yutian.auchestshop.manager.InteractiveManager; import com.io.yutian.auchestshop.manager.ShopManager; import com.io.yutian.aulib.lang.Lang; import org.bukkit.plugin.java.JavaPlugin; @@ -13,6 +15,7 @@ public class AuChestShop extends JavaPlugin { private static SQLIO sqlIO; private static ShopManager shopManager; private static CommandManager commandManager; + private static InteractiveManager interactiveManager; @Override public void onEnable() { @@ -21,15 +24,23 @@ public class AuChestShop extends JavaPlugin { sqlIO = new SQLIO(); commandManager = new CommandManager(); shopManager = new ShopManager(); + interactiveManager = new InteractiveManager(); commandManager.registerBukkitCommand(this, "auchestshop"); - Lang.reload(this); + registerListeners(); + Lang.registerLangFile(this); + reload(); try { sqlIO.init(); } catch (Exception e) { e.printStackTrace(); } + shopManager.loadAll(sqlIO); + } + + public void reload() { + Lang.reload(this); } @Override @@ -37,6 +48,10 @@ public class AuChestShop extends JavaPlugin { sqlIO.close(); } + private void registerListeners() { + new ShopListener(this); + } + public static SQLIO getSQLIO() { return sqlIO; } @@ -45,6 +60,14 @@ public class AuChestShop extends JavaPlugin { return shopManager; } + public static CommandManager getCommandManager() { + return commandManager; + } + + public static InteractiveManager getInteractiveManager() { + return interactiveManager; + } + 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 index c69ce6a..8353275 100644 --- a/src/main/java/com/io/yutian/auchestshop/command/CommandManager.java +++ b/src/main/java/com/io/yutian/auchestshop/command/CommandManager.java @@ -1,5 +1,6 @@ package com.io.yutian.auchestshop.command; +import com.io.yutian.auchestshop.command.subs.CommandReload; import com.io.yutian.auchestshop.command.subs.CommandTest; import com.io.yutian.aulib.command.SimpleCommandManager; @@ -8,6 +9,7 @@ public class CommandManager extends SimpleCommandManager { public CommandManager() { super("chestshop"); register(new CommandTest()); + register(new CommandReload()); } } diff --git a/src/main/java/com/io/yutian/auchestshop/command/subs/CommandReload.java b/src/main/java/com/io/yutian/auchestshop/command/subs/CommandReload.java new file mode 100644 index 0000000..677d013 --- /dev/null +++ b/src/main/java/com/io/yutian/auchestshop/command/subs/CommandReload.java @@ -0,0 +1,21 @@ +package com.io.yutian.auchestshop.command.subs; + +import com.io.yutian.auchestshop.AuChestShop; +import com.io.yutian.aulib.command.CommandContext; +import com.io.yutian.aulib.command.ICommand; +import org.bukkit.command.CommandSender; + +public class CommandReload extends ICommand { + + public CommandReload() { + super("reload"); + } + + @Override + public void executes(CommandContext commandContext) { + CommandSender sender = commandContext.getSender(); + AuChestShop.inst().reload(); + sender.sendMessage("§a重载成功"); + } + +} diff --git a/src/main/java/com/io/yutian/auchestshop/database/SQLIO.java b/src/main/java/com/io/yutian/auchestshop/database/SQLIO.java index c7caea0..075840b 100644 --- a/src/main/java/com/io/yutian/auchestshop/database/SQLIO.java +++ b/src/main/java/com/io/yutian/auchestshop/database/SQLIO.java @@ -45,19 +45,22 @@ public class SQLIO { public List loadAllShops() { List shops = new ArrayList<>(); - sqlManager.createQuery() + try (SQLQuery sqlQuery = sqlManager.createQuery() .inTable("shops") - .build().executeAsync(sqlQuery -> { - ResultSet resultSet = sqlQuery.getResultSet(); - while (resultSet.next()) { - String uuid = resultSet.getString("uuid"); - String owner = resultSet.getString("owner"); - String data = resultSet.getString("data"); - JSONObject dataJson = new JSONObject(data); - Shop shop = SerializeHelper.deserialize(Shop.class, dataJson); - shops.add(shop); - } - }); + .build().execute()) { + try (ResultSet resultSet = sqlQuery.getResultSet()) { + while (resultSet.next()) { + String uuid = resultSet.getString("uuid"); + String owner = resultSet.getString("owner"); + String data = resultSet.getString("data"); + JSONObject dataJson = new JSONObject(data); + Shop shop = SerializeHelper.deserialize(Shop.class, dataJson); + shops.add(shop); + } + } + } catch (Exception e) { + e.printStackTrace(); + } return shops; } @@ -71,7 +74,6 @@ public class SQLIO { JSONObject dataJson = SerializeHelper.serialize(shop); sqlManager.createUpdate("shops") .addCondition("uuid", shop.getUUID().toString()) - .setLimit(1) .setColumnValues("owner", shop.getOwner().toString()) .setColumnValues("data", dataJson.toString()) .build().execute(); @@ -94,6 +96,27 @@ public class SQLIO { } } + public void saveShop(Shop shop) { + try (SQLQuery sqlQuery = sqlManager.createQuery().inTable("shops").addCondition("uuid", shop.getUUID().toString()).setLimit(1).build().execute()) { + try (ResultSet resultSet = sqlQuery.getResultSet()) { + if (resultSet.next()) { + JSONObject dataJson = SerializeHelper.serialize(shop); + sqlManager.createUpdate("shops") + .addCondition("uuid", shop.getUUID().toString()) + .setLimit(1) + .setColumnValues("owner", shop.getOwner().toString()) + .setColumnValues("data", dataJson.toString()) + .build().execute(); + } else { + JSONObject dataJson = SerializeHelper.serialize(shop); + sqlManager.createInsert("shops").setIgnore(false).setColumnNames("uuid", "owner", "data").setParams(new Object[]{shop.getUUID().toString(), shop.getOwner().toString(), dataJson.toString()}).executeAsync(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + public void close() { if (sqlManager == null) { return; diff --git a/src/main/java/com/io/yutian/auchestshop/gui/CreateShopGui.java b/src/main/java/com/io/yutian/auchestshop/gui/CreateShopGui.java new file mode 100644 index 0000000..e6e42e3 --- /dev/null +++ b/src/main/java/com/io/yutian/auchestshop/gui/CreateShopGui.java @@ -0,0 +1,61 @@ +package com.io.yutian.auchestshop.gui; + +import com.io.yutian.auchestshop.AuChestShop; +import com.io.yutian.auchestshop.shop.ShopType; +import com.io.yutian.aulib.gui.Gui; +import com.io.yutian.aulib.gui.button.Button; +import com.io.yutian.aulib.lang.Lang; +import com.io.yutian.aulib.util.ItemStackBuilder; +import com.io.yutian.aulib.util.PlayerInventoryUtil; +import net.kyori.adventure.text.Component; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.ItemStack; + +public class CreateShopGui extends Gui { + + private Block block; + private ItemStack itemStack; + + private Runnable runnable; + + protected boolean created = false; + + public CreateShopGui(Player player, Block block, ItemStack itemStack, Runnable runnable) { + super(player, Component.text("创建商店"), 27); + this.block = block; + this.itemStack = itemStack.clone(); + this.itemStack.setAmount(1); + this.runnable = runnable; + init(); + initButton(); + } + + @Override + public void init() { + addButton(11, new Button(new ItemStackBuilder(Material.DIAMOND).setDisplayName("§a出售").build()).click((player1, clickType) -> { + created = true; + AuChestShop.getShopManager().createShop(player1, block, ShopType.SELLING); + player1.sendMessage(Lang.get("")); + player1.closeInventory(); + runnable.run(); + })); + addButton(15, new Button(new ItemStackBuilder(Material.EMERALD).setDisplayName("§a收购").build()).click((player1, clickType) -> { + created = true; + AuChestShop.getShopManager().createShop(player1, block, ShopType.BUYING); + player1.closeInventory(); + runnable.run(); + })); + } + + @Override + public void close(InventoryCloseEvent event) { + if (!created) { + block.setType(Material.AIR); + PlayerInventoryUtil.giveItemStack(player, itemStack); + } + runnable.run(); + } +} diff --git a/src/main/java/com/io/yutian/auchestshop/listener/ShopListener.java b/src/main/java/com/io/yutian/auchestshop/listener/ShopListener.java index b435ba0..2140e30 100644 --- a/src/main/java/com/io/yutian/auchestshop/listener/ShopListener.java +++ b/src/main/java/com/io/yutian/auchestshop/listener/ShopListener.java @@ -1,14 +1,163 @@ package com.io.yutian.auchestshop.listener; +import com.io.yutian.auchestshop.AuChestShop; +import com.io.yutian.auchestshop.gui.CreateShopGui; +import com.io.yutian.auchestshop.shop.Shop; +import com.io.yutian.auchestshop.util.ExpiringSet; import com.io.yutian.aulib.listener.IListener; +import com.io.yutian.aulib.nbt.NBTItem; +import com.io.yutian.aulib.nbt.NBTString; +import it.unimi.dsi.fastutil.Pair; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.type.Chest; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerAnimationEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + public class ShopListener extends IListener { + private final ExpiringSet adventureWorkaround = new ExpiringSet<>(1, TimeUnit.SECONDS); + private final Set cachedLocations = new HashSet<>(); + public ShopListener(Plugin plugin) { super(plugin); } + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onChat(AsyncPlayerChatEvent event) { + Player player = event.getPlayer(); + UUID uuid = player.getUniqueId(); + if (!AuChestShop.getInteractiveManager().containsKey(uuid)) { + return; + } + AuChestShop.getInteractiveManager().handler(uuid, event.getMessage()); + event.setCancelled(true); + } + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onBlockPlace(BlockPlaceEvent event) { + Player player = event.getPlayer(); + Block block = event.getBlock(); + ItemStack itemStack = event.getItemInHand(); + NBTItem nbtItem = new NBTItem(itemStack); + if (nbtItem.has("item_type", NBTString.TYPE_ID)) { + String itemType = (String) nbtItem.get("item_type").getValue(); + if (itemType.equals("chest_shop")) { + CreateShopGui createShopGui = new CreateShopGui(player, block, itemStack, ()->{ + cachedLocations.remove(block.getLocation()); + }); + createShopGui.open(); + cachedLocations.add(block.getLocation()); + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onBlockBreak(BlockBreakEvent event) { + Player player = event.getPlayer(); + Block block = event.getBlock(); + if (cachedLocations.contains(block.getLocation())) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onAdventureClick(PlayerAnimationEvent event) { + if (event.getPlayer().getGameMode() != GameMode.ADVENTURE) { + return; + } + if (adventureWorkaround.contains(event.getPlayer().getUniqueId())) { + return; + } + adventureWorkaround.add(event.getPlayer().getUniqueId()); + Block focused = event.getPlayer().getTargetBlockExact(5); + if (focused != null) { + PlayerInteractEvent interactEvent + = new PlayerInteractEvent(event.getPlayer(), + focused.getType() == Material.AIR ? Action.LEFT_CLICK_AIR : Action.LEFT_CLICK_BLOCK, + event.getPlayer().getInventory().getItemInMainHand(), + focused, + event.getPlayer().getFacing().getOppositeFace()); + onPlayerInteract(interactEvent); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getHand() != EquipmentSlot.HAND) { + return; + } + Player player = event.getPlayer(); + if (player.getGameMode() == GameMode.ADVENTURE) { + if (!adventureWorkaround.contains(player.getUniqueId())) { + return; + } + adventureWorkaround.add(player.getUniqueId()); + } + Action action = event.getAction(); + Block clickedBlock = event.getClickedBlock(); + if (clickedBlock == null) { + return; + } + if (cachedLocations.contains(clickedBlock.getLocation())) { + event.setCancelled(true); + return; + } + Pair shopSearched = searchShop(player, clickedBlock); + if (shopSearched.key() == null || shopSearched.value() == ClickType.AIR) { + return; + } + Shop shop = shopSearched.key(); + ClickType clickType = shopSearched.value(); + System.out.println(shop); + } + + private Pair searchShop(Player player, Block block) { + if (block == null || block.getType() == Material.AIR) { + return Pair.of(null, ClickType.AIR); + } + Shop shop = AuChestShop.getShopManager().getShop(block.getLocation()); + Material material = block.getType(); + if (shop == null) { + if (material == Material.CHEST || material == Material.TRAPPED_CHEST) { + Chest chest = (Chest) block.getState().getBlockData(); + Chest.ChestDoubleBlockHalfType halfType = chest.getDoubleBlockHalf(); + if (halfType == Chest.ChestDoubleBlockHalfType.LOWER) { + return Pair.of(null, ClickType.AIR); + } else if (halfType == Chest.ChestDoubleBlockHalfType.UPPER) { + Block attached = block.getRelative(BlockFace.DOWN, 1); + shop = AuChestShop.getShopManager().getShop(attached.getLocation()); + return Pair.of(shop, ClickType.UPPER); + } + } else { + return Pair.of(null, ClickType.AIR); + } + } + return Pair.of(shop, ClickType.LOWER); + } + + enum ClickType { + UPPER, + LOWER, + AIR; + } } diff --git a/src/main/java/com/io/yutian/auchestshop/manager/InteractiveManager.java b/src/main/java/com/io/yutian/auchestshop/manager/InteractiveManager.java new file mode 100644 index 0000000..a7b1a91 --- /dev/null +++ b/src/main/java/com/io/yutian/auchestshop/manager/InteractiveManager.java @@ -0,0 +1,38 @@ +package com.io.yutian.auchestshop.manager; + +import com.io.yutian.auchestshop.shop.ShopInteractiveInfo; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class InteractiveManager { + + private final Map actions = new HashMap<>(); + + public void handler(UUID uuid, String message) { + ShopInteractiveInfo info = actions.get(uuid); + + } + + public ShopInteractiveInfo put(UUID uuid, ShopInteractiveInfo info) { + return this.actions.put(uuid, info); + } + + public ShopInteractiveInfo remove(UUID uuid) { + return this.actions.remove(uuid); + } + + public ShopInteractiveInfo get(UUID uuid) { + return this.actions.get(uuid); + } + + public boolean containsKey(UUID uuid) { + return this.actions.containsKey(uuid); + } + + public Map getActions() { + return actions; + } + +} diff --git a/src/main/java/com/io/yutian/auchestshop/manager/ShopManager.java b/src/main/java/com/io/yutian/auchestshop/manager/ShopManager.java index 245ec21..e0c270b 100644 --- a/src/main/java/com/io/yutian/auchestshop/manager/ShopManager.java +++ b/src/main/java/com/io/yutian/auchestshop/manager/ShopManager.java @@ -2,15 +2,19 @@ package com.io.yutian.auchestshop.manager; import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import com.io.yutian.auchestshop.AuChestShop; +import com.io.yutian.auchestshop.database.SQLIO; 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.shop.ShopLocation; +import com.io.yutian.auchestshop.shop.ShopType; 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.bukkit.block.Block; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -18,17 +22,31 @@ import java.util.*; public class ShopManager { - private final Map>> shops = Maps.newConcurrentMap(); + private final Map>> shops = Maps.newConcurrentMap(); private final Set loadedShops = Sets.newConcurrentHashSet(); - public void loadAll(ShopLoader shopLoader) { + public void loadAll(SQLIO sqlio) { + List shopList = sqlio.loadAllShops(); + shopList.forEach(this::addShop); + } + public void saveAll(SQLIO sqlio) { + sqlio.saveAllShops(getAllShops()); + } + + public Shop createShop(Player player, Block block, ShopType shopType) { + Location location = block.getLocation(); + ShopLocation shopLocation = ShopLocation.fromLocation(location); + Shop shop = new Shop(player.getUniqueId(), shopLocation, shopType); + addShop(shop); + AuChestShop.getSQLIO().saveShop(shop); + return shop; } public @NotNull List getAllShops() { List shopsCollected = new ArrayList<>(); - for (Map> shopMapData : getShops().values()) { - for (Map shopData : shopMapData.values()) { + for (Map> shopMapData : getShops().values()) { + for (Map shopData : shopMapData.values()) { shopsCollected.addAll(shopData.values()); } } @@ -61,38 +79,35 @@ public class ShopManager { return null; } ShopChunk shopChunk = ShopChunk.fromLocation(location); - final Map inChunk = getShops(shopChunk); + 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); + ShopLocation shopLocation = ShopLocation.fromLocation(location); + return inChunk.get(shopLocation); } - public Map>> getShops() { + public Map>> getShops() { return this.shops; } - public Map getShops(@NotNull Chunk chunk) { + 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); + 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) { + public Map getShops(@NotNull ShopChunk shopChunk) { return getShops(shopChunk.getWorld(), shopChunk.getX(), shopChunk.getZ()); } - public Map> getShops(@NotNull String world) { + public Map> getShops(@NotNull String world) { return this.shops.get(world); } @@ -118,11 +133,19 @@ public class ShopManager { return worldShops; } - public void loadShop(@NotNull Shop shop) { + public void addShop(@NotNull Shop shop) { + ShopLocation shopLocation = shop.getLocation(); + String world = shopLocation.getWorld(); + Map> map = shops.computeIfAbsent(world, k -> new HashMap<>()); + int x = (int) Math.floor((shopLocation.getX()) / 16.0); + int z = (int) Math.floor((shopLocation.getZ()) / 16.0); + ShopChunk shopChunk = new ShopChunk(world, x, z); + Map inChunk = map.computeIfAbsent(shopChunk, k -> new HashMap<>()); + inChunk.put(shopLocation, shop); loadedShops.add(shop); } - public void unloadShop(@NotNull Shop shop) { + public void removeShop(@NotNull Shop shop) { this.loadedShops.remove(shop); } diff --git a/src/main/java/com/io/yutian/auchestshop/shop/Shop.java b/src/main/java/com/io/yutian/auchestshop/shop/Shop.java index 39cd172..47334ce 100644 --- a/src/main/java/com/io/yutian/auchestshop/shop/Shop.java +++ b/src/main/java/com/io/yutian/auchestshop/shop/Shop.java @@ -17,6 +17,10 @@ public class Shop { private boolean unlimited; private ShopLog shopLog; + public Shop(UUID owner, ShopLocation location, ShopType shopType) { + this(UUID.randomUUID(), owner, location, null, 0, shopType, false, new ShopLog()); + } + public Shop(UUID uuid, UUID owner, ShopLocation location, ItemStack item, double price, ShopType shopType, boolean unlimited, ShopLog shopLog) { this.uuid = uuid; this.owner = owner; diff --git a/src/main/java/com/io/yutian/auchestshop/shop/ShopInteractiveInfo.java b/src/main/java/com/io/yutian/auchestshop/shop/ShopInteractiveInfo.java new file mode 100644 index 0000000..346c8bf --- /dev/null +++ b/src/main/java/com/io/yutian/auchestshop/shop/ShopInteractiveInfo.java @@ -0,0 +1,35 @@ +package com.io.yutian.auchestshop.shop; + +import org.bukkit.event.block.Action; +import org.bukkit.inventory.ItemStack; + +public class ShopInteractiveInfo { + + private ItemStack itemStack; + private ShopLocation shopLocation; + private Action action; + private long time; + + public ShopInteractiveInfo(ItemStack itemStack, ShopLocation shopLocation, Action action, long time) { + this.itemStack = itemStack; + this.shopLocation = shopLocation; + this.action = action; + this.time = time; + } + + public ItemStack getItemStack() { + return itemStack; + } + + public ShopLocation getShopLocation() { + return shopLocation; + } + + public Action getAction() { + return action; + } + + public long getTime() { + return time; + } +} diff --git a/src/main/java/com/io/yutian/auchestshop/shop/ShopLoader.java b/src/main/java/com/io/yutian/auchestshop/shop/ShopLoader.java deleted file mode 100644 index aaa4bff..0000000 --- a/src/main/java/com/io/yutian/auchestshop/shop/ShopLoader.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.io.yutian.auchestshop.shop; - -public class ShopLoader { - - public void load() { - - } - - -} diff --git a/src/main/java/com/io/yutian/auchestshop/shop/ShopLocation.java b/src/main/java/com/io/yutian/auchestshop/shop/ShopLocation.java index 8cd922b..11b203c 100644 --- a/src/main/java/com/io/yutian/auchestshop/shop/ShopLocation.java +++ b/src/main/java/com/io/yutian/auchestshop/shop/ShopLocation.java @@ -1,6 +1,8 @@ package com.io.yutian.auchestshop.shop; -import org.json.JSONObject; +import org.bukkit.Location; + +import java.util.Objects; public class ShopLocation { @@ -16,17 +18,8 @@ public class ShopLocation { this.z = z; } - public static ShopLocation fromJSON(JSONObject json) { - return new ShopLocation(json.getString("world"), json.getInt("x"), json.getInt("y"), json.getInt("z")); - } - - public JSONObject toJSON() { - JSONObject json = new JSONObject(); - json.put("world", world); - json.put("x", x); - json.put("y", y); - json.put("z", z); - return json; + public static ShopLocation fromLocation(Location location) { + return new ShopLocation(location.getWorld().getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ()); } public String getWorld() { @@ -45,4 +38,21 @@ public class ShopLocation { return z; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ShopLocation that = (ShopLocation) o; + return getX() == that.getX() && getY() == that.getY() && getZ() == that.getZ() && Objects.equals(getWorld(), that.getWorld()); + } + + @Override + public int hashCode() { + int result = Objects.hashCode(getWorld()); + result = 31 * result + getX(); + result = 31 * result + getY(); + result = 31 * result + getZ(); + return result; + } } diff --git a/src/main/java/com/io/yutian/auchestshop/util/ExpiringSet.java b/src/main/java/com/io/yutian/auchestshop/util/ExpiringSet.java new file mode 100644 index 0000000..bcf51cc --- /dev/null +++ b/src/main/java/com/io/yutian/auchestshop/util/ExpiringSet.java @@ -0,0 +1,35 @@ +package com.io.yutian.auchestshop.util; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; + +import java.util.concurrent.TimeUnit; + +public class ExpiringSet { + private final Cache cache; + private final long lifetime; + + public ExpiringSet(long lifetime, TimeUnit timeUnit) { + this.cache = CacheBuilder + .newBuilder() + .expireAfterWrite(lifetime, timeUnit).build(); + this.lifetime = timeUnit.toMillis(lifetime); + } + + public void add(T item) { + this.cache.put(item, System.currentTimeMillis() + this.lifetime); + } + + public boolean contains(T item) { + Long timeout = this.cache.getIfPresent(item); + return timeout != null && timeout > System.currentTimeMillis(); + } + + public void remove(T item) { + this.cache.invalidate(item); + } + + public long size() { + return this.cache.size(); + } +} diff --git a/src/main/java/com/io/yutian/auchestshop/util/ShopUtil.java b/src/main/java/com/io/yutian/auchestshop/util/ShopUtil.java index a0dd313..efb4fe4 100644 --- a/src/main/java/com/io/yutian/auchestshop/util/ShopUtil.java +++ b/src/main/java/com/io/yutian/auchestshop/util/ShopUtil.java @@ -1,6 +1,10 @@ package com.io.yutian.auchestshop.util; import org.bukkit.Material; +import org.bukkit.Tag; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Directional; import org.jetbrains.annotations.NotNull; import java.util.EnumSet; @@ -14,6 +18,19 @@ public class ShopUtil { SHOPABLES.add(Material.TRAPPED_CHEST); } + public static Block getAttached(@NotNull Block block) { + BlockData blockData = block.getBlockData(); + if (blockData instanceof final Directional directional) { + return block.getRelative(directional.getFacing().getOppositeFace()); + } else { + return null; + } + } + + public static boolean isWallSign(@NotNull Material material) { + return Tag.WALL_SIGNS.isTagged(material); + } + public static boolean isShoppables(@NotNull Material material) { return SHOPABLES.contains(material); } diff --git a/src/main/resources/lang.yml b/src/main/resources/lang.yml new file mode 100644 index 0000000..4338334 --- /dev/null +++ b/src/main/resources/lang.yml @@ -0,0 +1,3 @@ +auchestshop: + create-shop: + success: "成功创建商店" \ No newline at end of file