UFO: Alien Invasion
Loading...
Searching...
No Matches
g_svcmds.cpp
Go to the documentation of this file.
1
5
6/*
7All original material Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9Original file from Quake 2 v3.21: quake2-2.31/game/g_svcmds.c
10Copyright (C) 1997-2001 Id Software, Inc.
11
12This program is free software; you can redistribute it and/or
13modify it under the terms of the GNU General Public License
14as published by the Free Software Foundation; either version 2
15of the License, or (at your option) any later version.
16
17This program is distributed in the hope that it will be useful,
18but WITHOUT ANY WARRANTY; without even the implied warranty of
19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20
21See the GNU General Public License for more details.
22
23You should have received a copy of the GNU General Public License
24along with this program; if not, write to the Free Software
25Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27*/
28
29
30#include "g_local.h"
31#include "g_ai.h"
32#include "g_client.h"
33#include "g_edicts.h"
34#include "g_inventory.h"
35#include "g_match.h"
36#include "g_vis.h"
37
57
58typedef struct ipfilter_s {
59 unsigned mask;
60 unsigned compare;
62
63#define MAX_IPFILTERS 1024
64
66static int numipfilters;
67
68static bool StringToFilter (const char* s, ipfilter_t* f)
69{
70 char num[128];
71 byte b[4];
72 byte m[4];
73
74 OBJZERO(b);
75 OBJZERO(m);
76
77 for (int i = 0; i < 4; i++) {
78 if (*s < '0' || *s > '9') {
80 //G_ClientPrintf(nullptr, PRINT_CONSOLE, "Bad filter address: %s\n", s);
81 return false;
82 }
83
84 int j = 0;
85 while (isdigit(*s)) {
86 num[j++] = *s++;
87 }
88 num[j] = 0;
89 b[i] = atoi(num);
90 if (b[i] != 0)
91 m[i] = 0xFF;
92
93 if (!*s)
94 break;
95 s++;
96 }
97
98 f->mask = *(unsigned* ) m;
99 f->compare = *(unsigned* ) b;
100
101 return true;
102}
103
104bool SV_FilterPacket (const char* from)
105{
106 byte m[4];
107 int i = 0;
108 const char* p = from;
109
110 while (*p && i < 4) {
111 m[i] = 0;
112 while (*p >= '0' && *p <= '9') {
113 m[i] = m[i] * 10 + (*p - '0');
114 p++;
115 }
116 if (!*p || *p == ':')
117 break;
118 i++, p++;
119 }
120
121 const unsigned in = *(unsigned* ) m;
122
123 for (i = 0; i < numipfilters; i++)
124 if ((in & ipfilters[i].mask) == ipfilters[i].compare)
125 return sv_filterban->integer;
126
127 return !sv_filterban->integer;
128}
129
130
134static void SVCmd_AddIP_f (void)
135{
136 if (gi.Cmd_Argc() < 3) {
137 gi.DPrintf("Usage: %s <ip-mask>\n", gi.Cmd_Argv(1));
138 return;
139 }
140
141 int i;
142 for (i = 0; i < numipfilters; i++)
143 if (ipfilters[i].compare == ~0x0)
144 break; /* free spot */
145 if (i == numipfilters) {
147 gi.DPrintf("IP filter list is full\n");
148 return;
149 }
150 numipfilters++;
151 }
152
153 if (!StringToFilter(gi.Cmd_Argv(2), &ipfilters[i]))
154 ipfilters[i].compare = ~0x0;
155}
156
160static void SVCmd_RemoveIP_f (void)
161{
162 if (gi.Cmd_Argc() < 3) {
163 gi.DPrintf("Usage: %s <ip-mask>\n", gi.Cmd_Argv(1));
164 return;
165 }
166
168 if (!StringToFilter(gi.Cmd_Argv(2), &f))
169 return;
170
171 for (int i = 0; i < numipfilters; i++)
172 if (ipfilters[i].mask == f.mask && ipfilters[i].compare == f.compare) {
173 for (int j = i + 1; j < numipfilters; j++)
174 ipfilters[j - 1] = ipfilters[j];
175 numipfilters--;
176 gi.DPrintf("Removed.\n");
177 return;
178 }
179 gi.DPrintf("Didn't find %s.\n", gi.Cmd_Argv(2));
180}
181
185static void SVCmd_ListIP_f (void)
186{
187 gi.DPrintf("Filter list:\n");
188 for (int i = 0; i < numipfilters; i++) {
189 byte b[4];
190 *(unsigned* ) b = ipfilters[i].compare;
191 gi.DPrintf("%3i.%3i.%3i.%3i\n", b[0], b[1], b[2], b[3]);
192 }
193}
194
198static void SVCmd_WriteIP_f (void)
199{
200 char name[MAX_OSPATH];
201
202 Com_sprintf(name, sizeof(name), "%s/listip.cfg", gi.FS_Gamedir());
203
204 gi.DPrintf("Writing %s.\n", name);
205
206 FILE* f = gi.Sys_Fopen(name, "wb");
207 if (!f) {
208 gi.DPrintf("Couldn't open %s\n", name);
209 return;
210 }
211
212 fprintf(f, "set sv_filterban %d\n", sv_filterban->integer);
213
214 for (int i = 0; i < numipfilters; i++) {
215 byte b[4];
216 *(unsigned* ) b = ipfilters[i].compare;
217 fprintf(f, "sv addip %i.%i.%i.%i\n", b[0], b[1], b[2], b[3]);
218 }
219
220 fclose(f);
221}
222
228static void SVCmd_AI_Add_f (void)
229{
230 if (gi.Cmd_Argc() < 3) {
231 gi.DPrintf("Usage: %s <teamnum>\n", gi.Cmd_Argv(1));
232 return;
233 }
234 const int team = atoi(gi.Cmd_Argv(2));
235 if (team > TEAM_CIVILIAN && team < MAX_TEAMS) {
236 if (!AI_CreatePlayer(team))
237 gi.DPrintf("Couldn't create AI player.\n");
238 } else
239 gi.DPrintf("Bad team number.\n");
240}
241
242
248static void SVCmd_Win_f (void)
249{
250 if (gi.Cmd_Argc() < 3) {
251 gi.DPrintf("Usage: %s <teamnum>\n", gi.Cmd_Argv(1));
252 return;
253 }
254 const int team = atoi(gi.Cmd_Argv(2));
255 if (team > TEAM_CIVILIAN && team < MAX_TEAMS)
256 G_MatchEndTrigger(team, 0);
257 else
258 gi.DPrintf("Bad team number.\n");
259}
260
261#ifdef DEBUG
262static void SVCmd_ShowAll_f (void)
263{
264 Edict* ent = nullptr;
265
266 /* Make everything visible to anyone who can't already see it */
267 while ((ent = G_EdictsGetNextInUse(ent))) {
268 G_AppearPerishEvent(~G_VisToPM(ent->visflags), 1, *ent, nullptr);
269 G_VisFlagsAdd(*ent, ~ent->visflags);
270 }
271 gi.DPrintf("All items and creatures revealed to all sides\n");
272}
273
274static void SVCmd_AddItem_f (void)
275{
276 const int team = TEAM_DEFAULT;
277 Actor* actor = G_EdictsGetNextLivingActorOfTeam(nullptr, team);
278
279 if (gi.Cmd_Argc() < 3) {
280 gi.DPrintf("Usage: %s <item-id>\n", gi.Cmd_Argv(1));
281 return;
282 }
283
284 if (!actor) {
285 gi.DPrintf("Could not add item, no living members of team %i left\n", team);
286 return;
287 }
288
289 G_AddItemToFloor(actor->pos, gi.Cmd_Argv(2));
290}
291
295static void SVCmd_ActorInvList_f (void)
296{
297 Player* player;
298 int i;
299
300 /* show inventory of all players around - include even the ai players */
301 for (i = 0, player = game.players; i < game.sv_maxplayersperteam * 2; i++, player++) {
302 if (!player->isInUse())
303 continue;
304 G_InvList_f(*player);
305 }
306}
307
308static void SVCmd_ListEdicts_f (void)
309{
310 Edict* ent = nullptr;
311 int i = 0;
312 Com_Printf("number | entnum | mapnum | type | inuse | pnum | team | size | HP | state | classname | model/ptl | pos\n");
313 while ((ent = G_EdictsGetNext(ent))) {
314 char buf[128];
315 const char* model;
316 if (ent->type == ET_PARTICLE)
317 model = ent->particle;
318 else if (ent->model)
319 model = ent->model;
320 else
321 model = "no mdl";
322 Com_sprintf(buf, sizeof(buf), "#%5i | #%5i | #%5i | %4i | %5i | %4i | %4i | %4i | %3i | %5i | %14s | %21s | %i:%i:%i",
323 i, ent->getIdNum(), ent->mapNum, ent->type, ent->inuse, ent->getPlayerNum(), ent->getTeam(), ent->fieldSize,
324 ent->HP, ent->state, ent->classname, model, ent->pos[0], ent->pos[1], ent->pos[2]);
325 Com_Printf("%s\n", buf);
326 i++;
327 }
328}
329#endif
330
338{
339 const char* cmd;
340
341 cmd = gi.Cmd_Argv(1);
342 if (Q_strcasecmp(cmd, "addip") == 0)
344 else if (Q_strcasecmp(cmd, "removeip") == 0)
346 else if (Q_strcasecmp(cmd, "listip") == 0)
348 else if (Q_strcasecmp(cmd, "writeip") == 0)
350 else if (Q_strcasecmp(cmd, "ai_add") == 0)
352 else if (Q_strcasecmp(cmd, "win") == 0)
353 SVCmd_Win_f();
354#ifdef DEBUG
355 else if (Q_strcasecmp(cmd, "debug_showall") == 0)
356 SVCmd_ShowAll_f();
357 else if (Q_strcasecmp(cmd, "debug_additem") == 0)
358 SVCmd_AddItem_f();
359 else if (Q_strcasecmp(cmd, "debug_actorinvlist") == 0)
360 SVCmd_ActorInvList_f();
361 else if (Q_strcasecmp(cmd, "debug_listedicts") == 0)
362 SVCmd_ListEdicts_f();
363#endif
364 else
365 gi.DPrintf("Unknown server command \"%s\"\n", cmd);
366}
An Edict of type Actor.
Definition g_edict.h:348
int getPlayerNum() const
Definition g_edict.h:234
teammask_t visflags
Definition g_edict.h:82
int getIdNum() const
Definition g_edict.h:231
const char * classname
Definition g_edict.h:67
const char * particle
Definition g_edict.h:128
pos3_t pos
Definition g_edict.h:55
actorSizeEnum_t fieldSize
Definition g_edict.h:141
int HP
Definition g_edict.h:89
bool inuse
Definition g_edict.h:47
int getTeam() const
Definition g_edict.h:269
int mapNum
Definition g_edict.h:73
entity_type_t type
Definition g_edict.h:81
int state
Definition g_edict.h:93
const char * model
Definition g_edict.h:74
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define MAX_TEAMS
Definition defines.h:98
#define TEAM_DEFAULT
Definition defines.h:51
#define MAX_OSPATH
Definition filesys.h:44
Player * AI_CreatePlayer(int team)
Spawn civilians and aliens.
Definition g_ai.cpp:1944
Artificial Intelligence functions.
void G_AppearPerishEvent(playermask_t playerMask, bool appear, Edict &check, const Edict *ent)
Send the appear or perish event to the affected clients.
Definition g_client.cpp:245
playermask_t G_VisToPM(teammask_t teamMask)
Converts vis mask to player mask.
Definition g_client.cpp:186
Interface for g_client.cpp.
Actor * G_EdictsGetNextLivingActorOfTeam(Actor *lastEnt, const int team)
Iterate through the living actor entities of the given team.
Definition g_edicts.cpp:216
Edict * G_EdictsGetNext(Edict *lastEnt)
Iterate through the list of entities.
Definition g_edicts.cpp:107
Edict * G_EdictsGetNextInUse(Edict *lastEnt)
Iterate through the entities that are in use.
Definition g_edicts.cpp:166
functions to handle the storage and lifecycle of all edicts in the game module.
bool G_AddItemToFloor(const pos3_t pos, const char *itemID)
Adds a new item to an existing or new floor container edict at the given grid location.
Local definitions for game module.
game_locals_t game
Definition g_main.cpp:37
cvar_t * sv_filterban
Definition g_main.cpp:58
game_import_t gi
Definition g_main.cpp:39
void G_MatchEndTrigger(int team, int timeGap)
Triggers the end of the game. Will be executed in the next server (or game) frame.
Definition g_match.cpp:125
Match related functions.
static void SVCmd_RemoveIP_f(void)
Definition g_svcmds.cpp:160
static void SVCmd_Win_f(void)
Call the end game function with the given team used to e.g. abort singleplayer games and let the alie...
Definition g_svcmds.cpp:248
static int numipfilters
Definition g_svcmds.cpp:66
static void SVCmd_AI_Add_f(void)
Used to add ai opponents to a game.
Definition g_svcmds.cpp:228
bool SV_FilterPacket(const char *from)
Definition g_svcmds.cpp:104
void G_ServerCommand(void)
ServerCommand will be called when an "sv" command is issued. The game can issue gi....
Definition g_svcmds.cpp:337
static void SVCmd_AddIP_f(void)
Definition g_svcmds.cpp:134
static void SVCmd_WriteIP_f(void)
Store all ips in the current filter list in.
Definition g_svcmds.cpp:198
static bool StringToFilter(const char *s, ipfilter_t *f)
Definition g_svcmds.cpp:68
static void SVCmd_ListIP_f(void)
Shows the current ip in the filter list.
Definition g_svcmds.cpp:185
#define MAX_IPFILTERS
Definition g_svcmds.cpp:63
static ipfilter_t ipfilters[MAX_IPFILTERS]
Definition g_svcmds.cpp:65
void G_VisFlagsAdd(Edict &ent, teammask_t teamMask)
Definition g_vis.cpp:433
voidpf void * buf
Definition ioapi.h:42
static struct mdfour * m
Definition md4.cpp:35
@ ET_PARTICLE
Definition q_shared.h:164
#define TEAM_CIVILIAN
Definition q_shared.h:61
QGL_EXTERN GLfloat f
Definition r_gl.h:114
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition r_gl.h:110
#define Q_strcasecmp(a, b)
Definition shared.h:131
#define OBJZERO(obj)
Definition shared.h:178
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition shared.cpp:494
PACKET FILTERING.
Definition g_svcmds.cpp:58
unsigned mask
Definition g_svcmds.cpp:59
unsigned compare
Definition g_svcmds.cpp:60
#define FILE