Exemple #1
0
        //This needs to be called from SetupRecipies, because chests are made in SetupContent.
        private void LoadChestAdapters()
        {
            ChestAdapter chestAdapter = new ChestAdapter(this);
            List <int>   chestTypes   = new List <int>();

            for (int i = 0; i < TileLoader.TileCount; i++)
            {
                if (TileID.Sets.BasicChest[i] || TileID.Sets.BasicChestFake[i] || TileLoader.IsDresser(i))
                {
                    chestTypes.Add(i);
                }
            }
            Call(registerAdapterReflection, chestAdapter, chestTypes.ToArray());
        }
        // Modded version of Terraria's original method.
        private Item PutItemInNearbyChest(TSPlayer player, Item itemToStore, Vector2 position)
        {
            bool isStored = false;

              for (int i = 0; i < Main.chest.Length; i++) {
            if (i == ChestManager.DummyChestIndex)
              continue;
            Chest tChest = Main.chest[i];
            if (tChest == null || !Main.tile[tChest.x, tChest.y].active())
              continue;

            bool isPlayerInChest = Main.player.Any((p) => p.chest == i);
            if (!isPlayerInChest) {
              IChest chest = new ChestAdapter(i, tChest);
              isStored = this.TryToStoreItemInNearbyChest(player, position, itemToStore, chest);
              if (isStored)
            break;
            }
              }

              if (!isStored) {
            lock (this.WorldMetadata.ProtectorChests) {
              foreach (DPoint chestLocation in this.WorldMetadata.ProtectorChests.Keys) {
            if (!TerrariaUtils.Tiles[chestLocation].active())
              continue;

            bool isPlayerInChest = this.ChestPlayerIndexDictionary.ContainsKey(chestLocation);
            if (!isPlayerInChest) {
              IChest chest = this.WorldMetadata.ProtectorChests[chestLocation];
              isStored = this.TryToStoreItemInNearbyChest(player, position, itemToStore, chest);
              if (isStored)
                break;
            }
              }
            }
              }

              return itemToStore;
        }
        public bool TrySwapChestData(TSPlayer player, DPoint anyChestTileLocation, out IChest newChest)
        {
            newChest = null;

              if (TerrariaUtils.Tiles[anyChestTileLocation].type != TileID.Containers && TerrariaUtils.Tiles[anyChestTileLocation].type != TileID.Dressers) {
            player.SendErrorMessage("The selected tile is not a chest or dresser.");
            return false;
              }

              DPoint chestLocation = TerrariaUtils.Tiles.MeasureObject(anyChestTileLocation).OriginTileLocation;
              IChest chest = this.ChestManager.ChestFromLocation(chestLocation, player);
              if (chest == null)
            return false;

              ItemData[] content = new ItemData[Chest.maxItems];
              for (int i = 0; i < Chest.maxItems; i++)
            content[i] = chest.Items[i];

              if (chest.IsWorldChest) {
            lock (this.WorldMetadata.ProtectorChests) {
              bool isChestAvailable = this.WorldMetadata.ProtectorChests.Count < this.Config.MaxProtectorChests;
              if (!isChestAvailable) {
            player?.SendErrorMessage("The maximum of possible Protector chests has been reached.");
            return false;
              }

              int playerUsingChestIndex = Chest.UsingChest(chest.Index);
              if (playerUsingChestIndex != -1)
            Main.player[playerUsingChestIndex].chest = -1;

              Main.chest[chest.Index] = null;
              newChest = new ProtectorChestData(chestLocation, content);

              this.WorldMetadata.ProtectorChests.Add(chestLocation, (ProtectorChestData)newChest);

              //TSPlayer.All.SendData(PacketTypes.ChestName, string.Empty, chest.Index, chestLocation.X, chestLocation.Y);

              // Tell the client to remove the chest with the given index from its own chest array.
              TSPlayer.All.SendData(PacketTypes.TileKill, string.Empty, 1, chestLocation.X, chestLocation.Y, 0, chest.Index);
              TSPlayer.All.SendTileSquare(chestLocation.X, chestLocation.Y, 2);
              player?.SendWarningMessage("This chest is now a Protector chest.");
            }
              } else {
            int availableUnnamedChestIndex = -1;
            int availableEmptyChestIndex = -1;
            for (int i = 0; i < Main.chest.Length; i++) {
              if (i == ChestManager.DummyChestIndex)
            continue;

              Chest tChest = Main.chest[i];
              if (tChest == null) {
            availableEmptyChestIndex = i;
            break;
              } else if (availableUnnamedChestIndex == -1 && string.IsNullOrWhiteSpace(tChest.name)) {
            availableUnnamedChestIndex = i;
              }
            }

            // Prefer unset chests over unnamed chests.
            int availableChestIndex = availableEmptyChestIndex;
            if (availableChestIndex == -1)
              availableChestIndex = availableUnnamedChestIndex;

            bool isChestAvailable = (availableChestIndex != -1);
            if (!isChestAvailable) {
              player?.SendErrorMessage("The maximum of possible world chests has been reached.");
              return false;
            }

            lock (this.WorldMetadata.ProtectorChests)
              this.WorldMetadata.ProtectorChests.Remove(chestLocation);

            Chest availableChest = Main.chest[availableChestIndex];
            bool isExistingButUnnamedChest = (availableChest != null);
            if (isExistingButUnnamedChest) {
              if (!this.TrySwapChestData(null, new DPoint(availableChest.x, availableChest.y), out newChest))
            return false;
            }

            availableChest = Main.chest[availableChestIndex] = new Chest();
            availableChest.x = chestLocation.X;
            availableChest.y = chestLocation.Y;
            availableChest.item = content.Select(i => i.ToItem()).ToArray();

            newChest = new ChestAdapter(availableChestIndex, availableChest);
            player?.SendWarningMessage("This chest is now a world chest.");
              }

              return true;
        }
        public IChest PlaceChest(ushort tileType, int style, DPoint placeLocation)
        {
            Contract.Requires<ArgumentException>(tileType == TileID.Containers || tileType == TileID.Dressers);

              IChest chest;
              bool isDresser = (tileType == TileID.Dressers);
              int chestIndex = WorldGen.PlaceChest(placeLocation.X, placeLocation.Y, tileType, false, style);
              bool isWorldFull = (chestIndex == -1 || chestIndex == ChestManager.DummyChestIndex);

              if (!isWorldFull) {
            chest = new ChestAdapter(chestIndex, Main.chest[chestIndex]);
              } else {
            lock (this.WorldMetadata.ProtectorChests) {
              isWorldFull = (this.WorldMetadata.ProtectorChests.Count >= this.Config.MaxProtectorChests);
              if (isWorldFull)
            throw new LimitEnforcementException();

              if (isDresser)
            WorldGen.PlaceDresserDirect(placeLocation.X, placeLocation.Y, tileType, style, chestIndex);
              else
            WorldGen.PlaceChestDirect(placeLocation.X, placeLocation.Y, tileType, style, chestIndex);

              DPoint chestLocation = TerrariaUtils.Tiles.MeasureObject(placeLocation).OriginTileLocation;
              chest = new ProtectorChestData(chestLocation);
              this.WorldMetadata.ProtectorChests.Add(chestLocation, (ProtectorChestData)chest);

              chestIndex = ChestManager.DummyChestIndex;
            }
              }

              int storageType = 0;
              if (isDresser)
            storageType = 2;

              TSPlayer.All.SendData(PacketTypes.TileKill, string.Empty, storageType, placeLocation.X, placeLocation.Y, style, chestIndex);
              // The client will always show open / close animations for the latest chest index. But when there are multiple chests with id 999
              // this will look awkard, so instead tell the client about another 999 chest on a location where the animation will never be noticed by the player.
              if (chestIndex == ChestManager.DummyChestIndex)
            TSPlayer.All.SendData(PacketTypes.TileKill, string.Empty, storageType, 0, 0, style, chestIndex);

              return chest;
        }
        public IChest ChestFromLocation(DPoint chestLocation, TSPlayer reportToPlayer = null)
        {
            Tile tile = TerrariaUtils.Tiles[chestLocation];
              if (!tile.active() || (tile.type != (int)BlockType.Chest && tile.type != (int)BlockType.Dresser)) {
            reportToPlayer?.SendErrorMessage("There is no chest at this position.");
            return null;
              }

              IChest chest = null;
              int chestIndex = Chest.FindChest(chestLocation.X, chestLocation.Y);
              bool isWorldDataChest = (chestIndex != -1 && chestIndex != ChestManager.DummyChestIndex);

              if (isWorldDataChest) {
            Chest tChest = Main.chest[chestIndex];
            if (tChest != null)
              chest = new ChestAdapter(chestIndex, Main.chest[chestIndex]);
            else
              reportToPlayer?.SendErrorMessage($"World data for this chest (id {chestIndex}) were expected, but was not present.");
              } else {
            lock (this.WorldMetadata.ProtectorChests) {
              ProtectorChestData protectorChest;
              if (this.WorldMetadata.ProtectorChests.TryGetValue(chestLocation, out protectorChest))
            chest = protectorChest;
              else
            reportToPlayer?.SendErrorMessage("The data record of this chest is missing in both world data and Protector's data.");
            }
              }

              return chest;
        }