Exemplo n.º 1
0
 public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
 {
     Tainted = msg.ReadBoolean();
     if (Tainted)
     {
         uint selectedTaintedEffectId = msg.ReadUInt32();
         selectedTaintedEffect = AfflictionPrefab.Prefabs.Find(a => a.UIntIdentifier == selectedTaintedEffectId);
     }
     else
     {
         uint selectedEffectId = msg.ReadUInt32();
         selectedEffect = AfflictionPrefab.Prefabs.Find(a => a.UIntIdentifier == selectedEffectId);
     }
 }
Exemplo n.º 2
0
        public bool ReadExtraCargo(IReadMessage msg)
        {
            bool   changed = false;
            UInt32 count   = msg.ReadUInt32();

            if (ExtraCargo == null || count != ExtraCargo.Count)
            {
                changed = true;
            }
            Dictionary <ItemPrefab, int> extraCargo = new Dictionary <ItemPrefab, int>();

            for (int i = 0; i < count; i++)
            {
                string prefabIdentifier = msg.ReadString();
                byte   amount           = msg.ReadByte();

                var itemPrefab = MapEntityPrefab.Find(null, prefabIdentifier, showErrorMessages: false) as ItemPrefab;
                if (itemPrefab != null && amount > 0)
                {
                    if (changed || !ExtraCargo.ContainsKey(itemPrefab) || ExtraCargo[itemPrefab] != amount)
                    {
                        changed = true;
                    }
                    extraCargo.Add(itemPrefab, amount);
                }
            }
            if (changed)
            {
                ExtraCargo = extraCargo;
            }
            return(changed);
        }
Exemplo n.º 3
0
        public void ClientAdminRead(IReadMessage incMsg)
        {
            int count = incMsg.ReadUInt16();

            for (int i = 0; i < count; i++)
            {
                UInt32 key = incMsg.ReadUInt32();
                if (netProperties.ContainsKey(key))
                {
                    bool changedLocally = netProperties[key].ChangedLocally;
                    netProperties[key].Read(incMsg);
                    netProperties[key].TempValue = netProperties[key].Value;

                    if (netProperties[key].GUIComponent != null)
                    {
                        if (!changedLocally)
                        {
                            netProperties[key].GUIComponentValue = netProperties[key].Value;
                        }
                    }
                }
                else
                {
                    UInt32 size = incMsg.ReadVariableUInt32();
                    incMsg.BitPosition += (int)(8 * size);
                }
            }

            ReadMonsterEnabled(incMsg);
            BanList.ClientAdminRead(incMsg);
            Whitelist.ClientAdminRead(incMsg);
        }
