private void DoWork(object o) { TicksToPing--; lock (listener) { if (listener.Pending()) { RemoteClient c = new RemoteClient() { TcpClient = listener.AcceptTcpClient(), }; Log("New connection from " + c.TcpClient.Client.RemoteEndPoint.ToString()); c.EndPoint = c.TcpClient.Client.RemoteEndPoint; clients.Add(c); } List<RemoteClient> newClientList = new List<RemoteClient>(); foreach (RemoteClient c in clients) { if (!c.TcpClient.Connected) { Log("Lost connection from " + c.EndPoint); if (newClientList.Contains(c)) newClientList.Remove(c); EnqueueToAllClients(CreateDespawnPlayer(c.ID)); c.LoggedIn = false; continue; } newClientList.Add(c); try { while (c.TcpClient.Connected && c.TcpClient.Available > 0) // Read available data { PacketID packet = (PacketID)c.TcpClient.GetStream().ReadByte(); switch (packet) { case PacketID.Identification: byte protocol = (byte)c.TcpClient.GetStream().ReadByte(); string username = ReadString(c.TcpClient.GetStream()); string key = ReadString(c.TcpClient.GetStream()); c.TcpClient.GetStream().ReadByte(); // Unused byte c.Username = username; c.PacketQueue.Enqueue(CreateInformationPacket(this, c)); c.PacketQueue.Enqueue(CreateLevelInitializePacket()); MemoryStream ms = new MemoryStream(); GZipStream s = new GZipStream(ms, CompressionMode.Compress, true); s.Write(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(Level.Data.Length)), 0, sizeof(int)); s.Write(Level.Data, 0, Level.Data.Length); s.Close(); byte[] data = ms.GetBuffer(); ms.Close(); Console.WriteLine("Map length: " + Level.Data.Length); double numChunks = data.Length / 1042; double chunksSent = 0; for (int i = 0; i < data.Length; i += 1024) { byte[] chunkData = new byte[1024]; short chunkLength = 1024; if (data.Length - i < chunkLength) chunkLength = (short)(data.Length - i); Array.Copy(data, i, chunkData, 0, chunkLength); byte[] b = new byte[] { (byte)PacketID.LevelDataChunk }; b = b.Concat(MakeShort(chunkLength)).ToArray(); Console.WriteLine("Chunk length: " + chunkLength); b = b.Concat(chunkData).ToArray(); b = b.Concat(new byte[] { (byte)((chunksSent / numChunks) * 100) }).ToArray(); c.PacketQueue.Enqueue(b); chunksSent++; } byte[] finalize = new byte[] { (byte)PacketID.LevelFinalize }; finalize = finalize.Concat(MakeShort(Level.Width)).ToArray(); finalize = finalize.Concat(MakeShort(Level.Width)).ToArray(); finalize = finalize.Concat(MakeShort(Level.Width)).ToArray(); c.PacketQueue.Enqueue(finalize); c.ID = NextID; NextID++; if (NextID < 0) NextID = 0; c.Position = Level.Spawn.Clone(); c.PacketQueue.Enqueue(CreatePositionAndOrientation(-1, c.Position.X, c.Position.Y, c.Position.Z, c.Yaw, c.Heading)); foreach (RemoteClient client in from cl in clients where cl.ID != c.ID select cl) { client.PacketQueue.Enqueue(CreateSpawnPlayer(c.ID, c.Username, c.Position.X, c.Position.Y, c.Position.Z, c.Yaw, c.Heading)); client.PacketQueue.Enqueue(CreatePositionAndOrientation(c.ID, c.Position.X, c.Position.Y, c.Position.Z, c.Yaw, c.Heading)); c.PacketQueue.Enqueue(CreateSpawnPlayer(client.ID, client.Username, client.Position.X, client.Position.Y, client.Position.Z, client.Yaw, client.Heading)); } //SendChat(c.Username + " joined the game", -1); break; case PacketID.PositionAndOrientation: c.TcpClient.GetStream().ReadByte(); // Discard c.Position.X = ReadFloat(c.TcpClient.GetStream()); c.Position.Y = ReadFloat(c.TcpClient.GetStream()); c.Position.Z = ReadFloat(c.TcpClient.GetStream()); c.Yaw = (byte)c.TcpClient.GetStream().ReadByte(); c.Heading = (byte)c.TcpClient.GetStream().ReadByte(); foreach (RemoteClient client in from cl in clients where cl.ID != c.ID select cl) { client.PacketQueue.Enqueue(CreatePositionAndOrientation(c.ID, c.Position.X, c.Position.Y, c.Position.Z, c.Yaw, c.Heading)); } break; case PacketID.ClientSetBlock: short x = ReadShort(c.TcpClient.GetStream()); short y = ReadShort(c.TcpClient.GetStream()); short z = ReadShort(c.TcpClient.GetStream()); byte mode = (byte)c.TcpClient.GetStream().ReadByte(); byte type = (byte)c.TcpClient.GetStream().ReadByte(); if (mode == 0) type = 0; Level.SetBlock(new Vector3(x, y, z), type); foreach (RemoteClient client in from cl in clients where cl.ID != c.ID select cl) { client.PacketQueue.Enqueue(CreateServerPlaceBlock(x, y, z, type)); } break; case PacketID.ChatMessage: c.TcpClient.GetStream().ReadByte(); string msg = ReadString(c.TcpClient.GetStream()); msg = "<" + c.Username + "> " + msg; if (msg.Length > 64) msg = msg.Remove(63); SendChat(msg, c.ID); break; default: // bad packet break; } } } catch { Log("Lost connection from " + c.EndPoint); if (newClientList.Contains(c)) newClientList.Remove(c); EnqueueToAllClients(CreateDespawnPlayer(c.ID)); c.LoggedIn = false; continue; } if (!c.TcpClient.Connected) { Log("Lost connection from " + c.EndPoint); if (newClientList.Contains(c)) newClientList.Remove(c); EnqueueToAllClients(CreateDespawnPlayer(c.ID)); c.LoggedIn = false; continue; } } clients = new List<RemoteClient>(newClientList); newClientList.Clear(); foreach (RemoteClient c in clients) // Write pending data { try { while (c.TcpClient.Connected && c.PacketQueue.Count != 0) { byte[] packet = c.PacketQueue.Dequeue(); c.TcpClient.GetStream().Write(packet, 0, packet.Length); Log("Server to client [" + c.EndPoint.ToString() + "]: " + packet[0] + " Length: " + packet.Length); } if (c.TcpClient.Connected) newClientList.Add(c); else { Log("Lost connection from " + c.EndPoint); if (newClientList.Contains(c)) newClientList.Remove(c); EnqueueToAllClients(CreateDespawnPlayer(c.ID)); c.LoggedIn = false; break; } } catch { Log("Lost connection from " + c.EndPoint); if (newClientList.Contains(c)) newClientList.Remove(c); EnqueueToAllClients(CreateDespawnPlayer(c.ID)); c.LoggedIn = false; continue; } } clients = new List<RemoteClient>(newClientList); } }
private void DoWork(object o) { TicksToPing--; lock (listener) { if (listener.Pending()) { RemoteClient c = new RemoteClient() { TcpClient = listener.AcceptTcpClient(), }; Log("New connection from " + c.TcpClient.Client.RemoteEndPoint.ToString()); c.EndPoint = c.TcpClient.Client.RemoteEndPoint; clients.Add(c); } List <RemoteClient> newClientList = new List <RemoteClient>(); foreach (RemoteClient c in clients) { if (!c.TcpClient.Connected) { Log("Lost connection from " + c.EndPoint); if (newClientList.Contains(c)) { newClientList.Remove(c); } EnqueueToAllClients(CreateDespawnPlayer(c.ID)); c.LoggedIn = false; continue; } newClientList.Add(c); try { while (c.TcpClient.Connected && c.TcpClient.Available > 0) // Read available data { PacketID packet = (PacketID)c.TcpClient.GetStream().ReadByte(); switch (packet) { case PacketID.Identification: byte protocol = (byte)c.TcpClient.GetStream().ReadByte(); string username = ReadString(c.TcpClient.GetStream()); string key = ReadString(c.TcpClient.GetStream()); c.TcpClient.GetStream().ReadByte(); // Unused byte c.Username = username; c.PacketQueue.Enqueue(CreateInformationPacket(this, c)); c.PacketQueue.Enqueue(CreateLevelInitializePacket()); MemoryStream ms = new MemoryStream(); GZipStream s = new GZipStream(ms, CompressionMode.Compress, true); s.Write(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(Level.Data.Length)), 0, sizeof(int)); s.Write(Level.Data, 0, Level.Data.Length); s.Close(); byte[] data = ms.GetBuffer(); ms.Close(); Console.WriteLine("Map length: " + Level.Data.Length); double numChunks = data.Length / 1042; double chunksSent = 0; for (int i = 0; i < data.Length; i += 1024) { byte[] chunkData = new byte[1024]; short chunkLength = 1024; if (data.Length - i < chunkLength) { chunkLength = (short)(data.Length - i); } Array.Copy(data, i, chunkData, 0, chunkLength); byte[] b = new byte[] { (byte)PacketID.LevelDataChunk }; b = b.Concat(MakeShort(chunkLength)).ToArray(); Console.WriteLine("Chunk length: " + chunkLength); b = b.Concat(chunkData).ToArray(); b = b.Concat(new byte[] { (byte)((chunksSent / numChunks) * 100) }).ToArray(); c.PacketQueue.Enqueue(b); chunksSent++; } byte[] finalize = new byte[] { (byte)PacketID.LevelFinalize }; finalize = finalize.Concat(MakeShort(Level.Width)).ToArray(); finalize = finalize.Concat(MakeShort(Level.Width)).ToArray(); finalize = finalize.Concat(MakeShort(Level.Width)).ToArray(); c.PacketQueue.Enqueue(finalize); c.ID = NextID; NextID++; if (NextID < 0) { NextID = 0; } c.Position = Level.Spawn.Clone(); c.PacketQueue.Enqueue(CreatePositionAndOrientation(-1, c.Position.X, c.Position.Y, c.Position.Z, c.Yaw, c.Heading)); foreach (RemoteClient client in from cl in clients where cl.ID != c.ID select cl) { client.PacketQueue.Enqueue(CreateSpawnPlayer(c.ID, c.Username, c.Position.X, c.Position.Y, c.Position.Z, c.Yaw, c.Heading)); client.PacketQueue.Enqueue(CreatePositionAndOrientation(c.ID, c.Position.X, c.Position.Y, c.Position.Z, c.Yaw, c.Heading)); c.PacketQueue.Enqueue(CreateSpawnPlayer(client.ID, client.Username, client.Position.X, client.Position.Y, client.Position.Z, client.Yaw, client.Heading)); } //SendChat(c.Username + " joined the game", -1); break; case PacketID.PositionAndOrientation: c.TcpClient.GetStream().ReadByte(); // Discard c.Position.X = ReadFloat(c.TcpClient.GetStream()); c.Position.Y = ReadFloat(c.TcpClient.GetStream()); c.Position.Z = ReadFloat(c.TcpClient.GetStream()); c.Yaw = (byte)c.TcpClient.GetStream().ReadByte(); c.Heading = (byte)c.TcpClient.GetStream().ReadByte(); foreach (RemoteClient client in from cl in clients where cl.ID != c.ID select cl) { client.PacketQueue.Enqueue(CreatePositionAndOrientation(c.ID, c.Position.X, c.Position.Y, c.Position.Z, c.Yaw, c.Heading)); } break; case PacketID.ClientSetBlock: short x = ReadShort(c.TcpClient.GetStream()); short y = ReadShort(c.TcpClient.GetStream()); short z = ReadShort(c.TcpClient.GetStream()); byte mode = (byte)c.TcpClient.GetStream().ReadByte(); byte type = (byte)c.TcpClient.GetStream().ReadByte(); if (mode == 0) { type = 0; } Level.SetBlock(new Vector3(x, y, z), type); foreach (RemoteClient client in from cl in clients where cl.ID != c.ID select cl) { client.PacketQueue.Enqueue(CreateServerPlaceBlock(x, y, z, type)); } break; case PacketID.ChatMessage: c.TcpClient.GetStream().ReadByte(); string msg = ReadString(c.TcpClient.GetStream()); msg = "<" + c.Username + "> " + msg; if (msg.Length > 64) { msg = msg.Remove(63); } SendChat(msg, c.ID); break; default: // bad packet break; } } } catch { Log("Lost connection from " + c.EndPoint); if (newClientList.Contains(c)) { newClientList.Remove(c); } EnqueueToAllClients(CreateDespawnPlayer(c.ID)); c.LoggedIn = false; continue; } if (!c.TcpClient.Connected) { Log("Lost connection from " + c.EndPoint); if (newClientList.Contains(c)) { newClientList.Remove(c); } EnqueueToAllClients(CreateDespawnPlayer(c.ID)); c.LoggedIn = false; continue; } } clients = new List <RemoteClient>(newClientList); newClientList.Clear(); foreach (RemoteClient c in clients) // Write pending data { try { while (c.TcpClient.Connected && c.PacketQueue.Count != 0) { byte[] packet = c.PacketQueue.Dequeue(); c.TcpClient.GetStream().Write(packet, 0, packet.Length); Log("Server to client [" + c.EndPoint.ToString() + "]: " + packet[0] + " Length: " + packet.Length); } if (c.TcpClient.Connected) { newClientList.Add(c); } else { Log("Lost connection from " + c.EndPoint); if (newClientList.Contains(c)) { newClientList.Remove(c); } EnqueueToAllClients(CreateDespawnPlayer(c.ID)); c.LoggedIn = false; break; } } catch { Log("Lost connection from " + c.EndPoint); if (newClientList.Contains(c)) { newClientList.Remove(c); } EnqueueToAllClients(CreateDespawnPlayer(c.ID)); c.LoggedIn = false; continue; } } clients = new List <RemoteClient>(newClientList); } }
internal static byte[] CreateInformationPacket(ClassicServer server, RemoteClient c) { byte[] b = new byte[] { (byte)PacketID.Identification, MinecraftVersion, }; b = b.Concat(MakeString(server.ServerName)).ToArray(); b = b.Concat(MakeString(server.MessageOfTheDay)).ToArray(); b = b.Concat(new byte[] { (byte)(c.IsOp ? 0x64 : 0) }).ToArray(); return b; }