diff --git a/.gitignore b/.gitignore index 6f4c8a6..27b10bd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ *.swp +include/ +.vscode +sourcemod/ *.bak *.smx diff --git a/README.md b/README.md index 8a27216..03f1c2d 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,9 @@ Start CMD and install the [Insurgency Server](https://developer.valvesoftware.co ## Compile Plugin Download and unpack [Sourcemod](http://www.sourcemod.net/downloads.php), after unpacking, there should be two directories, *addons* and *cfg*. Execute *build.sh* with the addons dir as argument. +Download and unpack the extensions [json](https://github.com/FAUSheppy/sm-json) and and move all files into the *scriping/include/* directory. +Download and upack the [system2](https://forums.alliedmods.net/showthread.php?t=146019), follow the instructions there to install it. + ./build.sh /path/to/addons/dir/ ## Add Sourcemod/Plugins to Insurgency Server diff --git a/build.sh b/build.sh index 729ffe8..dd31f60 100755 --- a/build.sh +++ b/build.sh @@ -11,18 +11,11 @@ sourcemod_addons_dir=$1 plugin_dir=$sourcemod_addons_dir/sourcemod/scripting ext_dir=$sourcemod_addons_dir/sourcemod/extensions -cp scripting/TrueSkillLoggingMain.sp \ - scripting/TrueSkillQueryMain.sp \ - scripting/client.sp \ - scripting/utils.sp \ - scripting/query.sp \ - $plugin_dir/ - -cp scripting/include/* $plugin_dir/include/ - +cp scripting/*.sp $plugin_dir/ +cp -r scripting/include/* $plugin_dir/include/ cp extensions/* $ext_dir/ originDir=$(pwd) cd $plugin_dir -./compile.sh TrueSkillLoggingMain.sp TrueSkillQueryMain.sp -cp compiled/TrueSkill* $originDir/ +./compile.exe Skillbird.sp +#cp compiled/TrueSkill* $originDir/ diff --git a/scripting/EventHandlers.sp b/scripting/EventHandlers.sp new file mode 100644 index 0000000..267da59 --- /dev/null +++ b/scripting/EventHandlers.sp @@ -0,0 +1,26 @@ +#include "Interfaces.sp" + +public Action:Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast){ + + SubmittEventActiveClients(); + SubmittEventMapInformation() + return Plugin_Continue; +} + +public Action:Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast){ + SubmittEventActiveClients(); + new team_id = GetEventInt(event, "winner"); + SubmittEventWinnerTeam(team_id); + SubmittEventRoundEnd(); + return Plugin_Continue; +} + +public Action:Event_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast){ + SubmittEventActiveClients(); + return Plugin_Continue; +} + +public Action:Event_PlayerChangedTeam(Handle:event, const String:name[], bool:dontBroadcast){ + SubmittEventActiveClients(); + return Plugin_Continue; +} \ No newline at end of file diff --git a/scripting/Interfaces.sp b/scripting/Interfaces.sp new file mode 100644 index 0000000..90aaa87 --- /dev/null +++ b/scripting/Interfaces.sp @@ -0,0 +1,47 @@ +#pragma tabsize 0 + +#include +#include +#include + +#define DEFAULT_LEN 64 +#define SNAME_LEN 256 +#define ACTIVE_CLIENTS_LENGTH 8192 + +public void SmartClientName(const client, char[] buf, buflen){ + new String:name[DEFAULT_LEN]; + if(IsClientConnected(client)){ + GetClientName(client, name, DEFAULT_LEN); + } +} + +public void SmartClientID(int client, char[] buf, int buflen){ + if(IsClientConnected(client)){ + GetClientAuthId(client, AuthId_SteamID64, buf, DEFAULT_LEN, true); + } +} + +public void SubmittEventActiveClients(){ + //new String:str_tmp[ACTIVE_CLIENTS_LENGTH]; + for(new i = 1; i <= MaxClients;i++){ + new String:strCliID[DEFAULT_LEN]; + new String:strCliName[DEFAULT_LEN]; + SmartClientID(i, strCliID, DEFAULT_LEN); + SmartClientName(i, strCliName, DEFAULT_LEN); + // strCliID, strCliName, GetClientTeam(i)); + } + // return json +} + +public void SubmittEventMapInformation(){ + new String:mapname[DEFAULT_LEN]; + GetCurrentMap(mapname, sizeof(mapname)); +} + +public void SubmittEventWinnerTeam(int team_id){ + +} + +public void SubmittEventRoundEnd(){ + +} \ No newline at end of file diff --git a/scripting/Skillbird.sp b/scripting/Skillbird.sp new file mode 100644 index 0000000..a17ae42 --- /dev/null +++ b/scripting/Skillbird.sp @@ -0,0 +1,38 @@ +#pragma tabsize 0 + +#include +#include +#include "Timers.sp" +#include "EventHandlers.sp" + +#define DEFAULT_LEN 64 +#define SNAME_LEN 256 + + +/* ---------------------- Plugin ---------------------- */ +public Plugin:myinfo = { + name = "skillbird", + author = "FAUSheppy", + description = "Module to interact with the skillbird framework", + version = "3.0", + url = "https://github.com/FAUSheppy/skillbird-sourcemod" +}; + +public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max){ + return APLRes_Success; +} + +public OnPluginStart(){ + + /* Hook Events */ + HookEvent("round_end", Event_RoundEnd); + HookEvent("player_team", Event_PlayerChangedTeam); + HookEvent("player_disconnect", Event_PlayerDisconnect); +} + +public OnClientAuthorized(client, const String:auth[]){ + CreateTimer(5.0, Timer_ConnectMessage, client); +} + +public OnMapStart(){ +} \ No newline at end of file diff --git a/scripting/Timers.sp b/scripting/Timers.sp new file mode 100644 index 0000000..84ad1c9 --- /dev/null +++ b/scripting/Timers.sp @@ -0,0 +1,4 @@ +public Action Timer_ConnectMessage(Handle timer, int client){ + //QueryRating(client); + return Plugin_Continue; +} \ No newline at end of file diff --git a/scripting/TrueSkillLoggingMain.sp b/scripting/TrueSkillLoggingMain.sp deleted file mode 100644 index 6f0ed04..0000000 --- a/scripting/TrueSkillLoggingMain.sp +++ /dev/null @@ -1,92 +0,0 @@ -#pragma tabsize 0 -#include -#include -#include -#include "client.sp" -#include "utils.sp" -#include "query.sp" -#define DEFAULT_LEN 64 -#define SNAME_LEN 256 - -/* ---------------------- Globals ---------------------- */ -static Handle:logfile; - -/* ---------------------- Timers ---------------------- */ -public Action:Timer_MapStart(Handle:timer){ - LogActiveClients(logfile, "0x42,map_start_active,"); - return Plugin_Continue; -} - -public Action:Timer_RoundStart(Handle:timer){ - LogActiveClients(logfile, "0x42,round_start_active,"); - char map[SNAME_LEN]; - MapName("0x42,mapname,", map, sizeof(map)); - LogToOpenFile(logfile, map); - return Plugin_Continue; -} - -/* ---------------------- Events ---------------------- */ -public Action:Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast){ - LogActiveClients(logfile, "0x42,round_start_active,"); - return Plugin_Continue; -} - -public Action:Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast){ - char eventWTeam[SNAME_LEN]; - EventWinnerTeam(event, "0x42,winner,", eventWTeam, sizeof(eventWTeam)); - LogToOpenFile(logfile, eventWTeam); - LogActiveClients(logfile, "0x42,round_end_active,"); - return Plugin_Continue; -} - -public Action:Event_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast){ - LogClientEventFormat(logfile, event, "0x42,disconnect,"); - LogActiveClients(logfile, "0x42,dc,"); - return Plugin_Continue; -} - -public Action:Event_PlayerChangedTeam(Handle:event, const String:name[], bool:dontBroadcast){ - LogActiveClients(logfile, "0x42,tc,"); - LogClientEventFormat(logfile, event, "0x42,teamchange,"); - return Plugin_Continue; -} - -public OnMapStart(){ - CreateTimer(5.0, Timer_MapStart); -} - -/* ---------------------- Plugin ---------------------- */ -public Plugin:myinfo = { - name = "skillbird-data-collection, - author = "FAUSheppy", - description = "Module to collect data for the skillbird framework", - version = "2.0", - url = "https://github.com/FAUSheppy/skillbird-sourcemod" -}; - -public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max){ - return APLRes_Success; -} - -public OnPluginStart(){ - - /* get and verify server name for output file */ - char server[SNAME_LEN]; - ServerName(server, sizeof(server)); - logfile = OpenFile(server, "at", false, NULL_STRING); - if strlen(server) < 1: - return ThrowNativeError(SP_ERROR_NATIVE, "Computed Invalid Servername '%s'", server) - - /* inial line */ - LogToOpenFile(logfile, "0x42,start"); - - /* Hook Events */ - HookEvent("round_end", Event_RoundEnd); - HookEvent("player_team", Event_PlayerChangedTeam); - HookEvent("player_disconnect", Event_PlayerDisconnect); -} - -public OnPluginEnd(){ - LogToOpenFile(logfile, "0x42,plugin unloaded"); - CloseHandle(logfile); -} diff --git a/scripting/TrueSkillQueryMain.sp b/scripting/TrueSkillQueryMain.sp deleted file mode 100644 index b30d4a0..0000000 --- a/scripting/TrueSkillQueryMain.sp +++ /dev/null @@ -1,61 +0,0 @@ -/* no idea, but removes warnings */ -#pragma tabsize 0 - -#include -#include -#include -#include "query.sp" -#include "client.sp" -#include "utils.sp" - -#define DEFAULT_LEN 64 -#define INVALID 0 - -#define REBUILD_TEAM true -#define NO_REBUILD_TEAM false - -/* ---------------------- Hooks ---------------------- */ -public OnClientAuthorized(client,const String:auth[]){ - CreateTimer(5.0, Timer_ConnectMessage, client); - CreateTimer(5.0, Timer_QueryTeam, client); -} -public OnScrambleTeams(){ - QueryTeam(GetSocket(), "NONE", REBUILD_TEAM); -} - -/* ---------------------- Timers ---------------------- */ -public Action Timer_ConnectMessage(Handle timer, int client){ - QueryRating(client); - return Plugin_Continue; -} - -public Action Timer_QueryTeam(Handle timer, int client){ - char clientIDString[DEFAULT_LEN]; - ClientID(client, clientIDString, DEFAULT_LEN); - QueryTeam(GetSocket(), clientIDString, false); - return Plugin_Continue; -} - -/* ---------------------- Plugin ---------------------- */ -public Plugin:myinfo = { - name = "skillbird-query", - author = "FAUSheppy", - description = "Module for interaction with the skillbird API", - version = "2.0", - url = "https://github.com/FAUSheppy/skillbird-sourcemod" -}; - -public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max){ - return APLRes_Success; -} - -public OnPluginStart(){ - CreateQuerySocket(7040); -} - -public OnPluginEnd(){ - if (GetSocket() == INVALID_HANDLE){ - return; - } - CloseHandle(GetSocket()); -} diff --git a/scripting/client.sp b/scripting/client.sp deleted file mode 100644 index 50ffb4a..0000000 --- a/scripting/client.sp +++ /dev/null @@ -1,63 +0,0 @@ -#pragma tabsize 0 - -#include -#include -#include - -#define DEFAULT_LEN 64 -#define SNAME_LEN 256 -#define ACTIVE_CLIENTS_LENGTH 8192 - -public void ClientName(const client,char[] buf,buflen){ - new String:name[DEFAULT_LEN]; - if(IsClientConnected(client)){ - GetClientName(client, name, DEFAULT_LEN); - - /* get fucked if you use my seperators in your name */ - ReplaceString(name, DEFAULT_LEN,",","$"); - ReplaceString(name, DEFAULT_LEN,"|","&"); - ReplaceString(name, DEFAULT_LEN,"0x42","0x21"); - } -} - -public void ClientID(int client, char[] buf, int buflen){ - if(IsClientConnected(client)){ - GetClientAuthId(client, AuthId_SteamID64, buf, DEFAULT_LEN, true); - } -} - -public void ActiveClients(char[] prefix, char[] buf, buflen){ - new String:str_tmp[ACTIVE_CLIENTS_LENGTH]; - for(new i = 1; i <= MaxClients;i++){ - new String:strCliID[DEFAULT_LEN]; - new String:strCliName[DEFAULT_LEN]; - ClientID(i, strCliID, DEFAULT_LEN); - ClientName(i, strCliName, DEFAULT_LEN); - Format(str_tmp, ACTIVE_CLIENTS_LENGTH, - "%s|%s|%s|%d,", str_tmp, strCliID, strCliName, GetClientTeam(i)); - } - Format(str_tmp, ACTIVE_CLIENTS_LENGTH, "%s%s", prefix,str_tmp); -} - -public void LogActiveClients(Handle:logfile, char[] prefix){ - char strActiveClients[ACTIVE_CLIENTS_LENGTH]; - ActiveClients(prefix, strActiveClients, ACTIVE_CLIENTS_LENGTH); - LogToOpenFile(logfile, strActiveClients); -} - -public void LogClientEventFormat(Handle:logfile, Handle:event, char[] prefix){ - char strClientEvent[2*DEFAULT_LEN]; - ClientEventFormat(event, prefix, strClientEvent, 2*DEFAULT_LEN); - LogToOpenFile(logfile, strClientEvent); - -} - -public void ClientEventFormat(Handle:event, char[] prefix, char[] buf, buflen){ - new client = GetClientOfUserId(GetEventInt(event, "userid")); - char team[4]; - Format(team, sizeof(team), "%d", GetClientTeam(client)); - char tmp[DEFAULT_LEN*2]; - char strCliID[DEFAULT_LEN]; - ClientID(client, strCliID, DEFAULT_LEN); - Format(tmp, 2*DEFAULT_LEN, "%s%s,%s", prefix, strCliID, team); -} diff --git a/scripting/query.sp b/scripting/query.sp deleted file mode 100644 index bf2799f..0000000 --- a/scripting/query.sp +++ /dev/null @@ -1,101 +0,0 @@ -/* no idea, but removes warnings */ -#pragma tabsize 0 - -#include -#include -#include - -#define DEFAULT_LEN 64 -#define TAG_LEN 64 -#define INDEX_SEP "," -#define ACTIVE_CLIENTS_LENGTH 8192 - -#define NO_PREFIX "" - -/* ---------------------- Globals ---------------------- */ -static Handle:socket - -/* ---------------------- Queries ---------------------- */ -public QueryTeam(Handle:socketl, char[] steamid, bool rebuild){ - /* steamid may be used to only query a single player's new team */ - char strActiveClients[ACTIVE_CLIENTS_LENGTH]; - char request[ACTIVE_CLIENTS_LENGTH + DEFAULT_LEN*2]; - - ActiveClients(NO_PREFIX, strActiveClients, ACTIVE_CLIENTS_LENGTH); - if(rebuild){ - Format(request, sizeof(request), "rebuildteam,%s", strActiveClients); - }else{ - Format(request, sizeof(request), "getteam,%s,%s", steamid, strActiveClients); - } - SocketSend(socket, request); -} - -public QueryRating(client){ - if(client>0 && IsClientConnected(client)){ - /* get steamid first */ - char pid[DEFAULT_LEN]; - GetClientAuthId(client, AuthId_SteamID64, pid, DEFAULT_LEN, true); - /* build the request and send */ - char request[2*DEFAULT_LEN]; - Format(request, sizeof(request), "player,%s", pid); - SocketSend(socket, request); - } -} - -/* ---------------------- Receive ---------------------- */ -public CaseSwitchReceive(Handle:socketl, String:receiveData[], const dataSize, any:arg) { - char tag[TAG_LEN]; - - //TODO why is receiveData and array of strings?!?! - SplitString(receiveData, INDEX_SEP, tag, TAG_LEN); - - if(StrEqual(tag, "BALANCE_SINGLE")){ - RebuildTeams(INDEX_SEP, "|",receiveData); - }else if(StrEqual(tag, "BALANCE_TEAMS")){ - RebuildTeams(INDEX_SEP, "|",receiveData); - }else if(StrEqual(tag, "RATING_SINGLE")){ - char ratingInfo[DEFAULT_LEN]; - SplitString(receiveData, INDEX_SEP, ratingInfo, DEFAULT_LEN); - PrintToChatAll("%s", receiveData); - } -} - -/* ---------------------- Socket ---------------------- */ -public CreateQuerySocket(int port){ - socket = SocketCreate(SOCKET_TCP, OnSocketError); - SocketConnect(socket, OnSocketConnected, CaseSwitchReceive, OnSocketDisconnected, "127.0.0.1", port); -} - -public Action AttemptReconnectSocket(Handle:socketl){ - if(socket != INVALID_HANDLE){ - CloseHandle(socketl); - }else{ - socket = SocketCreate(SOCKET_TCP,OnSocketError); - if(socket != INVALID_HANDLE){ - SocketConnect(socket, OnSocketConnected, CaseSwitchReceive, - OnSocketDisconnected, "127.0.0.1", 7040); - } - } - /* check if socket is connected */ - if(SocketIsConnected(socketl)){ - return Plugin_Stop; - }else{ - return Plugin_Continue; - } -} - -public Handle GetSocket(){ - return socket; -} - -public OnSocketConnected(Handle:socketl,any:arg) { -} - -public OnSocketDisconnected(Handle:socketl,any:arg) { - CreateTimer(10.0, AttemptReconnectSocket, socketl, TIMER_REPEAT); -} - -public OnSocketError(Handle:socketl, const errorType, const errorNum,any:arg) { - LogError("socket error %d (errno %d)", errorType, errorNum); - CloseHandle(socket); -} diff --git a/scripting/utils.sp b/scripting/utils.sp deleted file mode 100644 index 3435f44..0000000 --- a/scripting/utils.sp +++ /dev/null @@ -1,58 +0,0 @@ -#define DEFAULT_LEN 64 -#define MAX_PLAYERS 32 -#define MAX_LENGTH_ID_TEAM 128 - -public void EventWinnerTeam(Handle:event, char[] prefix, char[] buf, int buflen){ - new team_id = GetEventInt(event, "winner"); - Format(buf, buflen, "%s,%d", prefix, team_id); -} - -public void MapName(char[] prefix, char[] buf, int buflen){ - new String:map[DEFAULT_LEN]; - GetCurrentMap(map, sizeof(map)); - Format(buf, buflen, "%s%s", prefix, map); -} - -public void ServerName(char[] buf,int buflen){ - new String:sname[SNAME_LEN]; - ConVar servername = FindConVar("hostname"); - servername.GetString(sname,SNAME_LEN); - ReplaceString(sname, SNAME_LEN," ",""); - ReplaceString(sname, SNAME_LEN,"[",""); - ReplaceString(sname, SNAME_LEN,"]",""); - ReplaceString(sname, SNAME_LEN,"(",""); - ReplaceString(sname, SNAME_LEN,")",""); -} - - -public void RebuildTeams(char[] SEP, char[] SUBSEP, char[] input){ - - /* buffers for later */ - char buffers[MAX_PLAYERS][MAX_LENGTH_ID_TEAM]; - new parts = ExplodeString(input, SEP, buffers, MAX_PLAYERS, MAX_LENGTH_ID_TEAM); - new StringMap:map; - - /* i=1 to skip tag in something like TAG,player|team,player|team,... */ - for(new i = 1; i < parts; i++){ - char idAndTeam[2][MAX_LENGTH_ID_TEAM]; - ExplodeString(buffers[i], SUBSEP, idAndTeam, 2, MAX_LENGTH_ID_TEAM); - map.SetString(idAndTeam[0], idAndTeam[1], true); - } - - /* hasmap indirection nessesary cause there doesnt exist a "ClientByAuthID-like function */ - for(new client=0; client 0 && IsClientConnected(client)){ - GetClientAuthId(client, AuthId_SteamID64, sid, DEFAULT_LEN, true); - } - /* get team for steamid and balance*/ - char team[MAX_LENGTH_ID_TEAM]; - if(map.GetString(sid, team, sizeof(team))){ - new tid = StringToInt(team); - if(tid>0 && IsClientConnected(client)){ - ChangeClientTeam(client, tid); - } - } - } -}