diff --git a/src/main/java/com/garbagemule/MobArena/ArenaClass.java b/src/main/java/com/garbagemule/MobArena/ArenaClass.java index cd747870..11ab28bd 100644 --- a/src/main/java/com/garbagemule/MobArena/ArenaClass.java +++ b/src/main/java/com/garbagemule/MobArena/ArenaClass.java @@ -268,6 +268,9 @@ public void grantItems(Player p) { if (arena != null) { try { arena.getInventoryManager().equip(p); + if (arena.isKeepDrops()) { + arena.getInventoryManager().setOriginalItemsPDC(arena.getPlugin(), p); + } removeBannedItems(p.getInventory()); } catch (Exception e) { am.getPlugin().getLogger().severe("Failed to give " + p.getName() + " their own items: " + e.getMessage()); diff --git a/src/main/java/com/garbagemule/MobArena/ArenaImpl.java b/src/main/java/com/garbagemule/MobArena/ArenaImpl.java index c32b2e78..8a1031a7 100644 --- a/src/main/java/com/garbagemule/MobArena/ArenaImpl.java +++ b/src/main/java/com/garbagemule/MobArena/ArenaImpl.java @@ -1,15 +1,9 @@ package com.garbagemule.MobArena; -import static com.garbagemule.MobArena.util.config.ConfigUtils.makeSection; - import com.garbagemule.MobArena.ScoreboardManager.NullScoreboardManager; import com.garbagemule.MobArena.announce.Announcer; import com.garbagemule.MobArena.announce.MessengerAnnouncer; import com.garbagemule.MobArena.announce.TitleAnnouncer; -import com.garbagemule.MobArena.steps.Step; -import com.garbagemule.MobArena.steps.StepFactory; -import com.garbagemule.MobArena.steps.PlayerJoinArena; -import com.garbagemule.MobArena.steps.PlayerSpecArena; import com.garbagemule.MobArena.events.ArenaEndEvent; import com.garbagemule.MobArena.events.ArenaPlayerDeathEvent; import com.garbagemule.MobArena.events.ArenaPlayerJoinEvent; @@ -22,6 +16,12 @@ import com.garbagemule.MobArena.repairable.Repairable; import com.garbagemule.MobArena.repairable.RepairableComparator; import com.garbagemule.MobArena.repairable.RepairableContainer; +import com.garbagemule.MobArena.steps.CompositeStep; +import com.garbagemule.MobArena.steps.KeepDropsStep; +import com.garbagemule.MobArena.steps.PlayerJoinArena; +import com.garbagemule.MobArena.steps.PlayerSpecArena; +import com.garbagemule.MobArena.steps.Step; +import com.garbagemule.MobArena.steps.StepFactory; import com.garbagemule.MobArena.things.InvalidThingInputString; import com.garbagemule.MobArena.things.Thing; import com.garbagemule.MobArena.things.ThingPicker; @@ -73,8 +73,9 @@ import java.util.logging.Level; import java.util.stream.Collectors; -public class ArenaImpl implements Arena -{ +import static com.garbagemule.MobArena.util.config.ConfigUtils.makeSection; + +public class ArenaImpl implements Arena { // General stuff private MobArena plugin; private String name; @@ -98,10 +99,10 @@ public class ArenaImpl implements Arena private Leaderboard leaderboard; // Player stuff - private InventoryManager inventoryManager; - private RewardManager rewardManager; + private InventoryManager inventoryManager; + private RewardManager rewardManager; private ClassLimitManager limitManager; - private Map arenaPlayerMap; + private Map arenaPlayerMap; private Set arenaPlayers, lobbyPlayers, readyPlayers, specPlayers, deadPlayers; private Set movingPlayers; @@ -110,20 +111,20 @@ public class ArenaImpl implements Arena // Classes stuff private ArenaClass defaultClass; - private Map classes; + private Map classes; // Blocks and pets private PriorityBlockingQueue repairQueue; - private Set blocks; + private Set blocks; private LinkedList repairables, containables; // Monster stuff private MonsterManager monsterManager; // Wave stuff - private WaveManager waveManager; + private WaveManager waveManager; private MASpawnThread spawnThread; - private SheepBouncer sheepBouncer; + private SheepBouncer sheepBouncer; private Map everyWaveMap, afterWaveMap; // Misc @@ -132,6 +133,7 @@ public class ArenaImpl implements Arena private AutoStartTimer autoStartTimer; private StartDelayTimer startDelayTimer; private boolean isolatedChat; + private boolean keepDrops; // Warp offsets private double arenaWarpOffset; @@ -156,37 +158,37 @@ public ArenaImpl(MobArena plugin, ConfigurationSection section, String name, Wor if (world == null) throw new NullPointerException("[MobArena] ERROR! World for arena '" + name + "' does not exist!"); - this.name = name; - this.slug = Slugs.create(name); - this.world = world; - this.plugin = plugin; + this.name = name; + this.slug = Slugs.create(name); + this.world = world; + this.plugin = plugin; this.settings = makeSection(section, "settings"); - this.region = new ArenaRegion(section, this); + this.region = new ArenaRegion(section, this); this.enabled = settings.getBoolean("enabled", false); this.protect = settings.getBoolean("protect", true); this.running = false; - this.edit = false; + this.edit = false; this.inventoryManager = new InventoryManager(); - this.rewardManager = new RewardManager(this); + this.rewardManager = new RewardManager(this); // Warps, points and locations this.leaderboard = new Leaderboard(plugin, this, region.getLeaderboard()); // Player stuff this.arenaPlayerMap = new HashMap<>(); - this.arenaPlayers = new HashSet<>(); - this.lobbyPlayers = new HashSet<>(); - this.readyPlayers = new HashSet<>(); - this.specPlayers = new HashSet<>(); - this.deadPlayers = new HashSet<>(); - this.randoms = new HashSet<>(); - this.movingPlayers = new HashSet<>(); + this.arenaPlayers = new HashSet<>(); + this.lobbyPlayers = new HashSet<>(); + this.readyPlayers = new HashSet<>(); + this.specPlayers = new HashSet<>(); + this.deadPlayers = new HashSet<>(); + this.randoms = new HashSet<>(); + this.movingPlayers = new HashSet<>(); this.leavingPlayers = new HashSet<>(); // Classes, items and permissions - this.classes = plugin.getArenaMaster().getClasses(); + this.classes = plugin.getArenaMaster().getClasses(); this.limitManager = new ClassLimitManager(this, classes, makeSection(section, "class-limits")); String defaultClassName = settings.getString("default-class", null); @@ -196,23 +198,23 @@ public ArenaImpl(MobArena plugin, ConfigurationSection section, String name, Wor } // Blocks and pets - this.repairQueue = new PriorityBlockingQueue<>(100, new RepairableComparator()); - this.blocks = new HashSet<>(); - this.repairables = new LinkedList<>(); + this.repairQueue = new PriorityBlockingQueue<>(100, new RepairableComparator()); + this.blocks = new HashSet<>(); + this.repairables = new LinkedList<>(); this.containables = new LinkedList<>(); // Monster stuff this.monsterManager = new MonsterManager(); // Wave stuff - this.waveManager = new WaveManager(this, section.getConfigurationSection("waves")); + this.waveManager = new WaveManager(this, section.getConfigurationSection("waves")); this.everyWaveMap = MAUtils.getArenaRewardMap(plugin, section, name, "every"); this.afterWaveMap = MAUtils.getArenaRewardMap(plugin, section, name, "after"); // Misc this.eventListener = new ArenaListener(this, plugin); this.allowMonsters = world.getAllowMonsters(); - this.allowAnimals = world.getAllowAnimals(); + this.allowAnimals = world.getAllowAnimals(); this.entryFee = new ArrayList<>(); String feeString = settings.getString("entry-fee", ""); @@ -227,10 +229,12 @@ public ArenaImpl(MobArena plugin, ConfigurationSection section, String name, Wor } } - this.autoStartTimer = new AutoStartTimer(this); + this.autoStartTimer = new AutoStartTimer(this); this.startDelayTimer = new StartDelayTimer(this, autoStartTimer); - this.isolatedChat = settings.getBoolean("isolated-chat", false); + this.isolatedChat = settings.getBoolean("isolated-chat", false); + + this.keepDrops = settings.getBoolean("keep-drops", false); this.arenaWarpOffset = settings.getDouble("arena-warp-offset", 0.0); @@ -451,14 +455,10 @@ public ScoreboardManager getScoreboard() { return scoreboard; } - - - - - - - - + @Override + public boolean isKeepDrops() { + return keepDrops; + } @Override public Messenger getMessenger() { @@ -652,8 +652,7 @@ public boolean endArena() { } @Override - public void forceStart() - { + public void forceStart() { if (running) return; @@ -696,8 +695,7 @@ public boolean hasPermission(Player p) { } @Override - public boolean playerJoin(Player p, Location loc) - { + public boolean playerJoin(Player p, Location loc) { // Fire the event and check if it's been cancelled. ArenaPlayerJoinEvent event = new ArenaPlayerJoinEvent(p, this); plugin.getServer().getPluginManager().callEvent(event); @@ -774,8 +772,7 @@ public boolean playerJoin(Player p, Location loc) } @Override - public void playerReady(Player p) - { + public void playerReady(Player p) { ArenaPlayerReadyEvent event = new ArenaPlayerReadyEvent(p, this); plugin.getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { @@ -785,8 +782,7 @@ public void playerReady(Player p) readyPlayers.add(p); int minPlayers = getMinPlayers(); - if (minPlayers > 0 && lobbyPlayers.size() < minPlayers) - { + if (minPlayers > 0 && lobbyPlayers.size() < minPlayers) { messenger.tell(p, Msg.LOBBY_NOT_ENOUGH_PLAYERS, "" + minPlayers); return; } @@ -795,8 +791,7 @@ public void playerReady(Player p) } @Override - public boolean playerLeave(Player p) - { + public boolean playerLeave(Player p) { // Fire the event and check if it's been cancelled. ArenaPlayerLeaveEvent event = new ArenaPlayerLeaveEvent(p, this); plugin.getServer().getPluginManager().callEvent(event); @@ -859,8 +854,7 @@ public boolean isLeaving(Player p) { } @Override - public void playerDeath(Player p) - { + public void playerDeath(Player p) { // Check if we're the last player standing boolean last = arenaPlayers.size() == 1; if (last) lastStanding = p; @@ -875,6 +869,19 @@ public void playerDeath(Player p) // Clear the player's inventory, and unmount if (arenaPlayers.remove(p)) { unmount(p); + if (this.keepDrops) { + this.inventoryManager.removeOriginalItems(plugin, p); + final Step step = histories.get(p); + if (step != null) { + final Step keepDropsStep = KeepDropsStep.create(this).create(p); + keepDropsStep.run(); + final Step composite = CompositeStep.create( + step, + keepDropsStep + ).create(p); + histories.put(p, composite); + } + } clearInv(p); } @@ -926,7 +933,7 @@ public void revivePlayer(Player p) { } plugin.getServer().getScheduler() - .scheduleSyncDelayedTask(plugin, () -> playerLeave(p)); + .scheduleSyncDelayedTask(plugin, () -> playerLeave(p)); } @Override @@ -961,13 +968,16 @@ public void playerSpec(Player p, Location loc) { } private void rollback(Player p) { + Step step = histories.remove(p); if (step == null) { return; } try { + this.inventoryManager.removeOriginalItems(this.plugin, p); step.undo(); } catch (Exception e) { + e.printStackTrace(); plugin.getLogger().log(Level.SEVERE, () -> "Failed to revert player " + p.getName()); } } @@ -1028,20 +1038,29 @@ private void spawnMounts() { private EntityType horseTypeFromAmount(int amount) { switch (amount % 8) { - case 2: return EntityType.DONKEY; - case 3: return EntityType.MULE; - case 4: return EntityType.SKELETON_HORSE; - case 5: return EntityType.ZOMBIE_HORSE; - default: return EntityType.HORSE; + case 2: + return EntityType.DONKEY; + case 3: + return EntityType.MULE; + case 4: + return EntityType.SKELETON_HORSE; + case 5: + return EntityType.ZOMBIE_HORSE; + default: + return EntityType.HORSE; } } private Material bardingFromAmount(int amount) { switch ((amount >> 3) % 4) { - case 1: return Material.IRON_HORSE_ARMOR; - case 2: return Material.GOLDEN_HORSE_ARMOR; - case 3: return Material.DIAMOND_HORSE_ARMOR; - default: return null; + case 1: + return Material.IRON_HORSE_ARMOR; + case 2: + return Material.GOLDEN_HORSE_ARMOR; + case 3: + return Material.DIAMOND_HORSE_ARMOR; + default: + return null; } } @@ -1101,8 +1120,7 @@ private void stopBouncingSheep() { } @Override - public void storeContainerContents() - { + public void storeContainerContents() { for (Location loc : region.getContainers()) { BlockState state = world.getBlockAt(loc).getState(); if (state instanceof InventoryHolder) { @@ -1112,23 +1130,20 @@ public void storeContainerContents() } @Override - public void restoreContainerContents() - { + public void restoreContainerContents() { for (Repairable r : containables) { r.repair(); } } @Override - public void discardPlayer(Player p) - { + public void discardPlayer(Player p) { rollback(p); plugin.getArenaMaster().removePlayer(p); clearPlayer(p); } - private void clearPlayer(Player p) - { + private void clearPlayer(Player p) { // Remove from boss health bar monsterManager.getBossMonsters().forEach(entity -> { MABoss boss = monsterManager.getBoss(entity); @@ -1148,15 +1163,13 @@ private void clearPlayer(Player p) } @Override - public void repairBlocks() - { + public void repairBlocks() { while (!repairQueue.isEmpty()) repairQueue.poll().repair(); } @Override - public void queueRepairable(Repairable r) - { + public void queueRepairable(Repairable r) { repairQueue.add(r); } @@ -1171,7 +1184,7 @@ public void queueRepairable(Repairable r) @Override public void assignClass(Player p, String className) { ArenaPlayer arenaPlayer = arenaPlayerMap.get(p); - ArenaClass arenaClass = classes.get(className); + ArenaClass arenaClass = classes.get(className); if (arenaPlayer == null || arenaClass == null) { return; @@ -1203,7 +1216,7 @@ public void assignClass(Player p, String className) { @Override public void assignClassGiveInv(Player p, String className, ItemStack[] source) { ArenaPlayer arenaPlayer = arenaPlayerMap.get(p); - ArenaClass arenaClass = classes.get(className); + ArenaClass arenaClass = classes.get(className); if (arenaPlayer == null || arenaClass == null) { return; @@ -1232,7 +1245,7 @@ public void assignClassGiveInv(Player p, String className, ItemStack[] source) { ItemStack offhand = null; // Check the very last slot to see if it'll work as a helmet - int last = contents.length-1; + int last = contents.length - 1; if (contents[last] != null) { helmet = contents[last]; if (arenaClass.hasUnbreakableArmor()) { @@ -1242,7 +1255,7 @@ public void assignClassGiveInv(Player p, String className, ItemStack[] source) { } // Check the remaining three of the four last slots for armor - for (int i = contents.length-1; i > contents.length-5; i--) { + for (int i = contents.length - 1; i > contents.length - 5; i--) { if (contents[i] == null) continue; String[] parts = contents[i].getType().name().split("_"); @@ -1255,10 +1268,17 @@ public void assignClassGiveInv(Player p, String className, ItemStack[] source) { } switch (type) { case "ELYTRA": - case "CHESTPLATE": chestplate = stack; break; - case "LEGGINGS": leggings = stack; break; - case "BOOTS": boots = stack; break; - default: break; + case "CHESTPLATE": + chestplate = stack; + break; + case "LEGGINGS": + leggings = stack; + break; + case "BOOTS": + boots = stack; + break; + default: + break; } contents[i] = null; } @@ -1324,11 +1344,10 @@ public void addRandomPlayer(Player p) { } @Override - public void assignRandomClass(Player p) - { + public void assignRandomClass(Player p) { List classes = this.classes.values().stream() - .filter(c -> c.hasPermission(p)) - .collect(Collectors.toList()); + .filter(c -> c.hasPermission(p)) + .collect(Collectors.toList()); if (classes.isEmpty()) { plugin.getLogger().info("Player '" + p.getName() + "' has no class permissions!"); @@ -1358,16 +1377,16 @@ private void addClassPermissions(Player player) { private void removePermissionAttachments(Player player) { player.getEffectivePermissions().stream() - .filter(info -> info.getAttachment() != null) - .filter(info -> info.getAttachment().getPlugin().equals(plugin)) - .map(PermissionAttachmentInfo::getAttachment) - .forEach(PermissionAttachment::remove); + .filter(info -> info.getAttachment() != null) + .filter(info -> info.getAttachment().getPlugin().equals(plugin)) + .map(PermissionAttachmentInfo::getAttachment) + .forEach(PermissionAttachment::remove); } private void removePotionEffects(Player p) { p.getActivePotionEffects().stream() - .map(PotionEffect::getType) - .forEach(p::removePotionEffect); + .map(PotionEffect::getType) + .forEach(p::removePotionEffect); } private void cleanup() { @@ -1427,8 +1446,7 @@ private void clearPlayers() { ////////////////////////////////////////////////////////////////////*/ @Override - public void restoreRegion() - { + public void restoreRegion() { Collections.sort(repairables, new RepairableComparator()); for (Repairable r : repairables) @@ -1464,14 +1482,12 @@ public boolean isDead(Player p) { } @Override - public String configName() - { + public String configName() { return name; } @Override - public String arenaName() - { + public String arenaName() { return name; } @@ -1481,26 +1497,22 @@ public String getSlug() { } @Override - public MobArena getPlugin() - { + public MobArena getPlugin() { return plugin; } @Override - public Map getClasses() - { + public Map getClasses() { return classes; } @Override - public int getPlayerCount() - { + public int getPlayerCount() { return spawnThread.getPlayerCount(); } @Override - public List getAllPlayers() - { + public List getAllPlayers() { List result = new LinkedList<>(); result.addAll(arenaPlayers); result.addAll(lobbyPlayers); @@ -1510,8 +1522,7 @@ public List getAllPlayers() } @Override - public Collection getArenaPlayerSet() - { + public Collection getArenaPlayerSet() { return arenaPlayerMap.values(); } @@ -1533,8 +1544,7 @@ public List getArenaPlayerStatistics(Comparator getNonreadyPlayers() - { + public List getNonreadyPlayers() { List result = new LinkedList<>(); result.addAll(lobbyPlayers); result.removeAll(readyPlayers); @@ -1640,7 +1650,7 @@ public boolean equals(Object other) { if (getClass() != other.getClass()) return false; // Arenas must have different names. - if (other instanceof ArenaImpl && ((ArenaImpl)other).name.equals(name)) + if (other instanceof ArenaImpl && ((ArenaImpl) other).name.equals(name)) return true; return false; diff --git a/src/main/java/com/garbagemule/MobArena/framework/Arena.java b/src/main/java/com/garbagemule/MobArena/framework/Arena.java index 44c64d11..8f7f8486 100644 --- a/src/main/java/com/garbagemule/MobArena/framework/Arena.java +++ b/src/main/java/com/garbagemule/MobArena/framework/Arena.java @@ -64,6 +64,8 @@ public interface Arena int getMaxPlayers(); + boolean isKeepDrops(); + List getEntryFee(); Set> getEveryWaveEntrySet(); diff --git a/src/main/java/com/garbagemule/MobArena/steps/CompositeStep.java b/src/main/java/com/garbagemule/MobArena/steps/CompositeStep.java new file mode 100644 index 00000000..09b28f8a --- /dev/null +++ b/src/main/java/com/garbagemule/MobArena/steps/CompositeStep.java @@ -0,0 +1,34 @@ +package com.garbagemule.MobArena.steps; + +import org.bukkit.entity.Player; + +public class CompositeStep extends PlayerStep { + + private final Step original; + private final Step next; + + + private CompositeStep(Player player, Step original, Step next) { + super(player); + this.original = original; + this.next = next; + } + + @Override + public void run() { + this.original.run(); + this.next.run(); + } + + @Override + public void undo() { + this.original.undo(); + this.next.undo(); + } + + + public static StepFactory create(Step original, Step next) { + return player -> new CompositeStep(player, original, next); + } + +} diff --git a/src/main/java/com/garbagemule/MobArena/steps/KeepDropsStep.java b/src/main/java/com/garbagemule/MobArena/steps/KeepDropsStep.java new file mode 100644 index 00000000..e7cbea41 --- /dev/null +++ b/src/main/java/com/garbagemule/MobArena/steps/KeepDropsStep.java @@ -0,0 +1,71 @@ +package com.garbagemule.MobArena.steps; + +import com.garbagemule.MobArena.framework.Arena; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.logging.Level; + +public class KeepDropsStep extends PlayerStep { + + private final File keepDrops; + private final Arena arena; + + private ItemStack[] contents; + private File backup; + + private KeepDropsStep(Player player, Arena arena) { + super(player); + this.keepDrops = new File(arena.getPlugin().getDataFolder(), "extra-drops"); + this.arena = arena; + } + + @Override + public void run() { + contents = player.getInventory().getContents(); + createBackup(); + + player.getInventory().clear(); + } + + @Override + public void undo() { + for (ItemStack itemStack : contents) { + if (itemStack == null) continue; + player.getInventory().addItem(itemStack); + } + + arena.getInventoryManager().removeKeepDrops(player); + deleteBackup(); + } + + private void createBackup() { + arena.getInventoryManager().removeOriginalItems(arena.getPlugin(), player); + YamlConfiguration yaml = new YamlConfiguration(); + yaml.set("contents", contents); + + backup = new File(keepDrops, player.getUniqueId().toString()); + try { + yaml.save(backup); + } catch (IOException e) { + throw new RuntimeException("Failed to store keep-drops for " + player.getName(), e); + } + arena.getInventoryManager().putKeepDrops(player, contents); + } + + private void deleteBackup() { + try { + Files.delete(backup.toPath()); + } catch (IOException e) { + arena.getPlugin().getLogger().log(Level.WARNING, "Couldn't delete backup inventory file for " + player.getName(), e); + } + } + + public static StepFactory create(Arena arena) { + return player -> new KeepDropsStep(player, arena); + } +} diff --git a/src/main/java/com/garbagemule/MobArena/util/inventory/InventoryManager.java b/src/main/java/com/garbagemule/MobArena/util/inventory/InventoryManager.java index b8567715..3e8c37eb 100644 --- a/src/main/java/com/garbagemule/MobArena/util/inventory/InventoryManager.java +++ b/src/main/java/com/garbagemule/MobArena/util/inventory/InventoryManager.java @@ -2,12 +2,15 @@ import com.garbagemule.MobArena.MobArena; import org.bukkit.Material; +import org.bukkit.NamespacedKey; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; import java.io.File; import java.util.HashMap; @@ -16,16 +19,28 @@ public class InventoryManager { + private static final String ORIGINAL_ITEM_KEY = "original-item"; + private Map inventories; + private Map keepDrops; public InventoryManager() { this.inventories = new HashMap<>(); + this.keepDrops = new HashMap<>(); } public void put(Player p, ItemStack[] contents) { inventories.put(p, contents); } + public void putKeepDrops(Player p, ItemStack[] contents) { + keepDrops.put(p, contents); + } + + public ItemStack[] getKeepDrops(Player p) { + return keepDrops.get(p); + } + public void equip(Player p) { ItemStack[] contents = inventories.get(p); if (contents == null) { @@ -34,10 +49,44 @@ public void equip(Player p) { p.getInventory().setContents(contents); } + /** + * Sets PDC on the player's items from when they first joined the arena + * So that item drops in the arena can be kept when they leave + */ + public void setOriginalItemsPDC(MobArena plugin, Player player) { + final NamespacedKey key = new NamespacedKey(plugin, ORIGINAL_ITEM_KEY); + for (ItemStack itemStack : player.getInventory().getContents()) { + if (itemStack == null) continue; + final ItemMeta itemMeta = itemStack.getItemMeta(); + if (itemMeta == null) continue; + itemMeta.getPersistentDataContainer().set(key, PersistentDataType.BYTE, (byte) 1); + itemStack.setItemMeta(itemMeta); + } + } + + public void removeOriginalItems(MobArena plugin, Player player) { + final NamespacedKey key = new NamespacedKey(plugin, ORIGINAL_ITEM_KEY); + final ItemStack[] contents = player.getInventory().getContents(); + for (int i = 0; i < contents.length; i++) { + final ItemStack itemStack = contents[i]; + if (itemStack == null) continue; + final ItemMeta itemMeta = itemStack.getItemMeta(); + if (itemMeta == null) continue; + if (itemMeta.getPersistentDataContainer().has(key, PersistentDataType.BYTE)) { + itemStack.setType(Material.AIR); + player.getInventory().clear(i); + } + } + } + public void remove(Player p) { inventories.remove(p); } + public void removeKeepDrops(Player p) { + keepDrops.remove(p); + } + /** * Clear a player's inventory completely. * @param p a player @@ -83,6 +132,8 @@ public static boolean restoreFromFile(MobArena plugin, Player p) { File inventories = new File(plugin.getDataFolder(), "inventories"); File file = new File(inventories, p.getUniqueId().toString()); + restoreKeepDrops(plugin, p); + if (!file.exists()) { return false; } @@ -100,4 +151,25 @@ public static boolean restoreFromFile(MobArena plugin, Player p) { return false; } } + + private static void restoreKeepDrops(MobArena plugin, Player p) { + try { + File inventories = new File(plugin.getDataFolder(), "keep-drops"); + File file = new File(inventories, p.getUniqueId().toString()); + + if (!file.exists()) { + return; + } + + YamlConfiguration config = new YamlConfiguration(); + config.load(file); + + ItemStack[] contents = config.getList("extra-drops").toArray(new ItemStack[0]); + p.getInventory().addItem(contents); + + file.delete(); + } catch (Exception e) { + plugin.getLogger().log(Level.SEVERE, "Failed to restore extra drops for " + p.getName(), e); + } + } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index d1fef926..6cab255f 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -3,7 +3,8 @@ author: garbagemule main: com.garbagemule.MobArena.MobArena version: '${project.version}' api-version: 1.13 -softdepend: [Multiverse-Core,Towny,Heroes,MagicSpells,Vault] +softdepend: [Multiverse-Core,Towny,Heroes,MagicSpells,Vault,AdvancedEnchantments] +loadbefore: [AdvancedEnchantments] commands: ma: description: Base command for MobArena diff --git a/src/main/resources/res/settings.yml b/src/main/resources/res/settings.yml index b2a7f373..b63d1cb6 100644 --- a/src/main/resources/res/settings.yml +++ b/src/main/resources/res/settings.yml @@ -44,6 +44,7 @@ display-waves-as-level: false display-timer-as-level: false use-scoreboards: true isolated-chat: false +keep-drops: false announcer-type: title global-join-announce: false global-end-announce: false