Exemplo n.º 1
0
        internal void TogglePVP(Player p, bool status)
        {
            ushort length = 2;
            var    writer = WriteHeader(length, NetworkRequest.TogglePVP);

            writer.Write(p.GetSlot());
            writer.Write((byte)(status ? 1 : 0));
            SendWrittenBytes();
            PVPStatusChanged?.Invoke(p, status);
        }
Exemplo n.º 2
0
        private void Listen()
        {
            while (Thread.CurrentThread.IsAlive)
            {
                NetworkRequest type;
                byte[]         message = ReadMessage();
                if (message.Length == 0)
                {
                    continue;
                }
                type = (NetworkRequest)message[0];
                var          payload = new MemoryStream(message.Skip(1).ToArray());
                BinaryReader reader  = new BinaryReader(payload);
                switch (type)
                {
                case NetworkRequest.FatalError:     // Any fatal error that occured lead here
                    reader.ReadByte();
                    throw new Exception("Fatal error: " + reader.ReadString());

                case NetworkRequest.AuthentificationSuccess:     // Authentification confirmation
                {
                    byte slot = reader.ReadByte();
                    _me = new PlayerSelf(this, _playerInfos.GetName(), slot);
                    _otherPlayers.Add(slot, _me);
                    LogDebug("Player slot is now " + slot);
                    SendPlayerInfoMessage();
                    // We don't send our health/mana/etc because we keep the default one
                    if (_playerInfos.GetHealth() != 100)
                    {
                        SendPlayerHealth(_playerInfos.GetHealth());
                    }
                    if (_playerInfos.GetMana() != 20)
                    {
                        SendPlayerMana(_playerInfos.GetMana());
                    }
                    SendWorldInfoRequest();
                }
                break;

                case NetworkRequest.CharacterCreation:
                {
                    byte slot = reader.ReadByte();
                    reader.ReadByte();
                    reader.ReadByte();
                    string name = reader.ReadString();
                    if (!_otherPlayers.ContainsKey(slot))
                    {
                        LogInfo("New player with slot " + slot);
                        Player player = new Player(this, name, slot);
                        _otherPlayers.Add(slot, player);
                        NewPlayerJoined?.Invoke(player);
                    }
                }
                break;

                case NetworkRequest.WorldInfoAnswer:     // Various basic information about the world
                    if (!_didSpawn)
                    {
                        _didSpawn = true;
                        var   blocPixelSize = BlocGroup.blocPixelSize;
                        int   time          = reader.ReadInt32();
                        byte  moonInfo      = reader.ReadByte();
                        byte  moonPhase     = reader.ReadByte();
                        short maxTilesX     = reader.ReadInt16();
                        short maxTilesY     = reader.ReadInt16();
                        short spawnX        = reader.ReadInt16();
                        short spawnY        = reader.ReadInt16();
                        short surfaceY      = reader.ReadInt16();
                        short rockY         = reader.ReadInt16();
                        LogDebug("Current time is " + time);
                        LogDebug(ByteToBool(moonInfo, 1) ? "It's currently day time" : "It's currently night time");
                        LogDebug(ByteToBool(moonInfo, 2) ? "It's currently the blood moon" : "It's not currently the blood moon");
                        LogDebug(ByteToBool(moonInfo, 4) ? "It's currently an eclipse" : "It's not currently an eclipse");
                        LogDebug("The current moon phrase is " + moonPhase);
                        LogDebug("Maximum world value at (" + (maxTilesX * blocPixelSize) + ";" + (maxTilesY * blocPixelSize) + ")");
                        LogDebug("Spawn world value at (" + (spawnX * blocPixelSize) + ";" + (spawnY * blocPixelSize) + ")");
                        LogDebug("Surface layer is at heigth of " + surfaceY);
                        LogDebug("Rock layer is at height of " + rockY);
                        _me.SetPosition(new Vector2(spawnX * blocPixelSize, spawnY * blocPixelSize), Vector2.Zero);
                        _tiles = new Tile[maxTilesX, maxTilesY];
                        for (int i = 0; i < maxTilesX; i++)
                        {
                            for (int y = 0; y < maxTilesY; y++)
                            {
                                _tiles[i, y] = null;
                            }
                        }
                        SendInitialTile();
                    }
                    break;

                case NetworkRequest.TileData:     // Some information about a row of tile?
                {
                    MemoryStream stream = new MemoryStream();
                    if (payload.ReadByte() != 0)
                    {
                        using (DeflateStream deflate = new DeflateStream(payload, CompressionMode.Decompress))
                        {
                            deflate.CopyTo(stream);
                            deflate.Close();
                        }
                        stream.Position = 0L;
                    }
                    else
                    {
                        stream          = payload;
                        stream.Position = 1L;
                    }
                    using (BinaryReader r = new BinaryReader(stream))
                    {
                        int xStart = r.ReadInt32();
                        int yStart = r.ReadInt32();
                        int width  = r.ReadInt16();
                        int height = r.ReadInt16();
                        LogDebug("Updating " + width + " x " + height + " tiles beginning at (" + xStart + ";" + yStart + ")");
                        // I have no idea what I'm doing but it's what Terraria is doing
                        Tile tile  = null;
                        int  value = 0;
                        for (int y = yStart; y < yStart + height; y++)
                        {
                            for (int x = xStart; x < xStart + width; x++)
                            {
                                if (value != 0)
                                {
                                    value--;
                                    _tiles[x, y] = (tile == null ? new Tile() : new Tile(tile));
                                }
                                else
                                {
                                    byte b  = 0;
                                    byte b2 = 0;
                                    tile         = _tiles[x, y];
                                    _tiles[x, y] = new Tile();
                                    if (tile == null)
                                    {
                                        tile = _tiles[x, y];
                                    }
                                    byte b3 = r.ReadByte();
                                    if ((b3 & 1) == 1)
                                    {
                                        b2 = r.ReadByte();
                                        if ((b2 & 1) == 1)
                                        {
                                            b = r.ReadByte();
                                        }
                                    }
                                    bool flag = tile.IsActive();
                                    byte b4;
                                    if ((b3 & 2) == 2)
                                    {
                                        tile.Activate(true);
                                        ushort ttype = tile.GetTileType();
                                        int    num2;
                                        if ((b3 & 32) == 32)
                                        {
                                            b4   = r.ReadByte();
                                            num2 = r.ReadByte();
                                            num2 = (num2 << 8 | b4);
                                        }
                                        else
                                        {
                                            num2 = r.ReadByte();
                                        }
                                        tile.SetTileType((ushort)num2);
                                        // num2 < _tileFrameImportant.Length shouldn't be here
                                        if (num2 > _tileFrameImportant.Length)
                                        {
                                            LogError(num2 + " is bigger than _tileFrameImportant length (" + _tileFrameImportant.Length + ")");
                                        }
                                        if (num2 < _tileFrameImportant.Length && _tileFrameImportant[num2])
                                        {
                                            tile.SetFrames(r.ReadInt16(), r.ReadInt16());
                                        }
                                        else if (!flag || tile.GetTileType() != ttype)
                                        {
                                            tile.SetFrames(-1, -1);
                                        }
                                        if ((b & 8) == 8)
                                        {
                                            tile.Color(r.ReadByte());
                                        }
                                    }
                                    if ((b3 & 4) == 4)
                                    {
                                        tile.SetWall(r.ReadByte());
                                        if ((b & 16) == 16)
                                        {
                                            tile.ColorWall(r.ReadByte());
                                        }
                                    }
                                    b4 = (byte)((b3 & 24) >> 3);
                                    if (b4 != 0)
                                    {
                                        tile.SetLiquid(r.ReadByte());
                                        if (b4 > 1)
                                        {
                                            // Lava and honey management
                                        }
                                    }
                                    if (b2 > 1)
                                    {
                                        // Wires and slops management
                                    }
                                    if (b > 0)
                                    {
                                        // Some others electrical management
                                    }
                                    b4 = (byte)((b3 & 192) >> 6);
                                    if (b4 == 0)
                                    {
                                        value = 0;
                                    }
                                    else if (b4 == 1)
                                    {
                                        value = r.ReadByte();
                                    }
                                    else
                                    {
                                        value = r.ReadInt16();
                                    }
                                }
                            }
                        }
                    }
                }
                break;

                case NetworkRequest.PlayerControls:
                {
                    byte   slot          = reader.ReadByte();
                    byte   movement      = reader.ReadByte();
                    bool   up            = ByteToBool(movement, 1);
                    bool   down          = ByteToBool(movement, 2);
                    bool   left          = ByteToBool(movement, 4);
                    bool   right         = ByteToBool(movement, 8);
                    bool   jump          = ByteToBool(movement, 16);
                    bool   useItem       = ByteToBool(movement, 32);
                    bool   direction     = ByteToBool(movement, 64);
                    string keyInfo       = "Key pressed: " + (up ? "Up " : "") + (down ? ", Down " : "") + (left + ", Left " + "") + (right + ", Right " + "") + (jump + ", Jump " + "");
                    byte   otherMovement = reader.ReadByte();
                    byte   selectedItem  = reader.ReadByte();
                    float  posX          = reader.ReadSingle();
                    float  posY          = reader.ReadSingle();
                    var    player        = _otherPlayers[slot];
                    var    newPos        = new Vector2(posX, posY);
                    float  velX          = 0f;
                    float  velY          = 0f;
                    PlayerPositionUpdate?.Invoke(player, newPos);
                    if (ByteToBool(otherMovement, 4))
                    {
                        velX = reader.ReadSingle();
                        velY = reader.ReadSingle();
                        LogDebug("Player " + slot + " is at (" + posX + ";" + posY + ") with a velocity of (" + velX + ";" + velY + ") " + keyInfo);
                    }
                    player.SetPosition(newPos, new Vector2(velX, velY));
                    LogDebug("Player " + slot + " is at (" + posX + ";" + posY + ") " + keyInfo);
                }
                break;

                case NetworkRequest.TileEdit:
                {
                    byte  action = reader.ReadByte();
                    short xPos   = reader.ReadInt16();
                    short yPos   = reader.ReadInt16();
                    short tileId = reader.ReadInt16();
                    if (action == 0)         // Tile destroyed
                    {
                        _tiles[xPos, yPos] = new Tile();
                    }
                    else
                    {
                        _tiles[xPos, yPos] = new Tile((byte)tileId);
                    }
                }
                break;

                case NetworkRequest.TogglePVP:
                {
                    byte slot  = reader.ReadByte();
                    bool isPVP = reader.ReadByte() == 1;
                    PVPStatusChanged?.Invoke(_otherPlayers[slot], isPVP);
                }
                break;

                case NetworkRequest.PasswordRequest:     // The server need a password to be joined
                    if (_password == "")
                    {
                        throw new ArgumentException("A password is needed to connect to the server.");
                    }
                    else
                    {
                        LogDebug("Sending password to server");
                        SendStringMessage(NetworkRequest.PasswordAnswer, _password);
                    }
                    break;

                case NetworkRequest.JoinTeam:
                {
                    byte slot = reader.ReadByte();
                    byte team = reader.ReadByte();
                    TeamStatusChanged?.Invoke(_otherPlayers[slot], (Team)team);
                }
                break;

                case NetworkRequest.SpawnRequest:     // When this is received, need to reply with spawn location
                    LogInfo("Sending spawn request at (" + -1 + ";" + -1 + ")");
                    SendSpawnRequest();
                    ServerJoined?.Invoke(_me);
                    break;

                case NetworkRequest.ChatMessage:
                {
                    ushort id   = reader.ReadUInt16();
                    byte   slot = reader.ReadByte();
                    byte   mode = reader.ReadByte();
                    try
                    {
                        string content = reader.ReadString();
                        if (mode == 0 && _otherPlayers.ContainsKey(slot))
                        {
                            ChatMessageReceived?.Invoke(_otherPlayers[slot], content);
                        }
                        else if (mode == 2 && slot == 255)
                        {
                            LogDebug("Message received from server with id " + id + " and mode " + mode + ": " + content);
                        }
                    }
                    catch (EndOfStreamException)         // TODO: Need to fix this
                    { }
                }
                break;

                case NetworkRequest.CharacterInventorySlot:
                case NetworkRequest.Status:
                case NetworkRequest.RecalculateUV:
                case NetworkRequest.BlockUpdate:
                case NetworkRequest.ItemInfo:
                case NetworkRequest.ItemOwnerInfo:
                case NetworkRequest.NPCInfo:
                case NetworkRequest.UpdateProjectile:
                case NetworkRequest.DeleteProjectile:
                case NetworkRequest.EvilRatio:
                case NetworkRequest.DailyAnglerQuestFinished:
                case NetworkRequest.EightyThree:
                case NetworkRequest.CharacterStealth:
                case NetworkRequest.InventoryItemInfo:
                case NetworkRequest.NinetySix:
                case NetworkRequest.TowerShieldStrength:
                    break;

                default:
                    // LogDebug("Unknown message type " + type);
                    break;
                }
            }
        }