Ejemplo n.º 1
0
        private void SendKarmaNotifications(Client client, string debugKarmaChangeReason = "")
        {
            //send a notification about karma changing if the karma has changed by x%

            var   clientMemory = GetClientMemory(client);
            float karmaChange  = client.Karma - clientMemory.PreviousNotifiedKarma;

            if (Math.Abs(karmaChange) > 1.0f && TestMode)
            {
                string msg =
                    karmaChange < 0 ? $"Your karma has decreased to {client.Karma}" : $"Your karma has increased to {client.Karma}";
                if (!string.IsNullOrEmpty(debugKarmaChangeReason))
                {
                    msg += $". Reason: {debugKarmaChangeReason}";
                }
                GameMain.Server.SendDirectChatMessage(msg, client);
                clientMemory.PreviousNotifiedKarma         = client.Karma;
                clientMemory.PreviousKarmaNotificationTime = Timing.TotalTime;
            }
            else if (Timing.TotalTime >= clientMemory.PreviousKarmaNotificationTime + 5.0f &&
                     clientMemory.PreviousNotifiedKarma >= KickBanThreshold + KarmaNotificationInterval &&
                     client.Karma < KickBanThreshold + KarmaNotificationInterval)
            {
                GameMain.Server.SendDirectChatMessage(TextManager.Get("KarmaBanWarning"), client);
                GameServer.Log(GameServer.ClientLogName(client) + " has been warned for having dangerously low karma.", ServerLog.MessageType.Karma);
                clientMemory.PreviousNotifiedKarma         = client.Karma;
                clientMemory.PreviousKarmaNotificationTime = Timing.TotalTime;
            }
        }
Ejemplo n.º 2
0
        private void AdjustKarma(Character target, float amount, string debugKarmaChangeReason = "")
        {
            if (target == null)
            {
                return;
            }

            Client client = GameMain.Server.ConnectedClients.Find(c => c.Character == target);

            if (client == null)
            {
                return;
            }

            //all penalties/rewards are halved when wearing a clown costume
            if (target.HasEquippedItem("clownmask") &&
                target.HasEquippedItem("clowncostume"))
            {
                amount *= 0.5f;
            }

            client.Karma += amount;

            if (amount < 0.0f)
            {
                float?herpesStrength = client.Character?.CharacterHealth.GetAfflictionStrength("spaceherpes");
                var   clientMemory   = GetClientMemory(client);
                clientMemory.KarmaDecreasesInPastMinute.RemoveAll(ta => ta.Time + 60.0f < Timing.TotalTime);
                float aggregate = clientMemory.KarmaDecreasesInPastMinute.Select(ta => ta.Amount).DefaultIfEmpty().Aggregate((a, b) => a + b);
                clientMemory.KarmaDecreasesInPastMinute.Add(new ClientMemory.TimeAmount()
                {
                    Time = Timing.TotalTime, Amount = -amount
                });

                if (herpesStrength.HasValue && herpesStrength <= 0.0f && aggregate - amount > 25.0f && aggregate <= 25.0f)
                {
                    GameServer.Log($"{GameServer.ClientLogName(client)} has lost more than 25 karma in the past minute.", ServerLog.MessageType.Karma);
                }
            }

            if (TestMode)
            {
                SendKarmaNotifications(client, debugKarmaChangeReason);
            }
        }
Ejemplo n.º 3
0
        private void UpdateClient(Client client, float deltaTime)
        {
            if (client.Character != null && !client.Character.Removed && !client.Character.IsDead)
            {
                if (client.Karma > KarmaDecayThreshold)
                {
                    client.Karma -= KarmaDecay * deltaTime;
                }
                else if (client.Karma < KarmaIncreaseThreshold)
                {
                    client.Karma += KarmaIncrease * deltaTime;
                }

                //increase the strength of the herpes affliction in steps instead of linearly
                //otherwise clients could determine their exact karma value from the strength
                float herpesStrength = 0.0f;
                if (client.Karma < 20)
                {
                    herpesStrength = 100.0f;
                }
                else if (client.Karma < 30)
                {
                    herpesStrength = 60.0f;
                }
                else if (client.Karma < 40.0f)
                {
                    herpesStrength = 30.0f;
                }

                var existingAffliction = client.Character.CharacterHealth.GetAffliction <AfflictionSpaceHerpes>("spaceherpes");
                if (existingAffliction == null && herpesStrength > 0.0f)
                {
                    client.Character.CharacterHealth.ApplyAffliction(null, new Affliction(herpesAffliction, herpesStrength));
                    GameServer.Log($"{GameServer.ClientLogName(client)} has contracted space herpes due to low karma.", ServerLog.MessageType.Karma);
                    GameMain.NetworkMember.LastClientListUpdateID++;
                }
                else if (existingAffliction != null)
                {
                    existingAffliction.Strength = herpesStrength;
                    if (herpesStrength <= 0.0f)
                    {
                        client.Character.CharacterHealth.ReduceAffliction(null, "invertcontrols", 100.0f);
                    }
                }

                //check if the client has disconnected an excessive number of wires
                var clientMemory = GetClientMemory(client);
                if (clientMemory.WireDisconnectTime.Count > (int)AllowedWireDisconnectionsPerMinute)
                {
                    clientMemory.WireDisconnectTime.RemoveRange(0, clientMemory.WireDisconnectTime.Count - (int)AllowedWireDisconnectionsPerMinute);
                    if (clientMemory.WireDisconnectTime.All(w => Timing.TotalTime - w.Second < 60.0f))
                    {
                        float karmaDecrease = -WireDisconnectionKarmaDecrease;
                        //engineers don't lose as much karma for removing lots of wires
                        if (client.Character.Info?.Job.Prefab.Identifier == "engineer")
                        {
                            karmaDecrease *= 0.5f;
                        }
                        AdjustKarma(client.Character, karmaDecrease, "Disconnected excessive number of wires");
                    }
                }

                if (client.Character?.Info?.Job.Prefab.Identifier == "captain" && client.Character.SelectedConstruction != null)
                {
                    if (client.Character.SelectedConstruction.GetComponent <Steering>() != null)
                    {
                        AdjustKarma(client.Character, SteerSubKarmaIncrease * deltaTime, "Steering the sub");
                    }
                }
            }

            if (client.Karma < KickBanThreshold && client.Connection != GameMain.Server.OwnerConnection)
            {
                if (TestMode)
                {
                    client.Karma = 50.0f;
                    GameMain.Server.SendDirectChatMessage("BANNED! (not really because karma test mode is enabled)", client);
                }
                else
                {
                    bannedClients.Add(client);
                }
            }
        }
