Exemple #1
0
        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);
            }
        }
Exemple #2
0
        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);
        }
Exemple #3
0
 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();
     }
 }
Exemple #4
0
 /// <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);
        }
Exemple #6
0
        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
                    );
            }
        }