private void DeathFix(GetDataEventArgs args) { if (args.MsgID == PacketTypes.PlayerDeathV2) { using (BinaryReader reader = new BinaryReader(new MemoryStream(args.Msg.readBuffer, args.Index, args.Length))) { reader.ReadByte(); PlayerDeathReason playerDeathReason = PlayerDeathReason.FromReader(reader); var dmg = reader.ReadInt16(); var direction = (byte)(reader.ReadByte() - 1); BitsByte bits = reader.ReadByte(); bool pvp = bits[0]; TShock.Players[args.Msg.whoAmI].TPlayer.KillMe(playerDeathReason, dmg, direction, pvp); TShock.Players[args.Msg.whoAmI].Dead = true; TShock.Players[args.Msg.whoAmI].TPlayer.dead = true; NetMessage.SendPlayerDeath(args.Msg.whoAmI, playerDeathReason, dmg, direction, pvp); NetMessage.SendPlayerDeath(args.Msg.whoAmI, playerDeathReason, dmg, direction, pvp, args.Msg.whoAmI); args.Handled = true; } } }
private void OnGetData(GetDataEventArgs e) { if (!e.Handled) { if (e.MsgID == PacketTypes.PlayerDeathV2) { using (BinaryReader br = new BinaryReader(new MemoryStream(e.Msg.readBuffer, e.Index, e.Length))) { byte who = br.ReadByte(); var reason = PlayerDeathReason.FromReader(br); int damage = br.ReadInt16(); byte dir = br.ReadByte(); byte flag = br.ReadByte(); string d = TShock.Players[who].UUID; switch (flag) { case 0: block(d).IncreaseValue("pveDeaths", 1); break; case 1: block(d).IncreaseValue("pvpDeaths", 1); block(TShock.Players[reason.SourcePlayerIndex].UUID).IncreaseValue("Kills", 1); break; default: break; } } } } }
public PlayerDeathArgs(GetDataEventArgs args, MemoryStream data, TSPlayer player) : base(player) { data.ReadByte(); // Player ID PlayerDeathReason = PlayerDeathReason.FromReader(new BinaryReader(data)); Damage = data.ReadInt16(); HitDirection = (byte)data.ReadByte(); Flags = (byte)data.ReadByte(); }
private void OnDeathEvent(TSPlayer player, MemoryStream data) { // Read in Byte data.ReadByte(); PlayerDeathReason death = PlayerDeathReason.FromReader(new BinaryReader(data)); string reason = death.GetDeathText(player.TPlayer.name).ToString(); // Update player last death event lastPlaceOfDeathData.UpdateLocationUser(player.UUID, new Vector2(player.X, player.Y), reason); }
public PlayerHurtArgs(GetDataEventArgs args, MemoryStream data, TSPlayer player) : base(player) { Args = args; PlayerID = data.ReadByte(); PlayerHitReason = PlayerDeathReason.FromReader(new BinaryReader(data)); Damage = data.ReadInt16(); HitDirection = (byte)data.ReadByte(); Flags = (byte)data.ReadByte(); CooldownCounter = (sbyte)data.ReadByte(); }
private void OnGetData(GetDataEventArgs args) { if (args.MsgID == PacketTypes.PlayerDeathV2) //Checks the packet type for the playerdeath type, 118 { using (MemoryStream data = new MemoryStream(args.Msg.readBuffer, args.Index, args.Length)) { // You can see how packets are handled in MessageBuffer.cs and how they are sent in NetMessage.cs // TShock's GetDataHandler.cs can be used as an example on deserializing packets, same with other plugins // Some custom types from terraria have their own methods to read from a binary reader (you can see this in use by tshock & terraria's messagebuffer) // See https://tshock.readme.io/docs/multiplayer-packet-structure for more packet information int player = data.ReadByte(); //Player ID PlayerDeathReason deathReason = PlayerDeathReason.FromReader(new BinaryReader(data)); //Terraria.DataStructures.PlayerDeathReason int damage = data.ReadInt16(); //Damage taken int direction = data.ReadByte() - 1; //Direction, left or right, the player's body parts fly off to bool pvp = ((BitsByte)data.ReadByte())[0]; args.Handled = true; //Prevents the game from processing this event string customDeathReason = ""; //start of a custom death reason Projectile proj = new Projectile(); //a projectile object used to get the name of a projectile given the projectile id/type proj.SetDefaults(deathReason._sourceProjectileType); if (pvp) //conditions could be cleaner { customDeathReason = (deathReason._sourcePlayerIndex == 0) ? $"[c/00ccff:{TShock.Players[player].Name}] was dealt [c/afef2a:{damage}] mortal damage by their own [i/p{deathReason._sourceItemPrefix}:{deathReason._sourceItemType}]" : $"[c/00ccff:{TShock.Players[player].Name}] was dealt [c/afef2a:{damage}] fatal damage by {TShock.Players[deathReason._sourcePlayerIndex].Name}'s [i/p{deathReason._sourceItemPrefix}:{deathReason._sourceItemType}]"; } else if (deathReason._sourceNPCIndex != -1) { customDeathReason = $"[c/00ccff:{TShock.Players[player].Name}] was dealt [c/afef2a:{damage}] mortal damage by [c/00ff00:{Terraria.Main.npc[deathReason._sourceNPCIndex].TypeName}]"; } else if (deathReason._sourceOtherIndex == -1 && proj.hostile) { customDeathReason = $"[c/00ccff:{TShock.Players[player].Name}] was dealt [c/afef2a:{damage}] mortal damage by [c/00ff00:{proj.Name}]"; } else if (deathReason._sourceOtherIndex == 4) { string evil = WorldGen.crimson ? "Crimson" : "Demon"; customDeathReason = $"[c/00ccff:{TShock.Players[player].Name}] was driven insane trying to smash a [c/00ff00:{evil} altar]"; } if (customDeathReason != "") { deathReason = PlayerDeathReason.ByCustomReason(customDeathReason); } Terraria.Main.player[player].KillMe(deathReason, damage, direction, pvp); //Terraria method used in MessageBuffer.cs (where packets are dealt with) to kill the player and send out the death reason to all clients } } }
public bool ExtractData(GetDataEventArgs args, MemoryStream data, PvPPlayer attacker, out PlayerHurtArgs arg) { arg = null; int targetId = data.ReadByte(); var playerHitReason = PlayerDeathReason.FromReader(new BinaryReader(data)); PvPPlayer target; if (targetId > -1) { target = PvPModifier.PvPers[targetId]; if (target == null || !target.ConnectionAlive || !target.Active) { return(false); } if (attacker == target) { return(false); } } else { return(false); } var projectile = playerHitReason._sourceProjectileIndex == -1 ? null : attacker.ProjTracker.Projectiles[(int)playerHitReason.SourceProjectileType]; var weapon = projectile?.ItemOriginated ?? attacker.HeldItem; target.LastHitBy = attacker; target.LastHitWeapon = Weapon; target.LastHitProjectile = Projectile; arg = new PlayerHurtArgs { Args = args, Attacker = attacker, Target = target, Projectile = projectile, PlayerHitReason = playerHitReason, Weapon = weapon, InflictedDamage = data.ReadInt16(), DamageReceived = target.DamageReceived(InflictedDamage), HitDirection = data.ReadByte() - 1, Flag = data.ReadByte() }; return(true); }
private void GetData(GetDataEventArgs args) { if (args.MsgID == PacketTypes.PlayerHurtV2) { //Collects all necessary data to alter pvp //The person who would be sending data is the attacking player var attackingplayer = TShock.Players[args.Msg.whoAmI]; var data = new MemoryStream(args.Msg.readBuffer, args.Index, args.Length); var damagedplayer = TShock.Players[data.ReadByte()]; PlayerDeathReason playerHitReason = PlayerDeathReason.FromReader(new BinaryReader(data)); if (attackingplayer == null || !attackingplayer.ConnectionAlive || !attackingplayer.Active) { return; } if (damagedplayer == null || !damagedplayer.ConnectionAlive || !damagedplayer.Active) { return; } if (!attackingplayer.TPlayer.hostile || !damagedplayer.TPlayer.hostile) { return; } if (playerHitReason.SourcePlayerIndex == -1) { return; } int damage = data.ReadInt16(); int knockback = data.ReadByte() - 1; //Cancels client damage handling and makes it so the server does all the damage handling args.Handled = true; //Send the damage packet as long as they're not immune themselves if (!attackingplayer.TPlayer.immune) { if (Math.Abs(iframeTime[damagedplayer.Index] - DateTime.Now.ToFileTimeUtc()) >= config.iframeTime) { NetMessage.SendPlayerHurt(damagedplayer.Index, playerHitReason, damage, knockback, false, true, 5); iframeTime[damagedplayer.Index] = DateTime.Now.ToFileTimeUtc(); } } } }
private void NetHooks_GetData(GetDataEventArgs args) { if (args.MsgID == PacketTypes.PlayerDeathV2) { args.Msg.reader.BaseStream.Position = args.Index; var playerId = args.Msg.whoAmI; var tPlayer = TShock.Players[playerId]; var p = Main.player[playerId]; var deathReason = ""; using (var reader = new BinaryReader(new MemoryStream(args.Msg.readBuffer, args.Index, args.Length))) { reader.ReadByte(); var reason = PlayerDeathReason.FromReader(reader); deathReason = Convert.ToString(reason.GetDeathText(p.name)); if (!TShock.ServerSideCharacterConfig.Enabled) { return; } InventoryDrop(Main.player[playerId], Main.player[playerId].inventory, 0, InventoryDDR, InventoryDR); ArmDrop(Main.player[playerId], Main.player[playerId].armor, 59, ArmDDR, ArmDR); MiscItemDrop(Main.player[playerId], Main.player[playerId].miscEquips, 89, MEDDR, MEDR); } } if (args.MsgID == PacketTypes.PlayerUpdate) { var playerId = args.Msg.whoAmI; var tPlayer = TShock.Players[playerId]; var p = Main.player[playerId]; if (!TShock.ServerSideCharacterConfig.Enabled || tPlayer.User == null) { return; } else { var ppos = DB.GetPos(tPlayer.User.ID); if (ppos.indatabase) { if (tPlayer.Teleport(ppos.x, ppos.y)) { DB.UpdateStatus(false, tPlayer.User.ID); } } } } }
public PlayerHurtArgs(GetDataEventArgs args, MemoryStream data, PvPPlayer attacker) { Args = args; var target = PvPController.PvPers[data.ReadByte()]; var playerHitReason = PlayerDeathReason.FromReader(new BinaryReader(data)); if (target == null || !target.ConnectionAlive || !target.Active) { IsPvPDamage = false; return; } if (playerHitReason.SourcePlayerIndex == -1) { IsPvPDamage = false; target.LastHitBy = null; return; } Projectile = playerHitReason.SourceProjectileIndex == -1 ? null : attacker.ProjTracker.Projectiles[playerHitReason.SourceProjectileType]; int int1 = data.ReadInt16(); //damage int int2 = data.ReadByte(); //knockback target.LastHitBy = attacker; target.LastHitWeapon = Weapon; target.LastHitProjectile = Projectile; Attacker = attacker; Target = target; Weapon = Projectile == null ? attacker.GetPlayerItem : Projectile.ItemOriginated; InflictedDamage = PvPController.Config.EnableDamageChanges ? target.GetDamageDealt(attacker, Weapon, Projectile) : int1; DamageReceived = target.GetDamageReceived(InflictedDamage); HitDirection = int2 - 1; Crit = attacker.GetCrit(Weapon); PlayerHitReason = playerHitReason; IsPvPDamage = true; }
private bool RecordPlayerDeath(Player player, MemoryStream data) { // Unused initial ID, read byte so FromReader is properly aligned in stream. data.ReadByte(); PlayerDeathReason playerDeathReason = PlayerDeathReason.FromReader(new BinaryReader(data)); // Record failure in current death repository. string killerName = GetNameOfKiller(player, playerDeathReason); int totalDeathCount = deathRecords.RecordDeath(player.name, killerName); // Log objects for reference. string deathText = playerDeathReason.GetDeathText(player.name).ToString(); logWriter.ServerWriteLine(JsonConvert.SerializeObject(playerDeathReason), TraceLevel.Info); logWriter.ServerWriteLine(string.Format("{0} {1}->{2} ({3})", player.name, deathText, killerName, totalDeathCount), TraceLevel.Info); // Broadcast message to server. string serverMessage = GetServerMessage(player, killerName, totalDeathCount); TShockAPI.Utils.Instance.Broadcast(serverMessage, 255, 0, 0); return(true); }
void OnGetData(GetDataEventArgs e) { if (!e.Handled && TShock.Players[e.Msg.whoAmI].GetData <bool>("buildmode")) { Player plr = Main.player[e.Msg.whoAmI]; TSPlayer tsplr = TShock.Players[e.Msg.whoAmI]; switch (e.MsgID) { case PacketTypes.PlayerHurtV2: using (MemoryStream data = new MemoryStream(e.Msg.readBuffer, e.Index, e.Length)) { data.ReadByte(); PlayerDeathReason.FromReader(new BinaryReader(data)); int damage = data.ReadInt16(); tsplr.Heal((int)Terraria.Main.CalculateDamagePlayersTake(damage, plr.statDefense) + 2); } break; case PacketTypes.Teleport: if ((e.Msg.readBuffer[3] == 0)) { List <int> buffs = new List <int>(plr.buffType); if (buffs.Contains(Terraria.ID.BuffID.ChaosState) && plr.inventory[plr.selectedItem].netID == Terraria.ID.ItemID.RodofDiscord) //rod 1326 { tsplr.Heal(plr.statLifeMax2 / 7); } } break; case PacketTypes.PaintTile: case PacketTypes.PaintWall: //0% { int count = 0; int type = e.Msg.readBuffer[7]; Terraria.Item lastItem = null; foreach (Item i in plr.inventory) { if (i.paint == type) { lastItem = i; count += i.stack; } } if (count <= 10 && lastItem != null) { tsplr.GiveItem(lastItem.type, lastItem.maxStack + 1 - count); } } break; case PacketTypes.Tile: //1% { int count = 0; int type = e.Msg.readBuffer[e.Index]; switch (type) { case 1: //PlaceTile case 3: //PlaceWall case 21: //ReplaceTile case 22: //ReplaceWall if (plr.inventory[plr.selectedItem].type != Terraria.ID.ItemID.StaffofRegrowth) //230 { int tile = e.Msg.readBuffer[e.Index + 5]; if (tsplr.SelectedItem.tileWand > 0) { tile = tsplr.SelectedItem.tileWand; } Item lastItem = null; foreach (Item i in plr.inventory) { if (i.createTile == tile || i.createWall == tile) { lastItem = i; count += i.stack; } } if (count <= 10 && lastItem != null) { tsplr.GiveItem(lastItem.type, lastItem.maxStack + 1 - count); } } break; // Placing wires case 5: //Red case 10: //Blue case 12: //Green case 16: //Yellow foreach (Item i in plr.inventory) { if (i.type == Terraria.ID.ItemID.Wire) //530 { count += i.stack; } } if (count <= 10) { tsplr.GiveItem(Terraria.ID.ItemID.Wire, 1000 - count); } break; case 8: //Place Actuator foreach (Item i in plr.inventory) { if (i.type == Terraria.ID.ItemID.Actuator) //849 { count += i.stack; } } if (count <= 10) { tsplr.GiveItem(Terraria.ID.ItemID.Actuator, 1000 - count); } break; } } break; } } }
private void OnNetGetData(GetDataEventArgs args) { if (args.Handled) { return; } // if (args.MsgID == PacketTypes.NpcItemStrike || args.MsgID == PacketTypes.NpcStrike) // { // var player = TShock.Players[args.Msg.whoAmI]; // using (var reader = new BinaryReader(new MemoryStream(args.Msg.readBuffer, args.Index, args.Length))) // { // var npcIndex = reader.ReadInt16(); // void DoStrike(double damage, bool isCritical) // { // if (damage < 1.0) // { // return; // } // var npc = Main.npc[npcIndex]; // var defense = npc.defense; // defense -= npc.ichor ? 20 : 0; // defense -= npc.betsysCurse ? 40 : 0; // defense = Math.Max(0, defense); // damage = Main.CalculateDamage((int)damage, defense); // damage *= isCritical ? 2.0 : 1.0; // damage *= Math.Max(1.0, npc.takenDamageMultiplier); // var damages = _npcDamages.GetOrCreateValue(npc); // damages[player] = damages.Get(player) + (int)damage; ////Debug.Print($"Leveling - DoStrike! Damage: {damage}, Critical: {isCritical}"); //if (npc.life <= damage) // { // KillNpc(npc); // } // } // if (args.MsgID == PacketTypes.NpcItemStrike) // { // DoStrike(player.SelectedItem.damage, false); // } // else // { // var damage = reader.ReadInt16(); // reader.ReadSingle(); // reader.ReadByte(); // var isCritical = reader.ReadByte() == 1; // DoStrike(damage, isCritical); // } // } // } //else if (args.MsgID == PacketTypes.PlayerDeathV2) if (args.MsgID == PacketTypes.PlayerDeathV2) { var player = TShock.Players[args.Msg.whoAmI]; var session = GetOrCreateSession(player); using (var reader = new BinaryReader(new MemoryStream(args.Msg.readBuffer, args.Index, args.Length))) { reader.ReadByte(); var deathReason = PlayerDeathReason.FromReader(reader); reader.ReadInt16(); reader.ReadByte(); var wasPvP = ((BitsByte)reader.ReadByte())[0]; if (wasPvP) { var otherPlayer = deathReason.SourcePlayerIndex >= 0 ? TShock.Players[deathReason.SourcePlayerIndex] : null; if (otherPlayer == player) { return; } var expLoss = (long)Math.Round(Math.Max( Config.Instance.DeathPenaltyPvPMultiplier * session.Exp, Config.Instance.DeathPenaltyMinimum)); session.GiveExp(-expLoss); session.AddExpToReport(-expLoss); if (otherPlayer != null) { var otherSession = GetOrCreateSession(otherPlayer); otherSession.GiveExp(expLoss); otherSession.AddExpToReport(expLoss); } } else { var expLoss = (long)Math.Round(Math.Max( Config.Instance.DeathPenaltyMultiplier * (session.Class.DeathPenaltyMultiplierOverride ?? 1.0) * session.Exp, Config.Instance.DeathPenaltyMinimum)); session.GiveExp(-expLoss); session.AddExpToReport(-expLoss); } } } }
private void GetData(GetDataEventArgs args) { MemoryStream data = new MemoryStream(args.Msg.readBuffer, args.Index, args.Length); PvPPlayer attacker = pvpers[args.Msg.whoAmI]; if (attacker == null || !attacker.TPlayer.active || !attacker.ConnectionAlive) { return; } if (!attacker.TPlayer.hostile) { return; } switch (args.MsgID) { case PacketTypes.PlayerHurtV2: PvPPlayer target = pvpers[data.ReadByte()]; PlayerDeathReason playerHitReason = PlayerDeathReason.FromReader(new BinaryReader(data)); if (target == null || !target.ConnectionAlive || !target.Active) { return; } if (playerHitReason.SourcePlayerIndex == -1) { target.lastHitBy = null; return; } PvPProjectile projectile = playerHitReason.SourceProjectileIndex == -1 ? null : projectiles[playerHitReason.SourceProjectileIndex]; PvPItem weapon = projectile == null?attacker.GetPlayerItem() : projectile.itemOriginated; int inflictedDamage = PvPController.config.enableDamageChanges ? target.GetDamageDealt(attacker, weapon, projectile) : data.ReadByte(); int damageReceived = target.GetDamageReceived(inflictedDamage); data.ReadByte(); data.ReadByte(); int knockback = data.ReadByte() - 1; target.lastHitBy = attacker; target.lastHitWeapon = weapon; target.lastHitProjectile = projectile; DataHandler.OnPlayerHurtted(args, attacker, target, weapon, projectile, playerHitReason, inflictedDamage, damageReceived, knockback); break; case PacketTypes.TogglePvp: DataHandler.OnPvPToggled(attacker); break; case PacketTypes.PlayerSlot: data.ReadByte(); int slot = data.ReadByte(); DataHandler.OnPlayerSlotUpdated(attacker, slot); break; case PacketTypes.PlayerDeathV2: DataHandler.OnPlayerDead(attacker); break; case PacketTypes.ProjectileDestroy: DataHandler.OnProjectileDestroyed(data); break; case PacketTypes.PlayerUpdate: DataHandler.OnPlayerUpdated(data, attacker); break; } }
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)) { 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, 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, objectStyle )); } if (!e.Handled) { e.Handled = this.OnObjectPlacement( new ObjectPlacementEventArgs(player, new DPoint(x, y), 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 || type == 4) // Chest placement / Dresser Placement / Chest2 placement { e.Handled = this.OnChestPlace(new ChestPlaceEventArgs(player, new DPoint(x, y), type, style)); } else // Chest or Dresser or Chest2 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); int itemPrefix = e.Msg.readBuffer[e.Index + 5]; int 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: { 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); int itemPrefix = e.Msg.readBuffer[e.Index + 20]; bool noDelay = (e.Msg.readBuffer[e.Index + 21] != 0); int 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: { 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); int itemPrefix = e.Msg.readBuffer[e.Index + 4]; int 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)25: { 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.PlayerDeathV2: { if (this.PlayerDeath == null) { break; } using (BinaryReader reader = new BinaryReader(new MemoryStream(e.Msg.readBuffer, e.Index, e.Length, false))) { int playerIndex = reader.ReadByte(); var deathReason = PlayerDeathReason.FromReader(reader); int damage = reader.ReadInt16(); int direction = reader.ReadByte() - 1; bool pvp = reader.ReadByte() != 0; e.Handled = this.OnPlayerDeath(new PlayerDeathEventArgs(player, deathReason, direction, damage, pvp)); } 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; } case PacketTypes.NpcStrike: { if (this.NpcTookDamage == null) { break; } int npcIndex = BitConverter.ToInt16(e.Msg.readBuffer, e.Index); int damage = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 2); float knockback = BitConverter.ToSingle(e.Msg.readBuffer, e.Index + 4); int hitDirection = e.Msg.readBuffer[e.Index + 8] - 1; // 1 left, -1 right bool isCritical = (e.Msg.readBuffer[e.Index + 9] == 1); e.Handled = this.OnNpcTookDamage(new NpcTookDamageEventArgs(player, npcIndex, damage, knockback, hitDirection, isCritical)); break; } case PacketTypes.MassWireOperation: { if (this.MassWireOperation == null && this.TileEdit == null) { break; } int x1 = BitConverter.ToInt16(e.Msg.readBuffer, e.Index); int y1 = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 2); int x2 = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 4); int y2 = BitConverter.ToInt16(e.Msg.readBuffer, e.Index + 6); WiresUI.Settings.MultiToolMode toolMode = (WiresUI.Settings.MultiToolMode)e.Msg.readBuffer[e.Index + 7]; DPoint startLocation = new DPoint(x1, y1); DPoint endLocation = new DPoint(x2, y2); e.Handled = this.OnMassWireOperation(new MassWireOperationEventArgs(player, startLocation, endLocation, toolMode)); if (!e.Handled && this.InvokeTileEditOnMasswireOperation != MassWireOpTileEditInvokeType.DontInvoke) { e.Handled = this.RaiseTileEditDependingOnToolMode(player, startLocation, toolMode); if (startLocation != endLocation) { e.Handled = this.RaiseTileEditDependingOnToolMode(player, endLocation, toolMode) || e.Handled; } } break; } } } catch (Exception ex) { ServerApi.LogWriter.PluginWriteLine( this.Plugin, $"Internal error on handling data packet {e.MsgID}. Exception details: \n{ex}", TraceLevel.Error ); } }
private void OnGetData(GetDataEventArgs args) { var player = TShock.Players[args.Msg.whoAmI]; if (args.Handled || player == null || !player.ContainsData("buildmode") || !player.GetData <bool>("buildmode")) { return; } switch (args.MsgID) { case PacketTypes.Teleport: if (player.TPlayer.FindBuffIndex(88) > -1) { player.Heal(100); } break; case PacketTypes.PaintTile: case PacketTypes.PaintWall: int count = 0; int type = args.Msg.readBuffer[args.Index + 4]; Item lastItem = null; foreach (Item i in player.TPlayer.inventory) { if (i.paint == type) { lastItem = i; count += i.stack; } } if (count <= 5 && lastItem != null) { player.GiveItem(lastItem.type, lastItem.stack); } break; case PacketTypes.Tile: count = 0; type = args.Msg.readBuffer[args.Index]; if ((type == 1 || type == 3 || type == 21 || type == 22) && player.TPlayer.inventory[player.TPlayer.selectedItem].type != 213) // Tile or Wall or ReplaceTile or ReplaceWall { short tile = args.Msg.readBuffer[args.Index + 5]; if (player.SelectedItem.tileWand > 0) { tile = (short)player.SelectedItem.tileWand; } lastItem = null; foreach (Item i in player.TPlayer.inventory) { if (((type == 1 || type == 21) && i.createTile == tile) || ((type == 3 || type == 22) && i.createWall == tile)) { lastItem = i; count += i.stack; } } if (count <= 5 && lastItem != null) { player.GiveItem(lastItem.type, lastItem.maxStack - count); } } else if (type == 5 || type == 10 || type == 12 || type == 16) // Wire, Wire2, Wire3, Wire4 { foreach (Item i in player.TPlayer.inventory) { if (i.type == 530) { count += i.stack; } } if (count <= 5) { player.GiveItem(530, 1000 - count); } } else if (type == 8) // Actuator { foreach (Item i in player.TPlayer.inventory) { if (i.type == 849) { count += i.stack; } } if (count <= 5) { player.GiveItem(849, 1000 - count); } } break; case PacketTypes.PlayerHurtV2: using (var reader = new BinaryReader(new MemoryStream(args.Msg.readBuffer, args.Index, args.Length))) { reader.ReadByte(); PlayerDeathReason.FromReader(reader); short damage = reader.ReadInt16(); player.Heal(damage); player.TPlayer.statLife = player.TPlayer.statLifeMax2; } break; } }
private void OnNetGetData(GetDataEventArgs args) { if (args.Handled) { return; } switch (args.MsgID) { case PacketTypes.Tile: using (var reader = new BinaryReader(new MemoryStream(args.Msg.readBuffer, args.Index, args.Length))) { var action = reader.ReadByte(); if (action >= 0 && action <= 3) //0 kill, 1 place tile, 2 kill, 3 place wall { var tileX = reader.ReadInt16(); var tileY = reader.ReadInt16(); var var1 = reader.ReadInt16(); //kill tile status var var2 = reader.ReadInt16(); //place tile //Debug.Print($"action: {action}"); //Debug.Print($"tileX: {tileX}"); //Debug.Print($"tileY: {tileY}"); //Debug.Print($"var1: {var1}"); //Debug.Print($"var2: {var2}"); var player = TShock.Players[args.Msg.whoAmI]; TileSubTarget tileSubTarget; if (action < 2) { tileSubTarget = TileSubTarget.Tile; } else { tileSubTarget = TileSubTarget.Wall; } if ((action == 0 || action == 2) && var1 == 0) { var tile = Main.tile[tileX, tileY]; //kill tile if (action == 2 || tile.collisionType > 0) //ignore grass { OnTileKilled(new TileChangedEventArgs(player, tileX, tileY, tile.type, tile.wall, tileSubTarget)); return; } } else if (action == 1 || action == 3) // && var1 > 0) { //var1 should hold the type of the tile or wall we placed. //place tile OnTilePlaced(new TileChangedEventArgs(player, tileX, tileY, (ushort)var1, (byte)var1, tileSubTarget)); return; } } } break; case PacketTypes.PlayerDeathV2: //based off of MarioE's original code from the Leveling plugin... using (var reader = new BinaryReader(new MemoryStream(args.Msg.readBuffer, args.Index, args.Length))) { var player = TShock.Players[args.Msg.whoAmI]; reader.ReadByte(); var deathReason = PlayerDeathReason.FromReader(reader); reader.ReadInt16(); reader.ReadByte(); var wasPvP = ((BitsByte)reader.ReadByte())[0]; if (wasPvP) { var otherPlayer = deathReason.SourcePlayerIndex >= 0 ? TShock.Players[deathReason.SourcePlayerIndex] : null; if (otherPlayer == player) { return; } if (otherPlayer != null) { var reward = new DeathReward(player.Name, RewardReason.DeathPvP, otherPlayer.Name); RewardDistributor.EnqueueReward(reward); } else { var reward = new DeathReward(player.Name, RewardReason.DeathPvP, ""); RewardDistributor.EnqueueReward(reward); } } else { var reward = new DeathReward(player.Name, RewardReason.Death, ""); RewardDistributor.EnqueueReward(reward); } } break; case PacketTypes.ProjectileNew: //Debug.Print("ProjectileNew!"); using (var reader = new BinaryReader(new MemoryStream(args.Msg.readBuffer, args.Index, args.Length))) { var projectileId = reader.ReadInt16(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadInt16(); var playerId = reader.ReadByte(); var type = reader.ReadInt16(); //var aiFlags = reader.ReadByte(); //var ai0 = reader.ReadSingle(); //var ai1 = reader.ReadSingle(); //var projUUID = reader.ReadSingle(); PlayerFishingTracker.TryBeginFishing(playerId, projectileId, type); } break; case PacketTypes.ProjectileDestroy: //Debug.Print("ProjectileDestroy!"); using (var reader = new BinaryReader(new MemoryStream(args.Msg.readBuffer, args.Index, args.Length))) { var projectileId = reader.ReadInt16(); var ownerId = reader.ReadByte(); PlayerFishingTracker.TryEndFishing(ownerId, projectileId); } break; case PacketTypes.PlayerSlot: //Debug.Print("PlayerSlot!"); using (var reader = new BinaryReader(new MemoryStream(args.Msg.readBuffer, args.Index, args.Length))) { var playerId = reader.ReadByte(); var slotId = reader.ReadByte(); var stack = reader.ReadInt16(); var prefix = reader.ReadByte(); var itemId = reader.ReadInt16(); if (PlayerFishingTracker.IsItemFromFishing(playerId)) //, stack, prefix, itemId)) { var player = TShock.Players[args.Msg.whoAmI]; var reward = new FishingReward(player.Name, stack, prefix, itemId); RewardDistributor.EnqueueReward(reward); } } break; default: break; } }