public IChest PlaceChest(ushort tileType, int style, DPoint placeLocation) { Contract.Requires <ArgumentException>(tileType == TileID.Containers || tileType == TileID.Containers2 || 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; } if (tileType == TileID.Containers2) { storageType = 4; } 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 CreateChestData(DPoint chestLocation) { int chestIndex = Chest.CreateChest(chestLocation.X, chestLocation.Y); bool isWorldFull = (chestIndex == -1 || chestIndex == ChestManager.DummyChestIndex); if (!isWorldFull) { return(new ChestAdapter(chestIndex, Main.chest[chestIndex])); } else { lock (this.WorldMetadata.ProtectorChests) { isWorldFull = (this.WorldMetadata.ProtectorChests.Count >= this.Config.MaxProtectorChests); if (isWorldFull) { throw new LimitEnforcementException(); } IChest chest = new ProtectorChestData(chestLocation); this.WorldMetadata.ProtectorChests.Add(chestLocation, (ProtectorChestData)chest); return(chest); } } }
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 CreateChestData(DPoint chestLocation) { int chestIndex = Chest.CreateChest(chestLocation.X, chestLocation.Y); bool isWorldFull = (chestIndex == -1 || chestIndex == ChestManager.DummyChestIndex); if (!isWorldFull) { return new ChestAdapter(chestIndex, Main.chest[chestIndex]); } else { lock (this.WorldMetadata.ProtectorChests) { isWorldFull = (this.WorldMetadata.ProtectorChests.Count >= this.Config.MaxProtectorChests); if (isWorldFull) throw new LimitEnforcementException(); IChest chest = new ProtectorChestData(chestLocation); this.WorldMetadata.ProtectorChests.Add(chestLocation, (ProtectorChestData)chest); return chest; } } }