Ejemplo n.º 4
0
        public void ServerRead(IReadMessage inc, Client sender)
        {
            if (GameMain.Server == null || sender == null)
            {
                return;
            }

            byte     voteTypeByte = inc.ReadByte();
            VoteType voteType     = VoteType.Unknown;

            try
            {
                voteType = (VoteType)voteTypeByte;
            }
            catch (Exception e)
            {
                DebugConsole.ThrowError("Failed to cast vote type \"" + voteTypeByte + "\"", e);
                return;
            }

            switch (voteType)
            {
            case VoteType.Sub:
                string        subName = inc.ReadString();
                SubmarineInfo sub     = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName);
                sender.SetVote(voteType, sub);
                break;

            case VoteType.Mode:
                string         modeIdentifier = inc.ReadString();
                GameModePreset mode           = GameModePreset.List.Find(gm => gm.Identifier == modeIdentifier);
                if (!mode.Votable)
                {
                    break;
                }

                sender.SetVote(voteType, mode);
                break;

            case VoteType.EndRound:
                if (!sender.HasSpawned)
                {
                    return;
                }
                sender.SetVote(voteType, inc.ReadBoolean());

                GameMain.NetworkMember.EndVoteCount = GameMain.Server.ConnectedClients.Count(c => c.HasSpawned && c.GetVote <bool>(VoteType.EndRound));
                GameMain.NetworkMember.EndVoteMax   = GameMain.Server.ConnectedClients.Count(c => c.HasSpawned);

                break;

            case VoteType.Kick:
                byte kickedClientID = inc.ReadByte();

                Client kicked = GameMain.Server.ConnectedClients.Find(c => c.ID == kickedClientID);
                if (kicked != null && kicked.Connection != GameMain.Server.OwnerConnection && !kicked.HasKickVoteFrom(sender))
                {
                    kicked.AddKickVote(sender);
                    Client.UpdateKickVotes(GameMain.Server.ConnectedClients);
                    GameMain.Server.SendChatMessage($"ServerMessage.HasVotedToKick~[initiator]={sender.Name}~[target]={kicked.Name}", ChatMessageType.Server, null);
                }

                break;

            case VoteType.StartRound:
                bool ready = inc.ReadBoolean();
                if (ready != sender.GetVote <bool>(VoteType.StartRound))
                {
                    sender.SetVote(VoteType.StartRound, ready);
                    GameServer.Log(GameServer.ClientLogName(sender) + (ready ? " is ready to start the game." : " is not ready to start the game."), ServerLog.MessageType.ServerMessage);
                }
                break;

            case VoteType.PurchaseAndSwitchSub:
            case VoteType.PurchaseSub:
            case VoteType.SwitchSub:
                bool startVote = inc.ReadBoolean();
                if (startVote)
                {
                    StartSubmarineVote(inc, voteType, sender);
                }
                else
                {
                    sender.SetVote(voteType, (int)inc.ReadByte());
                }

                GameMain.Server.SubmarineVoteYesCount = GameMain.Server.ConnectedClients.Count(c => c.GetVote <int>(SubVote.VoteType) == 2);
                GameMain.Server.SubmarineVoteNoCount  = GameMain.Server.ConnectedClients.Count(c => c.GetVote <int>(SubVote.VoteType) == 1);
                GameMain.Server.SubmarineVoteMax      = GameMain.Server.ConnectedClients.Count(c => c.InGame);
                break;
            }

            inc.ReadPadBits();

            GameMain.Server.UpdateVoteStatus();
        }