mirror of
https://gitlab.com/phoenix-dvpmt/mmoitems.git
synced 2024-12-22 04:37:42 +01:00
Fixed soulbound when disabling 'keep-soulbound-on-death'
This commit is contained in:
parent
ebe041d8d5
commit
d1f2af29c3
@ -5,7 +5,7 @@ import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackMessage;
|
||||
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider;
|
||||
import io.lumine.mythic.lib.version.SpigotPlugin;
|
||||
import net.Indyuce.mmoitems.api.ItemTier;
|
||||
import net.Indyuce.mmoitems.api.SoulboundInfo;
|
||||
import net.Indyuce.mmoitems.api.DeathItemsHandler;
|
||||
import net.Indyuce.mmoitems.api.Type;
|
||||
import net.Indyuce.mmoitems.api.crafting.MMOItemUIFilter;
|
||||
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
|
||||
@ -263,8 +263,8 @@ public class MMOItems extends JavaPlugin {
|
||||
// Save player data
|
||||
PlayerData.getLoaded().forEach(data -> data.save(false));
|
||||
|
||||
// Drop abandonned soulbound items
|
||||
SoulboundInfo.getAbandonnedInfo().forEach(SoulboundInfo::dropItems);
|
||||
// Drop abandoned items
|
||||
DeathItemsHandler.getActive().forEach(info -> info.giveItems(true));
|
||||
|
||||
// Close inventories
|
||||
for (Player player : Bukkit.getOnlinePlayers())
|
||||
|
@ -0,0 +1,87 @@
|
||||
package net.Indyuce.mmoitems.api;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class DeathItemsHandler {
|
||||
|
||||
/**
|
||||
* Items that need to be given to the player whenever he respawns.
|
||||
*/
|
||||
private final List<ItemStack> items = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* If the player leaves the server before removing, the cached items will be
|
||||
* lost. the plugin saves the last location of the player to drop the items
|
||||
* when the server shuts down this way they are 'saved'
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* Used to store which items must be given back to which player
|
||||
*/
|
||||
private static final Map<UUID, DeathItemsHandler> INFO = new WeakHashMap<>();
|
||||
|
||||
/**
|
||||
* Instanced when a player dies if some Soulbound items must be kept in the
|
||||
* player's inventory and need to be cached before the player respawns.
|
||||
* <p>
|
||||
* If the player leaves the server leaving one object of this type in server
|
||||
* RAM, the cached items need to be dropped if the server closes before the
|
||||
* player respawns again.
|
||||
*/
|
||||
public DeathItemsHandler(@NotNull Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public void registerItem(@NotNull ItemStack item) {
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
public void registerIfNecessary() {
|
||||
if (!items.isEmpty()) INFO.put(player.getUniqueId(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forceDrop Should the items all drop on the ground
|
||||
*/
|
||||
public void giveItems(boolean forceDrop) {
|
||||
|
||||
// Drop all items on the ground
|
||||
if (forceDrop) for (ItemStack drop : items)
|
||||
player.getWorld().dropItem(player.getLocation(), drop);
|
||||
|
||||
// First try to add them to inventory
|
||||
else {
|
||||
final ItemStack[] toArray = this.items.toArray(new ItemStack[0]);
|
||||
for (ItemStack drop : player.getInventory().addItem(toArray).values())
|
||||
player.getWorld().dropItem(player.getLocation(), drop);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to add the items to the player's inventory, or drops them
|
||||
* on the ground if the player's inventory is full. In the meantime,
|
||||
* the player's item info is removed from the map.
|
||||
*
|
||||
* @param player Target player respawning
|
||||
*/
|
||||
public static void readAndRemove(@NotNull Player player) {
|
||||
final @Nullable DeathItemsHandler handler = INFO.remove(player.getUniqueId());
|
||||
if (handler != null) Bukkit.getScheduler().runTaskLater(MMOItems.plugin, () -> handler.giveItems(false), 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Soulbound info of players who have not clicked the respawn button
|
||||
* and yet have items cached in server RAM
|
||||
*/
|
||||
public static Collection<DeathItemsHandler> getActive() {
|
||||
return INFO.values();
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
package net.Indyuce.mmoitems.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class SoulboundInfo {
|
||||
|
||||
/*
|
||||
* Items that need to be given to the player whenever he respawns.
|
||||
*/
|
||||
private final List<ItemStack> items = new ArrayList<>();
|
||||
|
||||
/*
|
||||
* If the player leaves the server before removing, the cached items will be
|
||||
* lost. the plugin saves the last location of the player to drop the items
|
||||
* when the server shuts down this way they are 'saved'
|
||||
*/
|
||||
private final Location loc;
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* Used to store which items must be given back to which player
|
||||
*/
|
||||
private static final Map<UUID, SoulboundInfo> INFO = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Instanced when a player dies if some souljbound items must be kept in the
|
||||
* player's inventory and need to be cached before the player respawns.
|
||||
*
|
||||
* If the player leaves the server leaving one object of this type in server
|
||||
* RAM, the cached items need to be dropped if the server closes before the
|
||||
* player respawns again
|
||||
*/
|
||||
public SoulboundInfo(Player player) {
|
||||
this.player = player;
|
||||
loc = player.getLocation().clone();
|
||||
}
|
||||
|
||||
public void add(ItemStack item) {
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
public boolean hasItems() {
|
||||
return !items.isEmpty();
|
||||
}
|
||||
|
||||
public void setup() {
|
||||
INFO.put(player.getUniqueId(), this);
|
||||
}
|
||||
|
||||
public void giveItems() {
|
||||
for (ItemStack item : items)
|
||||
for (ItemStack drop : player.getInventory().addItem(item).values())
|
||||
player.getWorld().dropItem(player.getLocation(), drop);
|
||||
}
|
||||
|
||||
public void dropItems() {
|
||||
items.forEach(item -> loc.getWorld().dropItem(loc, item));
|
||||
}
|
||||
|
||||
public static void read(Player player) {
|
||||
if (INFO.containsKey(player.getUniqueId())) {
|
||||
INFO.get(player.getUniqueId()).giveItems();
|
||||
INFO.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Soulbound info of players who have not clicked the respawn button
|
||||
* and yet have items cached in server RAM
|
||||
*/
|
||||
public static Collection<SoulboundInfo> getAbandonnedInfo() {
|
||||
return INFO.values();
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import io.lumine.mythic.lib.api.event.armorequip.ArmorEquipEvent;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.api.player.EquipmentSlot;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.SoulboundInfo;
|
||||
import net.Indyuce.mmoitems.api.DeathItemsHandler;
|
||||
import net.Indyuce.mmoitems.api.Type;
|
||||
import net.Indyuce.mmoitems.api.interaction.util.InteractItem;
|
||||
import net.Indyuce.mmoitems.api.interaction.weapon.Weapon;
|
||||
@ -28,12 +28,12 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.*;
|
||||
|
||||
public class PlayerListener implements Listener {
|
||||
private final Map<Player, List<ItemStack>> deathItems = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Careful, MMOCore and MMOMana runs on LOWEST
|
||||
* MythicLib runs of LOWEST
|
||||
* MMOCore and MMOInventory runs on LOW
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void loadPlayerData(PlayerJoinEvent event) {
|
||||
MMOItems.plugin.getRecipes().refreshRecipeBook(event.getPlayer());
|
||||
PlayerData.load(event.getPlayer());
|
||||
@ -60,59 +60,40 @@ public class PlayerListener implements Listener {
|
||||
|
||||
/**
|
||||
* Prevent players from dropping items which are bound to them with a
|
||||
* soulbound. Items are cached inside a map waiting for the player to
|
||||
* Soulbound. Items are cached inside a map waiting for the player to
|
||||
* respawn. If he does not respawn the items are dropped on the ground, this
|
||||
* way there don't get lost
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onDeathForSoulbound(PlayerDeathEvent event) {
|
||||
if (event.getKeepInventory() || !MMOItems.plugin.getLanguage().keepSoulboundOnDeath)
|
||||
return;
|
||||
public void keepItemsOnDeath(PlayerDeathEvent event) {
|
||||
if (event.getKeepInventory()) return;
|
||||
|
||||
Player player = event.getEntity();
|
||||
SoulboundInfo soulboundInfo = new SoulboundInfo(player);
|
||||
final Player player = event.getEntity();
|
||||
final DeathItemsHandler soulboundInfo = new DeathItemsHandler(player);
|
||||
|
||||
Iterator<ItemStack> iterator = event.getDrops().iterator();
|
||||
final Iterator<ItemStack> iterator = event.getDrops().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
ItemStack item = iterator.next();
|
||||
NBTItem nbt = NBTItem.get(item);
|
||||
|
||||
if (nbt.hasTag("MMOITEMS_DISABLE_DEATH_DROP") && nbt.getBoolean("MMOITEMS_DISABLE_DEATH_DROP")) {
|
||||
iterator.remove();
|
||||
if (!deathItems.containsKey(player))
|
||||
deathItems.put(player, new ArrayList<>());
|
||||
|
||||
deathItems.get(player).add(item);
|
||||
}
|
||||
final ItemStack item = iterator.next();
|
||||
final NBTItem nbt = NBTItem.get(item);
|
||||
|
||||
/*
|
||||
* not a perfect check but it's very sufficient and so we avoid
|
||||
* Not a perfect check but it's very sufficient and so we avoid
|
||||
* using a JsonParser followed by map checkups in the SoulboundData
|
||||
* constructor
|
||||
*/
|
||||
else if (nbt.hasTag("MMOITEMS_SOULBOUND") && nbt.getString("MMOITEMS_SOULBOUND").contains(player.getUniqueId().toString())) {
|
||||
if ((MMOItems.plugin.getLanguage().keepSoulboundOnDeath && nbt.getBoolean("MMOITEMS_DISABLE_DEATH_DROP"))
|
||||
|| (nbt.hasTag("MMOITEMS_SOULBOUND") && nbt.getString("MMOITEMS_SOULBOUND").contains(player.getUniqueId().toString()))) {
|
||||
iterator.remove();
|
||||
soulboundInfo.add(item);
|
||||
soulboundInfo.registerItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (soulboundInfo.hasItems())
|
||||
soulboundInfo.setup();
|
||||
soulboundInfo.registerIfNecessary();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onRespawn(PlayerRespawnEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (MMOItems.plugin.getLanguage().keepSoulboundOnDeath)
|
||||
SoulboundInfo.read(player);
|
||||
|
||||
if (deathItems.containsKey(player)) {
|
||||
Bukkit.getScheduler().runTaskLater(MMOItems.plugin, () -> {
|
||||
player.getInventory().addItem(deathItems.get(player).toArray(new ItemStack[0]));
|
||||
deathItems.remove(player);
|
||||
}, 10);
|
||||
}
|
||||
DeathItemsHandler.readAndRemove(event.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@ -161,7 +142,7 @@ public class PlayerListener implements Listener {
|
||||
* player cast abilities or attacks with not the correct stats
|
||||
*
|
||||
* @deprecated This does cost some performance and that update
|
||||
* method NEEDS some improvement in the future
|
||||
* method NEEDS some improvement in the future
|
||||
*/
|
||||
@Deprecated
|
||||
@EventHandler
|
||||
@ -175,7 +156,7 @@ public class PlayerListener implements Listener {
|
||||
* player cast abilities or attacks with not the correct stats
|
||||
*
|
||||
* @deprecated This does cost some performance and that update
|
||||
* method NEEDS some improvement in the future
|
||||
* method NEEDS some improvement in the future
|
||||
*/
|
||||
@Deprecated
|
||||
@EventHandler
|
||||
|
Loading…
Reference in New Issue
Block a user