protected internal override TriggerStatus UpdateImpl() { while (!success && chestItemChanges.Count > 0) { if (chestItemChanges.TryDequeue(out var args)) { var newCount = ChestFunctions.CountChestItem(chestX, chestY, itemId, itemPrefix); if (newCount < chestItemCount) { var diff = chestItemCount - newCount; itemsGathered += diff; chestItemCount = newCount; } if (itemsGathered >= itemsRequired) { success = true; } } } return(success.ToTriggerStatus()); }
/// <inheritdoc /> protected override void Initialize() { //ensure chest exists... chestId = Chest.FindChest(chestX, chestY - 1); if (chestId == -1) { success = true; // just pass for now on invalid chests. //return; } //try to ensure valid item if we were passed an id string, and not an integer id. if (!string.IsNullOrWhiteSpace(itemType)) { var id = ItemFunctions.GetItemIdFromName(itemType); if (id != null) { itemId = (int)id; } else { success = true; } } //ensure the item actually exists in the chest, with enough quantity. chestItemCount = ChestFunctions.CountChestItem(chestX, chestY, itemId, itemPrefix); if (chestItemCount < itemsRequired) { //Debug.Print("There are not enough items in the chest. Skipping."); success = true; } CustomQuestsPlugin.Instance.ChestItemChanged += chestItemChanged; }
/// <summary> /// Pastes a Schematic into the world. /// </summary> /// <param name="x"></param> /// <param name="y"></param> public void Paste(int x, int y) { //clip var worldRect = new Rectangle(0, 0, Main.maxTilesX, Main.maxTilesY); var schematicRect = new Rectangle(x, y, Width, Height); var clippedRect = schematicRect; worldRect.Intersects(ref clippedRect, out var intersects); if (!intersects) { return; } //starting position within schematic to read from. var readColumnStart = clippedRect.Left - x; var readRowStart = clippedRect.Top - y; //clear existing chests ChestFunctions.ClearChests(clippedRect.Left, clippedRect.Top, clippedRect.Right, clippedRect.Bottom); #if SCHEMATIC_ENABLE_SIGNS //clear signs SignFunctions.ClearSigns(clippedRect.Left, clippedRect.Top, clippedRect.Right, clippedRect.Bottom, effectOnly: true); #endif //copy tiles var readRow = readRowStart; for (var row = clippedRect.Top; row < clippedRect.Bottom; row++) { var readColumn = readColumnStart; for (var column = clippedRect.Left; column < clippedRect.Right; column++) { var readTile = Tiles[readColumn, readRow]; Main.tile[column, row].CopyFrom(readTile); //TSPlayer.All.SendTileSquare(column, row, 1); readColumn++; } readRow++; } //try to send update, using the pasted schematics center point, and radius SendTileUpdates(TSPlayer.All, ref clippedRect); //paste chests foreach (var chest in Chests) { const int frameSize = 16 + 2; //presumably, this is the frame size. var tile = Tiles[chest.X, chest.Y]; var chestStyle = tile.U / frameSize; var chestX = x + chest.X; var chestY = y + chest.Y + 1; // we have to add 1, because create chest uses an offset. var chestId = ChestFunctions.CreateChest(chestX, chestY, chestStyle); if (chestId != -1) { foreach (var item in chest.Items) { ChestFunctions.PutItemIntoChest(chestId, item.NetId, item.StackSize, item.Prefix); } } else { //failed to create chest for some reason, maybe one already in the way. Debug.Print($"Failed to create schematic chest at {chestX}, {chestY}."); } //This is a bug in terraria server? or tshock? //PacketType 34 should be PlaceChest, not TileKill. Sigh. //TSPlayer.All.SendData(PacketTypes.TileKill, "", chestId, tileX, tileY, style, 0);//0 = ChestID to destroy, but we dont use this here.. } #if SCHEMATIC_ENABLE_SIGNS //paste signs foreach (var sign in Signs) { var signX = x + sign.X; var signY = y + sign.Y; var result = SignFunctions.TryCreateSignDirect(signX, signY, sign.Text); if (result) { Debug.Print($"Pasted sign at {signX}, {signY}."); } else { Debug.Print($"Failed to paste sign at {signX}, {signY}."); } } #endif }
/// <summary> /// Creates a Schematic, from existing tiles in the world. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="columns"></param> /// <param name="rows"></param> /// <returns></returns> public static Schematic Grab(int x, int y, int columns, int rows) { //clip var worldRect = new Rectangle(0, 0, Main.maxTilesX, Main.maxTilesY); var schematicRect = new Rectangle(x, y, columns, rows); var clippedRect = schematicRect; worldRect.Intersects(ref clippedRect, out var intersects); var result = new Schematic(clippedRect.Width, clippedRect.Height); result.IsGrabbed = true; result.GrabbedX = clippedRect.Left; result.GrabbedY = clippedRect.Top; if (!intersects) { return(result); } //starting position within schematic to read from. var writeColumnStart = clippedRect.Left - x; var writeRowStart = clippedRect.Top - y; var writeRow = writeRowStart; for (var row = clippedRect.Top; row < clippedRect.Bottom; row++) { var writeColumn = writeColumnStart; for (var column = clippedRect.Left; column < clippedRect.Right; column++) { //var readTile = Tiles[readColumn, readRow]; var itile = Main.tile[column, row]; var tile = new Tile(); tile.CopyFrom(itile); result.Tiles[writeColumn, writeRow] = tile; writeColumn++; } writeRow++; } //grab chests var chestIds = ChestFunctions.FindChests(clippedRect.Left, clippedRect.Top, clippedRect.Right, clippedRect.Bottom); foreach (var id in chestIds) { var srcChest = Main.chest[id]; if (srcChest != null) { Corruption.TEdit.Chest dst = new Corruption.TEdit.Chest(srcChest); //we have to offset dst into coords that are relative to the schematic, not the world tileset. dst.X = dst.X - x; dst.Y = dst.Y - y; result.Chests.Add(dst); } } #if SCHEMATIC_ENABLE_SIGNS //grab signs var signIds = SignFunctions.FindSigns(clippedRect.Left, clippedRect.Top, clippedRect.Right, clippedRect.Bottom); foreach (var id in signIds) { var srcSign = Main.sign[id]; if (srcSign != null) { Corruption.TEdit.Sign dst = new Corruption.TEdit.Sign(); //we have to offset dst into coords that are relative to the schematic, not the world tileset. dst.X = srcSign.x - x; dst.Y = srcSign.y - y; dst.Text = srcSign.text; result.Signs.Add(dst); } } #endif return(result); }