UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
g_svcmds.cpp
Go to the documentation of this file.
1 
6 /*
7 All original material Copyright (C) 2002-2020 UFO: Alien Invasion.
8 
9 Original file from Quake 2 v3.21: quake2-2.31/game/g_svcmds.c
10 Copyright (C) 1997-2001 Id Software, Inc.
11 
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 as published by the Free Software Foundation; either version 2
15 of the License, or (at your option) any later version.
16 
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 
21 See the GNU General Public License for more details.
22 
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, 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 
58 typedef struct ipfilter_s {
59  unsigned mask;
60  unsigned compare;
61 } ipfilter_t;
62 
63 #define MAX_IPFILTERS 1024
64 
66 static int numipfilters;
67 
68 static 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 
104 bool 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 
134 static 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) {
146  if (numipfilters == MAX_IPFILTERS) {
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 
160 static 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 
167  ipfilter_t f;
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 
185 static 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 
198 static 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 
228 static 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 
248 static 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
262 static 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 
274 static 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 
295 static 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 
308 static 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 
337 void G_ServerCommand (void)
338 {
339  const char* cmd;
340 
341  cmd = gi.Cmd_Argv(1);
342  if (Q_strcasecmp(cmd, "addip") == 0)
343  SVCmd_AddIP_f();
344  else if (Q_strcasecmp(cmd, "removeip") == 0)
346  else if (Q_strcasecmp(cmd, "listip") == 0)
347  SVCmd_ListIP_f();
348  else if (Q_strcasecmp(cmd, "writeip") == 0)
349  SVCmd_WriteIP_f();
350  else if (Q_strcasecmp(cmd, "ai_add") == 0)
351  SVCmd_AI_Add_f();
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 }
Edict * G_EdictsGetNextInUse(Edict *lastEnt)
Iterate through the entities that are in use.
Definition: g_edicts.cpp:166
int getIdNum() const
Definition: g_edict.h:231
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
#define MAX_TEAMS
Definition: defines.h:98
static void SVCmd_AI_Add_f(void)
Used to add ai opponents to a game.
Definition: g_svcmds.cpp:228
Player * players
Definition: g_local.h:70
Artificial Intelligence functions.
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
#define FILE
Definition: test_webapi.cpp:30
bool inuse
Definition: g_edict.h:47
int mapNum
Definition: g_edict.h:73
#define MAX_OSPATH
Definition: filesys.h:44
#define TEAM_CIVILIAN
Definition: q_shared.h:61
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
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
int integer
Definition: cvar.h:81
voidpf void * buf
Definition: ioapi.h:42
static bool StringToFilter(const char *s, ipfilter_t *f)
Definition: g_svcmds.cpp:68
game_locals_t game
Definition: g_main.cpp:37
int getTeam() const
Definition: g_edict.h:269
Match related functions.
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
cvar_t * sv_filterban
Definition: g_main.cpp:58
static ipfilter_t ipfilters[MAX_IPFILTERS]
Definition: g_svcmds.cpp:65
game_import_t gi
Definition: g_main.cpp:39
#define OBJZERO(obj)
Definition: shared.h:178
teammask_t visflags
Definition: g_edict.h:82
PACKET FILTERING.
Definition: g_svcmds.cpp:58
pos3_t pos
Definition: g_edict.h:55
const char *IMPORT * FS_Gamedir(void)
An Edict of type Actor.
Definition: g_edict.h:348
static void SVCmd_RemoveIP_f(void)
Definition: g_svcmds.cpp:160
#define TEAM_DEFAULT
Definition: defines.h:51
static void SVCmd_WriteIP_f(void)
Store all ips in the current filter list in.
Definition: g_svcmds.cpp:198
playermask_t G_VisToPM(teammask_t teamMask)
Converts vis mask to player mask.
Definition: g_client.cpp:186
#define Q_strcasecmp(a, b)
Definition: shared.h:131
int state
Definition: g_edict.h:93
bool SV_FilterPacket(const char *from)
Definition: g_svcmds.cpp:104
struct ipfilter_s ipfilter_t
PACKET FILTERING.
actorSizeEnum_t fieldSize
Definition: g_edict.h:141
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
static void SVCmd_ListIP_f(void)
Shows the current ip in the filter list.
Definition: g_svcmds.cpp:185
static int numipfilters
Definition: g_svcmds.cpp:66
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.
int sv_maxplayersperteam
Definition: g_local.h:73
Actor * G_EdictsGetNextLivingActorOfTeam(Actor *lastEnt, const int team)
Iterate through the living actor entities of the given team.
Definition: g_edicts.cpp:216
QGL_EXTERN GLint i
Definition: r_gl.h:113
int getPlayerNum() const
Definition: g_edict.h:234
void G_ServerCommand(void)
ServerCommand will be called when an "sv" command is issued. The game can issue gi.Cmd_Argc() / gi.Cmd_Argv() commands to get the rest of the parameters.
Definition: g_svcmds.cpp:337
Local definitions for game module.
unsigned mask
Definition: g_svcmds.cpp:59
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
entity_type_t type
Definition: g_edict.h:81
static void SVCmd_AddIP_f(void)
Definition: g_svcmds.cpp:134
functions to handle the storage and lifecycle of all edicts in the game module.
FILE *IMPORT * Sys_Fopen(const char *filename, const char *mode)
Player * AI_CreatePlayer(int team)
Spawn civilians and aliens.
Definition: g_ai.cpp:1944
const char * classname
Definition: g_edict.h:67
void G_VisFlagsAdd(Edict &ent, teammask_t teamMask)
Definition: g_vis.cpp:433
Definition: g_edict.h:45
uint8_t byte
Definition: ufotypes.h:34
unsigned compare
Definition: g_svcmds.cpp:60
static struct mdfour * m
Definition: md4.cpp:35
const char * model
Definition: g_edict.h:74
const char *IMPORT * Cmd_Argv(int n)
const char * particle
Definition: g_edict.h:128
#define MAX_IPFILTERS
Definition: g_svcmds.cpp:63
Interface for g_client.cpp.
Edict * G_EdictsGetNext(Edict *lastEnt)
Iterate through the list of entities.
Definition: g_edicts.cpp:107
int HP
Definition: g_edict.h:89