예제 #1
0
        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);
                }
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
 public void SendLobbyDataUpdate(byte messageIndex, LobbyServerInfo serverInfo, List <LobbyPlayerInfo> players)
 {
     new LobbyData(messageIndex, serverInfo, players).Send(this);
 }