allow mnemonics for execution context levels

scriptcontext and isolatecontext now allow plain text mnemonics for
context level arguments (one of CORE, CFG, PROMPT, MAPCFG, MDLCFG)

also:

- cleanup (some dead code and dead prototypes removed)
- some stuff renamed
- script errors now show context levels
- conc is no longer thread-safe (but slightly faster)

DOCREF scriptcontext isolatecontext
This commit is contained in:
ac-stef
2017-05-18 16:19:01 +02:00
parent ec2cdb4533
commit 2f99b368f0
12 changed files with 108 additions and 178 deletions
+1
View File
@@ -162,6 +162,7 @@ if (! (checkalias cmcur)) [ // execute this only once
newmenu "List licenses and mapmessages"
menuinit [
resetcurmenu
menusynctabstops 1
looplist (enumalias __convmaplicenses__) [mx m] [
menuitem (concatword $$mx "\t" $m) (concat cmpickmap $m)
]
+17 -12
View File
@@ -1,24 +1,29 @@
// define script security contexts to restrict commands to certain contexts
// do NOT modify
// supported contexts
const context_core 0 // hardcoded scripts
const context_cfg 1 // known scripts
const context_prompt 2 // command prompt
const context_mapcfg 3 // map configs, we don't trust them
const context_mdlcfg 4 // mdl configs, same
// supported contexts: CORE (hardcoded scripts), CFG (known scripts), PROMPT (command prompt),
// MAPCFG (map config files, we don't trust them), MDLCFG (model config files, same)
// set allowed commands for the map config context
mapcfgidents = [loadnotexture loadsky mapmodelreset mapmodel texturereset texture fog fogcolour mapsoundreset mapsound watercolour shadowyaw]
mdlcfgidents = [md2anim md2emit md2tag md3anim md3emit md3link md3load md3skin mdlalphatest mdlalphablend mdlcachelimit mdlcullface mdlscale mdlshadowdist mdltrans mdltranslucent mdlvertexlight mdlattribute]
loop i (listlen $mapcfgidents) [ scriptcontext $context_mapcfg (at $mapcfgidents $i) ]
loop i (listlen $mdlcfgidents) [ scriptcontext $context_mdlcfg (at $mdlcfgidents $i) ]
looplist [
loadnotexture loadsky fog fogcolour watercolour shadowyaw
mapmodelreset mapmodel texturereset texture mapsoundreset mapsound
] s [
scriptcontext MAPCFG $s
]
looplist [
md2anim md2emit md2tag
md3anim md3emit md3link md3load md3skin
mdlalphatest mdlalphablend mdlcachelimit mdlcullface mdlscale mdlshadowdist mdltrans mdltranslucent mdlvertexlight mdlattribute
] s [
scriptcontext MDLCFG $s
]
// isolate the map config context
// this disables access from this context to identifiers located in other contexts
// also it removes all aliases created in this context once the running context changes
isolatecontext $context_mapcfg
isolatecontext $context_mdlcfg
isolatecontext MAPCFG
isolatecontext MDLCFG
// secure this configuration for the rest of the game
sealcontexts
+2
View File
@@ -648,7 +648,9 @@ void audiomanager::updateaudio()
{
char *cmd = musicdonecmd;
musicdonecmd = NULL;
setcontext("hook", "musicdonecmd");
execute(cmd);
resetcontext();
delete[] cmd;
}
}
+3 -3
View File
@@ -544,8 +544,8 @@ void parsemessages(int cn, playerent *d, ucharbuf &p, bool demo = false)
case SV_ITEMLIST:
{
int n;
resetspawns();
while((n = getint(p))!=-1) setspawn(n, true);
resetpickups();
while((n = getint(p))!=-1) setpickupspawn(n, true);
break;
}
@@ -906,7 +906,7 @@ void parsemessages(int cn, playerent *d, ucharbuf &p, bool demo = false)
case SV_ITEMSPAWN:
{
int i = getint(p);
setspawn(i, true);
setpickupspawn(i, true);
break;
}
+68 -58
View File
@@ -3,14 +3,10 @@
#include "cube.h"
bool allowidentaccess(ident *id);
inline bool identaccessdenied(ident *id);
char *exchangestr(char *o, const char *n) { delete[] o; return newstring(n); }
vector<const char *> executionstack; // keep history of recursive command execution (to write to log in case of a crash)
vector<int> contextstack;
bool contextsealed = false;
bool contextisolated[IEXC_NUM] = { false };
int execcontext;
char *commandret = NULL;
bool loop_break = false, loop_skip = false; // break or continue (skip) current loop
@@ -76,7 +72,7 @@ ident *newident(const char *name, int context = execcontext)
void pusha(const char *name, char *action)
{
ident *id = newident(name, execcontext);
if(contextisolated[execcontext] && execcontext > id->context)
if(identaccessdenied(id))
{
conoutf("cannot redefine alias %s in this execution context", id->name);
scripterr();
@@ -95,7 +91,7 @@ void pop(const char *name)
{
ident *id = idents->access(name);
if(!id) return;
if(contextisolated[execcontext] && execcontext > id->context)
if(identaccessdenied(id))
{
conoutf("cannot redefine alias %s in this execution context", id->name);
scripterr();
@@ -118,7 +114,7 @@ void delalias(const char *name)
{
ident *id = idents->access(name);
if(!id || id->type != ID_ALIAS) return;
if(contextisolated[execcontext] && execcontext > id->context)
if(identaccessdenied(id))
{
conoutf("cannot remove alias %s in this execution context", id->name);
scripterr();
@@ -141,7 +137,7 @@ void alias(const char *name, const char *action, bool temp, bool constant)
}
else if(b->type==ID_ALIAS)
{
if(contextisolated[execcontext] && execcontext > b->context)
if(identaccessdenied(b))
{
conoutf("cannot redefine alias %s in this execution context", b->name);
scripterr();
@@ -232,7 +228,7 @@ void modifyvar(const char *name, int arg, char op)
{
ident *id = idents->access(name);
if(!id) return;
if(!allowidentaccess(id))
if(identaccessdenied(id))
{
conoutf("not allowed in this execution context: %s", id->name);
scripterr();
@@ -269,7 +265,7 @@ void modifyfvar(const char *name, float arg, char op)
{
ident *id = idents->access(name);
if(!id) return;
if(!allowidentaccess(id))
if(identaccessdenied(id))
{
conoutf("not allowed in this execution context: %s", id->name);
scripterr();
@@ -489,16 +485,20 @@ char *conc(const char **w, int n, bool space)
n = 0;
while(w[n] && w[n][0]) n++;
}
static vector<int> wlen;
wlen.setsize(0);
int len = space ? max(n-1, 0) : 0;
loopj(n) len += (int)strlen(w[j]);
char *r = newstring("", len);
loopj(n) len += wlen.add((int)strlen(w[j]));
char *r = newstring("", len), *res = r;
loopi(n)
{
strcat(r, w[i]); // make string-list out of all arguments
if(i == n - 1) break;
if(space) strcat(r, " ");
strncpy(r, w[i], wlen[i]); // make string-list out of all arguments
r += wlen[i];
if(space) *r++ = ' ';
}
return r;
if(space) --r;
*r = '\0';
return res;
}
VARN(numargs, _numargs, 25, 0, 0);
@@ -586,7 +586,7 @@ char *executeret(const char *p) // all evaluation hap
}
setretval(newstring(c));
}
else if(!allowidentaccess(id))
else if(identaccessdenied(id))
{
conoutf("not allowed in this execution context: %s", id->name);
scripterr();
@@ -978,36 +978,6 @@ void complete(char *s, bool reversedirection)
}
#endif
const char *curcontext = NULL, *curinfo = NULL;
void scripterr()
{
if(curcontext) conoutf("(%s: %s)", curcontext, curinfo);
else conoutf("(from console or builtin)");
}
void setcontext(const char *context, const char *info)
{
curcontext = context;
curinfo = info;
}
void resetcontext()
{
curcontext = curinfo = NULL;
}
void dumpexecutionstack(stream *f)
{
if(f && executionstack.length())
{
f->printf("cubescript execution stack (%d levels)\n", executionstack.length());
if(curcontext) f->printf(" cubescript context: %s %s\n", curcontext, curinfo ? curinfo : "");
loopvrev(executionstack) f->printf("%4d: %s\n", i + 1, executionstack[i]);
f->fflush();
}
}
bool execfile(const char *cfgfile)
{
string s;
@@ -1665,6 +1635,14 @@ void identnames(vector<const char *> &names, bool builtinonly)
});
}
// script execution context management
const char *contextnames[IEXC_NUM + 1] = { "CORE", "CFG", "PROMPT", "MAPCFG", "MDLCFG", "" };
bool contextisolated[IEXC_NUM] = { false };
bool contextsealed = false;
vector<int> contextstack;
int execcontext;
void pushscontext(int newcontext)
{
contextstack.add(execcontext);
@@ -1697,30 +1675,62 @@ int popscontext()
return execcontext;
}
void scriptcontext(int *context, char *idname)
void scriptcontext(char *context, char *idname)
{
if(contextsealed) return;
ident *id = idents->access(idname);
if(!id) return;
int c = *context;
int c = getlistindex(context, contextnames, true, -1);
if(c >= 0 && c < IEXC_NUM) id->context = c;
}
COMMAND(scriptcontext, "is");
COMMAND(scriptcontext, "ss");
void isolatecontext(int *context)
void isolatecontext(char *context)
{
if(*context >= 0 && *context < IEXC_NUM && !contextsealed) contextisolated[*context] = true;
int c = getlistindex(context, contextnames, true, -1);
if(c >= 0 && c < IEXC_NUM && !contextsealed) contextisolated[c] = true;
}
COMMAND(isolatecontext, "i");
COMMAND(isolatecontext, "s");
COMMANDF(sealcontexts, "",() { contextsealed = true; });
bool allowidentaccess(ident *id) // check if ident is allowed in current context
inline bool identaccessdenied(ident *id) // check if ident is allowed in current context
{
ASSERT(execcontext >= 0 && execcontext < IEXC_NUM && id);
return contextisolated[execcontext] && execcontext > id->context;
}
// script origin tracking
const char *curcontext = NULL, *curinfo = NULL;
void scripterr()
{
ASSERT(execcontext >= 0 && execcontext < IEXC_NUM);
if(!id) return false;
if(!contextisolated[execcontext]) return true; // only check if context is isolated
return execcontext <= id->context;
if(curcontext) conoutf("(%s: %s [%s])", curcontext, curinfo, contextnames[execcontext]);
else conoutf("(from console or builtin [%s])", contextnames[execcontext]);
}
void setcontext(const char *context, const char *info)
{
curcontext = context;
curinfo = info;
}
void resetcontext()
{
curcontext = curinfo = NULL;
}
void dumpexecutionstack(stream *f)
{
if(f && executionstack.length())
{
f->printf("cubescript execution stack (%d levels)\n", executionstack.length());
if(curcontext) f->printf(" cubescript context: %s %s\n", curcontext, curinfo ? curinfo : "");
loopvrev(executionstack) f->printf("%4d: %s\n", i + 1, executionstack[i]);
f->fflush();
}
}
#ifndef STANDALONE
+2 -11
View File
@@ -479,16 +479,7 @@ void checkitems(playerent *d)
}
}
void spawnallitems() // spawns items locally
{
loopv(ents) if(ents[i].fitsmode(gamemode) || (multiplayer(NULL) && gamespeed!=100 && (i=-1)))
{
ents[i].spawned = true;
ents[i].lastmillis = lastmillis;
}
}
void resetspawns(int type)
void resetpickups(int type)
{
loopv(ents) if(type < 0 || type == ents[i].type) ents[i].spawned = false;
if(m_noitemsnade || m_pistol)
@@ -497,7 +488,7 @@ void resetspawns(int type)
}
}
void setspawn(int i, bool on)
void setpickupspawn(int i, bool on)
{
if(ents.inrange(i))
{
+2
View File
@@ -37,7 +37,9 @@ void quit() // normal exit
{
if(clientlogfile) clientlogfile->fflush();
const char *onquit = getalias("onQuit");
setcontext("hook", "onQuit");
if(onquit && onquit[0]) execute(onquit);
resetcontext();
alias("onQuit", "");
alias("mapstartonce", "");
extern void writeinitcfg();
+13 -50
View File
@@ -267,7 +267,6 @@ struct mline { string name, cmd; };
// serverbrowser
extern void addserver(const char *servername, int serverport, int weight);
extern char *getservername(int n);
extern bool resolverwait(const char *name, ENetAddress *address);
extern int connectwithtimeout(ENetSocket sock, const char *hostname, ENetAddress &remoteaddress);
extern void writeservercfg();
@@ -378,7 +377,6 @@ extern void resetcamera();
extern void gl_checkextensions();
extern void gl_init(int w, int h, int bpp, int depth, int fsaa);
extern void cleangl();
extern void enablepolygonoffset(GLenum type);
extern void disablepolygonoffset(GLenum type, bool restore = true);
extern void line(int x1, int y1, float z1, int x2, int y2, float z2);
@@ -432,7 +430,6 @@ extern Texture *lookuptexture(int tex, Texture *failtex = notexture, bool trydl
extern const char *gettextureslot(int i);
extern bool reloadtexture(Texture &t);
extern void reloadtextures();
extern void blitsurface(SDL_Surface *dst, SDL_Surface *src, int x, int y);
extern bool loadskymap(bool reload);
extern void *texconfig_copy();
extern void texconfig_delete(void *s);
@@ -444,6 +441,13 @@ static inline Texture *lookupworldtexture(int tex, bool trydl = true)
extern float skyfloor;
extern void draw_envbox(int fogdist);
extern int maxtmus;
extern void inittmus();
extern void resettmu(int n);
extern void scaletmu(int n, int rgbscale, int alphascale = 0);
extern void colortmu(int n, float r = 0, float g = 0, float b = 0, float a = 0);
extern void setuptmu(int n, const char *rgbfunc = NULL, const char *alphafunc = NULL);
// renderhud
enum
{
@@ -468,13 +472,6 @@ extern int downloadpackages(bool loadscr = true);
extern void sortpckservers();
extern void writepcksourcecfg();
extern int maxtmus;
extern void inittmus();
extern void resettmu(int n);
extern void scaletmu(int n, int rgbscale, int alphascale = 0);
extern void colortmu(int n, float r = 0, float g = 0, float b = 0, float a = 0);
extern void setuptmu(int n, const char *rgbfunc = NULL, const char *alphafunc = NULL);
struct zone { int x1, x2, y1, y2, color; }; // zones (drawn on the minimap)
// rendercubes
@@ -520,13 +517,9 @@ extern int getbuildtype();
extern void sendintro();
extern void getdemo(int *idx, char *dsp);
extern void listdemos();
//extern bool tryauth(const char *desc);
//extern authkey *findauthkey(const char *desc);
// serverms
bool requestmasterf(const char *fmt, ...); // for AUTH et al
//moving to server.cpp seems a bad idea.
// :for AUTH
// clientgame
extern flaginfo flaginfos[2];
@@ -572,11 +565,9 @@ extern void flagdropped(int flag, float x, float y, float z);
extern void flaginbase(int flag);
extern void flagidle(int flag);
extern void flagmsg(int flag, int message, int actor, int flagtime);
extern void arenarespawn();
extern bool tryrespawn();
extern void gotoplayerstart(playerent *d, entity *e);
extern void findplayerstart(playerent *d, bool mapcenter = false, int arenaspawn = -1);
extern void serveropcommand(int cmd, int arg1);
extern void refreshsopmenu(void *menu, bool init);
extern char *colorname(playerent *d, char *name = NULL, const char *prefix = "");
extern char *colorping(int ping);
@@ -651,7 +642,6 @@ extern void blockpaste(const block &b, int bx, int by, bool light, uchar *texmap
extern void blockpaste(const block &b);
extern void freeblockp(block *b);
extern void freeblock(block *&b);
extern block *duplicateblock(const block *s);
// worldrender
extern void render_world(float vx, float vy, float vh, float changelod, int yaw, int pitch, float fov, float fovy, int w, int h);
@@ -874,25 +864,6 @@ extern bool objcollide(physent *d, const vec &objpos, float objrad, float objhei
extern bool collide(physent *d, bool spawn = false, float drop = 0, float rise = 0);
extern void attack(bool on);
// sound
/*
extern void audiomgr.playsound(int n, int priority = SP_NORMAL);
extern void audiomgr.playsound(int n, physent *p, int priority = SP_NORMAL);
extern void audiomgr.playsound(int n, entity *e, int priority = SP_NORMAL);
extern void audiomgr.playsound(int n, const vec *v, int priority = SP_NORMAL);
extern void audiomgr.playsoundc(int n, physent *p = NULL, int priority = SP_NORMAL);
extern void initsound();
extern void soundcleanup();
extern void musicsuggest(int id, int millis = 0, bool rndofs = false);
extern void musicfadeout(int id);
extern void clearworldsounds(bool fullclean = true);
extern void detachsounds(playerent *owner);
extern void updateaudio();
extern void preloadmapsound(entity &e);
extern void preloadmapsounds();
extern void writesoundconfig(stream *f);
*/
// rendermodel
extern void rendermodel(const char *mdl, int anim, int tex, float rad, const vec &o, float roll, float yaw, float pitch, float speed = 0, int basetime = 0, playerent *d = NULL, modelattach *a = NULL, float scale = 1.0f);
extern void startmodelbatches();
@@ -932,16 +903,14 @@ extern bool intersect(entity *e, const vec &from, const vec &to, vec *end = NULL
extern void damageeffect(int damage, playerent *d);
extern void tryreload(playerent *p);
extern void checkweaponstate();
extern struct projectile *newprojectile(vec &from, vec &to, float speed, bool local, playerent *owner, int gun, int id = lastmillis);
extern int burstshotssettings[NUMGUNS];
// entities
extern void spawnallitems();
extern void pickupeffects(int n, playerent *d);
extern void renderentities();
extern void rendermapmodels();
extern void resetspawns(int type = -1);
extern void setspawn(int i, bool on);
extern void resetpickups(int type = -1);
extern void setpickupspawn(int i, bool on);
extern void checkitems(playerent *d);
extern vector<int> changedents;
extern void syncentchanges(bool force = false);
@@ -999,7 +968,7 @@ extern void setsvar(const char *name, const char *str, bool dofunc = false);
extern bool identexists(const char *name);
extern bool addcommand(const char *name, void (*fun)(), const char *sig);
extern int execute(const char *p);
enum { HOOK_SP_MP = 1, HOOK_SP, HOOK_MP, HOOK_FLAGMASK = 0xff, HOOK_TEAM = 0x100, HOOK_NOTEAM = 0x200, HOOK_BOTMODE = 0x400, HOOK_FLAGMODE = 0x800, HOOK_ARENA = 0x1000 };
enum { HOOK_MP = 1, HOOK_SP, HOOK_SP_MP, HOOK_FLAGMASK = 0xff, HOOK_TEAM = 0x100, HOOK_NOTEAM = 0x200, HOOK_BOTMODE = 0x400, HOOK_FLAGMODE = 0x800, HOOK_ARENA = 0x1000 };
extern bool exechook(int context, const char *ident, const char *body,...) PRINTFARGS(3, 4); // execute cubescript hook if available and allowed in current context/gamemode
extern void identhash(uint64_t *d);
extern char *executeret(const char *p);
@@ -1021,20 +990,17 @@ extern const char *getalias(const char *name);
extern void writecfg();
extern void deletecfg();
extern void identnames(vector<const char *> &names, bool builtinonly);
extern void changescriptcontext(int newcontext);
extern void explodelist(const char *s, vector<char *> &elems);
extern char *indexlist(const char *s, int pos);
extern char *parseword(const char *&p);
extern void pushscontext(int newcontext);
extern int popscontext();
extern int curscontext();
extern const char *escapestring(const char *s, bool force = true, bool noquotes = false);
extern int execcontext;
extern const char *currentserver(int i);
extern void pushscontext(int newcontext);
extern int popscontext();
extern void scripterr();
extern void setcontext(const char *context, const char *info);
extern void resetcontext();
extern void dumpexecutionstack(stream *f);
extern const char *currentserver(int i);
// server
extern int modeacronyms;
@@ -1077,12 +1043,9 @@ extern char *filtertext(char *dst, const char *src, int flags = 1, int len = siz
extern void filterrichtext(char *dst, const char *src, int len = sizeof(string)-1);
extern void filterlang(char *d, const char *s);
extern void trimtrailingwhitespace(char *s);
extern void startintermission();
extern void restoreserverstate(vector<entity> &ents);
extern string mastername;
extern int masterport, mastertype;
extern ENetSocket connectmaster();
extern uchar *retrieveservers(uchar *buf, int buflen);
extern void serverms(int mode, int numplayers, int minremain, char *smapname, int millis, const ENetAddress &localaddr, int *mnum, int *msend, int *mrec, int *cnum, int *csend, int *crec, int protocol_version);
extern int msgsizelookup(int msg);
extern const char *genpwdhash(const char *name, const char *pwd, int salt);
-9
View File
@@ -403,15 +403,6 @@ savedscore *findscore(client &c, bool insert)
return &sc;
}
void restoreserverstate(vector<entity> &ents) // hack: called from savegame code, only works in SP
{
loopv(sents)
{
sents[i].spawned = ents[i].spawned;
sents[i].spawntime = 0;
}
}
void sendf(int cn, int chan, const char *format, ...)
{
int exclude = -1;
-2
View File
@@ -285,8 +285,6 @@ vector<serverinfo *> servers;
ENetSocket pingsock = ENET_SOCKET_NULL;
int lastinfo = 0;
char *getservername(int n) { return servers[n]->name; }
serverinfo *findserverinfo(ENetAddress address)
{
loopv(servers) if(servers[i]->address.host == address.host && servers[i]->port == address.port) return servers[i];
-25
View File
@@ -819,31 +819,6 @@ void cleanuptmus()
loopi(MAXTMUS) tmus[i] = invalidtmu;
}
// only works on 32 bit surfaces with alpha in 4th byte!
void blitsurface(SDL_Surface *dst, SDL_Surface *src, int x, int y)
{
uchar *dstp = (uchar *)dst->pixels + y*dst->pitch + x*4,
*srcp = (uchar *)src->pixels;
int dstpitch = dst->pitch - 4*src->w,
srcpitch = src->pitch - 4*src->w;
loop(dy, src->h)
{
loop(dx, src->w)
{
uint k1 = (255U - srcp[3]) * dstp[3], k2 = srcp[3] * 255U, kmax = max(dstp[3], srcp[3]), kscale = max(kmax * 255U, 1U);
dstp[0] = (dstp[0]*k1 + srcp[0]*k2) / kscale;
dstp[1] = (dstp[1]*k1 + srcp[1]*k2) / kscale;
dstp[2] = (dstp[2]*k1 + srcp[2]*k2) / kscale;
dstp[3] = kmax;
dstp += 4;
srcp += 4;
}
dstp += dstpitch;
srcp += srcpitch;
}
}
Texture *e_wall = NULL, *e_floor = NULL, *e_ceil = NULL;
void guidetoggle()
-8
View File
@@ -438,11 +438,3 @@ void freeblock(block *&b)
if(b) { freeblockp(b); b = NULL; }
}
block *duplicateblock(const block *s)
{
size_t len = sizeof(block) + s->xs * s->ys * sizeof(sqr);
block *b = (block *)new uchar[len];
memcpy(b, s, len);
return b;
}