moving plugin from steamworks to ripext due to sourcemod 1.13 upgrade. also removing detour callback due to pointer crashing with 1.13 update. instead relying on alternative approach for getting the client that needs their fastdownload value updated clientside
This commit is contained in:
@@ -1,23 +1,22 @@
|
||||
#include <sourcemod>
|
||||
#include <dhooks>
|
||||
#include <SteamWorks>
|
||||
#include <ripext>
|
||||
#include <sdktools>
|
||||
|
||||
#pragma semicolon 1
|
||||
#pragma newdecls required
|
||||
|
||||
Handle hPlayerSlot = INVALID_HANDLE;
|
||||
GameData gamedatafile; //Handle to the gamedata
|
||||
|
||||
char originalConVar[1024]; //original sv_downloadurl value
|
||||
char g_cBackupURLS[2][1024];
|
||||
char g_cIPaddresses[MAXPLAYERS + 1][256];
|
||||
int g_icurrentClient;
|
||||
StringMap g_SteamIDRotations;
|
||||
bool g_bDoesIndexHaveBZ2[sizeof(g_cBackupURLS)]; //must have same size as g_cBackupURLS
|
||||
bool g_bRotated[MAXPLAYERS + 1];
|
||||
ConVar downloadurl; // sv_downloadurl
|
||||
|
||||
public Plugin myinfo =
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Fastdownload rotater",
|
||||
description = "Rotates fastdl used for clients when missing map errors happen",
|
||||
@@ -42,45 +41,30 @@ public void OnPluginStart()
|
||||
//we only use one backup fastdl but you could potentially have several.
|
||||
|
||||
downloadurl = FindConVar("sv_downloadurl"); //Save original downloadurl, so we can send it to clients who we cant locate
|
||||
downloadurl.GetString(originalConVar, sizeof(originalConVar));
|
||||
downloadurl.GetString(originalConVar, sizeof(originalConVar));
|
||||
|
||||
gamedatafile = LoadGameConfigFile("fastdl_rotater.games");
|
||||
|
||||
|
||||
if(gamedatafile == null)
|
||||
SetFailState("Cannot load fastdl_rotater.games.txt! Make sure you have it installed!");
|
||||
|
||||
|
||||
Handle detourBuildConVarMessage = DHookCreateDetour(Address_Null, CallConv_CDECL, ReturnType_Void, ThisPointer_Ignore);
|
||||
if(detourBuildConVarMessage == null)
|
||||
SetFailState("Failed to create detour for Host_BuildConVarUpdateMessage!");
|
||||
|
||||
|
||||
if(!DHookSetFromConf(detourBuildConVarMessage, gamedatafile, SDKConf_Signature, "Host_BuildConVarUpdateMessage"))
|
||||
SetFailState("Failed to load Host_BuildConVarUpdateMessage signature from gamedata!");
|
||||
|
||||
DHookAddParam(detourBuildConVarMessage, HookParamType_Unknown);
|
||||
DHookAddParam(detourBuildConVarMessage, HookParamType_Int);
|
||||
DHookAddParam(detourBuildConVarMessage, HookParamType_Bool);
|
||||
|
||||
DHookAddParam(detourBuildConVarMessage, HookParamType_Bool);
|
||||
|
||||
if(!DHookEnableDetour(detourBuildConVarMessage, false, buildConVarMessageDetCallback_Pre))
|
||||
SetFailState("Failed to detour Host_BuildConVarUpdateMessage PreHook!");
|
||||
|
||||
|
||||
Handle detourSendServerInfo = DHookCreateDetour(Address_Null, CallConv_THISCALL, ReturnType_Bool, ThisPointer_Address);
|
||||
if(detourSendServerInfo == null)
|
||||
SetFailState("Failed to create detour for CBaseClient::SendServerInfo!");
|
||||
|
||||
if(!DHookSetFromConf(detourSendServerInfo, gamedatafile, SDKConf_Signature, "CBaseClient::SendServerInfo"))
|
||||
SetFailState("Failed to load CBaseClient::SendServerInfo signature from gamedata!");
|
||||
|
||||
if(!DHookEnableDetour(detourSendServerInfo, false, sendServerInfoDetCallback_Pre))
|
||||
SetFailState("Failed to detour CBaseClient::SendServerInfo PreHook!");
|
||||
|
||||
HookEvent("player_disconnect", Event_PlayerDisconnect, EventHookMode_Pre);
|
||||
|
||||
StartPrepSDKCall(SDKCall_Raw);
|
||||
PrepSDKCall_SetFromConf(gamedatafile, SDKConf_Virtual, "CBaseClient::GetPlayerSlot");
|
||||
PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);
|
||||
hPlayerSlot = EndPrepSDKCall();
|
||||
|
||||
OnMapStart();
|
||||
}
|
||||
|
||||
@@ -93,12 +77,13 @@ public Action Event_PlayerDisconnect(Handle event, const char[] name, bool dontB
|
||||
if (StrContains(reason, "Map is missing") != -1)
|
||||
{
|
||||
GetClientIP(client, g_cIPaddresses[client], sizeof(g_cIPaddresses[]));
|
||||
|
||||
|
||||
int rotated = -1;
|
||||
g_SteamIDRotations.GetValue(g_cIPaddresses[client], rotated);
|
||||
rotated++;
|
||||
g_SteamIDRotations.SetValue(g_cIPaddresses[client], rotated, true);
|
||||
}
|
||||
g_bRotated[client] = false;
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
@@ -113,32 +98,32 @@ public void OnMapStart()
|
||||
g_bDoesIndexHaveBZ2[i] = false; //resetting to false until the http header finished
|
||||
FormatEx(sRequest, sizeof(sRequest), "%s%s%s%s", g_cBackupURLS[i], "maps/", map, ".bsp.bz2");
|
||||
|
||||
Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodHEAD, sRequest);
|
||||
if (!hRequest ||
|
||||
!SteamWorks_SetHTTPCallbacks(hRequest, OnTransferComplete) ||
|
||||
!SteamWorks_SetHTTPRequestContextValue(hRequest, i) ||
|
||||
!SteamWorks_SendHTTPRequest(hRequest))
|
||||
{
|
||||
delete hRequest;
|
||||
}
|
||||
HTTPRequest hRequest = new HTTPRequest(sRequest);
|
||||
|
||||
// ripext has no HEAD verb (SteamWorks' k_EHTTPMethodHEAD has no
|
||||
// equivalent native here). Ask for just the first byte via a Range
|
||||
// header on a GET instead, so we still avoid downloading the whole
|
||||
// (potentially large) .bsp.bz2 just to check whether it exists.
|
||||
// A server that honors Range answers 206/200 without the full body;
|
||||
// one that doesn't just falls back to sending the whole file.
|
||||
hRequest.SetHeader("Range", "bytes=0-0");
|
||||
hRequest.Get(OnTransferComplete, i);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
public int OnTransferComplete(Handle hRequest, bool bFailure, bool bSuccessful, EHTTPStatusCode eStatusCode, int url_index)
|
||||
public void OnTransferComplete(HTTPResponse response, any url_index)
|
||||
{
|
||||
if (bFailure || !bSuccessful || eStatusCode != k_EHTTPStatusCode200OK)
|
||||
{
|
||||
g_bDoesIndexHaveBZ2[url_index] = false;
|
||||
}
|
||||
else
|
||||
if (response.Status == HTTPStatus_OK || response.Status == HTTPStatus_PartialContent)
|
||||
{
|
||||
g_bDoesIndexHaveBZ2[url_index] = true;
|
||||
}
|
||||
delete hRequest;
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
g_bDoesIndexHaveBZ2[url_index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnMapEnd()
|
||||
@@ -166,46 +151,42 @@ public void OnConfigsExecuted()
|
||||
downloadurl.GetString(originalConVar, sizeof(originalConVar));
|
||||
}
|
||||
|
||||
public MRESReturn sendServerInfoDetCallback_Pre(Address pointer, Handle hReturn, Handle hParams) //First callback
|
||||
{
|
||||
int client;
|
||||
client = view_as<int>(SDKCall(hPlayerSlot, pointer)) + 1; //we just use linux anyways, no reason to check OS.
|
||||
g_icurrentClient = client;
|
||||
return MRES_Ignored;
|
||||
}
|
||||
|
||||
public MRESReturn buildConVarMessageDetCallback_Pre(Handle hParams) //Second callback
|
||||
{
|
||||
if (g_icurrentClient > 0 && g_icurrentClient <= MaxClients && IsClientConnected(g_icurrentClient))
|
||||
for (int client = 1; client <= MaxClients; client++)
|
||||
{
|
||||
//LogMessage("client %N in buildConVarMessageDetCallback_Pre", g_icurrentClient);
|
||||
char clientIPAddress[64]; //IP of the connecting client
|
||||
GetClientIP(g_icurrentClient, clientIPAddress, sizeof(clientIPAddress));
|
||||
|
||||
for (int i = 0; i < sizeof(g_cIPaddresses); i++)
|
||||
if (IsClientConnected(client))
|
||||
{
|
||||
if (StrEqual(g_cIPaddresses[i], clientIPAddress))
|
||||
//LogMessage("client %N in buildConVarMessageDetCallback_Pre", client);
|
||||
char clientIPAddress[64];
|
||||
GetClientIP(client, clientIPAddress, sizeof(clientIPAddress));
|
||||
|
||||
for (int i = 0; i < sizeof(g_cIPaddresses); i++)
|
||||
{
|
||||
int rotated = -1;
|
||||
g_SteamIDRotations.GetValue(clientIPAddress, rotated);
|
||||
|
||||
//0 = ovh uk unloze. 1 = ovh uk unloze. 2 = default sv_downloadurl again. so not overwriting anything
|
||||
rotated = rotated % 3;
|
||||
|
||||
//the bz2 file does not exist on the backup urls so rotate to the next working one.
|
||||
while (rotated < sizeof(g_cBackupURLS) && !g_bDoesIndexHaveBZ2[rotated])
|
||||
if (StrEqual(g_cIPaddresses[i], clientIPAddress) && !g_bRotated[client])
|
||||
{
|
||||
rotated++;
|
||||
g_bRotated[client] = true; //its only from disconnecting that the clients needs to be rotated again by matching IP.
|
||||
int rotated = -1;
|
||||
g_SteamIDRotations.GetValue(clientIPAddress, rotated);
|
||||
|
||||
//0 = ovh uk unloze. 1 = ovh uk unloze. 2 = default sv_downloadurl again. so not overwriting anything
|
||||
rotated = rotated % 3;
|
||||
|
||||
//the bz2 file does not exist on the backup urls so rotate to the next working one.
|
||||
while (rotated < sizeof(g_cBackupURLS) && !g_bDoesIndexHaveBZ2[rotated])
|
||||
{
|
||||
rotated++;
|
||||
}
|
||||
if (rotated < sizeof(g_cBackupURLS))
|
||||
{
|
||||
char map[256];
|
||||
GetCurrentMap(map, sizeof(map));
|
||||
g_SteamIDRotations.SetValue(clientIPAddress, rotated, true); //adapting in case of increment.
|
||||
LogMessage("client %N had missing map with default sv_downloadurl on %s. using %s instead.", client, map, g_cBackupURLS[rotated]);
|
||||
setConVarValue(g_cBackupURLS[rotated]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (rotated < sizeof(g_cBackupURLS))
|
||||
{
|
||||
char map[256];
|
||||
GetCurrentMap(map, sizeof(map));
|
||||
g_SteamIDRotations.SetValue(clientIPAddress, rotated, true); //adapting in case of increment.
|
||||
LogMessage("client %N had missing map with default sv_downloadurl on %s. using %s instead.", g_icurrentClient, map, g_cBackupURLS[rotated]);
|
||||
setConVarValue(g_cBackupURLS[rotated]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,6 +197,6 @@ void setConVarValue(char[] value) //Sets the actual ConVar value
|
||||
{
|
||||
int oldflags = GetConVarFlags(downloadurl);
|
||||
SetConVarFlags(downloadurl, oldflags &~ FCVAR_REPLICATED);
|
||||
SetConVarString(downloadurl, value, true, false);
|
||||
SetConVarString(downloadurl, value, true, false);
|
||||
SetConVarFlags(downloadurl, oldflags|FCVAR_REPLICATED);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user