diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index 5c5d86495..38f338adc 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -24,7 +24,6 @@ You should have received a copy of the GNU General Public License using System.Linq; using System.Text; using System.Threading; -using TShockAPI.PluginUpdater; using Terraria; using TShockAPI.DB; @@ -186,7 +185,9 @@ public static void InitCommands() add(Permissions.causeevents, Star, "star"); add(Permissions.causeevents, Fullmoon, "fullmoon"); add(Permissions.causeevents, Bloodmoon, "bloodmoon"); + add(Permissions.causeevents, Eclipse, "eclipse"); add(Permissions.causeevents, Invade, "invade"); + add(Permissions.causeevents, Rain, "rain"); add(Permissions.spawnboss, Eater, "eater"); add(Permissions.spawnboss, Eye, "eye"); add(Permissions.spawnboss, King, "king"); @@ -483,7 +484,7 @@ private static void AttemptLogin(CommandArgs args) if (TShock.RememberedPos.GetLeavePos(args.Player.Name, args.Player.IP) != Vector2.Zero) { Vector2 pos = TShock.RememberedPos.GetLeavePos(args.Player.Name, args.Player.IP); - args.Player.Teleport((int)pos.X, (int)pos.Y + 3); + args.Player.Teleport((int)pos.X*16, (int)pos.Y *16 + 48); } args.Player.LoginHarassed = false; @@ -1259,7 +1260,6 @@ private static void UpdatePlugins(CommandArgs args) { args.Player.SendInfoMessage("Starting plugin update process:"); args.Player.SendInfoMessage("This may take a while, do not turn off the server!"); - new PluginUpdaterThread(args.Player); } private static void ManageRest(CommandArgs args) @@ -1354,6 +1354,12 @@ private static void Bloodmoon(CommandArgs args) TShock.Utils.Broadcast(string.Format("{0} turned on the blood moon.", args.Player.Name), Color.Green); } + private static void Eclipse(CommandArgs args) + { + TSPlayer.Server.SetEclipse(true); + TShock.Utils.Broadcast(string.Format("{0} has forced an Eclipse!", args.Player.Name), Color.Green); + } + private static void Invade(CommandArgs args) { if (Main.invasionSize <= 0) @@ -1635,7 +1641,7 @@ private static void Home(CommandArgs args) private static void Spawn(CommandArgs args) { - if (args.Player.Teleport(Main.spawnTileX, Main.spawnTileY)) + if (args.Player.Teleport(Main.spawnTileX*16, Main.spawnTileY*16)) args.Player.SendSuccessMessage("Teleported to the map's spawnpoint."); } @@ -1643,33 +1649,53 @@ private static void TP(CommandArgs args) { if (args.Parameters.Count < 1) { - args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /tp "); + args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /tp "); + args.Player.SendErrorMessage(" /tp "); return; } - string plStr = String.Join(" ", args.Parameters); - var players = TShock.Utils.FindPlayer(plStr); - if (players.Count == 0) - args.Player.SendErrorMessage("Invalid player!"); - else if (players.Count > 1) - TShock.Utils.SendMultipleMatchError(args.Player, players.Select(p => p.Name)); - else if (!players[0].TPAllow && !args.Player.Group.HasPermission(Permissions.tpall)) + if(args.Parameters.Count == 2) { - var plr = players[0]; - args.Player.SendErrorMessage(plr.Name + " has prevented users from teleporting to them."); - plr.SendInfoMessage(args.Player.Name + " attempted to teleport to you."); + float x, y; + if (float.TryParse(args.Parameters[0], out x) && float.TryParse(args.Parameters[1], out y)) + { + args.Player.Teleport(x, y); + args.Player.SendSuccessMessage("Teleported!"); + } } else { - var plr = players[0]; - if (args.Player.Teleport(plr.TileX, plr.TileY + 3)) + string plStr = String.Join(" ", args.Parameters); + var players = TShock.Utils.FindPlayer(plStr); + if (players.Count == 0) + { + args.Player.SendErrorMessage("Invalid user name."); + args.Player.SendErrorMessage("Proper syntax: /tp "); + args.Player.SendErrorMessage(" /tp "); + } + + else if (players.Count > 1) + TShock.Utils.SendMultipleMatchError(args.Player, players.Select(p => p.Name)); + else if (!players[0].TPAllow && !args.Player.Group.HasPermission(Permissions.tpall)) { - args.Player.SendSuccessMessage(string.Format("Teleported to {0}.", plr.Name)); - if (!args.Player.Group.HasPermission(Permissions.tphide)) - plr.SendInfoMessage(args.Player.Name + " teleported to you."); + var plr = players[0]; + args.Player.SendErrorMessage(plr.Name + " has prevented users from teleporting to them."); + plr.SendInfoMessage(args.Player.Name + " attempted to teleport to you."); + } + else + { + var plr = players[0]; + if (args.Player.Teleport(plr.TileX * 16, plr.TileY * 16 + 48)) + { + args.Player.SendSuccessMessage(string.Format("Teleported to {0}.", plr.Name)); + if (!args.Player.Group.HasPermission(Permissions.tphide)) + plr.SendInfoMessage(args.Player.Name + " teleported to you."); + } } } - } + + + } private static void TPHere(CommandArgs args) { @@ -1688,7 +1714,7 @@ private static void TPHere(CommandArgs args) { if (Main.player[i].active && (Main.player[i] != args.TPlayer)) { - if (TShock.Players[i].Teleport(args.Player.TileX, args.Player.TileY + 3)) + if (TShock.Players[i].Teleport(args.Player.TileX*16, args.Player.TileY*16 + 48)) TShock.Players[i].SendSuccessMessage(string.Format("You were teleported to {0}.", args.Player.Name) + "."); } } @@ -1707,7 +1733,7 @@ private static void TPHere(CommandArgs args) else { var plr = players[0]; - if (plr.Teleport(args.Player.TileX, args.Player.TileY + 3)) + if (plr.Teleport(args.Player.TileX*16, args.Player.TileY*16 + 48)) { plr.SendInfoMessage(string.Format("You were teleported to {0}.", args.Player.Name)); args.Player.SendSuccessMessage(string.Format("You brought {0} here.", plr.Name)); @@ -1851,7 +1877,7 @@ private static void Warp(CommandArgs args) var plr = foundplr[0]; if (warp.WarpPos != Vector2.Zero) { - if (plr.Teleport((int)warp.WarpPos.X, (int)warp.WarpPos.Y + 3)) + if (plr.Teleport((int)warp.WarpPos.X*16, (int)warp.WarpPos.Y*16 + 48)) { plr.SendSuccessMessage(string.Format("{0} warped you to {1}.", args.Player.Name, warpName)); args.Player.SendSuccessMessage(string.Format("You warped {0} to {1}.", plr.Name, warpName)); @@ -1869,7 +1895,7 @@ private static void Warp(CommandArgs args) var warp = TShock.Warps.FindWarp(warpName); if (warp.WarpPos != Vector2.Zero) { - if (args.Player.Teleport((int)warp.WarpPos.X, (int)warp.WarpPos.Y + 3)) + if (args.Player.Teleport((int)warp.WarpPos.X*16, (int)warp.WarpPos.Y*16 + 48)) args.Player.SendSuccessMessage("Warped to " + warpName + "."); } else @@ -2484,7 +2510,27 @@ private static void Time(CommandArgs args) } } - //TODO: Come back here + private static void Rain(CommandArgs args) + { + if (args.Parameters.Count != 1) + { + args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /rain "); + return; + } + + switch (args.Parameters[0]) + { + case "start": + Main.StartRain(); + TSPlayer.All.SendInfoMessage(string.Format("{0} caused it to rain.", args.Player.Name)); + break; + case "stop": + Main.StopRain(); + TSPlayer.All.SendInfoMessage(string.Format("{0} ended the downpour.", args.Player.Name)); + break; + } + } + private static void Slap(CommandArgs args) { @@ -2900,13 +2946,13 @@ private static void Region(CommandArgs args) // worth the effort as chances are very low that overwriting the wire for a few // nanoseconds will cause much trouble. Tile tile = Main.tile[boundaryPoint.X, boundaryPoint.Y]; - bool oldWireState = tile.wire; - tile.wire = true; + bool oldWireState = tile.wire(); + tile.wire(true); try { args.Player.SendTileSquare(boundaryPoint.X, boundaryPoint.Y, 1); } finally { - tile.wire = oldWireState; + tile.wire(oldWireState); } } } @@ -3027,7 +3073,7 @@ private static void Region(CommandArgs args) break; } - args.Player.Teleport(region.Area.Center.X, region.Area.Center.Y + 3); + args.Player.Teleport(region.Area.Center.X*16, region.Area.Center.Y*16 + 48); break; } @@ -3703,12 +3749,7 @@ private static void Heal(CommandArgs args) playerToHeal = args.Player; } - Item heart = TShock.Utils.GetItemById(58); - Item star = TShock.Utils.GetItemById(184); - for (int i = 0; i < 20; i++) - playerToHeal.GiveItem(heart.type, heart.name, heart.width, heart.height, heart.maxStack); - for (int i = 0; i < 10; i++) - playerToHeal.GiveItem(star.type, star.name, star.width, star.height, star.maxStack); + playerToHeal.Heal(); if (playerToHeal == args.Player) { args.Player.SendSuccessMessage("You just got healed!"); @@ -3829,7 +3870,7 @@ private static void Grow(CommandArgs args) case "tree": for (int i = x - 1; i < x + 2; i++) { - Main.tile[i, y].active = true; + Main.tile[i, y].active(true); Main.tile[i, y].type = 2; Main.tile[i, y].wall = 0; } @@ -3840,20 +3881,20 @@ private static void Grow(CommandArgs args) case "epictree": for (int i = x - 1; i < x + 2; i++) { - Main.tile[i, y].active = true; + Main.tile[i, y].active(true); Main.tile[i, y].type = 2; Main.tile[i, y].wall = 0; } Main.tile[x, y - 1].wall = 0; Main.tile[x, y - 1].liquid = 0; - Main.tile[x, y - 1].active = true; + Main.tile[x, y - 1].active(true); WorldGen.GrowEpicTree(x, y); name = "Epic Tree"; break; case "mushroom": for (int i = x - 1; i < x + 2; i++) { - Main.tile[i, y].active = true; + Main.tile[i, y].active(true); Main.tile[i, y].type = 70; Main.tile[i, y].wall = 0; } @@ -3867,7 +3908,7 @@ private static void Grow(CommandArgs args) name = "Cactus"; break; case "herb": - Main.tile[x, y].active = true; + Main.tile[x, y].active(true); Main.tile[x, y].frameX = 36; Main.tile[x, y].type = 83; WorldGen.GrowAlch(x, y); diff --git a/TShockAPI/DB/BanManager.cs b/TShockAPI/DB/BanManager.cs index c2fef99ee..4e7d1f92b 100644 --- a/TShockAPI/DB/BanManager.cs +++ b/TShockAPI/DB/BanManager.cs @@ -124,7 +124,7 @@ public bool AddBan(string ip, string name = "", string reason = "", bool excepti { try { - return database.Query("INSERT INTO Bans (IP, Name, Reason, BanningUser, Date, Expiration) VALUES (@0, @1, @2, @3, @4, @5);", ip, name, reason, banner, DateTime.Now.ToString("G"), expiration) != 0; + return database.Query("INSERT INTO Bans (IP, Name, Reason, BanningUser, Date, Expiration) VALUES (@0, @1, @2, @3, @4, @5);", ip, name, reason, banner, DateTime.UtcNow.ToString("s"), expiration) != 0; } catch (Exception ex) { diff --git a/TShockAPI/DB/UserManager.cs b/TShockAPI/DB/UserManager.cs index c8af324c8..8585d9075 100644 --- a/TShockAPI/DB/UserManager.cs +++ b/TShockAPI/DB/UserManager.cs @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License */ using System; +using System.CodeDom.Compiler; using System.Data; using System.Collections.Generic; using System.Linq; @@ -38,6 +39,7 @@ public UserManager(IDbConnection db) new SqlColumn("Username", MySqlDbType.VarChar, 32) {Unique = true}, new SqlColumn("Password", MySqlDbType.VarChar, 128), new SqlColumn("Usergroup", MySqlDbType.Text), + new SqlColumn("Registered", MySqlDbType.Text), new SqlColumn("LastAccessed", MySqlDbType.Text), new SqlColumn("KnownIPs", MySqlDbType.Text) ); @@ -60,8 +62,8 @@ public void AddUser(User user) int ret; try { - ret = database.Query("INSERT INTO Users (Username, Password, UserGroup) VALUES (@0, @1, @2);", user.Name, - TShock.Utils.HashPassword(user.Password), user.Group); + ret = database.Query("INSERT INTO Users (Username, Password, UserGroup, Registered) VALUES (@0, @1, @2, @3);", user.Name, + TShock.Utils.HashPassword(user.Password), user.Group, DateTime.UtcNow.ToString("s")); } catch (Exception ex) { @@ -146,7 +148,7 @@ public void UpdateLogin(User user) { try { - if (database.Query("UPDATE Users SET LastAccessed = @0, KnownIps = @1 WHERE Username = @2;", DateTime.Now.ToString("G"), user.KnownIps, user.Name) == 0) + if (database.Query("UPDATE Users SET LastAccessed = @0, KnownIps = @1 WHERE Username = @2;", DateTime.UtcNow.ToString("s"), user.KnownIps, user.Name) == 0) throw new UserNotExistException(user.Name); } catch (Exception ex) @@ -268,6 +270,7 @@ private User LoadUserFromResult(User user, QueryResult result) user.Group = result.Get("Usergroup"); user.Password = result.Get("Password"); user.Name = result.Get("Username"); + user.Registered = result.Get("Registered"); user.LastAccessed = result.Get("LastAccessed"); user.KnownIps = result.Get("KnownIps"); return user; @@ -280,14 +283,16 @@ public class User public string Name { get; set; } public string Password { get; set; } public string Group { get; set; } + public string Registered { get; set; } public string LastAccessed { get; set; } public string KnownIps { get; set; } - public User(string name, string pass, string group, string last, string known) + public User(string name, string pass, string group, string registered, string last, string known) { Name = name; Password = pass; Group = group; + Registered = registered; LastAccessed = last; KnownIps = known; } @@ -297,6 +302,7 @@ public User() Name = ""; Password = ""; Group = ""; + Registered = ""; LastAccessed = ""; KnownIps = ""; } diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 0b128ba92..fceab4440 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -78,17 +78,17 @@ public class TileEditEventArgs : HandledEventArgs /// /// The Tile ID being edited. /// - public byte Type { get; set; } + public byte EditData { get; set; } /// /// The EditType. /// (KillTile = 0, PlaceTile = 1, KillWall = 2, PlaceWall = 3, KillTileNoItem = 4, PlaceWire = 5, KillWire = 6) /// - public byte EditType { get; set; } + public EditAction Action { get; set; } /// /// Did the tile get destroyed successfully. /// - public bool Fail { get; set; } + public EditType editDetail { get; set; } /// /// Used when a tile is placed to denote a subtype of tile. (e.g. for tile id 21: Chest = 0, Gold Chest = 1) @@ -100,7 +100,7 @@ public class TileEditEventArgs : HandledEventArgs /// TileEdit - called when a tile is placed or destroyed /// public static HandlerList TileEdit; - private static bool OnTileEdit(TSPlayer ply, int x, int y, byte type, byte editType, bool fail, byte style) + private static bool OnTileEdit(TSPlayer ply, int x, int y, EditAction action, EditType editDetail, byte editData, byte style) { if (TileEdit == null) return false; @@ -110,9 +110,9 @@ private static bool OnTileEdit(TSPlayer ply, int x, int y, byte type, byte editT Player = ply, X = x, Y = y, - Type = type, - EditType = editType, - Fail = fail, + Action = action, + EditData = editData, + editDetail = editDetail, Style = style }; TileEdit.Invoke(null, args); @@ -443,13 +443,15 @@ public class PlayerUpdateEventArgs : HandledEventArgs /// Velocity of the player /// public Vector2 Velocity { get; set; } + + public byte Pulley { get; set; } } /// /// PlayerUpdate - When the player sends it's updated information to the server /// public static HandlerList PlayerUpdate; - private static bool OnPlayerUpdate(byte player, byte control, byte item, Vector2 position, Vector2 velocity) + private static bool OnPlayerUpdate(byte player, byte control, byte item, Vector2 position, Vector2 velocity, byte pulley) { if (PlayerUpdate == null) return false; @@ -461,16 +463,17 @@ private static bool OnPlayerUpdate(byte player, byte control, byte item, Vector2 Item = item, Position = position, Velocity = velocity, + Pulley = pulley }; PlayerUpdate.Invoke(null, args); return args.Handled; } public static bool TSCheckNoclip(Vector2 Position, int Width, int Height) { - int num = (int)(Position.X / 16f) - 1; - int num2 = (int)((Position.X + (float)Width) / 16f) + 2; - int num3 = (int)(Position.Y / 16f) - 1; - int num4 = (int)((Position.Y + (float)Height) / 16f) + 2; + int num = (int)(Position.X / 16f); + int num2 = (int)((Position.X + (float)Width) / 16f); + int num3 = (int)(Position.Y / 16f); + int num4 = (int)((Position.Y + (float)Height) / 16f); if (num < 0) { num = 0; @@ -499,15 +502,17 @@ public static bool TSCheckNoclip(Vector2 Position, int Width, int Height) { for (int j = num3; j < num4; j++) { - if (Main.tile[i, j] != null && Main.tile[i, j].active && Main.tileSolid[(int)Main.tile[i, j].type] && !Main.tileSolidTop[(int)Main.tile[i, j].type] &&(((int)Main.tile[i,j].type !=53) && ((int)Main.tile[i,j].type !=112) && ((int)Main.tile[i,j].type !=116) && ((int)Main.tile[i,j].type !=123)) && !Main.tile[i,j].lava) + if (Main.tile[i, j] == null || !Main.tile[i, j].active() || !Main.tileSolid[(int) Main.tile[i, j].type] || Main.tileSolidTop[(int) Main.tile[i, j].type] || (((int) Main.tile[i, j].type == 53) || ((int) Main.tile[i, j].type == 112) || ((int) Main.tile[i, j].type == 116) || ((int) Main.tile[i, j].type == 123)) || Main.tile[i, j].lava() || ((Main.tile[i, j].tileHeader2 & 16) == 16) || ((Main.tile[i, j].tileHeader2 & 32) == 32) || ((Main.tile[i, j].tileHeader & 32) == 32) || Main.tile[i, j].honey() || !Main.tileSolid[(int) Main.tile[i + 1, j].type] || !Main.tileSolid[(int) Main.tile[i - 1, j].type] || !Main.tileSolid[(int) Main.tile[i, j + 1].type] || !Main.tileSolid[(int) Main.tile[i, j - 1].type] || !Main.tileSolid[(int) Main.tile[i - 1, j - 1].type] || !Main.tileSolid[(int) Main.tile[i - 1, j + 1].type] || !Main.tileSolid[(int) Main.tile[i + 1, j - 1].type] || !Main.tileSolid[(int) Main.tile[i + 1, j + 1].type] || Main.tileSand[(int) Main.tile[i, j].type]) { - Vector2 vector; - vector.X = (float)(i * 16); - vector.Y = (float)(j * 16); - if (Position.X + (float)Width > vector.X && Position.X < vector.X + 16f && Position.Y + (float)Height > vector.Y && Position.Y < vector.Y + 16f) - { - return true; - } + continue; + } + + Vector2 vector; + vector.X = (float) (i*16); + vector.Y = (float) (j*16); + if (Position.X + (float) Width > vector.X && Position.X < vector.X + 16f && Position.Y + (float) Height > vector.Y && Position.Y < vector.Y + 16f) + { + return true; } } } @@ -628,20 +633,20 @@ public class LiquidSetEventArgs : HandledEventArgs /// public int TileY { get; set; } /// - /// ??? + /// Amount of liquid /// - public byte Liquid { get; set;} + public byte Amount { get; set;} /// - /// True if lava + /// Type of Liquid: 0=water, 1=lave, 2=honey /// - public bool Lava { get; set; } + public byte Type { get; set; } } /// /// LiquidSet - When ever a liquid is set /// public static HandlerList LiquidSet; - private static bool OnLiquidSet(int tilex, int tiley, byte liquid, bool lava) + private static bool OnLiquidSet(int tilex, int tiley, byte amount, byte type) { if (LiquidSet == null) return false; @@ -650,8 +655,8 @@ private static bool OnLiquidSet(int tilex, int tiley, byte liquid, bool lava) { TileX = tilex, TileY = tiley, - Liquid = liquid, - Lava = lava, + Amount = amount, + Type = type, }; LiquidSet.Invoke(null, args); return args.Handled; @@ -919,6 +924,10 @@ public class ItemDropEventArgs : HandledEventArgs /// public byte Prefix { get; set; } /// + /// No Delay on pickup + /// + public bool NoDelay { get; set; } + /// /// Item type /// public short Type { get; set; } @@ -928,7 +937,7 @@ public class ItemDropEventArgs : HandledEventArgs /// public static HandlerList ItemDrop; - private static bool OnItemDrop(short id, Vector2 pos, Vector2 vel, byte stacks, byte prefix, short type) + private static bool OnItemDrop(short id, Vector2 pos, Vector2 vel, byte stacks, byte prefix, bool noDelay, short type) { if (ItemDrop == null) return false; @@ -940,6 +949,7 @@ private static bool OnItemDrop(short id, Vector2 pos, Vector2 vel, byte stacks, Velocity = vel, Stacks = stacks, Prefix = prefix, + NoDelay = noDelay, Type = type, }; ItemDrop.Invoke(null, args); @@ -1125,6 +1135,53 @@ private static bool OnPlayerBuffUpdate(byte id) return args.Handled; } + /// + /// For use with a NPCStrike event + /// + public class TeleportEventArgs : HandledEventArgs + { + /// + /// ??? + /// + public Int16 ID { get; set; } + /// + /// Flag is a bit field + /// if the first bit is set -> 0 = player, 1 = NPC + /// if the second bit is set, ignore this packet + /// if the third bit is set, style +1 + /// if the fourth bit is set, style +1 + /// + public byte Flag { get; set; } + /// + /// X Location + /// + public float X { get; set; } + /// + /// Y Location + /// + public float Y { get; set; } + } + /// + /// NPCStrike - Called when an NPC is attacked + /// + public static HandlerList Teleport; + + private static bool OnTeleport(Int16 id, byte f, float x, float y) + { + if (Teleport == null) + return false; + + var args = new TeleportEventArgs + { + ID = id, + Flag = f, + X = x, + Y = y + }; + Teleport.Invoke(null, args); + return args.Handled; + } + #endregion public static void InitGetDataHandler() { @@ -1169,7 +1226,10 @@ public static void InitGetDataHandler() {PacketTypes.PasswordSend, HandlePassword}, {PacketTypes.ContinueConnecting2, HandleConnecting}, {PacketTypes.ProjectileDestroy, HandleProjectileKill}, - {PacketTypes.SpawnBossorInvasion, HandleSpawnBoss} + {PacketTypes.SpawnBossorInvasion, HandleSpawnBoss}, + {PacketTypes.Teleport, HandleTeleport}, + {PacketTypes.PaintTile, HandlePaintTile}, + {PacketTypes.PaintWall, HandlePaintWall} }; } @@ -1251,7 +1311,7 @@ public static bool HandlePlayerHp(GetDataHandlerArgs args) if (args.Player.FirstMaxHP == 0) args.Player.FirstMaxHP = max; - if (max > TShock.Config.MaxHealth && max > args.Player.FirstMaxHP) + if ((max > TShock.Config.MaxHealth && max > args.Player.FirstMaxHP) && !args.Player.Group.HasPermission(Permissions.ignorestathackdetection)) { TShock.Utils.ForceKick(args.Player, "Hacked Client Detected.", true); return false; @@ -1262,6 +1322,11 @@ public static bool HandlePlayerHp(GetDataHandlerArgs args) args.Player.PlayerData.maxHealth = max; } + if (args.Player.Group.HasPermission(Permissions.godmode) && (cur < max)) + { + args.Player.Heal(args.TPlayer.statLifeMax); + } + return false; } @@ -1330,6 +1395,7 @@ private static bool HandlePlayerInfo(GetDataHandlerArgs args) private static bool HandleConnecting(GetDataHandlerArgs args) { var user = TShock.Users.GetUserByName(args.Player.Name); + if (user != null && !TShock.Config.DisableLoginBeforeJoin) { args.Player.RequiresPassword = true; @@ -1388,7 +1454,7 @@ private static bool HandlePassword(GetDataHandlerArgs args) return true; } } - args.Player.LoginFailsBySsi = false; + args.Player.LoginFailsBySsi = false; if (group.HasPermission(Permissions.ignorestackhackdetection)) args.Player.IgnoreActionsForCheating = "none"; @@ -1543,10 +1609,10 @@ private static bool HandleSendTileSquare(GetDataHandlerArgs args) continue; } // Server now has a range check built in - /*if (TShock.CheckRangePermission(args.Player, realx, realy)) + if (TShock.CheckRangePermission(args.Player, realx, realy)) { continue; - }*/ + } if ((tile.type == 128 && newtile.Type == 128) || (tile.type == 105 && newtile.Type == 105) || (tile.type == 139 && newtile.Type == 139)) { if (TShock.Config.EnableInsecureTileFixes) @@ -1673,16 +1739,39 @@ private static bool HandleSendTileSquare(GetDataHandlerArgs args) return true; } + public enum EditAction + { + KillTile = 0, + PlaceTile, + KillWall, + PlaceWall, + KillTileNoItem, + PlaceWire, + KillWire, + PoundTile + } + public enum EditType + { + Fail = 0, + Type, + Slope, + } private static bool HandleTile(GetDataHandlerArgs args) { - var type = args.Data.ReadInt8(); + EditAction action = (EditAction)args.Data.ReadInt8(); var tileX = args.Data.ReadInt32(); var tileY = args.Data.ReadInt32(); - var tiletype = args.Data.ReadInt8(); - var fail = tiletype == 1; + var editData = args.Data.ReadInt8(); + EditType type = (action == EditAction.KillTile || action == EditAction.KillWall || + action == EditAction.KillTileNoItem) + ? EditType.Fail + : (action == EditAction.PlaceTile || action == EditAction.PlaceWall) + ? EditType.Type + : EditType.Slope; + var style = args.Data.ReadInt8(); - if (OnTileEdit(args.Player, tileX, tileY, tiletype, type, fail, style)) + if (OnTileEdit(args.Player, tileX, tileY, action, type, editData, style)) return true; if (!TShock.Utils.TilePlacementValid(tileX, tileY)) return false; @@ -1767,62 +1856,64 @@ private static bool HandleTile(GetDataHandlerArgs args) if (type == 0 && Main.tile[tileX, tileY].type != 127 && !Main.tileCut[Main.tile[tileX, tileY].type] && !rightClickKill.Contains(Main.tile[tileX, tileY].type)) { // If the tile is an axe tile and they aren't selecting an axe, they're hacking. - if (Main.tileAxe[Main.tile[tileX, tileY].type] && selectedItem.axe == 0) + if (Main.tileAxe[Main.tile[tileX, tileY].type] && (selectedItem.axe == 0 && selectedItem.explosive == 0 && args.Player.RecentFuse == 0)) { args.Player.SendTileSquare(tileX, tileY); return true; } // If the tile is a hammer tile and they aren't selecting an hammer, they're hacking. - else if (Main.tileHammer[Main.tile[tileX, tileY].type] && selectedItem.hammer == 0) + else if (Main.tileHammer[Main.tile[tileX, tileY].type] && (selectedItem.hammer == 0 && selectedItem.explosive == 0 && args.Player.RecentFuse == 0)) { args.Player.SendTileSquare(tileX, tileY); return true; } // If the tile is a pickaxe tile and they aren't selecting an pickaxe, they're hacking. - else if ((!Main.tileAxe[Main.tile[tileX, tileY].type] && !Main.tileHammer[Main.tile[tileX, tileY].type]) && selectedItem.pick == 0) + else if ((!Main.tileAxe[Main.tile[tileX, tileY].type] && !Main.tileHammer[Main.tile[tileX, tileY].type]) && (selectedItem.pick == 0 && selectedItem.explosive == 0 && args.Player.RecentFuse == 0)) { args.Player.SendTileSquare(tileX, tileY); + return true; } } - else if (type == 2) + else if (action == EditAction.KillWall) { // If they aren't selecting an hammer, they're hacking. - if (selectedItem.hammer == 0) + if (selectedItem.hammer == 0 && selectedItem.explosive == 0 && args.Player.RecentFuse == 0) { args.Player.SendTileSquare(tileX, tileY); return true; } + } - else if (type == 1 || type == 3) + else if (action == EditAction.PlaceTile || action == EditAction.PlaceWall) { - if (type == 1 && TShock.Config.PreventInvalidPlaceStyle && ((tiletype == 4 && style > 8) || - (tiletype == 13 && style > 4) || (tiletype == 15 && style > 1) || (tiletype == 21 && style > 6) || - (tiletype == 82 && style > 5) || (tiletype == 91 && style > 3) || (tiletype == 105 && style > 42) || - (tiletype == 135 && style > 3) || (tiletype == 139 && style > 12) || (tiletype == 144 && style > 2) || - (tiletype == 149 && style > 2))) + if (action == EditAction.PlaceTile && TShock.Config.PreventInvalidPlaceStyle && ((editData == 4 && style > 11) || + (editData == 13 && style > 4) || (editData == 15 && style > 17) || (editData == 21 && style > 22) || + (editData == 82 && style > 5) || (editData == 91 && style > 21) || (editData == 105 && style > 49) || + (editData == 135 && style > 6) || (editData == 139 && style > 27) || (editData == 144 && style > 2) || + (editData == 149 && style > 2))) { args.Player.SendTileSquare(tileX, tileY); return true; } // If they aren't selecting the item which creates the tile or wall, they're hacking. - if (tiletype != 127 && tiletype != (type == 1 ? selectedItem.createTile : selectedItem.createWall)) + if (editData != 127 && editData != (action == EditAction.PlaceTile ? selectedItem.createTile : selectedItem.createWall)) { args.Player.SendTileSquare(tileX, tileY); return true; } - if (TShock.Itembans.ItemIsBanned(selectedItem.name, args.Player) || tiletype >= (type == 1 ? Main.maxTileSets : Main.maxWallTypes)) + if (TShock.Itembans.ItemIsBanned(selectedItem.name, args.Player) || editData >= (action == EditAction.PlaceTile ? Main.maxTileSets : Main.maxWallTypes)) { args.Player.SendTileSquare(tileX, tileY); return true; } - if (type == 1 && (tiletype == 29 || tiletype == 97) && TShock.Config.ServerSideInventory && TShock.Config.DisablePiggybanksOnSSI) + if (action == EditAction.PlaceTile && (editData == 29 || editData == 97) && TShock.Config.ServerSideInventory && TShock.Config.DisablePiggybanksOnSSI) { args.Player.SendMessage("You cannot place this tile because server side inventory is enabled.", Color.Red); args.Player.SendTileSquare(tileX, tileY); return true; } - if (type == 1 && tiletype == 21) + if (action == EditAction.PlaceTile && editData == 21) { if (TShock.Utils.MaxChests()) { @@ -1838,7 +1929,7 @@ private static bool HandleTile(GetDataHandlerArgs args) } } } - else if (type == 5) + else if (action == EditAction.PlaceWire) { // If they aren't selecting the wrench, they're hacking. if (args.TPlayer.inventory[args.TPlayer.selectedItem].type != 509) @@ -1847,7 +1938,7 @@ private static bool HandleTile(GetDataHandlerArgs args) return true; } } - else if (type == 6) + else if (action == EditAction.KillWire) { // If they aren't selecting the wire cutter, they're hacking. if (args.TPlayer.inventory[args.TPlayer.selectedItem].type != 510) @@ -1863,13 +1954,13 @@ private static bool HandleTile(GetDataHandlerArgs args) return true; } - if (TShock.CheckTilePermission(args.Player, tileX, tileY, tiletype, type)) + if (TShock.CheckTilePermission(args.Player, tileX, tileY, editData, action)) { args.Player.SendTileSquare(tileX, tileY); return true; } - if ((tiletype == 127 || Main.tileCut[tiletype]) && (type == 0 || type == 4)) + if ((editData == 127 || Main.tileCut[editData]) && (action ==EditAction.KillTile || action == EditAction.KillTileNoItem)) { return false; } @@ -1900,26 +1991,103 @@ private static bool HandleTile(GetDataHandlerArgs args) return true; } - if ( ( type == 1 || type == 3 ) && !args.Player.Group.HasPermission(Permissions.ignoreplacetiledetection)) + if ( ( action == EditAction.PlaceTile || action == EditAction.PlaceWall ) && !args.Player.Group.HasPermission(Permissions.ignoreplacetiledetection)) { args.Player.TilePlaceThreshold++; var coords = new Vector2(tileX, tileY); if (!args.Player.TilesCreated.ContainsKey(coords)) - args.Player.TilesCreated.Add(coords, Main.tile[tileX, tileY].Data); + args.Player.TilesCreated.Add(coords, Main.tile[tileX, tileY]); } - if ((type == 0 || type == 4 || type == 2) && Main.tileSolid[Main.tile[tileX, tileY].type] && + if ((action == EditAction.KillTile || action == EditAction.KillTileNoItem || action == EditAction.KillWall) && Main.tileSolid[Main.tile[tileX, tileY].type] && !args.Player.Group.HasPermission(Permissions.ignorekilltiledetection)) { args.Player.TileKillThreshold++; var coords = new Vector2(tileX, tileY); if (!args.Player.TilesDestroyed.ContainsKey(coords)) - args.Player.TilesDestroyed.Add(coords, Main.tile[tileX, tileY].Data); + args.Player.TilesDestroyed.Add(coords, Main.tile[tileX, tileY]); } return false; } + /// + /// For use with a PaintTile event + /// + public class PaintTileEventArgs : HandledEventArgs + { + /// + /// X Location + /// + public Int32 X { get; set; } + /// + /// Y Location + /// + public Int32 Y { get; set; } + /// + /// Type + /// + public byte type { get; set; } + } + /// + /// NPCStrike - Called when an NPC is attacked + /// + public static HandlerList PaintTile; + + private static bool OnPaintTile(Int32 x, Int32 y, byte t) + { + if (PaintTile == null) + return false; + + var args = new PaintTileEventArgs + { + X = x, + Y = y, + type = t + }; + PaintTile.Invoke(null, args); + return args.Handled; + } + + + /// + /// For use with a PaintWall event + /// + public class PaintWallEventArgs : HandledEventArgs + { + /// + /// X Location + /// + public Int32 X { get; set; } + /// + /// Y Location + /// + public Int32 Y { get; set; } + /// + /// Type + /// + public byte type { get; set; } + } + /// + /// Called When a wall is painted + /// + public static HandlerList PaintWall; + + private static bool OnPaintWall(Int32 x, Int32 y, byte t) + { + if (PaintWall == null) + return false; + + var args = new PaintWallEventArgs + { + X = x, + Y = y, + type = t + }; + PaintWall.Invoke(null, args); + return args.Handled; + } + private static bool HandleTogglePvp(GetDataHandlerArgs args) { byte id = args.Data.ReadInt8(); @@ -1987,13 +2155,19 @@ private static bool HandlePlayerUpdate(GetDataHandlerArgs args) var item = args.Data.ReadInt8(); var pos = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle()); var vel = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle()); - if (OnPlayerUpdate(plr, control, item, pos, vel)) + byte pulley = args.Data.ReadInt8(); + if (OnPlayerUpdate(plr, control, item, pos, vel, pulley)) return true; if (item < 0 || item >= args.TPlayer.inventory.Length) { return true; } + if (pulley > 2) + { + return true; + } + if (args.Player.LastNetPosition == Vector2.Zero) { return true; @@ -2036,8 +2210,8 @@ private static bool HandlePlayerUpdate(GetDataHandlerArgs args) args.Player.SendMessage("PvP is forced! Enable PvP or else you can't do anything!", Color.Red); } - int lastTileX = (int) (args.Player.LastNetPosition.X/16f); - int lastTileY = (int) (args.Player.LastNetPosition.Y/16f); + var lastTileX = args.Player.LastNetPosition.X; + var lastTileY = args.Player.LastNetPosition.Y; if (!args.Player.Teleport(lastTileX, lastTileY)) { args.Player.Spawn(); @@ -2056,9 +2230,9 @@ private static bool HandlePlayerUpdate(GetDataHandlerArgs args) TSCheckNoclip(pos, args.TPlayer.width, args.TPlayer.height) && !TShock.Config.IgnoreNoClip && !args.TPlayer.tongued) { - int lastTileX = (int)(args.Player.LastNetPosition.X / 16f); - int lastTileY = (int)(args.Player.LastNetPosition.Y / 16f); - if (!args.Player.Teleport(lastTileX, lastTileY + 3)) + var lastTileX = args.Player.LastNetPosition.X; + var lastTileY = args.Player.LastNetPosition.Y; + if (!args.Player.Teleport(lastTileX, lastTileY + 48)) { args.Player.SendErrorMessage("You got stuck in a solid object, Sent to spawn point."); args.Player.Spawn(); @@ -2092,6 +2266,8 @@ private static bool HandlePlayerUpdate(GetDataHandlerArgs args) args.TPlayer.controlRight = false; args.TPlayer.controlJump = false; args.TPlayer.controlUseItem = false; + args.TPlayer.pulley = pulley != 0; + args.TPlayer.pulleyDir = pulley; args.TPlayer.direction = -1; if ((control & 1) == 1) { @@ -2207,12 +2383,14 @@ private static bool HandleProjectileNew(GetDataHandlerArgs args) } } - // force all explosives server-side. + // force all explosives server-side. -- DOES NOT WORK DUE TO LATENCY if (hasPermission && (type == 28 || type == 29 || type == 37)) { - args.Player.RemoveProjectile(ident, owner); - Projectile.NewProjectile(pos.X, pos.Y, vel.X, vel.Y, type, dmg, knockback); - return true; + // Denotes that the player has recently set a fuse - used for cheat detection. + args.Player.RecentFuse = 10; + // args.Player.RemoveProjectile(ident, owner); + // Projectile.NewProjectile(pos.X, pos.Y, vel.X, vel.Y, type, dmg, knockback); + // return true; } return false; @@ -2291,11 +2469,12 @@ private static bool HandleLiquidSet(GetDataHandlerArgs args) { int tileX = args.Data.ReadInt32(); int tileY = args.Data.ReadInt32(); - byte liquid = args.Data.ReadInt8(); - bool lava = args.Data.ReadBoolean(); + byte amount = args.Data.ReadInt8(); + byte type = args.Data.ReadInt8(); - if (OnLiquidSet(tileX, tileY, liquid, lava)) + if (OnLiquidSet(tileX, tileY, amount, type)) return true; + if (tileX < 0 || tileX >= Main.maxTilesX || tileY < 0 || tileY >= Main.maxTilesY) return false; @@ -2314,12 +2493,16 @@ private static bool HandleLiquidSet(GetDataHandlerArgs args) if (!args.Player.Group.HasPermission(Permissions.ignoreliquidsetdetection)) { - args.Player.TileLiquidThreshold++; + args.Player.TileLiquidThreshold+=amount; } - if (liquid != 0) + if (amount != 0) { - int bucket = 0; - if (args.TPlayer.inventory[args.TPlayer.selectedItem].type == 206) + int bucket = -1; + if (args.TPlayer.inventory[args.TPlayer.selectedItem].type == 205) + { + bucket = 0; + } + else if (args.TPlayer.inventory[args.TPlayer.selectedItem].type == 206) { bucket = 1; } @@ -2327,8 +2510,12 @@ private static bool HandleLiquidSet(GetDataHandlerArgs args) { bucket = 2; } + else if (args.TPlayer.inventory[args.TPlayer.selectedItem].type == 1128) + { + bucket = 3; + } - if(lava && bucket != 2) + if (type == 1 && !(bucket == 2 || bucket == 0)) { args.Player.SendErrorMessage("You do not have permission to perform this action."); args.Player.Disable("Spreading lava without holding a lava bucket"); @@ -2336,7 +2523,7 @@ private static bool HandleLiquidSet(GetDataHandlerArgs args) return true; } - if(lava && (!args.Player.Group.HasPermission(Permissions.usebanneditem) && + if(type == 1 && (!args.Player.Group.HasPermission(Permissions.usebanneditem) && TShock.Itembans.ItemIsBanned("Lava Bucket", args.Player))) { args.Player.SendErrorMessage("You do not have permission to perform this action."); @@ -2345,7 +2532,7 @@ private static bool HandleLiquidSet(GetDataHandlerArgs args) return true; } - if (!lava && bucket != 1) + if (type == 0 && !(bucket == 1 || bucket == 0)) { args.Player.SendErrorMessage("You do not have permission to perform this action."); args.Player.Disable("Spreading water without holding a water bucket"); @@ -2353,7 +2540,7 @@ private static bool HandleLiquidSet(GetDataHandlerArgs args) return true; } - if (!lava && (!args.Player.Group.HasPermission(Permissions.usebanneditem) && + if (type == 0 && (!args.Player.Group.HasPermission(Permissions.usebanneditem) && TShock.Itembans.ItemIsBanned("Water Bucket", args.Player))) { args.Player.SendErrorMessage("You do not have permission to perform this action."); @@ -2361,6 +2548,23 @@ private static bool HandleLiquidSet(GetDataHandlerArgs args) args.Player.SendTileSquare(tileX, tileY); return true; } + + if (type == 2 &&!(bucket == 3 || bucket == 0)) + { + args.Player.SendErrorMessage("You do not have permission to perform this action."); + args.Player.Disable("Spreading honey without holding a honey bucket"); + args.Player.SendTileSquare(tileX, tileY); + return true; + } + + if (type == 2 && (!args.Player.Group.HasPermission(Permissions.usebanneditem) && + TShock.Itembans.ItemIsBanned("Honey Bucket", args.Player))) + { + args.Player.SendErrorMessage("You do not have permission to perform this action."); + args.Player.Disable("Using banned honey bucket without permissions"); + args.Player.SendTileSquare(tileX, tileY); + return true; + } } if (TShock.CheckTilePermission(args.Player, tileX, tileY)) @@ -2631,13 +2835,14 @@ private static bool HandleItemDrop(GetDataHandlerArgs args) var vel = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle()); var stacks = args.Data.ReadInt8(); var prefix = args.Data.ReadInt8(); + var noDelay = args.Data.ReadBoolean(); var type = args.Data.ReadInt16(); - if (OnItemDrop(id, pos, vel, stacks, prefix, type)) + if (OnItemDrop(id, pos, vel, stacks, prefix, noDelay, type)) return true; // player is attempting to crash clients - if (type < -24 || type >= Main.maxItemTypes) + if (type < -48 || type >= Main.maxItemTypes) { return true; } @@ -2737,6 +2942,11 @@ private static bool HandlePlayerDamage(GetDataHandlerArgs args) return true; } + if (args.Player.Group.HasPermission(Permissions.godmode)) + { + args.Player.Heal(args.TPlayer.statLifeMax); + } + return false; } @@ -2939,5 +3149,96 @@ private static bool HandleSpawnBoss(GetDataHandlerArgs args) TShock.Utils.SendLogs(string.Format("{0} summoned {1}", args.Player.Name, boss), Color.PaleVioletRed, args.Player); return false; } + + private static bool HandlePaintTile(GetDataHandlerArgs args) + { + var x = args.Data.ReadInt32(); + var y = args.Data.ReadInt32(); + var t = args.Data.ReadInt8(); + + if (OnPaintTile(x, y, t)) + return true; + + if (!args.Player.Group.HasPermission(Permissions.canpaint)) + { + args.Player.SendTileSquare(x, y); + return true; + } + + return false; + } + + private static bool HandlePaintWall(GetDataHandlerArgs args) + { + var x = args.Data.ReadInt32(); + var y = args.Data.ReadInt32(); + var t = args.Data.ReadInt8(); + + if (OnPaintTile(x, y, t)) + return true; + + if (!args.Player.Group.HasPermission(Permissions.canpaint)) + { + args.Player.SendTileSquare(x, y); + return true; + } + + return false; + } + private static bool HandleTeleport(GetDataHandlerArgs args) + { + var flag = args.Data.ReadInt8(); + var id = args.Data.ReadInt16(); + var x = args.Data.ReadSingle(); + var y = args.Data.ReadSingle(); + + if (OnTeleport(id, flag, x, y)) + return true; + + byte style = 0; + var isNPC = false; + if ((flag & 1) == 1) + { + isNPC = true; + } + + if ((flag & 2) != 2) + { + if ((flag & 4) == 4) + { + style++; + } + + if ((flag & 8) == 8) + { + style++; + } + + if (id > (isNPC ? 200 : 255)) + { + return true; + } + + if (Main.player[id] == null || TShock.Players[id] == null) + { + return true; + } + + if (!isNPC && !args.Player.Group.HasPermission(Permissions.tp)) + { + args.Player.SendErrorMessage("You do not have permission to teleport."); + Main.player[id].Teleport(new Vector2(Main.player[id].position.X, Main.player[id].position.Y), style); + NetMessage.SendData(65, -1, -1, "", 0, (float)id, Main.player[id].position.X, Main.player[id].position.Y, style); + return true; + } + + if (!isNPC) + { + TShock.Players[id].Teleport(x, y, style); + } + } + + return true; + } } } diff --git a/TShockAPI/Net/NetTile.cs b/TShockAPI/Net/NetTile.cs index e3cc30f47..01a3b8fce 100644 --- a/TShockAPI/Net/NetTile.cs +++ b/TShockAPI/Net/NetTile.cs @@ -31,9 +31,13 @@ public class NetTile : IPackable public short FrameY { get; set; } public byte Wall { get; set; } public byte Liquid { get; set; } - public bool Lava { get; set; } + public byte LiquidType { get; set; } public bool Wire { get; set; } - + public byte HalfBrick { get; set; } + public byte Actuator { get; set; } + public bool Inactive { get; set; } + public bool IsHalf { get; set; } + public bool IsActuator { get; set; } public bool HasWall { get { return Wall > 0; } @@ -57,8 +61,10 @@ public NetTile() FrameY = -1; Wall = 0; Liquid = 0; - Lava = false; Wire = false; + HalfBrick = 0; + Actuator = 0; + Inactive = false; } public NetTile(Stream stream) @@ -71,7 +77,7 @@ public void Pack(Stream stream) { var flags = TileFlags.None; - if (Active) + if ((Active) && (!Inactive)) flags |= TileFlags.Active; if (HasWall) @@ -82,6 +88,17 @@ public void Pack(Stream stream) if (Wire) flags |= TileFlags.Wire; + + if (IsHalf) + flags |= TileFlags.HalfBrick; + + if (IsActuator) + flags |= TileFlags.Actuator; + + if (Inactive) + { + flags |= TileFlags.Inactive; + } stream.WriteInt8((byte) flags); @@ -101,7 +118,7 @@ public void Pack(Stream stream) if (HasLiquid) { stream.WriteInt8(Liquid); - stream.WriteBoolean(Lava); + stream.WriteInt8(LiquidType); } } @@ -128,11 +145,23 @@ public void Unpack(Stream stream) if (flags.HasFlag(TileFlags.Liquid)) { Liquid = stream.ReadInt8(); - Lava = stream.ReadBoolean(); + LiquidType = stream.ReadInt8(); } if (flags.HasFlag(TileFlags.Wire)) Wire = true; + + if (flags.HasFlag(TileFlags.HalfBrick)) + IsHalf = true; + + if (flags.HasFlag(TileFlags.Actuator)) + IsActuator = true; + + if (flags.HasFlag(TileFlags.Inactive)) + { + Inactive = true; + Active = false; + } } } @@ -144,6 +173,9 @@ public enum TileFlags : byte Lighted = 2, Wall = 4, Liquid = 8, - Wire = 16 + Wire = 16, + HalfBrick = 32, + Actuator = 64, + Inactive = 128 } -} \ No newline at end of file +} diff --git a/TShockAPI/Net/ProjectileRemoveMsg.cs b/TShockAPI/Net/ProjectileRemoveMsg.cs index d87753138..1f7907e6a 100644 --- a/TShockAPI/Net/ProjectileRemoveMsg.cs +++ b/TShockAPI/Net/ProjectileRemoveMsg.cs @@ -25,7 +25,7 @@ public class ProjectileRemoveMsg : BaseMsg { public override PacketTypes ID { - get { return PacketTypes.ProjectileNew; } + get{ return PacketTypes.ProjectileNew; } } public short Index { get; set; } diff --git a/TShockAPI/Net/WorldInfoMsg.cs b/TShockAPI/Net/WorldInfoMsg.cs index d95a8bf9d..472fd8614 100644 --- a/TShockAPI/Net/WorldInfoMsg.cs +++ b/TShockAPI/Net/WorldInfoMsg.cs @@ -24,7 +24,7 @@ You should have received a copy of the GNU General Public License namespace TShockAPI.Net { [Flags] - public enum WorldInfoFlag : byte + public enum BossFlags : byte { None = 0, OrbSmashed = 1, @@ -35,12 +35,25 @@ public enum WorldInfoFlag : byte DownedClown = 32 } + [Flags] + public enum BossFlags2 : byte + { + None = 0, + DownedMechBoss1 = 1, + DownedMechBoss2 = 2, + DownedMechBoss3 = 4, + DownedMechBossAny = 8, + CloudBg = 16, + Crimson = 32 + } + public class WorldInfoMsg : BaseMsg { public int Time { get; set; } public bool DayTime { get; set; } public byte MoonPhase { get; set; } public bool BloodMoon { get; set; } + public bool Eclipse { get; set; } public int MaxTilesX { get; set; } public int MaxTilesY { get; set; } public int SpawnX { get; set; } @@ -48,7 +61,37 @@ public class WorldInfoMsg : BaseMsg public int WorldSurface { get; set; } public int RockLayer { get; set; } public int WorldID { get; set; } - public WorldInfoFlag WorldFlags { get; set; } + public byte MoonType { get; set; } + public int TreeX0 { get; set; } + public int TreeX1 { get; set; } + public int TreeX2 { get; set; } + public byte TreeStyle0 { get; set; } + public byte TreeStyle1 { get; set; } + public byte TreeStyle2 { get; set; } + public byte TreeStyle3 { get; set; } + public int CaveBackX0 { get; set; } + public int CaveBackX1 { get; set; } + public int CaveBackX2 { get; set; } + public byte CaveBackStyle0 { get; set; } + public byte CaveBackStyle1 { get; set; } + public byte CaveBackStyle2 { get; set; } + public byte CaveBackStyle3 { get; set; } + public byte SetBG0 { get; set; } + public byte SetBG1 { get; set; } + public byte SetBG2 { get; set; } + public byte SetBG3 { get; set; } + public byte SetBG4 { get; set; } + public byte SetBG5 { get; set; } + public byte SetBG6 { get; set; } + public byte SetBG7 { get; set; } + public byte IceBackStyle { get; set; } + public byte JungleBackStyle { get; set; } + public byte HellBackStyle { get; set; } + public float WindSpeed { get; set; } + public byte NumberOfClouds { get; set; } + public BossFlags BossFlags { get; set; } + public BossFlags2 BossFlags2 { get; set; } + public float Rain { get; set; } public string WorldName { get; set; } public override PacketTypes ID @@ -62,6 +105,7 @@ public override void Pack(Stream stream) stream.WriteBoolean(DayTime); stream.WriteInt8(MoonPhase); stream.WriteBoolean(BloodMoon); + stream.WriteBoolean(Eclipse); stream.WriteInt32(MaxTilesX); stream.WriteInt32(MaxTilesY); stream.WriteInt32(SpawnX); @@ -69,7 +113,37 @@ public override void Pack(Stream stream) stream.WriteInt32(WorldSurface); stream.WriteInt32(RockLayer); stream.WriteInt32(WorldID); - stream.WriteInt8((byte) WorldFlags); + stream.WriteByte(MoonType); + stream.WriteInt32(TreeX0); + stream.WriteInt32(TreeX1); + stream.WriteInt32(TreeX2); + stream.WriteByte(TreeStyle0); + stream.WriteByte(TreeStyle1); + stream.WriteByte(TreeStyle2); + stream.WriteByte(TreeStyle3); + stream.WriteInt32(CaveBackX0); + stream.WriteInt32(CaveBackX1); + stream.WriteInt32(CaveBackX2); + stream.WriteByte(CaveBackStyle0); + stream.WriteByte(CaveBackStyle1); + stream.WriteByte(CaveBackStyle2); + stream.WriteByte(CaveBackStyle3); + stream.WriteByte(SetBG0); + stream.WriteByte(SetBG1); + stream.WriteByte(SetBG2); + stream.WriteByte(SetBG3); + stream.WriteByte(SetBG4); + stream.WriteByte(SetBG5); + stream.WriteByte(SetBG6); + stream.WriteByte(SetBG7); + stream.WriteByte(IceBackStyle); + stream.WriteByte(JungleBackStyle); + stream.WriteByte(HellBackStyle); + stream.WriteSingle(WindSpeed); + stream.WriteByte(NumberOfClouds); + stream.WriteInt8((byte) BossFlags); + stream.WriteInt8((byte)BossFlags2); + stream.WriteSingle(Rain); stream.WriteBytes(Encoding.UTF8.GetBytes(WorldName)); } } diff --git a/TShockAPI/PacketBufferer.cs b/TShockAPI/PacketBufferer.cs index d18ac47fe..ebab27d1b 100644 --- a/TShockAPI/PacketBufferer.cs +++ b/TShockAPI/PacketBufferer.cs @@ -22,8 +22,8 @@ You should have received a copy of the GNU General Public License using System.IO; using System.Net.Sockets; using System.Text; -using Hooks; using Terraria; +using TerrariaApi.Server; namespace TShockAPI { @@ -34,6 +34,8 @@ public class PacketBufferer : IDisposable /// public int BytesPerUpdate { get; set; } + private readonly TShock plugin; + private PacketBuffer[] buffers = new PacketBuffer[Netplay.serverSock.Length]; private int[] Bytes = new int[52]; @@ -45,8 +47,9 @@ public class PacketBufferer : IDisposable Command flush; #endif - public PacketBufferer() + public PacketBufferer(TShock p) { + plugin = p; BytesPerUpdate = 0xFFFF; for (int i = 0; i < buffers.Length; i++) buffers[i] = new PacketBuffer(); @@ -58,9 +61,9 @@ public PacketBufferer() Commands.ChatCommands.Add(flush); #endif - NetHooks.SendBytes += ServerHooks_SendBytes; - ServerHooks.SocketReset += ServerHooks_SocketReset; - GameHooks.PostUpdate += GameHooks_Update; + ServerApi.Hooks.NetSendBytes.Register(plugin, ServerHooks_SendBytes); + ServerApi.Hooks.ServerSocketReset.Register(plugin, ServerHooks_SocketReset); + ServerApi.Hooks.GamePostUpdate.Register(plugin, GameHooks_Update); } ~PacketBufferer() @@ -82,9 +85,9 @@ protected virtual void Dispose(bool disposing) Commands.ChatCommands.Remove(dump); Commands.ChatCommands.Remove(flush); #endif - NetHooks.SendBytes -= ServerHooks_SendBytes; - ServerHooks.SocketReset -= ServerHooks_SocketReset; - GameHooks.PostUpdate -= GameHooks_Update; + ServerApi.Hooks.NetSendBytes.Deregister(plugin, ServerHooks_SendBytes); + ServerApi.Hooks.ServerSocketReset.Deregister(plugin, ServerHooks_SocketReset); + ServerApi.Hooks.GamePostUpdate.Deregister(plugin, GameHooks_Update); } } @@ -107,7 +110,7 @@ private void Flush(CommandArgs args) Compressed = new int[52]; } - private void GameHooks_Update() + private void GameHooks_Update(EventArgs args) { FlushAll(); } @@ -148,9 +151,9 @@ public bool Flush(ServerSock socket) } - private void ServerHooks_SocketReset(ServerSock socket) + private void ServerHooks_SocketReset(SocketResetEventArgs args) { - buffers[socket.whoAmI] = new PacketBuffer(); + buffers[args.Socket.whoAmI] = new PacketBuffer(); } public bool SendBytes(ServerSock socket, byte[] buffer) @@ -217,10 +220,10 @@ public bool SendBytes(ServerSock socket, byte[] buffer, int offset, int count) return false; } - private void ServerHooks_SendBytes(ServerSock socket, byte[] buffer, int offset, int count, HandledEventArgs e) + private void ServerHooks_SendBytes(SendBytesEventArgs args) { - e.Handled = true; - BufferBytes(socket, buffer, offset, count); + args.Handled = true; + BufferBytes(args.Socket, args.Buffer, args.Offset, args.Count); } #if DEBUG_NET diff --git a/TShockAPI/Permissions.cs b/TShockAPI/Permissions.cs index f49067475..8330ce8e3 100644 --- a/TShockAPI/Permissions.cs +++ b/TShockAPI/Permissions.cs @@ -247,6 +247,9 @@ public static class Permissions [Description("User can modify the world.")] public static readonly string canbuild = "tshock.world.modify"; + + [Description("User can paint tiles.")] + public static readonly string canpaint = "tshock.world.paint"; // Non-grouped @@ -280,6 +283,9 @@ public static class Permissions [Description("User can get the server info.")] public static readonly string serverinfo = "tshock.info"; + [Description("Player recovers health as damage is taken. Can be one shotted.")] + public static readonly string godmode = "tshock.godmode"; + /// /// Lists all commands associated with a given permission /// diff --git a/TShockAPI/PluginUpdater/PluginUpdaterThread.cs b/TShockAPI/PluginUpdater/PluginUpdaterThread.cs deleted file mode 100644 index b77a13706..000000000 --- a/TShockAPI/PluginUpdater/PluginUpdaterThread.cs +++ /dev/null @@ -1,87 +0,0 @@ -/* -TShock, a server mod for Terraria -Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team) - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -using System; -using System.IO; -using System.Threading; -using Terraria; - -namespace TShockAPI.PluginUpdater -{ - class PluginUpdaterThread - { - private TSPlayer invoker; - public PluginUpdaterThread(TSPlayer player) - { - invoker = player; - PluginVersionCheck.PluginUpdate += PluginUpdate; - HandleUpdate(); - } - - private void HandleUpdate() - { - foreach(PluginContainer cont in ProgramServer.Plugins) - new Thread(PluginVersionCheck.CheckPlugin).Start(cont.Plugin); - } - - private int Updates = 0; - private void PluginUpdate(UpdateArgs args) - { - Updates++; - if(args.Success && String.IsNullOrEmpty(args.Error)) - { - invoker.SendSuccessMessage(String.Format("{0} was downloaded successfully.", args.Plugin.Name)); - } - else if(args.Success) - { - invoker.SendSuccessMessage(String.Format("{0} was skipped. Reason: {1}", args.Plugin.Name, args.Error)); - } - else - { - invoker.SendSuccessMessage(String.Format("{0} failed to downloaded. Error: {1}", args.Plugin.Name, args.Error)); - } - - if(Updates >= Terraria.ProgramServer.Plugins.Count) - { - PluginVersionCheck.PluginUpdate -= PluginUpdate; - - invoker.SendSuccessMessage("All plugins have been downloaded. Now copying them to the plugin folder..."); - - string folder = Path.Combine(TShock.SavePath, "UpdatedPlugins"); - string dest = Path.Combine(TShock.SavePath, "..", "ServerPlugins"); - - foreach (string dir in Directory.GetDirectories(folder, "*", System.IO.SearchOption.AllDirectories)) - { - string new_folder = dest + dir.Substring(folder.Length); - if (!Directory.Exists(new_folder)) - Directory.CreateDirectory(new_folder); - } - - foreach (string file_name in Directory.GetFiles(folder, "*.*", System.IO.SearchOption.AllDirectories)) - { - TSPlayer.Server.SendSuccessMessage(String.Format("Copied {0}", file_name)); - File.Copy(file_name, dest + file_name.Substring(folder.Length), true); - } - - - Directory.Delete(folder, true); - - invoker.SendSuccessMessage("All plugins have been processed. Restart the server to have access to the new plugins."); - } - } - } -} diff --git a/TShockAPI/PluginUpdater/PluginVersionCheck.cs b/TShockAPI/PluginUpdater/PluginVersionCheck.cs deleted file mode 100644 index 61858af83..000000000 --- a/TShockAPI/PluginUpdater/PluginVersionCheck.cs +++ /dev/null @@ -1,127 +0,0 @@ -/* -TShock, a server mod for Terraria -Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team) - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using JsonLoader; -using Newtonsoft.Json; - -namespace TShockAPI.PluginUpdater -{ - public class PluginVersionCheck - { - public delegate void PluginUpdateD(UpdateArgs e); - public static event PluginUpdateD PluginUpdate; - public static void OnPluginUpdate(UpdateArgs args) - { - if (PluginUpdate == null) - { - return; - } - - PluginUpdate(args); - } - - public static void CheckPlugin(object p) - { - TerrariaPlugin plugin = (TerrariaPlugin)p; - UpdateArgs args = new UpdateArgs {Plugin = plugin, Success = true, Error = ""}; - List files = new List(); - - try - { - if (!String.IsNullOrEmpty(plugin.UpdateURL)) - { - var request = HttpWebRequest.Create(plugin.UpdateURL); - VersionInfo vi; - - request.Timeout = 5000; - using (var response = request.GetResponse()) - { - using (var reader = new StreamReader(response.GetResponseStream())) - { - vi = JsonConvert.DeserializeObject(reader.ReadToEnd()); - } - } - - System.Version v = System.Version.Parse((vi.version.ToString())); - - if (!v.Equals(plugin.Version)) - { - DownloadPackage pkg; - request = HttpWebRequest.Create(vi.url); - - request.Timeout = 5000; - using (var response = request.GetResponse()) - { - using (var reader = new StreamReader(response.GetResponseStream())) - { - pkg = JsonConvert.DeserializeObject(reader.ReadToEnd()); - } - } - - foreach (PluginFile f in pkg.files) - { - using (WebClient Client = new WebClient()) - { - string dir = Path.Combine(TShock.SavePath, "UpdatedPlugins"); - if (!Directory.Exists(dir)) - Directory.CreateDirectory(dir); - - Client.DownloadFile(f.url, - Path.Combine(dir, f.destination)); - - files.Add(Path.Combine(dir, f.destination)); - } - } - } - else - { - args.Error = "Plugin is up to date."; - } - } - else - { - args.Error = "Plugin has no updater recorded."; - } - } - catch(Exception e) - { - args.Success = false; - args.Error = e.Message; - if(files.Count > 0) - { - foreach(string s in files) - { - File.Delete(s); - } - } - } - - OnPluginUpdate(args); - } - } - - public class UpdateArgs - { - public TerrariaPlugin Plugin { get; set; } - public bool Success { get; set; } - public string Error { get; set; } - } -} diff --git a/TShockAPI/PluginUpdater/VersionInfo.cs b/TShockAPI/PluginUpdater/VersionInfo.cs deleted file mode 100644 index 4dd061b32..000000000 --- a/TShockAPI/PluginUpdater/VersionInfo.cs +++ /dev/null @@ -1,87 +0,0 @@ -/* -TShock, a server mod for Terraria -Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team) - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -using System; -using System.Collections.Generic; - -namespace JsonLoader -{ - class VersionInfo - { - public Version version; - public string url; - } - - public class Version - { - public int Major; - public int Minor; - public int Build; - public int Revision; - public int MajorRevision; - public int MinorRevision; - - public Version() - { - SetVersion(0,0,0,0); - } - - public Version(int m) - { - SetVersion(m, 0, 0, 0); - } - - public Version(int ma, int mi) - { - SetVersion(ma, mi, 0, 0); - } - - public Version(int ma, int mi, int b) - { - SetVersion(ma, mi, b, 0); - } - - public Version(int ma, int mi, int b, int r) - { - SetVersion(ma, mi, b, r); - } - - private void SetVersion(int ma, int mi, int b, int r) - { - Major = ma; - Minor = mi; - Build = b; - Revision = r; - } - - public string ToString() - { - return String.Format("{0}.{1}.{2}.{3}", Major, Minor, Build, Revision); - } - } - - class DownloadPackage - { - public List files; - } - - class PluginFile - { - public string url; - public string destination = ""; - } -} diff --git a/TShockAPI/Rest/RestManager.cs b/TShockAPI/Rest/RestManager.cs index 8d872fe2b..c14e38d84 100644 --- a/TShockAPI/Rest/RestManager.cs +++ b/TShockAPI/Rest/RestManager.cs @@ -307,7 +307,7 @@ private object UserCreateV2(RestVerbs verbs, IParameterCollection parameters, Se return RestMissingParam("password"); // NOTE: ip can be blank - User user = new User(username, password, group, "", ""); + User user = new User(username, password, group, "", "", ""); try { TShock.Users.AddUser(user); diff --git a/TShockAPI/SaveManager.cs b/TShockAPI/SaveManager.cs index 7e0b0b57e..5d5e444c5 100644 --- a/TShockAPI/SaveManager.cs +++ b/TShockAPI/SaveManager.cs @@ -20,6 +20,7 @@ You should have received a copy of the GNU General Public License using System.ComponentModel; using System.Threading; using Terraria; +using TerrariaApi.Server; namespace TShockAPI { @@ -45,7 +46,7 @@ private SaveManager() /// /// SaveWorld event handler which notifies users that the server may lag /// - public void OnSaveWorld(bool resettime = false, HandledEventArgs e = null) + public void OnSaveWorld(WorldSaveEventArgs args) { // Protect against internal errors causing save failures // These can be caused by an unexpected error such as a bad or out of date plugin @@ -120,7 +121,7 @@ private void SaveWorker() { if (task.direct) { - OnSaveWorld(); + OnSaveWorld(new WorldSaveEventArgs()); WorldGen.realsaveWorld(task.resetTime); } else diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 0e1449d40..1f695a209 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -57,16 +57,21 @@ public class TSPlayer /// The number of projectiles created by the player in the last second. /// public int ProjectileThreshold { get; set; } + + /// + /// A timer to keep track of whether or not the player has recently thrown an explosive + // + public int RecentFuse = 0; /// /// A queue of tiles destroyed by the player for reverting. /// - public Dictionary TilesDestroyed { get; protected set; } + public Dictionary TilesDestroyed { get; protected set; } /// /// A queue of tiles placed by the player for reverting. /// - public Dictionary TilesCreated { get; protected set; } + public Dictionary TilesCreated { get; protected set; } public int FirstMaxHP { get; set; } @@ -390,7 +395,7 @@ public bool InventorySlotAvailable bool flag = false; if (RealPlayer) { - for (int i = 0; i < 40; i++) //41 is trash can, 42-45 is coins, 46-49 is ammo + for (int i = 0; i < 50; i++) //51 is trash can, 52-55 is coins, 56-59 is ammo { if (TPlayer.inventory[i] == null || !TPlayer.inventory[i].active || TPlayer.inventory[i].name == "") { @@ -405,8 +410,8 @@ public bool InventorySlotAvailable public TSPlayer(int index) { - TilesDestroyed = new Dictionary(); - TilesCreated = new Dictionary(); + TilesDestroyed = new Dictionary(); + TilesCreated = new Dictionary(); Index = index; Group = Group.DefaultGroup; IceTiles = new List(); @@ -415,8 +420,8 @@ public TSPlayer(int index) protected TSPlayer(String playerName) { - TilesDestroyed = new Dictionary(); - TilesCreated = new Dictionary(); + TilesDestroyed = new Dictionary(); + TilesCreated = new Dictionary(); Index = -1; FakePlayer = new Player {name = playerName, whoAmi = -1}; Group = Group.DefaultGroup; @@ -457,12 +462,47 @@ public void SendWorldInfo(int tilex, int tiley, bool fakeid) //Sending a fake world id causes the client to not be able to find a stored spawnx/y. //This fixes the bed spawn point bug. With a fake world id it wont be able to find the bed spawn. WorldID = !fakeid ? Main.worldID : -1, - WorldFlags = (WorldGen.shadowOrbSmashed ? WorldInfoFlag.OrbSmashed : WorldInfoFlag.None) | - (NPC.downedBoss1 ? WorldInfoFlag.DownedBoss1 : WorldInfoFlag.None) | - (NPC.downedBoss2 ? WorldInfoFlag.DownedBoss2 : WorldInfoFlag.None) | - (NPC.downedBoss3 ? WorldInfoFlag.DownedBoss3 : WorldInfoFlag.None) | - (Main.hardMode ? WorldInfoFlag.HardMode : WorldInfoFlag.None) | - (NPC.downedClown ? WorldInfoFlag.DownedClown : WorldInfoFlag.None), + MoonType = (byte)Main.moonType, + TreeX0 = Main.treeX[0], + TreeX1 = Main.treeX[1], + TreeX2 = Main.treeX[2], + TreeStyle0 = (byte)Main.treeStyle[0], + TreeStyle1 = (byte)Main.treeStyle[1], + TreeStyle2 = (byte)Main.treeStyle[2], + TreeStyle3 = (byte)Main.treeStyle[3], + CaveBackX0 = Main.caveBackX[0], + CaveBackX1 = Main.caveBackX[1], + CaveBackX2 = Main.caveBackX[2], + CaveBackStyle0 = (byte)Main.caveBackStyle[0], + CaveBackStyle1 = (byte)Main.caveBackStyle[1], + CaveBackStyle2 = (byte)Main.caveBackStyle[2], + CaveBackStyle3 = (byte)Main.caveBackStyle[3], + SetBG0 = (byte)WorldGen.treeBG, + SetBG1 = (byte)WorldGen.corruptBG, + SetBG2 = (byte)WorldGen.jungleBG, + SetBG3 = (byte)WorldGen.snowBG, + SetBG4 = (byte)WorldGen.hallowBG, + SetBG5 = (byte)WorldGen.crimsonBG, + SetBG6 = (byte)WorldGen.desertBG, + SetBG7 = (byte)WorldGen.oceanBG, + IceBackStyle = (byte)Main.iceBackStyle, + JungleBackStyle = (byte)Main.jungleBackStyle, + HellBackStyle = (byte)Main.hellBackStyle, + WindSpeed = Main.windSpeed, + NumberOfClouds = (byte)Main.numClouds, + BossFlags = (WorldGen.shadowOrbSmashed ? BossFlags.OrbSmashed : BossFlags.None) | + (NPC.downedBoss1 ? BossFlags.DownedBoss1 : BossFlags.None) | + (NPC.downedBoss2 ? BossFlags.DownedBoss2 : BossFlags.None) | + (NPC.downedBoss3 ? BossFlags.DownedBoss3 : BossFlags.None) | + (Main.hardMode ? BossFlags.HardMode : BossFlags.None) | + (NPC.downedClown ? BossFlags.DownedClown : BossFlags.None), + BossFlags2 = (NPC.downedMechBoss1 ? BossFlags2.DownedMechBoss1 : BossFlags2.None) | + (NPC.downedMechBoss2 ? BossFlags2.DownedMechBoss2 : BossFlags2.None) | + (NPC.downedMechBoss3 ? BossFlags2.DownedMechBoss3 : BossFlags2.None) | + (NPC.downedMechBossAny ? BossFlags2.DownedMechBossAny : BossFlags2.None) | + (Main.cloudBGActive == 1f ? BossFlags2.CloudBg : BossFlags2.None) | + (WorldGen.crimson ? BossFlags2.Crimson : BossFlags2.None), + Rain = Main.maxRaining, WorldName = TShock.Config.UseServerName ? TShock.Config.ServerName : Main.worldName }; msg.PackFull(ms); @@ -470,41 +510,35 @@ public void SendWorldInfo(int tilex, int tiley, bool fakeid) } } - public bool Teleport(int tilex, int tiley) + public bool Teleport(float x, float y, byte style = 1) { - InitSpawn = false; - - SendWorldInfo(tilex, tiley, true); - - //150 Should avoid all client crash errors - //The error occurs when a tile trys to update which the client hasnt load yet, Clients only update tiles withen 150 blocks - //Try 300 if it does not work (Higher number - Longer load times - Less chance of error) - //Should we properly send sections so that clients don't get tiles twice? - SendTileSquare(tilex, tiley, 150); - -/* //We shouldn't need this section anymore -it can prevent otherwise acceptable teleportation under some circumstances. - - if (!SendTileSquare(tilex, tiley, 150)) + if (x > Main.rightWorld - 992) { - InitSpawn = true; - SendWorldInfo(Main.spawnTileX, Main.spawnTileY, false); - return false; + x = Main.rightWorld - 992; + } + if (x < 992) + { + x = 992; + } + if (y > Main.bottomWorld - 992) + { + y = Main.bottomWorld - 992; + } + if (y < 992) + { + y = 992; } -*/ - Spawn(-1, -1); - - SendWorldInfo(Main.spawnTileX, Main.spawnTileY, false); - - TPlayer.position.X = (float)(tilex * 16 + 8 - TPlayer.width /2); - TPlayer.position.Y = (float)(tiley * 16 - TPlayer.height); - //We need to send the tile data again to prevent clients from thinking they *really* destroyed blocks just now. - - SendTileSquare(tilex, tiley, 10); - + TPlayer.Teleport(new Vector2(x, y), style); + NetMessage.SendData((int)PacketTypes.Teleport, -1, -1, "", 0, TPlayer.whoAmi, x, y, style); return true; } + public void Heal(int damage = 400) + { + NetMessage.SendData((int)PacketTypes.PlayerHealOther, -1, -1, "", this.TPlayer.whoAmi, damage); + } + public void Spawn() { Spawn(TPlayer.SpawnX, TPlayer.SpawnY); @@ -594,7 +628,7 @@ public bool GiveItemCheck(int type, string name, int width, int height, int stac public virtual void GiveItem(int type, string name, int width, int height, int stack, int prefix = 0) { - int itemid = Item.NewItem((int) X, (int) Y, width, height, type, stack, true, prefix); + int itemid = Item.NewItem((int) X, (int) Y, width, height, type, stack, true, prefix, true); // This is for special pickaxe/hammers/swords etc Main.item[itemid].SetDefaults(name); @@ -604,8 +638,10 @@ public virtual void GiveItem(int type, string name, int width, int height, int s Main.item[itemid].stack = stack; Main.item[itemid].owner = Index; Main.item[itemid].prefix = (byte) prefix; - NetMessage.SendData((int) PacketTypes.ItemDrop, -1, -1, "", itemid, 0f, 0f, 0f); - NetMessage.SendData((int) PacketTypes.ItemOwner, -1, -1, "", itemid, 0f, 0f, 0f); + Main.item[itemid].noGrabDelay = 1; + Main.item[itemid].velocity = Main.player[this.Index].velocity; + NetMessage.SendData((int)PacketTypes.ItemDrop, -1, -1, "", itemid, 0f, 0f, 0f); + NetMessage.SendData((int)PacketTypes.ItemOwner, -1, -1, "", itemid, 0f, 0f, 0f); } public virtual void SendInfoMessage(string msg) @@ -876,6 +912,12 @@ public void SetBloodMoon(bool bloodMoon) Main.bloodMoon = bloodMoon; SetTime(false, 0); } + + public void SetEclipse(bool Eclipse) + { + Main.eclipse = Eclipse; + SetTime(true, 150); + } public void SetTime(bool dayTime, double time) { @@ -910,12 +952,12 @@ public void StrikeNPC(int npcid, int damage, float knockBack, int hitDirection) NetMessage.SendData((int) PacketTypes.NpcStrike, -1, -1, "", npcid, damage, knockBack, hitDirection); } - public void RevertTiles(Dictionary tiles) + public void RevertTiles(Dictionary tiles) { // Update Main.Tile first so that when tile sqaure is sent it is correct - foreach (KeyValuePair entry in tiles) + foreach (KeyValuePair entry in tiles) { - Main.tile[(int) entry.Key.X, (int) entry.Key.Y].Data = entry.Value; + Main.tile[(int) entry.Key.X, (int) entry.Key.Y] = entry.Value; } // Send all players updated tile sqaures foreach (Vector2 coords in tiles.Keys) @@ -977,9 +1019,10 @@ public void CopyInventory(TSPlayer player) this.maxHealth = player.TPlayer.statLifeMax; Item[] inventory = player.TPlayer.inventory; Item[] armor = player.TPlayer.armor; + Item[] dye = player.TPlayer.dye; for (int i = 0; i < NetItem.maxNetInventory; i++) { - if (i < 49) + if (i < NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots)) { if (player.TPlayer.inventory[i] != null) { @@ -1001,11 +1044,35 @@ public void CopyInventory(TSPlayer player) this.inventory[i].prefix = 0; } } + else if (i < NetItem.maxNetInventory - NetItem.dyeSlots) + { + var index = i - (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots)); + if (player.TPlayer.armor[index] != null) + { + this.inventory[i].netID = armor[index].netID; + } + else + { + this.inventory[i].netID = 0; + } + + if (this.inventory[i].netID != 0) + { + this.inventory[i].stack = armor[index].stack; + this.inventory[i].prefix = armor[index].prefix; + } + else + { + this.inventory[i].stack = 0; + this.inventory[i].prefix = 0; + } + } else { - if (player.TPlayer.armor[i - 48] != null) + var index = i - (NetItem.maxNetInventory - NetItem.dyeSlots); + if (player.TPlayer.dye[index] != null) { - this.inventory[i].netID = armor[i - 48].netID; + this.inventory[i].netID = armor[index].netID; } else { @@ -1014,8 +1081,8 @@ public void CopyInventory(TSPlayer player) if (this.inventory[i].netID != 0) { - this.inventory[i].stack = armor[i - 48].stack; - this.inventory[i].prefix = armor[i - 48].prefix; + this.inventory[i].stack = armor[index].stack; + this.inventory[i].prefix = armor[index].prefix; } else { @@ -1029,11 +1096,13 @@ public void CopyInventory(TSPlayer player) public class NetItem { - public static int maxNetInventory = 59; + public static readonly int maxNetInventory = 73; + public static readonly int armorSlots = 11; + public static readonly int dyeSlots = 3; public int netID; public int stack; public int prefix; - + public static string ToString(NetItem[] inventory) { string inventoryString = ""; diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index b7ae63627..a66b4309a 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -27,19 +27,19 @@ You should have received a copy of the GNU General Public License using System.Linq; using System.Net; using System.Reflection; -using Hooks; using MaxMind; using Mono.Data.Sqlite; using MySql.Data.MySqlClient; using Newtonsoft.Json; using Rests; using Terraria; +using TerrariaApi.Server; using TShockAPI.DB; using TShockAPI.Net; namespace TShockAPI { - [APIVersion(1, 13)] + [ApiVersion(1, 14)] public class TShock : TerrariaPlugin { public static readonly Version VersionNum = Assembly.GetExecutingAssembly().GetName().Version; @@ -231,25 +231,25 @@ public override void Initialize() Log.ConsoleInfo(string.Format("|> Version {0} ({1}) now running.", Version, VersionCodename)); - GameHooks.PostInitialize += OnPostInit; - GameHooks.Update += OnUpdate; - GameHooks.HardUpdate += OnHardUpdate; - GameHooks.StatueSpawn += OnStatueSpawn; - ServerHooks.Connect += OnConnect; - ServerHooks.Join += OnJoin; - ServerHooks.Leave += OnLeave; - ServerHooks.Chat += OnChat; - ServerHooks.Command += ServerHooks_OnCommand; - NetHooks.GetData += OnGetData; - NetHooks.SendData += NetHooks_SendData; - NetHooks.GreetPlayer += OnGreetPlayer; - NpcHooks.StrikeNpc += NpcHooks_OnStrikeNpc; - NpcHooks.SetDefaultsInt += OnNpcSetDefaults; - ProjectileHooks.SetDefaults += OnProjectileSetDefaults; - WorldHooks.StartHardMode += OnStartHardMode; - WorldHooks.SaveWorld += SaveManager.Instance.OnSaveWorld; - WorldHooks.ChristmasCheck += OnXmasCheck; - NetHooks.NameCollision += NetHooks_NameCollision; + ServerApi.Hooks.GamePostInitialize.Register(this, OnPostInit); + ServerApi.Hooks.GameUpdate.Register(this, OnUpdate); + ServerApi.Hooks.GameHardmodeTileUpdate.Register(this, OnHardUpdate); + ServerApi.Hooks.GameStatueSpawn.Register(this, OnStatueSpawn); + ServerApi.Hooks.ServerConnect.Register(this, OnConnect); + ServerApi.Hooks.ServerJoin.Register(this, OnJoin); + ServerApi.Hooks.ServerLeave.Register(this, OnLeave); + ServerApi.Hooks.ServerChat.Register(this, OnChat); + ServerApi.Hooks.ServerCommand.Register(this, ServerHooks_OnCommand); + ServerApi.Hooks.NetGetData.Register(this, OnGetData); + ServerApi.Hooks.NetSendData.Register(this, NetHooks_SendData); + ServerApi.Hooks.NetGreetPlayer.Register(this, OnGreetPlayer); + ServerApi.Hooks.NpcStrike.Register(this, NpcHooks_OnStrikeNpc); + ServerApi.Hooks.NpcSetDefaultsInt.Register(this, OnNpcSetDefaults); + ServerApi.Hooks.ProjectileSetDefaults.Register(this, OnProjectileSetDefaults); + ServerApi.Hooks.WorldStartHardMode.Register(this, OnStartHardMode); + ServerApi.Hooks.WorldSave.Register(this, SaveManager.Instance.OnSaveWorld); + ServerApi.Hooks.WorldChristmasCheck.Register(this, OnXmasCheck); + ServerApi.Hooks.NetNameCollision.Register(this, NetHooks_NameCollision); TShockAPI.Hooks.PlayerHooks.PlayerPostLogin += OnPlayerLogin; GetDataHandlers.InitGetDataHandler(); @@ -260,7 +260,7 @@ public override void Initialize() RestApi.Start(); if (Config.BufferPackets) - PacketBuffer = new PacketBufferer(); + PacketBuffer = new PacketBufferer(this); Log.ConsoleInfo("AutoSave " + (Config.AutoSave ? "Enabled" : "Disabled")); Log.ConsoleInfo("Backups " + (Backups.Interval > 0 ? "Enabled" : "Disabled")); @@ -306,25 +306,26 @@ protected override void Dispose(bool disposing) } SaveManager.Instance.Dispose(); - GameHooks.PostInitialize -= OnPostInit; - GameHooks.Update -= OnUpdate; - GameHooks.HardUpdate -= OnHardUpdate; - GameHooks.StatueSpawn -= OnStatueSpawn; - ServerHooks.Connect -= OnConnect; - ServerHooks.Join -= OnJoin; - ServerHooks.Leave -= OnLeave; - ServerHooks.Chat -= OnChat; - ServerHooks.Command -= ServerHooks_OnCommand; - NetHooks.GetData -= OnGetData; - NetHooks.SendData -= NetHooks_SendData; - NetHooks.GreetPlayer -= OnGreetPlayer; - NpcHooks.StrikeNpc -= NpcHooks_OnStrikeNpc; - NpcHooks.SetDefaultsInt -= OnNpcSetDefaults; - ProjectileHooks.SetDefaults -= OnProjectileSetDefaults; - WorldHooks.StartHardMode -= OnStartHardMode; - WorldHooks.SaveWorld -= SaveManager.Instance.OnSaveWorld; - WorldHooks.ChristmasCheck -= OnXmasCheck; - NetHooks.NameCollision -= NetHooks_NameCollision; + + ServerApi.Hooks.GamePostInitialize.Deregister(this, OnPostInit); + ServerApi.Hooks.GameUpdate.Deregister(this, OnUpdate); + ServerApi.Hooks.GameHardmodeTileUpdate.Deregister(this, OnHardUpdate); + ServerApi.Hooks.GameStatueSpawn.Deregister(this, OnStatueSpawn); + ServerApi.Hooks.ServerConnect.Deregister(this, OnConnect); + ServerApi.Hooks.ServerJoin.Deregister(this, OnJoin); + ServerApi.Hooks.ServerLeave.Deregister(this, OnLeave); + ServerApi.Hooks.ServerChat.Deregister(this, OnChat); + ServerApi.Hooks.ServerCommand.Deregister(this, ServerHooks_OnCommand); + ServerApi.Hooks.NetGetData.Deregister(this, OnGetData); + ServerApi.Hooks.NetSendData.Deregister(this, NetHooks_SendData); + ServerApi.Hooks.NetGreetPlayer.Deregister(this, OnGreetPlayer); + ServerApi.Hooks.NpcStrike.Deregister(this, NpcHooks_OnStrikeNpc); + ServerApi.Hooks.NpcSetDefaultsInt.Deregister(this, OnNpcSetDefaults); + ServerApi.Hooks.ProjectileSetDefaults.Deregister(this, OnProjectileSetDefaults); + ServerApi.Hooks.WorldStartHardMode.Deregister(this, OnStartHardMode); + ServerApi.Hooks.WorldSave.Deregister(this, SaveManager.Instance.OnSaveWorld); + ServerApi.Hooks.WorldChristmasCheck.Deregister(this, OnXmasCheck); + ServerApi.Hooks.NetNameCollision.Deregister(this, NetHooks_NameCollision); TShockAPI.Hooks.PlayerHooks.PlayerPostLogin -= OnPlayerLogin; if (File.Exists(Path.Combine(SavePath, "tshock.pid"))) @@ -362,34 +363,34 @@ private void OnPlayerLogin(Hooks.PlayerPostLoginEventArgs args) Users.UpdateLogin(u); } - private void NetHooks_NameCollision(int who, string name, HandledEventArgs e) + private void NetHooks_NameCollision(NameCollisionEventArgs args) { - string ip = TShock.Utils.GetRealIP(Netplay.serverSock[who].tcpClient.Client.RemoteEndPoint.ToString()); + string ip = TShock.Utils.GetRealIP(Netplay.serverSock[args.Who].tcpClient.Client.RemoteEndPoint.ToString()); foreach (TSPlayer ply in TShock.Players) { if (ply == null) { continue; } - if (ply.Name == name && ply.Index != who) + if (ply.Name == args.Name && ply.Index != args.Who) { if (ply.IP == ip) { if (ply.State < 2) { Utils.ForceKick(ply, "Name collision and this client has no world data.", true, false); - e.Handled = true; + args.Handled = true; return; } else { - e.Handled = false; + args.Handled = false; return; } } } } - e.Handled = false; + args.Handled = false; return; } @@ -533,7 +534,7 @@ public static void HandleCommandLinePostConfigLoad(string[] parms) public static int AuthToken = -1; - private void OnPostInit() + private void OnPostInit(EventArgs args) { SetConsoleTitle(); if (!File.Exists(Path.Combine(SavePath, "auth.lck")) && !File.Exists(Path.Combine(SavePath, "authcode.txt"))) @@ -597,7 +598,7 @@ private void FixChestStacks() private DateTime LastCheck = DateTime.UtcNow; private DateTime LastSave = DateTime.UtcNow; - private void OnUpdate() + private void OnUpdate(EventArgs args) { UpdateManager.UpdateProcedureCheck(); if (Backups.IsBackupTime) @@ -608,7 +609,7 @@ private void OnUpdate() OnSecondUpdate(); LastCheck = DateTime.UtcNow; } - + if ((DateTime.UtcNow - LastSave).TotalMinutes >= Config.ServerSideInventorySave) { foreach (TSPlayer player in Players) @@ -638,12 +639,11 @@ private void OnSecondUpdate() break; } } - int count = 0; + foreach (TSPlayer player in Players) { if (player != null && player.Active) { - count++; if (player.TilesDestroyed != null) { if (player.TileKillThreshold >= Config.TileKillThreshold) @@ -672,6 +672,10 @@ private void OnSecondUpdate() { player.TilePlaceThreshold = 0; } + + if (player.RecentFuse >0) + player.RecentFuse--; + if (player.TileLiquidThreshold >= Config.TileLiquidThreshold) { player.Disable("Reached TileLiquid threshold."); @@ -737,7 +741,7 @@ private void SetConsoleTitle() Config.MaxSlots, Netplay.serverListenIP, Netplay.serverPort, Version); } - private void OnHardUpdate( HardUpdateEventArgs args ) + private void OnHardUpdate(HardmodeTileUpdateEventArgs args) { if (args.Handled) return; @@ -767,14 +771,14 @@ private void OnStatueSpawn( StatueSpawnEventArgs args ) } } - private void OnConnect(int ply, HandledEventArgs handler) + private void OnConnect(ConnectEventArgs args) { - var player = new TSPlayer(ply); + var player = new TSPlayer(args.Who); if (Utils.ActivePlayers() + 1 > Config.MaxSlots + Config.ReservedSlots) { Utils.ForceKick(player, Config.ServerFullNoReservedReason, true, false); - handler.Handled = true; + args.Handled = true; return; } @@ -790,7 +794,7 @@ private void OnConnect(int ply, HandledEventArgs handler) DateTime exp; string duration = DateTime.TryParse(ban.Expiration, out exp) ? String.Format("until {0}", exp.ToString("G")) : "forever"; Utils.ForceKick(player, string.Format("You are banned {0}: {1}", duration, ban.Reason), true, false); - handler.Handled = true; + args.Handled = true; return; } } @@ -798,7 +802,7 @@ private void OnConnect(int ply, HandledEventArgs handler) if (!FileTools.OnWhitelist(player.IP)) { Utils.ForceKick(player, Config.WhitelistKickReason, true, false); - handler.Handled = true; + args.Handled = true; return; } @@ -811,20 +815,20 @@ private void OnConnect(int ply, HandledEventArgs handler) if (Config.KickProxyUsers) { Utils.ForceKick(player, "Proxies are not allowed.", true, false); - handler.Handled = true; + args.Handled = true; return; } } } - Players[ply] = player; + Players[args.Who] = player; } - private void OnJoin(int ply, HandledEventArgs handler) + private void OnJoin(JoinEventArgs args) { - var player = Players[ply]; + var player = Players[args.Who]; if (player == null) { - handler.Handled = true; + args.Handled = true; return; } @@ -848,16 +852,16 @@ private void OnJoin(int ply, HandledEventArgs handler) DateTime exp; string duration = DateTime.TryParse(ban.Expiration, out exp) ? String.Format("until {0}", exp.ToString("G")) : "forever"; Utils.ForceKick(player, string.Format("You are banned {0}: {1}", duration, ban.Reason), true, false); - handler.Handled = true; + args.Handled = true; } } } - private void OnLeave(int ply) + private void OnLeave(LeaveEventArgs args) { - var tsplr = Players[ply]; - Players[ply] = null; + var tsplr = Players[args.Who]; + Players[args.Who] = null; if (tsplr != null && tsplr.ReceivedInfo) { @@ -880,15 +884,15 @@ private void OnLeave(int ply) } } - private void OnChat(messageBuffer msg, int ply, string text, HandledEventArgs e) + private void OnChat(ServerChatEventArgs args) { - if (e.Handled) + if (args.Handled) return; - var tsplr = Players[msg.whoAmI]; + var tsplr = Players[args.Who]; if (tsplr == null) { - e.Handled = true; + args.Handled = true; return; } @@ -898,11 +902,11 @@ private void OnChat(messageBuffer msg, int ply, string text, HandledEventArgs e) return; }*/ - if (text.StartsWith("/")) + if (args.Text.StartsWith("/")) { try { - e.Handled = Commands.HandleCommand(tsplr, text); + args.Handled = Commands.HandleCommand(tsplr, args.Text); } catch (Exception ex) { @@ -913,18 +917,18 @@ private void OnChat(messageBuffer msg, int ply, string text, HandledEventArgs e) else if (!tsplr.mute && !TShock.Config.EnableChatAboveHeads) { Utils.Broadcast( - String.Format(Config.ChatFormat, tsplr.Group.Name, tsplr.Group.Prefix, tsplr.Name, tsplr.Group.Suffix, text), + String.Format(Config.ChatFormat, tsplr.Group.Name, tsplr.Group.Prefix, tsplr.Name, tsplr.Group.Suffix, args.Text), tsplr.Group.R, tsplr.Group.G, tsplr.Group.B); - e.Handled = true; + args.Handled = true; } else if (!tsplr.mute && TShock.Config.EnableChatAboveHeads) { - Utils.Broadcast(ply, String.Format(Config.ChatAboveHeadsFormat, tsplr.Group.Name, tsplr.Group.Prefix, tsplr.Name, tsplr.Group.Suffix, text), tsplr.Group.R, tsplr.Group.G, tsplr.Group.B); - e.Handled = true; + Utils.Broadcast(args.Who, String.Format(Config.ChatAboveHeadsFormat, tsplr.Group.Name, tsplr.Group.Prefix, tsplr.Name, tsplr.Group.Suffix, args.Text), tsplr.Group.R, tsplr.Group.G, tsplr.Group.B); + args.Handled = true; } else if (tsplr.mute) { tsplr.SendErrorMessage("You are muted!"); - e.Handled = true; + args.Handled = true; } } @@ -933,9 +937,9 @@ private void OnChat(messageBuffer msg, int ply, string text, HandledEventArgs e) /// /// /// - private void ServerHooks_OnCommand(string text, HandledEventArgs e) + private void ServerHooks_OnCommand(CommandEventArgs args) { - if (e.Handled) + if (args.Handled) return; // Damn you ThreadStatic and Redigit @@ -948,7 +952,7 @@ private void ServerHooks_OnCommand(string text, HandledEventArgs e) WorldGen.genRand = new Random(); } - if (text.StartsWith("playing") || text.StartsWith("/playing")) + if (args.Command.StartsWith("playing") || args.Command.StartsWith("/playing")) { int count = 0; foreach (TSPlayer player in Players) @@ -962,20 +966,20 @@ private void ServerHooks_OnCommand(string text, HandledEventArgs e) } TSPlayer.Server.SendInfoMessage(string.Format("{0} players connected.", count)); } - else if (text == "autosave") + else if (args.Command == "autosave") { Main.autoSave = Config.AutoSave = !Config.AutoSave; Log.ConsoleInfo("AutoSave " + (Config.AutoSave ? "Enabled" : "Disabled")); } - else if (text.StartsWith("/")) + else if (args.Command.StartsWith("/")) { - Commands.HandleCommand(TSPlayer.Server, text); + Commands.HandleCommand(TSPlayer.Server, args.Command); } else { - Commands.HandleCommand(TSPlayer.Server, "/" + text); + Commands.HandleCommand(TSPlayer.Server, "/" + args.Command); } - e.Handled = true; + args.Handled = true; } private void OnGetData(GetDataEventArgs e) @@ -1027,12 +1031,12 @@ private void OnGetData(GetDataEventArgs e) } } - private void OnGreetPlayer(int who, HandledEventArgs e) + private void OnGreetPlayer(GreetPlayerEventArgs args) { - var player = Players[who]; + var player = Players[args.Who]; if (player == null) { - e.Handled = true; + args.Handled = true; return; } player.LoginMS= DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; @@ -1072,10 +1076,13 @@ private void OnGreetPlayer(int who, HandledEventArgs e) if (RememberedPos.GetLeavePos(player.Name, player.IP) != Vector2.Zero){ var pos = RememberedPos.GetLeavePos(player.Name, player.IP); - player.Teleport((int) pos.X, (int) pos.Y + 3); + player.Teleport(pos.X*16, pos.Y*16 + 48); }} - e.Handled = true; + Item i = new Item(); + i.SetDefaults("Confetti Gun"); + player.GiveItem(i.type, i.name, i.width, i.headSlot, 10); + args.Handled = true; } private void NpcHooks_OnStrikeNpc(NpcStrikeEventArgs e) @@ -1152,7 +1159,7 @@ public static bool SendBytesBufferless(ServerSock client, byte[] bytes) private void NetHooks_SendData(SendDataEventArgs e) { - if (e.MsgID == PacketTypes.Disconnect) + if (e.MsgId == PacketTypes.Disconnect) { Action senddisconnect = (sock, str) => { @@ -1182,7 +1189,7 @@ private void NetHooks_SendData(SendDataEventArgs e) } e.Handled = true; } - if (e.MsgID == PacketTypes.WorldInfo) + if (e.MsgId == PacketTypes.WorldInfo) { if (e.remoteClient == -1) return; var player = Players[e.remoteClient]; @@ -1193,26 +1200,62 @@ private void NetHooks_SendData(SendDataEventArgs e) { var msg = new WorldInfoMsg { - Time = (int)Main.time, - DayTime = Main.dayTime, - MoonPhase = (byte)Main.moonPhase, - BloodMoon = Main.bloodMoon, - MaxTilesX = Main.maxTilesX, - MaxTilesY = Main.maxTilesY, - SpawnX = Main.spawnTileX, - SpawnY = Main.spawnTileY, - WorldSurface = (int)Main.worldSurface, - RockLayer = (int)Main.rockLayer, - WorldID = Main.worldID, - WorldFlags = - (WorldGen.shadowOrbSmashed ? WorldInfoFlag.OrbSmashed : WorldInfoFlag.None) | - (NPC.downedBoss1 ? WorldInfoFlag.DownedBoss1 : WorldInfoFlag.None) | - (NPC.downedBoss2 ? WorldInfoFlag.DownedBoss2 : WorldInfoFlag.None) | - (NPC.downedBoss3 ? WorldInfoFlag.DownedBoss3 : WorldInfoFlag.None) | - (Main.hardMode ? WorldInfoFlag.HardMode : WorldInfoFlag.None) | - (NPC.downedClown ? WorldInfoFlag.DownedClown : WorldInfoFlag.None), - WorldName = Config.ServerName - }; + Time = (int) Main.time, + DayTime = Main.dayTime, + MoonPhase = (byte) Main.moonPhase, + BloodMoon = Main.bloodMoon, + MaxTilesX = Main.maxTilesX, + MaxTilesY = Main.maxTilesY, + SpawnX = Main.spawnTileX, + SpawnY = Main.spawnTileY, + WorldSurface = (int) Main.worldSurface, + RockLayer = (int) Main.rockLayer, + //Sending a fake world id causes the client to not be able to find a stored spawnx/y. + //This fixes the bed spawn point bug. With a fake world id it wont be able to find the bed spawn. + WorldID = Main.worldID, + MoonType = (byte)Main.moonType, + TreeX0 = Main.treeX[0], + TreeX1 = Main.treeX[1], + TreeX2 = Main.treeX[2], + TreeStyle0 = (byte)Main.treeStyle[0], + TreeStyle1 = (byte)Main.treeStyle[1], + TreeStyle2 = (byte)Main.treeStyle[2], + TreeStyle3 = (byte)Main.treeStyle[3], + CaveBackX0 = Main.caveBackX[0], + CaveBackX1 = Main.caveBackX[1], + CaveBackX2 = Main.caveBackX[2], + CaveBackStyle0 = (byte)Main.caveBackStyle[0], + CaveBackStyle1 = (byte)Main.caveBackStyle[1], + CaveBackStyle2 = (byte)Main.caveBackStyle[2], + CaveBackStyle3 = (byte)Main.caveBackStyle[3], + SetBG0 = (byte)WorldGen.treeBG, + SetBG1 = (byte)WorldGen.corruptBG, + SetBG2 = (byte)WorldGen.jungleBG, + SetBG3 = (byte)WorldGen.snowBG, + SetBG4 = (byte)WorldGen.hallowBG, + SetBG5 = (byte)WorldGen.crimsonBG, + SetBG6 = (byte)WorldGen.desertBG, + SetBG7 = (byte)WorldGen.oceanBG, + IceBackStyle = (byte)Main.iceBackStyle, + JungleBackStyle = (byte)Main.jungleBackStyle, + HellBackStyle = (byte)Main.hellBackStyle, + WindSpeed = Main.windSpeed, + NumberOfClouds = (byte)Main.numClouds, + BossFlags = (WorldGen.shadowOrbSmashed ? BossFlags.OrbSmashed : BossFlags.None) | + (NPC.downedBoss1 ? BossFlags.DownedBoss1 : BossFlags.None) | + (NPC.downedBoss2 ? BossFlags.DownedBoss2 : BossFlags.None) | + (NPC.downedBoss3 ? BossFlags.DownedBoss3 : BossFlags.None) | + (Main.hardMode ? BossFlags.HardMode : BossFlags.None) | + (NPC.downedClown ? BossFlags.DownedClown : BossFlags.None), + BossFlags2 = (NPC.downedMechBoss1 ? BossFlags2.DownedMechBoss1 : BossFlags2.None) | + (NPC.downedMechBoss2 ? BossFlags2.DownedMechBoss2 : BossFlags2.None) | + (NPC.downedMechBoss3 ? BossFlags2.DownedMechBoss3 : BossFlags2.None) | + (NPC.downedMechBossAny ? BossFlags2.DownedMechBossAny : BossFlags2.None) | + (Main.cloudBGActive == 1f ? BossFlags2.CloudBg : BossFlags2.None) | + (WorldGen.crimson ? BossFlags2.Crimson : BossFlags2.None), + Rain = Main.maxRaining, + WorldName = TShock.Config.UseServerName ? TShock.Config.ServerName : Main.worldName + }; msg.PackFull(ms); player.SendRawData(ms.ToArray()); } @@ -1332,11 +1375,11 @@ public static bool CheckRangePermission(TSPlayer player, int x, int y, int range return false; } - public static bool CheckTilePermission( TSPlayer player, int tileX, int tileY, byte tileType, byte actionType ) + public static bool CheckTilePermission( TSPlayer player, int tileX, int tileY, byte tileType, GetDataHandlers.EditAction actionType ) { if (!player.Group.HasPermission(Permissions.canbuild)) { - if (TShock.Config.AllowIce && actionType != 1) + if (TShock.Config.AllowIce && actionType != GetDataHandlers.EditAction.PlaceTile) { foreach (Point p in player.IceTiles) @@ -1356,7 +1399,7 @@ public static bool CheckTilePermission( TSPlayer player, int tileX, int tileY, b return true; } - if (TShock.Config.AllowIce && actionType == 1 && tileType == 127) + if (TShock.Config.AllowIce && actionType == GetDataHandlers.EditAction.PlaceTile && tileType == 127) { player.IceTiles.Add(new Point(tileX, tileY)); return false; @@ -1387,12 +1430,12 @@ public static bool CheckTilePermission( TSPlayer player, int tileX, int tileY, b { if (!player.Group.HasPermission(Permissions.editspawn)) { - if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000){ - player.SendMessage("The world is protected from changes.", Color.Red); - player.WPm=DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - -} - return true; + if (((DateTime.Now.Ticks/TimeSpan.TicksPerMillisecond) - player.WPm) > 2000) + { + player.SendMessage("The world is protected from changes.", Color.Red); + player.WPm = DateTime.Now.Ticks/TimeSpan.TicksPerMillisecond; + } + return true; } } if (Config.SpawnProtection) @@ -1498,9 +1541,10 @@ public static bool HackedInventory(TSPlayer player) Item[] inventory = player.TPlayer.inventory; Item[] armor = player.TPlayer.armor; + Item[] dye = player.TPlayer.dye; for (int i = 0; i < NetItem.maxNetInventory; i++) { - if (i < 49) + if (i < NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots)) { Item item = new Item(); if (inventory[i] != null && inventory[i].netID != 0) @@ -1517,15 +1561,16 @@ public static bool HackedInventory(TSPlayer player) } } } - else + else if(i < (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots))) { Item item = new Item(); - if (armor[i - 48] != null && armor[i - 48].netID != 0) + var index = i - (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots)); + if (armor[index] != null && armor[index].netID != 0) { - item.netDefaults(armor[i - 48].netID); - item.Prefix(armor[i - 48].prefix); + item.netDefaults(armor[index].netID); + item.Prefix(armor[index].prefix); item.AffixName(); - if (armor[i - 48].stack > item.maxStack) + if (armor[index].stack > item.maxStack) { check = true; player.SendMessage( @@ -1534,6 +1579,24 @@ public static bool HackedInventory(TSPlayer player) } } } + else if (i < (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots))) + { + Item item = new Item(); + var index = i - (NetItem.maxNetInventory - NetItem.dyeSlots); + if (dye[index] != null && dye[index].netID != 0) + { + item.netDefaults(dye[index].netID); + item.Prefix(dye[index].prefix); + item.AffixName(); + if (dye[index].stack > item.maxStack) + { + check = true; + player.SendMessage( + String.Format("Stack cheat detected. Remove dye {0} ({1}) and then rejoin", item.name, dye[index].stack), + Color.Cyan); + } + } + } } return check; @@ -1553,9 +1616,10 @@ public static bool CheckInventory(TSPlayer player) Item[] inventory = player.TPlayer.inventory; Item[] armor = player.TPlayer.armor; + Item[] dye = player.TPlayer.dye; for (int i = 0; i < NetItem.maxNetInventory; i++) { - if (i < 49) + if (i < NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots)) { Item item = new Item(); Item serverItem = new Item(); @@ -1592,34 +1656,35 @@ public static bool CheckInventory(TSPlayer player) } } } - else + else if(i < (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots))) { Item item = new Item(); Item serverItem = new Item(); - if (armor[i - 48] != null && armor[i - 48].netID != 0) + var index = i - (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots)); + if (armor[index] != null && armor[index].netID != 0) { - if (playerData.inventory[i].netID != armor[i - 48].netID) + if (playerData.inventory[i].netID != armor[index].netID) { - item.netDefaults(armor[i - 48].netID); - item.Prefix(armor[i - 48].prefix); + item.netDefaults(armor[index].netID); + item.Prefix(armor[index].prefix); item.AffixName(); player.SendMessage(player.IgnoreActionsForInventory = "Your armor (" + item.name + ") needs to be deleted.", Color.Cyan); check = false; } - else if (playerData.inventory[i].prefix != armor[i - 48].prefix) + else if (playerData.inventory[i].prefix != armor[index].prefix) { - item.netDefaults(armor[i - 48].netID); - item.Prefix(armor[i - 48].prefix); + item.netDefaults(armor[index].netID); + item.Prefix(armor[index].prefix); item.AffixName(); player.SendMessage(player.IgnoreActionsForInventory = "Your armor (" + item.name + ") needs to be deleted.", Color.Cyan); check = false; } - else if (armor[i - 48].stack > playerData.inventory[i].stack) + else if (armor[index].stack > playerData.inventory[i].stack) { - item.netDefaults(armor[i - 48].netID); - item.Prefix(armor[i - 48].prefix); + item.netDefaults(armor[index].netID); + item.Prefix(armor[index].prefix); item.AffixName(); player.SendMessage( player.IgnoreActionsForInventory = @@ -1629,6 +1694,44 @@ public static bool CheckInventory(TSPlayer player) } } } + else if(i < (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots))) + { + Item item = new Item(); + Item serverItem = new Item(); + var index = i - (NetItem.maxNetInventory - NetItem.dyeSlots); + if (dye[index] != null && dye[index].netID != 0) + { + if (playerData.inventory[i].netID != dye[index].netID) + { + item.netDefaults(dye[index].netID); + item.Prefix(dye[index].prefix); + item.AffixName(); + player.SendMessage(player.IgnoreActionsForInventory = "Your dye (" + item.name + ") needs to be deleted.", + Color.Cyan); + check = false; + } + else if (playerData.inventory[i].prefix != dye[index].prefix) + { + item.netDefaults(dye[index].netID); + item.Prefix(dye[index].prefix); + item.AffixName(); + player.SendMessage(player.IgnoreActionsForInventory = "Your dye (" + item.name + ") needs to be deleted.", + Color.Cyan); + check = false; + } + else if (dye[index].stack > playerData.inventory[i].stack) + { + item.netDefaults(dye[index].netID); + item.Prefix(dye[index].prefix); + item.AffixName(); + player.SendMessage( + player.IgnoreActionsForInventory = + "Your dye (" + item.name + ") (" + inventory[i].stack + ") needs to have its stack size decreased to (" + + playerData.inventory[i].stack + ").", Color.Cyan); + check = false; + } + } + } } return check; @@ -1636,20 +1739,7 @@ public static bool CheckInventory(TSPlayer player) public static bool CheckIgnores(TSPlayer player) { - bool check = false; - if (Config.PvPMode == "always" && !player.TPlayer.hostile) - check = true; - if (player.IgnoreActionsForInventory != "none") - check = true; - if (player.IgnoreActionsForCheating != "none") - check = true; - if (player.IgnoreActionsForDisabledArmor != "none") - check = true; - if (player.IgnoreActionsForClearingTrashCan) - check = true; - if (!player.IsLoggedIn && Config.RequireLogin) - check = true; - return check; + return Config.PvPMode == "always" && !player.TPlayer.hostile || player.IgnoreActionsForInventory != "none" || player.IgnoreActionsForCheating != "none" || player.IgnoreActionsForDisabledArmor != "none" || player.IgnoreActionsForClearingTrashCan || !player.IsLoggedIn && Config.RequireLogin;; } public void OnConfigRead(ConfigFile file) diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj index 880e7c769..f795ca39f 100644 --- a/TShockAPI/TShockAPI.csproj +++ b/TShockAPI/TShockAPI.csproj @@ -38,6 +38,7 @@ 4 true bin\Debug\TShockAPI.XML + x86 pdbonly @@ -67,7 +68,7 @@ - + False .exe ..\TerrariaServerBins\TerrariaServer.exe @@ -79,9 +80,6 @@ - - - diff --git a/TShockAPI/Utils.cs b/TShockAPI/Utils.cs index 4e3fdf1d4..351d5e77f 100644 --- a/TShockAPI/Utils.cs +++ b/TShockAPI/Utils.cs @@ -329,7 +329,7 @@ public bool TilePlacementValid(int tileX, int tileY) /// The state of the tile private bool TileClear(int tileX, int tileY) { - return !Main.tile[tileX, tileY].active; + return !Main.tile[tileX, tileY].active(); } /// @@ -371,7 +371,7 @@ public List GetItemByName(string name) var found = new List(); Item item = new Item(); string nameLower = name.ToLower(); - for (int i = -24; i < Main.maxItemTypes; i++) + for (int i = -48; i < Main.maxItemTypes; i++) { item.netDefaults(i); if (item.name.ToLower() == nameLower) diff --git a/TerrariaServerBins/TerrariaServer.exe b/TerrariaServerBins/TerrariaServer.exe index c9081b0e7..841efd5f4 100644 Binary files a/TerrariaServerBins/TerrariaServer.exe and b/TerrariaServerBins/TerrariaServer.exe differ