diff --git a/src/main/java/xyz/soukup/ecoCraftCore/EcoCraftCore.java b/src/main/java/xyz/soukup/ecoCraftCore/EcoCraftCore.java index aa96cc4..3c6d1d0 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/EcoCraftCore.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/EcoCraftCore.java @@ -6,7 +6,6 @@ import com.infernalsuite.asp.api.AdvancedSlimePaperAPI; import com.infernalsuite.asp.api.world.SlimeWorldInstance; import com.j256.ormlite.dao.DaoManager; import com.j256.ormlite.jdbc.DataSourceConnectionSource; -import com.j256.ormlite.jdbc.JdbcConnectionSource; import com.j256.ormlite.stmt.UpdateBuilder; import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.table.TableUtils; @@ -40,7 +39,7 @@ import xyz.soukup.ecoCraftCore.database.objects.Island; import xyz.soukup.ecoCraftCore.database.objects.Shop; import xyz.soukup.ecoCraftCore.database.objects.Transaction; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; -import xyz.soukup.ecoCraftCore.inventory.VirtualChest; +import xyz.soukup.ecoCraftCore.database.objects.VirtualChest; import xyz.soukup.ecoCraftCore.positionMarker.MarkerEvent; import xyz.soukup.ecoCraftCore.database.DaoRegistry; import xyz.soukup.ecoCraftCore.messages.Messages; diff --git a/src/main/java/xyz/soukup/ecoCraftCore/database/DaoRegistry.java b/src/main/java/xyz/soukup/ecoCraftCore/database/DaoRegistry.java index 9b62b01..eaf7907 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/database/DaoRegistry.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/database/DaoRegistry.java @@ -2,7 +2,7 @@ package xyz.soukup.ecoCraftCore.database; import com.j256.ormlite.dao.Dao; import xyz.soukup.ecoCraftCore.database.objects.*; -import xyz.soukup.ecoCraftCore.inventory.VirtualChest; +import xyz.soukup.ecoCraftCore.database.objects.VirtualChest; public class DaoRegistry { private static Dao shopDao; diff --git a/src/main/java/xyz/soukup/ecoCraftCore/database/objects/Shop.java b/src/main/java/xyz/soukup/ecoCraftCore/database/objects/Shop.java index 6317a3c..2df895e 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/database/objects/Shop.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/database/objects/Shop.java @@ -102,6 +102,7 @@ public class Shop { this.stock = stock; } + public static Shop findById(int id) { Shop shop = cache.get(id); @@ -116,6 +117,10 @@ public class Shop { } } + public static HashMap getCache(){ + return cache; + } + public void save(){ try { DaoRegistry.getShopDao().createOrUpdate(this); @@ -126,10 +131,21 @@ public class Shop { cache.put(this.id, this); } + public void delete(){ + try { + cache.remove(this.id); + DaoRegistry.getShopDao().delete(this); + } catch (SQLException e) { + throw new RuntimeException(e); + } + + } + public ItemStack getItemStack() { return Converter.itemstackFromString(this.itemStackString); } + public void writeIntoSign(Sign sign){ PDC.set(sign, "shop", this.id); @@ -159,7 +175,7 @@ public class Shop { } - public long getId() { + public int getId() { return id; } diff --git a/src/main/java/xyz/soukup/ecoCraftCore/inventory/VirtualChest.java b/src/main/java/xyz/soukup/ecoCraftCore/database/objects/VirtualChest.java similarity index 70% rename from src/main/java/xyz/soukup/ecoCraftCore/inventory/VirtualChest.java rename to src/main/java/xyz/soukup/ecoCraftCore/database/objects/VirtualChest.java index 5a09a87..4b7ba97 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/inventory/VirtualChest.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/database/objects/VirtualChest.java @@ -1,18 +1,22 @@ -package xyz.soukup.ecoCraftCore.inventory; +package xyz.soukup.ecoCraftCore.database.objects; import com.j256.ormlite.field.DataType; import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.stmt.DeleteBuilder; +import com.j256.ormlite.stmt.QueryBuilder; import com.j256.ormlite.table.DatabaseTable; import org.bukkit.block.Chest; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import xyz.soukup.ecoCraftCore.database.DaoRegistry; +import xyz.soukup.ecoCraftCore.inventory.InventoryUtils; import xyz.soukup.ecoCraftCore.utilities.Converter; import xyz.soukup.ecoCraftCore.utilities.PDC; import java.sql.SQLException; import java.util.HashMap; import java.util.HashSet; +import java.util.List; @DatabaseTable(tableName = "virtual_chests") public class VirtualChest { @@ -29,7 +33,7 @@ public class VirtualChest { private Inventory inventory; private static final HashMap cache = new HashMap<>(); - private static final HashSet cacheChanges = new HashSet<>(); + private static final HashSet changedCached = new HashSet<>(); public VirtualChest(){ @@ -77,7 +81,7 @@ public class VirtualChest { public static void saveCache(){ cache.forEach((key, value) -> { - if (!cacheChanges.contains(key)) return; + if (!changedCached.contains(key)) return; value.databaseSave(); }); @@ -87,7 +91,7 @@ public class VirtualChest { public void save() { cache.put(this.id, this); - cacheChanges.add(this.id); + changedCached.add(this.id); } public void databaseSave(){ @@ -101,7 +105,40 @@ public class VirtualChest { } cache.put(this.id, this); - cacheChanges.remove(this.id); + changedCached.remove(this.id); + } + + public void delete(){ + try { + DaoRegistry.getVirtualChestDao().delete(this); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + public void deleteSelfAndShops(){ + QueryBuilder queryBuilder = DaoRegistry.getShopDao().queryBuilder(); + DeleteBuilder deleteBuilder = DaoRegistry.getShopDao().deleteBuilder(); + try { + queryBuilder + .selectColumns("id") + .where() + .eq("virtualChestID", this.id); + + List shops = queryBuilder.query(); + HashMap cache = Shop.getCache(); + + for(Shop shop : shops){ + cache.remove(shop.getId()); + } + + deleteBuilder.where().eq("virtualChestID", this.id); + deleteBuilder.delete(); + + DaoRegistry.getVirtualChestDao().delete(this); + } catch (SQLException e) { + throw new RuntimeException(e); + } } public void setInventory(Inventory inventory) { diff --git a/src/main/java/xyz/soukup/ecoCraftCore/messages/Messages.java b/src/main/java/xyz/soukup/ecoCraftCore/messages/Messages.java index 2371064..cfc7595 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/messages/Messages.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/messages/Messages.java @@ -4,6 +4,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.YamlConfiguration; @@ -39,7 +40,7 @@ public class Messages { } public static String getAsString(String key){ - return MiniMessage.miniMessage().serialize(Messages.get(key)); + return LegacyComponentSerializer.legacySection().serialize(Messages.get(key)); } public static Component get(String key, HashMap placeholders){ diff --git a/src/main/java/xyz/soukup/ecoCraftCore/shop/ShopCommand.java b/src/main/java/xyz/soukup/ecoCraftCore/shop/ShopCommand.java index c53fbe0..a7c98d2 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/shop/ShopCommand.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/shop/ShopCommand.java @@ -11,7 +11,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import xyz.soukup.ecoCraftCore.positionMarker.MarkerEvent; import xyz.soukup.ecoCraftCore.database.objects.Shop; -import xyz.soukup.ecoCraftCore.inventory.VirtualChest; +import xyz.soukup.ecoCraftCore.database.objects.VirtualChest; import xyz.soukup.ecoCraftCore.inventory.InventoryUtils; import xyz.soukup.ecoCraftCore.messages.Messages; import xyz.soukup.ecoCraftCore.utilities.PDC; diff --git a/src/main/java/xyz/soukup/ecoCraftCore/shop/ShopLogic.java b/src/main/java/xyz/soukup/ecoCraftCore/shop/ShopLogic.java index e9905a6..78a3c0c 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/shop/ShopLogic.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/shop/ShopLogic.java @@ -1,6 +1,8 @@ package xyz.soukup.ecoCraftCore.shop; import com.github.stefvanschie.inventoryframework.gui.GuiItem; import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; +import com.github.stefvanschie.inventoryframework.gui.type.HopperGui; +import com.github.stefvanschie.inventoryframework.pane.OutlinePane; import com.github.stefvanschie.inventoryframework.pane.StaticPane; import io.papermc.paper.dialog.Dialog; import io.papermc.paper.dialog.DialogResponseView; @@ -11,13 +13,16 @@ import io.papermc.paper.registry.data.dialog.input.DialogInput; import io.papermc.paper.registry.data.dialog.type.DialogType; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.event.ClickCallback; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.Sign; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -29,7 +34,7 @@ import xyz.soukup.ecoCraftCore.messages.Messages; import xyz.soukup.ecoCraftCore.database.objects.Account; import xyz.soukup.ecoCraftCore.database.objects.Shop; import xyz.soukup.ecoCraftCore.database.objects.Transaction; -import xyz.soukup.ecoCraftCore.inventory.VirtualChest; +import xyz.soukup.ecoCraftCore.database.objects.VirtualChest; import xyz.soukup.ecoCraftCore.utilities.*; import java.util.HashMap; @@ -87,6 +92,39 @@ public class ShopLogic implements Listener { gui.show(player); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onDestroy(BlockBreakEvent event){ + + if (event.isCancelled()){ + return; + } + + Block block = event.getBlock(); + + if (!(block.getState() instanceof Sign sign)){ + return; + } + + Integer id = PDC.getInteger(sign, "shop"); + + if (id == null){ + return; + } + + Shop shop = Shop.findById(id); + + if (shop == null){ + return; + } + + event.setCancelled(true); + Player player = event.getPlayer(); + HopperGui gui = confirmBreakGui(block, shop); + gui.show(player); + + } public static ChestGui buildShopGui(Player player, Shop shop){ @@ -260,7 +298,7 @@ public class ShopLogic implements Listener { HashMap hashMap = new HashMap<>(); hashMap.put("count", Integer.toString(amount)); hashMap.put("price", String.format("%.2f", price)); - hashMap.put("item", itemStack.displayName().toString()); + hashMap.put("item", PlainTextComponentSerializer.plainText().serialize(itemStack.displayName())); Messages.send(player, "shop.buy", hashMap); @@ -348,9 +386,48 @@ public class ShopLogic implements Listener { HashMap hashMap = new HashMap<>(); hashMap.put("count", Integer.toString(amount)); hashMap.put("price", String.format("%.2f", price)); - hashMap.put("item", itemStack.displayName().toString()); + hashMap.put("item", PlainTextComponentSerializer.plainText().serialize(itemStack.displayName())); Messages.send(player, "shop.sell", hashMap); } + + public static HopperGui confirmBreakGui(Block block, Shop shop){ + HopperGui gui = new HopperGui(Messages.getAsString("menu.destroy-confirmation.title")); + OutlinePane pane = new OutlinePane(0,0, 5, 1); + + gui.setOnGlobalClick(inventoryClickEvent -> { + inventoryClickEvent.setCancelled(true); + }); + + GuiItem confirmButton = new GuiItemBuilder(Material.LIME_WOOL) + .setName(Messages.get("menu.destroy-confirmation.confirm")) + .build(); + + GuiItem cancelButton = new GuiItemBuilder(Material.RED_WOOL) + .setName(Messages.get("menu.destroy-confirmation.cancel")) + .build(); + + cancelButton.setAction(event -> { + event.getClickedInventory().close(); + }); + + confirmButton.setAction(event -> { + destroyShopAndBlock(block, shop); + event.getClickedInventory().close(); + }); + + pane.addItem(confirmButton); + pane.addItem(cancelButton); + + gui.getSlotsComponent().addPane(pane); + + + return gui; + } + + private static void destroyShopAndBlock(Block block, Shop shop){ + block.breakNaturally(); + shop.delete(); + } } diff --git a/src/main/java/xyz/soukup/ecoCraftCore/virtualChest/VirtualChestLogic.java b/src/main/java/xyz/soukup/ecoCraftCore/virtualChest/VirtualChestLogic.java index f84bf9f..14a6627 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/virtualChest/VirtualChestLogic.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/virtualChest/VirtualChestLogic.java @@ -1,17 +1,24 @@ package xyz.soukup.ecoCraftCore.virtualChest; -import org.bukkit.block.Chest; -import org.bukkit.block.DoubleChest; -import org.bukkit.block.TileState; +import com.github.stefvanschie.inventoryframework.gui.GuiItem; +import com.github.stefvanschie.inventoryframework.gui.type.HopperGui; +import com.github.stefvanschie.inventoryframework.pane.OutlinePane; +import org.bukkit.Material; +import org.bukkit.block.*; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryMoveItemEvent; import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; -import xyz.soukup.ecoCraftCore.inventory.VirtualChest; +import xyz.soukup.ecoCraftCore.database.objects.Shop; +import xyz.soukup.ecoCraftCore.gui.GuiItemBuilder; +import xyz.soukup.ecoCraftCore.database.objects.VirtualChest; +import xyz.soukup.ecoCraftCore.messages.Messages; import xyz.soukup.ecoCraftCore.utilities.PDC; import java.util.HashMap; @@ -20,6 +27,39 @@ public class VirtualChestLogic implements Listener { public static HashMap openedChests = new HashMap<>(); + @EventHandler(priority = EventPriority.HIGHEST) + public void blockBreak(BlockBreakEvent event){ + Block block = event.getBlock(); + BlockState blockState = block.getState(); + Player player = event.getPlayer(); + + Integer id; + + if (blockState instanceof Chest chest){ + id = PDC.getInteger(chest, "virtual"); + } else if (blockState instanceof DoubleChest doubleChest) { + id = PDC.getInteger((TileState) doubleChest.getRightSide(), "virtual"); + }else { + return; + } + + if (id == null){ + return; + } + + VirtualChest virtualChest = VirtualChest.findById(id); + + if (virtualChest == null){ + return; + } + + event.setCancelled(true); + + HopperGui gui = confirmBreakGui(block, virtualChest); + gui.show(player); + + } + @EventHandler public void chestOpen(InventoryOpenEvent event){ InventoryHolder inventoryHolder = event.getInventory().getHolder(); @@ -143,8 +183,43 @@ public class VirtualChestLogic implements Listener { virtualChest.save(); + } + public static HopperGui confirmBreakGui(Block block, VirtualChest virtualChest){ + HopperGui gui = new HopperGui(Messages.getAsString("menu.destroy-confirmation.title")); + OutlinePane pane = new OutlinePane(0,0, 5, 1); + + gui.setOnGlobalClick(inventoryClickEvent -> { + inventoryClickEvent.setCancelled(true); + }); + + GuiItem confirmButton = new GuiItemBuilder(Material.LIME_WOOL) + .setName(Messages.get("menu.destroy-confirmation.confirm")) + .build(); + + GuiItem cancelButton = new GuiItemBuilder(Material.RED_WOOL) + .setName(Messages.get("menu.destroy-confirmation.cancel")) + .build(); + + cancelButton.setAction(event -> { + event.getClickedInventory().close(); + }); + confirmButton.setAction(event -> { + destroyShopAndBlock(block, virtualChest); + event.getClickedInventory().close(); + }); + pane.addItem(confirmButton); + pane.addItem(cancelButton); + + gui.getSlotsComponent().addPane(pane); + + + return gui; + } + private static void destroyShopAndBlock(Block block, VirtualChest virtualChest){ + block.breakNaturally(); + virtualChest.deleteSelfAndShops(); } } \ No newline at end of file diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index 27f75fc..801f107 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -50,6 +50,10 @@ marker: primary: "První pozice označena (,,)" secondary: "Druhá pozice označena (,,)" menu: + destroy-confirmation: + title: "Zníčit obchod?" + confirm: "Ano." + cancel: "Ne." island-selector: title: "Výběr ostrovu" my-islands: "Moje ostrovy"