private bool TryGetProtectionInfo(TSPlayer player, DPoint tileLocation, bool sendFailureMessages = true) { Tile tile = TerrariaUtils.Tiles[tileLocation]; if (!tile.active()) return false; ProtectionEntry protection = null; // Only need the first enumerated entry as we don't need the protections of adjacent blocks. foreach (ProtectionEntry enumProtection in this.ProtectionManager.EnumerateProtectionEntries(tileLocation)) { protection = enumProtection; break; } BlockType blockType = (BlockType)TerrariaUtils.Tiles[tileLocation].type; if (protection == null) { if (sendFailureMessages) player.SendErrorMessage($"This {TerrariaUtils.Tiles.GetBlockTypeName(blockType)} is not protected by Protector at all."); return false; } bool canViewExtendedInfo = ( player.Group.HasPermission(ProtectorPlugin.ViewAllProtections_Permission) || protection.Owner == player.User.ID || protection.IsSharedWithPlayer(player) ); if (!canViewExtendedInfo) { player.SendMessage($"This {TerrariaUtils.Tiles.GetBlockTypeName(blockType)} is protected and not shared with you.", Color.LightGray); player.SendWarningMessage("You are not permitted to get more information about this protection."); return true; } string ownerName; if (protection.Owner == -1) ownerName = "{Server}"; else ownerName = GetUserName(protection.Owner); player.SendMessage($"This {TerrariaUtils.Tiles.GetBlockTypeName(blockType)} is protected. The owner is {TShock.Utils.ColorTag(ownerName, Color.Red)}.", Color.LightGray); string creationTimeFormat = "unknown"; if (protection.TimeOfCreation != DateTime.MinValue) creationTimeFormat = "{0:MM/dd/yy, h:mm tt} UTC ({1} ago)"; player.SendMessage( string.Format( CultureInfo.InvariantCulture, "Protection created On: " + creationTimeFormat, protection.TimeOfCreation, (DateTime.UtcNow - protection.TimeOfCreation).ToLongString() ), Color.LightGray ); if (blockType == BlockType.Chest || blockType == BlockType.Dresser) { if (protection.RefillChestData != null) { RefillChestMetadata refillChest = protection.RefillChestData; if (refillChest.RefillTime != TimeSpan.Zero) player.SendMessage($"This is a refill chest with a timer set to {TShock.Utils.ColorTag(refillChest.RefillTime.ToLongString(), Color.Red)}.", Color.LightGray); else player.SendMessage("This is a refill chest without a timer.", Color.LightGray); if (refillChest.OneLootPerPlayer || refillChest.RemainingLoots != -1) { StringBuilder messageBuilder = new StringBuilder(); messageBuilder.Append("It can only be looted "); if (refillChest.OneLootPerPlayer) messageBuilder.Append("one time by each player"); if (refillChest.RemainingLoots != -1) { if (messageBuilder.Length > 0) messageBuilder.Append(" and "); messageBuilder.Append(TShock.Utils.ColorTag(refillChest.RemainingLoots.ToString(), Color.Red)); messageBuilder.Append(" more times in total"); } if (refillChest.Looters != null) { messageBuilder.Append(" and was looted "); messageBuilder.Append(TShock.Utils.ColorTag(refillChest.Looters.Count.ToString(), Color.Red)); messageBuilder.Append(" times until now"); } messageBuilder.Append('.'); player.SendMessage(messageBuilder.ToString(), Color.LightGray); } } else if (protection.BankChestKey != BankChestDataKey.Invalid) { BankChestDataKey bankChestKey = protection.BankChestKey; player.SendMessage($"This is a bank chest instance with the number {bankChestKey.BankChestIndex}.", Color.LightGray); } else if (protection.TradeChestData != null) { Item sellItem = new Item(); sellItem.netDefaults(protection.TradeChestData.ItemToSellId); sellItem.stack = protection.TradeChestData.ItemToSellAmount; Item payItem = new Item(); payItem.netDefaults(protection.TradeChestData.ItemToPayId); payItem.stack = protection.TradeChestData.ItemToPayAmount; player.SendMessage($"This is a trade chest. It's selling {TShock.Utils.ItemTag(sellItem)} for {TShock.Utils.ItemTag(payItem)}", Color.LightGray); } IChest chest = this.ChestManager.ChestFromLocation(protection.TileLocation); if (chest.IsWorldChest) player.SendMessage($"It is stored as part of the world data (id: {TShock.Utils.ColorTag(chest.Index.ToString(), Color.Red)}).", Color.LightGray); else player.SendMessage($"It is {TShock.Utils.ColorTag("not", Color.Red)} stored as part of the world data.", Color.LightGray); } if (ProtectionManager.IsShareableBlockType(blockType)) { if (protection.IsSharedWithEveryone) { player.SendMessage("Protection is shared with everyone.", Color.LightGray); } else { StringBuilder sharedListBuilder = new StringBuilder(); if (protection.SharedUsers != null) { for (int i = 0; i < protection.SharedUsers.Count; i++) { if (i > 0) sharedListBuilder.Append(", "); TShockAPI.DB.User tsUser = TShock.Users.GetUserByID(protection.SharedUsers[i]); if (tsUser != null) sharedListBuilder.Append(tsUser.Name); } } if (sharedListBuilder.Length == 0 && protection.SharedGroups == null) { player.SendMessage($"Protection is {TShock.Utils.ColorTag("not", Color.Red)} shared with users or groups.", Color.LightGray); } else { if (sharedListBuilder.Length > 0) player.SendMessage($"Shared with users: {TShock.Utils.ColorTag(sharedListBuilder.ToString(), Color.Red)}", Color.LightGray); else player.SendMessage($"Protection is {TShock.Utils.ColorTag("not", Color.Red)} shared with users.", Color.LightGray); if (protection.SharedGroups != null) player.SendMessage($"Shared with groups: {TShock.Utils.ColorTag(protection.SharedGroups.ToString(), Color.Red)}", Color.LightGray); else player.SendMessage($"Protection is {TShock.Utils.ColorTag("not", Color.Red)} shared with groups.", Color.LightGray); } } } if (protection.TradeChestData != null && protection.TradeChestData.TransactionJournal.Count > 0) { player.SendMessage($"Trade Chest Journal (Last {protection.TradeChestData.TransactionJournal.Count} Transactions)", Color.LightYellow); protection.TradeChestData.TransactionJournal.ForEach(entry => { string entryText = entry.Item1; DateTime entryTime = entry.Item2; TimeSpan timeSpan = DateTime.UtcNow - entryTime; player.SendMessage($"{entryText} {timeSpan.ToLongString()} ago.", Color.LightGray); }); } return true; }
public override bool HandleTileEdit( TSPlayer player, TileEditType editType, BlockType blockType, DPoint location, int objectStyle ) { if (this.IsDisposed) return false; if (base.HandleTileEdit(player, editType, blockType, location, objectStyle)) return true; switch (editType) { case TileEditType.PlaceTile: { Tile tile = TerrariaUtils.Tiles[location]; if (tile == null) Main.tile[location.X, location.Y] = tile = new Tile(); WorldGen.PlaceTile(location.X, location.Y, (int)blockType, false, true, -1, objectStyle); NetMessage.SendData((int)PacketTypes.Tile, -1, player.Index, string.Empty, 1, location.X, location.Y, (int)blockType, objectStyle); if (this.Config.AutoProtectedTiles[(int)blockType]) this.TryCreateAutoProtection(player, location); return true; } case TileEditType.TileKill: case TileEditType.TileKillNoItem: { // Is the tile really going to be destroyed or just being hit? //if (blockType != 0) // break; Tile tile = TerrariaUtils.Tiles[location]; bool isChest = (tile.type == TileID.Containers || tile.type == TileID.Dressers); foreach (ProtectionEntry protection in this.ProtectionManager.EnumerateProtectionEntries(location)) { // If the protection is invalid, just remove it. if (!TerrariaUtils.Tiles.IsValidCoord(protection.TileLocation)) { this.ProtectionManager.RemoveProtection(TSPlayer.Server, protection.TileLocation, false); continue; } Tile protectedTile = TerrariaUtils.Tiles[protection.TileLocation]; // If the protection is invalid, just remove it. if (!protectedTile.active() || protectedTile.type != (int)protection.BlockType) { this.ProtectionManager.RemoveProtection(TSPlayer.Server, protection.TileLocation, false); continue; } string tileName = TerrariaUtils.Tiles.GetBlockTypeName((BlockType)protectedTile.type); if ( protection.Owner == player.User.ID || ( this.Config.AutoDeprotectEverythingOnDestruction && player.Group.HasPermission(ProtectorPlugin.ProtectionMaster_Permission) ) ) { if (isChest) { bool isBankChest = (protection.BankChestKey != BankChestDataKey.Invalid); ObjectMeasureData measureData = TerrariaUtils.Tiles.MeasureObject(protection.TileLocation); DPoint chestLocation = measureData.OriginTileLocation; IChest chest = this.ChestManager.ChestFromLocation(chestLocation); if (chest == null) return true; if (isBankChest) { this.DestroyBlockOrObject(chestLocation); } else { for (int i = 0; i < Chest.maxItems; i++) { if (chest.Items[i].StackSize > 0) return true; } } } this.ProtectionManager.RemoveProtection(player, protection.TileLocation, false); if (this.Config.NotifyAutoDeprotections) player.SendWarningMessage($"The {tileName} is not protected anymore."); } else { player.SendErrorMessage($"The {tileName} is protected."); if (protection.TradeChestData != null) player.SendWarningMessage("If you want to trade with this chest, right click it first."); player.SendTileSquare(location); return true; } } if (isChest) { ObjectMeasureData measureData = TerrariaUtils.Tiles.MeasureObject(location); DPoint chestLocation = measureData.OriginTileLocation; IChest chest = this.ChestManager.ChestFromLocation(chestLocation); if (chest != null) { // Don't allow removing of non empty chests. for (int i = 0; i < Chest.maxItems; i++) { if (chest.Items[i].StackSize > 0) return true; } this.DestroyBlockOrObject(chestLocation); return true; } } break; } case TileEditType.PlaceWire: case TileEditType.PlaceWireBlue: case TileEditType.PlaceWireGreen: case TileEditType.PlaceWireYellow: case TileEditType.PlaceActuator: case TileEditType.DestroyWire: case TileEditType.DestroyWireBlue: case TileEditType.DestroyWireGreen: case TileEditType.DestroyWireYellow: case TileEditType.DestroyActuator: if (this.Config.AllowWiringProtectedBlocks) break; if (this.CheckProtected(player, location, false)) { player.SendTileSquare(location); return true; } break; case TileEditType.PokeLogicGate: case TileEditType.Actuate: if (this.CheckProtected(player, location, false)) { player.SendTileSquare(location); return true; } break; } return false; }
public void EnsureProtectionData(TSPlayer player) { int invalidProtectionsCount; int invalidRefillChestCount; int invalidBankChestCount; this.ProtectionManager.EnsureProtectionData( false, out invalidProtectionsCount, out invalidRefillChestCount, out invalidBankChestCount); if (player != TSPlayer.Server) { if (invalidProtectionsCount > 0) player.SendWarningMessage("{0} invalid protections removed.", invalidProtectionsCount); if (invalidRefillChestCount > 0) player.SendWarningMessage("{0} invalid refill chests removed.", invalidRefillChestCount); if (invalidBankChestCount > 0) player.SendWarningMessage("{0} invalid bank chest instances removed.", invalidBankChestCount); player.SendInfoMessage("Finished ensuring protection data."); } if (invalidProtectionsCount > 0) this.PluginTrace.WriteLineWarning("{0} invalid protections removed.", invalidProtectionsCount); if (invalidRefillChestCount > 0) this.PluginTrace.WriteLineWarning("{0} invalid refill chests removed.", invalidRefillChestCount); if (invalidBankChestCount > 0) this.PluginTrace.WriteLineWarning("{0} invalid bank chest instances removed.", invalidBankChestCount); this.PluginTrace.WriteLineInfo("Finished ensuring protection data."); }
private bool TryCreateAutoProtection(TSPlayer forPlayer, DPoint location) { try { this.ProtectionManager.CreateProtection(forPlayer, location, false); if (this.Config.NotifyAutoProtections) forPlayer.SendSuccessMessage(string.Format("This {0} has been protected.", TerrariaUtils.Tiles.GetBlockTypeName((BlockType)TerrariaUtils.Tiles[location].type))); return true; } catch (PlayerNotLoggedInException) { forPlayer.SendWarningMessage(string.Format( "This {0} will not be protected because you're not logged in.", TerrariaUtils.Tiles.GetBlockTypeName((BlockType)TerrariaUtils.Tiles[location].type) )); } catch (LimitEnforcementException) { forPlayer.SendWarningMessage(string.Format( "This {0} will not be protected because you've reached the protection limit.", TerrariaUtils.Tiles.GetBlockTypeName((BlockType)TerrariaUtils.Tiles[location].type) )); } catch (TileProtectedException) { this.PluginTrace.WriteLineError("Error: A block was tried to be auto protected where tile placement should not be possible."); } catch (AlreadyProtectedException) { this.PluginTrace.WriteLineError("Error: A block was tried to be auto protected on the same position of an existing protection."); } catch (Exception ex) { this.PluginTrace.WriteLineError("Unexpected exception was thrown during auto protection: \n" + ex); } return false; }
// Called after (probably) all other plugin's tile edit handlers. public virtual bool HandlePostTileEdit( TSPlayer player, TileEditType editType, BlockType blockType, DPoint location, int objectStyle ) { if (this.IsDisposed || editType != TileEditType.PlaceTile) return false; if (!this.Config.AutoProtectedTiles[(int)blockType]) return false; Task.Factory.StartNew(() => { Thread.Sleep(150); Tile tile = TerrariaUtils.Tiles[location]; if (!tile.active()) return; try { this.ProtectionManager.CreateProtection(player, location, false); if (this.Config.NotifyAutoProtections) player.SendSuccessMessage(string.Format("This {0} has been protected.", TerrariaUtils.Tiles.GetBlockTypeName((BlockType)tile.type))); } catch (PlayerNotLoggedInException) { player.SendWarningMessage(string.Format( "This {0} will not be protected because you're not logged in.", TerrariaUtils.Tiles.GetBlockTypeName((BlockType)tile.type) )); } catch (LimitEnforcementException) { player.SendWarningMessage(string.Format( "This {0} will not be protected because you've reached the protection limit.", TerrariaUtils.Tiles.GetBlockTypeName((BlockType)tile.type) )); } catch (TileProtectedException) { this.PluginTrace.WriteLineError("Error: A block was tried to be auto protected where tile placement should not be possible."); } catch (AlreadyProtectedException) { this.PluginTrace.WriteLineError("Error: A block was tried to be auto protected on the same position of an existing protection."); } catch (Exception ex) { this.PluginTrace.WriteLineError("Unexpected exception was thrown during auto protection setup: \n" + ex); } }, TaskCreationOptions.PreferFairness); return false; }
public override bool HandleTileEdit( TSPlayer player, TileEditType editType, BlockType blockType, DPoint location, int objectStyle ) { if (this.IsDisposed) return false; if (base.HandleTileEdit(player, editType, blockType, location, objectStyle)) return true; switch (editType) { case TileEditType.TileKill: case TileEditType.TileKillNoItem: { // Is the tile really going to be destroyed or just being hit? //if (blockType != 0) // break; foreach (ProtectionEntry protection in this.ProtectionManager.EnumerateProtectionEntries(location)) { // If the protection is invalid, just remove it. if (!TerrariaUtils.Tiles.IsValidCoord(protection.TileLocation)) { this.ProtectionManager.RemoveProtection(TSPlayer.Server, protection.TileLocation, false); continue; } Tile protectedTile = TerrariaUtils.Tiles[protection.TileLocation]; // If the protection is invalid, just remove it. if ( !protectedTile.active() || protectedTile.type != (int)protection.BlockType ) { this.ProtectionManager.RemoveProtection(TSPlayer.Server, protection.TileLocation, false); continue; } string tileName = TerrariaUtils.Tiles.GetBlockTypeName((BlockType)protectedTile.type); if ( protection.Owner == player.User.ID || ( this.Config.AutoDeprotectEverythingOnDestruction && player.Group.HasPermission(ProtectorPlugin.ProtectionMaster_Permission) ) ) { bool isChest = (protectedTile.type == TileID.Containers || protectedTile.type == TileID.Dressers); if (isChest) { ObjectMeasureData measureData = TerrariaUtils.Tiles.MeasureObject(protection.TileLocation); DPoint chestLocation = measureData.OriginTileLocation; int chestId = Chest.FindChest(chestLocation.X, chestLocation.Y); if (chestId != -1) { bool isBankChest = (protection.BankChestKey != BankChestDataKey.Invalid); if (isBankChest) { Chest.DestroyChestDirect(chestLocation.X, chestLocation.Y, chestId); WorldGen.KillTile(location.X, location.Y); TSPlayer.All.SendData(PacketTypes.TileKill, string.Empty, 3, chestLocation.X, chestLocation.Y, 0f, chestId); } else { Chest tChest = Main.chest[chestId]; bool isFilled = tChest.item.Any(i => i != null && i.stack > 0); if (isFilled) break; // Do not remove protections of filled chests. } } } this.ProtectionManager.RemoveProtection(player, protection.TileLocation, false); if (this.Config.NotifyAutoDeprotections) { player.SendWarningMessage(string.Format("The {0} is not protected anymore.", tileName)); } } else { player.SendErrorMessage(string.Format("The {0} is protected.", tileName)); player.SendTileSquare(location); return true; } } break; } case TileEditType.PlaceWire: case TileEditType.DestroyWire: if (this.Config.AllowWiringProtectedBlocks) break; if (this.CheckProtected(player, location, false)) { player.SendTileSquare(location); return true; } break; case TileEditType.PlaceTile: // As of Terraria 1.2.3, this packet should never be sent for chests. // Fix: We do not allow chests to be placed on active stone to prevent players from using the chest duplication bugs. // Fix2: Don't allow on ice blocks either, you never know. /*if (blockType == BlockType.Chest) { for (int x = 0; x < 2; x++) { DPoint tileBeneathLocation = location.OffsetEx(x, 1); if ( TerrariaUtils.Tiles[tileBeneathLocation].active() && ( TerrariaUtils.Tiles[tileBeneathLocation].type == (int)BlockType.ActiveStone || TerrariaUtils.Tiles[tileBeneathLocation].type == (int)BlockType.IceRodBlock ) ) { TSPlayer.All.SendData(PacketTypes.Tile, string.Empty, 0, location.X, location.Y); bool dummy; ChestStyle chestStyle = TerrariaUtils.Tiles.GetChestStyle(objectStyle, out dummy); int itemType = (int)TerrariaUtils.Tiles.GetItemTypeFromChestType(chestStyle); Item.NewItem(location.X * TerrariaUtils.TileSize, location.Y * TerrariaUtils.TileSize, 32, 32, itemType); player.SendErrorMessage("Chests can not be placed on active stone or ice blocks."); return true; } } }*/ break; } return false; }
private bool TryGetProtectionInfo(TSPlayer player, DPoint tileLocation, bool sendFailureMessages = true) { Tile tile = TerrariaUtils.Tiles[tileLocation]; if (!tile.active()) return false; ProtectionEntry protection = null; // Only need the first enumerated entry as we don't need the protections of adjacent blocks. foreach (ProtectionEntry enumProtection in this.ProtectionManager.EnumerateProtectionEntries(tileLocation)) { protection = enumProtection; break; } BlockType blockType = (BlockType)TerrariaUtils.Tiles[tileLocation].type; if (protection == null) { if (sendFailureMessages) { player.SendErrorMessage(string.Format( "This {0} is not protected by Protector at all.", TerrariaUtils.Tiles.GetBlockTypeName(blockType) )); } return false; } bool canViewExtendedInfo = ( player.Group.HasPermission(ProtectorPlugin.ViewAllProtections_Permission) || protection.Owner == player.User.ID || protection.IsSharedWithPlayer(player) ); if (!canViewExtendedInfo) { player.SendMessage(string.Format( "This {0} is protected and not shared with you.", TerrariaUtils.Tiles.GetBlockTypeName(blockType) ), Color.LightGray); player.SendWarningMessage("You are not permitted to get more information about this protection."); return true; } string ownerName; if (protection.Owner == -1) { ownerName = "{Server}"; } else { TShockAPI.DB.User tsUser = TShock.Users.GetUserByID(protection.Owner); if (tsUser != null) ownerName = tsUser.Name; else ownerName = string.Concat("{deleted user id: ", protection.Owner, "}"); } player.SendMessage(string.Format( "This {0} is protected. The owner is {1}.", TerrariaUtils.Tiles.GetBlockTypeName(blockType), ownerName ), Color.LightGray); string creationTimeFormat = "Protection created On: unknown"; if (protection.TimeOfCreation != DateTime.MinValue) creationTimeFormat = "Protection created On: {0:MM/dd/yy, h:mm tt} UTC ({1} ago)"; player.SendMessage( string.Format( CultureInfo.InvariantCulture, creationTimeFormat, protection.TimeOfCreation, (DateTime.UtcNow - protection.TimeOfCreation).ToLongString() ), Color.LightGray ); if (blockType == BlockType.Chest || blockType == BlockType.Dresser) { if (protection.RefillChestData != null) { RefillChestMetadata refillChest = protection.RefillChestData; if (refillChest.RefillTime != TimeSpan.Zero) player.SendMessage(string.Format("This is a refill chest with a timer set to {0}.", refillChest.RefillTime.ToLongString()), Color.LightGray); else player.SendMessage("This is a refill chest without a timer.", Color.LightGray); if (refillChest.OneLootPerPlayer || refillChest.RemainingLoots != -1) { StringBuilder messageBuilder = new StringBuilder(); if (refillChest.OneLootPerPlayer) messageBuilder.Append("one time by each player"); if (refillChest.RemainingLoots != -1) { if (messageBuilder.Length > 0) messageBuilder.Append(" and "); messageBuilder.Append(refillChest.RemainingLoots); messageBuilder.Append(" more times in total"); } if (refillChest.Looters != null) { messageBuilder.Append(" and was looted "); messageBuilder.Append(refillChest.Looters.Count); messageBuilder.Append(" times until now"); } messageBuilder.Insert(0, "It can only be looted "); messageBuilder.Append('.'); player.SendMessage(messageBuilder.ToString(), Color.LightGray); } } else if (protection.BankChestKey != BankChestDataKey.Invalid) { BankChestDataKey bankChestKey = protection.BankChestKey; player.SendMessage( string.Format("This is a bank chest instance with the number {0}.", bankChestKey.BankChestIndex), Color.LightGray ); } } if (ProtectionManager.IsShareableBlockType(blockType)) { if (protection.IsSharedWithEveryone) { player.SendMessage("Protection is shared with everyone.", Color.LightGray); return true; } StringBuilder sharedListBuilder = new StringBuilder(); if (protection.SharedUsers != null) { for (int i = 0; i < protection.SharedUsers.Count; i++) { if (i > 0) sharedListBuilder.Append(", "); TShockAPI.DB.User tsUser = TShock.Users.GetUserByID(protection.SharedUsers[i]); if (tsUser != null) sharedListBuilder.Append(tsUser.Name); } } if (sharedListBuilder.Length == 0 && protection.SharedGroups == null) { player.SendMessage("Protection is not shared with users or groups.", Color.LightGray); return true; } if (sharedListBuilder.Length > 0) player.SendMessage("Shared with users: " + sharedListBuilder, Color.LightGray); else player.SendMessage("Protection is not shared with users.", Color.LightGray); if (protection.SharedGroups != null) player.SendMessage("Shared with groups: " + protection.SharedGroups.ToString(), Color.LightGray); else player.SendMessage("Protection is not shared with groups.", Color.LightGray); } return true; }
public override bool HandleTileEdit( TSPlayer player, TileEditType editType, BlockType blockType, DPoint location, int objectStyle ) { if (this.IsDisposed) return false; if (base.HandleTileEdit(player, editType, blockType, location, objectStyle)) return true; switch (editType) { case TileEditType.TileKill: case TileEditType.TileKillNoItem: { // Is the tile really going to be destroyed or just being hit? //if (blockType != 0) // break; foreach (ProtectionEntry protection in this.ProtectionManager.EnumerateProtectionEntries(location)) { // If the protection is invalid, just remove it. if (!TerrariaUtils.Tiles.IsValidCoord(protection.TileLocation)) { this.ProtectionManager.RemoveProtection(TSPlayer.Server, protection.TileLocation, false); continue; } Tile protectedTile = TerrariaUtils.Tiles[protection.TileLocation]; // If the protection is invalid, just remove it. if (!protectedTile.active() || protectedTile.type != (int)protection.BlockType) { this.ProtectionManager.RemoveProtection(TSPlayer.Server, protection.TileLocation, false); continue; } string tileName = TerrariaUtils.Tiles.GetBlockTypeName((BlockType)protectedTile.type); if ( protection.Owner == player.User.ID || ( this.Config.AutoDeprotectEverythingOnDestruction && player.Group.HasPermission(ProtectorPlugin.ProtectionMaster_Permission) ) ) { bool isChest = (protectedTile.type == TileID.Containers || protectedTile.type == TileID.Dressers); if (isChest) { ObjectMeasureData measureData = TerrariaUtils.Tiles.MeasureObject(protection.TileLocation); DPoint chestLocation = measureData.OriginTileLocation; int chestId = Chest.FindChest(chestLocation.X, chestLocation.Y); if (chestId != -1) { bool isBankChest = (protection.BankChestKey != BankChestDataKey.Invalid); if (isBankChest) { Chest.DestroyChestDirect(chestLocation.X, chestLocation.Y, chestId); WorldGen.KillTile(location.X, location.Y); TSPlayer.All.SendData(PacketTypes.TileKill, string.Empty, 3, chestLocation.X, chestLocation.Y, 0f, chestId); } else { Chest tChest = Main.chest[chestId]; bool isFilled = tChest.item.Any(i => i != null && i.stack > 0); if (isFilled) break; // Do not remove protections of filled chests. } } } this.ProtectionManager.RemoveProtection(player, protection.TileLocation, false); if (this.Config.NotifyAutoDeprotections) player.SendWarningMessage(string.Format("The {0} is not protected anymore.", tileName)); } else { player.SendErrorMessage(string.Format("The {0} is protected.", tileName)); player.SendTileSquare(location); return true; } } break; } case TileEditType.PlaceWire: case TileEditType.DestroyWire: if (this.Config.AllowWiringProtectedBlocks) break; if (this.CheckProtected(player, location, false)) { player.SendTileSquare(location); return true; } break; } return false; }
public override bool HandleTileEdit( TSPlayer player, TileEditType editType, BlockType blockType, DPoint location, int objectStyle ) { if (this.IsDisposed) return false; if (base.HandleTileEdit(player, editType, blockType, location, objectStyle)) return true; switch (editType) { case TileEditType.TileKill: case TileEditType.TileKillNoItem: { // Is the tile really going to be destroyed or just being hit? if (blockType != 0) break; // Because Terraria is dumb-assed, TileKill which is usually only sent on a chest being removed, is also sent // when the chest is filled but was hit enought times to be removed, thus we have to work around this by checking // if there's content in the chest. if (TerrariaUtils.Tiles[location].active() && TerrariaUtils.Tiles[location].type == (int)BlockType.Chest) { DPoint chestLocation = TerrariaUtils.Tiles.MeasureObject(location).OriginTileLocation; int chestIndex = Chest.FindChest(chestLocation.X, chestLocation.Y); // Non existing chests are considered empty. if (chestIndex != -1) { Chest tChest = Main.chest[chestIndex]; bool isFilled = tChest.item.Any(i => i != null && i.stack > 0); if (isFilled) { lock (this.WorldMetadata.Protections) { ProtectionEntry protection; if ( !this.WorldMetadata.Protections.TryGetValue(chestLocation, out protection) || protection.BankChestKey == BankChestDataKey.Invalid ) { break; } } } } } Tile protectedTile = null; foreach (ProtectionEntry protection in this.ProtectionManager.EnumerateProtectionEntries(location)) { if (!TerrariaUtils.Tiles.IsValidCoord(protection.TileLocation)) { this.ProtectionManager.RemoveProtection(TSPlayer.Server, protection.TileLocation, false); protectedTile = null; continue; } protectedTile = TerrariaUtils.Tiles[protection.TileLocation]; // If the protection is invalid, just remove it. if (!protectedTile.active() || protectedTile.type != (int)protection.BlockType) { this.ProtectionManager.RemoveProtection(TSPlayer.Server, protection.TileLocation, false); protectedTile = null; continue; } if ( protection.Owner == player.UserID || ( this.Config.AutoDeprotectEverythingOnDestruction && player.Group.HasPermission(ProtectorPlugin.ProtectionMaster_Permission) ) ) { this.ProtectionManager.RemoveProtection(player, protection.TileLocation, false); if (this.Config.NotifyAutoDeprotections) { player.SendWarningMessage(string.Format( "The {0} is not protected anymore.", TerrariaUtils.Tiles.GetBlockTypeName((BlockType)protectedTile.type) )); } protectedTile = null; continue; } } if (protectedTile != null) { player.SendErrorMessage(string.Format( "The {0} is protected.", TerrariaUtils.Tiles.GetBlockTypeName((BlockType)protectedTile.type) )); player.SendTileSquare(location); return true; } break; } case TileEditType.PlaceWire: case TileEditType.DestroyWire: if (this.Config.AllowWiringProtectedBlocks) break; if (this.CheckProtected(player, location, false)) { player.SendTileSquare(location); return true; } break; case TileEditType.PlaceTile: // As of Terraria 1.2.3, this packet should never be sent for chests. // Fix: We do not allow chests to be placed on active stone to prevent players from using the chest duplication bugs. // Fix2: Don't allow on ice blocks either, you never know. /*if (blockType == BlockType.Chest) { for (int x = 0; x < 2; x++) { DPoint tileBeneathLocation = location.OffsetEx(x, 1); if ( TerrariaUtils.Tiles[tileBeneathLocation].active() && ( TerrariaUtils.Tiles[tileBeneathLocation].type == (int)BlockType.ActiveStone || TerrariaUtils.Tiles[tileBeneathLocation].type == (int)BlockType.IceRodBlock ) ) { TSPlayer.All.SendData(PacketTypes.Tile, string.Empty, 0, location.X, location.Y); bool dummy; ChestStyle chestStyle = TerrariaUtils.Tiles.GetChestStyle(objectStyle, out dummy); int itemType = (int)TerrariaUtils.Tiles.GetItemTypeFromChestType(chestStyle); Item.NewItem(location.X * TerrariaUtils.TileSize, location.Y * TerrariaUtils.TileSize, 32, 32, itemType); player.SendErrorMessage("Chests can not be placed on active stone or ice blocks."); return true; } } }*/ break; } return false; }
private void RollCommand(TSPlayer sender, string[] arr) { if (arr.Length > 1) { switch (arr[1].ToLower()) { case "on": rollOnLoot = true; TSPlayer.All.SendMessage(string.Format("{0} set loot rules to roll-off.", sender.Name), Color.SeaGreen); break; case "off": rollOnLoot = false; TSPlayer.All.SendMessage(string.Format("{0} set loot rules to free-for-all.", sender.Name), Color.SeaGreen); break; case "list": StringBuilder sb = new StringBuilder(); sb.Append("Loot list: "); foreach (var item in itemsToRoll) { sb.Append(string.Format("{0} ({1}),", item.AffixName(),item.stack)); } sb.Remove(sb.Length - 1, 1); sender.SendMessage(sb.ToString(), Color.GreenYellow); sb = new StringBuilder(); var inQueue = winQueue.Where(q => q.PlayerID == sender.Index).ToList(); if (inQueue.Count > 0) { sb = new StringBuilder(); sb.Append("Items Won Awaiting space: "); foreach (var item in inQueue) { sb.Append(string.Format("{0} ({1}),",item.Item.AffixName(),item.Item.stack)); } sb.Remove(sb.Length - 1, 1); sender.SendMessage(sb.ToString(), Color.Teal); } break; case "idle": if (arr.Length < 3) sender.SendInfoMessage("Correct use is /roll idle pass|roll."); else { Player player = players.Where(p => p.Index == sender.Index).FirstOrDefault(); switch (arr[2].ToLower()) { case "pass": player.PassOnIdle = true; sender.SendInfoMessage("You have chosen to automatically pass on loot if you do not respond."); break; case "roll": player.PassOnIdle = false; sender.SendInfoMessage("You have chosen to automatically roll on loot if you do not respond."); break; default: sender.SendErrorMessage("Proper use is /roll idle pass|roll."); break; } } break; case "?": case "help": sender.SendInfoMessage("/roll on|off - Toggles loot rolling on item drops."); sender.SendInfoMessage("/roll list - Shows list of items to roll on, and any items awaiting for space in your inventory."); sender.SendInfoMessage("/roll idle pass|roll - Set whether to roll or pass if you're idle on loot rolls."); break; default: sender.SendInfoMessage("Invalid use. Proper use is /roll on|off|list|help|?"); break; } } else { if (itemsToRoll.Count <= 0) { sender.SendWarningMessage("No items to roll on. Type /roll ? or /roll help for more info."); } else { Player player = players.Where(p => p.Index == sender.Index).FirstOrDefault(); if (player.Roll == -1) sender.SendWarningMessage("You already passed on this item!"); else if (player.Roll != 0) sender.SendWarningMessage(string.Format("You already rolled a {0} on this item! Stop rolling!", player.Roll)); else { Random rnd = new Random(); player.Roll = (sbyte)rnd.Next(1, 101); TSPlayer.All.SendInfoMessage(string.Format("{0} rolled a {1}.", player.Name, player.Roll)); CheckLootRoll(); } } } }
private void PassCommand(TSPlayer sender) { if (itemsToRoll.Count <= 0) { sender.SendWarningMessage("No items to roll on."); } else { Player player = players.Where(p => p.Index == sender.Index).FirstOrDefault(); if (player.Roll != 0) sender.SendWarningMessage(string.Format("You already rolled a {0} on this item! Stop rolling!", player.Roll)); else { player.Roll = -1; TSPlayer.All.SendInfoMessage("{0} passes.",player.Name); CheckLootRoll(); } } }