Solved Problem Finding Event: "Item fell out of world"?

Discussion in 'Spigot Plugin Development' started by LeeSchoenwetter, Aug 12, 2018.


    Hello great, all-knowing and wise ones!

    I'm working on one of my existing plugins (GTDeathboxes), and trying to prevent people from being able to get many duplicate copies of what they were carrying, when they die... but the intention is to help them to recover things if they cannot get back to their items in time, or lose them in some other way.

    [I know that I could turn on "Keep items on respawn" (or called something similar), but that's a little *too easy* for the players.]

    I've got everything working, EXCEPT for when an item falls out of the world. I can't seem to find the correct Event that handles that occurrence.

    I'm using the following Events, already, but they don't handle it (EntityDamageEvent, EntityPickupItemEvent, ItemDespawnEvent) and even accounting for ItemMergeEvent.

    I've looked over EntityDeathEvent, but it appears to only work on "LivingEntity" entities.

    Just can't quite seem to find the one I'm looking for, and beginning to think I won't.

    Thoughts? Did I miss something obvious?

    SOLUTION: (a bunch of stuff was removed, so this code wouldn't work, BUT... the gist of it is there!)

    Code (Text):

    public class eventPlayerDeathEvent implements Listener {
        GTDeathBoxPlugin plugin;
        List<String> checkFallingItems = new ArrayList<String>();
        Boolean checkFallingIsRunning = false;
        public eventPlayerDeathEvent( GTDeathBoxPlugin passedPlugin ) {
            plugin = passedPlugin;
        public void onPlayerDeathEvent(PlayerDeathEvent event) {
            Player player = event.getEntity();
            World thisWorld = player.getWorld();
            String deathMessage = event.getDeathMessage();
            String deathboxWorldName = plugin.getConfig().getString( "deathboxLocation."+thisWorld.getName()+".world");
            World deathboxWorld = plugin.getServer().getWorld(deathboxWorldName);
                            final Location deathLocation = player.getLocation();
                            double deathX = deathLocation.getX();
                            double deathY = deathLocation.getY();
                            double deathZ = deathLocation.getZ();
                            UUID playerUUID = player.getUniqueId();
                            int playerInventorySize = playerItems.size();
                            for( int invLoop=0; invLoop<playerInventorySize; invLoop++ ) {
                                ItemStack playerItem = playerItems.get( invLoop );
    //                            plugin.getLogger().info("Item: " + playerItem.toString());
                                Item droppedItem = deathboxWorld.dropItemNaturally(player.getLocation(), playerItem);
                                plugin.getConfig().set("deathItems."+droppedItem.getUniqueId()+".playerUUID", playerUUID.toString() );
                                plugin.getConfig().set("deathItems."+droppedItem.getUniqueId()+".playerName013", player.getDisplayName().substring(0, nameLength) );
                                plugin.getConfig().set("deathItems."+droppedItem.getUniqueId()+".sdfDate", sdfDate.format( now ) );
                                plugin.getConfig().set("deathItems."+droppedItem.getUniqueId()+".chestX", blockLocation.getX() );
                                plugin.getConfig().set("deathItems."+droppedItem.getUniqueId()+".chestY", blockLocation.getY() );
                                plugin.getConfig().set("deathItems."+droppedItem.getUniqueId()+".chestZ", blockLocation.getZ() );
                                plugin.getConfig().set("checkFallingItems."+droppedItem.getUniqueId()+".uuid", droppedItem.getUniqueId().toString() );
                                plugin.getConfig().set("checkFallingItems."+droppedItem.getUniqueId()+".x", deathX );
                                plugin.getConfig().set("checkFallingItems."+droppedItem.getUniqueId()+".y", deathY );
                                plugin.getConfig().set("checkFallingItems."+droppedItem.getUniqueId()+".z", deathZ );
                           plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable(){
                                public void run(){
                                    checkFallingItems( deathLocation );
                            }, (long) 20 );
        public void checkFallingItems( final Location deathCheckLocation ) {
            Collection<Entity> entities = deathCheckLocation.getWorld().getNearbyEntities(deathCheckLocation, 10, 200, 10);
            int numFallingItems = 0;
            for( Entity entity : entities ) {
                if( !entity.getType().equals(EntityType.DROPPED_ITEM) ) {
                Item item = (Item) entity;
                UUID uniqueID = item.getUniqueId();
                if( !plugin.getConfig().contains("checkFallingItems."+uniqueID.toString()) ) {
                Double previousY = plugin.getConfig().getDouble("checkFallingItems."+uniqueID.toString()+".y");
                Location thisLocation = item.getLocation();
                Double thisY = thisLocation.getY();
                if( thisY.equals(previousY) ) {
                    plugin.getConfig().set("checkFallingItems."+item.getUniqueId(), null);
                } else {            
                    if( thisY < -30 ) {
                        UUID itemUUID = item.getUniqueId();
                        World thisWorld = item.getWorld();
                        if( !plugin.getConfig().contains("deathItems."+itemUUID.toString()) ) {

                        double chestX = plugin.getConfig().getDouble("deathItems."+itemUUID.toString()+".chestX");
                        double chestY = plugin.getConfig().getDouble("deathItems."+itemUUID.toString()+".chestY");
                        double chestZ = plugin.getConfig().getDouble("deathItems."+itemUUID.toString()+".chestZ");
                        Location chestLocation = new Location(thisWorld, chestX, chestY, chestZ);
                        Block chestBlock = chestLocation.getBlock();
                        CraftChest chest = (CraftChest) chestBlock.getState();
                        Inventory singleChestInventory = chest.getInventory();
                        DoubleChest doubleChest = (DoubleChest) singleChestInventory.getHolder();
                        DoubleChestInventory chestInventory = (DoubleChestInventory) doubleChest.getInventory();
                        chestInventory.addItem( item.getItemStack() );
                        plugin.getConfig().set("deathItems."+itemUUID.toString(), null);
                        plugin.getConfig().set("checkFallingItems."+item.getUniqueId(), null);
            if( numFallingItems > 0 ) {
                plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable(){
                    public void run(){
                        checkFallingItems( deathCheckLocation );
                }, (long) 20 );

    #1 LeeSchoenwetter, Aug 12, 2018
    Last edited: Aug 16, 2018
  2. You might just have to check on each item every second or so.

    First check if that item is below y = 0 so that you don't bother with any other item. This way, you can still grab items that fall below that limit as they would have been destroyed by the void.

    Even if you drop an Item from sky limit and have it fall below y = 0 your checks should be fast enough to catch it before it hits y = -64 which is where all non-player entities disappear completely.

    I'm suprised there is no event that can handle this scenario and I though ItemDespawnEvent would have been the solution.
  3. Hmm, I would have expected that PlayerDeathEvent would have provided a setDrops() method :/. Have you tried getting the item list from that event to add to the players death chest and clearing the players inventory (set all slots to null) to stop the players items from dropping on their death (this would require that no other plugin works with the players inventory or uses getDrops() on PlayerDeathEvent other some interesting things could happen!
  4. Whats about ItemDespawnEvent?
  5. @basicmark - I originally did just that, moving everything to the Chest, but then the Player couldn't retrieve their items from where they died, at all. The goal is to encourage them to go and get their items, but provide a backup if those items disappear.

    @Alex_qp - ItemDespawnEvent only captures things that reach the 5 minute mark. I'm using it, but it doesn't handle items that fall out of the world.

    @Rifle_D_Luffy - I think this is what I'll have to do. Basically, when I save the items to "be affected", I'll also save a "check < 0" list. If an item stops moving between checks, I'll remove it from the list, and if it drops below ~(-32), I'll throw them into the chest.

    Thanks, everyone for the input! I might leave it open for further discussion, until I get this coded, and then post that as I close the topic!