aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDLL/misccommands.cpp
blob: b316571c9589624ff486adc1d0cb27228a221b68 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include "pch.h"
#include "misccommands.h"
#include "concommand.h"
#include "playlist.h"
#include "r2engine.h"
#include "r2client.h"
#include "tier0.h"
#include "hoststate.h"
#include "masterserver.h"
#include "modmanager.h"
#include "serverauthentication.h"
#include "squirrel.h"

void ConCommand_force_newgame(const CCommand& arg)
{
	if (arg.ArgC() < 2)
		return;

	R2::g_pHostState->m_iNextState = R2::HostState_t::HS_NEW_GAME;
	strncpy(R2::g_pHostState->m_levelName, arg.Arg(1), sizeof(R2::g_pHostState->m_levelName));
}

void ConCommand_ns_start_reauth_and_leave_to_lobby(const CCommand& arg)
{
	// hack for special case where we're on a local server, so we erase our own newly created auth data on disconnect
	g_pMasterServerManager->m_bNewgameAfterSelfAuth = true;
	g_pMasterServerManager->AuthenticateWithOwnServer(R2::g_pLocalPlayerUserID, g_pMasterServerManager->m_sOwnClientAuthToken);
}

void ConCommand_ns_end_reauth_and_leave_to_lobby(const CCommand& arg)
{
	R2::Cbuf_AddText(
		R2::Cbuf_GetCurrentPlayer(),
		fmt::format("serverfilter {}", g_pServerAuthentication->m_RemoteAuthenticationData.begin()->first).c_str(),
		R2::cmd_source_t::kCommandSrcCode);
	R2::Cbuf_Execute();

	// weird way of checking, but check if client script vm is initialised, mainly just to allow players to cancel this
	if (g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM)
	{
		g_pServerAuthentication->m_bNeedLocalAuthForNewgame = true;

		// this won't set playlist correctly on remote clients, don't think they can set playlist until they've left which sorta
		// fucks things should maybe set this in HostState_NewGame?
		R2::SetCurrentPlaylist("tdm");
		strcpy(R2::g_pHostState->m_levelName, "mp_lobby");
		R2::g_pHostState->m_iNextState = R2::HostState_t::HS_NEW_GAME;
	}
}

void AddMiscConCommands()
{
	RegisterConCommand(
		"force_newgame",
		ConCommand_force_newgame,
		"forces a map load through directly setting g_pHostState->m_iNextState to HS_NEW_GAME",
		FCVAR_NONE);

	RegisterConCommand(
		"ns_start_reauth_and_leave_to_lobby",
		ConCommand_ns_start_reauth_and_leave_to_lobby,
		"called by the server, used to reauth and return the player to lobby when leaving a game",
		FCVAR_SERVER_CAN_EXECUTE);

	// this is a concommand because we make a deferred call to it from another thread
	RegisterConCommand("ns_end_reauth_and_leave_to_lobby", ConCommand_ns_end_reauth_and_leave_to_lobby, "", FCVAR_NONE);
}

// fixes up various cvar flags to have more sane values
void FixupCvarFlags()
{
	if (Tier0::CommandLine()->CheckParm("-allowdevcvars"))
	{
		// strip hidden and devonly cvar flags
		int iNumCvarsAltered = 0;
		for (auto& pair : R2::g_pCVar->DumpToMap())
		{
			// strip flags
			int flags = pair.second->GetFlags();
			if (flags & FCVAR_DEVELOPMENTONLY)
			{
				flags &= ~FCVAR_DEVELOPMENTONLY;
				iNumCvarsAltered++;
			}

			if (flags & FCVAR_HIDDEN)
			{
				flags &= ~FCVAR_HIDDEN;
				iNumCvarsAltered++;
			}

			pair.second->m_nFlags = flags;
		}

		spdlog::info("Removed {} hidden/devonly cvar flags", iNumCvarsAltered);
	}

	// make all engine client commands FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS
	// these are usually checked through CGameClient::IsEngineClientCommand, but we get more control over this if we just do it through
	// cvar flags
	const char** ppEngineClientCommands = CModule("engine.dll").Offset(0x7C5EF0).As<const char**>();

	int i = 0;
	do
	{
		ConCommandBase* pCommand = R2::g_pCVar->FindCommandBase(ppEngineClientCommands[i]);
		if (pCommand) // not all the commands in this array actually exist in respawn source
			pCommand->m_nFlags |= FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS;
	} while (ppEngineClientCommands[++i]);

	const std::vector<std::tuple<const char*, uint32_t>> CVAR_FIXUP_ADD_FLAGS = {
		// system commands (i.e. necessary for proper functionality)
		// servers need to be able to disconnect
		{"disconnect", FCVAR_SERVER_CAN_EXECUTE},

		// cheat commands
		{"give", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"give_server", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"givecurrentammo", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"takecurrentammo", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},

		{"switchclass", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"set", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"_setClassVarServer", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},

		{"ent_create", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"ent_throw", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"ent_setname", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"ent_teleport", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"ent_remove", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"ent_remove_all", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"ent_fire", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},

		{"particle_create", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"particle_recreate", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"particle_kill", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},

		{"test_setteam", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"melee_lunge_ent", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS}};

	const std::vector<std::tuple<const char*, uint32_t>> CVAR_FIXUP_REMOVE_FLAGS = {
		// unsure how this command works, not even sure it's used on retail servers, deffo shouldn't be used on northstar
		{"migrateme", FCVAR_SERVER_CAN_EXECUTE | FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"recheck", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS}, // we don't need this on northstar servers, it's for communities
		{"rpt_client_enable", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS},
		{"rpt_password", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS}};

	for (auto& fixup : CVAR_FIXUP_ADD_FLAGS)
		R2::g_pCVar->FindCommandBase(std::get<0>(fixup))->m_nFlags |= std::get<1>(fixup);

	for (auto& fixup : CVAR_FIXUP_REMOVE_FLAGS)
		R2::g_pCVar->FindCommandBase(std::get<0>(fixup))->m_nFlags &= ~std::get<1>(fixup);
}