Exemplo n.º 4
0
        public void ClientRead(ServerNetObject type, IReadMessage message, float sendingTime)
        {
            bool isBallastFloraUpdate = message.ReadBoolean();

            if (isBallastFloraUpdate)
            {
                BallastFloraBehavior.NetworkHeader header = (BallastFloraBehavior.NetworkHeader)message.ReadByte();
                if (header == BallastFloraBehavior.NetworkHeader.Spawn)
                {
                    string identifier = message.ReadString();
                    float  x          = message.ReadSingle();
                    float  y          = message.ReadSingle();
                    BallastFlora = new BallastFloraBehavior(this, BallastFloraPrefab.Find(identifier), new Vector2(x, y), firstGrowth: true)
                    {
                        PowerConsumptionTimer = message.ReadSingle()
                    };
                }
                else
                {
                    BallastFlora?.ClientRead(message, header);
                }
                return;
            }
            remoteWaterVolume      = message.ReadRangedSingle(0.0f, 1.5f, 8) * Volume;
            remoteOxygenPercentage = message.ReadRangedSingle(0.0f, 100.0f, 8);

            bool hasFireSources = message.ReadBoolean();

            remoteFireSources = new List <Vector3>();
            if (hasFireSources)
            {
                int fireSourceCount = message.ReadRangedInteger(0, 16);
                for (int i = 0; i < fireSourceCount; i++)
                {
                    remoteFireSources.Add(new Vector3(
                                              MathHelper.Clamp(message.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
                                              MathHelper.Clamp(message.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
                                              message.ReadRangedSingle(0.0f, 1.0f, 8)));
                }
            }

            bool hasExtraData = message.ReadBoolean();

            if (hasExtraData)
            {
                bool hasSectionUpdate = message.ReadBoolean();
                if (hasSectionUpdate)
                {
                    int sectorToUpdate = message.ReadRangedInteger(0, BackgroundSections.Count - 1);
                    int start          = sectorToUpdate * BackgroundSectionsPerNetworkEvent;
                    int end            = Math.Min((sectorToUpdate + 1) * BackgroundSectionsPerNetworkEvent, BackgroundSections.Count - 1);
                    for (int i = start; i < end; i++)
                    {
                        float colorStrength           = message.ReadRangedSingle(0.0f, 1.0f, 8);
                        Color color                   = new Color(message.ReadUInt32());
                        var   remoteBackgroundSection = remoteBackgroundSections.Find(s => s.Index == i);
                        if (remoteBackgroundSection != null)
                        {
                            remoteBackgroundSection.SetColorStrength(colorStrength);
                            remoteBackgroundSection.SetColor(color);
                        }
                        else
                        {
                            remoteBackgroundSections.Add(new BackgroundSection(new Rectangle(0, 0, 1, 1), i, colorStrength, color, 0));
                        }
                    }
                    paintAmount = BackgroundSections.Sum(s => s.ColorStrength);
                }
                else
                {
                    int decalCount = message.ReadRangedInteger(0, MaxDecalsPerHull);
                    if (decalCount == 0)
                    {
                        decals.Clear();
                    }
                    remoteDecals.Clear();
                    for (int i = 0; i < decalCount; i++)
                    {
                        UInt32 decalId        = message.ReadUInt32();
                        int    spriteIndex    = message.ReadByte();
                        float  normalizedXPos = message.ReadRangedSingle(0.0f, 1.0f, 8);
                        float  normalizedYPos = message.ReadRangedSingle(0.0f, 1.0f, 8);
                        float  decalScale     = message.ReadRangedSingle(0.0f, 2.0f, 12);
                        remoteDecals.Add(new RemoteDecal(decalId, spriteIndex, new Vector2(normalizedXPos, normalizedYPos), decalScale));
                    }
                }
            }

            if (serverUpdateDelay > 0.0f)
            {
                return;
            }

            ApplyRemoteState();
        }
        public void ServerRead(IReadMessage incMsg, Client c)
        {
            if (!c.HasPermission(Networking.ClientPermissions.ManageSettings))
            {
                return;
            }

            NetFlags flags = (NetFlags)incMsg.ReadByte();

            bool changed = false;

            if (flags.HasFlag(NetFlags.Name))
            {
                string serverName = incMsg.ReadString();
                if (ServerName != serverName)
                {
                    changed = true;
                }
                ServerName = serverName;
            }

            if (flags.HasFlag(NetFlags.Message))
            {
                string serverMessageText = incMsg.ReadString();
                if (ServerMessageText != serverMessageText)
                {
                    changed = true;
                }
                ServerMessageText = serverMessageText;
            }

            if (flags.HasFlag(NetFlags.Properties))
            {
                changed |= ReadExtraCargo(incMsg);

                UInt32 count = incMsg.ReadUInt32();

                for (int i = 0; i < count; i++)
                {
                    UInt32 key = incMsg.ReadUInt32();

                    if (netProperties.ContainsKey(key))
                    {
                        object prevValue = netProperties[key].Value;
                        netProperties[key].Read(incMsg);
                        if (!netProperties[key].PropEquals(prevValue, netProperties[key]))
                        {
                            GameServer.Log(GameServer.ClientLogName(c) + " changed " + netProperties[key].Name + " to " + netProperties[key].Value.ToString(), ServerLog.MessageType.ServerMessage);
                        }
                        changed = true;
                    }
                    else
                    {
                        UInt32 size = incMsg.ReadVariableUInt32();
                        incMsg.BitPosition += (int)(8 * size);
                    }
                }

                bool changedMonsterSettings = incMsg.ReadBoolean(); incMsg.ReadPadBits();
                changed |= changedMonsterSettings;
                if (changedMonsterSettings)
                {
                    ReadMonsterEnabled(incMsg);
                }
                changed |= BanList.ServerAdminRead(incMsg, c);
                changed |= Whitelist.ServerAdminRead(incMsg, c);
            }

            if (flags.HasFlag(NetFlags.Misc))
            {
                int orBits  = incMsg.ReadRangedInteger(0, (int)Barotrauma.MissionType.All) & (int)Barotrauma.MissionType.All;
                int andBits = incMsg.ReadRangedInteger(0, (int)Barotrauma.MissionType.All) & (int)Barotrauma.MissionType.All;
                GameMain.NetLobbyScreen.MissionType = (Barotrauma.MissionType)(((int)GameMain.NetLobbyScreen.MissionType | orBits) & andBits);

                int traitorSetting = (int)TraitorsEnabled + incMsg.ReadByte() - 1;
                if (traitorSetting < 0)
                {
                    traitorSetting = 2;
                }
                if (traitorSetting > 2)
                {
                    traitorSetting = 0;
                }
                TraitorsEnabled = (YesNoMaybe)traitorSetting;

                int botCount = BotCount + incMsg.ReadByte() - 1;
                if (botCount < 0)
                {
                    botCount = MaxBotCount;
                }
                if (botCount > MaxBotCount)
                {
                    botCount = 0;
                }
                BotCount = botCount;

                int botSpawnMode = (int)BotSpawnMode + incMsg.ReadByte() - 1;
                if (botSpawnMode < 0)
                {
                    botSpawnMode = 1;
                }
                if (botSpawnMode > 1)
                {
                    botSpawnMode = 0;
                }
                BotSpawnMode = (BotSpawnMode)botSpawnMode;

                float levelDifficulty = incMsg.ReadSingle();
                if (levelDifficulty >= 0.0f)
                {
                    SelectedLevelDifficulty = levelDifficulty;
                }

                UseRespawnShuttle = incMsg.ReadBoolean();

                bool changedAutoRestart = incMsg.ReadBoolean();
                bool autoRestart        = incMsg.ReadBoolean();
                if (changedAutoRestart)
                {
                    AutoRestart = autoRestart;
                }

                changed |= true;
            }

            if (flags.HasFlag(NetFlags.LevelSeed))
            {
                GameMain.NetLobbyScreen.LevelSeed = incMsg.ReadString();
                changed |= true;
            }

            if (changed)
            {
                if (KarmaPreset == "custom")
                {
                    GameMain.NetworkMember?.KarmaManager?.SaveCustomPreset();
                    GameMain.NetworkMember?.KarmaManager?.Save();
                }
                SaveSettings();
                GameMain.NetLobbyScreen.LastUpdateID++;
            }
        }
Exemplo n.º 6
0
        public void ClientRead(ServerNetObject type, IReadMessage message, float sendingTime)
        {
            remoteWaterVolume      = message.ReadRangedSingle(0.0f, 1.5f, 8) * Volume;
            remoteOxygenPercentage = message.ReadRangedSingle(0.0f, 100.0f, 8);

            bool hasFireSources = message.ReadBoolean();

            remoteFireSources = new List <Vector3>();
            if (hasFireSources)
            {
                int fireSourceCount = message.ReadRangedInteger(0, 16);
                for (int i = 0; i < fireSourceCount; i++)
                {
                    remoteFireSources.Add(new Vector3(
                                              MathHelper.Clamp(message.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
                                              MathHelper.Clamp(message.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
                                              message.ReadRangedSingle(0.0f, 1.0f, 8)));
                }
            }

            bool hasExtraData = message.ReadBoolean();

            if (hasExtraData)
            {
                bool hasSectionUpdate = message.ReadBoolean();
                if (hasSectionUpdate)
                {
                    int sectorToUpdate = message.ReadRangedInteger(0, BackgroundSections.Count - 1);
                    int start          = sectorToUpdate * BackgroundSectionsPerNetworkEvent;
                    int end            = Math.Min((sectorToUpdate + 1) * BackgroundSectionsPerNetworkEvent, BackgroundSections.Count - 1);
                    for (int i = start; i < end; i++)
                    {
                        float colorStrength     = message.ReadRangedSingle(0.0f, 1.0f, 8);
                        Color color             = new Color(message.ReadUInt32());
                        float prevColorStrength = BackgroundSections[i].ColorStrength;
                        BackgroundSections[i].SetColorStrength(colorStrength);
                        BackgroundSections[i].SetColor(color);
                        paintAmount = Math.Max(0, paintAmount + (BackgroundSections[i].ColorStrength - prevColorStrength) / BackgroundSections.Count);

                        var remoteBackgroundSection = remoteBackgroundSections.Find(s => s.Index == i);
                        if (remoteBackgroundSection != null)
                        {
                            remoteBackgroundSection.SetColorStrength(colorStrength);
                            remoteBackgroundSection.SetColor(color);
                        }
                        else
                        {
                            remoteBackgroundSections.Add(new BackgroundSection(new Rectangle(0, 0, 1, 1), i, colorStrength, color, 0));
                        }
                    }
                    paintAmount = BackgroundSections.Sum(s => s.ColorStrength);
                }
                else
                {
                    int decalCount = message.ReadRangedInteger(0, MaxDecalsPerHull);
                    decals.Clear();
                    for (int i = 0; i < decalCount; i++)
                    {
                        UInt32 decalId        = message.ReadUInt32();
                        float  normalizedXPos = message.ReadRangedSingle(0.0f, 1.0f, 8);
                        float  normalizedYPos = message.ReadRangedSingle(0.0f, 1.0f, 8);
                        float  decalPosX      = MathHelper.Lerp(rect.X, rect.Right, normalizedXPos);
                        float  decalPosY      = MathHelper.Lerp(rect.Y - rect.Height, rect.Y, normalizedYPos);
                        float  decalScale     = message.ReadRangedSingle(0.0f, 2.0f, 12);
                        AddDecal(decalId, new Vector2(decalPosX, decalPosY), decalScale, isNetworkEvent: true);
                    }
                }
            }

            if (serverUpdateDelay > 0.0f)
            {
                return;
            }

            ApplyRemoteState();
        }
Exemplo n.º 7
0
        public virtual void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            if (GameMain.Server == null)
            {
                return;
            }

            switch (type)
            {
            case ClientNetObject.CHARACTER_INPUT:

                if (c.Character != this)
                {
#if DEBUG
                    DebugConsole.Log("Received a character update message from a client who's not controlling the character");
#endif
                    return;
                }

                UInt16 networkUpdateID = msg.ReadUInt16();
                byte   inputCount      = msg.ReadByte();

                if (AllowInput)
                {
                    Enabled = true;
                }

                for (int i = 0; i < inputCount; i++)
                {
                    InputNetFlags newInput    = (InputNetFlags)msg.ReadRangedInteger(0, (int)InputNetFlags.MaxVal);
                    UInt16        newAim      = 0;
                    UInt16        newInteract = 0;

                    if (newInput != InputNetFlags.None && newInput != InputNetFlags.FacingLeft)
                    {
                        c.KickAFKTimer = 0.0f;
                    }
                    else if (AnimController.Dir < 0.0f != newInput.HasFlag(InputNetFlags.FacingLeft))
                    {
                        //character changed the direction they're facing
                        c.KickAFKTimer = 0.0f;
                    }

                    newAim = msg.ReadUInt16();
                    if (newInput.HasFlag(InputNetFlags.Select) ||
                        newInput.HasFlag(InputNetFlags.Deselect) ||
                        newInput.HasFlag(InputNetFlags.Use) ||
                        newInput.HasFlag(InputNetFlags.Health) ||
                        newInput.HasFlag(InputNetFlags.Grab))
                    {
                        newInteract = msg.ReadUInt16();
                    }

                    if (NetIdUtils.IdMoreRecent((ushort)(networkUpdateID - i), LastNetworkUpdateID) && (i < 60))
                    {
                        if ((i > 0 && memInput[i - 1].intAim != newAim))
                        {
                            c.KickAFKTimer = 0.0f;
                        }
                        NetInputMem newMem = new NetInputMem
                        {
                            states          = newInput,
                            intAim          = newAim,
                            interact        = newInteract,
                            networkUpdateID = (ushort)(networkUpdateID - i)
                        };
                        memInput.Insert(i, newMem);
                        LastInputTime = Timing.TotalTime;
                    }
                }

                if (NetIdUtils.IdMoreRecent(networkUpdateID, LastNetworkUpdateID))
                {
                    LastNetworkUpdateID = networkUpdateID;
                }
                else if (NetIdUtils.Difference(networkUpdateID, LastNetworkUpdateID) > 500)
                {
#if DEBUG || UNSTABLE
                    DebugConsole.AddWarning($"Large disrepancy between a client character's network update ID server-side and client-side (client: {networkUpdateID}, server: {LastNetworkUpdateID}). Resetting the ID.");
#endif
                    LastNetworkUpdateID = networkUpdateID;
                }
                if (memInput.Count > 60)
                {
                    //deleting inputs from the queue here means the server is way behind and data needs to be dropped
                    //we'll make the server drop down to 30 inputs for good measure
                    memInput.RemoveRange(30, memInput.Count - 30);
                }
                break;

            case ClientNetObject.ENTITY_STATE:
                int eventType = msg.ReadRangedInteger(0, 4);
                switch (eventType)
                {
                case 0:
                    Inventory.ServerRead(type, msg, c);
                    break;

                case 1:
                    bool doingCPR = msg.ReadBoolean();
                    if (c.Character != this)
                    {
#if DEBUG
                        DebugConsole.Log("Received a character update message from a client who's not controlling the character");
#endif
                        return;
                    }

                    AnimController.Anim = doingCPR ? AnimController.Animation.CPR : AnimController.Animation.None;
                    break;

                case 2:
                    if (c.Character != this)
                    {
#if DEBUG
                        DebugConsole.Log("Received a character update message from a client who's not controlling the character");
#endif
                        return;
                    }

                    if (IsIncapacitated)
                    {
                        var causeOfDeath = CharacterHealth.GetCauseOfDeath();
                        Kill(causeOfDeath.type, causeOfDeath.affliction);
                    }
                    break;

                case 3:         // NetEntityEvent.Type.UpdateTalents
                    if (c.Character != this)
                    {
#if DEBUG
                        DebugConsole.Log("Received a character update message from a client who's not controlling the character");
#endif
                        return;
                    }

                    // get the full list of talents from the player, only give the ones
                    // that are not already given (or otherwise not viable)
                    ushort        talentCount     = msg.ReadUInt16();
                    List <string> talentSelection = new List <string>();
                    for (int i = 0; i < talentCount; i++)
                    {
                        UInt32 talentIdentifier = msg.ReadUInt32();
                        var    prefab           = TalentPrefab.TalentPrefabs.Find(p => p.UIntIdentifier == talentIdentifier);
                        if (prefab != null)
                        {
                            talentSelection.Add(prefab.Identifier);
                        }
                    }
                    talentSelection = TalentTree.CheckTalentSelection(this, talentSelection);

                    foreach (string talent in talentSelection)
                    {
                        GiveTalent(talent);
                    }

                    break;
                }
                break;
            }
            msg.ReadPadBits();
        }
Exemplo n.º 8
0
        //used when clients use the water/fire console commands or section / decal updates are received
        public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            int messageType = msg.ReadRangedInteger(0, 2);

            if (messageType == 0)
            {
                float newWaterVolume = msg.ReadRangedSingle(0.0f, 1.5f, 8) * Volume;

                bool           hasFireSources  = msg.ReadBoolean();
                int            fireSourceCount = 0;
                List <Vector3> newFireSources  = new List <Vector3>();
                if (hasFireSources)
                {
                    fireSourceCount = msg.ReadRangedInteger(0, 16);
                    for (int i = 0; i < fireSourceCount; i++)
                    {
                        newFireSources.Add(new Vector3(
                                               MathHelper.Clamp(msg.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
                                               MathHelper.Clamp(msg.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
                                               msg.ReadRangedSingle(0.0f, 1.0f, 8)));
                    }
                }

                if (!c.HasPermission(ClientPermissions.ConsoleCommands) ||
                    !c.PermittedConsoleCommands.Any(command => command.names.Contains("fire") || command.names.Contains("editfire")))
                {
                    return;
                }

                WaterVolume = newWaterVolume;

                for (int i = 0; i < fireSourceCount; i++)
                {
                    Vector2 pos = new Vector2(
                        rect.X + rect.Width * newFireSources[i].X,
                        rect.Y - rect.Height + (rect.Height * newFireSources[i].Y));
                    float size = newFireSources[i].Z * rect.Width;

                    var newFire = i < FireSources.Count ?
                                  FireSources[i] :
                                  new FireSource(Submarine == null ? pos : pos + Submarine.Position, null, true);
                    newFire.Position = pos;
                    newFire.Size     = new Vector2(size, newFire.Size.Y);

                    //ignore if the fire wasn't added to this room (invalid position)?
                    if (!FireSources.Contains(newFire))
                    {
                        newFire.Remove();
                        continue;
                    }
                }

                for (int i = FireSources.Count - 1; i >= fireSourceCount; i--)
                {
                    FireSources[i].Remove();
                    if (i < FireSources.Count)
                    {
                        FireSources.RemoveAt(i);
                    }
                }
            }
            else if (messageType == 1)
            {
                byte  decalIndex = msg.ReadByte();
                float decalAlpha = msg.ReadRangedSingle(0.0f, 1.0f, 255);
                if (decalIndex < 0 || decalIndex >= decals.Count)
                {
                    return;
                }
                if (c.Character != null && c.Character.AllowInput && c.Character.SelectedItems.Any(it => it?.GetComponent <Sprayer>() != null))
                {
                    decals[decalIndex].BaseAlpha = decalAlpha;
                }
                decalUpdatePending = true;
            }
            else
            {
                int sectorToUpdate = msg.ReadRangedInteger(0, BackgroundSections.Count - 1);
                int start          = sectorToUpdate * BackgroundSectionsPerNetworkEvent;
                int end            = Math.Min((sectorToUpdate + 1) * BackgroundSectionsPerNetworkEvent, BackgroundSections.Count - 1);
                for (int i = start; i < end; i++)
                {
                    float colorStrength = msg.ReadRangedSingle(0.0f, 1.0f, 8);
                    Color color         = new Color(msg.ReadUInt32());

                    //TODO: verify the client is close enough to this hull to paint it, that the sprayer is functional and that the color matches
                    if (c.Character != null && c.Character.AllowInput && c.Character.SelectedItems.Any(it => it?.GetComponent <Sprayer>() != null))
                    {
                        BackgroundSections[i].SetColorStrength(colorStrength);
                        BackgroundSections[i].SetColor(color);
                    }
                }
                //add to pending updates to notify other clients as well
                pendingSectionUpdates.Add(sectorToUpdate);
            }
        }
Exemplo n.º 9
0
        public virtual void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
        {
            switch (type)
            {
            case ServerNetObject.ENTITY_POSITION:
                bool facingRight = AnimController.Dir > 0.0f;

                lastRecvPositionUpdateTime = (float)Lidgren.Network.NetTime.Now;

                AnimController.Frozen = false;
                Enabled = true;

                UInt16 networkUpdateID = 0;
                if (msg.ReadBoolean())
                {
                    networkUpdateID = msg.ReadUInt16();
                }
                else
                {
                    bool aimInput = msg.ReadBoolean();
                    keys[(int)InputType.Aim].Held = aimInput;
                    keys[(int)InputType.Aim].SetState(false, aimInput);

                    bool shootInput = msg.ReadBoolean();
                    keys[(int)InputType.Shoot].Held = shootInput;
                    keys[(int)InputType.Shoot].SetState(false, shootInput);

                    bool useInput = msg.ReadBoolean();
                    keys[(int)InputType.Use].Held = useInput;
                    keys[(int)InputType.Use].SetState(false, useInput);

                    if (AnimController is HumanoidAnimController)
                    {
                        bool crouching = msg.ReadBoolean();
                        keys[(int)InputType.Crouch].Held = crouching;
                        keys[(int)InputType.Crouch].SetState(false, crouching);
                    }

                    bool attackInput = msg.ReadBoolean();
                    keys[(int)InputType.Attack].Held = attackInput;
                    keys[(int)InputType.Attack].SetState(false, attackInput);

                    double aimAngle = msg.ReadUInt16() / 65535.0 * 2.0 * Math.PI;
                    cursorPosition = AimRefPosition + new Vector2((float)Math.Cos(aimAngle), (float)Math.Sin(aimAngle)) * 500.0f;
                    TransformCursorPos();

                    bool ragdollInput = msg.ReadBoolean();
                    keys[(int)InputType.Ragdoll].Held = ragdollInput;
                    keys[(int)InputType.Ragdoll].SetState(false, ragdollInput);

                    facingRight = msg.ReadBoolean();
                }

                bool      entitySelected    = msg.ReadBoolean();
                Character selectedCharacter = null;
                Item      selectedItem      = null;

                AnimController.Animation animation = AnimController.Animation.None;
                if (entitySelected)
                {
                    ushort characterID = msg.ReadUInt16();
                    ushort itemID      = msg.ReadUInt16();
                    selectedCharacter = FindEntityByID(characterID) as Character;
                    selectedItem      = FindEntityByID(itemID) as Item;
                    if (characterID != NullEntityID)
                    {
                        bool doingCpr = msg.ReadBoolean();
                        if (doingCpr && SelectedCharacter != null)
                        {
                            animation = AnimController.Animation.CPR;
                        }
                    }
                }

                Vector2 pos = new Vector2(
                    msg.ReadSingle(),
                    msg.ReadSingle());
                float   MaxVel         = NetConfig.MaxPhysicsBodyVelocity;
                Vector2 linearVelocity = new Vector2(
                    msg.ReadRangedSingle(-MaxVel, MaxVel, 12),
                    msg.ReadRangedSingle(-MaxVel, MaxVel, 12));
                linearVelocity = NetConfig.Quantize(linearVelocity, -MaxVel, MaxVel, 12);

                bool  fixedRotation   = msg.ReadBoolean();
                float?rotation        = null;
                float?angularVelocity = null;
                if (!fixedRotation)
                {
                    rotation = msg.ReadSingle();
                    float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity;
                    angularVelocity = msg.ReadRangedSingle(-MaxAngularVel, MaxAngularVel, 8);
                    angularVelocity = NetConfig.Quantize(angularVelocity.Value, -MaxAngularVel, MaxAngularVel, 8);
                }

                bool readStatus = msg.ReadBoolean();
                if (readStatus)
                {
                    ReadStatus(msg);
                    AIController?.ClientRead(msg);
                }

                msg.ReadPadBits();

                int index = 0;
                if (GameMain.Client.Character == this && CanMove)
                {
                    var posInfo = new CharacterStateInfo(
                        pos, rotation,
                        networkUpdateID,
                        facingRight ? Direction.Right : Direction.Left,
                        selectedCharacter, selectedItem, animation);

                    while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID))
                    {
                        index++;
                    }
                    memState.Insert(index, posInfo);
                }
                else
                {
                    var posInfo = new CharacterStateInfo(
                        pos, rotation,
                        linearVelocity, angularVelocity,
                        sendingTime, facingRight ? Direction.Right : Direction.Left,
                        selectedCharacter, selectedItem, animation);

                    while (index < memState.Count && posInfo.Timestamp > memState[index].Timestamp)
                    {
                        index++;
                    }
                    memState.Insert(index, posInfo);
                }

                break;

            case ServerNetObject.ENTITY_EVENT:
                int eventType = msg.ReadRangedInteger(0, 13);
                switch (eventType)
                {
                case 0:         //NetEntityEvent.Type.InventoryState
                    if (Inventory == null)
                    {
                        string errorMsg = "Received an inventory update message for an entity with no inventory (" + Name + ", removed: " + Removed + ")";
                        DebugConsole.ThrowError(errorMsg);
                        GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ClientRead:NoInventory" + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);

                        //read anyway to prevent messing up reading the rest of the message
                        _ = msg.ReadUInt16();
                        byte inventoryItemCount = msg.ReadByte();
                        for (int i = 0; i < inventoryItemCount; i++)
                        {
                            msg.ReadUInt16();
                        }
                    }
                    else
                    {
                        Inventory.ClientRead(type, msg, sendingTime);
                    }
                    break;

                case 1:         //NetEntityEvent.Type.Control
                    byte ownerID = msg.ReadByte();
                    ResetNetState();
                    if (ownerID == GameMain.Client.ID)
                    {
                        if (controlled != null)
                        {
                            LastNetworkUpdateID = controlled.LastNetworkUpdateID;
                        }

                        if (!IsDead)
                        {
                            Controlled = this;
                        }
                        IsRemotePlayer                          = false;
                        GameMain.Client.HasSpawned              = true;
                        GameMain.Client.Character               = this;
                        GameMain.LightManager.LosEnabled        = true;
                        GameMain.LightManager.LosAlpha          = 1f;
                        GameMain.Client.WaitForNextRoundRespawn = null;
                    }
                    else
                    {
                        if (controlled == this)
                        {
                            Controlled     = null;
                            IsRemotePlayer = ownerID > 0;
                        }
                    }
                    break;

                case 2:         //NetEntityEvent.Type.Status
                    ReadStatus(msg);
                    break;

                case 3:         //NetEntityEvent.Type.UpdateSkills
                    int skillCount = msg.ReadByte();
                    for (int i = 0; i < skillCount; i++)
                    {
                        string skillIdentifier = msg.ReadString();
                        float  skillLevel      = msg.ReadSingle();
                        info?.SetSkillLevel(skillIdentifier, skillLevel);
                    }
                    break;

                case 4:         // NetEntityEvent.Type.SetAttackTarget
                case 5:         //NetEntityEvent.Type.ExecuteAttack
                    int     attackLimbIndex = msg.ReadByte();
                    UInt16  targetEntityID  = msg.ReadUInt16();
                    int     targetLimbIndex = msg.ReadByte();
                    Vector2 targetSimPos    = new Vector2(msg.ReadSingle(), msg.ReadSingle());
                    //255 = entity already removed, no need to do anything
                    if (attackLimbIndex == 255 || Removed)
                    {
                        break;
                    }
                    if (attackLimbIndex >= AnimController.Limbs.Length)
                    {
                        DebugConsole.ThrowError($"Received invalid SetAttack/ExecuteAttack message. Limb index out of bounds (character: {Name}, limb index: {attackLimbIndex}, limb count: {AnimController.Limbs.Length})");
                        break;
                    }
                    Limb attackLimb = AnimController.Limbs[attackLimbIndex];
                    Limb targetLimb = null;
                    if (!(FindEntityByID(targetEntityID) is IDamageable targetEntity))
                    {
                        DebugConsole.ThrowError($"Received invalid SetAttack/ExecuteAttack message. Target entity not found (ID {targetEntityID})");
                        break;
                    }
                    if (targetEntity is Character targetCharacter)
                    {
                        if (targetLimbIndex >= targetCharacter.AnimController.Limbs.Length)
                        {
                            DebugConsole.ThrowError($"Received invalid SetAttack/ExecuteAttack message. Target limb index out of bounds (target character: {targetCharacter.Name}, limb index: {targetLimbIndex}, limb count: {targetCharacter.AnimController.Limbs.Length})");
                            break;
                        }
                        targetLimb = targetCharacter.AnimController.Limbs[targetLimbIndex];
                    }
                    if (attackLimb?.attack != null && Controlled != this)
                    {
                        if (eventType == 4)
                        {
                            SetAttackTarget(attackLimb, targetEntity, targetSimPos);
                            PlaySound(CharacterSound.SoundType.Attack, maxInterval: 3);
                        }
                        else
                        {
                            attackLimb.ExecuteAttack(targetEntity, targetLimb, out _);
                        }
                    }
                    break;

                case 6:         //NetEntityEvent.Type.AssignCampaignInteraction
                    byte campaignInteractionType = msg.ReadByte();
                    bool requireConsciousness    = msg.ReadBoolean();
                    (GameMain.GameSession?.GameMode as CampaignMode)?.AssignNPCMenuInteraction(this, (CampaignMode.InteractionType)campaignInteractionType);
                    RequireConsciousnessForCustomInteract = requireConsciousness;
                    break;

                case 7:         //NetEntityEvent.Type.ObjectiveManagerState
                    // 1 = order, 2 = objective
                    int msgType = msg.ReadRangedInteger(0, 2);
                    if (msgType == 0)
                    {
                        break;
                    }
                    bool validData = msg.ReadBoolean();
                    if (!validData)
                    {
                        break;
                    }
                    if (msgType == 1)
                    {
                        int    orderIndex  = msg.ReadRangedInteger(0, Order.PrefabList.Count);
                        var    orderPrefab = Order.PrefabList[orderIndex];
                        string option      = null;
                        if (orderPrefab.HasOptions)
                        {
                            int optionIndex = msg.ReadRangedInteger(-1, orderPrefab.AllOptions.Length);
                            if (optionIndex > -1)
                            {
                                option = orderPrefab.AllOptions[optionIndex];
                            }
                        }
                        GameMain.GameSession?.CrewManager?.SetOrderHighlight(this, orderPrefab.Identifier, option);
                    }
                    else if (msgType == 2)
                    {
                        string identifier = msg.ReadString();
                        string option     = msg.ReadString();
                        ushort objectiveTargetEntityId = msg.ReadUInt16();
                        var    objectiveTargetEntity   = FindEntityByID(objectiveTargetEntityId);
                        GameMain.GameSession?.CrewManager?.CreateObjectiveIcon(this, identifier, option, objectiveTargetEntity);
                    }
                    break;

                case 8:         //NetEntityEvent.Type.TeamChange
                    byte newTeamId = msg.ReadByte();
                    ChangeTeam((CharacterTeamType)newTeamId);
                    break;

                case 9:         //NetEntityEvent.Type.AddToCrew
                    GameMain.GameSession.CrewManager.AddCharacter(this);
                    CharacterTeamType teamID    = (CharacterTeamType)msg.ReadByte();
                    ushort            itemCount = msg.ReadUInt16();
                    for (int i = 0; i < itemCount; i++)
                    {
                        ushort itemID = msg.ReadUInt16();
                        if (!(Entity.FindEntityByID(itemID) is Item item))
                        {
                            continue;
                        }
                        item.AllowStealing = true;
                        var wifiComponent = item.GetComponent <WifiComponent>();
                        if (wifiComponent != null)
                        {
                            wifiComponent.TeamID = teamID;
                        }
                        var idCard = item.GetComponent <IdCard>();
                        if (idCard != null)
                        {
                            idCard.TeamID = teamID;
                            idCard.SubmarineSpecificID = 0;
                        }
                    }
                    break;

                case 10:         //NetEntityEvent.Type.UpdateExperience
                    int experienceAmount = msg.ReadInt32();
                    info?.SetExperience(experienceAmount);
                    break;

                case 11:         //NetEntityEvent.Type.UpdateTalents:
                    ushort talentCount = msg.ReadUInt16();
                    for (int i = 0; i < talentCount; i++)
                    {
                        bool   addedThisRound   = msg.ReadBoolean();
                        UInt32 talentIdentifier = msg.ReadUInt32();
                        GiveTalent(talentIdentifier, addedThisRound);
                    }
                    break;

                case 12:         //NetEntityEvent.Type.UpdateMoney:
                    int moneyAmount = msg.ReadInt32();
                    SetMoney(moneyAmount);
                    break;

                case 13:         //NetEntityEvent.Type.UpdatePermanentStats:
                    byte      savedStatValueCount = msg.ReadByte();
                    StatTypes statType            = (StatTypes)msg.ReadByte();
                    info?.ClearSavedStatValues(statType);
                    for (int i = 0; i < savedStatValueCount; i++)
                    {
                        string statIdentifier = msg.ReadString();
                        float  statValue      = msg.ReadSingle();
                        bool   removeOnDeath  = msg.ReadBoolean();
                        info?.ChangeSavedStatValue(statType, statValue, statIdentifier, removeOnDeath, setValue: true);
                    }
                    break;
                }
                msg.ReadPadBits();
                break;
            }
        }
Exemplo n.º 10
0
        protected void ReadConnectionInitializationStep(IReadMessage inc)
        {
            ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte();

            IWriteMessage outMsg;

            switch (step)
            {
            case ConnectionInitialization.SteamTicketAndVersion:
                if (initializationStep != ConnectionInitialization.SteamTicketAndVersion)
                {
                    return;
                }
                outMsg = new WriteOnlyMessage();
                outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
                outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion);
                outMsg.Write(Name);
                outMsg.Write(ownerKey);
                outMsg.Write(SteamManager.GetSteamID());
                if (steamAuthTicket == null)
                {
                    outMsg.Write((UInt16)0);
                }
                else
                {
                    outMsg.Write((UInt16)steamAuthTicket.Data.Length);
                    outMsg.Write(steamAuthTicket.Data, 0, steamAuthTicket.Data.Length);
                }
                outMsg.Write(GameMain.Version.ToString());
                outMsg.Write(GameMain.Config.Language);

                SendMsgInternal(DeliveryMethod.Reliable, outMsg);
                break;

            case ConnectionInitialization.ContentPackageOrder:
                if (initializationStep == ConnectionInitialization.SteamTicketAndVersion ||
                    initializationStep == ConnectionInitialization.Password)
                {
                    initializationStep = ConnectionInitialization.ContentPackageOrder;
                }
                if (initializationStep != ConnectionInitialization.ContentPackageOrder)
                {
                    return;
                }
                outMsg = new WriteOnlyMessage();
                outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
                outMsg.Write((byte)ConnectionInitialization.ContentPackageOrder);

                string serverName = inc.ReadString();

                UInt32 cpCount = inc.ReadVariableUInt32();
                ServerContentPackage        corePackage     = null;
                List <ServerContentPackage> regularPackages = new List <ServerContentPackage>();
                List <ServerContentPackage> missingPackages = new List <ServerContentPackage>();
                for (int i = 0; i < cpCount; i++)
                {
                    string   name                   = inc.ReadString();
                    string   hash                   = inc.ReadString();
                    UInt64   workshopId             = inc.ReadUInt64();
                    UInt32   installTimeDiffSeconds = inc.ReadUInt32();
                    DateTime installTime            = DateTime.UtcNow + TimeSpan.FromSeconds(installTimeDiffSeconds);

                    var pkg = new ServerContentPackage(name, hash, workshopId, installTime);
                    if (pkg.CorePackage != null)
                    {
                        corePackage = pkg;
                    }
                    else if (pkg.RegularPackage != null)
                    {
                        regularPackages.Add(pkg);
                    }
                    else
                    {
                        missingPackages.Add(pkg);
                    }
                }

                if (missingPackages.Count > 0)
                {
                    var nonDownloadable         = missingPackages.Where(p => p.WorkshopId == 0);
                    var mismatchedButDownloaded = missingPackages.Where(remote =>
                    {
                        return(ContentPackage.AllPackages.Any(local =>
                                                              local.SteamWorkshopId != 0 &&                 /* is a Workshop item */
                                                              remote.WorkshopId == local.SteamWorkshopId && /* ids match */
                                                              remote.InstallTime < local.InstallTime /* remote is older than local */));
                    });

                    if (mismatchedButDownloaded.Any())
                    {
                        string disconnectMsg;
                        if (mismatchedButDownloaded.Count() == 1)
                        {
                            disconnectMsg = $"DisconnectMessage.MismatchedWorkshopMod~[incompatiblecontentpackage]={GetPackageStr(mismatchedButDownloaded.First())}";
                        }
                        else
                        {
                            List <string> packageStrs = new List <string>();
                            mismatchedButDownloaded.ForEach(cp => packageStrs.Add(GetPackageStr(cp)));
                            disconnectMsg = $"DisconnectMessage.MismatchedWorkshopMods~[incompatiblecontentpackages]={string.Join(", ", packageStrs)}";
                        }
                        Close(disconnectMsg, disableReconnect: true);
                        OnDisconnectMessageReceived?.Invoke(DisconnectReason.MissingContentPackage + "/" + disconnectMsg);
                    }
                    else if (nonDownloadable.Any())
                    {
                        string disconnectMsg;
                        if (nonDownloadable.Count() == 1)
                        {
                            disconnectMsg = $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(nonDownloadable.First())}";
                        }
                        else
                        {
                            List <string> packageStrs = new List <string>();
                            nonDownloadable.ForEach(cp => packageStrs.Add(GetPackageStr(cp)));
                            disconnectMsg = $"DisconnectMessage.MissingContentPackages~[missingcontentpackages]={string.Join(", ", packageStrs)}";
                        }
                        Close(disconnectMsg, disableReconnect: true);
                        OnDisconnectMessageReceived?.Invoke(DisconnectReason.MissingContentPackage + "/" + disconnectMsg);
                    }
                    else
                    {
                        Close(disableReconnect: true);

                        string missingModNames   = "\n";
                        int    displayedModCount = 0;
                        foreach (ServerContentPackage missingPackage in missingPackages)
                        {
                            missingModNames += "\n- " + GetPackageStr(missingPackage);
                            displayedModCount++;
                            if (GUI.Font.MeasureString(missingModNames).Y > GameMain.GraphicsHeight * 0.5f)
                            {
                                missingModNames += "\n\n" + TextManager.GetWithVariable("workshopitemdownloadprompttruncated", "[number]", (missingPackages.Count - displayedModCount).ToString());
                                break;
                            }
                        }
                        missingModNames += "\n\n";

                        var msgBox = new GUIMessageBox(
                            TextManager.Get("WorkshopItemDownloadTitle"),
                            TextManager.GetWithVariable("WorkshopItemDownloadPrompt", "[items]", missingModNames),
                            new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
                        msgBox.Buttons[0].OnClicked = (yesBtn, userdata) =>
                        {
                            GameMain.ServerListScreen.Select();
                            IEnumerable <ServerListScreen.PendingWorkshopDownload> downloads =
                                missingPackages.Select(p => new ServerListScreen.PendingWorkshopDownload(p.Hash, p.WorkshopId));
                            GameMain.ServerListScreen.DownloadWorkshopItems(downloads, serverName, ServerConnection.EndPointString);
                            return(true);
                        };
                        msgBox.Buttons[0].OnClicked += msgBox.Close;
                        msgBox.Buttons[1].OnClicked  = msgBox.Close;
                    }

                    return;
                }

                if (!contentPackageOrderReceived)
                {
                    GameMain.Config.BackUpModOrder();
                    GameMain.Config.SwapPackages(corePackage.CorePackage, regularPackages.Select(p => p.RegularPackage).ToList());
                    contentPackageOrderReceived = true;
                }

                SendMsgInternal(DeliveryMethod.Reliable, outMsg);
                break;

            case ConnectionInitialization.Password:
                if (initializationStep == ConnectionInitialization.SteamTicketAndVersion)
                {
                    initializationStep = ConnectionInitialization.Password;
                }
                if (initializationStep != ConnectionInitialization.Password)
                {
                    return;
                }
                bool incomingSalt = inc.ReadBoolean(); inc.ReadPadBits();
                int  retries      = 0;
                if (incomingSalt)
                {
                    passwordSalt = inc.ReadInt32();
                }
                else
                {
                    retries = inc.ReadInt32();
                }
                OnRequestPassword?.Invoke(passwordSalt, retries);
                break;
            }
        }