-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
404 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
plugins/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,16 @@ | ||
# veterans | ||
"Veterans Only" is a simple Plugin for the Valve's FPS game, Counter Strike: Global Offensive Dedicated Servers using SourceMod and written in SourcePawn to restrict access of players based on their playtime in a specific game | ||
# Veterans Only | ||
"Veterans Only" (or simply "veterans") is a Plugin for SourceMod and written with SourcePawn to restrict access of players based on their playtime in a specific game | ||
|
||
## License | ||
This program 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. | ||
|
||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,364 @@ | ||
#pragma semicolon 1 | ||
#pragma dynamic 645221 | ||
#define AUTOLOAD_EXTENSIONS | ||
#define REQUIRE_EXTENSIONS | ||
#define PLUGIN_VERSION "1.0" | ||
|
||
#include <SteamWorks> | ||
|
||
|
||
new String:CacheFile[PLATFORM_MAX_PATH]; | ||
|
||
new Handle:cvar_enable; | ||
new Handle:cvar_minPlaytime; | ||
new Handle:cvar_minPlaytimeExcludingLast2Weeks; | ||
new Handle:cvar_cacheTime; | ||
new Handle:cvar_connectionTimeout; | ||
new Handle:cvar_kickWhenFailure; | ||
new Handle:cvar_kickWhenPrivate; | ||
new Handle:cvar_banTime; | ||
new Handle:cvar_gameId; | ||
|
||
public Plugin:myinfo = | ||
{ | ||
name = "VeteransOnly", | ||
author = "Soroush Falahati", | ||
description = "Kicks the players without enough playtime in the game", | ||
version = PLUGIN_VERSION, | ||
url = "http://www.falahati.net/" | ||
} | ||
|
||
public OnPluginStart() | ||
{ | ||
AddServerTag2("Veterans"); | ||
LoadTranslations("veterans.phrases"); | ||
|
||
CreateConVar("sm_veterans_version", PLUGIN_VERSION, "Veterans Only Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); | ||
|
||
cvar_enable = CreateConVar("sm_veterans_enable", "1", | ||
"Is VeteransOnly plugin enable?", FCVAR_PLUGIN, true, 0.0, true, 1.0); | ||
cvar_gameId = CreateConVar("sm_veterans_gameid", "730", | ||
"Steam's Store id of the game you want us to check against?", FCVAR_PLUGIN, | ||
true, 0.0, true, 99999999.0); | ||
cvar_kickWhenFailure = CreateConVar("sm_veterans_kickfailure", "0", | ||
"Should we kick the player when something bad happens such as failing to retrieve the user's info?", FCVAR_PLUGIN, | ||
true, 0.0, true, 1.0); | ||
cvar_kickWhenPrivate = CreateConVar("sm_veterans_kickprivate", "0", | ||
"Should we kick the player when he/she has a private or friend only profile?", FCVAR_PLUGIN, | ||
true, 0.0, true, 1.0); | ||
cvar_connectionTimeout = CreateConVar("sm_veterans_timeout", "10", | ||
"Maximum number of seconds till we consider the requesting connection timed out?", FCVAR_PLUGIN, | ||
true, 0.0, true, 300.0); | ||
cvar_banTime = CreateConVar("sm_veterans_bantime", "0", | ||
"Should me ban the player instead of kicking and if we should, for how long (in minutes)?", FCVAR_PLUGIN, | ||
true, 0.0, true, 31536000.0); | ||
cvar_minPlaytime = CreateConVar("sm_veterans_mintotal", "6000", | ||
"Minimum total playtime amount that player needs to have (in minutes)?", FCVAR_PLUGIN, | ||
true, 0.0, true, 600000.0); | ||
cvar_minPlaytimeExcludingLast2Weeks = CreateConVar("sm_veterans_mintotalminuslastweeks", "3000", | ||
"Minimum total playtime amount (excluding last 2 weeks) that player needs to have (in minutes)?", FCVAR_PLUGIN, | ||
true, 0.0, true, 600000.0); | ||
cvar_cacheTime = CreateConVar("sm_veterans_cachetime", "86400", | ||
"Amount of time in seconds that we should not send a delicate request for the same query.", FCVAR_PLUGIN, | ||
true, 0.0, true, 31536000.0); | ||
|
||
AutoExecConfig(true, "veterans"); | ||
BuildPath(Path_SM, CacheFile, sizeof(CacheFile), "data/veterans_cache.txt"); | ||
} | ||
|
||
public OnPluginEnd() | ||
{ | ||
RemoveServerTag2("Veterans"); | ||
} | ||
|
||
public OnMapStart() | ||
{ | ||
CleanupCache(); | ||
} | ||
|
||
public OnClientAuthorized(client, const String:steamId[]) | ||
{ | ||
if (!GetConVarBool(cvar_enable) || StrEqual(steamId, "BOT", false)) | ||
{ | ||
return; | ||
} | ||
|
||
new totalTime, last2WeeksTime; | ||
if (GetCache(SteamIdToInt(steamId), totalTime, last2WeeksTime)) | ||
{ | ||
PrintToServer("VeteransOnly: New client, playtime loaded from cache for SteamId %s", steamId); | ||
ApplyDecision(client, totalTime, last2WeeksTime); | ||
return; | ||
} | ||
PrintToServer("VeteransOnly: New client, requesting playtime for SteamId %s", steamId); | ||
RequestNewData(client, steamId); | ||
} | ||
|
||
ThrowOut(client, const String:reason[]) | ||
{ | ||
new clientId = GetClientUserId(client); | ||
if (CheckCommandAccess(clientId, "generic_admin", ADMFLAG_GENERIC, false)) | ||
{ | ||
return; | ||
} | ||
if (GetConVarInt(cvar_banTime) > 0) | ||
{ | ||
BanClient(client, GetConVarInt(cvar_banTime), BANFLAG_AUTHID, reason, reason); | ||
} | ||
else | ||
{ | ||
KickClient(client, reason); | ||
} | ||
} | ||
|
||
|
||
ApplyDecision(client, totalTime, last2WeeksTime) | ||
{ | ||
if (!Decide(totalTime, last2WeeksTime)) | ||
{ | ||
decl String:formated[256]; | ||
Format(formated, sizeof formated, "%T", "REJECTED", client, GetConVarFloat(cvar_minPlaytime) / 60, GetConVarFloat(cvar_minPlaytimeExcludingLast2Weeks) / 60); | ||
ThrowOut(client, formated); | ||
} | ||
} | ||
|
||
bool:Decide(totalTime, last2WeeksTime) | ||
{ | ||
PrintToServer("VeteransOnly: Deciding for Total of %d minutes, last two weeks %d minutes", totalTime, last2WeeksTime); | ||
return totalTime >= GetConVarInt(cvar_minPlaytime) && | ||
(totalTime > last2WeeksTime ? totalTime - last2WeeksTime : 0) >= GetConVarInt(cvar_minPlaytimeExcludingLast2Weeks); | ||
} | ||
|
||
RequestNewData(client, const String:steamId[]) | ||
{ | ||
decl String:gameId[16]; | ||
IntToString(GetConVarInt(cvar_gameId), gameId, sizeof gameId); | ||
decl String:maxTotal[16]; | ||
IntToString(GetConVarInt(cvar_minPlaytime), maxTotal, sizeof maxTotal); | ||
decl String:maxTotalNo2Weeks[16]; | ||
IntToString(GetConVarInt(cvar_minPlaytimeExcludingLast2Weeks), maxTotalNo2Weeks, sizeof maxTotalNo2Weeks); | ||
|
||
new Handle:hRequest = SteamWorks_CreateHTTPRequest(EHTTPMethod:k_EHTTPMethodGET, "http://falahati.net/steamapi/queryPlaytime.php"); | ||
|
||
SteamWorks_SetHTTPRequestNetworkActivityTimeout(hRequest, GetConVarInt(cvar_connectionTimeout)); | ||
|
||
SteamWorks_SetHTTPRequestGetOrPostParameter(hRequest, "gameId", gameId); | ||
SteamWorks_SetHTTPRequestGetOrPostParameter(hRequest, "steamId", steamId); | ||
SteamWorks_SetHTTPRequestGetOrPostParameter(hRequest, "maxTotal", maxTotal); | ||
SteamWorks_SetHTTPRequestGetOrPostParameter(hRequest, "maxTotalNo2Weeks", steamId); | ||
|
||
SteamWorks_SetHTTPCallbacks(hRequest, HTTP_RequestComplete); | ||
SteamWorks_SetHTTPRequestContextValue(hRequest, SteamIdToInt(steamId), GetClientUserId(client)); | ||
|
||
SteamWorks_SendHTTPRequest(hRequest); | ||
} | ||
|
||
SteamIdToInt(const String:steamId[]) | ||
{ | ||
decl String:subinfo[3][16]; | ||
ExplodeString(steamId, ":", subinfo, sizeof subinfo, sizeof subinfo[]); | ||
return (StringToInt(subinfo[2]) * 2) + StringToInt(subinfo[1]); | ||
} | ||
|
||
public HTTP_RequestComplete(Handle:HTTPRequest, bool:bFailure, bool:bRequestSuccessful, EHTTPStatusCode:eStatusCode, any:steamIntId, any:userId) | ||
{ | ||
|
||
new client = GetClientOfUserId(userId); | ||
if(!client) | ||
{ | ||
CloseHandle(HTTPRequest); | ||
return; | ||
} | ||
|
||
if(!bRequestSuccessful || eStatusCode != EHTTPStatusCode:k_EHTTPStatusCode200OK) | ||
{ | ||
if(bRequestSuccessful) | ||
{ | ||
CloseHandle(HTTPRequest); | ||
} | ||
if (GetConVarBool(cvar_kickWhenFailure)) | ||
{ | ||
decl String:formated[128]; | ||
Format(formated, sizeof(formated), "%T", "ERROR", client); | ||
ThrowOut(client, formated); | ||
} | ||
LogError("VeteransOnly: Failed to retrieve user's playtime (HTTP status: %d)", eStatusCode); | ||
return; | ||
} | ||
|
||
new totalTime, last2WeeksTime; | ||
|
||
new iBodySize; | ||
if (SteamWorks_GetHTTPResponseBodySize(HTTPRequest, iBodySize)) | ||
{ | ||
if (iBodySize == 0) | ||
{ | ||
if (GetConVarBool(cvar_kickWhenPrivate)) | ||
{ | ||
decl String:formated[128]; | ||
Format(formated, sizeof(formated), "%T", "PRIVATEPROFILE", client); | ||
ThrowOut(client, formated); | ||
return; | ||
} | ||
} | ||
else | ||
{ | ||
decl String:sBody[iBodySize + 1]; | ||
SteamWorks_GetHTTPResponseBodyData(HTTPRequest, sBody, iBodySize); | ||
if (StrContains(sBody, "|") >= 0 && iBodySize >= 5) | ||
{ | ||
decl String:times[4][10]; | ||
ExplodeString(sBody, "|", times, sizeof times, sizeof times[]); | ||
totalTime = StringToInt(times[1]); | ||
last2WeeksTime = StringToInt(times[2]); | ||
SetCache(steamIntId, totalTime, last2WeeksTime); | ||
ApplyDecision(client, totalTime, last2WeeksTime); | ||
return; | ||
} | ||
if (GetConVarBool(cvar_kickWhenFailure)) | ||
{ | ||
decl String:formated[128]; | ||
Format(formated, sizeof(formated), "%T", "ERROR", client); | ||
ThrowOut(client, formated); | ||
} | ||
} | ||
} | ||
else if (GetConVarBool(cvar_kickWhenFailure)) | ||
{ | ||
decl String:formated[128]; | ||
Format(formated, sizeof(formated), "%T", "ERROR", client); | ||
ThrowOut(client, formated); | ||
} | ||
} | ||
|
||
CleanupCache() | ||
{ | ||
new Handle:kv = CreateKeyValues("VeteranPlayersCache"); | ||
FileToKeyValues(kv, CacheFile); | ||
if (!KvGotoFirstSubKey(kv)) | ||
{ | ||
return; | ||
} | ||
new lastUpdate, totalTime, last2WeeksTime, maxTime, currentTime; | ||
maxTime = GetConVarInt(cvar_cacheTime); | ||
currentTime = GetTime(); | ||
do | ||
{ | ||
lastUpdate = KvGetNum(kv, "LastUpdate"); | ||
totalTime = KvGetNum(kv, "TotalTime"); | ||
last2WeeksTime = KvGetNum(kv, "Last2WeeksTime"); | ||
if (lastUpdate + maxTime < currentTime && !Decide(totalTime, last2WeeksTime)) | ||
{ | ||
KvDeleteThis(kv); | ||
} | ||
} while (KvGotoNextKey(kv)); | ||
KvRewind(kv); | ||
KeyValuesToFile(kv, "VeteranPlayerCache.txt"); | ||
CloseHandle(kv); | ||
} | ||
|
||
SetCache(steamIntId, totalTime, last2WeeksTime) | ||
{ | ||
decl String:steamId[32]; | ||
IntToString(steamIntId, steamId, sizeof steamId); | ||
|
||
new Handle:kv = CreateKeyValues("VeteranPlayersCache"); | ||
FileToKeyValues(kv, CacheFile); | ||
KvJumpToKey(kv, steamId, true); | ||
KvSetNum(kv, "LastUpdate", GetTime()); | ||
KvSetNum(kv, "TotalTime", totalTime); | ||
KvSetNum(kv, "Last2WeeksTime", last2WeeksTime); | ||
KvRewind(kv); | ||
KeyValuesToFile(kv, CacheFile); | ||
CloseHandle(kv); | ||
} | ||
|
||
bool:GetCache(steamIntId, &totalTime, &last2WeeksTime) | ||
{ | ||
decl String:steamId[32]; | ||
IntToString(steamIntId, steamId, sizeof steamId); | ||
|
||
totalTime = 0; | ||
last2WeeksTime = 0; | ||
new Handle:kv = CreateKeyValues("VeteranPlayersCache"); | ||
FileToKeyValues(kv, CacheFile); | ||
if (!KvJumpToKey(kv, steamId)) | ||
{ | ||
CloseHandle(kv); | ||
return false; | ||
} | ||
totalTime = KvGetNum(kv, "TotalTime"); | ||
last2WeeksTime = KvGetNum(kv, "Last2WeeksTime"); | ||
CloseHandle(kv); | ||
return true; | ||
} | ||
|
||
stock AddServerTag2(const String:tag[]) | ||
{ | ||
new Handle:hTags = INVALID_HANDLE; | ||
hTags = FindConVar("sv_tags"); | ||
if(hTags != INVALID_HANDLE) | ||
{ | ||
new String:tags[256]; | ||
GetConVarString(hTags, tags, sizeof(tags)); | ||
if(StrContains(tags, tag, true) > 0) return; | ||
if(strlen(tags) == 0) | ||
{ | ||
Format(tags, sizeof(tags), tag); | ||
} | ||
else | ||
{ | ||
Format(tags, sizeof(tags), "%s,%s", tags, tag); | ||
} | ||
SetConVarString(hTags, tags, true); | ||
} | ||
} | ||
|
||
stock RemoveServerTag2(const String:tag[]) | ||
{ | ||
new Handle:hTags = INVALID_HANDLE; | ||
hTags = FindConVar("sv_tags"); | ||
if(hTags != INVALID_HANDLE) | ||
{ | ||
decl String:tags[50]; //max size of sv_tags cvar | ||
GetConVarString(hTags, tags, sizeof(tags)); | ||
if(StrEqual(tags, tag, true)) | ||
{ | ||
Format(tags, sizeof(tags), ""); | ||
SetConVarString(hTags, tags, true); | ||
return; | ||
} | ||
new pos = StrContains(tags, tag, true); | ||
new len = strlen(tags); | ||
if(len > 0 && pos > -1) | ||
{ | ||
new bool:found; | ||
decl String:taglist[50][50]; | ||
ExplodeString(tags, ",", taglist, sizeof(taglist[]), sizeof(taglist)); | ||
for(new i;i < sizeof(taglist[]);i++) | ||
{ | ||
if(StrEqual(taglist[i], tag, true)) | ||
{ | ||
Format(taglist[i], sizeof(taglist), ""); | ||
found = true; | ||
break; | ||
} | ||
} | ||
if(!found) return; | ||
ImplodeStrings(taglist, sizeof(taglist[]), ",", tags, sizeof(tags)); | ||
if(pos == 0) | ||
{ | ||
tags[0] = 0x20; | ||
} | ||
else if(pos == len-1) | ||
{ | ||
Format(tags[strlen(tags)-1], sizeof(tags), ""); | ||
} | ||
else | ||
{ | ||
ReplaceString(tags, sizeof(tags), ",,", ","); | ||
} | ||
SetConVarString(hTags, tags, true); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/bin/sh | ||
set -x | ||
rm ./compiled/veterans.smx; | ||
yes | ./compile.sh ./veterans.sp; cp ./compiled/veterans.smx ../plugins | ||
|
Oops, something went wrong.