r5sdk/r5dev/game/server/vscript_server.cpp
Kawe Mazidjatari 12aa0f8ded Game: add game dll flags to "script(_*)" command
The flags were originally removed in commit 1bdc3b893e59f208dbeadd78b978096dcdd8e8f9, but this caused a regression in the dev menu. Restored flags (this also doesn't cause security issues as these commands are flagged devonly and cheats anyways).
2024-06-01 11:52:54 +02:00

337 lines
14 KiB
C++

//=============================================================================//
//
// Purpose: Expose native code to VScript API
//
//-----------------------------------------------------------------------------
//
// See 'game/shared/vscript_shared.cpp' for more details.
//
//=============================================================================//
#include "core/stdafx.h"
#include "engine/server/server.h"
#include "game/shared/vscript_shared.h"
#include "vscript/vscript.h"
#include "vscript/languages/squirrel_re/include/sqvm.h"
#include "liveapi/liveapi.h"
#include "vscript_server.h"
#include <engine/host_state.h>
#include <networksystem/hostmanager.h>
/*
=====================
SQVM_ServerScript_f
Executes input on the
VM in SERVER context.
=====================
*/
static void SQVM_ServerScript_f(const CCommand& args)
{
if (args.ArgC() >= 2)
{
Script_Execute(args.ArgS(), SQCONTEXT::SERVER);
}
}
static ConCommand script("script", SQVM_ServerScript_f, "Run input code as SERVER script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_GAMEDLL | FCVAR_CHEAT | FCVAR_SERVER_FRAME_THREAD);
namespace VScriptCode
{
namespace Server
{
//-----------------------------------------------------------------------------
// Purpose: create server via native serverbrowser entries
// TODO: return a boolean on failure instead of raising an error, so we could
// determine from scripts whether or not to spin a local server, or connect
// to a dedicated server (for disconnecting and loading the lobby, for example)
//-----------------------------------------------------------------------------
SQRESULT CreateServer(HSQUIRRELVM v)
{
const SQChar* serverName = nullptr;
const SQChar* serverDescription = nullptr;
const SQChar* serverMapName = nullptr;
const SQChar* serverPlaylist = nullptr;
sq_getstring(v, 2, &serverName);
sq_getstring(v, 3, &serverDescription);
sq_getstring(v, 4, &serverMapName);
sq_getstring(v, 5, &serverPlaylist);
SQInteger serverVisibility = 0;
sq_getinteger(v, 6, &serverVisibility);
if (!VALID_CHARSTAR(serverName) ||
!VALID_CHARSTAR(serverMapName) ||
!VALID_CHARSTAR(serverPlaylist))
{
v_SQVM_ScriptError("Empty or null server criteria");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
// Adjust browser settings.
NetGameServer_t& details = g_ServerHostManager.GetDetails();
details.name = serverName;
details.description = serverDescription;
details.map = serverMapName;
details.playlist = serverPlaylist;
// Launch server.
g_ServerHostManager.SetVisibility(ServerVisibility_e(serverVisibility));
g_ServerHostManager.LaunchServer(g_pServer->IsActive());
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: shuts the server down and disconnects all clients
//-----------------------------------------------------------------------------
SQRESULT DestroyServer(HSQUIRRELVM v)
{
if (g_pHostState->m_bActiveGame)
g_pHostState->m_iNextState = HostStates_t::HS_GAME_SHUTDOWN;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: sets whether the server could auto reload at this time (e.g. if
// server admin has host_autoReloadRate AND host_autoReloadRespectGameState
// set, and its time to auto reload, but the match hasn't finished yet, wait
// until this is set to proceed the reload of the server
//-----------------------------------------------------------------------------
SQRESULT SetAutoReloadState(HSQUIRRELVM v)
{
SQBool state = false;
sq_getbool(v, 2, &state);
g_hostReloadState = state;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: kicks a player by given name
//-----------------------------------------------------------------------------
SQRESULT KickPlayerByName(HSQUIRRELVM v)
{
const SQChar* playerName = nullptr;
const SQChar* reason = nullptr;
sq_getstring(v, 2, &playerName);
sq_getstring(v, 3, &reason);
if (!VALID_CHARSTAR(playerName))
{
v_SQVM_ScriptError("Empty or null player name");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
// Discard empty strings, this will use the default message instead.
if (!VALID_CHARSTAR(reason))
reason = nullptr;
g_BanSystem.KickPlayerByName(playerName, reason);
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: kicks a player by given handle or id
//-----------------------------------------------------------------------------
SQRESULT KickPlayerById(HSQUIRRELVM v)
{
const SQChar* playerHandle = nullptr;
const SQChar* reason = nullptr;
sq_getstring(v, 2, &playerHandle);
sq_getstring(v, 3, &reason);
if (!VALID_CHARSTAR(playerHandle))
{
v_SQVM_ScriptError("Empty or null player handle");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
// Discard empty strings, this will use the default message instead.
if (!VALID_CHARSTAR(reason))
reason = nullptr;
g_BanSystem.KickPlayerById(playerHandle, reason);
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: bans a player by given name
//-----------------------------------------------------------------------------
SQRESULT BanPlayerByName(HSQUIRRELVM v)
{
const SQChar* playerName = nullptr;
const SQChar* reason = nullptr;
sq_getstring(v, 2, &playerName);
sq_getstring(v, 3, &reason);
if (!VALID_CHARSTAR(playerName))
{
v_SQVM_ScriptError("Empty or null player name");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
// Discard empty strings, this will use the default message instead.
if (!VALID_CHARSTAR(reason))
reason = nullptr;
g_BanSystem.BanPlayerByName(playerName, reason);
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: bans a player by given handle or id
//-----------------------------------------------------------------------------
SQRESULT BanPlayerById(HSQUIRRELVM v)
{
const SQChar* playerHandle = nullptr;
const SQChar* reason = nullptr;
sq_getstring(v, 2, &playerHandle);
sq_getstring(v, 3, &reason);
if (!VALID_CHARSTAR(playerHandle))
{
v_SQVM_ScriptError("Empty or null player handle");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
// Discard empty strings, this will use the default message instead.
if (!VALID_CHARSTAR(reason))
reason = nullptr;
g_BanSystem.BanPlayerById(playerHandle, reason);
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: unbans a player by given nucleus id or ip address
//-----------------------------------------------------------------------------
SQRESULT UnbanPlayer(HSQUIRRELVM v)
{
const SQChar* szCriteria = nullptr;
sq_getstring(v, 2, &szCriteria);
if (!VALID_CHARSTAR(szCriteria))
{
v_SQVM_ScriptError("Empty or null player criteria");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
g_BanSystem.UnbanPlayer(szCriteria);
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: gets the number of real players on this server
//-----------------------------------------------------------------------------
SQRESULT GetNumHumanPlayers(HSQUIRRELVM v)
{
sq_pushinteger(v, g_pServer->GetNumHumanPlayers());
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: gets the number of fake players on this server
//-----------------------------------------------------------------------------
SQRESULT GetNumFakeClients(HSQUIRRELVM v)
{
sq_pushinteger(v, g_pServer->GetNumFakeClients());
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: gets the current server id
//-----------------------------------------------------------------------------
SQRESULT GetServerID(HSQUIRRELVM v)
{
sq_pushstring(v, g_LogSessionUUID.c_str(), (SQInteger)g_LogSessionUUID.length());
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: checks whether the server is active
//-----------------------------------------------------------------------------
SQRESULT IsServerActive(HSQUIRRELVM v)
{
bool isActive = g_pServer->IsActive();
sq_pushbool(v, isActive);
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: checks whether this SDK build is a dedicated server
//-----------------------------------------------------------------------------
SQRESULT IsDedicated(HSQUIRRELVM v)
{
sq_pushbool(v, ::IsDedicated());
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
}
}
//---------------------------------------------------------------------------------
// Purpose: registers script functions in SERVER context
// Input : *s -
//---------------------------------------------------------------------------------
void Script_RegisterServerFunctions(CSquirrelVM* s)
{
Script_RegisterCommonAbstractions(s);
Script_RegisterCoreServerFunctions(s);
Script_RegisterAdminPanelFunctions(s);
Script_RegisterLiveAPIFunctions(s);
}
void Script_RegisterServerEnums(CSquirrelVM* const s)
{
Script_RegisterLiveAPIEnums(s);
}
//---------------------------------------------------------------------------------
// Purpose: core server script functions
// Input : *s -
//---------------------------------------------------------------------------------
void Script_RegisterCoreServerFunctions(CSquirrelVM* s)
{
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, IsServerActive, "Returns whether the server is active", "bool", "");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, IsDedicated, "Returns whether this is a dedicated server", "bool", "");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, CreateServer, "Starts server with the specified settings", "void", "string, string, string, string, int");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, DestroyServer, "Shuts the local server down", "void", "");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, SetAutoReloadState, "Set whether we can auto-reload the server", "void", "bool");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, GetServerID, "Gets the current server ID", "string", "");
}
//---------------------------------------------------------------------------------
// Purpose: admin panel script functions
// Input : *s -
//
// Ideally, these get dropped entirely in favor of remote functions. Currently,
// the s3 build only supports remote function calls from server to client/ui.
// Client/ui to server is all done through clientcommands.
//---------------------------------------------------------------------------------
void Script_RegisterAdminPanelFunctions(CSquirrelVM* s)
{
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, GetNumHumanPlayers, "Gets the number of human players on the server", "int", "");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, GetNumFakeClients, "Gets the number of bot players on the server", "int", "");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, KickPlayerByName, "Kicks a player from the server by name", "void", "string, string");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, KickPlayerById, "Kicks a player from the server by handle or nucleus id", "void", "string, string");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, BanPlayerByName, "Bans a player from the server by name", "void", "string, string");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, BanPlayerById, "Bans a player from the server by handle or nucleus id", "void", "string, string");
DEFINE_SERVER_SCRIPTFUNC_NAMED(s, UnbanPlayer, "Unbans a player from the server by nucleus id or ip address", "void", "string");
}