From e44d8a85d824978deeda8643cce7362218837c4a Mon Sep 17 00:00:00 2001 From: Spoike Date: Fri, 6 Apr 2018 17:21:15 +0000 Subject: [PATCH] don't swallow multimedia keys unless they're actually bound to something. fix possible out-of-range issue with qc ent references. shader parsing is now a little more strict. lua code support updated to bring it more in line with hifi's efforts, still not enabled by default. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5233 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_ents.c | 2 +- engine/client/in_win.c | 41 +- engine/client/keys.c | 5 - engine/client/keys.h | 17 +- engine/client/pr_csqc.c | 25 +- engine/client/pr_menu.c | 14 +- engine/client/snd_dma.c | 2 +- engine/client/view.c | 4 +- engine/common/com_phys_ode.c | 10 +- engine/common/pmove.c | 2 +- engine/common/pr_bgcmd.c | 18 +- engine/common/world.h | 3 +- engine/gl/gl_shader.c | 24 +- engine/gl/gl_vidnt.c | 3 +- engine/qclib/execloop.h | 8 +- engine/qclib/initlib.c | 4 +- engine/qclib/pr_edict.c | 4 +- engine/qclib/pr_exec.c | 10 +- engine/qclib/progsint.h | 7 +- engine/qclib/progslib.h | 10 +- engine/server/net_preparse.c | 2 +- engine/server/pr_cmds.c | 34 +- engine/server/pr_lua.c | 2095 +++++++++++++++++++++++++-------- engine/server/pr_q1qvm.c | 23 +- engine/server/savegame.c | 25 +- engine/server/sv_ents.c | 32 +- engine/server/sv_init.c | 17 +- engine/server/sv_main.c | 4 +- engine/server/sv_phys.c | 8 +- engine/server/sv_send.c | 6 +- engine/server/sv_user.c | 32 +- engine/server/world.c | 12 +- plugins/avplug/avaudio.c | 4 +- plugins/bullet/bulletplug.cpp | 6 +- 34 files changed, 1834 insertions(+), 679 deletions(-) diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 16f50964a..a46d82967 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -2764,7 +2764,7 @@ void CLQ1_AddVisibleBBoxes(void) "}\n"); for (i = 1; i < w->num_edicts; i++) { - e = WEDICT_NUM(w->progs, i); + e = WEDICT_NUM_PB(w->progs, i); if (ED_ISFREE(e)) continue; diff --git a/engine/client/in_win.c b/engine/client/in_win.c index 34075f125..fe68a9bea 100644 --- a/engine/client/in_win.c +++ b/engine/client/in_win.c @@ -2405,31 +2405,34 @@ void INS_TranslateKeyEvent(WPARAM wParam, LPARAM lParam, qboolean down, int qdev int INS_AppCommand(LPARAM lParam) { + const char *b; int qkey = 0; switch(HIWORD(lParam)&0xfff) { - case APPCOMMAND_BROWSER_BACKWARD: qkey = K_MM_BACK; break; - case APPCOMMAND_BROWSER_FAVORITES: qkey = K_MM_FAVORITES; break; - case APPCOMMAND_BROWSER_FORWARD: qkey = K_MM_FORWARD; break; - case APPCOMMAND_BROWSER_HOME: qkey = K_MM_HOME; break; - case APPCOMMAND_BROWSER_REFRESH: qkey = K_MM_REFRESH; break; - case APPCOMMAND_BROWSER_SEARCH: qkey = K_SEARCH; break; - case APPCOMMAND_BROWSER_STOP: qkey = K_MM_STOP; break; -// case APPCOMMAND_VOLUME_MUTE: qkey = K_MM_MUTE; break; - case APPCOMMAND_VOLUME_UP: qkey = K_VOLUP; break; - case APPCOMMAND_VOLUME_DOWN: qkey = K_VOLDOWN; break; - -// I want to use these, but that would fuck up external music players. -// case APPCOMMAND_MEDIA_NEXTTRACK: -// case APPCOMMAND_MEDIA_PREVIOUSTRACK: -// case APPCOMMAND_MEDIA_STOP: -// case APPCOMMAND_MEDIA_PLAY_PAUSE: + case APPCOMMAND_BROWSER_BACKWARD: qkey = K_MM_BROWSER_BACK; break; + case APPCOMMAND_BROWSER_FAVORITES: qkey = K_MM_BROWSER_FAVORITES; break; + case APPCOMMAND_BROWSER_FORWARD: qkey = K_MM_BROWSER_FORWARD; break; + case APPCOMMAND_BROWSER_HOME: qkey = K_MM_BROWSER_HOME; break; + case APPCOMMAND_BROWSER_REFRESH: qkey = K_MM_BROWSER_REFRESH; break; + case APPCOMMAND_BROWSER_SEARCH: qkey = K_SEARCH; break; + case APPCOMMAND_BROWSER_STOP: qkey = K_MM_BROWSER_STOP; break; + case APPCOMMAND_VOLUME_MUTE: qkey = K_MM_VOLUME_MUTE; break; + case APPCOMMAND_VOLUME_UP: qkey = K_VOLUP; break; + case APPCOMMAND_VOLUME_DOWN: qkey = K_VOLDOWN; break; + case APPCOMMAND_MEDIA_NEXTTRACK: qkey = K_MM_TRACK_NEXT; break; + case APPCOMMAND_MEDIA_PREVIOUSTRACK:qkey = K_MM_TRACK_PREV; break; + case APPCOMMAND_MEDIA_STOP: qkey = K_MM_TRACK_STOP; break; + case APPCOMMAND_MEDIA_PLAY_PAUSE: qkey = K_MM_TRACK_PLAYPAUSE; break; default: return false; } - IN_KeyEvent(0, true, qkey, 0); - IN_KeyEvent(0, false, qkey, 0); - return true; + b = Key_GetBinding(qkey, 0, 0); + if (b && *b) + { //only take the key if its actually bound to something, otherwise let the system handle it normally. + IN_KeyEvent(0, true, qkey, 0); + IN_KeyEvent(0, false, qkey, 0); + return true; + } return false; } #endif diff --git a/engine/client/keys.c b/engine/client/keys.c index 47457e8ef..0ee3f4648 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -51,7 +51,6 @@ int key_bindmaps[2]; char *keybindings[K_MAX][KEY_MODIFIERSTATES]; qbyte bindcmdlevel[K_MAX][KEY_MODIFIERSTATES]; qboolean consolekeys[K_MAX]; // if true, can't be rebound while in console -qboolean menubound[K_MAX]; // if true, can't be rebound while in menu int keyshift[K_MAX]; // key to map to if shift held down in console int key_repeats[K_MAX]; // if > 1, it is autorepeating qboolean keydown[K_MAX]; @@ -2304,10 +2303,6 @@ void Key_Init (void) keyshift['`'] = '~'; keyshift['\\'] = '|'; - menubound[K_ESCAPE] = true; - for (i=0 ; i<12 ; i++) - menubound[K_F1+i] = true; - // // register our functions // diff --git a/engine/client/keys.h b/engine/client/keys.h index 1cff8d6d7..a7a8d0738 100644 --- a/engine/client/keys.h +++ b/engine/client/keys.h @@ -202,12 +202,17 @@ K_GP_DPAD_LEFT = 253, K_GP_DPAD_RIGHT = 254, K_GP_UNKNOWN = 255, -K_MM_BACK, -K_MM_FAVORITES, -K_MM_FORWARD, -K_MM_HOME, -K_MM_REFRESH, -K_MM_STOP, +K_MM_BROWSER_BACK, +K_MM_BROWSER_FAVORITES, +K_MM_BROWSER_FORWARD, +K_MM_BROWSER_HOME, +K_MM_BROWSER_REFRESH, +K_MM_BROWSER_STOP, +K_MM_VOLUME_MUTE, +K_MM_TRACK_NEXT, +K_MM_TRACK_PREV, +K_MM_TRACK_STOP, +K_MM_TRACK_PLAYPAUSE, K_MAX }; diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index b002dfa6d..94b35e8a2 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -39,11 +39,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern usercmd_t cl_pendingcmd[MAX_SPLITS]; -#ifndef TEXTEDITOR -//client only builds don't have a qc debugger -#define QCEditor NULL -#endif - static pubprogfuncs_t *csqcprogs; typedef struct csqctreadstate_s { @@ -1373,7 +1368,7 @@ static void QCBUILTIN PF_R_AddEntityMask(pubprogfuncs_t *prinst, struct globalva maxe = *prinst->parms->sv_num_edicts; for (e=1; e < maxe; e++) { - ent = (void*)EDICT_NUM(prinst, e); + ent = (void*)EDICT_NUM_PB(prinst, e); if (ED_ISFREE(ent)) continue; if (ent->v->think) @@ -1404,7 +1399,7 @@ static void QCBUILTIN PF_R_AddEntityMask(pubprogfuncs_t *prinst, struct globalva maxe = *prinst->parms->sv_num_edicts; for (e=1; e < maxe; e++) { - ent = (void*)EDICT_NUM(prinst, e); + ent = (void*)EDICT_NUM_PB(prinst, e); if (ED_ISFREE(ent)) continue; @@ -3185,7 +3180,7 @@ void CSQC_ResetTrails(void) for (i = 0; i < *prinst->parms->sv_num_edicts; i++) { - ent = (csqcedict_t*)EDICT_NUM(prinst, i); + ent = (csqcedict_t*)EDICT_NUM_PB(prinst, i); ent->trailstate = NULL; } } @@ -4577,8 +4572,8 @@ void CSQC_RunThreads(void) { //call it and forget it ever happened. The Sleep biltin will recreate if needed. - *csqcg.self = EDICT_TO_PROG(csqcprogs, EDICT_NUM(csqcprogs, state->self)); - *csqcg.other = EDICT_TO_PROG(csqcprogs, EDICT_NUM(csqcprogs, state->other)); + *csqcg.self = EDICT_TO_PROG(csqcprogs, EDICT_NUM_UB(csqcprogs, state->self)); + *csqcg.other = EDICT_TO_PROG(csqcprogs, EDICT_NUM_UB(csqcprogs, state->other)); csqcprogs->RunThread(csqcprogs, state->thread); csqcprogs->parms->memfree(state->thread); @@ -7331,7 +7326,7 @@ qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checks csqcentsize = PR_InitEnts(csqcprogs, pr_csqc_maxedicts.value); //world edict becomes readonly - worldent = (csqcedict_t *)EDICT_NUM(csqcprogs, 0); + worldent = (csqcedict_t *)EDICT_NUM_PB(csqcprogs, 0); worldent->ereftype = ER_ENTITY; for (i = 0; i < csqcprogs->numprogs; i++) @@ -7450,7 +7445,7 @@ void CSQC_WorldLoaded(void) csqc_world.worldmodel = cl.worldmodel; World_RBE_Start(&csqc_world); - worldent = (csqcedict_t *)EDICT_NUM(csqcprogs, 0); + worldent = (csqcedict_t *)EDICT_NUM_PB(csqcprogs, 0); worldent->v->solid = SOLID_BSP; wmodelindex = CS_FindModel(cl.worldmodel?cl.worldmodel->name:"", &tmp); tmp = csqc_worldchanged; @@ -7710,7 +7705,7 @@ qboolean CSQC_SetupToRenderPortal(int entkeynum) if (csqcprogs && entkeynum < 0) { - csqcedict_t *e = (void*)EDICT_NUM(csqcprogs, -entkeynum); + csqcedict_t *e = (void*)EDICT_NUM_UB(csqcprogs, -entkeynum); if (e->xv->camera_transform) { int oself = *csqcg.self; @@ -8483,7 +8478,7 @@ void CSQC_GetEntityOrigin(unsigned int csqcent, float *out) wedict_t *ent; if (!csqcprogs) return; - ent = WEDICT_NUM(csqcprogs, csqcent); + ent = WEDICT_NUM_UB(csqcprogs, csqcent); VectorCopy(ent->v->origin, out); } @@ -8631,7 +8626,7 @@ void CSQC_ParseEntities(void) #ifndef CLIENTONLY if (sv.state) { - Con_Printf("Server classname: \"%s\"\n", PR_GetString(svprogfuncs, EDICT_NUM(svprogfuncs, entnum)->v->classname)); + Con_Printf("Server classname: \"%s\"\n", PR_GetString(svprogfuncs, EDICT_NUM_UB(svprogfuncs, entnum)->v->classname)); } #endif } diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index a24eba30c..5d2a554c3 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -1512,7 +1512,7 @@ void QCBUILTIN PF_menu_findchain (pubprogfuncs_t *prinst, struct globalvars_s *p for (i = 1; i < *prinst->parms->sv_num_edicts; i++) { - ent = (menuedict_t *)EDICT_NUM(prinst, i); + ent = (menuedict_t *)EDICT_NUM_PB(prinst, i); if (ent->ereftype == ER_FREE) continue; t = *(string_t *)&((float*)ent->fields)[f]; @@ -1544,7 +1544,7 @@ void QCBUILTIN PF_menu_findchainfloat (pubprogfuncs_t *prinst, struct globalvars for (i = 1; i < *prinst->parms->sv_num_edicts; i++) { - ent = (menuedict_t*)EDICT_NUM(prinst, i); + ent = (menuedict_t*)EDICT_NUM_PB(prinst, i); if (ent->ereftype == ER_FREE) continue; if (((float *)ent->fields)[f] != s) @@ -1573,7 +1573,7 @@ void QCBUILTIN PF_menu_findchainflags (pubprogfuncs_t *prinst, struct globalvars for (i = 1; i < *prinst->parms->sv_num_edicts; i++) { - ent = (menuedict_t*)EDICT_NUM(prinst, i); + ent = (menuedict_t*)EDICT_NUM_PB(prinst, i); if (ent->ereftype == ER_FREE) continue; if ((int)((float *)ent->fields)[f] & s) @@ -1596,7 +1596,7 @@ void QCBUILTIN PF_ftoe(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { int entnum = G_FLOAT(OFS_PARM0); - RETURN_EDICT(prinst, EDICT_NUM(prinst, entnum)); + RETURN_EDICT(prinst, EDICT_NUM_UB(prinst, entnum)); } void QCBUILTIN PF_IsNotNull(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -2623,8 +2623,8 @@ qboolean MP_Init (void) //'world' edict -// EDICT_NUM(menu_world.progs, 0)->readonly = true; - EDICT_NUM(menu_world.progs, 0)->ereftype = ER_ENTITY; +// EDICT_NUM_PB(menu_world.progs, 0)->readonly = true; + EDICT_NUM_PB(menu_world.progs, 0)->ereftype = ER_ENTITY; mp_init_function = PR_FindFunction(menu_world.progs, "m_init", PR_ANY); @@ -2640,7 +2640,7 @@ qboolean MP_Init (void) PR_ExecuteProgram(menu_world.progs, mp_init_function); inmenuprogs--; - EDICT_NUM(menu_world.progs, 0)->readonly = true; + EDICT_NUM_PB(menu_world.progs, 0)->readonly = true; Con_DPrintf("Initialized menu.dat\n"); return true; diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index edf787a58..8cff26c24 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -2646,7 +2646,7 @@ static void SND_Spatialize(soundcardinfo_t *sc, channel_t *ch) #ifdef CSQC_DAT if (ch->entnum < 0 && -ch->entnum < csqc_world.num_edicts) { - wedict_t *ed = WEDICT_NUM(csqc_world.progs, -ch->entnum); + wedict_t *ed = WEDICT_NUM_PB(csqc_world.progs, -ch->entnum); if (ed->ereftype == ER_ENTITY) { VectorCopy(ed->v->origin, ch->origin); diff --git a/engine/client/view.c b/engine/client/view.c index 6032d571c..57ea63388 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1934,7 +1934,7 @@ void R_DrawNameTags(void) float bestscore = 0, score = 0; for (i = 1; i < w->num_edicts; i++) { - e = WEDICT_NUM(w->progs, i); + e = WEDICT_NUM_PB(w->progs, i); if (ED_ISFREE(e)) continue; VectorInterpolate(e->v->mins, 0.5, e->v->maxs, org); @@ -1957,7 +1957,7 @@ void R_DrawNameTags(void) } if (best) { - e = WEDICT_NUM(w->progs, best); + e = WEDICT_NUM_PB(w->progs, best); VectorInterpolate(e->v->mins, 0.5, e->v->maxs, org); VectorAdd(org, e->v->origin, org); if (Matrix4x4_CM_Project(org, screenspace, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y)) diff --git a/engine/common/com_phys_ode.c b/engine/common/com_phys_ode.c index a043a1a86..041fb3998 100644 --- a/engine/common/com_phys_ode.c +++ b/engine/common/com_phys_ode.c @@ -1627,9 +1627,9 @@ static void World_ODE_Frame_JointFromEntity(world_t *world, wedict_t *ed) //Con_Printf("made new joint %i\n", (int) (ed - prog->edicts)); dJointSetData(j, (void *) ed); if(enemy) - b1 = (dBodyID)((WEDICT_NUM(world->progs, enemy))->ode.ode_body); + b1 = (dBodyID)((WEDICT_NUM_UB(world->progs, enemy))->ode.ode_body); if(aiment) - b2 = (dBodyID)((WEDICT_NUM(world->progs, aiment))->ode.ode_body); + b2 = (dBodyID)((WEDICT_NUM_UB(world->progs, aiment))->ode.ode_body); dJointAttach(j, b1, b2); switch(jointtype) @@ -2641,14 +2641,14 @@ static void QDECL World_ODE_Frame(world_t *world, double frametime, double gravi // copy physics properties from entities to physics engine for (i = 0;i < world->num_edicts;i++) { - ed = (wedict_t*)EDICT_NUM(world->progs, i); + ed = (wedict_t*)EDICT_NUM_PB(world->progs, i); if (!ED_ISFREE(ed)) World_ODE_Frame_BodyFromEntity(world, ed); } // oh, and it must be called after all bodies were created for (i = 0;i < world->num_edicts;i++) { - ed = (wedict_t*)EDICT_NUM(world->progs, i); + ed = (wedict_t*)EDICT_NUM_PB(world->progs, i); if (!ED_ISFREE(ed)) World_ODE_Frame_JointFromEntity(world, ed); } @@ -2691,7 +2691,7 @@ static void QDECL World_ODE_Frame(world_t *world, double frametime, double gravi // copy physics properties from physics engine to entities for (i = 1;i < world->num_edicts;i++) { - ed = (wedict_t*)EDICT_NUM(world->progs, i); + ed = (wedict_t*)EDICT_NUM_PB(world->progs, i); if (!ED_ISFREE(ed)) World_ODE_Frame_BodyToEntity(world, ed); } diff --git a/engine/common/pmove.c b/engine/common/pmove.c index fcaddd174..f029eec3a 100644 --- a/engine/common/pmove.c +++ b/engine/common/pmove.c @@ -93,7 +93,7 @@ static qboolean PM_PortalTransform(world_t *w, int portalnum, vec3_t org, vec3_t { vec3_t rounded; qboolean okay = true; - wedict_t *portal = WEDICT_NUM(w->progs, portalnum); + wedict_t *portal = WEDICT_NUM_UB(w->progs, portalnum); int oself = *w->g.self; void *pr_globals = PR_globals(w->progs, PR_CURRENT); int i; diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 0bcb7a0d2..5b95490a2 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -1227,7 +1227,7 @@ void QCBUILTIN PF_findchainflags (pubprogfuncs_t *prinst, struct globalvars_s *p for (i = 1; i < *prinst->parms->sv_num_edicts; i++) { - ent = WEDICT_NUM(prinst, i); + ent = WEDICT_NUM_PB(prinst, i); if (ED_ISFREE(ent)) continue; if (!((int)((float *)ent->v)[ff] & s)) @@ -1258,7 +1258,7 @@ void QCBUILTIN PF_findchainfloat (pubprogfuncs_t *prinst, struct globalvars_s *p for (i = 1; i < *prinst->parms->sv_num_edicts; i++) { - ent = WEDICT_NUM(prinst, i); + ent = WEDICT_NUM_PB(prinst, i); if (ED_ISFREE(ent)) continue; if (((float *)ent->v)[ff] != s) @@ -1291,7 +1291,7 @@ void QCBUILTIN PF_findchain (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo for (i = 1; i < *prinst->parms->sv_num_edicts; i++) { - ent = WEDICT_NUM(prinst, i); + ent = WEDICT_NUM_PB(prinst, i); if (ED_ISFREE(ent)) continue; t = *(string_t *)&((float*)ent->v)[ff]; @@ -1321,7 +1321,7 @@ void QCBUILTIN PF_FindFlags (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo for (e++; e < *prinst->parms->sv_num_edicts; e++) { - ed = WEDICT_NUM(prinst, e); + ed = WEDICT_NUM_PB(prinst, e); if (ED_ISFREE(ed)) continue; if ((int)((float *)ed->v)[f] & s) @@ -1353,7 +1353,7 @@ void QCBUILTIN PF_FindFloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo for (e++; e < *prinst->parms->sv_num_edicts; e++) { - ed = WEDICT_NUM(prinst, e); + ed = WEDICT_NUM_PB(prinst, e); if (ED_ISFREE(ed)) continue; if (((int *)ed->v)[f] == s) @@ -1386,7 +1386,7 @@ void QCBUILTIN PF_FindString (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl for (e++ ; e < *prinst->parms->sv_num_edicts ; e++) { - ed = WEDICT_NUM(prinst, e); + ed = WEDICT_NUM_PB(prinst, e); if (ED_ISFREE(ed)) continue; t = ((string_t *)ed->v)[f]; @@ -2925,7 +2925,7 @@ void QCBUILTIN PF_edict_for_num(pubprogfuncs_t *prinst, struct globalvars_s *pr_ if (num >= w->num_edicts) RETURN_EDICT(prinst, w->edicts); - ent = (edict_t*)EDICT_NUM(prinst, num); + ent = (edict_t*)EDICT_NUM_PB(prinst, num); RETURN_EDICT(prinst, ent); } @@ -2998,7 +2998,7 @@ void QCBUILTIN PF_findradius (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl rad = rad*rad; for (i=1 ; inum_edicts ; i++) { - ent = WEDICT_NUM(prinst, i); + ent = WEDICT_NUM_PB(prinst, i); if (ED_ISFREE(ent)) continue; if (ent->v->solid == SOLID_NOT && (!((int)ent->v->flags & FL_FINDABLE_NONSOLID)) && !sv_gameplayfix_blowupfallenzombies.value) @@ -3031,7 +3031,7 @@ void QCBUILTIN PF_nextent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa RETURN_EDICT(prinst, *prinst->parms->sv_edicts); return; } - ent = WEDICT_NUM(prinst, i); + ent = WEDICT_NUM_PB(prinst, i); if (!ED_ISFREE(ent)) { RETURN_EDICT(prinst, ent); diff --git a/engine/common/world.h b/engine/common/world.h index c3285ca5c..9b99723f9 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -165,7 +165,8 @@ typedef struct areanode_s typedef struct wedict_s wedict_t; #define PROG_TO_WEDICT (wedict_t*)PROG_TO_EDICT -#define WEDICT_NUM (wedict_t *)EDICT_NUM +#define WEDICT_NUM_UB (wedict_t *)EDICT_NUM_UB //ent number isn't bounded +#define WEDICT_NUM_PB (wedict_t *)EDICT_NUM_PB //pre-bound #define G_WEDICT (wedict_t *)G_EDICT typedef struct diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index fe641531b..acc35369d 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -2592,11 +2592,6 @@ static shaderkey_t shaderkeys[] = {"clutter", Shader_ClutterParms, "fte"}, {"deferredlight", Shader_Deferredlight, "fte"}, //(sort = prelight) // {"lpp_light", Shader_Deferredlight, "fte"}, //(sort = prelight) - {"glslprogram", Shader_GLSLProgramName, "fte"}, - {"program", Shader_ProgramName, "fte"}, //gl or d3d - {"hlslprogram", Shader_HLSL9ProgramName, "fte"}, //for d3d - {"hlsl11program", Shader_HLSL11ProgramName, "fte"}, //for d3d - {"param", Shader_ProgramParam, "fte"}, //legacy {"affine", Shader_Affine, "fte"}, //some hardware is horribly slow, and can benefit from certain hints. {"bemode", Shader_BEMode, "fte"}, @@ -2609,9 +2604,14 @@ static shaderkey_t shaderkeys[] = {"lowermap", Shader_LowerMap, "fte"}, {"reflectmask", Shader_ReflectMask, "fte"}, - /*simpler parsing for fte shaders*/ - {"progblendfunc", Shader_ProgBlendFunc, "fte"}, - {"progmap", Shader_ProgMap, "fte"}, + /*program stuff at the material level is an outdated practise.*/ + {"program", Shader_ProgramName, "fte"}, //usable with any renderer that has a usable shader language... + {"glslprogram", Shader_GLSLProgramName, "fte"}, //for renderers that accept embedded glsl + {"hlslprogram", Shader_HLSL9ProgramName, "fte"}, //for d3d with embedded hlsl + {"hlsl11program", Shader_HLSL11ProgramName, "fte"}, //for d3d with embedded hlsl + {"param", Shader_ProgramParam, "fte"}, //legacy + {"progblendfunc", Shader_ProgBlendFunc, "fte"}, //specifies the blend mode (actually just overrides the first subpasses' blendmode. + {"progmap", Shader_ProgMap, "fte"}, //avoids needing extra subpasses (actually just inserts an extra pass). //dp compat {"reflectcube", Shader_ReflectCube, "dp"}, @@ -4364,6 +4364,8 @@ void Shader_Readpass (shader_t *shader, char **ptr) { if ( token[0] == '}' ) break; + else if (token[0] == '{') + Con_Printf("unexpected indentation in %s\n", shader->name); else if ( Shader_Parsetok (shader, pass, shaderpasskeys, token, ptr) ) break; } @@ -4471,6 +4473,12 @@ static qboolean Shader_Parsetok (shader_t *shader, shaderpass_t *pass, shaderkey char *prefix; qboolean toolchainprefix = false; + if (*token == '_') + { //forward compat: make sure there's a way to shut stuff up if you're using future extensions in an outdated engine. + token++; + toolchainprefix = true; + } + //handle known prefixes. if (!Q_strncasecmp(token, "fte", 3)) {prefix = token; token += 3; } else if (!Q_strncasecmp(token, "dp", 2)) {prefix = token; token += 2; } diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index 55e4978d1..d9cd1949c 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -2908,7 +2908,8 @@ static LONG WINAPI GLMainWndProc ( break; case WM_APPCOMMAND: - lRet = INS_AppCommand(lParam); + if (!INS_AppCommand(lParam)) + lRet = DefWindowProc(hWnd, uMsg, wParam, lParam); //otherwise it won't get handled by background apps, like media players. break; case WM_MOUSEACTIVATE: diff --git a/engine/qclib/execloop.h b/engine/qclib/execloop.h index 72257692a..efe7f9990 100644 --- a/engine/qclib/execloop.h +++ b/engine/qclib/execloop.h @@ -430,7 +430,7 @@ reeval: return pr_xstatement; break; } - ed = PROG_TO_EDICT(progfuncs, OPA->edict); + ed = PROG_TO_EDICT_PB(progfuncs, OPA->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif @@ -491,7 +491,7 @@ reeval: OPC->_int = 0; break; } - ed = PROG_TO_EDICT(progfuncs, OPA->edict); + ed = PROG_TO_EDICT_PB(progfuncs, OPA->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif @@ -528,7 +528,7 @@ reeval: OPC->_vector[2] = 0; break; } - ed = PROG_TO_EDICT(progfuncs, OPA->edict); + ed = PROG_TO_EDICT_PB(progfuncs, OPA->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif @@ -967,7 +967,7 @@ reeval: break; case OP_THINKTIME: - externs->thinktimeop(&progfuncs->funcs, (struct edict_s *)PROG_TO_EDICT(progfuncs, OPA->edict), OPB->_float); + externs->thinktimeop(&progfuncs->funcs, (struct edict_s *)PROG_TO_EDICT_UB(progfuncs, OPA->edict), OPB->_float); break; case OP_MULSTORE_F: diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index eba48fec7..709593d4a 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -498,6 +498,7 @@ int PDECL PR_InitEnts(pubprogfuncs_t *ppf, int max_ents) prinst.max_fields_size = prinst.fields_size; prinst.edicttable = (struct edictrun_s**)(progfuncs->funcs.edicttable = PRHunkAlloc(progfuncs, prinst.maxedicts*sizeof(struct edicts_s *), "edicttable")); + progfuncs->funcs.edicttable_length = prinst.maxedicts; e = PRHunkAlloc(progfuncs, externs->edictsize, "edict0"); e->fieldsize = prinst.fields_size; e->entnum = 0; @@ -571,6 +572,7 @@ static void PDECL PR_Configure (pubprogfuncs_t *ppf, size_t addressable_size, in prinst.profilingalert = Sys_GetClockRate(); prinst.maxedicts = 1; prinst.edicttable = (edictrun_t**)(progfuncs->funcs.edicttable = &sv_edicts); + progfuncs->funcs.edicttable_length = 1; sv_num_edicts = 1; //set up a safty buffer so things won't go horribly wrong too often sv_edicts=(struct edict_s *)&tempedict; tempedict.readonly = true; @@ -874,7 +876,7 @@ struct edict_s *PDECL ProgsToEdict (pubprogfuncs_t *ppf, int progs) } progs = 0; } - return (struct edict_s *)PROG_TO_EDICT(progfuncs.inst, progs); + return (struct edict_s *)PROG_TO_EDICT_PB(progfuncs.inst, progs); } int PDECL EdictToProgs (pubprogfuncs_t *ppf, struct edict_s *ed) { diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index dcd163885..54217ba76 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -802,7 +802,7 @@ char *PR_UglyOldValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val) QC_snprintfz (line, sizeof(line), "%s", PR_StringToNative(&progfuncs->funcs, val->string)); break; case ev_entity: - QC_snprintfz (line, sizeof(line), "%i", NUM_FOR_EDICT(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, val->edict))); + QC_snprintfz (line, sizeof(line), "%i", val->edict); break; case ev_function: f = pr_progstate[(val->function & 0xff000000)>>24].functions + (val->function & ~0xff000000); @@ -2143,7 +2143,7 @@ int PDECL PR_LoadEnts(pubprogfuncs_t *ppf, const char *file, void *ctx, void (PD sv_num_edicts = 1; //set up a safty buffer so things won't go horribly wrong too often sv_edicts=(struct edict_s *)&tempedict; prinst.edicttable = (struct edictrun_s**)(progfuncs->funcs.edicttable = &sv_edicts); - + progfuncs->funcs.edicttable_length = numents; sv_num_edicts = numents; //should be fine diff --git a/engine/qclib/pr_exec.c b/engine/qclib/pr_exec.c index 3a54a173c..75c76c4bc 100644 --- a/engine/qclib/pr_exec.c +++ b/engine/qclib/pr_exec.c @@ -329,7 +329,7 @@ static void PDECL PR_PrintRelevantLocals(progfuncs_t *progfuncs) } else { - ed = PROG_TO_EDICT(progfuncs, entnum); + ed = PROG_TO_EDICT_PB(progfuncs, entnum); if ((unsigned int)((eval_t *)&pr_globals[st16[st].b])->_int*4u >= ed->fieldsize) continue; else @@ -751,8 +751,10 @@ pbool LocateDebugTerm(progfuncs_t *progfuncs, char *key, eval_t **result, etype_ fofs = fdef->ofs; type = fdef->type; - - ed = PROG_TO_EDICT(progfuncs, val->_int); + if ((unsigned int)val->_int >= prinst.maxedicts) + ed = NULL; + else + ed = PROG_TO_EDICT_PB(progfuncs, val->_int); if (!ed) return false; if (fofs < 0 || fofs >= (int)prinst.max_fields_size) @@ -1492,7 +1494,7 @@ const char *PR_GetEdictClassname(progfuncs_t *progfuncs, unsigned int edict) fdef_t *cnfd = ED_FindField(progfuncs, "classname"); if (cnfd && edict < prinst.maxedicts) { - string_t *v = (string_t *)((char *)edvars(PROG_TO_EDICT(progfuncs, edict)) + cnfd->ofs*4); + string_t *v = (string_t *)((char *)edvars(PROG_TO_EDICT_PB(progfuncs, edict)) + cnfd->ofs*4); return PR_StringToNative(&progfuncs->funcs, *v); } return ""; diff --git a/engine/qclib/progsint.h b/engine/qclib/progsint.h index 860cfee7d..76e48a6ab 100644 --- a/engine/qclib/progsint.h +++ b/engine/qclib/progsint.h @@ -147,9 +147,6 @@ typedef struct prinst_s #define pr_xstatement prinst.pr_xstatement //pr_edict.c - - unsigned int maxedicts; - evalc_t spawnflagscache; unsigned int fields_size; // in bytes unsigned int max_fields_size; @@ -161,6 +158,7 @@ typedef struct prinst_s size_t addressableused; size_t addressablesize; + unsigned int maxedicts; struct edictrun_s **edicttable; } prinst_t; @@ -413,7 +411,8 @@ unsigned int PDECL QC_NUM_FOR_EDICT(pubprogfuncs_t *progfuncs, struct edict_s *e //#define NEXT_EDICT(e) ((edictrun_t *)( (byte *)e + pr_edict_size)) #define EDICT_TO_PROG(pf, e) (((edictrun_t*)e)->entnum) -#define PROG_TO_EDICT(pf, e) ((struct edictrun_s *)prinst.edicttable[e]) +#define PROG_TO_EDICT_PB(pf, e) ((struct edictrun_s *)prinst.edicttable[e]) //index already validated +#define PROG_TO_EDICT_UB(pf, e) ((struct edictrun_s *)prinst.edicttable[((unsigned int)(e)EDICT_NUM) (pf, num) #else -#define EDICT_NUM(pf, num) (pf->edicttable[num]) +#define EDICT_NUM_PB(pf, num) (pf->edicttable[num]) +#define EDICT_NUM_UB(pf, num) EDICT_NUM_PB(pf,(((unsigned int)(num))>=pf->edicttable_length)?0:num) #endif -#define NUM_FOR_EDICT(pf, e) (*pf->NUM_FOR_EDICT) (pf, (struct edict_s*)(e)) +#define NUM_FOR_EDICT(pf, e) (*pf->NumForEdict) (pf, (struct edict_s*)(e)) #define SetGlobalEdict(pf, ed, ofs) (*pf->SetGlobalEdict) (pf, ed, ofs) #define PR_VarString(pf,first) (*pf->VarString) (pf,first) diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index 179aca699..dde0f3ed0 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -1826,7 +1826,7 @@ void NPP_QWFlush(void) { short data; float org[3]; - edict_t *ent = EDICT_NUM(svprogfuncs, LittleShort((*(short*)&buffer[1]))); + edict_t *ent = EDICT_NUM_UB(svprogfuncs, LittleShort((*(short*)&buffer[1]))); ent->muzzletime = sv.world.physicstime+host_frametime; //flag the entity as needing an EF_MUZZLEFLASH VectorCopy(ent->v->origin, org); diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index c72513097..16f920fad 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -483,7 +483,7 @@ static void PDECL PR_SSQC_Relocated(pubprogfuncs_t *pr, char *oldb, char *newb, #ifdef VM_Q1 for (i = 0; i < sv.world.num_edicts; i++) { - ent = EDICT_NUM(pr, i); + ent = EDICT_NUM_PB(pr, i); if ((char*)ent->xv >= oldb && (char*)ent->xv < oldb+oldlen) ent->xv = (extentvars_t*)((char*)ent->xv - oldb + newb); } @@ -1273,7 +1273,7 @@ static void PR_ApplyCompilation_f (void) for (i=0 ; i= sv.allocated_client_slots+1) i = 1; - ent = EDICT_NUM(prinst, i); + ent = EDICT_NUM_UB(prinst, i); if (i == w->lastcheck) break; // didn't find anything else @@ -3747,7 +3747,7 @@ int PF_checkclient_Internal (pubprogfuncs_t *prinst) } // return check if it might be visible - ent = EDICT_NUM(prinst, w->lastcheck); + ent = EDICT_NUM_PB(prinst, w->lastcheck); if (ED_ISFREE(ent) || ent->v->health <= 0) { return 0; @@ -3776,7 +3776,7 @@ int PF_checkclient_Internal (pubprogfuncs_t *prinst) static void QCBUILTIN PF_checkclient (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { - RETURN_EDICT(prinst, EDICT_NUM(prinst, PF_checkclient_Internal(prinst))); + RETURN_EDICT(prinst, EDICT_NUM_PB(prinst, PF_checkclient_Internal(prinst))); } //============================================================================ @@ -3961,7 +3961,7 @@ static void QCBUILTIN PF_spawnclient (pubprogfuncs_t *prinst, struct globalvars_ svs.clients[i].datagram.allowoverflow = true; svs.clients[i].datagram.maxsize = 0; - svs.clients[i].edict = EDICT_NUM(prinst, i+1); + svs.clients[i].edict = EDICT_NUM_PB(prinst, i+1); SV_SetUpClientEdict (&svs.clients[i], svs.clients[i].edict); @@ -4700,7 +4700,7 @@ vector aim(entity, missilespeed) */ //cvar_t sv_aim = {"sv_aim", "0.93"}; cvar_t sv_aim = CVAR("sv_aim", "2"); -static void QCBUILTIN PF_aim (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +void QCBUILTIN PF_aim (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { edict_t *ent, *check, *bestent; vec3_t start, dir, end, bestdir; @@ -4754,7 +4754,7 @@ static void QCBUILTIN PF_aim (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl for (i=1 ; iv->takedamage != DAMAGE_AIM) continue; if (check == ent) @@ -8449,8 +8449,8 @@ void PRSV_RunThreads(void) { //call it and forget it ever happened. The Sleep biltin will recreate if needed. pr_globals = PR_globals(svprogfuncs, PR_CURRENT); - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, state->self)); - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, state->other)); + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, EDICT_NUM_UB(svprogfuncs, state->self)); + pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, EDICT_NUM_UB(svprogfuncs, state->other)); G_FLOAT(OFS_RETURN) = state->returnval; svprogfuncs->RunThread(svprogfuncs, state->thread); @@ -9256,7 +9256,7 @@ static void QCBUILTIN PF_ShowPic(pubprogfuncs_t *prinst, struct globalvars_s *pr prinst->callargc = 6; for (entnum = 0; entnum < sv.allocated_client_slots; entnum++) { - G_INT(OFS_PARM5) = EDICT_TO_PROG(prinst, EDICT_NUM(prinst, entnum+1)); + G_INT(OFS_PARM5) = EDICT_TO_PROG(prinst, EDICT_NUM_PB(prinst, entnum+1)); PF_ShowPic(prinst, pr_globals); } } @@ -9285,7 +9285,7 @@ static void QCBUILTIN PF_HidePic(pubprogfuncs_t *prinst, struct globalvars_s *pr prinst->callargc = 2; for (entnum = 0; entnum < sv.allocated_client_slots; entnum++) { - G_INT(OFS_PARM1) = EDICT_TO_PROG(prinst, EDICT_NUM(prinst, entnum+1)); + G_INT(OFS_PARM1) = EDICT_TO_PROG(prinst, EDICT_NUM_PB(prinst, entnum+1)); PF_HidePic(prinst, pr_globals); } } @@ -9323,7 +9323,7 @@ static void QCBUILTIN PF_MovePic(pubprogfuncs_t *prinst, struct globalvars_s *pr prinst->callargc = 5; for (entnum = 0; entnum < sv.allocated_client_slots; entnum++) { - G_INT(OFS_PARM4) = EDICT_TO_PROG(prinst, EDICT_NUM(prinst, entnum+1)); + G_INT(OFS_PARM4) = EDICT_TO_PROG(prinst, EDICT_NUM_PB(prinst, entnum+1)); PF_MovePic(prinst, pr_globals); } } @@ -9354,7 +9354,7 @@ static void QCBUILTIN PF_ChangePic(pubprogfuncs_t *prinst, struct globalvars_s * prinst->callargc = 3; for (entnum = 0; entnum < sv.allocated_client_slots; entnum++) { - G_INT(OFS_PARM2) = EDICT_TO_PROG(prinst, EDICT_NUM(prinst, entnum+1)); + G_INT(OFS_PARM2) = EDICT_TO_PROG(prinst, EDICT_NUM_PB(prinst, entnum+1)); PF_ChangePic(prinst, pr_globals); } } @@ -9531,7 +9531,7 @@ static void QCBUILTIN PF_runclientphys(pubprogfuncs_t *prinst, struct globalvars if (pmove.onground) { ent->v->flags = (int)ent->v->flags | FL_ONGROUND; - ent->v->groundentity = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, pmove.physents[pmove.groundent].info)); + ent->v->groundentity = EDICT_TO_PROG(svprogfuncs, EDICT_NUM_PB(svprogfuncs, pmove.physents[pmove.groundent].info)); } else ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND; @@ -9544,7 +9544,7 @@ static void QCBUILTIN PF_runclientphys(pubprogfuncs_t *prinst, struct globalvars if (pmove.physents[pmove.touchindex[i]].notouch) continue; n = pmove.physents[pmove.touchindex[i]].info; - touched = EDICT_NUM(svprogfuncs, n); + touched = EDICT_NUM_PB(svprogfuncs, n); if (!touched->v->touch || n >= playertouchmax || (playertouch[n/8]&(1<<(n%8)))) continue; diff --git a/engine/server/pr_lua.c b/engine/server/pr_lua.c index 16df2402f..358bc91c4 100644 --- a/engine/server/pr_lua.c +++ b/engine/server/pr_lua.c @@ -51,13 +51,14 @@ globalfunc (true, PutClientInServer) \ globalfunc (true, ClientDisconnect) \ globalfunc (false, SetNewParms) \ - globalfunc (false, SetChangeParms) + globalfunc (false, SetChangeParms) \ + globalfloat (false, dimension_default) \ + globalvec (false, global_gravitydir) //any globals or functions that the server might want access to need to be known also. #define luaextragloballist \ globalstring (true, startspot) \ - globalstring (true, ClientReEnter) \ - globalfloat (false, dimension_default) + globalfunc (true, ClientReEnter) typedef struct { @@ -75,6 +76,8 @@ luaextragloballist #undef globalstring #undef globalvec #undef globalfunc + + float parm[NUM_SPAWN_PARMS]; } luaglobalvars_t; typedef struct @@ -85,12 +88,105 @@ typedef struct bucket_t buck; } luafld_t; +//#define LIBLUA_STATIC + +#ifdef LIBLUA_STATIC + #ifdef _MSC_VER + #pragma comment(lib, "liblua.lib") + #endif + #include + //#include + #include +#else typedef struct lua_State lua_State; typedef void *(QDECL *lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); typedef const char *(QDECL *lua_Reader)(lua_State *L, void *data, size_t *size); typedef int (QDECL *lua_CFunction) (lua_State *L); typedef double lua_Number; -typedef int lua_Integer; +typedef long long lua_Integer; + + +#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) +#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) +#define lua_pop(L,n) lua_settop(L, -(n)-1) +#define lua_pushstring(L,s) lua_pushfstring(L,"%s",s) + +//#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) +#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) +#define lua_pushglobaltable(L) (lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)) +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define LUA_TNONE (-1) +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 +#define LUA_NUMTAGS 9 + +#define LUA_RIDX_GLOBALS 2 + +#define LUA_REGISTRYINDEX (-1000000 - 1000) + +#define lua_newstate lua.newstate +#define lua_atpanic lua.atpanic +#define lua_close lua.close +#define lua_load lua.load +#define lua_pcallk lua.pcallk +#define lua_callk lua.callk +#define lua_getfield lua.getfield +#define lua_setfield lua.setfield +#define lua_gettable lua.gettable +#define lua_settable lua.settable +#define lua_getglobal lua.getglobal +#define lua_setglobal lua.setglobal +#define lua_error lua.error +#define lua_type lua.type +#define lua_typename lua.typename +#define lua_rawget lua.rawget +#define lua_rawgeti lua.rawgeti +#define lua_rawgetp lua.rawgetp +#define lua_rawset lua.rawset +#define lua_createtable lua.createtable +#define lua_setmetatable lua.setmetatable +#define lua_newuserdata lua.newuserdata + +#define lua_copy lua.copy +#define lua_gettop lua.gettop +#define lua_settop lua.settop +#define lua_pushboolean lua.pushboolean +#define lua_pushnil lua.pushnil +#define lua_pushnumber lua.pushnumber +#define lua_pushinteger lua.pushinteger +#define lua_pushvalue lua.pushvalue +#define lua_pushcclosure lua.pushcclosure +#define lua_pushfstring lua.pushfstring +#define lua_pushliteral lua_pushstring +#define lua_pushlightuserdata lua.pushlightuserdata +#define lua_tolstring lua.tolstring +#define lua_toboolean lua.toboolean +#define lua_tonumberx lua.tonumberx +#define lua_tointegerx lua.tointegerx +#define lua_topointer lua.topointer +#define lua_touserdata lua.touserdata +#define lua_touserdata lua.touserdata +#define lua_next lua.next +//#define lua_remove lua.remove + +#define luaL_callmeta lua.Lcallmeta +#define luaL_newmetatable lua.Lnewmetatable + +#define lua_newtable(L) lua_createtable(L,0,0) +#define lua_pushcfunction(L,f) lua_pushcclosure(L,f,0) +#define lua_isnil(L,i) (lua_type(L,i)==LUA_TNIL) +#define lua_tostring(L,i) lua_tolstring(L,i,NULL) +#define lua_tonumber(L,i) lua_tonumberx(L,i,NULL) +#define lua_tointeger(L,i) lua_tointegerx(L,i,NULL) +#endif //I'm using this struct for all the global stuff. static struct @@ -101,12 +197,16 @@ static struct progexterns_t progfuncsparms; edict_t **edicttable; unsigned int maxedicts; + luaglobalvars_t globals; //internal global structure hashtable_t globalfields; //name->luafld_t luafld_t globflds[1024]; //fld->offset+type + hashtable_t entityfields; //name->luafld_t luafld_t entflds[1024]; //fld->offset+type + size_t numflds; +#ifndef LIBLUA_STATIC qboolean triedlib; dllhandle_t *lib; @@ -125,13 +225,16 @@ static struct int (QDECL *error) (lua_State *L); int (QDECL *type) (lua_State *L, int idx); const char *(QDECL *typename) (lua_State *L, int tp); - void (QDECL *rawget) (lua_State *L, int idx); + int (QDECL *rawget) (lua_State *L, int idx); + int (QDECL *rawgeti) (lua_State *L, int idx, lua_Integer n); + int (QDECL *rawgetp) (lua_State *L, int idx, const void *p); void (QDECL *rawset) (lua_State *L, int idx); void (QDECL *createtable) (lua_State *L, int narr, int nrec); int (QDECL *setmetatable) (lua_State *L, int objindex); void *(QDECL *newuserdata) (lua_State *L, size_t usize); - void (QDECL *replace) (lua_State *L, int idx); + void (QDECL *copy) (lua_State *L, int fromidx, int toidx); //added in 5.3 +// void (QDECL *replace) (lua_State *L, int idx); //removed in 5.3 int (QDECL *gettop) (lua_State *L); int (QDECL *settop) (lua_State *L, int idx); void (QDECL *pushboolean) (lua_State *L, int b); @@ -148,31 +251,17 @@ static struct lua_Integer (QDECL *tointegerx) (lua_State *L, int idx, int *isnum); const void *(QDECL *topointer) (lua_State *L, int idx); void *(QDECL *touserdata) (lua_State *L, int idx); + int (QDECL *next) (lua_State *L, int idx); +// void (QDECL *remove) (lua_State *L, int idx); int (QDECL *Lcallmeta) (lua_State *L, int obj, const char *e); int (QDECL *Lnewmetatable) (lua_State *L, const char *tname); +#endif } lua; -#define pcall(L,n,r,f) pcallk(L, (n), (r), (f), 0, NULL) -#define call(L,n,r) callk(L, (n), (r), 0, NULL) -#define pop(L,n) settop(L, -(n)-1) -#define pushstring(L,s) pushfstring(L,"%s",s) - -#define LUA_TNONE (-1) -#define LUA_TNIL 0 -#define LUA_TBOOLEAN 1 -#define LUA_TLIGHTUSERDATA 2 -#define LUA_TNUMBER 3 -#define LUA_TSTRING 4 -#define LUA_TTABLE 5 -#define LUA_TFUNCTION 6 -#define LUA_TUSERDATA 7 -#define LUA_TTHREAD 8 -#define LUA_NUMTAGS 9 - -#define LUA_REGISTRYINDEX (-1000000 - 1000) static qboolean init_lua(void) { +#ifndef LIBLUA_STATIC if (!lua.triedlib) { dllfunction_t luafuncs[] = @@ -193,12 +282,15 @@ static qboolean init_lua(void) {(void*)&lua.type, "lua_type"}, {(void*)&lua.typename, "lua_typename"}, {(void*)&lua.rawget, "lua_rawget"}, + {(void*)&lua.rawgeti, "lua_rawgeti"}, + {(void*)&lua.rawgetp, "lua_rawgetp"}, {(void*)&lua.rawset, "lua_rawset"}, {(void*)&lua.createtable, "lua_createtable"}, {(void*)&lua.setmetatable, "lua_setmetatable"}, {(void*)&lua.newuserdata, "lua_newuserdata"}, - - {(void*)&lua.replace, "lua_replace"}, + + {(void*)&lua.copy, "lua_copy"}, +// {(void*)&lua.replace, "lua_replace"}, {(void*)&lua.gettop, "lua_gettop"}, {(void*)&lua.settop, "lua_settop"}, {(void*)&lua.pushboolean, "lua_pushboolean"}, @@ -215,6 +307,8 @@ static qboolean init_lua(void) {(void*)&lua.tointegerx, "lua_tointegerx"}, {(void*)&lua.topointer, "lua_topointer"}, {(void*)&lua.touserdata, "lua_touserdata"}, + {(void*)&lua.next, "lua_next"}, +// {(void*)&lua.remove, "lua_remove"}, {(void*)&lua.Lcallmeta, "luaL_callmeta"}, {(void*)&lua.Lnewmetatable, "luaL_newmetatable"}, @@ -222,12 +316,67 @@ static qboolean init_lua(void) {NULL, NULL} }; lua.triedlib = true; - lua.lib = Sys_LoadLibrary("lua52", luafuncs); + lua.lib = Sys_LoadLibrary("lua53", luafuncs); } if (!lua.lib) return false; +#endif return true; } +char *QDECL Lua_AddString(pubprogfuncs_t *prinst, const char *val, int minlength, pbool demarkup); + +static void lua_pushedict(lua_State *L, struct edict_s *ent) +{ + lua_rawgetp(L, LUA_REGISTRYINDEX, ent); +} + +static void lua_debugstack(lua_State *L) +{ + int idx; + int top = lua_gettop(L); + for (idx = 1; idx <= top; idx++) + { + if (luaL_callmeta(L, idx, "__tostring")) + { + Con_Printf("Stack%i: %s\n", idx, lua_tolstring(L, -1, NULL)); + lua_pop(L, 1); + } + else + { + int t = lua_type(L, idx); + switch (t) + { + case LUA_TNUMBER: + Con_Printf("Stack%i: %g\n", idx, lua_tonumber(L, idx)); + break; + case LUA_TSTRING: + Con_Printf("Stack%i: %s\n", idx, lua_tolstring(L, idx, NULL)); + break; + case LUA_TBOOLEAN: + Con_Printf("Stack%i: %s\n", idx, (lua_toboolean(L, idx) ? "true" : "false")); + break; + case LUA_TNIL: + Con_Printf("Stack%i: %s\n", idx, "nil"); + break; + case LUA_TTABLE: + //special check for things that look like vectors. + lua_getfield(L, idx, "x"); + lua_getfield(L, idx, "y"); + lua_getfield(L, idx, "z"); + if (lua_type(L, -3) == LUA_TNUMBER && lua_type(L, -2) == LUA_TNUMBER && lua_type(L, -1) == LUA_TNUMBER) + { + Con_Printf("Stack%i: '%f %f %f'\n", idx, lua_tonumberx(L, -3, NULL), lua_tonumberx(L, -2, NULL), lua_tonumberx(L, -1, NULL)); + lua_pop(L, 3); + break; + } + lua_pop(L, 3); + default: + Con_Printf("Stack%i: %s: %p\n", idx, lua_typename(L, lua_type(L, idx)), lua_topointer(L, idx)); + break; + } + } + } +} static void *my_lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { @@ -247,107 +396,109 @@ const char * my_lua_Reader(lua_State *L, void *data, size_t *size) } //replace lua's standard 'print' function to use the console instead of stdout. intended to use the same linebreak rules. -static int my_lua_print(lua_State *L) +static int bi_lua_print(lua_State *L) { //the problem is that we can only really accept strings here. //so lets just use the tostring function to make sure things are actually readable as strings. - int args = lua.gettop(L); + int args = lua_gettop(L); int i; const char *s; - lua.getglobal(L, "tostring"); + lua_getglobal(L, "tostring"); //args now start at 1 for(i = 1; i <= args; i++) { - lua.pushvalue(L, -1); - lua.pushvalue(L, i); - lua.pcall(L, 1, 1, 0); //pops args+func - s = lua.tolstring(L, -1, NULL); + lua_pushvalue(L, -1); + lua_pushvalue(L, i); + lua_pcall(L, 1, 1, 0); //pops args+func + s = lua_tolstring(L, -1, NULL); if(s == NULL) s = "?"; if(i > 1) Con_Printf("\t"); Con_Printf("%s", s); - lua.pop(L, 1); //pop our lstring + lua_pop(L, 1); //pop our lstring }; - lua.pop(L, 1); //pop the cached tostring. + lua_pop(L, 1); //pop the cached tostring. Con_Printf("\n"); return 0; }; //more like quakec's print -static int my_lua_conprint(lua_State *L) +static int bi_lua_conprint(lua_State *L) { //the problem is that we can only really accept strings here. //so lets just use the tostring function to make sure things are actually readable as strings. - int args = lua.gettop(L); + int args = lua_gettop(L); int i; const char *s; - lua.getglobal(L, "tostring"); + lua_getglobal(L, "tostring"); //args start at stack index 1 for(i = 1; i <= args; i++) { - lua.pushvalue(L, -1); //dupe the tostring - lua.pushvalue(L, i); //dupe the argument - lua.pcall(L, 1, 1, 0); //pops args+func, pushes the string result - s = lua.tolstring(L, -1, NULL); + lua_pushvalue(L, -1); //dupe the tostring + lua_pushvalue(L, i); //dupe the argument + lua_pcall(L, 1, 1, 0); //pops args+func, pushes the string result + s = lua_tolstring(L, -1, NULL); if(s == NULL) s = "?"; Con_Printf("%s", s); - lua.pop(L, 1); //pop our lstring + lua_pop(L, 1); //pop our lstring }; - lua.pop(L, 1); //pop the cached tostring. + lua_pop(L, 1); //pop the cached tostring. return 0; }; static int bi_lua_dprint(lua_State *L) { if (!developer.ival) return 0; - return my_lua_conprint(L); + return bi_lua_conprint(L); } //taken from lua's baselib.c, with dependancies reduced a little. -static int my_lua_tostring(lua_State *L) +static int bi_lua_tostring(lua_State *L) { -// if (lua.type(L, 1) == LUA_TNONE) +// if (lua_type(L, 1) == LUA_TNONE) // luaL_argerror(L, narg, "value expected"); - if (lua.Lcallmeta(L, 1, "__tostring")) + if (luaL_callmeta(L, 1, "__tostring")) return 1; - switch (lua.type(L, 1)) + switch (lua_type(L, 1)) { case LUA_TNUMBER: - lua.pushfstring(L, lua.tolstring(L, 1, NULL)); + lua_pushfstring(L, lua_tolstring(L, 1, NULL)); break; case LUA_TSTRING: - lua.pushvalue(L, 1); + lua_pushvalue(L, 1); break; case LUA_TBOOLEAN: - lua.pushstring(L, (lua.toboolean(L, 1) ? "true" : "false")); + lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); break; case LUA_TNIL: - lua.pushstring(L, "nil"); + lua_pushstring(L, "nil"); break; case LUA_TTABLE: //special check for things that look like vectors. - lua.getfield(L, 1, "x"); - lua.getfield(L, 1, "y"); - lua.getfield(L, 1, "z"); - if (lua.type(L, -3) == LUA_TNUMBER && lua.type(L, -2) == LUA_TNUMBER && lua.type(L, -1) == LUA_TNUMBER) + lua_getfield(L, 1, "x"); + lua_getfield(L, 1, "y"); + lua_getfield(L, 1, "z"); + if (lua_type(L, -3) == LUA_TNUMBER && lua_type(L, -2) == LUA_TNUMBER && lua_type(L, -1) == LUA_TNUMBER) { - lua.pushfstring(L, "'%g %g %g'", lua.tonumberx(L, -3, NULL), lua.tonumberx(L, -2, NULL), lua.tonumberx(L, -1, NULL)); + lua_pushfstring(L, "'%g %g %g'", lua_tonumberx(L, -3, NULL), lua_tonumberx(L, -2, NULL), lua_tonumberx(L, -1, NULL)); return 1; } //fallthrough default: - lua.pushfstring(L, "%s: %p", lua.typename(L, lua.type(L, 1)), lua.topointer(L, 1)); + lua_pushfstring(L, "%s: %p", lua_typename(L, lua_type(L, 1)), lua_topointer(L, 1)); break; } return 1; } +#define bi_lua_vtos bi_lua_tostring +#define bi_lua_ftos bi_lua_tostring static int my_lua_panic(lua_State *L) { - const char *s = lua.tolstring(L, -1, NULL); + const char *s = lua_tolstring(L, -1, NULL); Sys_Error("lua error: %s", s); } @@ -356,13 +507,13 @@ static int my_lua_entity_eq(lua_State *L) //table1=1 //table2=2 unsigned int entnum1, entnum2; - lua.getfield(L, 1, "entnum"); - entnum1 = lua.tointegerx(L, -1, NULL); - lua.getfield(L, 2, "entnum"); - entnum2 = lua.tointegerx(L, -1, NULL); - lua.pop(L, 2); + lua_getfield(L, 1, "entnum"); + entnum1 = lua_tointegerx(L, -1, NULL); + lua_getfield(L, 2, "entnum"); + entnum2 = lua_tointegerx(L, -1, NULL); + lua_pop(L, 2); - lua.pushboolean(L, entnum1 == entnum2); + lua_pushboolean(L, entnum1 == entnum2); return 1; } @@ -370,22 +521,38 @@ static int my_lua_entity_tostring(lua_State *L) { //table=1 unsigned int entnum; - lua.getfield(L, 1, "entnum"); - entnum = lua.tointegerx(L, -1, NULL); - lua.pop(L, 1); + lua_getfield(L, 1, "entnum"); + entnum = lua_tointegerx(L, -1, NULL); + lua_pop(L, 1); - lua.pushstring(L, va("entity: %u", entnum)); + lua_pushstring(L, va("entity: %u", entnum)); return 1; } -static void lua_readvector(lua_State *L, int idx, float *result) +static int my_lua_vec3_tostring(lua_State *L) { - switch(lua.type(L, idx)) + //table=1 + lua_Number x,y,z; + lua_getfield(L, 1, "x"); + x = lua_tonumber(L, -1); + lua_getfield(L, 1, "y"); + y = lua_tonumber(L, -1); + lua_getfield(L, 1, "z"); + z = lua_tonumber(L, -1); + lua_pop(L, 3); + + lua_pushstring(L, va("'%g %g %g'", x, y, z)); + return 1; +} + +static qboolean lua_readvector(lua_State *L, int idx, float *result) +{ + switch(lua_type(L, idx)) { case LUA_TSTRING: { //we parse strings primnarily for easy .ent(or bsp) loading support. - const char *str = lua.tolstring(L, idx, NULL); + const char *str = lua_tolstring(L, idx, NULL); str = COM_Parse(str); result[0] = atof(com_token); str = COM_Parse(str); @@ -393,15 +560,20 @@ static void lua_readvector(lua_State *L, int idx, float *result) str = COM_Parse(str); result[2] = atof(com_token); } - break; + return true; case LUA_TTABLE: - lua.getfield(L, idx, "x"); - result[0] = lua.tonumberx(L, -1, NULL); - lua.getfield(L, idx, "y"); - result[1] = lua.tonumberx(L, -1, NULL); - lua.getfield(L, idx, "z"); - result[2] = lua.tonumberx(L, -1, NULL); - lua.pop(L, 3); + lua_getfield(L, idx, "x"); + result[0] = lua_tonumberx(L, -1, NULL); + lua_getfield(L, idx, "y"); + result[1] = lua_tonumberx(L, -1, NULL); + lua_getfield(L, idx, "z"); + result[2] = lua_tonumberx(L, -1, NULL); + lua_pop(L, 3); + return true; + case LUA_TNUMBER: + result[0] = + result[1] = + result[2] = lua_tonumber(L, idx); break; case LUA_TNIL: result[0] = 0; @@ -409,8 +581,68 @@ static void lua_readvector(lua_State *L, int idx, float *result) result[2] = 0; break; default: - Con_Printf("Expected vector, got something that wasn't\n"); + Con_Printf("Expected vector, got %s\n", lua_typename(L, lua_type(L, idx))); + result[0] = 0; + result[1] = 0; + result[2] = 0; + break; } + return false; +} +static void lua_pushvector(lua_State *L, vec_t x, vec_t y, vec_t z) +{ + lua_newtable(L); + //FIXME: should provide a metatable with a __tostring + lua_pushnumber(L, x); + lua_setfield (L, -2, "x"); + lua_pushnumber(L, y); + lua_setfield (L, -2, "y"); + lua_pushnumber(L, z); + lua_setfield (L, -2, "z"); + + luaL_getmetatable(L, "vec3_t"); + lua_setmetatable(L, -2); +} + +static int my_lua_vec3_eq(lua_State *L) +{ + vec3_t a, b; + lua_readvector(L, 1, a); + lua_readvector(L, 2, b); + lua_pushboolean(L, a[0]==b[0] && a[1]==b[1] && a[2]==b[2]); + return 1; +} +static int my_lua_vec3_sub(lua_State *L) +{ + vec3_t a, b; + lua_readvector(L, 1, a); + lua_readvector(L, 2, b); + lua_pushvector(L, a[0]-b[0], a[1]-b[1], a[2]-b[2]); + return 1; +} +static int my_lua_vec3_mul(lua_State *L) +{ + vec3_t a, b; + if (lua_readvector(L, 1, a) + lua_readvector(L, 2, b) == 2) + lua_pushnumber(L, DotProduct(a,b)); //vec*vec is a dotproduct + else + lua_pushvector(L, a[0]*b[0], a[1]*b[1], a[2]*b[2]); //one arg is a scaler. woot. + return 1; +} +static int my_lua_vec3_add(lua_State *L) +{ + vec3_t a, b; + lua_readvector(L, 1, a); + lua_readvector(L, 2, b); + lua_pushvector(L, a[0]+b[0], a[1]+b[1], a[2]+b[2]); + return 1; +} +static int my_lua_vec3_len(lua_State *L) +{ + vec3_t a; + lua_readvector(L, 1, a); + lua_pushnumber(L, VectorLength(a)); + return 1; } static int my_lua_entity_set(lua_State *L) //__newindex @@ -421,60 +653,60 @@ static int my_lua_entity_set(lua_State *L) //__newindex //key=2 //value=3 - if (lua.type(L, 2) == LUA_TSTRING) + if (lua_type(L, 2) == LUA_TSTRING) { - const char *s = lua.tolstring(L, 2, NULL); + const char *s = lua_tolstring(L, 2, NULL); luafld_t *fld = Hash_GetInsensitive(&lua.entityfields, s); eval_t *eval; unsigned int entnum; - if (fld) + if (fld && fld->offset >= 0) { - lua.getfield(L, 1, "entnum"); - entnum = lua.tointegerx(L, -1, NULL); - lua.pop(L, 1); + lua_getfield(L, 1, "entnum"); + entnum = lua_tointegerx(L, -1, NULL); + lua_pop(L, 1); if (entnum < lua.maxedicts && lua.edicttable[entnum] && !ED_ISFREE(lua.edicttable[entnum])) { eval = (eval_t*)((char*)lua.edicttable[entnum]->v + fld->offset); switch(fld->type) { case ev_float: - eval->_float = lua.tonumberx(L, 3, NULL); + eval->_float = lua_tonumberx(L, 3, NULL); return 0; case ev_vector: lua_readvector(L, 3, eval->_vector); return 0; case ev_integer: - eval->_int = lua.tointegerx(L, 3, NULL); + eval->_int = lua_tointegerx(L, 3, NULL); return 0; case ev_function: - if (lua.type(L, 3) == LUA_TNIL) + if (lua_type(L, 3) == LUA_TNIL) eval->function = 0; //so the engine can distinguish between nil and not. else eval->function = fld->offset | ((entnum+1)<<10); - lua.pushlightuserdata(L, (void *)(qintptr_t)fld->offset); //execute only knows a function id, so we need to translate the store to match. - lua.replace(L, 2); - lua.rawset(L, 1); + lua_pushlightuserdata(L, (void *)(qintptr_t)fld->offset); //execute only knows a function id, so we need to translate the store to match. + lua_replace(L, 2); + lua_rawset(L, 1); return 0; case ev_string: - if (lua.type(L, 3) == LUA_TNIL) + if (lua_type(L, 3) == LUA_TNIL) eval->string = 0; //so the engine can distinguish between nil and not. else eval->string = fld->offset | ((entnum+1)<<10); - lua.pushlightuserdata(L, (void *)(qintptr_t)fld->offset); //execute only knows a string id, so we need to translate the store to match. - lua.replace(L, 2); - lua.rawset(L, 1); + lua_pushlightuserdata(L, (void *)(qintptr_t)fld->offset); //execute only knows a string id, so we need to translate the store to match. + lua_replace(L, 2); + lua_rawset(L, 1); return 0; case ev_entity: //read the table's entnum field so we know which one its meant to be. - lua.getfield(L, 3, "entnum"); - eval->edict = lua.tointegerx(L, -1, NULL); + lua_getfield(L, 3, "entnum"); + eval->edict = lua_tointegerx(L, -1, NULL); return 0; } } } } - lua.rawset(L, 1); + lua_rawset(L, 1); return 0; } static int my_lua_entity_get(lua_State *L) //__index @@ -484,48 +716,72 @@ static int my_lua_entity_get(lua_State *L) //__index //table=1 //key=2 - if (lua.type(L, 2) == LUA_TSTRING) + if (lua_type(L, 2) == LUA_TSTRING) { - const char *s = lua.tolstring(L, 2, NULL); + const char *s = lua_tolstring(L, 2, NULL); luafld_t *fld = Hash_GetInsensitive(&lua.entityfields, s); eval_t *eval; int entnum; if (fld) { - lua.getfield(L, 1, "entnum"); - entnum = lua.tointegerx(L, -1, NULL); - lua.pop(L, 1); + if (fld->offset < 0) + { //negative offsets are not real fields, but are just there to ensure that no nils appear + lua_rawget(L, 1); + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + switch(fld->type) + { + case ev_float: + lua_pushnumber(L, 0); + return 1; + case ev_integer: + lua_pushinteger(L, 0); + return 1; + case ev_vector: + lua_pushvector(L, 0, 0, 0); + break; + case ev_function: + default: //no idea + lua_pushnil(L); + break; + case ev_string: + lua_pushliteral(L, ""); + break; + case ev_entity: + lua_pushedict(L, lua.edicttable[0]); + break; + } + } + return 1; + } + lua_getfield(L, 1, "entnum"); + entnum = lua_tointegerx(L, -1, NULL); + lua_pop(L, 1); if (entnum < lua.maxedicts && lua.edicttable[entnum])// && !lua.edicttable[entnum]->isfree) { eval = (eval_t*)((char*)lua.edicttable[entnum]->v + fld->offset); switch(fld->type) { case ev_float: - lua.pushnumber(L, eval->_float); + lua_pushnumber(L, eval->_float); return 1; case ev_integer: - lua.pushinteger(L, eval->_int); + lua_pushinteger(L, eval->_int); return 1; case ev_vector: - lua.createtable(L, 0, 0); - //FIXME: should provide a metatable with a __tostring - lua.pushnumber(L, eval->_vector[0]); - lua.setfield (L, -2, "x"); - lua.pushnumber(L, eval->_vector[1]); - lua.setfield (L, -2, "y"); - lua.pushnumber(L, eval->_vector[2]); - lua.setfield (L, -2, "z"); + lua_pushvector(L, eval->_vector[0], eval->_vector[1], eval->_vector[2]); return 1; case ev_function: case ev_string: - lua.pushlightuserdata(L, (void *)(qintptr_t)(eval->function & 1023)); //execute only knows a function id, so we need to translate the store to match. - lua.replace(L, 2); - lua.rawget(L, 1); + lua_pushlightuserdata(L, (void *)(qintptr_t)(eval->function & 1023)); //execute only knows a function id, so we need to translate the store to match. + lua_replace(L, 2); + lua_rawget(L, 1); return 1; case ev_entity: //return the table for the entity via the lua registry. - lua.pushlightuserdata(lua.ctx, lua.edicttable[eval->edict]); - lua.gettable(lua.ctx, LUA_REGISTRYINDEX); + lua_pushlightuserdata(lua.ctx, lua.edicttable[eval->edict]); + lua_gettable(lua.ctx, LUA_REGISTRYINDEX); return 1; } } @@ -533,8 +789,8 @@ static int my_lua_entity_get(lua_State *L) //__index } //make sure it exists so we don't get called constantly if code loops through stuff that wasn't set. -// lua.pushstring(L, "nil"); - lua.rawget(L, 1); +// lua_pushstring(L, "nil"); + lua_rawget(L, 1); return 1; } static int my_lua_global_set(lua_State *L) //__newindex @@ -545,9 +801,9 @@ static int my_lua_global_set(lua_State *L) //__newindex //key=2 //value=3 - if (lua.type(L, 2) == LUA_TSTRING) + if (lua_type(L, 2) == LUA_TSTRING) { - const char *s = lua.tolstring(L, 2, NULL); + const char *s = lua_tolstring(L, 2, NULL); luafld_t *fld = Hash_GetInsensitive(&lua.globalfields, s); eval_t *eval; if (fld) @@ -556,47 +812,47 @@ static int my_lua_global_set(lua_State *L) //__newindex switch(fld->type) { case ev_float: - eval->_float = lua.tonumberx(L, 3, NULL); + eval->_float = lua_tonumberx(L, 3, NULL); return 0; case ev_vector: - lua.getfield(L, 3, "x"); - eval->_vector[0] = lua.tonumberx(L, -1, NULL); - lua.getfield(L, 3, "y"); - eval->_vector[1] = lua.tonumberx(L, -1, NULL); - lua.getfield(L, 3, "z"); - eval->_vector[2] = lua.tonumberx(L, -1, NULL); + lua_getfield(L, 3, "x"); + eval->_vector[0] = lua_tonumberx(L, -1, NULL); + lua_getfield(L, 3, "y"); + eval->_vector[1] = lua_tonumberx(L, -1, NULL); + lua_getfield(L, 3, "z"); + eval->_vector[2] = lua_tonumberx(L, -1, NULL); return 0; case ev_integer: - eval->_int = lua.tointegerx(L, 3, NULL); + eval->_int = lua_tointegerx(L, 3, NULL); return 0; case ev_function: - if (lua.type(L, 3) == LUA_TNIL) + if (lua_type(L, 3) == LUA_TNIL) eval->function = 0; //so the engine can distinguish between nil and not. else eval->function = fld->offset; - lua.pushlightuserdata(L, (void *)fld->offset); //execute only knows a function id, so we need to translate the store to match. - lua.replace(L, 2); - lua.rawset(L, 1); + lua_pushlightuserdata(L, (void *)fld->offset); //execute only knows a function id, so we need to translate the store to match. + lua_replace(L, 2); + lua_rawset(L, 1); return 0; case ev_string: - if (lua.type(L, 3) == LUA_TNIL) + if (lua_type(L, 3) == LUA_TNIL) eval->string = 0; //so the engine can distinguish between nil and not. else eval->string = fld->offset; - lua.pushlightuserdata(L, (void *)fld->offset); //execute only knows a string id, so we need to translate the store to match. - lua.replace(L, 2); - lua.rawset(L, 1); + lua_pushlightuserdata(L, (void *)fld->offset); //execute only knows a string id, so we need to translate the store to match. + lua_replace(L, 2); + lua_rawset(L, 1); return 0; case ev_entity: //read the table's entnum field so we know which one its meant to be. - lua.getfield(L, 3, "entnum"); - eval->edict = lua.tointegerx(L, -1, NULL); + lua_getfield(L, 3, "entnum"); + eval->edict = lua_tointegerx(L, -1, NULL); return 0; } } } - lua.rawset(L, 1); + lua_rawset(L, 1); return 0; } static int my_lua_global_get(lua_State *L) //__index @@ -606,9 +862,9 @@ static int my_lua_global_get(lua_State *L) //__index //table=1 //key=2 - if (lua.type(L, 2) == LUA_TSTRING) + if (lua_type(L, 2) == LUA_TSTRING) { - const char *s = lua.tolstring(L, 2, NULL); + const char *s = lua_tolstring(L, 2, NULL); luafld_t *fld = Hash_GetInsensitive(&lua.globalfields, s); eval_t *eval; if (fld) @@ -617,25 +873,29 @@ static int my_lua_global_get(lua_State *L) //__index switch(fld->type) { case ev_float: - lua.pushnumber(L, eval->_float); + lua_pushnumber(L, eval->_float); + return 1; + case ev_integer: + lua_pushinteger(L, eval->_int); + return 1; + case ev_vector: + lua_pushvector(L, eval->_vector[0], eval->_vector[1], eval->_vector[2]); return 1; case ev_function: - lua.pushlightuserdata(L, (void *)(qintptr_t)eval->function); //execute only knows a function id, so we need to translate the store to match. - lua.replace(L, 2); - lua.rawget(L, 1); + lua_pushlightuserdata(L, (void *)(qintptr_t)eval->function); //execute only knows a function id, so we need to translate the store to match. + lua_replace(L, 2); + lua_rawget(L, 1); return 1; case ev_entity: - //return the table for the entity via the lua registry. - lua.pushlightuserdata(lua.ctx, lua.edicttable[eval->edict]); - lua.gettable(lua.ctx, LUA_REGISTRYINDEX); + lua_pushedict(L, lua.edicttable[eval->edict]); return 1; } } } //make sure it exists so we don't get called constantly if code loops through stuff that wasn't set. -// lua.pushstring(L, "nil"); - lua.rawget(L, 1); +// lua_pushstring(L, "nil"); + lua_rawget(L, 1); return 1; } @@ -643,47 +903,53 @@ static int bi_lua_setmodel(lua_State *L) { int entnum; edict_t *e; - lua.getfield(L, 1, "entnum"); - entnum = lua.tointegerx(L, -1, NULL); + lua_getfield(L, 1, "entnum"); + entnum = lua_tointegerx(L, -1, NULL); e = (entnum>=lua.maxedicts)?NULL:lua.edicttable[entnum]; - PF_setmodel_Internal(&lua.progfuncs, e, lua.tolstring(L, 2, NULL)); + PF_setmodel_Internal(&lua.progfuncs, e, lua_tolstring(L, 2, NULL)); return 0; } static int bi_lua_precache_model(lua_State *L) { - PF_precache_model_Internal(&lua.progfuncs, lua.tolstring(L, 1, NULL), false); + PF_precache_model_Internal(&lua.progfuncs, lua_tolstring(L, 1, NULL), false); return 0; } +#define bi_lua_precache_model2 bi_lua_precache_model static int bi_lua_precache_sound(lua_State *L) { - PF_precache_sound_Internal(&lua.progfuncs, lua.tolstring(L, 1, NULL)); + PF_precache_sound_Internal(&lua.progfuncs, lua_tolstring(L, 1, NULL)); + return 0; +} +#define bi_lua_precache_sound2 bi_lua_precache_sound +static int bi_lua_precache_file(lua_State *L) +{ return 0; } static int bi_lua_lightstyle(lua_State *L) { vec3_t rgb; - lua_readvector(L, 3, rgb); - PF_applylightstyle(lua.tointegerx(L, 1, NULL), lua.tolstring(L, 2, NULL), rgb); + if (lua_gettop(L) >= 3) + lua_readvector(L, 3, rgb); + else + VectorSet(rgb, 1, 1, 1); + PF_applylightstyle(lua_tointegerx(L, 1, NULL), lua_tolstring(L, 2, NULL), rgb); return 0; } static int bi_lua_spawn(lua_State *L) { edict_t *e = lua.progfuncs.EntAlloc(&lua.progfuncs, false, 0); if (e) - { - lua.pushlightuserdata(L, e); - lua.gettable(L, LUA_REGISTRYINDEX); - } + lua_pushedict(L, e); else - lua.pushnil(L); + lua_pushnil(L); return 1; } static int bi_lua_remove(lua_State *L) { int entnum; edict_t *e; - lua.getfield(L, 1, "entnum"); - entnum = lua.tointegerx(L, -1, NULL); + lua_getfield(L, 1, "entnum"); + entnum = lua_tointegerx(L, -1, NULL); e = (entnum>=lua.maxedicts)?NULL:lua.edicttable[entnum]; if (e) lua.progfuncs.EntFree(&lua.progfuncs, e); @@ -692,8 +958,8 @@ static int bi_lua_remove(lua_State *L) static int bi_lua_setorigin(lua_State *L) { edict_t *e; - lua.getfield(L, 1, "entnum"); - e = EDICT_NUM((&lua.progfuncs), lua.tointegerx(L, -1, NULL)); + lua_getfield(L, 1, "entnum"); + e = EDICT_NUM_UB((&lua.progfuncs), lua_tointegerx(L, -1, NULL)); lua_readvector(L, 2, e->v->origin); World_LinkEdict (&sv.world, (wedict_t*)e, false); return 0; @@ -701,8 +967,8 @@ static int bi_lua_setorigin(lua_State *L) static int bi_lua_setsize(lua_State *L) { edict_t *e; - lua.getfield(L, 1, "entnum"); - e = EDICT_NUM((&lua.progfuncs), lua.tointegerx(L, -1, NULL)); + lua_getfield(L, 1, "entnum"); + e = EDICT_NUM_UB((&lua.progfuncs), lua_tointegerx(L, -1, NULL)); lua_readvector(L, 2, e->v->mins); lua_readvector(L, 3, e->v->maxs); VectorSubtract (e->v->maxs, e->v->mins, e->v->size); @@ -712,7 +978,7 @@ static int bi_lua_setsize(lua_State *L) static int bi_lua_localcmd(lua_State *L) { - const char *str = lua.tolstring(lua.ctx, 1, NULL); + const char *str = lua_tolstring(lua.ctx, 1, NULL); Cbuf_AddText (str, RESTRICT_INSECURE); return 0; } @@ -725,16 +991,16 @@ static int bi_lua_changelevel(lua_State *L) return 0; sv.mapchangelocked = true; - if (lua.type(L, 2) == LUA_TSTRING) //and not nil or none + if (lua_type(L, 2) == LUA_TSTRING) //and not nil or none { - s = lua.tolstring(lua.ctx, 1, NULL); - spot = lua.tolstring(lua.ctx, 2, NULL); + s = lua_tolstring(lua.ctx, 1, NULL); + spot = lua_tolstring(lua.ctx, 2, NULL); Cbuf_AddText (va("\nchangelevel %s %s\n",s, spot), RESTRICT_LOCAL); } else { - s = lua.tolstring(lua.ctx, 1, NULL); - Cbuf_AddText (va("\nmap %s\n",s), RESTRICT_LOCAL); + s = lua_tolstring(lua.ctx, 1, NULL); + Cbuf_AddText (va("\nchangelevel %s\n",s), RESTRICT_LOCAL); } return 0; } @@ -743,9 +1009,9 @@ static int bi_lua_stuffcmd(lua_State *L) { int entnum; const char *str; - lua.getfield(L, 1, "entnum"); - entnum = lua.tointegerx(L, -1, NULL); - str = lua.tolstring(L, 2, NULL); + lua_getfield(L, 1, "entnum"); + entnum = lua_tointegerx(L, -1, NULL); + str = lua_tolstring(L, 2, NULL); PF_stuffcmd_Internal(entnum, str, 0); return 0; @@ -754,10 +1020,11 @@ static int bi_lua_centerprint(lua_State *L) { int entnum; const char *str; - lua.getfield(L, 1, "entnum"); - entnum = lua.tointegerx(L, -1, NULL); - str = lua.tolstring(L, 2, NULL); - + lua_getfield(L, 1, "entnum"); + entnum = lua_tointegerx(L, -1, NULL); + str = lua_tolstring(L, 2, NULL); + if (!str) + str = ""; PF_centerprint_Internal(entnum, false, str); return 0; } @@ -765,35 +1032,36 @@ static int bi_lua_getinfokey(lua_State *L) { int entnum; const char *key; - lua.getfield(L, 1, "entnum"); - entnum = lua.tointegerx(L, -1, NULL); - key = lua.tolstring(L, 2, NULL); + lua_getfield(L, 1, "entnum"); + entnum = lua_tointegerx(L, -1, NULL); + key = lua_tolstring(L, 2, NULL); key = PF_infokey_Internal(entnum, key); - lua.pushstring(L, key); + lua_pushstring(L, key); return 1; } +#define bi_lua_infokey bi_lua_getinfokey static int bi_lua_setinfokey(lua_State *L) { int entnum; const char *key; const char *value; int result; - lua.getfield(L, 1, "entnum"); - entnum = lua.tointegerx(L, -1, NULL); - key = lua.tolstring(L, 2, NULL); - value = lua.tolstring(L, 3, NULL); + lua_getfield(L, 1, "entnum"); + entnum = lua_tointegerx(L, -1, NULL); + key = lua_tolstring(L, 2, NULL); + value = lua_tolstring(L, 3, NULL); result = PF_ForceInfoKey_Internal(entnum, key, value); - lua.pushinteger(L, result); + lua_pushinteger(L, result); return 1; } static int bi_lua_ambientsound(lua_State *L) { vec3_t pos; - const char *samp = lua.tolstring(L, 2, NULL); - float vol = lua.tonumberx(L, 3, NULL); - float attenuation = lua.tonumberx(L, 4, NULL); + const char *samp = lua_tolstring(L, 2, NULL); + float vol = lua_tonumberx(L, 3, NULL); + float attenuation = lua_tonumberx(L, 4, NULL); lua_readvector(L, 1, pos); PF_ambientsound_Internal(pos, samp, vol, attenuation); @@ -802,17 +1070,17 @@ static int bi_lua_ambientsound(lua_State *L) static int bi_lua_sound(lua_State *L) { int entnum; - float channel = lua.tonumberx(L, 2, NULL); - const char *samp = lua.tolstring(L, 3, NULL); - float volume = lua.tonumberx(L, 4, NULL); - float attenuation = lua.tonumberx(L, 5, NULL); + float channel = lua_tonumberx(L, 2, NULL); + const char *samp = lua_tolstring(L, 3, NULL); + float volume = lua_tonumberx(L, 4, NULL); + float attenuation = lua_tonumberx(L, 5, NULL); - lua.getfield(L, 1, "entnum"); - entnum = lua.tointegerx(L, -1, NULL); + lua_getfield(L, 1, "entnum"); + entnum = lua_tointegerx(L, -1, NULL); //note: channel & 256 == reliable - SVQ1_StartSound (NULL, (wedict_t*)EDICT_NUM((&lua.progfuncs), entnum), channel, samp, volume*255, attenuation, 0, 0, 0); + SVQ1_StartSound (NULL, (wedict_t*)EDICT_NUM_UB((&lua.progfuncs), entnum), channel, samp, volume*255, attenuation, 0, 0, 0); return 0; } @@ -820,7 +1088,7 @@ static int bi_lua_pointcontents(lua_State *L) { vec3_t pos; lua_readvector(L, 1, pos); - lua.pushinteger(L, sv.world.worldmodel->funcs.PointContents(sv.world.worldmodel, NULL, pos)); + lua_pushinteger(L, sv.world.worldmodel->funcs.PointContents(sv.world.worldmodel, NULL, pos)); return 1; } @@ -828,8 +1096,8 @@ static int bi_lua_setspawnparms(lua_State *L) { globalvars_t pr_globals; - lua.getfield(L, 1, "entnum"); - pr_globals.param[0].i = lua.tointegerx(L, -1, NULL); + lua_getfield(L, 1, "entnum"); + pr_globals.param[0].i = lua_tointegerx(L, -1, NULL); PF_setspawnparms(&lua.progfuncs, &pr_globals); return 0; } @@ -837,8 +1105,8 @@ static int bi_lua_makestatic(lua_State *L) { globalvars_t pr_globals; - lua.getfield(L, 1, "entnum"); - pr_globals.param[0].i = lua.tointegerx(L, -1, NULL); + lua_getfield(L, 1, "entnum"); + pr_globals.param[0].i = lua_tointegerx(L, -1, NULL); PF_makestatic(&lua.progfuncs, &pr_globals); return 0; } @@ -872,14 +1140,14 @@ static int bi_lua_droptofloor(lua_State *L) trace = World_Move (world, start, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent); if (trace.fraction == 1 || trace.allsolid) - lua.pushboolean(L, false); + lua_pushboolean(L, false); else { VectorCopy (trace.endpos, ent->v->origin); World_LinkEdict (world, ent, false); ent->v->flags = (int)ent->v->flags | FL_ONGROUND; ent->v->groundentity = EDICT_TO_PROG(prinst, trace.ent); - lua.pushboolean(L, true); + lua_pushboolean(L, true); } return 1; } @@ -889,28 +1157,52 @@ static int bi_lua_checkbottom(lua_State *L) qboolean okay; int entnum; vec3_t up = {0,0,1}; - lua.getfield(L, 1, "entnum"); - entnum = lua.tointegerx(L, -1, NULL); - okay = World_CheckBottom(&sv.world, (wedict_t*)EDICT_NUM((&lua.progfuncs), entnum), up); - lua.pushboolean(L, okay); + lua_getfield(L, 1, "entnum"); + entnum = lua_tointegerx(L, -1, NULL); + okay = World_CheckBottom(&sv.world, (wedict_t*)EDICT_NUM_UB((&lua.progfuncs), entnum), up); + lua_pushboolean(L, okay); return 1; } -static int bi_lua_bprint(lua_State *L) +static int bi_lua_bprint_qw(lua_State *L) { - int level = lua.tointegerx(L, 1, NULL); - const char *str = lua.tolstring(L, 2, NULL); + int level = lua_tointegerx(L, 1, NULL); + const char *str = lua_tolstring(L, 2, NULL); SV_BroadcastPrintf (level, "%s", str); return 0; } -static int bi_lua_sprint(lua_State *L) +static int bi_lua_bprint_nq(lua_State *L) +{ + int level = PRINT_HIGH; + const char *str = lua_tolstring(L, 1, NULL); + SV_BroadcastPrintf (level, "%s", str); + return 0; +} +static int bi_lua_sprint_qw(lua_State *L) { int entnum; - int level = lua.tointegerx(L, 2, NULL); - const char *str = lua.tolstring(L, 3, NULL); + int level = lua_tointegerx(L, 2, NULL); + const char *str = lua_tolstring(L, 3, NULL); - lua.getfield(L, 1, "entnum"); - entnum = lua.tointegerx(L, -1, NULL); + lua_getfield(L, 1, "entnum"); + entnum = lua_tointegerx(L, -1, NULL); + + if (entnum < 1 || entnum > sv.allocated_client_slots) + { + Con_TPrintf ("tried to sprint to a non-client\n"); + return 0; + } + SV_ClientPrintf (&svs.clients[entnum-1], level, "%s", str); + return 0; +} +static int bi_lua_sprint_nq(lua_State *L) +{ + int entnum; + int level = PRINT_HIGH; + const char *str = lua_tolstring(L, 2, NULL); + + lua_getfield(L, 1, "entnum"); + entnum = lua_tointegerx(L, -1, NULL); if (entnum < 1 || entnum > sv.allocated_client_slots) { @@ -923,8 +1215,8 @@ static int bi_lua_sprint(lua_State *L) static int bi_lua_cvar_set(lua_State *L) { - const char *name = lua.tolstring(L, 1, NULL); - const char *str = lua.tolstring(L, 2, NULL); + const char *name = lua_tolstring(L, 1, NULL); + const char *str = lua_tolstring(L, 2, NULL); cvar_t *var = Cvar_FindVar(name); if (var) Cvar_Set(var, str); @@ -932,16 +1224,26 @@ static int bi_lua_cvar_set(lua_State *L) } static int bi_lua_cvar_get(lua_State *L) { - const char *name = lua.tolstring(L, 1, NULL); + const char *name = lua_tolstring(L, 1, NULL); cvar_t *var = Cvar_FindVar(name); if (var) - lua.pushstring(L, var->string); + lua_pushstring(L, var->string); else - lua.pushnil(L); - return 0; + lua_pushnil(L); + return 1; +} +static int bi_lua_cvar(lua_State *L) //useless get[float] +{ + const char *name = lua_tolstring(L, 1, NULL); + cvar_t *var = Cvar_FindVar(name); + if (var) + lua_pushnumber(L, var->value); + else + lua_pushnil(L); + return 1; } -static void set_trace_globals(trace_t *trace) +static int pushset_trace_globals(lua_State *L, trace_t *trace) { pr_global_struct->trace_allsolid = trace->allsolid; pr_global_struct->trace_startsolid = trace->startsolid; @@ -961,6 +1263,35 @@ static void set_trace_globals(trace_t *trace) VectorCopy (trace->plane.normal, P_VEC(trace_plane_normal)); pr_global_struct->trace_plane_dist = trace->plane.dist; pr_global_struct->trace_ent = trace->ent?((wedict_t*)trace->ent)->entnum:0; + + + lua_newtable(L); + lua_pushnumber(L, trace->fraction); + lua_setfield(L, -2, "fraction"); + lua_pushvector(L, trace->endpos[0], trace->endpos[1], trace->endpos[2]); + lua_setfield(L, -2, "endpos"); + if (trace->ent) + lua_pushedict(L, trace->ent); + else + lua_pushedict(L, lua.edicttable[0]); + lua_setfield(L, -2, "ent"); + + lua_pushboolean(L, trace->allsolid); + lua_setfield(L, -2, "allsolid"); + lua_pushboolean(L, trace->startsolid); + lua_setfield(L, -2, "startsolid"); + lua_pushboolean(L, trace->inwater); + lua_setfield(L, -2, "inwater"); + lua_pushboolean(L, trace->inopen); + lua_setfield(L, -2, "inopen"); + + lua_newtable(L); + lua_pushnumber(L, trace->plane.dist); + lua_setfield(L, -2, "dist"); + lua_pushvector(L, trace->plane.normal[0], trace->plane.normal[1], trace->plane.normal[2]); + lua_setfield(L, -2, "normal"); + lua_setfield(L, -2, "plane"); + return 1; } static int bi_lua_traceline(lua_State *L) @@ -972,15 +1303,13 @@ static int bi_lua_traceline(lua_State *L) lua_readvector(L, 1, v1); lua_readvector(L, 2, v2); - nomonsters = lua.tointegerx(L, 3, NULL); - lua.getfield(L, 4, "entnum"); - ent = (wedict_t*)EDICT_NUM((&lua.progfuncs), lua.tointegerx(L, -1, NULL)); + nomonsters = lua_tointegerx(L, 3, NULL); + lua_getfield(L, 4, "entnum"); + ent = (wedict_t*)EDICT_NUM_UB((&lua.progfuncs), lua_tointegerx(L, -1, NULL)); trace = World_Move (&sv.world, v1, vec3_origin, vec3_origin, v2, nomonsters|MOVE_IGNOREHULL, (wedict_t*)ent); - //FIXME: should we just return a table instead, and ignore the globals? - set_trace_globals(&trace); - return 0; + return pushset_trace_globals(L, &trace); } static int bi_lua_tracebox(lua_State *L) @@ -994,15 +1323,13 @@ static int bi_lua_tracebox(lua_State *L) lua_readvector(L, 2, v2); lua_readvector(L, 3, mins); lua_readvector(L, 4, maxs); - nomonsters = lua.tointegerx(L, 5, NULL); - lua.getfield(L, 6, "entnum"); - ent = (wedict_t*)EDICT_NUM((&lua.progfuncs), lua.tointegerx(L, -1, NULL)); + nomonsters = lua_tointegerx(L, 5, NULL); + lua_getfield(L, 6, "entnum"); + ent = (wedict_t*)EDICT_NUM_UB((&lua.progfuncs), lua_tointegerx(L, -1, NULL)); trace = World_Move (&sv.world, v1, mins, maxs, v2, nomonsters|MOVE_IGNOREHULL, (wedict_t*)ent); - //FIXME: should we just return a table instead, and ignore the globals? - set_trace_globals(&trace); - return 0; + return pushset_trace_globals(L, &trace); } static int bi_lua_walkmove(lua_State *L) @@ -1016,12 +1343,12 @@ static int bi_lua_walkmove(lua_State *L) vec3_t axis[3]; ent = PROG_TO_WEDICT(prinst, *world->g.self); - yaw = lua.tonumberx(L, 1, NULL); - dist = lua.tonumberx(L, 2, NULL); + yaw = lua_tonumberx(L, 1, NULL); + dist = lua_tonumberx(L, 2, NULL); if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) { - lua.pushboolean(L, false); + lua_pushboolean(L, false); return 1; } @@ -1035,7 +1362,7 @@ static int bi_lua_walkmove(lua_State *L) // save program state, because World_movestep may call other progs oldself = *world->g.self; - lua.pushboolean(L, World_movestep(world, ent, move, axis, true, false, NULL, NULL)); + lua_pushboolean(L, World_movestep(world, ent, move, axis, true, false, NULL, NULL)); // restore program state *world->g.self = oldself; @@ -1049,7 +1376,7 @@ static int bi_lua_movetogoal(lua_State *L) wedict_t *ent; float dist; ent = PROG_TO_WEDICT(prinst, *world->g.self); - dist = lua.tonumberx(L, 1, NULL); + dist = lua_tonumberx(L, 1, NULL); World_MoveToGoal (world, ent, dist); return 0; } @@ -1060,8 +1387,8 @@ static int bi_lua_nextent(lua_State *L) int i; wedict_t *ent; - lua.getfield(L, 1, "entnum"); - i = lua.tointegerx(L, -1, NULL); + lua_getfield(L, 1, "entnum"); + i = lua_tointegerx(L, -1, NULL); while (1) { @@ -1071,14 +1398,13 @@ static int bi_lua_nextent(lua_State *L) ent = world->edicts; break; } - ent = WEDICT_NUM(world->progs, i); + ent = (wedict_t *)lua.edicttable[i]; if (!ED_ISFREE(ent)) { break; } } - lua.pushlightuserdata(L, ent); - lua.gettable(L, LUA_REGISTRYINDEX); + lua_pushedict(L, (struct edict_s *)ent); return 1; } @@ -1088,8 +1414,8 @@ static int bi_lua_nextclient(lua_State *L) int i; wedict_t *ent; - lua.getfield(L, 1, "entnum"); - i = lua.tointegerx(L, -1, NULL); + lua_getfield(L, 1, "entnum"); + i = lua_tointegerx(L, -1, NULL); while (1) { @@ -1099,14 +1425,14 @@ static int bi_lua_nextclient(lua_State *L) ent = world->edicts; break; } - ent = WEDICT_NUM(world->progs, i); + ent = WEDICT_NUM_UB(world->progs, i); if (!ED_ISFREE(ent)) { break; } } - lua.pushlightuserdata(L, ent); - lua.gettable(L, LUA_REGISTRYINDEX); + lua_pushlightuserdata(L, ent); + lua_gettable(L, LUA_REGISTRYINDEX); return 1; } @@ -1114,15 +1440,15 @@ static int bi_lua_checkclient(lua_State *L) { pubprogfuncs_t *prinst = &lua.progfuncs; wedict_t *ent; - ent = WEDICT_NUM(prinst, PF_checkclient_Internal(prinst)); - lua.pushlightuserdata(L, ent); - lua.gettable(L, LUA_REGISTRYINDEX); + ent = WEDICT_NUM_PB(prinst, PF_checkclient_Internal(prinst)); + lua_pushlightuserdata(L, ent); + lua_gettable(L, LUA_REGISTRYINDEX); return 1; } static int bi_lua_random(lua_State *L) { - lua.pushnumber(L, (rand ()&0x7fff) / ((float)0x8000)); + lua_pushnumber(L, (rand ()&0x7fff) / ((float)0x8000)); return 1; } @@ -1133,7 +1459,26 @@ static int bi_lua_makevectors(lua_State *L) //perhaps we should support f,u,l=makevectors(ang)... meh, cba. lua_readvector(L, 1, angles); AngleVectors (angles, pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up); + +#if 1 + //globals suck, and lua allows multi-return. + lua_pushvector(L, (pr_global_struct->v_forward)[0], (pr_global_struct->v_forward)[1], (pr_global_struct->v_forward)[2]); + lua_pushvector(L, (pr_global_struct->v_right)[0], (pr_global_struct->v_right)[1], (pr_global_struct->v_right)[2]); + lua_pushvector(L, (pr_global_struct->v_up)[0], (pr_global_struct->v_up)[1], (pr_global_struct->v_up)[2]); + return 3; +#else return 0; +#endif +} +static int bi_lua_normalize(lua_State *L) +{ + vec3_t v; + lua_readvector(L, 1, v); + + VectorNormalize(v); + + lua_pushvector(L, v[0], v[1], v[2]); + return 1; } static int bi_lua_vectoangles(lua_State *L) { @@ -1142,47 +1487,69 @@ static int bi_lua_vectoangles(lua_State *L) float *uv = NULL; vec3_t ret; lua_readvector(L, 1, forward); - if (lua.type(L, 2) != LUA_TNONE) + if (lua_type(L, 2) != LUA_TNONE) { lua_readvector(L, 1, up); uv = up; } VectorAngles(forward, uv, ret, true); - lua.createtable(L, 0, 0); - //FIXME: should provide a metatable with a __tostring - lua.pushnumber(L, ret[0]); - lua.setfield (L, -2, "x"); - lua.pushnumber(L, ret[1]); - lua.setfield (L, -2, "y"); - lua.pushnumber(L, ret[2]); - lua.setfield (L, -2, "z"); + lua_pushvector(L, ret[0], ret[1], ret[2]); + return 1; +} +static int bi_lua_vectoyaw(lua_State *L) +{ + vec3_t forward; + vec3_t up; + float *uv = NULL; + vec3_t ret; + lua_readvector(L, 1, forward); + if (lua_type(L, 2) != LUA_TNONE) + { + lua_readvector(L, 1, up); + uv = up; + } + VectorAngles(forward, uv, ret, true); + + lua_pushnumber(L, ret[1]); + return 1; +} + +void QCBUILTIN PF_aim (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +static int bi_lua_aim(lua_State *L) +{ //aim builtin is for keyboard users, if they still exist. + globalvars_t pr_globals; + lua_getfield(L, 1, "entnum"); + pr_globals.param[0].i = lua_tointeger(L, -1); + pr_globals.param[1].f = lua_tonumber(L, 2); //speed + PF_aim(&lua.progfuncs, &pr_globals); + lua_pushvector(L, pr_globals.ret.vec[0], pr_globals.ret.vec[1], pr_globals.ret.vec[2]); return 1; } static int bi_lua_tokenize(lua_State *L) { - const char *instring = lua.tolstring(L, 1, NULL); + const char *instring = lua_tolstring(L, 1, NULL); int argc = 0; - lua.createtable(L, 0, 0); + lua_newtable(L); while(NULL != (instring = COM_Parse(instring))) { //lua is traditionally 1-based //for i=1,t.argc do - lua.pushinteger(L, ++argc); - lua.pushstring(L, com_token); - lua.settable(L, -3); + lua_pushinteger(L, ++argc); + lua_pushstring(L, com_token); + lua_settable(L, -3); if (argc == 1) { while (*instring == ' ' || *instring == '\t') instring++; - lua.pushstring(L, instring); - lua.setfield(L, -2, "args"); //args is all-but-the-first + lua_pushstring(L, instring); + lua_setfield(L, -2, "args"); //args is all-but-the-first } } - lua.pushinteger(L, argc); - lua.setfield(L, -2, "argc"); //argc is the count. + lua_pushinteger(L, argc); + lua_setfield(L, -2, "argc"); //argc is the count. return 1; } @@ -1199,12 +1566,12 @@ static int bi_lua_findradiuschain(lua_State *L) chain = (edict_t *)world->edicts; lua_readvector(L, 1, org); - rad = lua.tonumberx(L, 2, NULL); + rad = lua_tonumberx(L, 2, NULL); rad = rad*rad; for (i=1 ; inum_edicts ; i++) { - ent = EDICT_NUM(world->progs, i); + ent = EDICT_NUM_PB(world->progs, i); if (ED_ISFREE(ent)) continue; if (ent->v->solid == SOLID_NOT && (progstype != PROG_QW || !((int)ent->v->flags & FL_FINDABLE_NONSOLID)) && !sv_gameplayfix_blowupfallenzombies.value) @@ -1218,8 +1585,8 @@ static int bi_lua_findradiuschain(lua_State *L) chain = ent; } - lua.pushlightuserdata(L, chain); - lua.gettable(L, LUA_REGISTRYINDEX); + lua_pushlightuserdata(L, chain); + lua_gettable(L, LUA_REGISTRYINDEX); return 1; } static int bi_lua_findradiustable(lua_State *L) @@ -1236,14 +1603,14 @@ static int bi_lua_findradiustable(lua_State *L) chain = (edict_t *)world->edicts; lua_readvector(L, 1, org); - rad = lua.tonumberx(L, 2, NULL); + rad = lua_tonumberx(L, 2, NULL); rad = rad*rad; - lua.createtable(L, 0, 0); //our return value. + lua_newtable(L); //our return value. for (i=1 ; inum_edicts ; i++) { - ent = EDICT_NUM(world->progs, i); + ent = EDICT_NUM_PB(world->progs, i); if (ED_ISFREE(ent)) continue; if (ent->v->solid == SOLID_NOT && (progstype != PROG_QW || !((int)ent->v->flags & FL_FINDABLE_NONSOLID)) && !sv_gameplayfix_blowupfallenzombies.value) @@ -1253,24 +1620,61 @@ static int bi_lua_findradiustable(lua_State *L) if (DotProduct(eorg,eorg) > rad) continue; - lua.pushinteger(L, ++results); - lua.pushlightuserdata(L, ent); - lua.gettable(L, LUA_REGISTRYINDEX); - lua.settable(L, -3); + lua_pushinteger(L, ++results); + lua_pushlightuserdata(L, ent); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_settable(L, -3); } - lua.pushlightuserdata(L, chain); - lua.gettable(L, LUA_REGISTRYINDEX); + lua_pushlightuserdata(L, chain); + lua_gettable(L, LUA_REGISTRYINDEX); return 1; } #define bi_lua_findradius bi_lua_findradiuschain + +static int bi_lua_find(lua_State *L) +{ + world_t *world = &sv.world; + edict_t *ent; + size_t i; + const char *s; + const char *match; + + lua_getfield(L, 1, "entnum"); + i = lua_tointegerx(L, -1, NULL)+1; + match = lua_tostring(L, 3); + + for ( ; inum_edicts ; i++) + { + ent = EDICT_NUM_PB(world->progs, i); + if (ED_ISFREE(ent)) + continue; + lua_pushedict(L, ent); + lua_pushvalue(L, 2); + lua_gettable(L, -2); + s = lua_tostring(L, -1); + if (!s) + s = ""; + if (!strcmp(s, match)) //should probably do a lua comparison, but nils suck + { + lua_pop(L, 2); + lua_pushedict(L, ent); + return 1; + } + lua_pop(L, 2); + } + + lua_pushedict(L, EDICT_NUM_PB(world->progs, 0)); + return 1; +} + static int bi_lua_multicast(lua_State *L) { int dest; vec3_t org; - dest = lua.tointegerx(L, 1, NULL); + dest = lua_tointegerx(L, 1, NULL); lua_readvector(L, 2, org); NPP_Flush(); @@ -1283,7 +1687,7 @@ static int bi_lua_writechar(lua_State *L) { globalvars_t pr_globals; pr_globals.param[0].f = (csqcmsgbuffer.maxsize?MSG_CSQC:MSG_MULTICAST); - pr_globals.param[1].f = lua.tonumberx(L, 1, NULL); + pr_globals.param[1].f = lua_tonumberx(L, 1, NULL); PF_WriteChar(&lua.progfuncs, &pr_globals); return 0; } @@ -1291,7 +1695,7 @@ static int bi_lua_writebyte(lua_State *L) { globalvars_t pr_globals; pr_globals.param[0].f = (csqcmsgbuffer.maxsize?MSG_CSQC:MSG_MULTICAST); - pr_globals.param[1].f = lua.tonumberx(L, 1, NULL); + pr_globals.param[1].f = lua_tonumberx(L, 1, NULL); PF_WriteByte(&lua.progfuncs, &pr_globals); return 0; } @@ -1299,7 +1703,7 @@ static int bi_lua_writeshort(lua_State *L) { globalvars_t pr_globals; pr_globals.param[0].f = (csqcmsgbuffer.maxsize?MSG_CSQC:MSG_MULTICAST); - pr_globals.param[1].f = lua.tonumberx(L, 1, NULL); + pr_globals.param[1].f = lua_tonumberx(L, 1, NULL); PF_WriteShort(&lua.progfuncs, &pr_globals); return 0; } @@ -1307,7 +1711,7 @@ static int bi_lua_writelong(lua_State *L) { globalvars_t pr_globals; pr_globals.param[0].f = (csqcmsgbuffer.maxsize?MSG_CSQC:MSG_MULTICAST); - pr_globals.param[1].f = lua.tonumberx(L, 1, NULL); + pr_globals.param[1].f = lua_tonumberx(L, 1, NULL); PF_WriteLong(&lua.progfuncs, &pr_globals); return 0; } @@ -1315,7 +1719,7 @@ static int bi_lua_writeangle(lua_State *L) { globalvars_t pr_globals; pr_globals.param[0].f = (csqcmsgbuffer.maxsize?MSG_CSQC:MSG_MULTICAST); - pr_globals.param[1].f = lua.tonumberx(L, 1, NULL); + pr_globals.param[1].f = lua_tonumberx(L, 1, NULL); PF_WriteAngle(&lua.progfuncs, &pr_globals); return 0; } @@ -1323,85 +1727,200 @@ static int bi_lua_writecoord(lua_State *L) { globalvars_t pr_globals; pr_globals.param[0].f = (csqcmsgbuffer.maxsize?MSG_CSQC:MSG_MULTICAST); - pr_globals.param[1].f = lua.tonumberx(L, 1, NULL); + pr_globals.param[1].f = lua_tonumberx(L, 1, NULL); PF_WriteCoord(&lua.progfuncs, &pr_globals); return 0; } static int bi_lua_writestring(lua_State *L) { - PF_WriteString_Internal((csqcmsgbuffer.maxsize?MSG_CSQC:MSG_MULTICAST),lua.tolstring(L, 1, NULL)); + PF_WriteString_Internal((csqcmsgbuffer.maxsize?MSG_CSQC:MSG_MULTICAST),lua_tolstring(L, 1, NULL)); return 0; } static int bi_lua_writeentity(lua_State *L) { globalvars_t pr_globals; - lua.getfield(L, 1, "entnum"); + lua_getfield(L, 1, "entnum"); pr_globals.param[0].f = (csqcmsgbuffer.maxsize?MSG_CSQC:MSG_MULTICAST); - pr_globals.param[1].i = lua.tointegerx(L, -1, NULL); + pr_globals.param[1].i = lua_tointegerx(L, -1, NULL); PF_WriteEntity(&lua.progfuncs, &pr_globals); return 0; } +static int bi_lua_WriteChar(lua_State *L) +{ + globalvars_t pr_globals; + pr_globals.param[0].f = lua_tonumberx(L, 1, NULL); + pr_globals.param[1].f = lua_tonumberx(L, 2, NULL); + PF_WriteChar(&lua.progfuncs, &pr_globals); + return 0; +} +static int bi_lua_WriteByte(lua_State *L) +{ + globalvars_t pr_globals; + pr_globals.param[0].f = lua_tonumberx(L, 1, NULL); + pr_globals.param[1].f = lua_tonumberx(L, 2, NULL); + PF_WriteByte(&lua.progfuncs, &pr_globals); + return 0; +} +static int bi_lua_WriteShort(lua_State *L) +{ + globalvars_t pr_globals; + pr_globals.param[0].f = lua_tonumberx(L, 1, NULL); + pr_globals.param[1].f = lua_tonumberx(L, 2, NULL); + PF_WriteShort(&lua.progfuncs, &pr_globals); + return 0; +} +static int bi_lua_WriteLong(lua_State *L) +{ + globalvars_t pr_globals; + pr_globals.param[0].f = lua_tonumberx(L, 1, NULL); + pr_globals.param[1].f = lua_tonumberx(L, 2, NULL); + PF_WriteLong(&lua.progfuncs, &pr_globals); + return 0; +} +static int bi_lua_WriteAngle(lua_State *L) +{ + globalvars_t pr_globals; + pr_globals.param[0].f = lua_tonumberx(L, 1, NULL); + pr_globals.param[1].f = lua_tonumberx(L, 2, NULL); + PF_WriteAngle(&lua.progfuncs, &pr_globals); + return 0; +} +static int bi_lua_WriteCoord(lua_State *L) +{ + globalvars_t pr_globals; + pr_globals.param[0].f = lua_tonumberx(L, 1, NULL); + pr_globals.param[1].f = lua_tonumberx(L, 2, NULL); + PF_WriteCoord(&lua.progfuncs, &pr_globals); + return 0; +} +static int bi_lua_WriteString(lua_State *L) +{ + PF_WriteString_Internal(lua_tonumberx(L, 1, NULL),lua_tolstring(L, 2, NULL)); + return 0; +} +static int bi_lua_WriteEntity(lua_State *L) +{ + globalvars_t pr_globals; + lua_getfield(L, 2, "entnum"); + pr_globals.param[0].f = lua_tonumberx(L, 1, NULL); + pr_globals.param[1].i = lua_tointegerx(L, -1, NULL); + PF_WriteEntity(&lua.progfuncs, &pr_globals); + return 0; +} + +void QCBUILTIN PF_particle (pubprogfuncs_t *prinst, globalvars_t *pr_globals); +static int bi_lua_particle(lua_State *L) +{ + globalvars_t pr_globals; + lua_readvector(L, 1, pr_globals.param[0].vec); + lua_readvector(L, 2, pr_globals.param[1].vec); + pr_globals.param[2].f = lua_tonumberx(L, 3, NULL); + pr_globals.param[3].f = lua_tonumberx(L, 4, NULL); + PF_particle(&lua.progfuncs, &pr_globals); + return 0; +} +static int bi_lua_ChangeYaw(lua_State *L) +{ + PF_changeyaw(&lua.progfuncs, NULL); + return 0; +} + + static int bi_lua_bitnot(lua_State *L) { - lua.pushinteger(L, ~lua.tointegerx(L, 1, NULL)); + lua_pushinteger(L, ~lua_tointegerx(L, 1, NULL)); return 1; } static int bi_lua_bitclear(lua_State *L) { - lua.pushinteger(L, lua.tointegerx(L, 1, NULL)&~lua.tointegerx(L, 2, NULL)); + lua_pushinteger(L, lua_tointegerx(L, 1, NULL)&~lua_tointegerx(L, 2, NULL)); return 1; } static int bi_lua_bitset(lua_State *L) { - lua.pushnumber(L, lua.tointegerx(L, 1, NULL)|lua.tointegerx(L, 2, NULL)); + lua_pushnumber(L, lua_tointegerx(L, 1, NULL)|lua_tointegerx(L, 2, NULL)); return 1; } #define bi_lua_bitor bi_lua_bitset static int bi_lua_bitand(lua_State *L) { - lua.pushnumber(L, lua.tointegerx(L, 1, NULL)&lua.tointegerx(L, 2, NULL)); + lua_pushnumber(L, lua_tointegerx(L, 1, NULL)&lua_tointegerx(L, 2, NULL)); return 1; } static int bi_lua_bitxor(lua_State *L) { - lua.pushnumber(L, lua.tointegerx(L, 1, NULL)^lua.tointegerx(L, 2, NULL)); + lua_pushnumber(L, lua_tointegerx(L, 1, NULL)^lua_tointegerx(L, 2, NULL)); return 1; } static int bi_lua_sin(lua_State *L) { - lua.pushnumber(L, sin(lua.tonumberx(L, 1, NULL))); + lua_pushnumber(L, sin(lua_tonumberx(L, 1, NULL))); return 1; } static int bi_lua_cos(lua_State *L) { - lua.pushnumber(L, cos(lua.tonumberx(L, 1, NULL))); + lua_pushnumber(L, cos(lua_tonumberx(L, 1, NULL))); + return 1; +} +static int bi_lua_tan(lua_State *L) +{ + lua_pushnumber(L, tan(lua_tonumberx(L, 1, NULL))); return 1; } static int bi_lua_atan2(lua_State *L) { - lua.pushnumber(L, atan2(lua.tonumberx(L, 1, NULL), lua.tonumberx(L, 2, NULL))); + lua_pushnumber(L, atan2(lua_tonumberx(L, 1, NULL), lua_tonumberx(L, 2, NULL))); return 1; } static int bi_lua_sqrt(lua_State *L) { - lua.pushnumber(L, sin(lua.tonumberx(L, 1, NULL))); + lua_pushnumber(L, sin(lua_tonumberx(L, 1, NULL))); + return 1; +} +static int bi_lua_pow(lua_State *L) +{ + lua_pushnumber(L, pow(lua_tonumberx(L, 1, NULL), lua_tonumberx(L, 2, NULL))); return 1; } static int bi_lua_floor(lua_State *L) { - lua.pushnumber(L, floor(lua.tonumberx(L, 1, NULL))); + lua_pushnumber(L, floor(lua_tonumberx(L, 1, NULL))); + return 1; +} +static int bi_lua_rint(lua_State *L) +{ //C rounds towards 0, so bias away from 0 by 0.5 and we'll get the right rounded value. + lua_Number f = lua_tonumberx(L, 1, NULL); + if (f < 0) + lua_pushinteger(L, f - 0.5); + else + lua_pushinteger(L, f + 0.5); return 1; } static int bi_lua_ceil(lua_State *L) { - lua.pushnumber(L, ceil(lua.tonumberx(L, 1, NULL))); + lua_pushnumber(L, ceil(lua_tonumberx(L, 1, NULL))); + return 1; +} +static int bi_lua_fabs(lua_State *L) +{ + lua_pushnumber(L, fabs(lua_tonumberx(L, 1, NULL))); return 1; } static int bi_lua_acos(lua_State *L) { - lua.pushnumber(L, acos(lua.tonumberx(L, 1, NULL))); + lua_pushnumber(L, acos(lua_tonumberx(L, 1, NULL))); + return 1; +} +static int bi_lua_asin(lua_State *L) +{ + lua_pushnumber(L, asin(lua_tonumberx(L, 1, NULL))); + return 1; +} +static int bi_lua_atan(lua_State *L) +{ + lua_pushnumber(L, atan(lua_tonumberx(L, 1, NULL))); return 1; } @@ -1413,19 +1932,19 @@ typedef struct static int QDECL lua_file_enumerate(const char *fname, qofs_t fsize, time_t mtime, void *param, searchpathfuncs_t *spath) { luafsenum_t *e = param; - lua.pushinteger(e->L, e->idx++); - lua.pushfstring(e->L, "%s", fname); - lua.settable(e->L, -3); + lua_pushinteger(e->L, e->idx++); + lua_pushfstring(e->L, "%s", fname); + lua_settable(e->L, -3); return true; } static int bi_lua_getfilelist(lua_State *L) { luafsenum_t e; - const char *path = lua.tolstring(L, 1, NULL); + const char *path = lua_tolstring(L, 1, NULL); e.L = L; e.idx = 1; //lua arrays are 1-based. - lua.createtable(L, 0, 0); //our return value. + lua_newtable(L); //our return value. COM_EnumerateFiles(path, lua_file_enumerate, &e); return 1; } @@ -1435,7 +1954,7 @@ static int bi_lua_fclose(lua_State *L) //both fclose and __gc. //should we use a different function so that we can warn on dupe fcloses without bugging out on fclose+gc? //meh, cba - vfsfile_t **f = lua.touserdata(L, 1); + vfsfile_t **f = lua_touserdata(L, 1); if (f && *f != NULL) { VFS_CLOSE(*f); @@ -1446,7 +1965,7 @@ static int bi_lua_fclose(lua_State *L) static int bi_lua_fopen(lua_State *L) { vfsfile_t *f; - const char *fname = lua.tolstring(L, 1, NULL); + const char *fname = lua_tolstring(L, 1, NULL); qboolean read = true; vfsfile_t **ud; if (read) @@ -1455,37 +1974,37 @@ static int bi_lua_fopen(lua_State *L) f = FS_OpenVFS(fname, "wb", FS_GAMEONLY); if (!f) { - lua.pushnil(L); + lua_pushnil(L); return 1; } - ud = lua.newuserdata(L, sizeof(vfsfile_t*)); + ud = lua_newuserdata(L, sizeof(vfsfile_t*)); *ud = f; - lua.createtable(L, 0, 0); - lua.pushcclosure(L, bi_lua_fclose, 0); - lua.setfield(L, -2, "__gc"); - lua.setmetatable(L, -2); + lua_newtable(L); + lua_pushcclosure(L, bi_lua_fclose, 0); + lua_setfield(L, -2, "__gc"); + lua_setmetatable(L, -2); return 1; } static int bi_lua_fgets(lua_State *L) { - vfsfile_t **f = lua.touserdata(L, 1); + vfsfile_t **f = lua_touserdata(L, 1); char line[8192]; char *r = NULL; if (f && *f) r = VFS_GETS(*f, line, sizeof(line)); if (r) - lua.pushfstring(L, "%s", r); + lua_pushfstring(L, "%s", r); else - lua.pushnil(L); + lua_pushnil(L); return 1; } static int bi_lua_fputs(lua_State *L) { - vfsfile_t **f = lua.touserdata(L, 1); + vfsfile_t **f = lua_touserdata(L, 1); size_t l; - const char *str = lua.tolstring(L, 2, &l); + const char *str = lua_tolstring(L, 2, &l); if (f && *f != NULL) VFS_WRITE(*f, str, l); return 0; @@ -1493,55 +2012,341 @@ static int bi_lua_fputs(lua_State *L) static int bi_lua_loadlua(lua_State *L) { - const char *fname = lua.tolstring(L, 1, NULL); + const char *fname = lua_tolstring(L, 1, NULL); vfsfile_t *sourcefile = FS_OpenVFS(fname, "rb", FS_GAME); if (!sourcefile) { Con_Printf("Error trying to load %s\n", fname); - lua.pushnil(L); + lua_pushnil(L); } - else if (0 != lua.load(L, my_lua_Reader, sourcefile, fname, "bt")) //load the file, embed it within a function and push it + else if (0 != lua_load(L, my_lua_Reader, sourcefile, va("@%s", fname), "bt")) //load the file, embed it within a function and push it { - Con_Printf("Error trying to parse %s: %s\n", fname, lua.tolstring(L, -1, NULL)); - lua.pushnil(L); + Con_Printf("Error trying to parse %s: %s\n", fname, lua_tolstring(L, -1, NULL)); + lua_pushnil(L); } VFS_CLOSE(sourcefile); return 1; } -#define registerfunc(n) lua.pushcclosure(L, bi_lua_##n, 0); lua.setglobal(L, #n); +static int bi_lua_require(lua_State *L) +{ + const char *fname = lua_tolstring(L, 1, NULL); + vfsfile_t *sourcefile; + const char *usename; + if ((sourcefile = FS_OpenVFS(usename=fname, "rb", FS_GAME))) + ; + else if ((sourcefile = FS_OpenVFS(usename=va("%s.lua", fname), "rb", FS_GAME))) + ; + else + { + Con_Printf("Error trying to load %s\n", fname); + return 1; + } + + if (0 != lua_load(lua.ctx, my_lua_Reader, sourcefile, va("@%s", usename), "bt")) //load the file, embed it within a function and push it + { + //failed - it pushed an error code instead + Con_Printf("Error trying to parse %s: %s\n", fname, lua_tolstring(lua.ctx, -1, NULL)); + lua_pop(lua.ctx, 1); + } + else + { + if (lua_pcall(lua.ctx, 0, 0, 0) != 0) //now call it, so its actually run. + { + const char *s = lua_tolstring(lua.ctx, -1, NULL); + Con_Printf(CON_WARNING "%s\n", s); + lua_pop(lua.ctx, 1); + } + } + VFS_CLOSE(sourcefile); + return 0; +} + +static int bi_lua_vec3(lua_State *L) +{ + float x = lua_tonumberx(L, 1, NULL); + float y = lua_tonumberx(L, 2, NULL); + float z = lua_tonumberx(L, 3, NULL); + + lua_pushvector(L, x, y, z); + return 1; +} +static int bi_lua_field(lua_State *L) +{ + const char *fname = lua_tostring(L, 1); + const char *ftype = lua_tostring(L, 2); + int t; + size_t u; + + if (!strcmp(ftype, "string")) + t = ev_string; + else if (!strcmp(ftype, "float")) + t = ev_float; + else if (!strcmp(ftype, "integer")) + t = ev_integer; + else if (!strcmp(ftype, "vector")) + t = ev_vector; + else if (!strcmp(ftype, "function")) + t = ev_function; + else if (!strcmp(ftype, "entity")) + t = ev_entity; + else + { + Con_Printf("Unknown field type\n"); + return 0; + } + + if (lua.numflds == countof(lua.entflds)) + { + Con_Printf("Too many ent fields\n"); + return 0; + } + + //no dupes please. + for (u = 0; u < lua.numflds; u++) + { + if (!strcmp(lua.entflds[u].name, fname)) + return 0; + } + + lua.entflds[lua.numflds].offset = -1; //if we don't know about it yet, then its an artificial field, and present just so that self.whatever returns something other than nil. + lua.entflds[lua.numflds].name = Lua_AddString(NULL, fname, 0, false); + lua.entflds[lua.numflds].type = t; + Hash_AddInsensitive(&lua.entityfields, lua.entflds[lua.numflds].name, &lua.entflds[lua.numflds], &lua.entflds[lua.numflds].buck); + lua.numflds++; + + return 0; +} +static int bi_lua_type(lua_State *L) +{ + const char *tn; + int t = lua_type(L, 1); +// luaL_argcheck(L, t != LUA_TNONE, 1, "value expected"); + tn = lua_typename(L, t); + lua_pushstring(L, tn); + return 1; +} + +static int bi_lua_logfrag(lua_State *L) +{ + //stub... noone cares + return 0; +} + +/*static int bi_lua_entities(lua_State *L) +{ + //stub... noone cares + return 0; +}*/ + +#ifdef LIBLUA_STATIC +static int pairsmeta (lua_State *L, const char *method, int iszero, + lua_CFunction iter) { + luaL_checkany(L, 1); + if (luaL_getmetafield(L, 1, method) == LUA_TNIL) { /* no metamethod? */ + lua_pushcfunction(L, iter); /* will return generator, */ + lua_pushvalue(L, 1); /* state, */ + if (iszero) lua_pushinteger(L, 0); /* and initial value */ + else lua_pushnil(L); + } + else { + lua_pushvalue(L, 1); /* argument 'self' to metamethod */ + lua_call(L, 1, 3); /* get 3 values from metamethod */ + } + return 3; +} +static int luaB_next (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} +static int bi_lua_pairs (lua_State *L) { + return pairsmeta(L, "__pairs", 0, luaB_next); +} +#endif + +static int bi_lua_objerror (lua_State *L) +{ + SV_Error("objerror: %s\n", lua_tostring(L, 1)); + lua_pushedict(L, lua.edicttable[lua.globals.self]); + + lua_pushnil(L); + while (lua_next(L, -2)) + { //FIXME: this doesn't find vector fields + if (lua_type(L, -2) == LUA_TSTRING) + Con_Printf("%21s:", lua_tostring(L, -2)); + else if (lua_type(L, -2) == LUA_TLIGHTUSERDATA) + { + int i; + const void *ud = lua_topointer(L, -2); + for (i = 0; i < countof(lua.entflds); i++) + if (lua.entflds[i].offset == (ptrdiff_t)ud) + break; + + if (i == countof(lua.entflds)) + Con_Printf("%21s:", lua_typename(L, lua_type(L, -2))); + else + Con_Printf("%21s:", lua.entflds[i].name); + } + else + Con_Printf("%21s:", lua_typename(L, lua_type(L, -2))); + if (lua_type(L, -1) == LUA_TSTRING) + Con_Printf(" \"%s\"\n", lua_tostring(L, -1)); + else if (lua_type(L, -1) == LUA_TNUMBER) + Con_Printf(" \"%g\"\n", lua_tonumber(L, -1)); +#ifdef LIBLUA_STATIC + else if (lua_type(L, -1) == LUA_TFUNCTION) + { + lua_Debug ar = {0}; + lua_pushvalue(L, -1); + lua_getinfo(L, ">nS", &ar); + Con_Printf(" %s %s:%i\n", ar.name, ar.source, ar.linedefined); + } +#endif + else + Con_Printf(" %s\n", lua_typename(L, lua_type(L, -1))); + lua_pop(L, 1); + } + + lua_pop(L, 1); + return 0; +} +static int bi_lua_error (lua_State *L) +{ + SV_Error("Error: %s\n", lua_tostring(L, 1)); + return 0; +} +static int bi_lua_qtrue (lua_State *L) +{ + //the truth is what you make it... + + const char *s; + + switch(lua_type(L, 1)) + { + case LUA_TSTRING: + s = lua_tostring(L, 1); + lua_pushboolean(L, *s != 0); //empty string is considered false. WARNING: vanilla QC considered empty-but-not-null strings to be true + break; + + default: +// case LUA_TUSERDATA: +// case LUA_TTHREAD: +// case LUA_TLIGHTUSERDATA: +// case LUA_TNONE: +// case LUA_TNIL: + lua_pushboolean(L, false); + break; + case LUA_TBOOLEAN: + lua_pushvalue(L, 1); + break; + + case LUA_TNUMBER: + lua_pushboolean(L, lua_tonumber(L, 1) != 0); + break; + + case LUA_TFUNCTION: //functions are always considered true. otherwise they're nil and not functions. + lua_pushboolean(L, true); + break; + case LUA_TTABLE: + //might be a vector or an entity. + lua_getfield(L, 1, "entnum"); + if (!lua_isnil(L, -1)) + { //okay, so its a table with a valid entnum field. must be an entity. + lua_pushboolean(L, 0!=lua_tointegerx(L, -1, NULL)); //true if its not 0/world + } + else + { //assume that its a vector. + //note that this means that any table without x|y|z fields will be considered false. + vec3_t v; + lua_readvector(L, 1, v); + lua_pushboolean(L, v[0] || v[1] || v[2]); + } + break; + } + return 1; +} + +#define registerfunc(n) lua_pushcclosure(L, bi_lua_##n, 0); lua_setglobal(L, #n); +#define registerfuncn(n) registerfunc(n) //new crap +#define registerfuncd(n) registerfunc(n) //deprecated crap static void my_lua_registerbuiltins(lua_State *L) { - lua.atpanic (L, my_lua_panic); + lua_atpanic (L, my_lua_panic); + + lua_pushglobaltable(L); + lua_setfield(L, -1, "_G"); //standard lua library replacement //this avoids the risk of including any way to access os.execute etc, or other file access. - lua.pushcclosure(L, my_lua_tostring, 0); - lua.setglobal(L, "tostring"); - lua.pushcclosure(L, my_lua_print, 0); - lua.setglobal(L, "print"); + registerfuncn(tostring); //standardish + registerfuncn(type); //standardish + registerfuncn(print); //'standard' lua print, except prints to console. WARNING: this adds an implicit \n. Use conprint for the quake-style version. + registerfuncn(require); //'standard'ish, except uses quake's filesystem instead of reading random system paths. +#ifdef LIBLUA_STATIC + registerfuncn(pairs); +#endif - lua.pushcclosure(L, my_lua_conprint, 0); //for the luls. - lua.setglobal(L, "conprint"); + lua_newtable(L); + lua_pushcclosure(L, bi_lua_fabs, 0); lua_setfield(L, -2, "abs"); + lua_pushcclosure(L, bi_lua_rint, 0); lua_setfield(L, -2, "rint"); + lua_pushcclosure(L, bi_lua_ceil, 0); lua_setfield(L, -2, "ceil"); + lua_pushcclosure(L, bi_lua_floor, 0); lua_setfield(L, -2, "floor"); + lua_pushcclosure(L, bi_lua_sin, 0); lua_setfield(L, -2, "sin"); + lua_pushcclosure(L, bi_lua_cos, 0); lua_setfield(L, -2, "cos"); + lua_pushcclosure(L, bi_lua_tan, 0); lua_setfield(L, -2, "tan"); + lua_pushcclosure(L, bi_lua_asin, 0); lua_setfield(L, -2, "asin"); + lua_pushcclosure(L, bi_lua_acos, 0); lua_setfield(L, -2, "acos"); + lua_pushcclosure(L, bi_lua_atan, 0); lua_setfield(L, -2, "atan"); + lua_pushcclosure(L, bi_lua_atan2, 0); lua_setfield(L, -2, "atan2"); + lua_pushcclosure(L, bi_lua_sqrt, 0); lua_setfield(L, -2, "sqrt"); + lua_pushcclosure(L, bi_lua_pow, 0); lua_setfield(L, -2, "pow"); + lua_pushnumber (L, M_PI); lua_setfield(L, -2, "pi"); + lua_setglobal(L, "math"); - registerfunc(loadlua); +// registerfuncd(entities); + + registerfuncd(loadlua); //should probably use 'require' instead. + registerfuncn(vec3); + registerfuncn(field); + registerfuncn(qtrue); //for auto-converted code that tests for truth amongst a myriad of different custom types... registerfunc(setmodel); registerfunc(precache_model); + registerfuncd(precache_model2); //pointless alternative name registerfunc(precache_sound); + registerfuncd(precache_sound2); //pointless alternative name + registerfuncd(precache_file); //empty pointless function... registerfunc(lightstyle); registerfunc(spawn); registerfunc(remove); registerfunc(nextent); registerfunc(nextclient); - //registerfunc(AIM); registerfunc(makestatic); registerfunc(setorigin); registerfunc(setsize); - registerfunc(dprint); - registerfunc(bprint); - registerfunc(sprint); + registerfuncn(conprint); //dprint, without the developer + + registerfunc(bprint_qw); + registerfunc(sprint_qw); + if (progstype == PROG_QW) + { + lua_pushcclosure(L, bi_lua_conprint, 0); lua_setglobal(L, "dprint"); //ignores developer + lua_pushcclosure(L, bi_lua_bprint_qw, 0); lua_setglobal(L, "bprint"); //an extra level arg + lua_pushcclosure(L, bi_lua_sprint_qw, 0); lua_setglobal(L, "sprint"); //an extra level arg + } + else + { + lua_pushcclosure(L, bi_lua_dprint, 0); lua_setglobal(L, "dprint"); //responds to developer + lua_pushcclosure(L, bi_lua_bprint_nq, 0); lua_setglobal(L, "bprint"); //no level arg + lua_pushcclosure(L, bi_lua_sprint_nq, 0); lua_setglobal(L, "sprint"); //no level arg + } registerfunc(centerprint); registerfunc(ambientsound); registerfunc(sound); @@ -1549,75 +2354,131 @@ static void my_lua_registerbuiltins(lua_State *L) registerfunc(checkclient); registerfunc(stuffcmd); registerfunc(localcmd); - registerfunc(cvar_get); + registerfuncd(cvar); //gets a float value, never a string. + registerfuncn(cvar_get); registerfunc(cvar_set); - registerfunc(findradius); //qc legacy compat. should probably warn when its called or sommit. - registerfunc(findradiuschain); //like qc. - registerfunc(findradiustable); //findradius, but returns an array/table instead. + registerfuncd(findradius); //qc legacy compat. should probably warn when its called or sommit. + registerfuncn(findradiuschain); //renamed from qc. because qc's behaviour is annoying enough that we want to discourage its use. + registerfuncn(findradiustable); //findradius, but returns an array/table instead. + + registerfunc(objerror); + registerfunc(error); +// registerfuncd(break); //won't implement registerfunc(traceline); - registerfunc(tracebox); + registerfuncn(tracebox); registerfunc(walkmove); registerfunc(movetogoal); registerfunc(droptofloor); registerfunc(checkbottom); registerfunc(pointcontents); + registerfuncd(ChangeYaw); registerfunc(setspawnparms); registerfunc(changelevel); - //registerfunc(LOGFRAG); - registerfunc(getinfokey); - registerfunc(setinfokey); + registerfunc(logfrag); + registerfuncd(infokey); + registerfuncn(getinfokey); + registerfuncn(setinfokey); registerfunc(multicast); - registerfunc(writebyte); - registerfunc(writechar); - registerfunc(writeshort); - registerfunc(writelong); - registerfunc(writeangle); - registerfunc(writecoord); - registerfunc(writestring); - registerfunc(writeentity); - registerfunc(bitnot); - registerfunc(bitclear); - registerfunc(bitset); - registerfunc(bitor); - registerfunc(bitand); - registerfunc(bitxor); - registerfunc(sin); - registerfunc(cos); - registerfunc(atan2); - registerfunc(sqrt); + registerfuncn(writebyte); + registerfuncn(writechar); + registerfuncn(writeshort); + registerfuncn(writelong); + registerfuncn(writeangle); + registerfuncn(writecoord); + registerfuncn(writestring); + registerfuncn(writeentity); + registerfuncd(WriteByte); + registerfuncd(WriteChar); + registerfuncd(WriteShort); + registerfuncd(WriteLong); + registerfuncd(WriteAngle); + registerfuncd(WriteCoord); + registerfuncd(WriteString); + registerfuncd(WriteEntity); + registerfuncd(particle); + registerfuncn(bitnot); + registerfuncn(bitclear); + registerfuncn(bitset); + registerfuncn(bitor); + registerfuncn(bitand); + registerfuncn(bitxor); + registerfuncn(sin); + registerfuncn(cos); + registerfuncn(acos); + registerfuncn(asin); + registerfuncn(atan); + registerfuncn(atan2); + registerfuncn(sqrt); + registerfuncn(pow); registerfunc(floor); registerfunc(ceil); - registerfunc(acos); - registerfunc(fopen); - registerfunc(fclose); - registerfunc(fgets); - registerfunc(fputs); - registerfunc(getfilelist); - //registerfunc(Find); + registerfunc(rint); + registerfunc(fabs); + registerfuncn(fopen); + registerfuncn(fclose); + registerfuncn(fgets); + registerfuncn(fputs); + registerfuncn(getfilelist); + registerfuncd(find); //registerfunc(strftime); registerfunc(tokenize); registerfunc(makevectors); + registerfunc(normalize); registerfunc(vectoangles); + registerfunc(vectoyaw); + registerfuncd(aim); //original implementation nudges v_forward up or down so that keyboard players can still play. + registerfunc(vtos); + registerfunc(ftos); //registerfunc(PRECACHE_VWEP_MODEL); //registerfunc(SETPAUSE); - - lua.createtable(L, 0, 0); - if (lua.Lnewmetatable(L, "globals")) + //set a metatable on the globals table + //this means that we can just directly use self.foo instead of blob.self.foo + lua_pushglobaltable(L); + if (luaL_newmetatable(L, "globals")) { - lua.pushcclosure(L, my_lua_global_set, 0); //for the luls. - lua.setfield (L, -2, "__newindex"); + lua_pushcclosure(L, my_lua_global_set, 0); //for the luls. + lua_setfield (L, -2, "__newindex"); - lua.pushcclosure(L, my_lua_global_get, 0); //for the luls. - lua.setfield (L, -2, "__index"); + lua_pushcclosure(L, my_lua_global_get, 0); //for the luls. + lua_setfield (L, -2, "__index"); + } + lua_setmetatable(L, -2); + lua_pop(L, 1); + + if (luaL_newmetatable(L, "vec3_t")) + { +// lua_pushcclosure(L, my_lua_vec3_set, 0); //known writes should change the internal info so the engine can use the information. +// lua_setfield (L, -2, "__newindex"); + +// lua_pushcclosure(L, my_lua_vec3_get, 0); //we need to de-translate the engine's fields too. +// lua_setfield (L, -2, "__index"); + + lua_pushcclosure(L, my_lua_vec3_tostring, 0); //cos its prettier than seeing 'table 0x5425729' all over the place + lua_setfield (L, -2, "__tostring"); + + lua_pushcclosure(L, my_lua_vec3_eq, 0); //for comparisons, you know? + lua_setfield (L, -2, "__eq"); + + lua_pushcclosure(L, my_lua_vec3_add, 0); //for comparisons, you know? + lua_setfield (L, -2, "__add"); + + lua_pushcclosure(L, my_lua_vec3_sub, 0); //for comparisons, you know? + lua_setfield (L, -2, "__sub"); + + lua_pushcclosure(L, my_lua_vec3_mul, 0); //for comparisons, you know? + lua_setfield (L, -2, "__mul"); + + lua_pushcclosure(L, my_lua_vec3_len, 0); //for comparisons, you know? + lua_setfield (L, -2, "__len"); + + lua_pop(L, 1); } - lua.setmetatable(L, -2); - lua.setglobal(L, "glob"); } @@ -1634,6 +2495,9 @@ static edict_t *QDECL Lua_EdictNum(pubprogfuncs_t *pf, unsigned int num) lua.edicttable = realloc(lua.edicttable, newcount*sizeof(*lua.edicttable)); while(lua.maxedicts < newcount) lua.edicttable[lua.maxedicts++] = NULL; + + pf->edicttable_length = lua.maxedicts; + pf->edicttable = lua.edicttable; } return lua.edicttable[num]; } @@ -1678,9 +2542,9 @@ static void QDECL Lua_EntRemove(pubprogfuncs_t *pf, edict_t *e) //clear out the lua version of the entity, so that it can be garbage collected. //should probably clear out its entnum field too, just in case. - lua.pushlightuserdata(L, e); - lua.pushnil(L); - lua.settable(L, LUA_REGISTRYINDEX); + lua_pushlightuserdata(L, e); + lua_pushnil(L); + lua_settable(L, LUA_REGISTRYINDEX); } static edict_t *Lua_DoRespawn(pubprogfuncs_t *pf, edict_t *e, int num) { @@ -1693,26 +2557,26 @@ static edict_t *Lua_DoRespawn(pubprogfuncs_t *pf, edict_t *e, int num) ED_Spawned((struct edict_s *) e, false); //create a new table for the entity, give it a suitable metatable, and store it into the registry (avoiding GC and allowing us to actually hold on to it). - lua.pushlightuserdata(L, lua.edicttable[num]); - lua.createtable(L, 0, 0); - if (lua.Lnewmetatable(L, "entity")) + lua_pushlightuserdata(L, lua.edicttable[num]); + lua_newtable(L); + if (luaL_newmetatable(L, "entity")) { - lua.pushcclosure(L, my_lua_entity_set, 0); //known writes should change the internal info so the engine can use the information. - lua.setfield (L, -2, "__newindex"); + lua_pushcclosure(L, my_lua_entity_set, 0); //known writes should change the internal info so the engine can use the information. + lua_setfield (L, -2, "__newindex"); - lua.pushcclosure(L, my_lua_entity_get, 0); //we need to de-translate the engine's fields too. - lua.setfield (L, -2, "__index"); + lua_pushcclosure(L, my_lua_entity_get, 0); //we need to de-translate the engine's fields too. + lua_setfield (L, -2, "__index"); - lua.pushcclosure(L, my_lua_entity_tostring, 0); //cos its prettier than seeing 'table 0x5425729' all over the place - lua.setfield (L, -2, "__tostring"); + lua_pushcclosure(L, my_lua_entity_tostring, 0); //cos its prettier than seeing 'table 0x5425729' all over the place + lua_setfield (L, -2, "__tostring"); - lua.pushcclosure(L, my_lua_entity_eq, 0); //for comparisons, you know? - lua.setfield (L, -2, "__eq"); + lua_pushcclosure(L, my_lua_entity_eq, 0); //for comparisons, you know? + lua_setfield (L, -2, "__eq"); } - lua.setmetatable(L, -2); - lua.pushinteger(L, num); - lua.setfield (L, -2, "entnum"); //so we know which entity it is. - lua.settable(L, LUA_REGISTRYINDEX); + lua_setmetatable(L, -2); + lua_pushinteger(L, num); + lua_setfield (L, -2, "entnum"); //so we know which entity it is. + lua_settable(L, LUA_REGISTRYINDEX); return e; } static edict_t *QDECL Lua_EntAlloc(pubprogfuncs_t *pf, pbool isobject, size_t extrasize) @@ -1721,7 +2585,7 @@ static edict_t *QDECL Lua_EntAlloc(pubprogfuncs_t *pf, pbool isobject, size_t ex edict_t *e; for ( i=0 ; ifreetime < 2 || sv.time - e->freetime > 0.5 ) )) @@ -1735,7 +2599,7 @@ static edict_t *QDECL Lua_EntAlloc(pubprogfuncs_t *pf, pbool isobject, size_t ex { for ( i=0 ; i 1) + continue; + + strncpy (keyname, token, sizeof(keyname)-1); + keyname[sizeof(keyname)-1] = 0; + + // another hack to fix heynames with trailing spaces + n = strlen(keyname); + while (n && keyname[n-1] == ' ') + { + keyname[n-1] = 0; + n--; + } + + // parse value + data = COM_ParseOut(data, token, sizeof(token)); + if (!data) + { + Con_Printf ("Lua_ParseEdict: EOF without closing brace\n"); + return NULL; + } + + if (token[0] == '}') + { + Con_Printf ("Lua_ParseEdict: closing brace without data\n"); + return NULL; + } + + init = true; + +// keynames with a leading underscore are used for utility comments, +// and are immediately discarded by quake + if (keyname[0] == '_') + continue; + + + + if (!strcmp(keyname, "angle")) //Quake anglehack - we've got to leave it in cos it doesn't work for quake otherwise, and this is a QuakeC lib! + { + Q_snprintfz (keyname, sizeof(keyname), "angles"); //change it from yaw to 3d angle + Q_snprintfz (token, sizeof(token), "0 %f 0", atof(token)); //change it from yaw to 3d angle + goto cont; + } +/* + key = ED_FindField (progfuncs, keyname); + if (!key) + { + if (!strcmp(keyname, "light")) //Quake lighthack - allows a field name and a classname to go by the same thing in the level editor + if ((key = ED_FindField (progfuncs, "light_lev"))) + goto cont; + if (externs->badfield && externs->badfield(&progfuncs->funcs, (struct edict_s*)ent, keyname, qcc_token)) + continue; + Con_DPrintf ("'%s' is not a field\n", keyname); + continue; + } +*/ +cont: + + fld = Hash_GetInsensitive(&lua.entityfields, keyname); + if (fld && fld->type == ev_float) + lua_pushnumber(L, atof(token)); + else if (fld && fld->type == ev_integer) + lua_pushinteger(L, atoi(token)); + else if (fld && fld->type == ev_vector) + { + char *e; + float x,y,z; + x = strtod(token, &e); + if (*e == ' ') + e++; + y = strtod(e, &e); + if (*e == ' ') + e++; + z = strtod(e, &e); + if (*e == ' ') + e++; + lua_pushvector(L, x, y, z); + } + else + lua_pushstring(L, token); + lua_setfield(L, -2, keyname); + + /*if (!ED_ParseEpair (progfuncs, (char*)ent->fields - progfuncs->funcs.stringtable, key->ofs, key->type, qcc_token)) + { + continue; +// Sys_Error ("ED_ParseEdict: parse error on entities"); + }*/ + } + + if (!init) + ent->ereftype = ER_FREE; + + return data; +} + +static int QDECL Lua_LoadEnts(pubprogfuncs_t *pf, const char *mapstring, void *ctx, void (PDECL *callback) (pubprogfuncs_t *progfuncs, struct edict_s *ed, void *ctx, const char *entstart, const char *entend)) +{ + lua_State *L = lua.ctx; + struct edict_s *ed = NULL; + const char *datastart = mapstring; + + lua_pushglobaltable(L); + while (1) + { + datastart = mapstring; + + mapstring = COM_Parse(mapstring); + if (!strcmp(com_token, "{")) + { + if (!ed) //first entity + ed = EDICT_NUM_PB(pf, 0); + else + ed = ED_Alloc(pf, false, 0); + ed->ereftype = ER_ENTITY; + if (pf->parms->entspawn) + pf->parms->entspawn(ed, true); + + lua_pushedict(L, ed); + mapstring = Lua_ParseEdict(pf, mapstring, ed); + + if (1) + { //we can't call the callback, as it would be unable to represent the function references. + int spawnflags, killonspawnflags = *(int*)ctx;//lame. really lame + lua_getfield(L, -1, "spawnflags"); //push -1["classname"]... + spawnflags = lua_tointeger(L, -1); + lua_pop(L, 1); + if (spawnflags & killonspawnflags) + lua.progfuncs.EntFree(&lua.progfuncs, ed); + else + { + lua_getfield(L, -1, "classname"); //push -1["classname"]... + //-3:globaltable, -2:enttable, -1:classname string + lua_gettable(L, -3); //pop the classname and look it up inside the global table (to find the function in question) + lua.globals.self = ed->entnum; + if (lua_pcall(L, 0, 0, 0) != 0) + { + const char *s = lua_tolstring(L, -1, NULL); + lua_getfield(L, -2, "classname"); //push -1["classname"]... + Con_Printf(CON_WARNING "spawn func %s: %s\n", lua_tolstring(L, -1, NULL), s); + lua_pop(L, 2); + } + } + } + else + { + lua_pop(L, 1); + callback(pf, ed, ctx, datastart, mapstring); + } + lua_pop(L, 1); //pop ent table + } + else + break; //unexpected token... + } + lua_pop(L, 1); return sv.world.edict_size; } @@ -1858,9 +2913,7 @@ static void QDECL Lua_SetStringField(pubprogfuncs_t *prinst, edict_t *ed, string base = (ed->entnum+1)<<10; val = (char*)fld-(char*)ed->v; - //push the entity table - lua.pushlightuserdata(lua.ctx, lua.edicttable[ed->entnum]); - lua.gettable(lua.ctx, LUA_REGISTRYINDEX); + lua_pushedict(lua.ctx, lua.edicttable[ed->entnum]); } else { @@ -1868,17 +2921,17 @@ static void QDECL Lua_SetStringField(pubprogfuncs_t *prinst, edict_t *ed, string val = (char*)fld-(char*)&lua.globals; //push the globals list - lua.getglobal(lua.ctx, "glob"); + lua_pushglobaltable(L); } *fld = base | val; //set the engine's value //set the stuff so that lua can read it properly. - lua.pushlightuserdata(L, (void *)(qintptr_t)val); - lua.pushfstring(L, "%s", str); - lua.rawset(L, -3); + lua_pushlightuserdata(L, (void *)(qintptr_t)val); + lua_pushstring(L, str); + lua_rawset(L, -3); //and pop the table - lua.pop(L, 1); + lua_pop(L, 1); } static const char *ASMCALL QDECL Lua_StringToNative(pubprogfuncs_t *prinst, string_t str) @@ -1891,7 +2944,7 @@ static const char *ASMCALL QDECL Lua_StringToNative(pubprogfuncs_t *prinst, stri if (!entnum) { //okay, its the global table. - lua.getglobal(lua.ctx, "glob"); + lua_pushglobaltable(lua.ctx); } else { @@ -1899,15 +2952,15 @@ static const char *ASMCALL QDECL Lua_StringToNative(pubprogfuncs_t *prinst, stri if (entnum >= lua.maxedicts) return ret; //erk... //get the entity's table - lua.pushlightuserdata(lua.ctx, lua.edicttable[entnum]); - lua.gettable(lua.ctx, LUA_REGISTRYINDEX); + lua_pushlightuserdata(lua.ctx, lua.edicttable[entnum]); + lua_gettable(lua.ctx, LUA_REGISTRYINDEX); } //read the function from the table - lua.pushlightuserdata(lua.ctx, (void *)(qintptr_t)str); - lua.rawget(lua.ctx, -2); - ret = lua.tolstring(lua.ctx, -1, NULL); - lua.pop(lua.ctx, 2); //pop the table+string. + lua_pushlightuserdata(lua.ctx, (void *)(qintptr_t)str); + lua_rawget(lua.ctx, -2); + ret = lua_tolstring(lua.ctx, -1, NULL); + lua_pop(lua.ctx, 2); //pop the table+string. //popping the string is 'safe' on the understanding that the string reference is still held by its containing table, so don't store the string anywhere. } @@ -1922,7 +2975,24 @@ static void Lua_Event_Touch(world_t *w, wedict_t *s, wedict_t *o) pr_global_struct->self = EDICT_TO_PROG(w->progs, s); pr_global_struct->other = EDICT_TO_PROG(w->progs, o); pr_global_struct->time = w->physicstime; + +#if 1 PR_ExecuteProgram (w->progs, s->v->touch); +#else + lua_pushedict(lua.ctx, s); + //lua_pushliteral(lua.ctx, "touch"); + lua_pushlightuserdata(lua.ctx, (void*)((char*)&s->v->touch-(char*)s->v)); + lua_rawget(lua.ctx, -2); + lua_replace(lua.ctx, -2); + if (lua_pcall(lua.ctx, 0, 0, 0) != 0) + { + const char *e = lua_tolstring(lua.ctx, -1, NULL); + lua_pushedict(lua.ctx, (struct edict_s*)s); + lua_getfield(lua.ctx, -1, "classname"); + Con_Printf(CON_WARNING "%s touch: %s\n", lua_tostring(lua.ctx, -1), e); + lua_pop(lua.ctx, 3); //error, enttable, classname + } +#endif pr_global_struct->self = oself; pr_global_struct->other = oother; @@ -1932,12 +3002,29 @@ static void Lua_Event_Think(world_t *w, wedict_t *s) { pr_global_struct->self = EDICT_TO_PROG(w->progs, s); pr_global_struct->other = EDICT_TO_PROG(w->progs, w->edicts); + +#if 0 PR_ExecuteProgram (w->progs, s->v->think); +#else + lua_pushedict(lua.ctx, (struct edict_s*)s); +// lua_pushliteral(lua.ctx, "think"); + lua_pushlightuserdata(lua.ctx, (void*)((char*)&s->v->think-(char*)s->v)); + lua_rawget(lua.ctx, -2); + lua_replace(lua.ctx, -2); + if (lua_pcall(lua.ctx, 0, 0, 0) != 0) + { + const char *e = lua_tolstring(lua.ctx, -1, NULL); + lua_pushedict(lua.ctx, (struct edict_s*)s); + lua_getfield(lua.ctx, -1, "classname"); + Con_Printf(CON_WARNING "%s think: %s\n", lua_tostring(lua.ctx, -1), e); + lua_pop(lua.ctx, 3); //error, enttable, classname + } +#endif } static qboolean Lua_Event_ContentsTransition(world_t *w, wedict_t *ent, int oldwatertype, int newwatertype) { - return false; //always do legacy behaviour + return false; //always do legacy behaviour, because I cba implementing anything else. } static void Lua_SetupGlobals(world_t *world) @@ -1951,6 +3038,7 @@ static void Lua_SetupGlobals(world_t *world) lua.globals.physics_mode = 2; lua.globals.dimension_send = 255; lua.globals.dimension_default = 255; + lua.globals.global_gravitydir[2] = -1; flds = 0; bucks = 64; @@ -1982,23 +3070,34 @@ static void Lua_SetupGlobals(world_t *world) #define doglobal(n, t) doglobal_v(n,n,t) luaextragloballist - flds = 0; +#define parm(n)\ + pr_global_ptrs->spawnparamglobals[n] = &lua.globals.parm[n]; \ + lua.globflds[flds].offset = (char*)&lua.globals.parm[n] - (char*)&lua.globals; \ + lua.globflds[flds].name = "parm"#n; \ + lua.globflds[flds].type = ev_float; \ + Hash_AddInsensitive(&lua.globalfields, lua.globflds[flds].name, &lua.globflds[flds], &lua.globflds[flds].buck); \ + flds++; + parm( 0);parm( 1);parm( 2);parm( 3);parm( 4);parm( 5);parm( 6);parm( 7); + parm( 8);parm( 9);parm(10);parm(11);parm(12);parm(13);parm(14);parm(15); +#undef parm + + lua.numflds = 0; bucks = 256; Hash_InitTable(&lua.entityfields, bucks, Z_Malloc(Hash_BytesForBuckets(bucks))); #define doefield(n, t) \ - lua.entflds[flds].offset = (char*)&v->n - (char*)v; \ - lua.entflds[flds].name = #n; \ - lua.entflds[flds].type = t; \ - Hash_AddInsensitive(&lua.entityfields, lua.entflds[flds].name, &lua.entflds[flds], &lua.entflds[flds].buck); \ - flds++; + lua.entflds[lua.numflds].offset = (char*)&v->n - (char*)v; \ + lua.entflds[lua.numflds].name = #n; \ + lua.entflds[lua.numflds].type = t; \ + Hash_AddInsensitive(&lua.entityfields, lua.entflds[lua.numflds].name, &lua.entflds[lua.numflds], &lua.entflds[lua.numflds].buck); \ + lua.numflds++; #define doefield_v(o, f, t) \ - lua.entflds[flds].offset = (char*)&v->o - (char*)v; \ - lua.entflds[flds].name = #f; \ - lua.entflds[flds].type = t; \ - Hash_AddInsensitive(&lua.entityfields, lua.entflds[flds].name, &lua.entflds[flds], &lua.entflds[flds].buck); \ - flds++; + lua.entflds[lua.numflds].offset = (char*)&v->o - (char*)v; \ + lua.entflds[lua.numflds].name = #f; \ + lua.entflds[lua.numflds].type = t; \ + Hash_AddInsensitive(&lua.entityfields, lua.entflds[lua.numflds].name, &lua.entflds[lua.numflds], &lua.entflds[lua.numflds].buck); \ + lua.numflds++; #define comfieldentity(name,desc) doefield(name, ev_entity) #define comfieldint(name,desc) doefield(name, ev_integer) #define comfieldfloat(name,desc) doefield(name, ev_float) @@ -2009,17 +3108,17 @@ static void Lua_SetupGlobals(world_t *world) #undef doefield #undef doefield_v #define doefield(n, t) \ - lua.entflds[flds].offset = (char*)&xv->n - (char*)v; \ - lua.entflds[flds].name = #n; \ - lua.entflds[flds].type = t; \ - Hash_AddInsensitive(&lua.entityfields, lua.entflds[flds].name, &lua.entflds[flds], &lua.entflds[flds].buck); \ - flds++; + lua.entflds[lua.numflds].offset = (char*)&xv->n - (char*)v; \ + lua.entflds[lua.numflds].name = #n; \ + lua.entflds[lua.numflds].type = t; \ + Hash_AddInsensitive(&lua.entityfields, lua.entflds[lua.numflds].name, &lua.entflds[lua.numflds], &lua.entflds[lua.numflds].buck); \ + lua.numflds++; #define doefield_v(o, f, t) \ - lua.entflds[flds].offset = (char*)&xv->o - (char*)v; \ - lua.entflds[flds].name = #f; \ - lua.entflds[flds].type = t; \ - Hash_AddInsensitive(&lua.entityfields, lua.entflds[flds].name, &lua.entflds[flds], &lua.entflds[flds].buck); \ - flds++; + lua.entflds[lua.numflds].offset = (char*)&xv->o - (char*)v; \ + lua.entflds[lua.numflds].name = #f; \ + lua.entflds[lua.numflds].type = t; \ + Hash_AddInsensitive(&lua.entityfields, lua.entflds[lua.numflds].name, &lua.entflds[lua.numflds], &lua.entflds[lua.numflds].buck); \ + lua.numflds++; comextqcfields svextqcfields @@ -2033,7 +3132,7 @@ void QDECL Lua_ExecuteProgram(pubprogfuncs_t *funcs, func_t func) if (!entnum) { //okay, its the global table. - lua.getglobal(lua.ctx, "glob"); + lua_pushglobaltable(lua.ctx); } else { @@ -2041,37 +3140,62 @@ void QDECL Lua_ExecuteProgram(pubprogfuncs_t *funcs, func_t func) if (entnum >= lua.maxedicts) return; //erk... //get the entity's table - lua.pushlightuserdata(lua.ctx, lua.edicttable[entnum]); - lua.gettable(lua.ctx, LUA_REGISTRYINDEX); + lua_pushlightuserdata(lua.ctx, lua.edicttable[entnum]); + lua_gettable(lua.ctx, LUA_REGISTRYINDEX); } //read the function from the table - lua.pushlightuserdata(lua.ctx, (void *)(qintptr_t)func); - lua.rawget(lua.ctx, -2); + lua_pushlightuserdata(lua.ctx, (void *)(qintptr_t)func); + lua_rawget(lua.ctx, -2); //and now invoke it. - if (lua.pcall(lua.ctx, 0, 0, 0) != 0) + if (lua_pcall(lua.ctx, 0, 0, 0) != 0) { - const char *s = lua.tolstring(lua.ctx, -1, NULL); + const char *s = lua_tolstring(lua.ctx, -1, NULL); Con_Printf(CON_WARNING "%s\n", s); - lua.pop(lua.ctx, 1); + lua_pop(lua.ctx, 1); } } void PDECL Lua_CloseProgs(pubprogfuncs_t *inst) { - lua.close(lua.ctx); + lua_close(lua.ctx); free(lua.edicttable); lua.edicttable = NULL; lua.maxedicts = 0; + + memset(&lua, 0, sizeof(lua)); +} + +static void QDECL Lua_Get_FrameState(world_t *w, wedict_t *ent, framestate_t *fstate) +{ + memset(fstate, 0, sizeof(*fstate)); + fstate->g[FS_REG].frame[0] = ent->v->frame; + fstate->g[FS_REG].frametime[0] = ent->xv->frame1time; + fstate->g[FS_REG].lerpweight[0] = 1; + fstate->g[FS_REG].endbone = 0x7fffffff; + + fstate->g[FST_BASE].frame[0] = ent->xv->baseframe; + fstate->g[FST_BASE].frametime[0] = ent->xv->/*base*/frame1time; + fstate->g[FST_BASE].lerpweight[0] = 1; + fstate->g[FST_BASE].endbone = ent->xv->basebone; + +#if defined(SKELETALOBJECTS) || defined(RAGDOLL) + if (ent->xv->skeletonindex) + skel_lookup(w, ent->xv->skeletonindex, fstate); +#endif } qboolean PR_LoadLua(void) { world_t *world = &sv.world; pubprogfuncs_t *pf; - vfsfile_t *sourcefile = FS_OpenVFS("progs.lua", "rb", FS_GAME); - if (!sourcefile) + vfsfile_t *sourcefile = NULL; + if ((sourcefile = FS_OpenVFS("qwprogs.lua", "rb", FS_GAME))) + progstype = PROG_QW; + else if ((sourcefile = FS_OpenVFS("progs.lua", "rb", FS_GAME))) + progstype = PROG_NQ; + else return false; if (!init_lua()) @@ -2081,15 +3205,12 @@ qboolean PR_LoadLua(void) return false; } - progstype = PROG_QW; - - pf = svprogfuncs = &lua.progfuncs; pf->CloseProgs = Lua_CloseProgs; pf->AddString = Lua_AddString; - pf->EDICT_NUM = Lua_EdictNum; - pf->NUM_FOR_EDICT = Lua_NumForEdict; + pf->EdictNum = Lua_EdictNum; + pf->NumForEdict = Lua_NumForEdict; pf->EdictToProgs = Lua_EdictToProgs; pf->ProgsToEdict = Lua_ProgsToEdict; pf->EntAlloc = Lua_EntAlloc; @@ -2110,10 +3231,13 @@ qboolean PR_LoadLua(void) world->Event_Sound = SVQ1_StartSound; world->Event_ContentsTransition = Lua_Event_ContentsTransition; world->Get_CModel = SVPR_GetCModel; + world->Get_FrameState = Lua_Get_FrameState; world->progs = pf; world->progs->parms = &lua.progfuncsparms; world->progs->parms->user = world; + world->progs->parms->Printf = PR_Printf; + world->progs->parms->DPrintf = PR_DPrintf; world->usesolidcorpse = true; Lua_SetupGlobals(world); @@ -2129,25 +3253,26 @@ qboolean PR_LoadLua(void) sv.haveitems2 = true; //initalise basic lua context - lua.ctx = lua.newstate(my_lua_alloc, NULL); //create our lua state + lua.ctx = lua_newstate(my_lua_alloc, NULL); //create our lua state +// luaL_openlibs(lua.ctx); my_lua_registerbuiltins(lua.ctx); //spawn the world, woo. world->edicts = (wedict_t*)pf->EntAlloc(pf,false,0); //load the gamecode now. it should be safe for it to call various builtins. - if (0 != lua.load(lua.ctx, my_lua_Reader, sourcefile, "progs.lua", "bt")) //load the file, embed it within a function and push it + if (0 != lua_load(lua.ctx, my_lua_Reader, sourcefile, "progs.lua", "bt")) //load the file, embed it within a function and push it { - Con_Printf("Error trying to parse %s: %s\n", "progs.lua", lua.tolstring(lua.ctx, -1, NULL)); - lua.pop(lua.ctx, 1); + Con_Printf("Error trying to parse %s: %s\n", "progs.lua", lua_tolstring(lua.ctx, -1, NULL)); + lua_pop(lua.ctx, 1); } else { - if (lua.pcall(lua.ctx, 0, 0, 0) != 0) + if (lua_pcall(lua.ctx, 0, 0, 0) != 0) { - const char *s = lua.tolstring(lua.ctx, -1, NULL); + const char *s = lua_tolstring(lua.ctx, -1, NULL); Con_Printf(CON_WARNING "%s\n", s); - lua.pop(lua.ctx, 1); + lua_pop(lua.ctx, 1); } } VFS_CLOSE(sourcefile); diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index 55c9a94c8..abd891241 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -472,7 +472,7 @@ static edict_t *QDECL Q1QVMPF_EntAlloc(pubprogfuncs_t *pf, pbool object, size_t edict_t *e; for ( i=0 ; ifreetime < 2 || sv.time - e->freetime > 0.5 ) )) @@ -488,7 +488,7 @@ static edict_t *QDECL Q1QVMPF_EntAlloc(pubprogfuncs_t *pf, pbool object, size_t { for ( i=0 ; i sv.allocated_client_slots) + if ((unsigned)VM_LONG(arg[0])-1u >= sv.allocated_client_slots) return 0; SV_ClientPrintf(&svs.clients[VM_LONG(arg[0])-1], VM_LONG(arg[1]), "%s", (char*)VM_POINTER(arg[2])); return 0; @@ -951,7 +951,7 @@ static qintptr_t QVM_FindRadius (void *offset, quintptr_t mask, const qintptr_t rad *= rad; for(start++; start < sv.world.num_edicts; start++) { - ed = EDICT_NUM(svprogfuncs, start); + ed = EDICT_NUM_PB(svprogfuncs, start); if (ED_ISFREE(ed)) continue; VectorSubtract(ed->v->origin, org, diff); @@ -962,7 +962,7 @@ static qintptr_t QVM_FindRadius (void *offset, quintptr_t mask, const qintptr_t } static qintptr_t QVM_WalkMove (void *offset, quintptr_t mask, const qintptr_t *arg) { - wedict_t *ed = WEDICT_NUM(svprogfuncs, arg[0]); + wedict_t *ed = WEDICT_NUM_UB(svprogfuncs, arg[0]); float yaw = VM_FLOAT(arg[1]); float dist = VM_FLOAT(arg[2]); vec3_t move; @@ -985,7 +985,7 @@ static qintptr_t QVM_DropToFloor (void *offset, quintptr_t mask, const qintptr_t trace_t trace; extern cvar_t pr_droptofloorunits; - ent = EDICT_NUM(svprogfuncs, arg[0]); + ent = EDICT_NUM_UB(svprogfuncs, arg[0]); VectorCopy (ent->v->origin, end); if (pr_droptofloorunits.value > 0) @@ -1010,7 +1010,7 @@ static qintptr_t QVM_DropToFloor (void *offset, quintptr_t mask, const qintptr_t static qintptr_t QVM_CheckBottom (void *offset, quintptr_t mask, const qintptr_t *arg) { vec3_t up = {0,0,1}; - return World_CheckBottom(&sv.world, (wedict_t*)EDICT_NUM(svprogfuncs, VM_LONG(arg[0])), up); + return World_CheckBottom(&sv.world, (wedict_t*)EDICT_NUM_UB(svprogfuncs, VM_LONG(arg[0])), up); } static qintptr_t QVM_PointContents (void *offset, quintptr_t mask, const qintptr_t *arg) { @@ -1033,7 +1033,7 @@ static qintptr_t QVM_NextEnt (void *offset, quintptr_t mask, const qintptr_t *ar { return 0; } - ent = EDICT_NUM(svprogfuncs, i); + ent = EDICT_NUM_PB(svprogfuncs, i); if (!ED_ISFREE(ent)) { return i; @@ -1530,7 +1530,7 @@ static qintptr_t QVM_Add_Bot (void *offset, quintptr_t mask, const qintptr_t *ar cl->datagram.allowoverflow = true; cl->datagram.maxsize = 0; - cl->edict = EDICT_NUM(sv.world.progs, i+1); + cl->edict = EDICT_NUM_PB(sv.world.progs, i+1); Info_SetValueForKey(cl->userinfo, "name", name, sizeof(cl->userinfo)); Info_SetValueForKey(cl->userinfo, "topcolor", va("%i", top), sizeof(cl->userinfo)); @@ -2167,8 +2167,8 @@ qboolean PR_LoadQ1QVM(void) // q1qvmprogfuncs.AddString = Q1QVMPF_AddString; //using this breaks 64bit support, and is a 'bad plan' elsewhere too, - q1qvmprogfuncs.EDICT_NUM = Q1QVMPF_EdictNum; - q1qvmprogfuncs.NUM_FOR_EDICT = Q1QVMPF_NumForEdict; + q1qvmprogfuncs.EdictNum = Q1QVMPF_EdictNum; + q1qvmprogfuncs.NumForEdict = Q1QVMPF_NumForEdict; q1qvmprogfuncs.EdictToProgs = Q1QVMPF_EdictToProgs; q1qvmprogfuncs.ProgsToEdict = Q1QVMPF_ProgsToEdict; q1qvmprogfuncs.EntAlloc = Q1QVMPF_EntAlloc; @@ -2262,6 +2262,7 @@ qboolean PR_LoadQ1QVM(void) sv.world.num_edicts = 1; sv.world.max_edicts = bound(64, gd.maxedicts, MAX_EDICTS); q1qvmprogfuncs.edicttable = Z_Malloc(sizeof(*q1qvmprogfuncs.edicttable) * sv.world.max_edicts); + q1qvmprogfuncs.edicttable_length = sv.world.max_edicts; limit = VM_MemoryMask(q1qvm); if (gd.sizeofent < 0 || gd.sizeofent > 0xffffffff / gd.maxedicts) diff --git a/engine/server/savegame.c b/engine/server/savegame.c index 6f489a5e2..4b8884a81 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -341,7 +341,7 @@ void SV_Loadgame_Legacy(char *filename, vfsfile_t *f, int version) { if (cl->state) sv.spawned_client_slots += 1; - ent = EDICT_NUM(svprogfuncs, i+1); + ent = EDICT_NUM_PB(svprogfuncs, i+1); } else ent = NULL; @@ -824,7 +824,7 @@ qboolean SV_LoadLevelCache(const char *savename, const char *level, const char * for (i=0 ; iereftype = ER_ENTITY; } } @@ -1210,6 +1210,20 @@ void SV_Savegame (const char *savename, qboolean mapchange) return; } + switch(svs.gametype) + { + default: + case GT_Q1QVM: +#ifdef VM_LUA + case GT_LUA: +#endif + Con_Printf("gamecode doesn't support saving\n"); + return; + case GT_PROGS: + case GT_QUAKE2: + break; + } + if (sv.allocated_client_slots == 1 && svs.gametype == GT_PROGS) { if (svs.clients->state > cs_connected && svs.clients[0].edict->v->health <= 0) @@ -1444,9 +1458,6 @@ void SV_AutoSave(void) default: //probably broken. don't ever try. return; -#ifdef VM_LUA - case GT_LUA: -#endif case GT_Q1QVM: case GT_PROGS: //don't bother to autosave multiplayer games. diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 44e6b8f94..ba8757be2 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -328,7 +328,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber) { if (!(client->pendingcsqcbits[entnum] & SENDFLAGS_REMOVED)) { //while the entity has NOREMOVE, only remove it if the remove is a resend - if ((int)EDICT_NUM(svprogfuncs, en)->xv->pvsflags & PVSF_NOREMOVE) + if ((int)EDICT_NUM_PB(svprogfuncs, en)->xv->pvsflags & PVSF_NOREMOVE) continue; } if (msg->cursize + 5 >= msg->maxsize) @@ -451,7 +451,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber) { if (!(client->pendingcsqcbits[entnum] & SENDFLAGS_REMOVED)) { //while the entity has NOREMOVE, only remove it if the remove is a resend - if ((int)EDICT_NUM(svprogfuncs, en)->xv->pvsflags & PVSF_NOREMOVE) + if ((int)EDICT_NUM_PB(svprogfuncs, entnum)->xv->pvsflags & PVSF_NOREMOVE) continue; } if (msg->cursize + 5 >= msg->maxsize) @@ -1387,7 +1387,7 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb o = &client->sentents.entities[j]; if (o->number) { - e = EDICT_NUM(svprogfuncs, o->number); + e = EDICT_NUM_PB(svprogfuncs, o->number); if (!((int)e->xv->pvsflags & PVSF_NOREMOVE)) { client->pendingdeltabits[j] = UF_REMOVE; @@ -1446,7 +1446,7 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb o = &client->sentents.entities[j]; if (o->number) { - e = EDICT_NUM(svprogfuncs, o->number); + e = EDICT_NUM_PB(svprogfuncs, o->number); if (!((int)e->xv->pvsflags & PVSF_NOREMOVE)) { client->pendingdeltabits[j] = UF_REMOVE; @@ -1527,14 +1527,14 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb { /*if reset2, then this is the second packet sent to the client and should have a forced reset (but which isn't tracked)*/ resend[outno].bits = bits & ~UF_RESET2; - bits = UF_RESET | SVFTE_DeltaCalcBits(&EDICT_NUM(svprogfuncs, j)->baseline, NULL, &client->sentents.entities[j], client->sentents.bonedata); + bits = UF_RESET | SVFTE_DeltaCalcBits(&EDICT_NUM_PB(svprogfuncs, j)->baseline, NULL, &client->sentents.entities[j], client->sentents.bonedata); // Con_Printf("RESET2 %i @ %i\n", j, sequence); } else if (bits & UF_RESET) { /*flag the entity for the next packet, so we always get two resets when it appears, to reduce the effects of packetloss on seeing rockets etc*/ client->pendingdeltabits[j] = UF_RESET2; - bits = UF_RESET | SVFTE_DeltaCalcBits(&EDICT_NUM(svprogfuncs, j)->baseline, NULL, &client->sentents.entities[j], client->sentents.bonedata); + bits = UF_RESET | SVFTE_DeltaCalcBits(&EDICT_NUM_PB(svprogfuncs, j)->baseline, NULL, &client->sentents.entities[j], client->sentents.bonedata); resend[outno].bits = UF_RESET; // Con_Printf("RESET %i @ %i\n", j, sequence); } @@ -1623,7 +1623,7 @@ void SVQW_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t if (newnum < oldnum) { // this is a new entity, send it from the baseline if (svprogfuncs) - ent = EDICT_NUM(svprogfuncs, newnum); + ent = EDICT_NUM_UB(svprogfuncs, newnum); else ent = NULL; //Con_Printf ("baseline %i\n", newnum); @@ -2593,7 +2593,7 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t * ent = cl->edict; if (cl->viewent && ent == clent) { - vent = EDICT_NUM(svprogfuncs, cl->viewent); + vent = EDICT_NUM_UB(svprogfuncs, cl->viewent); if (!vent) vent = ent; } @@ -2704,7 +2704,7 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t * { if (client->spec_track > 0) { - edict_t *s = EDICT_NUM(svprogfuncs, client->spec_track); + edict_t *s = EDICT_NUM_UB(svprogfuncs, client->spec_track); clst.spectator = 2; clst.mins = s->v->mins; @@ -2766,7 +2766,7 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t * #ifdef NQPROT void SVNQ_EmitEntityState(sizebuf_t *msg, entity_state_t *ent) { - edict_t *ed = EDICT_NUM(svprogfuncs, ent->number); + edict_t *ed = EDICT_NUM_PB(svprogfuncs, ent->number); entity_state_t *baseline = &ed->baseline; int i, eff; @@ -3536,7 +3536,7 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t for ( ; exv->tag_entity&&c-->0) { - tracecullent = EDICT_NUM(svprogfuncs, tracecullent->xv->tag_entity); + tracecullent = EDICT_NUM_UB(svprogfuncs, tracecullent->xv->tag_entity); } if (tracecullent == clent) tracecullent = NULL; @@ -3800,13 +3800,13 @@ void SV_Snapshot_SetupPVS(client_t *client, pvscamera_t *camera) for (; client; client = client->controlled) { if (client->viewent) //svc_viewentity hack - SV_AddCameraEntity(camera, EDICT_NUM(svprogfuncs, client->viewent), client->edict->v->view_ofs); + SV_AddCameraEntity(camera, EDICT_NUM_UB(svprogfuncs, client->viewent), client->edict->v->view_ofs); else SV_AddCameraEntity(camera, client->edict, client->edict->v->view_ofs); //spectators should always see their targetted player if (client->spec_track) - SV_AddCameraEntity(camera, EDICT_NUM(svprogfuncs, client->spec_track), client->edict->v->view_ofs); + SV_AddCameraEntity(camera, EDICT_NUM_UB(svprogfuncs, client->spec_track), client->edict->v->view_ofs); //view2 support should always see the extra entity if (client->edict->xv->view2) @@ -4031,7 +4031,7 @@ void SV_ProcessSendFlags(client_t *c) return; for (e=1 ; emax_net_ents; e++) { - ent = EDICT_NUM(svprogfuncs, e); + ent = EDICT_NUM_PB(svprogfuncs, e); if (ED_ISFREE(ent)) continue; if (ent->xv->SendFlags) @@ -4052,7 +4052,7 @@ void SV_CleanupEnts(void) for (e=1 ; e<=needcleanup ; e++) { - ent = EDICT_NUM(svprogfuncs, e); + ent = EDICT_NUM_PB(svprogfuncs, e); ent->xv->SendFlags = 0; #ifndef NOLEGACY diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 65c655ec3..b8b2cb18c 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -232,7 +232,7 @@ void SVQ1_CreateBaseline (void) for (entnum = 0; entnum < sv.world.num_edicts ; entnum++) { - svent = EDICT_NUM(svprogfuncs, entnum); + svent = EDICT_NUM_PB(svprogfuncs, entnum); memcpy(&svent->baseline, &nullentitystate, sizeof(entity_state_t)); svent->baseline.number = entnum; @@ -304,6 +304,7 @@ void SV_SpawnParmsToClient(client_t *client) void SV_SaveSpawnparmsClient(client_t *client, float *transferparms) { int j; + eval_t *eval; SV_SpawnParmsToQC(client); #ifdef VM_Q1 @@ -344,7 +345,8 @@ void SV_SaveSpawnparmsClient(client_t *client, float *transferparms) } // call the progs to get default spawn parms for the new client - if (PR_FindGlobal(svprogfuncs, "ClientReEnter", 0, NULL)) + eval = PR_FindGlobal(svprogfuncs, "ClientReEnter", 0, NULL); + if (eval && eval->function) {//oooh, evil. char buffer[65536*4]; size_t bufsize = 0; @@ -1280,7 +1282,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents, #endif case GT_Q1QVM: case GT_PROGS: - ent = EDICT_NUM(svprogfuncs, 0); + ent = EDICT_NUM_PB(svprogfuncs, 0); ent->ereftype = ER_ENTITY; #ifndef SERVERONLY @@ -1386,7 +1388,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents, { //world entity is hackily spawned extern cvar_t coop, pr_imitatemvdsv; - ent = EDICT_NUM(svprogfuncs, 0); + ent = EDICT_NUM_PB(svprogfuncs, 0); ent->ereftype = ER_ENTITY; #ifdef VM_Q1 if (svs.gametype != GT_Q1QVM) //we cannot do this with qvm @@ -1518,7 +1520,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents, if (svprogfuncs) { eval_t *val; - ent = EDICT_NUM(svprogfuncs, 0); + ent = EDICT_NUM_PB(svprogfuncs, 0); ent->v->angles[0] = ent->v->angles[1] = ent->v->angles[2] = 0; if ((val = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "message", ev_string, NULL))) snprintf(sv.mapname, sizeof(sv.mapname), "%s", PR_GetString(svprogfuncs, val->string)); @@ -1614,7 +1616,8 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents, { eval_t *eval; eval = PR_FindGlobal(svprogfuncs, "startspot", 0, NULL); - if (eval) eval->string = PR_NewString(svprogfuncs, startspot); + if (eval && svs.gametype != GT_Q1QVM) //we cannot do this with qvm + svprogfuncs->SetStringField(svprogfuncs, NULL, &eval->string, startspot, false); } if (Cmd_AliasExist("f_svnewmap", RESTRICT_LOCAL)) @@ -1633,7 +1636,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents, //fixme: go off bsp extents instead? for(i = 1; i < sv.world.num_edicts; i++) { - ent = EDICT_NUM(svprogfuncs, i); + ent = EDICT_NUM_PB(svprogfuncs, i); for (j = 0; j < 3; j++) { ne = fabs(ent->v->origin[j]); diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 1a1ff363d..020babc51 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -2242,7 +2242,7 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id) break; #endif default: - cl->edict = EDICT_NUM(svprogfuncs, i+1); + cl->edict = EDICT_NUM_PB(svprogfuncs, i+1); break; } @@ -3006,7 +3006,7 @@ client_t *SVC_DirectConnect(void) } if (svprogfuncs) - ent = EDICT_NUM(svprogfuncs, edictnum); + ent = EDICT_NUM_UB(svprogfuncs, edictnum); else ent = NULL; #ifdef Q2SERVER diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index cc76617de..601213469 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -701,7 +701,7 @@ static qboolean WPhys_PushAngles (world_t *w, wedict_t *pusher, vec3_t move, vec if (pusher->v->movetype != MOVETYPE_H2PUSHPULL) for (e = 1; e < w->num_edicts; e++) { - check = WEDICT_NUM(w->progs, e); + check = WEDICT_NUM_PB(w->progs, e); if (ED_ISFREE(check)) continue; @@ -902,7 +902,7 @@ qboolean WPhys_Push (world_t *w, wedict_t *pusher, vec3_t move, vec3_t amove) num_moved = 0; for (e=1 ; enum_edicts ; e++) { - check = WEDICT_NUM(w->progs, e); + check = WEDICT_NUM_PB(w->progs, e); if (ED_ISFREE(check)) continue; if (check->v->movetype == MOVETYPE_PUSH @@ -2368,7 +2368,7 @@ void World_Physics_Frame(world_t *w) /*physics mode 1 = thinks only*/ for (i=0 ; inum_edicts ; i++) { - ent = (wedict_t*)EDICT_NUM(w->progs, i); + ent = (wedict_t*)EDICT_NUM_PB(w->progs, i); if (ED_ISFREE(ent)) continue; @@ -2386,7 +2386,7 @@ void World_Physics_Frame(world_t *w) // for (i=0 ; inum_edicts ; i++) { - ent = (wedict_t*)EDICT_NUM(w->progs, i); + ent = (wedict_t*)EDICT_NUM_PB(w->progs, i); if (ED_ISFREE(ent)) continue; diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index e9eabb2ef..0d22ee769 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -1710,7 +1710,7 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum) // a fixangle might get lost in a dropped packet. Oh well. if (client->spectator && ISNQCLIENT(client) && client->spec_track > 0) { - edict_t *ed = EDICT_NUM(svprogfuncs, client->spec_track); + edict_t *ed = EDICT_NUM_UB(svprogfuncs, client->spec_track); MSG_WriteByte(msg, svc_setangle); MSG_WriteAngle(msg, ed->v->v_angle[0]); MSG_WriteAngle(msg, ed->v->v_angle[1]); @@ -1841,7 +1841,7 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) #ifdef NQPROT ent = client->edict; if (client->spectator && client->spec_track) - ent = EDICT_NUM(svprogfuncs, client->spec_track); + ent = EDICT_NUM_UB(svprogfuncs, client->spec_track); if (progstype != PROG_QW) { if (ISQWCLIENT(client) && !(client->fteprotocolextensions2 & PEXT2_PREDINFO)) @@ -2250,7 +2250,7 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf // if we are a spectator and we are tracking a player, we get his stats // so our status bar reflects his if (client->spectator && client->spec_track > 0) - ent = EDICT_NUM(svprogfuncs, client->spec_track); + ent = EDICT_NUM_UB(svprogfuncs, client->spec_track); #ifdef HLSERVER if (svs.gametype == GT_HALFLIFE) diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 724baae9c..c41969d19 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -1536,7 +1536,7 @@ void SV_SendClientPrespawnInfo(client_t *client) break; } - ent = EDICT_NUM(svprogfuncs, client->prespawn_idx); + ent = EDICT_NUM_PB(svprogfuncs, client->prespawn_idx); if (!ent) state = &nullentitystate; @@ -1918,7 +1918,7 @@ void SV_SpawnSpectator (void) for (i=svs.allocated_client_slots+1 ; iv->classname), "info_player_start")) { VectorCopy (e->v->origin, sv_player->v->origin); @@ -2000,7 +2000,7 @@ void SV_Begin_Core(client_t *split) { //keep the spectator tracking the player from the previous map if (split->spec_track > 0) - split->edict->v->goalentity = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, split->spec_track)); + split->edict->v->goalentity = EDICT_TO_PROG(svprogfuncs, EDICT_NUM_UB(svprogfuncs, split->spec_track)); else split->edict->v->goalentity = 0; @@ -4144,8 +4144,8 @@ void SV_PTrack_f (void) { // turn off tracking host_client->spec_track = 0; - ent = EDICT_NUM(svprogfuncs, host_client - svs.clients + 1); - tent = EDICT_NUM(svprogfuncs, 0); + ent = EDICT_NUM_PB(svprogfuncs, host_client - svs.clients + 1); + tent = EDICT_NUM_PB(svprogfuncs, 0); ent->v->goalentity = EDICT_TO_PROG(svprogfuncs, tent); if (ISNQCLIENT(host_client)) @@ -4169,8 +4169,8 @@ void SV_PTrack_f (void) { SV_ClientTPrintf (host_client, PRINT_HIGH, "invalid player to track\n"); host_client->spec_track = 0; - ent = EDICT_NUM(svprogfuncs, host_client - svs.clients + 1); - tent = EDICT_NUM(svprogfuncs, 0); + ent = EDICT_NUM_PB(svprogfuncs, host_client - svs.clients + 1); + tent = EDICT_NUM_PB(svprogfuncs, 0); ent->v->goalentity = EDICT_TO_PROG(svprogfuncs, tent); if (ISNQCLIENT(host_client)) @@ -4182,8 +4182,8 @@ void SV_PTrack_f (void) } host_client->spec_track = i + 1; // now tracking - ent = EDICT_NUM(svprogfuncs, host_client - svs.clients + 1); - tent = EDICT_NUM(svprogfuncs, i + 1); + ent = EDICT_NUM_PB(svprogfuncs, host_client - svs.clients + 1); + tent = EDICT_NUM_PB(svprogfuncs, i + 1); ent->v->goalentity = EDICT_TO_PROG(svprogfuncs, tent); if (ISNQCLIENT(host_client)) @@ -7223,7 +7223,7 @@ if (sv_player->v->health > 0 && before && !after ) if (pmove.onground) { sv_player->v->flags = (int)sv_player->v->flags | FL_ONGROUND; - sv_player->v->groundentity = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, pmove.physents[pmove.groundent].info)); + sv_player->v->groundentity = EDICT_TO_PROG(svprogfuncs, EDICT_NUM_PB(svprogfuncs, pmove.physents[pmove.groundent].info)); } else sv_player->v->flags = (int)sv_player->v->flags & ~FL_ONGROUND; @@ -7305,7 +7305,7 @@ if (sv_player->v->health > 0 && before && !after ) float vel; vec3_t dir; vec3_t svel; - ent = EDICT_NUM(svprogfuncs, n); + ent = EDICT_NUM_PB(svprogfuncs, n); VectorSubtract(ent->v->origin, sv_player->v->origin, dir); VectorNormalize(dir); VectorCopy(sv_player->v->velocity, svel); @@ -7319,7 +7319,7 @@ if (sv_player->v->health > 0 && before && !after ) if (pmove.physents[pmove.touchindex[i]].notouch) continue; n = pmove.physents[pmove.touchindex[i]].info; - ent = EDICT_NUM(svprogfuncs, n); + ent = EDICT_NUM_PB(svprogfuncs, n); if (n >= playertouchmax || playertouch[n>>3]&(1<<(n&7))) continue; @@ -7437,7 +7437,7 @@ void SV_ReadPrydonCursor(void) } // as requested by FrikaC, cursor_trace_ent is reset to world if the // entity is free at time of receipt - if (!svprogfuncs || ED_ISFREE(EDICT_NUM(svprogfuncs, entnum))) + if (!svprogfuncs || ED_ISFREE(EDICT_NUM_UB(svprogfuncs, entnum))) entnum = 0; if (msg_badread) Con_Printf("SV_ReadPrydonCursor: badread at %s:%i\n", __FILE__, __LINE__); @@ -7512,7 +7512,7 @@ void SV_ReadQCRequest(void) e = MSGSV_ReadEntity(host_client); if (e < 0 || e >= sv.world.num_edicts) e = 0; - G_INT(OFS_PARM0+i*3) = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, e)); + G_INT(OFS_PARM0+i*3) = EDICT_TO_PROG(svprogfuncs, EDICT_NUM_PB(svprogfuncs, e)); break; } i++; @@ -8164,7 +8164,7 @@ void SVNQ_ReadClientMove (usercmd_t *move, qboolean forceangle16) if (host_client->spec_track) { //disable tracking host_client->spec_track = 0; - host_client->edict->v->goalentity = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, 0)); + host_client->edict->v->goalentity = EDICT_TO_PROG(svprogfuncs, EDICT_NUM_PB(svprogfuncs, 0)); ClientReliableWrite_Begin(host_client, svc_setview, 4); ClientReliableWrite_Entity(host_client, host_client - svs.clients + 1); } @@ -8194,7 +8194,7 @@ void SVNQ_ReadClientMove (usercmd_t *move, qboolean forceangle16) } host_client->spec_track = i; - host_client->edict->v->goalentity = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, i)); + host_client->edict->v->goalentity = EDICT_TO_PROG(svprogfuncs, EDICT_NUM_PB(svprogfuncs, i)); ClientReliableWrite_Begin(host_client, svc_setview, 4); ClientReliableWrite_Entity(host_client, i?i:(host_client - svs.clients + 1)); diff --git a/engine/server/world.c b/engine/server/world.c index b5c0b6c2a..73d5e863d 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -308,7 +308,7 @@ void World_ClearWorld_Nodes (world_t *w, qboolean relink) { for (i=0 ; inum_edicts ; i++) { - ent = WEDICT_NUM(w->progs, i); + ent = WEDICT_NUM_PB(w->progs, i); if (!ent) continue; ent->area.prev = ent->area.next = NULL; @@ -369,7 +369,7 @@ static void World_ClearWorld_AreaGrid (world_t *w, qboolean relink) { for (i=0 ; inum_edicts ; i++) { - ent = WEDICT_NUM(w->progs, i); + ent = WEDICT_NUM_PB(w->progs, i); if (!ent) continue; for (j = 0; j < countof(ent->gridareas); j++) @@ -1802,7 +1802,7 @@ static void World_ClipToEverything (world_t *w, moveclip_t *clip) wedict_t *touch; for (e=1 ; enum_edicts ; e++) { - touch = (wedict_t*)EDICT_NUM(w->progs, e); + touch = (wedict_t*)EDICT_NUM_PB(w->progs, e); if (ED_ISFREE(touch)) continue; @@ -2414,7 +2414,7 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e if (type & MOVE_OTHERONLY) { - wedict_t *other = WEDICT_NUM(w->progs, *w->g.other); + wedict_t *other = WEDICT_NUM_UB(w->progs, *w->g.other); return World_ClipMoveToEntity (w, other, other->v->origin, start, mins, maxs, end, hullnum, type & MOVE_HITMODEL, clip.capsule, clip.hitcontentsmask); } @@ -2502,7 +2502,7 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e if (clip.trace.allsolid) break; - touch = (wedict_t*)EDICT_NUM(w->progs, i+1); + touch = (wedict_t*)EDICT_NUM_PB(w->progs, i+1); if (touch->v->solid == SOLID_NOT) continue; if (touch == clip.passedict) @@ -2647,7 +2647,7 @@ void World_RBE_Shutdown(world_t *world) { for (u = 0; u < world->num_edicts; u++) { - ed = WEDICT_NUM(world->progs, u); + ed = WEDICT_NUM_PB(world->progs, u); world->rbe->RemoveJointFromEntity(world, ed); world->rbe->RemoveFromEntity(world, ed); } diff --git a/plugins/avplug/avaudio.c b/plugins/avplug/avaudio.c index e0e7fcec0..3d136f64c 100644 --- a/plugins/avplug/avaudio.c +++ b/plugins/avplug/avaudio.c @@ -287,7 +287,7 @@ static qboolean QDECL S_LoadAVSound (sfx_t *s, qbyte *data, size_t datalen, int const int iBufSize = 4 * 1024; if (!ffmpeg_audiodecoder) - ffmpeg_audiodecoder = pCvar_GetNVFDG("ffmpeg_audiodecoder_wip", "0", 0, "Enables the use of ffmpeg's decoder for pure audio files.", "ffmpeg"); + return false; if (!ffmpeg_audiodecoder->value /* && *ffmpeg_audiodecoder.string */) return false; @@ -358,6 +358,8 @@ static qboolean AVAudio_Init(void) { if (!pPlug_ExportNative("S_LoadSound", S_LoadAVSound)) { + ffmpeg_audiodecoder = pCvar_GetNVFDG("ffmpeg_audiodecoder_wip", "0", 0, "Enables the use of ffmpeg's decoder for pure audio files.", "ffmpeg"); + Con_Printf("avplug: Engine doesn't support audio decoder plugins\n"); return false; } diff --git a/plugins/bullet/bulletplug.cpp b/plugins/bullet/bulletplug.cpp index a0587a0c9..dd7c05e68 100644 --- a/plugins/bullet/bulletplug.cpp +++ b/plugins/bullet/bulletplug.cpp @@ -1572,14 +1572,14 @@ static void QDECL World_Bullet_Frame(world_t *world, double frametime, double gr // copy physics properties from entities to physics engine for (i = 0;i < world->num_edicts;i++) { - ed = (wedict_t*)EDICT_NUM(world->progs, i); + ed = (wedict_t*)EDICT_NUM_PB(world->progs, i); if (!ED_ISFREE(ed)) World_Bullet_Frame_BodyFromEntity(world, ed); } // oh, and it must be called after all bodies were created for (i = 0;i < world->num_edicts;i++) { - ed = (wedict_t*)EDICT_NUM(world->progs, i); + ed = (wedict_t*)EDICT_NUM_PB(world->progs, i); if (!ED_ISFREE(ed)) World_Bullet_Frame_JointFromEntity(world, ed); } @@ -1620,7 +1620,7 @@ static void QDECL World_Bullet_Frame(world_t *world, double frametime, double gr // copy physics properties from physics engine to entities for (i = 1;i < world->num_edicts;i++) { - ed = (wedict_t*)EDICT_NUM(world->progs, i); + ed = (wedict_t*)EDICT_NUM_PB(world->progs, i); if (!ED_ISFREE(ed)) World_Bullet_Frame_BodyToEntity(world, ed); }