From 3e9aee3414f2ffe767217f0a0ec8ef6190b3439d Mon Sep 17 00:00:00 2001 From: MarioE Date: Wed, 30 Oct 2013 22:34:09 -0400 Subject: [PATCH] Begin Raptor compatibility --- TShockAPI/Commands.cs | 37 ++++--- TShockAPI/DB/RegionManager.cs | 45 +++++++++ TShockAPI/DB/WarpsManager.cs | 68 +++++++++---- TShockAPI/GetDataHandlers.cs | 75 +++++++++++++- TShockAPI/Hooks/PlayerHooks.cs | 2 +- TShockAPI/RaptorPacketTypes.cs | 38 +++++++ TShockAPI/TSPlayer.cs | 179 +++++++++++++++++++++++++++++++++ TShockAPI/TShock.cs | 30 ++++-- TShockAPI/TShockAPI.csproj | 3 +- 9 files changed, 431 insertions(+), 46 deletions(-) create mode 100644 TShockAPI/RaptorPacketTypes.cs diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index 673dffd2..352b7d34 100755 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -3017,6 +3017,12 @@ namespace TShockAPI args.Player.TempPoints[0] = Point.Zero; args.Player.TempPoints[1] = Point.Zero; args.Player.SendMessage("Set region " + regionName, Color.Yellow); + + foreach (TSPlayer tsplr in TShock.Players) + { + if (tsplr.IsRaptor && tsplr.Group.HasPermission(Permissions.manageregion)) + tsplr.SendRaptorRegion(TShock.Regions.GetRegionByName(regionName)); + } } else { @@ -3064,19 +3070,26 @@ namespace TShockAPI { string regionName = String.Join(" ", args.Parameters.GetRange(1, args.Parameters.Count - 1)); if (TShock.Regions.DeleteRegion(regionName)) - args.Player.SendMessage("Deleted region " + regionName, Color.Yellow); + { + args.Player.SendInfoMessage("Deleted region \"{0}\".", regionName); + foreach (TSPlayer tsplr in TShock.Players) + { + if (tsplr.IsRaptor && tsplr.Group.HasPermission(Permissions.manageregion)) + tsplr.SendRaptorRegionDelete(TShock.Regions.GetRegionByName(regionName)); + } + } else - args.Player.SendMessage("Could not find specified region", Color.Red); + args.Player.SendErrorMessage("Could not find the specified region!"); } else - args.Player.SendMessage("Invalid syntax! Proper syntax: /region delete ", Color.Red); + args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /region delete "); break; } case "clear": { args.Player.TempPoints[0] = Point.Zero; args.Player.TempPoints[1] = Point.Zero; - args.Player.SendMessage("Cleared temp area", Color.Yellow); + args.Player.SendInfoMessage("Cleared temporary points."); args.Player.AwaitingTempPoint = 0; break; } @@ -3415,19 +3428,18 @@ namespace TShockAPI if (TShock.Regions.resizeRegion(args.Parameters[1], addAmount, direction)) { args.Player.SendMessage("Region Resized Successfully!", Color.Yellow); + foreach (TSPlayer tsplr in TShock.Players) + { + if (tsplr.IsRaptor && tsplr.Group.HasPermission(Permissions.manageregion)) + tsplr.SendRaptorRegion(TShock.Regions.GetRegionByName(args.Parameters[1])); + } TShock.Regions.ReloadAllRegions(); } else - { - args.Player.SendMessage("Invalid syntax! Proper syntax: /region resize ", - Color.Red); - } + args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /region resize "); } else - { - args.Player.SendMessage("Invalid syntax! Proper syntax: /region resize ", - Color.Red); - } + args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /region resize "); break; } case "tp": @@ -3452,7 +3464,6 @@ namespace TShockAPI } args.Player.Teleport(region.Area.Center.X * 16, region.Area.Center.Y * 16); - break; } case "help": diff --git a/TShockAPI/DB/RegionManager.cs b/TShockAPI/DB/RegionManager.cs index e01494ca..5fc97387 100644 --- a/TShockAPI/DB/RegionManager.cs +++ b/TShockAPI/DB/RegionManager.cs @@ -419,6 +419,51 @@ namespace TShockAPI.DB return false; } + /// + /// Sets the position of a region. + /// + /// The region name. + /// The X position. + /// The Y position. + /// The height. + /// The width. + /// Whether the operation succeeded. + public bool PositionRegion(string regionName, int x, int y, int width, int height) + { + try + { + if (database.Query("UPDATE Regions SET X1 = @0, Y1 = @1, width = @2, height = @3 WHERE RegionName = @4 AND WorldID = @5", + x, y, width, height, regionName, Main.worldID.ToString()) > 0) + return true; + } + catch (Exception ex) + { + Log.Error(ex.ToString()); + } + return false; + } + /// + /// Offsets a region. + /// + /// The region name. + /// The X offset. + /// The Y offset. + /// Whether the operation succeeded. + public bool OffsetRegion(string regionName, int x, int y) + { + try + { + if (database.Query("UPDATE Regions SET X1 = X1 + @0, Y1 = Y1 + @1 WHERE RegionName = @2 AND WorldID = @3", + x, y, regionName, Main.worldID.ToString()) > 0) + return true; + } + catch (Exception ex) + { + Log.Error(ex.ToString()); + } + return false; + } + /// /// Gets all the regions names from world /// diff --git a/TShockAPI/DB/WarpsManager.cs b/TShockAPI/DB/WarpsManager.cs index 9ece9591..bf66deb6 100644 --- a/TShockAPI/DB/WarpsManager.cs +++ b/TShockAPI/DB/WarpsManager.cs @@ -28,6 +28,10 @@ namespace TShockAPI.DB public class WarpManager { private IDbConnection database; + /// + /// The list of warps. + /// + public List Warps; [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")] public WarpManager(IDbConnection db) @@ -53,6 +57,7 @@ namespace TShockAPI.DB try { database.Query("INSERT INTO Warps (X, Y, WarpName, WorldID) VALUES (@0, @1, @2, @3);", x, y, name, worldid); + Warps.Add(new Warp(new Vector2(x, y), name, worldid, "0")); return true; } catch (Exception ex) @@ -67,6 +72,7 @@ namespace TShockAPI.DB try { database.Query("DELETE FROM Warps WHERE WarpName=@0 AND WorldID=@1", name, Main.worldID.ToString()); + Warps.RemoveAll(w => w.WarpName == name); return true; } catch (Exception ex) @@ -116,20 +122,11 @@ namespace TShockAPI.DB var warps = new List(); try { - using (var reader = database.QueryReader("SELECT * FROM Warps WHERE WorldID=@0", worldid)) + using (var reader = database.QueryReader("SELECT * FROM Warps WHERE Private = @0 AND WorldID = @1", + "0", worldid)) { while (reader.Read()) - { - try - { - if (reader.Get("Private") == "0" || reader.Get("Private") == null) - warps.Add(new Warp {WarpName = reader.Get("WarpName")}); - } - catch - { - warps.Add(new Warp {WarpName = reader.Get("WarpName")}); - } - } + warps.Add(new Warp {WarpName = reader.Get("WarpName")}); } } catch (Exception ex) @@ -140,25 +137,52 @@ namespace TShockAPI.DB } /// - /// Gets all the warps names from world + /// Sets the position of a warp. /// - /// World name to get warps from - /// List of warps with only their names - public bool HideWarp(string warp, bool state) + /// The warp name. + /// The X position. + /// The Y position. + /// Whether the operation suceeded. + public bool PositionWarp(string warpName, int x, int y) { try { - string query = "UPDATE Warps SET Private=@0 WHERE WarpName=@1 AND WorldID=@2"; - - database.Query(query, state ? "1" : "0", warp, Main.worldID.ToString()); - - return true; + if (database.Query("UPDATE Warps SET X = @0, Y = @1 WHERE WarpName = @2 AND WorldID = @3", + x, y, warpName, Main.worldID.ToString()) > 0) + { + Warps.Find(w => w.WarpName == warpName).WarpPos = new Vector2(x, y); + return true; + } } catch (Exception ex) { Log.Error(ex.ToString()); - return false; } + return false; + } + + /// + /// Sets the hidden state of a warp. + /// + /// The warp name. + /// The state. + /// Whether the operation suceeded. + public bool HideWarp(string warpName, bool state) + { + try + { + if (database.Query("UPDATE Warps SET Private = @0 WHERE WarpName = @1 AND WorldID = @2", + state ? "1" : "0", warpName, Main.worldID.ToString()) > 0) + { + Warps.Find(w => w.WarpName == warpName).Private = state ? "1" : "0"; + return true; + } + } + catch (Exception ex) + { + Log.Error(ex.ToString()); + } + return false; } } diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 9b90b858..056e3f9c 100755 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -1234,7 +1234,8 @@ namespace TShockAPI {PacketTypes.SpawnBossorInvasion, HandleSpawnBoss}, {PacketTypes.Teleport, HandleTeleport}, {PacketTypes.PaintTile, HandlePaintTile}, - {PacketTypes.PaintWall, HandlePaintWall} + {PacketTypes.PaintWall, HandlePaintWall}, + {PacketTypes.Placeholder, HandleRaptor} }; } @@ -3390,5 +3391,77 @@ namespace TShockAPI return true; } + + private static bool HandleRaptor(GetDataHandlerArgs args) + { + var type = (RaptorPacketTypes)args.Data.ReadInt8(); + + switch (type) + { + case RaptorPacketTypes.Acknowledge: + args.Player.IsRaptor = true; + return true; + case RaptorPacketTypes.Region: + if (args.Player.Group.HasPermission(Permissions.manageregion)) + { + int x = args.Data.ReadInt32(); + int y = args.Data.ReadInt32(); + int width = args.Data.ReadInt32(); + int height = args.Data.ReadInt32(); + string regionName = args.Data.ReadString(); + + if (TShock.Regions.GetRegionByName(regionName).Area == Rectangle.Empty) + { + TShock.Regions.AddRegion(x, y, width, height, regionName, args.Player.UserAccountName, Main.worldID.ToString()); + Log.Info("{0} added region \"{1}\".", args.Player.UserAccountName, regionName); + } + else + { + TShock.Regions.PositionRegion(regionName, x, y, width, height); + Log.Info("{0} moved region \"{1}\".", args.Player.UserAccountName, regionName); + } + } + return true; + case RaptorPacketTypes.RegionDelete: + if (args.Player.Group.HasPermission(Permissions.manageregion)) + { + string regionName = args.Data.ReadString(); + TShock.Regions.DeleteRegion(regionName); + Log.Info("{0} deleted region \"{1}\".", args.Player.UserAccountName, regionName); + } + return true; + case RaptorPacketTypes.Warp: + if (args.Player.Group.HasPermission(Permissions.managewarp)) + { + int x = (int)args.Data.ReadSingle(); + int y = (int)args.Data.ReadSingle(); + bool isHidden = args.Data.ReadBoolean(); + string warpName = args.Data.ReadString(); + + Warp warp = TShock.Warps.FindWarp(warpName); + if (warp.WarpPos == Vector2.Zero) + { + TShock.Warps.AddWarp(x, y, warpName, Main.worldID.ToString()); + Log.Info("{0} added warp \"{1}\".", args.Player.UserAccountName, warpName); + } + else + { + TShock.Warps.PositionWarp(warpName, x, y); + Log.Info("{0} moved warp \"{1}\".", args.Player.UserAccountName, warpName); + } + } + return true; + case RaptorPacketTypes.WarpDelete: + if (args.Player.Group.HasPermission(Permissions.managewarp)) + { + string warpName = args.Data.ReadString(); + TShock.Warps.RemoveWarp(warpName); + Log.Info("{0} deleted warp \"{1}\".", args.Player.UserAccountName, warpName); + } + return true; + default: + return true; + } + } } } diff --git a/TShockAPI/Hooks/PlayerHooks.cs b/TShockAPI/Hooks/PlayerHooks.cs index 047fca50..79db8a30 100644 --- a/TShockAPI/Hooks/PlayerHooks.cs +++ b/TShockAPI/Hooks/PlayerHooks.cs @@ -58,7 +58,7 @@ namespace TShockAPI.Hooks public static void OnPlayerPostLogin(TSPlayer ply) { - if(PlayerPostLogin == null) + if (PlayerPostLogin == null) { return; } diff --git a/TShockAPI/RaptorPacketTypes.cs b/TShockAPI/RaptorPacketTypes.cs new file mode 100644 index 00000000..81a6f125 --- /dev/null +++ b/TShockAPI/RaptorPacketTypes.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TShockAPI +{ + /// + /// Custom packet types for use with Raptor. + /// + public enum RaptorPacketTypes : byte + { + /// + /// The packet sent to the server to be acknowledged as a Raptor client. + /// + Acknowledge = 0, + /// + /// The packet sent to the client which dictates its permissions. + /// + Permissions, + /// + /// The packet sent which sets region info. + /// + Region, + /// + /// The packet sent to delete a region. + /// + RegionDelete, + /// + /// The packet sent which sets warp info. + /// + Warp, + /// + /// The packet sent to delete a warp. + /// + WarpDelete + } +} diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 15bb54ee..b78e9639 100755 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -20,8 +20,10 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Text; using System.Threading; using Terraria; +using TShockAPI.DB; using TShockAPI.Net; namespace TShockAPI @@ -38,6 +40,11 @@ namespace TShockAPI /// public static readonly TSPlayer All = new TSPlayer("All"); + /// + /// Gets whether the player is using Raptor. + /// + public bool IsRaptor { get; internal set; } + /// /// The amount of tiles that the player has killed in the last second. /// @@ -882,6 +889,178 @@ namespace TShockAPI return TShock.SendBytes(Netplay.serverSock[Index], data); } + /// + /// Sends Raptor permissions to the player. + /// + public void SendRaptorPermissions() + { + if (!IsRaptor) + return; + + lock (NetMessage.buffer[Index].writeBuffer) + { + int length = 0; + + using (var ms = new MemoryStream(NetMessage.buffer[Index].writeBuffer, true)) + { + using (var writer = new BinaryWriter(ms)) + { + writer.BaseStream.Position = 4; + + writer.Write((byte)PacketTypes.Placeholder); + writer.Write((byte)RaptorPacketTypes.Permissions); + + writer.Write(String.Join(",", Group.TotalPermissions.ToArray())); + + length = (int)writer.BaseStream.Position; + writer.BaseStream.Position = 0; + writer.Write(length - 4); + } + } + + TShock.PacketBuffer.SendBytes(Netplay.serverSock[Index], NetMessage.buffer[Index].writeBuffer, 0, length); + } + } + /// + /// Sends a region to the player. + /// The region. + /// + public void SendRaptorRegion(Region region) + { + if (!IsRaptor) + return; + + lock (NetMessage.buffer[Index].writeBuffer) + { + int length = 0; + + using (var ms = new MemoryStream(NetMessage.buffer[Index].writeBuffer, true)) + { + using (var writer = new BinaryWriter(ms)) + { + writer.BaseStream.Position = 4; + + writer.Write((byte)PacketTypes.Placeholder); + writer.Write((byte)RaptorPacketTypes.Region); + + writer.Write(region.Area.X); + writer.Write(region.Area.Y); + writer.Write(region.Area.Width); + writer.Write(region.Area.Height); + writer.Write(region.Name); + + length = (int)writer.BaseStream.Position; + writer.BaseStream.Position = 0; + writer.Write(length - 4); + } + } + + TShock.PacketBuffer.SendBytes(Netplay.serverSock[Index], NetMessage.buffer[Index].writeBuffer, 0, length); + } + } + /// + /// Sends a region deletion to the player. + /// The region. + /// + public void SendRaptorRegionDelete(Region region) + { + if (!IsRaptor) + return; + + lock (NetMessage.buffer[Index].writeBuffer) + { + int length = 0; + + using (var ms = new MemoryStream(NetMessage.buffer[Index].writeBuffer, true)) + { + using (var writer = new BinaryWriter(ms)) + { + writer.BaseStream.Position = 4; + + writer.Write((byte)PacketTypes.Placeholder); + writer.Write((byte)RaptorPacketTypes.RegionDelete); + + writer.Write(region.Name); + + length = (int)writer.BaseStream.Position; + writer.BaseStream.Position = 0; + writer.Write(length - 4); + } + } + + TShock.PacketBuffer.SendBytes(Netplay.serverSock[Index], NetMessage.buffer[Index].writeBuffer, 0, length); + } + } + /// + /// Sends a warp to the player. + /// The warp. + /// + public void SendRaptorWarp(Warp warp) + { + if (!IsRaptor) + return; + + lock (NetMessage.buffer[Index].writeBuffer) + { + int length = 0; + + using (var ms = new MemoryStream(NetMessage.buffer[Index].writeBuffer, true)) + { + using (var writer = new BinaryWriter(ms)) + { + writer.BaseStream.Position = 4; + + writer.Write((byte)PacketTypes.Placeholder); + writer.Write((byte)RaptorPacketTypes.Warp); + + writer.Write(warp.WarpPos.X); + writer.Write(warp.WarpPos.Y); + writer.Write(warp.Private != "0"); + writer.Write(warp.WarpName); + + length = (int)writer.BaseStream.Position; + writer.BaseStream.Position = 0; + writer.Write(length - 4); + } + } + + TShock.PacketBuffer.SendBytes(Netplay.serverSock[Index], NetMessage.buffer[Index].writeBuffer, 0, length); + } + } + /// + /// Sends a warp deletion to the player. + /// The warp. + /// + public void SendRaptorWarpDeletion(Warp warp) + { + if (!IsRaptor) + return; + + lock (NetMessage.buffer[Index].writeBuffer) + { + int length = 0; + + using (var ms = new MemoryStream(NetMessage.buffer[Index].writeBuffer, true)) + { + using (var writer = new BinaryWriter(ms)) + { + writer.BaseStream.Position = 4; + + writer.Write((byte)PacketTypes.Placeholder); + writer.Write((byte)RaptorPacketTypes.WarpDelete); + + writer.Write(warp.WarpName); + + length = (int)writer.BaseStream.Position; + writer.BaseStream.Position = 0; + writer.Write(length - 4); + } + } + + TShock.PacketBuffer.SendBytes(Netplay.serverSock[Index], NetMessage.buffer[Index].writeBuffer, 0, length); + } + } + /// /// Adds a command callback to a specified command string. /// diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index d215df12..27aed18c 100755 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -36,6 +36,8 @@ using Terraria; using TerrariaApi.Server; using TShockAPI.DB; using TShockAPI.Net; +using System.Threading; +using System.Threading.Tasks; namespace TShockAPI { @@ -346,6 +348,24 @@ namespace TShockAPI private void OnPlayerLogin(Hooks.PlayerPostLoginEventArgs args) { + if (args.Player.IsRaptor) + { + Task.Factory.StartNew(() => + { + args.Player.SendRaptorPermissions(); + if (args.Player.Group.HasPermission(Permissions.manageregion)) + { + for (int i = 0; i < Regions.Regions.Count; i++) + args.Player.SendRaptorRegion(Regions.Regions[i]); + } + if (args.Player.Group.HasPermission(Permissions.managewarp)) + { + for (int i = 0; i < Warps.Warps.Count; i++) + args.Player.SendRaptorWarp(Warps.Warps[i]); + } + }); + } + User u = Users.GetUserByName(args.Player.UserAccountName); List KnownIps = new List(); if (!string.IsNullOrWhiteSpace(u.KnownIps)) @@ -1090,13 +1110,7 @@ namespace TShockAPI Debug.WriteLine("Recv: {0:X}: {2} ({1:XX})", e.Msg.whoAmI, (byte) type, type); var player = Players[e.Msg.whoAmI]; - if (player == null) - { - e.Handled = true; - return; - } - - if (!player.ConnectionAlive) + if (player == null || !player.ConnectionAlive) { e.Handled = true; return; @@ -1109,7 +1123,7 @@ namespace TShockAPI } if ((player.State < 10 || player.Dead) && (int) type > 12 && (int) type != 16 && (int) type != 42 && (int) type != 50 && - (int) type != 38 && (int) type != 21) + (int) type != 38 && (int) type != 21 && (int) type != 67) { e.Handled = true; return; diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj index 6732d26f..a2a54944 100644 --- a/TShockAPI/TShockAPI.csproj +++ b/TShockAPI/TShockAPI.csproj @@ -80,6 +80,7 @@ + @@ -176,7 +177,7 @@ - +