diff --git a/src/main/java/de/fanta/challenges/gravestones/GravestoneListener.java b/src/main/java/de/fanta/challenges/gravestones/GravestoneListener.java new file mode 100644 index 0000000..44a208a --- /dev/null +++ b/src/main/java/de/fanta/challenges/gravestones/GravestoneListener.java @@ -0,0 +1,113 @@ +package de.fanta.challenges.gravestones; + +import de.fanta.challenges.Challenges; +import de.fanta.challenges.utils.ChatUtil; +import org.bukkit.NamespacedKey; +import org.bukkit.block.Block; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerArmorStandManipulateEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class GravestoneListener implements Listener { + + private static final Challenges plugin = Challenges.getPlugin(); + + @EventHandler + public void onDeath(PlayerDeathEvent e) { + if (!plugin.getConfig().getBoolean("gravestone")) { + return; + } + e.getDrops().clear(); + Player p = e.getPlayer(); + Block block = p.getLocation().subtract(0, 1, 0).getBlock(); + String inventoryString = GravestoneUtils.createInventoryString(p); + byte[] inventoryByte = GravestoneUtils.compressString(inventoryString); + GravestoneUtils.spawnAtBlock(block, e.getPlayer(), inventoryByte); + } + + @EventHandler + public void onEquip(PlayerArmorStandManipulateEvent e) { + ArmorStand stand = e.getRightClicked(); + PersistentDataContainer container = stand.getPersistentDataContainer(); + if (container.has(GravestoneUtils.getInventoryKey())) { + e.setCancelled(true); + } + + } + + @EventHandler + public void onEntityDamage(EntityDamageEvent e) { + if (e.getEntity() instanceof ArmorStand stand) { + PersistentDataContainer container = stand.getPersistentDataContainer(); + if (container.has(GravestoneUtils.getInventoryKey())) { + e.setCancelled(true); + } + } + } + + @EventHandler + public void onGravestoneAttack(EntityDamageByEntityEvent e) { + if (!(e.getDamager() instanceof Player player)) { + return; + } + + if (!(e.getEntity() instanceof ArmorStand armorStand)) { + return; + } + + PersistentDataContainer container = armorStand.getPersistentDataContainer(); + NamespacedKey UUIDKey = GravestoneUtils.getUUIDKey(); + if (container.has(UUIDKey)) { + if (!plugin.getConfig().getBoolean("gravestone")) { + ChatUtil.sendWarningMessage(player, "Grabschsteine können nur gegrabscht werden wenn sie Aktiv sind."); + return; + } + String playerUUID = container.get(UUIDKey, PersistentDataType.STRING); + if (playerUUID.equals(player.getUniqueId().toString())) { + NamespacedKey InventoryKey = GravestoneUtils.getInventoryKey(); + byte[] inventorybyte = container.get(InventoryKey, PersistentDataType.BYTE_ARRAY); + String yamlstring = GravestoneUtils.decompressString(inventorybyte); + try { + YamlConfiguration conf = new YamlConfiguration(); + conf.loadFromString(yamlstring); + List stacks = (List) conf.getList("inv"); + List fullinvstacklist = new ArrayList<>(); + for (int i = 0; i < stacks.size(); i++) { + ItemStack stack = stacks.get(i); + if (stack != null) { + if (player.getInventory().getItem(i) == null) { + player.getInventory().setItem(i, stack); + } else { + fullinvstacklist.add(stack); + } + } + } + Collection droplist = player.getInventory().addItem(fullinvstacklist.toArray(new ItemStack[fullinvstacklist.size()])).values(); + for (ItemStack stack : droplist) { + armorStand.getLocation().getWorld().dropItem(armorStand.getLocation(), stack); + } + } catch (InvalidConfigurationException ex) { + ex.printStackTrace(); + } + armorStand.remove(); + } else { + ChatUtil.sendWarningMessage(player, "Du kannst nur deine eigenen Grabschsteine grabschen."); + } + } + + } +} diff --git a/src/main/java/de/fanta/challenges/gravestones/GravestoneUtils.java b/src/main/java/de/fanta/challenges/gravestones/GravestoneUtils.java new file mode 100644 index 0000000..48c2145 --- /dev/null +++ b/src/main/java/de/fanta/challenges/gravestones/GravestoneUtils.java @@ -0,0 +1,124 @@ +package de.fanta.challenges.gravestones; + +import de.fanta.challenges.Challenges; +import de.iani.cubesideutils.bukkit.items.ItemGroups; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.data.type.Slab; +import org.bukkit.block.data.type.Snow; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; +import java.util.Random; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.InflaterInputStream; + +public class GravestoneUtils { + + protected static final Random random = new Random(); + + private static final NamespacedKey UUIDKey = new NamespacedKey(Challenges.getPlugin(), "uuid_gravestone"); + private static final NamespacedKey inventoryKey = new NamespacedKey(Challenges.getPlugin(), "inventory_gravestone"); + + public static byte[] compressString(String s) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + OutputStreamWriter osw = new OutputStreamWriter(new DeflaterOutputStream(baos, new Deflater(Deflater.BEST_COMPRESSION)), StandardCharsets.UTF_8); + osw.write(s); + osw.flush(); + osw.close(); + } catch (IOException e) { + throw new RuntimeException("Could not compress data", e); + } + return baos.toByteArray(); + } + + public static String decompressString(byte[] data) { + try { + InputStreamReader reader = new InputStreamReader(new InflaterInputStream(new ByteArrayInputStream(data)), StandardCharsets.UTF_8); + StringBuilder sb = new StringBuilder(); + char[] temp = new char[1024]; + while (true) { + int readBytes; + readBytes = reader.read(temp); + if (readBytes < 0) { + break; + } + sb.append(temp, 0, readBytes); + } + return sb.toString(); + } catch (IOException e) { + throw new RuntimeException("Error while decompressing inventory string", e); + } + } + + public static String createInventoryString(Player player) { + YamlConfiguration conf = new YamlConfiguration(); + ItemStack[] inventory = player.getInventory().getContents(); + conf.set("inv", inventory); + return conf.saveToString(); + } + + + public static void spawnAtBlock(Block block, Player player, byte[] inventoryBytes) { + World world = block.getWorld(); + double y = block.getY(); + Material type = block.getType(); + String typeName = type.name(); + double placeableY; + if (typeName.endsWith("_SLAB")) { + Slab slab = (Slab) block.getBlockData(); + placeableY = y - 0.44; + if (slab.getType() == Slab.Type.BOTTOM) { + placeableY -= 0.5; + } + } else if (typeName.endsWith("_STAIRS") || type.isOccluding() || type == Material.GLASS || ItemGroups.isStainedGlass(type) || type == Material.ICE || type == Material.PACKED_ICE || type == Material.BLUE_ICE || ItemGroups.isLeaves(type)) { + placeableY = y - 0.44; + } else if (ItemGroups.isCarpet(type)) { + placeableY = y - 1.44 + (1 / 16.0); + } else if (type == Material.SNOW) { + Snow snow = (Snow) block.getBlockData(); + int layers = snow.getLayers(); + placeableY = y - 1.44 + (layers / 8.0); + } else { + placeableY = y - 0.44; + } + if (!Double.isNaN(placeableY)) { + world.spawn(new Location(world, block.getX() + 0.5, placeableY, block.getZ() + 0.5, player.getLocation().getYaw(), 0), ArmorStand.class, t -> { + t.setVisible(false); + t.setGravity(false); + ItemStack itemStack = new ItemStack(Material.PLAYER_HEAD, 1); + SkullMeta meta = (SkullMeta) itemStack.getItemMeta(); + meta.setOwner(player.getName()); + itemStack.setItemMeta(meta); + t.getEquipment().setHelmet(itemStack); + PersistentDataContainer container = t.getPersistentDataContainer(); + container.set(UUIDKey, PersistentDataType.STRING, player.getUniqueId().toString()); + container.set(inventoryKey, PersistentDataType.BYTE_ARRAY, inventoryBytes); + }); + } + } + + public static NamespacedKey getUUIDKey() { + return UUIDKey; + } + + public static NamespacedKey getInventoryKey() { + return inventoryKey; + } +} diff --git a/src/main/java/de/fanta/challenges/guis/settingsgui/OtherSettingsGui.java b/src/main/java/de/fanta/challenges/guis/settingsgui/OtherSettingsGui.java index 00bb145..7b2b413 100644 --- a/src/main/java/de/fanta/challenges/guis/settingsgui/OtherSettingsGui.java +++ b/src/main/java/de/fanta/challenges/guis/settingsgui/OtherSettingsGui.java @@ -14,20 +14,21 @@ public class OtherSettingsGui implements Listener { - public static final int INVENTORY_SIZE = 27; + public static final int INVENTORY_SIZE = 36; private static final Challenges plugin = Challenges.getPlugin(); public static final Inventory OTHER_SETTINGS_GUI = Bukkit.createInventory(null, INVENTORY_SIZE, plugin.getGUIPREFIX() + " >> Other Settings"); - private static final int BACK_INDEX = 18; - private static final int BACKPACK_INDEX = 10; + private static final int BACK_INDEX = 27; + private static final int BACKPACK_INDEX = 16; private static final int DMG_INCHAT_INDEX = 11; private static final int TELEPORT_COMMAND_INDEX = 12; private static final int TAB_HP_INDEX = 13; private static final int DIREKT_SMLET_INDEX = 14; private static final int FAST_FURNACE_INDEX = 15; - private static final int DISABLE_VILLAGER_TRADE_LIMITS_INDEX = 16; - private static final int BACKPACK_ADD_INDEX = 1; - private static final int BACKPACK_REMOVE_INDEX = 19; - private static final int CLOSE_IDEX = 26; + private static final int DISABLE_VILLAGER_TRADE_LIMITS_INDEX = 10; + private static final int BACKPACK_ADD_INDEX = 7; + private static final int BACKPACK_REMOVE_INDEX = 25; + private static final int GRAVESTONE_INDEX = 19; + private static final int CLOSE_IDEX = 35; public static void createOtherSettingsGUI(Player p) { OTHER_SETTINGS_GUI.setItem(BACKPACK_INDEX, GUIUtils.createGuiItem(Material.LIME_SHULKER_BOX, ChatUtil.GREEN + "Rucksack Größe: " + plugin.getBackpack().getSize() / 9 + "/6")); @@ -67,6 +68,11 @@ } else { OTHER_SETTINGS_GUI.setItem(FAST_FURNACE_INDEX, GUIUtils.createGuiItem(Material.FURNACE, ChatUtil.RED + "Schneller Ofen deaktiviert")); } + if (plugin.getConfig().getBoolean("gravestone")) { + OTHER_SETTINGS_GUI.setItem(GRAVESTONE_INDEX, GUIUtils.createGuiItem(Material.HOPPER, ChatUtil.GREEN + "Grabstein aktiviert", true)); + } else { + OTHER_SETTINGS_GUI.setItem(GRAVESTONE_INDEX, GUIUtils.createGuiItem(Material.HOPPER, ChatUtil.RED + "Grabstein deaktiviert")); + } if (plugin.getConfig().getBoolean("disablevillagertradelimits")) { OTHER_SETTINGS_GUI.setItem(DISABLE_VILLAGER_TRADE_LIMITS_INDEX, GUIUtils.createGuiItem(Material.EMERALD, ChatUtil.GREEN + "Villager Trade Limits aktiviert ", true)); } else { @@ -155,6 +161,15 @@ GUIUtils.setConfig("disablevillagertradelimits", true); } break; + case GRAVESTONE_INDEX: + if (plugin.getConfig().getBoolean("gravestone")) { + GUIUtils.sendTitleToAll("Einstellungen", "Grabsteine deaktiviert", ChatUtil.RED); + GUIUtils.setConfig("gravestone", false); + } else { + GUIUtils.sendTitleToAll("Einstellungen", "Grabsteine aktiviert", ChatUtil.GREEN); + GUIUtils.setConfig("gravestone", true); + } + break; } createOtherSettingsGUI(p); switch (slot) { diff --git a/src/main/java/de/fanta/challenges/listeners/EventRegistration.java b/src/main/java/de/fanta/challenges/listeners/EventRegistration.java index bbb5291..e49a8c2 100644 --- a/src/main/java/de/fanta/challenges/listeners/EventRegistration.java +++ b/src/main/java/de/fanta/challenges/listeners/EventRegistration.java @@ -2,6 +2,7 @@ import de.fanta.challenges.Challenges; import de.fanta.challenges.challenges.*; +import de.fanta.challenges.gravestones.GravestoneListener; import de.fanta.challenges.guis.ResetGui; import de.fanta.challenges.guis.TeleportGUI; import de.fanta.challenges.guis.TimerGui; @@ -40,6 +41,8 @@ pM.registerEvents(new CommandBlockListener(), plugin); pM.registerEvents(new TeleportGUI(), plugin); + pM.registerEvents(new GravestoneListener(), plugin); + pM.registerEvents(new ChallengeGoals(), plugin); pM.registerEvents(new RandomEffectChallenge(), plugin); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index ab45e79..5a1c675 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -28,6 +28,7 @@ worldborderlevelxp: 0 disablevillagertradelimits: false teleportcommand: false +gravestone: false #Mögliche werte: 1-6 backpack_size: 3 mlg: