public LobbyData(byte number, LobbyServerInfo serverInfo, List <LobbyPlayerInfo> players) { Number = number; if (players.Count > 4) { throw new ExceptionFreeserf("Player count must not exceed 4."); } int dataSize = MIN_DATA_SIZE + (players.Count == 0 ? 0 : players.Select(p => p.GetDataSize()).Aggregate((a, b) => a + b)); if (dataSize > 255) { throw new ExceptionFreeserf("Lobby data length must not exceed 255."); } header.DataSize = (byte)dataSize; header.PlayerCount = (byte)players.Count; var serverSettings = new LobbyServerSettings(); if (serverInfo.UseServerValues) { serverSettings.Flags |= 0x01; } if (serverInfo.UseSameValues) { serverSettings.Flags |= 0x02; } serverSettings.MapSize = (byte)serverInfo.MapSize; byte[] mapSeed = Encoding.ASCII.GetBytes(serverInfo.MapSeed); if (mapSeed.Length != 16) { throw new ExceptionFreeserf("Invalid map seed. Length must be 16."); } unsafe { Marshal.Copy(mapSeed, 0, (IntPtr)serverSettings.MapSeed, 16); } var typeBytes = BitConverter.GetBytes((UInt16)Type); int dataOffset = 3; sendData = new byte[dataSize]; sendData[0] = typeBytes[0]; sendData[1] = typeBytes[1]; sendData[2] = Number; NetworkDataConverter <LobbyDataHeader> .ToBytes(header, sendData, ref dataOffset); NetworkDataConverter <LobbyServerSettings> .ToBytes(serverSettings, sendData, ref dataOffset); foreach (var player in players) { var playerData = new LobbyPlayerData(); playerData.Type = 0; if (player.Identification != null) { playerData.Type = (byte)(player.IsHost ? 1 : 2); } playerData.Face = (byte)player.Face; playerData.Supplies = (byte)player.Supplies; playerData.Reproduction = (byte)player.Reproduction; NetworkDataConverter <LobbyPlayerData> .ToBytes(playerData, sendData, ref dataOffset); if (playerData.Type == 0) // AI { var aiPlayerData = new LobbyAIPlayerData(); aiPlayerData.Intelligence = (byte)player.Intelligence; NetworkDataConverter <LobbyAIPlayerData> .ToBytes(aiPlayerData, sendData, ref dataOffset); } else // Human { var humanPlayerData = new LobbyHumanPlayerData(); var ipParts = player.Identification.Split('.'); if (ipParts.Length != 4) { throw new ExceptionFreeserf("Invalid IP address."); } byte[] ipBytes = ipParts.Select(p => (byte)int.Parse(p)).ToArray(); unsafe { Marshal.Copy(ipBytes, 0, (IntPtr)humanPlayerData.IP, 4); } NetworkDataConverter <LobbyHumanPlayerData> .ToBytes(humanPlayerData, sendData, ref dataOffset); } } }
unsafe public INetworkData Parse(byte[] rawData) { sendData = rawData; if (rawData.Length == 2) { throw new ExceptionFreeserf("Empty lobby data received."); } else if (rawData.Length < MIN_DATA_SIZE) { throw new ExceptionFreeserf("Invalid lobby data received."); } Number = rawData[2]; header.DataSize = rawData[3]; header.PlayerCount = rawData[4]; if (header.PlayerCount > 4) { throw new ExceptionFreeserf("Lobby player count was > 4. Lobby data is corrupted."); } int dataIndex = 5; var serverSettings = NetworkDataConverter <LobbyServerSettings> .FromBytes(rawData, ref dataIndex); byte[] mapSeed = new byte[16]; Marshal.Copy((IntPtr)serverSettings.MapSeed, mapSeed, 0, 16); ServerInfo = new LobbyServerInfo( (serverSettings.Flags & 0x01) != 0, (serverSettings.Flags & 0x02) != 0, serverSettings.MapSize, Encoding.ASCII.GetString(mapSeed) ); for (int i = 0; i < header.PlayerCount; ++i) { var player = NetworkDataConverter <LobbyPlayerData> .FromBytes(rawData, ref dataIndex); LobbyPlayerInfo playerInfo; if (player.Type == 0) // AI { var aiPlayer = NetworkDataConverter <LobbyAIPlayerData> .FromBytes(rawData, ref dataIndex); playerInfo = new LobbyPlayerInfo(null, false, player.Face, player.Supplies, aiPlayer.Intelligence, player.Reproduction); } else // Human { var humanPlayer = NetworkDataConverter <LobbyHumanPlayerData> .FromBytes(rawData, ref dataIndex); byte[] ipBytes = new byte[4]; Marshal.Copy((IntPtr)humanPlayer.IP, ipBytes, 0, 4); string ip = $"{ipBytes[0]}.{ipBytes[1]}.{ipBytes[2]}.{ipBytes[3]}"; playerInfo = new LobbyPlayerInfo(ip, player.Type == 1, player.Face, player.Supplies, 40, player.Reproduction); } players.Add(playerInfo); } return(this); }
public void SendLobbyDataUpdate(byte messageIndex, LobbyServerInfo serverInfo, List <LobbyPlayerInfo> players) { new LobbyData(messageIndex, serverInfo, players).Send(this); }