/*
* AdKats - Advanced In-Game Admin and Ban Enforcer for Procon Frostbite.
*
* Copyright 2014 A Different Kind, LLC
*
* AdKats was inspired by the gaming community A Different Kind (ADK). Visit http://www.ADKGamers.com/ for more information.
*
* The AdKats Frostbite Plugin is free software: You can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version. AdKats is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. To view this license, visit http://www.gnu.org/licenses/.
*
* Code Credit:
* Modded Levenshtein Distance algorithm and Tag Parsing from Micovery's InsaneLimits
* Email System adapted from MorpheusX(AUT)'s "Notify Me!"
* TeamSpeak Integration by Imisnew2
* Discord report posting by jbrunink
*
* Development by Daniel J. Gradinjan (ColColonCleaner)
*
* AdKats.cs
* Version 7.6.1.1
* 04-June-2021
*
* Automatic Update Information
* 7.6.1.1
*/
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using Microsoft.CSharp;
using MySql.Data.MySqlClient;
using PRoCon.Core;
using PRoCon.Core.Players;
using PRoCon.Core.Players.Items;
using PRoCon.Core.Plugin;
using PRoCon.Core.Plugin.Commands;
using PRoCon.Core.Maps;
namespace PRoConEvents
{
public class AdKats :PRoConPluginAPI, IPRoConPluginInterface
{
//Current Plugin Version
private const String PluginVersion = "7.6.1.1";
public enum GameVersionEnum
{
UNKNOWN,
BF3,
BF4,
BFHL
};
public enum RoundState
{
Loaded,
Playing,
Ended
}
public enum PopulationState
{
Unknown,
Low,
Medium,
High,
}
public enum PlayerType
{
Player,
Spectator,
CommanderPC,
CommanderMobile
}
public enum VersionStatus
{
OutdatedBuild,
StableBuild,
TestBuild,
UnknownBuild,
UnfetchedBuild
}
public enum AutoSurrenderAction
{
None,
Surrender,
Nuke,
Vote
}
public enum VoipJoinDisplayType
{
Disabled,
Say,
Yell,
Tell
}
private const string s = " | ";
private const string t = "|";
private Utilities Util;
//State
private Boolean _LevelLoadShutdown;
private const Boolean FullDebug = false;
private volatile String _pluginChangelog;
private volatile String _pluginDescription;
private volatile String _pluginLinks;
private volatile Boolean _pluginEnabled;
private volatile Boolean _pluginRebootOnDisable;
private volatile String _pluginRebootOnDisableSource;
private volatile Boolean _threadsReady;
private volatile String _latestPluginVersion;
private Int64 _latestPluginVersionInt;
private Int64 _currentPluginVersionInt;
private volatile String _pluginVersionStatusString;
private volatile VersionStatus _pluginVersionStatus = VersionStatus.UnfetchedBuild;
private volatile Boolean _pluginUpdateServerInfoChecked;
private volatile Boolean _pluginUpdatePatched;
private volatile String _pluginPatchedVersion;
private Int64 _pluginPatchedVersionInt;
private volatile String _pluginUpdateProgress = "NotStarted";
private volatile String _pluginDescFetchProgress = "NotStarted";
private ARecord _pluginUpdateCaller;
private volatile Boolean _useKeepAlive;
private Int32 _startingTicketCount = -1;
private RoundState _roundState = RoundState.Loaded;
private DateTime _playingStartTime = DateTime.UtcNow;
private Int32 _highestTicketCount;
private Int32 _lowestTicketCount = 500000;
private volatile Boolean _fetchedPluginInformation;
private Boolean _firstUserListComplete;
private Boolean _firstPlayerListStarted;
private Boolean _firstPlayerListComplete;
private String _vipKickedPlayerName;
private Boolean _enforceSingleInstance = true;
private GameVersionEnum GameVersion = GameVersionEnum.UNKNOWN;
private Boolean _endingRound;
private readonly AServer _serverInfo;
private TimeSpan _previousRoundDuration = TimeSpan.Zero;
private Int32 _soldierHealth = 100;
private Int64 _settingImportID = -1;
private Boolean _settingsFetched;
private Boolean _settingsLocked;
private String _settingsPassword;
private Int32 _pingKicksThisRound;
private Int32 _mapBenefitIndex;
private Int32 _mapDetrimentIndex;
private Int32 _pingKicksTotal;
private Int32 _roundID;
private Boolean _versionTrackingDisabled;
private Boolean _automaticUpdatesDisabled;
private String _currentFlagMessage;
private Boolean _populationPopulating;
private readonly Dictionary _populationPopulatingPlayers = new Dictionary();
private String _AdKatsLRTExtensionToken = String.Empty;
private List _roundOverPlayers = null;
private Int32 _MemoryUsageCurrent = 0;
private Int32 _MemoryUsageWarn = 512;
private Int32 _MemoryUsageRestartPlugin = 1024;
private Int32 _MemoryUsageRestartProcon = 2048;
//Debug
private String _debugSoldierName = "ColColonCleaner";
private Boolean _toldCol;
private Boolean _debugDisplayPlayerFetches;
//Timing
private readonly DateTime _proconStartTime = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _AdKatsStartTime = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _AdKatsRunningTime = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _commandStartTime = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _lastBanListCall = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _lastDbBanFetch = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _lastGUIDBanCountFetch = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _lastIPBanCountFetch = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _lastNameBanCountFetch = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _lastStatLoggerStatusUpdateTime = DateTime.UtcNow - TimeSpan.FromMinutes(60);
private DateTime _lastSuccessfulBanList = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _populationTransitionTime = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _populationUpdateTime = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _lastDatabaseTimeout = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _lastDbActionFetch = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _lastDbSettingFetch = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _lastSettingPageUpdate = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _lastSettingPageUpdateRequest = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _lastUserFetch = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _LastPlayerMoveIssued = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _LastPluginDescFetch = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private DateTime _LastWeaponCodePost = DateTime.UtcNow - TimeSpan.FromHours(1);
private DateTime _LastTicketRateDisplay = DateTime.UtcNow - TimeSpan.FromSeconds(30);
private DateTime _lastAutoSurrenderTriggerTime = DateTime.UtcNow - TimeSpan.FromSeconds(10);
private DateTime _LastBattlelogAction = DateTime.UtcNow - TimeSpan.FromSeconds(2);
private DateTime _LastBattlelogIssue = DateTime.UtcNow - TimeSpan.FromSeconds(30);
private DateTime _LastServerInfoTrigger = DateTime.UtcNow - TimeSpan.FromSeconds(30);
private DateTime _LastServerInfoReceive = DateTime.UtcNow - TimeSpan.FromSeconds(30);
private Object _battlelogLocker = new Object();
private TimeSpan _BattlelogWaitDuration = TimeSpan.FromSeconds(5);
private DateTime _LastIPAPIAction = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private readonly TimeSpan _IPAPIWaitDuration = TimeSpan.FromSeconds(6);
private Object _IPAPILocker = new Object();
private DateTime _LastGoogleAction = DateTime.UtcNow - TimeSpan.FromSeconds(0.3);
private readonly TimeSpan _GoogleWaitDuration = TimeSpan.FromSeconds(0.3);
private DateTime _lastGlitchedPlayerNotification = DateTime.UtcNow;
private DateTime _lastInvalidPlayerNameNotification = DateTime.UtcNow;
private DateTime _lastIPAPIError = DateTime.UtcNow;
private DateTime _lastBattlelogFrequencyMessage = DateTime.UtcNow - TimeSpan.FromSeconds(5);
private Queue _BattlelogActionTimes = new Queue();
private DateTime _LastPlayerListTrigger = DateTime.UtcNow - TimeSpan.FromSeconds(30);
private Queue _PlayerListTriggerTimes = new Queue();
private DateTime _LastPlayerListReceive = DateTime.UtcNow - TimeSpan.FromSeconds(30);
private Queue _PlayerListReceiveTimes = new Queue();
private DateTime _LastPlayerListAccept = DateTime.UtcNow - TimeSpan.FromSeconds(30);
private Queue _PlayerListAcceptTimes = new Queue();
private DateTime _LastPlayerListProcessed = DateTime.UtcNow - TimeSpan.FromSeconds(30);
private Queue _PlayerListProcessedTimes = new Queue();
private Boolean _DebugPlayerListing = false;
private DateTime _LastDebugPlayerListingMessage = DateTime.UtcNow - TimeSpan.FromSeconds(30);
private Queue _startupDurations = new Queue();
private DateTime _LastShortKeepAliveCheck = DateTime.UtcNow - TimeSpan.FromSeconds(30);
private DateTime _LastLongKeepAliveCheck = DateTime.UtcNow - TimeSpan.FromSeconds(30);
private DateTime _LastVeryLongKeepAliveCheck = DateTime.UtcNow - TimeSpan.FromSeconds(30);
private DateTime _LastMemoryWarning = DateTime.UtcNow - TimeSpan.FromSeconds(30);
//Server
private PopulationState _populationStatus = PopulationState.Unknown;
private readonly Dictionary _populationDurations = new Dictionary();
private Int32 _lowPopulationPlayerCount = 20;
private Int32 _highPopulationPlayerCount = 40;
private String _shortServerName = "";
private Boolean _automaticServerRestart = false;
private Boolean _automaticServerRestartProcon = false;
private Int32 _automaticServerRestartMinHours = 18;
private Dictionary ReadableMaps = new Dictionary();
private Dictionary ReadableModes = new Dictionary();
//MySQL connection
private String _mySqlSchemaName = "";
private String _mySqlHostname = "";
private String _mySqlPassword = "";
private String _mySqlPort = "";
private String _mySqlUsername = "";
private readonly MySqlConnectionStringBuilder _dbCommStringBuilder = new MySqlConnectionStringBuilder();
private Boolean _fetchActionsFromDb = true;
private const Boolean UseConnectionPooling = true;
private const Int32 MinConnectionPoolSize = 0;
private const Int32 MaxConnectionPoolSize = 20;
private const Boolean UseCompressedConnection = false;
private const Int32 DatabaseTimeoutThreshold = 15;
private const Int32 DatabaseSuccessThreshold = 5;
private Boolean _databaseConnectionCriticalState;
private Int32 _databaseSuccess;
private Int32 _databaseTimeouts;
private readonly List _DatabaseReaderDurations = new List();
private Double _DatabaseReadAverageDuration = 100;
private readonly List _DatabaseNonQueryDurations = new List();
private Double _DatabaseWriteAverageDuration = 100;
private volatile Boolean _dbSettingsChanged = true;
private Boolean _dbTimingChecked;
private Boolean _dbTimingValid;
private TimeSpan _dbTimingOffset = TimeSpan.Zero;
private Boolean _globalTimingChecked;
private Boolean _globalTimingValid;
private TimeSpan _globalTimingOffset = TimeSpan.Zero;
private Boolean _timingValidOverride;
private String _statLoggerVersion = "BF3";
//Action fetching
private const Int32 DbActionFetchFrequency = 10;
private const Int32 DbSettingFetchFrequency = 300;
private const Int32 DbBanFetchFrequency = 60;
//Event trigger dictionaries
private readonly Dictionary _ActOnIsAliveDictionary = new Dictionary();
private readonly Dictionary _ActOnSpawnDictionary = new Dictionary();
private readonly Dictionary _LoadoutConfirmDictionary = new Dictionary();
private readonly Dictionary _ActionConfirmDic = new Dictionary();
private readonly Dictionary _RoundMutedPlayers = new Dictionary();
private readonly List _PlayerReports = new List();
private readonly HashSet _PlayersRequestingCommands = new HashSet();
//Threads
private ThreadManager Threading;
private Thread _Activator;
private Thread _Finalizer;
private Thread _DatabaseCommunicationThread;
private Thread _MessageProcessingThread;
private Thread _CommandParsingThread;
private Thread _PlayerListingThread;
private Thread _TeamSwapThread;
private Thread _BanEnforcerThread;
private Thread _RoundTimerThread;
private Thread _KillProcessingThread;
private Thread _AntiCheatThread;
private Thread _DisconnectHandlingThread;
private Thread _AccessFetchingThread;
private Thread _ActionHandlingThread;
private Thread _BattlelogCommThread;
private Thread _IPAPICommThread;
//Threading queues
private readonly Queue _BanEnforcerCheckingQueue = new Queue();
private readonly Queue _BanEnforcerProcessingQueue = new Queue();
private readonly Queue _CBanProcessingQueue = new Queue();
private readonly Queue _CommandRemovalQueue = new Queue();
private readonly Queue _CommandUploadQueue = new Queue();
private readonly Queue _AntiCheatQueue = new Queue();
private readonly Queue _KillProcessingQueue = new Queue();
private readonly Queue> _PlayerListProcessingQueue = new Queue>();
private readonly Queue _PlayerRemovalProcessingQueue = new Queue();
private readonly Queue _RoleRemovalQueue = new Queue();
private readonly Queue _RoleUploadQueue = new Queue();
private readonly Queue _SettingUploadQueue = new Queue();
private readonly Queue _UnparsedCommandQueue = new Queue();
private readonly Queue _UnparsedMessageQueue = new Queue();
private readonly Queue _UnprocessedActionQueue = new Queue();
private readonly Queue _UnprocessedRecordQueue = new Queue();
private readonly Queue _UnprocessedStatisticQueue = new Queue();
private readonly Queue _UserRemovalQueue = new Queue();
private readonly Queue _UserUploadQueue = new Queue();
private readonly Queue _BattlelogFetchQueue = new Queue();
private readonly Queue _IPInfoFetchQueue = new Queue();
//Threading wait handles
private EventWaitHandle _WeaponStatsWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _AccessFetchWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _TeamswapWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _StatLoggerStatusWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _ServerInfoWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _RoundEndingWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _PlayerListUpdateWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _MessageParsingWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _KillProcessingWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _AntiCheatWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _DbCommunicationWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _CommandParsingWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _BanEnforcerWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _ActionHandlingWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _PlayerProcessingWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _PluginDescriptionWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle _BattlelogCommWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private readonly EventWaitHandle _IPInfoWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
//Procon MatchCommand
private readonly MatchCommand _PluginEnabledMatchCommand;
private readonly MatchCommand _fetchAuthorizedSoldiersMatchCommand;
private readonly MatchCommand _subscribeAsClientMatchCommand;
private readonly MatchCommand _issueCommandMatchCommand;
//Commands global
private readonly Dictionary _CommandIDDictionary = new Dictionary();
private readonly Dictionary _CommandKeyDictionary = new Dictionary();
private readonly Dictionary _CommandNameDictionary = new Dictionary();
private readonly Dictionary _CommandTextDictionary = new Dictionary();
private readonly Dictionary _CommandDescriptionDictionary = new Dictionary();
private readonly Dictionary> _commandTimeoutDictionary = new Dictionary>();
private readonly Dictionary _commandUsageTimes = new Dictionary();
private Boolean _AllowAdminSayCommands = true;
private Boolean _ReservedSquadLead = false;
private Boolean _ReservedSelfMove = false;
private Boolean _ReservedSelfKill = false;
private Boolean _bypassCommandConfirmation = false;
private List _ExternalPlayerCommands = new List();
private List _ExternalAdminCommands = new List();
private List _CommandTargetWhitelistCommands = new List();
private Int32 _RequiredReasonLength = 4;
private Int32 _minimumAssistMinutes = 5;
//Commands specific
private String _ServerVoipAddress = "Enter teamspeak/discord/etc address here.";
//Dynamic access
public Func AAPerkFunc = ((plugin, aPlayer) => ((plugin._EnableAdminAssistantPerk && aPlayer.player_aa) || (aPlayer.player_reputation > _reputationThresholdGood)));
public Func TeamSwapFunc = ((plugin, aPlayer) => ((plugin._EnableAdminAssistantPerk && aPlayer.player_aa) || plugin.GetMatchingVerboseASPlayersOfGroup("whitelist_teamswap", aPlayer).Any()));
//Roles
private readonly Dictionary _RoleIDDictionary = new Dictionary();
private readonly Dictionary _RoleKeyDictionary = new Dictionary();
private readonly Dictionary _RoleNameDictionary = new Dictionary();
private Boolean _PlayerRoleRefetch;
private readonly Dictionary _RoleCommandCache = new Dictionary();
private DateTime _RoleCommandCacheUpdate = DateTime.UtcNow - TimeSpan.FromMinutes(5);
private TimeSpan _RoleCommandCacheUpdateBufferDuration = TimeSpan.FromSeconds(5);
private DateTime _RoleCommandCacheUpdateBufferStart = DateTime.UtcNow - TimeSpan.FromSeconds(5);
//Users
private const Int32 DbUserFetchFrequency = 300;
private readonly Dictionary _userCache = new Dictionary();
private readonly Dictionary _specialPlayerGroupIDDictionary = new Dictionary();
private readonly Dictionary _specialPlayerGroupKeyDictionary = new Dictionary();
private readonly Dictionary _baseSpecialPlayerCache = new Dictionary();
private readonly Dictionary _verboseSpecialPlayerCache = new Dictionary();
//Games and teams
private readonly Dictionary _gameIDDictionary = new Dictionary();
private readonly Dictionary _teamDictionary = new Dictionary();
private Boolean _acceptingTeamUpdates;
private readonly Dictionary _unmatchedRoundDeathCounts = new Dictionary();
private readonly HashSet _unmatchedRoundDeaths = new HashSet();
private readonly Dictionary _roundAssists = new Dictionary();
//Players
private readonly Dictionary _PlayerDictionary = new Dictionary();
private readonly List _MissingPlayers = new List();
private readonly List _RoundPrepSquads = new List();
private readonly Dictionary _PlayerLeftDictionary = new Dictionary();
private readonly Dictionary _FetchedPlayers = new Dictionary();
private readonly Dictionary> _RoundPlayerIDs = new Dictionary>();
//Punishment settings
private readonly List _PunishmentSeverityIndex;
private Boolean _CombineServerPunishments;
private Boolean _AutomaticForgives;
private Int32 _AutomaticForgiveLastPunishDays = 30;
private Int32 _AutomaticForgiveLastForgiveDays = 14;
private Boolean _IROActive = true;
private Boolean _IROOverridesLowPop;
private Int32 _IROOverridesLowPopInfractions = 5;
private Int32 _IROTimeout = 10;
private Boolean _OnlyKillOnLowPop = true;
private String[] _PunishmentHierarchy = { "kill", "kick", "tban120", "kill", "kick", "tbanday", "kick", "tbanweek", "kick", "tban2weeks", "kick", "tbanmonth", "kick", "ban" };
//Teamswap
private Int32 _TeamSwapTicketWindowHigh = 500000;
private Int32 _TeamSwapTicketWindowLow;
private Queue _Team1MoveQueue = new Queue();
private Queue _Team2MoveQueue = new Queue();
private Queue _TeamswapForceMoveQueue = new Queue();
private Queue _TeamswapOnDeathCheckingQueue = new Queue();
private readonly Dictionary _TeamswapOnDeathMoveDic = new Dictionary();
//AFK manager
private Boolean _AFKManagerEnable;
private Boolean _AFKAutoKickEnable;
private Double _AFKTriggerDurationMinutes = 5;
private Int32 _AFKTriggerMinimumPlayers = 20;
private Boolean _AFKIgnoreUserList = true;
private String[] _AFKIgnoreRoles = { };
private Boolean _AFKIgnoreChat;
//Ping enforcer
private Boolean _pingEnforcerEnable;
private Int32 _pingEnforcerTriggerMinimumPlayers = 50;
private Double _pingEnforcerLowTriggerMS = 300;
private Int32[] _pingEnforcerLowTimeModifier = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
private Double _pingEnforcerMedTriggerMS = 300;
private Int32[] _pingEnforcerMedTimeModifier = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
private Double _pingEnforcerHighTriggerMS = 300;
private Int32[] _pingEnforcerHighTimeModifier = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
private Double _pingEnforcerFullTriggerMS = 300;
private Int32[] _pingEnforcerFullTimeModifier = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
private Double _pingMovingAverageDurationSeconds = 180;
private Boolean _pingEnforcerKickMissingPings = true;
private Boolean _pingEnforcerIgnoreUserList = true;
private String _pingEnforcerMessagePrefix = "Please fix your ping and join us again.";
private String[] _pingEnforcerIgnoreRoles = { };
private Boolean _attemptManualPingWhenMissing = false;
private Boolean _pingEnforcerDisplayProconChat = true;
//Commander manager
private Boolean _CMDRManagerEnable = false;
private Int32 _CMDRMinimumPlayers = 40;
//Ban enforcer
private Boolean _UseBanAppend;
private String _BanAppend = "Appeal at your_site.com";
private Boolean _UseBanEnforcer;
private Boolean _UseBanEnforcerPreviousState;
private Boolean _BanEnforcerBF4LenientKick = false;
private List _BanEnforcerSearchResults = new List();
private Boolean _BansQueuing;
private String _CBanAdminName = "BanEnforcer";
private Boolean _DefaultEnforceGUID = true;
private Boolean _DefaultEnforceIP = false;
private Boolean _DefaultEnforceName = false;
private Int64 _GUIDBanCount = -1;
private Int64 _IPBanCount = -1;
private Int64 _NameBanCount = -1;
private TimeSpan _MaxTempBanDuration = TimeSpan.FromDays(3650);
//Reports
public String[] _AutoReportHandleStrings = { };
private Boolean _InformReportedPlayers;
private String[] _PlayerInformExclusionStrings = { };
private Int32 _MinimumReportHandleSeconds;
//Email
private Boolean _UseEmail;
//PushBullet
private Boolean _UsePushBullet;
//Muting
private Int32 _MutedPlayerChances = 5;
private String _MutedPlayerKickMessage = "Talking excessively while muted.";
private String _MutedPlayerKillMessage = "Do not talk while muted. You can speak again next round.";
private String _MutedPlayerMuteMessage = "You have been muted by an admin, talking will cause punishment. You can speak again next round.";
private Boolean _MutedPlayerIgnoreCommands = true;
//Surrender
private Boolean _surrenderVoteEnable;
private Double _surrenderVoteMinimumPlayerPercentage = 30;
private Int32 _surrenderVoteMinimumPlayerCount = 16;
private Int32 _surrenderVoteMinimumTicketGap = 250;
private Boolean _surrenderVoteTicketRateGapEnable;
private Double _surrenderVoteMinimumTicketRateGap = 10;
private Boolean _surrenderVoteTimeoutEnable;
private Double _surrenderVoteTimeoutMinutes = 5;
private Boolean _surrenderVoteActive;
private Boolean _surrenderVoteSucceeded;
private DateTime _surrenderVoteStartTime = DateTime.UtcNow;
private readonly HashSet _surrenderVoteList = new HashSet();
private readonly HashSet _nosurrenderVoteList = new HashSet();
//Auto-Surrender
private Boolean _surrenderAutoEnable;
private Boolean _surrenderAutoSucceeded;
private Boolean _surrenderAutoUseMetroValues;
private Boolean _surrenderAutoUseLockerValues;
private Int32 _surrenderAutoMinimumTicketGap = 100;
private Int32 _surrenderAutoMinimumTicketCount = 100;
private Int32 _surrenderAutoMaximumTicketCount = 999;
private Double _surrenderAutoLosingRateMax = 999;
private Double _surrenderAutoLosingRateMin = 999;
private Double _surrenderAutoWinningRateMax = 999;
private Double _surrenderAutoWinningRateMin = 999;
private Int32 _surrenderAutoTriggerCountToSurrender = 10;
private Boolean _surrenderAutoResetTriggerCountOnCancel = true;
private Boolean _surrenderAutoResetTriggerCountOnFire = true;
private Int32 _surrenderAutoTriggerCountCurrent;
private Int32 _surrenderAutoTriggerCountPause;
private Int32 _surrenderAutoMinimumPlayers = 10;
private String _surrenderAutoMessage = "Auto-Resolving Round. %WinnerName% Wins!";
private Boolean _surrenderAutoNukeInstead;
private Boolean _nukeAutoSlayActive = false;
private Int32 _surrenderAutoNukeDurationHigh = 0;
private Int32 _surrenderAutoNukeDurationMed = 0;
private Int32 _surrenderAutoNukeDurationLow = 0;
private Int32 _nukeAutoSlayActiveDuration = 0;
private String _lastNukeSlayDurationMessage = null;
private Int32 _surrenderAutoNukeDurationIncrease = 0;
private Int32 _surrenderAutoNukeDurationIncreaseTicketDiff = 100;
private Int32 _surrenderAutoNukeMinBetween = 60;
private DateTime _lastNukeTime = DateTime.UtcNow - TimeSpan.FromMinutes(10);
private ATeam _lastNukeTeam;
private Boolean _surrenderAutoAnnounceNukePrep = true;
private Boolean _surrenderAutoNukeLosingTeams = false;
private Int32 _surrenderAutoNukeLosingMaxDiff = 200;
private Boolean _surrenderAutoNukeResolveAfterMax = false;
private Int32 _surrenderAutoMaxNukesEachRound = 4;
private Dictionary _nukesThisRound = new Dictionary();
private Boolean _surrenderAutoTriggerVote;
private String _surrenderAutoNukeMessage = "Nuking %WinnerName% for baserape!";
private Int32 _NukeCountdownDurationSeconds = 0;
private Int32 _NukeWinningTeamUpTicketCount = 9999;
private Boolean _NukeWinningTeamUpTicketHigh = true;
//EmailHandler
private EmailHandler _EmailHandler;
private Boolean _EmailReportsOnlyWhenAdminless;
//PushBullet
private PushBulletHandler _PushBulletHandler;
private Boolean _PushBulletReportsOnlyWhenAdminless;
//Perks
private String[] _PerkSpecialPlayerGroups = {
"slot_reserved",
"slot_spectator",
"whitelist_report",
"whitelist_spambot",
"whitelist_adminassistant",
"whitelist_ping",
"whitelist_anticheat",
"whitelist_multibalancer",
"whitelist_populator",
"whitelist_teamkill"
};
private Boolean _UsePerkExpirationNotify = false;
private Int32 _PerkExpirationNotifyDays = 7;
//Orchestration
private List _CurrentReservedSlotPlayers = new List();
private List _CurrentSpectatorListPlayers;
private Boolean _FeedMultiBalancerWhitelist;
private Boolean _FeedMultiBalancerWhitelist_Admins = true;
private Boolean _FeedMultiBalancerDisperseList;
private Boolean _FeedTeamKillTrackerWhitelist;
private Boolean _FeedTeamKillTrackerWhitelist_Admins;
private Boolean _FeedServerReservedSlots;
private Boolean _FeedServerReservedSlots_VSM;
private Boolean _FeedServerReservedSlots_Admins = true;
private Boolean _FeedServerReservedSlots_Admins_VIPKickWhitelist = false;
private Boolean _FeedServerSpectatorList;
private Boolean _FeedServerSpectatorList_Admins;
private Boolean _FeedStatLoggerSettings;
private Boolean _PostStatLoggerChatManually;
private Boolean _PostStatLoggerChatManually_PostServerChatSpam = true;
private Boolean _PostStatLoggerChatManually_IgnoreCommands;
private Boolean _PostMapBenefitStatistics;
private Boolean _MULTIBalancerUnswitcherDisabled;
public readonly String[] _subscriptionGroups = { "OnlineSoldiers" };
private readonly List _subscribedClients = new List();
private String[] _BannedTags = { };
private DateTime _AutoKickNewPlayerDate = DateTime.UtcNow + TimeSpan.FromDays(7300);
//Team Power Monitor
private Boolean _UseTeamPowerMonitorSeeders = false;
private Boolean _UseTeamPowerDisplayBalance = false;
private Boolean _UseTeamPowerMonitorScrambler = false;
private Boolean _ScrambleRequiredTeamsRemoved = false;
private Boolean _UseTeamPowerMonitorReassign = false;
private Boolean _UseTeamPowerMonitorReassignLenient = false;
private Double _TeamPowerMonitorReassignLenientPercent = 30;
private Boolean _UseTeamPowerMonitorUnswitcher = false;
private Boolean currentStartingTeam1 = true;
private Boolean _PlayersAutoAssistedThisRound = false;
private Double _TeamPowerActiveInfluence = 35;
//Populators
private Boolean _PopulatorMonitor;
private Boolean _PopulatorUseSpecifiedPopulatorsOnly;
private Boolean _PopulatorPopulatingThisServerOnly;
private Int32 _PopulatorMinimumPopulationCountPastWeek = 5;
private Int32 _PopulatorMinimumPopulationCountPast2Weeks = 10;
private readonly Dictionary _populatorPlayers = new Dictionary();
private Boolean _PopulatorPerksEnable;
private Boolean _PopulatorPerksReservedSlot;
private Boolean _PopulatorPerksBalanceWhitelist;
private Boolean _PopulatorPerksPingWhitelist;
private Boolean _PopulatorPerksTeamKillTrackerWhitelist;
//Teamspeak
private readonly TeamSpeakClientViewer _TeamspeakManager;
private Boolean _TeamspeakPlayerMonitorView;
private Boolean _TeamspeakPlayerMonitorEnable;
private readonly Dictionary _TeamspeakPlayers = new Dictionary();
private Boolean _TeamspeakPlayerPerksEnable;
private Boolean _TeamspeakPlayerPerksVIPKickWhitelist;
private Boolean _TeamspeakPlayerPerksBalanceWhitelist;
private Boolean _TeamspeakPlayerPerksPingWhitelist;
private Boolean _TeamspeakPlayerPerksTeamKillTrackerWhitelist;
//Discord
private readonly DiscordManager _DiscordManager;
private Boolean _DiscordPlayerMonitorView;
private Boolean _DiscordPlayerMonitorEnable;
private readonly Dictionary _DiscordPlayers = new Dictionary();
private Boolean _DiscordPlayerRequireVoiceForAdmin;
private Boolean _DiscordPlayerPerksEnable;
private Boolean _DiscordPlayerPerksVIPKickWhitelist;
private Boolean _DiscordPlayerPerksBalanceWhitelist;
private Boolean _DiscordPlayerPerksPingWhitelist;
private Boolean _DiscordPlayerPerksTeamKillTrackerWhitelist;
private Boolean _UseDiscordForReports;
private Boolean _DiscordReportsOnlyWhenAdminless;
private Boolean _DiscordReportsLeftWithoutAction;
//Challenge
private AChallengeManager ChallengeManager;
//AntiCheat
private Boolean _useAntiCheatLIVESystem = true;
private Boolean _AntiCheatLIVESystemActiveStats = false;
private Boolean _UseHskChecker;
private Boolean _UseKpmChecker;
private Double _HskTriggerLevel = 60.0;
private Double _KpmTriggerLevel = 5.0;
private String _AntiCheatDPSBanMessage = "DPS Automatic Ban";
private String _AntiCheatHSKBanMessage = "HSK Automatic Ban";
private String _AntiCheatKPMBanMessage = "KPM Automatic Ban";
//External commands
private readonly String _instanceKey = GetRandom32BitHashCode();
//Admin assistants
public Boolean _EnableAdminAssistantPerk = false;
public Boolean _EnableAdminAssistants = false;
public Int32 _MinimumRequiredMonthlyReports = 10;
public Boolean _UseAAReportAutoHandler = false;
//Messaging
private List _PreMessageList;
private Boolean _RequirePreMessageUse;
private Boolean _ShowAdminNameInAnnouncement;
private Boolean _ShowNewPlayerAnnouncement = true;
private Boolean _ShowPlayerNameChangeAnnouncement = true;
private Boolean _ShowTargetedPlayerLeftNotification = true;
private Int32 _YellDuration = 5;
private Boolean _UseFirstSpawnMessage;
private Boolean _useFirstSpawnRepMessage;
private String _FirstSpawnMessage = "FIRST SPAWN MESSAGE";
private Boolean _DisplayTicketRatesInProconChat;
private Boolean _InformReputablePlayersOfAdminJoins = false;
private Boolean _InformAdminsOfAdminJoins = true;
private Boolean _UseAllCapsLimiter = false;
private Boolean _AllCapsLimiterSpecifiedPlayersOnly = false;
private Int32 _AllCapsLimterPercentage = 80;
private Int32 _AllCapsLimterMinimumCharacters = 15;
private Int32 _AllCapsLimiterWarnThreshold = 3;
private Int32 _AllCapsLimiterKillThreshold = 5;
private Int32 _AllCapsLimiterKickThreshold = 6;
//SpamBot
private Boolean _spamBotEnabled;
private List _spamBotSayList;
private readonly Queue _spamBotSayQueue = new Queue();
private Int32 _spamBotSayDelaySeconds = 300;
private DateTime _spamBotSayLastPost = DateTime.UtcNow - TimeSpan.FromSeconds(300);
private List _spamBotYellList;
private readonly Queue _spamBotYellQueue = new Queue();
private Int32 _spamBotYellDelaySeconds = 600;
private DateTime _spamBotYellLastPost = DateTime.UtcNow - TimeSpan.FromSeconds(600);
private List _spamBotTellList;
private readonly Queue _spamBotTellQueue = new Queue();
private Int32 _spamBotTellDelaySeconds = 900;
private DateTime _spamBotTellLastPost = DateTime.UtcNow - TimeSpan.FromSeconds(900);
private Boolean _spamBotExcludeAdminsAndWhitelist;
//Rules
private Double _ServerRulesDelay = 0.5;
private Double _ServerRulesInterval = 5;
private String[] _ServerRulesList = { "No AdKats rules have been set." };
private Boolean _ServerRulesNumbers = true;
private Boolean _ServerRulesYell;
//Locking
private Double _playerLockingManualDuration = 10;
private Boolean _playerLockingAutomaticLock;
private Double _playerLockingAutomaticDuration = 2.5;
//Round monitor
private Boolean _useRoundTimer;
private Double _maxRoundTimeMinutes = 30;
//Reputation
private Dictionary _commandSourceReputationDictionary;
private Dictionary _commandTargetReputationDictionary;
private const Double _reputationThresholdGood = 75;
private const Double _reputationThresholdBad = 0;
//Assist
private Queue _AssistAttemptQueue = new Queue();
DateTime _LastAutoAssist = DateTime.UtcNow - TimeSpan.FromSeconds(300);
//Battlecries
public enum BattlecryVolume
{
Say,
Yell,
Tell,
Disabled
}
private BattlecryVolume _battlecryVolume = BattlecryVolume.Disabled;
private Int32 _battlecryMaxLength = 100;
private String[] _battlecryDeniedWords = { };
//Faction randomizer
public enum FactionRandomizerRestriction
{
NoRestriction,
NeverSameFaction,
AlwaysSameFaction,
AlwaysSwapUSvsRU,
AlwaysSwapUSvsCN,
AlwaysSwapRUvsCN,
AlwaysBothUS,
AlwaysBothRU,
AlwaysBothCN,
AlwaysUSvsX,
AlwaysRUvsX,
AlwaysCNvsX,
NeverUSvsX,
NeverRUvsX,
NeverCNvsX
}
private Boolean _factionRandomizerEnable = false;
private FactionRandomizerRestriction _factionRandomizerRestriction = FactionRandomizerRestriction.NoRestriction;
private Boolean _factionRandomizerAllowRepeatSelection = true;
private Int32 _factionRandomizerCurrentTeam1 = 0;
private Int32 _factionRandomizerCurrentTeam2 = 1;
//MapModes
public List _AvailableMapModes = null;
//Weapon stats
protected AWeaponDictionary WeaponDictionary;
private StatLibrary _StatLibrary;
HashSet _AntiCheatCheckedPlayers = new HashSet();
HashSet _AntiCheatCheckedPlayersStats = new HashSet();
//Polling
private APoll _ActivePoll = null;
private TimeSpan _PollMaxDuration = TimeSpan.FromMinutes(4);
private TimeSpan _PollPrintInterval = TimeSpan.FromSeconds(30);
private Int32 _PollMaxVotes = 18;
private String[] _AvailablePolls = new String[] {
"event"
};
//Experimental
private Boolean _UseExperimentalTools;
private Boolean _ShowQuerySettings;
private Boolean _DebugKills;
private readonly Ping _PingProcessor = new Ping();
private Boolean _UseGrenadeCookCatcher;
private Dictionary _RoundCookers = new Dictionary();
private Boolean _UseWeaponLimiter;
private String _WeaponLimiterExceptionString = "_Flechette|_Slug|_Dart|_SHG";
private String _WeaponLimiterString = "ROADKILL|Death|_LVG|_HE|_Frag|_XM25|_FLASH|_V40|_M34|_Flashbang|_SMK|_Smoke|_FGM148|_Grenade|_SLAM|_NLAW|_RPG7|_C4|_Claymore|_FIM92|_M67|_SMAW|_SRAW|_Sa18IGLA|_Tomahawk|_3GL|USAS|MGL|UCAV";
//Events
private Boolean _EventWeeklyRepeat = false;
private DayOfWeek _EventWeeklyDay = DayOfWeek.Saturday;
private Boolean _EventPollAutomatic = false;
private Boolean _eventPollYellWinningRule = true;
private DateTime _EventDate = GetLocalEpochTime();
private Double _EventHour = 0;
private Int32 _EventTestRoundNumber = 999999;
private Double _EventAnnounceDayDifference = 7;
private Int32 _CurrentEventRoundNumber = 999999;
private List _EventRoundOptions = new List();
private Boolean _EventRoundPolled = false;
private Int32 _EventPollMaxOptions = 4;
private Int32 _EventRoundAutoPollsMax = 7;
private TimeSpan _EventRoundAutoVoteDuration = TimeSpan.FromMinutes(2.5);
private List _EventRoundPollOptions = new List();
private String _EventRoundOptionsEnum;
private String _eventBaseServerName = "Event Base Server Name";
private String _eventCountdownServerName = "Event Countdown Server Name";
private String _eventConcreteCountdownServerName = "Event Concrete Countdown Server Name";
private String _eventActiveServerName = "Event Active Server Name";
private readonly HashSet _DetectedWeaponCodes = new HashSet();
// Proxy
private Boolean _UseProxy = false;
private String _ProxyURL = "";
//Settings display
private Dictionary _SettingSections = new Dictionary();
private String _SettingSectionEnum;
private String _CurrentSettingSection;
private const String _AllSettingSections = "All Settings .*";
public readonly Logger Log;
public AdKats()
{
Log = new Logger(this);
Util = new Utilities(Log);
Threading = new ThreadManager(Log);
//Create the server reference
_serverInfo = new AServer(this);
//Set defaults for webclient
ServicePointManager.Expect100Continue = false;
//By default plugin is not enabled or ready
_pluginEnabled = false;
_threadsReady = false;
//Assign the match commands
_PluginEnabledMatchCommand = new MatchCommand("AdKats", "PluginEnabled", new List(), "AdKats_PluginEnabled", new List(), new ExecutionRequirements(ExecutionScope.None), "Useable by other plugins to check if AdKats is enabled or in process of starting up.");
_issueCommandMatchCommand = new MatchCommand("AdKats", "IssueCommand", new List(), "AdKats_IssueCommand", new List(), new ExecutionRequirements(ExecutionScope.None), "Useable by other plugins to call AdKats commands.");
_fetchAuthorizedSoldiersMatchCommand = new MatchCommand("AdKats", "FetchAuthorizedSoldiers", new List(), "AdKats_FetchAuthorizedSoldiers", new List(), new ExecutionRequirements(ExecutionScope.None), "Useable by other plugins to fetch authorized soldiers.");
_subscribeAsClientMatchCommand = new MatchCommand("AdKats", "SubscribeAsClient", new List(), "AdKats_SubscribeAsClient", new List(), new ExecutionRequirements(ExecutionScope.None), "Useable by other plugins to subscribe to group events.");
//Debug level is 0 by default
Log.DebugLevel = 0;
//Setting Sections
AddSettingSection("*", _AllSettingSections);
AddSettingSection("0", "Instance Settings");
AddSettingSection("1", "Server Settings");
AddSettingSection("2", "MySQL Settings");
AddSettingSection("3", "User Settings");
AddSettingSection("3-2", "Special Player Display");
AddSettingSection("3-3", "Verbose Special Player Display");
AddSettingSection("4", "Role Settings");
AddSettingSection("4-2", "Role Group Settings");
AddSettingSection("5", "Command Settings");
AddSettingSection("6", "Command List");
AddSettingSection("7", "Punishment Settings");
AddSettingSection("8", "Email Settings");
AddSettingSection("8-2", "PushBullet Settings");
AddSettingSection("8-3", "Discord WebHook Settings");
AddSettingSection("9", "TeamSwap Settings");
AddSettingSection("A10", "Admin Assistant Settings");
AddSettingSection("A11", "Player Mute Settings");
AddSettingSection("A12", "Messaging Settings");
AddSettingSection("A12-2", "SpamBot Settings");
AddSettingSection("A12-3", "Battlecry Settings - Thanks WDF");
AddSettingSection("A12-4", "All-Caps Chat Monitor");
AddSettingSection("A13", "Banning Settings");
AddSettingSection("A13-2", "Ban Enforcer Settings");
AddSettingSection("A13-3", "Mini Ban Management");
AddSettingSection("A14", "External Command Settings");
AddSettingSection("A15", "VOIP Settings");
AddSettingSection("A16", "Orchestration Settings");
AddSettingSection("A17", "Round Settings");
AddSettingSection("A17-2", "Round Faction Randomizer Settings - Thanks FPSG");
AddSettingSection("A18", "AntiCheat Settings");
AddSettingSection("A19", "Server Rules Settings");
AddSettingSection("B20", "AFK Settings");
AddSettingSection("B21", "Ping Enforcer Settings");
AddSettingSection("B22", "Commander Manager Settings");
AddSettingSection("B23", "Player Locking Settings");
AddSettingSection("B24", "Surrender Vote Settings");
AddSettingSection("B25", "Auto-Surrender Settings");
AddSettingSection("B25-2", "Auto-Nuke Settings");
AddSettingSection("B26", "Statistics Settings");
AddSettingSection("B27", "Populator Monitor Settings - Thanks CMWGaming");
AddSettingSection("B28", "Teamspeak Player Monitor Settings - Thanks CMWGaming");
AddSettingSection("B29", "Discord Player Monitor Settings");
AddSettingSection("C30", "Team Power Monitor");
AddSettingSection("C31", "Weapon Limiter Settings");
AddSettingSection("C32", "Challenge Settings");
AddSettingSection("D98", "Database Timing Mismatch");
AddSettingSection("D99", "Debugging");
AddSettingSection("X98", "Proxy Settings");
AddSettingSection("X99", "Experimental");
AddSettingSection("Y99", "Event Automation");
//Build setting section enum
_SettingSectionEnum = String.Empty;
Random random = new Random(Environment.TickCount);
var sections = _SettingSections.Keys.ToList();
sections.Sort();
foreach (String sectionKey in sections)
{
if (String.IsNullOrEmpty(_SettingSectionEnum))
{
_SettingSectionEnum += "enum.SettingSectionEnum_" + random.Next(100000, 999999) + "(";
}
else
{
_SettingSectionEnum += "|";
}
_SettingSectionEnum += GetSettingSection(sectionKey);
}
_SettingSectionEnum += ")";
//Set default setting section
_CurrentSettingSection = GetSettingSection("*");
//Build event round options enum
_EventRoundOptionsEnum = String.Empty;
random = new Random(Environment.TickCount);
foreach (String map in AEventOption.MapNames.Values)
{
foreach (String mode in AEventOption.ModeNames.Values)
{
foreach (String rule in AEventOption.RuleNames.Values.Where(ruleValue => ruleValue != AEventOption.RuleNames[AEventOption.RuleCode.ENDEVENT]))
{
if (String.IsNullOrEmpty(_EventRoundOptionsEnum))
{
_EventRoundOptionsEnum += "enum.EventRoundOptionsEnum_" + random.Next(100000, 999999) + "(Remove|";
}
else
{
_EventRoundOptionsEnum += "|";
}
_EventRoundOptionsEnum += map + "/" + mode + "/" + rule;
}
}
}
_EventRoundOptionsEnum += ")";
//Init the punishment severity index
_PunishmentSeverityIndex = new List {
"warn",
"kill",
"kick",
"tban60",
"tban120",
"tbanday",
"tban2days",
"tban3days",
"tbanweek",
"tban2weeks",
"tbanmonth",
"ban"
};
//Init the pre-message list
_PreMessageList = new List {
"Predefined message 1",
"Predefined message 2",
"Predefined message 3",
"Predefined message 4",
"Predefined message 5",
};
//Init the spam message lists
_spamBotSayList = new List {
"AdminSay1",
"AdminSay2",
"AdminSay3"
};
foreach (String line in _spamBotSayList)
{
_spamBotSayQueue.Enqueue(line);
}
_spamBotYellList = new List {
"AdminYell1",
"AdminYell2",
"AdminYell3"
};
foreach (String line in _spamBotYellList)
{
_spamBotYellQueue.Enqueue(line);
}
_spamBotTellList = new List {
"AdminTell1",
"AdminTell2",
"AdminTell3"
};
foreach (String line in _spamBotTellList)
{
_spamBotTellQueue.Enqueue(line);
}
//Fill the population durations
foreach (PopulationState popState in Enum.GetValues(typeof(PopulationState)).Cast())
{
_populationDurations[popState] = TimeSpan.Zero;
}
//Fetch the plugin description and changelog
FetchPluginDocumentation();
//Fill command descriptions
FillCommandDescDictionary();
//Prepare the keep-alive threads
SetupStatusMonitor();
SetupFastStatusMonitor();
//Start up TeamSpeakClientViewer
_TeamspeakManager = new TeamSpeakClientViewer(this);
_DiscordManager = new DiscordManager(this);
FillReadableMapModeDictionaries();
try
{
//Initialize the weapon name dictionary
WeaponDictionary = new AWeaponDictionary(this);
//Initialize the challenge manager
ChallengeManager = new AChallengeManager(this);
}
catch (Exception e)
{
Log.HandleException(new AException("Error while enabling weapon dictionary or challenge manager.", e));
}
}
public String GetPluginName()
{
return "AdKats - Advanced In-Game Admin";
}
public String GetPluginVersion()
{
return PluginVersion;
}
public String GetPluginAuthor()
{
return "ColColonCleaner";
}
public String GetPluginWebsite()
{
return "github.com/AdKats/AdKats";
}
public String GetPluginDescription()
{
String concat = @"
";
try
{
if (!_fetchedPluginInformation)
{
//Wait up to 10 seconds for the description to fetch
Log.Debug(() => "Waiting for plugin information...", 1);
_PluginDescriptionWaitHandle.WaitOne(10000);
}
//Parse out the descriptions
if (!String.IsNullOrEmpty(_pluginVersionStatusString))
{
concat += _pluginVersionStatusString;
}
if (!String.IsNullOrEmpty(_pluginLinks))
{
concat += _pluginLinks;
}
}
catch (Exception e)
{
Log.HandleException(new AException("Error while fetching plugin information.", e));
}
return concat;
}
private String AddSettingSection(String number, String desc)
{
_SettingSections[number] = desc;
return GetSettingSection(number);
}
private String GetSettingSection(String number)
{
return number + ". " + _SettingSections[number];
}
private Boolean IsActiveSettingSection(String number)
{
return _CurrentSettingSection == GetSettingSection("*") || _CurrentSettingSection == GetSettingSection(number);
}
public void BuildUnreadySettings(List lstReturn)
{
List buildList = new List();
try
{
if (!_settingsLocked)
{
if (_useKeepAlive)
{
buildList.Add(new CPluginVariable(GetSettingSection("0") + t + "Auto-Enable/Keep-Alive", typeof(Boolean), true));
}
buildList.Add(new CPluginVariable("Complete these settings before enabling.", typeof(String), "Once enabled, more settings will appear."));
//SQL Settings
buildList.Add(new CPluginVariable(GetSettingSection("2") + t + "MySQL Hostname", typeof(String), _mySqlHostname));
buildList.Add(new CPluginVariable(GetSettingSection("2") + t + "MySQL Port", typeof(String), _mySqlPort));
buildList.Add(new CPluginVariable(GetSettingSection("2") + t + "MySQL Database", typeof(String), _mySqlSchemaName));
buildList.Add(new CPluginVariable(GetSettingSection("2") + t + "MySQL Username", typeof(String), _mySqlUsername));
buildList.Add(new CPluginVariable(GetSettingSection("2") + t + "MySQL Password", typeof(String), _mySqlPassword));
}
//Debugging Settings
buildList.Add(new CPluginVariable(GetSettingSection("D99") + t + "Debug level", typeof(Int32), Log.DebugLevel));
//Database Timing
if (_dbTimingChecked && !_dbTimingValid)
{
buildList.Add(new CPluginVariable(GetSettingSection("D98") + t + "Override Timing Confirmation", typeof(Boolean), _timingValidOverride));
}
lstReturn.AddRange(buildList);
}
catch (Exception e)
{
Log.HandleException(new AException("Error building unready setting section.", e));
lstReturn.Add(new CPluginVariable(GetSettingSection("0") + t + "Failed to build setting section.", typeof(String), ""));
}
}
public void BuildReadyLockedSettings(List lstReturn)
{
List buildList = new List();
try
{
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Server ID (Display)", typeof(int), _serverInfo.ServerID));
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Server IP (Display)", typeof(String), _serverInfo.ServerIP));
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Server Round (Display)", typeof(String), _roundID));
if (_UseBanEnforcer)
{
buildList.Add(new CPluginVariable(GetSettingSection("A13-3") + t + "NAME Ban Count", typeof(int), _NameBanCount));
buildList.Add(new CPluginVariable(GetSettingSection("A13-3") + t + "GUID Ban Count", typeof(int), _GUIDBanCount));
buildList.Add(new CPluginVariable(GetSettingSection("A13-3") + t + "IP Ban Count", typeof(int), _IPBanCount));
buildList.Add(new CPluginVariable(GetSettingSection("A13-3") + t + "Ban Search", typeof(String), ""));
buildList.AddRange(_BanEnforcerSearchResults.Select(aBan => new CPluginVariable(GetSettingSection("A13-3") + t + "BAN" + aBan.ban_id + s + aBan.ban_record.target_player.player_name + s + aBan.ban_record.source_name + s + aBan.ban_record.record_message, "enum.commandActiveEnum(Active|Disabled|Expired)", aBan.ban_status)));
}
buildList.Add(new CPluginVariable(GetSettingSection("D99") + t + "Debug level", typeof(int), Log.DebugLevel));
buildList.Add(new CPluginVariable(GetSettingSection("D99") + t + "Debug Soldier Name", typeof(String), _debugSoldierName));
lstReturn.AddRange(buildList);
}
catch (Exception e)
{
Log.HandleException(new AException("Error building ready locked setting section.", e));
lstReturn.Add(new CPluginVariable(GetSettingSection("1") + t + "Failed to build setting section.", typeof(String), ""));
}
}
public void BuildServerSettings(List lstReturn)
{
List buildList = new List();
try
{
if (IsActiveSettingSection("1"))
{
//Server Settings
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Setting Import", typeof(String), _serverInfo.ServerID));
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Server ID (Display)", typeof(Int32), _serverInfo.ServerID));
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Server IP (Display)", typeof(String), _serverInfo.ServerIP));
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Server Round (Display)", typeof(String), _roundID));
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Server Game (Display)", typeof(String), GameVersion.ToString()));
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Short Server Name", typeof(String), _shortServerName));
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Low Population Value", typeof(Int32), _lowPopulationPlayerCount));
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "High Population Value", typeof(Int32), _highPopulationPlayerCount));
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Automatic Server Restart When Empty", typeof(Boolean), _automaticServerRestart));
if (_automaticServerRestart)
{
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Automatic Restart Minimum Uptime Hours", typeof(Int32), _automaticServerRestartMinHours));
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Automatic Procon Reboot When Server Reboots", typeof(Boolean), _automaticServerRestartProcon));
}
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Procon Memory Usage MB (Display)", typeof(Int32), _MemoryUsageCurrent));
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Procon Memory Usage MB Warning", typeof(Int32), _MemoryUsageWarn));
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Procon Memory Usage MB AdKats Restart", typeof(Int32), _MemoryUsageRestartPlugin));
buildList.Add(new CPluginVariable(GetSettingSection("1") + t + "Procon Memory Usage MB Procon Restart", typeof(Int32), _MemoryUsageRestartProcon));
}
lstReturn.AddRange(buildList);
}
catch (Exception e)
{
Log.HandleException(new AException("Error building server setting section.", e));
lstReturn.Add(new CPluginVariable(GetSettingSection("1") + t + "Failed to build setting section.", typeof(String), ""));
}
}
public void BuildSQLSettings(List lstReturn)
{
List buildList = new List();
try
{
if (IsActiveSettingSection("2"))
{
//SQL Settings
buildList.Add(new CPluginVariable(GetSettingSection("2") + t + "MySQL Hostname", typeof(String), _mySqlHostname));
buildList.Add(new CPluginVariable(GetSettingSection("2") + t + "MySQL Port", typeof(String), _mySqlPort));
buildList.Add(new CPluginVariable(GetSettingSection("2") + t + "MySQL Database", typeof(String), _mySqlSchemaName));
buildList.Add(new CPluginVariable(GetSettingSection("2") + t + "MySQL Username", typeof(String), _mySqlUsername));
buildList.Add(new CPluginVariable(GetSettingSection("2") + t + "MySQL Password", typeof(String), _mySqlPassword));
}
lstReturn.AddRange(buildList);
}
catch (Exception e)
{
Log.HandleException(new AException("Error building sql setting section.", e));
lstReturn.Add(new CPluginVariable(GetSettingSection("2") + t + "Failed to build setting section.", typeof(String), ""));
}
}
public void BuildUserSettings(List lstReturn)
{
List buildList = new List();
try
{
if (IsActiveSettingSection("3"))
{
//User Settings
buildList.Add(new CPluginVariable(GetSettingSection("3") + t + "Add User", typeof(String), ""));
if (_userCache.Count > 0)
{
//Sort access list by access level, then by id
List tempAccess = _userCache.Values.ToList();
tempAccess.Sort((a1, a2) => (a1.user_role.role_powerLevel == a2.user_role.role_powerLevel) ? (String.CompareOrdinal(a1.user_name.ToLower(), a2.user_name.ToLower())) : ((a1.user_role.role_powerLevel > a2.user_role.role_powerLevel) ? (-1) : (1)));
String roleEnum = String.Empty;
if (_RoleKeyDictionary.Count > 0)
{
Random random = new Random();
foreach (ARole role in _RoleKeyDictionary.Values.ToList())
{
if (String.IsNullOrEmpty(roleEnum))
{
roleEnum += "enum.RoleEnum_" + random.Next(100000, 999999) + "(";
}
else
{
roleEnum += "" + t.ToString();
}
roleEnum += role.role_name;
}
roleEnum += ")";
}
foreach (AUser user in tempAccess)
{
String userPrefix = GetSettingSection("3") + t + "USR" + user.user_id + s + user.user_name + s;
if (_UseEmail)
{
buildList.Add(new CPluginVariable(userPrefix + "User Email", typeof(String), user.user_email));
}
buildList.Add(new CPluginVariable(userPrefix + "User Expiration", typeof(String), user.user_expiration.ToShortDateString()));
buildList.Add(new CPluginVariable(userPrefix + "User Notes", typeof(String), user.user_notes));
//Do not display phone input until that operation is available for use
//lstReturn.Add(new CPluginVariable(userPrefix + "User Phone", typeof(String), user.user_phone));
buildList.Add(new CPluginVariable(userPrefix + "User Role", roleEnum, user.user_role.role_name));
buildList.Add(new CPluginVariable(userPrefix + "Delete User?", typeof(String), ""));
buildList.Add(new CPluginVariable(userPrefix + "Add Soldier?", typeof(String), ""));
String soldierPrefix = userPrefix + "Soldiers" + s;
buildList.AddRange(user.soldierDictionary.Values.Select(aPlayer =>
new CPluginVariable(soldierPrefix + aPlayer.player_id + s +
(_gameIDDictionary.ContainsKey(aPlayer.game_id) ? (_gameIDDictionary[aPlayer.game_id].ToString()) : ("INVALID GAME ID [" + aPlayer.game_id + "]")) + s +
aPlayer.player_name + s + "Delete Soldier?", typeof(String), "")));
}
}
else
{
if (_firstUserListComplete)
{
buildList.Add(new CPluginVariable(GetSettingSection("3") + t + "No Users in User List", typeof(String), "Add Users with 'Add User'."));
}
else
{
buildList.Add(new CPluginVariable(GetSettingSection("3") + t + "Please Wait, Fetching User List.", typeof(String), "Please Wait, Fetching User List."));
}
}
}
lstReturn.AddRange(buildList);
}
catch (Exception e)
{
Log.HandleException(new AException("Error building user setting section.", e));
lstReturn.Add(new CPluginVariable(GetSettingSection("3") + t + "Failed to build setting section.", typeof(String), ""));
}
}
public void BuildSpecialPlayerSettings(List lstReturn)
{
List buildList = new List();
try
{
if (IsActiveSettingSection("3-2"))
{
if (_firstUserListComplete)
{
//Special Player Settings
Boolean anyList = false;
foreach (ASpecialGroup asGroup in _specialPlayerGroupIDDictionary.Values.OrderBy(aGroup => aGroup.group_name))
{
List groupList = new List();
foreach (ASpecialPlayer asPlayer in GetASPlayersOfGroup(asGroup.group_key).OrderBy(asPlayer => asPlayer.player_object != null ? (asPlayer.player_object.GetVerboseName()) : (asPlayer.player_identifier)))
{
String playerIdentifier = null;
if (asPlayer.player_object != null && !String.IsNullOrEmpty(asPlayer.player_object.player_name))
{
playerIdentifier = asPlayer.player_object.player_name;
}
else
{
playerIdentifier = asPlayer.player_identifier;
}
if (String.IsNullOrEmpty(playerIdentifier))
{
continue;
}
TimeSpan duration = (asPlayer.player_expiration - UtcNow()).Duration();
if (duration.TotalDays > 3650)
{
playerIdentifier += " | Permanent";
}
else
{
playerIdentifier += " | " + FormatTimeString(duration, 3);
}
if (!groupList.Contains(playerIdentifier))
{
groupList.Add(playerIdentifier);
}
}
if (groupList.Any())
{
anyList = true;
buildList.Add(new CPluginVariable(GetSettingSection("3-2") + t + "[" + groupList.Count + "] " + asGroup.group_name + " (Display)", typeof(String[]), groupList.ToArray()));
}
}
if (!anyList)
{
buildList.Add(new CPluginVariable(GetSettingSection("3-2") + t + "All Groups Empty", typeof(String), "All Groups Empty"));
}
}
}
lstReturn.AddRange(buildList);
}
catch (Exception e)
{
Log.HandleException(new AException("Error building special player setting section.", e));
lstReturn.Add(new CPluginVariable(GetSettingSection("3-2") + t + "Failed to build setting section.", typeof(String), ""));
}
}
public void BuildVerboseSpecialPlayerSettings(List lstReturn)
{
List buildList = new List();
try
{
if (IsActiveSettingSection("3-3"))
{
if (_firstUserListComplete)
{
//Verbose Special Player Settings
Boolean anyVerbostList = false;
foreach (ASpecialGroup asGroup in _specialPlayerGroupIDDictionary.Values.OrderBy(aGroup => aGroup.group_name))
{
List groupList = new List();
foreach (ASpecialPlayer asPlayer in GetVerboseASPlayersOfGroup(asGroup.group_key).OrderBy(asPlayer => asPlayer.player_object != null ? (asPlayer.player_object.GetVerboseName()) : (asPlayer.player_identifier)))
{
String playerIdentifier = null;
if (asPlayer.player_object != null && !String.IsNullOrEmpty(asPlayer.player_object.player_name))
{
playerIdentifier = asPlayer.player_object.player_name;
}
else
{
playerIdentifier = asPlayer.player_identifier;
}
if (String.IsNullOrEmpty(playerIdentifier))
{
continue;
}
if (!groupList.Contains(playerIdentifier))
{
groupList.Add(playerIdentifier);
}
}
if (groupList.Any())
{
anyVerbostList = true;
buildList.Add(new CPluginVariable(GetSettingSection("3-3") + t + "[" + groupList.Count + "] Verbose " + asGroup.group_name + " (Display)", typeof(String[]), groupList.ToArray()));
}
}
if (!anyVerbostList)
{
buildList.Add(new CPluginVariable(GetSettingSection("3-3") + t + "All Verbose Groups Empty", typeof(String), "All Verbose Groups Empty"));
}
}
}
lstReturn.AddRange(buildList);
}
catch (Exception e)
{
Log.HandleException(new AException("Error building verbose special player setting section.", e));
lstReturn.Add(new CPluginVariable(GetSettingSection("3-3") + t + "Failed to build setting section.", typeof(String), ""));
}
}
public void BuildRoleSettings(List lstReturn)
{
List buildList = new List();
try
{
if (IsActiveSettingSection("4"))
{
//Role Settings
buildList.Add(new CPluginVariable(GetSettingSection("4") + t + "Add Role", typeof(String), ""));
var useCache = NowDuration(_RoleCommandCacheUpdate).TotalMinutes < 5 &&
_RoleCommandCache != null &&
NowDuration(_RoleCommandCacheUpdateBufferStart) > _RoleCommandCacheUpdateBufferDuration;
if (_RoleIDDictionary.Count > 0)
{
if (!useCache)
{
// We are not using the cache; clear the entries to we can rebuild it
_RoleCommandCache.Clear();
_RoleCommandCacheUpdate = UtcNow();
}
lock (_RoleIDDictionary)
{
foreach (ARole aRole in _RoleKeyDictionary.Values.ToList())
{
lock (_CommandIDDictionary)
{
Random random = new Random();
String rolePrefix = GetSettingSection("4") + t + "RLE" + aRole.role_id + s + ((RoleIsAdmin(aRole)) ? ("[A]") : ("")) + aRole.role_name + s;
foreach (var aCommand in _CommandNameDictionary.Values.Where(dCommand => dCommand.command_active == ACommand.CommandActive.Active &&
// Never allow the confirm/cancel commands to be edited, players need these to be universal across servers
dCommand.command_key != "command_confirm" &&
dCommand.command_key != "command_cancel" &&
// Never allow the default guest role to have admin commands assigned to it
(aRole.role_key != "guest_default" || !dCommand.command_playerInteraction)))
{
var allowed = aRole.RoleAllowedCommands.ContainsKey(aCommand.command_key);
var key = aRole.role_id + "-" + aCommand.command_id;
String display;
if (useCache && _RoleCommandCache.ContainsKey(key))
{
// Using the role command cache; fetch from the dictionary
display = _RoleCommandCache[key];
}
else
{
display = rolePrefix + "CDE" + aCommand.command_id + s + aCommand.command_name + ((aCommand.command_playerInteraction) ? (" [ADMIN]") : ("")) + ((aCommand.command_playerInteraction && allowed) ? (" <---") : (""));
// We've just generated a new display string, add it to the cache
_RoleCommandCache[key] = display;
}
buildList.Add(new CPluginVariable(display, "enum.roleAllowCommandEnum(Allow|Deny)", allowed ? ("Allow") : ("Deny")));
}
//Do not display the delete option for default guest
if (aRole.role_key != "guest_default")
{
buildList.Add(new CPluginVariable(rolePrefix + "Delete Role? (All assignments will be removed)", typeof(String), ""));
}
}
}
}
}
else
{
buildList.Add(new CPluginVariable(GetSettingSection("4") + t + "Role List Empty", typeof(String), "No valid roles found in database."));
}
}
lstReturn.AddRange(buildList);
}
catch (Exception e)
{
Log.HandleException(new AException("Error building role setting section.", e));
lstReturn.Add(new CPluginVariable(GetSettingSection("4") + t + "Failed to build setting section.", typeof(String), ""));
}
}
public void BuildRoleGroupSettings(List lstReturn)
{
List buildList = new List();
try
{
if (IsActiveSettingSection("4-2"))
{
//Role Group Settings
if (_RoleIDDictionary.Count > 0)
{
lock (_RoleIDDictionary)
{
foreach (ARole aRole in _RoleKeyDictionary.Values.ToList())
{
lock (_specialPlayerGroupKeyDictionary)
{
Random random = new Random();
String rolePrefix = GetSettingSection("4-2") + t + "RLE" + aRole.role_id + s + ((RoleIsAdmin(aRole)) ? ("[A]") : ("")) + aRole.role_name + s;
buildList.AddRange(from aGroup in _specialPlayerGroupKeyDictionary.Values
let allowed = aRole.RoleSetGroups.ContainsKey(aGroup.group_key)
let required =
(aGroup.group_key == "slot_reserved" && _FeedServerReservedSlots && _FeedServerReservedSlots_Admins && RoleIsAdmin(aRole)) ||
(aGroup.group_key == "slot_spectator" && _FeedServerSpectatorList && _FeedServerSpectatorList_Admins && RoleIsAdmin(aRole)) ||
(aGroup.group_key == "whitelist_multibalancer" && _FeedMultiBalancerWhitelist && _FeedMultiBalancerWhitelist_Admins && RoleIsAdmin(aRole)) ||
(aGroup.group_key == "whitelist_teamkill" && _FeedTeamKillTrackerWhitelist && _FeedTeamKillTrackerWhitelist_Admins && RoleIsAdmin(aRole)) ||
(aGroup.group_key == "whitelist_spambot" && _spamBotExcludeAdminsAndWhitelist && RoleIsAdmin(aRole))
let blocked = (aGroup.group_key == "whitelist_adminassistant" && RoleIsAdmin(aRole))
let enumString = blocked ? "enum.roleSetGroupEnum_blocked(Blocked Based On Other Settings)" : (required ? "enum.roleSetGroupEnum_required(Required Based On Other Settings)" : "enum.roleSetGroupEnum(Assign|Ignore)")
let display = rolePrefix + "GPE" + aGroup.group_id + s + aGroup.group_name
select new CPluginVariable(display, enumString, blocked ? "Blocked Based On Other Settings" : (required ? "Required Based On Other Settings" : (allowed ? ("Assign") : ("Ignore")))));
}
}
}
}
else
{
buildList.Add(new CPluginVariable(GetSettingSection("4-2") + t + "Role List Empty", typeof(String), "No valid roles found in database."));
}
}
lstReturn.AddRange(buildList);
}
catch (Exception e)
{
Log.HandleException(new AException("Error building role group setting section.", e));
lstReturn.Add(new CPluginVariable(GetSettingSection("4-2") + t + "Failed to build setting section.", typeof(String), ""));
}
}
public void BuildCommandSettings(List lstReturn)
{
List buildList = new List();
try
{
if (IsActiveSettingSection("5"))
{
buildList.Add(new CPluginVariable(GetSettingSection("5") + t + "Minimum Required Reason Length", typeof(int), _RequiredReasonLength));
buildList.Add(new CPluginVariable(GetSettingSection("5") + t + "Minimum Report Handle Seconds", typeof(int), _MinimumReportHandleSeconds));
buildList.Add(new CPluginVariable(GetSettingSection("5") + t + "Minimum Minutes Into Round To Use Assist", typeof(int), _minimumAssistMinutes));
buildList.Add(new CPluginVariable(GetSettingSection("5") + t + "Maximum Temp-Ban Duration Minutes", typeof(Double), _MaxTempBanDuration.TotalMinutes));
buildList.Add(new CPluginVariable(GetSettingSection("5") + t + "Countdown Duration before a Nuke is fired", typeof(int), _NukeCountdownDurationSeconds));
buildList.Add(new CPluginVariable(GetSettingSection("5") + t + "Allow Commands from Admin Say", typeof(Boolean), _AllowAdminSayCommands));
buildList.Add(new CPluginVariable(GetSettingSection("5") + t + "Bypass all command confirmation -DO NOT USE-", typeof(Boolean), _bypassCommandConfirmation));
buildList.Add(new CPluginVariable(GetSettingSection("5") + t + "External plugin player commands", typeof(String[]), _ExternalPlayerCommands.ToArray()));
buildList.Add(new CPluginVariable(GetSettingSection("5") + t + "External plugin admin commands", typeof(String[]), _ExternalAdminCommands.ToArray()));
buildList.Add(new CPluginVariable(GetSettingSection("5") + t + "Command Target Whitelist Commands", typeof(String[]), _CommandTargetWhitelistCommands.ToArray()));
buildList.Add(new CPluginVariable(GetSettingSection("5") + t + "Reserved slot grants access to squad lead command", typeof(Boolean), _ReservedSquadLead));
buildList.Add(new CPluginVariable(GetSettingSection("5") + t + "Reserved slot grants access to self-move command", typeof(Boolean), _ReservedSelfMove));
buildList.Add(new CPluginVariable(GetSettingSection("5") + t + "Reserved slot grants access to self-kill command", typeof(Boolean), _ReservedSelfKill));
}
lstReturn.AddRange(buildList);
}
catch (Exception e)
{
Log.HandleException(new AException("Error building command setting section.", e));
lstReturn.Add(new CPluginVariable(GetSettingSection("5") + t + "Failed to build setting section.", typeof(String), ""));
}
}
public void BuildCommandListSettings(List lstReturn)
{
List buildList = new List();
try
{
if (IsActiveSettingSection("6"))
{
//Command Settings
if (_CommandNameDictionary.Count > 0)
{
lock (_CommandIDDictionary)
{
foreach (ACommand command in _CommandIDDictionary.Values.ToList())
{
if (command.command_active != ACommand.CommandActive.Invisible)
{
String commandPrefix = GetSettingSection("6") + t + "CDE" + command.command_id + s + command.command_name + s;
buildList.Add(new CPluginVariable(commandPrefix + "Active", "enum.commandActiveEnum(Active|Disabled)", command.command_active.ToString()));
if (command.command_active != ACommand.CommandActive.Disabled)
{
if (command.command_logging != ACommand.CommandLogging.Mandatory && command.command_logging != ACommand.CommandLogging.Unable)
{
buildList.Add(new CPluginVariable(commandPrefix + "Logging", "enum.commandLoggingEnum(Log|Ignore)", command.command_logging.ToString()));
}
buildList.Add(new CPluginVariable(commandPrefix + "Text", typeof(String), command.command_text));
buildList.Add(new CPluginVariable(commandPrefix + "Access Method", CreateEnumString(typeof(ACommand.CommandAccess)), command.command_access.ToString()));
}
}
}
}
}
else
{
buildList.Add(new CPluginVariable(GetSettingSection("6") + t + "Command List Empty", typeof(String), "No valid commands found in database."));
}
}
lstReturn.AddRange(buildList);
}
catch (Exception e)
{
Log.HandleException(new AException("Error building command list setting section.", e));
lstReturn.Add(new CPluginVariable(GetSettingSection("6") + t + "Failed to build setting section.", typeof(String), ""));
}
}
public void BuildPunishmentSettings(List