diff --git a/TShockAPI/Net/WorldInfoMsg.cs b/TShockAPI/Net/WorldInfoMsg.cs index b2361699..913b976c 100644 --- a/TShockAPI/Net/WorldInfoMsg.cs +++ b/TShockAPI/Net/WorldInfoMsg.cs @@ -18,12 +18,70 @@ along with this program. If not, see . using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; +using Terraria; +using TerrariaAPI; +using XNAHelpers; namespace TShockAPI.Net { - class WorldInfoMsg + [Flags] + public enum WorldInfoFlag : byte { + None = 0, + OrbSmashed = 1, + DownedBoss1 = 2, + DownedBoss2 = 4, + DownedBoss3 = 8, + } + public class WorldInfoMsg : IPackable + { + public int Time { get; set; } + public bool DayTime { get; set; } + public byte MoonPhase { get; set; } + public bool BloodMoon { get; set; } + public int MaxTilesX { get; set; } + public int MaxTilesY { get; set; } + public int SpawnX { get; set; } + public int SpawnY { get; set; } + public int WorldSurface { get; set; } + public int RockLayer { get; set; } + public int WorldID { get; set; } + public WorldInfoFlag WorldFlags { get; set; } + public string WorldName { get; set; } + public void PackFull(Stream stream) + { + long start = stream.Position; + stream.WriteInt32(1); + stream.WriteInt8((byte)PacketTypes.WorldInfo); + Pack(stream); + long end = stream.Position; + stream.Position = start; + stream.WriteInt32((int)(end - start) - 4); + stream.Position = end; + } + public void Pack(Stream stream) + { + stream.Write(Time); + stream.Write(DayTime); + stream.Write(MoonPhase); + stream.Write(BloodMoon); + stream.Write(MaxTilesX); + stream.Write(MaxTilesY); + stream.Write(SpawnX); + stream.Write(SpawnY); + stream.Write(WorldSurface); + stream.Write(RockLayer); + stream.Write(WorldID); + stream.Write((byte)WorldFlags); + stream.Write(Encoding.ASCII.GetBytes(WorldName)); + } + + public void Unpack(Stream stream) + { + throw new NotImplementedException(); + } } } diff --git a/TShockAPI/Properties/AssemblyInfo.cs b/TShockAPI/Properties/AssemblyInfo.cs index e0b89dc5..09c15782 100644 --- a/TShockAPI/Properties/AssemblyInfo.cs +++ b/TShockAPI/Properties/AssemblyInfo.cs @@ -35,5 +35,5 @@ using System.Runtime.InteropServices; // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.3.2.0707")] -[assembly: AssemblyFileVersion("2.3.2.0707")] +[assembly: AssemblyVersion("2.3.4.0708")] +[assembly: AssemblyFileVersion("2.3.4.0708")] diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 472a1513..1ac96159 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -17,9 +17,11 @@ along with this program. If not, see . */ using System; using System.Collections.Generic; +using System.IO; using Microsoft.Xna.Framework; using Terraria; using TerrariaAPI; +using TShockAPI.Net; namespace TShockAPI { @@ -43,7 +45,6 @@ namespace TShockAPI public Vector2 oldSpawn = Vector2.Zero; public TSPlayer LastWhisper; public int LoginAttempts { get; set; } - public bool Teleporting = false; public Vector2 TeleportCoords = new Vector2(-1, -1); Player FakePlayer = null; @@ -87,17 +88,17 @@ namespace TShockAPI } public float X { - get + get { - return RealPlayer ? TPlayer.position.X : Main.spawnTileX * 16; + return RealPlayer ? TPlayer.position.X : Main.spawnTileX * 16; } } public float Y { - get + get { - return RealPlayer ? TPlayer.position.Y : Main.spawnTileY * 16; + return RealPlayer ? TPlayer.position.Y : Main.spawnTileY * 16; } } public int TileX @@ -148,18 +149,44 @@ namespace TShockAPI SendData(PacketTypes.Disconnect, reason); } - public bool Teleport(int tileX, int tileY) + void SendTeleport(int tilex, int tiley) + { + 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 = tilex, + SpawnY = tiley, + 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), + WorldName = Main.worldName + }; + + + var ms = new MemoryStream(); + msg.PackFull(ms); + SendRawData(ms.ToArray()); + } + + public bool Teleport(int tilex, int tiley) { InitSpawn = false; - Teleporting = true; - TeleportCoords = new Vector2(tileX, tileY); - SendData(PacketTypes.WorldInfo); + SendTeleport(tilex, tiley); //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) - if (!SendTileSquare(tileX, tileY, 150)) + if (!SendTileSquare(tilex, tiley, 150)) { SendMessage("Warning, teleport failed due to being too close to the edge of the map.", Color.Red); return false; @@ -195,23 +222,30 @@ namespace TShockAPI } } - Teleporting = false; - SendData(PacketTypes.WorldInfo); + SendTeleport(Main.spawnTileX, Main.spawnTileY); return true; } public void Spawn() { - SendData(PacketTypes.PlayerSpawn, "", Index, 0.0f, 0.0f, 0.0f); + SendData(PacketTypes.PlayerSpawn, "", Index, 0.0f, 0.0f, 0.0f); } public virtual bool SendTileSquare(int x, int y, int size = 10) { if (x + size >= Main.maxTilesX || y + size >= Main.maxTilesX) return false; - SendData(PacketTypes.TileSendSquare, "", size, (float)(x - (size / 2)), (float)(y - (size / 2)), 0f); - return true; + try + { + SendData(PacketTypes.TileSendSquare, "", size, (float)(x - (size / 2)), (float)(y - (size / 2))); + return true; + } + catch (Exception ex) + { + Log.Error(ex.ToString()); + } + return false; } public virtual void GiveItem(int type, string name, int width, int height, int stack) @@ -260,17 +294,39 @@ namespace TShockAPI } //Todo: Separate this into a few functions. SendTo, SendToAll, etc - public void SendData(PacketTypes msgType, string text = "", int number = 0, float number2 = 0f, float number3 = 0f, float number4 = 0f, int number5 = 0) + public virtual void SendData(PacketTypes msgType, string text = "", int number = 0, float number2 = 0f, float number3 = 0f, float number4 = 0f, int number5 = 0) { if (RealPlayer && !ConnectionAlive) return; NetMessage.SendData((int)msgType, Index, -1, text, number, number2, number3, number4, number5); } + + public virtual bool SendRawData(byte[] data) + { + if (!RealPlayer || !ConnectionAlive) + return false; + + try + { + if (Netplay.serverSock[Index].tcpClient.Connected) + { + Netplay.serverSock[Index].networkStream.Write(data, 0, data.Length); + return true; + } + + } + catch (Exception ex) + { + Log.Error(ex.ToString()); + } + return false; + } } public class TSServerPlayer : TSPlayer { - public TSServerPlayer() : base("Server") + public TSServerPlayer() + : base("Server") { Group = new SuperAdminGroup(); } @@ -329,7 +385,7 @@ namespace TShockAPI foreach (KeyValuePair entry in destroyedTiles) { Main.tile[(int)entry.Key.X, (int)entry.Key.Y] = entry.Value; - Log.Debug(string.Format("Reverted DestroyedTile(TileXY:{0}_{1}, Type:{2})", + Log.Debug(string.Format("Reverted DestroyedTile(TileXY:{0}_{1}, Type:{2})", entry.Key.X, entry.Key.Y, Main.tile[(int)entry.Key.X, (int)entry.Key.Y].type)); } // Send all players updated tile sqaures diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index 44388dc1..ba7d5e91 100755 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -104,7 +104,6 @@ namespace TShockAPI ServerHooks.Command += ServerHooks_OnCommand; NetHooks.GetData += GetData; NetHooks.GreetPlayer += OnGreetPlayer; - NetHooks.SendData += OnSendData; NpcHooks.StrikeNpc += NpcHooks_OnStrikeNpc; @@ -130,7 +129,6 @@ namespace TShockAPI ServerHooks.Command -= ServerHooks_OnCommand; NetHooks.GetData -= GetData; NetHooks.GreetPlayer -= OnGreetPlayer; - NetHooks.SendData -= OnSendData; NpcHooks.StrikeNpc -= NpcHooks_OnStrikeNpc; } @@ -450,53 +448,6 @@ namespace TShockAPI } } - private void OnSendData(SendDataEventArgs e) - { - //TODO - Clean this code up - switch (e.MsgID) - { - case PacketTypes.WorldInfo: - if (e.remoteClient >= 0 && Players[e.remoteClient] != null && Players[e.remoteClient].Teleporting) - { - var stream = new MemoryStream(messageBuffer.writeBufferMax); - var writer = new BinaryWriter(stream); - stream.Position = 4; - writer.Write(BitConverter.GetBytes(7), 0, 1); - writer.Write(BitConverter.GetBytes((int)Main.time)); - writer.Write(BitConverter.GetBytes(Main.dayTime)); - writer.Write((byte)Main.moonPhase); - writer.Write(Main.bloodMoon); - writer.Write(BitConverter.GetBytes(Main.maxTilesX)); - writer.Write(BitConverter.GetBytes(Main.maxTilesY)); - writer.Write(BitConverter.GetBytes((int)Players[e.remoteClient].TeleportCoords.X)); - writer.Write(BitConverter.GetBytes((int)Players[e.remoteClient].TeleportCoords.Y)); - writer.Write(BitConverter.GetBytes((int)Main.worldSurface)); - writer.Write(BitConverter.GetBytes((int)Main.rockLayer)); - writer.Write(BitConverter.GetBytes(Main.worldID)); - writer.Write((byte)(0 + (WorldGen.shadowOrbSmashed ? 1 : 0) + (NPC.downedBoss1 ? 2 : 0) + (NPC.downedBoss2 ? 4 : 0) + (NPC.downedBoss3 ? 8 : 0))); - writer.Write(Encoding.ASCII.GetBytes(Main.worldName)); - var length = (int)(stream.Length - 4); - stream.Position = 0; - writer.Write(length); - NetMessage.buffer[e.remoteClient].writeBuffer = stream.GetBuffer(); - try - { - if (Netplay.serverSock[e.remoteClient].tcpClient.Connected) - { - NetMessage.buffer[e.remoteClient].spamCount++; - Netplay.serverSock[e.remoteClient].networkStream.BeginWrite(NetMessage.buffer[e.remoteClient].writeBuffer, 0, (int)stream.Length, new AsyncCallback(Netplay.serverSock[e.remoteClient].ServerWriteCallBack), Netplay.serverSock[e.remoteClient].networkStream); - } - } - catch { } - NetMessage.buffer[e.remoteClient].writeLocked = false; - e.Handled = true; - } - break; - default: - break; - } - } - private void OnGreetPlayer(int who, HandledEventArgs e) { var player = Players[who];