mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 14:20:59 +00:00
provide builtin mappings for id (none, really), qf and ktpro/qwe (qw only),
add qwe builtin extensions to qw-server. provide sv_progs_ext to control the builtin mapping. valid values are "id", "qf" (our old static builtins), "qwe"/"ktpro" (either works. for ktpro mod support) and "none" (no mapping). any other value is equivalent to "none".
This commit is contained in:
parent
d7592781d7
commit
133879f8fa
12 changed files with 739 additions and 42 deletions
|
@ -178,6 +178,23 @@ qboolean PR_EdictValid (progs_t *pr, int e);
|
|||
#define E_GSTRING(p,e,o) (PR_GetString (p, E_STRING (e, o)))
|
||||
#define E_DSTRING(p,e,o) (PR_GetDString (p, E_STRING (e, o)))
|
||||
|
||||
/*
|
||||
Builtins are arranged into groups of 65536 to allow for diffent expantion
|
||||
sets. eg, stock id is 0x0000xxxx, quakeforge is 0x000fxxxx. predefined
|
||||
groups go up to 0x0fffxxxx allowing 4096 different groups. Builtins
|
||||
0x10000000 to 0x7fffffff are reserved for auto-allocation. The range
|
||||
0x8000000 to 0xffffffff is unavailable due to the builtin number being
|
||||
a negative statement address.
|
||||
*/
|
||||
#define PR_RANGE_SHIFT 16
|
||||
#define PR_RANGE_MASK 0xffff0000
|
||||
|
||||
#define PR_RANGE_QF 0x000f
|
||||
|
||||
#define PR_RANGE_AUTO 0x1000
|
||||
#define PR_RANGE_NONE 0xffff
|
||||
#define PR_AUTOBUILTIN (PR_RANGE_AUTO << PR_RANGE_SHIFT)
|
||||
|
||||
typedef void (*builtin_proc) (progs_t *pr);
|
||||
typedef struct {
|
||||
const char *name;
|
||||
|
|
|
@ -592,6 +592,8 @@ PR_gametype (progs_t *pr)
|
|||
RETURN_STRING (pr, pr_gametype);
|
||||
}
|
||||
|
||||
#define QF (PR_RANGE_QF << PR_RANGE_SHIFT) |
|
||||
|
||||
static builtin_t builtins[] = {
|
||||
{"break", PF_break, 6},
|
||||
{"random", PF_random, 7},
|
||||
|
@ -617,15 +619,15 @@ static builtin_t builtins[] = {
|
|||
{"stof", PF_stof, 81},
|
||||
|
||||
|
||||
{"strlen", PF_strlen, 100},
|
||||
{"charcount", PF_charcount, 101},
|
||||
{"sprintf", PF_sprintf, 109},
|
||||
{"ftoi", PF_ftoi, 110},
|
||||
{"itof", PF_itof, 111},
|
||||
{"itos", PF_itos, 112},
|
||||
{"stoi", PF_stoi, 113},
|
||||
{"stov", PF_stov, 114},
|
||||
{"gametype", PR_gametype, 115},
|
||||
{"strlen", PF_strlen, QF 100},
|
||||
{"charcount", PF_charcount, QF 101},
|
||||
{"sprintf", PF_sprintf, QF 109},
|
||||
{"ftoi", PF_ftoi, QF 110},
|
||||
{"itof", PF_itof, QF 111},
|
||||
{"itos", PF_itos, QF 112},
|
||||
{"stoi", PF_stoi, QF 113},
|
||||
{"stov", PF_stov, QF 114},
|
||||
{"gametype", PR_gametype, QF 115},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
|
|
@ -54,16 +54,6 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
|
||||
#include "compat.h"
|
||||
|
||||
/*
|
||||
Builtins are arranged into groups of 65536 to allow for diffent expantion
|
||||
sets. eg, stock id is 0x0000xxxx, quakeforge is 0x000fxxxx. predefined
|
||||
groups go up to 0x0fffxxxx allowing 4096 different groups. Builtins
|
||||
0x10000000 to 0x7fffffff are reserved for auto-allocation. The range
|
||||
0x8000000 to 0xffffffff is unavailable due to the builtin number being
|
||||
a negative statement address.
|
||||
*/
|
||||
#define PR_AUTOBUILTIN 0x10000000
|
||||
|
||||
static const char *
|
||||
builtin_get_key (void *_bi, void *unused)
|
||||
{
|
||||
|
|
|
@ -187,6 +187,9 @@ typedef struct
|
|||
|
||||
extern sv_fields_t sv_fields;
|
||||
|
||||
#define PR_RANGE_ID 0x0000
|
||||
#define PR_RANGE_ID_MAX 82
|
||||
|
||||
#if TYPECHECK_PROGS
|
||||
#define SVFIELD(e,f,t) E_var (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__), t)
|
||||
#else
|
||||
|
|
|
@ -1351,6 +1351,8 @@ PF_checkextension (progs_t *pr)
|
|||
R_FLOAT (pr) = 0; // FIXME: make this function actually useful
|
||||
}
|
||||
|
||||
#define QF (PR_RANGE_QF << PR_RANGE_SHIFT) |
|
||||
|
||||
static builtin_t builtins[] = {
|
||||
{"makevectors", PF_makevectors, 1},
|
||||
{"setorigin", PF_setorigin, 2},
|
||||
|
@ -1397,12 +1399,12 @@ static builtin_t builtins[] = {
|
|||
{"precache_sound2", PF_precache_sound, 76},
|
||||
{"precache_file2", PF_precache_file, 77},
|
||||
{"setspawnparms", PF_setspawnparms, 78},
|
||||
{"hullpointcontents", PF_hullpointcontents, 93},
|
||||
{"getboxbounds", PF_getboxbounds, 94},
|
||||
{"getboxhull", PF_getboxhull, 95},
|
||||
{"freeboxhull", PF_freeboxhull, 96},
|
||||
{"rotate_bbox", PF_rotate_bbox, 97},
|
||||
{"checkextension", PF_checkextension, 99},
|
||||
{"hullpointcontents", PF_hullpointcontents, QF 93},
|
||||
{"getboxbounds", PF_getboxbounds, QF 94},
|
||||
{"getboxhull", PF_getboxhull, QF 95},
|
||||
{"freeboxhull", PF_freeboxhull, QF 96},
|
||||
{"rotate_bbox", PF_rotate_bbox, QF 97},
|
||||
{"checkextension", PF_checkextension, QF 99},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
#include "QF/cvar.h"
|
||||
#include "QF/quakefs.h"
|
||||
|
||||
#include "compat.h"
|
||||
#include "host.h"
|
||||
#include "server.h"
|
||||
#include "sv_progs.h"
|
||||
|
@ -55,6 +56,7 @@ sv_fields_t sv_fields;
|
|||
|
||||
cvar_t *sv_progs;
|
||||
cvar_t *sv_progs_zone;
|
||||
cvar_t *sv_progs_ext;
|
||||
cvar_t *pr_checkextensions;
|
||||
|
||||
cvar_t *nomonsters;
|
||||
|
@ -71,6 +73,22 @@ cvar_t *saved4;
|
|||
|
||||
func_t EndFrame;
|
||||
|
||||
static int sv_range;
|
||||
|
||||
static unsigned
|
||||
bi_map (progs_t *pr, unsigned binum)
|
||||
{
|
||||
unsigned range;
|
||||
|
||||
if (sv_range != PR_RANGE_NONE) {
|
||||
range = (binum & PR_RANGE_MASK) >> PR_RANGE_SHIFT;
|
||||
|
||||
if (!range && binum > PR_RANGE_ID_MAX)
|
||||
binum |= sv_range << PR_RANGE_SHIFT;
|
||||
}
|
||||
return binum;
|
||||
}
|
||||
|
||||
static int
|
||||
prune_edict (progs_t *pr, edict_t *ent)
|
||||
{
|
||||
|
@ -143,12 +161,25 @@ SV_LoadProgs (void)
|
|||
ddef_t *def;
|
||||
dfunction_t *f;
|
||||
const char *progs_name = "progs.dat";
|
||||
const char *range;
|
||||
|
||||
if (qfs_gamedir->gamecode && *qfs_gamedir->gamecode)
|
||||
progs_name = qfs_gamedir->gamecode;
|
||||
if (*sv_progs->string)
|
||||
progs_name = sv_progs->string;
|
||||
|
||||
if (strequal (sv_progs_ext->string, "qf")) {
|
||||
sv_range = PR_RANGE_QF;
|
||||
range = "QF";
|
||||
} else if (strequal (sv_progs_ext->string, "id")) {
|
||||
sv_range = PR_RANGE_ID;
|
||||
range = "ID";
|
||||
} else {
|
||||
sv_range = PR_RANGE_NONE;
|
||||
range = "None";
|
||||
}
|
||||
Con_DPrintf ("Using %s builtin extention mapping\n", range);
|
||||
|
||||
PR_LoadProgs (&sv_pr_state, progs_name, sv.max_edicts,
|
||||
sv_progs_zone->int_val * 1024);
|
||||
if (!sv_pr_state.progs)
|
||||
|
@ -342,6 +373,7 @@ SV_Progs_Init (void)
|
|||
sv_pr_state.unlink = SV_UnlinkEdict;
|
||||
sv_pr_state.parse_field = parse_field;
|
||||
sv_pr_state.prune_edict = prune_edict;
|
||||
sv_pr_state.bi_map = bi_map;
|
||||
|
||||
SV_PR_Cmds_Init ();
|
||||
|
||||
|
@ -362,6 +394,9 @@ SV_Progs_Init_Cvars (void)
|
|||
"Override the default game progs.");
|
||||
sv_progs_zone = Cvar_Get ("sv_progs_zone", "256", CVAR_NONE, NULL,
|
||||
"size of the zone for progs in kb");
|
||||
sv_progs_ext = Cvar_Get ("sv_progs_ext", "qf", CVAR_NONE, NULL,
|
||||
"extention mapping to use: "
|
||||
"none, id, qf");
|
||||
pr_checkextensions = Cvar_Get ("pr_checkextensions", "1", CVAR_ROM, NULL,
|
||||
"indicate the presence of the "
|
||||
"checkextentions qc function");
|
||||
|
|
36
qw/include/sv_pr_qwe.h
Normal file
36
qw/include/sv_pr_qwe.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
sv_pr_qwe.h
|
||||
|
||||
server side QuakeC builtins
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#ifndef __sv_pr_qwe_h
|
||||
#define __sv_pr_qwe_h
|
||||
|
||||
struct progs_s;
|
||||
|
||||
void SV_PR_QWE_Init (struct progs_s *pr);
|
||||
|
||||
#endif // __sv_pr_qwe_h
|
|
@ -176,6 +176,10 @@ extern sv_fields_t sv_fields;
|
|||
|
||||
extern struct progs_s sv_pr_state;
|
||||
|
||||
#define PR_RANGE_ID 0x0000
|
||||
#define PR_RANGE_ID_MAX 82
|
||||
#define PR_RANGE_QWE 0x0001
|
||||
|
||||
#if TYPECHECK_PROGS
|
||||
#define SVFIELD(e,f,t) E_var (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__), t)
|
||||
#else
|
||||
|
|
|
@ -70,8 +70,8 @@ EXTRA_DIST=sv_sys_win.c sv_sys_unix.c
|
|||
|
||||
libqw_server_a_SOURCES= \
|
||||
crudefile.c sv_ccmds.c sv_demo.c sv_ents.c sv_gib.c sv_init.c sv_main.c \
|
||||
sv_move.c sv_nchan.c sv_phys.c sv_pr_cmds.c sv_progs.c sv_send.c \
|
||||
sv_user.c world.c $(syssv_SRC)
|
||||
sv_move.c sv_nchan.c sv_phys.c sv_pr_cmds.c sv_pr_qwe.c sv_progs.c \
|
||||
sv_send.c sv_user.c world.c $(syssv_SRC)
|
||||
|
||||
qf_server_LIBS= \
|
||||
$(SERVER_PLUGIN_STATIC_LIBS) \
|
||||
|
|
|
@ -1912,6 +1912,8 @@ PR_SV_Spawn (progs_t *pr)
|
|||
SV_Spawn (cl);
|
||||
}
|
||||
|
||||
#define QF (PR_RANGE_QF << PR_RANGE_SHIFT) |
|
||||
|
||||
static builtin_t builtins[] = {
|
||||
{"makevectors", PF_makevectors, 1},
|
||||
{"setorigin", PF_setorigin, 2},
|
||||
|
@ -1974,22 +1976,22 @@ static builtin_t builtins[] = {
|
|||
{"logfrag", PF_logfrag, 79},
|
||||
{"infokey", PF_infokey, 80},
|
||||
{"multicast", PF_multicast, 82},
|
||||
{"testentitypos", PF_testentitypos, 92},
|
||||
{"hullpointcontents", PF_hullpointcontents, 93},
|
||||
{"getboxbounds", PF_getboxbounds, 94},
|
||||
{"getboxhull", PF_getboxhull, 95},
|
||||
{"freeboxhull", PF_freeboxhull, 96},
|
||||
{"rotate_bbox", PF_rotate_bbox, 97},
|
||||
{"testentitypos", PF_testentitypos, QF 92},
|
||||
{"hullpointcontents", PF_hullpointcontents, QF 93},
|
||||
{"getboxbounds", PF_getboxbounds, QF 94},
|
||||
{"getboxhull", PF_getboxhull, QF 95},
|
||||
{"freeboxhull", PF_freeboxhull, QF 96},
|
||||
{"rotate_bbox", PF_rotate_bbox, QF 97},
|
||||
|
||||
{"checkmove", PF_checkmove, 98},
|
||||
{"checkextension", PF_checkextension, 99},
|
||||
{"setinfokey", PF_setinfokey, 102},
|
||||
{"cfopen", PF_cfopen, 103},
|
||||
{"cfclose", PF_cfclose, 104},
|
||||
{"cfread", PF_cfread, 105},
|
||||
{"cfwrite", PF_cfwrite, 106},
|
||||
{"cfeof", PF_cfeof, 107},
|
||||
{"cfquota", PF_cfquota, 108},
|
||||
{"checkmove", PF_checkmove, QF 98},
|
||||
{"checkextension", PF_checkextension, QF 99},
|
||||
{"setinfokey", PF_setinfokey, QF 102},
|
||||
{"cfopen", PF_cfopen, QF 103},
|
||||
{"cfclose", PF_cfclose, QF 104},
|
||||
{"cfread", PF_cfread, QF 105},
|
||||
{"cfwrite", PF_cfwrite, QF 106},
|
||||
{"cfeof", PF_cfeof, QF 107},
|
||||
{"cfquota", PF_cfquota, QF 108},
|
||||
|
||||
{"SV_AllocClient", PF_SV_AllocClient, -1},
|
||||
{"SV_FreeClient", PF_SV_FreeClient, -1},
|
||||
|
|
566
qw/source/sv_pr_qwe.c
Normal file
566
qw/source/sv_pr_qwe.c
Normal file
|
@ -0,0 +1,566 @@
|
|||
/*
|
||||
sv_pr_qwe.c
|
||||
|
||||
qwe extentions needed by the KTPro mod
|
||||
|
||||
Copyright (C) 2003 Bill Currie
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2003/11/17
|
||||
|
||||
taken from qwe (actual author currently unkown, probably
|
||||
`highlander') and ported to qf
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((unused))
|
||||
const char rcsid[] = "$Id$";
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "QF/cbuf.h"
|
||||
#include "QF/cmd.h"
|
||||
#include "QF/dstring.h"
|
||||
#include "QF/idparse.h"
|
||||
#include "QF/progs.h"
|
||||
#include "QF/quakefs.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
#include "sv_demo.h"
|
||||
#include "sv_pr_qwe.h"
|
||||
#include "sv_progs.h"
|
||||
|
||||
typedef struct {
|
||||
func_t timeofday;
|
||||
func_t ConsoleCmd;
|
||||
func_t UserCmd;
|
||||
} qwe_funcs_t;
|
||||
|
||||
static qwe_funcs_t qwe_funcs;
|
||||
|
||||
static void
|
||||
PF_executecmd (progs_t * pr)
|
||||
{
|
||||
int old_other, old_self; // mod_consolecmd will be executed, so
|
||||
// we need to store these
|
||||
|
||||
old_self = *sv_globals.self;
|
||||
old_other = *sv_globals.other;
|
||||
|
||||
Cbuf_Execute (sv_cbuf);
|
||||
|
||||
*sv_globals.self = old_self;
|
||||
*sv_globals.other = old_other;
|
||||
}
|
||||
|
||||
/*
|
||||
PF_tokanize
|
||||
|
||||
tokanize string
|
||||
|
||||
void tokanize(string)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_tokanize (progs_t * pr)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
str = P_GSTRING (pr, 0);
|
||||
COM_TokenizeString (str, sv_args);
|
||||
cmd_args = sv_args;
|
||||
}
|
||||
|
||||
/*
|
||||
PF_argc
|
||||
|
||||
returns number of tokens (must be executed after PF_Tokanize!)
|
||||
|
||||
float argc(void)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_argc (progs_t * pr)
|
||||
{
|
||||
R_FLOAT (pr) = (float) Cmd_Argc ();
|
||||
}
|
||||
|
||||
/*
|
||||
PF_argv
|
||||
|
||||
returns token requested by user (must be executed after PF_Tokanize!)
|
||||
|
||||
string argc(float)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_argv (progs_t * pr)
|
||||
{
|
||||
int num;
|
||||
|
||||
num = (int) P_FLOAT (pr, 0);
|
||||
|
||||
if (num < 0)
|
||||
num = 0;
|
||||
if (num > Cmd_Argc () - 1)
|
||||
num = Cmd_Argc () - 1;
|
||||
|
||||
RETURN_STRING (pr, Cmd_Argv (num));
|
||||
}
|
||||
|
||||
/*
|
||||
PF_teamfield
|
||||
|
||||
string teamfield(.string field)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_teamfield (progs_t * pr)
|
||||
{
|
||||
sv_fields.team_str = P_INT (pr, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
PF_substr
|
||||
|
||||
string substr(string str, float start, float len)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_substr (progs_t * pr)
|
||||
{
|
||||
const char *s;
|
||||
char *tmp;
|
||||
int start, len, l;
|
||||
|
||||
s = P_GSTRING (pr, 0);
|
||||
start = (int) P_FLOAT (pr, 1);
|
||||
len = (int) P_FLOAT (pr, 2);
|
||||
l = strlen (s);
|
||||
|
||||
if (start >= l || !len || !*s) {
|
||||
R_STRING (pr) = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
s += start;
|
||||
l -= start;
|
||||
|
||||
if (len > l + 1)
|
||||
len = l + 1;
|
||||
|
||||
tmp = Hunk_TempAlloc (len);
|
||||
strncpy (tmp, s, len - 1);
|
||||
tmp[len] = 0;
|
||||
|
||||
RETURN_STRING (pr, tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
PF_strcat
|
||||
|
||||
string strcat(string str1, string str2)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_strcat (progs_t * pr)
|
||||
{
|
||||
RETURN_STRING (pr, PF_VarString (pr, 0));
|
||||
}
|
||||
|
||||
/*
|
||||
PF_strlen
|
||||
|
||||
float strlen(string str)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_strlen (progs_t * pr)
|
||||
{
|
||||
R_FLOAT (pr) = (float) strlen (P_GSTRING (pr, 0));
|
||||
}
|
||||
|
||||
/*
|
||||
PF_str2byte
|
||||
|
||||
float str2byte (string str)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_str2byte (progs_t * pr)
|
||||
{
|
||||
R_FLOAT (pr) = (float) *P_GSTRING (pr, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
PF_str2short
|
||||
|
||||
float str2short (string str)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_str2short (progs_t * pr)
|
||||
{
|
||||
const unsigned char *str = P_GSTRING (pr, 0);
|
||||
|
||||
R_FLOAT (pr) = (short) ((str[1] << 8) | str[0]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
PF_newstr
|
||||
|
||||
string newstr (string str [, float size])
|
||||
|
||||
ignores size (there for compatability with qwe)
|
||||
*/
|
||||
static void
|
||||
PF_newstr (progs_t * pr)
|
||||
{
|
||||
const char *s;
|
||||
dstring_t *dstr;
|
||||
int i;
|
||||
|
||||
s = P_GSTRING (pr, 0);
|
||||
|
||||
i = PR_NewString (pr);
|
||||
dstr = PR_GetDString (pr, i);
|
||||
|
||||
dstring_copystr (dstr, s);
|
||||
|
||||
R_STRING (pr) = i;
|
||||
}
|
||||
|
||||
/*
|
||||
PF_frestr
|
||||
|
||||
void freestr (string str)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_freestr (progs_t * pr)
|
||||
{
|
||||
PR_FreeString (pr, P_STRING (pr, 0));
|
||||
}
|
||||
|
||||
/*
|
||||
PF_readcmd
|
||||
|
||||
string readmcmd (string str)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_readcmd (progs_t *pr)
|
||||
{
|
||||
const char *s;
|
||||
redirect_t old;
|
||||
|
||||
s = P_GSTRING (pr, 0);
|
||||
|
||||
Cbuf_Execute (sv_cbuf);
|
||||
Cbuf_AddText (sv_cbuf, s);
|
||||
|
||||
old = sv_redirected;
|
||||
if (old != RD_NONE)
|
||||
SV_EndRedirect ();
|
||||
|
||||
SV_BeginRedirect (RD_MOD);
|
||||
Cbuf_Execute (sv_cbuf);
|
||||
RETURN_STRING (pr, outputbuf.str);
|
||||
SV_EndRedirect ();
|
||||
|
||||
if (old != RD_NONE)
|
||||
SV_BeginRedirect (old);
|
||||
}
|
||||
|
||||
/*
|
||||
PF_redirectcmd
|
||||
|
||||
void redirectcmd (entity to, string str)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_redirectcmd (progs_t *pr)
|
||||
{
|
||||
const char *s;
|
||||
int entnum;
|
||||
extern redirect_t sv_redirected;
|
||||
|
||||
if (sv_redirected)
|
||||
return;
|
||||
|
||||
entnum = P_EDICTNUM (pr, 0);
|
||||
if (entnum < 1 || entnum > MAX_CLIENTS)
|
||||
PR_RunError (pr, "Parm 0 not a client");
|
||||
|
||||
s = P_GSTRING (pr, 1);
|
||||
|
||||
Cbuf_AddText (sv_cbuf, s);
|
||||
|
||||
SV_BeginRedirect (RD_MOD + entnum);
|
||||
Cbuf_Execute (sv_cbuf);
|
||||
SV_EndRedirect ();
|
||||
}
|
||||
|
||||
static void
|
||||
PF_calltimeofday (progs_t * pr)
|
||||
{
|
||||
date_t date;
|
||||
dfunction_t *f;
|
||||
|
||||
if ((f = ED_FindFunction (pr, "timeofday")) != NULL) {
|
||||
|
||||
Sys_TimeOfDay (&date);
|
||||
|
||||
PR_PushFrame (&sv_pr_state);
|
||||
P_FLOAT (pr, 0) = (float) date.sec;
|
||||
P_FLOAT (pr, 1) = (float) date.min;
|
||||
P_FLOAT (pr, 2) = (float) date.hour;
|
||||
P_FLOAT (pr, 3) = (float) date.day;
|
||||
P_FLOAT (pr, 4) = (float) date.mon;
|
||||
P_FLOAT (pr, 5) = (float) date.year;
|
||||
P_STRING (pr, 6) = PR_SetTempString (pr, date.str);
|
||||
|
||||
PR_ExecuteProgram (pr, (func_t) (f - sv_pr_state.pr_functions));
|
||||
PR_PopFrame (&sv_pr_state);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
PF_forcedemoframe
|
||||
|
||||
void PF_forcedemoframe(float now)
|
||||
Forces demo frame
|
||||
if argument 'now' is set, frame is written instantly
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_forcedemoframe (progs_t * pr)
|
||||
{
|
||||
demo.forceFrame = 1;
|
||||
if (P_FLOAT (pr, 0) == 1)
|
||||
SV_SendDemoMessage ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
PF_strcpy
|
||||
|
||||
void strcpy(string dst, string src)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_strcpy (progs_t * pr)
|
||||
{
|
||||
dstring_copystr (P_DSTRING (pr, 0), P_GSTRING (pr, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
PF_strncpy
|
||||
|
||||
void strcpy(string dst, string src, float count)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_strncpy (progs_t * pr)
|
||||
{
|
||||
dstring_t *dst = P_DSTRING (pr, 0);
|
||||
const char *src = P_GSTRING (pr, 1);
|
||||
size_t count = P_FLOAT (pr, 2);
|
||||
|
||||
dst->size = count;
|
||||
dstring_adjust (dst);
|
||||
strncpy (dst->str, src, count);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
PF_strstr
|
||||
|
||||
string strstr(string str, string sub)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_strstr (progs_t * pr)
|
||||
{
|
||||
const char *str, *sub, *p;
|
||||
|
||||
str = P_GSTRING (pr, 0);
|
||||
sub = P_GSTRING (pr, 1);
|
||||
|
||||
if ((p = strstr (str, sub)) == NULL) {
|
||||
R_STRING (pr) = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
R_STRING (pr) = p - pr->pr_strings;
|
||||
}
|
||||
|
||||
static inline void
|
||||
clean_text (unsigned char *text)
|
||||
{
|
||||
while (*text) {
|
||||
*text = sys_char_map[*text];
|
||||
text++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
PF_log
|
||||
|
||||
void log(string name, float console, string text)
|
||||
*/
|
||||
|
||||
static void
|
||||
PF_log (progs_t * pr)
|
||||
{
|
||||
const char *name;
|
||||
char *text;
|
||||
QFile *file;
|
||||
|
||||
name = va ("%s/%s.log", qfs_gamedir->dir.def, P_GSTRING (pr, 0));
|
||||
file = QFS_Open (name, "a");
|
||||
|
||||
text = PF_VarString (pr, 2);
|
||||
clean_text (text);
|
||||
|
||||
if (P_FLOAT (pr, 1))
|
||||
Sys_Printf ("%s", text);
|
||||
|
||||
if (!file) {
|
||||
Sys_Printf ("coldn't open log file %s\n", name);
|
||||
} else {
|
||||
Qputs (file, text);
|
||||
Qflush (file);
|
||||
Qclose (file);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
PF_conprint
|
||||
*/
|
||||
static void
|
||||
PF_conprint (progs_t * pr)
|
||||
{
|
||||
Con_Printf ("%s", PF_VarString (pr, 0));
|
||||
}
|
||||
|
||||
#define QWE (PR_RANGE_QWE << PR_RANGE_SHIFT) |
|
||||
|
||||
static builtin_t builtins[] = {
|
||||
{"QWE:executecmd", PF_executecmd, QWE 83},
|
||||
{"QWE:tokanize" /* sic */, PF_tokanize, QWE 84},
|
||||
{"QWE:argc", PF_argc, QWE 85},
|
||||
{"QWE:argv", PF_argv, QWE 86},
|
||||
{"QWE:teamfield", PF_teamfield, QWE 87},
|
||||
{"QWE:substr", PF_substr, QWE 88},
|
||||
{"QWE:strcat", PF_strcat, QWE 89},
|
||||
{"QWE:strlen", PF_strlen, QWE 90},
|
||||
{"QWE:str2byte", PF_str2byte, QWE 91},
|
||||
{"QWE:str2short", PF_str2short, QWE 92},
|
||||
{"QWE:newstr", PF_newstr, QWE 93},
|
||||
{"QWE:freestr", PF_freestr, QWE 94},
|
||||
{"QWE:conprint", PF_conprint, QWE 95},
|
||||
{"QWE:readcmd", PF_readcmd, QWE 96},
|
||||
{"QWE:strcpy", PF_strcpy, QWE 97},
|
||||
{"QWE:strstr", PF_strstr, QWE 98},
|
||||
{"QWE:strncpy", PF_strncpy, QWE 99},
|
||||
{"QWE:log", PF_log, QWE 100},
|
||||
{"QWE:redirectcmd", PF_redirectcmd, QWE 101},
|
||||
{"QWE:calltimeofday", PF_calltimeofday, QWE 102},
|
||||
{"QWE:forceddemoframe", PF_forcedemoframe, QWE 103},
|
||||
};
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
int *field;
|
||||
} qwe_func_list[] = {
|
||||
{"timeofday", &qwe_funcs.timeofday},
|
||||
{"ConsoleCmd", &qwe_funcs.ConsoleCmd},
|
||||
{"UserCmd", &qwe_funcs.UserCmd},
|
||||
{"localinfoChanged", &sv_funcs.LocalinfoChanged},
|
||||
{"UserInfo_Changed", &sv_funcs.UserInfoChanged},
|
||||
{"ChatMessage", &sv_funcs.ChatMessage},
|
||||
};
|
||||
|
||||
static int
|
||||
qwe_console_cmd (void)
|
||||
{
|
||||
if (qwe_funcs.ConsoleCmd) {
|
||||
if (sv_redirected != RD_MOD) {
|
||||
*sv_globals.time = sv.time;
|
||||
*sv_globals.self = 0;
|
||||
}
|
||||
PR_ExecuteProgram (&sv_pr_state, qwe_funcs.ConsoleCmd);
|
||||
return (int) R_FLOAT (&sv_pr_state);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
qwe_user_cmd (void)
|
||||
{
|
||||
if (qwe_funcs.UserCmd) {
|
||||
if (sv_redirected != RD_MOD) {
|
||||
*sv_globals.time = sv.time;
|
||||
*sv_globals.self = EDICT_TO_PROG(&sv_pr_state, sv_player);
|
||||
}
|
||||
PR_ExecuteProgram (&sv_pr_state, qwe_funcs.UserCmd);
|
||||
return (int) R_FLOAT (&sv_pr_state);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
qwe_load (progs_t * pr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof (qwe_func_list) / sizeof (qwe_func_list[0]); i++) {
|
||||
dfunction_t *f = ED_FindFunction (pr, qwe_func_list[i].name);
|
||||
|
||||
*qwe_func_list[i].field = 0;
|
||||
if (f)
|
||||
*qwe_func_list[i].field = (func_t) (f - pr->pr_functions);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
SV_PR_QWE_Init (progs_t *pr)
|
||||
{
|
||||
PR_RegisterBuiltins (pr, builtins);
|
||||
PR_AddLoadFunc (pr, qwe_load);
|
||||
|
||||
sv_cbuf->unknown_command = qwe_console_cmd;
|
||||
ucmd_unknown = qwe_user_cmd;
|
||||
}
|
|
@ -43,6 +43,7 @@
|
|||
#include "compat.h"
|
||||
#include "server.h"
|
||||
#include "sv_progs.h"
|
||||
#include "sv_pr_qwe.h"
|
||||
#include "world.h"
|
||||
|
||||
sv_globals_t sv_globals;
|
||||
|
@ -53,12 +54,29 @@ progs_t sv_pr_state;
|
|||
cvar_t *r_skyname;
|
||||
cvar_t *sv_progs;
|
||||
cvar_t *sv_progs_zone;
|
||||
cvar_t *sv_progs_ext;
|
||||
cvar_t *pr_checkextensions;
|
||||
cvar_t *sv_old_entity_free;
|
||||
cvar_t *sv_hide_version_info;
|
||||
|
||||
static int reserved_edicts = MAX_CLIENTS;
|
||||
|
||||
static int sv_range;
|
||||
|
||||
static unsigned
|
||||
bi_map (progs_t *pr, unsigned binum)
|
||||
{
|
||||
unsigned range;
|
||||
|
||||
if (sv_range != PR_RANGE_NONE) {
|
||||
range = (binum & PR_RANGE_MASK) >> PR_RANGE_SHIFT;
|
||||
|
||||
if (!range && binum > PR_RANGE_ID_MAX)
|
||||
binum |= sv_range << PR_RANGE_SHIFT;
|
||||
}
|
||||
return binum;
|
||||
}
|
||||
|
||||
static void
|
||||
free_edict (progs_t *pr, edict_t *ent)
|
||||
{
|
||||
|
@ -162,9 +180,26 @@ SV_LoadProgs (void)
|
|||
ddef_t *def;
|
||||
dfunction_t *f;
|
||||
const char *progs_name = "qwprogs.dat";
|
||||
const char *range;
|
||||
|
||||
memset (&sv_funcs, 0, sizeof (sv_funcs));
|
||||
|
||||
if (strequal (sv_progs_ext->string, "qf")) {
|
||||
sv_range = PR_RANGE_QF;
|
||||
range = "QF";
|
||||
} else if (strequal (sv_progs_ext->string, "id")) {
|
||||
sv_range = PR_RANGE_ID;
|
||||
range = "ID";
|
||||
} else if (strequal (sv_progs_ext->string, "qwe")
|
||||
|| strequal (sv_progs_ext->string, "ktpro")) {
|
||||
sv_range = PR_RANGE_QWE;
|
||||
range = "QWE/KTPro";
|
||||
} else {
|
||||
sv_range = PR_RANGE_NONE;
|
||||
range = "None";
|
||||
}
|
||||
Con_DPrintf ("Using %s builtin extention mapping\n", range);
|
||||
|
||||
if (qfs_gamedir->gamecode && *qfs_gamedir->gamecode)
|
||||
progs_name = qfs_gamedir->gamecode;
|
||||
if (*sv_progs->string)
|
||||
|
@ -351,9 +386,11 @@ SV_Progs_Init (void)
|
|||
sv_pr_state.parse_field = parse_field;
|
||||
sv_pr_state.prune_edict = prune_edict;
|
||||
sv_pr_state.free_edict = free_edict; // eww, I hate the need for this :(
|
||||
sv_pr_state.bi_map = bi_map;
|
||||
|
||||
PR_Resources_Init (&sv_pr_state);
|
||||
SV_PR_Cmds_Init ();
|
||||
SV_PR_QWE_Init (&sv_pr_state);
|
||||
Cmd_Progs_Init (&sv_pr_state);
|
||||
Hash_Progs_Init (&sv_pr_state);
|
||||
|
||||
|
@ -376,6 +413,9 @@ SV_Progs_Init_Cvars (void)
|
|||
"Override the default game progs.");
|
||||
sv_progs_zone = Cvar_Get ("sv_progs_zone", "256", CVAR_NONE, NULL,
|
||||
"size of the zone for progs in kb");
|
||||
sv_progs_ext = Cvar_Get ("sv_progs_ext", "qf", CVAR_NONE, NULL,
|
||||
"extention mapping to use: "
|
||||
"none, id, qf, qwe, ktpro");
|
||||
pr_checkextensions = Cvar_Get ("pr_checkextensions", "1", CVAR_ROM, NULL,
|
||||
"indicate the presence of the "
|
||||
"checkextentions qc function");
|
||||
|
|
Loading…
Reference in a new issue