This commit is contained in:
Yannik Schmidt
2020-06-14 00:52:35 +02:00
parent e734033a82
commit 6af5c082ec
12 changed files with 125 additions and 386 deletions

3
.gitignore vendored
View File

@@ -1,3 +1,6 @@
*.swp
include/
.vscode
sourcemod/
*.bak
*.smx

View File

@@ -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

View File

@@ -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/

View File

@@ -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;
}

47
scripting/Interfaces.sp Normal file
View File

@@ -0,0 +1,47 @@
#pragma tabsize 0
#include <sourcemod>
#include <sdktools>
#include <socket>
#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(){
}

38
scripting/Skillbird.sp Normal file
View File

@@ -0,0 +1,38 @@
#pragma tabsize 0
#include <sourcemod>
#include <sdktools>
#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(){
}

4
scripting/Timers.sp Normal file
View File

@@ -0,0 +1,4 @@
public Action Timer_ConnectMessage(Handle timer, int client){
//QueryRating(client);
return Plugin_Continue;
}

View File

@@ -1,92 +0,0 @@
#pragma tabsize 0
#include <sourcemod>
#include <sdktools>
#include <socket>
#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);
}

View File

@@ -1,61 +0,0 @@
/* no idea, but removes warnings */
#pragma tabsize 0
#include <sourcemod>
#include <sdktools>
#include <socket>
#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());
}

View File

@@ -1,63 +0,0 @@
#pragma tabsize 0
#include <sourcemod>
#include <sdktools>
#include <socket>
#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);
}

View File

@@ -1,101 +0,0 @@
/* no idea, but removes warnings */
#pragma tabsize 0
#include <sourcemod>
#include <sdktools>
#include <socket>
#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);
}

View File

@@ -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 <MaxClients; client++){
/* get Steam-Id to match */
char sid[DEFAULT_LEN];
if(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);
}
}
}
}