//Receive Inventories stored on the world from the server and rebuilds the dictionary of inventories
        public override void NetReceive(BinaryReader reader)
        {
            mod.Logger.Debug($"Net receive");
            playerDeathInventoryMap = new Dictionary <Point, PlayerDeathInventory>();

            Point  position          = new Point();
            string playerName        = "";
            int    dInventoryLength  = 0;
            int    dArmorLength      = 0;
            int    dDyeLength        = 0;
            int    dMiscEquipsLength = 0;
            int    dMiscDyesLength   = 0;

            int numOfInventories = reader.ReadInt32();

            for (int i = 0; i < numOfInventories; i++)
            {
                position   = new Point(reader.ReadInt32(), reader.ReadInt32());
                playerName = reader.ReadString();

                dInventoryLength = reader.ReadInt32();
                Item[] dInventory = new Item[dInventoryLength];
                for (int j = 0; j < dInventoryLength; j++)
                {
                    dInventory[j] = ItemIO.Receive(reader, readStack: true, readFavorite: true);
                }

                dArmorLength = reader.ReadInt32();
                Item[] dArmor = new Item[dArmorLength];
                for (int j = 0; j < dArmorLength; j++)
                {
                    dArmor[j] = ItemIO.Receive(reader, readStack: true);
                }

                dDyeLength = reader.ReadInt32();
                Item[] dDye = new Item[dDyeLength];
                for (int j = 0; j < dDyeLength; j++)
                {
                    dDye[j] = ItemIO.Receive(reader, readStack: true);
                }

                dMiscEquipsLength = reader.ReadInt32();
                Item[] dMiscEquips = new Item[dMiscEquipsLength];
                for (int j = 0; j < dMiscEquipsLength; j++)
                {
                    dMiscEquips[j] = ItemIO.Receive(reader, readStack: true);
                }

                dMiscDyesLength = reader.ReadInt32();
                Item[] dMiscDyes = new Item[dMiscDyesLength];
                for (int j = 0; j < dMiscDyesLength; j++)
                {
                    dMiscDyes[j] = ItemIO.Receive(reader, readStack: true);
                }

                playerDeathInventoryMap[position] = new PlayerDeathInventory(dInventory, dArmor, dDye, dMiscEquips, dMiscDyes, playerName);
            }
        }
        public override void Load(TagCompound tag)
        {
            try
            {
                var inventoryMap = tag.GetList <TagCompound>("playerDeathInventoryMap");
                foreach (var inventory in inventoryMap)
                {
                    Point position = new Point(inventory.GetInt("positionX"), inventory.GetInt("positionY"));

                    mod.Logger.Debug($"Loading inventory at  - {position}");

                    string playerID = inventory.GetString("playerID");

                    Item[] dInventory  = new Item[Main.player[0].inventory.Length];
                    Item[] dArmor      = new Item[Main.player[0].armor.Length];
                    Item[] dDye        = new Item[Main.player[0].dye.Length];
                    Item[] dMiscEquips = new Item[Main.player[0].miscEquips.Length];
                    Item[] dMiscDyes   = new Item[Main.player[0].miscDyes.Length];

                    LoadItemList(inventory.Get <List <Item> >("inventory"), dInventory);
                    LoadItemList(inventory.Get <List <Item> >("armor"), dArmor);
                    LoadItemList(inventory.Get <List <Item> >("dye"), dDye);
                    LoadItemList(inventory.Get <List <Item> >("miscEquips"), dMiscEquips);
                    LoadItemList(inventory.Get <List <Item> >("miscDyes"), dMiscDyes);

                    playerDeathInventoryMap[position] = new PlayerDeathInventory(dInventory, dArmor, dDye, dMiscEquips, dMiscDyes, playerID);

                    //Spawn NPC for each loaded inventory and pass the X and Y position to its ai
                    NPC.NewNPC(position.X, position.Y, mod.NPCType("GhostInventory"), ai0: position.X, ai1: position.Y);
                }
            }
            catch (Exception e)
            {
                mod.Logger.Error("Error loading saved death inventories " + e.Message);
            }
        }
        public override bool PreKill(double damage, int hitDirection, bool pvp, ref bool playSound, ref bool genGore, ref PlayerDeathReason damageSource)
        {
            //if not mediumcore
            if (player.difficulty != (byte)1)
            {
                return(true);
            }

            MediumcoreGhostInventoriesWorld currentWorld = ModContent.GetInstance <MediumcoreGhostInventoriesWorld>();

            playerDeathInventoryMap = currentWorld.playerDeathInventoryMap;

            Item[] deathInventory  = new Item[player.inventory.Length];
            bool[] favourites      = new bool[player.inventory.Length];
            Item[] deathArmor      = new Item[player.armor.Length];
            Item[] deathDye        = new Item[player.dye.Length];
            Item[] deathMiscEquips = new Item[player.miscEquips.Length];
            Item[] deathMiscDyes   = new Item[player.miscDyes.Length];

            //If player is holding an item on their mouse, drop it
            if (Main.netMode != NetmodeID.Server && Main.mouseItem.type > ItemID.None)
            {
                int itemIndex = Item.NewItem(player.getRect(), Main.mouseItem.type, Stack: Main.mouseItem.stack, prefixGiven: Main.mouseItem.prefix);
                Main.item[itemIndex].noGrabDelay = 100;                     //Make player not instantly pick up item, without this the player will pick it up before dying
                NetMessage.SendData(MessageID.SyncItem, number: itemIndex); // Sync the item across clients
            }

            //Clears current player inventory and stores it in above arrays
            GetAndClearInventory(ref deathInventory, ref favourites, ref deathArmor, ref deathDye, ref deathMiscEquips, ref deathMiscDyes);
            PlayerDeathInventory currentInventory = new PlayerDeathInventory(deathInventory, deathArmor, deathDye, deathMiscEquips, deathMiscDyes, player.name);

            //Dont continue if inventory is just the starter inventory
            if (currentInventory.numOfItems == 3)
            {
                if (currentInventory.deathInventory[0].Name == "Copper Shortsword" && currentInventory.deathInventory[1].Name == "Copper Pickaxe" && currentInventory.deathInventory[2].Name == "Copper Axe")
                {
                    return(true);
                }
            }

            //Dont continue if empty inventory
            if (currentInventory.numOfItems == 0)
            {
                return(true);
            }

            //Set death position to the centre of the player
            Point deathPosition = new Point((int)player.position.X, (int)player.position.Y);

            mod.Logger.Debug($"player death position - {player.position}");

            //if near current position doesnt already have an inventory  on it and is within the map bounds spawn the npc and add to the inventory dictionary. Else search for a new untaken position
            if (CheckPosition(deathPosition))
            {
                playerDeathInventoryMap[deathPosition] = currentInventory;
                if (Main.netMode == NetmodeID.Server)
                {
                    NetMessage.SendData(MessageID.WorldData);    //Update inventory positions on clients to make sure they all match
                    SendSpawn(deathPosition.X, deathPosition.Y); //Send message to clients to spawn the npc
                }
                //Make sure npc isnt spawned yet on multiplayer clients incase they do not have updated deathInventoryMap, they will spawn the npc once they receive the spawnNPC message
                if (Main.netMode != NetmodeID.MultiplayerClient)
                {
                    NPC.NewNPC(deathPosition.X, deathPosition.Y, mod.NPCType("GhostInventory"), ai0: deathPosition.X, ai1: deathPosition.Y);
                }

                if (Main.netMode == NetmodeID.MultiplayerClient && Array.Exists(favourites, element => element))
                {
                    SendFavorites(favourites, deathPosition.X, deathPosition.Y);//Send favourited items to server
                }
            }
            else
            {
                Point nextUntakenDeathPosition = FindUntakenDeathPosition(deathPosition);
                playerDeathInventoryMap[nextUntakenDeathPosition] = currentInventory;
                if (Main.netMode == NetmodeID.Server)
                {
                    NetMessage.SendData(MessageID.WorldData);                          //Update inventory positions on clients to make sure they all match
                    SendSpawn(nextUntakenDeathPosition.X, nextUntakenDeathPosition.Y); //Send message to clients to spawn the npc
                }
                //Make sure npc isnt spawned yet on multiplayer clients incase they do not have updated deathInventoryMap, they will spawn the npc once they receive the spawnNPC message
                if (Main.netMode != NetmodeID.MultiplayerClient)
                {
                    NPC.NewNPC(nextUntakenDeathPosition.X, nextUntakenDeathPosition.Y, mod.NPCType("GhostInventory"), ai0: nextUntakenDeathPosition.X, ai1: nextUntakenDeathPosition.Y);
                }

                if (Main.netMode == NetmodeID.MultiplayerClient && Array.Exists(favourites, element => element))
                {
                    SendFavorites(favourites, nextUntakenDeathPosition.X, nextUntakenDeathPosition.Y);//Send favourited items to server
                }
            }

            return(true);
        }