Results 1 to 10 of 33
Thread: Plugin API 2.0
-
07-10-2010, 07:53 #1
Plugin API 2.0
IPRoConPluginInterface
Before you used to implement different interfaces in a vague attempt to have version control to plugins. It was a bad idea and generally a terrible way of doing it. It didn't even work =)
Now you only implement IPRoConPluginInterface, the rest of the interfaces are blank but still inherit from IPRoConPluginInterface so it does not really matter. They are only left in the code for legacy reasons.
IPRoConPluginInterface consists of the absolute basics. You only need to implement these methods for your plugin to function. I think the new Spambot only implements these methods and no other.
Code:// Compile and init events void OnPluginLoaded(string strHostName, string strPort, string strPRoConVersion); void OnPluginEnable(); void OnPluginDisable(); // Plugin details string GetPluginName(); string GetPluginVersion(); string GetPluginAuthor(); string GetPluginWebsite(); string GetPluginDescription(); // Plugin variables List<CPluginVariable> GetDisplayPluginVariables(); List<CPluginVariable> GetPluginVariables(); void SetPluginVariable(string strVariable, string strValue);
The new class to inherit from, this used to be CPRoConMarshalByRefObject but PRoConPluginAPI inherits from that and implements all of the methods that used to be in the other interfaces as virtual methods for you to override.
This class will expand with community made helper methods that are general to all plugins. I've seen a couple but didn't throw them in just yet.
#include preprocessor directive
#include is not using!
#include is dumb and simply opens up a file whose path is relative to the .cs file and replaces the directive with the contents of the file. This takes place on your source code before any compiling takes place. The idea is that for plugins to function in different games only very minor sections of code need to be changed.
You'll see the updated plugins .cs file will generally sit in the BFBC2 or MOH directory with one line, including the shared source between the two games. Open it up, have a look. It's pretty simply but makes writing plugins a lot neater provided you use some naming structure.
this.RegisterEvents
The highest cpu usage, most time consuming-est task within procon is remoting each packet recieved to each plugin. You can see a very noticeable speed difference if you enable all of your plugins and restart procon. Quickly switch to the console and you'll see it tick over very slowly. Now disable all of your plugins and repeat. I don't have the numbers handy but I'm sure if you google it you'll come across number like: in the time it takes to do 1,000,000 calls to methods within the same AppDomain you'll only be able to do 30,000 calls via remoting.
Soooo now you know how really really slow it is so you can now make your plugin faster, and i'll nag you to do it as well =)
The below code will tell procon that your plugin does not want any of the other events fired and is only interested in the player list and the player join event.
Code:public void OnPluginLoaded(string strHostName, string strPort, string strPRoConVersion) { this.RegisterEvents(this.GetType().Name, "OnListPlayers", "OnPlayerJoin"); }
I started at DICE late Oct. 2014, so ignore every post before that.
-
07-10-2010, 17:44 #2
Re: Plugin API 2.0
Code:// new events #region Text Chat Moderation public virtual void OnTextChatModerationAddPlayer(TextChatModerationEntry playerEntry) { } public virtual void OnTextChatModerationRemovePlayer(TextChatModerationEntry playerEntry) { } public virtual void OnTextChatModerationClear() { } public virtual void OnTextChatModerationSave() { } public virtual void OnTextChatModerationLoad() { } public virtual void OnTextChatModerationList(TextChatModerationDictionary moderationList) { } #endregion #region Text Chat Moderation Settings public virtual void OnTextChatModerationMode(ServerModerationModeType mode) { } public virtual void OnTextChatSpamTriggerCount(int limit) { } public virtual void OnTextChatSpamDetectionTime(int limit) { } public virtual void OnTextChatSpamCoolDownTime(int limit) { } #endregion public virtual void OnPlayerKilledByAdmin(string soldierName) { } public virtual void OnPlayerKickedByAdmin(string soldierName, string reason) { } public virtual void OnPlayerMovedByAdmin(string soldierName, int destinationTeamId, int destinationSquadId, bool forceKilled) { } public virtual void OnAccountLogin(string accountName, string ip, CPrivileges privileges) { } public virtual void OnAccountLogout(string accountName, string ip, CPrivileges privileges) { } // new methods // List of account names currently logged in List<string> GetLoggedInAccountUsernames(); void RegisterEvents(string className, params string[] a_events);
I started at DICE late Oct. 2014, so ignore every post before that.
-
29-10-2010, 07:07 #3
- Join Date
- Sep 2010
- Posts
- 800
Re: Plugin API 2.0
Why have IPRoConPluginInterface and PRoConPluginAPI ... instead of just making PRoConPluginAPI an abstract class?
-
11-11-2011, 17:48 #4
Hi.
Time for an update.
Note that not all are usable with BF3 and note OnLevelLoaded and OnMapListGetMapIndices. The last one will be usable with the next Procon version and will carry the data queried by mapList.getMapIndices.
Code:#region Global/Login public virtual void OnLogin() { } public virtual void OnLogout() { } public virtual void OnQuit() { } public virtual void OnVersion(string serverType, string version) { } public virtual void OnHelp(List<string> commands) { } public virtual void OnRunScript(string scriptFileName) { } public virtual void OnRunScriptError(string scriptFileName, int lineError, string errorDescription) { } public virtual void OnServerInfo(CServerInfo serverInfo) { } public virtual void OnResponseError(List<string> requestWords, string error) { } public virtual void OnYelling(string message, int messageDuration, CPlayerSubset subset) { } public virtual void OnSaying(string message, CPlayerSubset subset) { } #endregion #region Map Functions public virtual void OnRestartLevel() { } public virtual void OnSupportedMaps(string playlist, List<string> lstSupportedMaps) { } public virtual void OnListPlaylists(List<string> playlists) { } public virtual void OnListPlayers(List<CPlayerInfo> players, CPlayerSubset subset) { } public virtual void OnEndRound(int iWinningTeamID) { } public virtual void OnRunNextLevel() { } public virtual void OnCurrentLevel(string mapFileName) { } #region BFBC2 public virtual void OnPlaylistSet(string playlist) { } #endregion #endregion #region Banlist public virtual void OnBanAdded(CBanInfo ban) { } public virtual void OnBanRemoved(CBanInfo ban) { } public virtual void OnBanListClear() { } public virtual void OnBanListSave() { } public virtual void OnBanListLoad() { } public virtual void OnBanList(List<CBanInfo> banList) { } #endregion #region Text Chat Moderation /// BFBC2 & MoH public virtual void OnTextChatModerationAddPlayer(TextChatModerationEntry playerEntry) { } public virtual void OnTextChatModerationRemovePlayer(TextChatModerationEntry playerEntry) { } public virtual void OnTextChatModerationClear() { } public virtual void OnTextChatModerationSave() { } public virtual void OnTextChatModerationLoad() { } public virtual void OnTextChatModerationList(TextChatModerationDictionary moderationList) { } #endregion #region Maplist public virtual void OnMaplistConfigFile(string configFileName) { } public virtual void OnMaplistLoad() { } public virtual void OnMaplistSave() { } public virtual void OnMaplistList(List<MaplistEntry> lstMaplist) { } public virtual void OnMaplistCleared() { } public virtual void OnMaplistMapAppended(string mapFileName) { } public virtual void OnMaplistNextLevelIndex(int mapIndex) { } public virtual void OnMaplistGetMapIndices(int mapIndex, int nextIndex) { } // BF3 public virtual void OnMaplistMapRemoved(int mapIndex) { } public virtual void OnMaplistMapInserted(int mapIndex, string mapFileName) { } #endregion #region Variables #region Details public virtual void OnServerName(string serverName) { } public virtual void OnServerDescription(string serverDescription) { } public virtual void OnBannerURL(string url) { } #endregion #region Configuration public virtual void OnGamePassword(string gamePassword) { } public virtual void OnPunkbuster(bool isEnabled) { } public virtual void OnRanked(bool isEnabled) { } public virtual void OnRankLimit(int iRankLimit) { } public virtual void OnPlayerLimit(int limit) { } public virtual void OnMaxPlayerLimit(int limit) { } public virtual void OnCurrentPlayerLimit(int limit) { } public virtual void OnIdleTimeout(int limit) { } public virtual void OnProfanityFilter(bool isEnabled) { } #endregion #region Gameplay public virtual void OnFriendlyFire(bool isEnabled) { } public virtual void OnHardcore(bool isEnabled) { } #region BFBC2 public virtual void OnTeamBalance(bool isEnabled) { } public virtual void OnKillCam(bool isEnabled) { } public virtual void OnMiniMap(bool isEnabled) { } public virtual void OnCrossHair(bool isEnabled) { } public virtual void On3dSpotting(bool isEnabled) { } public virtual void OnMiniMapSpotting(bool isEnabled) { } public virtual void OnThirdPersonVehicleCameras(bool isEnabled) { } #endregion #endregion #region Team Kill public virtual void OnTeamKillCountForKick(int limit) { } public virtual void OnTeamKillValueIncrease(int limit) { } public virtual void OnTeamKillValueDecreasePerSecond(int limit) { } public virtual void OnTeamKillValueForKick(int limit) { } #endregion #region Level Variables /// NOT BF3 public virtual void OnLevelVariablesList(LevelVariable requestedContext, List<LevelVariable> returnedValues) { } public virtual void OnLevelVariablesEvaluate(LevelVariable requestedContext, LevelVariable returnedValue) { } public virtual void OnLevelVariablesClear(LevelVariable requestedContext) { } public virtual void OnLevelVariablesSet(LevelVariable requestedContext) { } public virtual void OnLevelVariablesGet(LevelVariable requestedContext, LevelVariable returnedValue) { } #endregion #region Text Chat Moderation Settings /// NOT BF3 public virtual void OnTextChatModerationMode(ServerModerationModeType mode) { } public virtual void OnTextChatSpamTriggerCount(int limit) { } public virtual void OnTextChatSpamDetectionTime(int limit) { } public virtual void OnTextChatSpamCoolDownTime(int limit) { } #endregion #region Reserved/Specate Slots /// Note: This covers MoH's reserved spectate slots as well. /// NOT BF3 (yet) public virtual void OnReservedSlotsConfigFile(string configFileName) { } public virtual void OnReservedSlotsLoad() { } public virtual void OnReservedSlotsSave() { } public virtual void OnReservedSlotsPlayerAdded(string soldierName) { } public virtual void OnReservedSlotsPlayerRemoved(string soldierName) { } public virtual void OnReservedSlotsCleared() { } public virtual void OnReservedSlotsList(List<string> soldierNames) { } #endregion #endregion #region Player Actions public virtual void OnPlayerKilledByAdmin(string soldierName) { } public virtual void OnPlayerKickedByAdmin(string soldierName, string reason) { } public virtual void OnPlayerMovedByAdmin(string soldierName, int destinationTeamId, int destinationSquadId, bool forceKilled) { } #endregion #endregion // These events are sent from the server without any initial request from the client. #region Game Server Requests (Events) #region Players public virtual void OnPlayerJoin(string soldierName) { } public virtual void OnPlayerLeft(CPlayerInfo playerInfo) { } public virtual void OnPlayerAuthenticated(string soldierName, string guid) { } public virtual void OnPlayerKilled(Kill kKillerVictimDetails) { } public virtual void OnPlayerKicked(string soldierName, string reason) { } public virtual void OnPlayerSpawned(string soldierName, Inventory spawnedInventory) { } public virtual void OnPlayerTeamChange(string soldierName, int teamId, int squadId) { } public virtual void OnPlayerSquadChange(string soldierName, int teamId, int squadId) { } #endregion #region Chat public virtual void OnGlobalChat(string speaker, string message) { } public virtual void OnTeamChat(string speaker, string message, int teamId) { } public virtual void OnSquadChat(string speaker, string message, int teamId, int squadId) { } #endregion #region Round Over Events public virtual void OnRoundOverPlayers(List<CPlayerInfo> players) { } public virtual void OnRoundOverTeamScores(List<TeamScore> teamScores) { } public virtual void OnRoundOver(int winningTeamId) { } #endregion #region Levels public virtual void OnLoadingLevel(string mapFileName, int roundsPlayed, int roundsTotal) { } public virtual void OnLevelStarted() { } public virtual void OnLevelLoaded(string mapFileName, string Gamemode, int roundsPlayed, int roundsTotal) { } // BF3 #endregion #region Punkbuster public virtual void OnPunkbusterMessage(string punkbusterMessage) { } public virtual void OnPunkbusterBanInfo(CBanInfo ban) { } public virtual void OnPunkbusterUnbanInfo(CBanInfo unban) { } public virtual void OnPunkbusterBeginPlayerInfo() { } public virtual void OnPunkbusterEndPlayerInfo() { } public virtual void OnPunkbusterPlayerInfo(CPunkbusterInfo playerInfo) { } #endregion #endregion #region Internal Procon Events #region Accounts public virtual void OnAccountCreated(string username) { } public virtual void OnAccountDeleted(string username) { } public virtual void OnAccountPrivilegesUpdate(string username, CPrivileges privileges) { } public virtual void OnAccountLogin(string accountName, string ip, CPrivileges privileges) { } public virtual void OnAccountLogout(string accountName, string ip, CPrivileges privileges) { } #endregion #region Command Registration public virtual void OnAnyMatchRegisteredCommand(string speaker, string text, MatchCommand matchedCommand, CapturedCommand capturedCommand, CPlayerSubset matchedScope) { } public virtual void OnRegisteredCommand(MatchCommand command) { } public virtual void OnUnregisteredCommand(MatchCommand command) { } #endregion #region Battlemap Events public virtual void OnZoneTrespass(CPlayerInfo playerInfo, ZoneAction action, MapZone sender, Point3D tresspassLocation, float tresspassPercentage, object trespassState) { } #endregion #region HTTP Server public virtual HttpWebServerResponseData OnHttpRequest(HttpWebServerRequestData data) { } #endregion #endregion #region Layer Procon Events #region Variables public virtual void OnReceiveProconVariable(string variableName, string value) { } #endregion #endregion
Phil.
-
14-11-2011, 09:23 #5
- Join Date
- Feb 2011
- Posts
- 859
Good stuff thanks Phil
-
28-11-2011, 18:32 #6
Hi.
As promised here is the API update based on Procon 1.1.2.0
Code:/* Copyright 2010 Geoffrey 'Phogue' Green http://www.phogue.net This file is part of PRoCon Frostbite. PRoCon Frostbite 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. PRoCon Frostbite 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. You should have received a copy of the GNU General Public License along with PRoCon Frostbite. If not, see <http://www.gnu.org/licenses/>. */ /// <summary> /// You need to allow "OnPunkbusterPlayerInfo" and "OnPlayerLeft" for the pb list /// to be properly updated /// </summary> protected Dictionary<string, CPunkbusterInfo> PunkbusterPlayerInfoList; /// <summary> /// You need to allow "OnListPlayers", "OnPlayerJoin" and "OnPlayerLeft" /// </summary> protected Dictionary<string, CPlayerInfo> FrostbitePlayerInfoList; public PRoConPluginAPI() { this.PunkbusterPlayerInfoList = new Dictionary<string, CPunkbusterInfo>(); this.FrostbitePlayerInfoList = new Dictionary<string, CPlayerInfo>(); } public virtual void OnConnectionClosed() { } public string CreateEnumString(Type enumeration) { return string.Format("enum.{0}_{1}({2})", GetType().Name, enumeration.Name, string.Join("|", Enum.GetNames(enumeration))); } public virtual void OnLogin() { } public virtual void OnLogout() { } public virtual void OnQuit() { } public virtual void OnVersion(string serverType, string version) { } public virtual void OnHelp(List<string> commands) { } public virtual void OnRunScript(string scriptFileName) { } public virtual void OnRunScriptError(string scriptFileName, int lineError, string errorDescription) { } public virtual void OnServerInfo(CServerInfo serverInfo) { } public virtual void OnResponseError(List<string> requestWords, string error) { } public virtual void OnYelling(string message, int messageDuration, CPlayerSubset subset) { } public virtual void OnSaying(string message, CPlayerSubset subset) { } public virtual void OnRestartLevel() { } public virtual void OnSupportedMaps(string playlist, List<string> lstSupportedMaps) { } public virtual void OnListPlaylists(List<string> playlists) { } public virtual void OnListPlayers(List<CPlayerInfo> players, CPlayerSubset subset) { } public virtual void OnEndRound(int iWinningTeamID) { } public virtual void OnRunNextLevel() { } public virtual void OnCurrentLevel(string mapFileName) { } public virtual void OnPlaylistSet(string playlist) { } public virtual void OnBanAdded(CBanInfo ban) { } public virtual void OnBanRemoved(CBanInfo ban) { } public virtual void OnBanListClear() { } public virtual void OnBanListSave() { } public virtual void OnBanListLoad() { } public virtual void OnBanList(List<CBanInfo> banList) { } public virtual void OnTextChatModerationAddPlayer(TextChatModerationEntry playerEntry) { } public virtual void OnTextChatModerationRemovePlayer(TextChatModerationEntry playerEntry) { } public virtual void OnTextChatModerationClear() { } public virtual void OnTextChatModerationSave() { } public virtual void OnTextChatModerationLoad() { } public virtual void OnTextChatModerationList(TextChatModerationDictionary moderationList) { } public virtual void OnMaplistConfigFile(string configFileName) { } public virtual void OnMaplistLoad() { } public virtual void OnMaplistSave() { } public virtual void OnMaplistList(List<MaplistEntry> lstMaplist) { } public virtual void OnMaplistCleared() { } public virtual void OnMaplistMapAppended(string mapFileName) { } public virtual void OnMaplistNextLevelIndex(int mapIndex) { } public virtual void OnMaplistGetMapIndices(int mapIndex, int nextIndex) { } // BF3 public virtual void OnMaplistGetRounds(int currentRound, int totalRounds) { } // BF3 public virtual void OnMaplistMapRemoved(int mapIndex) { } public virtual void OnMaplistMapInserted(int mapIndex, string mapFileName) { } public virtual void OnServerName(string serverName) { } public virtual void OnServerDescription(string serverDescription) { } public virtual void OnBannerURL(string url) { } public virtual void OnGamePassword(string gamePassword) { } public virtual void OnPunkbuster(bool isEnabled) { } public virtual void OnRanked(bool isEnabled) { } public virtual void OnRankLimit(int iRankLimit) { } public virtual void OnPlayerLimit(int limit) { } public virtual void OnMaxPlayerLimit(int limit) { } public virtual void OnMaxPlayers(int limit) { } // BF3 public virtual void OnCurrentPlayerLimit(int limit) { } public virtual void OnIdleTimeout(int limit) { } public virtual void OnIdleBanRounds(int limit) { } //BF3 public virtual void OnProfanityFilter(bool isEnabled) { } public virtual void OnRoundRestartPlayerCount(int limit) { } public virtual void OnRoundStartPlayerCount(int limit) { } public virtual void OnGameModeCounter(int limit) { } public virtual void OnFriendlyFire(bool isEnabled) { } public virtual void OnHardcore(bool isEnabled) { } public virtual void OnTeamBalance(bool isEnabled) { } public virtual void OnKillCam(bool isEnabled) { } public virtual void OnMiniMap(bool isEnabled) { } public virtual void OnCrossHair(bool isEnabled) { } public virtual void On3dSpotting(bool isEnabled) { } public virtual void OnMiniMapSpotting(bool isEnabled) { } public virtual void OnThirdPersonVehicleCameras(bool isEnabled) { } public virtual void OnTeamKillCountForKick(int limit) { } public virtual void OnTeamKillValueIncrease(int limit) { } public virtual void OnTeamKillValueDecreasePerSecond(int limit) { } public virtual void OnTeamKillValueForKick(int limit) { } public virtual void OnLevelVariablesList(LevelVariable requestedContext, List<LevelVariable> returnedValues) { } public virtual void OnLevelVariablesEvaluate(LevelVariable requestedContext, LevelVariable returnedValue) { } public virtual void OnLevelVariablesClear(LevelVariable requestedContext) { } public virtual void OnLevelVariablesSet(LevelVariable requestedContext) { } public virtual void OnLevelVariablesGet(LevelVariable requestedContext, LevelVariable returnedValue) { } public virtual void OnTextChatModerationMode(ServerModerationModeType mode) { } public virtual void OnTextChatSpamTriggerCount(int limit) { } public virtual void OnTextChatSpamDetectionTime(int limit) { } public virtual void OnTextChatSpamCoolDownTime(int limit) { } public virtual void OnReservedSlotsConfigFile(string configFileName) { } public virtual void OnReservedSlotsLoad() { } public virtual void OnReservedSlotsSave() { } public virtual void OnReservedSlotsPlayerAdded(string soldierName) { } public virtual void OnReservedSlotsPlayerRemoved(string soldierName) { } public virtual void OnReservedSlotsCleared() { } public virtual void OnReservedSlotsList(List<string> soldierNames) { } public virtual void OnPlayerKilledByAdmin(string soldierName) { } public virtual void OnPlayerKickedByAdmin(string soldierName, string reason) { } public virtual void OnPlayerMovedByAdmin(string soldierName, int destinationTeamId, int destinationSquadId, bool forceKilled) { } public virtual void OnPlayerJoin(string soldierName) { } public virtual void OnPlayerLeft(CPlayerInfo playerInfo) { } public virtual void OnPlayerAuthenticated(string soldierName, string guid) { } public virtual void OnPlayerKilled(Kill kKillerVictimDetails) { } public virtual void OnPlayerKicked(string soldierName, string reason) { } public virtual void OnPlayerSpawned(string soldierName, Inventory spawnedInventory) { } public virtual void OnPlayerTeamChange(string soldierName, int teamId, int squadId) { } public virtual void OnPlayerSquadChange(string soldierName, int teamId, int squadId) { } public virtual void OnGlobalChat(string speaker, string message) { } public virtual void OnTeamChat(string speaker, string message, int teamId) { } public virtual void OnSquadChat(string speaker, string message, int teamId, int squadId) { } public virtual void OnRoundOverPlayers(List<CPlayerInfo> players) { } public virtual void OnRoundOverTeamScores(List<TeamScore> teamScores) { } public virtual void OnRoundOver(int winningTeamId) { } public virtual void OnLoadingLevel(string mapFileName, int roundsPlayed, int roundsTotal) { } public virtual void OnLevelStarted() { } public virtual void OnLevelLoaded(string mapFileName, string Gamemode, int roundsPlayed, int roundsTotal) { } // BF3 public virtual void OnPunkbusterMessage(string punkbusterMessage) { } public virtual void OnPunkbusterBanInfo(CBanInfo ban) { } public virtual void OnPunkbusterUnbanInfo(CBanInfo unban) { } public virtual void OnPunkbusterBeginPlayerInfo() { } public virtual void OnPunkbusterEndPlayerInfo() { } public virtual void OnPunkbusterPlayerInfo(CPunkbusterInfo playerInfo) { } public virtual void OnAccountCreated(string username) { } public virtual void OnAccountDeleted(string username) { } public virtual void OnAccountPrivilegesUpdate(string username, CPrivileges privileges) { } public virtual void OnAccountLogin(string accountName, string ip, CPrivileges privileges) { } public virtual void OnAccountLogout(string accountName, string ip, CPrivileges privileges) { } public virtual void OnAnyMatchRegisteredCommand(string speaker, string text, MatchCommand matchedCommand, CapturedCommand capturedCommand, CPlayerSubset matchedScope) { } public virtual void OnRegisteredCommand(MatchCommand command) { } public virtual void OnUnregisteredCommand(MatchCommand command) { } public virtual void OnZoneTrespass(CPlayerInfo playerInfo, ZoneAction action, MapZone sender, Point3D tresspassLocation, float tresspassPercentage, object trespassState) { } public virtual HttpWebServerResponseData OnHttpRequest(HttpWebServerRequestData data) { return null; } public virtual void OnReceiveProconVariable(string variableName, string value) { }
Phil.
-
06-01-2012, 18:21 #7
- Join Date
- Sep 2010
- Posts
- 107
Hi Phil,
does this line work now?
public virtual void OnLevelLoaded(string mapFileName, string Gamemode, int roundsPlayed, int roundsTotal) { } // BF3
And where can i find a new(uptodate) kind of Reference_Plugin.CS? i think about an empty skeleton of an plugin wich is running so far, and i just have to put in my additional code.
Regards, DaBIGfisH
-
26-04-2012, 08:05 #8
why is this not sticky
-
26-04-2012, 12:36 #9
- Join Date
- Dec 2010
- Posts
- 1,031
-
12-03-2013, 01:25 #10
- Join Date
- Nov 2011
- Posts
- 13
Im trying to extract the current ticket count for team 1 and 2 from the array that is generated by the 'public virtual void OnServerInfo(CServerInfo serverInfo) { }' method.
When I qry the server with php I get a normal array. Procon seems to convert that into an associative array (eg. serverInfo.GameMode; )
I have two questions.
1. Where can I find the names of the array keys I'm looking for?
2. How could I avoid having to ask similar questions in the future by lets say outputing the array in the console?