using Multiplayer.Network; using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Sockets; using System.Threading; using UnityEngine; public class GameServer : MonoBehaviour { private TcpListener listener; private List<TcpClient> clients = new List<TcpClient>(); private Dictionary<ushort, PlayerData> connectedPlayers = new Dictionary<ushort, PlayerData>(); private Dictionary<TcpClient, ushort> clientToPlayerId = new Dictionary<TcpClient, ushort>(); private Thread serverThread; private bool isRunning; private ushort nextPlayerId = 1; void Start() { isRunning = true; serverThread = new Thread(RunServer); serverThread.Start(); } //Runs the server void RunServer() { listener = new TcpListener(IPAddress.Any, 7777); listener.Start(); Debug.Log("Server started on port 7777"); while (isRunning) { if (listener.Pending()) { TcpClient client = listener.AcceptTcpClient(); clients.Add(client); Debug.Log("Client connected!"); Thread clientThread = new Thread(() => HandleClient(client)); clientThread.Start(); } Thread.Sleep(10); } } void HandleClient(TcpClient client) { NetworkStream stream = client.GetStream(); byte[] buffer = new byte[1024]; try { // Wait for initial player data (as serialized NetworkMessage) int bytesRead = stream.Read(buffer, 0, buffer.Length); byte[] receivedData = new byte[bytesRead]; Array.Copy(buffer, receivedData, bytesRead); NetworkMessage joinMsg = NetworkSerializer.FromBytes<NetworkMessage>(receivedData); if (joinMsg.command != NetworkCommand.PlayerJoin || !(joinMsg.data is PlayerData)) { Debug.LogError("Invalid initial message received from client."); return; } PlayerData playerData = (PlayerData)joinMsg.data; playerData.playerId = nextPlayerId++; // Store player info connectedPlayers[playerData.playerId] = playerData; clientToPlayerId[client] = playerData.playerId; Debug.Log($"Player '{playerData.username}' connected with ID {playerData.playerId}"); //Send PlayerJoinConfirmed message to this client NetworkMessage confirmMsg = new NetworkMessage { command = NetworkCommand.PlayerJoinConfirmed, data = playerData }; byte[] confirmBytes = NetworkSerializer.ToBytes(confirmMsg); stream.Write(confirmBytes, 0, confirmBytes.Length); // Send existing players to the new client SendExistingPlayers(client, playerData.playerId); // Notify all clients of the new player BroadcastPlayerJoin(playerData); while (isRunning && client.Connected) { if (stream.DataAvailable) { bytesRead = stream.Read(buffer, 0, buffer.Length); receivedData = new byte[bytesRead]; Array.Copy(buffer, receivedData, bytesRead); NetworkMessage msg = NetworkSerializer.FromBytes<NetworkMessage>(receivedData); switch (msg.command) { case NetworkCommand.PlayerMove: PlayerData moveData = (PlayerData)msg.data; moveData.playerId = playerData.playerId; // ensure correct ID connectedPlayers[moveData.playerId] = moveData; BroadcastPlayerMove(moveData); break; // Add more cases here if needed (e.g. chat, item pickup, etc.) } } Thread.Sleep(10); } } catch (Exception ex) { Debug.LogError($"Exception while handling client: {ex}"); } finally { // Handle disconnect if (clientToPlayerId.TryGetValue(client, out ushort id)) { BroadcastPlayerLeave(id); connectedPlayers.Remove(id); clientToPlayerId.Remove(client); } clients.Remove(client); client.Close(); } } void SendExistingPlayers(TcpClient newClient, ushort newPlayerId) { NetworkStream stream = newClient.GetStream(); foreach (KeyValuePair<ushort, PlayerData> kvp in connectedPlayers) { if (kvp.Key != newPlayerId) { NetworkMessage msg = new NetworkMessage { command = NetworkCommand.PlayerJoin, data = kvp.Value }; byte[] data = NetworkSerializer.ToBytes(msg); stream.Write(data, 0, data.Length); } } } void BroadcastPlayerJoin(PlayerData playerData) { NetworkMessage msg = new NetworkMessage { command = NetworkCommand.PlayerJoin, data = playerData }; BroadcastSerialized(msg); } void BroadcastPlayerMove(PlayerData playerData) { NetworkMessage msg = new NetworkMessage { command = NetworkCommand.PlayerMove, data = playerData }; BroadcastSerialized(msg); } void BroadcastPlayerLeave(ushort playerId) { PlayerData leaveData = new PlayerData { playerId = playerId }; NetworkMessage msg = new NetworkMessage { command = NetworkCommand.PlayerLeave, data = leaveData }; BroadcastSerialized(msg); } void BroadcastSerialized(NetworkMessage msg, TcpClient excludeClient = null) { byte[] bytes = NetworkSerializer.ToBytes(msg); foreach (TcpClient client in clients) { if (client == excludeClient || !client.Connected) continue; try { client.GetStream().Write(bytes, 0, bytes.Length); } catch (Exception e) { Debug.LogError("Failed to send message to client: " + e); } } } void OnDestroy() { isRunning = false; listener?.Stop(); foreach (TcpClient client in clients) { client.Close(); } } }