diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs index 5258e7dd..511c5820 100644 --- a/TShockAPI/Bouncer.cs +++ b/TShockAPI/Bouncer.cs @@ -99,7 +99,7 @@ namespace TShockAPI byte plr = args.PlayerId; BitsByte control = args.Control; BitsByte pulley = args.Pulley; - byte item = args.Item; + byte item = args.SelectedItem ; var pos = args.Position; var vel = args.Velocity; @@ -183,6 +183,7 @@ namespace TShockAPI /// The packet arguments that the event has. internal void OnTileEdit(object sender, GetDataHandlers.TileEditEventArgs args) { + // TODO: Add checks on the new edit actions. ReplaceTile, ReplaceWall, TryKillTile, Acutate, PokeLogicGate, SlopePoundTile EditAction action = args.Action; int tileX = args.X; int tileY = args.Y; @@ -795,6 +796,17 @@ namespace TShockAPI return; } + + if (stabProjectile.ContainsKey(type)) + { + if (stabProjectile[type] == args.Player.TPlayer.HeldItem.type) + { + args.Handled = false; + return; + } + } + + // Main.projHostile contains projectiles that can harm players // without PvP enabled and belong to enemy mobs, so they shouldn't be // possible for players to create. (Source: Ijwu, QuiCM) @@ -1284,7 +1296,7 @@ namespace TShockAPI internal void OnPlayerBuff(object sender, GetDataHandlers.PlayerBuffEventArgs args) { byte id = args.ID; - byte type = args.Type; + int type = args.Type; int time = args.Time; if (TShock.Players[id] == null) @@ -1341,7 +1353,7 @@ namespace TShockAPI internal void OnNPCAddBuff(object sender, GetDataHandlers.NPCAddBuffEventArgs args) { short id = args.ID; - byte type = args.Type; + int type = args.Type; short time = args.Time; if (id >= Main.npc.Length) @@ -1856,7 +1868,7 @@ namespace TShockAPI } - private static Dictionary NPCAddBuffTimeMax = new Dictionary() + private static Dictionary NPCAddBuffTimeMax = new Dictionary() { { BuffID.Poisoned, 3600 }, { BuffID.OnFire, 1200 }, @@ -1921,5 +1933,18 @@ namespace TShockAPI TileID.Campfire }; + private static Dictionary stabProjectile = new Dictionary() + { + { ProjectileID.GladiusStab, ItemID.Gladius }, + { ProjectileID.RulerStab, ItemID.Ruler }, + { ProjectileID.CopperShortswordStab, ItemID.CopperShortsword }, + { ProjectileID.TinShortswordStab, ItemID.TinShortsword }, + { ProjectileID.IronShortswordStab, ItemID.IronShortsword }, + { ProjectileID.LeadShortswordStab, ItemID.LeadShortsword }, + { ProjectileID.SilverShortswordStab, ItemID.SilverShortsword }, + { ProjectileID.TungstenShortswordStab, ItemID.TungstenShortsword }, + { ProjectileID.GoldShortswordStab, ItemID.GoldShortsword }, + { ProjectileID.PlatinumShortswordStab, ItemID.PlatinumShortsword } + }; } } diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 31a316b1..a1fc937d 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -307,25 +307,44 @@ namespace TShockAPI /// public byte Control { get; set; } /// - /// Selected item + /// Pulley update (BitFlags) /// - public byte Item { get; set; } + public byte Pulley { get; set; } /// - /// Position of the player + /// Misc (BitFlags) Check tshock.readme.io + /// + public byte Misc { get; set; } + /// + /// (BitFlags) Wether or not the player is sleeping. + /// + public byte Sleeping { get; set; } + /// + /// The selected item in player's hand. + /// + public byte SelectedItem { get; set; } + /// + /// Position of the player. /// public Vector2 Position { get; set; } /// - /// Velocity of the player + /// Velocity of the player. /// public Vector2 Velocity { get; set; } - /// Pulley update (BitFlags) - public byte Pulley { get; set; } + /// + /// Original poisition of the player when using Potion of Return. + /// + public Vector2? OriginalPos { get; set; } + /// + /// Home Position of the player for Potion of Return. + /// + public Vector2? HomePos { get; set; } + } /// /// PlayerUpdate - When the player sends it's updated information to the server /// public static HandlerList PlayerUpdate = new HandlerList(); - private static bool OnPlayerUpdate(TSPlayer player, MemoryStream data, byte plr, byte control, byte item, Vector2 position, Vector2 velocity, byte pulley) + private static bool OnPlayerUpdate(TSPlayer player, MemoryStream data, byte plr, byte control, byte pulley, byte misc, byte sleeping, byte selectedItem, Vector2 position, Vector2 velocity, Vector2? originalPos, Vector2? homePos) { if (PlayerUpdate == null) return false; @@ -336,10 +355,14 @@ namespace TShockAPI Data = data, PlayerId = plr, Control = control, - Item = item, + Pulley = pulley, + Misc = misc, + Sleeping = sleeping, + SelectedItem = selectedItem, Position = position, Velocity = velocity, - Pulley = pulley + OriginalPos = originalPos, + HomePos = homePos }; PlayerUpdate.Invoke(null, args); return args.Handled; @@ -746,12 +769,21 @@ namespace TShockAPI /// Y location of the player's spawn /// public int SpawnY { get; set; } + /// + /// Value of the timer countdown before the player can respawn alive. + /// If > 0, then player is still dead. + /// + public int RespawnTimer { get; set; } + /// + /// Context of where the player is spawning from. + /// + public PlayerSpawnContext SpawnContext { get; set; } } /// /// PlayerSpawn - When a player spawns /// public static HandlerList PlayerSpawn = new HandlerList(); - private static bool OnPlayerSpawn(TSPlayer player, MemoryStream data, byte pid, int spawnX, int spawnY) + private static bool OnPlayerSpawn(TSPlayer player, MemoryStream data, byte pid, int spawnX, int spawnY, int respawnTimer, PlayerSpawnContext spawnContext) { if (PlayerSpawn == null) return false; @@ -763,6 +795,8 @@ namespace TShockAPI PlayerId = pid, SpawnX = spawnX, SpawnY = spawnY, + RespawnTimer = respawnTimer, + SpawnContext = spawnContext }; PlayerSpawn.Invoke(null, args); return args.Handled; @@ -910,7 +944,7 @@ namespace TShockAPI /// public BitsByte Zone3 { get; set; } /// - /// 0 = Old One's Army + /// 0 = Old One's Army, 1 = Granite, 2 = Marble, 3 = Hive, 4 = Gem Cave, 5 = Lihzhard Temple, 6 = Graveyard /// public BitsByte Zone4 { get; set; } } @@ -1181,7 +1215,7 @@ namespace TShockAPI /// /// Buff Type /// - public byte Type { get; set; } + public int Type { get; set; } /// /// Time the buff lasts /// @@ -1191,7 +1225,7 @@ namespace TShockAPI /// NPCAddBuff - Called when a npc is buffed /// public static HandlerList NPCAddBuff = new HandlerList(); - private static bool OnNPCAddBuff(TSPlayer player, MemoryStream data, short id, byte type, short time) + private static bool OnNPCAddBuff(TSPlayer player, MemoryStream data, short id, int type, short time) { if (NPCAddBuff == null) return false; @@ -1220,7 +1254,7 @@ namespace TShockAPI /// /// Buff Type /// - public byte Type { get; set; } + public int Type { get; set; } /// /// Time the buff lasts /// @@ -1230,7 +1264,7 @@ namespace TShockAPI /// PlayerBuff - Called when a player is buffed /// public static HandlerList PlayerBuff = new HandlerList(); - private static bool OnPlayerBuff(TSPlayer player, MemoryStream data, byte id, byte type, int time) + private static bool OnPlayerBuff(TSPlayer player, MemoryStream data, byte id, int type, int time) { if (PlayerBuff == null) return false; @@ -2006,11 +2040,13 @@ namespace TShockAPI private static bool HandleSpawn(GetDataHandlerArgs args) { - var player = args.Data.ReadInt8(); - var spawnx = args.Data.ReadInt16(); - var spawny = args.Data.ReadInt16(); + byte player = args.Data.ReadInt8(); + short spawnx = args.Data.ReadInt16(); + short spawny = args.Data.ReadInt16(); + int respawnTimer = args.Data.ReadInt32(); + PlayerSpawnContext context = (PlayerSpawnContext)args.Data.ReadByte(); - if (OnPlayerSpawn(args.Player, args.Data, player, spawnx, spawny)) + if (OnPlayerSpawn(args.Player, args.Data, player, spawnx, spawny, respawnTimer, context)) return true; if ((Main.ServerSideCharacter) && (args.Player.sX > 0) && (args.Player.sY > 0) && (args.TPlayer.SpawnX > 0) && ((args.TPlayer.SpawnX != args.Player.sX) && (args.TPlayer.SpawnY != args.Player.sY))) @@ -2029,7 +2065,10 @@ namespace TShockAPI args.Player.Teleport(args.Player.sX * 16, (args.Player.sY * 16) - 48); } - args.Player.Dead = false; + if (respawnTimer > 0) + args.Player.Dead = true; + else + args.Player.Dead = false; return false; } @@ -2040,34 +2079,45 @@ namespace TShockAPI return true; } - byte plr = args.Data.ReadInt8(); - BitsByte control = args.Data.ReadInt8(); - BitsByte pulley = args.Data.ReadInt8(); - byte item = args.Data.ReadInt8(); - var pos = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle()); - var vel = Vector2.Zero; - if (pulley[2]) - vel = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle()); + byte playerID = args.Data.ReadInt8(); + BitsByte control = (BitsByte)args.Data.ReadByte(); + BitsByte pulley = (BitsByte)args.Data.ReadByte(); + BitsByte misc = (BitsByte)args.Data.ReadByte(); + BitsByte sleeping = (BitsByte)args.Data.ReadByte(); + byte selectedItem = args.Data.ReadInt8(); + Vector2 position = args.Data.ReadVector2(); - if (OnPlayerUpdate(args.Player, args.Data, plr, control, item, pos, vel, pulley)) + Vector2 velocity = Vector2.Zero; + if (pulley[2]) // if UpdateVelocity + velocity = args.Data.ReadVector2(); + + Vector2? originalPosition = new Vector2?(); + Vector2? homePosition = Vector2.Zero; + if (misc[6]) // if UsedPotionofReturn + { + originalPosition = new Vector2?(args.Data.ReadVector2()); + homePosition = new Vector2?(args.Data.ReadVector2()); + } + + if (OnPlayerUpdate(args.Player, args.Data, playerID, control, pulley, misc, sleeping, selectedItem, position, velocity, originalPosition, homePosition)) return true; if (control[5]) { // Reimplementation of normal Terraria stuff? - if (args.TPlayer.inventory[item].Name == "Mana Crystal" && args.Player.TPlayer.statManaMax <= 180) + if (args.TPlayer.inventory[selectedItem].Name == "Mana Crystal" && args.Player.TPlayer.statManaMax <= 180) { args.Player.TPlayer.statMana += 20; args.Player.TPlayer.statManaMax += 20; args.Player.PlayerData.maxMana += 20; } - else if (args.TPlayer.inventory[item].Name == "Life Crystal" && args.Player.TPlayer.statLifeMax <= 380) + else if (args.TPlayer.inventory[selectedItem].Name == "Life Crystal" && args.Player.TPlayer.statLifeMax <= 380) { args.TPlayer.statLife += 20; args.TPlayer.statLifeMax += 20; args.Player.PlayerData.maxHealth += 20; } - else if (args.TPlayer.inventory[item].Name == "Life Fruit" && args.Player.TPlayer.statLifeMax >= 400 && args.Player.TPlayer.statLifeMax <= 495) + else if (args.TPlayer.inventory[selectedItem].Name == "Life Fruit" && args.Player.TPlayer.statLifeMax >= 400 && args.Player.TPlayer.statLifeMax <= 495) { args.TPlayer.statLife += 5; args.TPlayer.statLifeMax += 5; @@ -2076,11 +2126,11 @@ namespace TShockAPI } // Where we rebuild sync data for Terraria? - args.TPlayer.selectedItem = item; - args.TPlayer.position = pos; + args.TPlayer.selectedItem = selectedItem; + args.TPlayer.position = position; args.TPlayer.oldVelocity = args.TPlayer.velocity; - args.TPlayer.velocity = vel; - args.TPlayer.fallStart = (int)(pos.Y / 16f); + args.TPlayer.velocity = velocity; + args.TPlayer.fallStart = (int)(position.Y / 16f); args.TPlayer.controlUp = false; args.TPlayer.controlDown = false; args.TPlayer.controlLeft = false; @@ -2199,17 +2249,17 @@ namespace TShockAPI private static bool HandleTile(GetDataHandlerArgs args) { EditAction action = (EditAction)args.Data.ReadInt8(); - var tileX = args.Data.ReadInt16(); - var tileY = args.Data.ReadInt16(); - var editData = args.Data.ReadInt16(); + short tileX = args.Data.ReadInt16(); + short tileY = args.Data.ReadInt16(); + short editData = args.Data.ReadInt16(); EditType type = (action == EditAction.KillTile || action == EditAction.KillWall || - action == EditAction.KillTileNoItem) + action == EditAction.KillTileNoItem || action == EditAction.TryKillTile) ? EditType.Fail - : (action == EditAction.PlaceTile || action == EditAction.PlaceWall) + : (action == EditAction.PlaceTile || action == EditAction.PlaceWall || action == EditAction.ReplaceTile || action == EditAction.ReplaceWall) ? EditType.Type : EditType.Slope; - var style = args.Data.ReadInt8(); + byte style = args.Data.ReadInt8(); if (OnTileEdit(args.Player, args.Data, tileX, tileY, action, type, editData, style)) return true; @@ -2296,23 +2346,21 @@ namespace TShockAPI private static bool HandleProjectileNew(GetDataHandlerArgs args) { short ident = args.Data.ReadInt16(); - var pos = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle()); - var vel = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle()); - float knockback = args.Data.ReadSingle(); - short dmg = args.Data.ReadInt16(); + Vector2 pos = args.Data.ReadVector2(); + Vector2 vel = args.Data.ReadVector2(); byte owner = args.Data.ReadInt8(); short type = args.Data.ReadInt16(); - BitsByte bits = args.Data.ReadInt8(); - //owner = (byte)args.Player.Index; + BitsByte bits = (BitsByte)args.Data.ReadByte(); float[] ai = new float[Projectile.maxAI]; + for (int i = 0; i < Projectile.maxAI; ++i) + ai[i] = !bits[i] ? 0.0f : args.Data.ReadSingle(); + short dmg = bits[4] ? args.Data.ReadInt16() : (short)0; + float knockback = bits[5] ? args.Data.ReadSingle() : 0.0f; + short origDmg = bits[6] ? args.Data.ReadInt16() : (short)0; + short projUUID = bits[7] ? args.Data.ReadInt16() : (short)-1; + if (projUUID >= 1000) + projUUID = -1; - for (int i = 0; i < Projectile.maxAI; i++) - { - if (bits[i]) - ai[i] = args.Data.ReadSingle(); - else - ai[i] = 0f; - } var index = TShock.Utils.SearchProjectile(ident, owner); @@ -2666,7 +2714,7 @@ namespace TShockAPI for (int i = 0; i < Terraria.Player.maxBuffs; i++) { - var buff = args.Data.ReadInt8(); + var buff = args.Data.ReadUInt16(); if (buff == 10 && TShock.Config.DisableInvisPvP && args.TPlayer.hostile) buff = 0; @@ -2717,7 +2765,7 @@ namespace TShockAPI private static bool HandleNPCAddBuff(GetDataHandlerArgs args) { var id = args.Data.ReadInt16(); - var type = args.Data.ReadInt8(); + var type = args.Data.ReadUInt16(); var time = args.Data.ReadInt16(); if (OnNPCAddBuff(args.Player, args.Data, id, type, time)) @@ -2729,7 +2777,7 @@ namespace TShockAPI private static bool HandlePlayerAddBuff(GetDataHandlerArgs args) { var id = args.Data.ReadInt8(); - var type = args.Data.ReadInt8(); + var type = args.Data.ReadUInt16(); var time = args.Data.ReadInt32(); if (OnPlayerBuff(args.Player, args.Data, id, type, time)) @@ -3358,7 +3406,13 @@ namespace TShockAPI SlopeTile, FrameTrack, PlaceWire4, - KillWire4 + KillWire4, + PokeLogicGate, + Acutate, + TryKillTile, + ReplaceTile, + ReplaceWall, + SlopePoundTile } public enum EditType { @@ -3366,7 +3420,6 @@ namespace TShockAPI Type, Slope, } - /// /// The maximum place styles for each tile. /// diff --git a/TShockAPI/ItemBans.cs b/TShockAPI/ItemBans.cs index a85f462c..0ebd7ee6 100644 --- a/TShockAPI/ItemBans.cs +++ b/TShockAPI/ItemBans.cs @@ -156,9 +156,9 @@ namespace TShockAPI DisableFlags disableFlags = TShock.Config.DisableSecondUpdateLogs ? DisableFlags.WriteToConsole : DisableFlags.WriteToLogAndConsole; bool useItem = ((BitsByte) args.Control)[5]; TSPlayer player = args.Player; - string itemName = player.TPlayer.inventory[args.Item].Name; + string itemName = player.TPlayer.inventory[args.SelectedItem].Name; - if (DataModel.ItemIsBanned(EnglishLanguage.GetItemNameById(player.TPlayer.inventory[args.Item].netID), args.Player)) + if (DataModel.ItemIsBanned(EnglishLanguage.GetItemNameById(player.TPlayer.inventory[args.SelectedItem].netID), args.Player)) { player.TPlayer.controlUseItem = false; player.Disable($"holding banned item: {itemName}", disableFlags); diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 5829f877..9a772227 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -360,6 +360,8 @@ namespace TShockAPI Item[] piggy = TPlayer.bank.item; Item[] safe = TPlayer.bank2.item; Item[] forge = TPlayer.bank3.item; + Item[] voidVault = TPlayer.bank4.item; + Item trash = TPlayer.trashItem; for (int i = 0; i < NetItem.MaxInventory; i++) { @@ -507,7 +509,7 @@ namespace TShockAPI } else if (i < NetItem.TrashIndex.Item2) { - // 179-219 + // 178-179 Item item = new Item(); if (trash != null && trash.netID != 0) { @@ -525,9 +527,9 @@ namespace TShockAPI } } } - else + else if (i < NetItem.ForgeIndex.Item2) { - // 220 + // 179-220 var index = i - NetItem.ForgeIndex.Item1; Item item = new Item(); if (forge[index] != null && forge[index].netID != 0) @@ -545,8 +547,29 @@ namespace TShockAPI } } } - } + else if (i < NetItem.VoidIndex.Item2) + { + // 220-260 + var index = i - NetItem.VoidIndex.Item1; + Item item = new Item(); + if (voidVault[index] != null && voidVault[index].netID != 0) + { + item.netDefaults(voidVault[index].netID); + item.Prefix(voidVault[index].prefix); + item.AffixName(); + + if (voidVault[index].stack > item.maxStack || voidVault[index].stack < 0) + { + check = true; + if (shouldWarnPlayer) + { + SendErrorMessage("Stack cheat detected. Remove Void Vault item {0} ({1}) and then rejoin.", item.Name, voidVault[index].stack); + } + } + } + } + } return check;