private static void ServerRemoveMemberNoChecks(string characterName, ILogicObject faction) { var factionPrivateState = Faction.GetPrivateState(faction); var members = factionPrivateState.Members; for (var index = 0; index < members.Count; index++) { var entry = members[index]; if (!string.Equals(entry.Name, characterName, StringComparison.Ordinal)) { continue; } if (entry.Role == FactionMemberRole.Leader) { } // member found members.RemoveAt(index); Faction.GetPublicState(faction).PlayersNumberCurrent--; Logger.Important($"Faction member removed: {characterName} from {faction}"); var character = Server.Characters.GetPlayerCharacter(characterName); if (character is not null) { // record the time when player has left or was removed from the faction factionPrivateState.ServerPlayerLeaveDateDictionary[character.Id] = Server.Game.FrameTime; ServerCharacterFactionDictionary.Remove(character); PlayerCharacter.GetPublicState(character).ClanTag = null; PlayerCharacter.GetPrivateState(character).LastFactionLeaveTime = Server.Game.FrameTime; // remove all requests by this character ServerInvitations.RemoveAllInvitationsBy(character, faction); Api.SafeInvoke( () => ServerCharacterJoinedOrLeftFaction?.Invoke(character, faction, isJoined: false)); Api.SafeInvoke( () => ServerFactionMemberAccessRightsChanged?.Invoke(faction, characterName, FactionMemberAccessRights.None)); Server.World.ForceExitScope(character, faction); // send "no faction" for this player ServerSendCurrentFaction(character); ChatSystem.ServerRemoveChatRoomFromPlayerScope(character, ServerGetFactionChat(faction)); } if (members.Count == 0) { ServerRemoveFaction(faction); } return; } Logger.Warning($"Faction member is not found: {characterName} in {faction}"); }
private static void ServerAddMember( ICharacter character, ILogicObject faction, FactionMemberRole role) { Api.Assert(!character.IsNpc, "NPC cannot join a faction"); if (!SharedIsValidRole(role)) { throw new Exception("Invalid role: " + role); } var currentFaction = ServerGetFaction(character); if (currentFaction == faction) { // already in faction return; } if (currentFaction is not null) { throw new Exception($"Player already has a faction: {character} in {faction}"); } // faction members cannot have a newbie protection NewbieProtectionSystem.ServerDisableNewbieProtection(character); var members = ServerGetFactionMembersEditable(faction); var factionPublicState = Faction.GetPublicState(faction); var maxMembers = FactionConstants.SharedGetFactionMembersMax(factionPublicState.Kind); if (members.Count >= maxMembers) { throw new Exception("Faction size exceeded - max " + maxMembers); } if (role == FactionMemberRole.Leader) { foreach (var otherMember in members) { if (otherMember.Role == FactionMemberRole.Leader) { throw new Exception("Faction can have only a single leader"); } } } members.Add(new FactionMemberEntry(character.Name, role)); ServerCharacterFactionDictionary[character] = faction; PlayerCharacter.GetPublicState(character).ClanTag = factionPublicState.ClanTag; factionPublicState.PlayersNumberCurrent++; Logger.Important($"Player joined faction: {character} in {faction} - role: {role}", character); ServerInvitations.RemoveAllInvitationsFor(character); Api.SafeInvoke( () => ServerCharacterJoinedOrLeftFaction?.Invoke(character, faction, isJoined: true)); // add this with some delay to prevent from the bug when the player name listed twice due to the late delta-replication ServerTimersSystem.AddAction(delaySeconds: 0.1, () => ServerSendCurrentFaction(character)); }