public static void OnLeave(LeaveEventArgs args) { if (args.Who >= TShockB.Players.Length || args.Who < 0) { //Something not right has happened return; } var tsplr = TShockB.Players[args.Who]; TShockB.Players[args.Who] = null; if (tsplr != null && tsplr.ReceivedInfo) { if (!tsplr.SilentKickInProgress && tsplr.State >= 3) { string playername = $"[c/4747BF:{tsplr.Name}]"; if (!tsplr.TPlayer.Male) { playername = $"[c/800080:{tsplr.Name}]"; } TShock.AllSendMessagev2($"{playername} saiu do servidor.", $"{playername} has left the server.", Color.Gray); } Logger.doLog($"{tsplr.Name} has left the server.", Config.DebugLevel.Info); if (tsplr.IsLoggedIn && !tsplr.IgnoreActionsForClearingTrashCan && Main.ServerSideCharacter && (!tsplr.Dead || tsplr.TPlayer.difficulty != 2)) { tsplr.PlayerData.CopyCharacter(tsplr); TShock.CharacterDB.InsertPlayerData(tsplr); } if (TShock.Config.RememberLeavePos && !tsplr.LoginHarassed) { TShock.RememberedPos.InsertLeavePos(tsplr.Name, tsplr.IP, (int)(tsplr.X / 16), (int)(tsplr.Y / 16)); } if (tsplr.tempGroupTimer != null) { tsplr.tempGroupTimer.Stop(); } } // Fire the OnPlayerLogout hook too, if the player was logged in and they have a TSPlayer object. if (tsplr != null && tsplr.IsLoggedIn) { TShockAPI.Hooks.PlayerHooks.OnPlayerLogout(tsplr); } // The last player will leave after this hook is executed. if (UtilsB.ActivePlayers() == 1) { if (TShock.Config.SaveWorldOnLastPlayerExit) { SaveManagerB.Instance.SaveWorld(); } TShockB.SetConsoleTitle(true); } }
public ProtectionEntry CreateProtection( TSPlayer player, DPoint tileLocation, bool checkIfBlockTypeProtectableByConfig = true, bool checkTShockBuildAndRegionAccess = true, bool checkLimits = true ) { Contract.Requires <ArgumentNullException>(player != null); Contract.Requires <ArgumentException>(TerrariaUtils.Tiles[tileLocation] != null, "tileLocation"); Contract.Requires <ArgumentException>(TerrariaUtils.Tiles[tileLocation].active(), "tileLocation"); Tile tile = TerrariaUtils.Tiles[tileLocation]; BlockType blockType = (BlockType)tile.type; tileLocation = TerrariaUtils.Tiles.MeasureObject(tileLocation).OriginTileLocation; if (checkIfBlockTypeProtectableByConfig && !this.Config.ManuallyProtectableTiles[tile.type]) { throw new InvalidBlockTypeException(blockType); } if (checkTShockBuildAndRegionAccess && TShock.CheckTilePermission(player, tileLocation.X, tileLocation.Y)) { throw new TileProtectedException(tileLocation); } if ( checkLimits && !player.Group.HasPermission(ProtectorPlugin.NoProtectionLimits_Permission) && this.WorldMetadata.CountUserProtections(player.UserID) >= this.Config.MaxProtectionsPerPlayerPerWorld ) { throw new LimitEnforcementException(); } ProtectionEntry protection; lock (this.WorldMetadata.Protections) { if (this.WorldMetadata.Protections.TryGetValue(tileLocation, out protection)) { if (protection.Owner == player.UserID) { throw new AlreadyProtectedException(); } throw new TileProtectedException(tileLocation); } } protection = new ProtectionEntry(player.UserID, tileLocation, (BlockType)tile.type); lock (this.WorldMetadata.Protections) this.WorldMetadata.Protections.Add(tileLocation, protection); return(protection); }
private void SaveWorker() { while (true) { lock (_saveLock) { // NOTE: lock for the entire process so wait works in SaveWorld if (_saveQueue.Count > 0) { SaveTask task = _saveQueue.Dequeue(); if (null == task) { return; } else { // Ensure that save handler errors don't bubble up and cause a recursive call // These can be caused by an unexpected error such as a bad or out of date plugin try { if (task.direct) { OnSaveWorld(new WorldSaveEventArgs()); WorldFile.saveWorld(task.resetTime); } else { WorldFile.saveWorld(task.resetTime); } TShock.Log.ConsoleInfo("Mapa Salvo"); TShock.AllSendMessagev2("Mapa Salvo", "World Saved", Color.SeaGreen); TShock.Log.Info(string.Format("World saved at ({0})", Main.worldPathName)); } catch (Exception e) { TShock.AllSendMessagev2("O salvamento do mapa falhou", "World saved failed", Color.Red); TShock.Log.Error("World saved failed"); TShock.Log.Error(e.ToString()); } } } } _wh.WaitOne(); } }
/// <summary> /// SaveWorld event handler which notifies users that the server may lag /// </summary> public void OnSaveWorld(WorldSaveEventArgs args) { if (TShock.Config.AnnounceSave) { // Protect against internal errors causing save failures // These can be caused by an unexpected error such as a bad or out of date plugin try { TShock.Log.ConsoleInfo("Salvando Mundo. Lag momentâneo poderá ser notado durante alguns segundos."); TShock.AllSendMessagev2("Salvando Mundo. Lag momentâneo poderá ser notado durante alguns segundos.", "Saving World...", Color.DarkSeaGreen); } catch (Exception ex) { TShock.Log.Error("World saved notification failed"); TShock.Log.Error(ex.ToString()); } } }
private bool TryExecuteSubCommand(string commandNameLC, CommandArgs args) { switch (commandNameLC) { case "commands": case "cmds": args.Player.SendMessage("Available Sub-Commands:", Color.White); args.Player.SendMessage("/ac blocks", Color.Yellow); args.Player.SendMessage("/ac toggle|switch", Color.Yellow); if (args.Player.Group.HasPermission(AdvancedCircuitsPlugin.ReloadCfg_Permission)) { args.Player.SendMessage("/ac reloadcfg", Color.Yellow); } return(true); case "reloadcfg": if (args.Player.Group.HasPermission(AdvancedCircuitsPlugin.ReloadCfg_Permission)) { this.PluginTrace.WriteLineInfo("Reloading configuration file."); try { this.ReloadConfigurationCallback(); this.PluginTrace.WriteLineInfo("Configuration file successfully reloaded."); if (args.Player != TSPlayer.Server) { args.Player.SendMessage("Configuration file successfully reloaded.", Color.Yellow); } } catch (Exception ex) { this.PluginTrace.WriteLineError( "Reloading the configuration file failed. Keeping old configuration. Exception details:\n{0}", ex ); } } else { args.Player.SendErrorMessage("You do not have the necessary permission to do that."); } return(true); case "blocks": case "ores": case "tiles": int pageNumber; if (!PaginationUtil.TryParsePageNumber(args.Parameters, 1, args.Player, out pageNumber)) { return(true); } PaginationUtil.SendPage( args.Player, pageNumber, new List <string>() { "Copper Ore - OR-Gate", "Silver Ore - AND-Gate", "Gold Ore - XOR-Gate / XOR-Port", "Obsidian - NOT-Gate / NOT-Port", "Iron Ore - Swapper", "Spike - Crossover Bridge", "Glass - Input Port", "Active Stone - Active Stone and Block Activator", "Adamantite Ore - Wireless Transmitter" }, new PaginationUtil.Settings { HeaderFormat = "Advanced Circuits Special Blocks (Page {0} of {1})", HeaderTextColor = Color.Lime, LineTextColor = Color.LightGray, MaxLinesPerPage = 4, } ); return(true); case "toggle": case "switch": args.Player.SendInfoMessage("Place or destroy a wire on the component you want to toggle."); if (args.Parameters.Count > 3) { args.Player.SendErrorMessage("Proper syntax: /ac switch [state] [+p]"); args.Player.SendInfoMessage("Type /ac switch help to get more help to this command."); return(true); } bool persistentMode = false; bool?newState = null; if (args.Parameters.Count > 1) { int newStateRaw; if (int.TryParse(args.Parameters[1], out newStateRaw)) { newState = (newStateRaw == 1); } persistentMode = args.ContainsParameter("+p", StringComparison.InvariantCultureIgnoreCase); } CommandInteraction interaction = this.StartOrResetCommandInteraction(args.Player); interaction.DoesNeverComplete = persistentMode; interaction.TileEditCallback = (player, editType, blockType, location, blockStyle) => { if ( editType != TileEditType.PlaceTile || editType != TileEditType.PlaceWall || editType != TileEditType.DestroyWall || editType != TileEditType.PlaceActuator ) { CommandInteractionResult result = new CommandInteractionResult { IsHandled = true, IsInteractionCompleted = true }; Tile tile = TerrariaUtils.Tiles[location]; if ( TShock.CheckTilePermission(args.Player, location.X, location.Y) || ( this.PluginCooperationHandler.IsProtectorAvailable && this.PluginCooperationHandler.Protector_CheckProtected(args.Player, location, false) ) ) { player.SendErrorMessage("This object is protected."); player.SendTileSquare(location, 1); return(result); } BlockType hitBlockType = (BlockType)tile.type; if (tile.active() && hitBlockType == BlockType.ActiveStone) { if (newState == null || newState == false) { TerrariaUtils.Tiles.SetBlock(location, BlockType.InactiveStone); } else { args.Player.SendTileSquare(location); } } else if (hitBlockType == BlockType.InactiveStone) { if (tile.active() && newState == null || newState == true) { TerrariaUtils.Tiles.SetBlock(location, BlockType.ActiveStone); } else { args.Player.SendTileSquare(location); } } else if (tile.active() && TerrariaUtils.Tiles.IsMultistateObject(hitBlockType)) { ObjectMeasureData measureData = TerrariaUtils.Tiles.MeasureObject(location); bool currentState = TerrariaUtils.Tiles.ObjectHasActiveState(measureData); if (newState == null) { newState = !TerrariaUtils.Tiles.ObjectHasActiveState(measureData); } if (currentState != newState.Value) { TerrariaUtils.Tiles.SetObjectState(measureData, newState.Value); } else { args.Player.SendTileSquare(location); } } else if ( hitBlockType == AdvancedCircuits.BlockType_ORGate || hitBlockType == AdvancedCircuits.BlockType_ANDGate || hitBlockType == AdvancedCircuits.BlockType_XORGate ) { if ( TShock.CheckTilePermission(args.Player, location.X, location.Y) || ( this.PluginCooperationHandler.IsProtectorAvailable && this.PluginCooperationHandler.Protector_CheckProtected(args.Player, location, false) )) { player.SendErrorMessage("This gate is protected."); player.SendTileSquare(location); return(result); } PaintColor paint = (PaintColor)TerrariaUtils.Tiles[location].color(); if (paint == AdvancedCircuits.Paint_Gate_TemporaryState) { player.SendErrorMessage("The gate is painted {0}, there's no point in initializing it.", AdvancedCircuits.Paint_Gate_TemporaryState); args.Player.SendTileSquare(location); return(result); } GateStateMetadata gateState; if (!this.WorldMetadata.GateStates.TryGetValue(location, out gateState)) { gateState = new GateStateMetadata(); this.WorldMetadata.GateStates.Add(location, gateState); } List <DPoint> gatePortLocations = new List <DPoint>(AdvancedCircuits.EnumerateComponentPortLocations(location, new DPoint(1, 1))); for (int i = 0; i < 4; i++) { Tile gatePort = TerrariaUtils.Tiles[gatePortLocations[i]]; if (!gatePort.active() || gatePort.type != (int)AdvancedCircuits.BlockType_InputPort) { continue; } if (newState == null) { if (gateState.PortStates[i] == null) { gateState.PortStates[i] = true; } else { gateState.PortStates[i] = !gateState.PortStates[i]; } } else { gateState.PortStates[i] = newState.Value; } } player.SendSuccessMessage("The states of this gate's ports are now:"); this.SendGatePortStatesInfo(args.Player, gateState); args.Player.SendTileSquare(location); } else if (tile.active() && tile.type == (int)AdvancedCircuits.BlockType_InputPort) { foreach (DPoint adjacentTileLocation in AdvancedCircuits.EnumerateComponentPortLocations(location, new DPoint(1, 1))) { Tile adjacentTile = TerrariaUtils.Tiles[adjacentTileLocation]; if (!adjacentTile.active() || !AdvancedCircuits.IsLogicalGate((BlockType)adjacentTile.type)) { continue; } if ( TShock.CheckTilePermission(args.Player, adjacentTileLocation.X, adjacentTileLocation.Y) || ( this.PluginCooperationHandler.IsProtectorAvailable && this.PluginCooperationHandler.Protector_CheckProtected(args.Player, adjacentTileLocation, false) ) ) { player.SendErrorMessage("This gate is protected."); player.SendTileSquare(location); return(result); } PaintColor paint = (PaintColor)TerrariaUtils.Tiles[location].color(); if (paint == AdvancedCircuits.Paint_Gate_TemporaryState) { player.SendErrorMessage("The gate is painted {0}, there's no point in initializing it.", AdvancedCircuits.Paint_Gate_TemporaryState); args.Player.SendTileSquare(location); return(result); } GateStateMetadata gateState; if (!this.WorldMetadata.GateStates.TryGetValue(adjacentTileLocation, out gateState)) { gateState = new GateStateMetadata(); this.WorldMetadata.GateStates.Add(adjacentTileLocation, gateState); } int portIndex; switch (AdvancedCircuits.DirectionFromTileLocations(adjacentTileLocation, location)) { case Direction.Up: portIndex = 0; break; case Direction.Down: portIndex = 1; break; case Direction.Left: portIndex = 2; break; case Direction.Right: portIndex = 3; break; default: return(result); } if (newState == null) { if (gateState.PortStates[portIndex] == null) { gateState.PortStates[portIndex] = true; } else { gateState.PortStates[portIndex] = !gateState.PortStates[portIndex]; } } else { gateState.PortStates[portIndex] = newState.Value; } player.SendSuccessMessage("The states of this gate's ports are now:"); this.SendGatePortStatesInfo(args.Player, gateState); args.Player.SendTileSquare(location); return(result); } player.SendErrorMessage(string.Format( "The state of \"{0}\" can not be changed.", TerrariaUtils.Tiles.GetBlockTypeName(hitBlockType) )); player.SendTileSquare(location); } return(result); } return(new CommandInteractionResult { IsHandled = false, IsInteractionCompleted = false }); }; interaction.TimeExpiredCallback = (player) => { player.SendErrorMessage("Waited too long, no component will be toggled."); }; args.Player.SendSuccessMessage("Hit an object to change its state."); return(true); } return(false); }
private void NetHooks_GetData(GetDataEventArgs e) { if (e == null || this.isDisposed || e.Handled) { return; } TSPlayer player = TShock.Players[e.Msg.whoAmI]; if (player == null) { return; } try { switch (e.MsgID) { case PacketTypes.Tile: { if (this.TileEdit == null) { break; } int editType = e.Msg.readBuffer[e.Index]; int x = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 1); int y = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 3); if (!TerrariaUtils.Tiles.IsValidCoord(x, y) || editType > 14) { return; } int blockType = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 5); int objectStyle = e.Msg.readBuffer[e.Index + 7]; e.Handled = this.OnTileEdit( new TileEditEventArgs(player, (TileEditType)editType, new DPoint(x, y), (BlockType)blockType, objectStyle )); break; } case PacketTypes.PlaceObject: { if (this.ObjectPlacement == null && this.TileEdit == null) { break; } int x = BitConverter.ToInt16(e.Msg.readBuffer, e.Index); int y = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 2); if (!TerrariaUtils.Tiles.IsValidCoord(x, y)) { return; } int blockType = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 4); int objectStyle = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 6); int alternative = e.Msg.readBuffer[e.Index + 8]; int random = ((sbyte)e.Msg.readBuffer[e.Index + 9]); bool direction = BitConverter.ToBoolean(e.Msg.readBuffer, e.Index + 10); if (this.InvokeTileOnObjectPlacement) { e.Handled = this.OnTileEdit( new TileEditEventArgs(player, TileEditType.PlaceTile, new DPoint(x, y), (BlockType)blockType, objectStyle )); } if (!e.Handled) { e.Handled = this.OnObjectPlacement( new ObjectPlacementEventArgs(player, new DPoint(x, y), (BlockType)blockType, objectStyle, alternative, random, direction )); } break; } // Note: As for TileKill and TileKillNoItem, blockId will be of "1" if the player attempted to destroy // a tile but didn't succeed yet, and will be of "0" as the tile is actually destroyed. // However, there's one exception with Chests, they will never send their actual destroy packet, except a hack // tool is used, it seems. case PacketTypes.TileKill: { int type = e.Msg.readBuffer[e.Index]; int x = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 1); int y = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 3); if (!TerrariaUtils.Tiles.IsValidCoord(x, y)) { break; } int style = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 5); if (type == 0 || type == 2) // Chest placement / Dresser Placement { e.Handled = this.OnChestPlace(new ChestPlaceEventArgs(player, new DPoint(x, y), type, style)); } else // Chest kill { int tileType = TerrariaUtils.Tiles[x, y].type; if (tileType != TileID.Containers && tileType != TileID.Dressers) { break; } if (this.InvokeTileEditOnChestKill) { e.Handled = this.OnTileEdit(new TileEditEventArgs(player, TileEditType.TileKill, new DPoint(x, y), 0, 0)); } if (!e.Handled) { e.Handled = this.OnChestKill(new TileLocationEventArgs(player, new DPoint(x, y))); } } break; } case PacketTypes.ChestOpen: { if (this.ChestOpen == null && this.ChestRename == null) { break; } int chestIndex = BitConverter.ToInt16(e.Msg.readBuffer, e.Index); int x = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 2); int y = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 4); if (!TerrariaUtils.Tiles.IsValidCoord(x, y)) { break; } int nameLength = e.Msg.readBuffer[e.Index + 6]; string newName = string.Empty; if ((nameLength > 0 && nameLength <= 20) || nameLength == 255) // Name change requested? { if (nameLength != 255) { newName = Encoding.UTF8.GetString(e.Msg.readBuffer, e.Index + 8, nameLength); } e.Handled = this.OnChestRename(new ChestRenameEventArgs(player, chestIndex, newName)); } if (!e.Handled) { e.Handled = this.OnChestOpen(new ChestOpenEventArgs(player, chestIndex, new DPoint(x, y))); } break; } case PacketTypes.ChestGetContents: { if (this.ChestGetContents == null) { break; } int x = BitConverter.ToInt16(e.Msg.readBuffer, e.Index); int y = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 2); if (!TerrariaUtils.Tiles.IsValidCoord(x, y) || !Main.tile[x, y].active()) { return; } e.Handled = this.OnChestGetContents(new TileLocationEventArgs(player, new DPoint(x, y))); break; } case PacketTypes.ChestItem: { if (this.ChestModifySlot == null) { break; } int chestIndex = BitConverter.ToInt16(e.Msg.readBuffer, e.Index); int slotIndex = e.Msg.readBuffer[e.Index + 2]; int itemStackSize = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 3); ItemPrefix itemPrefix = (ItemPrefix)e.Msg.readBuffer[e.Index + 5]; ItemType itemType = (ItemType)BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 6); if (chestIndex >= Main.chest.Length || slotIndex > 39) { break; } e.Handled = this.OnChestModifySlot(new ChestModifySlotEventArgs( player, chestIndex, slotIndex, new ItemData(itemPrefix, itemType, itemStackSize) )); break; } case PacketTypes.SignNew: { if (this.SignEdit == null) { break; } int signIndex = BitConverter.ToInt16(e.Msg.readBuffer, e.Index); int x = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 2); int y = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 4); string newText; using (MemoryStream stream = new MemoryStream(e.Msg.readBuffer, e.Index + 6, e.Length - 7)) newText = new BinaryReader(stream).ReadString(); if (!TerrariaUtils.Tiles.IsValidCoord(x, y) || !Main.tile[x, y].active()) { return; } e.Handled = this.OnSignEdit(new SignEditEventArgs(player, signIndex, new DPoint(x, y), newText)); break; } case PacketTypes.SignRead: { if (this.SignRead == null) { break; } int x = BitConverter.ToInt16(e.Msg.readBuffer, e.Index); int y = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 2); if (!TerrariaUtils.Tiles.IsValidCoord(x, y)) { break; } e.Handled = this.OnSignRead(new TileLocationEventArgs(player, new DPoint(x, y))); break; } case PacketTypes.HitSwitch: { if (this.HitSwitch == null) { break; } int x = BitConverter.ToInt16(e.Msg.readBuffer, e.Index); int y = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 2); if (!TerrariaUtils.Tiles.IsValidCoord(x, y) || !Main.tile[x, y].active()) { return; } // For some reason, TShock doesn't handle this packet so we just do our own checks. if (TShock.CheckIgnores(player)) { return; } if (TShock.CheckRangePermission(player, x, y, 32)) { return; } e.Handled = this.OnHitSwitch(new TileLocationEventArgs(player, new DPoint(x, y))); break; } case PacketTypes.SpawnBossorInvasion: { if (this.BossSpawn == null) { break; } //int playerIndex = BitConverter.ToInt32(e.Msg.readBuffer, e.Index); int bossType = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 2); e.Handled = this.OnBossSpawn(new BossSpawnEventArgs(player, (BossType)bossType)); break; } case PacketTypes.ItemDrop: case PacketTypes.UpdateItemDrop: { // ItemDrop2 if (this.ItemUpdate == null) { break; } int itemIndex = BitConverter.ToInt16(e.Msg.readBuffer, e.Index); float x = BitConverter.ToSingle(e.Msg.readBuffer, e.Index + 2); float y = BitConverter.ToSingle(e.Msg.readBuffer, e.Index + 6); float velocityX = BitConverter.ToSingle(e.Msg.readBuffer, e.Index + 10); float velocityY = BitConverter.ToSingle(e.Msg.readBuffer, e.Index + 14); int itemStackSize = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 18); ItemPrefix itemPrefix = (ItemPrefix)e.Msg.readBuffer[e.Index + 20]; bool noDelay = (e.Msg.readBuffer[e.Index + 21] != 0); ItemType itemType = (ItemType)BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 22); // If it is actually an item pick up, then ensure a valid item index. if (itemType == 0 && (itemIndex < 0 || itemIndex >= Main.item.Length)) { break; } e.Handled = this.OnItemUpdate(new ItemUpdateEventArgs( player, itemIndex, new Vector2(x, y), new Vector2(velocityX, velocityY), noDelay, new ItemData(itemPrefix, itemType, itemStackSize) )); break; } case PacketTypes.ItemOwner: { if (this.ItemOwner == null) { break; } int itemIndex = BitConverter.ToInt16(e.Msg.readBuffer, e.Index); int newOwnerPlayerIndex = e.Msg.readBuffer[e.Index + 2]; TSPlayer newOwner; if (newOwnerPlayerIndex < 255) { newOwner = TShock.Players[newOwnerPlayerIndex]; } else { break; } e.Handled = this.OnItemOwner(new ItemOwnerEventArgs(player, itemIndex, newOwner)); break; } case PacketTypes.ForceItemIntoNearestChest: { // QuickStackNearby if (this.QuickStackNearby == null) { break; } int slotIndex = e.Msg.readBuffer[e.Index]; if (slotIndex >= TSPlayer.Server.TPlayer.inventory.Length) { break; } e.Handled = this.OnQuickStackNearby(new PlayerSlotEventArgs(player, slotIndex)); break; } case PacketTypes.PlayerSlot: { if (this.PlayerModifySlot == null) { break; } //byte playerIndex = e.Msg.readBuffer[e.Index]; int slotIndex = e.Msg.readBuffer[e.Index + 1]; int itemStackSize = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 2); ItemPrefix itemPrefix = (ItemPrefix)e.Msg.readBuffer[e.Index + 4]; ItemType itemType = (ItemType)BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 5); Player tServerPlayer = TSPlayer.Server.TPlayer; if (slotIndex >= tServerPlayer.inventory.Length + tServerPlayer.bank.item.Length + tServerPlayer.bank2.item.Length) { break; } e.Handled = this.OnPlayerModifySlot(new PlayerModifySlotEventArgs( player, slotIndex, new ItemData(itemPrefix, itemType, itemStackSize) )); break; } case PacketTypes.LiquidSet: { if (this.LiquidSet == null) { break; } int x = BitConverter.ToInt16(e.Msg.readBuffer, e.Index); int y = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 2); if (!TerrariaUtils.Tiles.IsValidCoord(x, y)) { break; } int liquidAmount = e.Msg.readBuffer[e.Index + 4]; LiquidKind liquidKind = (LiquidKind)e.Msg.readBuffer[e.Index + 5]; e.Handled = this.OnLiquidSet(new LiquidSetEventArgs(player, new DPoint(x, y), liquidAmount, liquidKind)); break; } case PacketTypes.DoorUse: { if (this.DoorUse == null) { break; } byte action = e.Msg.readBuffer[e.Index]; int x = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 1); int y = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 3); if (!TerrariaUtils.Tiles.IsValidCoord(x, y)) { break; } int direction = e.Msg.readBuffer[e.Index + 5]; Direction actualDirection = Direction.Right; if (direction == 0) { actualDirection = Direction.Left; } e.Handled = this.OnDoorUse(new DoorUseEventArgs(player, new DPoint(x, y), (DoorAction)action, actualDirection)); break; } case PacketTypes.PlayerSpawn: { if (this.PlayerSpawn == null) { break; } int playerIndex = e.Msg.readBuffer[e.Index]; int spawnX = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 1); int spawnY = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 3); if (!TerrariaUtils.Tiles.IsValidCoord(spawnX, spawnY)) { break; } e.Handled = this.OnPlayerSpawn(new PlayerSpawnEventArgs(player, new DPoint(spawnX, spawnY))); break; } // Note: Also door unlock case PacketTypes.ChestUnlock: { if (this.ChestUnlock == null) { break; } UnlockType unlockType = (UnlockType)e.Msg.readBuffer[e.Index]; int chestX = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 1); int chestY = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 3); if (!TerrariaUtils.Tiles.IsValidCoord(chestX, chestY)) { break; } e.Handled = this.OnChestUnlock(new UnlockEventArgs(player, new DPoint(chestX, chestY), unlockType)); break; } case PacketTypes.ChatText: { if (this.ChatText == null) { break; } short playerIndex = e.Msg.readBuffer[e.Index]; if (playerIndex != e.Msg.whoAmI) { break; } int colorR = e.Msg.readBuffer[e.Index + 1]; int colorG = e.Msg.readBuffer[e.Index + 2]; int colorB = e.Msg.readBuffer[e.Index + 3]; string text = Encoding.UTF8.GetString(e.Msg.readBuffer, e.Index + 4, e.Length - 5); e.Handled = this.OnChatText(new ChatTextEventArgs(player, new Color(colorR, colorG, colorB), text)); break; } case PacketTypes.TileSendSquare: { if (this.SendTileSquare == null) { break; } int size = BitConverter.ToInt16(e.Msg.readBuffer, e.Index); int tileX = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 2); int tileY = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 4); if (!TerrariaUtils.Tiles.IsValidCoord(tileX, tileY)) { break; } e.Handled = this.OnSendTileSquare(new SendTileSquareEventArgs(player, new DPoint(tileX, tileY), size)); break; } case PacketTypes.PaintTile: { if (this.TilePaint == null) { break; } int tileX = BitConverter.ToInt16(e.Msg.readBuffer, e.Index); int tileY = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 2); if (!TerrariaUtils.Tiles.IsValidCoord(tileX, tileY)) { break; } int color = e.Msg.readBuffer[e.Index + 8]; e.Handled = this.OnTilePaint(new TilePaintEventArgs(player, new DPoint(tileX, tileY), (PaintColor)color)); break; } case PacketTypes.PlayerKillMe: { if (this.PlayerDeath == null) { break; } int playerIndex = e.Msg.readBuffer[e.Index]; int direction = e.Msg.readBuffer[e.Index + 1]; int dmg = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 2); bool pvp = e.Msg.readBuffer[e.Index + 4] != 0; string deathText = Encoding.UTF8.GetString(e.Msg.readBuffer, e.Index + 6, e.Length - 7); e.Handled = this.OnPlayerDeath(new PlayerDeathEventArgs(player, direction, dmg, pvp, deathText)); break; } case PacketTypes.Teleport: { if (this.Teleport == null) { break; } BitsByte flags = e.Msg.readBuffer[e.Index]; int playerIndex = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 1); float x = BitConverter.ToSingle(e.Msg.readBuffer, e.Index + 3); float y = BitConverter.ToSingle(e.Msg.readBuffer, e.Index + 7); Vector2 destLocation = new Vector2(x, y); TeleportType tpType = TeleportType.PlayerToPos; if (flags[0]) { tpType = TeleportType.NpcToPos; } if (flags[1]) { if (flags[0]) { tpType = TeleportType.Unknown; } else { tpType = TeleportType.PlayerNearPlayerWormhole; } } e.Handled = this.OnTeleport(new TeleportEventArgs(player, destLocation, tpType)); break; } } } catch (Exception ex) { ServerApi.LogWriter.PluginWriteLine( this.Plugin, string.Format("Internal error on handling data packet {0}. Exception details: \n{1}", e.MsgID, ex), TraceLevel.Error ); } }