From eccb2b8b615f77b2ecebf4d0dbcfad281800eef8 Mon Sep 17 00:00:00 2001 From: Brant Martin Date: Thu, 1 Jun 2017 12:30:45 -0400 Subject: [PATCH] Fix chat crash. Refactor reserved slot system. Admins and whitelisted players can simply bypass the player limit set on the server. --- EssentialsPlugin.sln.DotSettings | 74 ---- EssentialsPlugin/AssemblyFileVersion.cs | 6 +- EssentialsPlugin/Essentials.cs | 30 +- .../NetworkHandlers/SyncPropertyHandler.cs | 52 +-- .../ProcessHandlers/ProcessReservedSlots.cs | 363 +++++++++--------- EssentialsPlugin/Settings/PluginSettings.cs | 24 +- EssentialsPlugin/Utility/Communication.cs | 4 +- 7 files changed, 248 insertions(+), 305 deletions(-) delete mode 100644 EssentialsPlugin.sln.DotSettings diff --git a/EssentialsPlugin.sln.DotSettings b/EssentialsPlugin.sln.DotSettings deleted file mode 100644 index 9ec7834..0000000 --- a/EssentialsPlugin.sln.DotSettings +++ /dev/null @@ -1,74 +0,0 @@ - - False - False - True - True - True - True - True - True - SOLUTION - True - DO_NOT_SHOW - HINT - DO_NOT_SHOW - DO_NOT_SHOW - DO_NOT_SHOW - DO_NOT_SHOW - DoHide - <?xml version="1.0" encoding="utf-16"?><Profile name="Full Clean"><AspOptimizeRegisterDirectives>True</AspOptimizeRegisterDirectives><CSArrangeThisQualifier>True</CSArrangeThisQualifier><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSUpdateFileHeader>True</CSUpdateFileHeader><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><CSReorderTypeMembers>True</CSReorderTypeMembers><JsInsertSemicolon>True</JsInsertSemicolon><JsReformatCode>True</JsReformatCode><JsFormatDocComments>True</JsFormatDocComments><CssAlphabetizeProperties>True</CssAlphabetizeProperties><CssReformatCode>True</CssReformatCode><XMLReformatCode>True</XMLReformatCode><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><CSArrangeQualifiers>True</CSArrangeQualifiers><CSEnforceVarKeywordUsageSettings>True</CSEnforceVarKeywordUsageSettings><AgentSmithReflowAndRetagXMLDoc>True</AgentSmithReflowAndRetagXMLDoc><AgentSmithReflowXMLDoc>True</AgentSmithReflowXMLDoc></Profile> - True - True - True - True - True - True - True - True - True - True - True - True - True - True - True - True - True - True - True - True - False - True - UseExplicitType - UseExplicitType - UseExplicitType - False - True - Automatic property - True - Default body (from options) - True - True - True - False - True - True - True - 02/08/2016 18:25:09 - VS - 1 - <AssemblyExportHisory> - <ExportElement Assembly="130665497077728238|C:\USERS\BRANDON\DOWNLOADS\GAMES\SPACE ENGINEERS\SE-COMMUNITY-MOD-API\GAMELIBRARIES\SANDBOX.GAME.DLL" Project="C:\Users\Brandon\Downloads\Games\Space Engineers\Sandbox.Game\Sandbox.Game\Sandbox.Game.csproj" /> -</AssemblyExportHisory> - True - user_name - C:\Users\Brandon\AppData\Local\Temp\tmpC92C.tmp - youtrack@@FVL8jaRtGis=#user_name@Brandon Thetford@brandon<at>dodecatec.com#anonymous@user - True - C:\Users\Brandon\Downloads\Games\Space Engineers\Sandbox.Game - [0,10](300,320) - [-87,-76](1024,768) - CSharpCodeStyle2 - -90,-441 - False - True \ No newline at end of file diff --git a/EssentialsPlugin/AssemblyFileVersion.cs b/EssentialsPlugin/AssemblyFileVersion.cs index 10c2f4d..00227f5 100644 --- a/EssentialsPlugin/AssemblyFileVersion.cs +++ b/EssentialsPlugin/AssemblyFileVersion.cs @@ -1,4 +1,4 @@ -//421 +//430 // // This code was generated by a tool. Any changes made manually will be lost // the next time this code is regenerated. @@ -6,5 +6,5 @@ using System.Reflection; -[assembly: AssemblyFileVersion("1.13.7.421")] -[assembly: AssemblyVersion("1.13.7.421")] +[assembly: AssemblyFileVersion("1.13.7.430")] +[assembly: AssemblyVersion("1.13.7.430")] diff --git a/EssentialsPlugin/Essentials.cs b/EssentialsPlugin/Essentials.cs index 5d67718..8ae45ea 100644 --- a/EssentialsPlugin/Essentials.cs +++ b/EssentialsPlugin/Essentials.cs @@ -951,21 +951,21 @@ public bool ReservedSlotsEnabled } } - [Category( "Reserved Slots" )] - [Description( "Number of slots to reserve." )] - [Browsable( true )] - [ReadOnly( false )] - public int ReservedSlotsCount - { - get - { - return PluginSettings.Instance.ReservedSlotsCount; - } - set - { - PluginSettings.Instance.ReservedSlotsCount = value; - } - } + //[Category( "Reserved Slots" )] + //[Description( "Number of slots to reserve." )] + //[Browsable( true )] + //[ReadOnly( false )] + //public int ReservedSlotsCount + //{ + // get + // { + // return PluginSettings.Instance.ReservedSlotsCount; + // } + // set + // { + // PluginSettings.Instance.ReservedSlotsCount = value; + // } + //} [Category( "Reserved Slots" )] [Description( "Group ID number. Players in this group can occupy a reserved slot." )] diff --git a/EssentialsPlugin/NetworkHandlers/SyncPropertyHandler.cs b/EssentialsPlugin/NetworkHandlers/SyncPropertyHandler.cs index ed42387..48b40f0 100644 --- a/EssentialsPlugin/NetworkHandlers/SyncPropertyHandler.cs +++ b/EssentialsPlugin/NetworkHandlers/SyncPropertyHandler.cs @@ -61,44 +61,44 @@ public override bool Handle( ulong remoteUserId, CallSite site, BitStream stream { //TODO return false; - MyPropertySyncStateGroup sync = (MyPropertySyncStateGroup)obj; + //MyPropertySyncStateGroup sync = (MyPropertySyncStateGroup)obj; - var properties = (ListReader)sync.GetType().GetField("m_properties", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(sync); + //var properties = (ListReader)sync.GetType().GetField("m_properties", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(sync); - byte index = 0; - BitReaderWriter bits = new BitReaderWriter(); + //byte index = 0; + //BitReaderWriter bits = new BitReaderWriter(); - Serialize(site.MethodInfo, stream, ref index, ref bits); + //Serialize(site.MethodInfo, stream, ref index, ref bits); - MyTerminalBlock entity = null; + //MyTerminalBlock entity = null; - MyExternalReplicable rep = sync.Owner as MyExternalReplicable; + //MyExternalReplicable rep = sync.Owner as MyExternalReplicable; - if ( rep == null ) - { - //there are lots of reasons this wouldn't be MySyncedBlock, so just ignore it and move on - return false; - } + //if ( rep == null ) + //{ + // //there are lots of reasons this wouldn't be MySyncedBlock, so just ignore it and move on + // return false; + //} - entity = rep.Instance as MyTerminalBlock; + //entity = rep.Instance as MyTerminalBlock; - MyCubeGrid grid = entity?.CubeGrid; + //MyCubeGrid grid = entity?.CubeGrid; - if ( grid == null ) - { - Essentials.Log.Info( "Null grid in SyncPropertyHandler" ); - return false; - } + //if ( grid == null ) + //{ + // Essentials.Log.Info( "Null grid in SyncPropertyHandler" ); + // return false; + //} - Essentials.Log.Warn( $"{entity.CustomName} | {index} | {properties[index].ValueType}" ); + //Essentials.Log.Warn( $"{entity.CustomName} | {index} | {properties[index].ValueType}" ); - if (entity is MyLandingGear) - { - //clients sometimes send updates for landing gear for no discernable reason? - //just ignore it, it's mostly harmless - return false; - } + //if (entity is MyLandingGear) + //{ + // //clients sometimes send updates for landing gear for no discernable reason? + // //just ignore it, it's mostly harmless + // return false; + //} //bool found = false; //foreach ( ProtectedItem item in PluginSettings.Instance.ProtectedItems ) diff --git a/EssentialsPlugin/ProcessHandlers/ProcessReservedSlots.cs b/EssentialsPlugin/ProcessHandlers/ProcessReservedSlots.cs index bd55bf3..360535f 100644 --- a/EssentialsPlugin/ProcessHandlers/ProcessReservedSlots.cs +++ b/EssentialsPlugin/ProcessHandlers/ProcessReservedSlots.cs @@ -1,47 +1,53 @@ -namespace EssentialsPlugin.ProcessHandlers +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using Sandbox; +using Sandbox.Engine.Multiplayer; +using Sandbox.Game.World; +using SteamSDK; +using VRage.Game.ModAPI; +using VRage.Network; +using VRage.Utils; + +namespace EssentialsPlugin.ProcessHandlers { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Reflection; - using Sandbox.Engine.Multiplayer; - using Sandbox.Game.World; - using Sandbox.ModAPI; - using Settings; - using SEModAPI.API; - using SEModAPIExtensions.API; - using SEModAPIInternal.API.Common; - using SEModAPIInternal.API.Server; - using SteamSDK; - using VRage.Game.ModAPI; - using VRage.Network; - public class ProcessReservedSlots : ProcessHandlerBase { - private static List _reservedPlayers = new List( ); - private static List _waitingPlayers = new List( ); + private static List _reservedPlayers = new List(); + private static List _waitingPlayers = new List(); private static bool _init; - public static void Init( ) + private static string ConvertSteamIDFrom64(ulong from) + { + from -= 76561197960265728UL; + return new StringBuilder("STEAM_").Append("0:").Append(from % 2UL).Append(':').Append(from / 2UL).ToString(); + } + + public static void Init() { - if ( _init ) + if (_init) return; _init = true; - //RemoveHandlers(); + RemoveHandlers(); SteamServerAPI.Instance.GameServer.UserGroupStatus += GameServer_UserGroupStatus; SteamServerAPI.Instance.GameServer.ValidateAuthTicketResponse += GameServer_ValidateAuthTicketResponse; - Essentials.Log.Info( "Reserved slots initialized" ); + m_waitingForGroup = (HashSet)typeof(MyDedicatedServerBase).GetField("m_waitingForGroup", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(MyMultiplayer.Static); + m_groupId = (ulong)typeof(MyDedicatedServerBase).GetField("m_groupId", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(MyMultiplayer.Static); + + Essentials.Log.Info("Reserved slots initialized"); } private static void RemoveHandlers() { - var eventField = typeof(GameServer).GetField("ValidateAuthTicketResponse", BindingFlags.NonPublic | BindingFlags.Instance); + FieldInfo eventField = typeof(GameServer).GetField("ValidateAuthTicketResponse", BindingFlags.NonPublic | BindingFlags.Instance); var eventDel = eventField?.GetValue(SteamServerAPI.Instance.GameServer) as MulticastDelegate; if (eventDel != null) { - foreach (var handle in eventDel.GetInvocationList()) + foreach (Delegate handle in eventDel.GetInvocationList()) { if (handle.Method.Name == "GameServer_ValidateAuthTicketResponse") { @@ -50,183 +56,194 @@ private static void RemoveHandlers() } } } - } - private static void GameServer_ValidateAuthTicketResponse( ulong remoteUserId, AuthSessionResponseEnum response, - ulong ownerSteamId ) - { - //using the player join event takes too long, sometimes they can load in before we boot them - //we're not replacing the lobby yet, but hooking into this event will give us more time to verify players - - if ( !PluginSettings.Instance.ReservedSlotsEnabled ) - return; - - if ( response != AuthSessionResponseEnum.OK ) - return; - - if ( PluginSettings.Instance.ReservedSlotsPlayers.Contains( remoteUserId.ToString( ) ) ) - { - _reservedPlayers.Add( remoteUserId ); - Essentials.Log.Info( "Whitelisted player connected: " + remoteUserId ); - Essentials.Log.Info( "{0} whitelisted players connected. {1} of {2} reserved slots allocated.", - _reservedPlayers.Count, - Math.Min( _reservedPlayers.Count, PluginSettings.Instance.ReservedSlotsCount ), - PluginSettings.Instance.ReservedSlotsCount ); - return; - } - - if ( PluginSettings.Instance.TicketPlayers.Any( item => item.TicketId == remoteUserId ) ) - { - _reservedPlayers.Add(remoteUserId); - Essentials.Log.Info("Ticket player connected: " + remoteUserId); - Essentials.Log.Info("{0} whitelisted players connected. {1} of {2} reserved slots allocated.", - _reservedPlayers.Count, - Math.Min(_reservedPlayers.Count, PluginSettings.Instance.ReservedSlotsCount), - PluginSettings.Instance.ReservedSlotsCount); - return; - } - - if ( PluginSettings.Instance.ReservedSlotsAdmins && PlayerManager.Instance.IsUserAdmin( remoteUserId ) ) - { - _reservedPlayers.Add( remoteUserId ); - Essentials.Log.Info( "Whitelisted admin connected: " + remoteUserId ); - Essentials.Log.Info( "{0} whitelisted players connected. {1} of {2} reserved slots allocated.", - _reservedPlayers.Count, - Math.Min( _reservedPlayers.Count, PluginSettings.Instance.ReservedSlotsCount ), - PluginSettings.Instance.ReservedSlotsCount ); - - return; - } - - if ( PluginSettings.Instance.ReservedSlotsGroup != 0 ) + eventField = typeof(GameServer).GetField("UserGroupStatus", BindingFlags.NonPublic | BindingFlags.Instance); + eventDel = eventField?.GetValue(SteamServerAPI.Instance.GameServer) as MulticastDelegate; + if (eventDel != null) { - _waitingPlayers.Add( remoteUserId ); - - //ask Steam if the connecting player is in the whitelisted group. response is raised as an event; GameServer_UserGroupStatus - SteamServerAPI.Instance.GameServer.RequestGroupStatus( remoteUserId, - PluginSettings.Instance.ReservedSlotsGroup ); - return; + foreach (Delegate handle in eventDel.GetInvocationList()) + { + if (handle.Method.Name == "GameServer_UserGroupStatus") + { + SteamServerAPI.Instance.GameServer.ValidateAuthTicketResponse -= handle as ValidateAuthTicketResponse; + Essentials.Log.Warn("Removed handler from UserGroupSataus"); + } + } } - - DenyPlayer( remoteUserId ); } - /* - public override void OnPlayerJoined( ulong remoteUserId ) + private static ulong m_groupId; + private static HashSet m_waitingForGroup; + private static readonly HashSet _waitingForWhitelistGroup = new HashSet(); + + /// + /// Reimplementation of the vanilla event + /// + /// + /// + /// + private static void GameServer_ValidateAuthTicketResponse(ulong steamID, AuthSessionResponseEnum response, + ulong steamOwner) { - //it might be better to hook into ValidateAuthTicketResponse, but doing it this way lets the game - //take care of denying banned players and group/friend whitelisting - - if ( !PluginSettings.Instance.ReservedSlotsEnabled ) - return; - - if ( PluginSettings.Instance.ReservedSlotsPlayers.Contains( remoteUserId.ToString( ) ) ) + try { - reservedPlayers.Add( remoteUserId ); - Essentials.Log.Info( "Whitelisted player connected: " + remoteUserId.ToString( ) ); - Essentials.Log.Info( string.Format( "{0} whitelisted players connected. {1} of {2} reserved slots allocated.", - reservedPlayers.Count, Math.Min( reservedPlayers.Count, PluginSettings.Instance.ReservedSlotsCount ), PluginSettings.Instance.ReservedSlotsCount ) ); + MyLog.Default.WriteLineAndConsole($"Essentials ValidateAuthTicketResponse ({response}), owner: {steamOwner}"); - return; - } + if (IsClientBanned(steamOwner) || MySandboxGame.ConfigDedicated.Banned.Contains(steamOwner)) + { + UserRejected(steamID, JoinResult.BannedByAdmins); + RaiseClientKicked(steamID); + } + else + { + if (IsClientKicked(steamOwner)) + { + UserRejected(steamID, JoinResult.KickedRecently); + RaiseClientKicked(steamID); + } + } - if ( PluginSettings.Instance.ReservedSlotsAdmins && PlayerManager.Instance.IsUserAdmin( remoteUserId ) ) - { - reservedPlayers.Add( remoteUserId ); - Essentials.Log.Info( "Whitelisted admin connected: " + remoteUserId.ToString( ) ); - Essentials.Log.Info( string.Format( "{0} whitelisted players connected. {1} of {2} reserved slots allocated.", - reservedPlayers.Count, Math.Min( reservedPlayers.Count, PluginSettings.Instance.ReservedSlotsCount ), PluginSettings.Instance.ReservedSlotsCount ) ); + if (response == AuthSessionResponseEnum.OK) + { + if (MyMultiplayer.Static.MemberLimit > 0 && MyMultiplayer.Static.MemberCount - 1 >= MyMultiplayer.Static.MemberLimit) // Unfortunately, DS counds into the members, so subtract it + { + if (!PluginSettings.Instance.ReservedSlotsEnabled) + { + UserRejected(steamID, JoinResult.ServerFull); + return; + } + + if (PluginSettings.Instance.ReservedSlotsPlayers.Contains(steamID.ToString()) || PluginSettings.Instance.ReservedSlotsAdmins && MySession.Static.GetUserPromoteLevel(steamID) >= MyPromoteLevel.Admin) + { + Essentials.Log.Info($"Added whitelisted player {steamID}"); + UserAccepted(steamID); + } + else + { + if (PluginSettings.Instance.ReservedSlotsGroup != 0) + { + if (SteamServerAPI.Instance.GameServer.RequestGroupStatus(steamID, PluginSettings.Instance.ReservedSlotsGroup)) + { + // Returns false when there's no connection to Steam + _waitingForWhitelistGroup.Add(steamID); + } + else + UserRejected(steamID, JoinResult.SteamServersOffline); + } + else + UserRejected(steamID, JoinResult.ServerFull); + } + } + else + { + if (m_groupId == 0 || MySandboxGame.ConfigDedicated.Administrators.Contains(steamID.ToString()) || MySandboxGame.ConfigDedicated.Administrators.Contains(ConvertSteamIDFrom64(steamID))) + { + UserAccepted(steamID); + } + else + { + if (SteamServerAPI.Instance.GetAccountType(m_groupId) != AccountType.Clan) + { + UserRejected(steamID, JoinResult.GroupIdInvalid); + } + else + { + if (SteamServerAPI.Instance.GameServer.RequestGroupStatus(steamID, m_groupId)) + { + // Returns false when there's no connection to Steam + m_waitingForGroup.Add(steamID); + } + else + UserRejected(steamID, JoinResult.SteamServersOffline); + } + } + } + } + else + { + var joinResult = JoinResult.TicketInvalid; + switch (response) + { + case AuthSessionResponseEnum.AuthTicketCanceled: + joinResult = JoinResult.TicketCanceled; + break; + case AuthSessionResponseEnum.AuthTicketInvalidAlreadyUsed: + joinResult = JoinResult.TicketAlreadyUsed; + break; + case AuthSessionResponseEnum.LoggedInElseWhere: + joinResult = JoinResult.LoggedInElseWhere; + break; + case AuthSessionResponseEnum.NoLicenseOrExpired: + joinResult = JoinResult.NoLicenseOrExpired; + break; + case AuthSessionResponseEnum.UserNotConnectedToSteam: + joinResult = JoinResult.UserNotConnected; + break; + case AuthSessionResponseEnum.VACBanned: + joinResult = JoinResult.VACBanned; + break; + case AuthSessionResponseEnum.VACCheckTimedOut: + joinResult = JoinResult.VACCheckTimedOut; + break; + } - return; + UserRejected(steamID, joinResult); + } } - - if ( PluginSettings.Instance.ReservedSlotsGroup != 0 ) + catch (Exception ex) { - //ask Steam if the connecting player is in the whitelisted group. response is raised as an event; GameServer_UserGroupStatus - SteamServerAPI.Instance.GameServer.RequestGroupStatus( remoteUserId, PluginSettings.Instance.ReservedSlotsGroup ); - waitingPlayers.Add( remoteUserId ); - return; + Essentials.Log.Error(ex); } - - DenyPlayer( remoteUserId ); } - */ - private static void DenyPlayer( ulong remoteUserId ) + private static void UserRejected(ulong steamId, JoinResult joinResult) { - //get the list of current players just so we can count them (this is a stupid solution) - List connectedPlayers = new List( ); - MyAPIGateway.Players.GetPlayers( connectedPlayers ); - RefreshPlayers( connectedPlayers ); - - int publicPlayers = connectedPlayers.Count - - Math.Min( _reservedPlayers.Count, PluginSettings.Instance.ReservedSlotsCount ); - int publicSlots = Server.Instance.Config.MaxPlayers - PluginSettings.Instance.ReservedSlotsCount; - - if ( ExtenderOptions.IsDebugging ) - { - Essentials.Log.Debug( "Public players: " + publicPlayers.ToString( ) ); - Essentials.Log.Debug( "Public slots: " + publicSlots.ToString( ) ); - Essentials.Log.Debug( "Connected players: " + connectedPlayers.Count.ToString( ) ); - Essentials.Log.Debug( "Reserved players: " + _reservedPlayers.Count.ToString( ) ); - Essentials.Log.Debug( "Reserved slots: " + PluginSettings.Instance.ReservedSlotsCount.ToString( ) ); - } + MethodInfo userRejectedMethod = typeof(MyDedicatedServerBase).GetMethod("UserRejected", BindingFlags.NonPublic | BindingFlags.Instance); + userRejectedMethod.Invoke(MyMultiplayer.Static, new object[] {steamId, joinResult}); + } - if ( publicPlayers < publicSlots ) - return; + private static void UserAccepted(ulong steamId) + { + MethodInfo userAcceptedMethod = typeof(MyDedicatedServerBase).GetMethod("UserAccepted", BindingFlags.NonPublic | BindingFlags.Instance); + userAcceptedMethod.Invoke(MyMultiplayer.Static, new object[] {steamId}); + } - //don't do anything while we're waiting for group authorization - if ( _waitingPlayers.Contains( remoteUserId ) ) - return; + private static bool IsClientBanned(ulong steamId) + { + return (bool)typeof(MyMultiplayerBase).GetMethod("IsClientBanned", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(MyMultiplayer.Static, new object[] {steamId}); + } - //kick the player with the "Server is full" message - //too bad we can't send a custom message, but they're hardcoded into the client - Essentials.Log.Info("Player denied: " + remoteUserId); - var userRejectedMethod = typeof(MyDedicatedServerBase).GetMethod("UserRejected", BindingFlags.NonPublic | BindingFlags.Instance); - userRejectedMethod.Invoke(MyMultiplayer.Static, new object[] { remoteUserId, JoinResult.ServerFull }); + private static bool IsClientKicked(ulong steamId) + { + return (bool)typeof(MyMultiplayerBase).GetMethod("IsClientKicked", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(MyMultiplayer.Static, new object[] {steamId}); } - private static void GameServer_UserGroupStatus( ulong userId, ulong groupId, bool member, bool officier ) + private static void RaiseClientKicked(ulong steamId) { - if ( !PluginSettings.Instance.ReservedSlotsEnabled ) - return; + typeof(MyMultiplayerBase).GetMethod("RaiseClientKicked", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(MyMultiplayer.Static, new object[] {steamId}); + } - if ( groupId == PluginSettings.Instance.ReservedSlotsGroup ) + private static void GameServer_UserGroupStatus(ulong userId, ulong groupId, bool member, bool officier) + { + if (PluginSettings.Instance.ReservedSlotsEnabled && groupId == PluginSettings.Instance.ReservedSlotsGroup && _waitingForWhitelistGroup.Remove(userId)) { - _waitingPlayers.Remove( userId ); - if ( member || officier ) + if (member || officier) { - _reservedPlayers.Add( userId ); - Essentials.Log.Info( "Whitelisted player connected: " + userId ); - Essentials.Log.Info( "{0} whitelisted players connected. {1} of {2} reserved slots allocated.", - _reservedPlayers.Count, - Math.Min( _reservedPlayers.Count, PluginSettings.Instance.ReservedSlotsCount ), - PluginSettings.Instance.ReservedSlotsCount ); + Essentials.Log.Info("Whitelisted player connected: " + userId); + UserAccepted(userId); } else - DenyPlayer( userId ); + UserRejected(userId, JoinResult.ServerFull); } - } - - public override void OnPlayerLeft( ulong remoteUserId ) - { - //free up allocated slots so someone else can use it - if ( _reservedPlayers.Contains( remoteUserId ) ) + else { - Essentials.Log.Info( "Freed slot from: " + remoteUserId ); - _reservedPlayers.Remove( remoteUserId ); - Essentials.Log.Info( "{0} slots of {1} allocated.", _reservedPlayers.Count, - PluginSettings.Instance.ReservedSlotsCount ); + if (groupId == m_groupId && m_waitingForGroup.Remove(userId)) + { + if (member || officier) + UserAccepted(userId); + else + UserRejected(userId, JoinResult.NotInGroup); + } } - - if ( _waitingPlayers.Contains( remoteUserId ) ) - _waitingPlayers.Remove( remoteUserId ); - } - - private static void RefreshPlayers( List connectedPlayers ) - { - List steamIds = connectedPlayers.Select( x => x.SteamUserId ).ToList( ); - _reservedPlayers.Clear( ); - _reservedPlayers = steamIds.Where( x => PluginSettings.Instance.ReservedSlotsPlayers.Contains( x.ToString( ) ) ).ToList( ); } } } diff --git a/EssentialsPlugin/Settings/PluginSettings.cs b/EssentialsPlugin/Settings/PluginSettings.cs index c1d4d39..2770bd6 100644 --- a/EssentialsPlugin/Settings/PluginSettings.cs +++ b/EssentialsPlugin/Settings/PluginSettings.cs @@ -847,18 +847,18 @@ public bool ReservedSlotsEnabled } } - public int ReservedSlotsCount - { - get - { - return _reservedSlotsCount; - } - set - { - _reservedSlotsCount = value; - Save( ); - } - } + //public int ReservedSlotsCount + //{ + // get + // { + // return _reservedSlotsCount; + // } + // set + // { + // _reservedSlotsCount = value; + // Save( ); + // } + //} public ulong ReservedSlotsGroup { diff --git a/EssentialsPlugin/Utility/Communication.cs b/EssentialsPlugin/Utility/Communication.cs index 063b0cc..0d90483 100644 --- a/EssentialsPlugin/Utility/Communication.cs +++ b/EssentialsPlugin/Utility/Communication.cs @@ -36,7 +36,7 @@ public static class Communication public static void SendPublicInformation( string infoText ) { - if ( infoText == "" ) + if ( string.IsNullOrEmpty( infoText ) ) return; ScriptedChatMsg msg = new ScriptedChatMsg @@ -69,7 +69,7 @@ public static void SendPublicInformation( string infoText ) public static void SendPrivateInformation( ulong playerId, string infoText, string from = null ) { - if ( infoText == "" ) + if ( string.IsNullOrEmpty( infoText )) return; ulong steamId = from == null ? 0 : PlayerMap.Instance.GetSteamIdFromPlayerName( from );