diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e2080466..3a0fe5904 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,7 +94,7 @@ IF(NOT PNG_FOUND) MESSAGE(WARNING "libpng library NOT available. Good luck with screenshots.") SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_PNG) ENDIF() - + FIND_PACKAGE(Freetype) IF(FREETYPE_FOUND) INCLUDE_DIRECTORIES( ${FREETYPE_INCLUDE_DIRS} ) @@ -708,7 +708,6 @@ ELSE() FIND_PACKAGE(Bullet) IF (BULLET_FOUND) ADD_LIBRARY(bullet MODULE - plugins/qvm_api.c plugins/plugin.c plugins/bullet/bulletplug.cpp ) @@ -850,7 +849,22 @@ ELSE() SET(INSTALLTARGS ${INSTALLTARGS} fteqccgui) ELSE() FIND_PACKAGE(Qt5Widgets) - IF (Qt5Widgets_FOUND) + + FIND_PATH(QSCINTILLA_INCLUDE_DIR + NAMES Qsci/qsciglobal.h + PATHS ${Qt5Widgets_INCLUDE_DIRS} + PATH_SUFFIXES Qsci + ) + FIND_LIBRARY(QSCINTILLA_LIBRARY + NAMES qscintilla2_qt5 + PATHS + ${QT_LIBRARY_DIR} + /usr/local/lib + /usr/local/lib/qt5 + /usr/lib + ) + + IF (QSCINTILLA_INCLUDE_DIR AND QSCINTILLA_LIBRARY AND Qt5Widgets_FOUND) ADD_EXECUTABLE(fteqccgui engine/qclib/qccguiqt.cpp engine/qclib/qccguistuff.c @@ -864,10 +878,12 @@ ELSE() engine/qclib/packager.c engine/qclib/qcd_main.c ) - TARGET_INCLUDE_DIRECTORIES(fteqccgui PUBLIC ${Qt5Widgets_INCLUDE_DIRS}) + TARGET_INCLUDE_DIRECTORIES(fteqccgui PUBLIC ${Qt5Widgets_INCLUDE_DIRS} ${QSCINTILLA_INCLUDE_DIR}) SET_TARGET_PROPERTIES(fteqccgui PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_REVISON};${Qt5Widgets_COMPILE_DEFINITIONS}") SET_PROPERTY(TARGET fteqccgui PROPERTY POSITION_INDEPENDENT_CODE TRUE) - TARGET_LINK_LIBRARIES(fteqccgui ${ZLIB_LIBRARIES} ${Qt5Widgets_LIBRARIES} qscintilla2_qt5) + TARGET_LINK_LIBRARIES(fteqccgui ${ZLIB_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${QSCINTILLA_LIBRARY}) + ELSE() + MESSAGE(WARNING "qscintilla/qt5widgets library not detected, no fteqccgui for you") SET(INSTALLTARGS ${INSTALLTARGS} fteqccgui) ENDIF() ENDIF() @@ -875,7 +891,6 @@ ENDIF() #Quake Injector Alike plugin ADD_LIBRARY(qi MODULE - plugins/qvm_api.c plugins/plugin.c plugins/qi/qi.c plugins/emailnot/md5.c @@ -892,7 +907,6 @@ FIND_PATH(LIBODE_INCLUDE_DIR ode/ode.h) FIND_LIBRARY(LIBODE_LIBRARY ode) IF (LIBODE_INCLUDE_DIR) ADD_LIBRARY(ode MODULE - plugins/qvm_api.c plugins/plugin.c engine/common/com_phys_ode.c engine/common/mathlib.c @@ -907,7 +921,6 @@ ENDIF() #EzQuake Hud port plugin ADD_LIBRARY(ezhud MODULE - plugins/qvm_api.c plugins/plugin.c plugins/ezhud/ezquakeisms.c plugins/ezhud/hud.c @@ -920,9 +933,30 @@ SET_TARGET_PROPERTIES(ezhud PROPERTIES LINK_FLAGS "-Wl,--no-undefined") TARGET_LINK_LIBRARIES(ezhud m) SET(INSTALLTARGS ${INSTALLTARGS} ezhud) +#NameMaker string generation plugin +ADD_LIBRARY(namemaker MODULE + plugins/plugin.c + plugins/namemaker/namemaker.c +) +SET_TARGET_PROPERTIES(namemaker PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES}") +SET_TARGET_PROPERTIES(namemaker PROPERTIES PREFIX "fteplug_") +SET_TARGET_PROPERTIES(namemaker PROPERTIES LINK_FLAGS "-Wl,--no-undefined") +TARGET_LINK_LIBRARIES(namemaker m) +SET(INSTALLTARGS ${INSTALLTARGS} namemaker) + +#Terrain Generation plugin +ADD_LIBRARY(terrorgen MODULE + plugins/plugin.c + plugins/terrorgen/terragen.c +) +SET_TARGET_PROPERTIES(terrorgen PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}") +SET_TARGET_PROPERTIES(terrorgen PROPERTIES PREFIX "fteplug_") +SET_TARGET_PROPERTIES(terrorgen PROPERTIES LINK_FLAGS "-Wl,--no-undefined") +TARGET_LINK_LIBRARIES(terrorgen m) +SET(INSTALLTARGS ${INSTALLTARGS} terrorgen) + #IRC client plugin ADD_LIBRARY(irc MODULE - plugins/qvm_api.c plugins/plugin.c plugins/irc/ircclient.c ) @@ -934,10 +968,10 @@ SET(INSTALLTARGS ${INSTALLTARGS} irc) #model formats plugin ADD_LIBRARY(models MODULE - plugins/qvm_api.c plugins/plugin.c plugins/models/models.c plugins/models/gltf.c + plugins/models/exportiqm.c ) SET_TARGET_PROPERTIES(models PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}") SET_TARGET_PROPERTIES(models PROPERTIES PREFIX "fteplug_") @@ -945,20 +979,22 @@ SET_TARGET_PROPERTIES(models PROPERTIES LINK_FLAGS "-Wl,--no-undefined") TARGET_LINK_LIBRARIES(models m) SET(INSTALLTARGS ${INSTALLTARGS} models) -#x11 server plugin (note: for displaying other programs) -ADD_LIBRARY(x11 MODULE - plugins/qvm_api.c - plugins/plugin.c - plugins/xsv/m_x.c - plugins/xsv/x_reqs.c - plugins/xsv/x_res.c - engine/qclib/hash.c -) -SET_TARGET_PROPERTIES(x11 PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}") -SET_TARGET_PROPERTIES(x11 PROPERTIES PREFIX "fteplug_") -SET_TARGET_PROPERTIES(x11 PROPERTIES LINK_FLAGS "-Wl,--no-undefined") -TARGET_LINK_LIBRARIES(x11 m) -SET(INSTALLTARGS ${INSTALLTARGS} x11) +IF(0) + #x11 server plugin (note: for displaying other programs) + #not stable enough, and probably won't ever be + ADD_LIBRARY(x11sv MODULE + plugins/plugin.c + plugins/xsv/m_x.c + plugins/xsv/x_reqs.c + plugins/xsv/x_res.c + engine/qclib/hash.c + ) + SET_TARGET_PROPERTIES(x11sv PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}") + SET_TARGET_PROPERTIES(x11sv PROPERTIES PREFIX "fteplug_") + SET_TARGET_PROPERTIES(x11sv PROPERTIES LINK_FLAGS "-Wl,--no-undefined") + TARGET_LINK_LIBRARIES(x11sv m) + SET(INSTALLTARGS ${INSTALLTARGS} x11sv) +ENDIF() #ffmpeg client plugin. no proper way to detect dependancies right now, so I've gotta try the manual way. FIND_PATH(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h) @@ -972,7 +1008,6 @@ IF((AVFORMAT_INCLUDE_DIR) AND (AVSWSCALE_INCLUDE_DIR)) FIND_LIBRARY(AVSWSCALE_LIBRARY swscale) ADD_LIBRARY(ffmpeg MODULE - plugins/qvm_api.c plugins/plugin.c plugins/avplug/avaudio.c plugins/avplug/avdecode.c @@ -988,10 +1023,11 @@ ELSE() MESSAGE(WARNING "ffmpeg library NOT available. Quake shouldn't be playing fmv anyway.") ENDIF() +#TODO: cef plugin + IF(NOT ANDROID) #XMPP/jabber client plugin ADD_LIBRARY(xmpp MODULE - plugins/qvm_api.c plugins/plugin.c plugins/jabber/jabberclient.c plugins/jabber/xml.c @@ -1016,5 +1052,3 @@ INSTALL(TARGETS ${INSTALLTARGS} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}${FTE_INSTALL_BINDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" ) - -#cef plugin diff --git a/engine/client/api_menu.h b/engine/client/api_menu.h index 62f44aec5..209859e00 100644 --- a/engine/client/api_menu.h +++ b/engine/client/api_menu.h @@ -64,6 +64,7 @@ struct menu_inputevent_args_s MIE_KEYUP = 1, MIE_MOUSEDELTA = 2, MIE_MOUSEABS = 3, + MIE_JOYAXIS = 4, } eventtype; unsigned int devid; union @@ -78,6 +79,11 @@ struct menu_inputevent_args_s float delta[2]; float screen[2]; //virtual coords } mouse; + struct + { + unsigned int axis; + float val; + } axis; }; }; @@ -159,9 +165,10 @@ typedef struct { void (*renderscene) (menuscene_t *scene); // Menu specific stuff - qboolean (*setkeydest) (qboolean focused); //returns whether it changed. - int (*getkeydest) (void); //returns 0 if unfocused, -1 if active-but-unfocused, 1 if focused-and-active. - int (*setmousetarget) (const char *cursorname, float hot_x, float hot_y, float scale); //forces absolute mouse coords whenever cursorname isn't NULL + void (*pushmenu) (void *ctx); //will have key focus. + qboolean (*ismenupushed) (void *ctx); //reports if its still pushed (but not necessarily the active one!). + void (*killmenu) (void *ctx); //force-removes a menu. + int (*setmousecursor) (const char *cursorname, float hot_x, float hot_y, float scale); //forces absolute mouse coords whenever cursorname isn't NULL const char *(*keynumtostring) (int keynum, int modifier); int (*stringtokeynum) (const char *key, int *modifier); int (*findkeysforcommand) (int bindmap, const char *command, int *out_scancodes, int *out_modifiers, int keycount); @@ -185,11 +192,13 @@ typedef struct { void (*Init) (mintreason_t reason, float vwidth, float vheight, int pwidth, int pheight); void (*Shutdown) (mintreason_t reason); - void (*Draw) (double frametime); - void (*DrawLoading) (double frametime); + void (*DrawLoading) (double frametime); //pure loading screen. void (*Toggle) (int wantmode); - int (*InputEvent) (struct menu_inputevent_args_s ev); qboolean(*ConsoleCommand) (const char *cmdline, int argc, char const*const*argv); + + void (*Draw) (void *ctx, double frametime); //draws a menu. + qboolean(*InputEvent) (void *ctx, struct menu_inputevent_args_s ev); //return true to prevent the engine handling it (ie: because you already did). + void (*Closed) (void *ctx); //a pushed menu was closed. } menu_export_t; #ifndef NATIVEEXPORT diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index 1e8b52a62..8435303aa 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -1081,10 +1081,10 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con break; case CG_KEY_GETCATCHER: - VM_LONG(ret) = keycatcher; + VM_LONG(ret) = Q3_GetKeyCatcher(); break; case CG_KEY_SETCATCHER: - keycatcher = VM_LONG(arg[0]); + Q3_SetKeyCatcher(VM_LONG(arg[0])); break; case CG_GETGLCONFIG: @@ -1313,7 +1313,7 @@ int CG_Refresh(void) void CG_Stop (void) { - keycatcher &= ~2; + Q3_SetKeyCatcher(Q3_GetKeyCatcher()&~2); if (cgvm) { VM_Call(cgvm, CG_SHUTDOWN); @@ -1380,7 +1380,8 @@ void CG_Command_f(void) qboolean CG_KeyPress(int key, int unicode, int down) { - if (!cgvm || !(keycatcher&8)) + int catcher = Q3_GetKeyCatcher(); + if (!cgvm || !(catcher&8)) return false; return VM_Call(cgvm, CG_KEY_EVENT, key, down); } diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 46fcf53b8..5c3553b87 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -547,8 +547,7 @@ qboolean CL_GetDemoMessage (void) { //start the timer only once we are connected. //make sure everything is loaded, to avoid stalls - if (Key_Dest_Has(kdm_gmenu)) - MP_Toggle(0); + Menu_PopAll(); COM_WorkerFullSync(); cls.td_starttime = Sys_DoubleTime(); @@ -556,7 +555,6 @@ qboolean CL_GetDemoMessage (void) //force the console up, we're done loading. Key_Dest_Remove(kdm_console); - Key_Dest_Remove(kdm_emenu); scr_con_current = 0; } @@ -2619,7 +2617,7 @@ void CL_QTVPoll (void) qboolean streamavailable = false; qboolean saidheader = false; #ifndef NOBUILTINMENUS - menu_t *sourcesmenu = NULL; + emenu_t *sourcesmenu = NULL; #endif int sourcenum = 0; @@ -2794,7 +2792,6 @@ void CL_QTVPoll (void) //now put it on a menu if (!sourcesmenu) { - Key_Dest_Add(kdm_emenu); sourcesmenu = M_CreateMenu(0); MC_AddPicture(sourcesmenu, 16, 4, 32, 144, "gfx/qplaque.lmp"); diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index fad7b0b42..8a2311f0e 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -35,6 +35,8 @@ extern cvar_t cl_item_bobbing; extern cvar_t r_rocketlight; extern cvar_t r_lightflicker; +extern cvar_t r_dimlight_colour; +extern cvar_t r_brightlight_colour; extern cvar_t cl_r2g; extern cvar_t r_powerupglow; extern cvar_t v_powerupshell; @@ -1396,7 +1398,7 @@ entity_state_t *CL_FindOldPacketEntity(int num) #ifdef NQPROT void DP5_ParseDelta(entity_state_t *s, packet_entities_t *pack) { - int bits; + unsigned int bits; if (cl_shownet.ival >= 3) Con_Printf("%3i: Update %i", msg_readcount, s->number); @@ -3992,17 +3994,13 @@ void CL_LinkPacketEntities (void) if (state->effects & EF_BRIGHTLIGHT) { - radius = max(radius,400); - colour[0] += 2.0; - colour[1] += 1.0; - colour[2] += 0.5; + radius = max(radius,r_dimlight_colour.vec4[3]); + VectorAdd(colour, r_dimlight_colour.vec4, colour); } if (state->effects & EF_DIMLIGHT) { - radius = max(radius,200); - colour[0] += 2.0; - colour[1] += 1.0; - colour[2] += 0.5; + radius = max(radius,r_dimlight_colour.vec4[3]); + VectorAdd(colour, r_dimlight_colour.vec4, colour); } if (state->effects & EF_BLUE) { @@ -4415,12 +4413,8 @@ void CL_LinkPacketEntities (void) if (r_rocketlight.value && (modelflags & MF_ROCKET) && !(state->lightpflags & (PFLAGS_FULLDYNAMIC|PFLAGS_CORONA))) { float rad = 0; - vec3_t dclr; - - dclr[0] = 2.0; - dclr[1] = 1.0; - dclr[2] = 0.25; - rad = 200; + extern cvar_t r_rocketlight_colour; + rad = r_rocketlight_colour.vec4[3]; rad += r_lightflicker.value?((flicker + state->number)&31):0; dl = CL_AllocDlight (state->number); @@ -4430,7 +4424,7 @@ void CL_LinkPacketEntities (void) if (modelflags & MF_ROCKET) dl->origin[2] += 1; // is this even necessary dl->radius = rad * r_rocketlight.value; - VectorCopy(dclr, dl->color); + VectorCopy(r_rocketlight_colour.vec4, dl->color); } } } @@ -4856,7 +4850,7 @@ void CLQW_ParsePlayerinfo (void) #ifdef PEXT_SCALE if ((flags & PF_SCALE) && (cls.fteprotocolextensions & PEXT_SCALE)) - state->scale = (float)MSG_ReadByte()/50; + state->scale = MSG_ReadByte()/50.0; #endif #ifdef PEXT_TRANS if ((flags & PF_TRANS) && (cls.fteprotocolextensions & PEXT_TRANS)) @@ -4864,7 +4858,7 @@ void CLQW_ParsePlayerinfo (void) #endif #ifdef PEXT_FATNESS if ((flags & PF_FATNESS) && (cls.fteprotocolextensions & PEXT_FATNESS)) - state->fatness = (float)MSG_ReadChar(); + state->fatness = MSG_ReadChar(); #endif #ifdef PEXT_HULLSIZE if ((cls.fteprotocolextensions & PEXT_HULLSIZE) && (flags & PF_HULLSIZE_Z)) @@ -5642,7 +5636,9 @@ void CL_SetSolidEntities (void) model_t *mod; VALGRIND_MAKE_MEM_UNDEFINED(&pmove, sizeof(pmove)); +#ifdef CSQC_DAT pmove.world = &csqc_world; +#endif memset(&pmove.physents[0], 0, sizeof(physent_t)); pmove.physents[0].model = cl.worldmodel; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 8c239e521..e50b2c95e 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -5536,7 +5536,7 @@ done: if (!(f->flags & HRF_ACTION)) { Key_Dest_Remove(kdm_console); - M_Menu_Prompt(Host_RunFilePrompted, f, va("Exec %s?\n", COM_SkipPath(f->fname)), "Yes", NULL, "Cancel"); + Menu_Prompt(Host_RunFilePrompted, f, va("Exec %s?\n", COM_SkipPath(f->fname)), "Yes", NULL, "Cancel"); return; } if (f->flags & HRF_OPENED) @@ -5636,7 +5636,7 @@ done: if (!(f->flags & HRF_ACTION)) { Key_Dest_Remove(kdm_console); - M_Menu_Prompt(Host_RunFilePrompted, f, va("File already exists.\nWhat would you like to do?\n%s\n", displayname), "Overwrite", "Run old", "Cancel"); + Menu_Prompt(Host_RunFilePrompted, f, va("File already exists.\nWhat would you like to do?\n%s\n", displayname), "Overwrite", "Run old", "Cancel"); return; } } @@ -5645,7 +5645,7 @@ done: if (!(f->flags & HRF_ACTION)) { Key_Dest_Remove(kdm_console); - M_Menu_Prompt(Host_RunFilePrompted, f, va("File appears new.\nWould you like to install\n%s\n", displayname), "Install!", "", "Cancel"); + Menu_Prompt(Host_RunFilePrompted, f, va("File appears new.\nWould you like to install\n%s\n", displayname), "Install!", "", "Cancel"); return; } } @@ -5878,20 +5878,12 @@ double Host_Frame (double time) if (startuppending) CL_StartCinematicOrMenu(); -#ifdef PLUGINS - Plug_Tick(); -#endif - NET_Tick(); - if (cl.paused) cl.gametimemark += time; //if we're at a menu/console/thing - idle = Key_Dest_Has_Higher(kdm_gmenu); -#ifdef VM_UI - idle |= UI_MenuState() != 0; -#endif - idle = ((cls.state == ca_disconnected) || cl.paused) && !idle; //idle if we're disconnected/paused and not at a menu + idle = !Key_Dest_Has_Higher(kdm_menu); + idle = ((cls.state == ca_disconnected) || cl.paused) && idle; //idle if we're disconnected/paused and not at a menu idle |= !vid.activeapp; //always idle when tabbed out //read packets early and always, so we don't have stuff waiting for reception quite so often. @@ -5924,6 +5916,11 @@ double Host_Frame (double time) } } +#ifdef PLUGINS + Plug_Tick(); +#endif + NET_Tick(); + /* if (cl_maxfps.value) fps = cl_maxfps.value;//max(30.0, min(cl_maxfps.value, 72.0)); @@ -6285,7 +6282,7 @@ void CL_StartCinematicOrMenu(void) #endif } - if (!sv_state && !cls.demoinfile && !cls.state && !*cls.servername && !Media_PlayingFullScreen()) + if (!sv_state && !cls.demoinfile && !cls.state && !*cls.servername) { TP_ExecTrigger("f_startup", true); Cbuf_Execute (); @@ -6293,7 +6290,7 @@ void CL_StartCinematicOrMenu(void) //and any startup cinematics #ifdef HAVE_MEDIA_DECODER - if (!sv_state && !cls.demoinfile && !cls.state && !*cls.servername && !Media_PlayingFullScreen()) + if (!sv_state && !cls.demoinfile && !cls.state && !*cls.servername) { int ol_depth; int idcin_depth; @@ -6324,20 +6321,20 @@ void CL_StartCinematicOrMenu(void) } #endif - if (!sv_state && !cls.demoinfile && !cls.state && !*cls.servername && !Media_PlayingFullScreen()) + if (!sv_state && !cls.demoinfile && !cls.state && !*cls.servername) { - if (qrenderer > QR_NONE && !Key_Dest_Has(kdm_emenu)) + if (qrenderer > QR_NONE && !Key_Dest_Has(kdm_menu)) { #ifndef NOBUILTINMENUS - if (!cls.state && !Key_Dest_Has(kdm_emenu) && !*FS_GetGamedir(false)) + if (!cls.state && !Key_Dest_Has(kdm_menu) && !*FS_GetGamedir(false)) M_Menu_Mods_f(); #endif - if (!cls.state && !Key_Dest_Has(kdm_emenu) && cl_demoreel.ival) + if (!cls.state && !Key_Dest_Has(kdm_menu) && cl_demoreel.ival) { cls.demonum = 0; CL_NextDemo(); } - if (!cls.state && !Key_Dest_Has(kdm_emenu)) + if (!cls.state && !Key_Dest_Has(kdm_menu)) //if we're (now) meant to be using csqc for menus, make sure that its running. if (!CSQC_UnconnectedInit()) M_ToggleMenu_f(); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index df3de8416..d382789d8 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -2842,6 +2842,7 @@ static void CLDP_ParseDownloadBegin(char *s) if (!dl || strcmp(fname, dl->remotename)) { +#ifdef CSQC_DAT if (cls.demoplayback && !dl && cl_dp_csqc_progssize && size == cl_dp_csqc_progssize && !strcmp(fname, cl_dp_csqc_progsname)) { //its somewhat common for demos to contain a copy of the csprogs, so that the same version is available when trying to play the demo back. extern cvar_t cl_download_csprogs, cl_nocsqc; @@ -2857,6 +2858,7 @@ static void CLDP_ParseDownloadBegin(char *s) return; //silently ignore it } else +#endif { Con_Printf("Warning: server started sending a file we did not request. Ignoring.\n"); return; @@ -4512,10 +4514,6 @@ static void CLQ2_ParseConfigString (void) Con_Printf(CON_WARNING "WARNING: Client checksum does not match server checksum (%i != %i)", map_checksum, serverchecksum); } } - -#ifdef VM_UI - UI_StringChanged(i); -#endif } #endif @@ -5720,21 +5718,20 @@ static void CL_MuzzleFlash (int entnum) if (P_RunParticleEffectType(org, axis[0], 1, pt_muzzleflash)) { + extern cvar_t r_muzzleflash_colour; + extern cvar_t r_muzzleflash_fade; + dl = CL_AllocDlight (dlightkey); VectorMA (org, 15, axis[0], dl->origin); memcpy(dl->axis, axis, sizeof(dl->axis)); - dl->radius = 200 + (rand()&31); dl->minlight = 32; dl->die = cl.time + 0.1; - dl->color[0] = 1.5; - dl->color[1] = 1.3; - dl->color[2] = 1.0; - dl->channelfade[0] = 1.5; - dl->channelfade[1] = 0.75; - dl->channelfade[2] = 0.375; - dl->decay = 1000; + VectorCopy(r_muzzleflash_colour.vec4, dl->color); + dl->radius = r_muzzleflash_colour.vec4[3] + (rand()&31); + VectorCopy(r_muzzleflash_fade.vec4, dl->channelfade); + dl->decay = r_muzzleflash_fade.vec4[3]; #ifdef RTLIGHTS dl->lightcolourscales[2] = 4; #endif @@ -7531,9 +7528,6 @@ isilegible: case svcq2_layout: s = MSG_ReadString (); Q_strncpyz (cl.q2layout[seat], s, sizeof(cl.q2layout[seat])); -#ifdef VM_UI - UI_Q2LayoutChanged(); -#endif break; case svcq2_inventory: CLQ2_ParseInventory(seat); diff --git a/engine/client/cl_plugin.inc b/engine/client/cl_plugin.inc index 7eb6b9df6..c573101aa 100644 --- a/engine/client/cl_plugin.inc +++ b/engine/client/cl_plugin.inc @@ -1,66 +1,111 @@ //included directly from plugin.c //this is the client-only things. - - - - - -plugin_t *menuplug; //plugin that has the current menu static plugin_t *protocolclientplugin; - -static qintptr_t VARGS Plug_Menu_Control(void *offset, quintptr_t mask, const qintptr_t *arg) +static void PlugMenu_Close(menu_t *m) { - if (qrenderer == QR_NONE) - return 0; + Z_Free(m); +} +static qboolean PlugMenu_Event(menu_t *m, int eventtype, int keyparam, int unicodeparam) //eventtype = draw/keydown/keyup, param = time/key +{ + plugin_t *oc=currentplug; + qboolean ret; - switch(VM_LONG(arg[0])) + currentplug = m->ctx; + ret = currentplug->menufunction(eventtype, keyparam, unicodeparam, mousecursor_x, mousecursor_y, vid.width, vid.height); + currentplug=oc; + return ret; +} +static qboolean PlugMenu_KeyEvent(menu_t *m, qboolean isdown, unsigned int devid, int key, int unicode) +{ + return PlugMenu_Event(m, isdown?1:2, key, unicode); +} +static void PlugMenu_Draw(menu_t *m) +{ + PlugMenu_Event (m, 0, (realtime*1000), 0); +} +static qboolean QDECL Plug_SetMenuFocus (qboolean wantkeyfocus, const char *cursorname, float hot_x, float hot_y, float scale) //null cursorname=relmouse, set/empty cursorname=absmouse +{ + menu_t *m; + if (qrenderer == QR_NONE) + return false; + + m = Menu_FindContext(currentplug); + + if (wantkeyfocus) { - case 0: //take away all menus - case 1: - if (menuplug) + if (!m) { - plugin_t *oldplug = currentplug; - currentplug = menuplug; - Plug_Menu_Event(3, 0); - menuplug = NULL; - currentplug = oldplug; + m = Z_Malloc(sizeof(*m)); + m->ctx = currentplug; + m->cursor = &key_customcursor[kc_plugin]; + m->release = PlugMenu_Close; + m->keyevent = PlugMenu_KeyEvent; + m->drawmenu = PlugMenu_Draw; + Menu_Push(m, false); } - if (VM_LONG(arg[0]) != 1) - return 1; - //give us menu control - menuplug = currentplug; - Key_Dest_Add(kdm_emenu); - return 1; - case 2: //weather it's us or not. - return currentplug == menuplug && Key_Dest_Has(kdm_emenu); - case 3: //weather a menu is active - return !!Key_Dest_Has(kdm_emenu|kdm_gmenu); - default: - return 0; } -} + else if (m) + Menu_Unlink(m); -static qintptr_t VARGS Plug_Key_GetKeyCode(void *offset, quintptr_t mask, const qintptr_t *arg) + if (wantkeyfocus) + { + struct key_cursor_s *mc = &key_customcursor[kc_plugin]; + + if (cursorname) + { + if (scale <= 0) + scale = 1; + if (strcmp(cursorname, mc->name) || mc->hotspot[0] != hot_x || mc->hotspot[1] != hot_y || mc->scale != scale) + { + Q_strncpyz(mc->name, cursorname, sizeof(mc->name)); + mc->hotspot[0] = hot_x; + mc->hotspot[1] = hot_y; + mc->scale = scale; + mc->dirty = true; + } + } + } + return true; +} +static qboolean QDECL Plug_HasMenuFocus(void) { - int modifier; - return Key_StringToKeynum(VM_POINTER(arg[0]), &modifier); + return topmenu&&topmenu->ctx==currentplug && Key_Dest_Has(kdm_menu); } - - - -static qintptr_t VARGS Plug_SCR_CenterPrint(void *offset, quintptr_t mask, const qintptr_t *arg) +static int QDECL Plug_Key_GetKeyCode(const char *keyname, int *modifier) { - if (qrenderer == QR_NONE) - return 0; - - SCR_CenterPrint(0, VM_POINTER(arg[0]), true); - return 0; + int modifier_; + if (!modifier) + modifier = &modifier_; + return Key_StringToKeynum(keyname, modifier); +} +static const char *QDECL Plug_Key_GetKeyName(int keycode, int modifier) +{ + return Key_KeynumToString(keycode, modifier); } +const char *QDECL Plug_Key_GetKeyBind(int bindmap, int keynum, int modifier) +{ + return Key_GetBinding(keynum, bindmap, modifier); +} +void QDECL Plug_Key_SetKeyBind(int bindmap, int keycode, int modifier, const char *newbinding) +{ + if (bindmap && !modifier) + modifier = (bindmap-1) | KEY_MODIFIER_ALTBINDMAP; + Key_SetBinding (keycode, modifier, newbinding, RESTRICT_LOCAL); +} + +/* + +static void QDECL Plug_SCR_CenterPrint(int seat, const char *text) +{ + if (qrenderer != QR_NONE) + SCR_CenterPrint(seat, text, true); +} +*/ @@ -68,16 +113,46 @@ typedef struct { //Make SURE that the engine has resolved all cvar pointers into globals before this happens. plugin_t *plugin; char name[64]; - int type; + int type; //cache, wad, shader, raw char *script; mpic_t *pic; } pluginimagearray_t; -int pluginimagearraylen; +size_t pluginimagearraylen; pluginimagearray_t *pluginimagearray; #include "shader.h" -static qintptr_t VARGS Plug_Draw_LoadImage(char *name, int type, char *script) +static void Plug_Draw_UnloadImage(qhandle_t image) +{ + size_t i = image-1; + if (i < 0 || i >= pluginimagearraylen) + return; + if (pluginimagearray[i].plugin == currentplug) + { + pluginimagearray[i].plugin = 0; + if (pluginimagearray[i].pic) + R_UnloadShader(pluginimagearray[i].pic); + pluginimagearray[i].pic = NULL; + pluginimagearray[i].name[0] = '\0'; + } +} +static void Plug_FreePlugImages(plugin_t *plug) +{ + size_t i; + for (i = 0; i < pluginimagearraylen; i++) + { + if (pluginimagearray[i].plugin == plug) + { + pluginimagearray[i].plugin = 0; + if (pluginimagearray[i].pic) + R_UnloadShader(pluginimagearray[i].pic); + pluginimagearray[i].pic = NULL; + pluginimagearray[i].name[0] = '\0'; + } + } +} + +static qhandle_t Plug_Draw_LoadImage(const char *name, int type, const char *script) { int i; @@ -128,20 +203,13 @@ static qintptr_t VARGS Plug_Draw_LoadImage(char *name, int type, char *script) return i + 1; } -static qintptr_t VARGS Plug_Draw_LoadImageData(void *offset, quintptr_t mask, const qintptr_t *arg) +static qhandle_t QDECL Plug_Draw_LoadImageData(const char *name, const char *mimetype, void *codeddata, size_t datalength) { - qintptr_t ret = 0; - char *name = VM_POINTER(arg[0]); -// char *mimetype = VM_POINTER(arg[1]); - void *codeddata = VM_POINTER(arg[2]); - unsigned int datalength = VM_LONG(arg[3]); + qhandle_t ret = 0; image_t *t; qbyte *rgbdata; unsigned int width, height; uploadfmt_t format; - - if (VM_OOB(arg[2], arg[3])) - return 0; if ((rgbdata = ReadRawImageFile(codeddata, datalength, &width, &height, &format, false, name))) { @@ -160,16 +228,12 @@ static qintptr_t VARGS Plug_Draw_LoadImageData(void *offset, quintptr_t mask, co } return ret; } -static qintptr_t VARGS Plug_Draw_LoadImageShader(void *offset, quintptr_t mask, const qintptr_t *arg) +static qhandle_t QDECL Plug_Draw_LoadImageShader(const char *name, const char *script) { - char *name = VM_POINTER(arg[0]); - char *script = VM_POINTER(arg[1]); return Plug_Draw_LoadImage(name, 2, script); } -static qintptr_t VARGS Plug_Draw_LoadImagePic(void *offset, quintptr_t mask, const qintptr_t *arg) +static qhandle_t QDECL Plug_Draw_LoadImagePic(const char *name, qboolean type) { - char *name = VM_POINTER(arg[0]); - int type = arg[1]; if (type != 0 && type != 1) return 0; return Plug_Draw_LoadImage(name, type, NULL); @@ -192,36 +256,19 @@ void Plug_DrawReloadImages(void) } } -static void Plug_FreePlugImages(plugin_t *plug) -{ - int i; - for (i = 0; i < pluginimagearraylen; i++) - { - if (pluginimagearray[i].plugin == plug) - { - pluginimagearray[i].plugin = 0; - pluginimagearray[i].pic = NULL; - pluginimagearray[i].name[0] = '\0'; - } - } -} - //int R2D_ImageSize (qhandle_t image, float *w, float *h) -static qintptr_t VARGS Plug_Draw_ImageSize(void *offset, quintptr_t mask, const qintptr_t *arg) +static int QDECL Plug_Draw_ImageSize(qhandle_t image, float *w, float *h) { - float *w = VM_POINTER(arg[1]), *h = VM_POINTER(arg[2]); int iw, ih, ret; mpic_t *pic; int i; - if (VM_OOB(arg[1], sizeof(*w)) || VM_OOB(arg[2], sizeof(*w))) - return -1; *w = 0; *h = 0; if (qrenderer == QR_NONE) return 0; - i = VM_LONG(arg[0]); + i = image; if (i <= 0 || i > pluginimagearraylen) return -1; // you fool i = i - 1; @@ -245,15 +292,14 @@ static qintptr_t VARGS Plug_Draw_ImageSize(void *offset, quintptr_t mask, const return ret; } -//int R2D_Image (float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t image) -static qintptr_t VARGS Plug_Draw_Image(void *offset, quintptr_t mask, const qintptr_t *arg) +static int QDECL Plug_Draw_Image(float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t image) { mpic_t *pic; int i; if (qrenderer == QR_NONE) return 0; - i = VM_LONG(arg[8]); + i = image; if (i <= 0 || i > pluginimagearraylen) return -1; // you fool i = i - 1; @@ -271,35 +317,28 @@ static qintptr_t VARGS Plug_Draw_Image(void *offset, quintptr_t mask, const qint return -1; } - R2D_Image(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), VM_FLOAT(arg[2]), VM_FLOAT(arg[3]), VM_FLOAT(arg[4]), VM_FLOAT(arg[5]), VM_FLOAT(arg[6]), VM_FLOAT(arg[7]), pic); + R2D_Image(x, y, w, h, s1, t1, s2, t2, pic); return 1; } //x1,y1,x2,y2 -static qintptr_t VARGS Plug_Draw_Line(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Draw_Line(float x1, float y1, float x2, float y2) { - R2D_Line(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), VM_FLOAT(arg[2]), VM_FLOAT(arg[3]), NULL); - return 1; + R2D_Line(x1,y1, x2,y2, NULL); } -static qintptr_t VARGS Plug_Draw_Character(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Draw_Character(float x, float y, unsigned int character) { - int x, y; + int px, py; if (qrenderer == QR_NONE) - return 0; - Font_BeginString(font_default, arg[0], arg[1], &x, &y); - Font_DrawChar(x, y, CON_WHITEMASK, 0xe000 | (unsigned int)arg[2]); + return; + Font_BeginString(font_default, x, y, &px, &py); + Font_DrawChar(x, y, CON_WHITEMASK, character); Font_EndString(font_default); - return 0; } -static qintptr_t VARGS Plug_Draw_CharacterH(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Draw_CharacterH(float x, float y, float h, unsigned int flags, unsigned int charc) { - float x = VM_FLOAT(arg[0]); - float y = VM_FLOAT(arg[1]); - float h = VM_FLOAT(arg[2]); - unsigned int flags = VM_LONG(arg[3]); - unsigned int charc = VM_LONG(arg[4]); conchar_t cmask = CON_WHITEMASK; if (qrenderer == QR_NONE) - return 0; + return; if (flags & 1) cmask |= CON_2NDCHARSETTEXT; if (!(flags & 2)) @@ -307,18 +346,17 @@ static qintptr_t VARGS Plug_Draw_CharacterH(void *offset, quintptr_t mask, const Font_BeginScaledString(font_default, x, y, h, h, &x, &y); Font_DrawScaleChar(x, y, cmask, charc); Font_EndString(font_default); - return 0; } -static qintptr_t VARGS Plug_Draw_String(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Draw_String(float x, float y, const char *string) { int ipx, px, py; conchar_t buffer[2048], *str; unsigned int codeflags, codepoint; if (qrenderer == QR_NONE) - return 0; - COM_ParseFunString(CON_WHITEMASK, VM_POINTER(arg[2]), buffer, sizeof(buffer), false); + return; + COM_ParseFunString(CON_WHITEMASK, string, buffer, sizeof(buffer), false); str = buffer; - Font_BeginString(font_default, VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), &px, &py); + Font_BeginString(font_default, x, y, &px, &py); ipx = px; while(*str) { @@ -331,21 +369,15 @@ static qintptr_t VARGS Plug_Draw_String(void *offset, quintptr_t mask, const qin px = Font_DrawChar(px, py, codeflags, codepoint); } Font_EndString(font_default); - return 0; } -static qintptr_t VARGS Plug_Draw_StringH(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Draw_StringH(float x, float y, float h, unsigned int flags, const char *instr) { - float x = VM_FLOAT(arg[0]); - float y = VM_FLOAT(arg[1]); - float h = VM_FLOAT(arg[2]); - unsigned int flags = VM_LONG(arg[3]); - char *instr = VM_POINTER(arg[4]); float ipx; conchar_t buffer[2048], *str, cmask = CON_WHITEMASK; unsigned int codeflags, codepoint; unsigned int parseflags = 0; if (qrenderer == QR_NONE) - return 0; + return; if (flags & 1) cmask |= CON_2NDCHARSETTEXT; if (flags & 2) @@ -365,15 +397,10 @@ static qintptr_t VARGS Plug_Draw_StringH(void *offset, quintptr_t mask, const qi x = Font_DrawScaleChar(x, y, codeflags, codepoint); } Font_EndString(font_default); - return 0; } -static qintptr_t VARGS Plug_Draw_StringWidth(void *offset, quintptr_t mask, const qintptr_t *arg) +static float QDECL Plug_Draw_StringWidth(float h, unsigned int flags, const char *instr) { - qintptr_t ret; - float h = VM_FLOAT(arg[0]); - unsigned int flags = VM_LONG(arg[1]); - char *instr = VM_POINTER(arg[2]); conchar_t buffer[2048], *str, cmask = CON_WHITEMASK; unsigned int parseflags = 0; float px,py; @@ -390,87 +417,49 @@ static qintptr_t VARGS Plug_Draw_StringWidth(void *offset, quintptr_t mask, cons Font_EndString(NULL); //put it back in virtual space - VM_FLOAT(ret) = (px*(float)vid.width) / (float)vid.rotpixelwidth; - return ret; + return (px*(float)vid.width) / (float)vid.rotpixelwidth; } -static qintptr_t VARGS Plug_Draw_Fill(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Draw_Fill(float x, float y, float width, float height) { - float x, y, width, height; - if (qrenderer == QR_NONE) - return 0; - x = VM_FLOAT(arg[0]); - y = VM_FLOAT(arg[1]); - width = VM_FLOAT(arg[2]); - height = VM_FLOAT(arg[3]); - - R2D_FillBlock(x, y, width, height); - return 0; + if (qrenderer != QR_NONE) + R2D_FillBlock(x, y, width, height); } -static qintptr_t VARGS Plug_Draw_ColourP(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Draw_ColourP(int palcol, float a) { - int p = VM_LONG(arg[0]); - if (p<0 || p>255) - return false; - - R2D_ImagePaletteColour(p, 1); - return 1; + if (palcol>=0 && palcol<=255) + R2D_ImagePaletteColour(palcol, a); } -static qintptr_t VARGS Plug_Draw_ColourPA(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Draw_Colour4f(float r, float g, float b, float a) { - int p = VM_LONG(arg[0]); - float a = VM_FLOAT(arg[1]); - if (p<0 || p>255) - return false; - - R2D_ImagePaletteColour(p, a); - return 1; + R2D_ImageColours(r,g,b,a); } -static qintptr_t VARGS Plug_Draw_Colour3f(void *offset, quintptr_t mask, const qintptr_t *arg) + + + + + + + + + +static void QDECL Plug_LocalSound(const char *soundname, int channel, float volume) { - R2D_ImageColours(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), VM_FLOAT(arg[2]), 1); - return 1; -} -static qintptr_t VARGS Plug_Draw_Colour4f(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - R2D_ImageColours(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), VM_FLOAT(arg[2]), VM_FLOAT(arg[3])); - return 1; + if (qrenderer != QR_NONE) + S_LocalSound(soundname); } - - - - - - -static qintptr_t VARGS Plug_LocalSound(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - if (qrenderer == QR_NONE) - return false; - - S_LocalSound(VM_POINTER(arg[0])); - return 0; -} - - - -static qintptr_t VARGS Plug_CL_GetStats(void *offset, quintptr_t mask, const qintptr_t *arg) +static int QDECL Plug_CL_GetStats(int pnum, unsigned int *stats, int maxstats) { int i = 0; - int pnum = VM_LONG(arg[0]); - unsigned int *stats = VM_POINTER(arg[1]); - int pluginstats = VM_LONG(arg[2]); int max; - if (VM_OOB(arg[1], arg[2]*4)) - return 0; - if (qrenderer == QR_NONE || !cls.state) return 0; - max = pluginstats; + max = maxstats; if (max > MAX_CL_STATS) max = MAX_CL_STATS; if (pnum < 0) @@ -491,48 +480,28 @@ static qintptr_t VARGS Plug_CL_GetStats(void *offset, quintptr_t mask, const qin } max = i; - for (; i < pluginstats; i++) //plugin has too many stats (wow) + for (; i < maxstats; i++) //plugin has too many stats (wow) stats[i] = 0; //fill the rest. return max; } -#define PLUGMAX_SCOREBOARDNAME 64 -typedef struct { - int topcolour; - int bottomcolour; - int frags; - char name[PLUGMAX_SCOREBOARDNAME]; - int ping; - int pl; - float activetime; - int userid; - int spectator; - char userinfo[1024]; - char team[8]; -} vmplugclientinfo_t; - -static qintptr_t VARGS Plug_GetPlayerInfo(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_GetPlayerInfo(int playernum, plugclientinfo_t *out) { - int i, pt; - vmplugclientinfo_t *out; + int i; - if (VM_OOB(arg[1], sizeof(vmplugclientinfo_t))) - return -1; - if (VM_LONG(arg[0]) < -1 || VM_LONG(arg[0] ) >= MAX_CLIENTS) - return -2; + if (playernum < -cl.splitclients || playernum >= MAX_CLIENTS) + return; - i = VM_LONG(arg[0]); - out = VM_POINTER(arg[1]); + i = playernum; if (out) { if (i < 0) { - if (i >= -(int)MAX_SPLITS) - i = cl.playerview[-i-1].playernum; + i = cl.playerview[-i-1].playernum; if (i < 0) { memset(out, 0, sizeof(*out)); - return 0; + return; } } out->bottomcolour = cl.players[i].rbottomcolor; @@ -547,48 +516,26 @@ static qintptr_t VARGS Plug_GetPlayerInfo(void *offset, quintptr_t mask, const q InfoBuf_ToString(&cl.players[i].userinfo, out->userinfo, sizeof(out->userinfo), basicuserinfos, NULL, NULL, NULL, NULL); Q_strncpyz(out->team, cl.players[i].team, sizeof(out->team)); } - - pt = Cam_TrackNum(&cl.playerview[0]); - if (pt < 0) - return (cl.playerview[0].playernum == i); - else - return pt == i; } -static qintptr_t VARGS Plug_LocalPlayerNumber(void *offset, quintptr_t mask, const qintptr_t *arg) +static size_t QDECL Plug_GetLocalPlayerNumbers(size_t first, size_t count, int *playernums, int *spectracks) { - return cl.playerview[0].playernum; -} -static qintptr_t VARGS Plug_GetLocalPlayerNumbers(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - int i; - int first = VM_LONG(arg[0]); - int count = VM_LONG(arg[1]); - int *playernums = VM_POINTER(arg[2]); - int *spectracks = VM_POINTER(arg[3]); + size_t i; if (count < 0 || count > 1000) count = 0; - if (VM_OOB(arg[2], sizeof(*playernums)*count) || VM_OOB(arg[3], sizeof(*playernums)*count)) - return false; - if (first < 0) first = 0; if (first > cl.splitclients) first = cl.splitclients; if (first+count > cl.splitclients) count = cl.splitclients-first; for (i = 0; i < count; i++) { - playernums[i] = cl.playerview[i].playernum; - spectracks[i] = Cam_TrackNum(&cl.playerview[i]); + playernums[i] = cl.playerview[first+i].playernum; + spectracks[i] = Cam_TrackNum(&cl.playerview[first+i]); } return count; } -static qintptr_t VARGS Plug_GetServerInfo(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_GetServerInfo(char *outptr, size_t outlen) { - char *outptr = VM_POINTER(arg[0]); - unsigned int outlen = VM_LONG(arg[1]); extern float demtime; - if (VM_OOB(arg[0], outlen)) - return false; - InfoBuf_ToString(&cl.serverinfo, outptr, outlen, NULL, NULL, NULL, NULL, NULL); Q_strncatz(outptr, va("\\intermission\\%i", cl.intermissionmode), outlen); switch(cls.demoplayback) @@ -621,69 +568,26 @@ static qintptr_t VARGS Plug_GetServerInfo(void *offset, quintptr_t mask, const q else #endif Q_strncatz(outptr, va("\\matchstart\\%f", cl.matchgametimestart), outlen); - - return true; } -static qintptr_t VARGS Plug_SetUserInfo(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_SetUserInfo(int seat, const char *key, const char *value) { - char *key = VM_POINTER(arg[0]); - char *value = VM_POINTER(arg[1]); - - CL_SetInfo(0, key, value); - - return true; + CL_SetInfo(seat, key, value); } -typedef struct { - int seats; - struct - { - float s_avg; - float s_mn; - float s_mx; - float ms_stddev; - float fr_avg; - int fr_mn; - int fr_mx; - } ping; - struct - { //decimals - float dropped; - float choked; - float invalid; - } loss; - float mlatency; - float mrate; - float vlatency; - float vrate; - vec3_t speed; //player speed - - struct - { - float in_pps; - float in_bps; - float out_pps; - float out_bps; - } clrate; - struct - { - float in_pps; - float in_bps; - float out_pps; - float out_bps; - } svrate; - int capturing; -} vmnetinfo_t; -#define has(x) (((quintptr_t)&((vmnetinfo_t*)NULL)->x + sizeof(((vmnetinfo_t*)NULL)->x)) <= outlen) -//aka: misc other hud timing crap -static qintptr_t VARGS Plug_GetNetworkInfo(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_GetLastInputFrame(int seat, usercmd_t *outcmd) { - vmnetinfo_t *outptr = VM_POINTER(arg[0]); - unsigned int outlen = VM_LONG(arg[1]); - if (VM_OOB(arg[0], outlen)) + unsigned int curframe = (cl.movesequence-1u) & UPDATE_MASK; + if (!cl.movesequence || seat < 0 || seat >= cl.splitclients) return false; + *outcmd = cl.outframes[curframe].cmd[seat]; + return true; +} +#define has(x) (((quintptr_t)&((plugnetinfo_t*)NULL)->x + sizeof(((plugnetinfo_t*)NULL)->x)) <= outlen) +//aka: misc other hud timing crap +static size_t QDECL Plug_GetNetworkInfo(plugnetinfo_t *outptr, size_t outlen) +{ if (has(capturing)) { #ifdef HAVE_MEDIA_ENCODER @@ -718,71 +622,47 @@ static qintptr_t VARGS Plug_GetNetworkInfo(void *offset, quintptr_t mask, const #endif } - return sizeof(vmnetinfo_t); + return min(outlen,sizeof(*outptr)); } #undef has #ifdef QUAKEHUD -static qintptr_t VARGS Plug_GetTrackerOwnFrags(void *offset, quintptr_t mask, const qintptr_t *arg) +static float QDECL Plug_GetTrackerOwnFrags(int seat, char *outptr, size_t outlen) { - int ret; - int seat = VM_LONG(arg[0]); - char *outptr = VM_POINTER(arg[1]); - size_t outlen = VM_LONG(arg[2]); - if (VM_OOB(arg[1], outlen) || !outlen) - VM_FLOAT(ret) = 0; + if (!outlen) + return 0; else - VM_FLOAT(ret) = Stats_GetLastOwnFrag(seat, outptr, outlen); - return ret; + return Stats_GetLastOwnFrag(seat, outptr, outlen); } #endif -static qintptr_t VARGS Plug_GetLocationName(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_GetLocationName(const float *locpoint, char *outbuffer, size_t bufferlen) { - float *locpoint = VM_POINTER(arg[0]); - char *locname = VM_POINTER(arg[1]); - unsigned int locnamelen = VM_LONG(arg[2]); - char *result; - - if (VM_OOB(arg[1], locnamelen)) - return 0; - - result = TP_LocationName(locpoint); - Q_strncpyz(locname, result, locnamelen); - return VM_LONG(arg[1]); + const char *result = TP_LocationName(locpoint); + Q_strncpyz(outbuffer, result, bufferlen); } #ifdef QUAKEHUD -typedef struct +static size_t QDECL Plug_GetTeamInfo(teamplayerinfo_t *players, size_t maxplayers, qboolean showenemies, int seat) { - unsigned int client; - unsigned int items; - float armor; - float health; - vec3_t org; - char nick[16]; -} teamplayerinfo_t; -static qintptr_t VARGS Plug_GetTeamInfo(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - teamplayerinfo_t *players = VM_POINTER(arg[0]); - size_t maxplayers = VM_LONG(arg[1]); - qboolean showenemies = VM_LONG(arg[2]); - qboolean showself = VM_LONG(arg[3]); int count = 0; int i; int self; lerpents_t *le; player_info_t *pl; - if (VM_OOB(arg[0], maxplayers*sizeof(*players))) - return 0; maxplayers = min(maxplayers, cl.allocated_client_slots); Cvar_Get("ti", "1", CVAR_USERINFO, "Hacks because ktx sucks. Must be 1 in order to receive team information in ktx."); - self = cl.playerview[0].playernum; - if (cl.playerview[0].cam_state != CAM_FREECAM) - self = cl.playerview[0].cam_spec_track; + if (seat >= 0) + { + self = cl.playerview[seat].playernum; + if (cl.playerview[seat].cam_state != CAM_FREECAM) + self = cl.playerview[seat].cam_spec_track; + } + else + self = -1; for (i = 0; i < cl.allocated_client_slots && maxplayers > 0; i++) { @@ -790,7 +670,7 @@ static qintptr_t VARGS Plug_GetTeamInfo(void *offset, quintptr_t mask, const qin continue; if (cl.players[i].spectator) //shoo! continue; - if (i == self && !showself) + if (i == self) continue; if (!showenemies && strcmp(cl.players[i].team, cl.players[self].team)) continue; @@ -807,9 +687,9 @@ static qintptr_t VARGS Plug_GetTeamInfo(void *offset, quintptr_t mask, const qin } else if (i == self) { //oh hey look, its me. - players->items = cl.playerview[0].stats[STAT_ITEMS]; - players->armor = cl.playerview[0].statsf[STAT_ARMOR]; - players->health = cl.playerview[0].statsf[STAT_HEALTH]; + players->items = cl.playerview[seat].stats[STAT_ITEMS]; + players->armor = cl.playerview[seat].statsf[STAT_ARMOR]; + players->health = cl.playerview[seat].statsf[STAT_HEALTH]; Q_strncpyz(players->nick, "", sizeof(players->nick)); } else if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) @@ -841,19 +721,12 @@ static qintptr_t VARGS Plug_GetTeamInfo(void *offset, quintptr_t mask, const qin count++; } - return VM_LONG(count); + return count; } #endif #ifdef QUAKEHUD -static qintptr_t VARGS Plug_GetWeaponStats(void *offset, quintptr_t mask, const qintptr_t *arg) +static int QDECL Plug_GetWeaponStats(int self, struct wstats_s *result, size_t maxresults) { - int self = VM_LONG(arg[0]); - struct wstats_s *result = VM_POINTER(arg[1]); - size_t maxresults = VM_LONG(arg[2]); - - if (VM_OOB(arg[0], maxresults*sizeof(*result))) - return 0; - //FIXME: we should support some way to clear this to 0 again, other than nosave. Cvar_Get("wpsx", "1", CVAR_USERINFO|CVAR_NOSAVE, "Hacks because ktx sucks. Must be 1 in order to receive weapon stats information in ktx."); @@ -870,14 +743,12 @@ static qintptr_t VARGS Plug_GetWeaponStats(void *offset, quintptr_t mask, const if (maxresults > countof(cl.players[self].weaponstats)) maxresults = countof(cl.players[self].weaponstats); memcpy(result, cl.players[self].weaponstats, sizeof(*result) * maxresults); - return VM_LONG(maxresults); + return maxresults; } #endif -static qintptr_t VARGS Plug_Con_SubPrint(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_Con_SubPrint(const char *name, const char *text) { - char *name = VM_POINTER(arg[0]); - char *text = VM_POINTER(arg[1]); console_t *con; if (!name) name = ""; @@ -887,7 +758,7 @@ static qintptr_t VARGS Plug_Con_SubPrint(void *offset, quintptr_t mask, const qi if (!*name) { Con_Printf("%s", text); - return 1; + return true; } return false; } @@ -913,78 +784,66 @@ static qintptr_t VARGS Plug_Con_SubPrint(void *offset, quintptr_t mask, const qi Con_PrintCon(con, text, con->parseflags); - return 1; + return true; } -static qintptr_t VARGS Plug_Con_RenameSub(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_Con_RenameSub(const char *oldname, const char *newname) { - char *name = VM_POINTER(arg[0]); console_t *con; if (qrenderer == QR_NONE) return false; - con = Con_FindConsole(name); + con = Con_FindConsole(oldname); if (!con) - return 0; + return false; - Q_strncpyz(con->name, name, sizeof(con->name)); + Q_strncpyz(con->name, newname, sizeof(con->name)); - return 1; + return true; } -static qintptr_t VARGS Plug_Con_IsActive(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_Con_IsActive(const char *conname) { - char *name = VM_POINTER(arg[0]); console_t *con; if (qrenderer == QR_NONE) return false; - con = Con_FindConsole(name); + con = Con_FindConsole(conname); if (!con) return false; return Con_IsActive(con); } -static qintptr_t VARGS Plug_Con_SetActive(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_Con_SetActive(const char *conname) { - char *name = VM_POINTER(arg[0]); console_t *con; if (qrenderer == QR_NONE) return false; - con = Con_FindConsole(name); + con = Con_FindConsole(conname); if (!con) - con = Con_Create(name, 0); + con = Con_Create(conname, 0); Con_SetActive(con); return true; } -static qintptr_t VARGS Plug_Con_Destroy(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_Con_Destroy(const char *conname) { - char *name = VM_POINTER(arg[0]); console_t *con; if (qrenderer == QR_NONE) return false; - con = Con_FindConsole(name); + con = Con_FindConsole(conname); if (!con) return false; Con_Destroy(con); return true; } -static qintptr_t VARGS Plug_Con_NameForNum(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_Con_NameForNum(qintptr_t connum, char *outconname, size_t connamesize) { - char num = VM_LONG(arg[0]); - char *buffer = VM_POINTER(arg[1]); - int buffersize = VM_LONG(arg[2]); - if (VM_OOB(arg[1], buffersize) || buffersize < 1) - return false; if (qrenderer == QR_NONE) return false; - return Con_NameForNum(num, buffer, buffersize); + return Con_NameForNum(connum, outconname, connamesize); } -static qintptr_t VARGS Plug_Con_GetConsoleFloat(void *offset, quintptr_t mask, const qintptr_t *arg) +static float QDECL Plug_Con_GetConsoleFloat(const char *conname, const char *attrib) { - char *conname = VM_POINTER(arg[0]); - char *attrib = VM_POINTER(arg[1]); - int retbuf; float ret; console_t *con = Con_FindConsole(conname); ret = -1; @@ -1021,22 +880,18 @@ static qintptr_t VARGS Plug_Con_GetConsoleFloat(void *offset, quintptr_t mask, c else if (!strcmp(attrib, "linecount")) ret = con->linecount; - VM_FLOAT(retbuf) = ret; - return retbuf; + return ret; } -static qintptr_t VARGS Plug_Con_SetConsoleFloat(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_Con_SetConsoleFloat(const char *conname, const char *attrib, float val) { - char *conname = VM_POINTER(arg[0]); - char *attrib = VM_POINTER(arg[1]); - float val = VM_FLOAT(arg[2]); console_t *con = Con_FindConsole(conname); if (!con) { con = Con_Create(conname, 0); if (!con) - return -1; + return false; con->userdata = currentplug; con->linebuffered = Plug_SubConsoleCommand; } @@ -1094,26 +949,19 @@ static qintptr_t VARGS Plug_Con_SetConsoleFloat(void *offset, quintptr_t mask, c con->parseflags = pfl; } else - return -1; + return false; } else - return -1; + return false; return true; } -static qintptr_t VARGS Plug_Con_GetConsoleString(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_Con_GetConsoleString(const char *conname, const char *attrib, char *value, size_t size) { - const char *conname = VM_POINTER(arg[0]); - const char *attrib = VM_POINTER(arg[1]); - char *value = VM_POINTER(arg[2]); - size_t size = VM_LONG(arg[3]); console_t *con = Con_FindConsole(conname); - - if (VM_OOB(arg[2], arg[3])) - return 0; if (!con) - return 0; + return false; else if (!strcmp(attrib, "footer")) ; else if (!strcmp(attrib, "title")) @@ -1135,25 +983,24 @@ static qintptr_t VARGS Plug_Con_GetConsoleString(void *offset, quintptr_t mask, else Q_strncpyz(value, con->backimage, size); } - return 0; + else + return false; + return true; } -static qintptr_t VARGS Plug_Con_SetConsoleString(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_Con_SetConsoleString(const char *conname, const char *attrib, const char *value) { - const char *conname = VM_POINTER(arg[0]); - const char *attrib = VM_POINTER(arg[1]); - const char *value = VM_POINTER(arg[2]); console_t *con = Con_FindConsole(conname); if (!con) { con = Con_Create(conname, 0); if (!con) - return -1; + return false; con->userdata = currentplug; con->linebuffered = Plug_SubConsoleCommand; } if (!con) - return 0; + return false; else if (!strcmp(attrib, "footer")) Con_Footerf(con, false, "%s", value); else if (!strcmp(attrib, "title")) @@ -1179,156 +1026,22 @@ static qintptr_t VARGS Plug_Con_SetConsoleString(void *offset, quintptr_t mask, con->backshader = NULL; } else - return -1; - return 0; -} - -static qintptr_t VARGS Plug_S_RawAudio(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - int sourceid = VM_LONG(arg[0]); - qbyte *data = VM_POINTER(arg[1]); - int speed = VM_LONG(arg[2]); - int samples = VM_LONG(arg[3]); - int channels = VM_LONG(arg[4]); - int width = VM_LONG(arg[5]); - int volume = VM_FLOAT(arg[6]); - - int datasize = samples * channels * width; - - if (VM_OOB(arg[1], datasize) || datasize < 1) return false; - + return true; +} + +static void QDECL Plug_S_RawAudio(int sourceid, void *data, int speed, int samples, int channels, int width, float volume) +{ S_RawAudio(sourceid, data, speed, samples, channels, width, volume); - return 0; -} - -#include "com_mesh.h" - -#ifdef SKELETALMODELS -static int QDECL Plug_RegisterModelFormatText(const char *formatname, char *magictext, qboolean (QDECL *load) (struct model_s *mod, void *buffer, size_t fsize)) -{ - void *module = currentplug; - return Mod_RegisterModelFormatText(module, formatname, magictext, load); -} -static int QDECL Plug_RegisterModelFormatMagic(const char *formatname, unsigned int magic, qboolean (QDECL *load) (struct model_s *mod, void *buffer, size_t fsize)) -{ - void *module = currentplug; - return Mod_RegisterModelFormatMagic(module, formatname, magic, load); -} -static void QDECL Plug_UnRegisterModelFormat(int idx) -{ - void *module = currentplug; - Mod_UnRegisterModelFormat(module, idx); -} -static void QDECL Plug_UnRegisterAllModelFormats(void) -{ - void *module = currentplug; - Mod_UnRegisterAllModelFormats(module); -} -#endif -static qintptr_t VARGS Plug_Mod_GetPluginModelFuncs(void *offset, quintptr_t mask, const qintptr_t *arg) -{ -#ifdef SKELETALMODELS - static modplugfuncs_t funcs = - { - MODPLUGFUNCS_VERSION, - - Plug_RegisterModelFormatText, - Plug_RegisterModelFormatMagic, - Plug_UnRegisterModelFormat, - Plug_UnRegisterAllModelFormats, - ZG_Malloc, - - R_ConcatTransforms, - Matrix3x4_Invert_Simple, - VectorAngles, - AngleVectors, - GenMatrixPosQuat4Scale, - COM_StripExtension, - Alias_ForceConvertBoneData, -#ifdef TERRAIN - Terr_GetTerrainFuncs, -#else - NULL, -#endif - NULL, - Image_GetTexture, - FS_OpenVFS, - Mod_AccumulateTextureVectors, - Mod_NormaliseTextureVectors, - }; - if (VM_LONG(arg[0]) >= sizeof(funcs)) - return (qintptr_t)&funcs; - else -#endif - return 0; -} - -static void Plug_Client_Init(void) -{ - Plug_RegisterBuiltin("CL_GetStats", Plug_CL_GetStats, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Menu_Control", Plug_Menu_Control, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Key_GetKeyCode", Plug_Key_GetKeyCode, PLUG_BIF_NEEDSRENDERER); - - Plug_RegisterBuiltin("Draw_LoadImageData", Plug_Draw_LoadImageData, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_LoadImageShader", Plug_Draw_LoadImageShader, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_LoadImage", Plug_Draw_LoadImagePic, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_Image", Plug_Draw_Image, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_ImageSize", Plug_Draw_ImageSize, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_Character", Plug_Draw_Character, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_CharacterH", Plug_Draw_CharacterH, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_String", Plug_Draw_String, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_StringH", Plug_Draw_StringH, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_StringWidth", Plug_Draw_StringWidth, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_Fill", Plug_Draw_Fill, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_Line", Plug_Draw_Line, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_Colourp", Plug_Draw_ColourP, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_Colourpa", Plug_Draw_ColourPA, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_Colour3f", Plug_Draw_Colour3f, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Draw_Colour4f", Plug_Draw_Colour4f, PLUG_BIF_NEEDSRENDERER); - - Plug_RegisterBuiltin("Con_SubPrint", Plug_Con_SubPrint, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Con_RenameSub", Plug_Con_RenameSub, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Con_IsActive", Plug_Con_IsActive, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Con_SetActive", Plug_Con_SetActive, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Con_Destroy", Plug_Con_Destroy, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Con_NameForNum", Plug_Con_NameForNum, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Con_GetConsoleFloat", Plug_Con_GetConsoleFloat, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Con_SetConsoleFloat", Plug_Con_SetConsoleFloat, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Con_GetConsoleString", Plug_Con_GetConsoleString, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Con_SetConsoleString", Plug_Con_SetConsoleString, PLUG_BIF_NEEDSRENDERER); - - Plug_RegisterBuiltin("LocalSound", Plug_LocalSound, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("SCR_CenterPrint", Plug_SCR_CenterPrint, PLUG_BIF_NEEDSRENDERER); - -#ifdef QUAKEHUD - Plug_RegisterBuiltin("GetTeamInfo", Plug_GetTeamInfo, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("GetWeaponStats", Plug_GetWeaponStats, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("GetTrackerOwnFrags", Plug_GetTrackerOwnFrags, PLUG_BIF_NEEDSRENDERER); -#endif - Plug_RegisterBuiltin("GetLocationName", Plug_GetLocationName, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("GetPlayerInfo", Plug_GetPlayerInfo, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("LocalPlayerNumber", Plug_LocalPlayerNumber, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("GetLocalPlayerNumbers", Plug_GetLocalPlayerNumbers, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("GetServerInfo", Plug_GetServerInfo, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("SetUserInfo", Plug_SetUserInfo, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("GetNetworkInfo", Plug_GetNetworkInfo, PLUG_BIF_NEEDSRENDERER); - - Plug_RegisterBuiltin("S_RawAudio", Plug_S_RawAudio, PLUG_BIF_NEEDSRENDERER); - - Plug_RegisterBuiltin("Mod_GetPluginModelFuncs", Plug_Mod_GetPluginModelFuncs, PLUG_BIF_NEEDSRENDERER|PLUG_BIF_DLLONLY); } static void Plug_Client_Close(plugin_t *plug) { + menu_t *m = Menu_FindContext(currentplug); Plug_FreePlugImages(plug); - - if (menuplug == plug) - { - menuplug = NULL; - Key_Dest_Remove(kdm_emenu); - } + if (m) + Menu_Unlink(m); if (protocolclientplugin == plug) { protocolclientplugin = NULL; diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 92d34420d..0292c8283 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -943,7 +943,7 @@ void SCR_DrawCursor(void) char *newc; int prydoncursornum = 0; extern qboolean cursor_active; - int cmod = kc_console; + struct key_cursor_s *kcurs; void *oldcurs = NULL; if (cursor_active && cl_prydoncursor.ival > 0) @@ -951,48 +951,54 @@ void SCR_DrawCursor(void) else if (!Key_MouseShouldBeFree()) return; + if ((key_dest_mask & key_dest_absolutemouse & kdm_prompt)) + { + if (promptmenu&&promptmenu->cursor) + kcurs = promptmenu->cursor; + else + kcurs = &key_customcursor[kc_console]; + } //choose the cursor based upon the module that has primary focus - if (key_dest_mask & key_dest_absolutemouse & (kdm_console|kdm_cwindows)) - cmod = kc_console; - else if ((key_dest_mask & key_dest_absolutemouse & kdm_emenu)) - cmod = kc_console; - else if ((key_dest_mask & key_dest_absolutemouse & kdm_gmenu)) - cmod = kc_menu; -#ifdef MENU_NATIVECODE - else if ((key_dest_mask & key_dest_absolutemouse & kdm_nmenu)) - cmod = kc_nmenu; -#endif + else if (key_dest_mask & key_dest_absolutemouse & (kdm_console|kdm_cwindows)) + kcurs = &key_customcursor[kc_console]; + else if ((key_dest_mask & key_dest_absolutemouse & kdm_menu)) + { + if (topmenu&&topmenu->cursor) + kcurs = topmenu->cursor; + else + kcurs = &key_customcursor[kc_console]; + } else// if (key_dest_mask & key_dest_absolutemouse) - cmod = prydoncursornum?kc_console:kc_game; + kcurs = &key_customcursor[prydoncursornum?kc_console:kc_game]; - if (cmod == kc_console) + if (kcurs == &key_customcursor[kc_console]) { if (!*cl_cursor.string || prydoncursornum>1) newc = va("gfx/prydoncursor%03i.lmp", prydoncursornum); else newc = cl_cursor.string; - if (strcmp(key_customcursor[kc_console].name, newc) || key_customcursor[kc_console].hotspot[0] != cl_cursorbiasx.value || key_customcursor[kc_console].hotspot[1] != cl_cursorbiasy.value || key_customcursor[kc_console].scale != cl_cursorscale.value) + if (strcmp(kcurs->name, newc) || kcurs->hotspot[0] != cl_cursorbiasx.value || kcurs->hotspot[1] != cl_cursorbiasy.value || kcurs->scale != cl_cursorscale.value) { - key_customcursor[kc_console].dirty = true; - Q_strncpyz(key_customcursor[cmod].name, newc, sizeof(key_customcursor[cmod].name)); - key_customcursor[kc_console].hotspot[0] = cl_cursorbiasx.value; - key_customcursor[kc_console].hotspot[1] = cl_cursorbiasy.value; - key_customcursor[kc_console].scale = cl_cursorscale.value; + kcurs->dirty = true; + Q_strncpyz(kcurs->name, newc, sizeof(kcurs->name)); + kcurs->hotspot[0] = cl_cursorbiasx.value; + kcurs->hotspot[1] = cl_cursorbiasy.value; + kcurs->scale = cl_cursorscale.value; } } - if (key_customcursor[cmod].dirty) + if (kcurs->dirty) { - if (key_customcursor[cmod].scale <= 0 || !*key_customcursor[cmod].name) + if (kcurs->scale <= 0 || !*kcurs->name) { - key_customcursor[cmod].hotspot[0] = cl_cursorbiasx.value; - key_customcursor[cmod].hotspot[1] = cl_cursorbiasy.value; - key_customcursor[cmod].scale = cl_cursorscale.value; + kcurs->hotspot[0] = cl_cursorbiasx.value; + kcurs->hotspot[1] = cl_cursorbiasy.value; + kcurs->scale = cl_cursorscale.value; } - key_customcursor[cmod].dirty = false; - oldcurs = key_customcursor[cmod].handle; - if (rf->VID_CreateCursor && strcmp(key_customcursor[cmod].name, "none")) + kcurs->dirty = false; + oldcurs = kcurs->handle; + if (rf->VID_CreateCursor && strcmp(kcurs->name, "none")) { image_t dummytex; flocation_t loc; @@ -1003,16 +1009,16 @@ void SCR_DrawCursor(void) void *filedata = NULL; int filelen = 0, width, height; - key_customcursor[cmod].handle = NULL; + kcurs->handle = NULL; memset(&dummytex, 0, sizeof(dummytex)); dummytex.flags = IF_NOREPLACE; //no dds files *bestname = 0; //first try the named image, if possible - if (!filedata && *key_customcursor[cmod].name) + if (!filedata && *kcurs->name) { - dummytex.ident = key_customcursor[cmod].name; + dummytex.ident = kcurs->name; if (Image_LocateHighResTexture(&dummytex, &loc, bestname, sizeof(bestname), &bestflags)) filelen = FS_LoadFile(bestname, &filedata); } @@ -1050,7 +1056,7 @@ void SCR_DrawCursor(void) #undef W #undef B }; - key_customcursor[cmod].handle = rf->VID_CreateCursor(lamecursor, 8, 15, PTI_LLLA8, 0, 0, 1); //try the fallback + kcurs->handle = rf->VID_CreateCursor(lamecursor, 8, 15, PTI_LLLA8, 0, 0, 1); //try the fallback } else if (!filedata) FS_FreeFile(filedata); //format not okay, just free it. @@ -1088,18 +1094,18 @@ void SCR_DrawCursor(void) format = (format==PTI_LLLX8)?PTI_LLLA8:PTI_RGBA8; } - key_customcursor[cmod].handle = rf->VID_CreateCursor(rgbadata, width, height, format, key_customcursor[cmod].hotspot[0], key_customcursor[cmod].hotspot[1], key_customcursor[cmod].scale); //try the fallback + kcurs->handle = rf->VID_CreateCursor(rgbadata, width, height, format, kcurs->hotspot[0], kcurs->hotspot[1], kcurs->scale); //try the fallback BZ_Free(rgbadata); } } } else - key_customcursor[cmod].handle = NULL; + kcurs->handle = NULL; } - if (scr_curcursor != key_customcursor[cmod].handle) + if (scr_curcursor != kcurs->handle) { - scr_curcursor = key_customcursor[cmod].handle; + scr_curcursor = kcurs->handle; rf->VID_SetCursor(scr_curcursor); } if (oldcurs) @@ -1109,16 +1115,16 @@ void SCR_DrawCursor(void) return; //system doesn't support a hardware cursor, so try to draw a software one. - if (!strcmp(key_customcursor[cmod].name, "none")) + if (!strcmp(kcurs->name, "none")) return; - p = R2D_SafeCachePic(key_customcursor[cmod].name); + p = R2D_SafeCachePic(kcurs->name); if (!p || !R_GetShaderSizes(p, NULL, NULL, false)) p = R2D_SafeCachePic("gfx/cursor.lmp"); if (p && R_GetShaderSizes(p, NULL, NULL, false)) { R2D_ImageColours(1, 1, 1, 1); - R2D_Image(mousecursor_x-key_customcursor[cmod].hotspot[0], mousecursor_y-key_customcursor[cmod].hotspot[1], p->width*cl_cursorscale.value, p->height*cl_cursorscale.value, 0, 0, 1, 1, p); + R2D_Image(mousecursor_x-kcurs->hotspot[0], mousecursor_y-kcurs->hotspot[1], p->width*cl_cursorscale.value, p->height*cl_cursorscale.value, 0, 0, 1, 1, p); } else { @@ -1905,7 +1911,7 @@ void SCR_DrawPause (void) return; #endif - if (Key_Dest_Has(kdm_emenu) || Key_Dest_Has(kdm_gmenu)) + if (Key_Dest_Has(kdm_menu)) return; pic = R2D_SafeCachePic ("gfx/pause.lmp"); @@ -2305,7 +2311,7 @@ void SCR_SetUpToDrawConsole (void) // Key_Dest_Add(kdm_console); scr_con_target = scr_con_current = vid.height * fullscreenpercent; } - else if (!startuppending && !Key_Dest_Has(kdm_emenu|kdm_gmenu) && (!Key_Dest_Has(~((!con_stayhidden.ival?kdm_console:0)|kdm_game))) && SCR_GetLoadingStage() == LS_NONE && cls.state < ca_active && !Media_PlayingFullScreen() && !CSQC_UnconnectedOkay(false)) + else if (!startuppending && !Key_Dest_Has(kdm_menu) && (!Key_Dest_Has(~((!con_stayhidden.ival?kdm_console:0)|kdm_prompt|kdm_game))) && SCR_GetLoadingStage() == LS_NONE && cls.state < ca_active && !CSQC_UnconnectedOkay(false)) { //go fullscreen if we're not doing anything if (con_curwindow && !cls.state && !scr_drawloading && !Key_Dest_Has(kdm_console)) @@ -2314,7 +2320,7 @@ void SCR_SetUpToDrawConsole (void) scr_con_target = 0; // not looking at an normal console } #ifdef VM_UI - else if (UI_MenuState() || UI_OpenMenu()) + else if (UI_OpenMenu()) scr_con_current = scr_con_target = 0; //force instantly hidden. #endif else @@ -2329,7 +2335,7 @@ void SCR_SetUpToDrawConsole (void) { if (CL_TryingToConnect()) //if we're trying to connect, make sure there's a loading/connecting screen showing instead of forcing the menu visible SCR_SetLoadingStage(LS_CONNECTION); - else if (!Key_Dest_Has(kdm_emenu) && !startuppending) //don't force anything until the startup stuff has been done + else if (!Key_Dest_Has(kdm_menu) && !startuppending) //don't force anything until the startup stuff has been done M_ToggleMenu_f(); } } @@ -2396,7 +2402,7 @@ void SCR_DrawConsole (qboolean noback) { if (!scr_con_current) { - if (!Key_Dest_Has(kdm_console|kdm_gmenu|kdm_emenu)) + if (!Key_Dest_Has(kdm_console|kdm_menu)) Con_DrawNotify (); // only draw notify in game } Con_DrawConsole (scr_con_current, noback); @@ -3326,7 +3332,7 @@ void SCR_TileClear (int skipbottom) // The 2d refresh stuff. -void SCR_DrawTwoDimensional(int uimenu, qboolean nohud) +void SCR_DrawTwoDimensional(qboolean nohud) { qboolean consolefocused = !!Key_Dest_Has(kdm_console|kdm_cwindows); RSpeedMark(); @@ -3386,19 +3392,14 @@ void SCR_DrawTwoDimensional(int uimenu, qboolean nohud) if (!consolefocused) SCR_DrawConsole (false); -#ifdef MENU_DAT - MP_Draw(); -#endif -#ifdef MENU_NATIVECODE - if (mn_entry) - mn_entry->Draw(host_frametime); -#endif - M_Draw (uimenu); + Menu_Draw(); //but if the console IS focused, then always show it infront. if (consolefocused) SCR_DrawConsole (false); + Prompts_Draw(); + SCR_DrawCursor(); SCR_DrawSimMTouchCursor(); diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index caf7bab09..8a3443e5c 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -240,8 +240,8 @@ typedef struct trailstate_t *trailstate; } explosion_t; -explosion_t *cl_explosions; -int cl_explosions_max; +static explosion_t *cl_explosions; +static int cl_explosions_max; static int explosions_running; static int beams_running; @@ -271,16 +271,23 @@ static tentmodels_t beamtypes[] = }; -sfx_t *cl_sfx_wizhit; +static sfx_t *cl_sfx_wizhit; sfx_t *cl_sfx_knighthit; -sfx_t *cl_sfx_tink1; -sfx_t *cl_sfx_ric1; -sfx_t *cl_sfx_ric2; -sfx_t *cl_sfx_ric3; +static sfx_t *cl_sfx_tink1; +static sfx_t *cl_sfx_ric1; +static sfx_t *cl_sfx_ric2; +static sfx_t *cl_sfx_ric3; sfx_t *cl_sfx_r_exp3; cvar_t cl_expsprite = CVARFD("cl_expsprite", "1", CVAR_ARCHIVE, "Display a central sprite in explosion effects. QuakeWorld typically does so, NQ mods should not (which is problematic when played with the qw protocol)."); cvar_t r_explosionlight = CVARFC("r_explosionlight", "1", CVAR_ARCHIVE, Cvar_Limiter_ZeroToOne_Callback); +static cvar_t r_explosionlight_colour = CVARF("r_explosionlight_colour", "4.0 2.0 0.5", CVAR_ARCHIVE); +static cvar_t r_explosionlight_fade = CVARF("r_explosionlight_fade", "0.784 0.92 0.48", CVAR_ARCHIVE); +cvar_t r_dimlight_colour = CVARF("r_dimlight_colour", "2.0 1.0 0.5 200", CVAR_ARCHIVE); +cvar_t r_brightlight_colour = CVARF("r_brightlight_colour", "2.0 1.0 0.5 400", CVAR_ARCHIVE); +cvar_t r_rocketlight_colour = CVARF("r_rocketlight_colour", "2.0 1.0 0.25 200", CVAR_ARCHIVE); +cvar_t r_muzzleflash_colour = CVARF("r_muzzleflash_colour", "1.5 1.3 1.0 200", CVAR_ARCHIVE); +cvar_t r_muzzleflash_fade = CVARF("r_muzzleflash_fade", "1.5 0.75 0.375 1000", CVAR_ARCHIVE); cvar_t cl_truelightning = CVARF("cl_truelightning", "0", CVAR_SEMICHEAT); static cvar_t cl_beam_trace = CVAR("cl_beam_trace", "0"); static cvar_t cl_legacystains = CVARD("cl_legacystains", "1", "WARNING: this cvar will default to 0 and later removed at some point"); //FIXME: do as the description says! @@ -412,6 +419,13 @@ void CL_InitTEnts (void) Cvar_Register (&cl_truelightning, "Temporary entity control"); Cvar_Register (&cl_beam_trace, "Temporary entity control"); Cvar_Register (&r_explosionlight, "Temporary entity control"); + Cvar_Register (&r_explosionlight_colour, "Temporary entity control"); + Cvar_Register (&r_explosionlight_fade, "Temporary entity control"); + Cvar_Register (&r_muzzleflash_colour, "Temporary entity control"); + Cvar_Register (&r_muzzleflash_fade, "Temporary entity control"); + Cvar_Register (&r_dimlight_colour, "Temporary entity control"); + Cvar_Register (&r_brightlight_colour, "Temporary entity control"); + Cvar_Register (&r_rocketlight_colour, "Temporary entity control"); Cvar_Register (&cl_legacystains, "Temporary entity control"); Cvar_Register (&cl_shaftlight, "Temporary entity control"); @@ -1379,12 +1393,8 @@ void CL_ParseTEnt (void) dl->die = cl.time + 0.75; dl->decay = dl->radius*2; - dl->color[0] = 4.0; - dl->color[1] = 2.0; - dl->color[2] = 0.5; - dl->channelfade[0] = 0.784; - dl->channelfade[1] = 0.92; - dl->channelfade[2] = 0.48; + VectorCopy(r_explosionlight_colour.vec4, dl->color); + VectorCopy(r_explosionlight_fade.vec4, dl->channelfade); } diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index d179305a6..42ff2c1fa 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -5,7 +5,7 @@ #include "cl_master.h" #include "shader.h" -int keycatcher; +static int keycatcher; #define TT_STRING 1 // string #define TT_LITERAL 2 // literal @@ -29,6 +29,25 @@ typedef struct { static script_t *scripts; static int maxscripts; static unsigned int ui_width, ui_height; //to track when it needs to be restarted (the api has no video mode changed event) +static menu_t uimenu; + +void Q3_SetKeyCatcher(int newcatcher) +{ + int delta = newcatcher^keycatcher; + keycatcher = newcatcher; + if (delta & 2) + { + uimenu.isopaque = false; //no surprises. + if (newcatcher&2) + Menu_Push(&uimenu, false); + else + Menu_Unlink(&uimenu); + } +} +int Q3_GetKeyCatcher(void) +{ + return keycatcher; +} #define Q3SCRIPTPUNCTUATION "(,{})(\':;=!><&|+-\"" void StripCSyntax (char *s) { @@ -272,11 +291,6 @@ typedef float m3by3_t[3][3]; static vm_t *uivm; -static char *scr_centerstring; - -char *Get_Q2ConfigString(int i); - - #define MAX_PINGREQUESTS 32 struct @@ -1049,7 +1063,7 @@ static qintptr_t UI_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con VM_LONG(ret) = keycatcher; break; case UI_KEY_SETCATCHER: - keycatcher = VM_LONG(arg[0]); + Q3_SetKeyCatcher(VM_LONG(arg[0])); break; case UI_GETGLCONFIG: //get glconfig @@ -1388,41 +1402,6 @@ static qintptr_t UI_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con Q_strncpyz(vi->renderername, q_renderername, sizeof(vi->renderername)); } break; - case UI_GET_STRING: - { - char *str = NULL; - switch (arg[0]) - { - case SID_Q2STATUSBAR: - str = cl.q2statusbar; - break; - case SID_Q2LAYOUT: - str = cl.q2layout; - break; - case SID_CENTERPRINTTEXT: - str = scr_centerstring; - break; - case SID_SERVERNAME: - str = cls.servername; - break; - - default: - str = Get_Q2ConfigString(arg[0]); - break; - } - if (!str) - return -1; - - if (arg[1] + arg[2] >= mask || VM_POINTER(arg[1]) < offset) - return -1; //out of bounds. - - if (strlen(str)>= arg[2]) - return -1; - - strcpy(VM_POINTER(arg[1]), str); //already made sure buffer is big enough - - return strlen(str); - } */ case UI_PC_ADD_GLOBAL_DEFINE: @@ -1504,29 +1483,11 @@ static qintptr_t EXPORT_FN UI_SystemCallsNative(qintptr_t arg, ...) return UI_SystemCalls(NULL, ~(quintptr_t)0, arg, args); } -qboolean UI_DrawStatusBar(int scores) +static void UI_Release(menu_t *m) { - return false; -/* - if (!uivm) - return false; - - return VM_Call(uivm, UI_DRAWSTATUSBAR, scores); -*/ + keycatcher &= ~2; } - -qboolean UI_DrawIntermission(void) -{ - return false; -/* - if (!uivm) - return false; - - return VM_Call(uivm, UI_INTERMISSION); -*/ -} - -void UI_DrawMenu(void) +static void UI_DrawMenu(menu_t *m) { if (uivm) { @@ -1537,66 +1498,12 @@ void UI_DrawMenu(void) VM_Call(uivm, UI_INIT); } VM_Call(uivm, UI_REFRESH, (int)(realtime * 1000)); + + + uimenu.isopaque = VM_Call(uivm, UI_IS_FULLSCREEN); } } - -qboolean UI_CenterPrint(char *text, qboolean finale) -{ - scr_centerstring = text; - return false; -/* - if (!uivm) - return false; - - return VM_Call(uivm, UI_STRINGCHANGED, SID_CENTERPRINTTEXT); -*/ -} - -qboolean UI_Q2LayoutChanged(void) -{ - return false; -/* - if (!uivm) - return false; - - return VM_Call(uivm, UI_STRINGCHANGED, SID_CENTERPRINTTEXT); -*/ -} - -void UI_StringChanged(int num) -{ -/* if (uivm) - VM_Call(uivm, UI_STRINGCHANGED, num); -*/ -} - -void UI_Reset(void) -{ - keycatcher &= ~2; - - if (qrenderer == QR_NONE) //no renderer loaded - UI_Stop(); - else if (uivm) - VM_Call(uivm, UI_INIT); -} - -int UI_MenuState(void) -{ - if (Key_Dest_Has(kdm_gmenu) || Key_Dest_Has(kdm_emenu)) - { //engine's menus take precedence over q3's ui - return false; - } - if (!uivm) - return false; - if (VM_Call(uivm, UI_IS_FULLSCREEN)) - return 2; - else if (keycatcher&2) - return 3; - else - return 0; -} - -qboolean UI_KeyPress(int key, int unicode, qboolean down) +qboolean UI_KeyPress(struct menu_s *m, qboolean isdown, unsigned int devid, int key, int unicode) { extern qboolean keydown[K_MAX]; extern int keyshift[K_MAX]; // key to map to if shift held down in console @@ -1607,13 +1514,8 @@ qboolean UI_KeyPress(int key, int unicode, qboolean down) // return false; if (!(keycatcher&2)) { - if (key == K_ESCAPE && down) + if (key == K_ESCAPE && isdown) { - if (Media_PlayingFullScreen()) - { - Media_StopFilm(true); - } - UI_OpenMenu(); return true; } @@ -1625,35 +1527,39 @@ qboolean UI_KeyPress(int key, int unicode, qboolean down) if (key < K_BACKSPACE && key >= ' ') key |= 1024; - /*result = */VM_Call(uivm, UI_KEY_EVENT, key, down); -/* - if (!keycatcher && !cls.state && key == K_ESCAPE && down) - { - M_Menu_Main_f(); - return true; - }*/ - + /*result = */VM_Call(uivm, UI_KEY_EVENT, key, isdown); return true; - -// return result; } -qboolean UI_MousePosition(float xpos, float ypos) -{ - if (uivm && (keycatcher&2)) +static qboolean UI_MousePosition(struct menu_s *m, qboolean abs, unsigned int devid, float x, float y) +{ //q3ui is a peice of poo and only accepts relative mouse movements. + //which it then clamps arbitrarily + //which means we can't use hardware cursors + //which results in clumsyness when switching between q3ui and everything else. + + if (uivm && !abs) { - int px, py; - px = (xpos);//*640/(int)vid.width; - py = (ypos);//*480/(int)vid.height; + int px = x, py = y; VM_Call(uivm, UI_MOUSE_EVENT, px, py); return true; } return false; } +void UI_Reset(void) +{ + Menu_Unlink(&uimenu); + + if (qrenderer == QR_NONE) //no renderer loaded + UI_Stop(); + else if (uivm) + VM_Call(uivm, UI_INIT); +} + void UI_Stop (void) { - keycatcher &= ~2; + Menu_Unlink(&uimenu); + if (uivm) { VM_Call(uivm, UI_SHUTDOWN); @@ -1683,6 +1589,11 @@ void UI_Start (void) for (i = 0; i < MAX_PINGREQUESTS; i++) ui_pings[i].adr.type = NA_INVALID; + uimenu.drawmenu = UI_DrawMenu; + uimenu.mousemove = UI_MousePosition; + uimenu.keyevent = UI_KeyPress; + uimenu.release = UI_Release; + ui_width = vid.width; ui_height = vid.height; uivm = VM_Create("ui", com_nogamedirnativecode.ival?NULL:UI_SystemCallsNative, "vm/ui", UI_SystemCallsVM); diff --git a/engine/client/client.h b/engine/client/client.h index 9d6975204..5512e8c11 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -1232,7 +1232,7 @@ int Master_FindBestRoute(char *server, char *out, size_t outsize, int *directcos float CL_KeyState (kbutton_t *key, int pnum, qboolean noslowstart); const char *Key_KeynumToString (int keynum, int modifier); int Key_StringToKeynum (const char *str, int *modifier); -char *Key_GetBinding(int keynum, int bindmap, int modifier); +const char *Key_GetBinding(int keynum, int bindmap, int modifier); void Key_GetBindMap(int *bindmaps); void Key_SetBindMap(int *bindmaps); @@ -1530,7 +1530,7 @@ char* TP_EnemyTeam (void); void TP_ExecTrigger (char *s, qboolean indemos); qboolean TP_FilterMessage (char *s); void TP_Init(void); -char* TP_LocationName (vec3_t location); +char* TP_LocationName (const vec3_t location); char* TP_MapName (void); void TP_NewMap (void); void TP_ParsePlayerInfo(player_state_t *oldstate, player_state_t *state, player_info_t *info); @@ -1682,7 +1682,6 @@ typedef enum CINSTATE_FLUSHED, //video will restart from beginning } cinstates_t; /*media playing system*/ -qboolean Media_PlayingFullScreen(void); qboolean Media_PlayFilm(char *name, qboolean enqueue); qboolean Media_StopFilm(qboolean all); struct cin_s *Media_StartCin(char *name); @@ -1701,8 +1700,6 @@ cinstates_t Media_GetState(cin_t *cin); const char *Media_Send_GetProperty(cin_t *cin, const char *key); #else -#define Media_Playing() false -#define Media_PlayingFullScreen() false #define Media_PlayFilm(n,e) false #define Media_StopFilm(a) (void)true #endif diff --git a/engine/client/clq3_parse.c b/engine/client/clq3_parse.c index 1630afd2a..ae3b095ea 100644 --- a/engine/client/clq3_parse.c +++ b/engine/client/clq3_parse.c @@ -900,7 +900,6 @@ void CLQ3_SendCmd(usercmd_t *cmd) outframe_t *frame, *oldframe; int cmdcount, key; usercmd_t *to, *from; - extern int keycatcher; extern cvar_t cl_nodelta, cl_c2sdupe; //reuse the q1 array @@ -928,7 +927,7 @@ void CLQ3_SendCmd(usercmd_t *cmd) cmd->upmove = 100; cmd->buttons &= ~2; } - if (Key_Dest_Has(~kdm_game) || (keycatcher&3)) + if (Key_Dest_Has(~kdm_game)) cmd->buttons |= 2; //add in the 'at console' button cl.outframes[cl.movesequence&Q3CMD_MASK].cmd[0] = *cmd; diff --git a/engine/client/clq3defs.h b/engine/client/clq3defs.h index 8a65c7cfa..32c78561e 100644 --- a/engine/client/clq3defs.h +++ b/engine/client/clq3defs.h @@ -2,6 +2,9 @@ #define _Q3DEFS_H_ #define PROTOCOL_VERSION_Q3 68 +void Q3_SetKeyCatcher(int newcatcher); +int Q3_GetKeyCatcher(void); + int StringKey( const char *string, int length ); typedef struct { diff --git a/engine/client/console.c b/engine/client/console.c index 3cca2de5a..c99bd9e5b 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -1075,7 +1075,7 @@ static void Con_PrintFromThread (void *ctx, void *data, size_t a, size_t b) BZ_Free(data); } -vfsfile_t *Con_POpen(char *conname) +vfsfile_t *Con_POpen(const char *conname) { if (!conname || !*conname) { diff --git a/engine/client/image.c b/engine/client/image.c index 7ee4f0afd..4238a0547 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -9262,7 +9262,7 @@ qboolean Image_LocateHighResTexture(image_t *tex, flocation_t *bestloc, char *be Q_strncpyz(bestname, fname, bestnamesize); bestdepth = depth; *bestloc = loc; - bestflags = 0; + *bestflags = 0; } #endif @@ -9324,7 +9324,7 @@ qboolean Image_LocateHighResTexture(image_t *tex, flocation_t *bestloc, char *be Q_strncpyz(bestname, fname, bestnamesize); bestdepth = depth; *bestloc = loc; - bestflags = 0; + *bestflags = 0; } } } @@ -9343,7 +9343,7 @@ qboolean Image_LocateHighResTexture(image_t *tex, flocation_t *bestloc, char *be Q_strncpyz(bestname, fname, bestnamesize); bestdepth = depth; *bestloc = loc; - bestflags = 0; + *bestflags = 0; } } } @@ -9408,7 +9408,7 @@ qboolean Image_LocateHighResTexture(image_t *tex, flocation_t *bestloc, char *be Q_strncpyz(bestname, fname, bestnamesize); bestdepth = depth; *bestloc = loc; - bestflags = 0; + *bestflags = 0; } } } diff --git a/engine/client/in_generic.c b/engine/client/in_generic.c index be8c30d00..e4dce32d1 100644 --- a/engine/client/in_generic.c +++ b/engine/client/in_generic.c @@ -126,7 +126,7 @@ static cvar_t joy_radialdeadzone = CVARD("joyradialdeadzone", "1", "Treat contro #define EVENTQUEUELENGTH 1024 -struct eventlist_s +static struct eventlist_s { enum { @@ -166,8 +166,8 @@ struct eventlist_s } gyro; }; } eventlist[EVENTQUEUELENGTH]; -volatile int events_avail; /*volatile to make sure the cc doesn't try leaving these cached in a register*/ -volatile int events_used; +static volatile int events_avail; /*volatile to make sure the cc doesn't try leaving these cached in a register*/ +static volatile int events_used; static struct eventlist_s *in_newevent(void) { @@ -182,7 +182,7 @@ static void in_finishevent(void) } #define MAXPOINTERS 8 -struct mouse_s +static struct mouse_s { enum { @@ -202,11 +202,11 @@ struct mouse_s unsigned int updates; //tracks updates per second qboolean updated; } ptr[MAXPOINTERS]; -int touchcursor = -1; //the cursor follows whichever finger was most recently pressed in preference to any mouse also on the same system +static int touchcursor = -1; //the cursor follows whichever finger was most recently pressed in preference to any mouse also on the same system #define MAXJOYAXIS 6 #define MAXJOYSTICKS 8 -struct joy_s +static struct joy_s { unsigned int qdeviceid; float axis[MAXJOYAXIS]; @@ -466,11 +466,9 @@ void IN_Commands(void) case IEV_JOYAXIS: if (ev->devid < MAXJOYSTICKS && ev->joy.axis < MAXJOYAXIS) { -#ifdef MENU_DAT - if (MP_JoystickAxis(ev->joy.axis, ev->joy.value, ev->devid)) + if (topmenu && topmenu->joyaxis && topmenu->joyaxis(topmenu, ev->devid, ev->joy.axis, ev->joy.value)) joy[ev->devid].axis[ev->joy.axis] = 0; else -#endif #ifdef CSQC_DAT if (CSQC_JoystickAxis(ev->joy.axis, ev->joy.value, ev->devid)) joy[ev->devid].axis[ev->joy.axis] = 0; @@ -659,19 +657,7 @@ void IN_MoveMouse(struct mouse_s *mouse, float *movements, int pnum, float frame mousemove_y += my; if (Key_MouseShouldBeFree()) - { mx=my=0; - } - else - { -#ifdef VM_UI - if (UI_MousePosition(mx, my)) - { - mx = 0; - my = 0; - } -#endif - } if (mouse->type == M_TOUCH) { @@ -744,28 +730,12 @@ void IN_MoveMouse(struct mouse_s *mouse, float *movements, int pnum, float frame mouse->updated = false; if (!runningindepphys) { -#ifdef MENU_NATIVECODE - if (mn_entry) - { - struct menu_inputevent_args_s ev = {MIE_MOUSEABS, mouse->qdeviceid}; - ev.mouse.delta[0] = mx; - ev.mouse.delta[1] = my; - ev.mouse.screen[0] = (mouse->oldpos[0] * vid.width) / vid.pixelwidth; - ev.mouse.screen[1] = (mouse->oldpos[1] * vid.width) / vid.pixelwidth; - if (mn_entry->InputEvent(ev)) - { - mx = 0; - my = 0; - } - } -#endif -#ifdef MENU_DAT - if (MP_MousePosition(mouse->oldpos[0], mouse->oldpos[1], mouse->qdeviceid)) + if ((promptmenu && promptmenu->mousemove && promptmenu->mousemove(topmenu, true, mouse->qdeviceid, mouse->oldpos[0], mouse->oldpos[1])) || + (topmenu && topmenu->mousemove && topmenu->mousemove(topmenu, true, mouse->qdeviceid, mouse->oldpos[0], mouse->oldpos[1]))) { mx = 0; my = 0; } -#endif #ifdef CSQC_DAT if (!runningindepphys && CSQC_MousePosition(mouse->oldpos[0], mouse->oldpos[1], mouse->qdeviceid)) { @@ -778,30 +748,13 @@ void IN_MoveMouse(struct mouse_s *mouse, float *movements, int pnum, float frame } else { -#ifdef MENU_NATIVECODE - if (mn_entry && Key_Dest_Has(kdm_nmenu) && (mx || my)) - { - struct menu_inputevent_args_s ev = {MIE_MOUSEABS, mouse->qdeviceid}; - ev.mouse.delta[0] = mx; - ev.mouse.delta[1] = my; - ev.mouse.screen[0] = (mouse->oldpos[0] * vid.width) / vid.pixelwidth; - ev.mouse.screen[1] = (mouse->oldpos[1] * vid.height) / vid.pixelheight; - if (mn_entry->InputEvent(ev)) - { - mx = 0; - my = 0; - } - } -#endif -#ifdef MENU_DAT - if (Key_Dest_Has(kdm_gmenu)) + if (Key_Dest_Has(kdm_menu)) if (mx || my) - if (!runningindepphys && MP_MouseMove(mx, my, mouse->qdeviceid)) + if (!runningindepphys && topmenu && topmenu->mousemove && topmenu->mousemove(topmenu, false, mouse->qdeviceid, mx, my)) { mx = 0; my = 0; } -#endif #ifdef CSQC_DAT if (mx || my) diff --git a/engine/client/keys.c b/engine/client/keys.c index 46841ba34..35b60d1f9 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -1762,6 +1762,13 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode) { if (con->redirect && con->redirect(con, unicode, key)) return true; +#ifdef HAVE_MEDIA_DECODER + if (con->backshader && R_ShaderGetCinematic(con->backshader)) + { + Media_Send_KeyEvent(R_ShaderGetCinematic(con->backshader), rkey, unicode, 0); + return true; + } +#endif if (Key_IsTouchScreen() || con->mousecursor[0] > ((con->flags & CONF_ISWINDOW)?con->wnd_w-16:vid.width)-8) { //just scroll the console up/down con->buttonsdown = CB_SCROLL; @@ -2100,7 +2107,7 @@ void Key_Message (int key, int unicode) //============================================================================ //for qc -char *Key_GetBinding(int keynum, int bindmap, int modifier) +const char *Key_GetBinding(int keynum, int bindmap, int modifier) { char *key = NULL; if (keynum < 0 || keynum >= K_MAX) @@ -2596,8 +2603,8 @@ void Key_Init (void) } key_linepos = 0; - key_dest_mask = kdm_game; - key_dest_absolutemouse = kdm_centerprint | kdm_console | kdm_cwindows | kdm_emenu; + Key_Dest_Add(kdm_game); + key_dest_absolutemouse = kdm_centerprint | kdm_console | kdm_cwindows | kdm_menu; // // init ascii characters in console mode @@ -2700,14 +2707,6 @@ qboolean Key_MouseShouldBeFree(void) if (key_dest_absolutemouse & key_dest_mask) return true; -#ifdef VM_UI - if (UI_MenuState()) - return false; -#endif - - if (Media_PlayingFullScreen()) - return true; - if (cl_prydoncursor.ival) return true; @@ -2786,7 +2785,7 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down //yes, csqc is allowed to steal the escape key. if (key != '`' && (!down || key != K_ESCAPE || (!Key_Dest_Has(~kdm_game) && !shift_down)) && - !Key_Dest_Has(~kdm_game) && !Media_PlayingFullScreen()) + !Key_Dest_Has(~kdm_game)) { #ifdef CSQC_DAT if (CSQC_KeyPress(key, unicode, down, devid)) //give csqc a chance to handle it. @@ -2810,70 +2809,38 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down // if (key == K_ESCAPE) { -#ifdef VM_UI -#ifdef TEXTEDITOR - if (!Key_Dest_Has(~kdm_game) && !Key_Dest_Has(kdm_console)) -#endif + if (!Key_Dest_Has(~kdm_game)) { - if (down && Media_PlayingFullScreen()) - { - Media_StopFilm(false); - return; - } - if (UI_KeyPress(key, unicode, down)) //Allow the UI to see the escape key. It is possible that a developer may get stuck at a menu. - return; - } +#ifdef VM_UI +// if (UI_KeyPress(key, unicode, down)) //Allow the UI to see the escape key. It is possible that a developer may get stuck at a menu. +// return; #endif + } if (!down) { -#ifdef MENU_DAT - if (Key_Dest_Has(kdm_gmenu) && !Key_Dest_Has(kdm_console|kdm_cwindows)) - MP_Keyup (key, unicode, devid); -#endif -#ifdef MENU_NATIVECODE - if (mn_entry) - { - struct menu_inputevent_args_s ev = {MIE_KEYUP, devid}; - ev.key.scancode = key; - ev.key.charcode = unicode; - mn_entry->InputEvent(ev); - } -#endif + if (Key_Dest_Has(kdm_prompt) || (Key_Dest_Has(kdm_menu) && !Key_Dest_Has(kdm_console|kdm_cwindows))) + Menu_KeyEvent (false, devid, key, unicode); return; } - if (Key_Dest_Has(kdm_console)) + if (Key_Dest_Has(kdm_prompt)) + Menu_KeyEvent (true, devid, key, unicode); + else if (Key_Dest_Has(kdm_console)) { Key_Dest_Remove(kdm_console); Key_Dest_Remove(kdm_cwindows); - if (!cls.state && !Key_Dest_Has(~kdm_game) && !Media_PlayingFullScreen()) + if (!cls.state && !Key_Dest_Has(~kdm_game)) M_ToggleMenu_f (); } else if (Key_Dest_Has(kdm_cwindows)) { Key_Dest_Remove(kdm_cwindows); - if (!cls.state && !Key_Dest_Has(~kdm_game) && !Media_PlayingFullScreen()) + if (!cls.state && !Key_Dest_Has(~kdm_game)) M_ToggleMenu_f (); } - else if (Key_Dest_Has(kdm_emenu)) - M_Keydown (key, unicode); -#ifdef MENU_NATIVECODE - else if (Key_Dest_Has(kdm_nmenu)) - { - if (mn_entry) - { - struct menu_inputevent_args_s ev = {MIE_KEYDOWN, devid}; - ev.key.scancode = key; - ev.key.charcode = unicode; - mn_entry->InputEvent(ev); - } - } -#endif -#ifdef MENU_DAT - else if (Key_Dest_Has(kdm_gmenu)) - MP_Keydown (key, unicode, devid); -#endif + else if (Key_Dest_Has(kdm_menu)) + Menu_KeyEvent (true, devid, key, unicode); else if (Key_Dest_Has(kdm_message)) { Key_Dest_Remove(kdm_message); @@ -2882,16 +2849,7 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down chat_bufferpos = 0; } else - { - if (Media_PlayingFullScreen()) - { - Media_StopFilm(true); - if (!cls.state) - M_ToggleMenu_f (); - } - else - M_ToggleMenu_f (); - } + M_ToggleMenu_f (); return; } @@ -2924,25 +2882,8 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down Key_ConsoleRelease(con, key, unicode); } } - if (Key_Dest_Has(kdm_emenu)) - M_Keyup (key, unicode); -#ifdef MENU_NATIVECODE - if (Key_Dest_Has(kdm_nmenu) && mn_entry) - { - struct menu_inputevent_args_s ev = {MIE_KEYUP, devid}; - ev.key.scancode = key; - ev.key.charcode = unicode; - mn_entry->InputEvent(ev); - } -#endif -#ifdef MENU_DAT - if (Key_Dest_Has(kdm_gmenu)) - MP_Keyup (key, unicode, devid); -#endif -#ifdef HAVE_MEDIA_DECODER - if (Media_PlayingFullScreen()) - Media_Send_KeyEvent(NULL, key, unicode, down?0:1); -#endif + if (Key_Dest_Has(kdm_menu|kdm_prompt)) + Menu_KeyEvent (false, devid, key, unicode); uc = releasecommand[key][devid%MAX_INDEVS]; if (uc) //this wasn't down, so don't crash on bad commands. @@ -2980,6 +2921,16 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down } } + //prompts get the first chance + if (Key_Dest_Has(kdm_prompt)) + { + if (key < K_F1 || key > K_F15) + { //function keys don't get intercepted by the menu... + Menu_KeyEvent (true, devid, key, unicode); + return; + } + } + // // if not a consolekey, send to the interpreter no matter what mode is // @@ -2999,49 +2950,16 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down Key_Dest_Remove(kdm_cwindows); } -#ifdef HAVE_MEDIA_DECODER - if (Media_PlayingFullScreen()) - { - Media_Send_KeyEvent(NULL, key, unicode, down?0:1); - return; - } -#endif -#ifdef VM_UI - if (!Key_Dest_Has(~kdm_game) || !down) - { - if (UI_KeyPress(key, unicode, down) && down) //UI is allowed to take these keydowns. Keyups are always maintained. - return; - } -#endif - if (Key_Dest_Has(kdm_emenu)) + //menus after console stuff + if (Key_Dest_Has(kdm_menu)) { if (key < K_F1 || key > K_F15) { //function keys don't get intercepted by the menu... - M_Keydown (key, unicode); + Menu_KeyEvent (true, devid, key, unicode); return; } } -#ifdef MENU_NATIVECODE - if (Key_Dest_Has(kdm_nmenu)) - { - if (mn_entry) - { - struct menu_inputevent_args_s ev = {down?MIE_KEYDOWN:MIE_KEYUP, devid}; - ev.key.scancode = key; - ev.key.charcode = unicode; - if (mn_entry->InputEvent(ev)) - return; - } - } -#endif -#ifdef MENU_DAT - if (Key_Dest_Has(kdm_gmenu)) - { - if (MP_Keydown (key, unicode, devid)) - return; - } -#endif if (Key_Dest_Has(kdm_message)) { Key_Message (key, unicode); diff --git a/engine/client/keys.h b/engine/client/keys.h index 53ee21f90..0dfb9d352 100644 --- a/engine/client/keys.h +++ b/engine/client/keys.h @@ -250,15 +250,10 @@ typedef enum //highest has priority kdm_game = 1u<<0, //should always be set kdm_centerprint = 1u<<1, //enabled when there's a centerprint menu with clickable things. kdm_message = 1u<<2, - kdm_gmenu = 1u<<3, //menu.dat -#ifdef MENU_NATIVECODE - kdm_nmenu = 1u<<4, //should probably reuse gmenu... -#else - kdm_nmenu = 0, -#endif - kdm_emenu = 1u<<5, //engine's menus - kdm_console = 1u<<6, - kdm_cwindows = 1u<<7, + kdm_menu = 1u<<3, //layered menus (engine menus, qc menus, or plugins/etc) + kdm_console = 1u<<4, + kdm_cwindows = 1u<<5, + kdm_prompt = 1u<<6, //highest priority - popups that require user interaction (eg: confirmation from untrusted console commands) } keydestmask_t; //unsigned int Key_Dest_Get(void); //returns highest priority destination @@ -277,12 +272,11 @@ extern int key_lastpress; enum { - kc_game, //csprogs.dat - kc_menu, //menu.dat -#ifdef MENU_NATIVECODE - kc_nmenu, -#endif - kc_console, //generic engine-defined cursor + kc_game, //csprogs.dat + kc_menuqc, // + kc_nativemenu, // + kc_plugin, //for plugins + kc_console, //generic engine-defined cursor kc_max }; extern struct key_cursor_s diff --git a/engine/client/m_download.c b/engine/client/m_download.c index 49de84c01..95f5f4ca0 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -1198,7 +1198,7 @@ static void PM_PreparePackageList(void) { pluginpromptshown = true; #ifndef SERVERONLY - M_Menu_Prompt(PM_PluginDetected, NULL, "Plugin(s) appears to have\nbeen installed externally.\nUse the updates menu\nto enable them.", "View", NULL, "Disable"); + Menu_Prompt(PM_PluginDetected, NULL, "Plugin(s) appears to have\nbeen installed externally.\nUse the updates menu\nto enable them.", "View", NULL, "Disable"); #endif } } @@ -1758,12 +1758,7 @@ static void PM_ListDownloaded(struct dl_download *dl) #ifdef DOWNLOADMENU if (!isDedicated) { - if (Key_Dest_Has(kdm_emenu)) - Key_Dest_Remove(kdm_emenu); -#ifdef MENU_DAT - if (Key_Dest_Has(kdm_gmenu)) - MP_Toggle(0); -#endif + Menu_PopAll(); Cmd_ExecuteString("menu_download\n", RESTRICT_LOCAL); } else @@ -2717,7 +2712,7 @@ static void PM_PromptApplyChanges(void) //lock it down, so noone can make any changes while this prompt is still displayed if (pkg_updating) { - M_Menu_Prompt(PM_PromptApplyChanges_Callback, NULL, "An update is already in progress\nPlease wait\n", NULL, NULL, "Cancel"); + Menu_Prompt(PM_PromptApplyChanges_Callback, NULL, "An update is already in progress\nPlease wait\n", NULL, NULL, "Cancel"); return; } pkg_updating = true; @@ -2725,7 +2720,7 @@ static void PM_PromptApplyChanges(void) strcpy(text, "Really decline the following\nrecommendedpackages?\n\n"); if (PM_DeclinedPackages(text+strlen(text), sizeof(text)-strlen(text))) - M_Menu_Prompt(PM_PromptApplyDecline_Callback, NULL, text, NULL, "Confirm", "Cancel"); + Menu_Prompt(PM_PromptApplyDecline_Callback, NULL, text, NULL, "Confirm", "Cancel"); else { strcpy(text, "Apply the following changes?\n\n"); @@ -2737,7 +2732,7 @@ static void PM_PromptApplyChanges(void) #endif } else - M_Menu_Prompt(PM_PromptApplyChanges_Callback, NULL, text, "Apply", NULL, "Cancel"); + Menu_Prompt(PM_PromptApplyChanges_Callback, NULL, text, "Apply", NULL, "Cancel"); } } #endif @@ -3105,7 +3100,7 @@ typedef struct { qboolean populated; } dlmenu_t; -static void MD_Draw (int x, int y, struct menucustom_s *c, struct menu_s *m) +static void MD_Draw (int x, int y, struct menucustom_s *c, struct emenu_s *m) { package_t *p; char *n; @@ -3217,7 +3212,7 @@ static void MD_Draw (int x, int y, struct menucustom_s *c, struct menu_s *m) } } -static qboolean MD_Key (struct menucustom_s *c, struct menu_s *m, int key, unsigned int unicode) +static qboolean MD_Key (struct menucustom_s *c, struct emenu_s *m, int key, unsigned int unicode) { extern qboolean keydown[]; qboolean ctrl = keydown[K_LCTRL] || keydown[K_RCTRL]; @@ -3329,7 +3324,7 @@ static qboolean MD_Key (struct menucustom_s *c, struct menu_s *m, int key, unsig } #ifdef WEBCLIENT -static void MD_AutoUpdate_Draw (int x, int y, struct menucustom_s *c, struct menu_s *m) +static void MD_AutoUpdate_Draw (int x, int y, struct menucustom_s *c, struct emenu_s *m) { char *settings[] = { @@ -3345,7 +3340,7 @@ static void MD_AutoUpdate_Draw (int x, int y, struct menucustom_s *c, struct men // else Draw_FunString (x, y, text); } -static qboolean MD_AutoUpdate_Key (struct menucustom_s *c, struct menu_s *m, int key, unsigned int unicode) +static qboolean MD_AutoUpdate_Key (struct menucustom_s *c, struct emenu_s *m, int key, unsigned int unicode) { if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START || key == K_MOUSE1) { @@ -3360,7 +3355,7 @@ static qboolean MD_AutoUpdate_Key (struct menucustom_s *c, struct menu_s *m, int return false; } -static qboolean MD_MarkUpdatesButton (union menuoption_s *mo,struct menu_s *m,int key) +static qboolean MD_MarkUpdatesButton (union menuoption_s *mo,struct emenu_s *m,int key) { if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START || key == K_MOUSE1) { @@ -3371,7 +3366,7 @@ static qboolean MD_MarkUpdatesButton (union menuoption_s *mo,struct menu_s *m,in } #endif -qboolean MD_PopMenu (union menuoption_s *mo,struct menu_s *m,int key) +qboolean MD_PopMenu (union menuoption_s *mo,struct emenu_s *m,int key) { if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START || key == K_MOUSE1) { @@ -3381,7 +3376,7 @@ qboolean MD_PopMenu (union menuoption_s *mo,struct menu_s *m,int key) return false; } -static qboolean MD_ApplyDownloads (union menuoption_s *mo,struct menu_s *m,int key) +static qboolean MD_ApplyDownloads (union menuoption_s *mo,struct emenu_s *m,int key) { if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START || key == K_MOUSE1) { @@ -3391,7 +3386,7 @@ static qboolean MD_ApplyDownloads (union menuoption_s *mo,struct menu_s *m,int k return false; } -static qboolean MD_RevertUpdates (union menuoption_s *mo,struct menu_s *m,int key) +static qboolean MD_RevertUpdates (union menuoption_s *mo,struct emenu_s *m,int key) { if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START || key == K_MOUSE1) { @@ -3401,7 +3396,7 @@ static qboolean MD_RevertUpdates (union menuoption_s *mo,struct menu_s *m,int ke return false; } -static int MD_AddItemsToDownloadMenu(menu_t *m, int y, const char *pathprefix) +static int MD_AddItemsToDownloadMenu(emenu_t *m, int y, const char *pathprefix) { char path[MAX_QPATH]; package_t *p; @@ -3471,7 +3466,7 @@ static int MD_AddItemsToDownloadMenu(menu_t *m, int y, const char *pathprefix) } #include "shader.h" -static void MD_Download_UpdateStatus(struct menu_s *m) +static void MD_Download_UpdateStatus(struct emenu_s *m) { dlmenu_t *info = m->data; int i, y; @@ -3621,15 +3616,13 @@ static void MD_Download_UpdateStatus(struct menu_s *m) void Menu_DownloadStuff_f (void) { - menu_t *menu; + emenu_t *menu; dlmenu_t *info; - Key_Dest_Add(kdm_emenu); - menu = M_CreateMenu(sizeof(dlmenu_t)); info = menu->data; - menu->persist = true; + menu->menu.persist = true; menu->predraw = MD_Download_UpdateStatus; info->downloadablessequence = downloadablessequence; diff --git a/engine/client/m_items.c b/engine/client/m_items.c index 413101565..f9e5ad2ce 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -78,16 +78,16 @@ void Draw_TextBox (int x, int y, int width, int lines) #ifndef NOBUILTINMENUS -int omousex; -int omousey; -qboolean mousemoved; -qboolean bindingactive; +static int omousex; +static int omousey; +static qboolean mousemoved; +static qboolean bindingactive; extern cvar_t cl_cursor; extern cvar_t cl_cursorsize; extern cvar_t cl_cursorbias; extern cvar_t m_preset_chosen; -menu_t *topmenu; -menuoption_t *M_NextSelectableItem(menu_t *m, menuoption_t *old); +extern menu_t *topmenu; +menuoption_t *M_NextSelectableItem(emenu_t *m, menuoption_t *old); #ifdef HEXEN2 //this function is so fucked up. @@ -266,7 +266,7 @@ int maxdots; int mindot; int dotofs; -static void MenuTooltipChange(menu_t *menu, const char *text) +static void MenuTooltipChange(emenu_t *menu, const char *text) { unsigned int MAX_CHARS=1024; menutooltip_t *mtt; @@ -329,7 +329,7 @@ static qboolean MI_Selectable(menuoption_t *op) } } -static qboolean M_MouseMoved(menu_t *menu) +static qboolean M_MouseMoved(emenu_t *menu) { int ypos = menu->ypos, framescroll = 0; menuoption_t *option; @@ -393,7 +393,7 @@ static qboolean M_MouseMoved(menu_t *menu) return true; } -static void M_CheckMouseMove(void) +static void M_CheckMouseMove(emenu_t *m) { if (omousex != (int)mousecursor_x || omousey != (int)mousecursor_y) mousemoved = true; @@ -403,7 +403,7 @@ static void M_CheckMouseMove(void) omousey = mousecursor_y; if (mousemoved) - M_MouseMoved(topmenu); + M_MouseMoved(m); } static float M_DrawScrollbar(int x, int y, int width, int height, float frac, qboolean mgrabbed) @@ -461,7 +461,7 @@ static float M_DrawScrollbar(int x, int y, int width, int height, float frac, qb return frac; } -static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu) +static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, emenu_t *menu) { int i; mpic_t *p; @@ -479,7 +479,7 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu if (option->common.ishidden) continue; - if (menu == topmenu && menu->mouseitem == option) + if (&menu->menu == topmenu && menu->mouseitem == option) { float alphamax = 0.5, alphamin = 0.2; R2D_ImageColours(.5,.4,0,(sin(realtime*2)+1)*0.5*(alphamax-alphamin)+alphamin); @@ -763,11 +763,8 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu } } -static void MenuDraw(menu_t *menu) +static void MenuDraw(emenu_t *menu) { - if (!menu->exclusive && menu->prev) //popup menus draw the one underneath them - MenuDraw(menu->prev); - if (!menu->dontexpand) menu->xpos = ((vid.width - 320)>>1); if (menu->predraw) @@ -831,7 +828,7 @@ static void MenuDraw(menu_t *menu) } -menutext_t *MC_AddWhiteText(menu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign) +menutext_t *MC_AddWhiteText(emenu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign) { menutext_t *n = Z_Malloc(sizeof(menutext_t) + (text?strlen(text):0)+1); n->common.type = mt_text; @@ -851,7 +848,7 @@ menutext_t *MC_AddWhiteText(menu_t *menu, int lhs, int rhs, int y, const char *t return n; } -menutext_t *MC_AddBufferedText(menu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign, qboolean red) +menutext_t *MC_AddBufferedText(emenu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign, qboolean red) { menutext_t *n = Z_Malloc(sizeof(menutext_t) + strlen(text)+1); n->common.type = mt_text; @@ -871,7 +868,7 @@ menutext_t *MC_AddBufferedText(menu_t *menu, int lhs, int rhs, int y, const char return n; } -menutext_t *MC_AddRedText(menu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign) +menutext_t *MC_AddRedText(emenu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign) { menutext_t *n; n = MC_AddWhiteText(menu, lhs, rhs, y, text, rightalign); @@ -879,7 +876,7 @@ menutext_t *MC_AddRedText(menu_t *menu, int lhs, int rhs, int y, const char *tex return n; } -menubind_t *MC_AddBind(menu_t *menu, int cx, int bx, int y, const char *caption, char *command, char *tooltip) +menubind_t *MC_AddBind(emenu_t *menu, int cx, int bx, int y, const char *caption, char *command, char *tooltip) { menubind_t *n = Z_Malloc(sizeof(*n) + strlen(caption)+1 + strlen(command)+1 + (tooltip?strlen(tooltip)+1:0)); n->common.type = mt_bind; @@ -905,7 +902,7 @@ menubind_t *MC_AddBind(menu_t *menu, int cx, int bx, int y, const char *caption, return n; } -menupicture_t *MC_AddSelectablePicture(menu_t *menu, int x, int y, int height, char *picname) +menupicture_t *MC_AddSelectablePicture(emenu_t *menu, int x, int y, int height, char *picname) { char selname[MAX_QPATH]; menupicture_t *n; @@ -934,7 +931,7 @@ menupicture_t *MC_AddSelectablePicture(menu_t *menu, int x, int y, int height, c return n; } -menupicture_t *MC_AddPicture(menu_t *menu, int x, int y, int width, int height, char *picname) +menupicture_t *MC_AddPicture(emenu_t *menu, int x, int y, int width, int height, char *picname) { menupicture_t *n; if (qrenderer == QR_NONE) @@ -957,7 +954,7 @@ menupicture_t *MC_AddPicture(menu_t *menu, int x, int y, int width, int height, return n; } -menupicture_t *MC_AddCenterPicture(menu_t *menu, int y, int height, char *picname) +menupicture_t *MC_AddCenterPicture(emenu_t *menu, int y, int height, char *picname) { int x; int width; @@ -984,7 +981,7 @@ menupicture_t *MC_AddCenterPicture(menu_t *menu, int y, int height, char *picnam return MC_AddPicture(menu, x, y, width, height, picname); } -menuoption_t *MC_AddCursorSmall(menu_t *menu, menuresel_t *reselection, int x, int y) +menuoption_t *MC_AddCursorSmall(emenu_t *menu, menuresel_t *reselection, int x, int y) { menuoption_t *n = Z_Malloc(sizeof(menucommon_t)); if (reselection) @@ -1017,7 +1014,7 @@ menuoption_t *MC_AddCursorSmall(menu_t *menu, menuresel_t *reselection, int x, i return n; } -menupicture_t *MC_AddCursor(menu_t *menu, menuresel_t *reselection, int x, int y) +menupicture_t *MC_AddCursor(emenu_t *menu, menuresel_t *reselection, int x, int y) { int i; menupicture_t *n = Z_Malloc(sizeof(menupicture_t)); @@ -1089,7 +1086,7 @@ menupicture_t *MC_AddCursor(menu_t *menu, menuresel_t *reselection, int x, int y return n; } -menuedit_t *MC_AddEdit(menu_t *menu, int cx, int ex, int y, char *text, char *def) +menuedit_t *MC_AddEdit(emenu_t *menu, int cx, int ex, int y, char *text, char *def) { menuedit_t *n = Z_Malloc(sizeof(menuedit_t)+strlen(text)+1); n->slim = false; @@ -1110,7 +1107,7 @@ menuedit_t *MC_AddEdit(menu_t *menu, int cx, int ex, int y, char *text, char *de return n; } -menuedit_t *MC_AddEditCvar(menu_t *menu, int cx, int ex, int y, char *text, char *name, qboolean isslim) +menuedit_t *MC_AddEditCvar(emenu_t *menu, int cx, int ex, int y, char *text, char *name, qboolean isslim) { menuedit_t *n = Z_Malloc(sizeof(menuedit_t)+strlen(text)+1); cvar_t *cvar; @@ -1139,7 +1136,7 @@ menuedit_t *MC_AddEditCvar(menu_t *menu, int cx, int ex, int y, char *text, char return n; } -menubox_t *MC_AddBox(menu_t *menu, int x, int y, int width, int height) +menubox_t *MC_AddBox(emenu_t *menu, int x, int y, int width, int height) { menubox_t *n = Z_Malloc(sizeof(menubox_t)); n->common.type = mt_box; @@ -1154,7 +1151,7 @@ menubox_t *MC_AddBox(menu_t *menu, int x, int y, int width, int height) return n; } -menucustom_t *MC_AddCustom(menu_t *menu, int x, int y, void *dptr, int dint, const char *tooltip) +menucustom_t *MC_AddCustom(emenu_t *menu, int x, int y, void *dptr, int dint, const char *tooltip) { menucustom_t *n = Z_Malloc(sizeof(menucustom_t) + (tooltip?strlen(tooltip)+1:0)); n->common.type = mt_custom; @@ -1170,7 +1167,7 @@ menucustom_t *MC_AddCustom(menu_t *menu, int x, int y, void *dptr, int dint, con return n; } -menucheck_t *MC_AddCheckBox(menu_t *menu, int tx, int cx, int y, const char *text, cvar_t *var, int bits) +menucheck_t *MC_AddCheckBox(emenu_t *menu, int tx, int cx, int y, const char *text, cvar_t *var, int bits) { menucheck_t *n = Z_Malloc(sizeof(menucheck_t)+strlen(text)+1); n->common.type = mt_checkbox; @@ -1200,7 +1197,7 @@ menucheck_t *MC_AddCheckBox(menu_t *menu, int tx, int cx, int y, const char *tex menu->options = (menuoption_t *)n; return n; } -menuframe_t *MC_AddFrameStart(menu_t *menu, int y) +menuframe_t *MC_AddFrameStart(emenu_t *menu, int y) { menuframe_t *n = Z_Malloc(sizeof(menuframe_t)); n->common.type = mt_framestart; @@ -1214,7 +1211,7 @@ menuframe_t *MC_AddFrameStart(menu_t *menu, int y) menu->options = (menuoption_t *)n; return n; } -menuframe_t *MC_AddFrameEnd(menu_t *menu, int y) +menuframe_t *MC_AddFrameEnd(emenu_t *menu, int y) { menuframe_t *n = Z_Malloc(sizeof(menuframe_t)); n->common.type = mt_frameend; @@ -1228,7 +1225,7 @@ menuframe_t *MC_AddFrameEnd(menu_t *menu, int y) menu->options = (menuoption_t *)n; return n; } -menucheck_t *MC_AddCheckBoxFunc(menu_t *menu, int tx, int cx, int y, const char *text, qboolean (*func) (menucheck_t *option, menu_t *menu, chk_set_t set), int bits) +menucheck_t *MC_AddCheckBoxFunc(emenu_t *menu, int tx, int cx, int y, const char *text, qboolean (*func) (menucheck_t *option, emenu_t *menu, chk_set_t set), int bits) { menucheck_t *n = Z_Malloc(sizeof(menucheck_t)+strlen(text)+1); n->common.type = mt_checkbox; @@ -1249,7 +1246,7 @@ menucheck_t *MC_AddCheckBoxFunc(menu_t *menu, int tx, int cx, int y, const char } //delta may be 0 -menuslider_t *MC_AddSlider(menu_t *menu, int tx, int sx, int y, const char *text, cvar_t *var, float min, float max, float delta) +menuslider_t *MC_AddSlider(emenu_t *menu, int tx, int sx, int y, const char *text, cvar_t *var, float min, float max, float delta) { menuslider_t *n = Z_Malloc(sizeof(menuslider_t)+strlen(text)+1); n->common.type = mt_slider; @@ -1285,7 +1282,7 @@ menuslider_t *MC_AddSlider(menu_t *menu, int tx, int sx, int y, const char *text return n; } -menucombo_t *MC_AddCombo(menu_t *menu, int tx, int cx, int y, const char *caption, const char **ops, int initialvalue) +menucombo_t *MC_AddCombo(emenu_t *menu, int tx, int cx, int y, const char *caption, const char **ops, int initialvalue) { int numopts; int optlen; @@ -1344,7 +1341,7 @@ menucombo_t *MC_AddCombo(menu_t *menu, int tx, int cx, int y, const char *captio return n; } -menucombo_t *MC_AddCvarCombo(menu_t *menu, int tx, int cx, int y, const char *caption, cvar_t *cvar, const char **ops, const char **values) +menucombo_t *MC_AddCvarCombo(emenu_t *menu, int tx, int cx, int y, const char *caption, cvar_t *cvar, const char **ops, const char **values) { int numopts; int optlen; @@ -1389,8 +1386,8 @@ menucombo_t *MC_AddCvarCombo(menu_t *menu, int tx, int cx, int y, const char *ca n->caption = optbuf; optbuf += strlen(optbuf)+1; - n->options = (const char **)newops; - n->values = (const char **)newvalues; + n->options = (char const*const*)newops; + n->values = (char const*const*)newvalues; n->cvar = cvar; // if (!(cvar->flags & CVAR_ARCHIVE)) @@ -1421,7 +1418,7 @@ menucombo_t *MC_AddCvarCombo(menu_t *menu, int tx, int cx, int y, const char *ca return n; } -menubutton_t *MC_AddConsoleCommand(menu_t *menu, int lhs, int rhs, int y, const char *text, const char *command) +menubutton_t *MC_AddConsoleCommand(emenu_t *menu, int lhs, int rhs, int y, const char *text, const char *command) { menubutton_t *n = Z_Malloc(sizeof(menubutton_t)+strlen(text)+1+strlen(command)+1); n->common.type = mt_button; @@ -1441,7 +1438,7 @@ menubutton_t *MC_AddConsoleCommand(menu_t *menu, int lhs, int rhs, int y, const return n; } -menubutton_t *MC_AddConsoleCommandQBigFont(menu_t *menu, int x, int y, const char *text, const char *command) +menubutton_t *MC_AddConsoleCommandQBigFont(emenu_t *menu, int x, int y, const char *text, const char *command) { menubutton_t *n = Z_Malloc(sizeof(menubutton_t)+strlen(text)+1+strlen(command)+1); n->common.type = mt_qbuttonbigfont; @@ -1460,7 +1457,7 @@ menubutton_t *MC_AddConsoleCommandQBigFont(menu_t *menu, int x, int y, const cha return n; } #ifdef HEXEN2 -menubutton_t *MC_AddConsoleCommandHexen2BigFont(menu_t *menu, int x, int y, const char *text, const char *command) +menubutton_t *MC_AddConsoleCommandHexen2BigFont(emenu_t *menu, int x, int y, const char *text, const char *command) { menubutton_t *n = Z_Malloc(sizeof(menubutton_t)+strlen(text)+1+strlen(command)+1); n->common.type = mt_hexen2buttonbigfont; @@ -1479,7 +1476,7 @@ menubutton_t *MC_AddConsoleCommandHexen2BigFont(menu_t *menu, int x, int y, cons return n; } #endif -menubutton_t *MC_AddCommand(menu_t *menu, int lhs, int rhs, int y, char *text, qboolean (*command) (union menuoption_s *,struct menu_s *,int)) +menubutton_t *MC_AddCommand(emenu_t *menu, int lhs, int rhs, int y, char *text, qboolean (*command) (union menuoption_s *,struct emenu_s *,int)) { menubutton_t *n = Z_Malloc(sizeof(menubutton_t)); n->common.type = mt_button; @@ -1498,7 +1495,7 @@ menubutton_t *MC_AddCommand(menu_t *menu, int lhs, int rhs, int y, char *text, q return n; } -menubutton_t *VARGS MC_AddConsoleCommandf(menu_t *menu, int lhs, int rhs, int y, int rightalign, const char *text, char *command, ...) +menubutton_t *VARGS MC_AddConsoleCommandf(emenu_t *menu, int lhs, int rhs, int y, int rightalign, const char *text, char *command, ...) { va_list argptr; static char string[1024]; @@ -1598,7 +1595,7 @@ void MC_Slider_Key(menuslider_t *option, int key) Cvar_SetValue(option->var, option->current); } -void MC_CheckBox_Key(menucheck_t *option, menu_t *menu, int key) +void MC_CheckBox_Key(menucheck_t *option, emenu_t *menu, int key) { if (key != K_ENTER && key != K_KP_ENTER && key != K_GP_START && key != K_GP_A && key != K_GP_B && key != K_LEFTARROW && key != K_KP_LEFTARROW && key != K_GP_DPAD_LEFT && key != K_RIGHTARROW && key != K_KP_LEFTARROW && key != K_GP_DPAD_RIGHT && key != K_MWHEELUP && key != K_MWHEELDOWN && key != K_MOUSE1) return; @@ -1686,61 +1683,73 @@ changed: } } -void M_AddMenu (menu_t *menu) +static qboolean menu_mousedown; +extern menu_t *menu_script; +static void M_Draw (menu_t *menu) { - menu->prev = topmenu; - if (topmenu) - topmenu->next = menu; - menu->next = NULL; - topmenu = menu; + emenu_t *m = (emenu_t*)menu; + qboolean stillactive = false; - menu->exclusive = true; -} -menu_t *M_CreateMenu (int extrasize) -{ - menu_t *menu; - menu = Z_Malloc(sizeof(menu_t)+extrasize); - menu->iszone=true; - menu->data = menu+1; - - M_AddMenu(menu); - - return menu; -} -menu_t *M_CreateMenuInfront (int extrasize) -{ - menu_t *menu; - menu = Z_Malloc(sizeof(menu_t)+extrasize); - menu->iszone=true; - menu->data = menu+1; - - M_AddMenu(menu); - menu->xpos = ((vid.width - 320)>>1); - menu->exclusive = false; - - return menu; -} -void M_HideMenu (menu_t *menu) -{ - if (menu == topmenu) + if (!Key_Dest_Has(kdm_menu)) { - topmenu = menu->prev; - if (topmenu) - topmenu->next = NULL; - menu->prev = NULL; + M_RemoveAllMenus(false); + menu_mousedown = false; + return; + } + if ((!menu_script || scr_con_current)) + { + if (m->selecteditem && m->selecteditem->common.type == mt_slider && (m->selecteditem->slider.var == &v_gamma || m->selecteditem->slider.var == &v_contrast)) + /*no menu tint if we're trying to adjust gamma*/; + else + R2D_FadeScreen (); + } + + R2D_ImageColours(1, 1, 1, 1); + + if (m) + { + M_CheckMouseMove(m); + + MenuDraw(m); + stillactive = true; + } + + if (!stillactive) + Key_Dest_Remove(kdm_menu); +} + +static qboolean M_KeyEvent(menu_t *m, qboolean isdown, unsigned int devid, int key, int unicode) +{ + emenu_t *menu = (emenu_t*)m; + if (isdown) + { + if (key == K_MOUSE1) //mouse clicks are deferred until the release event. this is for touch screens and aiming. + { + if (menu->mouseitem && menu->mouseitem->common.type == mt_frameend) + menu->mouseitem->frame.mousedown = true; + else + menu_mousedown = true; + } + else if (key == K_LSHIFT || key == K_RSHIFT || key == K_LALT || key == K_RALT || key == K_LCTRL || key == K_RCTRL) + ; //modifiers are sent on up events instead. + else + M_Complex_Key (menu, key, unicode); + return true; //eat all keys... } else { - menu_t *prev; - prev = menu->next; - if (prev) - prev->prev = menu->prev; - if (menu->prev) - menu->prev->next = menu; + if (key == K_MOUSE1 && menu_mousedown) + M_Complex_Key (menu, key, unicode); + else if (key == K_LSHIFT || key == K_RSHIFT || key == K_LALT || key == K_RALT || key == K_LCTRL || key == K_RCTRL) + M_Complex_Key (menu, key, unicode); + menu_mousedown = false; + return false; } } -void M_RemoveMenu (menu_t *menu) + +void M_Release (menu_t *m) { + emenu_t *menu = (emenu_t*)m; menuoption_t *op, *oop; if (menu->reselection) { @@ -1750,21 +1759,6 @@ void M_RemoveMenu (menu_t *menu) if (menu->remove) menu->remove(menu); - if (menu == topmenu) - { - topmenu = menu->prev; - if (topmenu) - topmenu->next = NULL; - } - else - { - menu_t *prev; - prev = menu->next; - if (prev) - prev->prev = menu->prev; - if (menu->prev) - menu->prev->next = menu; - } op = menu->options; while(op) @@ -1789,14 +1783,41 @@ void M_RemoveMenu (menu_t *menu) } } +emenu_t *M_CreateMenu (int extrasize) +{ + emenu_t *menu; + menu = Z_Malloc(sizeof(emenu_t)+extrasize); + menu->iszone=true; + menu->data = menu+1; + + menu->menu.cursor = &key_customcursor[kc_console]; + /*void (*videoreset) (struct menu_s *); //called after a video mode switch / shader reload. + void (*release) (struct menu_s *); // + qboolean (*keyevent)(struct menu_s *, qboolean isdown, unsigned int devid, int key, int unicode); //true if key was handled + qboolean (*mousemove)(struct menu_s *, qboolean abs, unsigned int devid, float x, float y); + qboolean (*joyaxis) (struct menu_s *, unsigned int devid, int axis, float val); + void (*drawmenu) (struct menu_s *); + */ + menu->menu.drawmenu = M_Draw; + menu->menu.keyevent = M_KeyEvent; + menu->menu.release = M_Release; + Menu_Push(&menu->menu, false); + + return menu; +} +void M_RemoveMenu (emenu_t *menu) +{ + Menu_Unlink((menu_t*)menu); +} + void M_ReloadMenus(void) { menu_t *m; for (m = topmenu; m; m = m->prev) { - if (m->reset) - m->reset(m); + if (m->videoreset) + m->videoreset(m); } } @@ -1807,10 +1828,10 @@ void M_RemoveAllMenus (qboolean leaveprompts) for (link = &topmenu; *link; ) { m = *link; - if ((m->persist || !m->exclusive) && leaveprompts) + if (m->persist && leaveprompts) link = &m->prev; else - M_RemoveMenu(m); + Menu_Unlink(m); } } @@ -1818,23 +1839,10 @@ void M_MenuPop_f (void) { if (!topmenu) return; - M_RemoveMenu(topmenu); + Menu_Unlink(topmenu); } -void M_Complex_Draw(void) -{ - if (!topmenu) - { - Key_Dest_Remove(kdm_emenu); - return; - } - - M_CheckMouseMove(); - - MenuDraw(topmenu); -} - -menuoption_t *M_NextItem(menu_t *m, menuoption_t *old) +menuoption_t *M_NextItem(emenu_t *m, menuoption_t *old) { menuoption_t *op = m->options; while(op->common.next) @@ -1846,7 +1854,7 @@ menuoption_t *M_NextItem(menu_t *m, menuoption_t *old) } return op; } -menuoption_t *M_NextSelectableItem(menu_t *m, menuoption_t *old) +menuoption_t *M_NextSelectableItem(emenu_t *m, menuoption_t *old) { menuoption_t *op; @@ -1877,7 +1885,7 @@ menuoption_t *M_NextSelectableItem(menu_t *m, menuoption_t *old) } } -menuoption_t *M_PrevSelectableItem(menu_t *m, menuoption_t *old) +menuoption_t *M_PrevSelectableItem(emenu_t *m, menuoption_t *old) { menuoption_t *op; @@ -1904,13 +1912,12 @@ menuoption_t *M_PrevSelectableItem(menu_t *m, menuoption_t *old) } } -void M_Complex_Key(int key, int unicode) +void M_Complex_Key(emenu_t *currentmenu, int key, int unicode) { - menu_t *currentmenu = topmenu; if (!currentmenu) return; //erm... - M_CheckMouseMove(); + M_CheckMouseMove(currentmenu); if (currentmenu->key) if (currentmenu->key(key, currentmenu)) @@ -2095,8 +2102,7 @@ void M_Complex_Key(int key, int unicode) -extern int m_save_demonum; -qboolean MC_Main_Key (int key, menu_t *menu) //here purly to restart demos. +qboolean MC_Main_Key (int key, emenu_t *menu) //here purly to restart demos. { if (key == K_ESCAPE || key == K_GP_BACK || key == K_MOUSE2) { @@ -2106,14 +2112,11 @@ qboolean MC_Main_Key (int key, menu_t *menu) //here purly to restart demos. if (con_stayhidden.ival && cls.state == ca_disconnected) if (!CL_TryingToConnect()) return true; - - Key_Dest_Remove(kdm_emenu); - return true; } return false; } -static int M_Main_AddExtraOptions(menu_t *mainm, int y) +static int M_Main_AddExtraOptions(emenu_t *mainm, int y) { if (Cmd_AliasExist("mod_menu", RESTRICT_LOCAL)) {MC_AddConsoleCommandQBigFont(mainm, 72, y, va("%-14s", Cvar_Get("mod_menu", "Mod Menu", 0, NULL)->string), "mod_menu\n"); y += 20;} @@ -2142,7 +2145,7 @@ void M_Menu_Main_f (void) { extern cvar_t m_helpismedia; menubutton_t *b; - menu_t *mainm = NULL; + emenu_t *mainm = NULL; mpic_t *p; static menuresel_t resel; int y; @@ -2198,7 +2201,6 @@ void M_Menu_Main_f (void) if (R_GetShaderSizes(R2D_SafeCachePic("pics/m_main_quit"), NULL, NULL, true) > 0) { int itemheight = 32; - Key_Dest_Add(kdm_emenu); mainm = M_CreateMenu(0); mainm->key = MC_Main_Key; @@ -2251,7 +2253,6 @@ void M_Menu_Main_f (void) p = R2D_SafeCachePic("gfx/menu/title0.lmp"); if (R_GetShaderSizes(p, NULL, NULL, true) > 0) { - Key_Dest_Add(kdm_emenu); mainm = M_CreateMenu(0); mainm->key = MC_Main_Key; @@ -2293,7 +2294,6 @@ void M_Menu_Main_f (void) p = R2D_SafeCachePic("gfx/ttl_main.lmp"); if (R_GetShaderSizes(p, NULL, NULL, true) > 0) { - Key_Dest_Add(kdm_emenu); mainm = M_CreateMenu(0); mainm->key = MC_Main_Key; MC_AddPicture(mainm, 16, 4, 32, 144, "gfx/qplaque.lmp"); @@ -2328,7 +2328,6 @@ void M_Menu_Main_f (void) R2D_SafeCachePic("gfx/ttl_main.lmp"); if (R_GetShaderSizes(p, &width, NULL, true) > 0) { - Key_Dest_Add(kdm_emenu); mainm = M_CreateMenu(0); mainm->key = MC_Main_Key; @@ -2379,7 +2378,6 @@ void M_Menu_Main_f (void) if (!mainm) { - Key_Dest_Add(kdm_emenu); mainm = M_CreateMenu(0); MC_AddRedText(mainm, 16, 170, 0, "MAIN MENU", false); @@ -2398,7 +2396,7 @@ void M_Menu_Main_f (void) M_Menu_Preset_f(); } -int MC_AddBulk(struct menu_s *menu, menuresel_t *resel, menubulk_t *bulk, int xstart, int xtextend, int y) +int MC_AddBulk(struct emenu_s *menu, menuresel_t *resel, menubulk_t *bulk, int xstart, int xtextend, int y) { int selectedy = y; menuoption_t *selected = NULL; diff --git a/engine/client/m_master.c b/engine/client/m_master.c index 38f37c928..e8829e2ad 100644 --- a/engine/client/m_master.c +++ b/engine/client/m_master.c @@ -32,7 +32,7 @@ static int serverpreview; extern cvar_t slist_writeserverstxt; extern cvar_t slist_cacheinfo; -static void CalcFilters(menu_t *menu); +static void CalcFilters(emenu_t *menu); void M_Serverlist_Init(void) { @@ -104,7 +104,7 @@ static void SL_DrawColumnTitle (int *x, int y, int xlen, int mx, char *str, qboo *x -= xlen + 8; } -static void SL_TitlesDraw (int x, int y, menucustom_t *ths, menu_t *menu) +static void SL_TitlesDraw (int x, int y, menucustom_t *ths, emenu_t *menu) { int sf = Master_GetSortField(); int mx = mousecursor_x; @@ -128,7 +128,7 @@ static void SL_TitlesDraw (int x, int y, menucustom_t *ths, menu_t *menu) SL_DrawColumnTitle(NULL, y, x, mx, "hostname ", (sf==SLKEY_NAME), clr, &filldraw); } -static qboolean SL_TitlesKey (menucustom_t *ths, menu_t *menu, int key, unsigned int unicode) +static qboolean SL_TitlesKey (menucustom_t *ths, emenu_t *menu, int key, unsigned int unicode) { int x; int mx = mousecursor_x/8; @@ -255,7 +255,7 @@ static servertypes_t flagstoservertype(int flags) } } -static void SL_ServerDraw (int x, int y, menucustom_t *ths, menu_t *menu) +static void SL_ServerDraw (int x, int y, menucustom_t *ths, emenu_t *menu) { serverlist_t *info = (serverlist_t*)(menu + 1); serverinfo_t *si; @@ -305,7 +305,7 @@ static void SL_ServerDraw (int x, int y, menucustom_t *ths, menu_t *menu) } } void MC_EditBox_Key(menuedit_t *edit, int key, unsigned int unicode); -static qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key, unsigned int unicode) +static qboolean SL_ServerKey (menucustom_t *ths, emenu_t *menu, int key, unsigned int unicode) { static int lastclick; int curtime; @@ -375,7 +375,7 @@ static qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key, unsigned } return false; } -static void SL_PreDraw (menu_t *menu) +static void SL_PreDraw (emenu_t *menu) { serverlist_t *info = (serverlist_t*)(menu + 1); Master_CheckPollSockets(); @@ -409,7 +409,7 @@ static void SL_PreDraw (menu_t *menu) snprintf(info->refreshtext, sizeof(info->refreshtext), "Refresh - %u/%u/%u\n", info->numslots, Master_NumAlive(), Master_TotalCount()); } qboolean NET_SendPollPacket(int len, void *data, netadr_t to); -static void SL_PostDraw (menu_t *menu) +static void SL_PostDraw (emenu_t *menu) { static char *helpstrings[] = { @@ -725,7 +725,7 @@ static void SL_PostDraw (menu_t *menu) } } } -static qboolean SL_Key (int key, menu_t *menu) +static qboolean SL_Key (int key, emenu_t *menu) { serverlist_t *info = (serverlist_t*)(menu + 1); @@ -916,7 +916,7 @@ dojoin: return true; } -static void SL_ServerPlayer (int x, int y, menucustom_t *ths, menu_t *menu) +static void SL_ServerPlayer (int x, int y, menucustom_t *ths, emenu_t *menu) { if (selectedserver.inuse) { @@ -941,7 +941,7 @@ static void SL_ServerPlayer (int x, int y, menucustom_t *ths, menu_t *menu) } } -static void SL_SliderDraw (int x, int y, menucustom_t *ths, menu_t *menu) +static void SL_SliderDraw (int x, int y, menucustom_t *ths, emenu_t *menu) { extern qboolean keydown[K_MAX]; serverlist_t *info = (serverlist_t*)(menu + 1); @@ -1013,7 +1013,7 @@ static void SL_SliderDraw (int x, int y, menucustom_t *ths, menu_t *menu) info->sliderpressed = false; } } -static qboolean SL_SliderKey (menucustom_t *ths, menu_t *menu, int key, unsigned int unicode) +static qboolean SL_SliderKey (menucustom_t *ths, emenu_t *menu, int key, unsigned int unicode) { if (key == K_MOUSE1) { @@ -1043,7 +1043,7 @@ static qboolean SL_SliderKey (menucustom_t *ths, menu_t *menu, int key, unsigned return false; } -static void CalcFilters(menu_t *menu) +static void CalcFilters(emenu_t *menu) { serverlist_t *info = (serverlist_t*)(menu + 1); info->filtermodcount = sb_filtertext.modified; @@ -1070,7 +1070,7 @@ static void CalcFilters(menu_t *menu) Master_SortServers(); } -static qboolean SL_ReFilter (menucheck_t *option, menu_t *menu, chk_set_t set) +static qboolean SL_ReFilter (menucheck_t *option, emenu_t *menu, chk_set_t set) { serverlist_t *info = (serverlist_t*)(menu + 1); switch(set) @@ -1097,7 +1097,7 @@ static qboolean SL_ReFilter (menucheck_t *option, menu_t *menu, chk_set_t set) return true; } -static void SL_Remove (menu_t *menu) +static void SL_Remove (emenu_t *menu) { serverlist_t *info = (serverlist_t*)(menu + 1); @@ -1108,7 +1108,7 @@ static void SL_Remove (menu_t *menu) Cvar_Set(&sb_hidefull, info->filter[7]?"1":"0"); } -static qboolean SL_DoRefresh (menuoption_t *opt, menu_t *menu, int key) +static qboolean SL_DoRefresh (menuoption_t *opt, emenu_t *menu, int key) { if (key == K_MOUSE1 || key == K_MOUSE1 || key == K_ENTER || key == K_KP_ENTER) { @@ -1122,7 +1122,7 @@ static qboolean SL_DoRefresh (menuoption_t *opt, menu_t *menu, int key) void M_Menu_ServerList2_f(void) { int i, y, x; - menu_t *menu; + emenu_t *menu; menucustom_t *cust; serverlist_t *info; qboolean descending; @@ -1138,7 +1138,6 @@ void M_Menu_ServerList2_f(void) serverpreview = false; //in case it was lingering. Key_Dest_Remove(kdm_console); - Key_Dest_Add(kdm_emenu); menu = M_CreateMenu(sizeof(serverlist_t)); menu->predraw = SL_PreDraw; @@ -1262,7 +1261,7 @@ void M_Menu_ServerList2_f(void) static float quickconnecttimeout; -static void M_QuickConnect_PreDraw(menu_t *menu) +static void M_QuickConnect_PreDraw(emenu_t *menu) { serverinfo_t *best = NULL; serverinfo_t *s; @@ -1318,21 +1317,21 @@ static void M_QuickConnect_PreDraw(menu_t *menu) } } -static qboolean M_QuickConnect_Key (int key, menu_t *menu) +static qboolean M_QuickConnect_Key (int key, emenu_t *menu) { return false; } -static void M_QuickConnect_Remove (menu_t *menu) +static void M_QuickConnect_Remove (emenu_t *menu) { } -static qboolean M_QuickConnect_Cancel (menuoption_t *opt, menu_t *menu, int key) +static qboolean M_QuickConnect_Cancel (menuoption_t *opt, emenu_t *menu, int key) { return false; } -static void M_QuickConnect_DrawStatus (int x, int y, menucustom_t *ths, menu_t *menu) +static void M_QuickConnect_DrawStatus (int x, int y, menucustom_t *ths, emenu_t *menu) { Draw_FunString(x, y, va("Polling, %i secs\n", (int)(quickconnecttimeout - Sys_DoubleTime() + 0.9))); } @@ -1340,9 +1339,7 @@ static void M_QuickConnect_DrawStatus (int x, int y, menucustom_t *ths, menu_t * void M_QuickConnect_f(void) { menucustom_t *cust; - menu_t *menu; - - Key_Dest_Add(kdm_emenu); + emenu_t *menu; MasterInfo_Refresh(false); isrefreshing = true; diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 5663f409e..ae52da0d9 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -128,7 +128,6 @@ cvar_t media_hijackwinamp = CVAR("media_hijackwinamp", "0"); #endif int selectedoption=-1; -static int mouseselectedoption=-1; int numtracks; int nexttrack=-1; mediatrack_t *tracks; @@ -136,6 +135,7 @@ mediatrack_t *tracks; char media_iofilename[MAX_OSPATH]=""; #if !defined(NOMEDIAMENU) && !defined(NOBUILTINMENUS) +static int mouseselectedoption=-1; void Media_LoadTrackNames (char *listname); void Media_SaveTrackNames (char *listname); int loadedtracknames; @@ -920,6 +920,8 @@ void Media_RemoveTrack(const char *fname) } } } + +#if !defined(NOMEDIAMENU) && !defined(NOBUILTINMENUS) void M_Media_Add_f (void) { char *fname = Cmd_Argv(1); @@ -947,8 +949,6 @@ void M_Media_Remove_f (void) } -#if !defined(NOMEDIAMENU) && !defined(NOBUILTINMENUS) - void Media_LoadTrackNames (char *listname); #define MEDIA_MIN -7 @@ -960,7 +960,7 @@ void Media_LoadTrackNames (char *listname); #define MEDIA_SHUFFLE -2 #define MEDIA_REPEAT -1 -void M_Media_Draw (menu_t *menu) +void M_Media_Draw (emenu_t *menu) { mediatrack_t *track; int y; @@ -1145,7 +1145,7 @@ void Com_CompleateOSFileName(char *name) strcpy(name, compleatenamename); } -qboolean M_Media_Key (int key, menu_t *menu) +qboolean M_Media_Key (int key, emenu_t *menu) { int dir; if (key == K_ESCAPE || key == K_GP_BACK || key == K_MOUSE2) @@ -1347,11 +1347,10 @@ qboolean M_Media_Key (int key, menu_t *menu) void M_Menu_Media_f (void) { - menu_t *menu; + emenu_t *menu; if (!loadedtracknames) Media_LoadTrackNames("sound/media.m3u"); - Key_Dest_Add(kdm_emenu); menu = M_CreateMenu(0); // MC_AddPicture(menu, 16, 4, 32, 144, "gfx/qplaque.lmp"); @@ -1668,7 +1667,8 @@ struct cin_s qbyte *framedata; //Z_Malloced buffer }; -shader_t *videoshader; +static menu_t videomenu; //to capture keys+draws+etc. a singleton - multiple videos will be queued instead of simultaneous. +static shader_t *videoshader; ////////////////////////////////////////////////////////////////////////////////// //AVI Support (windows) @@ -2412,11 +2412,6 @@ static cin_t *Media_Cin_TryLoad(char *name) //Quake2 CIN Support ////////////////////////////////////////////////////////////////////////////////// -qboolean Media_PlayingFullScreen(void) -{ - return videoshader!=NULL; -} - void Media_ShutdownCin(cin_t *cin) { if (!cin) @@ -2473,12 +2468,75 @@ cin_t *Media_StartCin(char *name) return cin; } -struct pendingfilms_s +static struct pendingfilms_s { struct pendingfilms_s *next; char name[1]; } *pendingfilms; -qboolean Media_BeginNextFilm(void) + +static void MediaView_DrawFilm(menu_t *m) +{ + if (videoshader) + { + cin_t *cin = R_ShaderGetCinematic(videoshader); + if (cin && cin->playstate == CINSTATE_INVALID) + Media_SetState(cin, CINSTATE_PLAY); //err... wot? must have vid_reloaded or something + if (cin && cin->playstate == CINSTATE_ENDED) + Media_StopFilm(false); + else if (cin) + { + int cw, ch; + float aspect; + if (cin->cursormove) + cin->cursormove(cin, mousecursor_x/(float)vid.width, mousecursor_y/(float)vid.height); + if (cin->setsize) + cin->setsize(cin, vid.pixelwidth, vid.pixelheight); + + //FIXME: should have a proper aspect ratio setting. RoQ files are always power of two, which makes things ugly. + if (cin->getsize) + cin->getsize(cin, &cw, &ch, &aspect); + else + { + cw = 4; + ch = 3; + } + + R2D_Letterbox(0, 0, vid.fbvwidth, vid.fbvheight, videoshader, cw, ch); + + SCR_SetUpToDrawConsole(); + if (scr_con_current) + SCR_DrawConsole (false); + } + } + else if (!videoshader) + Menu_Unlink(m); +} +static qboolean MediaView_KeyEvent(menu_t *m, qboolean isdown, unsigned int devid, int key, int unicode) +{ + if (isdown && key == K_ESCAPE) + { + Media_StopFilm(false); //skip to the next. + return true; + } + Media_Send_KeyEvent(NULL, key, unicode, !isdown); + return true; +} +static qboolean MediaView_MouseMove(menu_t *m, qboolean isabs, unsigned int devid, float x, float y) +{ + cin_t *cin; + cin = R_ShaderGetCinematic(videoshader); + if (!cin || !cin->cursormove) + return false; + if (isabs) + cin->cursormove(cin, x, y); + return true; +} +static void MediaView_StopFilm(menu_t *m) +{ //display is going away for some reason. might as well kill them all + Media_StopFilm(true); +} + +static qboolean Media_BeginNextFilm(void) { cin_t *cin; char sname[MAX_QPATH]; @@ -2513,6 +2571,19 @@ qboolean Media_BeginNextFilm(void) videoshader = NULL; } Z_Free(p); + + if (videoshader) + { + videomenu.cursor = NULL; + videomenu.release = MediaView_StopFilm; + videomenu.drawmenu = MediaView_DrawFilm; + videomenu.mousemove = MediaView_MouseMove; + videomenu.keyevent = MediaView_KeyEvent; + videomenu.isopaque = true; + Menu_Push(&videomenu, false); + } + else + Menu_Unlink(&videomenu); return !!videoshader; } qboolean Media_StopFilm(qboolean all) @@ -2580,12 +2651,6 @@ qboolean Media_PlayFilm(char *name, qboolean enqueue) #endif SCR_EndLoadingPlaque(); - if (Key_Dest_Has(kdm_emenu)) - Key_Dest_Remove(kdm_emenu); -#ifdef MENU_DAT - if (Key_Dest_Has(kdm_gmenu)) - MP_Toggle(0); -#endif if (!Key_Dest_Has(kdm_console)) scr_con_current=0; return true; @@ -2593,45 +2658,6 @@ qboolean Media_PlayFilm(char *name, qboolean enqueue) else return false; } -qboolean Media_ShowFilm(void) -{ - if (videoshader) - { - cin_t *cin = R_ShaderGetCinematic(videoshader); - if (cin && cin->playstate == CINSTATE_INVALID) - Media_SetState(cin, CINSTATE_PLAY); //err... wot? must have vid_reloaded or something - if (cin && cin->playstate == CINSTATE_ENDED) - { - Media_StopFilm(false); - } - else if (cin) - { - int cw, ch; - float aspect; - if (cin->cursormove) - cin->cursormove(cin, mousecursor_x/(float)vid.width, mousecursor_y/(float)vid.height); - if (cin->setsize) - cin->setsize(cin, vid.pixelwidth, vid.pixelheight); - - //FIXME: should have a proper aspect ratio setting. RoQ files are always power of two, which makes things ugly. - if (cin->getsize) - cin->getsize(cin, &cw, &ch, &aspect); - else - { - cw = 4; - ch = 3; - } - - R2D_Letterbox(0, 0, vid.fbvwidth, vid.fbvheight, videoshader, cw, ch); - - SCR_SetUpToDrawConsole(); - if (scr_con_current) - SCR_DrawConsole (false); - return true; - } - } - return false; -} #ifndef SERVERONLY void QDECL Media_UpdateTexture(void *ctx, uploadfmt_t fmt, int width, int height, void *data, void *palette) @@ -2852,8 +2878,6 @@ void Media_PlayVideoWindowed_f (void) Con_SetActive(con); } -#else -qboolean Media_ShowFilm(void){return false;} #endif //HAVE_MEDIA_DECODER @@ -4116,12 +4140,9 @@ void Media_RecordDemo_f(void) //FIXME: make sure it loaded okay Media_RecordFilm(videoname, true); scr_con_current=0; - Key_Dest_Remove(kdm_console|kdm_emenu); -#ifdef MENU_DAT - if (Key_Dest_Has(kdm_gmenu)) - MP_Toggle(0); -#endif + Menu_PopAll(); + Key_Dest_Remove(kdm_console); if (!currentcapture_funcs) CL_Stopdemo_f(); //capturing failed for some reason @@ -5123,9 +5144,9 @@ void Media_Init(void) #endif Cvar_Register(&media_shuffle, "Media player things"); Cvar_Register(&media_repeat, "Media player things"); - Cmd_AddCommand ("media_add", M_Media_Add_f); - Cmd_AddCommand ("media_remove", M_Media_Remove_f); #if !defined(NOMEDIAMENU) && !defined(NOBUILTINMENUS) + Cmd_AddCommand ("media_add", M_Media_Add_f); + Cmd_AddCommand ("media_remove", M_Media_Remove_f); Cmd_AddCommand ("menu_media", M_Menu_Media_f); #endif #endif diff --git a/engine/client/m_multi.c b/engine/client/m_multi.c index 2a960e16b..08ea4d188 100644 --- a/engine/client/m_multi.c +++ b/engine/client/m_multi.c @@ -12,13 +12,12 @@ extern cvar_t maxclients; void M_Menu_MultiPlayer_f (void) { menubutton_t *b; - menu_t *menu; + emenu_t *menu; mpic_t *p; int mgt; static menuresel_t resel; p = NULL; - Key_Dest_Add(kdm_emenu); mgt = M_GameType(); @@ -133,7 +132,7 @@ typedef struct { int tiwidth, tiheight; qbyte translationimage[128*128]; } setupmenu_t; -qboolean ApplySetupMenu (union menuoption_s *option,struct menu_s *menu, int key) +qboolean ApplySetupMenu (union menuoption_s *option,struct emenu_s *menu, int key) { char bot[64], top[64]; setupmenu_t *info = menu->data; @@ -218,7 +217,7 @@ static unsigned int hsvtorgb(float inh, float s, float v) return 0xff000000 | (r<<16)|(g<<8)|(b<<0); }; -qboolean SetupMenuColour (union menuoption_s *option,struct menu_s *menu, int key) +qboolean SetupMenuColour (union menuoption_s *option,struct emenu_s *menu, int key) { extern qboolean keydown[K_MAX]; setupmenu_t *info = menu->data; @@ -312,7 +311,7 @@ void q2skin_destroy(q2skinsearch_t *s) BZ_Free(s); } -qboolean MSetupQ2_ChangeSkin (struct menucustom_s *option,struct menu_s *menu, int key, unsigned int unicode) +qboolean MSetupQ2_ChangeSkin (struct menucustom_s *option,struct emenu_s *menu, int key, unsigned int unicode) { setupmenu_t *info = menu->data; q2skinsearch_t *s = Z_Malloc(sizeof(*s)); @@ -340,7 +339,7 @@ qboolean MSetupQ2_ChangeSkin (struct menucustom_s *option,struct menu_s *menu, i q2skin_destroy(s); return true; } -void MSetupQ2_TransDraw (int x, int y, menucustom_t *option, menu_t *menu) +void MSetupQ2_TransDraw (int x, int y, menucustom_t *option, emenu_t *menu) { setupmenu_t *info = menu->data; mpic_t *p; @@ -364,7 +363,7 @@ void MSetupQ2_TransDraw (int x, int y, menucustom_t *option, menu_t *menu) R2D_ScalePic (x, y-8, w, h, p); } -void MSetup_TransDraw (int x, int y, menucustom_t *option, menu_t *menu) +void MSetup_TransDraw (int x, int y, menucustom_t *option, emenu_t *menu) { unsigned int translationTable[256]; setupmenu_t *info = menu->data; @@ -431,7 +430,7 @@ void MSetup_TransDraw (int x, int y, menucustom_t *option, menu_t *menu) void M_Menu_Setup_f (void) { setupmenu_t *info; - menu_t *menu; + emenu_t *menu; menucustom_t *ci; menubutton_t *b; static menuresel_t resel; @@ -446,7 +445,6 @@ void M_Menu_Setup_f (void) NULL }; menucustom_t *cu; - Key_Dest_Add(kdm_emenu); menu = M_CreateMenu(sizeof(setupmenu_t)); info = menu->data; @@ -470,8 +468,6 @@ void M_Menu_Setup_f (void) } #endif - Key_Dest_Add(kdm_emenu); - menu = M_CreateMenu(sizeof(setupmenu_t)); info = menu->data; @@ -563,7 +559,7 @@ static const char *numplayeroptions[] = { NULL }; -qboolean MultiBeginGame (union menuoption_s *option,struct menu_s *menu, int key) +qboolean MultiBeginGame (union menuoption_s *option,struct emenu_s *menu, int key) { newmultimenu_t *info = menu->data; if (key != K_ENTER && key != K_KP_ENTER && key != K_GP_START && key != K_MOUSE1) @@ -652,13 +648,11 @@ void M_Menu_GameOptions_f (void) NULL }; newmultimenu_t *info; - menu_t *menu; + emenu_t *menu; int y = 40; int mgt; int players; - Key_Dest_Add(kdm_emenu); - menu = M_CreateMenu(sizeof(newmultimenu_t)); info = menu->data; @@ -757,13 +751,12 @@ void M_Menu_Teamplay_f (void) MB_END() }; static menuresel_t resel; - menu_t *menu = M_Options_Title(&y, 0); + emenu_t *menu = M_Options_Title(&y, 0); MC_AddBulk(menu, &resel, bulk, 16, 200, y); } void M_Menu_Teamplay_Locations_f (void) { - menu_t *menu; int y; menubulk_t bulk[] = { @@ -792,13 +785,12 @@ void M_Menu_Teamplay_Locations_f (void) MB_END() }; static menuresel_t resel; - menu = M_Options_Title(&y, 0); + emenu_t *menu = M_Options_Title(&y, 0); MC_AddBulk(menu, &resel, bulk, 16, 200, y); } void M_Menu_Teamplay_Needs_f (void) { - menu_t *menu; int y; menubulk_t bulk[] = { @@ -819,13 +811,12 @@ void M_Menu_Teamplay_Needs_f (void) MB_END() }; static menuresel_t resel; - menu = M_Options_Title(&y, 0); + emenu_t *menu = M_Options_Title(&y, 0); MC_AddBulk(menu, &resel, bulk, 16, 200, y); } void M_Menu_Teamplay_Items_f (void) { - menu_t *menu; int y; menubulk_t bulk[] = { @@ -840,13 +831,12 @@ void M_Menu_Teamplay_Items_f (void) MB_END() }; static menuresel_t resel; - menu = M_Options_Title(&y, 0); + emenu_t *menu = M_Options_Title(&y, 0); MC_AddBulk(menu, &resel, bulk, 16, 224, y); } void M_Menu_Teamplay_Items_Armor_f (void) { - menu_t *menu; int y; menubulk_t bulk[] = { @@ -863,13 +853,12 @@ void M_Menu_Teamplay_Items_Armor_f (void) MB_END() }; static menuresel_t resel; - menu = M_Options_Title(&y, 0); + emenu_t *menu = M_Options_Title(&y, 0); MC_AddBulk(menu, &resel, bulk, 16, 200, y); } void M_Menu_Teamplay_Items_Weapons_f (void) { - menu_t *menu; int y; menubulk_t bulk[] = { @@ -888,13 +877,12 @@ void M_Menu_Teamplay_Items_Weapons_f (void) MB_END() }; static menuresel_t resel; - menu = M_Options_Title(&y, 0); + emenu_t *menu = M_Options_Title(&y, 0); MC_AddBulk(menu, &resel, bulk, 16, 200, y); } void M_Menu_Teamplay_Items_Powerups_f (void) { - menu_t *menu; int y; menubulk_t bulk[] = { @@ -916,13 +904,12 @@ void M_Menu_Teamplay_Items_Powerups_f (void) MB_END() }; static menuresel_t resel; - menu = M_Options_Title(&y, 0); + emenu_t *menu = M_Options_Title(&y, 0); MC_AddBulk(menu, &resel, bulk, 16, 200, y); } void M_Menu_Teamplay_Items_Ammo_Health_f (void) { - menu_t *menu; int y; menubulk_t bulk[] = { @@ -939,13 +926,12 @@ void M_Menu_Teamplay_Items_Ammo_Health_f (void) MB_END() }; static menuresel_t resel; - menu = M_Options_Title(&y, 0); + emenu_t *menu = M_Options_Title(&y, 0); MC_AddBulk(menu, &resel, bulk, 16, 200, y); } void M_Menu_Teamplay_Items_Team_Fortress_f (void) { - menu_t *menu; int y; menubulk_t bulk[] = { @@ -957,13 +943,12 @@ void M_Menu_Teamplay_Items_Team_Fortress_f (void) MB_END() }; static menuresel_t resel; - menu = M_Options_Title(&y, 0); + emenu_t *menu = M_Options_Title(&y, 0); MC_AddBulk(menu, &resel, bulk, 16, 200, y); } void M_Menu_Teamplay_Items_Status_Location_Misc_f (void) { - menu_t *menu; int y; menubulk_t bulk[] = { @@ -985,7 +970,7 @@ void M_Menu_Teamplay_Items_Status_Location_Misc_f (void) MB_END() }; static menuresel_t resel; - menu = M_Options_Title(&y, 0); + emenu_t *menu = M_Options_Title(&y, 0); MC_AddBulk(menu, &resel, bulk, 16, 200, y); } @@ -1026,7 +1011,6 @@ void M_Menu_Network_f (void) static const char *smoothingvalues[] = {"0", "1", "2", NULL}; extern cvar_t cl_download_csprogs, cl_download_redirection, requiredownloads, cl_solid_players; extern cvar_t cl_predict_players, cl_predict_smooth, cl_predict_extrapolate; - menu_t *menu; static menuresel_t resel; int y; menubulk_t bulk[] = @@ -1050,7 +1034,7 @@ void M_Menu_Network_f (void) #endif MB_END() }; - menu = M_Options_Title(&y, 0); + emenu_t *menu = M_Options_Title(&y, 0); MC_AddBulk(menu, &resel, bulk, 16, 200, y); } #endif diff --git a/engine/client/m_native.c b/engine/client/m_native.c index 5946312c8..b69ce5949 100644 --- a/engine/client/m_native.c +++ b/engine/client/m_native.c @@ -8,6 +8,55 @@ extern unsigned int r2d_be_flags; #include "shader.h" #include "cl_master.h" +//static void MN_Menu_VideoReset(struct menu_s *m); +//static void MN_Menu_Released(struct menu_s *m); +static qboolean MN_Menu_KeyEvent(struct menu_s *m, qboolean isdown, unsigned int devid, int key, int unicode) +{ + if (mn_entry && mn_entry->InputEvent) + { + void *nctx = (m->ctx==libmenu)?NULL:m->ctx; + struct menu_inputevent_args_s ev = {isdown?MIE_KEYDOWN:MIE_KEYUP, devid}; + ev.key.scancode = key; + ev.key.charcode = unicode; + return mn_entry->InputEvent(nctx, ev); + } + return false; +} +static qboolean MN_Menu_MouseMove(struct menu_s *m, qboolean abs, unsigned int devid, float x, float y) +{ + if (mn_entry && mn_entry->InputEvent) + { + void *nctx = (m->ctx==libmenu)?NULL:m->ctx; + struct menu_inputevent_args_s ev = {abs?MIE_MOUSEABS:MIE_MOUSEDELTA, devid}; + ev.mouse.delta[0] = x; + ev.mouse.delta[1] = y; + ev.mouse.screen[0] = mousecursor_x; + ev.mouse.screen[1] = mousecursor_y; + return mn_entry->InputEvent(nctx, ev); + } + return false; +} +static qboolean MN_Menu_JoyAxis(struct menu_s *m, unsigned int devid, int axis, float val) +{ + if (mn_entry && mn_entry->InputEvent) + { + void *nctx = (m->ctx==libmenu)?NULL:m->ctx; + struct menu_inputevent_args_s ev = {MIE_JOYAXIS, devid}; + ev.axis.axis = axis; + ev.axis.val = val; + return mn_entry->InputEvent(nctx, ev); + } + return false; +} +static void MN_Menu_DrawMenu(struct menu_s *m) +{ + void *nctx = (m->ctx==libmenu)?NULL:m->ctx; + if (mn_entry && mn_entry->Draw) + mn_entry->Draw(nctx, host_frametime); + else + Menu_Unlink(m); +} + static int MN_CheckExtension(const char *extname) { unsigned int i; @@ -149,42 +198,60 @@ static void MN_DrawResetClipArea(void) R2D_Flush(); BE_Scissor(NULL); } -static qboolean MN_SetKeyDest(qboolean focused) +static void MN_PushMenu(void *ctx) { - qboolean ret = Key_Dest_Has(kdm_nmenu); - if (ret == focused) - return false; - if (focused) - { - if (key_dest_absolutemouse & kdm_nmenu) - { //we're activating the mouse cursor now... make sure the position is actually current. - //FIXME: we should probably get the input code to do this for us when switching cursor modes. - struct menu_inputevent_args_s ev = {MIE_MOUSEABS, -1}; - ev.mouse.screen[0] = (mousecursor_x * vid.width) / vid.pixelwidth; - ev.mouse.screen[1] = (mousecursor_y * vid.height) / vid.pixelheight; - mn_entry->InputEvent(ev); - } - Key_Dest_Add(kdm_nmenu); + menu_t *m; + if (!ctx) + ctx = libmenu; //to match kill + m = Menu_FindContext(ctx); + if (!m) + { //not created yet. + m = Z_Malloc(sizeof(*m)); + m->ctx = ctx; + +// m->videoreset = MN_Menu_VideoReset; +// m->release = MN_Menu_Released; + m->keyevent = MN_Menu_KeyEvent; + m->mousemove = MN_Menu_MouseMove; + m->joyaxis = MN_Menu_JoyAxis; + m->drawmenu = MN_Menu_DrawMenu; + } + m->cursor = &key_customcursor[kc_nativemenu]; + Menu_Push(m, false); + + if (ctx == libmenu) + ctx = NULL; + if (m->cursor) + { //we're activating the mouse cursor now... make sure the position is actually current. + //FIXME: we should probably get the input code to do this for us when switching cursor modes. + struct menu_inputevent_args_s ev = {MIE_MOUSEABS, -1}; + ev.mouse.screen[0] = mousecursor_x; + ev.mouse.screen[1] = mousecursor_y; + mn_entry->InputEvent(ctx, ev); } - else - Key_Dest_Remove(kdm_nmenu); - return true; } -static int MN_GetKeyDest(void) +static qboolean MN_IsMenuPushed(void *ctx) { - if (Key_Dest_Has(kdm_nmenu)) - { - if (Key_Dest_Has_Higher(kdm_nmenu)) - return -1; - return 1; - } - return 0; + menu_t *m; + if (!ctx) + ctx = libmenu; //to match kill + m = Menu_FindContext(ctx); + return !!m; +} +static void MN_KillMenu(void *ctx) +{ + menu_t *m; + if (!ctx) + ctx = libmenu; //don't allow null contexts, because that screws up any other menus. + m = Menu_FindContext(ctx); + if (m) + Menu_Unlink(m); } static int MN_SetMouseTarget(const char *cursorname, float hot_x, float hot_y, float scale) { if (cursorname) { - struct key_cursor_s *m = &key_customcursor[kc_nmenu]; + struct key_cursor_s *m = &key_customcursor[kc_nativemenu]; if (scale <= 0) scale = 1; if (!strcmp(m->name, cursorname) || m->hotspot[0] != hot_x || m->hotspot[1] != hot_y || m->scale != scale) @@ -195,10 +262,7 @@ static int MN_SetMouseTarget(const char *cursorname, float hot_x, float hot_y, f m->scale = scale; m->dirty = true; } - key_dest_absolutemouse |= kdm_nmenu; } - else - key_dest_absolutemouse &= ~kdm_nmenu; return true; } @@ -300,7 +364,6 @@ static void MN_RenderScene(menuscene_t *scene) void MN_Shutdown(void) { - Key_Dest_Remove(kdm_nmenu); if (mn_entry) { mn_entry->Shutdown(MI_INIT); @@ -367,8 +430,9 @@ qboolean MN_Init(void) MN_RenderScene, // Menu specific stuff - MN_SetKeyDest, - MN_GetKeyDest, + MN_PushMenu, + MN_IsMenuPushed, + MN_KillMenu, MN_SetMouseTarget, Key_KeynumToString, Key_StringToKeynum, @@ -420,8 +484,6 @@ qboolean MN_Init(void) { imports.engine_version = version_string(); - key_dest_absolutemouse |= kdm_nmenu; - mn_entry = pGetMenuAPI (&imports); if (mn_entry && mn_entry->api_version >= NATIVEMENU_API_VERSION_MIN && mn_entry->api_version <= NATIVEMENU_API_VERSION_MAX) { diff --git a/engine/client/m_options.c b/engine/client/m_options.c index baa858ad9..840169ec6 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -110,13 +110,11 @@ qboolean M_Vid_GetMode(qboolean forfullscreen, int num, int *w, int *h) extern qboolean forcesaveprompt; extern cvar_t pr_debugger; -menu_t *M_Options_Title(int *y, int infosize) +emenu_t *M_Options_Title(int *y, int infosize) { - struct menu_s *menu; + struct emenu_s *menu; *y = 32; - Key_Dest_Add(kdm_emenu); - menu = M_CreateMenu(infosize); switch(M_GameType()) @@ -140,7 +138,7 @@ menu_t *M_Options_Title(int *y, int infosize) } //these are awkward/strange -qboolean M_Options_AlwaysRun (menucheck_t *option, struct menu_s *menu, chk_set_t set) +qboolean M_Options_AlwaysRun (menucheck_t *option, struct emenu_s *menu, chk_set_t set) { if (M_GameType() == MGT_QUAKE2) { @@ -171,7 +169,7 @@ qboolean M_Options_AlwaysRun (menucheck_t *option, struct menu_s *menu, chk_set_ } } } -qboolean M_Options_InvertMouse (menucheck_t *option, struct menu_s *menu, chk_set_t set) +qboolean M_Options_InvertMouse (menucheck_t *option, struct emenu_s *menu, chk_set_t set) { if (set == CHK_CHECKED) return m_pitch.value < 0; @@ -341,7 +339,7 @@ void M_Menu_Options_f (void) // removed singleplayer cheats (move this to single player menu) MB_END() }; - menu_t *menu = M_Options_Title(&y, 0); + emenu_t *menu = M_Options_Title(&y, 0); static menuresel_t resel; int framey = y; @@ -383,7 +381,7 @@ typedef struct { soundcardinfo_t *card; } audiomenuinfo_t; -qboolean M_Audio_Key (int key, struct menu_s *menu) +qboolean M_Audio_Key (int key, struct emenu_s *menu) { int i; audiomenuinfo_t *info = menu->data; @@ -432,7 +430,7 @@ qboolean M_Audio_Key (int key, struct menu_s *menu) return false; } -void M_Audio_StartSound (struct menu_s *menu) +void M_Audio_StartSound (struct emenu_s *menu) { int i; vec3_t org; @@ -477,9 +475,7 @@ void M_Menu_Audio_Speakers_f (void) { int i; audiomenuinfo_t *info; - menu_t *menu; - - Key_Dest_Add(kdm_emenu); + emenu_t *menu; menu = M_CreateMenu(sizeof(audiomenuinfo_t)); info = menu->data; @@ -505,7 +501,7 @@ struct audiomenuinfo char **capdevdescs; #endif }; -void M_Menu_Audio_Remove(menu_t *menu) +void M_Menu_Audio_Remove(emenu_t *menu) { int i; struct audiomenuinfo *info = menu->data; @@ -524,7 +520,7 @@ void M_Menu_Audio_Remove(menu_t *menu) Z_Free(info->capdevdescs); #endif } -struct audiomenuinfo *M_Menu_Audio_Setup(menu_t *menu) +struct audiomenuinfo *M_Menu_Audio_Setup(emenu_t *menu) { #ifdef VOICECHAT extern cvar_t snd_voip_capturedevice_opts; @@ -564,7 +560,7 @@ struct audiomenuinfo *M_Menu_Audio_Setup(menu_t *menu) void M_Menu_Audio_f (void) { int y; - menu_t *menu = M_Options_Title(&y, sizeof(struct audiomenuinfo)); + emenu_t *menu = M_Options_Title(&y, sizeof(struct audiomenuinfo)); struct audiomenuinfo *info = M_Menu_Audio_Setup(menu); extern cvar_t nosound, snd_leftisright, snd_device, snd_khz, snd_speakers, ambient_level, bgmvolume, snd_playersoundvolume, ambient_fade, cl_staticsounds, snd_inactive, _snd_mixahead, snd_doppler; // extern cvar_t snd_noextraupdate, snd_eax, precache; @@ -720,7 +716,7 @@ void M_Menu_Audio_f (void) void M_Menu_Particles_f (void) { - menu_t *menu; + emenu_t *menu; extern cvar_t r_bouncysparks, r_part_rain, gl_part_flame, r_grenadetrail, r_rockettrail, r_part_rain_quantity, r_particledesc, r_particle_tracelimit, r_part_contentswitch, r_bloodstains; // extern cvar_t r_part_sparks_trifan, r_part_sparks_textured, r_particlesystem; @@ -1022,7 +1018,7 @@ static void ApplyPreset (int presetnum) void M_Menu_Preset_f (void) { extern cvar_t cfg_save_auto; - menu_t *menu; + emenu_t *menu; int y; menubulk_t bulk[] = { @@ -1214,7 +1210,7 @@ void FPS_Preset_f (void) Con_Printf("%s\n", presetname[i]); } -qboolean M_PresetApply (union menuoption_s *op, struct menu_s *menu, int key) +qboolean M_PresetApply (union menuoption_s *op, struct emenu_s *menu, int key) { fpsmenuinfo_t *info = (fpsmenuinfo_t*)menu->data; @@ -1267,7 +1263,7 @@ void M_Menu_FPS_f (void) static const char *values_0_1_2[] = {"0", "1", "2", NULL}; static const char *values_0_1[] = {"0", "1", NULL}; - menu_t *menu; + emenu_t *menu; fpsmenuinfo_t *info; extern cvar_t v_contentblend, show_fps, cl_r2g, cl_gibfilter, cl_expsprite, cl_deadbodyfilter, cl_lerp_players, cl_nolerp, cl_maxfps, cl_yieldcpu; @@ -1327,7 +1323,7 @@ void M_Menu_Render_f (void) static const char *cshiftopts[] = {"Off", "Fullscreen", "Edges", NULL}; static const char *cshiftvalues[] = {"0", "1", "2", NULL}; - menu_t *menu; + emenu_t *menu; extern cvar_t r_novis, cl_item_bobbing, r_waterwarp, r_nolerp, r_noframegrouplerp, r_fastsky, gl_nocolors, gl_lerpimages, r_wateralpha, r_drawviewmodel, gl_cshiftenabled, r_hdr_irisadaptation, scr_logcenterprint, r_fxaa, r_graphics; #ifdef GLQUAKE extern cvar_t r_bloom; @@ -1459,7 +1455,7 @@ void M_Menu_Textures_f (void) MB_COMBOCVAR("Max Texture Size", gl_max_size, texturesizeoptions, texturesizeoptions, NULL), MB_END() }; - menu_t *menu = M_Options_Title(&y, 0); + emenu_t *menu = M_Options_Title(&y, 0); static menuresel_t resel; MC_AddFrameStart(menu, y); MC_AddBulk(menu, &resel, bulk, 16, 216, y); @@ -1471,7 +1467,7 @@ typedef struct { menucombo_t *dlightcombo; } lightingmenuinfo_t; -qboolean M_VideoApplyShadowLighting (union menuoption_s *op,struct menu_s *menu,int key) +qboolean M_VideoApplyShadowLighting (union menuoption_s *op,struct emenu_s *menu,int key) { lightingmenuinfo_t *info = (lightingmenuinfo_t*)menu->data; @@ -1686,7 +1682,7 @@ void M_Menu_Lighting_f (void) }; int y; - menu_t *menu = M_Options_Title(&y, sizeof(lightingmenuinfo_t)); + emenu_t *menu = M_Options_Title(&y, sizeof(lightingmenuinfo_t)); int lightselect, dlightselect; @@ -1934,7 +1930,7 @@ static const char *mapoptions_q2[] = #endif #endif -qboolean M_Apply_SP_Cheats (union menuoption_s *op,struct menu_s *menu,int key) +qboolean M_Apply_SP_Cheats (union menuoption_s *op,struct emenu_s *menu,int key) { singleplayerinfo_t *info = menu->data; @@ -1988,7 +1984,7 @@ void M_Menu_Singleplayer_Cheats_Quake (void) singleplayerinfo_t *info; int cursorpositionY; int y; - menu_t *menu = M_Options_Title(&y, sizeof(*info)); + emenu_t *menu = M_Options_Title(&y, sizeof(*info)); info = menu->data; cursorpositionY = (y + 24); @@ -2053,7 +2049,7 @@ menucombo_t *skillcombo; menucombo_t *mapcombo; } singleplayerq2info_t; -qboolean M_Apply_SP_Cheats_Q2 (union menuoption_s *op,struct menu_s *menu,int key) +qboolean M_Apply_SP_Cheats_Q2 (union menuoption_s *op,struct emenu_s *menu,int key) { singleplayerq2info_t *info = menu->data; @@ -2102,7 +2098,7 @@ void M_Menu_Singleplayer_Cheats_Quake2 (void) extern cvar_t host_mapname; #endif int y; - menu_t *menu = M_Options_Title(&y, sizeof(*info)); + emenu_t *menu = M_Options_Title(&y, sizeof(*info)); info = menu->data; cursorpositionY = (y + 24); @@ -2176,7 +2172,7 @@ menucombo_t *skillcombo; menucombo_t *mapcombo; } singleplayerh2info_t; -qboolean M_Apply_SP_Cheats_H2 (union menuoption_s *op,struct menu_s *menu,int key) +qboolean M_Apply_SP_Cheats_H2 (union menuoption_s *op,struct emenu_s *menu,int key) { singleplayerh2info_t *info = menu->data; @@ -2384,7 +2380,7 @@ void M_Menu_Singleplayer_Cheats_Hexen2 (void) #endif extern cvar_t host_mapname; int y; - menu_t *menu = M_Options_Title(&y, sizeof(*info)); + emenu_t *menu = M_Options_Title(&y, sizeof(*info)); info = menu->data; cursorpositionY = (y + 24); @@ -2565,7 +2561,7 @@ typedef struct { menucombo_t *res2dsize[ASPECT_RATIOS]; } videomenuinfo_t; -void CheckCustomMode(struct menu_s *menu) +void CheckCustomMode(struct emenu_s *menu) { int i, sel; videomenuinfo_t *info = (videomenuinfo_t*)menu->data; @@ -2658,7 +2654,7 @@ int M_MatchModes(int width, int height, int *outres) return ratio; } -qboolean M_VideoApply (union menuoption_s *op, struct menu_s *menu, int key) +qboolean M_VideoApply (union menuoption_s *op, struct emenu_s *menu, int key) { extern cvar_t vid_desktopsettings; videomenuinfo_t *info = (videomenuinfo_t*)menu->data; @@ -2986,11 +2982,10 @@ void M_Menu_Video_f (void) int y; int resmodechoice, res2dmodechoice; int reschoices[ASPECT_RATIOS], res2dchoices[ASPECT_RATIOS]; - menu_t *menu; + emenu_t *menu; //not calling M_Options_Title because of quake2's different banner. y = 32; - Key_Dest_Add(kdm_emenu); menu = M_CreateMenu(sizeof(videomenuinfo_t)); switch(M_GameType()) { @@ -3252,7 +3247,7 @@ static unsigned int tobit(unsigned int bitmask) } return 0; } -static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_s *m) +static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct emenu_s *m) { static playerview_t pv; entity_t ent; @@ -3813,7 +3808,7 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_ break; } } -static qboolean M_ModelViewerKey(struct menucustom_s *c, struct menu_s *m, int key, unsigned int unicode) +static qboolean M_ModelViewerKey(struct menucustom_s *c, struct emenu_s *m, int key, unsigned int unicode) { modelview_t *mods = c->dptr; @@ -3927,7 +3922,7 @@ static qboolean M_ModelViewerKey(struct menucustom_s *c, struct menu_s *m, int k } #ifdef RAGDOLL -void M_Modelviewer_Shutdown(struct menu_s *menu) +void M_Modelviewer_Shutdown(struct emenu_s *menu) { modelview_t *mv = menu->data; rag_removedeltaent(&mv->ragent); @@ -3949,9 +3944,7 @@ void M_Menu_ModelViewer_f(void) { modelview_t *mv; menucustom_t *c; - menu_t *menu; - - Key_Dest_Add(kdm_emenu); + emenu_t *menu; menu = M_CreateMenu(sizeof(*mv)); mv = menu->data; @@ -4028,7 +4021,7 @@ typedef struct size_t nummods; } modmenu_t; -static void Mods_Draw(int x, int y, struct menucustom_s *c, struct menu_s *m) +static void Mods_Draw(int x, int y, struct menucustom_s *c, struct emenu_s *m) { modmenu_t *mods = c->dptr; int i = c->dint; @@ -4069,7 +4062,7 @@ static void Mods_Draw(int x, int y, struct menucustom_s *c, struct menu_s *m) Draw_FunString(x, y, mods->mod[i].gamedir); } } -static qboolean Mods_Key(struct menucustom_s *c, struct menu_s *m, int key, unsigned int unicode) +static qboolean Mods_Key(struct menucustom_s *c, struct emenu_s *m, int key, unsigned int unicode) { modmenu_t *mods = c->dptr; int i; @@ -4102,7 +4095,7 @@ static qboolean Mods_Key(struct menucustom_s *c, struct menu_s *m, int key, unsi return false; } -static void Mods_Remove (struct menu_s *m) +static void Mods_Remove (struct emenu_s *m) { modmenu_t *mods = m->data; int i; @@ -4170,7 +4163,7 @@ void M_Menu_Mods_f (void) { modmenu_t mods; menucustom_t *c; - menu_t *menu; + emenu_t *menu; size_t i; extern qboolean com_homepathenabled; @@ -4183,8 +4176,6 @@ void M_Menu_Mods_f (void) //FIXME: sort by mtime? - Key_Dest_Add(kdm_emenu); - menu = M_CreateMenu(sizeof(modmenu_t)); *(modmenu_t*)menu->data = mods; if (COM_FCheckExists("gfx/p_option.lmp")) diff --git a/engine/client/m_script.c b/engine/client/m_script.c index 8104d02f5..3a91cae3e 100644 --- a/engine/client/m_script.c +++ b/engine/client/m_script.c @@ -6,9 +6,9 @@ #ifndef NOBUILTINMENUS int selectitem; -menu_t *menu_script; +emenu_t *menu_script; -void M_Script_Option (menu_t *menu, char *optionvalue, qboolean isexplicit) +void M_Script_Option (emenu_t *menu, char *optionvalue, qboolean isexplicit) { menuoption_t *mo; char *scriptname = menu->data; @@ -50,14 +50,14 @@ void M_Script_Option (menu_t *menu, char *optionvalue, qboolean isexplicit) Cbuf_AddText("\n", execlevel); } -void M_Script_Remove (menu_t *menu) +void M_Script_Remove (emenu_t *menu) { if (menu == menu_script) menu_script = NULL; M_Script_Option(menu, "cancel", false); } -qboolean M_Script_Key (int key, menu_t *menu) +qboolean M_Script_Key (int key, emenu_t *menu) { if (menu->selecteditem && menu->selecteditem->common.type == mt_edit) return false; @@ -90,9 +90,7 @@ void M_MenuS_Clear_f (void) void M_MenuS_Script_f (void) //create a menu. { int items; - menu_t *oldmenu; char *alias = Cmd_Argv(1); - Key_Dest_Add(kdm_emenu); selectitem = 0; items=0; @@ -113,14 +111,7 @@ void M_MenuS_Script_f (void) //create a menu. M_MenuS_Clear_f(); } - oldmenu = topmenu; - menu_script = M_CreateMenu(0); - if (oldmenu) - { - M_HideMenu(oldmenu); //bring to front - M_AddMenu(oldmenu); - } menu_script->remove = M_Script_Remove; menu_script->key = M_Script_Key; diff --git a/engine/client/m_single.c b/engine/client/m_single.c index 555be9f12..3589ab0d1 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -139,7 +139,7 @@ static void M_ScanSaves (void) M_ScanSave(i, va("s%i", i-SAVEFIRST_STANDARD), true); } -static void M_Menu_LoadSave_UnloadShaders(menu_t *menu) +static void M_Menu_LoadSave_UnloadShaders(emenu_t *menu) { loadsavemenuinfo_t *info = menu->data; if (info->picshader) @@ -150,7 +150,7 @@ static void M_Menu_LoadSave_UnloadShaders(menu_t *menu) } } -static void M_Menu_LoadSave_Preview_Draw(int x, int y, menucustom_t *item, menu_t *menu) +static void M_Menu_LoadSave_Preview_Draw(int x, int y, menucustom_t *item, emenu_t *menu) { loadsavemenuinfo_t *info = menu->data; int slot; @@ -225,7 +225,7 @@ static void M_Menu_LoadSave_Preview_Draw(int x, int y, menucustom_t *item, menu_ void M_Menu_Save_f (void) { menuoption_t *op = NULL; - menu_t *menu; + emenu_t *menu; int i; if (!sv.state) @@ -234,8 +234,6 @@ void M_Menu_Save_f (void) if (cl.intermissionmode != IM_NONE) return; - Key_Dest_Add(kdm_emenu); - menu = M_CreateMenu(sizeof(loadsavemenuinfo_t)); menu->data = menu+1; menu->remove = M_Menu_LoadSave_UnloadShaders; @@ -272,12 +270,10 @@ void M_Menu_Save_f (void) void M_Menu_Load_f (void) { menuoption_t *op = NULL; - menu_t *menu; + emenu_t *menu; int i; char time[64]; - Key_Dest_Add(kdm_emenu); - menu = M_CreateMenu(sizeof(loadsavemenuinfo_t)); menu->data = menu+1; menu->remove = M_Menu_LoadSave_UnloadShaders; @@ -323,7 +319,7 @@ void M_Menu_Load_f (void) extern cvar_t cl_splitscreen; void M_Menu_SinglePlayer_f (void) { - menu_t *menu; + emenu_t *menu; #ifndef CLIENTONLY menubutton_t *b; mpic_t *p; @@ -349,8 +345,6 @@ void M_Menu_SinglePlayer_f (void) }; #endif - Key_Dest_Add(kdm_emenu); - #ifdef CLIENTONLY menu = M_CreateMenu(0); @@ -617,7 +611,7 @@ typedef struct { demoitem_t *items; } demomenu_t; -static void M_DemoDraw(int x, int y, menucustom_t *control, menu_t *menu) +static void M_DemoDraw(int x, int y, menucustom_t *control, emenu_t *menu) { extern qboolean keydown[K_MAX]; char *text; @@ -699,8 +693,8 @@ static void M_DemoDraw(int x, int y, menucustom_t *control, menu_t *menu) item = item->next; } } -static void ShowDemoMenu (menu_t *menu, const char *path); -static qboolean M_DemoKey(menucustom_t *control, menu_t *menu, int key, unsigned int unicode) +static void ShowDemoMenu (emenu_t *menu, const char *path); +static qboolean M_DemoKey(menucustom_t *control, emenu_t *menu, int key, unsigned int unicode) { demomenu_t *info = menu->data; demoitem_t *it; @@ -944,13 +938,13 @@ static void M_Demo_Flush (demomenu_t *info) info->firstitem = NULL; } -static void M_Demo_Remove (menu_t *menu) +static void M_Demo_Remove (emenu_t *menu) { demomenu_t *info = menu->data; M_Demo_Flush(info); } -static void ShowDemoMenu (menu_t *menu, const char *path) +static void ShowDemoMenu (emenu_t *menu, const char *path) { demomenu_t *info = menu->data; @@ -1071,10 +1065,9 @@ void M_Menu_Demos_f (void) }; size_t u; demomenu_t *info; - menu_t *menu; + emenu_t *menu; static demoloc_t mediareenterloc = {FS_GAME, "demos/"}; - Key_Dest_Add(kdm_emenu); Key_Dest_Remove(kdm_console); menu = M_CreateMenu(sizeof(demomenu_t)); @@ -1131,11 +1124,9 @@ void M_Menu_Demos_f (void) void M_Menu_MediaFiles_f (void) { demomenu_t *info; - menu_t *menu; + emenu_t *menu; static demoloc_t mediareenterloc = {FS_GAME}; - Key_Dest_Add(kdm_emenu); - menu = M_CreateMenu(sizeof(demomenu_t)); menu->remove = M_Demo_Remove; info = menu->data; diff --git a/engine/client/menu.c b/engine/client/menu.c index a79995b5d..f1d5e079e 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -22,7 +22,153 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "shader.h" #include "cl_master.h" -qboolean menu_mousedown; +menu_t *topmenu; +menu_t *promptmenu; + +void Menu_KeyEvent(qboolean isdown, int deviceid, int key, int unicode) +{ + if (promptmenu && promptmenu->keyevent) + promptmenu->keyevent(promptmenu, isdown, deviceid, key, unicode); + else if (topmenu && topmenu->keyevent) + topmenu->keyevent(topmenu, isdown, deviceid, key, unicode); + else if (isdown) + Key_Dest_Remove(kdm_menu); //it doesn't want it then... +} +static void Menu_UpdateFocus(void) +{ + if (!promptmenu || !promptmenu->keyevent) + Key_Dest_Remove(kdm_prompt); //can't take key presses, so don't take keys. + if (promptmenu && promptmenu->cursor) + key_dest_absolutemouse |= kdm_prompt; + else + key_dest_absolutemouse &= ~kdm_prompt; + + if (!topmenu || !topmenu->keyevent) + Key_Dest_Remove(kdm_menu); //can't take key presses, so don't take keys. + if (topmenu && topmenu->cursor) + key_dest_absolutemouse |= kdm_menu; + else + key_dest_absolutemouse &= ~kdm_menu; +} +qboolean Menu_IsLinked(menu_t *menu) +{ + menu_t *link; + for (link = topmenu; link; link = link->prev) + { + if (menu == link) + return true; + } + return false; +} +menu_t *Menu_FindContext(void *ctx) +{ + menu_t *link; + for (link = promptmenu; link; link = link->prev) + { + if (link->ctx == ctx) + return link; + } + for (link = topmenu; link; link = link->prev) + { + if (link->ctx == ctx) + return link; + } + return NULL; +} +void Menu_Unlink(menu_t *menu) +{ + menu_t **link; + for (link = &promptmenu; *link; link = &(*link)->prev) + { + if (menu == *link) + { + *link = menu->prev; + if (menu->release) + menu->release(menu); + + Menu_UpdateFocus(); + return; + } + } + for (link = &topmenu; *link; link = &(*link)->prev) + { + if (menu == *link) + { + *link = menu->prev; + if (menu->release) + menu->release(menu); + + Menu_UpdateFocus(); + return; + } + } +} +void Menu_Push(menu_t *menu, qboolean prompt) +{ + if (!Menu_IsLinked(menu)) + { //only link once. + if (prompt) + { + menu->prev = promptmenu; + promptmenu = menu; + } + else + { + menu->prev = topmenu; + topmenu = menu; + } + } + if (menu == promptmenu) + { + Key_Dest_Add(kdm_prompt); + Menu_UpdateFocus(); + } + if (menu == topmenu) + { + Key_Dest_Add(kdm_menu); + Menu_UpdateFocus(); + } +} +void Menu_PopAll(void) +{ + qboolean popped = false; + menu_t **link, *menu; + for (link = &topmenu; *link;) + { + menu = *link; + if (menu->persist) + link = &(*link)->prev; + else + { + *link = menu->prev; + menu->prev = NULL; + if (menu->release) + menu->release(menu); + popped = true; + } + } + + if (popped) + Menu_UpdateFocus(); +} + +void Menu_Draw(void) +{ +#ifdef MENU_DAT + //shitty always-drawn crap + MP_Draw(); +#endif + + //draw whichever menu has focus + if (topmenu && topmenu->drawmenu) + topmenu->drawmenu(topmenu); +} +void Prompts_Draw(void) +{ + //prompts always appear over the top of everything else, particuarly other menus. + if (promptmenu && promptmenu->drawmenu) + promptmenu->drawmenu(promptmenu); +} void M_DrawScalePic (int x, int y, int w, int h, mpic_t *pic) { @@ -105,7 +251,7 @@ void M_DrawTextBox (int x, int y, int width, int lines) M_DrawScalePic (cx, cy+8, 8, 8, p); } -int M_FindKeysForBind (int bindmap, const char *command, int *keylist, int *keymods, int keycount) +int QDECL M_FindKeysForBind (int bindmap, const char *command, int *keylist, int *keymods, int keycount) { int count; int j, m; @@ -203,13 +349,11 @@ M_ToggleMenu_f */ void M_ToggleMenu_f (void) { -#ifndef NOBUILTINMENUS if (topmenu) { - Key_Dest_Add(kdm_emenu); + Key_Dest_Add(kdm_menu); return; } -#endif #ifdef CSQC_DAT if (CSQC_ConsoleCommand(-1, "togglemenu")) @@ -264,6 +408,200 @@ void M_Restart_f(void) } +//============================================================================= +/* Various callback-based prompts */ + +typedef struct +{ + menu_t m; + void (*callback)(void *, int); + void *ctx; + + int lines; + const char *messages; + const char *buttons[3]; + int kbutton, mbutton; +} promptmenu_t; +static qboolean Prompt_MenuKeyEvent(struct menu_s *gm, qboolean isdown, unsigned int devid, int key, int unicode) +{ + promptmenu_t *m = (promptmenu_t*)gm; + int action; + void (*callback)(void *, int) = m->callback; + void *ctx = m->ctx; + extern qboolean keydown[]; + + if (!isdown != (key==K_MOUSE1)) + return false; //don't care about releases, unless mouse1. + + if (key == 'n' || key == 'N') + action = 1; + else if (key == 'y' || key == 'Y') + action = 0; + else if (key==K_RIGHTARROW || key==K_GP_DPAD_RIGHT || key==K_DOWNARROW || key==K_GP_DPAD_DOWN || (key == K_TAB && !keydown[K_LSHIFT] && !keydown[K_RSHIFT])) + { + for(;;) + { + m->kbutton++; + if (m->kbutton >= 3) + m->kbutton -= 3; + if (m->buttons[m->kbutton]) + break; + } + return true; + } + else if (key == K_LEFTARROW || key == K_GP_DPAD_LEFT || key==K_UPARROW || key==K_GP_DPAD_UP || key==K_TAB) + { + for(;;) + { + m->kbutton--; + if (m->kbutton < 0) + m->kbutton += 3; + if (m->buttons[m->kbutton]) + break; + } + return true; + } + else if (key == K_ESCAPE || key == K_GP_BACK || key == K_MOUSE2) + action = -1; + else if (key == K_ENTER || key == K_KP_ENTER || key == K_MOUSE1 || key == K_GP_A) + { + if (key == K_MOUSE1) + action = m->mbutton; + else + action = m->kbutton; + + if (action == -1) //nothing focused + return false; + if (action == 2) //convert buttons to actions... + action = -1; + } + else + return false; // no idea what that is + + m->callback = NULL; //so the remove handler can't fire. + Menu_Unlink(&m->m); + if (callback) + callback(ctx, action); + + return true; +} +static void Prompt_Draw(struct menu_s *g) +{ + promptmenu_t *m = (promptmenu_t*)g; + int x = 64; + int y = 76; + int w = 224; + int h = m->lines*8+16; + int i; + const char *msg = m->messages; + int bx[4]; + + x = ((vid.width-w)>>1); + + Draw_TextBox(x-8, y, w/8, h/8); + y+=8; + for (i = 0; i < m->lines; i++, msg = msg+strlen(msg)+1) + { + Draw_FunStringWidth(x, y, msg, w, 2, false); + y+=8; + } + y+=8; + m->mbutton = -1; + bx[0] = x; + bx[1] = x+w/3; + bx[2] = x+w-w/3; + bx[3] = x+w; + if (mousecursor_y >= y && mousecursor_y <= y+8) + { + for (i = 0; i < 3; i++) + { + if (m->buttons[i] && mousecursor_x >= bx[i] && mousecursor_x < bx[i+1]) + m->mbutton = i; + } + } + for (i = 0; i < 3; i++) + { + if (m->buttons[i]) + { + if (m->mbutton == i) + { + float alphamax = 0.5, alphamin = 0.2; + R2D_ImageColours(.5,.4,0,(sin(realtime*2)+1)*0.5*(alphamax-alphamin)+alphamin); + R2D_FillBlock(bx[i], y, bx[i+1]-bx[i], 8); + R2D_ImageColours(1,1,1,1); + } + Draw_FunStringWidth(bx[i], y, m->buttons[i], bx[i+1]-bx[i], 2, m->kbutton==i); + } + } +} +static void Prompt_Release(struct menu_s *gm) +{ + promptmenu_t *m = (promptmenu_t*)gm; + void (*callback)(void *, int) = m->callback; + void *ctx = m->ctx; + m->callback = NULL; + + if (callback) + callback(ctx, -1); + Z_Free(m); +} +void Menu_Prompt (void (*callback)(void *, int), void *ctx, const char *messages, char *optionyes, char *optionno, char *optioncancel) +{ + promptmenu_t *m; + char *t; + + m = (promptmenu_t*)Z_Malloc(sizeof(*m) + strlen(messages)+(optionyes?strlen(optionyes):0)+(optionno?strlen(optionno):0)+(optioncancel?strlen(optioncancel):0)+7); + + m->m.cursor = &key_customcursor[kc_console]; + /*void (*videoreset) (struct menu_s *); //called after a video mode switch / shader reload. + void (*release) (struct menu_s *); // + qboolean (*keyevent)(struct menu_s *, qboolean isdown, unsigned int devid, int key, int unicode); //true if key was handled + qboolean (*mousemove)(struct menu_s *, qboolean abs, unsigned int devid, float x, float y); + qboolean (*joyaxis) (struct menu_s *, unsigned int devid, int axis, float val); + void (*drawmenu) (struct menu_s *); + */ + m->m.drawmenu = Prompt_Draw; + m->m.keyevent = Prompt_MenuKeyEvent; + m->m.release = Prompt_Release; + m->mbutton = -1; + m->kbutton = -1; + Menu_Push(&m->m, true); + + m->callback = callback; + m->ctx = ctx; + + t = (char*)(m+1); + if (optionyes) + { + m->buttons[0] = t; + strcpy(t, optionyes); + t += strlen(t)+1; + } + if (optionno) + { + m->buttons[1] = t; + strcpy(t, optionno); + t += strlen(t)+1; + } + if (optioncancel) + { + m->buttons[2] = t; + strcpy(t, optioncancel); + t += strlen(t)+1; + } + + m->messages = t; + strcpy(t, messages); + + for(messages = t; t;) + { + t = strchr(t, '\n'); + if (t) + *t++ = 0; + m->lines++; + } +} + #ifndef NOBUILTINMENUS void M_Menu_Audio_f (void); @@ -272,10 +610,6 @@ void M_Menu_Mods_f (void); void M_Menu_ModelViewer_f(void); void M_Menu_ModelViewer_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx); -extern menu_t *menu_script; - -qboolean m_recursiveDraw; - void M_ConfigureNetSubsystem(void); cvar_t m_helpismedia = CVAR("m_helpismedia", "0"); @@ -378,14 +712,11 @@ void M_BuildTranslationTable(unsigned int pc, unsigned int top, unsigned int bot //============================================================================= -int m_save_demonum; - void M_CloseMenu_f (void) { - if (!Key_Dest_Has(kdm_emenu)) + if (!Key_Dest_Has(kdm_menu)) return; M_RemoveAllMenus(false); - Key_Dest_Remove(kdm_emenu); } //============================================================================= @@ -517,14 +848,12 @@ int bind_grab; void M_Menu_Keys_f (void) { int y; - menu_t *menu; + emenu_t *menu; vfsfile_t *bindslist; #if MAX_SPLITS > 1 extern cvar_t cl_splitscreen; #endif - Key_Dest_Add(kdm_emenu); - menu = M_CreateMenu(0); switch(M_GameType()) { @@ -658,7 +987,7 @@ struct {"gfx/menu/help%02i.lmp",1} //hexen2 }; -void M_Help_Draw (menu_t *m) +void M_Help_Draw (emenu_t *m) { int i; mpic_t *pic = NULL; @@ -690,7 +1019,7 @@ void M_Help_Draw (menu_t *m) R2D_ScalePic ((vid.width-width)/2, (vid.height-height)/2, width, height, pic); } } -qboolean M_Help_Key (int key, menu_t *m) +qboolean M_Help_Key (int key, emenu_t *m) { switch (key) { @@ -726,8 +1055,7 @@ qboolean M_Help_Key (int key, menu_t *m) void M_Menu_Help_f (void) { int i; - menu_t *helpmenu = M_CreateMenu(0); - Key_Dest_Add(kdm_emenu); + emenu_t *helpmenu = M_CreateMenu(0); helpmenu->predraw = M_Help_Draw; helpmenu->key = M_Help_Key; @@ -748,226 +1076,53 @@ void M_Menu_Help_f (void) } } - -//============================================================================= -/* Various callback-based prompts */ - -typedef struct -{ - menu_t m; - void (*callback)(void *, int); - void *ctx; - menubutton_t *b_yes; - menubutton_t *b_no; - menubutton_t *b_cancel; -} promptmenu_t; -static qboolean M_Menu_Prompt_Button (union menuoption_s *b,struct menu_s *gm, int key) -{ - int action; - promptmenu_t *m = (promptmenu_t*)gm; - void (*callback)(void *, int) = m->callback; - void *ctx = m->ctx; - - if (key != K_ENTER && key != K_KP_ENTER && key != K_MOUSE1) - return true; - - if (b == (menuoption_t*)m->b_yes) - action = 0; - else if (b == (menuoption_t*)m->b_no) - action = 1; - else //if (b == (menuoption_t*)m->b_cancel) - action = -1; - m->callback = NULL; - - M_RemoveMenu(&m->m); - - if (callback) - callback(ctx, action); - return true; -} -static void M_Menu_Prompt_Cancel (struct menu_s *gm) -{ - promptmenu_t *m = (promptmenu_t*)gm; - void (*callback)(void *, int) = m->callback; - void *ctx = m->ctx; - m->callback = NULL; - - if (callback) - callback(ctx, -1); -} -void M_Menu_Prompt (void (*callback)(void *, int), void *ctx, const char *messages, char *optionyes, char *optionno, char *optioncancel) -{ - promptmenu_t *m; - char *t; - int y; - int x = 64, w = 224; - - Key_Dest_Add(kdm_emenu); - - m = (promptmenu_t*)M_CreateMenuInfront(sizeof(*m) - sizeof(m->m) + strlen(messages)+(optionyes?strlen(optionyes):0)+(optionno?strlen(optionno):0)+(optioncancel?strlen(optioncancel):0)+6); - m->callback = callback; - m->ctx = ctx; - m->m.remove = M_Menu_Prompt_Cancel; - - t = (char*)(m+1); - if (optionyes) - { - strcpy(t, optionyes); - optionyes = t; - t += strlen(t)+1; - } - if (optionno) - { - strcpy(t, optionno); - optionno = t; - t += strlen(t)+1; - } - if (optioncancel) - { - strcpy(t, optioncancel); - optioncancel = t; - t += strlen(t)+1; - } - - y = 76; - y += 8; //top border - strcpy(t, messages); - - for(messages = t; t; y += 8) - { - messages = t; - t = strchr(messages, '\n'); - if (t) - *t++ = 0; - if (*messages) - MC_AddWhiteText(&m->m, x, x+w, y, messages, 2); - } - - y += 8; //blank space - - if (optionyes) - { - m->b_yes = MC_AddCommand(&m->m, x, x+70, y, optionyes, M_Menu_Prompt_Button); - m->b_yes->rightalign = 2; - } - if (optionno) - { - m->b_no = MC_AddCommand(&m->m, x+w/3, x+(2*w)/3, y, optionno, M_Menu_Prompt_Button); - m->b_no->rightalign = 2; //actually center align - } - if (optioncancel) - { - m->b_cancel = MC_AddCommand(&m->m, x+(2*w)/3, x+w, y, optioncancel, M_Menu_Prompt_Button); - m->b_cancel->rightalign = 2; - } - y += 8; //footer - - y += 8; //bottom border - - m->m.selecteditem = (menuoption_t *)m->b_cancel; - - MC_AddBox (&m->m, x-8, 76, (w/8), (y-76)/8); -} - //============================================================================= /* QUIT MENU */ -int msgNumber; -int m_quit_prevstate; -qboolean wasInMenus; - -char *quitMessage [] = +static char *quitMessage [] = { /* .........1.........2.... */ - " Are you gonna quit ", - " this game just like ", - " everything else? ", - " ", + "Are you gonna quit\n" + "this game just like\n" + "everything else?", - " Milord, methinks that ", - " thou art a lowly ", - " quitter. Is this true? ", - " ", + "Milord, methinks that\n" + "thou art a lowly\n" + "quitter. Is this true?", - " Do I need to bust your ", - " face open for trying ", - " to quit? ", - " ", + "Do I need to bust your\n" + "face open for trying\n" + "to quit?", - " Man, I oughta smack you", - " for trying to quit! ", - " Press Y to get ", - " smacked out. ", + "Man, I oughta smack you\n" + "for trying to quit!\n" + "Press Y to get\n" + "smacked out.", - " Press Y to quit like a ", - " big loser in life. ", - " Press N to stay proud ", - " and successful! ", + "Press Y to quit like a\n" + "big loser in life.\n" + "Press N to stay proud\n" + "and successful!", - " If you press Y to ", - " quit, I will summon ", - " Satan all over your ", - " hard drive! ", + "If you press Y to\n" + "quit, I will summon\n" + "Satan all over your\n" + "hard drive!", - " Um, Asmodeus dislikes ", - " his children trying to ", - " quit. Press Y to return", - " to your Tinkertoys. ", + "Um, Asmodeus dislikes\n" + "his children trying to\n" + "quit. Press Y to return\n" + "to your Tinkertoys.", - " If you quit now, I'll ", - " throw a blanket-party ", - " for you next time! ", - " " + "If you quit now, I'll\n" + "throw a blanket-party\n" + "for you next time!", }; -/* -void OldM_Menu_Quit_f (void) -{ - if (m_state == m_quit) - return; - wasInMenus = (key_dest == key_menu); - key_dest = key_menu; - m_quit_prevstate = m_state; - m_state = m_quit; - m_entersound = true; - msgNumber = rand()&7; -} -void M_Quit_Key (int key) -{ - switch (key) - { - case K_ESCAPE: - case 'n': - case 'N': - if (wasInMenus) - { - m_state = m_quit_prevstate; - m_entersound = true; - } - else - key_dest = key_game; - break; - case 'Y': - case 'y': - key_dest = key_console; - CL_Disconnect (); - Sys_Quit (); - break; - - default: - break; - } - -} - -void M_Quit_Draw (void) -{ -#define VSTR(x) #x -#define VSTR2(x) VSTR(x) - char *cmsg[] = { -// 0123456789012345678901234567890123456789 +/* char *cmsg[] = { +// 0123456789012345678901234567890123456789 "0 QuakeWorld", "1 version " VSTR2(VERSION), "1modified by Forethought Entertainment", @@ -990,108 +1145,28 @@ void M_Quit_Draw (void) "0NIN(r) is a registered trademark", "0licensed to Nothing Interactive, Inc.", "0All rights reserved. Press y to exit", - NULL }; - char **p; - int y; - - if (wasInMenus) - { - m_state = m_quit_prevstate; - m_recursiveDraw = true; - M_Draw (); - m_state = m_quit; - } -#if 1 - M_DrawTextBox (0, 0, 38, 23); - y = 12; - for (p = cmsg; *p; p++, y += 8) { - if (**p == '0') - M_PrintWhite (16, y, *p + 1); - else - M_Print (16, y, *p + 1); - } -#else - M_DrawTextBox (56, 76, 24, 4); - M_Print (64, 84, quitMessage[msgNumber*4+0]); - M_Print (64, 92, quitMessage[msgNumber*4+1]); - M_Print (64, 100, quitMessage[msgNumber*4+2]); - M_Print (64, 108, quitMessage[msgNumber*4+3]); -#endif -} -*/ -qboolean MC_Quit_Key (int key, menu_t *menu) -{ - switch (key) - { - case K_ESCAPE: - case K_GP_BACK: - case 'n': - case 'N': - M_RemoveMenu(menu); - break; - - case 'q': - case 'Q': - case 'Y': - case 'y': - M_RemoveMenu(menu); - Key_Dest_Add(kdm_console); - CL_Disconnect (NULL); - Sys_Quit (); - break; - - default: - return false; - } - - return true; -} + NULL };*/ void Cmd_WriteConfig_f(void); -qboolean MC_SaveQuit_Key (int key, menu_t *menu) +static void M_Menu_DoQuit(void *ctx, int option) { - switch (key) - { - case 'o': - case 'O': - case K_ESCAPE: - case K_GP_BACK: - case K_MOUSE2: - M_RemoveMenu(menu); - break; - - case 'q': - case 'Q': - case 'n': - case 'N': - M_RemoveMenu(menu); -#ifndef FTE_TARGET_WEB - CL_Disconnect (NULL); - Sys_Quit (); -#endif - break; - - case 'Y': - case 'y': - M_RemoveMenu(menu); - Cmd_ExecuteString("cfg_save", RESTRICT_LOCAL); -#ifndef FTE_TARGET_WEB - CL_Disconnect (NULL); - Sys_Quit (); -#endif - break; - - default: - return false; - } - - return true; + if (option == 0) //'yes - quit' + Cmd_ExecuteString("menu_quit force\n", RESTRICT_LOCAL); +// else if (option == 1) //'no - don't quit' +// else if (option == -1) //'cancel - don't quit' +} +static void M_Menu_DoQuitSave(void *ctx, int option) +{ + if (option == 0) //'yes - save-and-quit' + Cmd_ExecuteString("menu_quit forcesave\n", RESTRICT_LOCAL); + else if (option == 1) //'no - nosave-and-quit' + Cmd_ExecuteString("menu_quit force\n", RESTRICT_LOCAL); +// else if (option == -1) //'cancel - don't quit' } //quit menu void M_Menu_Quit_f (void) { - menu_t *quitmenu; int mode; extern cvar_t cfg_save_auto; char *arg = Cmd_Argv(1); @@ -1133,58 +1208,10 @@ void M_Menu_Quit_f (void) #endif break; case 2: - Key_Dest_Add(kdm_emenu); - Key_Dest_Remove(kdm_console); - - quitmenu = M_CreateMenuInfront(0); - quitmenu->key = MC_SaveQuit_Key; - - MC_AddWhiteText(quitmenu, 64, 256, 84, "You have unsaved settings ", 2); - MC_AddWhiteText(quitmenu, 64, 256, 92, " Would you like to ", 2); - MC_AddWhiteText(quitmenu, 64, 256, 100, " save them now? ", 2); - - quitmenu->selecteditem = (menuoption_t *) -#ifdef FTE_TARGET_WEB - MC_AddConsoleCommand (quitmenu, 64, 0, 116, "Yes", "cfg_save; menupop\n"); - MC_AddConsoleCommand (quitmenu, 224,0, 116, "Cancel", "menupop\n"); -#else - MC_AddConsoleCommand (quitmenu, 64, 0, 116, "Yes", "menu_quit forcesave\n"); - MC_AddConsoleCommand (quitmenu, 144,0, 116, "No", "menu_quit force\n"); - MC_AddConsoleCommand (quitmenu, 224,0, 116, "Cancel", "menupop\n"); -#endif - - MC_AddBox (quitmenu, 56, 76, 25, 5); + Menu_Prompt (M_Menu_DoQuitSave, NULL, "You have unsaved settings\nWould you like to\nsave them now?", "Yes", "No", "Cancel"); break; case 1: - Key_Dest_Add(kdm_emenu); - Key_Dest_Remove(kdm_console); - - quitmenu = M_CreateMenuInfront(0); - quitmenu->key = MC_Quit_Key; - - -#ifdef FTE_TARGET_WEB - -// MC_AddWhiteText(quitmenu, 64, 256, 84, " ", 2); - MC_AddWhiteText(quitmenu, 64, 256, 92, " There is nothing to save ", 2); -// MC_AddWhiteText(quitmenu, 64, 256, 100, " ", 2); - - quitmenu->selecteditem = (menuoption_t *) - MC_AddConsoleCommand (quitmenu, 120, 0, 116, "Oh", "menupop\n"); -#else - { - int i = rand()&7; - MC_AddWhiteText(quitmenu, 64, 256, 84, quitMessage[i*4+0], 2); - MC_AddWhiteText(quitmenu, 64, 256, 92, quitMessage[i*4+1], 2); - MC_AddWhiteText(quitmenu, 64, 256, 100, quitMessage[i*4+2], 2); - MC_AddWhiteText(quitmenu, 64, 256, 108, quitMessage[i*4+3], 2); - } - - quitmenu->selecteditem = (menuoption_t *) - MC_AddConsoleCommand (quitmenu, 100, 0, 116, "Quit", "menu_quit force\n"); - MC_AddConsoleCommand (quitmenu, 194, 0, 116, "Cancel", "menupop\n"); -#endif - MC_AddBox (quitmenu, 56, 76, 24, 5); + Menu_Prompt (M_Menu_DoQuit, NULL, quitMessage[rand()%countof(quitMessage)], "Quit", NULL, "Cancel"); break; } } @@ -1435,118 +1462,6 @@ void M_Init (void) #endif -void M_Draw (int uimenu) -{ - qboolean stillactive = false; - - if (uimenu) - { - if (uimenu == 2) - R2D_FadeScreen (); -#ifdef VM_UI - UI_DrawMenu(); -#endif - } - -#ifndef NOBUILTINMENUS - if (!Key_Dest_Has(kdm_emenu)) - { - M_RemoveAllMenus(false); - menu_mousedown = false; - return; - } -#endif - -#ifndef NOBUILTINMENUS - if ((!menu_script || scr_con_current) && !m_recursiveDraw) - { - if (topmenu && topmenu->selecteditem && topmenu->selecteditem->common.type == mt_slider && (topmenu->selecteditem->slider.var == &v_gamma || topmenu->selecteditem->slider.var == &v_contrast)) - /*no menu tint if we're trying to adjust gamma*/; - else - R2D_FadeScreen (); - } - else - { - m_recursiveDraw = false; - } -#endif - - R2D_ImageColours(1, 1, 1, 1); - -#ifdef PLUGINS - if (menuplug) - { - Plug_Menu_Event (0, (int)(realtime*1000)); - stillactive = true; - } -#endif - -#ifndef NOBUILTINMENUS - if (topmenu) - { - M_Complex_Draw (); - stillactive = true; - } -#endif - if (!stillactive) - Key_Dest_Remove(kdm_emenu); -} - - -void M_Keydown (int key, int unicode) -{ -#ifndef NOBUILTINMENUS - if (topmenu) - { - if (key == K_MOUSE1) //mouse clicks are deferred until the release event. this is for touch screens and aiming. - { - if (topmenu->mouseitem && topmenu->mouseitem->common.type == mt_frameend) - topmenu->mouseitem->frame.mousedown = true; - else - menu_mousedown = true; - } - else if (key == K_LSHIFT || key == K_RSHIFT || key == K_LALT || key == K_RALT || key == K_LCTRL || key == K_RCTRL) - ; //modifiers are sent on up events instead. - else - M_Complex_Key (key, unicode); - return; - } -#endif - -#ifdef PLUGINS - if (menuplug) - { - Plug_Menu_Event (1, key); - return; - } -#endif - - Key_Dest_Remove(kdm_emenu); -} - - -void M_Keyup (int key, int unicode) -{ -#ifndef NOBUILTINMENUS - if (topmenu) - { - if (key == K_MOUSE1 && menu_mousedown) - M_Complex_Key (key, unicode); - else if (key == K_LSHIFT || key == K_RSHIFT || key == K_LALT || key == K_RALT || key == K_LCTRL || key == K_RCTRL) - M_Complex_Key (key, unicode); - menu_mousedown = false; - return; - } -#endif -#ifdef PLUGINS - if (menuplug) - { - Plug_Menu_Event (2, key); - return; - } -#endif -} - // Generic function to choose which game menu to draw int M_GameType (void) { diff --git a/engine/client/menu.h b/engine/client/menu.h index f7af2a421..e9cda8bf5 100644 --- a/engine/client/menu.h +++ b/engine/client/menu.h @@ -91,14 +91,38 @@ void M_SomeInitialisationFunctionCalledAtStartup(void) } */ -#ifdef PLUGINS -extern struct plugin_s *menuplug; -#endif -#ifndef NOBUILTINMENUS -extern struct menu_s *topmenu; -#endif void M_DrawTextBox (int x, int y, int width, int lines); +//menus can have all sorts of implementation. +//however, to avoid a cacophony of ugly blends, these are always mutually exclusive - only one type of menu will be at the top and only that one will be drawn. +//if you want windows etc you can implement that inside a single one of these. +//each menu subsystem can implement this and then provide its own widgets. +typedef struct menu_s { + struct menu_s *prev; + + void *ctx; //for finding a specific menu + void (*videoreset) (struct menu_s *); //called after a video mode switch / shader reload. + void (*release) (struct menu_s *); // + qboolean (*keyevent)(struct menu_s *, qboolean isdown, unsigned int devid, int key, int unicode); //true if key was handled + qboolean (*mousemove)(struct menu_s *, qboolean abs, unsigned int devid, float x, float y); + qboolean (*joyaxis) (struct menu_s *, unsigned int devid, int axis, float val); + void (*drawmenu) (struct menu_s *); + struct key_cursor_s *cursor; //NULL for relative motion + qboolean isopaque; //guarentees an opaque background + qboolean persist; //try really hard to not kill this. +} menu_t; +extern menu_t *topmenu; //the currently visible menu. +extern menu_t *promptmenu; //the currently visible prompt (separate from menus, so they always appear over the top of consoles too, they also always show the menu underneath) +void Menu_KeyEvent(qboolean down, int qdeviceid, int key, int unicode); +void Menu_Draw(void); +void Prompts_Draw(void); +void Menu_PopAll(void); //attempts to pop all menus (this is for map starts, some might linger) +void Menu_Unlink(menu_t *menu); +void Menu_Push(menu_t *menu, qboolean prompt); +menu_t *Menu_FindContext(void *ctx); + +void Menu_Prompt (void (*callback)(void *, int), void *ctx, const char *messages, char *optionyes, char *optionno, char *optioncancel); + #ifndef NOBUILTINMENUS // @@ -107,16 +131,12 @@ void M_DrawTextBox (int x, int y, int width, int lines); void M_Init (void); void M_Reinit(void); void M_Shutdown(qboolean total); -void M_Keydown (int key, int unicode); -void M_Keyup (int key, int unicode); -void M_Draw (int uimenu); void M_Menu_Mods_f (void); //used at startup if the current gamedirs look dodgy. void M_Menu_Installer (void); //given an embedded manifest, this displays an install menu for said game. mpic_t *M_CachePic (char *path); void M_Menu_Quit_f (void); -void M_Menu_Prompt (void (*callback)(void *, int), void *ctx, const char *messages, char *optionyes, char *optionno, char *optioncancel); - -struct menu_s; +void menufixme(void); //REMOVE REMOVE REMOVE +typedef struct emenu_s emenu_t; typedef enum { @@ -161,7 +181,7 @@ typedef struct { const char *text; const char *command; qboolean rightalign; - qboolean (*key) (union menuoption_s *option, struct menu_s *, int key); + qboolean (*key) (union menuoption_s *option, struct emenu_s *, int key); } menubutton_t; #define MAX_EDIT_LENGTH 256 @@ -196,7 +216,7 @@ typedef struct menucheck_s { cvar_t *var; int bits; float value; - qboolean (*func) (struct menucheck_s *option, struct menu_s *menu, chk_set_t set); + qboolean (*func) (struct menucheck_s *option, struct emenu_s *menu, chk_set_t set); } menucheck_t; typedef struct { @@ -210,8 +230,8 @@ typedef struct menucustom_s { menucommon_t common; void *dptr; int dint; - void (*draw) (int x, int y, struct menucustom_s *, struct menu_s *); - qboolean (*key) (struct menucustom_s *, struct menu_s *, int key, unsigned int unicode); + void (*draw) (int x, int y, struct menucustom_s *, struct emenu_s *); + qboolean (*key) (struct menucustom_s *, struct emenu_s *, int key, unsigned int unicode); } menucustom_t; typedef struct { @@ -229,9 +249,9 @@ typedef struct { menucommon_t common; int captionwidth; - const char *caption; - const char **options; - const char **values; + char const*caption; + char const*const*options; + char const*const*values; cvar_t *cvar; int numoptions; int selectedoption; @@ -276,7 +296,9 @@ typedef struct menuresel_s //THIS STRUCT MUST BE STATICALLY ALLOCATED. int x, y; } menuresel_t; -typedef struct menu_s { +struct emenu_s { + menu_t menu; + int xpos; int ypos; int width; @@ -286,16 +308,14 @@ typedef struct menu_s { menuresel_t *reselection; //stores some info to restore selection properly. qboolean iszone; - qboolean exclusive; - qboolean persist; //persists despite menuqc/engine changes etc void *data; //typecast - void (*reset) (struct menu_s *); //called after a video mode switch / shader reload. - void (*remove) (struct menu_s *); - qboolean (*key) (int key, struct menu_s *); //true if key was handled - void (*predraw) (struct menu_s *); - void (*postdraw) (struct menu_s *); + void (*reset) (struct emenu_s *); //called after a video mode switch / shader reload. + void (*remove) (struct emenu_s *); + qboolean (*key) (int key, struct emenu_s *); //true if key was handled + void (*predraw) (struct emenu_s *); + void (*postdraw) (struct emenu_s *); menuoption_t *options; menuoption_t *selecteditem; @@ -304,39 +324,36 @@ typedef struct menu_s { menutooltip_t *tooltip; double tooltiptime; - struct menu_s *prev; - struct menu_s *next; - int cursorpos; menuoption_t *cursoritem; -} menu_t; +}; -menutext_t *MC_AddBufferedText(menu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign, qboolean red); -menutext_t *MC_AddRedText(menu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign); -menutext_t *MC_AddWhiteText(menu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign); -menubind_t *MC_AddBind(menu_t *menu, int cx, int bx, int y, const char *caption, char *command, char *tooltip); -menubox_t *MC_AddBox(menu_t *menu, int x, int y, int width, int height); -menupicture_t *MC_AddPicture(menu_t *menu, int x, int y, int width, int height, char *picname); -menupicture_t *MC_AddSelectablePicture(menu_t *menu, int x, int y, int height, char *picname); -menupicture_t *MC_AddCenterPicture(menu_t *menu, int y, int height, char *picname); -menupicture_t *MC_AddCursor(menu_t *menu, menuresel_t *resel, int x, int y); -menuoption_t *MC_AddCursorSmall(menu_t *menu, menuresel_t *reselection, int x, int y); -menuslider_t *MC_AddSlider(menu_t *menu, int tx, int sx, int y, const char *text, cvar_t *var, float min, float max, float delta); -menucheck_t *MC_AddCheckBox(menu_t *menu, int tx, int cx, int y, const char *text, cvar_t *var, int cvarbitmask); -menucheck_t *MC_AddCheckBoxFunc(menu_t *menu, int tx, int cx, int y, const char *text, qboolean (*func) (menucheck_t *option, menu_t *menu, chk_set_t set), int bits); -menubutton_t *MC_AddConsoleCommand(menu_t *menu, int lhs, int rhs, int y, const char *text, const char *command); -menubutton_t *MC_AddConsoleCommandQBigFont(menu_t *menu, int x, int y, const char *text, const char *command); +menutext_t *MC_AddBufferedText(emenu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign, qboolean red); +menutext_t *MC_AddRedText(emenu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign); +menutext_t *MC_AddWhiteText(emenu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign); +menubind_t *MC_AddBind(emenu_t *menu, int cx, int bx, int y, const char *caption, char *command, char *tooltip); +menubox_t *MC_AddBox(emenu_t *menu, int x, int y, int width, int height); +menupicture_t *MC_AddPicture(emenu_t *menu, int x, int y, int width, int height, char *picname); +menupicture_t *MC_AddSelectablePicture(emenu_t *menu, int x, int y, int height, char *picname); +menupicture_t *MC_AddCenterPicture(emenu_t *menu, int y, int height, char *picname); +menupicture_t *MC_AddCursor(emenu_t *menu, menuresel_t *resel, int x, int y); +menuoption_t *MC_AddCursorSmall(emenu_t *menu, menuresel_t *reselection, int x, int y); +menuslider_t *MC_AddSlider(emenu_t *menu, int tx, int sx, int y, const char *text, cvar_t *var, float min, float max, float delta); +menucheck_t *MC_AddCheckBox(emenu_t *menu, int tx, int cx, int y, const char *text, cvar_t *var, int cvarbitmask); +menucheck_t *MC_AddCheckBoxFunc(emenu_t *menu, int tx, int cx, int y, const char *text, qboolean (*func) (menucheck_t *option, emenu_t *menu, chk_set_t set), int bits); +menubutton_t *MC_AddConsoleCommand(emenu_t *menu, int lhs, int rhs, int y, const char *text, const char *command); +menubutton_t *MC_AddConsoleCommandQBigFont(emenu_t *menu, int x, int y, const char *text, const char *command); mpic_t *QBigFontWorks(void); -menubutton_t *MC_AddConsoleCommandHexen2BigFont(menu_t *menu, int x, int y, const char *text, const char *command); -menubutton_t *VARGS MC_AddConsoleCommandf(menu_t *menu, int lhs, int rhs, int y, int rightalign, const char *text, char *command, ...); -menubutton_t *MC_AddCommand(menu_t *menu, int lhs, int rhs, int y, char *text, qboolean (*command) (union menuoption_s *,struct menu_s *,int)); -menucombo_t *MC_AddCombo(menu_t *menu, int tx, int cx, int y, const char *caption, const char **ops, int initialvalue); -menucombo_t *MC_AddCvarCombo(menu_t *menu, int tx, int cx, int y, const char *caption, cvar_t *cvar, const char **ops, const char **values); -menuedit_t *MC_AddEdit(menu_t *menu, int cx, int ex, int y, char *text, char *def); -menuedit_t *MC_AddEditCvar(menu_t *menu, int cx, int ex, int y, char *text, char *name, qboolean slim); -menucustom_t *MC_AddCustom(menu_t *menu, int x, int y, void *dptr, int dint, const char *tooltip); -menuframe_t *MC_AddFrameStart(menu_t *menu, int y); //call before items are added -menuframe_t *MC_AddFrameEnd(menu_t *menu, int y); //and call AFTER that stuff with the same y. +menubutton_t *MC_AddConsoleCommandHexen2BigFont(emenu_t *menu, int x, int y, const char *text, const char *command); +menubutton_t *VARGS MC_AddConsoleCommandf(emenu_t *menu, int lhs, int rhs, int y, int rightalign, const char *text, char *command, ...); +menubutton_t *MC_AddCommand(emenu_t *menu, int lhs, int rhs, int y, char *text, qboolean (*command) (union menuoption_s *,struct emenu_s *,int)); +menucombo_t *MC_AddCombo(emenu_t *menu, int tx, int cx, int y, const char *caption, const char **ops, int initialvalue); +menucombo_t *MC_AddCvarCombo(emenu_t *menu, int tx, int cx, int y, const char *caption, cvar_t *cvar, const char **ops, const char **values); +menuedit_t *MC_AddEdit(emenu_t *menu, int cx, int ex, int y, char *text, char *def); +menuedit_t *MC_AddEditCvar(emenu_t *menu, int cx, int ex, int y, char *text, char *name, qboolean slim); +menucustom_t *MC_AddCustom(emenu_t *menu, int x, int y, void *dptr, int dint, const char *tooltip); +menuframe_t *MC_AddFrameStart(emenu_t *menu, int y); //call before items are added +menuframe_t *MC_AddFrameEnd(emenu_t *menu, int y); //and call AFTER that stuff with the same y. typedef struct menubulk_s { menutype_t type; @@ -346,12 +363,12 @@ typedef struct menubulk_s { char *consolecmd; // console command cvar_t *cvar; // check box, slider int flags; // check box - qboolean (*func) (struct menucheck_s *option, struct menu_s *menu, chk_set_t set); // check box + qboolean (*func) (struct menucheck_s *option, struct emenu_s *menu, chk_set_t set); // check box float min; // slider float max; // slider float delta; // slider qboolean rightalign; // text - qboolean (*command) (union menuoption_s *, struct menu_s *, int); // command + qboolean (*command) (union menuoption_s *, struct emenu_s *, int); // command char *cvarname; // edit cvar const char **options; // combo const char **values; // cvar combo @@ -379,21 +396,17 @@ typedef struct menubulk_s { #define MB_SPACING(space) {mt_text, 2, NULL, NULL, NULL, NULL, 0, NULL, 0, 0, 0, false, NULL, NULL, NULL, NULL, 0, NULL, space} #define MB_END() {mt_text, -1} -int MC_AddBulk(struct menu_s *menu, menuresel_t *resel, menubulk_t *bulk, int xstart, int xtextend, int y); +int MC_AddBulk(emenu_t *menu, menuresel_t *resel, menubulk_t *bulk, int xstart, int xtextend, int y); -menu_t *M_Options_Title(int *y, int infosize); /*Create a menu with the default options titlebar*/ -menu_t *M_CreateMenu (int extrasize); -menu_t *M_CreateMenuInfront (int extrasize); -void M_AddMenu (menu_t *menu); -void M_HideMenu (menu_t *menu); -void M_RemoveMenu (menu_t *menu); +emenu_t *M_Options_Title(int *y, int infosize); /*Create a menu with the default options titlebar*/ +emenu_t *M_CreateMenu (int extrasize); +void M_RemoveMenu (emenu_t *menu); void M_RemoveAllMenus (qboolean leaveprompts); void M_ReloadMenus(void); -void M_Complex_Key(int key, int unicode); -void M_Complex_Draw(void); +void M_Complex_Key(emenu_t *currentmenu, int key, int unicode); void M_Script_Init(void); void M_Serverlist_Init(void); @@ -463,18 +476,14 @@ void M_UnbindCommand (const char *command); #else //no builtin menu code. //stubs -#define M_Menu_Prompt(cb,ctx,messages,optionyes,optionno,optioncancel) (cb)(ctx,-1) //#define M_Shutdown(t) MP_Shutdown() void M_Init (void); void M_Reinit(void); void M_Shutdown(qboolean total); -void M_Keydown (int key, int unicode); -void M_Keyup (int key, int unicode); -void M_Draw (int uimenu); #endif int M_FindKeysForCommand (int bindmap, int pnum, const char *command, int *keylist, int *keymods, int keycount); -int M_FindKeysForBind (int bindmap, const char *command, int *keylist, int *keymods, int keycount); +int QDECL M_FindKeysForBind (int bindmap, const char *command, int *keylist, int *keymods, int keycount); void M_ToggleMenu_f (void); #ifdef MENU_DAT @@ -485,11 +494,6 @@ qboolean MP_Toggle(int mode); void MP_Draw(void); qboolean MP_UsingGamecodeLoadingScreen(void); void MP_RegisterCvarsAndCmds(void); -qboolean MP_Keydown(int key, int unicode, unsigned int devid); -void MP_Keyup(int key, int unicode, unsigned int devid); -qboolean MP_MouseMove(float x, float y, unsigned int devid); -qboolean MP_MousePosition(float x, float y, unsigned int devid); -qboolean MP_JoystickAxis(int axis, float value, unsigned int devid); int MP_BuiltinValid(const char *name, int num); qboolean MP_ConsoleCommand(const char *cmdtext); int MP_GetServerCategory(int index); @@ -509,3 +513,32 @@ qboolean MN_Init(void); #define MGT_HEXEN2 1 #define MGT_QUAKE2 2 int M_GameType(void); + + + + + +//plugin functions +#ifdef PLUGINS +qboolean Plug_CenterPrintMessage(char *buffer, int clientnum); +qboolean Plug_ChatMessage(char *buffer, int talkernum, int tpflags); +void Plug_Command_f(void); +int Plug_ConnectionlessClientPacket(char *buffer, int size); +qboolean Plug_ConsoleLink(char *text, char *info, const char *consolename); +qboolean Plug_ConsoleLinkMouseOver(float x, float y, char *text, char *info); +void Plug_DrawReloadImages(void); +void Plug_Initialise(qboolean fromgamedir); +void Plug_Shutdown(qboolean preliminary); +qboolean Plug_Menu_Event(int eventtype, int keyparam, int unicodeparam); +void Plug_ResChanged(void); +void Plug_SBar(playerview_t *pv); +qboolean Plug_ServerMessage(char *buffer, int messagelevel); +void Plug_Tick(void); +qboolean Plugin_ExecuteString(void); + +#ifdef ANDROID +#define PLUGINPREFIX "libplug_" //android is kinda annoying and only extracts specific files. +#else +#define PLUGINPREFIX "fteplug_" //this string defines what consitutes a plugin, as opposed to some other dll +#endif +#endif \ No newline at end of file diff --git a/engine/client/merged.h b/engine/client/merged.h index 402cd0bcb..6d9c907c5 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -381,6 +381,7 @@ typedef struct texnums_s { texid_t reflectcube; texid_t reflectmask; texid_t displacement; + texid_t occlusion; //occlusion map... //the material's pushconstants. vulkan guarentees only 128 bytes. so 8 vec4s. note that lmscales should want 4 of them... /*struct diff --git a/engine/client/pr_clcmd.c b/engine/client/pr_clcmd.c index b983ba31d..8def47443 100644 --- a/engine/client/pr_clcmd.c +++ b/engine/client/pr_clcmd.c @@ -405,7 +405,7 @@ void QCBUILTIN PF_cl_getkeybind (pubprogfuncs_t *prinst, struct globalvars_s *pr { int bindmap = (prinst->callargc > 1)?G_FLOAT(OFS_PARM1):0; int modifier = (prinst->callargc > 2)?G_FLOAT(OFS_PARM2):0; - char *binding = Key_GetBinding(MP_TranslateQCtoFTECodes(G_FLOAT(OFS_PARM0)), bindmap, modifier); + const char *binding = Key_GetBinding(MP_TranslateQCtoFTECodes(G_FLOAT(OFS_PARM0)), bindmap, modifier); RETURN_TSTRING(binding); } void QCBUILTIN PF_cl_setkeybind (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -472,7 +472,7 @@ void QCBUILTIN PF_cl_setcursormode (pubprogfuncs_t *prinst, struct globalvars_s if (prinst->callargc>1) { - struct key_cursor_s *m = &key_customcursor[(world->keydestmask==kdm_game)?kc_game:kc_menu]; + struct key_cursor_s *m = &key_customcursor[(world->keydestmask==kdm_game)?kc_game:kc_menuqc]; Q_strncpyz(m->name, PR_GetStringOfs(prinst, OFS_PARM1), sizeof(m->name)); m->hotspot[0] = (prinst->callargc>2)?G_FLOAT(OFS_PARM2+0):0; m->hotspot[1] = (prinst->callargc>2)?G_FLOAT(OFS_PARM2+1):0; diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index e2bb674b6..f725b306d 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -2474,7 +2474,7 @@ static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars SCR_TileClear (0); #endif - if (!Key_Dest_Has(kdm_emenu|kdm_gmenu|kdm_cwindows)) + if (!Key_Dest_Has(kdm_menu|kdm_cwindows)) { if (cl.intermissionmode == IM_NQFINALE || cl.intermissionmode == IM_NQCUTSCENE || cl.intermissionmode == IM_H2FINALE) { @@ -6459,27 +6459,27 @@ static struct { // {"?", PF_Fixme, 313}, // #313 //2d (immediate) operations - {"drawtextfield", PF_CL_DrawTextField, 0/*314*/}, - {"drawline", PF_CL_drawline, 315}, // #315 void(float width, vector pos1, vector pos2) drawline (EXT_CSQC) - {"iscachedpic", PF_CL_is_cached_pic, 316}, // #316 float(string name) iscachedpic (EXT_CSQC) - {"precache_pic", PF_CL_precache_pic, 317}, // #317 string(string name, float trywad) precache_pic (EXT_CSQC) - {"r_uploadimage", PF_CL_uploadimage, 0}, - {"r_readimage", PF_CL_readimage, 0}, - {"drawgetimagesize", PF_CL_drawgetimagesize, 318}, // #318 vector(string picname) draw_getimagesize (EXT_CSQC) - {"freepic", PF_CL_free_pic, 319}, // #319 void(string name) freepic (EXT_CSQC) + {"drawtextfield", PF_CL_DrawTextField, 0/*314*/}, + {"drawline", PF_CL_drawline, 315}, // #315 void(float width, vector pos1, vector pos2) drawline (EXT_CSQC) + {"iscachedpic", PF_CL_is_cached_pic, 316}, // #316 float(string name) iscachedpic (EXT_CSQC) + {"precache_pic", PF_CL_precache_pic, 317}, // #317 string(string name, float trywad) precache_pic (EXT_CSQC) + {"r_uploadimage", PF_CL_uploadimage, 0}, + {"r_readimage", PF_CL_readimage, 0}, + {"drawgetimagesize", PF_CL_drawgetimagesize, 318}, // #318 vector(string picname) draw_getimagesize (EXT_CSQC) + {"freepic", PF_CL_free_pic, 319}, // #319 void(string name) freepic (EXT_CSQC) //320 - {"drawcharacter", PF_CL_drawcharacter, 320}, // #320 float(vector position, float character, vector scale, vector rgb, float alpha [, float flag]) drawcharacter (EXT_CSQC, [EXT_CSQC_???]) - {"drawrawstring", PF_CL_drawrawstring, 321}, // #321 float(vector position, string text, vector scale, vector rgb, float alpha [, float flag]) drawstring (EXT_CSQC, [EXT_CSQC_???]) - {"drawpic", PF_CL_drawpic, 322}, // #322 float(vector position, string pic, vector size, vector rgb, float alpha [, float flag]) drawpic (EXT_CSQC, [EXT_CSQC_???]) - {"drawrotpic", PF_CL_drawrotpic, 0}, - {"drawfill", PF_CL_drawfill, 323}, // #323 float(vector position, vector size, vector rgb, float alpha [, float flag]) drawfill (EXT_CSQC, [EXT_CSQC_???]) + {"drawcharacter", PF_CL_drawcharacter, 320}, // #320 float(vector position, float character, vector scale, vector rgb, float alpha [, float flag]) drawcharacter (EXT_CSQC, [EXT_CSQC_???]) + {"drawrawstring", PF_CL_drawrawstring, 321}, // #321 float(vector position, string text, vector scale, vector rgb, float alpha [, float flag]) drawstring (EXT_CSQC, [EXT_CSQC_???]) + {"drawpic", PF_CL_drawpic, 322}, // #322 float(vector position, string pic, vector size, vector rgb, float alpha [, float flag]) drawpic (EXT_CSQC, [EXT_CSQC_???]) + {"drawrotpic", PF_CL_drawrotpic, 0}, + {"drawfill", PF_CL_drawfill, 323}, // #323 float(vector position, vector size, vector rgb, float alpha [, float flag]) drawfill (EXT_CSQC, [EXT_CSQC_???]) {"drawsetcliparea", PF_CL_drawsetcliparea, 324}, // #324 void(float x, float y, float width, float height) drawsetcliparea (EXT_CSQC_???) - {"drawresetcliparea", PF_CL_drawresetcliparea, 325}, // #325 void(void) drawresetcliparea (EXT_CSQC_???) + {"drawresetcliparea", PF_CL_drawresetcliparea, 325}, // #325 void(void) drawresetcliparea (EXT_CSQC_???) - {"drawstring", PF_CL_drawcolouredstring, 326}, // #326 - {"stringwidth", PF_CL_stringwidth, 327}, // #327 EXT_CSQC_'DARKPLACES' - {"drawsubpic", PF_CL_drawsubpic, 328}, // #328 EXT_CSQC_'DARKPLACES' - {"drawrotsubpic", PF_CL_drawrotsubpic, 0}, + {"drawstring", PF_CL_drawcolouredstring, 326}, // #326 + {"stringwidth", PF_CL_stringwidth, 327}, // #327 EXT_CSQC_'DARKPLACES' + {"drawsubpic", PF_CL_drawsubpic, 328}, // #328 EXT_CSQC_'DARKPLACES' + {"drawrotsubpic", PF_CL_drawrotsubpic, 0}, // {"?", PF_Fixme, 329}, // #329 EXT_CSQC_'DARKPLACES' //330 @@ -8177,7 +8177,7 @@ qboolean CSQC_DrawView(void) G_FLOAT(OFS_PARM0) = vid.width; G_FLOAT(OFS_PARM1) = vid.height; } - G_FLOAT(OFS_PARM2) = !Key_Dest_Has(kdm_emenu|kdm_gmenu|kdm_cwindows) && !r_refdef.eyeoffset[0] && !r_refdef.eyeoffset[1]; + G_FLOAT(OFS_PARM2) = !Key_Dest_Has(kdm_menu|kdm_cwindows) && !r_refdef.eyeoffset[0] && !r_refdef.eyeoffset[1]; if (csqcg.f_updateviewloading && cls.state && cls.state < ca_active) PR_ExecuteProgram(csqcprogs, csqcg.f_updateviewloading); diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index 31b448732..5909bc583 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -10,10 +10,14 @@ #if defined(MENU_DAT) || defined(CSQC_DAT) #include "cl_master.h" -qbyte mpkeysdown[K_MAX/8]; +//MP_MouseMove(mx, my, mouse->qdeviceid) +static qbyte mpkeysdown[K_MAX/8]; extern qboolean csqc_dp_lastwas3d; +void M_Init_Internal (void); +void M_DeInit_Internal (void); + extern unsigned int r2d_be_flags; #define DRAWFLAG_NORMAL 0 #define DRAWFLAG_ADD 1 @@ -32,7 +36,9 @@ static unsigned int PF_SelectDPDrawFlag(pubprogfuncs_t *prinst, int flag) PR_RunWarning(prinst, "Detected attempt to draw to framebuffer where framebuffer is not valid\n"); } } +#ifdef CSQC_DAT csqc_dp_lastwas3d = false; //for compat with dp's stupid beginpolygon +#endif //flags: //0 = blend @@ -69,7 +75,9 @@ void QCBUILTIN PF_CL_drawsetcliparea (pubprogfuncs_t *prinst, struct globalvars_ if (R2D_Flush) R2D_Flush(); +#ifdef CSQC_DAT csqc_dp_lastwas3d = false; +#endif srect.x = G_FLOAT(OFS_PARM0) / (float)vid.fbvwidth; srect.y = G_FLOAT(OFS_PARM1) / (float)vid.fbvheight; @@ -88,7 +96,9 @@ void QCBUILTIN PF_CL_drawresetcliparea (pubprogfuncs_t *prinst, struct globalvar if (R2D_Flush) R2D_Flush(); +#ifdef CSQC_DAT csqc_dp_lastwas3d = false; +#endif BE_Scissor(NULL); G_FLOAT(OFS_RETURN) = 1; @@ -720,6 +730,7 @@ void QCBUILTIN PF_CL_precache_pic (pubprogfuncs_t *prinst, struct globalvars_s * G_INT(OFS_RETURN) = 0; } +#ifdef CSQC_DAT //warning: not threaded. void QCBUILTIN PF_CL_uploadimage (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -777,6 +788,7 @@ void QCBUILTIN PF_CL_uploadimage (pubprogfuncs_t *prinst, struct globalvars_s *p } } } +#endif //warning: not threadable. hopefully noone abuses it. void QCBUILTIN PF_CL_readimage (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -1224,7 +1236,30 @@ static struct } menuc_eval; static playerview_t menuview; -int menuentsize; + +static menu_t menuqc; //this is how the client forwards events etc. +static int inmenuprogs; +static progparms_t menuprogparms; +static menuedict_t *menu_edicts; +static int num_menu_edicts; +world_t menu_world; +static int menuentsize; +double menutime; +static struct +{ + func_t init; + func_t shutdown; + func_t draw; + func_t drawloading; + func_t keydown; + func_t keyup; + func_t inputevent; + func_t toggle; + func_t consolecommand; + func_t gethostcachecategory; +} mpfuncs; +jmp_buf mp_abort; + // cvars #define MENUPROGSGROUP "Menu progs control" @@ -1450,9 +1485,10 @@ void QCBUILTIN PF_cl_setkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr { case 0: // key_game - if (Key_Dest_Has(kdm_gmenu)) + if (Key_Dest_Has(kdm_menu)) { - Key_Dest_Remove(kdm_gmenu); + Menu_Unlink(&menuqc); + Key_Dest_Remove(kdm_menu); // Key_Dest_Remove(kdm_message); // if (cls.state == ca_disconnected) // Key_Dest_Add(kdm_console); @@ -1461,9 +1497,9 @@ void QCBUILTIN PF_cl_setkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr case 2: // key_menu Key_Dest_Remove(kdm_message); - if (!Key_Dest_Has(kdm_gmenu)) + if (!Key_Dest_Has(kdm_menu)) Key_Dest_Remove(kdm_console); - Key_Dest_Add(kdm_gmenu); + Menu_Push(&menuqc, false); break; case 1: // key_message @@ -1477,9 +1513,7 @@ void QCBUILTIN PF_cl_setkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr //float getkeydest(void) = #602; void QCBUILTIN PF_cl_getkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { - if (Key_Dest_Has(kdm_emenu)) - G_FLOAT(OFS_RETURN) = 3; - else if (Key_Dest_Has(kdm_gmenu)) + if (Key_Dest_Has(kdm_menu)) G_FLOAT(OFS_RETURN) = 2; // else if (Key_Dest_Has(kdm_message)) // G_FLOAT(OFS_RETURN) = 1; @@ -2191,17 +2225,23 @@ static struct { {"clearscene", PF_m_clearscene, 300}, //no addentities {"addentity", PF_m_addentity, 302},//FIXME: needs setmodel, origin, angles, colormap(eep), frame etc, skin, +#ifdef CSQC_DAT {"setproperty", PF_R_SetViewFlag, 303},//should be okay to share +#endif {"renderscene", PF_m_renderscene, 304},//too module-specific // {"dynamiclight_add", PF_R_DynamicLight_Add, 305},//should be okay to share {"R_BeginPolygon", PF_R_PolygonBegin, 306},//useful for 2d stuff {"R_PolygonVertex", PF_R_PolygonVertex, 307}, {"R_EndPolygon", PF_R_PolygonEnd, 308}, +#ifdef CSQC_DAT {"getproperty", PF_R_GetViewFlag, 309},//should be okay to share +#endif //unproject 310 //project 311 +#ifdef CSQC_DAT {"r_uploadimage", PF_CL_uploadimage, 0}, +#endif {"r_readimage", PF_CL_readimage, 0}, @@ -2361,7 +2401,7 @@ static struct { {"getgamedirinfo", PF_cl_getgamedirinfo, 626}, {"sprintf", PF_sprintf, 627}, //gap - {"setkeybind", PF_Fixme, 630}, + {"setkeybind", PF_cl_setkeybind, 630}, {"getbindmaps", PF_cl_GetBindMap, 631}, {"setbindmaps", PF_cl_SetBindMap, 632}, {"crypto_getkeyfp", PF_crypto_getkeyfp, 633}, @@ -2437,37 +2477,142 @@ static int PDECL PR_Menu_MapNamedBuiltin(pubprogfuncs_t *progfuncs, int headercr return 0; } -void M_Init_Internal (void); -void M_DeInit_Internal (void); -int inmenuprogs; -progparms_t menuprogparms; -menuedict_t *menu_edicts; -int num_menu_edicts; -world_t menu_world; - -static struct +static qboolean MP_MouseMove(menu_t *menu, qboolean isabs, unsigned int devid, float xdelta, float ydelta) { - func_t init; - func_t shutdown; - func_t draw; - func_t drawloading; - func_t keydown; - func_t keyup; - func_t inputevent; - func_t toggle; - func_t consolecommand; - func_t gethostcachecategory; -} mpfuncs; + void *pr_globals; -jmp_buf mp_abort; + if (!menu_world.progs || !mpfuncs.inputevent) + return false; + if (setjmp(mp_abort)) + return false; + inmenuprogs++; + pr_globals = PR_globals(menu_world.progs, PR_CURRENT); + G_FLOAT(OFS_PARM0) = isabs?CSIE_MOUSEABS:CSIE_MOUSEDELTA; + G_FLOAT(OFS_PARM1) = (xdelta * vid.width) / vid.pixelwidth; + G_FLOAT(OFS_PARM2) = (ydelta * vid.height) / vid.pixelheight; + G_FLOAT(OFS_PARM3) = devid; + PR_ExecuteProgram (menu_world.progs, mpfuncs.inputevent); + if (R2D_Flush) + R2D_Flush(); + inmenuprogs--; + return G_FLOAT(OFS_RETURN); +} + +static qboolean MP_JoystickAxis(menu_t *menu, unsigned int devid, int axis, float value) +{ + void *pr_globals; + if (!menu_world.progs || !mpfuncs.inputevent) + return false; + if (setjmp(mp_abort)) + return false; + inmenuprogs++; + pr_globals = PR_globals(menu_world.progs, PR_CURRENT); + G_FLOAT(OFS_PARM0) = CSIE_JOYAXIS; + G_FLOAT(OFS_PARM1) = axis; + G_FLOAT(OFS_PARM2) = value; + G_FLOAT(OFS_PARM3) = devid; + PR_ExecuteProgram (menu_world.progs, mpfuncs.inputevent); + if (R2D_Flush) + R2D_Flush(); + inmenuprogs--; + return G_FLOAT(OFS_RETURN); +} +static qboolean MP_KeyEvent(menu_t *menu, qboolean isdown, unsigned int devid, int key, int unicode) +{ + qboolean result; + +#ifdef TEXTEDITOR + if (editormodal) + return false; +#endif + + if (setjmp(mp_abort)) + return true; + + if (isdown) + { +#ifndef NOBUILTINMENUS + if (key == 'c') + { + extern qboolean keydown[K_MAX]; + if (keydown[K_LCTRL] || keydown[K_RCTRL]) + { + MP_Shutdown(); + M_Init_Internal(); + return true; + } + } +#endif + + mpkeysdown[key>>3] |= (1<<(key&7)); + } + else + { //don't fire up events if it was not actually pressed. + if (key && !(mpkeysdown[key>>3] & (1<<(key&7)))) + return false; + mpkeysdown[key>>3] &= ~(1<<(key&7)); + } + + menutime = Sys_DoubleTime(); + if (menu_world.g.time) + *menu_world.g.time = menutime; + + inmenuprogs++; + if (mpfuncs.inputevent) + { + void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT); + G_FLOAT(OFS_PARM0) = isdown?CSIE_KEYDOWN:CSIE_KEYUP; + G_FLOAT(OFS_PARM1) = MP_TranslateFTEtoQCCodes(key); + G_FLOAT(OFS_PARM2) = unicode; + G_FLOAT(OFS_PARM3) = devid; + if (isdown) + { + qcinput_scan = G_FLOAT(OFS_PARM1); + qcinput_unicode = G_FLOAT(OFS_PARM2); + } + PR_ExecuteProgram(menu_world.progs, mpfuncs.inputevent); + result = G_FLOAT(OFS_RETURN); + qcinput_scan = 0; + qcinput_unicode = 0; + } + else if (isdown && mpfuncs.keydown) + { + void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT); + G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoQCCodes(key); + G_FLOAT(OFS_PARM1) = unicode; + PR_ExecuteProgram(menu_world.progs, mpfuncs.keydown); + result = true; //doesn't have a return value, so if the menu is set up for key events, all events are considered eaten. + } + else if (!isdown && mpfuncs.keyup) + { + void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT); + G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoQCCodes(key); + G_FLOAT(OFS_PARM1) = unicode; + PR_ExecuteProgram(menu_world.progs, mpfuncs.keyup); + result = false; // doesn't have a return value, so don't block it + } + else + result = false; + inmenuprogs--; + + if (R2D_Flush) //shouldn't be needed, but in case the mod is buggy. + R2D_Flush(); + return result; +} +static void MP_TryRelease(menu_t *m) +{ + MP_Toggle(0); +} void MP_Shutdown (void) { func_t temp; if (!menu_world.progs) return; + + Menu_Unlink(&menuqc); /* { char *buffer; @@ -2486,7 +2631,7 @@ void MP_Shutdown (void) PR_Common_Shutdown(menu_world.progs, false); menu_world.progs->CloseProgs(menu_world.progs); memset(&menu_world, 0, sizeof(menu_world)); - PR_ReleaseFonts(kdm_gmenu); + PR_ReleaseFonts(kdm_menu); #ifdef CL_MASTER Master_ClearMasks(); @@ -2494,8 +2639,8 @@ void MP_Shutdown (void) Cmd_RemoveCommands(MP_ConsoleCommand_f); - Key_Dest_Remove(kdm_gmenu); - key_dest_absolutemouse &= ~kdm_gmenu; + Key_Dest_Remove(kdm_menu); + key_dest_absolutemouse &= ~kdm_menu; } void *VARGS PR_CB_Malloc(int size); //these functions should be tracked by the library reliably, so there should be no need to track them ourselves. @@ -2582,10 +2727,9 @@ static int PDECL MP_PRFileSize (const char *path) return -1; } -double menutime; qboolean MP_Init (void) { - struct key_cursor_s *m = &key_customcursor[kc_menu]; + struct key_cursor_s *m = &key_customcursor[kc_menuqc]; if (qrenderer == QR_NONE) { @@ -2639,16 +2783,22 @@ qboolean MP_Init (void) menuprogparms.useeditor = QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms); menuprogparms.user = &menu_world; - menu_world.keydestmask = kdm_gmenu; + menu_world.keydestmask = kdm_menu; //default to free mouse+hidden cursor, to match dp's default setting, and because its generally the right thing for a menu. - key_dest_absolutemouse |= kdm_gmenu; Q_strncpyz(m->name, "none", sizeof(m->name)); m->hotspot[0] = 0; m->hotspot[1] = 0; m->scale = 1; m->dirty = true; + menuqc.cursor = &key_customcursor[kc_menuqc]; + menuqc.drawmenu = NULL; //menuqc sucks! + menuqc.mousemove = MP_MouseMove; + menuqc.keyevent = MP_KeyEvent; + menuqc.joyaxis = MP_JoystickAxis; + menuqc.release = MP_TryRelease; + menutime = Sys_DoubleTime(); if (!menu_world.progs) { @@ -2890,168 +3040,6 @@ void MP_Draw(void) inmenuprogs--; } - -qboolean MP_Keydown(int key, int unicode, unsigned int devid) -{ - qboolean result = false; - -#ifdef TEXTEDITOR - if (editormodal) - return true; -#endif - - if (setjmp(mp_abort)) - return true; - -#ifndef NOBUILTINMENUS - if (key == 'c') - { - extern qboolean keydown[K_MAX]; - if (keydown[K_LCTRL] || keydown[K_RCTRL]) - { - MP_Shutdown(); - M_Init_Internal(); - return true; - } - } -#endif - - mpkeysdown[key>>3] |= (1<<(key&7)); - - menutime = Sys_DoubleTime(); - if (menu_world.g.time) - *menu_world.g.time = menutime; - - inmenuprogs++; - if (mpfuncs.inputevent) - { - void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT); - G_FLOAT(OFS_PARM0) = CSIE_KEYDOWN; - G_FLOAT(OFS_PARM1) = qcinput_scan = MP_TranslateFTEtoQCCodes(key); - G_FLOAT(OFS_PARM2) = qcinput_unicode = unicode; - G_FLOAT(OFS_PARM3) = devid; - PR_ExecuteProgram(menu_world.progs, mpfuncs.inputevent); - result = G_FLOAT(OFS_RETURN); - qcinput_scan = 0; - qcinput_unicode = 0; - } - else if (mpfuncs.keydown) - { - void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT); - G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoQCCodes(key); - G_FLOAT(OFS_PARM1) = unicode; - PR_ExecuteProgram(menu_world.progs, mpfuncs.keydown); - result = true; //doesn't have a return value, so if the menu is set up for key events, all events are considered eaten. - } - if (R2D_Flush) - R2D_Flush(); - inmenuprogs--; - return result; -} - -void MP_Keyup(int key, int unicode, unsigned int devid) -{ -#ifdef TEXTEDITOR - if (editormodal) - return; -#endif - - if (setjmp(mp_abort)) - return; - - if (key && !(mpkeysdown[key>>3] & (1<<(key&7)))) - return; - mpkeysdown[key>>3] &= ~(1<<(key&7)); - - menutime = Sys_DoubleTime(); - if (menu_world.g.time) - *menu_world.g.time = menutime; - - inmenuprogs++; - if (mpfuncs.inputevent) - { - void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT); - G_FLOAT(OFS_PARM0) = CSIE_KEYUP; - G_FLOAT(OFS_PARM1) = MP_TranslateFTEtoQCCodes(key); - G_FLOAT(OFS_PARM2) = unicode; - G_FLOAT(OFS_PARM3) = devid; - PR_ExecuteProgram(menu_world.progs, mpfuncs.inputevent); - } - else if (mpfuncs.keyup) - { - void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT); - G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoQCCodes(key); - G_FLOAT(OFS_PARM1) = unicode; - PR_ExecuteProgram(menu_world.progs, mpfuncs.keyup); - } - if (R2D_Flush) - R2D_Flush(); - inmenuprogs--; -} - -qboolean MP_MousePosition(float xabs, float yabs, unsigned int devid) -{ - void *pr_globals; - - if (!menu_world.progs || !mpfuncs.inputevent) - return false; - - if (setjmp(mp_abort)) - return false; - inmenuprogs++; - pr_globals = PR_globals(menu_world.progs, PR_CURRENT); - G_FLOAT(OFS_PARM0) = CSIE_MOUSEABS; - G_FLOAT(OFS_PARM1) = (xabs * vid.width) / vid.pixelwidth; - G_FLOAT(OFS_PARM2) = (yabs * vid.height) / vid.pixelheight; - G_FLOAT(OFS_PARM3) = devid; - PR_ExecuteProgram (menu_world.progs, mpfuncs.inputevent); - if (R2D_Flush) - R2D_Flush(); - inmenuprogs--; - return G_FLOAT(OFS_RETURN); -} -qboolean MP_MouseMove(float xdelta, float ydelta, unsigned int devid) -{ - void *pr_globals; - - if (!menu_world.progs || !mpfuncs.inputevent) - return false; - - if (setjmp(mp_abort)) - return false; - inmenuprogs++; - pr_globals = PR_globals(menu_world.progs, PR_CURRENT); - G_FLOAT(OFS_PARM0) = CSIE_MOUSEDELTA; - G_FLOAT(OFS_PARM1) = (xdelta * vid.width) / vid.pixelwidth; - G_FLOAT(OFS_PARM2) = (ydelta * vid.height) / vid.pixelheight; - G_FLOAT(OFS_PARM3) = devid; - PR_ExecuteProgram (menu_world.progs, mpfuncs.inputevent); - if (R2D_Flush) - R2D_Flush(); - inmenuprogs--; - return G_FLOAT(OFS_RETURN); -} - -qboolean MP_JoystickAxis(int axis, float value, unsigned int devid) -{ - void *pr_globals; - if (!menu_world.progs || !mpfuncs.inputevent) - return false; - if (setjmp(mp_abort)) - return false; - inmenuprogs++; - pr_globals = PR_globals(menu_world.progs, PR_CURRENT); - G_FLOAT(OFS_PARM0) = CSIE_JOYAXIS; - G_FLOAT(OFS_PARM1) = axis; - G_FLOAT(OFS_PARM2) = value; - G_FLOAT(OFS_PARM3) = devid; - PR_ExecuteProgram (menu_world.progs, mpfuncs.inputevent); - if (R2D_Flush) - R2D_Flush(); - inmenuprogs--; - return G_FLOAT(OFS_RETURN); -} - qboolean MP_Toggle(int mode) { if (!menu_world.progs) @@ -3061,7 +3049,7 @@ qboolean MP_Toggle(int mode) return false; #endif - if (!mode && !Key_Dest_Has(kdm_gmenu)) + if (!mode && !Key_Dest_Has(kdm_menu)) return false; if (setjmp(mp_abort)) diff --git a/engine/client/pr_skelobj.c b/engine/client/pr_skelobj.c index e0991c9b1..310025e88 100644 --- a/engine/client/pr_skelobj.c +++ b/engine/client/pr_skelobj.c @@ -965,7 +965,7 @@ void skel_info_f(void) { if (skelobjects[i].world) { -#ifndef SERVERONLY +#if defined(HAVE_CLIENT) && defined(CSQC_DAT) extern world_t csqc_world; #endif Con_Printf("doll %i:\n", i); @@ -973,7 +973,7 @@ void skel_info_f(void) if (skelobjects[i].world == &sv.world) Con_Printf(" SSQC\n"); #endif -#ifndef SERVERONLY +#if defined(HAVE_CLIENT) && defined(CSQC_DAT) if (skelobjects[i].world == &csqc_world) Con_Printf(" CSQC\n"); #endif diff --git a/engine/client/render.h b/engine/client/render.h index d1c415de2..d9e773b98 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -564,7 +564,6 @@ extern const size_t lightthreadctxsize; extern struct model_s *currentmodel; -qboolean Media_ShowFilm(void); void Media_CaptureDemoEnd(void); void Media_RecordFrame (void); qboolean Media_PausedDemo (qboolean fortiming); diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 0bf209ccb..6b50793d6 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -2224,13 +2224,6 @@ qboolean Sbar_ShouldDraw (playerview_t *pv) return false; #endif -#ifdef VM_UI - if (UI_DrawStatusBar((pv->sb_showscores?1:0) + (pv->sb_showteamscores?2:0))>0) - return false; - if (UI_MenuState()) - return false; -#endif - headsup = !(cl_sbar.value || (scr_viewsize.value<100)); if ((sb_updates >= vid.numpages) && !headsup) return false; @@ -3803,11 +3796,6 @@ Sbar_IntermissionOverlay */ void Sbar_IntermissionOverlay (playerview_t *pv) { -#ifdef VM_UI - if (UI_DrawIntermission()>0) - return; -#endif - Sbar_Start(); if (!cls.deathmatch) diff --git a/engine/client/screen.h b/engine/client/screen.h index f0afd8c7c..da4cf8e1e 100644 --- a/engine/client/screen.h +++ b/engine/client/screen.h @@ -233,7 +233,7 @@ typedef enum uploadfmt qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void **buffer, int numbuffers, qintptr_t bytestride, int width, int height, enum uploadfmt fmt, qboolean writemeta); -void SCR_DrawTwoDimensional(int uimenu, qboolean nohud); +void SCR_DrawTwoDimensional(qboolean nohud); enum { diff --git a/engine/client/snd_al.c b/engine/client/snd_al.c index d219f1362..2bf639411 100644 --- a/engine/client/snd_al.c +++ b/engine/client/snd_al.c @@ -127,6 +127,7 @@ static AL_API void (AL_APIENTRY *palSourceQueueBuffers)(ALuint source, ALsizei n static AL_API void (AL_APIENTRY *palSourceUnqueueBuffers)(ALuint source, ALsizei n, ALuint* buffers); //for extensions like efx +static AL_API ALboolean (AL_APIENTRY *palIsExtensionPresent)(const ALchar *fextame); static AL_API void*(AL_APIENTRY *palGetProcAddress)(const ALchar *fname); #define AL_NONE 0 @@ -288,6 +289,10 @@ static AL_API ALvoid (AL_APIENTRY *palEffectf)(ALuint effect, ALenum param, ALfl static AL_API ALvoid (AL_APIENTRY *palEffectfv)(ALuint effect, ALenum param, const ALfloat *pflValues); #endif +//AL_EXT_float32 +#define AL_FORMAT_MONO_FLOAT32 0x10010 +#define AL_FORMAT_STEREO_FLOAT32 0x10011 + #define SOUNDVARS SDRVNAME" variables" @@ -342,6 +347,10 @@ typedef struct ALfloat ListenVel[3]; // Velocity of the listener. ALfloat ListenOri[6]; // Orientation of the listener. (first 3 elements are "at", second 3 are "up") +#ifdef MIXER_F32 + qboolean canfloataudio; +#endif + int cureffect; ALuint effectslot; //the global reverb slot size_t numeffecttypes; @@ -384,7 +393,7 @@ static void PrintALError(char *string) Con_Printf("OpenAL - %s: %x: %s\n",string,err,text); } -static qboolean OpenAL_LoadCache(unsigned int *bufptr, sfxcache_t *sc, float volume) +static qboolean OpenAL_LoadCache(oalinfo_t *oali, unsigned int *bufptr, sfxcache_t *sc, float volume) { unsigned int fmt; unsigned int size; @@ -421,6 +430,22 @@ static qboolean OpenAL_LoadCache(unsigned int *bufptr, sfxcache_t *sc, float vol size = sc->length*2; } break; +#ifdef MIXER_F32 + case 4: + if (!oali->canfloataudio) + return false; + if (sc->numchannels == 2) + { + fmt = AL_FORMAT_STEREO_FLOAT32; + size = sc->length*8; + } + else + { + fmt = AL_FORMAT_MONO_FLOAT32; + size = sc->length*4; + } + break; +#endif default: return false; } @@ -461,6 +486,20 @@ static qboolean OpenAL_LoadCache(unsigned int *bufptr, sfxcache_t *sc, float vol palBufferData(*bufptr, fmt, tmp, size, sc->speed); free(tmp); } +#ifdef MIXER_F32 + else if (sc->width == 4) + { + float *tmp = malloc(size); + float *src = (float*)sc->data; + int i; + for (i = 0; i < (size>>1); i++) + { + tmp[i] = src[i]*volume; //signed. oversaturation isn't my problem + } + palBufferData(*bufptr, fmt, tmp, size, sc->speed); + free(tmp); + } +#endif } else { @@ -476,7 +515,7 @@ static qboolean OpenAL_LoadCache(unsigned int *bufptr, sfxcache_t *sc, float vol palBufferData(*bufptr, fmt, tmp, size, sc->speed); free(tmp); } - else if (sc->width == 2) + else if (sc->width == 2 || sc->width == 4) { #if 0 short *tmp = malloc(size); @@ -762,7 +801,7 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned { //build a buffer with it and queue it up. //buffer will be purged later on when its unqueued - OpenAL_LoadCache(&buf, &sbuf, max(1,cvolume)); + OpenAL_LoadCache(oali, &buf, &sbuf, max(1,cvolume)); palSourceQueueBuffers(src, 1, &buf); } else @@ -774,7 +813,7 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned silence.data = NULL; silence.length = 0.1 * silence.speed; silence.soundoffset = 0; - OpenAL_LoadCache(&buf, &silence, 1); + OpenAL_LoadCache(oali, &buf, &silence, 1); palSourceQueueBuffers(src, 1, &buf); } queuedbufs++; @@ -803,7 +842,7 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned silence.data = NULL; silence.length = 0.1 * silence.speed; silence.soundoffset = 0; - OpenAL_LoadCache(&buf, &silence, 1); + OpenAL_LoadCache(oali, &buf, &silence, 1); palSourceQueueBuffers(src, 1, &buf); queuedbufs++; } @@ -828,7 +867,7 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned { if (!sfx->decoder.buf) return; - if (!OpenAL_LoadCache(&sfx->openal_buffer, sfx->decoder.buf, 1)) + if (!OpenAL_LoadCache(oali, &sfx->openal_buffer, sfx->decoder.buf, 1)) return; palSourcei(src, AL_BUFFER, sfx->openal_buffer); } @@ -1016,6 +1055,7 @@ static qboolean OpenAL_InitLibrary(void) {(void*)&palSpeedOfSound, "alSpeedOfSound"}, {(void*)&palDistanceModel, "alDistanceModel"}, + {(void*)&palIsExtensionPresent, "alIsExtensionPresent"}, {(void*)&palGetProcAddress, "alGetProcAddress"}, {(void*)&palGetSourcei, "alGetSourcei"}, {(void*)&palSourceQueueBuffers, "alSourceQueueBuffers"}, @@ -1383,6 +1423,9 @@ static qboolean QDECL OpenAL_InitCard(soundcardinfo_t *sc, const char *devname) sc->Submit = OpenAL_Submit; sc->GetDMAPos = OpenAL_GetDMAPos; +#ifdef MIXER_F32 + oali->canfloataudio = palIsExtensionPresent("AL_EXT_float32"); +#endif sc->inactive_sound = true; sc->selfpainting = true; diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index 5cd10f2c9..c9ad2fb37 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -4196,6 +4196,7 @@ void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels, double speedfactor; qbyte *newcache; streaming_t *s, *free=NULL; + for (s = s_streamers, i = 0; i < MAX_RAW_SOURCES; i++, s++) { if (!s->inuse) diff --git a/engine/client/snd_mem.c b/engine/client/snd_mem.c index 1acde12bb..92790178f 100644 --- a/engine/client/snd_mem.c +++ b/engine/client/snd_mem.c @@ -794,34 +794,51 @@ static qboolean QDECL S_LoadBrowserFile (sfx_t *s, qbyte *data, size_t datalen, #endif //highest priority is last. -static S_LoadSound_t AudioInputPlugins[10] = +static struct +{ + S_LoadSound_t loadfunc; + void *module; +} AudioInputPlugins[10] = { #ifdef FTE_TARGET_WEB - S_LoadBrowserFile, + {S_LoadBrowserFile}, #endif #ifdef AVAIL_OGGVORBIS - S_LoadOVSound, + {S_LoadOVSound}, #endif - S_LoadWavSound, + {S_LoadWavSound}, #ifdef PACKAGE_DOOMWAD - S_LoadDoomSound, -// S_LoadDoomSpeakerSound, + {S_LoadDoomSound}, +// {S_LoadDoomSpeakerSound}, #endif }; -qboolean S_RegisterSoundInputPlugin(S_LoadSound_t loadfnc) +qboolean S_RegisterSoundInputPlugin(void *module, S_LoadSound_t loadfnc) { int i; for (i = 0; i < sizeof(AudioInputPlugins)/sizeof(AudioInputPlugins[0]); i++) { - if (!AudioInputPlugins[i]) + if (!AudioInputPlugins[i].loadfunc) { - AudioInputPlugins[i] = loadfnc; + AudioInputPlugins[i].module = module; + AudioInputPlugins[i].loadfunc = loadfnc; return true; } } return false; } +void S_UnregisterSoundInputModule(void *module) +{ //unregister all sound handlers for the given module. + int i; + for (i = 0; i < sizeof(AudioInputPlugins)/sizeof(AudioInputPlugins[0]); i++) + { + if (AudioInputPlugins[i].module == module) + { + AudioInputPlugins[i].module = NULL; + AudioInputPlugins[i].loadfunc = NULL; + } + } +} static void S_LoadedOrFailed (void *ctx, void *ctxdata, size_t a, size_t b) { @@ -941,9 +958,9 @@ static void S_LoadSoundWorker (void *ctx, void *ctxdata, size_t forcedecode, siz for (i = sizeof(AudioInputPlugins)/sizeof(AudioInputPlugins[0])-1; i >= 0; i--) { - if (AudioInputPlugins[i]) + if (AudioInputPlugins[i].loadfunc) { - if (AudioInputPlugins[i](s, data, filesize, snd_speed, forcedecode)) + if (AudioInputPlugins[i].loadfunc(s, data, filesize, snd_speed, forcedecode)) { //wake up the main thread in case it decided to wait for us. COM_AddWork(WG_MAIN, S_LoadedOrFailed, s, NULL, SLS_LOADED, 0); diff --git a/engine/client/snd_mix.c b/engine/client/snd_mix.c index 392f61be0..9dabf3438 100644 --- a/engine/client/snd_mix.c +++ b/engine/client/snd_mix.c @@ -157,6 +157,14 @@ static void SND_PaintChannel16_O8I1 (channel_t *ch, sfxcache_t *sc, int count, i static void SND_PaintChannel8_O2I2 (channel_t *ch, sfxcache_t *sc, int starttime, int count, int rate); static void SND_PaintChannel16_O2I2 (channel_t *ch, sfxcache_t *sc, int starttime, int count, int rate); +#ifdef MIXER_F32 +static void SND_PaintChannel32F_O2I1(channel_t *ch, sfxcache_t *sc, int starttime, int count, int rate); +static void SND_PaintChannel32F_O4I1(channel_t *ch, sfxcache_t *sc, int count, int rate); +static void SND_PaintChannel32F_O6I1(channel_t *ch, sfxcache_t *sc, int count, int rate); +static void SND_PaintChannel32F_O8I1(channel_t *ch, sfxcache_t *sc, int count, int rate); +static void SND_PaintChannel32F_O2I2(channel_t *ch, sfxcache_t *sc, int starttime, int count, int rate); +#endif + //NOTE: MAY NOT CALL SYS_ERROR void S_PaintChannels(soundcardinfo_t *sc, int endtime) { @@ -329,6 +337,21 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime) else SND_PaintChannel16_O8I1(ch, scache, count, rate); } +#ifdef MIXER_F32 + else if (scache->width == 4) + { + if (scache->numchannels==2) + SND_PaintChannel32F_O2I2(ch, scache, ltime-sc->paintedtime, count, rate); + else if (sc->sn.numchannels <= 2) + SND_PaintChannel32F_O2I1(ch, scache, ltime-sc->paintedtime, count, rate); + else if (sc->sn.numchannels <= 4) + SND_PaintChannel32F_O4I1(ch, scache, count, rate); + else if (sc->sn.numchannels <= 6) + SND_PaintChannel32F_O6I1(ch, scache, count, rate); + else + SND_PaintChannel32F_O8I1(ch, scache, count, rate); + } +#endif ltime += count; ch->pos += rate * count; } @@ -720,4 +743,214 @@ static void SND_PaintChannel16_O8I1 (channel_t *ch, sfxcache_t *sc, int count, i } } } + +#ifdef MIXER_F32 +static void SND_PaintChannel32F_O2I1 (channel_t *ch, sfxcache_t *sc, int starttime, int count, int rate) +{ + float data; + int left, right; + int leftvol, rightvol; + float *sfx; + int i; + unsigned int pos = ch->pos-(sc->soundoffset<vol[0]*128; + rightvol = ch->vol[1]*128; + + if (rate != (1<data; + for (i=0 ; i>PITCHSHIFT] * (1-frac) + sfx[(pos>>PITCHSHIFT)+1] * frac; + pos += rate; + paintbuffer[starttime+i].s[0] += (leftvol * data); + paintbuffer[starttime+i].s[1] += (rightvol * data); + } + } + else + { + sfx = (float *)sc->data + (pos>>PITCHSHIFT); + for (i=0 ; ipos-(sc->soundoffset<vol[0]*128; + rightvol = ch->vol[1]*128; + + if (rate != (1<data; + for (i=0 ; i>(PITCHSHIFT-1))&~1]; + r = sfx[(pos>>(PITCHSHIFT-1))|1]; + pos += rate; + paintbuffer[starttime+i].s[0] += (l * leftvol); + paintbuffer[starttime+i].s[1] += (r * rightvol); + } + } + else + { + sfx = (float *)sc->data + (pos>>PITCHSHIFT)*2; + for (i=0 ; ipos-(sc->soundoffset<vol[0]*128; + vol[1] = ch->vol[1]*128; + vol[2] = ch->vol[2]*128; + vol[3] = ch->vol[3]*128; + + if (rate != (1<data; + for (i=0 ; i>PITCHSHIFT]; + pos += rate; + paintbuffer[i].s[0] += (vol[0] * data); + paintbuffer[i].s[1] += (vol[1] * data); + paintbuffer[i].s[2] += (vol[2] * data); + paintbuffer[i].s[3] += (vol[3] * data); + } + } + else + { + sfx = (float *)sc->data + (pos>>PITCHSHIFT); + for (i=0 ; ipos-(sc->soundoffset<vol[0]*128; + vol[1] = ch->vol[1]*128; + vol[2] = ch->vol[2]*128; + vol[3] = ch->vol[3]*128; + vol[4] = ch->vol[4]*128; + vol[5] = ch->vol[5]*128; + + if (rate != (1<data; + for (i=0 ; i>PITCHSHIFT]; + pos += rate; + paintbuffer[i].s[0] += (vol[0] * data); + paintbuffer[i].s[1] += (vol[1] * data); + paintbuffer[i].s[2] += (vol[2] * data); + paintbuffer[i].s[3] += (vol[3] * data); + paintbuffer[i].s[4] += (vol[4] * data); + paintbuffer[i].s[5] += (vol[5] * data); + } + } + else + { + sfx = (float *)sc->data + (pos>>PITCHSHIFT); + for (i=0 ; ipos-(sc->soundoffset<vol is 0-255, so we just need to scale up by an extra 128 + vol[0] = ch->vol[0]*128; + vol[1] = ch->vol[1]*128; + vol[2] = ch->vol[2]*128; + vol[3] = ch->vol[3]*128; + vol[4] = ch->vol[4]*128; + vol[5] = ch->vol[5]*128; + vol[6] = ch->vol[6]*128; + vol[7] = ch->vol[7]*128; + + if (rate != (1<data; + for (i=0 ; i>PITCHSHIFT]; + pos += rate; + paintbuffer[i].s[0] += (vol[0] * data); + paintbuffer[i].s[1] += (vol[1] * data); + paintbuffer[i].s[2] += (vol[2] * data); + paintbuffer[i].s[3] += (vol[3] * data); + paintbuffer[i].s[4] += (vol[4] * data); + paintbuffer[i].s[5] += (vol[5] * data); + paintbuffer[i].s[6] += (vol[6] * data); + paintbuffer[i].s[7] += (vol[7] * data); + } + } + else + { + sfx = (float *)sc->data + (pos>>PITCHSHIFT); + for (i=0 ; iselstartline, n); } } + con->userline = con->selstartline; + con->useroffset = con->selstartoffset; } - con->userline = con->selstartline; - con->useroffset = con->selstartoffset; } static void Con_Editor_DoPaste(void *ctx, char *utf8) { @@ -850,7 +850,7 @@ qboolean Con_Editor_Close(console_t *con, qboolean force) { if (!strncmp(con->title, "MODIFIED: ", 10)) { - M_Menu_Prompt(Con_Editor_CloseCallback, con, va("Save changes?\n%s\n", con->name), "Yes", "No", "Cancel"); + Menu_Prompt(Con_Editor_CloseCallback, con, va("Save changes?\n%s\n", con->name), "Yes", "No", "Cancel"); return false; } } diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 2f7df39a0..0388c27c8 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -175,7 +175,6 @@ extern cvar_t host_mapname; void TP_UpdateAutoStatus(void); static void TP_FindModelNumbers (void); static void TP_FindPoint (void); -char *TP_LocationName (vec3_t location); #define MAX_LOC_NAME 48 @@ -1640,7 +1639,7 @@ static void TP_LoadLocFile_f (void) TP_LoadLocFile (Cmd_Argv(1), false); } -char *TP_LocationName (vec3_t location) +char *TP_LocationName (const vec3_t location) { int i, j, minnum; float dist, mindist; diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 5deb001cf..d0cdc3bd2 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // release version #define FTE_VER_MAJOR 1 -#define FTE_VER_MINOR 6 +#define FTE_VER_MINOR 7 #if defined(__APPLE__) && defined(__MACH__) #define MACOSX @@ -562,7 +562,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define VM_UI #endif -#if defined(VM_Q1) || defined(VM_UI) || defined(VM_CG) || defined(Q3SERVER) || defined(PLUGINS) +#if defined(VM_Q1) || defined(VM_UI) || defined(VM_CG) || defined(Q3SERVER) #define VM_ANY #endif diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 42df57bd5..9ae7c4ef2 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -1009,6 +1009,7 @@ typedef struct int lerpcount; //number of pose+frac entries. float frac[FRAME_BLENDS*2]; //weight of this animation (1 if lerpcount is 1) float *pose[FRAME_BLENDS*2]; //pointer to the raw frame data for bone 0. + void *needsfree[FRAME_BLENDS*2]; } skellerps_t; static qboolean Alias_BuildSkelLerps(skellerps_t *lerps, const struct framestateregion_s *fs, int numbones, const galiasinfo_t *inf) { @@ -1043,6 +1044,26 @@ static qboolean Alias_BuildSkelLerps(skellerps_t *lerps, const struct framestate } g = &inf->ofsanimations[frame]; + + if (lerps->skeltype == SKEL_IDENTITY) + lerps->skeltype = g->skeltype; + else if (lerps->skeltype != g->skeltype) + { + dropweight += fs->lerpweight[b]; + continue; //oops, can't cope with mixed blend types + } + + if (g->GetRawBones) + { + lerps->frac[l] = fs->lerpweight[b]; + lerps->needsfree[l] = BZ_Malloc(sizeof(float)*12*numbones); + lerps->pose[l] = g->GetRawBones(inf, g, time, lerps->needsfree[l], numbones); + if (lerps->pose[l]) + l++; + else + dropweight += lerps->frac[l]; + continue; + } if (!g->numposes) { dropweight += fs->lerpweight[b]; @@ -1068,14 +1089,6 @@ static qboolean Alias_BuildSkelLerps(skellerps_t *lerps, const struct framestate frame2=bound(0, frame2, g->numposes-1); } - if (lerps->skeltype == SKEL_IDENTITY) - lerps->skeltype = g->skeltype; - else if (lerps->skeltype != g->skeltype) - { - dropweight += fs->lerpweight[b]; - continue; //oops, can't cope with mixed blend types - } - if (frame1 == frame2) mlerp = 0; else if (r_noframegrouplerp.ival) @@ -1084,13 +1097,15 @@ static qboolean Alias_BuildSkelLerps(skellerps_t *lerps, const struct framestate if (lerps->frac[l]>0) { totalweight += lerps->frac[l]; - lerps->pose[l++] = g->boneofs + numbones*12*frame1; + lerps->needsfree[l] = NULL; + lerps->pose[l++] = (float*)g->boneofs + numbones*12*frame1; } lerps->frac[l] = (mlerp)*fs->lerpweight[b]; if (lerps->frac[l]>0) { totalweight += lerps->frac[l]; - lerps->pose[l++] = g->boneofs + numbones*12*frame2; + lerps->needsfree[l] = NULL; + lerps->pose[l++] = (float*)g->boneofs + numbones*12*frame2; } } } @@ -1157,6 +1172,7 @@ static int Alias_FindRawSkelData(galiasinfo_t *inf, const framestate_t *fstate, if (!inf->baseframeofs) continue; //nope, not happening. lerps->skeltype = SKEL_ABSOLUTE; + lerps->needsfree[0] = NULL; lerps->frac[0] = 1; lerps->pose[0] = inf->baseframeofs; lerps->lerpcount = 1; @@ -1186,32 +1202,34 @@ static int Alias_BlendBoneData(galiasinfo_t *inf, framestate_t *fstate, float *r for (lerp = lerps; numgroups--; lerp++) { - if (lerp[0].skeltype != skeltype) - continue; //egads, its buggy. should probably convert. - - bone = lerp->firstbone; - endbone = lerp->endbone; - if (lerp->lerpcount == 1 && lerp->frac[0] == 1) - memcpy(result+bone*12, lerp->pose[0]+bone*12, (endbone-bone)*12*sizeof(float)); - else + if (lerp->skeltype == skeltype) { - //set up the identity matrix - for (; bone < endbone; bone++) + bone = lerp->firstbone; + endbone = lerp->endbone; + if (lerp->lerpcount == 1 && lerp->frac[0] == 1) + memcpy(result+bone*12, lerp->pose[0]+bone*12, (endbone-bone)*12*sizeof(float)); + else { - pose = result + 12*bone; - //set up the per-bone transform matrix - matrix = lerps->pose[0] + bone*12; - for (k = 0;k < 12;k++) - pose[k] = matrix[k] * lerp->frac[0]; - for (b = 1;b < lerp->lerpcount;b++) + //set up the identity matrix + for (; bone < endbone; bone++) { - matrix = lerps->pose[b] + bone*12; - + pose = result + 12*bone; + //set up the per-bone transform matrix + matrix = lerps->pose[0] + bone*12; for (k = 0;k < 12;k++) - pose[k] += matrix[k] * lerp->frac[b]; + pose[k] = matrix[k] * lerp->frac[0]; + for (b = 1;b < lerp->lerpcount;b++) + { + matrix = lerps->pose[b] + bone*12; + + for (k = 0;k < 12;k++) + pose[k] += matrix[k] * lerp->frac[b]; + } } } } + for (k = 0; k < lerp->lerpcount; k++) + BZ_Free(lerp->needsfree[k]); } return endbone; } @@ -1225,6 +1243,7 @@ static const float *Alias_GetBoneInformation(galiasinfo_t *inf, const framestate skellerps_t lerps[FS_COUNT], *lerp; size_t numgroups; size_t bone, endbone; + const float *ret; lerps[0].skeltype = SKEL_IDENTITY; //just in case. #ifdef SKELETALOBJECTS @@ -1235,6 +1254,7 @@ static const float *Alias_GetBoneInformation(galiasinfo_t *inf, const framestate lerps[0].endbone = framestate->bonecount; lerps[0].pose[0] = framestate->bonestate; lerps[0].frac[0] = 1; + lerps[0].needsfree[0] = NULL; lerps[0].lerpcount = 1; numgroups = 1; } @@ -1246,7 +1266,11 @@ static const float *Alias_GetBoneInformation(galiasinfo_t *inf, const framestate //try to return data in-place. if (numgroups==1 && lerps[0].lerpcount == 1) - return Alias_ConvertBoneData(lerps[0].skeltype, lerps[0].pose[0], min(lerps[0].endbone, inf->numbones), inf->ofsbones, targettype, targetbuffer, targetbufferalt, maxbufferbones); + { + ret = Alias_ConvertBoneData(lerps[0].skeltype, lerps[0].pose[0], min(lerps[0].endbone, inf->numbones), inf->ofsbones, targettype, targetbuffer, targetbufferalt, maxbufferbones); + BZ_Free(lerps[0].needsfree[0]); + return ret; + } for (lerp = lerps; numgroups--; lerp++) { @@ -1265,6 +1289,8 @@ static const float *Alias_GetBoneInformation(galiasinfo_t *inf, const framestate for (k = 0; k < 12; k++) //please please unroll! out[k] = (pose1[k]*frac1) + (frac2*pose2[k]); } + BZ_Free(lerp->needsfree[0]); + BZ_Free(lerp->needsfree[1]); } break; case 3: @@ -1278,6 +1304,9 @@ static const float *Alias_GetBoneInformation(galiasinfo_t *inf, const framestate for (k = 0; k < 12; k++) //please please unroll! out[k] = (pose1[k]*frac1) + (frac2*pose2[k]) + (pose3[k]*frac3); } + BZ_Free(lerp->needsfree[0]); + BZ_Free(lerp->needsfree[1]); + BZ_Free(lerp->needsfree[2]); } break; case 4: @@ -1291,6 +1320,10 @@ static const float *Alias_GetBoneInformation(galiasinfo_t *inf, const framestate for (k = 0; k < 12; k++) //please please unroll! out[k] = (pose1[k]*frac1) + (frac2*pose2[k]) + (pose3[k]*frac3) + (frac4*pose4[k]); } + BZ_Free(lerp->needsfree[0]); + BZ_Free(lerp->needsfree[1]); + BZ_Free(lerp->needsfree[2]); + BZ_Free(lerp->needsfree[3]); } break; case 0: @@ -1316,6 +1349,7 @@ static const float *Alias_GetBoneInformation(galiasinfo_t *inf, const framestate for (k = 0; k < 12; k++) out[k] += (pose[k]*frac); } + BZ_Free(lerp->needsfree[i]); } } break; @@ -4609,6 +4643,7 @@ qboolean Mod_GetTag(model_t *model, int tagnum, framestate_t *fstate, float *res lerps[0].pose[0] = fstate->bonestate; lerps[0].frac[0] = 1; + lerps[0].needsfree[0] = 0; lerps[0].lerpcount = 1; lerps[0].firstbone = 0; lerps[0].endbone = fstate->bonecount; @@ -4625,6 +4660,7 @@ qboolean Mod_GetTag(model_t *model, int tagnum, framestate_t *fstate, float *res { lerps[0].pose[0] = inf->baseframeofs; lerps[0].frac[0] = 1; + lerps[0].needsfree[0] = 0; lerps[0].lerpcount = 1; lerps[0].firstbone = 0; lerps[0].endbone = inf->numbones; @@ -4660,7 +4696,7 @@ qboolean Mod_GetTag(model_t *model, int tagnum, framestate_t *fstate, float *res if (lerp->skeltype == SKEL_ABSOLUTE) { memcpy(result, m, sizeof(tempmatrix)); - return true; + break; } memcpy(tempmatrix, result, sizeof(tempmatrix)); @@ -4669,6 +4705,9 @@ qboolean Mod_GetTag(model_t *model, int tagnum, framestate_t *fstate, float *res tagnum = bone[tagnum].parent; } + for (b = 0; b < numbonegroups; lerp++, b++) + for (k = 0; k < lerps[b].lerpcount; k++) + BZ_Free(lerps[b].needsfree[k]); return true; } #endif diff --git a/engine/common/com_mesh.h b/engine/common/com_mesh.h index 79f2ef79b..6b8b0a435 100644 --- a/engine/common/com_mesh.h +++ b/engine/common/com_mesh.h @@ -13,6 +13,8 @@ extern "C" { #include "model_hl.h" #endif +struct galiasinfo_s; //per-surface info. + #ifdef NONSKELETALMODELS //a single pose within an animation (note: always refered to via a framegroup, even if there's only one frame in that group). typedef struct @@ -43,12 +45,13 @@ typedef struct galiasevent_s } galiasevent_t; //a frame group (aka: animation) -typedef struct +typedef struct galiasanimation_s { #ifdef SKELETALMODELS skeltype_t skeltype; //for models with transforms, states that bones need to be transformed from their parent. //this is actually bad, and can result in bones shortening as they interpolate. - float *boneofs; //numposes*12*numbones + float *(QDECL *GetRawBones)(const struct galiasinfo_s *mesh, const struct galiasanimation_s *a, float time, float *bonematrixstorage, int numbones); + void *boneofs; //numposes*12*numbones #endif qboolean loop; int numposes; @@ -208,6 +211,8 @@ typedef struct galiasinfo_s FTE_DEPRECATED int numtags; FTE_DEPRECATED md3tag_t *ofstags; #endif + + void *ctx; //loader-specific stuff. must be ZG_Malloced if it lasts beyond the loader. unsigned int warned; //passed around at load time, so we don't spam warnings } galiasinfo_t; @@ -215,36 +220,36 @@ struct terrainfuncs_s; typedef struct modplugfuncs_s { int version; + + //format handling int (QDECL *RegisterModelFormatText)(const char *formatname, char *magictext, qboolean (QDECL *load) (struct model_s *mod, void *buffer, size_t fsize)); int (QDECL *RegisterModelFormatMagic)(const char *formatname, unsigned int magic, qboolean (QDECL *load) (struct model_s *mod, void *buffer, size_t fsize)); void (QDECL *UnRegisterModelFormat)(int idx); void (QDECL *UnRegisterAllModelFormats)(void); + //util void *(QDECL *ZG_Malloc)(zonegroup_t *ctx, size_t size); //ctx=&mod->memgroup and the data will be freed when the model is freed. + void (QDECL *StripExtension) (const char *in, char *out, int outlen); + //matrix maths void (QDECL *ConcatTransforms) (const float in1[3][4], const float in2[3][4], float out[3][4]); void (QDECL *M3x4_Invert) (const float *in1, float *out); void (QDECL *VectorAngles)(const float *forward, const float *up, float *result, qboolean meshpitch); void (QDECL *AngleVectors)(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); void (QDECL *GenMatrixPosQuat4Scale)(const vec3_t pos, const vec4_t quat, const vec3_t scale, float result[12]); - void (QDECL *StripExtension) (const char *in, char *out, int outlen); + //bone stuff void (QDECL *ForceConvertBoneData)(skeltype_t sourcetype, const float *sourcedata, size_t bonecount, galiasbone_t *bones, skeltype_t desttype, float *destbuffer, size_t destbonecount); - struct terrainfuncs_s *(QDECL *GetTerrainFuncs)(void); - void *reserved2; + //texturing image_t *(QDECL *GetTexture)(const char *identifier, const char *subpath, unsigned int flags, void *fallbackdata, void *fallbackpalette, int fallbackwidth, int fallbackheight, uploadfmt_t fallbackfmt); - vfsfile_t *(QDECL *OpenVFS)(const char *filename, const char *mode, enum fs_relative relativeto); void (QDECL *AccumulateTextureVectors)(vecV_t *const vc, vec2_t *const tc, vec3_t *nv, vec3_t *sv, vec3_t *tv, const index_t *idx, int numidx, qboolean calcnorms); void (QDECL *NormaliseTextureVectors)(vec3_t *n, vec3_t *s, vec3_t *t, int v, qboolean calcnorms); - void *unused5; - void *unused6; - void *unused7; - void *unused8; - void *unused9; - void *unused10; -} modplugfuncs_t; -#define MODPLUGFUNCS_VERSION 2 + + model_t *(QDECL *GetModel)(const char *identifier, enum mlverbosity_e verbosity); +#define plugmodfuncs_name "Models" +} plugmodfuncs_t; +#define MODPLUGFUNCS_VERSION 1 #ifdef SKELETALMODELS void Alias_TransformVerticies(float *bonepose, galisskeletaltransforms_t *weights, int numweights, vecV_t *xyzout, vec3_t *normout); diff --git a/engine/common/com_phys_ode.c b/engine/common/com_phys_ode.c index 43c46ef27..f70be232c 100644 --- a/engine/common/com_phys_ode.c +++ b/engine/common/com_phys_ode.c @@ -29,10 +29,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef FTEPLUGIN #define FTEENGINE #define FTEPLUGIN -#define pCvar_Register Cvar_Get -#define pCvar_GetFloat(x) Cvar_FindVar(x)->value -#define Sys_Errorf Sys_Error -#define pSys_Error(p) Sys_Errorf("%s",p) #define Plug_Init Plug_ODE_Init #endif @@ -67,17 +63,6 @@ static int VectorCompare (const vec3_t v1, const vec3_t v2) #endif - -#define ARGNAMES ,name,funcs -static BUILTINR(dllhandle_t *, Sys_LoadLibrary, (const char *name,dllfunction_t *funcs)); -#undef ARGNAMES -#define ARGNAMES ,hdl -static BUILTIN(void, Sys_CloseLibrary, (dllhandle_t *hdl)); -#undef ARGNAMES -#define ARGNAMES ,version -static BUILTINR(rbeplugfuncs_t*, RBE_GetPluginFuncs, (int version)); -#undef ARGNAMES - static rbeplugfuncs_t *rbefuncs; cvar_t r_meshpitch; @@ -1288,29 +1273,29 @@ static qboolean World_ODE_Init(void) }; #endif - physics_ode_quadtree_depth = pCvar_GetNVFDG("physics_ode_quadtree_depth", "5", 0, "desired subdivision level of quadtree culling space", "ODE Physics Library"); - physics_ode_contactsurfacelayer = pCvar_GetNVFDG("physics_ode_contactsurfacelayer", "0", 0, "allows objects to overlap this many units to reduce jitter", "ODE Physics Library"); - physics_ode_worldquickstep = pCvar_GetNVFDG("physics_ode_worldquickstep", "1", 0, "use dWorldQuickStep rather than dWorldStep", "ODE Physics Library"); - physics_ode_worldquickstep_iterations = pCvar_GetNVFDG("physics_ode_worldquickstep_iterations", "20", 0, "parameter to dWorldQuickStep", "ODE Physics Library"); - physics_ode_contact_mu = pCvar_GetNVFDG("physics_ode_contact_mu", "1", 0, "contact solver mu parameter - friction pyramid approximation 1 (see ODE User Guide)", "ODE Physics Library"); - physics_ode_contact_erp = pCvar_GetNVFDG("physics_ode_contact_erp", "0.96", 0, "contact solver erp parameter - Error Restitution Percent (see ODE User Guide)", "ODE Physics Library"); - physics_ode_contact_cfm = pCvar_GetNVFDG("physics_ode_contact_cfm", "0", 0, "contact solver cfm parameter - Constraint Force Mixing (see ODE User Guide)", "ODE Physics Library"); - physics_ode_world_damping = pCvar_GetNVFDG("physics_ode_world_damping", "1", 0, "enabled damping scale (see ODE User Guide), this scales all damping values, be aware that behavior depends of step type", "ODE Physics Library"); - physics_ode_world_damping_linear = pCvar_GetNVFDG("physics_ode_world_damping_linear", "-1",0, "world linear damping scale (see ODE User Guide); use defaults when set to -1", "ODE Physics Library"); - physics_ode_world_damping_linear_threshold = pCvar_GetNVFDG("physics_ode_world_damping_linear_threshold", "-1", 0, "world linear damping threshold (see ODE User Guide); use defaults when set to -1", "ODE Physics Library"); - physics_ode_world_damping_angular = pCvar_GetNVFDG("physics_ode_world_damping_angular", "-1",0, "world angular damping scale (see ODE User Guide); use defaults when set to -1", "ODE Physics Library"); - physics_ode_world_damping_angular_threshold = pCvar_GetNVFDG("physics_ode_world_damping_angular_threshold", "-1", 0, "world angular damping threshold (see ODE User Guide); use defaults when set to -1", "ODE Physics Library"); - physics_ode_world_erp = pCvar_GetNVFDG("physics_ode_world_erp", "-1", 0, "world solver erp parameter - Error Restitution Percent (see ODE User Guide); use defaults when set to -1", "ODE Physics Library"); - physics_ode_world_cfm = pCvar_GetNVFDG("physics_ode_world_cfm", "-1", 0, "world solver cfm parameter - Constraint Force Mixing (see ODE User Guide); not touched when -1", "ODE Physics Library"); - physics_ode_iterationsperframe = pCvar_GetNVFDG("physics_ode_iterationsperframe", "4", 0, "divisor for time step, runs multiple physics steps per frame", "ODE Physics Library"); - physics_ode_movelimit = pCvar_GetNVFDG("physics_ode_movelimit", "0.5", 0, "clamp velocity if a single move would exceed this percentage of object thickness, to prevent flying through walls","ODE Physics Library"); - physics_ode_spinlimit = pCvar_GetNVFDG("physics_ode_spinlimit", "10000",0, "reset spin velocity if it gets too large", "ODE Physics Library"); - physics_ode_autodisable = pCvar_GetNVFDG("physics_ode_autodisable", "1", 0, "automatic disabling of objects which dont move for long period of time, makes object stacking a lot faster", "ODE Physics Library"); - physics_ode_autodisable_steps = pCvar_GetNVFDG("physics_ode_autodisable_steps", "10", 0, "how many steps object should be dormant to be autodisabled", "ODE Physics Library"); - physics_ode_autodisable_time = pCvar_GetNVFDG("physics_ode_autodisable_time", "0", 0, "how many seconds object should be dormant to be autodisabled", "ODE Physics Library"); - physics_ode_autodisable_threshold_linear = pCvar_GetNVFDG("physics_ode_autodisable_threshold_linear", "0.2", 0, "body will be disabled if it's linear move below this value", "ODE Physics Library"); - physics_ode_autodisable_threshold_angular = pCvar_GetNVFDG("physics_ode_autodisable_threshold_angular", "0.3", 0, "body will be disabled if it's angular move below this value", "ODE Physics Library"); - physics_ode_autodisable_threshold_samples = pCvar_GetNVFDG("physics_ode_autodisable_threshold_samples", "5", 0, "average threshold with this number of samples", "ODE Physics Library"); + physics_ode_quadtree_depth = cvarfuncs->GetNVFDG("physics_ode_quadtree_depth", "5", 0, "desired subdivision level of quadtree culling space", "ODE Physics Library"); + physics_ode_contactsurfacelayer = cvarfuncs->GetNVFDG("physics_ode_contactsurfacelayer", "0", 0, "allows objects to overlap this many units to reduce jitter", "ODE Physics Library"); + physics_ode_worldquickstep = cvarfuncs->GetNVFDG("physics_ode_worldquickstep", "1", 0, "use dWorldQuickStep rather than dWorldStep", "ODE Physics Library"); + physics_ode_worldquickstep_iterations = cvarfuncs->GetNVFDG("physics_ode_worldquickstep_iterations", "20", 0, "parameter to dWorldQuickStep", "ODE Physics Library"); + physics_ode_contact_mu = cvarfuncs->GetNVFDG("physics_ode_contact_mu", "1", 0, "contact solver mu parameter - friction pyramid approximation 1 (see ODE User Guide)", "ODE Physics Library"); + physics_ode_contact_erp = cvarfuncs->GetNVFDG("physics_ode_contact_erp", "0.96", 0, "contact solver erp parameter - Error Restitution Percent (see ODE User Guide)", "ODE Physics Library"); + physics_ode_contact_cfm = cvarfuncs->GetNVFDG("physics_ode_contact_cfm", "0", 0, "contact solver cfm parameter - Constraint Force Mixing (see ODE User Guide)", "ODE Physics Library"); + physics_ode_world_damping = cvarfuncs->GetNVFDG("physics_ode_world_damping", "1", 0, "enabled damping scale (see ODE User Guide), this scales all damping values, be aware that behavior depends of step type", "ODE Physics Library"); + physics_ode_world_damping_linear = cvarfuncs->GetNVFDG("physics_ode_world_damping_linear", "-1",0, "world linear damping scale (see ODE User Guide); use defaults when set to -1", "ODE Physics Library"); + physics_ode_world_damping_linear_threshold = cvarfuncs->GetNVFDG("physics_ode_world_damping_linear_threshold", "-1", 0, "world linear damping threshold (see ODE User Guide); use defaults when set to -1", "ODE Physics Library"); + physics_ode_world_damping_angular = cvarfuncs->GetNVFDG("physics_ode_world_damping_angular", "-1",0, "world angular damping scale (see ODE User Guide); use defaults when set to -1", "ODE Physics Library"); + physics_ode_world_damping_angular_threshold = cvarfuncs->GetNVFDG("physics_ode_world_damping_angular_threshold", "-1", 0, "world angular damping threshold (see ODE User Guide); use defaults when set to -1", "ODE Physics Library"); + physics_ode_world_erp = cvarfuncs->GetNVFDG("physics_ode_world_erp", "-1", 0, "world solver erp parameter - Error Restitution Percent (see ODE User Guide); use defaults when set to -1", "ODE Physics Library"); + physics_ode_world_cfm = cvarfuncs->GetNVFDG("physics_ode_world_cfm", "-1", 0, "world solver cfm parameter - Constraint Force Mixing (see ODE User Guide); not touched when -1", "ODE Physics Library"); + physics_ode_iterationsperframe = cvarfuncs->GetNVFDG("physics_ode_iterationsperframe", "4", 0, "divisor for time step, runs multiple physics steps per frame", "ODE Physics Library"); + physics_ode_movelimit = cvarfuncs->GetNVFDG("physics_ode_movelimit", "0.5", 0, "clamp velocity if a single move would exceed this percentage of object thickness, to prevent flying through walls","ODE Physics Library"); + physics_ode_spinlimit = cvarfuncs->GetNVFDG("physics_ode_spinlimit", "10000",0, "reset spin velocity if it gets too large", "ODE Physics Library"); + physics_ode_autodisable = cvarfuncs->GetNVFDG("physics_ode_autodisable", "1", 0, "automatic disabling of objects which dont move for long period of time, makes object stacking a lot faster", "ODE Physics Library"); + physics_ode_autodisable_steps = cvarfuncs->GetNVFDG("physics_ode_autodisable_steps", "10", 0, "how many steps object should be dormant to be autodisabled", "ODE Physics Library"); + physics_ode_autodisable_time = cvarfuncs->GetNVFDG("physics_ode_autodisable_time", "0", 0, "how many seconds object should be dormant to be autodisabled", "ODE Physics Library"); + physics_ode_autodisable_threshold_linear = cvarfuncs->GetNVFDG("physics_ode_autodisable_threshold_linear", "0.2", 0, "body will be disabled if it's linear move below this value", "ODE Physics Library"); + physics_ode_autodisable_threshold_angular = cvarfuncs->GetNVFDG("physics_ode_autodisable_threshold_angular", "0.3", 0, "body will be disabled if it's angular move below this value", "ODE Physics Library"); + physics_ode_autodisable_threshold_samples = cvarfuncs->GetNVFDG("physics_ode_autodisable_threshold_samples", "5", 0, "average threshold with this number of samples", "ODE Physics Library"); #ifdef ODE_DYNAMIC // Load the DLL @@ -2753,12 +2738,12 @@ static void QDECL World_ODE_Start(world_t *world) memset(ctx, 0, sizeof(*ctx)); world->rbe = &ctx->pub; - r_meshpitch.value = pCvar_GetFloat("r_meshpitch"); + r_meshpitch.value = cvarfuncs->GetFloat("r_meshpitch"); VectorAvg(world->worldmodel->mins, world->worldmodel->maxs, center); VectorSubtract(world->worldmodel->maxs, center, extents); ctx->dworld = dWorldCreate(); - ctx->space = dQuadTreeSpaceCreate(NULL, center, extents, bound(1, pCvar_GetFloat("physics_ode_quadtree_depth"), 10)); + ctx->space = dQuadTreeSpaceCreate(NULL, center, extents, bound(1, cvarfuncs->GetFloat("physics_ode_quadtree_depth"), 10)); ctx->contactgroup = dJointGroupCreate(0); ctx->pub.End = World_ODE_End; @@ -2836,38 +2821,28 @@ static void World_ODE_RunCmd(world_t *world, rbecommandqueue_t *cmd) } } -static qintptr_t QDECL Plug_ODE_Shutdown(qintptr_t *args) +static void QDECL Plug_ODE_Shutdown(void) { if (rbefuncs) rbefuncs->UnregisterPhysicsEngine("ODE"); World_ODE_Shutdown(); - return 0; } -qintptr_t Plug_Init(qintptr_t *args) +qboolean Plug_Init(void) { - CHECKBUILTIN(RBE_GetPluginFuncs); #ifndef ODE_STATIC CHECKBUILTIN(Sys_LoadLibrary); CHECKBUILTIN(Sys_CloseLibrary); #endif - if (BUILTINISVALID(RBE_GetPluginFuncs)) - { - rbefuncs = pRBE_GetPluginFuncs(sizeof(rbeplugfuncs_t)); - if (rbefuncs && rbefuncs->version < RBEPLUGFUNCS_VERSION) - rbefuncs = NULL; - } + rbefuncs = plugfuncs->GetEngineInterface("RBE", sizeof(rbeplugfuncs_t)); + if (rbefuncs && rbefuncs->version < RBEPLUGFUNCS_VERSION) + rbefuncs = NULL; if (!rbefuncs) { Con_Printf("ODE plugin failed: Engine does not support external rigid body engines.\n"); return false; } - if (!BUILTINISVALID(Cvar_GetNVFDG)) - { - Con_Printf("ODE plugin failed: Engine too old.\n"); - return false; - } #ifndef ODE_STATIC if (!BUILTINISVALID(Sys_LoadLibrary) || !BUILTINISVALID(Sys_CloseLibrary)) { @@ -2888,7 +2863,7 @@ qintptr_t Plug_Init(qintptr_t *args) rbefuncs->UnregisterPhysicsEngine("ODE"); return false; } - Plug_Export("Shutdown", Plug_ODE_Shutdown); + plugfuncs->ExportFunction("Shutdown", Plug_ODE_Shutdown); return true; } return false; diff --git a/engine/common/common.c b/engine/common/common.c index 105a56090..111b2f0b0 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -7615,7 +7615,7 @@ void SV_FlushRedirect (void); vfsfile_t *con_pipe; #ifdef HAVE_SERVER -vfsfile_t *Con_POpen(char *conname) +vfsfile_t *Con_POpen(const char *conname) { if (!conname || !*conname) { diff --git a/engine/common/common.h b/engine/common/common.h index 4b810b151..6bc0c4f0a 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -576,6 +576,7 @@ void VARGS VFS_PRINTF(vfsfile_t *vf, const char *fmt, ...) LIKEPRINTF(2); enum fs_relative{ FS_BINARYPATH, //for dlls and stuff + FS_LIBRARYPATH, //for system dlls and stuff FS_ROOT, //./ (effective -homedir if enabled, otherwise effective -basedir arg) FS_SYSTEM, //a system path. absolute paths are explicitly allowed and expected, but not required. diff --git a/engine/common/console.h b/engine/common/console.h index 106a776ac..ac3241f2d 100644 --- a/engine/common/console.h +++ b/engine/common/console.h @@ -254,7 +254,7 @@ void Con_ToggleConsole_Force(void); int Con_ExecuteLine(console_t *con, const char *line); //takes normal console commands int Con_Navigate(console_t *con, const char *line); //special webbrowser hacks -vfsfile_t *Con_POpen(char *conname); +vfsfile_t *Con_POpen(const char *conname); void Con_CycleConsole (void); int Con_IsActive (console_t *con); void Con_Destroy (console_t *con); diff --git a/engine/common/log.c b/engine/common/log.c index eeb0352fd..efd384352 100644 --- a/engine/common/log.c +++ b/engine/common/log.c @@ -787,9 +787,9 @@ qboolean CertLog_ConnectOkay(const char *hostname, void *cert, size_t certsize) //FIXME: display some sort of fingerprint if (!l) - M_Menu_Prompt(CertLog_Add_Prompted, ctx, va("%s\nServer certificate is\nself-signed", hostname), "Trust", NULL, "Disconnect"); + Menu_Prompt(CertLog_Add_Prompted, ctx, va("%s\nServer certificate is\nself-signed", hostname), "Trust", NULL, "Disconnect"); else - M_Menu_Prompt(CertLog_Add_Prompted, ctx, va("%s\n^1Server certificate HAS CHANGED\nZomg\n^bFlee in Terror", hostname), "ReTrust", NULL, "Disconnect"); + Menu_Prompt(CertLog_Add_Prompted, ctx, va("%s\n^1Server certificate HAS CHANGED\nZomg\n^bFlee in Terror", hostname), "ReTrust", NULL, "Disconnect"); } return false; //can't connect yet... } diff --git a/engine/common/net.h b/engine/common/net.h index 7c53ba555..0e47373da 100644 --- a/engine/common/net.h +++ b/engine/common/net.h @@ -62,7 +62,7 @@ typedef enum { typedef enum {NS_CLIENT, NS_SERVER} netsrc_t; -typedef struct +typedef struct netadr_s { netadrtype_t type; netproto_t prot; diff --git a/engine/common/plugin.c b/engine/common/plugin.c index ad6935f4c..b0a3ac6b1 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -4,23 +4,18 @@ #include "quakedef.h" #include "fs.h" - -#define PLUG_NONE 0 -#define PLUG_NATIVE 1 -#define PLUG_QVM 2 -#define PLUG_EITHER 3 +#define FTEENGINE +#include "../plugins/plugin.h" #ifdef PLUGINS cvar_t plug_sbar = CVARD("plug_sbar", "3", "Controls whether plugins are allowed to draw the hud, rather than the engine (when allowed by csqc). This is typically used to permit the ezhud plugin without needing to bother unloading it.\n=0: never use hud plugins.\n&1: Use hud plugins in deathmatch.\n&2: Use hud plugins in singleplayer/coop.\n=3: Always use hud plugins (when loaded)."); cvar_t plug_loaddefault = CVARD("plug_loaddefault", "1", "0: Load plugins only via explicit plug_load commands\n1: Load built-in plugins and those selected via the package manager\n2: Scan for misc plugins, loading all that can be found, but not built-ins.\n3: Scan for plugins, and then load any built-ins"); -qintptr_t Plug_Bullet_Init(qintptr_t *args); -qintptr_t Plug_ODE_Init(qintptr_t *args); -struct +static struct { const char *name; - qintptr_t (*initfunction)(qintptr_t *args); + qboolean (QDECL *initfunction)(void); } staticplugins[] = { #if defined(USE_INTERNAL_BULLET) @@ -31,46 +26,72 @@ struct #endif {NULL} }; +//for internal plugins to link against +plugcorefuncs_t *plugfuncs; +plugcvarfuncs_t *cvarfuncs; +plugcmdfuncs_t *cmdfuncs; #ifdef GLQUAKE #include "glquake.h" #endif +#include "com_mesh.h" +#include "shader.h" + +static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t structsize); + +#ifdef SKELETALMODELS +static int QDECL Plug_RegisterModelFormatText(const char *formatname, char *magictext, qboolean (QDECL *load) (struct model_s *mod, void *buffer, size_t fsize)) +{ + void *module = currentplug; + return Mod_RegisterModelFormatText(module, formatname, magictext, load); +} +static int QDECL Plug_RegisterModelFormatMagic(const char *formatname, unsigned int magic, qboolean (QDECL *load) (struct model_s *mod, void *buffer, size_t fsize)) +{ + void *module = currentplug; + return Mod_RegisterModelFormatMagic(module, formatname, magic, load); +} +static void QDECL Plug_UnRegisterModelFormat(int idx) +{ + void *module = currentplug; + Mod_UnRegisterModelFormat(module, idx); +} +static void QDECL Plug_UnRegisterAllModelFormats(void) +{ + void *module = currentplug; + Mod_UnRegisterAllModelFormats(module); +} +#endif //custom plugin builtins. -typedef qintptr_t (EXPORT_FN *Plug_Builtin_t)(void *offset, quintptr_t mask, const qintptr_t *arg); -void Plug_RegisterBuiltin(char *name, Plug_Builtin_t bi, int flags); -#define PLUG_BIF_DLLONLY 1 //WARNING: it is not enough to just specify this flag, but also the builtin code must return if there is an offset passed. -#define PLUG_BIF_QVMONLY 2 +void Plug_RegisterBuiltin_(char *name, funcptr_t bi, int flags); +#define Plug_RegisterBuiltin(n,bi,fl) Plug_RegisterBuiltin_(n,(funcptr_t)bi,fl) #define PLUG_BIF_NEEDSRENDERER 4 #include "netinc.h" typedef struct plugin_s { char *name; - vm_t *vm; + char filename[MAX_OSPATH]; + dllhandle_t *lib; - int blockcloses; - - void *inputptr; - size_t inputbytes; - - qintptr_t tick; - qintptr_t executestring; + void (QDECL *tick)(double realtime, double gametime); + qboolean (QDECL *executestring)(qboolean isinsecure); #ifndef SERVERONLY - qintptr_t consolelink; - qintptr_t consolelinkmouseover; - qintptr_t conexecutecommand; - qintptr_t menufunction; - qintptr_t sbarlevel[3]; //0 - main sbar, 1 - supplementry sbar sections (make sure these can be switched off), 2 - overlays (scoreboard). menus kill all. - qintptr_t reschange; + qboolean (QDECL *consolelink)(void); + qboolean (QDECL *consolelinkmouseover)(float x, float y); + int (QDECL *conexecutecommand)(qboolean isinsecure); + qboolean (QDECL *menufunction)(int eventtype, int keyparam, int unicodeparm, float mousecursor_x, float mousecursor_y, float vidwidth, float vidheight); + int (QDECL *sbarlevel[3])(int seat, float x, float y, float w, float h, unsigned int showscores); //0 - main sbar, 1 - supplementry sbar sections (make sure these can be switched off), 2 - overlays (scoreboard). menus kill all. + void (QDECL *reschange)(int width, int height); //protocol-in-a-plugin - qintptr_t connectionlessclientpacket; + int (QDECL *connectionlessclientpacket)(const char *buffer, size_t size, netadr_t *from); #endif - qintptr_t svmsgfunction; - qintptr_t chatmsgfunction; - qintptr_t centerprintfunction; - qintptr_t shutdown; + qboolean (QDECL *svmsgfunction)(int messagelevel); + qboolean (QDECL *chatmsgfunction)(int talkernum, int tpflags); + qboolean (QDECL *centerprintfunction)(int clientnum); + qboolean (QDECL *mayshutdown)(void); //lets the plugin report when its safe to close it. + void (QDECL *shutdown)(void); struct plugin_s *next; } plugin_t; @@ -88,164 +109,15 @@ void Plug_Client_Init(void){} void Plug_Client_Close(plugin_t *plug) {} #endif - -void Plug_Init(void); void Plug_Close(plugin_t *plug); -void Plug_Tick(void); -qboolean Plugin_ExecuteString(void); - static plugin_t *plugs; - -typedef struct { - char *name; - Plug_Builtin_t func; - int flags; -} Plug_Plugins_t; -Plug_Plugins_t *plugbuiltins; -int numplugbuiltins; - -void Plug_RegisterBuiltin(char *name, Plug_Builtin_t bi, int flags) -{ - //randomize the order a little. - int newnum; - - newnum = (rand()%128)+1; - while(newnum < numplugbuiltins && plugbuiltins[newnum].func) - newnum+=128; - - if (newnum >= numplugbuiltins) - { - int newbuiltins = newnum+128; - plugbuiltins = BZ_Realloc(plugbuiltins, sizeof(Plug_Plugins_t)*newbuiltins); - memset(plugbuiltins + numplugbuiltins, 0, sizeof(Plug_Plugins_t)*(newbuiltins - numplugbuiltins)); - numplugbuiltins = newbuiltins; - } - - //got an empty number. - Con_DLPrintf(2, "%s: %i\n", name, newnum); - plugbuiltins[newnum].name = name; - plugbuiltins[newnum].func = bi; - plugbuiltins[newnum].flags = flags; -} - -static qintptr_t VARGS Plug_GetNativePointer(void *offset, quintptr_t mask, const qintptr_t *args) -{ -#ifdef SUPPORT_ICE - char *p = (char *)VM_POINTER(args[0]); - if (offset) //QVMs are not allowed to call this - return 0; - if (!strcmp(p, ICE_API_CURRENT)) - return (qintptr_t)&iceapi; +#ifdef USERBE +#include "pr_common.h" #endif - return (qintptr_t)NULL; -} - -/* -static void Plug_RegisterBuiltinIndex(char *name, Plug_Builtin_t bi, int flags, int index) //I d -{ - //randomize the order a little. - int newnum; - - newnum = rand()%128; - while(newnum+1 < numplugbuiltins && plugbuiltins[newnum+1].func) - newnum+=128; - - newnum++; - - if (newnum >= numplugbuiltins) - { - numplugbuiltins = newnum+128; - plugbuiltins = BZ_Realloc(plugbuiltins, sizeof(Plug_Plugins_t)*numplugbuiltins); - } - - //got an empty number. - plugbuiltins[newnum].name = name; - plugbuiltins[newnum].func = bi; -} -*/ - -static qintptr_t Plug_FindBuiltin(qboolean native, const char *p) -{ - int i; - for (i = 0; i < numplugbuiltins; i++) - if (plugbuiltins[i].name) - if (p && !strcmp(plugbuiltins[i].name, p)) - { - if (!native && plugbuiltins[i].flags & PLUG_BIF_DLLONLY) - return 0; //block it, if not native - if (native && plugbuiltins[i].flags & PLUG_BIF_QVMONLY) - return 0; //block it, if not native - return -i; - } - - return 0; -} -static qintptr_t VARGS Plug_GetBuiltin(void *offset, quintptr_t mask, const qintptr_t *args) -{ - char *p = (char *)VM_POINTER(args[0]); - return Plug_FindBuiltin(!offset, p); -} - -static int Plug_SystemCallsVM(void *offset, quintptr_t mask, int fn, const int *arg) -{ -#if FTE_WORDSIZE == 32 - #define args arg -#else - qintptr_t args[9]; - - args[0]=arg[0]; - args[1]=arg[1]; - args[2]=arg[2]; - args[3]=arg[3]; - args[4]=arg[4]; - args[5]=arg[5]; - args[6]=arg[6]; - args[7]=arg[7]; - args[8]=arg[8]; -#endif - - fn = fn+1; - - if (fn>=0 && fn < numplugbuiltins && plugbuiltins[fn].func!=NULL) - return plugbuiltins[fn].func(offset, mask, (qintptr_t*)args); -#undef args - Sys_Error("QVM Plugin tried calling invalid builtin %i", fn); - return 0; -} - -//I'm not keen on this. -//but dlls call it without saying what sort of vm it comes from, so I've got to have them as specifics -static qintptr_t EXPORT_FN Plug_SystemCallsNative(qintptr_t arg, ...) -{ - qintptr_t args[9]; - va_list argptr; - - va_start(argptr, arg); - args[0]=va_arg(argptr, qintptr_t); - args[1]=va_arg(argptr, qintptr_t); - args[2]=va_arg(argptr, qintptr_t); - args[3]=va_arg(argptr, qintptr_t); - args[4]=va_arg(argptr, qintptr_t); - args[5]=va_arg(argptr, qintptr_t); - args[6]=va_arg(argptr, qintptr_t); - args[7]=va_arg(argptr, qintptr_t); - args[8]=va_arg(argptr, qintptr_t); - va_end(argptr); - - arg = -arg; - - if (arg>=0 && arg < numplugbuiltins && plugbuiltins[arg].func) - return plugbuiltins[arg].func(NULL, ~0, args); - - Sys_Error("DLL Plugin tried calling invalid builtin %i", (int)arg); - return 0; -} -qintptr_t (QDECL *plugin_syscall)( qintptr_t arg, ... ) = Plug_SystemCallsNative; - static char *Plug_CleanName(const char *file, char *out, size_t sizeof_out) { size_t len; @@ -267,12 +139,39 @@ static char *Plug_CleanName(const char *file, char *out, size_t sizeof_out) } return out; } -static plugin_t *Plug_Load(const char *file, int type) +static plugin_t *Plug_Load(const char *file) { + static enum fs_relative prefixes[] = + { + FS_BINARYPATH, +#ifndef ANDROID + FS_ROOT, +#endif + }; + static char *postfixes[] = + { + "_" ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, +#ifndef ANDROID + ARCH_DL_POSTFIX, +#endif + }; + size_t i, j; char temp[MAX_OSPATH]; plugin_t *newplug; - Plug_CleanName(file, temp, sizeof(temp)); + int nlen = strlen(file); + qboolean success = false; + qboolean (QDECL *initfunction)(plugcorefuncs_t*); + dllfunction_t funcs[] = + { + {(void**)&initfunction, "FTEPlug_Init"}, + {NULL,NULL}, + }; + //reject obviously invalid names + if (!*file || strchr(file, '/') || strchr(file, '\\')) + return NULL; + + Plug_CleanName(file, temp, sizeof(temp)); for (newplug = plugs; newplug; newplug = newplug->next) { if (!Q_strcasecmp(newplug->name, temp)) @@ -283,68 +182,88 @@ static plugin_t *Plug_Load(const char *file, int type) newplug->name = (char*)(newplug+1); strcpy(newplug->name, temp); - if (!newplug->vm && (type & PLUG_NATIVE) && !Q_strncasecmp(file, PLUGINPREFIX, strlen(PLUGINPREFIX)) && !Q_strcasecmp(ARCH_DL_POSTFIX+1, COM_FileExtension(file, temp, sizeof(temp)))) + //[basedir|binroot]fteplug_%s[_cpu][.so] + for (i = 0; i < countof(prefixes) && !newplug->lib; i++) { - COM_StripExtension(file, temp, sizeof(temp)); - newplug->vm = VM_Create(temp, Plug_SystemCallsNative, NULL, NULL); + //if the name matches a postfix then just go with that + for (j = 0; j < countof(postfixes); j++) + { + int pfl = strlen(postfixes[j]); + if (nlen > pfl && !Q_strcasecmp(file+nlen-pfl, postfixes[j])) + break; + } + if (j < countof(postfixes)) + { //already postfixed, don't mess with the name given + //mandate the fteplug_ prefix (don't let them load random dlls) + if (!Q_strncasecmp(file, PLUGINPREFIX, strlen(PLUGINPREFIX))) + if (FS_NativePath(file, prefixes[i], newplug->filename, sizeof(newplug->filename))) + newplug->lib = Sys_LoadLibrary(newplug->filename, funcs); + } + else + { //otherwise scan for it + for (j = 0; j < countof(postfixes) && !newplug->lib; j++) + { + if (FS_NativePath(va(PLUGINPREFIX"%s%s", file, postfixes[j]), prefixes[i], newplug->filename, sizeof(newplug->filename))) + newplug->lib = Sys_LoadLibrary(newplug->filename, funcs); + } + } } - if (!newplug->vm && (type & PLUG_NATIVE)) + +#ifdef _WIN32 { - Q_snprintfz(temp, sizeof(temp), PLUGINPREFIX"%s", file); - newplug->vm = VM_Create(temp, Plug_SystemCallsNative, NULL, NULL); + char *mssuck; + while ((mssuck=strchr(newplug->filename, '\\'))) + *mssuck = '/'; } - if (!newplug->vm && (type & PLUG_QVM)) - newplug->vm = VM_Create(NULL, NULL, file, Plug_SystemCallsVM); - if (!newplug->vm && (type & PLUG_NATIVE)) +#endif + + newplug->next = plugs; + plugs = newplug; + if (newplug->lib) + { + Con_DPrintf("Created plugin %s\n", file); + + currentplug = newplug; + success = initfunction(PlugBI_GetEngineInterface(plugcorefuncs_name, sizeof(plugcorefuncs_t))); + } + else { unsigned int u; for (u = 0; staticplugins[u].name; u++) { if (!Q_strcasecmp(file, staticplugins[u].name)) - newplug->vm = VM_CreateBuiltin(file, Plug_SystemCallsNative, staticplugins[u].initfunction); - break; + { + Con_DPrintf("Activated module %s\n", file); + newplug->lib = NULL; + + currentplug = newplug; + success = staticplugins[u].initfunction(); + break; + } } } - currentplug = newplug; - if (newplug->vm) + if (!success) { - Con_DPrintf("Created plugin %s\n", file); + Plug_Close(newplug); + return NULL; + } - newplug->next = plugs; - plugs = newplug; - - if (!VM_Call(newplug->vm, 0, Plug_FindBuiltin(true, "Plug_GetEngineFunction"))) - { - Plug_Close(newplug); - return NULL; - } #ifndef SERVERONLY - if (newplug->reschange) - VM_Call(newplug->vm, newplug->reschange, vid.width, vid.height); + if (newplug->reschange) + newplug->reschange(vid.width, vid.height); #endif - } - else - { - Z_Free(newplug); - newplug = NULL; - } + currentplug = NULL; return newplug; } - -static int QDECL Plug_Emumerated (const char *name, qofs_t size, time_t mtime, void *param, searchpathfuncs_t *spath) +static void Plug_Load_Update(const char *name) { - char vmname[MAX_QPATH]; - Q_strncpyz(vmname, name, sizeof(vmname)); - vmname[strlen(vmname) - strlen(param)] = '\0'; - if (!Plug_Load(vmname, PLUG_QVM)) - Con_Printf("Couldn't load plugin %s\n", vmname); - - return true; + Plug_Load(name); } + static int QDECL Plug_EnumeratedRoot (const char *name, qofs_t size, time_t mtime, void *param, searchpathfuncs_t *spath) { char vmname[MAX_QPATH]; @@ -366,159 +285,84 @@ static int QDECL Plug_EnumeratedRoot (const char *name, qofs_t size, time_t mtim len = strlen(vmname); if (len > 0 && vmname[len-1] == '_') vmname[len-1] = 0; - if (!Plug_Load(vmname, PLUG_NATIVE)) + if (!Plug_Load(vmname)) Con_Printf("Couldn't load plugin %s\n", vmname); return true; } -static qintptr_t VARGS Plug_Con_Print(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Con_Print(const char *text) { -// if (qrenderer == QR_NONE) -// return false; - Con_Printf("%s", (char*)VM_POINTER(arg[0])); - return 0; + Con_Printf("%s", text); } -static qintptr_t VARGS Plug_Sys_Error(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Sys_Error(const char *text) { - Sys_Error("%s", (char*)offset+arg[0]); - return 0; + Sys_Error("%s", text); } -static qintptr_t VARGS Plug_Sys_Milliseconds(void *offset, quintptr_t mask, const qintptr_t *arg) +static quintptr_t QDECL Plug_Sys_Milliseconds(void) { - return Sys_DoubleTime()*1000; -} -static qintptr_t VARGS Plug_Sys_LoadLibrary(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - if (offset) - return 0; - return (qintptr_t)Sys_LoadLibrary(VM_POINTER(arg[0]), VM_POINTER(arg[1])); -} -static qintptr_t VARGS Plug_Sys_CloseLibrary(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - if (offset) - return 0; - Sys_CloseLibrary(VM_POINTER(arg[0])); - return 1; + return Sys_DoubleTime()*1000u; } -#ifdef MULTITHREAD -#ifdef Sys_CreateMutex -#undef Sys_CreateMutex -#endif -static qintptr_t VARGS Plug_Sys_GetThreadingFuncs(void *offset, quintptr_t mask, const qintptr_t *arg) +qboolean VARGS PlugBI_ExportFunction(const char *name, funcptr_t function) { - int threadingsize = VM_LONG(arg[0]); - static threading_t funcs = - { - Sys_CreateMutex, - Sys_LockMutex, - Sys_UnlockMutex, - Sys_DestroyMutex - }; - if (offset) - return 0; - if (threadingsize != sizeof(threading_t)) - return 0; - return (qintptr_t)&funcs; -} -#endif -static qintptr_t VARGS Plug_PR_GetVMInstance(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - int vmid = VM_LONG(arg[0]); - struct pubprogfuncs_s *pr = NULL; - if (offset) - return 0; - switch(vmid) - { -#ifndef CLIENTONLY - case 0: - pr = sv.world.progs; - break; -#endif -#if defined(CSQC_DAT) && !defined(SERVERONLY) - case 1: - { - extern world_t csqc_world; - pr = csqc_world.progs; - } - break; -#endif -#if defined(MENU_DAT) && !defined(SERVERONLY) - case 2: - { - extern world_t menu_world; - pr = menu_world.progs; - } - break; -#endif - default: - pr = NULL; //unknown vmid / not present in this build. - break; - } - return (qintptr_t)pr; -} - -static qintptr_t VARGS Plug_ExportToEngine(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - char *name = (char*)VM_POINTER(arg[0]); - quintptr_t functionid = arg[1]; - if (!strcmp(name, "Tick")) //void(int realtime) - currentplug->tick = functionid; + currentplug->tick = function; else if (!strcmp(name, "ExecuteCommand")) //bool(isinsecure) - currentplug->executestring = functionid; + currentplug->executestring = function; else if (!strcmp(name, "Shutdown")) //void() - currentplug->shutdown = functionid; -#ifndef SERVERONLY + currentplug->shutdown = function; + else if (!strcmp(name, "MayShutdown")||!strcmp(name, "MayUnload")) + currentplug->mayshutdown = function; +#ifdef HAVE_CLIENT else if (!strcmp(name, "ConsoleLink")) - currentplug->consolelink = functionid; + currentplug->consolelink = function; else if (!strcmp(name, "ConsoleLinkMouseOver")) - currentplug->consolelinkmouseover = functionid; + currentplug->consolelinkmouseover = function; else if (!strcmp(name, "ConExecuteCommand")) - currentplug->conexecutecommand = functionid; + currentplug->conexecutecommand = function; else if (!strcmp(name, "MenuEvent")) - currentplug->menufunction = functionid; + currentplug->menufunction = function; else if (!strcmp(name, "UpdateVideo")) - currentplug->reschange = functionid; + currentplug->reschange = function; else if (!strcmp(name, "SbarBase")) //basic SBAR. - currentplug->sbarlevel[0] = functionid; + currentplug->sbarlevel[0] = function; else if (!strcmp(name, "SbarSupplement")) //supplementry stuff - teamplay - currentplug->sbarlevel[1] = functionid; + currentplug->sbarlevel[1] = function; else if (!strcmp(name, "SbarOverlay")) //overlay - scoreboard type stuff. - currentplug->sbarlevel[2] = functionid; + currentplug->sbarlevel[2] = function; else if (!strcmp(name, "ConnectionlessClientPacket")) - currentplug->connectionlessclientpacket = functionid; + currentplug->connectionlessclientpacket = function; else if (!strcmp(name, "ServerMessageEvent")) - currentplug->svmsgfunction = functionid; + currentplug->svmsgfunction = function; else if (!strcmp(name, "ChatMessageEvent")) - currentplug->chatmsgfunction = functionid; + currentplug->chatmsgfunction = function; else if (!strcmp(name, "CenterPrintMessage")) - currentplug->centerprintfunction = functionid; + currentplug->centerprintfunction = function; + else if (!strcmp(name, "S_LoadSound")) //a hook for loading extra types of sound (wav, mp3, ogg, midi, whatever you choose to support) + S_RegisterSoundInputPlugin(currentplug, function); #endif + else if (!strncmp(name, "FS_RegisterArchiveType_", 23)) //module as in pak/pk3 + FS_RegisterFileSystemType(currentplug, name+23, function, true); else return 0; return 1; } //retrieve a plugin's name -static qintptr_t VARGS Plug_GetPluginName(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL PlugBI_GetPluginName(int plugnum, char *outname, size_t namesize) { - int plugnum = VM_LONG(arg[0]); plugin_t *plug; //int plugnum (0 for current), char *buffer, int bufferlen - if (VM_OOB(arg[1], arg[2])) - return false; - if (plugnum <= 0) { if (!currentplug) return false; - else if (plugnum == -1 && currentplug->vm) //plugin file name - Q_strncpyz(VM_POINTER(arg[1]), VM_GetFilename(currentplug->vm), VM_LONG(arg[2])); + else if (plugnum == -1 && currentplug->lib) //plugin file name + Q_strncpyz(outname, currentplug->filename, namesize); else //plugin name - Q_strncpyz(VM_POINTER(arg[1]), currentplug->name, VM_LONG(arg[2])); + Q_strncpyz(outname, currentplug->name, namesize); return true; } @@ -526,42 +370,17 @@ static qintptr_t VARGS Plug_GetPluginName(void *offset, quintptr_t mask, const q { if (--plugnum == 0) { - Q_strncpyz(VM_POINTER(arg[1]), plug->name, VM_LONG(arg[2])); + Q_strncpyz(outname, plug->name, namesize); return true; } } return false; } -static qintptr_t VARGS Plug_ExportNative(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL PlugBI_ExportInterface(const char *name, void *interfaceptr, size_t structsize) { - void *func; - char *name = (char*)VM_POINTER(arg[0]); - - if (offset) //QVMs are not allowed to call this - return 0; - - arg++; - - func = ((void**)arg)[0]; - - if (!strcmp(name, "UnsafeClose")) - { - //not used by the engine, but stops the user from being able to unload the plugin. - //this is useful for certain things, like if the plugin uses some external networking or direct disk access or whatever. - currentplug->blockcloses++; - } - else if (!strncmp(name, "FS_RegisterArchiveType_", 23)) //module as in pak/pk3 - { - FS_RegisterFileSystemType(currentplug, name+23, func, true); - } - /* - else if (!strncmp(name, "S_OutputDriver")) //a sound driver (takes higher priority over the built-in ones) - { - S_RegisterOutputDriver(name + 13, func); - currentplug->blockcloses++; - } - */ + if (0) + ; /* else if (!strncmp(name, "VID_DisplayDriver")) //a video driver, loaded by name as given by vid_renderer { @@ -572,43 +391,23 @@ static qintptr_t VARGS Plug_ExportNative(void *offset, quintptr_t mask, const qi #if defined(PLUGINS) && !defined(SERVERONLY) #ifdef HAVE_MEDIA_DECODER else if (!strcmp(name, "Media_VideoDecoder")) - { - Media_RegisterDecoder(currentplug, func); -// currentplug->blockcloses++; - } + Media_RegisterDecoder(currentplug, interfaceptr); #endif #ifdef HAVE_MEDIA_ENCODER else if (!strcmp(name, "Media_VideoEncoder")) - { - Media_RegisterEncoder(currentplug, func); -// currentplug->blockcloses++; - } + Media_RegisterEncoder(currentplug, interfaceptr); #endif -#endif - -#ifndef SERVERONLY - else if (!strcmp(name, "S_LoadSound")) //a hook for loading extra types of sound (wav, mp3, ogg, midi, whatever you choose to support) - { - S_RegisterSoundInputPlugin((void*)func); - currentplug->blockcloses++; - } #endif else return 0; return 1; } -static qintptr_t VARGS Plug_Cvar_GetNVFDG(void *offset, quintptr_t mask, const qintptr_t *arg) +static cvar_t *QDECL Plug_Cvar_GetNVFDG(const char *name, const char *defaultvalue, unsigned int flags, const char *description, const char *groupname) { - char *name = VM_POINTER(arg[0]); - char *defaultvalue = VM_POINTER(arg[1]); - unsigned int flags = VM_LONG(arg[2]); - char *description = VM_POINTER(arg[3]); - char *groupname = VM_POINTER(arg[4]); - if (!defaultvalue) - return (qintptr_t)Cvar_FindVar(name); - return (qintptr_t)Cvar_Get2(name, defaultvalue, flags&1, description, groupname); + return Cvar_FindVar(name); + return Cvar_Get2(name, defaultvalue, flags&1, description, groupname); } @@ -617,15 +416,11 @@ typedef struct { plugin_t *plugin; cvar_t *var; } plugincvararray_t; -int plugincvararraylen; -plugincvararray_t *plugincvararray; +static int plugincvararraylen; +static plugincvararray_t *plugincvararray; //qhandle_t Cvar_Register (char *name, char *defaultval, int flags, char *grouphint); -static qintptr_t VARGS Plug_Cvar_Register(void *offset, quintptr_t mask, const qintptr_t *arg) +static qhandle_t QDECL Plug_Cvar_Register(const char *name, const char *defaultvalue, int flags, const char *groupname) { - char *name = VM_POINTER(arg[0]); - char *defaultvalue = VM_POINTER(arg[1]); - unsigned int flags = VM_LONG(arg[2]); - char *groupname = VM_POINTER(arg[3]); cvar_t *var; int i; @@ -649,185 +444,136 @@ static qintptr_t VARGS Plug_Cvar_Register(void *offset, quintptr_t mask, const q return i; } //int Cvar_Update, (qhandle_t handle, int modificationcount, char *stringv, float *floatv)); //stringv is 256 chars long, don't expect this function to do anything if modification count is unchanged. -static qintptr_t VARGS Plug_Cvar_Update(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_Cvar_Update(qhandle_t handle, int *modificationcount, char *outstringv, size_t stringsize, float *outfloatv) { - int handle; -// int modcount; - char *stringv; //255 bytes long. - float *floatv; cvar_t *var; - handle = VM_LONG(arg[0]); if (handle < 0 || handle >= plugincvararraylen) - return 0; + return false; if (plugincvararray[handle].plugin != currentplug) - return 0; //I'm not letting you know what annother plugin has registered. - - if (VM_OOB(arg[2], 256) || VM_OOB(arg[3], 4)) //Oi, plugin - you screwed up - return 0; - - //modcount = VM_LONG(arg[1]); //for future optimisation - stringv = VM_POINTER(arg[2]); - floatv = VM_POINTER(arg[3]); + return false; //I'm not letting you know what annother plugin has registered. var = plugincvararray[handle].var; - //if (var->modified != modcount) //for future optimisation + //if (var->modified != *modificationcount) //for future optimisation { - strcpy(stringv, var->string); - *floatv = var->value; + //*modificationcount = var->modified; + Q_strncpyz(outstringv, var->string, stringsize); + *outfloatv = var->value; + return true; } - return var->modified; + return false; } //void Cmd_Args(char *buffer, int buffersize) -static qintptr_t VARGS Plug_Cmd_Args(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Cmd_Args(char *buffer, int maxsize) { - char *buffer = (char*)VM_POINTER(arg[0]); - size_t maxsize = VM_LONG(arg[1]); char *args; args = Cmd_Args(); - if (VM_OOB(arg[0], arg[1])) - return false; if (strlen(args)+1>maxsize) { if (maxsize) *buffer = 0; - return 0; } - strcpy(buffer, args); - return 1; + else + strcpy(buffer, args); } //void Cmd_Argv(int num, char *buffer, int buffersize) -static qintptr_t VARGS Plug_Cmd_Argv(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Cmd_Argv(int argn, char *outbuffer, size_t buffersize) { - char *buffer = (char*)VM_POINTER(arg[1]); - size_t maxsize = VM_LONG(arg[2]); char *args; - args = Cmd_Argv(arg[0]); + args = Cmd_Argv(argn); - if (VM_OOB(arg[1], arg[2])) - return false; - if (strlen(args)+1>maxsize) + if (strlen(args)+1>buffersize) { - if (maxsize) - *buffer = 0; - return 0; + if (buffersize) + *outbuffer = 0; } - strcpy(buffer, args); - return 1; + else + strcpy(outbuffer, args); } //int Cmd_Argc(void) -static qintptr_t VARGS Plug_Cmd_Argc(void *offset, quintptr_t mask, const qintptr_t *arg) +static int QDECL Plug_Cmd_Argc(void) { return Cmd_Argc(); } //void Cvar_SetString (char *name, char *value); -static qintptr_t VARGS Plug_Cvar_SetString(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Cvar_SetString(const char *name, const char *value) { - char *name = VM_POINTER(arg[0]), - *value = VM_POINTER(arg[1]); cvar_t *var = Cvar_Get(name, value, 0, "Plugin vars"); if (var) - { Cvar_Set(var, value); - return 1; - } - - return 0; } //void Cvar_SetFloat (char *name, float value); -static qintptr_t VARGS Plug_Cvar_SetFloat(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Cvar_SetFloat(const char *cvarname, float newvalue) { - char *name = VM_POINTER(arg[0]); - float value = VM_FLOAT(arg[1]); - cvar_t *var = Cvar_Get(name, "", 0, "Plugin vars"); //"" because I'm lazy + cvar_t *var = Cvar_Get(cvarname, "", 0, "Plugin vars"); //"" because I'm lazy if (var) - { - Cvar_SetValue(var, value); - return 1; - } - - return 0; + Cvar_SetValue(var, newvalue); } //void Cvar_GetFloat (char *name); -static qintptr_t VARGS Plug_Cvar_GetFloat(void *offset, quintptr_t mask, const qintptr_t *arg) +static float QDECL Plug_Cvar_GetFloat(const char *cvarname) { - char *name = VM_POINTER(arg[0]); int ret; cvar_t *var; #ifndef CLIENTONLY - if (!strcmp(name, "sv.state")) - VM_FLOAT(ret) = sv.state; + if (!strcmp(cvarname, "sv.state")) //ugly hack + return sv.state; else #endif { - var = Cvar_Get(name, "", 0, "Plugin vars"); + var = Cvar_Get(cvarname, "", 0, "Plugin vars"); if (var) - { - VM_FLOAT(ret) = var->value; - } + return var->value; else - VM_FLOAT(ret) = 0; + return 0; } return ret; } //qboolean Cvar_GetString (char *name, char *retstring, int sizeofretstring); -static qintptr_t VARGS Plug_Cvar_GetString(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_Cvar_GetString(const char *name, char *outbuffer, quintptr_t sizeofbuffer) { - char *name, *ret; - int retsize; cvar_t *var; - if (VM_OOB(arg[1], arg[2])) - { - return false; - } - - name = VM_POINTER(arg[0]); - ret = VM_POINTER(arg[1]); - retsize = VM_LONG(arg[2]); if (!strcmp(name, "sv.mapname")) { #ifdef CLIENTONLY Q_strncpyz(ret, "", retsize); #else - Q_strncpyz(ret, svs.name, retsize); + Q_strncpyz(outbuffer, svs.name, sizeofbuffer); #endif } else { var = Cvar_Get(name, "", 0, "Plugin vars"); - if (strlen(var->name)+1 > retsize) + if (strlen(var->name)+1 > sizeofbuffer) return false; - strcpy(ret, var->string); + strcpy(outbuffer, var->string); } return true; } //void Cmd_AddText (char *text, qboolean insert); //abort the entire engine. -static qintptr_t VARGS Plug_Cmd_AddText(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Cmd_AddText(const char *text, qboolean insert) { - int level = offset?RESTRICT_INSECURE:RESTRICT_LOCAL; - if (VM_LONG(arg[1])) - Cbuf_InsertText(VM_POINTER(arg[0]), level, false); + int level = RESTRICT_LOCAL; + if (insert) + Cbuf_InsertText(text, level, false); else - Cbuf_AddText(VM_POINTER(arg[0]), level); - - return 1; + Cbuf_AddText(text, level); } -int plugincommandarraylen; +static int plugincommandarraylen; typedef struct { plugin_t *plugin; char command[64]; } plugincommand_t; -plugincommand_t *plugincommandarray; +static plugincommand_t *plugincommandarray; void Plug_Command_f(void) { int i; @@ -844,17 +590,16 @@ void Plug_Command_f(void) currentplug = plugincommandarray[i].plugin; if (currentplug->executestring) - VM_Call(currentplug->vm, currentplug->executestring, Cmd_IsInsecure(), 0, 0, 0); + currentplug->executestring(Cmd_IsInsecure()); break; } currentplug = oldplug; } -static qintptr_t VARGS Plug_Cmd_AddCommand(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_Cmd_AddCommand(const char *name) { int i; - char *name = VM_POINTER(arg[0]); for (i = 0; i < plugincommandarraylen; i++) { if (!plugincommandarray[i].plugin) @@ -877,7 +622,7 @@ static qintptr_t VARGS Plug_Cmd_AddCommand(void *offset, quintptr_t mask, const plugincommandarray[i].plugin = currentplug; //worked return true; } -static void VARGS Plug_FreeConCommands(plugin_t *plug) +static void Plug_FreeConCommands(plugin_t *plug) { int i; for (i = 0; i < plugincommandarraylen; i++) @@ -911,8 +656,8 @@ typedef struct { // int curpos; } file; } pluginstream_t; -pluginstream_t *pluginstreamarray; -unsigned int pluginstreamarraylen; +static pluginstream_t *pluginstreamarray; +static unsigned int pluginstreamarraylen; static int Plug_NewStreamHandle(plugstream_e type) { @@ -937,10 +682,22 @@ static int Plug_NewStreamHandle(plugstream_e type) return i; } +#ifdef HAVE_CLIENT +static qhandle_t QDECL Plug_Con_POpen(const char *consolename) +{ + int handle; + if (!currentplug) + return -3; //streams depend upon current plugin context. which isn't valid in a thread. + handle = Plug_NewStreamHandle(STREAM_VFS); + pluginstreamarray[handle].vfs = Con_POpen(consolename); + return handle; +} +#endif + #ifdef HAVE_PACKET //EBUILTIN(int, NET_TCPListen, (char *ip, int port, int maxcount)); //returns a new socket with listen enabled. -static qintptr_t VARGS Plug_Net_TCPListen(void *offset, quintptr_t mask, const qintptr_t *arg) +static qhandle_t QDECL Plug_Net_TCPListen(const char *localip, int localport, int maxcount) { int handle; int sock; @@ -948,10 +705,6 @@ static qintptr_t VARGS Plug_Net_TCPListen(void *offset, quintptr_t mask, const q int _true = 1; int alen; - char *localip = VM_POINTER(arg[0]); - unsigned short localport = VM_LONG(arg[1]); - int maxcount = VM_LONG(arg[2]); - netadr_t a; if (!currentplug) return -3; //streams depend upon current plugin context. which isn't valid in a thread. @@ -993,10 +746,10 @@ static qintptr_t VARGS Plug_Net_TCPListen(void *offset, quintptr_t mask, const q return handle; } -static qintptr_t VARGS Plug_Net_Accept(void *offset, quintptr_t mask, const qintptr_t *arg) + +static qhandle_t QDECL Plug_Net_Accept(qhandle_t handle, char *outaddress, int outaddresssize) { - int handle = VM_LONG(arg[0]); - struct sockaddr_in address; + struct sockaddr_qstorage address; int addrlen; int sock; int _true = 1; @@ -1020,13 +773,13 @@ static qintptr_t VARGS Plug_Net_Accept(void *offset, quintptr_t mask, const qint return -1; } - if (arg[2] && !VM_OOB(arg[1], arg[2])) + if (outaddresssize) { netadr_t a; char *s; - SockadrToNetadr((struct sockaddr_qstorage *)&address, addrlen, &a); + SockadrToNetadr(&address, addrlen, &a); s = NET_AdrToString(adr, sizeof(adr), &a); - Q_strncpyz(VM_POINTER(arg[1]), s, addrlen); + Q_strncpyz(outaddress, s, addrlen); } handle = Plug_NewStreamHandle(STREAM_SOCKET); @@ -1034,12 +787,9 @@ static qintptr_t VARGS Plug_Net_Accept(void *offset, quintptr_t mask, const qint return handle; } -//EBUILTIN(int, NET_TCPConnect, (char *ip, int port)); -static qintptr_t VARGS Plug_Net_TCPConnect(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - char *remoteip = VM_POINTER(arg[0]); - unsigned short remoteport = VM_LONG(arg[1]); +static qhandle_t QDECL Plug_Net_TCPConnect(const char *remoteip, int remoteport) +{ int handle; vfsfile_t *stream = FS_OpenTCP(remoteip, remoteport); if (!currentplug || !stream) @@ -1051,12 +801,11 @@ static qintptr_t VARGS Plug_Net_TCPConnect(void *offset, quintptr_t mask, const } -void Plug_Net_Close_Internal(int handle); +void Plug_Net_Close_Internal(qhandle_t handle); #ifdef HAVE_SSL -static qintptr_t VARGS Plug_Net_SetTLSClient(void *offset, quintptr_t mask, const qintptr_t *arg) +static int QDECL Plug_Net_SetTLSClient(qhandle_t handle, const char *certhostname) { pluginstream_t *stream; - unsigned int handle = VM_LONG(arg[0]); if (handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug) { Con_Printf("Plug_Net_SetTLSClient: socket does not belong to you (or is invalid)\n"); @@ -1069,7 +818,7 @@ static qintptr_t VARGS Plug_Net_SetTLSClient(void *offset, quintptr_t mask, cons return -2; } - stream->vfs = FS_OpenSSL(VM_POINTER(arg[1]), stream->vfs, false); + stream->vfs = FS_OpenSSL(certhostname, stream->vfs, false); if (!stream->vfs) { Plug_Net_Close_Internal(handle); @@ -1078,18 +827,11 @@ static qintptr_t VARGS Plug_Net_SetTLSClient(void *offset, quintptr_t mask, cons return 0; } -static qintptr_t VARGS Plug_Net_GetTLSBinding(void *offset, quintptr_t mask, const qintptr_t *arg) +static int QDECL Plug_Net_GetTLSBinding(qhandle_t handle, char *outbinddata, int *outbinddatalen) { pluginstream_t *stream; - unsigned int handle = VM_LONG(arg[0]); - qbyte *binddata = VM_POINTER(arg[1]); - unsigned int *bindsize = VM_POINTER(arg[2]); size_t sz; int r; - if (VM_OOB(arg[2], sizeof(int))) - return -2; - if (VM_OOB(arg[1], *bindsize)) - return -2; if ((size_t)handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug) { Con_Printf("Plug_Net_GetTLSBinding: socket does not belong to you (or is invalid)\n"); @@ -1102,33 +844,14 @@ static qintptr_t VARGS Plug_Net_GetTLSBinding(void *offset, quintptr_t mask, con return -2; } - sz = *bindsize; - r = TLS_GetChannelBinding(stream->vfs, binddata, &sz); - *bindsize = sz; + sz = *outbinddatalen; + r = TLS_GetChannelBinding(stream->vfs, outbinddata, &sz); + *outbinddatalen = sz; return r; } #endif #endif -static qintptr_t VARGS Plug_VFS_Open(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - char *fname = VM_POINTER(arg[0]); - vfsfile_t **handle = VM_POINTER(arg[1]); - char *mode = VM_POINTER(arg[2]); - *handle = offset?NULL:FS_OpenVFS(fname, mode, FS_GAME); - if (*handle) - return true; - return false; -} -static qintptr_t VARGS Plug_FS_NativePath(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - const char *fname = VM_POINTER(arg[0]); - enum fs_relative relativeto = VM_LONG(arg[1]); - char *out = VM_POINTER(arg[2]); - size_t outlen = VM_LONG(arg[3]); - return offset?false:FS_NativePath(fname, relativeto, out, outlen); -} - #ifdef WEBCLIENT static void Plug_DownloadComplete(struct dl_download *dl) { @@ -1139,18 +862,8 @@ static void Plug_DownloadComplete(struct dl_download *dl) } #endif -static qintptr_t VARGS Plug_Con_POpen(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - char *conname = VM_POINTER(arg[0]); - int handle; - if (!currentplug) - return -3; //streams depend upon current plugin context. which isn't valid in a thread. - handle = Plug_NewStreamHandle(STREAM_VFS); - pluginstreamarray[handle].vfs = Con_POpen(conname); - return handle; -} -static qintptr_t VARGS Plug_FS_Open(void *offset, quintptr_t mask, const qintptr_t *arg) +static qhandle_t QDECL Plug_FS_Open(const char *fname, qhandle_t *outhandle, int modenum) { //modes: //1: read @@ -1161,20 +874,15 @@ static qintptr_t VARGS Plug_FS_Open(void *offset, quintptr_t mask, const qintptr //return value is length of the file. int handle; - int *ret; //char *data; char *mode; vfsfile_t *f; - char *fname = VM_POINTER(arg[0]); - if (VM_OOB(arg[1], sizeof(int))) - return -2; - ret = VM_POINTER(arg[1]); - *ret = -1; + *outhandle = -1; if (!currentplug) return -3; //streams depend upon current plugin context. which isn't valid in a thread. - switch(arg[2]) + switch(modenum) { case 1: mode = "rb"; @@ -1200,11 +908,11 @@ static qintptr_t VARGS Plug_FS_Open(void *offset, quintptr_t mask, const qintptr #ifdef MULTITHREAD DL_CreateThread(pluginstreamarray[handle].dl, NULL, NULL); #endif - *ret = handle; + *outhandle = handle; return VFS_GETLEN(pluginstreamarray[handle].vfs); #endif } - else if (arg[2] == 2) + else if (modenum == 2) f = FS_OpenVFS(fname, mode, FS_GAMEONLY); else f = FS_OpenVFS(fname, mode, FS_GAME); @@ -1213,13 +921,11 @@ static qintptr_t VARGS Plug_FS_Open(void *offset, quintptr_t mask, const qintptr handle = Plug_NewStreamHandle(STREAM_VFS); pluginstreamarray[handle].vfs = f; Q_strncpyz(pluginstreamarray[handle].file.filename, fname, sizeof(pluginstreamarray[handle].file.filename)); - *ret = handle; + *outhandle = handle; return VFS_GETLEN(pluginstreamarray[handle].vfs); } -static qintptr_t VARGS Plug_FS_Seek(void *offset, quintptr_t mask, const qintptr_t *arg) +static int QDECL Plug_FS_Seek(qhandle_t handle, qofs_t offset) { - unsigned int handle = VM_LONG(arg[0]); - unsigned int low = VM_LONG(arg[1]), high = VM_LONG(arg[2]); pluginstream_t *stream; if (handle >= pluginstreamarraylen) @@ -1227,125 +933,28 @@ static qintptr_t VARGS Plug_FS_Seek(void *offset, quintptr_t mask, const qintptr stream = &pluginstreamarray[handle]; if (stream->type != STREAM_VFS) return -1; - VFS_SEEK(stream->vfs, low | ((quint64_t)high<<32)); + VFS_SEEK(stream->vfs, offset); return VFS_TELL(stream->vfs); } -static qintptr_t VARGS Plug_FS_GetLength(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_FS_GetLength(qhandle_t handle, qofs_t *outsize) { - unsigned int handle = VM_LONG(arg[0]); - unsigned int *low = VM_POINTER(arg[1]), *high = VM_POINTER(arg[2]); pluginstream_t *stream; - qofs_t size; if (handle >= pluginstreamarraylen) return false; - if (VM_OOB(arg[1], sizeof(*low))) - return false; - if (VM_OOB(arg[2], sizeof(*high))) - return false; - stream = &pluginstreamarray[handle]; if (stream->type == STREAM_VFS) if (stream->vfs->GetLen) { - size = VFS_GETLEN(stream->vfs); - if (low) - *low = qofs_Low(size); - if (high) - *high = qofs_High(size); + *outsize = VFS_GETLEN(stream->vfs); return true; } - if (low) - *low = 0; - if (high) - *high = 0; + *outsize = 0; return false; } -static qintptr_t VARGS Plug_memset(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - void *p = VM_POINTER(arg[0]); - - if (VM_OOB(arg[0], arg[2])) - return false; - - if (p) - memset(p, VM_LONG(arg[1]), VM_LONG(arg[2])); - - return arg[0]; -} -static qintptr_t VARGS Plug_memcpy(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - void *p1 = VM_POINTER(arg[0]); - void *p2 = VM_POINTER(arg[1]); - - if (VM_OOB(arg[0], arg[2])) - return false; - - if (VM_OOB(arg[1], arg[2])) - return false; - - if (p1 && p2) - memcpy(p1, p2, VM_LONG(arg[2])); - - return arg[0]; -} -static qintptr_t VARGS Plug_memmove(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - void *p1 = VM_POINTER(arg[0]); - void *p2 = VM_POINTER(arg[1]); - - if (VM_OOB(arg[0], arg[2])) - return false; - - if (VM_OOB(arg[1], arg[2])) - return false; - - if (p1 && p2) - memmove(p1, p2, VM_LONG(arg[2])); - - return arg[0]; -} - -static qintptr_t VARGS Plug_sqrt(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - union { - qintptr_t i; - float f; - } ret = {0}; - ret.f = sqrt(VM_FLOAT(arg[0])); - return ret.i; -} -static qintptr_t VARGS Plug_sin(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - union { - qintptr_t i; - float f; - } ret = {0}; - ret.f = sin(VM_FLOAT(arg[0])); - return ret.i; -} -static qintptr_t VARGS Plug_cos(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - union { - qintptr_t i; - float f; - } ret = {0}; - ret.f = cos(VM_FLOAT(arg[0])); - return ret.i; -} -static qintptr_t VARGS Plug_atan2(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - union { - qintptr_t i; - float f; - } ret = {0}; - ret.f = atan2(VM_FLOAT(arg[0]), VM_FLOAT(arg[1])); - return ret.i; -} - -void Plug_Net_Close_Internal(int handle) +void Plug_Net_Close_Internal(qhandle_t handle) { switch(pluginstreamarray[handle].type) { @@ -1383,15 +992,10 @@ void Plug_Net_Close_Internal(int handle) pluginstreamarray[handle].type = STREAM_NONE; pluginstreamarray[handle].plugin = NULL; } -static qintptr_t VARGS Plug_Net_Recv(void *offset, quintptr_t mask, const qintptr_t *arg) + +static int QDECL Plug_Net_Recv(qhandle_t handle, void *dest, int destlen) { int read; - int handle = VM_LONG(arg[0]); - void *dest = VM_POINTER(arg[1]); - int destlen = VM_LONG(arg[2]); - - if (VM_OOB(arg[1], arg[2])) - return -2; if (handle < 0 || handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug) return -2; @@ -1419,12 +1023,9 @@ static qintptr_t VARGS Plug_Net_Recv(void *offset, quintptr_t mask, const qintpt return -2; } } -static qintptr_t VARGS Plug_Net_Send(void *offset, quintptr_t mask, const qintptr_t *arg) +static int QDECL Plug_Net_Send(qhandle_t handle, void *src, int srclen) { int written; - int handle = VM_LONG(arg[0]); - void *src = VM_POINTER(arg[1]); - int srclen = VM_LONG(arg[2]); if (handle < 0 || handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug) return -2; switch(pluginstreamarray[handle].type) @@ -1451,15 +1052,9 @@ static qintptr_t VARGS Plug_Net_Send(void *offset, quintptr_t mask, const qintpt return -2; } } -static qintptr_t VARGS Plug_Net_SendTo(void *offset, quintptr_t mask, const qintptr_t *arg) +static int QDECL Plug_Net_SendTo(qhandle_t handle, void *src, int srclen, netadr_t *address) { int written; - int handle = VM_LONG(arg[0]); - void *src = VM_POINTER(arg[1]); - int srclen = VM_LONG(arg[2]); - - netadr_t *address = VM_POINTER(arg[3]); - struct sockaddr_qstorage sockaddr; if (handle == -1) @@ -1496,44 +1091,17 @@ static qintptr_t VARGS Plug_Net_SendTo(void *offset, quintptr_t mask, const qint return -2; } } -static qintptr_t VARGS Plug_Net_Close(void *offset, quintptr_t mask, const qintptr_t *arg) +static void QDECL Plug_Net_Close(qhandle_t handle) { - int handle = VM_LONG(arg[0]); if (handle < 0 || handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug) - return -2; - + return; Plug_Net_Close_Internal(handle); - return 0; -} - -static qintptr_t VARGS Plug_ReadInputBuffer(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - void *buffer = VM_POINTER(arg[0]); - int bufferlen = VM_LONG(arg[1]); - if (bufferlen > currentplug->inputbytes) - bufferlen = currentplug->inputbytes; - memcpy(buffer, currentplug->inputptr, currentplug->inputbytes); - return bufferlen; -} -static qintptr_t VARGS Plug_UpdateInputBuffer(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - void *buffer = VM_POINTER(arg[0]); - int bufferlen = VM_LONG(arg[1]); - if (bufferlen > currentplug->inputbytes) - bufferlen = currentplug->inputbytes; - memcpy(currentplug->inputptr, buffer, currentplug->inputbytes); - return bufferlen; } #if defined(HAVE_SERVER) && defined(HAVE_CLIENT) qboolean FS_PathURLCache(const char *url, char *path, size_t pathsize); -static qintptr_t VARGS Plug_MapLog_Query(void *offset, quintptr_t mask, const qintptr_t *arg) +static qboolean QDECL Plug_MapLog_Query(const char *packagename, const char *mapname, float *vals) { - const char *packagename = VM_POINTER(arg[0]); - const char *mapname = VM_POINTER(arg[1]); - float *vals = VM_POINTER(arg[2]); - if (VM_OOB(arg[2], sizeof(*vals)*4)) - return false; if (!strncmp(packagename, "http://", 7) || !strncmp(packagename, "https://", 8)) { char temp[MAX_OSPATH]; @@ -1547,31 +1115,6 @@ static qintptr_t VARGS Plug_MapLog_Query(void *offset, quintptr_t mask, const qi } #endif -#ifdef USERBE -#include "pr_common.h" -//functions useful for rigid body engines. -static qintptr_t VARGS Plug_RBE_GetPluginFuncs(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - static rbeplugfuncs_t funcs = - { - RBEPLUGFUNCS_VERSION, - - World_RegisterPhysicsEngine, - World_UnregisterPhysicsEngine, - World_GenerateCollisionMesh, - World_ReleaseCollisionMesh, - World_LinkEdict, - - VectorAngles, - AngleVectors - }; - if (VM_LONG(arg[0]) >= sizeof(funcs)) - return (qintptr_t)&funcs; - else - return 0; -} -#endif - void Plug_CloseAll_f(void); void Plug_List_f(void); void Plug_Close_f(void); @@ -1584,53 +1127,18 @@ static void Plug_Load_f(void) Con_Printf("Loads a plugin\n"); Con_Printf("plug_load [pluginpath]\n"); Con_Printf("example pluginpath: blah\n"); - Con_Printf("will load "PLUGINPREFIX"blah"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX" or $gamedir/plugins/blah.qvm\n"); + Con_Printf("will load "PLUGINPREFIX"blah"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX"\n"); return; } - if (!Plug_Load(plugin, PLUG_EITHER)) - { - if (!Plug_Load(va("plugins/%s", plugin), PLUG_QVM)) - Con_Printf("Couldn't load plugin %s\n", Cmd_Argv(1)); - } -} -/* -static qintptr_t Test_SysCalls_Ex(void *offset, quintptr_t mask, int fn, qintptr_t *arg) -{ - switch(fn) - { - case 1: - Con_Printf("%s", VM_POINTER(arg[0])); - break; - default: - Con_Printf("Can't handle %i\n", fn); - } - return 0; -} -static int EXPORT_FN Test_SysCalls(int arg, ...) -{ - return 0; -} -void VM_Test_f(void) -{ - vm_t *vm; - vm = VM_Create(NULL, "vm/test", com_nogamedirnativecode.ival?NULL:Test_SysCalls, Test_SysCalls_Ex); - if (vm) - { - VM_Call(vm, 0, ""); - VM_Destroy(vm); - } -}*/ - -static void Plug_LoadDownloaded(const char *fname) -{ - Plug_Load(fname, PLUG_NATIVE); + if (!Plug_Load(plugin)) + Con_Printf("Couldn't load plugin %s\n", Cmd_Argv(1)); } void Plug_Initialise(qboolean fromgamedir) { char nat[MAX_OSPATH]; - if (!numplugbuiltins) + if (!plugfuncs) { Cvar_Register(&plug_sbar, "plugins"); Cvar_Register(&plug_loaddefault, "plugins"); @@ -1640,83 +1148,10 @@ void Plug_Initialise(qboolean fromgamedir) Cmd_AddCommand("plug_load", Plug_Load_f); Cmd_AddCommand("plug_list", Plug_List_f); - Plug_RegisterBuiltin("Plug_GetNativePointer", Plug_GetNativePointer, PLUG_BIF_DLLONLY);//plugin wishes to get a native interface. - Plug_RegisterBuiltin("Plug_GetEngineFunction", Plug_GetBuiltin, 0);//plugin wishes to find a builtin number. - Plug_RegisterBuiltin("Plug_ExportToEngine", Plug_ExportToEngine, 0); //plugin has a call back that we might be interested in. - Plug_RegisterBuiltin("Plug_ExportNative", Plug_ExportNative, PLUG_BIF_DLLONLY); - Plug_RegisterBuiltin("Plug_GetPluginName", Plug_GetPluginName, 0); - Plug_RegisterBuiltin("Con_Print", Plug_Con_Print, 0); //printf is not possible - qvm floats are never doubles, vararg floats in a cdecl call are always converted to doubles. - Plug_RegisterBuiltin("Con_POpen", Plug_Con_POpen, PLUG_BIF_DLLONLY); - Plug_RegisterBuiltin("Sys_Error", Plug_Sys_Error, 0); - Plug_RegisterBuiltin("Sys_Milliseconds", Plug_Sys_Milliseconds, 0); - Plug_RegisterBuiltin("Com_Error", Plug_Sys_Error, 0); //make zquake programmers happy. - - Plug_RegisterBuiltin("Cmd_AddCommand", Plug_Cmd_AddCommand, 0); - Plug_RegisterBuiltin("Cmd_Args", Plug_Cmd_Args, 0); - Plug_RegisterBuiltin("Cmd_Argc", Plug_Cmd_Argc, 0); - Plug_RegisterBuiltin("Cmd_Argv", Plug_Cmd_Argv, 0); - Plug_RegisterBuiltin("Cmd_AddText", Plug_Cmd_AddText, 0); - - Plug_RegisterBuiltin("Cvar_Register", Plug_Cvar_Register, 0); - Plug_RegisterBuiltin("Cvar_Update", Plug_Cvar_Update, 0); - Plug_RegisterBuiltin("Cvar_SetString", Plug_Cvar_SetString, 0); - Plug_RegisterBuiltin("Cvar_SetFloat", Plug_Cvar_SetFloat, 0); - Plug_RegisterBuiltin("Cvar_GetString", Plug_Cvar_GetString, 0); - Plug_RegisterBuiltin("Cvar_GetFloat", Plug_Cvar_GetFloat, 0); - Plug_RegisterBuiltin("Cvar_GetNVFDG", Plug_Cvar_GetNVFDG, PLUG_BIF_DLLONLY); - -#ifdef HAVE_PACKET - Plug_RegisterBuiltin("Net_TCPListen", Plug_Net_TCPListen, 0); - Plug_RegisterBuiltin("Net_Accept", Plug_Net_Accept, 0); - Plug_RegisterBuiltin("Net_TCPConnect", Plug_Net_TCPConnect, 0); -#ifdef HAVE_SSL - Plug_RegisterBuiltin("Net_SetTLSClient", Plug_Net_SetTLSClient, 0); - Plug_RegisterBuiltin("Net_GetTLSBinding", Plug_Net_GetTLSBinding, 0); -#endif - Plug_RegisterBuiltin("Net_Recv", Plug_Net_Recv, 0); - Plug_RegisterBuiltin("Net_Send", Plug_Net_Send, 0); - Plug_RegisterBuiltin("Net_SendTo", Plug_Net_SendTo, 0); - Plug_RegisterBuiltin("Net_Close", Plug_Net_Close, 0); -#endif - - - Plug_RegisterBuiltin("VFS_Open", Plug_VFS_Open, PLUG_BIF_DLLONLY); - Plug_RegisterBuiltin("FS_NativePath", Plug_FS_NativePath, PLUG_BIF_DLLONLY); - Plug_RegisterBuiltin("FS_Open", Plug_FS_Open, 0); - Plug_RegisterBuiltin("FS_Read", Plug_Net_Recv, 0); - Plug_RegisterBuiltin("FS_Write", Plug_Net_Send, 0); - Plug_RegisterBuiltin("FS_Close", Plug_Net_Close, 0); - Plug_RegisterBuiltin("FS_Seek", Plug_FS_Seek, 0); - Plug_RegisterBuiltin("FS_GetLen", Plug_FS_GetLength, 0); - - - Plug_RegisterBuiltin("memset", Plug_memset, 0); - Plug_RegisterBuiltin("memcpy", Plug_memcpy, 0); - Plug_RegisterBuiltin("memmove", Plug_memmove, 0); - Plug_RegisterBuiltin("sqrt", Plug_sqrt, 0); - Plug_RegisterBuiltin("sin", Plug_sin, 0); - Plug_RegisterBuiltin("cos", Plug_cos, 0); - Plug_RegisterBuiltin("atan2", Plug_atan2, 0); - - Plug_RegisterBuiltin("ReadInputBuffer", Plug_ReadInputBuffer, 0); - Plug_RegisterBuiltin("UpdateInputBuffer", Plug_UpdateInputBuffer, 0); - - Plug_RegisterBuiltin("Sys_LoadLibrary", Plug_Sys_LoadLibrary, PLUG_BIF_DLLONLY); - Plug_RegisterBuiltin("Sys_CloseLibrary", Plug_Sys_CloseLibrary, PLUG_BIF_DLLONLY); - -#ifdef USERBE - Plug_RegisterBuiltin("RBE_GetPluginFuncs", Plug_RBE_GetPluginFuncs, PLUG_BIF_DLLONLY); -#endif -#ifdef MULTITHREAD - Plug_RegisterBuiltin("Sys_GetThreadingFuncs", Plug_Sys_GetThreadingFuncs, PLUG_BIF_DLLONLY); -#endif - Plug_RegisterBuiltin("PR_GetVMInstance", Plug_PR_GetVMInstance, PLUG_BIF_DLLONLY); - -#if defined(HAVE_SERVER) && defined(HAVE_CLIENT) - Plug_RegisterBuiltin("MapLog_Query", Plug_MapLog_Query, 0); -#endif - - Plug_Client_Init(); + //set up internal plugins + plugfuncs = PlugBI_GetEngineInterface(plugcorefuncs_name, sizeof(*plugfuncs)); + cvarfuncs = plugfuncs->GetEngineInterface(plugcvarfuncs_name, sizeof(*cvarfuncs)); + cmdfuncs = plugfuncs->GetEngineInterface(plugcmdfuncs_name, sizeof(*cmdfuncs)); } #ifdef SUBSERVERS @@ -1730,18 +1165,14 @@ void Plug_Initialise(qboolean fromgamedir) Con_DPrintf("Loading plugins from \"%s\"\n", nat); Sys_EnumerateFiles(nat, PLUGINPREFIX"*" ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, Plug_EnumeratedRoot, NULL, NULL); } - if (fromgamedir) - { - COM_EnumerateFiles("plugins/*.qvm", Plug_Emumerated, ".qvm"); - } } if (plug_loaddefault.ival & 1) { unsigned int u; - PM_EnumeratePlugins(Plug_LoadDownloaded); + PM_EnumeratePlugins(Plug_Load_Update); for (u = 0; staticplugins[u].name; u++) { - Plug_Load(staticplugins[u].name, PLUG_NATIVE); + Plug_Load(staticplugins[u].name); } } } @@ -1753,8 +1184,7 @@ void Plug_Tick(void) { if (currentplug->tick) { - float rt = realtime; - float st = 0; + double st = 0; #ifdef SERVERONLY st = sv.time; #elif defined(CLIENTONLY) @@ -1762,7 +1192,7 @@ void Plug_Tick(void) #else st = sv.state?sv.time:cl.time; #endif - VM_Call(currentplug->vm, currentplug->tick, (int)(realtime*1000), *(int*)&(rt), *(int*)&(st)); + currentplug->tick(realtime, st); } } currentplug = oldplug; @@ -1775,7 +1205,7 @@ void Plug_ResChanged(void) for (currentplug = plugs; currentplug; currentplug = currentplug->next) { if (currentplug->reschange) - VM_Call(currentplug->vm, currentplug->reschange, vid.width, vid.height); + currentplug->reschange(vid.width, vid.height); } currentplug = oldplug; } @@ -1790,7 +1220,7 @@ qboolean Plugin_ExecuteString(void) { if (currentplug->executestring) { - if (VM_Call(currentplug->vm, currentplug->executestring, 0)) + if (currentplug->executestring(0)) { currentplug = oldplug; return true; @@ -1819,7 +1249,7 @@ qboolean Plug_ConsoleLinkMouseOver(float x, float y, char *text, char *info) COM_QuotedString(info, ptr, sizeof(buffer)-(ptr-buffer), false); Cmd_TokenizeString(buffer, false, false); - result = VM_Call(currentplug->vm, currentplug->consolelinkmouseover, *(int*)&(x), *(int*)&(y)); + result = currentplug->consolelinkmouseover(x, y); if (result) break; } @@ -1848,7 +1278,7 @@ qboolean Plug_ConsoleLink(char *text, char *info, const char *consolename) COM_QuotedString(consolename, ptr, sizeof(buffer)-(ptr-buffer), false); Cmd_TokenizeString(buffer, false, false); - result = VM_Call(currentplug->vm, currentplug->consolelink); + result = currentplug->consolelink(); if (result) break; } @@ -1866,27 +1296,12 @@ int Plug_SubConsoleCommand(console_t *con, const char *line) Q_strncpyz(buffer, va("\"%s\" %s", con->name, line), sizeof(buffer)); Cmd_TokenizeString(buffer, false, false); - ret = VM_Call(currentplug->vm, currentplug->conexecutecommand, 0); + ret = currentplug->conexecutecommand(0); currentplug = oldplug; return ret; } #endif -#ifndef SERVERONLY -qboolean Plug_Menu_Event(int eventtype, int param) //eventtype = draw/keydown/keyup, param = time/key -{ - plugin_t *oc=currentplug; - qboolean ret; - - if (!menuplug) - return false; - - currentplug = menuplug; - ret = VM_Call(menuplug->vm, menuplug->menufunction, eventtype, param, (int)mousecursor_x, (int)mousecursor_y); - currentplug=oc; - return ret; -} -#endif #ifndef SERVERONLY int Plug_ConnectionlessClientPacket(char *buffer, int size) { @@ -1894,7 +1309,7 @@ int Plug_ConnectionlessClientPacket(char *buffer, int size) { if (currentplug->connectionlessclientpacket) { - switch (VM_Call(currentplug->vm, currentplug->connectionlessclientpacket, buffer, size, &net_from)) + switch (currentplug->connectionlessclientpacket(buffer, size, &net_from)) { case 0: continue; //wasn't handled @@ -1958,7 +1373,7 @@ void Plug_SBar(playerview_t *pv) cleared = true; SCR_TileClear (0); } - ret |= VM_Call(currentplug->vm, currentplug->sbarlevel[0], pv-cl.playerview, (int)r_refdef.vrect.x, (int)r_refdef.vrect.y, (int)r_refdef.vrect.width, (int)r_refdef.vrect.height, sb_showscores+sb_showteamscores*2); + ret |= currentplug->sbarlevel[0](pv-cl.playerview, (int)r_refdef.vrect.x, (int)r_refdef.vrect.y, (int)r_refdef.vrect.width, (int)r_refdef.vrect.height, sb_showscores+sb_showteamscores*2); break; } } @@ -1975,7 +1390,7 @@ void Plug_SBar(playerview_t *pv) if (currentplug->sbarlevel[1]) { R2D_ImageColours(1, 1, 1, 1); // ensure menu colors are reset - ret |= VM_Call(currentplug->vm, currentplug->sbarlevel[1], pv-cl.playerview, r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, sb_showscores+sb_showteamscores*2); + ret |= currentplug->sbarlevel[1](pv-cl.playerview, r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, sb_showscores+sb_showteamscores*2); } } @@ -1984,7 +1399,7 @@ void Plug_SBar(playerview_t *pv) if (currentplug->sbarlevel[2]) { R2D_ImageColours(1, 1, 1, 1); // ensure menu colors are reset - ret |= VM_Call(currentplug->vm, currentplug->sbarlevel[2], pv-cl.playerview, r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, sb_showscores+sb_showteamscores*2); + ret |= currentplug->sbarlevel[2](pv-cl.playerview, r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, sb_showscores+sb_showteamscores*2); } } @@ -2009,7 +1424,7 @@ qboolean Plug_ServerMessage(char *buffer, int messagelevel) { if (currentplug->svmsgfunction) { - ret &= VM_Call(currentplug->vm, currentplug->svmsgfunction, messagelevel); + ret &= currentplug->svmsgfunction(messagelevel); } } @@ -2029,7 +1444,7 @@ qboolean Plug_ChatMessage(char *buffer, int talkernum, int tpflags) { if (currentplug->chatmsgfunction) { - ret &= VM_Call(currentplug->vm, currentplug->chatmsgfunction, talkernum, tpflags); + ret &= currentplug->chatmsgfunction(talkernum, tpflags); } } @@ -2049,7 +1464,7 @@ qboolean Plug_CenterPrintMessage(char *buffer, int clientnum) { if (currentplug->centerprintfunction) { - ret &= VM_Call(currentplug->vm, currentplug->centerprintfunction, clientnum); + ret &= currentplug->centerprintfunction(clientnum); } } @@ -2061,9 +1476,11 @@ qboolean Plug_CenterPrintMessage(char *buffer, int clientnum) void Plug_Close(plugin_t *plug) { int i; - if (plug->blockcloses) + currentplug = plug; + if (plug->mayshutdown && !plug->mayshutdown()) { - Con_Printf("Plugin %s provides driver features, and cannot safely be unloaded\n", plug->name); + currentplug = NULL; + Con_Printf("Plugin %s provides driver features, and cannot safely be unloaded at this time\n", plug->name); return; } if (plugs == plug) @@ -2092,6 +1509,9 @@ void Plug_Close(plugin_t *plug) #ifdef HAVE_MEDIA_ENCODER Media_UnregisterEncoder(plug, NULL); #endif +#endif +#ifdef HAVE_CLIENT + S_UnregisterSoundInputModule(plug); #endif FS_UnRegisterFileSystemModule(plug); Mod_UnRegisterAllModelFormats(plug); @@ -2102,11 +1522,12 @@ void Plug_Close(plugin_t *plug) { plugin_t *cp = currentplug; currentplug = plug; - VM_Call(plug->vm, plug->shutdown); + plug->shutdown(); currentplug = cp; } - VM_Destroy(plug->vm); + if (plug->lib) + Sys_CloseLibrary(plug->lib); //make sure anything else that was left is unlinked (stuff without destroy callbacks). for (i = 0; i < pluginstreamarraylen; i++) @@ -2122,8 +1543,7 @@ void Plug_Close(plugin_t *plug) Plug_Client_Close(plug); Z_Free(plug); - if (currentplug == plug) - currentplug = NULL; + currentplug = NULL; } void Plug_Close_f(void) @@ -2171,7 +1591,7 @@ void Plug_CloseAll_f(void) while(plugs) { p = plugs; - while (p->blockcloses) + while (p->mayshutdown && !p->mayshutdown()) { p = p->next; if (!p) @@ -2194,6 +1614,11 @@ int QDECL Plug_List_Print(const char *fname, qofs_t fsize, time_t modtime, void "arm", "arm64", "armhf", //various arm ABIs "ppc", "unk", //various misc ABIs }; +#ifdef _WIN32 + char *mssuck; + while ((mssuck=strchr(fname, '\\'))) + *mssuck = '/'; +#endif if (nl >= strlen(ARCH_DL_POSTFIX) && !Q_strcasecmp(fname+nl-strlen(ARCH_DL_POSTFIX), ARCH_DL_POSTFIX)) { nl -= strlen(ARCH_DL_POSTFIX); @@ -2218,11 +1643,10 @@ int QDECL Plug_List_Print(const char *fname, qofs_t fsize, time_t modtime, void //don't bother printing it if its already loaded. for (plug = plugs; plug; plug = plug->next) { - const char *existing = VM_GetFilename(plug->vm); - if (!Q_strncasecmp(existing, parm, strlen(parm)) && !Q_strcasecmp(existing+strlen(parm), fname)) + if (!Q_strncasecmp(plug->filename, parm, strlen(parm)) && !Q_strcasecmp(plug->filename+strlen(parm), fname)) return true; } - Con_Printf("^[%s%s\\type\\plug_load %s\\^]: not loaded\n", (const char*)parm, fname, plugname+((!Q_strncasecmp(plugname,PLUGINPREFIX, strlen(PLUGINPREFIX)))?strlen(PLUGINPREFIX):0)); + Con_Printf("^[^1%s%s\\type\\plug_load %s\\^]: not loaded\n", (const char*)parm, fname, plugname+((!Q_strncasecmp(plugname,PLUGINPREFIX, strlen(PLUGINPREFIX)))?strlen(PLUGINPREFIX):0)); } } return true; @@ -2233,23 +1657,26 @@ void Plug_List_f(void) char binarypath[MAX_OSPATH]; char rootpath[MAX_OSPATH]; unsigned int u; - char *mssuck; plugin_t *plug; for (plug = plugs; plug; plug = plug->next) - { - VM_PrintInfo(plug->vm); - } + Con_Printf("^[^2%s\\type\\plug_close %s\\^]: loaded\n", plug->filename, plug->name); if (FS_NativePath("", FS_BINARYPATH, binarypath, sizeof(binarypath))) { +#ifdef _WIN32 + char *mssuck; while ((mssuck=strchr(binarypath, '\\'))) *mssuck = '/'; +#endif Sys_EnumerateFiles(binarypath, PLUGINPREFIX"*" ARCH_DL_POSTFIX, Plug_List_Print, binarypath, NULL); } if (FS_NativePath("", FS_ROOT, rootpath, sizeof(rootpath))) { +#ifdef _WIN32 + char *mssuck; while ((mssuck=strchr(rootpath, '\\'))) *mssuck = '/'; +#endif if (strcmp(binarypath, rootpath)) Sys_EnumerateFiles(rootpath, PLUGINPREFIX"*" ARCH_DL_POSTFIX, Plug_List_Print, rootpath, NULL); } @@ -2266,7 +1693,7 @@ void Plug_Shutdown(qboolean preliminary) //close the non-block-closes plugins first, before most of the rest of the subsystems are down for (p = &plugs; *p; ) { - if ((*p)->blockcloses) + if ((*p)->mayshutdown && !(*p)->mayshutdown()) p = &(*p)->next; else Plug_Close(*p); @@ -2277,7 +1704,7 @@ void Plug_Shutdown(qboolean preliminary) //now that our various handles etc are closed, its safe to terminate the various driver plugins. while(plugs) { - plugs->blockcloses = 0; + plugs->mayshutdown = NULL; Plug_Close(plugs); } @@ -2285,10 +1712,6 @@ void Plug_Shutdown(qboolean preliminary) pluginstreamarray = NULL; pluginstreamarraylen = 0; - numplugbuiltins = 0; - BZ_Free(plugbuiltins); - plugbuiltins = NULL; - plugincvararraylen = 0; BZ_Free(plugincvararray); plugincvararray = NULL; @@ -2304,15 +1727,284 @@ void Plug_Shutdown(qboolean preliminary) } -//for built-in plugins -qboolean Plug_Export(const char *name, qintptr_t(QDECL *func)(qintptr_t *args)) + + + +static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t structsize) { - qintptr_t args[] = {(qintptr_t)name, (qintptr_t)func}; - return Plug_ExportToEngine(NULL, ~(size_t)0, args); -} -void *pPlug_GetEngineFunction(const char *funcname) -{ - return (void*)Plug_FindBuiltin(true, funcname); + if (!strcmp(interfacename, plugcorefuncs_name)) + { + static plugcorefuncs_t funcs = + { + PlugBI_GetEngineInterface, + PlugBI_ExportFunction, + PlugBI_ExportInterface, + PlugBI_GetPluginName, + Plug_Con_Print, + Plug_Sys_Error, + Plug_Sys_Milliseconds, + }; + if (structsize == sizeof(funcs)) + return &funcs; + } + if (!strcmp(interfacename, plugcmdfuncs_name)) + { + static plugcmdfuncs_t funcs = + { + Plug_Cmd_AddCommand, + NULL,//Plug_Cmd_TokenizeString, + Plug_Cmd_Args, + Plug_Cmd_Argv, + Plug_Cmd_Argc, + Plug_Cmd_AddText, + }; + if (structsize == sizeof(funcs)) + return &funcs; + } + if (!strcmp(interfacename, plugcvarfuncs_name)) + { + static plugcvarfuncs_t funcs = + { + Plug_Cvar_SetString, + Plug_Cvar_SetFloat, + Plug_Cvar_GetString, + Plug_Cvar_GetFloat, + Plug_Cvar_Register, + Plug_Cvar_Update, + Plug_Cvar_GetNVFDG, + }; + if (structsize == sizeof(funcs)) + return &funcs; + } + if (!strcmp(interfacename, plugfsfuncs_name)) + { + static plugfsfuncs_t funcs = + { + Plug_FS_Open, + Plug_Net_Close, + Plug_Net_Send, + Plug_Net_Recv, + Plug_FS_Seek, + Plug_FS_GetLength, + + FS_OpenVFS, + FS_NativePath, + COM_EnumerateFiles, + }; + if (structsize == sizeof(funcs)) + return &funcs; + } + if (!strcmp(interfacename, plugnetfuncs_name)) + { + static plugnetfuncs_t funcs = + { + Plug_Net_TCPConnect, + Plug_Net_TCPListen, + Plug_Net_Accept, + Plug_Net_Recv, + Plug_Net_Send, + Plug_Net_SendTo, + Plug_Net_Close, + Plug_Net_SetTLSClient, + Plug_Net_GetTLSBinding, + }; + if (structsize == sizeof(funcs)) + return &funcs; + } +#ifdef HAVE_CLIENT + if (!strcmp(interfacename, plug2dfuncs_name)) + { + static plug2dfuncs_t funcs = + { + Plug_Draw_LoadImageData, + Plug_Draw_LoadImageShader, + Plug_Draw_LoadImagePic, + Plug_Draw_UnloadImage, + Plug_Draw_Image, + Plug_Draw_ImageSize, + Plug_Draw_Fill, + Plug_Draw_Line, + Plug_Draw_Character, + Plug_Draw_String, + Plug_Draw_CharacterH, + Plug_Draw_StringH, + Plug_Draw_StringWidth, + Plug_Draw_ColourP, + Plug_Draw_Colour4f, + + Plug_LocalSound, + }; + if (structsize == sizeof(funcs)) + return &funcs; + } + if (!strcmp(interfacename, plugclientfuncs_name)) + { + static plugclientfuncs_t funcs = + { + Plug_CL_GetStats, + Plug_GetPlayerInfo, + Plug_GetTeamInfo, + Plug_GetWeaponStats, + Plug_GetNetworkInfo, + Plug_GetLocalPlayerNumbers, + Plug_GetLocationName, + Plug_GetTrackerOwnFrags, + Plug_GetLastInputFrame, + Plug_GetServerInfo, + Plug_SetUserInfo, + Plug_MapLog_Query, + }; + if (structsize == sizeof(funcs)) + return &funcs; + } + if (!strcmp(interfacename, pluginputfuncs_name)) + { + static pluginputfuncs_t funcs = + { + Plug_SetMenuFocus, + Plug_HasMenuFocus, + + //for menu input + Plug_Key_GetKeyCode, + Plug_Key_GetKeyName, + M_FindKeysForBind, + Plug_Key_GetKeyBind, + Plug_Key_SetKeyBind, + }; + if (structsize == sizeof(funcs)) + return &funcs; + } + if (!strcmp(interfacename, plugsubconsolefuncs_name)) + { + static plugsubconsolefuncs_t funcs = + { + Plug_Con_POpen, + Plug_Con_SubPrint, + Plug_Con_RenameSub, + Plug_Con_IsActive, + Plug_Con_SetActive, + Plug_Con_Destroy, + Plug_Con_NameForNum, + Plug_Con_GetConsoleFloat, + Plug_Con_SetConsoleFloat, + Plug_Con_GetConsoleString, + Plug_Con_SetConsoleString, + }; + if (structsize == sizeof(funcs)) + return &funcs; + } + if (!strcmp(interfacename, plugaudiofuncs_name)) + { + static plugaudiofuncs_t funcs = + { + Plug_LocalSound, + Plug_S_RawAudio, + }; + if (structsize == sizeof(funcs)) + return &funcs; + } +#endif + +#ifdef SUPPORT_ICE + if (!strcmp(interfacename, ICE_API_CURRENT) && structsize == sizeof(iceapi)) + return &iceapi; +#endif +#ifdef USERBE + if (!strcmp(interfacename, "RBE")) + { + static rbeplugfuncs_t funcs = + { + RBEPLUGFUNCS_VERSION, + + World_RegisterPhysicsEngine, + World_UnregisterPhysicsEngine, + World_GenerateCollisionMesh, + World_ReleaseCollisionMesh, + World_LinkEdict, + + VectorAngles, + AngleVectors + }; + if (structsize == sizeof(funcs)) + return &funcs; + } +#endif +#ifdef MULTITHREAD + if (!strcmp(interfacename, "Threading")) + { + static threading_t funcs = + { + Sys_CreateMutex, + Sys_LockMutex, + Sys_UnlockMutex, + Sys_DestroyMutex + }; + + if (structsize == sizeof(funcs)) + return &funcs; + } +#endif +#ifdef SKELETALMODELS + if (!strcmp(interfacename, "Models")) + { + static plugmodfuncs_t funcs = + { + MODPLUGFUNCS_VERSION, + + Plug_RegisterModelFormatText, + Plug_RegisterModelFormatMagic, + Plug_UnRegisterModelFormat, + Plug_UnRegisterAllModelFormats, + + ZG_Malloc, + COM_StripExtension, + + R_ConcatTransforms, + Matrix3x4_Invert_Simple, + VectorAngles, + AngleVectors, + GenMatrixPosQuat4Scale, + + Alias_ForceConvertBoneData, + +#ifdef HAVE_CLIENT + Image_GetTexture, +#else + NULL, +#endif + Mod_AccumulateTextureVectors, + Mod_NormaliseTextureVectors, + Mod_ForName + }; + if (structsize == sizeof(funcs)) + return &funcs; + } +#endif + +#ifdef TERRAIN + if (!strcmp(interfacename, "Terrain")) + return Terr_GetTerrainFuncs(structsize); +#endif + +#ifdef HAVE_SERVER + if (!strcmp(interfacename, "SSQCVM")) + return sv.world.progs; +#endif +#if defined(CSQC_DAT) && defined(HAVE_CLIENT) + if (!strcmp(interfacename, "CSQCVM")) + { + extern world_t csqc_world; + return csqc_world.progs; + } +#endif +#if defined(MENU_DAT) && defined(HAVE_CLIENT) + if (!strcmp(interfacename, "MenuQCVM")) + { + extern world_t menu_world; + return menu_world.progs; + } +#endif + return NULL; } #endif diff --git a/engine/common/protocol.h b/engine/common/protocol.h index ded2b08aa..ac501c5a2 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -1778,7 +1778,7 @@ typedef struct q1usercmd_s // unused #define E5_UNUSED30 (1<<30) // bits2 > 0 -#define E5_EXTEND4 (1<<31) +#define E5_EXTEND4 (1u<<31) #define E5_ALLUNUSED (E5_UNUSED27|E5_UNUSED28|E5_UNUSED29|E5_UNUSED30) #define E5_SERVERPRIVATE (E5_EXTEND1|E5_EXTEND2|E5_EXTEND3|E5_EXTEND4) diff --git a/engine/common/ui_public.h b/engine/common/ui_public.h index 4c7878438..3305ff19d 100644 --- a/engine/common/ui_public.h +++ b/engine/common/ui_public.h @@ -127,15 +127,6 @@ typedef enum { // overlayed over whatever the cgame has drawn. // a GetClientState syscall will be made to get the current strings - -/* - UI_DRAWSTATUSBAR = 500, - UI_MOUSE_POS, - UI_INTERMISSION, - UI_FINALE, - UI_STRINGCHANGED, //parma is the string id - UI_NEWSERVER //indicates that all the strings have changed. -*/ } uiExport_t; typedef enum { diff --git a/engine/common/vm.h b/engine/common/vm.h index 989a09aec..502fbc60d 100644 --- a/engine/common/vm.h +++ b/engine/common/vm.h @@ -31,33 +31,6 @@ void *VM_MemoryBase(vm_t *vm); quintptr_t VM_MemoryMask(vm_t *vm); - -//plugin functions -#ifdef PLUGINS -qboolean Plug_CenterPrintMessage(char *buffer, int clientnum); -qboolean Plug_ChatMessage(char *buffer, int talkernum, int tpflags); -void Plug_Command_f(void); -int Plug_ConnectionlessClientPacket(char *buffer, int size); -qboolean Plug_ConsoleLink(char *text, char *info, const char *consolename); -qboolean Plug_ConsoleLinkMouseOver(float x, float y, char *text, char *info); -void Plug_DrawReloadImages(void); -void Plug_Initialise(qboolean fromgamedir); -void Plug_Shutdown(qboolean preliminary); -qboolean Plug_Menu_Event(int eventtype, int param); -void Plug_ResChanged(void); -void Plug_SBar(playerview_t *pv); -qboolean Plug_ServerMessage(char *buffer, int messagelevel); -void Plug_Tick(void); -qboolean Plugin_ExecuteString(void); - -#ifdef ANDROID -#define PLUGINPREFIX "libplug_" //android is kinda annoying and only extracts specific files. -#else -#define PLUGINPREFIX "fteplug_" //this string defines what consitutes a plugin, as opposed to some other dll -#endif -#endif - - #define VM_TOSTRCACHE(a) VMQ3_StringToHandle(VM_POINTER(a)) #define VM_FROMSTRCACHE(a) VMQ3_StringFromHandle(a) char *VMQ3_StringFromHandle(int handle); @@ -72,16 +45,8 @@ void UI_Start (void); void UI_Stop (void); qboolean UI_OpenMenu(void); void UI_Restart_f(void); -qboolean UI_Q2LayoutChanged(void); -void UI_StringChanged(int num); -qboolean UI_MousePosition(float xpos, float ypos); -int UI_MenuState(void); -qboolean UI_KeyPress(int key, int unicode, qboolean down); +int UI_IsFullscreen(void); void UI_Reset(void); -void UI_DrawMenu(void); -qboolean UI_DrawStatusBar(int scores); -qboolean UI_DrawIntermission(void); -int UI_MenuState(void); //sans botlib struct pc_token_s; diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index e3e84a664..1cd9f011d 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -1288,6 +1288,12 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass) else t = r_whiteimage; break; + case T_GEN_OCCLUSION: + if (shaderstate.curtexnums && TEXLOADED(shaderstate.curtexnums->occlusion)) + t = shaderstate.curtexnums->occlusion; + else + t = r_whiteimage; + break; case T_GEN_SHADOWMAP: t = shaderstate.curshadowmap; break; diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index d267ce5d8..be6a1458f 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -12,7 +12,7 @@ See gl_terrain.h for terminology, networking notes, etc. #include "gl_terrain.h" -static terrainfuncs_t terrainfuncs; +static plugterrainfuncs_t terrainfuncs; struct patchvert_s { vec3_t v; @@ -6534,7 +6534,9 @@ void CL_Parse_BrushEdit(void) else mod->entityinfo[idx].keyvals = NULL; +#ifdef CSQC_DAT CSQC_MapEntityEdited(modelindex, idx, data); +#endif } } } @@ -8442,8 +8444,10 @@ void Mod_Terrain_Reload_f(void) Terr_PurgeTerrainModel(mod, false, true); } -terrainfuncs_t *QDECL Terr_GetTerrainFuncs(void) +plugterrainfuncs_t *Terr_GetTerrainFuncs(size_t structsize) { + if (structsize != sizeof(plugterrainfuncs_t)) + return NULL; #ifdef SERVERONLY return NULL; //dedicated server builds have all the visual stuff stripped, which makes APIs too inconsistent. Generate then save. Or fix up the API... #else diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 6201e8c8f..6493705d4 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -1079,8 +1079,8 @@ float RadiusFromBounds (const vec3_t mins, const vec3_t maxs); // #ifdef TERRAIN void Terr_Init(void); -struct terrainfuncs_s; -struct terrainfuncs_s *QDECL Terr_GetTerrainFuncs(void); +struct plugterrainfuncs_s; +struct plugterrainfuncs_s *Terr_GetTerrainFuncs(size_t structsize); void Terr_DrawTerrainModel (batch_t **batch, entity_t *e); void Terr_FreeModel(model_t *mod); void Terr_FinishTerrain(model_t *model); diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index f6fa2d14b..89a23d870 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -59,7 +59,6 @@ needs almost the entire 256k of stack space! void SCR_DrawCursor(void); qboolean GLSCR_UpdateScreen (void) { - int uimenu; qboolean nohud; qboolean noworld; extern cvar_t vid_srgb; @@ -127,11 +126,6 @@ qboolean GLSCR_UpdateScreen (void) Shader_DoReload(); qglDisable(GL_SCISSOR_TEST); -#ifdef VM_UI - uimenu = UI_MenuState(); -#else - uimenu = 0; -#endif #ifdef TEXTEDITOR if (editormodal) @@ -149,14 +143,6 @@ qboolean GLSCR_UpdateScreen (void) } else #endif - if (Media_ShowFilm()) - { - M_Draw(0); - V_UpdatePalette (false); - R2D_BrightenScreen(); - Media_RecordFrame(); - } - else { // // do 3D refresh drawing, and then update the screen @@ -174,25 +160,23 @@ qboolean GLSCR_UpdateScreen (void) depthcleared = true; } -#ifdef VM_CG - if (CG_Refresh()) + if (topmenu && topmenu->isopaque) + nohud = true; +#ifdef VM_CG + else if (CG_Refresh()) nohud = true; - else #endif #ifdef CSQC_DAT - if (CSQC_DrawView()) + else if (CSQC_DrawView()) nohud = true; - else #endif + else { - if (uimenu != 1) + if (r_worldentity.model && cls.state == ca_active) + V_RenderView (nohud); + else { - if (r_worldentity.model && cls.state == ca_active) - V_RenderView (nohud); - else - { - noworld = true; - } + noworld = true; } } @@ -212,7 +196,7 @@ qboolean GLSCR_UpdateScreen (void) nohud = true; } - SCR_DrawTwoDimensional(uimenu, nohud); + SCR_DrawTwoDimensional(nohud); V_UpdatePalette (false); R2D_BrightenScreen(); diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 861d1d8cf..8718fe2e2 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -1198,15 +1198,16 @@ const struct sh_defaultsamplers_s sh_defaultsamplers[] = {"s_reflectcube", 1u<<9}, {"s_reflectmask", 1u<<10}, {"s_displacement", 1u<<11}, - {"s_lightmap", 1u<<12}, - {"s_deluxemap", 1u<<13}, + {"s_occlusion", 1u<<12}, + {"s_lightmap", 1u<<13}, + {"s_deluxemap", 1u<<14}, #if MAXRLIGHTMAPS > 1 - {"s_lightmap1", 1u<<14}, - {"s_lightmap2", 1u<<15}, - {"s_lightmap3", 1u<<16}, - {"s_deluxemap1", 1u<<17}, - {"s_deluxemap2", 1u<<18}, - {"s_deluxemap3", 1u<<19}, + {"s_lightmap1", 1u<<15}, + {"s_lightmap2", 1u<<16}, + {"s_lightmap3", 1u<<17}, + {"s_deluxemap1", 1u<<18}, + {"s_deluxemap2", 1u<<19}, + {"s_deluxemap3", 1u<<20}, #else {"s_lightmap1", 0}, {"s_lightmap2", 0}, @@ -4341,16 +4342,17 @@ void Shader_FixupProgPasses(parsestate_t *ps, shaderpass_t *pass) {T_GEN_REFLECTCUBE, 0}, //9 {T_GEN_REFLECTMASK, 0}, //10 {T_GEN_DISPLACEMENT, SHADER_HASDISPLACEMENT},//11 + {T_GEN_OCCLUSION, 0}, //12 // {T_GEN_REFLECTION, SHADER_HASREFLECT}, // // {T_GEN_REFRACTION, SHADER_HASREFRACT}, // // {T_GEN_REFRACTIONDEPTH, SHADER_HASREFRACTDEPTH},// // {T_GEN_RIPPLEMAP, SHADER_HASRIPPLEMAP}, // //batch - {T_GEN_LIGHTMAP, SHADER_HASLIGHTMAP}, //12 - {T_GEN_DELUXMAP, 0}, //13 - //more lightmaps //14,15,16 - //mode deluxemaps //17,18,19 + {T_GEN_LIGHTMAP, SHADER_HASLIGHTMAP}, //13 + {T_GEN_DELUXMAP, 0}, //14 + //more lightmaps //15,16,17 + //mode deluxemaps //18,19,20 }; #ifdef HAVE_MEDIA_DECODER @@ -5464,16 +5466,17 @@ done:; {T_GEN_REFLECTCUBE, 0}, //9 {T_GEN_REFLECTMASK, 0}, //10 {T_GEN_DISPLACEMENT, SHADER_HASDISPLACEMENT},//11 + {T_GEN_OCCLUSION, 0}, //12 // {T_GEN_REFLECTION, SHADER_HASREFLECT}, // // {T_GEN_REFRACTION, SHADER_HASREFRACT}, // // {T_GEN_REFRACTIONDEPTH, SHADER_HASREFRACTDEPTH},// // {T_GEN_RIPPLEMAP, SHADER_HASRIPPLEMAP}, // //batch - {T_GEN_LIGHTMAP, SHADER_HASLIGHTMAP}, //12 - {T_GEN_DELUXMAP, 0}, //13 - //more lightmaps //14,15,16 - //mode deluxemaps //17,18,19 + {T_GEN_LIGHTMAP, SHADER_HASLIGHTMAP}, //13 + {T_GEN_DELUXMAP, 0}, //14 + //more lightmaps //15,16,17 + //mode deluxemaps //18,19,20 }; #ifdef HAVE_MEDIA_DECODER @@ -7465,6 +7468,7 @@ static char *Shader_DecomposeSubPass(char *o, shader_t *s, shaderpass_t *p, qboo case T_GEN_REFLECTCUBE: Shader_DecomposeSubPassMap(o, s, "map $reflectcube", s->defaulttextures[0].reflectcube); break; case T_GEN_REFLECTMASK: Shader_DecomposeSubPassMap(o, s, "map $reflectmask", s->defaulttextures[0].reflectmask); break; case T_GEN_DISPLACEMENT: Shader_DecomposeSubPassMap(o, s, "map $displacement", s->defaulttextures[0].displacement); break; + case T_GEN_OCCLUSION: Shader_DecomposeSubPassMap(o, s, "map $occlusion", s->defaulttextures[0].occlusion); break; case T_GEN_CURRENTRENDER: sprintf(o, "map $currentrender "); break; case T_GEN_SOURCECOLOUR: sprintf(o, "map $sourcecolour"); break; case T_GEN_SOURCEDEPTH: sprintf(o, "map $sourcedepth"); break; diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 639a6cff0..1254c5cbc 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -65,8 +65,6 @@ cvar_t r_shadow_realtime_dlight_specular = CVAR ("r_shadow_realtime_dlight_specu cvar_t r_shadow_playershadows = CVARD ("r_shadow_playershadows", "1", "Controls the presence of shadows on the local player."); cvar_t r_shadow_shadowmapping = CVARFD ("r_shadow_shadowmapping", "1", CVAR_ARCHIVE, "Enables soft shadows instead of stencil shadows."); cvar_t r_shadow_shadowmapping_precision = CVARD ("r_shadow_shadowmapping_precision", "1", "Scales the shadowmap detail level up or down."); -extern cvar_t r_shadow_shadowmapping_nearclip; -extern cvar_t r_shadow_shadowmapping_bias; cvar_t r_sun_dir = CVARD ("r_sun_dir", "0.2 0.5 0.8", "Specifies the direction that crepusular rays appear along"); cvar_t r_sun_colour = CVARFD ("r_sun_colour", "0 0 0", CVAR_ARCHIVE, "Specifies the colour of sunlight that appears in the form of crepuscular rays."); diff --git a/engine/gl/gl_terrain.h b/engine/gl/gl_terrain.h index 251a7a4b1..fce0f941a 100644 --- a/engine/gl/gl_terrain.h +++ b/engine/gl/gl_terrain.h @@ -396,7 +396,7 @@ typedef struct heightmap_s qboolean brushesedited; } heightmap_t; -typedef struct terrainfuncs_s +typedef struct plugterrainfuncs_s { void *(QDECL *GenerateWater) (hmsection_t *s, float maxheight); qboolean (QDECL *InitLightmap) (hmsection_t *s, qboolean initialise); @@ -407,5 +407,6 @@ typedef struct terrainfuncs_s void (QDECL *FinishedSection) (hmsection_t *s, qboolean success); qboolean (QDECL *AutogenerateSection)(heightmap_t *hm, int sx, int sy, unsigned int tgsflags); //replace this if you want to make a terrain generator. -} terrainfuncs_t; +#define plugterrainfuncs_name "Terrain" +} plugterrainfuncs_t; #endif diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 42692cbf4..a69123675 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -2314,6 +2314,7 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int "uniform samplerCube s_reflectcube;\n", "uniform sampler2D s_reflectmask;\n", "uniform sampler2D s_displacement;\n", + "uniform sampler2D s_occlusion;\n", "uniform sampler2D s_lightmap;\n#define s_lightmap0 s_lightmap\n", "uniform sampler2D s_deluxemap;\n#define s_deluxemap0 s_deluxemap\n", diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 548f4fc45..1b8fc4767 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -272,6 +272,7 @@ typedef struct shaderpass_s { T_GEN_REFLECTCUBE, //dpreflectcube T_GEN_REFLECTMASK, //dpreflectcube mask T_GEN_DISPLACEMENT, //displacement texture (probably half-float or something so higher precision than normalmap.a) + T_GEN_OCCLUSION, //occlusion mask (instead of baking it into the texture itself, required for correct pbr) T_GEN_CURRENTRENDER,//copy the current screen to a texture, and draw that diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 34829b16f..62446dbfd 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -817,9 +817,8 @@ void SV_Map_f (void) } #endif -#if defined(MENU_DAT) && !defined(SERVERONLY) - if (Key_Dest_Has(kdm_gmenu)) - MP_Toggle(0); +#ifdef HAVE_CLIENT + Menu_PopAll(); #endif if (preserveplayers && svprogfuncs) diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index c885c0586..183a04586 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -3060,6 +3060,9 @@ void SVC_DirectConnect(int expectedreliablesequence) info.expectedreliablesequence = expectedreliablesequence; #endif +#ifdef HUFFNETWORK + info.huffcrc = 0; +#endif info.mtu = 0; info.ftepext1 = 0; info.ftepext2 = 0; @@ -3109,7 +3112,7 @@ void SVC_DirectConnect(int expectedreliablesequence) Info_SetValueForKey(userinfo, "name", "UnnamedQ3", sizeof(userinfo)); #ifdef HUFFNETWORK - huffcrc = HUFFCRC_QUAKE3; + info.huffcrc = HUFFCRC_QUAKE3; #endif #endif } diff --git a/engine/vk/vk_init.c b/engine/vk/vk_init.c index 362d41b56..532dbeef8 100644 --- a/engine/vk/vk_init.c +++ b/engine/vk/vk_init.c @@ -3040,7 +3040,6 @@ char *VKVID_GetRGBInfo (int *bytestride, int *truevidwidth, int *truevidheight static void VK_PaintScreen(void) { - int uimenu; qboolean nohud; qboolean noworld; @@ -3088,12 +3087,6 @@ static void VK_PaintScreen(void) } */ -#ifdef VM_UI - uimenu = UI_MenuState(); -#else - uimenu = 0; -#endif - #ifdef TEXTEDITOR if (editormodal) { @@ -3112,16 +3105,6 @@ static void VK_PaintScreen(void) return; } #endif - if (Media_ShowFilm()) - { - M_Draw(0); - V_UpdatePalette (false); - R2D_BrightenScreen(); -#if defined(_WIN32) && defined(GLQUAKE) - Media_RecordFrame(); -#endif - return; - } // // do 3D refresh drawing, and then update the screen @@ -3131,25 +3114,23 @@ static void VK_PaintScreen(void) noworld = false; nohud = false; -#ifdef VM_CG - if (CG_Refresh()) + if (topmenu && topmenu->isopaque) + nohud = true; +#ifdef VM_CG + else if (CG_Refresh()) nohud = true; - else #endif #ifdef CSQC_DAT - if (CSQC_DrawView()) + else if (CSQC_DrawView()) nohud = true; - else #endif + else { - if (uimenu != 1) + if (r_worldentity.model && cls.state == ca_active) + V_RenderView (nohud); + else { - if (r_worldentity.model && cls.state == ca_active) - V_RenderView (nohud); - else - { - noworld = true; - } + noworld = true; } } @@ -3175,7 +3156,7 @@ static void VK_PaintScreen(void) nohud = true; } - SCR_DrawTwoDimensional(uimenu, nohud); + SCR_DrawTwoDimensional(nohud); V_UpdatePalette (false); R2D_BrightenScreen(); diff --git a/plugins/Makefile b/plugins/Makefile index 5b5babb4d..7b137d827 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -91,39 +91,16 @@ PLUG_LDFLAGS:=-L../engine/libs-$(ARCH) $(PLUG_LDFLAGS) PLUG_CFLAGS:=-I../engine/libs-$(ARCH) $(PLUG_CFLAGS) PLUG_CXXFLAGS:=-I../engine/libs-$(ARCH) $(PLUG_CXXFLAGS) -all: ezscript qi hud irc +#legacy build rule, now equivelent to all +native: all clean: ezscript-clean qi-clean hud-clean irc-clean -.PHONY: all ezscript hud irc native distclean clean +.PHONY: all native distclean clean help: @-echo make a subdirectory -ezscript: - $(MAKE) -C ezscript - -ezscript-clean: - $(MAKE) clean -C ezscript - -hud: - $(MAKE) -C hud - -hud-clean: - $(MAKE) clean -C hud - -qi: - $(MAKE) -C qi - -qi-clean: - $(MAKE) clean -C qi - -irc: - $(MAKE) -C irc - -irc-clean: - $(MAKE) clean -C irc - #small script to download+install avformat for windows cross compiles. #linux users are expected to have the library installed locally already. If your version is too old or missing, run the following command to install it (to /usr/local), then delete the gz and directory. #wget http://ffmpeg.org/releases/ffmpeg-1.2.tar.gz && cd tar xvfz ffmpeg-1.2.tar.gz && cd ffmpeg-1.2/ && ./configure --disable-yasm --enable-shared && make && sudo make install @@ -161,7 +138,7 @@ else endif -AVPLUG_OBJS= avplug/avaudio.c avplug/avencode.c avplug/avdecode.c plugin.c qvm_api.c +AVPLUG_OBJS= avplug/avaudio.c avplug/avencode.c avplug/avdecode.c plugin.c ifeq ($(FTE_TARGET),win32) FFMPEG_ZIP=$(OUT_DIR)/$(AV_VER)-x86.zip #NATIVE_PLUGINS+=ffmpeg @@ -229,7 +206,7 @@ $(ODE_LIB): $(OUT_DIR)/../ode-$(ODE_VER).tar.gz mkdir -p $(ODE_BASE) && cd $(ODE_BASE) && tar xvfz $< cd $(ODE_BASE)ode-$(ODE_VER)/ && ./bootstrap && ./configure --enable-double-precision --disable-demos --without-x --with-pic CC="$(CC) $(PLUG_CXXFLAGS)" CXX="$(CC) $(PLUG_CXXFLAGS)" --host=`$(CC) -dumpmachine` && make -ODE_FILES=../engine/common/com_phys_ode.c ../engine/common/mathlib.c plugin.c qvm_api.c $(ODE_LIB) +ODE_FILES=../engine/common/com_phys_ode.c ../engine/common/mathlib.c plugin.c $(ODE_LIB) $(PLUG_PREFIX)ode$(PLUG_NATIVE_EXT): $(ODE_FILES) $(CC) -flto -s $(BASE_CFLAGS) $(CFLAGS) -Os -DFTEPLUGIN -DODE_STATIC -o $@ -shared $(PLUG_CFLAGS) -I$(ODE_BASE)ode-$(ODE_VER)/include $(ODE_FILES) $(PLUG_DEFFILE) $(PLUG_LDFLAGS) -static-libgcc `$(CC) -print-file-name=libstdc++.a` -lpthread #NATIVE_PLUGINS+=ode @@ -255,22 +232,22 @@ $(BULLET_LIB): $(OUT_DIR)/../bullet3-$(BULLET_VER).tar.gz #./configure --enable-double-precision --disable-demos --without-x CXX="$(CC)" CFLAGS="$(PLUG_CFLAGS)" CXXFLAGS="$(PLUG_CXXFLAGS)" --host=`$(CC) -dumpmachine` && make -$(PLUG_PREFIX)bullet$(PLUG_NATIVE_EXT): bullet/bulletplug.cpp plugin.c qvm_api.c $(BULLET_LIBS) +$(PLUG_PREFIX)bullet$(PLUG_NATIVE_EXT): bullet/bulletplug.cpp plugin.c $(BULLET_LIBS) $(CXX) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) $(BULLET_CFLAGS) #NATIVE_PLUGINS+=bullet -include Makefile.private -$(PLUG_PREFIX)mpq$(PLUG_NATIVE_EXT): mpq/fs_mpq.c mpq/blast.c plugin.c qvm_api.c +$(PLUG_PREFIX)mpq$(PLUG_NATIVE_EXT): mpq/fs_mpq.c mpq/blast.c plugin.c $(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Impq $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS_ZLIB) $(PLUG_LDFLAGS) NATIVE_PLUGINS+=mpq -$(PLUG_PREFIX)xmpp$(PLUG_NATIVE_EXT): jabber/jabberclient.c jabber/jingle.c jabber/sift.c jabber/xml.c plugin.c qvm_api.c ../engine/common/sha1.c emailnot/md5.c +$(PLUG_PREFIX)xmpp$(PLUG_NATIVE_EXT): jabber/jabberclient.c jabber/jingle.c jabber/sift.c jabber/xml.c plugin.c ../engine/common/sha1.c emailnot/md5.c $(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Ijabber $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) $(LIBRESOLV) NATIVE_PLUGINS+=xmpp -$(PLUG_PREFIX)qi$(PLUG_NATIVE_EXT): qi/qi.c jabber/xml.c plugin.c qvm_api.c +$(PLUG_PREFIX)qi$(PLUG_NATIVE_EXT): qi/qi.c jabber/xml.c plugin.c $(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Ijabber $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) NATIVE_PLUGINS+=qi @@ -308,7 +285,7 @@ cef/$(CEF_NAME)/rel.zip: cef/$(CEF_NAME)/include/cef_version.h $(OUT_DIR)/cef_$(CEF_VER).zip: cef/$(CEF_NAME)/rel.zip cp cef/$(CEF_NAME)/rel.zip $@ -CEF_SOURCES=cef/cef.c plugin.c qvm_api.c +CEF_SOURCES=cef/cef.c plugin.c $(PLUG_PREFIX)cef$(PLUG_NATIVE_EXT): $(CEF_SOURCES) $(OUT_DIR)/cef_$(CEF_VER).zip cef/$(CEF_NAME)/include/cef_version.h $(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $(PLUG_PREFIX)cef$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Icef/$(CEF_NAME) $(CEF_SOURCES) $(PLUG_DEFFILE) $(PLUG_LDFLAGS) -Wl,-rpath,. $(PLUG_LDFLAGS_DL) #NATIVE_PLUGINS+=cef @@ -318,18 +295,17 @@ $(PLUG_PREFIX)cef$(PLUG_NATIVE_EXT): echo cef plugin not supported on this arch endif -#irc plugin can still be built as a qvm. -$(PLUG_PREFIX)irc$(PLUG_NATIVE_EXT): irc/ircclient.c plugin.c qvm_api.c +$(PLUG_PREFIX)irc$(PLUG_NATIVE_EXT): irc/ircclient.c plugin.c $(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Iirc $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) NATIVE_PLUGINS+=irc #for compat with ezquake -$(PLUG_PREFIX)ezhud$(PLUG_NATIVE_EXT): ezhud/ezquakeisms.c ezhud/hud.c ezhud/hud_common.c ezhud/hud_editor.c plugin.c qvm_api.c +$(PLUG_PREFIX)ezhud$(PLUG_NATIVE_EXT): ezhud/ezquakeisms.c ezhud/hud.c ezhud/hud_common.c ezhud/hud_editor.c plugin.c $(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Iezhud $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) NATIVE_PLUGINS+=ezhud -$(PLUG_PREFIX)models$(PLUG_NATIVE_EXT): models/gltf.c models/models.c plugin.c qvm_api.c +$(PLUG_PREFIX)models$(PLUG_NATIVE_EXT): models/gltf.c models/models.c plugin.c $(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Imodels $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) #NATIVE_PLUGINS+=models -native: $(foreach FOO,$(NATIVE_PLUGINS), $(PLUG_PREFIX)$(FOO)$(PLUG_NATIVE_EXT)) +all: $(foreach FOO,$(NATIVE_PLUGINS), $(PLUG_PREFIX)$(FOO)$(PLUG_NATIVE_EXT)) diff --git a/plugins/avplug/avaudio.c b/plugins/avplug/avaudio.c index 0cbff74b8..b2b676a98 100644 --- a/plugins/avplug/avaudio.c +++ b/plugins/avplug/avaudio.c @@ -4,6 +4,7 @@ #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" +static size_t activedecoders; static cvar_t *ffmpeg_audiodecoder, *pdeveloper; #define HAVE_DECOUPLED_API (LIBAVCODEC_VERSION_MAJOR>57 || (LIBAVCODEC_VERSION_MAJOR==57&&LIBAVCODEC_VERSION_MINOR>=36)) @@ -56,6 +57,8 @@ static void S_AV_Purge(sfx_t *s) //file storage will be cleared here too free(ctx); + if (s->decoder.ended) + activedecoders--; memset(&s->decoder, 0, sizeof(s->decoder)); } static void S_AV_ReadFrame(struct avaudioctx *ctx) @@ -329,15 +332,18 @@ static qboolean QDECL S_LoadAVSound (sfx_t *s, qbyte *data, size_t datalen, int if (!ffmpeg_audiodecoder) return false; - if (!ffmpeg_audiodecoder->value /* && *ffmpeg_audiodecoder.string */) + if (!ffmpeg_audiodecoder->ival /* && *ffmpeg_audiodecoder.string */) return false; if (!data || !datalen) return false; + //ignore it if it looks like a wav file. that means we don't need to figure out how to calculate loopstart. + //FIXME: this also blocks playing the audio from avi files too! if (datalen >= 4 && !strncmp(data, "RIFF", 4)) - return false; //ignore it if it looks like a wav file. that means we don't need to figure out how to calculate loopstart. + return false; + // if (strcasecmp(COM_GetFileExtension(s->name), "wav")) //don't do .wav - I've no idea how to read the loopstart tag with ffmpeg. // return false; @@ -402,20 +408,28 @@ static qboolean QDECL S_LoadAVSound (sfx_t *s, qbyte *data, size_t datalen, int s->decoder.purge = S_AV_Purge; s->decoder.decodedata = S_AV_Locate; s->decoder.querydata = S_AV_Query; + activedecoders++; return true; } } S_AV_Purge(s); return false; } +qboolean AVAudio_MayUnload(void) +{ + return activedecoders==0; +} static qboolean AVAudio_Init(void) { - if (!pPlug_ExportNative("S_LoadSound", S_LoadAVSound)) + if (!plugfuncs->ExportFunction("MayUnload", AVAudio_MayUnload) || + !plugfuncs->ExportFunction("S_LoadSound", S_LoadAVSound)) { - Con_Printf("avplug: Engine doesn't support audio decoder plugins\n"); + Con_Printf("ffmpeg: Engine doesn't support audio decoder plugins\n"); return false; } - ffmpeg_audiodecoder = pCvar_GetNVFDG("ffmpeg_audiodecoder_wip", "0", 0, "Enables the use of ffmpeg's decoder for pure audio files.", "ffmpeg"); + ffmpeg_audiodecoder = cvarfuncs->GetNVFDG("ffmpeg_audiodecoder_wip", "1", 0, "Enables the use of ffmpeg's decoder for pure audio files.", "ffmpeg"); + if (!ffmpeg_audiodecoder->ival) + Con_Printf("ffmpeg: audio decoding disabled, use \"set %s 1\" to enable ffmpeg audio decoding\n", ffmpeg_audiodecoder->name); return true; } @@ -427,14 +441,14 @@ static void AVLogCallback(void *avcl, int level, const char *fmt, va_list vl) char string[1024]; Q_vsnprintf (string, sizeof(string), fmt, vl); if (pdeveloper && pdeveloper->ival) - pCon_Print(string); + Con_Printf("%s", string); #endif } //get the encoder/decoders to register themselves with the engine, then make sure avformat/avcodec have registered all they have to give. qboolean AVEnc_Init(void); qboolean AVDec_Init(void); -qintptr_t Plug_Init(qintptr_t *args) +qboolean Plug_Init(void) { qboolean okay = false; @@ -448,7 +462,7 @@ qintptr_t Plug_Init(qintptr_t *args) avcodec_register_all(); #endif - pdeveloper = pCvar_GetNVFDG("developer", "0", 0, "Developer spam.", "ffmpeg"); + pdeveloper = cvarfuncs->GetNVFDG("developer", "0", 0, "Developer spam.", "ffmpeg"); av_log_set_level(AV_LOG_WARNING); av_log_set_callback(AVLogCallback); } diff --git a/plugins/avplug/avdecode.c b/plugins/avplug/avdecode.c index 1a67e5823..25a7804b5 100644 --- a/plugins/avplug/avdecode.c +++ b/plugins/avplug/avdecode.c @@ -1,6 +1,9 @@ #include "../plugin.h" #include "../engine.h" +static plugfsfuncs_t *filefuncs; +static plugaudiofuncs_t *audiofuncs; + //#include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" @@ -24,12 +27,6 @@ #define DECODERNAME "ffmpeg" -#define PASSFLOAT(f) *(int*)&(f) - -#define ARGNAMES ,sourceid, data, speed, samples, channels, width, PASSFLOAT(volume) -BUILTIN(void, S_RawAudio, (int sourceid, void *data, int speed, int samples, int channels, int width, float volume)) -#undef ARGNAMES - /*should probably try threading this, though I suppose it should be the engine doing that.*/ /*timing is based upon the start time. this means overflow issues with rtsp etc*/ @@ -37,7 +34,7 @@ struct decctx { unsigned int width, height; - qhandle_t file; + vfsfile_t *file; int64_t fileofs; int64_t filelen; AVFormatContext *pFormatCtx; @@ -92,7 +89,7 @@ static int AVIO_Read(void *opaque, uint8_t *buf, int buf_size) { struct decctx *ctx = opaque; int ammount; - ammount = pFS_Read(ctx->file, buf, buf_size); + ammount = VFS_READ(ctx->file, buf, buf_size); if (ammount > 0) ctx->fileofs += ammount; return ammount; @@ -117,7 +114,7 @@ static int64_t AVIO_Seek(void *opaque, int64_t offset, int whence) case AVSEEK_SIZE: return ctx->filelen; } - pFS_Seek(ctx->file, ctx->fileofs & 0xffffffff, ctx->fileofs>>32); + VFS_SEEK(ctx->file, ctx->fileofs); return ctx->fileofs; } @@ -139,8 +136,8 @@ static void AVDec_Destroy(void *vctx) // Close the video file avformat_close_input(&ctx->pFormatCtx); - if (ctx->file >= 0) - pFS_Close(ctx->file); + if (ctx->file) + VFS_CLOSE(ctx->file); free(ctx); } @@ -154,17 +151,17 @@ static void *AVDec_Create(const char *medianame) qboolean useioctx = false; /*always respond to av: media prefixes*/ - if (!strncmp(medianame, "av:", 3)) + if (!strncmp(medianame, "av:", 3) || !strncmp(medianame, "ff:", 3)) { medianame = medianame + 3; useioctx = true; } - else if (!strncmp(medianame, "avs:", 4)) + else if (!strncmp(medianame, "avs:", 4) || !strncmp(medianame, "ffs:", 4)) { medianame = medianame + 4; //let avformat do its own avio context stuff } - else if (strchr(medianame, ':')) //block other types of url. + else if (strchr(medianame, ':')) //block other types of url/prefix. return NULL; else //if (!strcasecmp(extension, ".roq") || !strcasecmp(extension, ".roq")) return NULL; //roq+cin should be played back via the engine instead. @@ -173,7 +170,7 @@ static void *AVDec_Create(const char *medianame) memset(ctx, 0, sizeof(*ctx)); ctx->lasttime = -1; - ctx->file = -1; + ctx->file = NULL; if (useioctx) { // Create internal Buffer for FFmpeg: @@ -181,14 +178,15 @@ static void *AVDec_Create(const char *medianame) char *pBuffer = av_malloc(iBufSize); AVIOContext *ioctx; - ctx->filelen = pFS_Open(medianame, &ctx->file, 1); - if (ctx->filelen < 0) + ctx->file = filefuncs->OpenVFS(medianame, "rb", FS_GAME); + if (!ctx->file) { Con_Printf("Unable to open %s\n", medianame); free(ctx); av_free(pBuffer); return NULL; } + ctx->filelen = VFS_GETLEN(ctx->file); ioctx = avio_alloc_context(pBuffer, iBufSize, 0, ctx, AVIO_Read, 0, AVIO_Seek); ctx->pFormatCtx = avformat_alloc_context(); @@ -317,6 +315,8 @@ static qboolean VARGS AVDec_DisplayFrame(void *vctx, qboolean nosound, qboolean int64_t curtime; curtime = (mediatime * ctx->denum) / ctx->num; + + nosound |= !audiofuncs; while (1) { @@ -374,18 +374,33 @@ static qboolean VARGS AVDec_DisplayFrame(void *vctx, qboolean nosound, qboolean break; case AV_SAMPLE_FMT_FLTP: - //FIXME: support float audio internally. + if (channels == 2) { +#ifdef MIXER_F32 + float *l = (float*)ctx->pAFrame->data[0], *r = (float*)ctx->pAFrame->data[1], *t; + unsigned int i; + unsigned int frames = ctx->pAFrame->nb_samples; + width = sizeof(*t); + auddatasize = frames*width*channels; + t = malloc(auddatasize); + for (i = 0; i < frames; i++) + { + t[2*i+0] = l[i]; + t[2*i+1] = r[i]; + } + audiofuncs->RawAudio(-1, t, ctx->pACodecCtx->sample_rate, auddatasize/(channels*width), channels, width, 1); + free(t); + continue; +#else + //note that we can only reformat in place because we are NOT outputting floats. float *in[2] = {(float*)ctx->pAFrame->data[0],(float*)ctx->pAFrame->data[1]}; signed short *out = (void*)auddata; int v; unsigned int i, c; unsigned int frames = ctx->pAFrame->nb_samples; - if (channels > 2) - channels = 2; for (i = 0; i < frames; i++) { - for (c = 0; c < channels; c++) + for (c = 0; c < 2; c++) { v = (short)(in[c][i]*32767); if (v < -32767) @@ -397,10 +412,17 @@ static qboolean VARGS AVDec_DisplayFrame(void *vctx, qboolean nosound, qboolean } width = sizeof(*out); auddatasize = frames*width*channels; + break; +#endif } - break; + + auddatasize /= channels; + channels = 1; + //fallthrough, using just the first channel as mono case AV_SAMPLE_FMT_FLT: - //FIXME: support float audio internally. +#ifdef MIXER_F32 + width = 4; +#else { float *in = (void*)auddata; signed short *out = (void*)auddata; @@ -418,8 +440,8 @@ static qboolean VARGS AVDec_DisplayFrame(void *vctx, qboolean nosound, qboolean auddatasize/=2; width = 2; } +#endif break; - case AV_SAMPLE_FMT_DBLP: auddatasize /= channels; channels = 1; @@ -443,7 +465,7 @@ static qboolean VARGS AVDec_DisplayFrame(void *vctx, qboolean nosound, qboolean } break; } - pS_RawAudio(-1, auddata, ctx->pACodecCtx->sample_rate, auddatasize/(channels*width), channels, width, 1); + audiofuncs->RawAudio(-1, auddata, ctx->pACodecCtx->sample_rate, auddatasize/(channels*width), channels, width, 1); } } @@ -561,7 +583,7 @@ static qboolean VARGS AVDec_DisplayFrame(void *vctx, qboolean nosound, qboolean } break; } - pS_RawAudio(-1, auddata, ctx->pACodecCtx->sample_rate, auddatasize/(channels*width), channels, width, 1); + audiofuncs->RawAudio(-1, auddata, ctx->pACodecCtx->sample_rate, auddatasize/(channels*width), channels, width, 1); } } packet.data = odata; @@ -608,7 +630,7 @@ static void AVDec_Rewind(void *vctx) /* //avcodec has no way to shut down properly. -static qintptr_t AVDec_Shutdown(qintptr_t *args) +static qboolean AVDec_Shutdown(void) { return 0; } @@ -632,14 +654,14 @@ static media_decoder_funcs_t decoderfuncs = qboolean AVDec_Init(void) { - if (!pPlug_ExportNative("Media_VideoDecoder", &decoderfuncs)) + filefuncs = plugfuncs->GetEngineInterface(plugfsfuncs_name, sizeof(*filefuncs)); + audiofuncs = plugfuncs->GetEngineInterface(plugaudiofuncs_name, sizeof(*audiofuncs)); + if (!filefuncs || + !plugfuncs->ExportInterface("Media_VideoDecoder", &decoderfuncs, sizeof(decoderfuncs))) { Con_Printf(DECODERNAME": Engine doesn't support media decoder plugins\n"); return false; } - CHECKBUILTIN(S_RawAudio); - CHECKBUILTIN(FS_Seek); - return true; } diff --git a/plugins/avplug/avencode.c b/plugins/avplug/avencode.c index d5f791b21..ceb5f0ce7 100644 --- a/plugins/avplug/avencode.c +++ b/plugins/avplug/avencode.c @@ -27,6 +27,8 @@ #define AV_ERROR_MAX_STRING_SIZE 64 #endif +static plugfsfuncs_t *filefuncs; + /* Most of the logic in here came from here: http://svn.gnumonks.org/tags/21c3-video/upstream/ffmpeg-0.4.9-pre1/output_example.c @@ -669,7 +671,7 @@ static void *AVEnc_Begin (char *streamname, int videorate, int width, int height if (!(fmt->flags & AVFMT_NOFILE)) { //okay, this is annoying, but I'm too lazy to figure out the issue I was having with avio stuff. - if (!pFS_NativePath(streamname, FS_GAMEONLY, ctx->abspath, sizeof(ctx->abspath))) + if (!filefuncs->NativePath(streamname, FS_GAMEONLY, ctx->abspath, sizeof(ctx->abspath))) { Con_Printf("Couldn't find system path for '%s'\n", streamname); AVEnc_End(ctx); @@ -747,10 +749,10 @@ static media_encoder_funcs_t encoderfuncs = }; -qintptr_t AVEnc_ExecuteCommand(qintptr_t *args) +qboolean AVEnc_ExecuteCommand(qboolean isinsecure) { char cmd[256]; - pCmd_Argv(0, cmd, sizeof(cmd)); + cmdfuncs->Argv(0, cmd, sizeof(cmd)); /* if (!strcmp(cmd, ENCODERNAME"_configure")) { @@ -770,38 +772,38 @@ menutext 0 24 "Cancel" */ if (!strcmp(cmd, ENCODERNAME"_nvidia")) { - pCvar_SetString("capturedriver", ENCODERNAME); //be sure to use our encoder - pCvar_SetString(ENCODERNAME"_videocodec", "h264_nvenc"); - pCvar_SetString("capturerate", "60"); //we should be able to cope with it, and the default of 30 sucks - pCvar_SetString("capturedemowidth", "1920"); //force a specific size, some codecs need multiples of 16 or whatever. - pCvar_SetString("capturedemoheight", "1080"); //so this avoids issues with various video codecs. + cvarfuncs->SetString("capturedriver", ENCODERNAME); //be sure to use our encoder + cvarfuncs->SetString(ENCODERNAME"_videocodec", "h264_nvenc"); + cvarfuncs->SetString("capturerate", "60"); //we should be able to cope with it, and the default of 30 sucks + cvarfuncs->SetString("capturedemowidth", "1920"); //force a specific size, some codecs need multiples of 16 or whatever. + cvarfuncs->SetString("capturedemoheight", "1080"); //so this avoids issues with various video codecs. - pCvar_SetString("capturesound", "1"); - pCvar_SetString("capturesoundchannels", "2"); - pCvar_SetString("capturesoundbits", "16"); + cvarfuncs->SetString("capturesound", "1"); + cvarfuncs->SetString("capturesoundchannels", "2"); + cvarfuncs->SetString("capturesoundbits", "16"); Con_Printf(ENCODERNAME": now configured for nvidia's hardware encoder\n"); Con_Printf(ENCODERNAME": use ^[/capture foo.mp4^] or ^[/capturedemo foo.mvd foo.mkv^] commands to begin capturing\n"); } if (!strcmp(cmd, ENCODERNAME"_defaults")) { //most formats will end up using the x264 encoder or something - pCvar_SetString(ENCODERNAME"_format_force", ""); - pCvar_SetString(ENCODERNAME"_videocodec", ""); - pCvar_SetString(ENCODERNAME"_videobitrate", ""); - pCvar_SetString(ENCODERNAME"_videoforcewidth", ""); - pCvar_SetString(ENCODERNAME"_videoforceheight", ""); - pCvar_SetString(ENCODERNAME"_videopreset", "veryfast"); - pCvar_SetString(ENCODERNAME"_video_crf", ""); - pCvar_SetString(ENCODERNAME"_audiocodec", ""); - pCvar_SetString(ENCODERNAME"_audiobitrate", ""); + cvarfuncs->SetString(ENCODERNAME"_format_force", ""); + cvarfuncs->SetString(ENCODERNAME"_videocodec", ""); + cvarfuncs->SetString(ENCODERNAME"_videobitrate", ""); + cvarfuncs->SetString(ENCODERNAME"_videoforcewidth", ""); + cvarfuncs->SetString(ENCODERNAME"_videoforceheight", ""); + cvarfuncs->SetString(ENCODERNAME"_videopreset", "veryfast"); + cvarfuncs->SetString(ENCODERNAME"_video_crf", ""); + cvarfuncs->SetString(ENCODERNAME"_audiocodec", ""); + cvarfuncs->SetString(ENCODERNAME"_audiobitrate", ""); - pCvar_SetString("capturedriver", ENCODERNAME); - pCvar_SetString("capturerate", "30"); - pCvar_SetString("capturedemowidth", "0"); - pCvar_SetString("capturedemoheight", "0"); - pCvar_SetString("capturesound", "1"); - pCvar_SetString("capturesoundchannels", "2"); - pCvar_SetString("capturesoundbits", "16"); + cvarfuncs->SetString("capturedriver", ENCODERNAME); + cvarfuncs->SetString("capturerate", "30"); + cvarfuncs->SetString("capturedemowidth", "0"); + cvarfuncs->SetString("capturedemoheight", "0"); + cvarfuncs->SetString("capturesound", "1"); + cvarfuncs->SetString("capturesoundchannels", "2"); + cvarfuncs->SetString("capturesoundbits", "16"); Con_Printf(ENCODERNAME": capture settings reset to "ENCODERNAME" defaults\n"); Con_Printf(ENCODERNAME": Note that some codecs may have restrictions on video sizes\n"); @@ -812,32 +814,27 @@ menutext 0 24 "Cancel" qboolean AVEnc_Init(void) { - CHECKBUILTIN(FS_NativePath); - if (!BUILTINISVALID(FS_NativePath)) - { - Con_Printf(ENCODERNAME": Engine too old\n"); - return false; - } - if (!pPlug_ExportNative("Media_VideoEncoder", &encoderfuncs)) + filefuncs = plugfuncs->GetEngineInterface(plugfsfuncs_name, sizeof(*filefuncs)); + if (!cvarfuncs || !cmdfuncs || !filefuncs || !plugfuncs->ExportInterface("Media_VideoEncoder", &encoderfuncs, sizeof(encoderfuncs))) { Con_Printf(ENCODERNAME": Engine doesn't support media encoder plugins\n"); return false; } - ffmpeg_format_force = pCvar_GetNVFDG(ENCODERNAME"_format_force", "", 0, "Forces the output container format. If blank, will guess based upon filename extension.", ENCODERNAME); - ffmpeg_videocodec = pCvar_GetNVFDG(ENCODERNAME"_videocodec", "", 0, "Forces which video encoder to use. If blank, guesses based upon container defaults.\nCommon names are libx264 (software), x264_nvenc (hardware accelerated)", ENCODERNAME); - ffmpeg_videobitrate = pCvar_GetNVFDG(ENCODERNAME"_videobitrate", "", 0, "Specifies the target video bitrate", ENCODERNAME); - ffmpeg_videoforcewidth = pCvar_GetNVFDG(ENCODERNAME"_videoforcewidth", "", 0, "Rescales the input video width. Best to leave blank in order to record the video at the native resolution.", ENCODERNAME); - ffmpeg_videoforceheight = pCvar_GetNVFDG(ENCODERNAME"_videoforceheight", "", 0, "Rescales the input video height. Best to leave blank in order to record the video at the native resolution.", ENCODERNAME); - ffmpeg_videopreset = pCvar_GetNVFDG(ENCODERNAME"_videopreset", "veryfast", 0, "Specifies which codec preset to use, for codecs that support such presets.", ENCODERNAME); - ffmpeg_video_crf = pCvar_GetNVFDG(ENCODERNAME"_video_crf", "", 0, "Specifies the 'Constant Rate Factor' codec setting.\nA value of 0 is 'lossless', a value of 51 is 'worst quality posible', a value of 23 is default.", ENCODERNAME); - ffmpeg_audiocodec = pCvar_GetNVFDG(ENCODERNAME"_audiocodec", "", 0, "Forces which audio encoder to use. If blank, guesses based upon container defaults.", ENCODERNAME); - ffmpeg_audiobitrate = pCvar_GetNVFDG(ENCODERNAME"_audiobitrate", "", 0, "Specifies the target audio bitrate", ENCODERNAME); + ffmpeg_format_force = cvarfuncs->GetNVFDG(ENCODERNAME"_format_force", "", 0, "Forces the output container format. If blank, will guess based upon filename extension.", ENCODERNAME); + ffmpeg_videocodec = cvarfuncs->GetNVFDG(ENCODERNAME"_videocodec", "", 0, "Forces which video encoder to use. If blank, guesses based upon container defaults.\nCommon names are libx264 (software), x264_nvenc (hardware accelerated)", ENCODERNAME); + ffmpeg_videobitrate = cvarfuncs->GetNVFDG(ENCODERNAME"_videobitrate", "", 0, "Specifies the target video bitrate", ENCODERNAME); + ffmpeg_videoforcewidth = cvarfuncs->GetNVFDG(ENCODERNAME"_videoforcewidth", "", 0, "Rescales the input video width. Best to leave blank in order to record the video at the native resolution.", ENCODERNAME); + ffmpeg_videoforceheight = cvarfuncs->GetNVFDG(ENCODERNAME"_videoforceheight", "", 0, "Rescales the input video height. Best to leave blank in order to record the video at the native resolution.", ENCODERNAME); + ffmpeg_videopreset = cvarfuncs->GetNVFDG(ENCODERNAME"_videopreset", "veryfast", 0, "Specifies which codec preset to use, for codecs that support such presets.", ENCODERNAME); + ffmpeg_video_crf = cvarfuncs->GetNVFDG(ENCODERNAME"_video_crf", "", 0, "Specifies the 'Constant Rate Factor' codec setting.\nA value of 0 is 'lossless', a value of 51 is 'worst quality posible', a value of 23 is default.", ENCODERNAME); + ffmpeg_audiocodec = cvarfuncs->GetNVFDG(ENCODERNAME"_audiocodec", "", 0, "Forces which audio encoder to use. If blank, guesses based upon container defaults.", ENCODERNAME); + ffmpeg_audiobitrate = cvarfuncs->GetNVFDG(ENCODERNAME"_audiobitrate", "", 0, "Specifies the target audio bitrate", ENCODERNAME); - if (Plug_Export("ExecuteCommand", AVEnc_ExecuteCommand)) + if (plugfuncs->ExportFunction("ExecuteCommand", AVEnc_ExecuteCommand)) { -// pCmd_AddCommand(ENCODERNAME"_configure"); - pCmd_AddCommand(ENCODERNAME"_nvidia"); +// cmdfuncs->AddCommand(ENCODERNAME"_configure"); + cmdfuncs->AddCommand(ENCODERNAME"_nvidia"); } return true; diff --git a/plugins/bullet/bulletplug.cpp b/plugins/bullet/bulletplug.cpp index 24814b15c..e0a47a970 100644 --- a/plugins/bullet/bulletplug.cpp +++ b/plugins/bullet/bulletplug.cpp @@ -84,14 +84,10 @@ static cvar_t *pr_meshpitch; void World_Bullet_Init(void) { - physics_bullet_enable = pCvar_GetNVFDG("physics_bullet_enable", "1", 0, "", "Bullet"); - physics_bullet_maxiterationsperframe = pCvar_GetNVFDG("physics_bullet_maxiterationsperframe", "10", 0, "FIXME: should be 1 when CCD is working properly.", "Bullet"); - physics_bullet_framerate = pCvar_GetNVFDG("physics_bullet_framerate", "60", 0, "Bullet physics run at a fixed framerate in order to preserve numerical stability (interpolation is used to smooth out the result). Higher framerates are of course more demanding.", "Bullet"); - pr_meshpitch = pCvar_GetNVFDG("r_meshpitch", "-1", 0, "", "Bullet"); -} - -void World_Bullet_Shutdown(void) -{ + physics_bullet_enable = cvarfuncs->GetNVFDG("physics_bullet_enable", "1", 0, "", "Bullet"); + physics_bullet_maxiterationsperframe = cvarfuncs->GetNVFDG("physics_bullet_maxiterationsperframe", "10", 0, "FIXME: should be 1 when CCD is working properly.", "Bullet"); + physics_bullet_framerate = cvarfuncs->GetNVFDG("physics_bullet_framerate", "60", 0, "Bullet physics run at a fixed framerate in order to preserve numerical stability (interpolation is used to smooth out the result). Higher framerates are of course more demanding.", "Bullet"); + pr_meshpitch = cvarfuncs->GetNVFDG("r_meshpitch", "-1", 0, "", "Bullet"); } typedef struct bulletcontext_s @@ -1786,11 +1782,10 @@ static void QDECL World_Bullet_Start(world_t *world) */ } -static qintptr_t QDECL World_Bullet_Shutdown(qintptr_t *args) +static void QDECL World_Bullet_Shutdown(void) { if (rbefuncs) rbefuncs->UnregisterPhysicsEngine("Bullet"); - return 0; } static bool World_Bullet_DoInit(void) @@ -1810,23 +1805,14 @@ static bool World_Bullet_DoInit(void) return false; } -#define ARGNAMES ,version -static BUILTINR(rbeplugfuncs_t*, RBE_GetPluginFuncs, (int version)); -#undef ARGNAMES - -extern "C" qintptr_t Plug_Init(qintptr_t *args) +extern "C" qboolean Plug_Init(void) { - CHECKBUILTIN(RBE_GetPluginFuncs); + rbefuncs = (rbeplugfuncs_t*)plugfuncs->GetEngineInterface("RBE", sizeof(*rbefuncs)); + if (rbefuncs && rbefuncs->version < RBEPLUGFUNCS_VERSION) + rbefuncs = nullptr; - if (BUILTINISVALID(RBE_GetPluginFuncs)) - { - rbefuncs = pRBE_GetPluginFuncs(sizeof(rbeplugfuncs_t)); - if (rbefuncs && rbefuncs->version < RBEPLUGFUNCS_VERSION) - rbefuncs = NULL; - } - - Plug_Export("Shutdown", World_Bullet_Shutdown); - return World_Bullet_DoInit(); + plugfuncs->ExportFunction("Shutdown", (funcptr_t)World_Bullet_Shutdown); + return World_Bullet_DoInit()?qtrue:qfalse; } diff --git a/plugins/emailnot/Makefile b/plugins/emailnot/Makefile deleted file mode 100755 index fe05e16db..000000000 --- a/plugins/emailnot/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -LCC_FLAGS=-DQ3_VM -S -Wf-target=bytecode -Wf-g - -qvm: - lcc $(LCC_FLAGS) imapnoti.c; lcc $(LCC_FLAGS) md5.c; lcc $(LCC_FLAGS) pop3noti.c; lcc $(LCC_FLAGS) ../memory.c; lcc $(LCC_FLAGS) ../plugin.c; lcc $(LCC_FLAGS) ../qvm_api.c; q3asm -f emailnot -clean: - rm -rf $(OBJECTS) $(OUTFILE) *.qvm *.asm \ No newline at end of file diff --git a/plugins/emailnot/compile.bat b/plugins/emailnot/compile.bat deleted file mode 100644 index 6d7e465cc..000000000 --- a/plugins/emailnot/compile.bat +++ /dev/null @@ -1,29 +0,0 @@ -@echo off -call ..\paths.bat - -del vm\*.asm -rmdir vm -mkdir vm -cd vm -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../imapnoti.c -if errorlevel 1 goto error -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../md5.c -if errorlevel 1 goto error -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../pop3noti.c -if errorlevel 1 goto error -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../memory.c -if errorlevel 1 goto error -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../plugin.c -if errorlevel 1 goto error -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../qvm_api.c -if errorlevel 1 goto error -q3asm -f ../emailnot - -:error -cd .. - -pause -goto endbat - - -:endbat \ No newline at end of file diff --git a/plugins/ezhud/ezquakeisms.c b/plugins/ezhud/ezquakeisms.c index 15d4a648f..03c2747c4 100644 --- a/plugins/ezhud/ezquakeisms.c +++ b/plugins/ezhud/ezquakeisms.c @@ -3,6 +3,11 @@ #include "hud.h" #include "hud_editor.h" +plug2dfuncs_t *drawfuncs; +plugclientfuncs_t *clientfuncs; +plugfsfuncs_t *filefuncs; +pluginputfuncs_t *inputfuncs; + int sb_lines; float scr_con_current; int sb_showteamscores; @@ -12,12 +17,18 @@ float alphamul; cvar_t *scr_newHud; +static void QDECL EZHud_UpdateVideo(int width, int height) +{ + vid.width = width; + vid.height = height; +} + char *Cmd_Argv(int arg) { static char buf[4][128]; if (arg >= 4) return ""; - pCmd_Argv(arg, buf[arg], sizeof(buf[arg])); + cmdfuncs->Argv(arg, buf[arg], sizeof(buf[arg])); return buf[arg]; } @@ -29,15 +40,15 @@ void Draw_SetOverallAlpha(float a) } void Draw_AlphaFillRGB(float x, float y, float w, float h, qbyte r, qbyte g, qbyte b, qbyte a) { - pDraw_Colour4f(r/255.0, g/255.0, b/255.0, a/255.0 * alphamul); - pDraw_Fill(x, y, w, h); - pDraw_Colour4f(1, 1, 1, 1); + drawfuncs->Colour4f(r/255.0, g/255.0, b/255.0, a/255.0 * alphamul); + drawfuncs->Fill(x, y, w, h); + drawfuncs->Colour4f(1, 1, 1, 1); } void Draw_Fill(float x, float y, float w, float h, qbyte pal) { - pDraw_Colourpa(pal, alphamul); - pDraw_Fill(x, y, w, h); - pDraw_Colour4f(1, 1, 1, 1); + drawfuncs->Colourpa(pal, alphamul); + drawfuncs->Fill(x, y, w, h); + drawfuncs->Colour4f(1, 1, 1, 1); } const char *ColorNameToRGBString (const char *newval) { @@ -62,10 +73,10 @@ void Draw_TextBox (int x, int y, int width, int lines) { } -char *TP_LocationName (vec3_t location) +char *TP_LocationName (const vec3_t location) { static char locname[256]; - pGetLocationName(location, locname, sizeof(locname)); + clientfuncs->GetLocationName(location, locname, sizeof(locname)); return locname; } @@ -74,75 +85,75 @@ void Draw_SPic(float x, float y, mpic_t *pic, float scale) { qhandle_t image = (intptr_t)pic; float w, h; - pDraw_ImageSize(image, &w, &h); - pDraw_Image(x, y, w*scale, h*scale, 0, 0, 1, 1, image); + drawfuncs->ImageSize(image, &w, &h); + drawfuncs->Image(x, y, w*scale, h*scale, 0, 0, 1, 1, image); } void Draw_SSubPic(float x, float y, mpic_t *pic, float s1, float t1, float s2, float t2, float scale) { qhandle_t image = (intptr_t)pic; float w, h; - pDraw_ImageSize(image, &w, &h); - pDraw_Image(x, y, (s2-s1)*scale, (t2-t1)*scale, s1/w, t1/h, s2/w, t2/h, image); + drawfuncs->ImageSize(image, &w, &h); + drawfuncs->Image(x, y, (s2-s1)*scale, (t2-t1)*scale, s1/w, t1/h, s2/w, t2/h, image); } void Draw_EZString(float x, float y, char *str, float scale, qboolean red) { unsigned int flags = 0; if (red) flags |= 1; - pDraw_StringH(x, y, scale, flags, str); + drawfuncs->StringH(x, y, scale, flags, str); } #define Draw_STransPic Draw_SPic void Draw_Character(float x, float y, unsigned int ch) { - pDraw_Character(x, y, 0xe000|ch); + drawfuncs->Character(x, y, 0xe000|ch); } void Draw_SCharacter(float x, float y, unsigned int ch, float scale) { - pDraw_CharacterH(x, y, 8*scale, 0, 0xe000|ch); + drawfuncs->CharacterH(x, y, 8*scale, 0, 0xe000|ch); } void SCR_DrawWadString(float x, float y, float scale, char *str) { - pDraw_String(x, y, str); //FIXME + drawfuncs->String(x, y, str); //FIXME } void Draw_SAlphaSubPic2(float x, float y, mpic_t *pic, float s1, float t1, float s2, float t2, float sw, float sh, float alpha) { qhandle_t image = (intptr_t)pic; float w, h; - pDraw_ImageSize(image, &w, &h); - pDraw_Colour4f(1, 1, 1, alpha * alphamul); - pDraw_Image(x, y, (s2-s1)*sw, (t2-t1)*sh, s1/w, t1/h, s2/w, t2/h, image); - pDraw_Colour4f(1, 1, 1, 1); + drawfuncs->ImageSize(image, &w, &h); + drawfuncs->Colour4f(1, 1, 1, alpha * alphamul); + drawfuncs->Image(x, y, (s2-s1)*sw, (t2-t1)*sh, s1/w, t1/h, s2/w, t2/h, image); + drawfuncs->Colour4f(1, 1, 1, 1); } void Draw_AlphaFill(float x, float y, float w, float h, unsigned int pal, float alpha) { if (pal >= 256) - pDraw_Colour4f(((pal>>16)&0xff)/255.0, ((pal>>8)&0xff)/255.0, ((pal>>0)&0xff)/255.0, alpha * alphamul); + drawfuncs->Colour4f(((pal>>16)&0xff)/255.0, ((pal>>8)&0xff)/255.0, ((pal>>0)&0xff)/255.0, alpha * alphamul); else - pDraw_Colourpa(pal, alpha * alphamul); - pDraw_Fill(x, y, w, h); - pDraw_Colour4f(1, 1, 1, 1); + drawfuncs->Colourpa(pal, alpha * alphamul); + drawfuncs->Fill(x, y, w, h); + drawfuncs->Colour4f(1, 1, 1, 1); } void Draw_AlphaPic(float x, float y, mpic_t *pic, float alpha) { qhandle_t image = (intptr_t)pic; float w, h; - pDraw_ImageSize(image, &w, &h); - pDraw_Colour4f(1, 1, 1, alpha * alphamul); - pDraw_Image(x, y, w, h, 0, 0, 1, 1, image); - pDraw_Colour4f(1, 1, 1, 1); + drawfuncs->ImageSize(image, &w, &h); + drawfuncs->Colour4f(1, 1, 1, alpha * alphamul); + drawfuncs->Image(x, y, w, h, 0, 0, 1, 1, image); + drawfuncs->Colour4f(1, 1, 1, 1); } void Draw_AlphaSubPic(float x, float y, mpic_t *pic, float s1, float t1, float s2, float t2, float alpha) { qhandle_t image = (intptr_t)pic; float w, h; - pDraw_ImageSize(image, &w, &h); - pDraw_Colour4f(1, 1, 1, alpha * alphamul); - pDraw_Image(x, y, s2-s1, t2-t1, s1/w, t1/h, s2/w, t2/h, image); - pDraw_Colour4f(1, 1, 1, 1); + drawfuncs->ImageSize(image, &w, &h); + drawfuncs->Colour4f(1, 1, 1, alpha * alphamul); + drawfuncs->Image(x, y, s2-s1, t2-t1, s1/w, t1/h, s2/w, t2/h, image); + drawfuncs->Colour4f(1, 1, 1, 1); } void SCR_HUD_DrawBar(int direction, int value, float max_value, float *rgba, int x, int y, int width, int height) { @@ -154,33 +165,33 @@ void SCR_HUD_DrawBar(int direction, int value, float max_value, float *rgba, int else// left-right amount = Q_rint(fabs((width * value) / max_value)); - pDraw_Colour4f(rgba[0]/255.0, rgba[1]/255.0, rgba[2]/255.0, rgba[3]/255.0 * alphamul); + drawfuncs->Colour4f(rgba[0]/255.0, rgba[1]/255.0, rgba[2]/255.0, rgba[3]/255.0 * alphamul); if(direction == 0) // left->right - pDraw_Fill(x, y, amount, height); + drawfuncs->Fill(x, y, amount, height); else if (direction == 1) // right->left - pDraw_Fill(x + width - amount, y, amount, height); + drawfuncs->Fill(x + width - amount, y, amount, height); else if (direction == 2) // down -> up - pDraw_Fill(x, y + height - amount, width, amount); + drawfuncs->Fill(x, y + height - amount, width, amount); else // up -> down - pDraw_Fill(x, y, width, amount); - pDraw_Colour4f(1, 1, 1, 1); + drawfuncs->Fill(x, y, width, amount); + drawfuncs->Colour4f(1, 1, 1, 1); } void Draw_Polygon(int x, int y, vec3_t *vertices, int num_vertices, qbool fill, byte r, byte g, byte b, byte a) { - pDraw_Colour4f(r/255.0, g/255.0, b/255.0, a/255.0 * alphamul); -// pDraw_Line(x1, y1, x2, y1); - pDraw_Colour4f(1, 1, 1, 1); + drawfuncs->Colour4f(r/255.0, g/255.0, b/255.0, a/255.0 * alphamul); +// drawfuncs->Line(x1, y1, x2, y1); + drawfuncs->Colour4f(1, 1, 1, 1); } void Draw_ColoredString3(float x, float y, const char *str, clrinfo_t *clr, int huh, int wut) { - pDraw_Colour4f(clr->c[0]/255.0, clr->c[1]/255.0, clr->c[2]/255.0, clr->c[3]/255.0 * alphamul); - pDraw_String(x, y, str); - pDraw_Colour4f(1, 1, 1, 1); + drawfuncs->Colour4f(clr->c[0]/255.0, clr->c[1]/255.0, clr->c[2]/255.0, clr->c[3]/255.0 * alphamul); + drawfuncs->String(x, y, str); + drawfuncs->Colour4f(1, 1, 1, 1); } void UI_PrintTextBlock(void) { @@ -191,29 +202,29 @@ void Draw_AlphaRectangleRGB(int x, int y, int w, int h, int foo, int bar, byte r float x2 = x+w; float y1 = y; float y2 = y+h; - pDraw_Colour4f(r/255.0, g/255.0, b/255.0, a/255.0 * alphamul); - pDraw_Line(x1, y1, x2, y1); - pDraw_Line(x2, y1, x2, y2); - pDraw_Line(x1, y2, x2, y2); - pDraw_Line(x1, y1, x1, y2); - pDraw_Colour4f(1, 1, 1, 1); + drawfuncs->Colour4f(r/255.0, g/255.0, b/255.0, a/255.0 * alphamul); + drawfuncs->Line(x1, y1, x2, y1); + drawfuncs->Line(x2, y1, x2, y2); + drawfuncs->Line(x1, y2, x2, y2); + drawfuncs->Line(x1, y1, x1, y2); + drawfuncs->Colour4f(1, 1, 1, 1); } void Draw_AlphaLineRGB(float x1, float y1, float x2, float y2, float width, byte r, byte g, byte b, byte a) { - pDraw_Colour4f(r/255.0, g/255.0, b/255.0, a/255.0 * alphamul); - pDraw_Line(x1, y1, x2, y2); - pDraw_Colour4f(1, 1, 1, 1); + drawfuncs->Colour4f(r/255.0, g/255.0, b/255.0, a/255.0 * alphamul); + drawfuncs->Line(x1, y1, x2, y2); + drawfuncs->Colour4f(1, 1, 1, 1); } mpic_t *Draw_CachePicSafe(const char *name, qbool crash, qbool ignorewad) { if (!*name) return NULL; - return (mpic_t*)(qintptr_t)pDraw_LoadImage(name, false); + return (mpic_t*)(qintptr_t)drawfuncs->LoadImage(name, false); } mpic_t *Draw_CacheWadPic(const char *name) { - return (mpic_t*)(qintptr_t)pDraw_LoadImage(name, true); + return (mpic_t*)(qintptr_t)drawfuncs->LoadImage(name, true); } mpic_t *SCR_LoadCursorImage(char *cursorimage) @@ -488,15 +499,15 @@ void SCR_DrawSmallClock(int x, int y, int style, int blink, float scale, const c void EZHud_UseNquake_f(void) { const char *hudstr = builtin_hud_nquake; - pCmd_AddText(hudstr, true); + cmdfuncs->AddText(hudstr, true); } -struct +static struct { xcommand_t cmd; const char *name; } concmds[128]; -int numconcmds; +static int numconcmds; qboolean Cmd_AddCommand (const char *funcname, xcommand_t function) { if (numconcmds < sizeof(concmds)/sizeof(concmds[0])) @@ -504,17 +515,17 @@ qboolean Cmd_AddCommand (const char *funcname, xcommand_t function) concmds[numconcmds].cmd = function; concmds[numconcmds].name = funcname; numconcmds++; - pCmd_AddCommand(funcname); + cmdfuncs->AddCommand(funcname); return true; } Con_Printf("ezhud: too many console commands\n"); return false; }; -qintptr_t EZHud_ExecuteCommand(qintptr_t *args) +static qboolean QDECL EZHud_ExecuteCommand(qboolean isinsecure) { char buffer[128]; int i; - pCmd_Argv(0, buffer, sizeof(buffer)); + cmdfuncs->Argv(0, buffer, sizeof(buffer)); for (i = 0; i < numconcmds; i++) { if (!strcmp(buffer, concmds[i].name)) @@ -537,17 +548,17 @@ double vid_vsync_lag; vrect_t scr_vrect; -qintptr_t EZHud_Tick(qintptr_t *args) +void EZHud_Tick(double realtime, double gametime) { static float lasttime, lasttime_min = 99999; static int framecount; //realtime(ms), realtime(secs), servertime float oldtime = cls.realtime; - cls.realtime = *(float*)&args[1]; + cls.realtime = realtime; cls.frametime = cls.realtime - oldtime; - cl.time = *(float*)&args[2]; + cl.time = gametime; if (cls.realtime - lasttime > 1) { @@ -564,8 +575,6 @@ qintptr_t EZHud_Tick(qintptr_t *args) cls.min_fps = cls.fps; } framecount++; - - return 1; } char *findinfo(char *info, char *findkey) { @@ -612,25 +621,25 @@ float infofloat(char *info, char *findkey, float def) return atof(value); return def; } -qintptr_t EZHud_Draw(qintptr_t *args) +int EZHud_Draw(int seat, float viewx, float viewy, float viewwidth, float viewheight, int showscores) { char serverinfo[4096]; char val[64]; int i; - cl.splitscreenview = args[0]; - scr_vrect.x = args[1]; - scr_vrect.y = args[2]; - scr_vrect.width = args[3]; - scr_vrect.height = args[4]; - sb_showscores = args[5] & 1; - sb_showteamscores = args[5] & 2; + cl.splitscreenview = seat; + scr_vrect.x = viewx; + scr_vrect.y = viewy; + scr_vrect.width = viewwidth; + scr_vrect.height = viewheight; + sb_showscores = showscores & 1; + sb_showteamscores = showscores & 2; - pCL_GetStats(0, cl.stats, sizeof(cl.stats)/sizeof(cl.stats[0])); + clientfuncs->GetStats(0, cl.stats, sizeof(cl.stats)/sizeof(cl.stats[0])); for (i = 0; i < 32; i++) - pGetPlayerInfo(i, &cl.players[i]); + clientfuncs->GetPlayerInfo(i, &cl.players[i]); - pGetLocalPlayerNumbers(cl.splitscreenview, 1, &cl.playernum, &cl.tracknum); - pGetServerInfo(cl.serverinfo, sizeof(serverinfo)); + clientfuncs->GetLocalPlayerNumbers(cl.splitscreenview, 1, &cl.playernum, &cl.tracknum); + clientfuncs->GetServerInfo(cl.serverinfo, sizeof(serverinfo)); cl.deathmatch = infofloat(cl.serverinfo, "deathmatch", 0); cl.teamplay = infofloat(cl.serverinfo, "teamplay", 0); cl.intermission = infofloat(cl.serverinfo, "intermission", 0); @@ -640,8 +649,6 @@ qintptr_t EZHud_Draw(qintptr_t *args) cl.countdown = !strcmp(val, "countdown"); cl.matchstart = infofloat(cl.serverinfo, "matchstart", 0); cls.state = ca_active; - vid.width = pvid.width; - vid.height = pvid.height; infostring(cl.serverinfo, "demotype", val, sizeof(val)); cls.mvdplayback = !strcmp(val, "mvd"); @@ -652,7 +659,7 @@ qintptr_t EZHud_Draw(qintptr_t *args) static cvar_t *pscr_viewsize = NULL; int size; if (!pscr_viewsize) - pscr_viewsize = pCvar_GetNVFDG("viewsize", "100", 0, NULL, NULL); + pscr_viewsize = cvarfuncs->GetNVFDG("viewsize", "100", 0, NULL, NULL); size = cl.intermission ? 120 : pscr_viewsize->value; if (size >= 120) sb_lines = 0; // no status bar at all @@ -686,14 +693,12 @@ float cursor_y; float mouse_x; float mouse_y; mpic_t *scr_cursor_icon = NULL; -qintptr_t EZHud_MenuEvent(qintptr_t *args) +qboolean QDECL EZHud_MenuEvent(int eventtype, int keyparam, int unicodeparm, float mousecursor_x, float mousecursor_y, float vidwidth, float vidheight) { - int eventtype = args[0]; - int param = args[1]; - mouse_x += args[2] - cursor_x; //FIXME: the hud editor should NOT need this sort of thing - mouse_y += args[3] - cursor_y; - cursor_x = args[2]; - cursor_y = args[3]; + mouse_x += mousecursor_x - cursor_x; //FIXME: the hud editor should NOT need this sort of thing + mouse_y += mousecursor_y - cursor_y; + cursor_x = mousecursor_x; + cursor_y = mousecursor_y; HUD_Editor_MouseEvent(cursor_x, cursor_y); @@ -708,33 +713,39 @@ qintptr_t EZHud_MenuEvent(qintptr_t *args) mouse_y = 0; break; case 1: - if (param < K_MAX) - keydown[param] = true; - HUD_Editor_Key(param, 0, true); + if (keyparam < K_MAX) + keydown[keyparam] = true; + HUD_Editor_Key(keyparam, 0, true); break; case 2: - if (param < K_MAX) - keydown[param] = false; - HUD_Editor_Key(param, 0, false); + if (keyparam < K_MAX) + keydown[keyparam] = false; + HUD_Editor_Key(keyparam, 0, false); break; } return 1; } -qintptr_t Plug_Init(qintptr_t *args) +qboolean Plug_Init(void) { - if (BUILTINISVALID(Cvar_GetNVFDG) && - BUILTINISVALID(Draw_ImageSize) && - BUILTINISVALID(GetTeamInfo) && - Plug_Export("SbarBase", EZHud_Draw) && - Plug_Export("MenuEvent", EZHud_MenuEvent) && - Plug_Export("Tick", EZHud_Tick) && - Plug_Export("ExecuteCommand", EZHud_ExecuteCommand)) + drawfuncs = plugfuncs->GetEngineInterface(plug2dfuncs_name, sizeof(*drawfuncs)); + clientfuncs = plugfuncs->GetEngineInterface(plugclientfuncs_name, sizeof(*clientfuncs)); + filefuncs = plugfuncs->GetEngineInterface(plugfsfuncs_name, sizeof(*filefuncs)); + inputfuncs = plugfuncs->GetEngineInterface(pluginputfuncs_name, sizeof(*inputfuncs)); + + plugfuncs->ExportFunction("UpdateVideo", EZHud_UpdateVideo); + + if (cvarfuncs && drawfuncs && clientfuncs && filefuncs && inputfuncs && + plugfuncs->ExportFunction("SbarBase", EZHud_Draw) && + plugfuncs->ExportFunction("MenuEvent", EZHud_MenuEvent) && + plugfuncs->ExportFunction("Tick", EZHud_Tick) && + plugfuncs->ExportFunction("ExecuteCommand", EZHud_ExecuteCommand)) { Cmd_AddCommand("ezhud_nquake", EZHud_UseNquake_f); HUD_Init(); HUD_Editor_Init(); - return 1; + return true; } + Con_Printf("EZHud: Unable to initiailise\n"); return false; } diff --git a/plugins/ezhud/ezquakeisms.h b/plugins/ezhud/ezquakeisms.h index a04534ab9..d0e2c0acb 100644 --- a/plugins/ezhud/ezquakeisms.h +++ b/plugins/ezhud/ezquakeisms.h @@ -2,6 +2,11 @@ #include #include +extern plug2dfuncs_t *drawfuncs; +extern plugfsfuncs_t *filefuncs; +extern plugclientfuncs_t *clientfuncs; +extern pluginputfuncs_t *inputfuncs; + //ezquake sucks. I'd fix these, but that'd make diffs more messy. #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wold-style-definition" @@ -14,12 +19,12 @@ #define qbool qboolean #define Com_Printf Con_Printf #define Com_DPrintf Con_DPrintf -#define Cvar_Find(n) pCvar_GetNVFDG(n,NULL,0,NULL,NULL) -#define Cvar_SetValue(var,val) pCvar_SetFloat(var->name,val) -#define Cvar_Set(var,val) pCvar_SetString(var->name,val) -#define Cmd_Argc pCmd_Argc -#define Cbuf_AddText(x) pCmd_AddText(x,false) -#define Sys_Error(x) pSys_Error(x) +#define Cvar_Find(n) cvarfuncs->GetNVFDG(n,NULL,0,NULL,NULL) +#define Cvar_SetValue(var,val) cvarfuncs->SetFloat(var->name,val) +#define Cvar_Set(var,val) cvarfuncs->SetString(var->name,val) +#define Cmd_Argc cmdfuncs->Argc +#define Cbuf_AddText(x) cmdfuncs->AddText(x,false) +#define Sys_Error(x) plugfuncs->Error(x) #define Q_calloc calloc #define Q_malloc malloc #define Q_strdup strdup @@ -99,7 +104,7 @@ void Draw_Fill(float x, float y, float w, float h, qbyte pal); const char *ColorNameToRGBString (const char *newval); byte *StringToRGB(const char *str); -#define Draw_String pDraw_String +#define Draw_String drawfuncs->String void Draw_EZString(float x, float y, char *str, float scale, qboolean red); #define Draw_Alt_String(x,y,s) Draw_EZString(x,y,s,8,true) @@ -138,7 +143,7 @@ void Replace_In_String(char *string, size_t strsize, char leadchar, int patterns #define Utils_RegExpMatch(regexp,term) (true) #define clamp(v,min,max) v=bound(min,v,max) -#define strlen_color(line) (pDraw_StringWidth(8, 0, line)/8.0) +#define strlen_color(line) (drawfuncs->StringWidth(8, 0, line)/8.0) #define TIMETYPE_CLOCK 0 #define TIMETYPE_GAMECLOCK 1 @@ -160,10 +165,6 @@ void Draw_AlphaRectangleRGB(int x, int y, int w, int h, int foo, int bar, byte r void Draw_AlphaLineRGB(float x1, float y1, float x2, float y2, float width, byte r, byte g, byte b, byte a); void Draw_Polygon(int x, int y, vec3_t *vertices, int num_vertices, qbool fill, byte r, byte g, byte b, byte a); -//glue -EBUILTIN(cvar_t*, Cvar_GetNVFDG, (const char *name, const char *defaultval, unsigned int flags, const char *description, const char *groupname)); - - #undef sb_lines //just in case. #ifndef SBAR_HEIGHT #define SBAR_HEIGHT 24 diff --git a/plugins/ezhud/hud.c b/plugins/ezhud/hud.c index b8e2341b8..1fe435303 100644 --- a/plugins/ezhud/hud.c +++ b/plugins/ezhud/hud.c @@ -796,22 +796,22 @@ void HUD_Export_f(void) char fname[64]; char fdesc[256]; - pCmd_Argv(1, fname, sizeof(fname)); - pCmd_Argv(2, fdesc, sizeof(fdesc)); + cmdfuncs->Argv(1, fname, sizeof(fname)); + cmdfuncs->Argv(2, fdesc, sizeof(fdesc)); if (!*fdesc) snprintf(fdesc, sizeof(fdesc), "%s", fname); snprintf(line, sizeof(line), "configs/hud_%s.cfg", fname); - if (pFS_Open(line, &handle, 2) < 0) + if (filefuncs->Open(line, &handle, 2) < 0) Com_Printf("Couldn't open %s\n", line); else { //FIXME: should print the result of an flocate, but plugins are not really aware of that stuff. Com_Printf("Writing %s\n", line); snprintf(line, sizeof(line), "//desc:%s\n\n//hud cvar settings, for use with FTEQW's ezhud plugin.\n", fdesc); - pFS_Write(handle, line, strlen(line)); + filefuncs->Write(handle, line, strlen(line)); for (hud = hud_huds; hud; hud = hud->next) { @@ -820,11 +820,11 @@ void HUD_Export_f(void) var = hud->params[i]; //fixme: deal with " and \n snprintf(line, sizeof(line), "set %s \"%s\"\n", var->name, var->string); - pFS_Write(handle, line, strlen(line)); + filefuncs->Write(handle, line, strlen(line)); } } - pFS_Close(handle); + filefuncs->Close(handle); } } @@ -1168,7 +1168,7 @@ cvar_t * HUD_CreateVar(char *hud_name, char *subvar, char *value) snprintf (buf, sizeof (buf), "hud_%s_%s", hud_name, subvar); - return pCvar_GetNVFDG(buf, value, 0, NULL, "ezhud"); + return cvarfuncs->GetNVFDG(buf, value, 0, NULL, "ezhud"); } // diff --git a/plugins/ezhud/hud_common.c b/plugins/ezhud/hud_common.c index 63a01b900..cb973e68d 100644 --- a/plugins/ezhud/hud_common.c +++ b/plugins/ezhud/hud_common.c @@ -147,14 +147,14 @@ void HUD_InitSbarImages(void) sb_ibar = Draw_CacheWadPic("ibar"); } -vmnetinfo_t *GetNetworkInfo(void) +plugnetinfo_t *GetNetworkInfo(void) { - static vmnetinfo_t ni; + static plugnetinfo_t ni; static int uc; - if (uc != host_screenupdatecount && BUILTINISVALID(GetNetworkInfo)) + if (uc != host_screenupdatecount) { uc = host_screenupdatecount; - pGetNetworkInfo(&ni, sizeof(ni)); + clientfuncs->GetNetworkInfo(&ni, sizeof(ni)); } return ∋ } @@ -393,7 +393,7 @@ void SCR_HUD_DrawFPS(hud_t *hud) if (HUD_PrepareDraw(hud, strlen(st)*8, 8, &x, &y)) { - vmnetinfo_t *netinfo = GetNetworkInfo(); + plugnetinfo_t *netinfo = GetNetworkInfo(); if (netinfo->capturing == 2) //don't show fps if its locked to something anyway. return; @@ -418,7 +418,7 @@ void SCR_HUD_DrawVidLag(hud_t *hud) char st[128]; static cvar_t *hud_vidlag_style = NULL; - vmnetinfo_t *netinfo = GetNetworkInfo(); + plugnetinfo_t *netinfo = GetNetworkInfo(); static double old_lag; if (netinfo->vlatency) @@ -462,7 +462,7 @@ void SCR_HUD_DrawMouserate(hud_t *hud) char st[80]; // string buffer double t; // current time static double lastframetime; // last refresh - vmnetinfo_t *netinfo = GetNetworkInfo(); + plugnetinfo_t *netinfo = GetNetworkInfo(); static cvar_t *hud_mouserate_title = NULL, *hud_mouserate_interval, @@ -655,7 +655,7 @@ static void SCR_HUD_DrawPing(hud_t *hud) int width, height; int x, y; char buf[512]; - vmnetinfo_t *netinfo = GetNetworkInfo(); + plugnetinfo_t *netinfo = GetNetworkInfo(); static cvar_t *hud_ping_period = NULL, @@ -823,12 +823,12 @@ static void SCR_HUD_DrawNotify(hud_t* hud) if (HUD_PrepareDraw(hud, width, height, &x, &y)) { - pCvar_SetFloat("con_notify_x", (float)x / vid.width); - pCvar_SetFloat("con_notify_y", (float)y / vid.height); - pCvar_SetFloat("con_notify_w", (float)width / vid.width); - pCvar_SetFloat("con_numnotifylines",(int)(height/(8*hud_notify_scale->value) + 0.01)); - pCvar_SetFloat("con_notifytime", (float)hud_notify_time->ival); - pCvar_SetFloat("con_textsize", 8.0 * hud_notify_scale->value); + cvarfuncs->SetFloat("con_notify_x", (float)x / vid.width); + cvarfuncs->SetFloat("con_notify_y", (float)y / vid.height); + cvarfuncs->SetFloat("con_notify_w", (float)width / vid.width); + cvarfuncs->SetFloat("con_numnotifylines",(int)(height/(8*hud_notify_scale->value) + 0.01)); + cvarfuncs->SetFloat("con_notifytime", (float)hud_notify_time->ival); + cvarfuncs->SetFloat("con_textsize", 8.0 * hud_notify_scale->value); // SCR_DrawNotify(x, y, hud_notify_scale->value, hud_notify_time->ival, hud_notify_rows->ival, hud_notify_cols->ival); } } @@ -926,7 +926,7 @@ void SCR_HUD_DrawDemoClock(hud_t *hud) // // network statistics // -static void SCR_NetStats(int x, int y, float period, vmnetinfo_t *netinfo) +static void SCR_NetStats(int x, int y, float period, plugnetinfo_t *netinfo) { char line[128]; double t; @@ -1002,7 +1002,7 @@ static void SCR_NetStats(int x, int y, float period, vmnetinfo_t *netinfo) clamp(bandwidth_out, 0, 99999); clamp(bandwidth_all, 0, 99999); - with_delta = !pCvar_GetFloat("cl_nodelta"); + with_delta = !cvarfuncs->GetFloat("cl_nodelta"); } Draw_Alt_String(x+36, y, "latency"); @@ -1068,7 +1068,7 @@ static void SCR_HUD_DrawNetStats(hud_t *hud) int width, height; int x, y; - vmnetinfo_t *netinfo = GetNetworkInfo(); + plugnetinfo_t *netinfo = GetNetworkInfo(); static cvar_t *hud_net_period = NULL; @@ -2314,7 +2314,7 @@ void Draw_AMFStatLoss (int stat, hud_t* hud) { else alpha = 0; - pDraw_Colour4f(1,1,1,alpha); + drawfuncs->Colour4f(1,1,1,alpha); { static cvar_t *scale[2] = {NULL}, *style[2], *digits[2], *align[2]; if (scale[elem] == NULL) // first time called @@ -2327,7 +2327,7 @@ void Draw_AMFStatLoss (int stat, hud_t* hud) { SCR_HUD_DrawNum (hud, abs(*vxdmgcnt), 1, scale[elem]->value, style[elem]->value, digits[elem]->ival, align[elem]->string); } - pDraw_Colour4f(1,1,1,1); + drawfuncs->Colour4f(1,1,1,1); } static void SCR_HUD_DrawHealthDamage(hud_t *hud) @@ -2476,11 +2476,11 @@ static void SCR_HUD_NetProblem (hud_t *hud) { static cvar_t *scale = NULL; int x, y; extern qbool hud_editor; - vmnetinfo_t *netinfo = GetNetworkInfo(); + plugnetinfo_t *netinfo = GetNetworkInfo(); float picwidth = 64; float picheight = 64; - pDraw_ImageSize((intptr_t)sb_net, &picwidth, &picheight); + drawfuncs->ImageSize((intptr_t)sb_net, &picwidth, &picheight); if(scale == NULL) scale = HUD_FindVar(hud, "scale"); @@ -2524,7 +2524,7 @@ void SCR_HUD_DrawGroup(hud_t *hud, int width, int height, mpic_t *pic, int pic_s float picwidth = 64; float picheight = 64; - if (pic && pDraw_ImageSize((intptr_t)pic, &picwidth, &picheight) <= 0) + if (pic && drawfuncs->ImageSize((intptr_t)pic, &picwidth, &picheight) <= 0) { pic = NULL; picwidth = 64; @@ -2650,7 +2650,7 @@ void SCR_HUD_LoadGroupPic(cvar_t *var, mpic_t **hud_pic, char *oldval) if (!(temp_pic = Draw_CachePicSafe(pic_path, false, true))) { Com_Printf("Couldn't load picture %s for hud group.\n", newpic); - pCvar_SetString(var->name, ""); + cvarfuncs->SetString(var->name, ""); return; } @@ -3305,7 +3305,7 @@ int TeamFrags_DrawExtraSpecInfo(int num, int px, int py, int width, int height, { float rl_width, rl_height; mpic_t *pic = sb_weapons[0][5]; - pDraw_ImageSize((intptr_t)pic, &rl_width, &rl_height); + drawfuncs->ImageSize((intptr_t)pic, &rl_width, &rl_height); // Only allow this for spectators. if (!(cls.demoplayback || cl.spectator) @@ -3415,7 +3415,7 @@ static int Frags_DrawExtraSpecInfo(player_info_t *info, int health_spacing = 1; int weapon_width = 24; - pDraw_ImageSize((intptr_t)rl_picture, &rl_width, &rl_height); + drawfuncs->ImageSize((intptr_t)rl_picture, &rl_width, &rl_height); // Only allow this for spectators. if (!(cls.demoplayback || cl.spectator)) @@ -3686,7 +3686,7 @@ void SCR_HUD_DrawFrags(hud_t *hud) mpic_t *rl_picture = sb_weapons[0][5]; float rl_width, rl_height; - pDraw_ImageSize((intptr_t)rl_picture, &rl_width, &rl_height); + drawfuncs->ImageSize((intptr_t)rl_picture, &rl_width, &rl_height); if (hud_frags_cell_width == NULL) // first time { @@ -4116,7 +4116,7 @@ void SCR_HUD_DrawTeamFrags(hud_t *hud) mpic_t *rl_picture = sb_weapons[0][5]; float rl_width, rl_height; - pDraw_ImageSize((intptr_t)rl_picture, &rl_width, &rl_height); + drawfuncs->ImageSize((intptr_t)rl_picture, &rl_width, &rl_height); if (hud_teamfrags_cell_width == 0) // first time { @@ -4720,31 +4720,31 @@ void HUD_AutoLoad_MVD(int autoload) { { // Save old cfg_save values so that we don't screw the users // settings when saving the temp config. - int old_cmdline = pCvar_GetFloat("cfg_save_cmdline"); - int old_cvars = pCvar_GetFloat("cfg_save_cvars"); - int old_cmds = pCvar_GetFloat("cfg_save_cmds"); - int old_aliases = pCvar_GetFloat("cfg_save_aliases"); - int old_binds = pCvar_GetFloat("cfg_save_binds"); + int old_cmdline = cvarfuncs->GetFloat("cfg_save_cmdline"); + int old_cvars = cvarfuncs->GetFloat("cfg_save_cvars"); + int old_cmds = cvarfuncs->GetFloat("cfg_save_cmds"); + int old_aliases = cvarfuncs->GetFloat("cfg_save_aliases"); + int old_binds = cvarfuncs->GetFloat("cfg_save_binds"); autohud.old_fov = (int) scr_fov->value; autohud.old_multiview = (int) cl_multiview->value; autohud.old_newhud = (int) scr_newHud->value; // Make sure everything current settings are saved. - pCvar_SetFloat("cfg_save_cmdline", 1); - pCvar_SetFloat("cfg_save_cvars", 1); - pCvar_SetFloat("cfg_save_cmds", 1); - pCvar_SetFloat("cfg_save_aliases", 1); - pCvar_SetFloat("cfg_save_binds", 1); + cvarfuncs->SetFloat("cfg_save_cmdline", 1); + cvarfuncs->SetFloat("cfg_save_cvars", 1); + cvarfuncs->SetFloat("cfg_save_cmds", 1); + cvarfuncs->SetFloat("cfg_save_aliases", 1); + cvarfuncs->SetFloat("cfg_save_binds", 1); // Save a temporary config. DumpConfig(TEMPHUD_NAME".cfg"); - pCvar_SetFloat("cfg_save_cmdline", old_cmdline); - pCvar_SetFloat("cfg_save_cvars", old_cvars); - pCvar_SetFloat("cfg_save_cmds", old_cmds); - pCvar_SetFloat("cfg_save_aliases", old_aliases); - pCvar_SetFloat("cfg_save_binds", old_binds); + cvarfuncs->SetFloat("cfg_save_cmdline", old_cmdline); + cvarfuncs->SetFloat("cfg_save_cvars", old_cvars); + cvarfuncs->SetFloat("cfg_save_cmds", old_cmds); + cvarfuncs->SetFloat("cfg_save_aliases", old_aliases); + cvarfuncs->SetFloat("cfg_save_binds", old_binds); } // load MVD HUD config @@ -4778,9 +4778,9 @@ void HUD_AutoLoad_MVD(int autoload) { Com_DPrintf("Unloading MVD Hud\n"); // load stored settings - pCvar_SetFloat(scr_fov->name, autohud.old_fov); - pCvar_SetFloat(cl_multiview->name, autohud.old_multiview); - pCvar_SetFloat(scr_newHud->name, autohud.old_newhud); + cvarfuncs->SetFloat(scr_fov->name, autohud.old_fov); + cvarfuncs->SetFloat(cl_multiview->name, autohud.old_multiview); + cvarfuncs->SetFloat(scr_newHud->name, autohud.old_newhud); //Cmd_TokenizeString("exec "TEMPHUD_FULLPATH); Cmd_TokenizeString("cfg_load "TEMPHUD_FULLPATH); Cmd_Exec_f(); @@ -5373,7 +5373,7 @@ static void SCR_HUD_DrawTeamInfo(hud_t *hud) // if ( CURRVIEW != 1 && CURRVIEW != 0) // return; - slots_num = pGetTeamInfo(ti_clients, countof(ti_clients), hud_teaminfo_show_enemies->ival, hud_teaminfo_show_self->ival); + slots_num = clientfuncs->GetTeamInfo(ti_clients, countof(ti_clients), hud_teaminfo_show_enemies->ival, hud_teaminfo_show_self->ival?-1:0); // fill data we require to draw teaminfo for ( maxloc = maxname = i = 0; i < slots_num; i++ ) { @@ -5537,7 +5537,7 @@ static int SCR_HudDrawTeamInfoPlayer(teamplayerinfo_t *ti_cl, int x, int y, int case 1: if(!width_only) { if (Has_Both_RL_and_LG(ti_cl->items)) { - char *weap_str = pCvar_GetNVFDG("tp_name_rlg", "rlg", 0, NULL, NULL)->string; + char *weap_str = cvarfuncs->GetNVFDG("tp_name_rlg", "rlg", 0, NULL, NULL)->string; char weap_white_stripped[32]; Util_SkipChars(weap_str, "{}", weap_white_stripped, 32); Draw_ColoredString (x, y, weap_white_stripped, false); @@ -6362,13 +6362,8 @@ void SCR_HUD_DrawOwnFrags(hud_t *hud) strcpy(ownfragtext, "Own Frags"); age = 0; } - else if (BUILTINISVALID(GetTrackerOwnFrags)) - age = pGetTrackerOwnFrags(0, ownfragtext, sizeof(ownfragtext)); else - { - strcpy(ownfragtext, "Engine does not support OwnFrags"); - age = 0; - } + age = clientfuncs->GetTrackerOwnFrags(0, ownfragtext, sizeof(ownfragtext)); width = strlen(ownfragtext)*8; width *= hud_ownfrags_scale->value; @@ -6388,9 +6383,9 @@ void SCR_HUD_DrawOwnFrags(hud_t *hud) if (!HUD_PrepareDraw(hud, width, height, &x, &y)) return; - pDraw_Colour4f(1, 1, 1, alpha); + drawfuncs->Colour4f(1, 1, 1, alpha); Draw_SString(x, y, ownfragtext, hud_ownfrags_scale->value); - pDraw_Colour4f(1, 1, 1, 1); + drawfuncs->Colour4f(1, 1, 1, 1); } #ifdef QUAKEHUD @@ -6415,10 +6410,7 @@ static void SCR_HUD_DrawWeaponStats(hud_t *hud) int ws; struct wstats_s wstats[16]; - if (BUILTINISVALID(GetWeaponStats)) - ws = pGetWeaponStats(-1, wstats, countof(wstats)); - else - ws = 0; + ws = clientfuncs->GetWeaponStats(-1, wstats, countof(wstats)); if (hud_editor) { @@ -6507,8 +6499,7 @@ void SCR_HUD_DrawKeys(hud_t *hud) float scale; memset(&b, 0, sizeof(b)); - if (BUILTINISVALID(GetLastInputFrame)) - pGetLastInputFrame(0, &b); + clientfuncs->GetLastInputFrame(0, &b); if (!vscale) { vscale = HUD_FindVar(hud, "scale"); @@ -7714,24 +7705,24 @@ void CommonDraw_Init(void) HUD_InitSbarImages(); // variables - hud_planmode = pCvar_GetNVFDG("hud_planmode", "0", 0, NULL, "ezhud"); - hud_tp_need = pCvar_GetNVFDG("hud_tp_need", "0", 0, NULL, "ezhud"); - hud_digits_trim = pCvar_GetNVFDG("hud_digits_trim", "1", 0, NULL, "ezhud"); - mvd_autohud = pCvar_GetNVFDG("mvd_autohud", "0", 0, NULL, "ezhud"); - cl_weaponpreselect = pCvar_GetNVFDG("cl_weaponpreselect", "0", 0, NULL, "ezhud"); - cl_multiview = pCvar_GetNVFDG("cl_multiview", "0", 0, NULL, "ezhud"); + hud_planmode = cvarfuncs->GetNVFDG("hud_planmode", "0", 0, NULL, "ezhud"); + hud_tp_need = cvarfuncs->GetNVFDG("hud_tp_need", "0", 0, NULL, "ezhud"); + hud_digits_trim = cvarfuncs->GetNVFDG("hud_digits_trim", "1", 0, NULL, "ezhud"); + mvd_autohud = cvarfuncs->GetNVFDG("mvd_autohud", "0", 0, NULL, "ezhud"); + cl_weaponpreselect = cvarfuncs->GetNVFDG("cl_weaponpreselect", "0", 0, NULL, "ezhud"); + cl_multiview = cvarfuncs->GetNVFDG("cl_multiview", "0", 0, NULL, "ezhud"); - tp_need_health = pCvar_GetNVFDG("tp_need_health", "50", 0, NULL, "ezhud"); - tp_need_ra = pCvar_GetNVFDG("tp_need_ra", "50", 0, NULL, "ezhud"); - tp_need_ya = pCvar_GetNVFDG("tp_need_ya", "50", 0, NULL, "ezhud"); - tp_need_ga = pCvar_GetNVFDG("tp_need_ga", "50", 0, NULL, "ezhud"); - tp_weapon_order = pCvar_GetNVFDG("tp_weapon_order", "78654321", 0, NULL, "ezhud"); - tp_need_weapon = pCvar_GetNVFDG("tp_need_weapon", "35687", 0, NULL, "ezhud"); - tp_need_shells = pCvar_GetNVFDG("tp_need_shells", "10", 0, NULL, "ezhud"); - tp_need_nails = pCvar_GetNVFDG("tp_need_nails", "40", 0, NULL, "ezhud"); - tp_need_rockets = pCvar_GetNVFDG("tp_need_rockets", "5", 0, NULL, "ezhud"); - tp_need_cells = pCvar_GetNVFDG("tp_need_cells", "20", 0, NULL, "ezhud"); + tp_need_health = cvarfuncs->GetNVFDG("tp_need_health", "50", 0, NULL, "ezhud"); + tp_need_ra = cvarfuncs->GetNVFDG("tp_need_ra", "50", 0, NULL, "ezhud"); + tp_need_ya = cvarfuncs->GetNVFDG("tp_need_ya", "50", 0, NULL, "ezhud"); + tp_need_ga = cvarfuncs->GetNVFDG("tp_need_ga", "50", 0, NULL, "ezhud"); + tp_weapon_order = cvarfuncs->GetNVFDG("tp_weapon_order", "78654321", 0, NULL, "ezhud"); + tp_need_weapon = cvarfuncs->GetNVFDG("tp_need_weapon", "35687", 0, NULL, "ezhud"); + tp_need_shells = cvarfuncs->GetNVFDG("tp_need_shells", "10", 0, NULL, "ezhud"); + tp_need_nails = cvarfuncs->GetNVFDG("tp_need_nails", "40", 0, NULL, "ezhud"); + tp_need_rockets = cvarfuncs->GetNVFDG("tp_need_rockets", "5", 0, NULL, "ezhud"); + tp_need_cells = cvarfuncs->GetNVFDG("tp_need_cells", "20", 0, NULL, "ezhud"); // init HUD STAT table for (i=0; i < MAX_CL_STATS; i++) diff --git a/plugins/ezhud/hud_editor.c b/plugins/ezhud/hud_editor.c index 1d35349f7..be51075e1 100644 --- a/plugins/ezhud/hud_editor.c +++ b/plugins/ezhud/hud_editor.c @@ -2438,7 +2438,7 @@ void HUD_Editor_Toggle_f(void) { // Start HUD Editor. - pMenu_Control(MENU_GRAB); + inputfuncs->SetMenuFocus(true, "", 0, 0, 0); HUD_Editor_SetMode(hud_editmode_normal); // Set planmode by default. @@ -2452,7 +2452,7 @@ void HUD_Editor_Toggle_f(void) { // Exit the HUD Editor. - pMenu_Control(MENU_CLEAR); + inputfuncs->SetMenuFocus(false, "", 0, 0, 0); HUD_Editor_SetMode(hud_editmode_off); scr_cursor_icon = NULL; @@ -2760,10 +2760,10 @@ void HUD_Editor_Init(void) Cmd_AddCommand("hud_editor", HUD_Editor_Toggle_f); // Register variables. - hud_editor_allowresize = pCvar_GetNVFDG("hud_editor_allowresize", "1", 0, NULL, "hud"); - hud_editor_allowmove = pCvar_GetNVFDG("hud_editor_allowmove", "1", 0, NULL, "hud"); - hud_editor_allowplace = pCvar_GetNVFDG("hud_editor_allowplace", "1", 0, NULL, "hud"); - hud_editor_allowalign = pCvar_GetNVFDG("hud_editor_allowalign", "1", 0, NULL, "hud"); + hud_editor_allowresize = cvarfuncs->GetNVFDG("hud_editor_allowresize", "1", 0, NULL, "hud"); + hud_editor_allowmove = cvarfuncs->GetNVFDG("hud_editor_allowmove", "1", 0, NULL, "hud"); + hud_editor_allowplace = cvarfuncs->GetNVFDG("hud_editor_allowplace", "1", 0, NULL, "hud"); + hud_editor_allowalign = cvarfuncs->GetNVFDG("hud_editor_allowalign", "1", 0, NULL, "hud"); // Load HUD editor cursor icons. hud_editor_move_icon = SCR_LoadCursorImage("gfx/hud_move_icon"); diff --git a/plugins/ezscript/Makefile b/plugins/ezscript/Makefile deleted file mode 100644 index 466024118..000000000 --- a/plugins/ezscript/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -DO_CC=$(CC) -ggdb -fPIC -Wall $(CFLAGS) -o $@ -c $< -OBJECTS=ezscript.o plugin.o qvm_api.o -HEADERS=../plugin.h -OUTFILE=../ezscriptx86.so -LCC_FLAGS=-DQ3_VM -S -Wf-target=bytecode -Wf-g -all: $(OBJECTS) - $(CC) -ggdb -fPIC -shared $(OBJECTS) -o $(OUTFILE) - -clean: - rm -rf $(OBJECTS) $(OUTFILE) *.qvm *.asm - -qvm: - lcc $(LCC_FLAGS) ezscript.c; lcc $(LCC_FLAGS) ../plugin.c; lcc $(LCC_FLAGS) ../qvm_api.c; q3asm -f ezscript - - -ezscript.o: ezscript.c $(HEADERS) - $(DO_CC) - -plugin.o: ../plugin.c $(HEADERS) - $(DO_CC) - -qvm_api.o: ../qvm_api.c $(HEADERS) - $(DO_CC) - - diff --git a/plugins/ezscript/compile.bat b/plugins/ezscript/compile.bat deleted file mode 100644 index 872edc9e0..000000000 --- a/plugins/ezscript/compile.bat +++ /dev/null @@ -1,15 +0,0 @@ -@echo off -call ..\paths.bat - -del vm\*.asm -rmdir vm -mkdir vm -cd vm -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../ezscript.c -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../plugin.c -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../qvm_api.c -q3asm -f ../ezscript - -cd .. - -pause \ No newline at end of file diff --git a/plugins/hud/Makefile b/plugins/hud/Makefile deleted file mode 100644 index 998805823..000000000 --- a/plugins/hud/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -DO_CC=$(CC) -ggdb -fPIC -Wall $(CFLAGS) -o $@ -c $< -OBJECTS=ui_sbar.o plugin.o qvm_api.o -HEADERS=../plugin.h -OUTFILE=../hudx86.so -ASM=q3asm -#ASM=q3asm -vq3 #Uncomment this if you are using Icculus q3asm -LCC=q3lcc -LCC_FLAGS=-DQ3_VM -S -Wf-target=bytecode -Wf-g -all: $(OBJECTS) - $(CC) -ggdb -fPIC -shared $(OBJECTS) -o $(OUTFILE) - -qvm: - $(LCC) $(LCC_FLAGS) ui_sbar.c; $(LCC) $(LCC_FLAGS) ../plugin.c; $(LCC) $(LCC_FLAGS) ../qvm_api.c; $(ASM) -f qwui -clean: - rm -rf $(OBJECTS) $(OUTFILE) *.qvm *.asm - -ui_sbar.o: ui_sbar.c $(HEADERS) - $(DO_CC) - -plugin.o: ../plugin.c $(HEADERS) - $(DO_CC) - -qvm_api.o: ../qvm_api.c $(HEADERS) - $(DO_CC) - diff --git a/plugins/hud/compile.bat b/plugins/hud/compile.bat deleted file mode 100644 index 0168997e0..000000000 --- a/plugins/hud/compile.bat +++ /dev/null @@ -1,20 +0,0 @@ -@echo off -call ..\paths.bat - -del vm\*.asm -rmdir vm -mkdir vm -cd vm -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../ui_sbar.c -if errorlevel 1 goto end -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../plugin.c -if errorlevel 1 goto end -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../qvm_api.c -if errorlevel 1 goto end -q3asm -f ../qwui - -:end - -cd .. - -pause \ No newline at end of file diff --git a/plugins/irc/Makefile b/plugins/irc/Makefile deleted file mode 100644 index 067f12ae0..000000000 --- a/plugins/irc/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -DO_CC=$(CC) -fPIC $(CFLAGS) -o $@ -c $< -OBJECTS=ircclient.o plugin.o qvm_api.o -HEADERS=../plugin.h -OUTFILE=../ircx86.so -ASM=q3asm -#ASM=q3asm -vq3 #Uncomment this if you are using Icculus q3asm -LCC=q3lcc -LCC_FLAGS=-DQ3_VM -I/usr/include -S -Wf-target=bytecode -Wf-g -all: $(OBJECTS) - $(CC) --shared -ldl $(OBJECTS) -o $(OUTFILE) - -qvm: - $(LCC) $(LCC_FLAGS) ircclient.c; $(LCC) $(LCC_FLAGS) ../plugin.c; $(LCC) $(LCC_FLAGS) ../qvm_api.c; $(ASM) -f ircclient -clean: - rm -rf $(OBJECTS) $(OUTFILE) *.qvm *.asm - -ircclient.o: ircclient.c $(HEADERS) - $(DO_CC) - -plugin.o: ../plugin.c $(HEADERS) - $(DO_CC) - -qvm_api.o: ../qvm_api.c $(HEADERS) - $(DO_CC) - diff --git a/plugins/irc/compile.bat b/plugins/irc/compile.bat deleted file mode 100644 index 0aa060851..000000000 --- a/plugins/irc/compile.bat +++ /dev/null @@ -1,15 +0,0 @@ -@echo off -call ..\paths.bat - -del vm\*.asm -rmdir vm -mkdir vm -cd vm -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../ircclient.c -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../plugin.c -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../qvm_api.c -q3asm -f ../ircclient - -cd .. - -pause \ No newline at end of file diff --git a/plugins/irc/ircclient.c b/plugins/irc/ircclient.c index aa9b345c0..07a5dde49 100644 --- a/plugins/irc/ircclient.c +++ b/plugins/irc/ircclient.c @@ -9,6 +9,10 @@ #include "../plugin.h" +static plugsubconsolefuncs_t *confuncs; +static plugfsfuncs_t *filefuncs; +static plugnetfuncs_t *netfuncs; +static plug2dfuncs_t *drawfuncs; #include #include #include "../../engine/common/netinc.h" @@ -64,10 +68,22 @@ static char casevar[9][1000]; //numbered_command #define COMMANDNAME "irc" #define RELEASE __DATE__ -static void (*Con_TrySubPrint)(const char *subname, const char *text); -static void Con_FakeSubPrint(const char *subname, const char *text) +static struct { - pCon_Print(text); + int width; + int height; +} pvid; +static void QDECL IRC_UpdateVideo(int width, int height) +{ + pvid.width = width; + pvid.height = height; +} + +static qboolean (*Con_TrySubPrint)(const char *subname, const char *text); +static qboolean Con_FakeSubPrint(const char *subname, const char *text) +{ + plugfuncs->Print(text); + return true; } //porting zone: @@ -248,14 +264,14 @@ static void IRC_SetFooter(ircclient_t *irc, const char *subname, const char *for lwr[i] = '\0'; - if (BUILTINISVALID(Con_SetConsoleFloat) && pCon_GetConsoleFloat(lwr, "iswindow") < true) + if (confuncs && confuncs->GetConsoleFloat(lwr, "iswindow") < true) { - pCon_SetConsoleString(lwr, "title", *channame?channame:irc->server); - pCon_SetConsoleString(lwr, "prompt", va("[^1%s^7]: ", irc->nick)); - pCon_SetConsoleFloat(lwr, "iswindow", 2); - pCon_SetConsoleFloat(lwr, "forceutf8", true); - pCon_SetConsoleFloat(lwr, "wnd_w", 256); - pCon_SetConsoleFloat(lwr, "wnd_h", 320); + confuncs->SetConsoleString(lwr, "title", *channame?channame:irc->server); + confuncs->SetConsoleString(lwr, "prompt", va("[^1%s^7]: ", irc->nick)); + confuncs->SetConsoleFloat(lwr, "iswindow", 2); + confuncs->SetConsoleFloat(lwr, "forceutf8", true); + confuncs->SetConsoleFloat(lwr, "wnd_w", 256); + confuncs->SetConsoleFloat(lwr, "wnd_h", 320); //lame, but whatever. if (next_window_x + 256 > pvid.width) @@ -265,13 +281,13 @@ static void IRC_SetFooter(ircclient_t *irc, const char *subname, const char *for if (next_window_y + 320 > pvid.height) next_window_y = 0; } - pCon_SetConsoleFloat(lwr, "wnd_x", next_window_x); - pCon_SetConsoleFloat(lwr, "wnd_y", next_window_y); + confuncs->SetConsoleFloat(lwr, "wnd_x", next_window_x); + confuncs->SetConsoleFloat(lwr, "wnd_y", next_window_y); next_window_x += 256; } - if (BUILTINISVALID(Con_SetConsoleString)) - pCon_SetConsoleString(lwr, "footer", string); + if (confuncs) + confuncs->SetConsoleString(lwr, "footer", string); } } static qboolean IRC_WindowShown(ircclient_t *irc, const char *subname) @@ -291,7 +307,7 @@ static qboolean IRC_WindowShown(ircclient_t *irc, const char *subname) lwr[i] = '\0'; - if (BUILTINISVALID(Con_SetConsoleFloat) && pCon_GetConsoleFloat(lwr, "iswindow") < true) + if (confuncs && confuncs->GetConsoleFloat(lwr, "iswindow") < true) return false; } return true; @@ -310,7 +326,7 @@ static void IRC_Printf(ircclient_t *irc, const char *subname, const char *format va_end (argptr); if (!irc) - pCon_Print(string); + plugfuncs->Print(string); else { Q_strlcpy(lwr, irc->id, sizeof(lwr)); @@ -324,14 +340,14 @@ static void IRC_Printf(ircclient_t *irc, const char *subname, const char *format lwr[i] = '\0'; - if (BUILTINISVALID(Con_SetConsoleFloat) && pCon_GetConsoleFloat(lwr, "iswindow") < true) + if (confuncs && confuncs->GetConsoleFloat(lwr, "iswindow") < true) { - pCon_SetConsoleString(lwr, "title", *channame?channame:irc->server); - pCon_SetConsoleString(lwr, "prompt", va("[^1%s^7]: ", irc->nick)); - pCon_SetConsoleFloat(lwr, "iswindow", 2); - pCon_SetConsoleFloat(lwr, "forceutf8", true); - pCon_SetConsoleFloat(lwr, "wnd_w", 256); - pCon_SetConsoleFloat(lwr, "wnd_h", 320); + confuncs->SetConsoleString(lwr, "title", *channame?channame:irc->server); + confuncs->SetConsoleString(lwr, "prompt", va("[^1%s^7]: ", irc->nick)); + confuncs->SetConsoleFloat(lwr, "iswindow", 2); + confuncs->SetConsoleFloat(lwr, "forceutf8", true); + confuncs->SetConsoleFloat(lwr, "wnd_w", 256); + confuncs->SetConsoleFloat(lwr, "wnd_h", 320); //lame, but whatever. if (next_window_x + 256 > pvid.width) @@ -341,12 +357,12 @@ static void IRC_Printf(ircclient_t *irc, const char *subname, const char *format if (next_window_y + 320 > pvid.height) next_window_y = 0; } - pCon_SetConsoleFloat(lwr, "wnd_x", next_window_x); - pCon_SetConsoleFloat(lwr, "wnd_y", next_window_y); + confuncs->SetConsoleFloat(lwr, "wnd_x", next_window_x); + confuncs->SetConsoleFloat(lwr, "wnd_y", next_window_y); next_window_x += 256; } if (!*string) - pCon_SetActive(lwr); + confuncs->SetActive(lwr); Con_TrySubPrint(lwr, string); } @@ -362,7 +378,7 @@ static void IRC_InitCvars(void) for (i=0; cvarlist[i]; i++) { v = cvarlist[i]; - v->handle = pCvar_Register(v->name, v->string, v->flags, v->group); + v->handle = cvarfuncs->Register(v->name, v->string, v->flags, v->group); } } @@ -373,71 +389,77 @@ static int IRC_CvarUpdate(void) // perhaps void instead? for (i=0; cvarlist[i]; i++) { v = cvarlist[i]; - v->modificationcount = pCvar_Update(v->handle, &v->modificationcount, v->string, &v->value); + cvarfuncs->Update(v->handle, &v->modificationcount, v->string, sizeof(v->string), &v->value); } return 0; } void IRC_Command(ircclient_t *ircclient, char *dest, char *args); -qintptr_t IRC_ExecuteCommand(qintptr_t *args); -qintptr_t IRC_ConExecuteCommand(qintptr_t *args); -qintptr_t IRC_Frame(qintptr_t *args); -qintptr_t IRC_ConsoleLink(qintptr_t *args); +qboolean IRC_ExecuteCommand(qboolean isinsecure); +int IRC_ConExecuteCommand(qboolean isinsecure); +void IRC_Frame(double realtime, double gametime); +qboolean IRC_ConsoleLink(void); -qintptr_t Plug_Init(qintptr_t *args) +qboolean Plug_Init(void) { - if ( Plug_Export("Tick", IRC_Frame) && - Plug_Export("ExecuteCommand", IRC_ExecuteCommand)) - { - pCmd_AddCommand(COMMANDNAME); + confuncs = plugfuncs->GetEngineInterface(plugsubconsolefuncs_name, sizeof(*confuncs)); + filefuncs = plugfuncs->GetEngineInterface(plugfsfuncs_name, sizeof(*filefuncs)); + netfuncs = plugfuncs->GetEngineInterface(plugnetfuncs_name, sizeof(*netfuncs)); + drawfuncs = plugfuncs->GetEngineInterface(plug2dfuncs_name, sizeof(*drawfuncs)); + piceapi = plugfuncs->GetEngineInterface(ICE_API_CURRENT, sizeof(*piceapi)); + plugfuncs->ExportFunction("UpdateVideo", IRC_UpdateVideo); - Plug_Export("ConsoleLink", IRC_ConsoleLink); - if (!Plug_Export("ConExecuteCommand", IRC_ConExecuteCommand)) + if (netfuncs && + filefuncs && + plugfuncs->ExportFunction("Tick", IRC_Frame) && + plugfuncs->ExportFunction("ExecuteCommand", IRC_ExecuteCommand)) + { + cmdfuncs->AddCommand(COMMANDNAME); + + plugfuncs->ExportFunction("ConsoleLink", IRC_ConsoleLink); + if (!confuncs || !plugfuncs->ExportFunction("ConExecuteCommand", IRC_ConExecuteCommand)) Con_TrySubPrint = Con_FakeSubPrint; else - Con_TrySubPrint = pCon_SubPrint; + Con_TrySubPrint = confuncs->SubPrint; reloadconfig = true; IRC_InitCvars(); - if (BUILTINISVALID(Plug_GetNativePointer)) - piceapi = pPlug_GetNativePointer(ICE_API_CURRENT); - return true; } else { - pCon_Print("IRC Client Plugin failed\n"); + plugfuncs->Print("IRC Client Plugin failed\n"); } return false; } -qintptr_t IRC_ExecuteCommand(qintptr_t *args) +qboolean IRC_ExecuteCommand(qboolean isinsecure) { char cmd[256]; - pCmd_Argv(0, cmd, sizeof(cmd)); + cmdfuncs->Argv(0, cmd, sizeof(cmd)); if (!strcmp(cmd, COMMANDNAME)) { ircclient_t *ircclient = ircclients; char imsg[8192]; - pCmd_Args(imsg, sizeof(imsg)); + cmdfuncs->Args(imsg, sizeof(imsg)); //FIXME: select an irc network more inteligently IRC_Command(ircclient, ircclient?ircclient->defaultdest:"", imsg); return true; } return false; } -qintptr_t IRC_ConExecuteCommand(qintptr_t *args) +int IRC_ConExecuteCommand(qboolean isinsecure) { char buffer[256]; char imsg[8192]; ircclient_t *ircclient; //FIXME: select the right network - pCmd_Argv(0, buffer, sizeof(buffer)); - pCmd_Args(imsg, sizeof(imsg)); + cmdfuncs->Argv(0, buffer, sizeof(buffer)); + cmdfuncs->Args(imsg, sizeof(imsg)); //buffer is something like: irc53:#foo for (ircclient = ircclients; ircclient; ircclient = ircclient->next) @@ -576,7 +598,7 @@ static qboolean IRC_Establish(ircclient_t *irc) irc->bufferedinammount = 0; irc->quitting = false; - irc->socket = pNet_TCPConnect(irc->server, 6667); //port is only used if the url doesn't contain one. It's a default. + irc->socket = netfuncs->TCPConnect(irc->server, 6667); //port is only used if the url doesn't contain one. It's a default. //not yet blocking. So no frequent attempts please... //non blocking prevents connect from returning worthwhile sensible value. @@ -588,9 +610,9 @@ static qboolean IRC_Establish(ircclient_t *irc) if (irc->tlsmode == TLS_INITIAL) { - if (pNet_SetTLSClient(irc->socket, irc->server) < 0) + if (netfuncs->SetTLSClient(irc->socket, irc->server) < 0) { - pNet_Close(irc->socket); + netfuncs->Close(irc->socket); irc->socket = invalid_handle; return false; } @@ -614,14 +636,14 @@ static qboolean IRC_Establish(ircclient_t *irc) static void IRC_ParseConfig(void) { qhandle_t config; - int len = pFS_Open("**plugconfig", &config, 1); + int len = filefuncs->Open("**plugconfig", &config, 1); if (len >= 0) { char *buf = malloc(len+1); char *msg = buf; buf[len] = 0; - pFS_Read(config, buf, len); - pFS_Close(config); + filefuncs->Read(config, buf, len); + filefuncs->Close(config); while (msg && *msg) { @@ -668,7 +690,7 @@ static void IRC_WriteConfig(void) if (irc_config.value == 0) return; - pFS_Open("**plugconfig", &config, 2); + filefuncs->Open("**plugconfig", &config, 2); if (config >= 0) { ircclient_t *irc; @@ -677,10 +699,10 @@ static void IRC_WriteConfig(void) char *s = va("\"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", irc->server, irc->autochannels, irc->primarynick, irc->pwd, irc->realname, irc->hostname, irc->username); if (irc->quitting || !irc->persist) continue; - pFS_Write(config, s, strlen(s)); + filefuncs->Write(config, s, strlen(s)); } - pFS_Close(config); + filefuncs->Close(config); } } static void IRC_MakeDefault(ircclient_t *irc) @@ -1286,7 +1308,7 @@ static void numbered_command(int comm, char *msg, ircclient_t *irc) // move vars } case 670: /* RPL_STARTTLS */ { - pNet_SetTLSClient(irc->socket, irc->server); + netfuncs->SetTLSClient(irc->socket, irc->server); irc->tlsmode = TLS_START; irc->nicktries = 0; IRC_SetPass(irc, irc->pwd); @@ -1297,7 +1319,7 @@ static void numbered_command(int comm, char *msg, ircclient_t *irc) // move vars case 691: /* ERR_STARTTLS */ { IRC_Printf(irc, DEFAULTCONSOLE, COLOURYELLOW "STARTTLS Failed: %s\n", casevar[3]); - pNet_Close(irc->socket); + netfuncs->Close(irc->socket); irc->socket = invalid_handle; return; } @@ -1706,7 +1728,7 @@ static void IRC_ICE_Authorise(ircclient_t *irc, const char *with, enum iceproto_ IRC_Printf(irc, announce, "Connection is already terminated\n"); } -qintptr_t IRC_ConsoleLink(qintptr_t *args) +qboolean IRC_ConsoleLink(void) { ircclient_t *irc; char link[256]; @@ -1716,9 +1738,9 @@ qintptr_t IRC_ConsoleLink(qintptr_t *args) char whobuf[256]; char which[512]; enum iceproto_e type; -// pCmd_Argv(0, text, sizeof(text)); - pCmd_Argv(1, link, sizeof(link)); - pCmd_Argv(2, which, sizeof(which)); +// cmdfuncs->Argv(0, text, sizeof(text)); + cmdfuncs->Argv(1, link, sizeof(link)); + cmdfuncs->Argv(2, which, sizeof(which)); Plug_Info_ValueForKey(link, "act", what, sizeof(what)); who = Plug_Info_ValueForKey(link, "who", whobuf, sizeof(whobuf)); @@ -1863,7 +1885,7 @@ static int IRC_ClientFrame(ircclient_t *irc) int i = 1; - ret = pNet_Recv(irc->socket, irc->bufferedinmessage+irc->bufferedinammount, sizeof(irc->bufferedinmessage)-1 - irc->bufferedinammount); + ret = netfuncs->Recv(irc->socket, irc->bufferedinmessage+irc->bufferedinammount, sizeof(irc->bufferedinmessage)-1 - irc->bufferedinammount); if (ret == 0) { if (!irc->bufferedinammount) //if we are half way through a message, read any possible conjunctions. @@ -2037,8 +2059,8 @@ static int IRC_ClientFrame(ircclient_t *irc) //message takes the form :FROM PRIVMSG TO :MESSAGE - if (BUILTINISVALID(LocalSound)) - pLocalSound ("misc/talk.wav"); + if (drawfuncs) + drawfuncs->LocalSound ("misc/talk.wav", 256, 1); if ((!strcasecmp(var[4]+1, "\1VERSION\1")) && (!strncmp(var[2], "PRIVMSG ", 7))) { @@ -2087,7 +2109,8 @@ static int IRC_ClientFrame(ircclient_t *irc) *exc = '\0'; //a link to interact with the sender - Q_snprintf(link, sizeof(link), "^["COLOURGREEN"%s\\act\\user\\who\\%s^]", prefix, prefix); + if (Q_snprintf(link, sizeof(link), "^["COLOURGREEN"%s\\act\\user\\who\\%s^]", prefix, prefix) >= sizeof(link)) + Q_snprintf(link, sizeof(link), "%s", prefix); if (!strncmp(col, "\001", 1)) { @@ -2178,13 +2201,13 @@ static int IRC_ClientFrame(ircclient_t *irc) *exc = '\0'; //fixme: print this in all channels as appropriate. IRC_Printf(irc, DEFAULTCONSOLE, COLOURGREEN "%s changes name to %s\n", prefix, col+1); - if (BUILTINISVALID(Con_RenameSub)) + if (confuncs) { char oldname[256]; char newname[256]; Q_snprintf(oldname, sizeof(oldname), irc->id, prefix); Q_snprintf(newname, sizeof(newname), irc->id, col+1); - pCon_RenameSub(oldname, newname); //if we were pming to them, rename accordingly. + confuncs->RenameSub(oldname, newname); //if we were pming to them, rename accordingly. } } else IRC_Printf(irc, DEFAULTCONSOLE, COLOURGREEN ":%s%s\n", prefix, msg+6); @@ -2377,7 +2400,7 @@ static int IRC_ClientFrame(ircclient_t *irc) //functions above this line allow connections to multiple servers. //it is just the control functions that only allow one server. -qintptr_t IRC_Frame(qintptr_t *args) +void IRC_Frame(double realtime, double gametime) { ircclient_t *ircclient; if (reloadconfig) @@ -2395,7 +2418,7 @@ qintptr_t IRC_Frame(qintptr_t *args) stat = IRC_ClientFrame(ircclient); if (ircclient->bufferedoutammount) { - int flushed = pNet_Send(ircclient->socket, ircclient->bufferedoutmessage, ircclient->bufferedoutammount); //FIXME: This needs rewriting to cope with errors+throttle. + int flushed = netfuncs->Send(ircclient->socket, ircclient->bufferedoutmessage, ircclient->bufferedoutammount); //FIXME: This needs rewriting to cope with errors+throttle. if (flushed > 0) { memmove(ircclient->bufferedoutmessage, ircclient->bufferedoutmessage+flushed, ircclient->bufferedoutammount - flushed); @@ -2407,7 +2430,7 @@ qintptr_t IRC_Frame(qintptr_t *args) stat = IRC_KILL; if (stat == IRC_KILL) { - pNet_Close(ircclient->socket); + netfuncs->Close(ircclient->socket); ircclient->socket = invalid_handle; IRC_Printf(ircclient, DEFAULTCONSOLE, "Disconnected from irc\n^[[Reconnect]\\act\\reconnect^]\n"); break; //lazy @@ -2415,7 +2438,6 @@ qintptr_t IRC_Frame(qintptr_t *args) else IRC_ICE_Frame(ircclient); } - return 0; } void IRC_Command(ircclient_t *ircclient, char *dest, char *args) @@ -2458,7 +2480,7 @@ void IRC_Command(ircclient_t *ircclient, char *dest, char *args) if (!*nick) Q_strlcpy(nick, irc_nick.string, sizeof(nick)); if (!*nick) - pCvar_GetString("name", nick, sizeof(nick)); + cvarfuncs->GetString("name", nick, sizeof(nick)); ircclient = IRC_FindAccount(server); if (ircclient) @@ -2497,7 +2519,7 @@ void IRC_Command(ircclient_t *ircclient, char *dest, char *args) { msg = COM_Parse(msg, token, sizeof(token)); if (!ircclient) //not yet connected. - pCvar_SetString(irc_nick.name, token); + cvarfuncs->SetString(irc_nick.name, token); else { if (!handleisvalid(ircclient->socket)) @@ -2511,7 +2533,7 @@ void IRC_Command(ircclient_t *ircclient, char *dest, char *args) else if (!strcmp(token+1, "user")) { msg = COM_Parse(msg, token, sizeof(token)); - pCvar_SetString(irc_username.name, token); + cvarfuncs->SetString(irc_username.name, token); if (ircclient) IRC_SetUser(ircclient, token); diff --git a/plugins/jabber/Makefile b/plugins/jabber/Makefile deleted file mode 100644 index d8399f699..000000000 --- a/plugins/jabber/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -LCC_FLAGS=-DQ3_VM -S -Wf-target=bytecode -Wf-g - -qvm: - lcc $(LCC_FLAGS) jabberclient.c; lcc $(LCC_FLAGS) ../memory.c; lcc $(LCC_FLAGS) ../plugin.c; lcc $(LCC_FLAGS) ../qvm_api.c; q3asm -f jabbercl -clean: - rm -rf $(OBJECTS) $(OUTFILE) *.qvm *.asm - -all: native - -native: - gcc -shared -fPIC -ggdb jabberclient.c ../qvm_api.c ../plugin.c -o jabberx86.so - -install: native - cp jabberx86.so /opt/quake/fte/plugins/ - diff --git a/plugins/jabber/compile.bat b/plugins/jabber/compile.bat deleted file mode 100644 index be044a22c..000000000 --- a/plugins/jabber/compile.bat +++ /dev/null @@ -1,22 +0,0 @@ -@echo off -call ..\paths.bat - -del vm\*.asm -rmdir vm -mkdir vm -cd vm -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../jabberclient.c -if errorlevel 1 goto end -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../memory.c -if errorlevel 1 goto end -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../plugin.c -if errorlevel 1 goto end -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../qvm_api.c -if errorlevel 1 goto end -q3asm -f ../jabbercl - -:end - -cd .. - -pause \ No newline at end of file diff --git a/plugins/jabber/jabberclient.c b/plugins/jabber/jabberclient.c index 540e18aa6..1c5fc3758 100644 --- a/plugins/jabber/jabberclient.c +++ b/plugins/jabber/jabberclient.c @@ -56,9 +56,19 @@ client compat: otherwise works. */ -#include "../plugin.h" -#include #include "xmpp.h" +#include + +static plugsubconsolefuncs_t *confuncs; +static plug2dfuncs_t *drawfuncs; //needed for avatars. +plugnetfuncs_t *netfuncs; +plugfsfuncs_t *filefuncs; +static plugclientfuncs_t *clientfuncs; //for more accurate presence info. +static struct +{ + int width; + int height; +} pvid; //#define USE_GOOGLE_MAIL_NOTIFY @@ -72,11 +82,11 @@ client compat: #ifdef JINGLE icefuncs_t *piceapi; #endif -qboolean jclient_needreadconfig; -qboolean jclient_updatebuddylist; -jclient_t *jclient_action_cl; -buddy_t *jclient_action_buddy; -enum +static qboolean jclient_needreadconfig; +static qboolean jclient_updatebuddylist; +static jclient_t *jclient_action_cl; +static buddy_t *jclient_action_buddy; +static enum { ACT_NONE, ACT_OAUTH, @@ -101,13 +111,13 @@ enum #define Q_strncpyz(o, i, l) do {strncpy(o, i, l-1);o[l-1]='\0';}while(0) -void (*Con_TrySubPrint)(const char *conname, const char *message); -void Fallback_ConPrint(const char *conname, const char *message) +static qboolean (*Con_TrySubPrint)(const char *conname, const char *message); +qboolean Fallback_ConPrint(const char *conname, const char *message) { - pCon_Print(message); + plugfuncs->Print(message); + return true; } -void XMPP_ConversationPrintf(const char *context, const char *title, char *format, ...); void Con_SubPrintf(const char *subname, const char *format, ...) { va_list argptr; @@ -698,10 +708,10 @@ qboolean NET_DNSLookup_SRV(const char *host, char *out, int outlen) #endif -char base64[((4096+3)*4/3)+1]; -unsigned int base64_len; //current output length -unsigned int base64_cur; //current pending value -unsigned int base64_bits;//current pending bits +static char base64[((4096+3)*4/3)+1]; +static unsigned int base64_len; //current output length +static unsigned int base64_cur; //current pending value +static unsigned int base64_bits;//current pending bits char Base64_From64(int byt) { if (byt >= 0 && byt < 26) @@ -737,7 +747,7 @@ void Base64_Byte(unsigned int byt) void Base64_Add(const char *s, int len) { - unsigned char *us = (unsigned char *)s; + const unsigned char *us = (const unsigned char *)s; while(len-->0) Base64_Byte(*us++); } @@ -839,7 +849,7 @@ void JCL_Command(int accid, char *consolename); void JCL_LoadConfig(void); void JCL_WriteConfig(void); -struct { +static struct { char *names; unsigned int cap; } capnames[] = @@ -856,92 +866,85 @@ struct { {NULL} }; - -qintptr_t JCL_ExecuteCommand(qintptr_t *args) +qboolean JCL_ExecuteCommand(qboolean isinsecure) { char cmd[256]; - pCmd_Argv(0, cmd, sizeof(cmd)); + cmdfuncs->Argv(0, cmd, sizeof(cmd)); if (!strcmp(cmd, COMMANDPREFIX) || !strcmp(cmd, COMMANDPREFIX2) || !strcmp(cmd, COMMANDPREFIX3)) { - if (!args[0] || pCmd_Argc() == 1) + if (!isinsecure || cmdfuncs->Argc() == 1) JCL_Command(0, ""); return true; } if (!strncmp(cmd, COMMANDPREFIX, strlen(COMMANDPREFIX))) { - if (!args[0] || pCmd_Argc() == 1) + if (!isinsecure || cmdfuncs->Argc() == 1) JCL_Command(atoi(cmd+strlen(COMMANDPREFIX)), ""); return true; } return false; } -qintptr_t JCL_ConsoleLink(qintptr_t *args); -qintptr_t JCL_ConsoleLinkMouseOver(qintptr_t *args); -qintptr_t JCL_ConExecuteCommand(qintptr_t *args); +qboolean JCL_ConsoleLink(void); +qboolean JCL_ConsoleLinkMouseOver(float x, float y); +int JCL_ConExecuteCommand(qboolean isinsecure); -qintptr_t JCL_Frame(qintptr_t *args); -qintptr_t JCL_Shutdown(qintptr_t *args); +void JCL_Frame(double realtime, double gametime); +void JCL_Shutdown(void); -static qintptr_t QDECL JCL_UpdateVideo(qintptr_t *args) +static void QDECL JCL_UpdateVideo(int width, int height) { - pvid.width = args[0]; - pvid.height = args[1]; + pvid.width = width; + pvid.height = height; //FIXME: clear/reload images. - - return true; } -qintptr_t Plug_Init(qintptr_t *args) +qboolean Plug_Init(void) { jclient_needreadconfig = true; - if ( Plug_Export("Tick", JCL_Frame) && - Plug_Export("Shutdown", JCL_Shutdown) && - Plug_Export("ExecuteCommand", JCL_ExecuteCommand)) + if (plugfuncs->ExportFunction("Tick", JCL_Frame) && + plugfuncs->ExportFunction("Shutdown", JCL_Shutdown) && + plugfuncs->ExportFunction("ExecuteCommand", JCL_ExecuteCommand)) { - if (!BUILTINISVALID(Net_SetTLSClient)) - Con_Printf("XMPP Plugin Loaded ^1without^7 TLS\n"); //most servers REQUIRE tls now - else - Con_Printf("XMPP Plugin Loaded. For help, use: ^[/"COMMANDPREFIX" /help^]\n"); + Con_Printf("XMPP Plugin Loaded. For help, use: ^[/"COMMANDPREFIX" /help^]\n"); - Plug_Export("UpdateVideo", JCL_UpdateVideo); - Plug_Export("ConsoleLink", JCL_ConsoleLink); - Plug_Export("ConsoleLinkMouseOver", JCL_ConsoleLinkMouseOver); + plugfuncs->ExportFunction("UpdateVideo", JCL_UpdateVideo); + plugfuncs->ExportFunction("ConsoleLink", JCL_ConsoleLink); + plugfuncs->ExportFunction("ConsoleLinkMouseOver", JCL_ConsoleLinkMouseOver); - if (!Plug_Export("ConExecuteCommand", JCL_ConExecuteCommand)) + if (!plugfuncs->ExportFunction("ConExecuteCommand", JCL_ConExecuteCommand)) { Con_Printf("XMPP plugin in single-console mode\n"); Con_TrySubPrint = Fallback_ConPrint; } else - Con_TrySubPrint = pCon_SubPrint; + Con_TrySubPrint = confuncs->SubPrint; - pCmd_AddCommand(COMMANDPREFIX); - pCmd_AddCommand(COMMANDPREFIX2); - pCmd_AddCommand(COMMANDPREFIX3); + cmdfuncs->AddCommand(COMMANDPREFIX); + cmdfuncs->AddCommand(COMMANDPREFIX2); + cmdfuncs->AddCommand(COMMANDPREFIX3); - pCmd_AddCommand(COMMANDPREFIX"0"); - pCmd_AddCommand(COMMANDPREFIX"1"); - pCmd_AddCommand(COMMANDPREFIX"2"); - pCmd_AddCommand(COMMANDPREFIX"3"); - pCmd_AddCommand(COMMANDPREFIX"4"); - pCmd_AddCommand(COMMANDPREFIX"5"); - pCmd_AddCommand(COMMANDPREFIX"6"); - pCmd_AddCommand(COMMANDPREFIX"7"); + cmdfuncs->AddCommand(COMMANDPREFIX"0"); + cmdfuncs->AddCommand(COMMANDPREFIX"1"); + cmdfuncs->AddCommand(COMMANDPREFIX"2"); + cmdfuncs->AddCommand(COMMANDPREFIX"3"); + cmdfuncs->AddCommand(COMMANDPREFIX"4"); + cmdfuncs->AddCommand(COMMANDPREFIX"5"); + cmdfuncs->AddCommand(COMMANDPREFIX"6"); + cmdfuncs->AddCommand(COMMANDPREFIX"7"); //flags&1 == archive - pCvar_Register("xmpp_nostatus", "0", 0, "xmpp"); - pCvar_Register("xmpp_showstatusupdates", "0", 0, "xmpp"); - pCvar_Register("xmpp_autoacceptjoins", "0", 0, "xmpp"); - pCvar_Register("xmpp_autoacceptinvites", "0", 0, "xmpp"); - pCvar_Register("xmpp_autoacceptvoice", "0", 0, "xmpp"); - pCvar_Register("xmpp_debug", "0", 0, "xmpp"); + cvarfuncs->Register("xmpp_nostatus", "0", 0, "xmpp"); + cvarfuncs->Register("xmpp_showstatusupdates", "0", 0, "xmpp"); + cvarfuncs->Register("xmpp_autoacceptjoins", "0", 0, "xmpp"); + cvarfuncs->Register("xmpp_autoacceptinvites", "0", 0, "xmpp"); + cvarfuncs->Register("xmpp_autoacceptvoice", "0", 0, "xmpp"); + cvarfuncs->Register("xmpp_debug", "0", 0, "xmpp"); #ifdef JINGLE - if (BUILTINISVALID(Plug_GetNativePointer)) - piceapi = pPlug_GetNativePointer(ICE_API_CURRENT); + piceapi = plugfuncs->GetEngineInterface(ICE_API_CURRENT, sizeof(*piceapi)); #endif return 1; @@ -964,9 +967,9 @@ qintptr_t Plug_Init(qintptr_t *args) //meaning \0s are valid. //but never used cos it breaks strings -jclient_t *jclients[8]; -int jclient_curtime; -int jclient_poketime; +static jclient_t *jclients[8]; +static int jclient_curtime; +static int jclient_poketime; typedef struct saslmethod_s { @@ -1106,17 +1109,20 @@ static int sasl_digestmd5_challenge(struct sasl_ctx_s *ctx, char *in, int inlen, if (!*realm) Q_strlcpy(realm, ctx->domain, sizeof(realm)); - Q_snprintf(digesturi, sizeof(digesturi), "xmpp/%s", realm); + if (Q_snprintf(digesturi, sizeof(digesturi), "xmpp/%s", realm) >= sizeof(digesturi)) + return -1; - Q_snprintf(X, sizeof(X), "%s:%s:", username, realm); + if (Q_snprintf(X, sizeof(X), "%s:%s:", username, realm) >= sizeof(X)) + return -1; if (ctx->password_hash_size == 16 && !strcmp(X, ctx->password_validity)) memcpy(Y, ctx->password_hash, 16); //use the hashed password, instead of the (missing) plain one else if (*ctx->password_plain) { Q_strlcpy(ctx->password_validity, X, sizeof(ctx->password_validity)); - Q_snprintf(X, sizeof(X), "%s:%s:%s", username, realm, ctx->password_plain); + if (Q_snprintf(X, sizeof(X), "%s:%s:%s", username, realm, ctx->password_plain) < sizeof(X)) + return -1; MD5_ToBinary(X, strlen(X), Y, sizeof(Y)); ctx->password_hash_size = 16; @@ -1127,13 +1133,21 @@ static int sasl_digestmd5_challenge(struct sasl_ctx_s *ctx, char *in, int inlen, memcpy(A1, Y, 16); if (*authzid) - Q_snprintf(A1+16, sizeof(A1)-16, ":%s:%s:%s", nonce, cnonce, authzid); + { + if (Q_snprintf(A1+16, sizeof(A1)-16, ":%s:%s:%s", nonce, cnonce, authzid) >= sizeof(A1)-16) + return -1; + } else - Q_snprintf(A1+16, sizeof(A1)-16, ":%s:%s", nonce, cnonce); - Q_snprintf(A2, sizeof(A2), "%s:%s", "AUTHENTICATE", digesturi); + { + if (Q_snprintf(A1+16, sizeof(A1)-16, ":%s:%s", nonce, cnonce) >= sizeof(A1)-16) + return -1; + } + if (Q_snprintf(A2, sizeof(A2), "%s:%s", "AUTHENTICATE", digesturi) >= sizeof(A2)) + return -1; MD5_ToHex(A1, strlen(A1+16)+16, HA1, sizeof(HA1)); MD5_ToHex(A2, strlen(A2), HA2, sizeof(HA2)); - Q_snprintf(KD, sizeof(KD), "%s:%s:%s:%s:%s:%s", HA1, nonce, nc, cnonce, qop, HA2); + if (Q_snprintf(KD, sizeof(KD), "%s:%s:%s:%s:%s:%s", HA1, nonce, nc, cnonce, qop, HA2) >= sizeof(KD)) + return -1; MD5_ToHex(KD, strlen(KD), Z, sizeof(Z)); if (*authzid) @@ -1167,8 +1181,8 @@ static int sasl_scram_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize, ha if (ctx->issecure) { bindingdata.len = sizeof(bindingdata.buf); - if (BUILTINISVALID(Net_GetTLSBinding)) - bs = pNet_GetTLSBinding(ctx->socket, bindingdata.buf, &bindingdata.len); + if (netfuncs) + bs = netfuncs->GetTLSBinding(ctx->socket, bindingdata.buf, &bindingdata.len); else bs = -1; } @@ -1199,7 +1213,7 @@ static int sasl_scram_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize, ha //FIXME: this should be more random, to validate that the server actually knows our password too //we can't really do anything until we've already signed in, so why bother? - t = pSys_Milliseconds(); + t = plugfuncs->GetMilliseconds(); Base64_Add((void*)&t, sizeof(t)); Base64_Add("0123456789abcdef", 16); Base64_Add((void*)&jclient_curtime, sizeof(jclient_curtime)); @@ -1475,19 +1489,22 @@ static int sasl_oauth2_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize) host, (unsigned)strlen(body)); - sock = pNet_TCPConnect(host, 443); - pNet_SetTLSClient(sock, host); - pNet_Send(sock, header, strlen(header)); - pNet_Send(sock, body, strlen(body)); - while(1) + sock = netfuncs->TCPConnect(host, 443); + if (netfuncs->SetTLSClient(sock, host) >= 0) { - l = pNet_Recv(sock, result+rl, sizeof(result)-rl); - if (l < 0) - break; - else - rl += l; + netfuncs->Send(sock, header, strlen(header)); + netfuncs->Send(sock, body, strlen(body)); + while(1) + { + //FIXME: infinite loop! + l = netfuncs->Recv(sock, result+rl, sizeof(result)-rl); + if (l < 0) + break; + else + rl += l; + } } - pNet_Close(sock); + netfuncs->Close(sock); result[rl] = 0; Con_Printf("Got %s\n", result); @@ -1549,20 +1566,23 @@ static int sasl_oauth2_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize) resource, host, (unsigned)strlen(body)); Con_Printf("XMPP: Requesting access token\n"); - sock = pNet_TCPConnect(host, 443); - pNet_SetTLSClient(sock, host); - pNet_Send(sock, header, strlen(header)); - pNet_Send(sock, body, strlen(body)); - while(1) + sock = netfuncs->TCPConnect(host, 443); + if (netfuncs->SetTLSClient(sock, host) >= 0) { - l = pNet_Recv(sock, result+rl, sizeof(result)-rl); - if (l < 0) - break; - else - rl += l; + netfuncs->Send(sock, header, strlen(header)); + netfuncs->Send(sock, body, strlen(body)); + while(1) + { + //FIXME: infinite loop! + l = netfuncs->Recv(sock, result+rl, sizeof(result)-rl); + if (l < 0) + break; + else + rl += l; + } } result[rl] = 0; - pNet_Close(sock); + netfuncs->Close(sock); //should contain something like: //{ @@ -1621,19 +1641,22 @@ static int sasl_oauth2_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize) resource, host, (unsigned)strlen(body)); Con_Printf("XMPP: Refreshing access token\n"); - sock = pNet_TCPConnect(host, 443); - pNet_SetTLSClient(sock, host); - pNet_Send(sock, header, strlen(header)); - pNet_Send(sock, body, strlen(body)); - while(1) + sock = netfuncs->TCPConnect(host, 443); + if (netfuncs->SetTLSClient(sock, host) >= 0) { - l = pNet_Recv(sock, result+rl, sizeof(result)-rl); - if (l < 0) - break; - else - rl += l; + netfuncs->Send(sock, header, strlen(header)); + netfuncs->Send(sock, body, strlen(body)); + while(1) + { + //FIXME: infinite loop! + l = netfuncs->Recv(sock, result+rl, sizeof(result)-rl); + if (l < 0) + break; + else + rl += l; + } } - pNet_Close(sock); + netfuncs->Close(sock); result[rl] = 0; l = strstr(result, "\r\n\r\n")-result; @@ -1684,7 +1707,7 @@ static int sasl_oauth2_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize) } //in descending priority order -saslmethod_t saslmethods[] = +static saslmethod_t saslmethods[] = { // {"SCRAM-SHA-512-PLUS", sasl_scramsha512plus_initial, sasl_scram_challenge, sasl_scram_final}, //lots of unreadable hashing, with added channel bindings // {"SCRAM-SHA-256-PLUS", sasl_scramsha256plus_initial, sasl_scram_challenge, sasl_scram_final}, //lots of unreadable hashing, with added channel bindings @@ -1784,7 +1807,7 @@ char *TrimResourceFromJid(char *jid) return NULL; } -qintptr_t JCL_ConsoleLinkMouseOver(qintptr_t *args) +qboolean JCL_ConsoleLinkMouseOver(float x, float y) { jclient_t *jcl; // char text[256]; @@ -1796,11 +1819,9 @@ qintptr_t JCL_ConsoleLinkMouseOver(qintptr_t *args) int i; buddy_t *b, *me = NULL; bresource_t *br; - float x = *(float*)&args[0]; - float y = *(float*)&args[1]; -// pCmd_Argv(0, text, sizeof(text)); - pCmd_Argv(1, link, sizeof(link)); +// cmdfuncs->Argv(0, text, sizeof(text)); + cmdfuncs->Argv(1, link, sizeof(link)); JCL_Info_ValueForKey(link, "xmpp", who, sizeof(who)); JCL_Info_ValueForKey(link, "xmppact", what, sizeof(what)); @@ -1820,7 +1841,7 @@ qintptr_t JCL_ConsoleLinkMouseOver(qintptr_t *args) if (jcl->status != JCL_ACTIVE) { - pDraw_String(x, y, "^&C0You are currently offline"); + drawfuncs->String(x, y, "^&C0You are currently offline"); return true; } @@ -1860,7 +1881,7 @@ qintptr_t JCL_ConsoleLinkMouseOver(qintptr_t *args) return false; JCL_FindBuddy(jcl, jcl->fulljid, &me, NULL, true); - if ((jcl->enabledcapabilities & CAP_AVATARS) && BUILTINISVALID(Draw_LoadImageData)) + if ((jcl->enabledcapabilities & CAP_AVATARS) && drawfuncs) { if (b->vcardphotochanged && b->friended && !jcl->avatarupdate) { @@ -1874,29 +1895,29 @@ qintptr_t JCL_ConsoleLinkMouseOver(qintptr_t *args) //96 just feels far too large for a game that was origionally running at a resolution of 320*200. //FIXME: we should proably respect the image's aspect ratio... #define IMGSIZE 96/2 - pDraw_Image (x, y, IMGSIZE, IMGSIZE, 0, 0, 1, 1, b->image); + drawfuncs->Image (x, y, IMGSIZE, IMGSIZE, 0, 0, 1, 1, b->image); x += IMGSIZE+8; } } - pDraw_String(x, y, va("^&F0%s ^2%s", actiontext, b->name)); + drawfuncs->String(x, y, va("^&F0%s ^2%s", actiontext, b->name)); y+=8; - pDraw_String(x, y, va("^&F0%s", b->accountdomain)); + drawfuncs->String(x, y, va("^&F0%s", b->accountdomain)); y+=8; if (br) { - pDraw_String(x, y, va("^&F0 %s", br->resource)); + drawfuncs->String(x, y, va("^&F0 %s", br->resource)); y+=8; } if (b == me) - pDraw_String(x, y, "^&90" "You"); + drawfuncs->String(x, y, "^&90" "You"); else if (!b->friended) - pDraw_String(x, y, "^&C0" "Unknown"); + drawfuncs->String(x, y, "^&C0" "Unknown"); y+=8; return true; } -qintptr_t JCL_ConsoleLink(qintptr_t *args) +qboolean JCL_ConsoleLink(void) { jclient_t *jcl; char link[256]; @@ -1905,8 +1926,8 @@ qintptr_t JCL_ConsoleLink(qintptr_t *args) char which[256]; int i; buddy_t *b = NULL; -// pCmd_Argv(0, text, sizeof(text)); - pCmd_Argv(1, link, sizeof(link)); +// cmdfuncs->Argv(0, text, sizeof(text)); + cmdfuncs->Argv(1, link, sizeof(link)); JCL_Info_ValueForKey(link, "xmpp", who, sizeof(who)); JCL_Info_ValueForKey(link, "xmppact", what, sizeof(what)); @@ -2009,8 +2030,8 @@ qintptr_t JCL_ConsoleLink(qintptr_t *args) { if (jcl) { - pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); - pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter your friend's account name"); + confuncs->SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); + confuncs->SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter your friend's account name"); jclient_action_cl = jcl; jclient_action_buddy = NULL; jclient_action = ACT_ADDFRIEND; @@ -2046,48 +2067,48 @@ qintptr_t JCL_ConsoleLink(qintptr_t *args) } else if (!strcmp(what, "newaccount")) { - pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); - pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter your XMPP account name\neg: example@"EXAMPLEDOMAIN); + confuncs->SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); + confuncs->SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter your XMPP account name\neg: example@"EXAMPLEDOMAIN); jclient_action_cl = jcl; jclient_action_buddy = NULL; jclient_action = ACT_NEWACCOUNT; } else if (!strcmp(what, "setausername")) { - pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); - pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter your user name"); + confuncs->SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); + confuncs->SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter your user name"); jclient_action_cl = jcl; jclient_action_buddy = NULL; jclient_action = ACT_SETAUSERNAME; } else if (!strcmp(what, "setadomain")) { - pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); - pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter the domain for which your account is valid"); + confuncs->SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); + confuncs->SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter the domain for which your account is valid"); jclient_action_cl = jcl; jclient_action_buddy = NULL; jclient_action = ACT_SETADOMAIN; } else if (!strcmp(what, "setaserver")) { - pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); - pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter the server to connect to."); + confuncs->SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); + confuncs->SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter the server to connect to."); jclient_action_cl = jcl; jclient_action_buddy = NULL; jclient_action = ACT_SETASERVER; } else if (!strcmp(what, "setaresource")) { - pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); - pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter some resource name."); + confuncs->SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); + confuncs->SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter some resource name."); jclient_action_cl = jcl; jclient_action_buddy = NULL; jclient_action = ACT_SETARESOURCE; } else if (!strcmp(what, "setapassword")) { - pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); - pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter your XMPP account name\neg: example@"EXAMPLEDOMAIN); + confuncs->SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); + confuncs->SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter your XMPP account name\neg: example@"EXAMPLEDOMAIN); jclient_action_cl = jcl; jclient_action_buddy = NULL; jclient_action = ACT_SETAPASSWORD; @@ -2153,7 +2174,7 @@ qintptr_t JCL_ConsoleLink(qintptr_t *args) Q_strlcat(footer, link, sizeof(footer)); } - pCon_SetConsoleString(BUDDYLISTTITLE, "footer", footer); + confuncs->SetConsoleString(BUDDYLISTTITLE, "footer", footer); } } else if (!strcmp(what, "buddyopts")) @@ -2179,7 +2200,7 @@ qintptr_t JCL_ConsoleLink(qintptr_t *args) } Q_snprintf(footer, sizeof(footer), "\n%s\n%s\n%s", chatlink, unfriend, realias); - pCon_SetConsoleString(BUDDYLISTTITLE, "footer", footer); + confuncs->SetConsoleString(BUDDYLISTTITLE, "footer", footer); } } else if (!strcmp(what, "unfriend")) @@ -2217,8 +2238,8 @@ qintptr_t JCL_ConsoleLink(qintptr_t *args) JCL_FindBuddy(jcl, *who?who:jcl->defaultdest, &b, NULL, false); if (b) { - pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); - pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter what you want to see them as"); + confuncs->SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); + confuncs->SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter what you want to see them as"); jclient_action_cl = jcl; jclient_action_buddy = b; jclient_action = ACT_SETBALIAS; @@ -2238,18 +2259,16 @@ qintptr_t JCL_ConsoleLink(qintptr_t *args) if (b->btype != BT_CHATROOM) b->defaultresource = br; - if (BUILTINISVALID(Con_SetConsoleFloat)) + if (confuncs) { - pCon_SetConsoleString(f, "title", b->name); - pCon_SetConsoleFloat(f, "iswindow", true); - pCon_SetConsoleFloat(f, "forceutf8", true); - pCon_SetConsoleFloat(f, "wnd_w", 256); - pCon_SetConsoleFloat(f, "wnd_h", 320); + confuncs->SetConsoleString(f, "title", b->name); + confuncs->SetConsoleFloat(f, "iswindow", true); + confuncs->SetConsoleFloat(f, "forceutf8", true); + confuncs->SetConsoleFloat(f, "wnd_w", 256); + confuncs->SetConsoleFloat(f, "wnd_h", 320); } - else if (BUILTINISVALID(Con_SubPrint)) - pCon_SubPrint(f, ""); - if (BUILTINISVALID(Con_SetActive)) - pCon_SetActive(f); + if (confuncs) + confuncs->SetActive(f); } } return true; @@ -2347,21 +2366,21 @@ void XMPP_AddFriend(jclient_t *jcl, const char *account, const char *nick) JCL_AddClientMessagef(jcl, "", jid); } jclient_t *JCL_Connect(int accnum, char *server, int forcetls, char *account, char *password); -qintptr_t JCL_ConExecuteCommand(qintptr_t *args) +int JCL_ConExecuteCommand(qboolean isinsecure) { buddy_t *b; char consolename[256]; jclient_t *jcl; int i; - pCmd_Argv(0, consolename, sizeof(consolename)); + cmdfuncs->Argv(0, consolename, sizeof(consolename)); if (!strcmp(consolename, BUDDYLISTTITLE)) { char args[512]; - pCmd_Args(args, sizeof(args)); - pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", false); - pCon_SetConsoleString(BUDDYLISTTITLE, "footer", ""); + cmdfuncs->Args(args, sizeof(args)); + confuncs->SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", false); + confuncs->SetConsoleString(BUDDYLISTTITLE, "footer", ""); jclient_updatebuddylist = true; //FIXME: validate that the client is still active. @@ -2386,18 +2405,18 @@ qintptr_t JCL_ConExecuteCommand(qintptr_t *args) { if (jclients[i]) continue; - jclients[i] = JCL_Connect(i, "", BUILTINISVALID(Net_SetTLSClient)?1:0, args, ""); + jclients[i] = JCL_Connect(i, "", 1, args, ""); break; } if (i == sizeof(jclients)/sizeof(jclients[0])) - pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Too many accounts open"); + confuncs->SetConsoleString(BUDDYLISTTITLE, "footer", "Too many accounts open"); else if (!jclients[i]) - pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Unable to create account"); + confuncs->SetConsoleString(BUDDYLISTTITLE, "footer", "Unable to create account"); else { //now ask for a password instantly. because oauth2 is basically unusable. jclients[i]->status = JCL_INACTIVE; - pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); - pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter password"); + confuncs->SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); + confuncs->SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter password"); jclient_action_cl = jclients[i]; jclient_action_buddy = NULL; jclient_action = ACT_SETAPASSWORD; @@ -2434,8 +2453,8 @@ qintptr_t JCL_ConExecuteCommand(qintptr_t *args) Q_strncpyz(jclient_action_buddy->name, args, sizeof(jclient_action_buddy->name)); if (jclient_action_buddy->btype == BT_ROSTER) JCL_SendIQf(jclient_action_cl, NULL, "set", NULL, "", jclient_action_buddy->accountdomain, jclient_action_buddy->name); - if (BUILTINISVALID(Con_SetConsoleString)) - pCon_SetConsoleString(jclient_action_buddy->accountdomain, "title", jclient_action_buddy->name); + if (confuncs) + confuncs->SetConsoleString(jclient_action_buddy->accountdomain, "title", jclient_action_buddy->name); break; } jclient_action = ACT_NONE; @@ -2479,7 +2498,7 @@ void JCL_FlushOutgoing(jclient_t *jcl) if (!jcl || !jcl->outbuflen || jcl->socket == -1) return; - sent = pNet_Send(jcl->socket, jcl->outbuf + jcl->outbufpos, jcl->outbuflen); //FIXME: This needs rewriting to cope with errors. + sent = netfuncs->Send(jcl->socket, jcl->outbuf + jcl->outbufpos, jcl->outbuflen); //FIXME: This needs rewriting to cope with errors. if (sent > 0) { //and print it on some subconsole if we're debugging @@ -2487,7 +2506,7 @@ void JCL_FlushOutgoing(jclient_t *jcl) { char t = jcl->outbuf[jcl->outbufpos+sent]; jcl->outbuf[jcl->outbufpos+sent] = 0; - XMPP_ConversationPrintf("xmppout", "xmppout", "^3%s\n", jcl->outbuf + jcl->outbufpos); + XMPP_ConversationPrintf("xmppout", "xmppout", false, "^3%s\n", jcl->outbuf + jcl->outbufpos); jcl->outbuf[jcl->outbufpos+sent] = t; } @@ -2578,23 +2597,22 @@ qboolean JCL_Reconnect(jclient_t *jcl) //jcl->tlsconnect requires an explicit hostname, so should not be able to take this path. char srv[256]; char srvserver[256]; - Q_snprintf(srv, sizeof(srv), "_xmpp-client._tcp.%s", jcl->domain); - if (NET_DNSLookup_SRV(srv, srvserver, sizeof(srvserver))) + if (Q_snprintf(srv, sizeof(srv), "_xmpp-client._tcp.%s", jcl->domain) < sizeof(srv) && NET_DNSLookup_SRV(srv, srvserver, sizeof(srvserver))) { Con_DPrintf("XMPP: Trying to connect to %s (%s)\n", jcl->domain, srvserver); - jcl->socket = pNet_TCPConnect(srvserver, jcl->serverport); //port is should already be part of the srvserver name + jcl->socket = netfuncs->TCPConnect(srvserver, jcl->serverport); //port is should already be part of the srvserver name } else { //SRV lookup failed. attempt to just use the domain directly. Con_DPrintf("XMPP: Trying to connect to %s\n", jcl->domain); - jcl->socket = pNet_TCPConnect(jcl->domain, jcl->serverport); //port is only used if the url doesn't contain one. It's a default. + jcl->socket = netfuncs->TCPConnect(jcl->domain, jcl->serverport); //port is only used if the url doesn't contain one. It's a default. } } else { Con_DPrintf("XMPP: Trying to connect to %s\n", jcl->domain); - jcl->socket = pNet_TCPConnect(serveraddr, jcl->serverport); //port is only used if the url doesn't contain one. It's a default. + jcl->socket = netfuncs->TCPConnect(serveraddr, jcl->serverport); //port is only used if the url doesn't contain one. It's a default. } //not yet blocking. So no frequent attempts please... @@ -2607,7 +2625,7 @@ qboolean JCL_Reconnect(jclient_t *jcl) jcl->issecure = false; if (jcl->forcetls==2) - if (pNet_SetTLSClient(jcl->socket, jcl->certificatedomain)>=0) + if (netfuncs->SetTLSClient(jcl->socket, jcl->certificatedomain)>=0) jcl->issecure = true; jcl->status = JCL_AUTHING; @@ -2694,7 +2712,7 @@ jclient_t *JCL_ConnectXML(xmltree_t *acc) jclient_t *jcl; xmltree_t *oauth2; xmltree_t *features; - char oauthname[256]; + char oauthname[512]; struct buddyinfo_s *bi; int bn; @@ -2747,7 +2765,7 @@ jclient_t *JCL_ConnectXML(xmltree_t *acc) if (!*jcl->resource) { //the default resource matches the game that they're trying to play. char gamename[64], *res, *o; - if (pCvar_GetString("fs_gamename", gamename, sizeof(gamename))) + if (cvarfuncs->GetString("fs_gamename", gamename, sizeof(gamename))) { //strip out any weird chars (namely whitespace) for (o = gamename, res = gamename; *res; ) @@ -2881,7 +2899,7 @@ jclient_t *JCL_Connect(int accnum, char *server, int forcetls, char *account, ch if (!res || !*res) { //the default resource matches the game that they're trying to play. - if (pCvar_GetString("fs_gamename", gamename, sizeof(gamename))) + if (cvarfuncs->GetString("fs_gamename", gamename, sizeof(gamename))) { //strip out any weird chars (namely whitespace) char *o; @@ -2896,6 +2914,7 @@ jclient_t *JCL_Connect(int accnum, char *server, int forcetls, char *account, ch } } +/* if (forcetls>0) { if (!BUILTINISVALID(Net_SetTLSClient)) @@ -2904,6 +2923,7 @@ jclient_t *JCL_Connect(int accnum, char *server, int forcetls, char *account, ch return NULL; } } +*/ domain = strchr(account, '@'); if (domain) @@ -2965,7 +2985,7 @@ void JCL_ForgetBuddy(jclient_t *jcl, buddy_t *buddy, bresource_t *bres) JCL_ForgetBuddyResource(jcl, b, bres); if (jclient_action_buddy == b) { - pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", false); + confuncs->SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", false); jclient_action = ACT_NONE; jclient_action_buddy = NULL; jclient_action_cl = NULL; @@ -2987,7 +3007,7 @@ struct stringprep_range unsigned int cp_max; unsigned int remap[2]; }; -struct stringprep_range stringprep_A1[] = +static struct stringprep_range stringprep_A1[] = { {0x0234,0x024F}, {0x02AE,0x02AF}, @@ -3018,7 +3038,7 @@ struct stringprep_range stringprep_A1[] = {0x05F5,0x060B}, {0x0600,~0}, //FIXME rest of A.1 (utf) }; -struct stringprep_range stringprep_B1[] = +static struct stringprep_range stringprep_B1[] = { {0x00AD}, {0x034F}, @@ -3048,14 +3068,14 @@ struct stringprep_range stringprep_B1[] = {0xFE0F}, {0xFEFF}, }; -struct stringprep_range stringprep_B2[] = +static struct stringprep_range stringprep_B2[] = { {0x0041, 0x005A, {0x0061}}, {0x00B5, 0x00B5, {0x03BC}}, {0x00C0, 0x00DE, {0x00E0}}, {0x00DF, 0, {0x0073, 0x0073}}, }; -struct stringprep_range stringprep_C1[] = +static struct stringprep_range stringprep_C1[] = { //C1.1 {0x0020}, @@ -3065,7 +3085,7 @@ struct stringprep_range stringprep_C1[] = {0x1680}, //FIXME... utf }; -struct stringprep_range stringprep_C2[] = +static struct stringprep_range stringprep_C2[] = { //C.2.1 {0x0000, 0x001F}, @@ -3075,13 +3095,13 @@ struct stringprep_range stringprep_C2[] = //FIXME... utf {0x06DD, ~0}, }; -struct stringprep_range stringprep_C3[] = +static struct stringprep_range stringprep_C3[] = { {0xE000, 0xF8FF}, {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}, }; -struct stringprep_range stringprep_C4[] = +static struct stringprep_range stringprep_C4[] = { {0xFDD0, 0xFDEF}, {0xFFFE, 0xFFFF}, @@ -3102,11 +3122,11 @@ struct stringprep_range stringprep_C4[] = {0xFFFFE, 0xFFFFF}, {0x10FFFE, 0x10FFFF}, }; -struct stringprep_range stringprep_C5[] = +static struct stringprep_range stringprep_C5[] = { {0xD800, 0xDFFF}, }; -struct stringprep_range stringprep_C6[] = +static struct stringprep_range stringprep_C6[] = { {0xFFF9}, {0xFFFA}, @@ -3114,11 +3134,11 @@ struct stringprep_range stringprep_C6[] = {0xFFFC}, {0xFFFD}, }; -struct stringprep_range stringprep_C7[] = +static struct stringprep_range stringprep_C7[] = { {0x2FF0, 0x2FFB}, }; -struct stringprep_range stringprep_C8[] = +static struct stringprep_range stringprep_C8[] = { {0x0340}, {0x0341}, @@ -3136,14 +3156,14 @@ struct stringprep_range stringprep_C8[] = {0x206E}, {0x206F}, }; -struct stringprep_range stringprep_C9[] = +static struct stringprep_range stringprep_C9[] = { {0xE0001}, {0xE0001}, {0xE0020, 0xE007F}, }; -static struct stringprep_range *StringPrep_InRange(unsigned int codepoint, struct stringprep_range *range, size_t slots) +static struct stringprep_range *StringPrep_InRange_(unsigned int codepoint, struct stringprep_range *range, size_t slots) { int i; for (i = 0; i < slots; i++) @@ -3163,7 +3183,7 @@ static struct stringprep_range *StringPrep_InRange(unsigned int codepoint, struc } return NULL; } -#define StringPrep_InRange(cp,r) StringPrep_InRange(cp,r,sizeof(r)/sizeof(r[0])) +#define StringPrep_InRange(cp,r) StringPrep_InRange_(cp,r,sizeof(r)/sizeof(r[0])) static qboolean JCL_NamePrep(const char *in, size_t insize, char *out, size_t outsize) { @@ -3515,7 +3535,7 @@ static qboolean JCL_BindReply(jclient_t *jcl, xmltree_t *tree, struct iq_s *iq) } static qboolean JCL_BuddyVCardReply(jclient_t *jcl, xmltree_t *tree, struct iq_s *iq) { - char myself[256]; + char myself[512]; char photodata[65536]; xmltree_t *vc, *photo, *photobinval; const char *nickname; @@ -3565,7 +3585,7 @@ static qboolean JCL_BuddyVCardReply(jclient_t *jcl, xmltree_t *tree, struct iq_s photo = XML_ChildOfTree(vc, "PHOTO", 0); photobinval = XML_ChildOfTree(photo, "BINVAL", 0); - if ((jcl->enabledcapabilities & CAP_AVATARS) && BUILTINISVALID(Draw_LoadImageData)) + if ((jcl->enabledcapabilities & CAP_AVATARS) && drawfuncs) { if (photobinval) { @@ -3575,7 +3595,7 @@ static qboolean JCL_BuddyVCardReply(jclient_t *jcl, xmltree_t *tree, struct iq_s //xep-0153: If the is something other than image/gif, image/jpeg, or image/png, it SHOULD be ignored. if (strcmp(photomime, "image/png") && strcmp(photomime, "image/jpeg") && strcmp(photomime, "image/gif")) photomime = ""; - b->image = pDraw_LoadImageData(va("xmpp/%s.png", b->accountdomain), photomime, photodata, photosize); + b->image = drawfuncs->LoadImageData(va("xmpp/%s.png", b->accountdomain), photomime, photodata, photosize); Con_DPrintf("vcard photo updated from %s\n", from); for (bi = jcl->buddyinfo; bi; bi = bi->next) @@ -3615,7 +3635,7 @@ static qboolean JCL_BuddyVCardReply(jclient_t *jcl, xmltree_t *tree, struct iq_s } else { - b->image = pDraw_LoadImageData(va("xmpp/%s.png", b->accountdomain), "", NULL, 0); + b->image = drawfuncs->LoadImageData(va("xmpp/%s.png", b->accountdomain), "", NULL, 0); Con_DPrintf("vcard photo invalidated from %s\n", from); } } @@ -3911,8 +3931,8 @@ static void buildcaps(jclient_t *jcl, char *out, int outlen) } static int qsortcaps(const void *va, const void *vb) { - char *a = *(char**)va; - char *b = *(char**)vb; + char *const a = *(char*const *)va; + char *const b = *(char*const *)vb; return strcmp(a, b); } char *buildcapshash(jclient_t *jcl) @@ -4262,14 +4282,14 @@ void JCL_ParseIQ(jclient_t *jcl, xmltree_t *tree) if (*pwd) { char rcon_password[64]; - pCvar_GetString("rcon_password", rcon_password, sizeof(rcon_password)); + cvarfuncs->GetString("rcon_password", rcon_password, sizeof(rcon_password)); if (*rcon_password && !strcmp(JCL_Info_ValueForKey(infostring, "password", pwd, sizeof(pwd)), rcon_password)) { Q_strlcpy(jcl->rcon_peer, from, sizeof(jcl->rcon_peer)); if (jcl->rcon_pipe >= 0) - pFS_Close(jcl->rcon_pipe); - if (BUILTINISVALID(Con_POpen)) - jcl->rcon_pipe = pCon_POpen(NULL, 0); + filefuncs->Close(jcl->rcon_pipe); + if (confuncs) + jcl->rcon_pipe = confuncs->POpen(NULL); if (jcl->rcon_pipe < 0) canceled = "Unable to read console"; @@ -4420,7 +4440,7 @@ void JCL_ParseIQ(jclient_t *jcl, xmltree_t *tree) XML_ConPrintTree(tree, "", 0); } } -void XMPP_ConversationPrintf(const char *context, const char *title, char *format, ...) +void XMPP_ConversationPrintf(const char *context, const char *title, qboolean takefocus, char *format, ...) { va_list argptr; static char string[1024]; @@ -4429,13 +4449,13 @@ void XMPP_ConversationPrintf(const char *context, const char *title, char *forma Q_vsnprintf (string, sizeof(string), format,argptr); va_end (argptr); - if (*context && BUILTINISVALID(Con_GetConsoleFloat) && pCon_GetConsoleFloat(context, "iswindow") < true) + if (*context && confuncs && confuncs->GetConsoleFloat(context, "iswindow") < true) { - pCon_SetConsoleFloat(context, "iswindow", true); - pCon_SetConsoleFloat(context, "forceutf8", true); - pCon_SetConsoleFloat(context, "wnd_w", 256); - pCon_SetConsoleFloat(context, "wnd_h", 320); - pCon_SetConsoleString(context, "title", title); + confuncs->SetConsoleFloat(context, "iswindow", true); + confuncs->SetConsoleFloat(context, "forceutf8", true); + confuncs->SetConsoleFloat(context, "wnd_w", 256); + confuncs->SetConsoleFloat(context, "wnd_h", 320); + confuncs->SetConsoleString(context, "title", title); } Con_TrySubPrint(context, string); } @@ -4498,7 +4518,7 @@ void JCL_ParseMessage(jclient_t *jcl, xmltree_t *tree) } else { - if (BUILTINISVALID(Con_SetConsoleString)) + if (confuncs) showicon = b->accountdomain; f = b->name; if (br) @@ -4545,23 +4565,23 @@ void JCL_ParseMessage(jclient_t *jcl, xmltree_t *tree) if (ot) { if (reason) - XMPP_ConversationPrintf(ctx, f, "^1Error: %s (%s): ", reason, f); + XMPP_ConversationPrintf(ctx, f, false, "^1Error: %s (%s): ", reason, f); else - XMPP_ConversationPrintf(ctx, f, "^1error sending message to %s: ", f); + XMPP_ConversationPrintf(ctx, f, false, "^1error sending message to %s: ", f); if (f) { if (!strncmp(ot->body, "/me ", 4)) - XMPP_ConversationPrintf(ctx, f, "* ^2%s^7%s\r", ((!strcmp(jcl->localalias, ">>"))?"me":jcl->localalias), ot->body+3); + XMPP_ConversationPrintf(ctx, f, false, "* ^2%s^7%s\r", ((!strcmp(jcl->localalias, ">>"))?"me":jcl->localalias), ot->body+3); else - XMPP_ConversationPrintf(ctx, f, "%s\r", ot->body); + XMPP_ConversationPrintf(ctx, f, false, "%s\r", ot->body); } } else { if (reason) - XMPP_ConversationPrintf(ctx, f, "^1Error: %s (%s)\r", reason, f); + XMPP_ConversationPrintf(ctx, f, false, "^1Error: %s (%s)\r", reason, f); else - XMPP_ConversationPrintf(ctx, f, "error sending message to %s\r", f); + XMPP_ConversationPrintf(ctx, f, false, "error sending message to %s\r", f); } return; } @@ -4572,31 +4592,31 @@ void JCL_ParseMessage(jclient_t *jcl, xmltree_t *tree) if (ot && !strcmp(ot->xmlns, "http://jabber.org/protocol/chatstates")) { unparsable = false; - XMPP_ConversationPrintf(ctx, f, "%s is typing\r", f); + XMPP_ConversationPrintf(ctx, f, false, "%s is typing\r", f); } ot = XML_ChildOfTree(tree, "paused", 0); if (ot && !strcmp(ot->xmlns, "http://jabber.org/protocol/chatstates")) { unparsable = false; - XMPP_ConversationPrintf(ctx, f, "%s has stopped typing\r", f); + XMPP_ConversationPrintf(ctx, f, false, "%s has stopped typing\r", f); } ot = XML_ChildOfTree(tree, "inactive", 0); if (ot && !strcmp(ot->xmlns, "http://jabber.org/protocol/chatstates")) { unparsable = false; - XMPP_ConversationPrintf(ctx, f, "\r", f); + XMPP_ConversationPrintf(ctx, f, false, "\r", f); } ot = XML_ChildOfTree(tree, "active", 0); if (ot && !strcmp(ot->xmlns, "http://jabber.org/protocol/chatstates")) { unparsable = false; - XMPP_ConversationPrintf(ctx, f, "\r", f); + XMPP_ConversationPrintf(ctx, f, false, "\r", f); } ot = XML_ChildOfTree(tree, "gone", 0); if (ot && !strcmp(ot->xmlns, "http://jabber.org/protocol/chatstates")) { unparsable = false; - XMPP_ConversationPrintf(ctx, f, "%s has gone away\r", f); + XMPP_ConversationPrintf(ctx, f, false, "%s has gone away\r", f); } } @@ -4607,11 +4627,9 @@ void JCL_ParseMessage(jclient_t *jcl, xmltree_t *tree) if (jclient_poketime < jclient_curtime) //throttle these. { jclient_poketime = jclient_curtime + 10*1000; - XMPP_ConversationPrintf(ctx, f, "%s is an attention whore.\n", f); - if (BUILTINISVALID(Con_SetActive)) - pCon_SetActive(ctx); - if (BUILTINISVALID(LocalSound)) - pLocalSound("misc/talk.wav"); + XMPP_ConversationPrintf(ctx, f, true, "%s is an attention whore.\n", f); + if (drawfuncs) + drawfuncs->LocalSound("misc/talk.wav", 256, 1); } } @@ -4629,9 +4647,9 @@ void JCL_ParseMessage(jclient_t *jcl, xmltree_t *tree) unparsable = false; if (sent) - XMPP_ConversationPrintf(ctx, f, COL_NAME_US"You"COL_TEXT_US" have set the topic to: %s\n", ot->body); + XMPP_ConversationPrintf(ctx, f, false, COL_NAME_US"You"COL_TEXT_US" have set the topic to: %s\n", ot->body); else - XMPP_ConversationPrintf(ctx, f, COL_NAME_THEM"%s"COL_TEXT_THEM" has set the topic to: %s\n", f, ot->body); + XMPP_ConversationPrintf(ctx, f, false, COL_NAME_THEM"%s"COL_TEXT_THEM" has set the topic to: %s\n", f, ot->body); } ot = XML_ChildOfTreeNS(tree, "http://jabber.org/protocol/pubsub#event", "event", 0); @@ -4696,11 +4714,9 @@ void JCL_ParseMessage(jclient_t *jcl, xmltree_t *tree) JCL_GenLink(jcl, link, sizeof(link), "mucjoin", f, NULL, password, "%s", f); // ctx = who; if (reason) - XMPP_ConversationPrintf(ctx, f, "* ^2%s^7 has invited you to join %s: %s.\n", who, link, reason); + XMPP_ConversationPrintf(ctx, f, true, "* ^2%s^7 has invited you to join %s: %s.\n", who, link, reason); else - XMPP_ConversationPrintf(ctx, f, "* ^2%s^7 has invited you to join %s.\n", who, link); - if (BUILTINISVALID(Con_SetActive)) - pCon_SetActive(ctx); + XMPP_ConversationPrintf(ctx, f, true, "* ^2%s^7 has invited you to join %s.\n", who, link); } return; //ignore any body/jabber:x:conference } @@ -4719,19 +4735,17 @@ void JCL_ParseMessage(jclient_t *jcl, xmltree_t *tree) if (sent) { if (reason) - XMPP_ConversationPrintf(ctx, f, "* You have invited ^2%s^7 to join %s: %s.\n", f, link, reason); + XMPP_ConversationPrintf(ctx, f, true, "* You have invited ^2%s^7 to join %s: %s.\n", f, link, reason); else - XMPP_ConversationPrintf(ctx, f, "* You have invited ^2%s^7 to join %s.\n", f, link); + XMPP_ConversationPrintf(ctx, f, true, "* You have invited ^2%s^7 to join %s.\n", f, link); } else { if (reason) - XMPP_ConversationPrintf(ctx, f, "* ^2%s^7 has invited you to join %s: %s.\n", f, link, reason); + XMPP_ConversationPrintf(ctx, f, true, "* ^2%s^7 has invited you to join %s: %s.\n", f, link, reason); else - XMPP_ConversationPrintf(ctx, f, "* ^2%s^7 has invited you to join %s.\n", f, link); + XMPP_ConversationPrintf(ctx, f, true, "* ^2%s^7 has invited you to join %s.\n", f, link); } - if (BUILTINISVALID(Con_SetActive)) - pCon_SetActive(ctx); return; //ignore any body } @@ -4744,30 +4758,30 @@ void JCL_ParseMessage(jclient_t *jcl, xmltree_t *tree) if (sent) { if (!strncmp(ot->body, "/me ", 4)) - XMPP_ConversationPrintf(ctx, f, "* "COL_NAME_US"%s"COL_TEXT_US"%s\n", jcl->localalias, ot->body+3); + XMPP_ConversationPrintf(ctx, f, false, "* "COL_NAME_US"%s"COL_TEXT_US"%s\n", jcl->localalias, ot->body+3); else if (showicon) - XMPP_ConversationPrintf(ctx, f, "^[\\img\\xmpp/%s.png\\fbimg\\"IMG_FB_US"\\w\\32\\h\\32^]"COL_NAME_US"%s"COL_TEXT_US":\v%s\n", jcl->barejid, jcl->localalias, ot->body); + XMPP_ConversationPrintf(ctx, f, false, "^[\\img\\xmpp/%s.png\\fbimg\\"IMG_FB_US"\\w\\32\\h\\32^]"COL_NAME_US"%s"COL_TEXT_US":\v%s\n", jcl->barejid, jcl->localalias, ot->body); else - XMPP_ConversationPrintf(ctx, f, COL_NAME_US"%s"COL_TEXT_US": %s\n", jcl->localalias, ot->body); + XMPP_ConversationPrintf(ctx, f, false, COL_NAME_US"%s"COL_TEXT_US": %s\n", jcl->localalias, ot->body); } else { if (!strncmp(ot->body, "/me ", 4)) - XMPP_ConversationPrintf(ctx, f, "* "COL_NAME_THEM"%s"COL_TEXT_THEM"%s\n", f, ot->body+3); + XMPP_ConversationPrintf(ctx, f, false, "* "COL_NAME_THEM"%s"COL_TEXT_THEM"%s\n", f, ot->body+3); else if (showicon) - XMPP_ConversationPrintf(ctx, f, "^[\\img\\xmpp/%s.png\\fbimg\\"IMG_FB_THEM"\\w\\32\\h\\32^]"COL_NAME_THEM"%s"COL_TEXT_THEM":\v%s\n", showicon, f, ot->body); + XMPP_ConversationPrintf(ctx, f, false, "^[\\img\\xmpp/%s.png\\fbimg\\"IMG_FB_THEM"\\w\\32\\h\\32^]"COL_NAME_THEM"%s"COL_TEXT_THEM":\v%s\n", showicon, f, ot->body); else - XMPP_ConversationPrintf(ctx, f, COL_NAME_THEM"%s"COL_TEXT_THEM": %s\n", f, ot->body); + XMPP_ConversationPrintf(ctx, f, false, COL_NAME_THEM"%s"COL_TEXT_THEM": %s\n", f, ot->body); } } else { if (!sent) - XMPP_ConversationPrintf(ctx, f, "NOTICE: %s\n", ot->body); + XMPP_ConversationPrintf(ctx, f, false, "NOTICE: %s\n", ot->body); } - if (BUILTINISVALID(LocalSound)) - pLocalSound("misc/talk.wav"); + if (drawfuncs) + drawfuncs->LocalSound("misc/talk.wav", 256, 1); } if (unparsable) @@ -4775,7 +4789,7 @@ void JCL_ParseMessage(jclient_t *jcl, xmltree_t *tree) unparsable = false; if (jcl->streamdebug) { - XMPP_ConversationPrintf(ctx, f, "Received a message without a body\n"); + XMPP_ConversationPrintf(ctx, f, false, "Received a message without a body\n"); XML_ConPrintTree(tree, "", 0); } } @@ -5254,9 +5268,9 @@ void JCL_ParsePresence(jclient_t *jcl, xmltree_t *tree) //332=shutdown JCL_GenLink(jcl, startconvo, sizeof(startconvo), NULL, from, NULL, NULL, "%s", bres->resource); if (type && !strcmp(type, "unavailable")) - XMPP_ConversationPrintf(buddy->name, buddy->name, "%s has left the conversation\n", bres->resource); + XMPP_ConversationPrintf(buddy->name, buddy->name, false, "%s has left the conversation\n", bres->resource); else if (strcmp(oldbstatus, bres->bstatus)) - XMPP_ConversationPrintf(buddy->name, buddy->name, "%s is now %s\n", startconvo, bres->bstatus); + XMPP_ConversationPrintf(buddy->name, buddy->name, false, "%s is now %s\n", startconvo, bres->bstatus); } else { @@ -5264,23 +5278,23 @@ void JCL_ParsePresence(jclient_t *jcl, xmltree_t *tree) char *title = buddy->name; //if we're not currently talking with them, put the status update into the main console instead (which will probably then get dropped). - if (!BUILTINISVALID(Con_GetConsoleFloat) || pCon_GetConsoleFloat(conv, "iswindow") != true) + if (!confuncs || confuncs->GetConsoleFloat(conv, "iswindow") != true) conv = ""; if (bres->servertype == 2) { char joinlink[512]; JCL_GenLink(jcl, joinlink, sizeof(joinlink), "join", from, NULL, NULL, "Playing Quake - %s", bres->server); - XMPP_ConversationPrintf(conv, title, "%s is now %s\n", startconvo, joinlink); + XMPP_ConversationPrintf(conv, title, false, "%s is now %s\n", startconvo, joinlink); } else if (bres->servertype == 1) - XMPP_ConversationPrintf(conv, title, "%s is now ^[[Playing Quake - %s]\\observe\\%s^]\n", startconvo, bres->server, bres->server); - else if ((pCvar_GetFloat("xmpp_showstatusupdates")||*conv) && (strcmp(oldbstatus, bres->bstatus) || strcmp(oldfstatus, bres->fstatus))) + XMPP_ConversationPrintf(conv, title, false, "%s is now ^[[Playing Quake - %s]\\observe\\%s^]\n", startconvo, bres->server, bres->server); + else if ((cvarfuncs->GetFloat("xmpp_showstatusupdates")||*conv) && (strcmp(oldbstatus, bres->bstatus) || strcmp(oldfstatus, bres->fstatus))) { if (*bres->fstatus) - XMPP_ConversationPrintf(conv, title, "%s is now %s: %s\n", startconvo, bres->bstatus, bres->fstatus); + XMPP_ConversationPrintf(conv, title, false, "%s is now %s: %s\n", startconvo, bres->bstatus, bres->fstatus); else - XMPP_ConversationPrintf(conv, title, "%s is now %s\n", startconvo, bres->bstatus); + XMPP_ConversationPrintf(conv, title, false, "%s is now %s\n", startconvo, bres->bstatus); } } @@ -5308,7 +5322,7 @@ int JCL_ClientFrame(jclient_t *jcl, char **error) int ret; qboolean unparsable; - ret = pNet_Recv(jcl->socket, jcl->bufferedinmessage+jcl->bufferedinammount, sizeof(jcl->bufferedinmessage)-1 - jcl->bufferedinammount); + ret = netfuncs->Recv(jcl->socket, jcl->bufferedinmessage+jcl->bufferedinammount, sizeof(jcl->bufferedinmessage)-1 - jcl->bufferedinammount); if (ret == 0) { if (!jcl->bufferedinammount) //if we are half way through a message, read any possible conjunctions. @@ -5318,7 +5332,7 @@ int JCL_ClientFrame(jclient_t *jcl, char **error) { *error = "Socket Error"; if (jcl->socket != -1) - pNet_Close(jcl->socket); + netfuncs->Close(jcl->socket); jcl->socket = -1; return JCL_KILL; } @@ -5374,9 +5388,9 @@ int JCL_ClientFrame(jclient_t *jcl, char **error) { char t = jcl->bufferedinmessage[pos]; jcl->bufferedinmessage[pos] = 0; - XMPP_ConversationPrintf("xmppin", "xmppin", jcl->bufferedinmessage); + XMPP_ConversationPrintf("xmppin", "xmppin", false, "%s", jcl->bufferedinmessage); if (tree) - XMPP_ConversationPrintf("xmppin", "xmppin", "\n"); + XMPP_ConversationPrintf("xmppin", "xmppin", false, "\n"); jcl->bufferedinmessage[pos] = t; } @@ -5419,8 +5433,8 @@ int JCL_ClientFrame(jclient_t *jcl, char **error) { char t = jcl->bufferedinmessage[pos]; jcl->bufferedinmessage[pos] = 0; - XMPP_ConversationPrintf("xmppin", "xmppin", jcl->bufferedinmessage); - XMPP_ConversationPrintf("xmppin", "xmppin", "\n"); + XMPP_ConversationPrintf("xmppin", "xmppin", false, "%s", jcl->bufferedinmessage); + XMPP_ConversationPrintf("xmppin", "xmppin", false, "\n"); jcl->bufferedinmessage[pos] = t; } @@ -5441,7 +5455,7 @@ int JCL_ClientFrame(jclient_t *jcl, char **error) if (jcl->streamdebug == 1) { - XMPP_ConversationPrintf("xmppin", "xmppin", ""); + XMPP_ConversationPrintf("xmppin", "xmppin", false, ""); XML_ConPrintTree(tree, "xmppin", 0); } @@ -5450,8 +5464,12 @@ int JCL_ClientFrame(jclient_t *jcl, char **error) unparsable = true; if (!strcmp(tree->name, "features")) { - Q_snprintf(jcl->barejid, sizeof(jcl->barejid), "%s@%s", jcl->username, jcl->domain); - Q_snprintf(jcl->fulljid, sizeof(jcl->fulljid), "%s@%s/%s", jcl->username, jcl->domain, jcl->resource); + if (Q_snprintf(jcl->barejid, sizeof(jcl->barejid), "%s@%s", jcl->username, jcl->domain) >= sizeof(jcl->barejid) || + Q_snprintf(jcl->fulljid, sizeof(jcl->fulljid), "%s@%s/%s", jcl->username, jcl->domain, jcl->resource) >= sizeof(jcl->fulljid)) + { + XML_Destroy(tree); + return JCL_KILL; + } if ((ot=XML_ChildOfTree(tree, "bind", 0))) { unparsable = false; @@ -5469,7 +5487,7 @@ int JCL_ClientFrame(jclient_t *jcl, char **error) if (unparsable) { - if ((!jcl->issecure) && BUILTINISVALID(Net_SetTLSClient) && XML_ChildOfTree(tree, "starttls", 0) != NULL && jcl->forcetls >= 0) + if ((!jcl->issecure) && XML_ChildOfTree(tree, "starttls", 0) != NULL && jcl->forcetls >= 0) { Con_DPrintf("XMPP: Attempting to switch to TLS\n"); JCL_AddClientMessageString(jcl, ""); @@ -5485,15 +5503,8 @@ int JCL_ClientFrame(jclient_t *jcl, char **error) qboolean needpass = false; if (jcl->forcetls > 0 && !jcl->issecure) { - if (BUILTINISVALID(Net_SetTLSClient)) - { - *error = "Unable to switch to TLS. You are probably being man-in-the-middle attacked."; - XML_ConPrintTree(tree, "", 0); - } - else - { - *error = "Unable to switch to TLS. Your engine does not provide the feature. You can use the xmpp /autoconnect command to register your account instead, as this does not enforce the use of tls (but does still use it in case your future engine versions support it)."; - } + *error = "Unable to switch to TLS. You are probably being man-in-the-middle attacked."; + XML_ConPrintTree(tree, "", 0); XML_Destroy(tree); return JCL_KILL; } @@ -5594,16 +5605,9 @@ int JCL_ClientFrame(jclient_t *jcl, char **error) jcl->bufferedinammount = 0; jcl->instreampos = 0; - if (!BUILTINISVALID(Net_SetTLSClient)) - { - *error = "proceed without TLS"; - XML_Destroy(tree); - return JCL_KILL; - } - //when using srv records, the certificate must match the user's domain, rather than merely the hostname of the server. //if you want to match the hostname of the server, use (oldstyle) tlsconnect directly instead. - if (pNet_SetTLSClient(jcl->socket, jcl->certificatedomain)<0) + if (netfuncs->SetTLSClient(jcl->socket, jcl->certificatedomain)<0) { *error = "failed to switch to TLS"; XML_Destroy(tree); @@ -5765,7 +5769,7 @@ void JCL_CloseConnection(jclient_t *jcl, const char *reason, qboolean reconnect) jcl->outbufmax = 0; if (jcl->socket != -1) - pNet_Close(jcl->socket); + netfuncs->Close(jcl->socket); jcl->socket = -1; jcl->status = JCL_DEAD; Q_strncpyz(jcl->errormsg, reason, sizeof(jcl->errormsg)); @@ -5797,20 +5801,20 @@ void JCL_GeneratePresence(jclient_t *jcl, qboolean force) serveraddr[0] = 0; servermap[0] = 0; - if (!pCvar_GetFloat("xmpp_nostatus")) + if (!cvarfuncs->GetFloat("xmpp_nostatus")) { - if (pCvar_GetFloat("sv.state")) + if (cvarfuncs->GetFloat("sv.state")) { - pCvar_GetString("sv.mapname", servermap, sizeof(servermap)); + cvarfuncs->GetString("sv.mapname", servermap, sizeof(servermap)); } else { - if (!pCvar_GetString("cl_serveraddress", serveraddr, sizeof(serveraddr))) + if (!cvarfuncs->GetString("cl_serveraddress", serveraddr, sizeof(serveraddr))) serveraddr[0] = 0; - if (BUILTINISVALID(CL_GetStats)) + if (clientfuncs) { //if we can't get any stats, its because we're not actually on the server. - if (!pCL_GetStats(0, &dummystat, 1)) + if (!clientfuncs->GetStats(0, &dummystat, 1)) serveraddr[0] = 0; } } @@ -5900,26 +5904,26 @@ static void JCL_RegenerateBuddyList(qboolean force) jclient_updatebuddylist = false; - if (!BUILTINISVALID(Con_GetConsoleFloat)) + if (!confuncs) return; //only redraw the window if it actually exists. if they closed it, then don't mess things up. - if (!force && pCon_GetConsoleFloat(console, "iswindow") <= 0) + if (!force && confuncs->GetConsoleFloat(console, "iswindow") <= 0) return; - if (pCon_GetConsoleFloat(console, "iswindow") != true) + if (confuncs->GetConsoleFloat(console, "iswindow") != true) { - pCon_SetConsoleFloat(console, "iswindow", true); - pCon_SetConsoleFloat(console, "forceutf8", true); - pCon_SetConsoleFloat(console, "linebuffered", false); - pCon_SetConsoleFloat(console, "wnd_x", pvid.width - 256); - pCon_SetConsoleFloat(console, "wnd_y", true); - pCon_SetConsoleFloat(console, "wnd_w", 256); - pCon_SetConsoleFloat(console, "wnd_h", pvid.height); + confuncs->SetConsoleFloat(console, "iswindow", true); + confuncs->SetConsoleFloat(console, "forceutf8", true); + confuncs->SetConsoleFloat(console, "linebuffered", false); + confuncs->SetConsoleFloat(console, "wnd_x", pvid.width - 256); + confuncs->SetConsoleFloat(console, "wnd_y", true); + confuncs->SetConsoleFloat(console, "wnd_w", 256); + confuncs->SetConsoleFloat(console, "wnd_h", pvid.height); } - pCon_SetConsoleFloat(console, "linecount", 0); //clear it + confuncs->SetConsoleFloat(console, "linecount", 0); //clear it if (force) - pCon_SetActive(console); + confuncs->SetActive(console); for (i = 0; i < sizeof(jclients)/sizeof(jclients[0]); i++) { @@ -6040,7 +6044,7 @@ static void JCL_RegenerateBuddyList(qboolean force) { char photodata[65536]; unsigned int photosize = bi->image?Base64_Decode(photodata, sizeof(photodata), bi->image, strlen(bi->image)):0; - b->image = pDraw_LoadImageData(va("xmpp/%s.png", b->accountdomain), bi->imagemime, photodata, photosize); + b->image = drawfuncs->LoadImageData(va("xmpp/%s.png", b->accountdomain), bi->imagemime, photodata, photosize); b->vcardphotochanged = false; } else if (!*b->vcardphotohash) @@ -6280,10 +6284,10 @@ static void JCL_PrintBuddyList(char *console, jclient_t *jcl, qboolean all) //functions above this line allow connections to multiple servers. //it is just the control functions that only allow one server. -qintptr_t JCL_Frame(qintptr_t *args) +void JCL_Frame(double realtime, double gametime) { int i; - jclient_curtime = args[0]; + jclient_curtime = realtime; if (jclient_needreadconfig) { JCL_LoadConfig(); @@ -6340,7 +6344,7 @@ qintptr_t JCL_Frame(qintptr_t *args) if (jcl->rcon_pipe >= 0) { char rcondata[64000]; - int rconsize = pNet_Recv(jcl->rcon_pipe, rcondata, sizeof(rcondata)-1); + int rconsize = netfuncs->Recv(jcl->rcon_pipe, rcondata, sizeof(rcondata)-1); if (rconsize > 0) { char *ls, *le; @@ -6358,7 +6362,7 @@ qintptr_t JCL_Frame(qintptr_t *args) else if (rconsize < 0) { JCL_AddClientMessagef(jcl, "%s", jcl->rcon_peer, "RCON ERROR"); - pFS_Close(jcl->rcon_pipe); + filefuncs->Close(jcl->rcon_pipe); jcl->rcon_pipe = -1; } } @@ -6372,7 +6376,6 @@ qintptr_t JCL_Frame(qintptr_t *args) JCL_IQTimeouts(jcl); } } - return 0; } void JCL_WriteConfig(void) @@ -6477,14 +6480,14 @@ void JCL_WriteConfig(void) } } - pFS_Open("**plugconfig", &config, 2); + filefuncs->Open("**plugconfig", &config, 2); if (config >= 0) { char *s = XML_GenerateString(m, true); - pFS_Write(config, s, strlen(s)); + filefuncs->Write(config, s, strlen(s)); free(s); - pFS_Close(config); + filefuncs->Close(config); } XML_Destroy(m); } @@ -6497,13 +6500,13 @@ void JCL_LoadConfig(void) qhandle_t config; char *buf; qboolean oldtls; - len = pFS_Open("**plugconfig", &config, 1); + len = filefuncs->Open("**plugconfig", &config, 1); if (len >= 0) { buf = malloc(len+1); buf[len] = 0; - pFS_Read(config, buf, len); - pFS_Close(config); + filefuncs->Read(config, buf, len); + filefuncs->Close(config); if (len && *buf != '<') {//legacy code, to be removed @@ -6548,7 +6551,7 @@ void JCL_LoadConfig(void) } //on shutdown, write config and close connections. -qintptr_t JCL_Shutdown(qintptr_t *args) +void JCL_Shutdown(void) { jclient_t *jcl; int i; @@ -6562,7 +6565,6 @@ qintptr_t JCL_Shutdown(qintptr_t *args) // if (_CrtDumpMemoryLeaks()) // OutputDebugStringA("Leaks detected\n"); - return true; } void JCL_SendMessage(jclient_t *jcl, char *to, char *msg) @@ -6607,11 +6609,11 @@ void JCL_SendMessage(jclient_t *jcl, char *to, char *msg) if (b->btype == BT_CHATROOM && !br) return; if (!strncmp(msg, "/me ", 4)) - XMPP_ConversationPrintf(con, title, "* "COL_NAME_US"%s^7"COL_TEXT_US"%s\n", ((!strcmp(jcl->localalias, ">>"))?"me":jcl->localalias), msg+3); - else if (b->btype == BT_ROSTER && BUILTINISVALID(Con_SetConsoleString)) - XMPP_ConversationPrintf(con, title, "^[\\img\\xmpp/%s.png\\fbimg\\"IMG_FB_US"\\w\\32\\h\\32^]"COL_NAME_US"%s^7:\v"COL_TEXT_US"%s\n", jcl->barejid, jcl->localalias, msg); + XMPP_ConversationPrintf(con, title, false, "* "COL_NAME_US"%s^7"COL_TEXT_US"%s\n", ((!strcmp(jcl->localalias, ">>"))?"me":jcl->localalias), msg+3); + else if (b->btype == BT_ROSTER && confuncs) + XMPP_ConversationPrintf(con, title, false, "^[\\img\\xmpp/%s.png\\fbimg\\"IMG_FB_US"\\w\\32\\h\\32^]"COL_NAME_US"%s^7:\v"COL_TEXT_US"%s\n", jcl->barejid, jcl->localalias, msg); else - XMPP_ConversationPrintf(con, title, COL_NAME_US"%s^7: "COL_TEXT_US"%s\n", jcl->localalias, msg); + XMPP_ConversationPrintf(con, title, false, COL_NAME_US"%s^7: "COL_TEXT_US"%s\n", jcl->localalias, msg); } void JCL_AttentionMessage(jclient_t *jcl, char *to, char *msg) { @@ -6722,14 +6724,14 @@ void XMPP_Menu_Password(jclient_t *acc) if (!jclient_action) { JCL_RegenerateBuddyList(true); - pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); + confuncs->SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); jclient_action_cl = acc; jclient_action_buddy = NULL; jclient_action = ACT_SETAPASSWORD; } /* - pCmd_AddText("conmenu\n" + cmdfuncs->AddText("conmenu\n" "{\n" "menuclear\n" "if (option == \"SignIn\")\n" @@ -6740,18 +6742,18 @@ void XMPP_Menu_Password(jclient_t *acc) "}\n", false); y = 36; - pCmd_AddText(va("menutext 48 %i \"^sXMPP Sign In\"\n", y), false); y+=16; - pCmd_AddText(va("menutext 48 %i \"^sPlease provide your password for\"\n", y), false); y+=16; - pCmd_AddText(va("menueditpriv 48 %i \"%s@%s\" \"example\"\n", y, acc->username, acc->domain), false);y+=16; - pCmd_AddText(va("set _t1 0\nmenucheck 48 %i \"Save Password\" _t1 1\n", y), false); y+=16; - pCmd_AddText(va("menutext 48 %i \"Sign In\" SignIn\n", y), false); - pCmd_AddText(va("menutext 256 %i \"Cancel\" cancel\n", y), false); + cmdfuncs->AddText(va("menutext 48 %i \"^sXMPP Sign In\"\n", y), false); y+=16; + cmdfuncs->AddText(va("menutext 48 %i \"^sPlease provide your password for\"\n", y), false); y+=16; + cmdfuncs->AddText(va("menueditpriv 48 %i \"%s@%s\" \"example\"\n", y, acc->username, acc->domain), false);y+=16; + cmdfuncs->AddText(va("set _t1 0\nmenucheck 48 %i \"Save Password\" _t1 1\n", y), false); y+=16; + cmdfuncs->AddText(va("menutext 48 %i \"Sign In\" SignIn\n", y), false); + cmdfuncs->AddText(va("menutext 256 %i \"Cancel\" cancel\n", y), false); */ } void XMPP_Menu_Connect(void) { int y; - pCmd_AddText("conmenu\n" + cmdfuncs->AddText("conmenu\n" "{\n" "menuclear\n" "if (option == \"SignIn\")\n" @@ -6759,12 +6761,12 @@ void XMPP_Menu_Connect(void) "}\n", false); y = 36; - pCmd_AddText(va("menutext 48 %i \"^sXMPP Sign In\"\n", y), false); y+=16; - pCmd_AddText(va("menueditpriv 48 %i \"Username\" \"example\"\n", y), false);y+=16; - pCmd_AddText(va("menueditpriv 48 %i \"Domain\" \""EXAMPLEDOMAIN"\"\n", y), false);y+=16; - pCmd_AddText(va("menueditpriv 48 %i \"Resource\" \"\"\n", y), false);y+=32; - pCmd_AddText(va("menutext 48 %i \"Sign In\" SignIn\n", y), false); - pCmd_AddText(va("menutext 256 %i \"Cancel\" cancel\n", y), false); + cmdfuncs->AddText(va("menutext 48 %i \"^sXMPP Sign In\"\n", y), false); y+=16; + cmdfuncs->AddText(va("menueditpriv 48 %i \"Username\" \"example\"\n", y), false);y+=16; + cmdfuncs->AddText(va("menueditpriv 48 %i \"Domain\" \""EXAMPLEDOMAIN"\"\n", y), false);y+=16; + cmdfuncs->AddText(va("menueditpriv 48 %i \"Resource\" \"\"\n", y), false);y+=32; + cmdfuncs->AddText(va("menutext 48 %i \"Sign In\" SignIn\n", y), false); + cmdfuncs->AddText(va("menutext 256 %i \"Cancel\" cancel\n", y), false); } void JCL_Command(int accid, char *console) @@ -6780,7 +6782,7 @@ void JCL_Command(int accid, char *console) return; jcl = jclients[accid]; - pCmd_Args(imsg, sizeof(imsg)); + cmdfuncs->Args(imsg, sizeof(imsg)); msg = imsg; for (i = 0; i < 6; i++) @@ -6963,19 +6965,10 @@ void JCL_Command(int accid, char *console) else if (!strcmp(arg[0]+1, "help")) { Con_TrySubPrint(console, "^[/" COMMANDPREFIX " /connect USERNAME@DOMAIN/RESOURCE [PASSWORD] [XMPPSERVER]^]\n"); - if (BUILTINISVALID(Net_SetTLSClient)) - { - Con_TrySubPrint(console, "eg for gmail: ^[/" COMMANDPREFIX " /connect myusername@gmail.com^] (using oauth2)\n"); - Con_TrySubPrint(console, "eg for gmail: ^[/" COMMANDPREFIX " /connect myusername@gmail.com mypassword^] (warning: password will be saved locally in plain text)\n"); -// Con_TrySubPrint(console, "eg for facebook: ^[/" COMMANDPREFIX " /connect myusername@chat.facebook.com mypassword chat.facebook.com^]\n"); -// Con_TrySubPrint(console, "eg for msn: ^[/" COMMANDPREFIX " /connect myusername@messanger.live.com mypassword^]\n"); - } - else - { //if we don't have tls support, we can still connect to google with oauth2 - //no idea about other networks. - //however, the regular 'connect' command will insist on tls, so make sure the helpful command displayed is different - Con_TrySubPrint(console, "eg for gmail: ^[/" COMMANDPREFIX " /autoconnect myusername@gmail.com^] (using oauth2)\n"); - } + Con_TrySubPrint(console, "eg for gmail: ^[/" COMMANDPREFIX " /connect myusername@gmail.com^] (using oauth2)\n"); + Con_TrySubPrint(console, "eg for gmail: ^[/" COMMANDPREFIX " /connect myusername@gmail.com mypassword^] (warning: password will be saved locally in plain text)\n"); +// Con_TrySubPrint(console, "eg for facebook: ^[/" COMMANDPREFIX " /connect myusername@chat.facebook.com mypassword chat.facebook.com^]\n"); +// Con_TrySubPrint(console, "eg for msn: ^[/" COMMANDPREFIX " /connect myusername@messanger.live.com mypassword^]\n"); Con_TrySubPrint(console, "Note that this info will be used the next time you start quake.\n"); //small note: @@ -7009,13 +7002,13 @@ void JCL_Command(int accid, char *console) //just clears the current console. if (*console) { - pCon_Destroy(console); + confuncs->Destroy(console); Con_SubPrintf(console, ""); - if (BUILTINISVALID(Con_SetActive)) - pCon_SetActive(console); + if (confuncs) + confuncs->SetActive(console); } else - pCmd_AddText("\nclear\n", true); + cmdfuncs->AddText("\nclear\n", true); } else if (!jcl) { @@ -7169,8 +7162,7 @@ void JCL_Command(int accid, char *console) char roomserverhandle[512]; buddy_t *b; bresource_t *r; - Q_snprintf(roomserverhandle, sizeof(roomserverhandle), "%s@%s/%s", arg[1], arg[2], arg[3]); - if (JCL_FindBuddy(jcl, roomserverhandle, &b, &r, false)) + if (Q_snprintf(roomserverhandle, sizeof(roomserverhandle), "%s@%s/%s", arg[1], arg[2], arg[3]) < sizeof(roomserverhandle) && JCL_FindBuddy(jcl, roomserverhandle, &b, &r, false)) { JCL_AddClientMessagef(jcl, "", roomserverhandle); JCL_ForgetBuddy(jcl, b, NULL); @@ -7234,7 +7226,7 @@ void JCL_Command(int accid, char *console) { if (!*console) { - if (BUILTINISVALID(Con_GetConsoleFloat)) + if (confuncs) JCL_RegenerateBuddyList(true); else JCL_PrintBuddyList(console, jcl, false); @@ -7249,7 +7241,7 @@ void JCL_Command(int accid, char *console) } else { - if (!*msg && BUILTINISVALID(Con_GetConsoleFloat)) + if (!*msg && confuncs) JCL_RegenerateBuddyList(true); else Con_TrySubPrint(console, "Not connected. For help, type \"^[/" COMMANDPREFIX " /help^]\"\n"); diff --git a/plugins/jabber/jingle.c b/plugins/jabber/jingle.c index b6544c844..10b97e821 100644 --- a/plugins/jabber/jingle.c +++ b/plugins/jabber/jingle.c @@ -72,8 +72,7 @@ static struct c2c_s *JCL_JingleAddContentToSession(jclient_t *jcl, struct c2c_s //for msn, live.com has one, messanger.live.com has one, but messenger.live.com does NOT. seriously, the typo has more services. wtf microsoft? //google doesn't provide a stun srv entry //facebook doesn't provide a stun srv entry - Q_snprintf(stunhost, sizeof(stunhost), "_stun._udp.%s", jcl->domain); - if (NET_DNSLookup_SRV(stunhost, stunhost, sizeof(stunhost))) + if (Q_snprintf(stunhost, sizeof(stunhost), "_stun._udp.%s", jcl->domain) < sizeof(stunhost) && NET_DNSLookup_SRV(stunhost, stunhost, sizeof(stunhost))) piceapi->ICE_Set(ice, "stunip", stunhost); else { @@ -581,10 +580,10 @@ void JCL_Join(jclient_t *jcl, const char *target, const char *sid, qboolean allo JCL_GenLink(jcl, convolink, sizeof(convolink), NULL, target, NULL, NULL, "%s", target); JCL_GenLink(jcl, hanguplink, sizeof(hanguplink), "jdeny", target, NULL, c2c->sid, "%s", "Hang Up"); - XMPP_ConversationPrintf(b->accountdomain, b->name, "%s %s %s.\n", protocol==ICEP_VOICE?"Calling":"Requesting session with", convolink, hanguplink); + XMPP_ConversationPrintf(b->accountdomain, b->name, false, "%s %s %s.\n", protocol==ICEP_VOICE?"Calling":"Requesting session with", convolink, hanguplink); } else - XMPP_ConversationPrintf(b->accountdomain, b->name, "That session has expired.\n"); + XMPP_ConversationPrintf(b->accountdomain, b->name, false, "That session has expired.\n"); } else if (c2c->creator) { @@ -592,16 +591,16 @@ void JCL_Join(jclient_t *jcl, const char *target, const char *sid, qboolean allo //resend initiate if they've not acked it... I dunno... JCL_JingleSend(jcl, c2c, "session-initiate"); JCL_GenLink(jcl, convolink, sizeof(convolink), NULL, target, NULL, NULL, "%s", target); - XMPP_ConversationPrintf(b->accountdomain, b->name, "Restarting session with %s.\n", convolink); + XMPP_ConversationPrintf(b->accountdomain, b->name, false, "Restarting session with %s.\n", convolink); } else if (c2c->accepted) - XMPP_ConversationPrintf(b->accountdomain, b->name, "That session was already accepted.\n"); + XMPP_ConversationPrintf(b->accountdomain, b->name, false, "That session was already accepted.\n"); else { char convolink[512]; JCL_JingleSend(jcl, c2c, "session-accept"); JCL_GenLink(jcl, convolink, sizeof(convolink), NULL, target, NULL, NULL, "%s", target); - XMPP_ConversationPrintf(b->accountdomain, b->name, "Accepting session from %s.\n", convolink); + XMPP_ConversationPrintf(b->accountdomain, b->name, false, "Accepting session from %s.\n", convolink); } } else @@ -611,10 +610,10 @@ void JCL_Join(jclient_t *jcl, const char *target, const char *sid, qboolean allo char convolink[512]; JCL_JingleSend(jcl, c2c, "session-terminate"); JCL_GenLink(jcl, convolink, sizeof(convolink), NULL, target, NULL, NULL, "%s", target); - XMPP_ConversationPrintf(b->accountdomain, b->name, "Terminating session with %s.\n", convolink); + XMPP_ConversationPrintf(b->accountdomain, b->name, false, "Terminating session with %s.\n", convolink); } else - XMPP_ConversationPrintf(b->accountdomain, b->name, "That session has already expired.\n"); + XMPP_ConversationPrintf(b->accountdomain, b->name, false, "That session has already expired.\n"); } } @@ -853,9 +852,8 @@ static qboolean JCL_JingleHandleInitiate_GoogleSession(jclient_t *jcl, xmltree_t JCL_GenLink(jcl, denylink, sizeof(denylink), "jdeny", from, NULL, sid, "%s", "Reject"); //show a prompt for it, send the reply when the user decides. - XMPP_ConversationPrintf(b->accountdomain, b->name, + XMPP_ConversationPrintf(b->accountdomain, b->name, true, "%s %s. %s %s\n", convolink, offer, authlink, denylink); - pCon_SetActive(b->name); return true; } else @@ -965,7 +963,7 @@ static struct c2c_s *JCL_JingleHandleInitiate(jclient_t *jcl, xmltree_t *inj, co { char convolink[512]; JCL_GenLink(jcl, convolink, sizeof(convolink), NULL, from, NULL, NULL, "%s", b->name); - XMPP_ConversationPrintf(b->accountdomain, b->name, "%s does not support any compatible codecs, and is unable to call you.\n", convolink); + XMPP_ConversationPrintf(b->accountdomain, b->name, false, "%s does not support any compatible codecs, and is unable to call you.\n", convolink); if (c2c->content[c].ice) piceapi->ICE_Close(c2c->content[c].ice); @@ -1001,14 +999,14 @@ static qboolean JCL_JingleHandleSessionTerminate(jclient_t *jcl, xmltree_t *tree int c; if (!c2c) { - XMPP_ConversationPrintf(b->accountdomain, b->name, "Received session-terminate without an active session\n"); + XMPP_ConversationPrintf(b->accountdomain, b->name, false, "Received session-terminate without an active session\n"); return false; } if (reason && reason->child) - XMPP_ConversationPrintf(b->accountdomain, b->name, "Session ended: %s\n", reason->child->name); + XMPP_ConversationPrintf(b->accountdomain, b->name, false, "Session ended: %s\n", reason->child->name); else - XMPP_ConversationPrintf(b->accountdomain, b->name, "Session ended\n"); + XMPP_ConversationPrintf(b->accountdomain, b->name, false, "Session ended\n"); //unlink it for (link = &jcl->c2c; *link; link = &(*link)->next) @@ -1059,7 +1057,7 @@ static qboolean JCL_JingleHandleSessionAccept(jclient_t *jcl, xmltree_t *tree, c { return false; } - XMPP_ConversationPrintf(b->accountdomain, b->name, "Session Accepted!\n"); + XMPP_ConversationPrintf(b->accountdomain, b->name, false, "Session Accepted!\n"); // XML_ConPrintTree(tree, 0); JCL_JingleParsePeerPorts(jcl, c2c, tree, from, XML_GetParameter(tree, "sid", "")); @@ -1305,12 +1303,12 @@ qboolean JCL_ParseJingle(jclient_t *jcl, xmltree_t *tree, const char *from, cons { switch(c2c->content[c].mediatype) { - case ICEP_INVALID: break; - case ICEP_VOICE: voice = true; doprompt |= !pCvar_GetFloat("xmpp_autoacceptvoice"); break; - case ICEP_VIDEO: video = true; doprompt |= !pCvar_GetFloat("xmpp_autoacceptvoice"); break; - case ICEP_QWSERVER: server = true; doprompt |= !pCvar_GetFloat("xmpp_autoacceptjoins"); break; - case ICEP_QWCLIENT: client = true; doprompt |= !pCvar_GetFloat("xmpp_autoacceptinvites"); break; - default: doprompt |= true; break; + case ICEP_INVALID: break; + case ICEP_VOICE: voice = true; doprompt |= !cvarfuncs->GetFloat("xmpp_autoacceptvoice"); break; + case ICEP_VIDEO: video = true; doprompt |= !cvarfuncs->GetFloat("xmpp_autoacceptvoice"); break; + case ICEP_QWSERVER: server = true; doprompt |= !cvarfuncs->GetFloat("xmpp_autoacceptjoins"); break; + case ICEP_QWCLIENT: client = true; doprompt |= !cvarfuncs->GetFloat("xmpp_autoacceptinvites"); break; + default: doprompt |= true; break; } } @@ -1351,13 +1349,12 @@ qboolean JCL_ParseJingle(jclient_t *jcl, xmltree_t *tree, const char *from, cons JCL_GenLink(jcl, denylink, sizeof(denylink), "jdeny", from, NULL, sid, "%s", "Reject"); //show a prompt for it, send the reply when the user decides. - XMPP_ConversationPrintf(b->accountdomain, b->name, + XMPP_ConversationPrintf(b->accountdomain, b->name, true, "%s %s. %s %s\n", convolink, offer, authlink, denylink); - pCon_SetActive(b->accountdomain); } else { - XMPP_ConversationPrintf(b->accountdomain, b->name, "Auto-accepting session from %s\n", convolink); + XMPP_ConversationPrintf(b->accountdomain, b->name, false, "Auto-accepting session from %s\n", convolink); JCL_Join(jcl, from, sid, true, ICEP_INVALID); } } diff --git a/plugins/jabber/sift.c b/plugins/jabber/sift.c index 83f85b201..c80d2b7bf 100644 --- a/plugins/jabber/sift.c +++ b/plugins/jabber/sift.c @@ -20,14 +20,14 @@ void XMPP_FT_Frame(jclient_t *jcl) if (ft->nexthost > 0) { ft->nexthost--; - ft->stream = pNet_TCPConnect(ft->streamhosts[ft->nexthost].host, ft->streamhosts[ft->nexthost].port); + ft->stream = netfuncs->TCPConnect(ft->streamhosts[ft->nexthost].host, ft->streamhosts[ft->nexthost].port); if (ft->stream == -1) continue; ft->streamstatus = STRM_AUTH; //'authenticate' with socks5 proxy. tell it that we only support 'authless'. - pNet_Send(ft->stream, "\x05\x01\x00", 3); + netfuncs->Send(ft->stream, "\x05\x01\x00", 3); } else { @@ -47,13 +47,13 @@ void XMPP_FT_Frame(jclient_t *jcl) int len; if (ft->streamstatus == STRM_ACTIVE) { - len = pNet_Recv(ft->stream, data, sizeof(data)-1); + len = netfuncs->Recv(ft->stream, data, sizeof(data)-1); if (len > 0) - pFS_Write(ft->file, data, len); + filefuncs->Write(ft->file, data, len); } else { - len = pNet_Recv(ft->stream, data, sizeof(data)-1); + len = netfuncs->Recv(ft->stream, data, sizeof(data)-1); if (len > 0) { if (ft->streamstatus == STRM_AUTH) @@ -74,7 +74,7 @@ void XMPP_FT_Frame(jclient_t *jcl) //connect with hostname(3). req = va("\x05\x01%c\x03""%c%s%c%c", 0, (int)strlen(domain), domain, 0, 0); - pNet_Send(ft->stream, req, strlen(domain)+7); + netfuncs->Send(ft->stream, req, strlen(domain)+7); ft->streamstatus = STRM_AUTHED; } else @@ -84,7 +84,7 @@ void XMPP_FT_Frame(jclient_t *jcl) { if (data[0] == 0x05 && data[1] == 0x00) { - if (pFS_Open(ft->fname, &ft->file, 2) < 0) + if (filefuncs->Open(ft->fname, &ft->file, 2) < 0) { len = -1; JCL_AddClientMessagef(jcl, "", ft->iqid, ft->with); @@ -108,18 +108,18 @@ void XMPP_FT_Frame(jclient_t *jcl) if (len == -1) { - pNet_Close(ft->stream); + netfuncs->Close(ft->stream); ft->stream = -1; if (ft->streamstatus == STRM_ACTIVE) { int size; if (ft->file != -1) - pFS_Close(ft->file); + filefuncs->Close(ft->file); ft->file = -1; - size = pFS_Open(ft->fname, &ft->file, 1); + size = filefuncs->Open(ft->fname, &ft->file, 1); if (ft->file != -1) - pFS_Close(ft->file); + filefuncs->Close(ft->file); if (size == ft->size) { Con_Printf("File Transfer Completed\n"); @@ -174,7 +174,7 @@ void XMPP_FT_AcceptFile(jclient_t *jcl, int fileid, qboolean accept) } if (ft->file != -1) - pFS_Close(ft->file); + filefuncs->Close(ft->file); *link = ft->next; free(ft); } @@ -222,7 +222,7 @@ static qboolean XMPP_FT_IBBChunked(jclient_t *jcl, xmltree_t *x, struct iq_s *iq char *base64; char rawbuf[4096]; int sz; - sz = pFS_Read(ft->file, rawbuf, ft->blocksize); + sz = filefuncs->Read(ft->file, rawbuf, ft->blocksize); Base64_Add(rawbuf, sz); base64 = Base64_Finish(); @@ -256,7 +256,7 @@ static qboolean XMPP_FT_IBBChunked(jclient_t *jcl, xmltree_t *x, struct iq_s *iq //errored if (ft->file != -1) - pFS_Close(ft->file); + filefuncs->Close(ft->file); *link = ft->next; free(ft); return true; @@ -278,7 +278,7 @@ static qboolean XMPP_FT_IBBBegun(jclient_t *jcl, xmltree_t *x, struct iq_s *iq) Con_Printf("%s aborted %s\n", ft->with, ft->fname); //errored if (ft->file != -1) - pFS_Close(ft->file); + filefuncs->Close(ft->file); *link = ft->next; free(ft); } @@ -307,7 +307,7 @@ qboolean XMPP_FT_OfferAcked(jclient_t *jcl, xmltree_t *x, struct iq_s *iq) Con_Printf("%s doesn't want %s\n", ft->with, ft->fname); //errored if (ft->file != -1) - pFS_Close(ft->file); + filefuncs->Close(ft->file); *link = ft->next; free(ft); } @@ -338,19 +338,21 @@ void XMPP_FT_SendFile(jclient_t *jcl, const char *console, const char *to, const ft = malloc(sizeof(*ft)); memset(ft, 0, sizeof(*ft)); ft->stream = -1; - ft->next = jcl->ft; - jcl->ft = ft; ft->allowed = true; ft->transmitting = true; ft->blocksize = 4096; Q_strlcpy(ft->fname, fname, sizeof(ft->fname)); - Q_snprintf(ft->sid, sizeof(ft->sid), "%x%s", rand(), ft->fname); + if (Q_snprintf(ft->sid, sizeof(ft->sid), "%x%s", rand(), ft->fname) >= sizeof(ft->sid)) + /*doesn't matter so long as its unique*/; Q_strlcpy(ft->md5hash, "", sizeof(ft->md5hash)); - ft->size = pFS_Open(ft->fname, &ft->file, 1); + ft->size = filefuncs->Open(ft->fname, &ft->file, 1); ft->with = strdup(to); ft->method = FT_IBB; ft->begun = false; + ft->next = jcl->ft; + jcl->ft = ft; + //generate an offer. xsi = XML_CreateNode(NULL, "si", "http://jabber.org/protocol/si", ""); XML_AddParameter(xsi, "profile", "http://jabber.org/protocol/si/profile/file-transfer"); @@ -463,7 +465,7 @@ qboolean XMPP_FT_ParseIQSet(jclient_t *jcl, const char *iqfrom, const char *iqid } else { //it looks okay - pFS_Open(ft->fname, &ft->file, 2); + filefuncs->Open(ft->fname, &ft->file, 2); ft->method = FT_IBB; ft->blocksize = blocksize; ft->begun = true; @@ -490,7 +492,7 @@ qboolean XMPP_FT_ParseIQSet(jclient_t *jcl, const char *iqfrom, const char *iqid { int size; if (ft->file != -1) - pFS_Close(ft->file); + filefuncs->Close(ft->file); if (ft->transmitting) { if (ft->eof) @@ -500,9 +502,9 @@ qboolean XMPP_FT_ParseIQSet(jclient_t *jcl, const char *iqfrom, const char *iqid } else { - size = pFS_Open(ft->fname, &ft->file, 1); + size = filefuncs->Open(ft->fname, &ft->file, 1); if (ft->file != -1) - pFS_Close(ft->file); + filefuncs->Close(ft->file); if (size == ft->size) Con_Printf("Received file \"%s\" successfully\n", ft->fname); else @@ -534,7 +536,7 @@ qboolean XMPP_FT_ParseIQSet(jclient_t *jcl, const char *iqfrom, const char *iqid blocksize = Base64_Decode(block, sizeof(block), ot->body, strlen(ot->body)); if (blocksize && blocksize <= ft->blocksize) { - pFS_Write(ft->file, block, blocksize); + filefuncs->Write(ft->file, block, blocksize); JCL_AddClientMessagef(jcl, "", iqid, iqfrom); return true; } diff --git a/plugins/jabber/xmpp.h b/plugins/jabber/xmpp.h index 6e89c5816..30f25465e 100644 --- a/plugins/jabber/xmpp.h +++ b/plugins/jabber/xmpp.h @@ -1,4 +1,6 @@ #include "../plugin.h" +extern plugnetfuncs_t *netfuncs; +extern plugfsfuncs_t *filefuncs; #include "xml.h" @@ -339,7 +341,7 @@ void JCL_ForgetBuddy(jclient_t *jcl, buddy_t *buddy, bresource_t *bres); //quake functionality void JCL_GenLink(jclient_t *jcl, char *out, int outlen, const char *action, const char *context, const char *contextres, const char *sid, const char *txtfmt, ...); void Con_SubPrintf(const char *subname, const char *format, ...); -void XMPP_ConversationPrintf(const char *context, const char *title, char *format, ...); +void XMPP_ConversationPrintf(const char *context, const char *title, qboolean takefocus, char *format, ...); //jingle functions void JCL_Join(jclient_t *jcl, const char *target, const char *sid, qboolean allow, int protocol); diff --git a/plugins/memory.c b/plugins/memory.c deleted file mode 100644 index 1dd0fbf93..000000000 --- a/plugins/memory.c +++ /dev/null @@ -1,125 +0,0 @@ -//a qvm compatable malloc/free interface - -//This is seperate from qvm_api.c because this has a chunk of memory that simply isn't needed in all plugins. - -#include "plugin.h" - -struct memhead_s -{ - int size; - int isfree; - struct memhead_s *next; - struct memhead_s *prev; -}; - -#ifndef MEMSIZE -#define MEMSIZE 1024*64 //64kb -#endif - -static struct memhead_s *head; -static char memory[MEMSIZE]; - -//we create two dummies at the start and end -//these will never be freed -//we then have dynamic allocation in the middle. -//sizes include the headers - -void *malloc(int size) -{ - struct memhead_s *lasthead; - - if (size <= 0) - return NULL; - - size = ((size+4) & ~3) + sizeof(struct memhead_s); //round up - if (!head) - { //first call - struct memhead_s *last; - struct memhead_s *middle; - struct memhead_s *first; - - first = (struct memhead_s*)memory; - last= (struct memhead_s*)((char*)memory - sizeof(struct memhead_s)); - first->size = last->size = sizeof(struct memhead_s); - first->isfree = last->isfree = false; - - middle = (struct memhead_s*)((char*)first+first->size); - middle->size = sizeof(memory) - sizeof(struct memhead_s)*3; - middle->isfree = true; - - last->next = first; - last->prev = middle; - first->next = middle; - first->prev = last; - middle->next = last; - middle->prev = first; - - head = middle; - } - lasthead = head; - - do - { - if (head->isfree) - if (head->size >= size) - { - struct memhead_s *split; - if (head->size > size + sizeof(struct memhead_s)+1) - { //split - split = (struct memhead_s*)((char*)head + size); - split->size = head->size - size; - head->size = size; - split->next = head->next; - split->prev = head; - head->next = split; - split->next->prev = split; - split->isfree = true; - head->isfree = false; - } - else - { //no point in splitting - head->isfree = false; - } - split = head; - head = head->next; - return (char*)split + sizeof(struct memhead_s); - } - head = head->next; - } while (lasthead != head); - - Sys_Errorf("VM Out of memory on allocation of %i bytes\n", size); - - return NULL; -} - -static struct memhead_s *mergeblock(struct memhead_s *b1, struct memhead_s *b2) -{ - //b1 and b2 must be in logical order - - b1->next = b2->next; - b2->next->prev = b1; - b1->size += b2->size; - - return b1; -} - -void free(void *mem) -{ //the foot hopefully isn't going to be freed - struct memhead_s *block; - block = (struct memhead_s*)((char*)mem - sizeof(struct memhead_s)); - - if (block->isfree) - Sys_Error("(plugin) Double free\n"); - block->isfree = true; - - if (block->prev->isfree) - { //merge previous with this - block = mergeblock(block->prev, block); - } - if (block->next) - { //merge next with this - block = mergeblock(block, block->next); - } - - head = (struct memhead_s*)memory; -} diff --git a/plugins/models/gltf.c b/plugins/models/gltf.c index 9f571930b..5fbf96c84 100644 --- a/plugins/models/gltf.c +++ b/plugins/models/gltf.c @@ -1,10 +1,11 @@ #ifndef GLQUAKE -#define GLQUAKE //this is shit. +//#define GLQUAKE //this is shit. #endif #include "quakedef.h" #include "../plugin.h" #include "com_mesh.h" -extern modplugfuncs_t *modfuncs; +extern plugmodfuncs_t *modfuncs; +extern plugfsfuncs_t *filefuncs; #ifdef SKELETALMODELS #define GLTFMODELS @@ -355,6 +356,21 @@ static double JSON_GetIndexedFloat(json_t *t, unsigned int idx, double fallback) Q_snprintf(idxname, sizeof(idxname), "%u", idx); return JSON_GetFloat(t, idxname, fallback); } +static const char *JSON_GetString(json_t *t, const char *child, char *buffer, size_t buffersize, const char *fallback) +{ + if (child) + t = JSON_FindChild(t, child); + if (t) + { //copy it to another buffer. can probably skip that tbh. + size_t l = t->bodyend-t->bodystart; + if (l > buffersize-1) + l = buffersize-1; + memcpy(buffer, t->bodystart, l); + buffer[l] = 0; + return buffer; + } + return fallback; +} static void JSON_GetPath(json_t *t, qboolean ignoreroot, char *buffer, size_t buffersize) { @@ -510,6 +526,13 @@ static size_t JSON_ReadBody(json_t *t, char *out, size_t outsize) return t->bodyend-t->bodystart; } + + + + + + + //glTF 1.0 and 2.0 differ in that 1 uses names and 2 uses indexes. There's also some significant differences with materials. //we only support 2.0 @@ -524,6 +547,11 @@ struct gltf_buffer void *data; size_t length; }; +struct galiasbone_gltf_s +{ //stored in galiasinfo_t->ctx + double rmatrix[16]; //gah + double quat[4], scale[3], trans[3]; //annoying smeg +}; typedef struct gltf_s { struct model_s *mod; @@ -538,11 +566,7 @@ typedef struct gltf_s int camera; double amatrix[16]; double inverse[16]; - struct - { - double rmatrix[16]; //gah - double quat[4], scale[3], trans[3]; //annoying smeg - } rel; + struct galiasbone_gltf_s rel; struct { struct gltf_accessor *input; @@ -644,7 +668,7 @@ static struct gltf_buffer *GLTF_GetBufferData(gltf_t *gltf, int bufferidx) char filename[MAX_QPATH]; JSON_ReadBody(uri, uritext, sizeof(uritext)); GLTF_RelativePath(gltf->mod->name, uritext, filename, sizeof(filename)); - f = modfuncs->OpenVFS(filename, "rb", FS_GAME); + f = filefuncs->OpenVFS(filename, "rb", FS_GAME); if (f) { out->length = VFS_GETLEN(f); @@ -775,8 +799,8 @@ static qboolean GLTF_GetAccessor(gltf_t *gltf, int accessorid, struct gltf_acces maxs = JSON_FindChild(a, "max"); for (j = 0; j < (out->type>>8)*(out->type&0xff); j++) { //'must' be set in various situations. - out->mins[j] = JSON_GetIndexedInteger(mins, j, 0); - out->maxs[j] = JSON_GetIndexedInteger(maxs, j, 0); + out->mins[j] = JSON_GetIndexedFloat(mins, j, 0); + out->maxs[j] = JSON_GetIndexedFloat(maxs, j, 0); } // JSON_WarnIfChild(a, "sparse"); @@ -1125,29 +1149,61 @@ static texid_t GLTF_LoadTexture(gltf_t *gltf, int texture, unsigned int flags) JSON_FlagAsUsed(sampler, "name"); JSON_FlagAsUsed(sampler, "extensions"); - (void)minFilter; switch(magFilter) { default: break; case 9728: //NEAREST flags |= IF_NOMIPMAP|IF_NEAREST; + if (minFilter != 9728) + if (gltf->warnlimit --> 0) + Con_Printf(CON_WARNING"%s: mixed min/mag filters\n", gltf->mod->name); break; + case 9986: // NEAREST_MIPMAP_LINEAR + if (gltf->warnlimit --> 0) + Con_Printf(CON_WARNING"%s: mixed mag/mip filters\n", gltf->mod->name); + //fallthrough + case 9984: // NEAREST_MIPMAP_NEAREST + flags |= IF_NEAREST; + if (minFilter != 9728) + if (gltf->warnlimit --> 0) + Con_Printf(CON_WARNING"%s: mixed min/mag filters\n", gltf->mod->name); + break; + case 9729: //LINEAR flags |= IF_NOMIPMAP|IF_LINEAR; - break; - case 9984: // NEAREST_MIPMAP_NEAREST - case 9986: // NEAREST_MIPMAP_LINEAR - flags |= IF_NEAREST; + if (minFilter != 9729) + if (gltf->warnlimit --> 0) + Con_Printf(CON_WARNING"%s: mixed min/mag filters\n", gltf->mod->name); break; case 9985: // LINEAR_MIPMAP_NEAREST + if (gltf->warnlimit --> 0) + Con_Printf(CON_WARNING"%s: mixed mag/mip filters\n", gltf->mod->name); + //fallthrough case 9987: // LINEAR_MIPMAP_LINEAR flags |= IF_LINEAR; + if (minFilter != 9729) + if (gltf->warnlimit --> 0) + Con_Printf(CON_WARNING"%s: mixed min/mag filters\n", gltf->mod->name); break; } - - if (wrapS == 33071 || wrapT == 33071) + if (wrapS == 10497 && wrapT == 10497) //REPEAT + ; + else if (wrapS == 33071 && wrapT == 33071) //CLAMP_TO_EDGE flags |= IF_CLAMP; + else if (wrapS == 33648 && wrapT == 33648) //MIRRORED_REPEAT + { + if (gltf->warnlimit --> 0) + Con_Printf(CON_WARNING"%s: MIRRORED_REPEAT wrap mode not supported\n", gltf->mod->name); + } + else + { + if (gltf->warnlimit --> 0) + Con_Printf(CON_WARNING"%s: unsupported/mixed texture wrap modes %i,%i\n", gltf->mod->name, wrapS, wrapT); + + if (wrapS == 33071 || wrapT == 33071) + flags |= IF_CLAMP; + } flags |= IF_NOREPLACE; @@ -1164,6 +1220,8 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, int material, qboolean vert char alphaCutoffmodifier[128]; json_t *mat = JSON_FindIndexedChild(gltf->r, "materials", material); galiasskin_t *ret; + char tmp[64]; + const char *t; json_t *nam, *unlit, *pbrsg, *pbrmr, *blinn; @@ -1175,12 +1233,19 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, int material, qboolean vert doubleSided = JSON_GetInteger(mat, "doubleSided", false); alphaCutoff = JSON_GetFloat(mat, "alphaCutoff", 0.5); - if (JSON_Equals(mat, "alphaMode", "MASK")) + t = JSON_GetString(mat, "alphaMode", tmp, sizeof(tmp), "OPAQUE"); + if (!strcmp(t, "MASK")) alphaMode = 1; - else if (JSON_Equals(mat, "alphaMode", "BLEND")) + else if (!strcmp(t, "BLEND")) alphaMode = 2; - else //if (JSON_Equals(mat, "alphaMode", "OPAQUE")) + else if (!strcmp(t, "OPAQUE")) alphaMode = 0; + else + { + alphaMode = 0; + if (gltf->warnlimit --> 0) + Con_Printf(CON_WARNING"%s: unsupported alphaMode: %s\n", gltf->mod->name, t); + } ret = modfuncs->ZG_Malloc(&gltf->mod->memgroup, sizeof(*ret)); ret->numframes = 1; @@ -1271,13 +1336,16 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, int material, qboolean vert } else if (pbrsg) { //if this extension was used, then we can use rgb gloss instead of metalness stuff. + int occ = JSON_GetInteger(mat, "occlusionTexture.index", -1); //.r ret->frame->texnums.base = GLTF_LoadTexture(gltf, JSON_GetInteger(pbrsg, "diffuseTexture.index", -1), 0); ret->frame->texnums.specular = GLTF_LoadTexture(gltf, JSON_GetInteger(pbrsg, "specularGlossinessTexture.index", -1), 0); + if (occ != -1) + ret->frame->texnums.occlusion = GLTF_LoadTexture(gltf, occ, IF_NOSRGB); Q_snprintf(shader, sizeof(shader), "{\n" "%s"//cull - "program defaultskin#SG#VC#NOOCCLUDE%s\n" + "program defaultskin#SG#VC%s%s\n" "{\n" "map $diffuse\n" "%s" //blend @@ -1289,6 +1357,7 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, int material, qboolean vert "bemode rtlight rtlight_sg\n" "}\n", doubleSided?"cull disable\n":"", + (occ!=-1)?"#OCCLUDE":"", alphaCutoffmodifier, (alphaMode==1)?"":(alphaMode==2)?"blendfunc blend\n":"", vertexcolours?"rgbgen vertex\nalphagen vertex\n":"", @@ -1299,7 +1368,7 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, int material, qboolean vert JSON_GetFloat(pbrsg, "specularFactor.0", 1), JSON_GetFloat(pbrsg, "specularFactor.1", 1), JSON_GetFloat(pbrsg, "specularFactor.2", 1), - JSON_GetFloat(pbrsg, "glossinessFactor", 1)*32, //this is fucked. + JSON_GetFloat(pbrsg, "glossinessFactor", 1), JSON_GetFloat(mat, "emissiveFactor.0", 0), JSON_GetFloat(mat, "emissiveFactor.1", 0), JSON_GetFloat(mat, "emissiveFactor.2", 0) @@ -1315,12 +1384,9 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, int material, qboolean vert occ = JSON_GetInteger(mat, "extensions.MSFT_packing_occlusionRoughnessMetallic.occlusionRoughnessMetallicTexture.index", occ); mrt = JSON_GetInteger(mat, "extensions.MSFT_packing_occlusionRoughnessMetallic.occlusionRoughnessMetallicTexture.index", mrt); - if (occ != mrt && occ != -1) //if its -1 then the mrt should have an unused channel set to 1. however, this isn't guarenteed... - { - occ = -1; //not supported. fixme: support some weird loadtexture channel merging stuff - if (gltf->warnlimit --> 0) - Con_Printf(CON_WARNING"%s: Separate occlusion and metallicRoughness textures are not supported\n", gltf->mod->name); - } + //ideally we use the ORM.r for the occlusion map, but some people just love being annoying. + if (occ != mrt && occ != -1) + ret->frame->texnums.occlusion = GLTF_LoadTexture(gltf, occ, IF_NOSRGB); //note: extensions.MSFT_packing_normalRoughnessMetallic.normalRoughnessMetallicTexture.index gives rg=normalxy, b=roughness, .a=metalic //(would still need an ao map, and probably wouldn't work well as bc3 either) @@ -1343,7 +1409,7 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, int material, qboolean vert "bemode rtlight rtlight_orm\n" "}\n", doubleSided?"cull disable\n":"", - (occ==-1)?"#NOOCCLUDE":"", + (occ==-1)?"#NOOCCLUDE":((occ!=mrt)?"#OCCLUDE":""), alphaCutoffmodifier, (alphaMode==1)?"":(alphaMode==2)?"blendfunc blend\n":"", vertexcolours?"rgbgen vertex\nalphagen vertex\n":"", @@ -1781,23 +1847,58 @@ static qboolean GLTF_ProcessNode(gltf_t *gltf, int nodeidx, double pmatrix[16], struct gltf_animsampler { - struct gltf_accessor input; - struct gltf_accessor output; + enum { + AINTERP_LINEAR, //(s)lerp + AINTERP_STEP, //round down + AINTERP_CUBICSPLINE, //3 outputs per input, requires at least two inputs. messy. + } interptype; + struct gltf_accessor input; //timestamps + struct gltf_accessor output; //values }; +static void GLTF_Animation_Persist(gltf_t *gltf, struct gltf_accessor *accessor) +{ + model_t *mod = gltf->mod; + qbyte *newdata = modfuncs->ZG_Malloc(&mod->memgroup, accessor->length); + memcpy(newdata, accessor->data, accessor->length); + accessor->data = newdata; +} static struct gltf_animsampler GLTF_AnimationSampler(gltf_t *gltf, json_t *samplers, int sampleridx, int elems) { + int outsperinput=1; struct gltf_animsampler r; json_t *sampler = JSON_FindIndexedChild(samplers, NULL, sampleridx); + char t[32]; + const char *lerptype = JSON_GetString(sampler, "interpolation", t, sizeof(t), "LINEAR"); + if (!strcmp(lerptype, "LINEAR")) + r.interptype = AINTERP_LINEAR; + else if (!strcmp(lerptype, "STEP")) + r.interptype = AINTERP_STEP; + else if (!strcmp(lerptype, "CUBICSPLINE")) + { + outsperinput = 3; + r.interptype = AINTERP_CUBICSPLINE; + } + else + { + Con_Printf("Unknown interpolation type %s\n", lerptype); + r.interptype = AINTERP_LINEAR; + } + GLTF_GetAccessor(gltf, JSON_GetInteger(sampler, "input", -1), &r.input); GLTF_GetAccessor(gltf, JSON_GetInteger(sampler, "output", -1), &r.output); - if (!r.input.data || !r.output.data || r.input.count != r.output.count) + if (!r.input.data || !r.output.data || r.input.count*outsperinput != r.output.count) memset(&r, 0, sizeof(r)); + else + { + GLTF_Animation_Persist(gltf, &r.input); + GLTF_Animation_Persist(gltf, &r.output); + } return r; } -static float Anim_GetTime(struct gltf_accessor *in, int index) +static float Anim_GetTime(const struct gltf_accessor *in, int index) { //read the input sampler (to get timestamps) switch(in->componentType) @@ -1815,11 +1916,11 @@ static float Anim_GetTime(struct gltf_accessor *in, int index) case 5126: //FLOAT return *(float*)((qbyte*)in->data + in->bytestride*index); default: - Con_Printf("Unsupported input component type\n"); + Con_Printf("Unsupported input component type %i\n", in->componentType); return 0; } } -static void Anim_GetVal(struct gltf_accessor *in, int index, float *result, int elems) +static void Anim_GetVal(const struct gltf_accessor *in, int index, float *result, int elems) { //read the input sampler (to get timestamps) switch(in->componentType) @@ -1849,58 +1950,136 @@ static void Anim_GetVal(struct gltf_accessor *in, int index, float *result, int result[elems] = ((float*)((qbyte*)in->data + in->bytestride*index))[elems]; break; default: - Con_Printf("Unsupported output component type\n"); + Con_Printf("Unsupported output component type %i\n", in->componentType); break; } } -static void LerpAnimData(gltf_t *gltf, struct gltf_animsampler *samp, float time, float *result, int elems) +static void QuaternionSlerp_(const vec4_t p, const vec4_t q, float t, vec4_t qt) { - float t1, t2; - float w1, w2; - float v1[4], v2[4]; - int f1 = 0, f2, c; + int i; + float omega, cosom, sinom, sclp, sclq; + vec4_t flipped; - struct gltf_accessor *in = &samp->input; - struct gltf_accessor *out = &samp->output; + // decide if one of the quaternions is backwards + float a = 0; + float b = 0; + for (i = 0; i < 4; i++) { + a += (p[i]-q[i])*(p[i]-q[i]); + b += (p[i]+q[i])*(p[i]+q[i]); + } + if (a > b) { + for (i = 0; i < 4; i++) { + flipped[i] = -q[i]; + } + q = flipped; + } - t1 = t2 = Anim_GetTime(in, f1); - for (f2 = 1; f2 < in->count; f2++) + cosom = p[0]*q[0] + p[1]*q[1] + p[2]*q[2] + p[3]*q[3]; + + if ((1.0 + cosom) > 0.00000001) { + if ((1.0 - cosom) > 0.00000001) { + omega = acos( cosom ); + sinom = sin( omega ); + sclp = sin( (1.0 - t)*omega) / sinom; + sclq = sin( t*omega ) / sinom; + } + else { + sclp = 1.0 - t; + sclq = t; + } + for (i = 0; i < 4; i++) { + qt[i] = sclp * p[i] + sclq * q[i]; + } + } + else { + qt[0] = -p[1]; + qt[1] = p[0]; + qt[2] = -p[3]; + qt[3] = p[2]; + sclp = sin( (1.0 - t) * 0.5 * M_PI); + sclq = sin( t * 0.5 * M_PI); + for (i = 0; i < 4; i++) { + qt[i] = sclp * p[i] + sclq * qt[i]; + } + } +} +static void LerpAnimData(const struct gltf_animsampler *samp, float time, float *result, int elems) +{ + float t0, t1; + float w0, w1; + float v0[4], v1[4]; + int f0, f1, c; + + const struct gltf_accessor *in = &samp->input; + const struct gltf_accessor *out = &samp->output; + + t0 = t1 = Anim_GetTime(in, f1=f0=0); + while (time > t1 && f1 < in->count-1) { - t2 = Anim_GetTime(in, f2); - if (t2 > time) - break; //now have before and after - t1 = t2; - f1 = f2; + t0 = t1; + f0 = f1; + f1++; + t1 = Anim_GetTime(in, f1); } - if (time <= t1) - { //if before the first time, clamp it. - w1 = 1; - w2 = 0; - } - else if (time >= t2) - { //if after tha last frame we could find, clamp it to the last. - w1 = 0; - w2 = 1; - } - else - { //assume linear - w2 = (time-t1)/(t2-t1); -// if (1) //step it. it'll still get lerped though. :( -// w2 = (w2>0.5)?1:0; - w1 = 1-w2; - } - - if (w1 >= 1) - Anim_GetVal(out, f1, result, elems); - else if (w2 >= 1) - Anim_GetVal(out, f2, result, elems); - else + if (samp->interptype == AINTERP_CUBICSPLINE) { - Anim_GetVal(out, f1, v1, elems); - Anim_GetVal(out, f2, v2, elems); + float step=t1-t0; + float t=bound(0, (time-t0)/step, 1); + float tt=t*t, ttt=tt*t; + //Hermite spline factors + float m0 = (2*ttt - 3*tt + 1); + float mb = (ttt - 2*tt + t)*step; + float m1 = (-2*ttt + 3*tt); + float ma = (ttt - tt)*step; + float a[4], b[4]; + + //get the relevant tangents+sample values + //When used with CUBICSPLINE interpolation, tangents (ak, bk) and values (vk) are grouped within keyframes: + //a1,a2,...an,v1,v2,...vn,b1,b2,...bn + //so ignore that and use avb,avb,avb groups... + Anim_GetVal(out, f1*3+0, a, elems); + Anim_GetVal(out, f0*3+1, v0, elems); + Anim_GetVal(out, f1*3+1, v1, elems); + Anim_GetVal(out, f0*3+2, b, elems); + + //and compute the spline. for (c = 0; c < elems; c++) - result[c] = v1[c]*w1 + w2*v2[c]; + result[c] = m0*v0[c] + mb*b[c] + m1*v1[c] + ma*a[c]; + + //quats must be normalized. + if (elems == 4) + { + float len = sqrt(DotProduct4(result,result)); + Vector4Scale(result, 1/len, result); + } + return; + } + else if (time <= t0) //if before the first time, clamp it. + w1 = 0; + else if (time >= t1) //if after tha last frame we could find, clamp it to the last. + w1 = 1; + else if (samp->interptype == AINTERP_LINEAR) + w1 = (time-t0)/(t1-t0); + else //if (samp->interptype == AINTERP_STEP) + w1 = 0; + + if (w1 <= 0) + Anim_GetVal(out, f0, result, elems); + else if (w1 >= 1) + Anim_GetVal(out, f1, result, elems); + else + { + Anim_GetVal(out, f0, v0, elems); + Anim_GetVal(out, f1, v1, elems); + if (elems == 4) + QuaternionSlerp_(v0, v1, w1, result); + else + { + w0 = 1-w1; + for (c = 0; c < elems; c++) + result[c] = v0[c]*w0 + w1*v1[c]; + } } } @@ -1953,6 +2132,63 @@ static void GLTF_RewriteBoneTree(gltf_t *gltf) } } +struct galiasanimation_gltf_s +{ //stored in galiasanimation_t->boneofs + float duration; + struct + { + struct gltf_animsampler rot,scale,trans; + } bone[1]; +}; +static float *QDECL GLTF_AnimateBones(const galiasinfo_t *surf, const galiasanimation_t *anim, float time, float *bonematrix, int numbones) +{ + const struct galiasbone_gltf_s *defbone = surf->ctx; + int j = 0, l; + const struct galiasanimation_gltf_s *a = anim->boneofs; + + if (anim->loop && time >= a->duration) + time = time - a->duration*floor(time/a->duration); + + for (j = 0; j < numbones; j++, bonematrix+=12) + { + float scale[3]; + float rot[4]; + float trans[3]; + //eww, weird inheritance crap. + if (a->bone[j].rot.input.data || a->bone[j].scale.input.data || a->bone[j].trans.input.data) + { + VectorCopy(defbone[j].scale, scale); + Vector4Copy(defbone[j].quat, rot); + VectorCopy(defbone[j].trans, trans); + + if (a->bone[j].rot.input.data) + LerpAnimData(&a->bone[j].rot, time, rot, 4); + if (a->bone[j].scale.input.data) + LerpAnimData(&a->bone[j].scale, time, scale, 3); + if (a->bone[j].trans.input.data) + LerpAnimData(&a->bone[j].trans, time, trans, 3); + //figure out the bone matrix... + modfuncs->GenMatrixPosQuat4Scale(trans, rot, scale, bonematrix); + } + else + { //nothing animated, use what we calculated earlier. + for (l = 0; l < 12; l++) + bonematrix[l] = defbone[j].rmatrix[l]; + } + if (surf->ofsbones[j].parent < 0) + { //rotate any root bones from gltf to quake's orientation. + float fnar[12]; + static float toquake[12]={ + 0,0,GLTFSCALE, 0, + GLTFSCALE,0,0, 0, + 0,GLTFSCALE,0, 0}; + memcpy(fnar, bonematrix, sizeof(fnar)); + modfuncs->ConcatTransforms((void*)toquake, (void*)fnar, (void*)bonematrix); + } + } + return bonematrix - j*12; +} + //okay, so gltf is some weird scene thing. //mostly there should be some default scene, so we'll just use that. //we do NOT supported nested nodes right now... @@ -1982,6 +2218,7 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize, galiasanimation_t *framegroups = NULL; unsigned int numframegroups = 0; float *baseframe; + struct galiasbone_gltf_s *gltfbone; memset(&gltf, 0, sizeof(gltf)); gltf.bonemap = malloc(sizeof(*gltf.bonemap)*MAX_BONES); gltf.bones = malloc(sizeof(*gltf.bones)*MAX_BONES); @@ -2088,6 +2325,7 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize, GLTF_RewriteBoneTree(&gltf); + gltfbone = modfuncs->ZG_Malloc(&mod->memgroup, sizeof(*gltfbone)*gltf.numbones); bone = modfuncs->ZG_Malloc(&mod->memgroup, sizeof(*bone)*gltf.numbones); baseframe = modfuncs->ZG_Malloc(&mod->memgroup, sizeof(float)*12*gltf.numbones); for (j = 0; j < gltf.numbones; j++) @@ -2103,16 +2341,13 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize, baseframe[j*12+k] = gltf.bones[j].amatrix[k]; bone[j].inverse[k] = gltf.bones[j].inverse[k]; } + gltfbone[j] = gltf.bones[j].rel; } for(anim = JSON_FindIndexedChild(gltf.r, "animations", 0); anim; anim = anim->sibling) numframegroups++; if (numframegroups) { - struct - { - struct gltf_animsampler rot,scale,trans; - } *b = malloc(sizeof(*b)*gltf.numbones); framegroups = modfuncs->ZG_Malloc(&mod->memgroup, sizeof(*framegroups)*numframegroups); for (k = 0; k < numframegroups; k++) { @@ -2120,9 +2355,9 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize, json_t *anim = JSON_FindIndexedChild(gltf.r, "animations", k); json_t *chan; json_t *samps = JSON_FindChild(anim, "samplers"); - int f, l; +// int f, l; float maxtime = 0; - memset(b, 0, sizeof(*b)*gltf.numbones); + struct galiasanimation_gltf_s *a = modfuncs->ZG_Malloc(&mod->memgroup, sizeof(*a)+sizeof(a->bone[0])*(gltf.numbones-1)); if (!JSON_ReadBody(JSON_FindChild(anim, "name"), fg->name, sizeof(fg->name))) { @@ -2152,11 +2387,11 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize, s = GLTF_AnimationSampler(&gltf, samps, sampler, 4); maxtime = max(maxtime, s.input.maxs[0]); if (JSON_Equals(path, NULL, "rotation")) - b[bone].rot = s; + a->bone[bone].rot = s; else if (JSON_Equals(path, NULL, "scale")) - b[bone].scale = s; + a->bone[bone].scale = s; else if (JSON_Equals(path, NULL, "translation")) - b[bone].trans = s; + a->bone[bone].trans = s; else if (gltf.warnlimit --> 0) { //these are unsupported if (JSON_Equals(path, NULL, "weights")) //morph weights @@ -2166,6 +2401,8 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize, } } + a->duration = maxtime; + //TODO: make a guess at the framerate according to sampler intervals fg->rate = 60; fg->numposes = max(1, maxtime*fg->rate); @@ -2173,6 +2410,9 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize, fg->rate = fg->numposes/maxtime; //fix up the rate so we hit the exact end of the animation (so it doesn't have to be quite so exact). fg->skeltype = SKEL_RELATIVE; + fg->GetRawBones = GLTF_AnimateBones; + fg->boneofs = a; +#if 0 fg->boneofs = modfuncs->ZG_Malloc(&mod->memgroup, sizeof(*fg->boneofs)*12*gltf.numbones*fg->numposes); for (f = 0; f < fg->numposes; f++) @@ -2192,11 +2432,11 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize, VectorCopy(gltf.bones[j].rel.trans, trans); if (b[j].rot.input.data) - LerpAnimData(&gltf, &b[j].rot, time, rot, 4); + LerpAnimData(&b[j].rot, time, rot, 4); if (b[j].scale.input.data) - LerpAnimData(&gltf, &b[j].scale, time, scale, 3); + LerpAnimData(&b[j].scale, time, scale, 3); if (b[j].trans.input.data) - LerpAnimData(&gltf, &b[j].trans, time, trans, 3); + LerpAnimData(&b[j].trans, time, trans, 3); //figure out the bone matrix... modfuncs->GenMatrixPosQuat4Scale(trans, rot, scale, bonematrix); } @@ -2214,8 +2454,8 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize, } } } +#endif } - free(b); } for(surf = mod->meshinfo; surf; surf = surf->nextsurf) @@ -2223,6 +2463,7 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize, surf->shares_bones = 0; surf->numbones = gltf.numbones; surf->ofsbones = bone; + surf->ctx = gltfbone; surf->baseframeofs = baseframe; surf->ofsanimations = framegroups; surf->numanimations = numframegroups; diff --git a/plugins/models/models.c b/plugins/models/models.c index 58af7b4ee..68ff16cb5 100644 --- a/plugins/models/models.c +++ b/plugins/models/models.c @@ -4,7 +4,8 @@ #include "quakedef.h" #include "../plugin.h" #include "com_mesh.h" -modplugfuncs_t *modfuncs; +plugmodfuncs_t *modfuncs; +plugfsfuncs_t *filefuncs; //#define ASEMODELS //FIXME: TEST TEST TEST. shold be working iiuc //#define LWOMODELS //not working @@ -812,21 +813,39 @@ static qboolean QDECL Mod_LoadLWOModel (struct model_s *mod, void *buffer, size_ } #endif -qboolean QDECL Mod_LoadGLTFModel (struct model_s *mod, void *buffer, size_t fsize); -qboolean QDECL Mod_LoadGLBModel (struct model_s *mod, void *buffer, size_t fsize); +extern qboolean QDECL Mod_LoadGLTFModel (struct model_s *mod, void *buffer, size_t fsize); +extern qboolean QDECL Mod_LoadGLBModel (struct model_s *mod, void *buffer, size_t fsize); +extern void Mod_ExportIQM(char *fname, int flags, galiasinfo_t *mesh); -qintptr_t Plug_Init(qintptr_t *args) +qboolean Mod_ExecuteCommand(qboolean isinsecure) { - CHECKBUILTIN(Mod_GetPluginModelFuncs); - - if (BUILTINISVALID(Mod_GetPluginModelFuncs)) + char tok[128]; + cmdfuncs->Argv(0, tok, sizeof(tok)); + if (!strcmp(tok, "exportiqm")) { - modfuncs = pMod_GetPluginModelFuncs(sizeof(modplugfuncs_t)); - if (modfuncs && modfuncs->version < MODPLUGFUNCS_VERSION) - modfuncs = NULL; + model_t *mod; + cmdfuncs->Argv(1, tok, sizeof(tok)); + mod = modfuncs->GetModel(tok, true); + if (!mod || mod->type != mod_alias || !mod->meshinfo) + Con_Printf("Couldn't load \"%s\"\n", tok); + else + { + cmdfuncs->Argv(2, tok, sizeof(tok)); + Mod_ExportIQM(tok, mod->flags, mod->meshinfo); + } + return true; } + return false; +} - if (modfuncs) +qboolean Plug_Init(void) +{ + filefuncs = plugfuncs->GetEngineInterface(plugfsfuncs_name, sizeof(*filefuncs)); + modfuncs = plugfuncs->GetEngineInterface(plugmodfuncs_name, sizeof(*modfuncs)); + if (modfuncs && modfuncs->version < MODPLUGFUNCS_VERSION) + modfuncs = NULL; + + if (modfuncs && filefuncs) { #ifdef ASEMODELS modfuncs->RegisterModelFormatText("ASE models (ase)", "*3DSMAX_ASCIIEXPORT", Mod_LoadASEModel); @@ -838,6 +857,9 @@ qintptr_t Plug_Init(qintptr_t *args) modfuncs->RegisterModelFormatText("glTF2 models (glTF)", ".gltf", Mod_LoadGLTFModel); modfuncs->RegisterModelFormatMagic("glTF2 models (glb)", (('F'<<24)+('T'<<16)+('l'<<8)+'g'), Mod_LoadGLBModel); #endif + + plugfuncs->ExportFunction("ExecuteCommand", Mod_ExecuteCommand); + cmdfuncs->AddCommand("exportiqm"); return true; } return false; diff --git a/plugins/mpq/fs_mpq.c b/plugins/mpq/fs_mpq.c index e3c3bcced..42dde3f40 100644 --- a/plugins/mpq/fs_mpq.c +++ b/plugins/mpq/fs_mpq.c @@ -11,6 +11,7 @@ //http://www.zezula.net/en/mpq/main.html //http://www.wc3c.net/tools/specs/QuantamMPQFormat.txt +size_t activempqcount; //number of active archives. we can't unload the dll while we still have files open. #ifdef MULTITHREAD threading_t *threading; #define Sys_CreateMutex threading->CreateMutex @@ -273,6 +274,7 @@ static void MPQ_ClosePath(searchpathfuncs_t *handle) free(mpq->hashdata); free(mpq->listfile); free(mpq); + activempqcount--; } static unsigned int MPQ_FindFile(searchpathfuncs_t *handle, flocation_t *loc, const char *name, void *hashedresult) { @@ -517,7 +519,7 @@ static searchpathfuncs_t *MPQ_OpenArchive(vfsfile_t *file, const char *desc, con ); }*/ - + activempqcount++; mpq->references = 1; mpq->mutex = Sys_CreateMutex(); @@ -886,7 +888,12 @@ static vfsfile_t *MPQ_OpenVFS(searchpathfuncs_t *handle, flocation_t *loc, const return &f->funcs; } -qintptr_t Plug_Init(qintptr_t *args) +qboolean MPQ_MayShutdown(void) +{ + return activempqcount==0; +} + +qboolean Plug_Init(void) { mpq_init_cryptography(); @@ -902,14 +909,14 @@ qintptr_t Plug_Init(qintptr_t *args) //we can't cope with being closed randomly. files cannot be orphaned safely. //so ask the engine to ensure we don't get closed before everything else is. - pPlug_ExportNative("UnsafeClose", NULL); + pPlug_ExportFunction("MayShutdown", NULL); - if (!pPlug_ExportNative("FS_RegisterArchiveType_mpq", MPQ_OpenArchive)) + if (!pPlug_ExportFunction("FS_RegisterArchiveType_mpq", MPQ_OpenArchive)) { Con_Printf("mpq: Engine doesn't support filesystem plugins\n"); return false; } - if (!pPlug_ExportNative("FS_RegisterArchiveType_MPQ", MPQ_OpenArchive)) + if (!pPlug_ExportFunction("FS_RegisterArchiveType_MPQ", MPQ_OpenArchive)) { Con_Printf("mpq: Engine doesn't support filesystem plugins\n"); return false; diff --git a/plugins/namemaker/Makefile b/plugins/namemaker/Makefile deleted file mode 100644 index 308cc8656..000000000 --- a/plugins/namemaker/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -LCC_FLAGS=-DQ3_VM -S -Wf-target=bytecode -Wf-g - -qvm: - lcc $(LCC_FLAGS) namemaker.c; lcc $(LCC_FLAGS) ../plugin.c; lcc $(LCC_FLAGS) ../qvm_api.c; q3asm -f namemaker -clean: - rm -rf $(OBJECTS) $(OUTFILE) *.qvm *.asm diff --git a/plugins/namemaker/compile.bat b/plugins/namemaker/compile.bat deleted file mode 100644 index 26e5e6e85..000000000 --- a/plugins/namemaker/compile.bat +++ /dev/null @@ -1,20 +0,0 @@ -@echo off -call ..\paths.bat - -del vm\*.asm -rmdir vm -mkdir vm -cd vm -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../namemaker.c -if errorlevel 1 goto end -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../plugin.c -if errorlevel 1 goto end -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../qvm_api.c -if errorlevel 1 goto end -q3asm -f ../namemaker - -:end - -cd .. - -pause \ No newline at end of file diff --git a/plugins/namemaker/namemaker.c b/plugins/namemaker/namemaker.c index 2bce99506..f48dc06eb 100644 --- a/plugins/namemaker/namemaker.c +++ b/plugins/namemaker/namemaker.c @@ -1,54 +1,80 @@ #include "../plugin.h" -int K_UPARROW; -int K_DOWNARROW; -int K_LEFTARROW; -int K_RIGHTARROW; -int K_ESCAPE; -int K_MOUSE1; -int K_MOUSE2; -int K_HOME; -int K_SHIFT; -int K_MWHEELDOWN; -int K_MWHEELUP; -int K_PAGEUP; -int K_PAGEDOWN; -int K_BACKSPACE; +extern plugcorefuncs_t *plugfuncs; +extern plugcmdfuncs_t *cmdfuncs; +extern plugcvarfuncs_t *cvarfuncs; +static plug2dfuncs_t *drawfuncs; +static pluginputfuncs_t *inputfuncs; -qhandle_t con_chars; -qhandle_t pic_cursor; +static int K_UPARROW; +static int K_DOWNARROW; +static int K_LEFTARROW; +static int K_RIGHTARROW; +static int K_ESCAPE; +static int K_ENTER; +static int K_KP_ENTER; +static int K_MOUSE1; +static int K_MOUSE2; +static int K_HOME; +static int K_SHIFT; +static int K_MWHEELDOWN; +static int K_MWHEELUP; +static int K_PAGEUP; +static int K_PAGEDOWN; +static int K_BACKSPACE; -float drawscalex; -float drawscaley; +static qhandle_t con_chars; +static qhandle_t pic_cursor; -unsigned char namebuffer[256]; -int insertpos; -unsigned int currenttime; +static float drawscalex; +static float drawscaley; -void LoadPics(void) +static unsigned char namebuffer[256]; +static int insertpos; + +static void LoadPics(void) { char buffer[256]; //main bar (add cvars later) - con_chars = Draw_LoadImage("conchars", false); - Cvar_GetString("cl_cursor", buffer, sizeof(buffer)); + con_chars = drawfuncs->LoadImage("gfx/conchars.lmp", false); + cvarfuncs->GetString("cl_cursor", buffer, sizeof(buffer)); if (*buffer) - pic_cursor = Draw_LoadImage(buffer, false); + pic_cursor = drawfuncs->LoadImage(buffer, false); else - pic_cursor = NULL; + pic_cursor = 0; } -void DrawChar(unsigned int c, int x, int y) +static void DrawChar(unsigned int c, int x, int y) { -static float size = 1.0f/16.0f; + static const float size = 1.0f/16.0f; float s1 = size * (c&15); float t1 = size * (c>>4); - Draw_Image((float)x*drawscalex, y*drawscaley, 16*drawscalex, 16*drawscaley, s1, t1, s1+size, t1+size, con_chars); +// drawfuncs->Character(x, y, 0xe000|c); + drawfuncs->Image((float)x*drawscalex, y*drawscaley, 16*drawscalex, 16*drawscaley, s1, t1, s1+size, t1+size, con_chars); } -void InsertChar(int newchar) +static qboolean AllowedChar(int c) +{ + //normalise away any unicode chars... + if (c >= 0xe000 && c <= 0xe0ff) + c &= 0xff; + + if (c < 0x00 || c > 0xff) + return false; //not a byte + + if (c == 0) return false; //block null chars + if (c == '\\') return false; //invalid in infokeys + if (c == '\"') return false; //breaks string escapes + if (c == 255) return false; //block this byte, as it causes illegible server messages in vanilla + + return true; //other chars are okay. +} +static void InsertChar(int newchar) { int oldlen; + if (!AllowedChar(newchar)) + return; oldlen = strlen(namebuffer); if (oldlen + 1 == sizeof(namebuffer)) @@ -60,14 +86,17 @@ void InsertChar(int newchar) namebuffer[insertpos++] = newchar; } -void KeyPress(int key, int mx, int my) +static void KeyPress(int key, int unicode, int mx, int my) { - int newchar; int oldlen; - if (key == K_ESCAPE) + if (!key) + ; //invalid keys... + else if (key == K_ESCAPE) + inputfuncs->SetMenuFocus(false, NULL, 0, 0, 0); //release input focus + else if (key == K_ENTER || key == K_KP_ENTER) { - Menu_Control(0); - Cvar_SetString("name", (char*)namebuffer); + inputfuncs->SetMenuFocus(false, NULL, 0, 0, 0); //release input focus + cvarfuncs->SetString("name", (char*)namebuffer); } else if (key == K_MOUSE1) { @@ -75,10 +104,10 @@ void KeyPress(int key, int mx, int my) my -= 16; mx /= (480-16)/16; my /= (480-16)/16; + if (mx < 0 || my < 0 || mx >= 16 || my >= 16) + return; //outside the grid - newchar = (int)mx + (int)my * 16; - - InsertChar(newchar); + InsertChar(mx + my*16); } else if (key == K_MOUSE2 || key == K_BACKSPACE) { @@ -101,38 +130,35 @@ void KeyPress(int key, int mx, int my) } else if (key == K_SHIFT) return; - else if (key > 0 && key < 255) - InsertChar(key); + else if ((unicode >= 0x20 && unicode <= 0x7f) || (unicode >= 0xe000 && unicode <= 0xe0ff)) + InsertChar(unicode); } -int Plug_MenuEvent(int *args) +static qboolean QDECL Plug_MenuEvent(int eventtype, int param, int unicode, float mousecursor_x, float mousecursor_y, float vidwidth, float vidheight) { int i; - float cbias; - drawscalex = vid.width/640.0f; - drawscaley = vid.height/480.0f; + quintptr_t currenttime; + drawscalex = vidwidth/640.0f; + drawscaley = vidheight/480.0f; - args[2]=(int)(args[2]/drawscalex); - args[3]=(int)(args[3]/drawscaley); + mousecursor_x /= drawscalex; + mousecursor_y /= drawscaley; - switch(args[0]) + switch(eventtype) { case 0: //draw + currenttime = plugfuncs->GetMilliseconds(); - Draw_Colour4f(1,1,1,1); + drawfuncs->Colour4f(1,1,1,1); - Draw_Image(((640 - (480-16))/2)*drawscalex, 16*drawscaley, (480-16)*drawscalex, (480-16)*drawscaley, 0, 0, 1, 1, con_chars); + drawfuncs->Image(((640 - (480-16))/2)*drawscalex, 16*drawscaley, (480-16)*drawscalex, (480-16)*drawscaley, 0, 0, 1, 1, con_chars); for (i = 0; namebuffer[i]; i++) DrawChar(namebuffer[i], i*16, 0); DrawChar(10 + (((currenttime/250)&1)==1), insertpos*16, 0); - - cbias = Cvar_GetFloat("cl_cursorbias"); - if (!pic_cursor || Draw_Image((float)(args[2]-cbias)*drawscalex, (float)(args[3]-cbias)*drawscaley, (float)32*drawscalex, (float)32*drawscaley, 0, 0, 1, 1, pic_cursor) <= 0) - DrawChar('+', args[2]-4, args[3]-4); break; case 1: //keydown - KeyPress(args[1], args[2], args[3]); + KeyPress(param, unicode, mousecursor_x, mousecursor_y); break; case 2: //keyup break; @@ -145,51 +171,49 @@ int Plug_MenuEvent(int *args) return 0; } -int Plug_Tick(int *args) -{ - currenttime = args[0]; - return true; -} - -int Plug_ExecuteCommand(int *args) +static qboolean Plug_ExecuteCommand(qboolean isinsecure) { char cmd[256]; - Cmd_Argv(0, cmd, sizeof(cmd)); + cmdfuncs->Argv(0, cmd, sizeof(cmd)); if (!strcmp("namemaker", cmd)) { - Menu_Control(1); - Cvar_GetString("name", (char*)namebuffer, sizeof(namebuffer)); + inputfuncs->SetMenuFocus(true, NULL, 0, 0, 0); //grab input focus + cvarfuncs->GetString("name", (char*)namebuffer, sizeof(namebuffer)); insertpos = strlen(namebuffer); return 1; } return 0; } -int Plug_Init(int *args) +qboolean Plug_Init(void) { - if (Plug_Export("Tick", Plug_Tick) && -// Plug_Export("SbarBase", UI_StatusBar) && -// Plug_Export("SbarOverlay", UI_ScoreBoard) && - Plug_Export("ExecuteCommand", Plug_ExecuteCommand) && - Plug_Export("MenuEvent", Plug_MenuEvent)) + drawfuncs = plugfuncs->GetEngineInterface(plug2dfuncs_name, sizeof(*drawfuncs)); + inputfuncs = plugfuncs->GetEngineInterface(pluginputfuncs_name, sizeof(*inputfuncs)); + if (drawfuncs && inputfuncs && +// plugfuncs->ExportFunction("SbarBase", UI_StatusBar) && +// plugfuncs->ExportFunction("SbarOverlay", UI_ScoreBoard) && + plugfuncs->ExportFunction("ExecuteCommand", Plug_ExecuteCommand) && + plugfuncs->ExportFunction("MenuEvent", Plug_MenuEvent)) { - K_UPARROW = Key_GetKeyCode("uparrow"); - K_DOWNARROW = Key_GetKeyCode("downarrow"); - K_LEFTARROW = Key_GetKeyCode("leftarrow"); - K_RIGHTARROW = Key_GetKeyCode("rightarrow"); - K_ESCAPE = Key_GetKeyCode("escape"); - K_HOME = Key_GetKeyCode("home"); - K_MOUSE1 = Key_GetKeyCode("mouse1"); - K_MOUSE2 = Key_GetKeyCode("mouse2"); - K_MWHEELDOWN = Key_GetKeyCode("mwheeldown"); - K_MWHEELUP = Key_GetKeyCode("mwheelup"); - K_SHIFT = Key_GetKeyCode("shift"); - K_PAGEUP = Key_GetKeyCode("pgup"); - K_PAGEDOWN = Key_GetKeyCode("pgdn"); - K_BACKSPACE = Key_GetKeyCode("backspace"); + K_UPARROW = inputfuncs->GetKeyCode("uparrow", NULL); + K_DOWNARROW = inputfuncs->GetKeyCode("downarrow", NULL); + K_LEFTARROW = inputfuncs->GetKeyCode("leftarrow", NULL); + K_RIGHTARROW = inputfuncs->GetKeyCode("rightarrow", NULL); + K_ESCAPE = inputfuncs->GetKeyCode("escape", NULL); + K_ENTER = inputfuncs->GetKeyCode("enter", NULL); + K_KP_ENTER = inputfuncs->GetKeyCode("kp_enter", NULL); + K_HOME = inputfuncs->GetKeyCode("home", NULL); + K_MOUSE1 = inputfuncs->GetKeyCode("mouse1", NULL); + K_MOUSE2 = inputfuncs->GetKeyCode("mouse2", NULL); + K_MWHEELDOWN = inputfuncs->GetKeyCode("mwheeldown", NULL); + K_MWHEELUP = inputfuncs->GetKeyCode("mwheelup", NULL); + K_SHIFT = inputfuncs->GetKeyCode("shift", NULL); + K_PAGEUP = inputfuncs->GetKeyCode("pgup", NULL); + K_PAGEDOWN = inputfuncs->GetKeyCode("pgdn", NULL); + K_BACKSPACE = inputfuncs->GetKeyCode("backspace", NULL); - Cmd_AddCommand("namemaker"); + cmdfuncs->AddCommand("namemaker"); LoadPics(); diff --git a/plugins/paths.bat b/plugins/paths.bat deleted file mode 100644 index b19b58b2a..000000000 --- a/plugins/paths.bat +++ /dev/null @@ -1,15 +0,0 @@ -REM batch file that sets the path to your q3asm and lcc -REM building qvms is dependant upon the q3 source release. -REM the gpled version is safe to use, but you will need to compile your own q3asm. -REM I guess we should include our own copy of them. - -set QuakeDir=h:\quake -set Q3SrcDir=h:\quakestuff\quake3 -set Path=%Q3SrcDir%\quake3-1.32b\lcc\bin;%Q3SrcDir%\quake3-1.32b\q3asm\debug;..\..\..\lcc;..\..\..\q3asm2;..\.. - -set PluginsDir=%QuakeDir%\fte\plugins - -REM we might as well remove some other things at the same time, so that we don't get conflicts with gcc and stuff. -set include= -set lib= -set MSDevDir= diff --git a/plugins/plugin.c b/plugins/plugin.c index 94ccfe792..0ce8a6015 100644 --- a/plugins/plugin.c +++ b/plugins/plugin.c @@ -1,372 +1,138 @@ //contains generic plugin code for dll/qvm //it's this one or the engine... #include "plugin.h" +#include +#include -typedef struct -{ - const char *name; - export_t func; -} exports_t; -extern exports_t exports[16]; -qintptr_t NATIVEEXPORT vmMain( qintptr_t command, qintptr_t arg0, qintptr_t arg1, qintptr_t arg2, qintptr_t arg3, qintptr_t arg4, qintptr_t arg5, qintptr_t arg6, qintptr_t arg7/*, qintptr_t arg8, qintptr_t arg9, qintptr_t arg10, qintptr_t arg11*/) +plugcorefuncs_t *plugfuncs; +plugcmdfuncs_t *cmdfuncs; +plugcvarfuncs_t *cvarfuncs; +//plugclientfuncs_t *clientfuncs; + + + + +/* An implementation of some 'standard' functions */ +void Q_strlncpy(char *d, const char *s, int sizeofd, int lenofs) { - qintptr_t args[] = + int i; + sizeofd--; + if (sizeofd < 0) + return; //this could be an error + + for (i=0; lenofs-- > 0; i++) { - arg0, - arg1, - arg2, - arg3, - arg4, - arg5, - arg6, - arg7, -// arg8, -// arg9, -// arg10, -// arg11, - }; - return exports[command].func(args); + if (i == sizeofd) + break; + *d++ = *s++; + } + *d='\0'; +} +void Q_strlcpy(char *d, const char *s, int n) +{ + int i; + n--; + if (n < 0) + return; //this could be an error + + for (i=0; *s; i++) + { + if (i == n) + break; + *d++ = *s++; + } + *d='\0'; +} +void Q_strlcat(char *d, const char *s, int n) +{ + if (n) + { + int dlen = strlen(d); + int slen = strlen(s)+1; + if (slen > (n-1)-dlen) + slen = (n-1)-dlen; + memcpy(d+dlen, s, slen); + d[n - 1] = 0; + } } +char *Plug_Info_ValueForKey (const char *s, const char *key, char *out, size_t outsize) +{ + int isvalue = 0; + const char *start; + char *oout = out; + *out = 0; + if (*s != '\\') + return out; //gah, get lost with your corrupt infostrings. -#ifndef Q3_VM -qintptr_t (QDECL *plugin_syscall)( qintptr_t arg, ... ); + start = ++s; + while(1) + { + while(s[0] == '\\' && s[1] == '\\') + s+=2; + if (s[0] != '\\' && *s) + { + s++; + continue; + } + + //okay, it terminates here + isvalue = !isvalue; + if (isvalue) + { + if (strlen(key) == (size_t)(s - start) && !strncmp(start, key, s - start)) + { + s++; + while (outsize --> 1) + { + if (s[0] == '\\' && s[1] == '\\') + s++; + else if (s[0] == '\\' || !s[0]) + break; + *out++ = *s++; + } + *out++ = 0; + return oout; + } + } + if (*s) + start = ++s; + else + break; + } + return oout; +} + +#if defined(_MSC_VER) && _MSC_VER < 2015 +int Q_vsnprintf(char *buffer, size_t maxlen, const char *format, va_list argptr) +{ + int r = _vsnprintf (buffer, maxlen-1, format, argptr); + buffer[maxlen-1] = 0; //make sure its null terminated + if (r < 0) //work around dodgy return value. we can't use this to check required length but can check for truncation + r = maxlen; + return r; +} +int Q_snprintf(char *buffer, size_t maxlen, const char *format, ...) +{ + int p; + va_list argptr; + + va_start (argptr, format); + p = Q_vsnprintf (buffer, maxlen, format,argptr); + va_end (argptr); + + return p; +} #endif -#define PASSFLOAT(f) *(int*)&(f) - -#define ARGNAMES ,funcname -BUILTINR(funcptr_t, Plug_GetEngineFunction, (const char *funcname)); -#undef ARGNAMES - -#define ARGNAMES ,funcname,expnum -static BUILTINR(int, Plug_ExportToEngine, (const char *funcname, quintptr_t expnum)); -#undef ARGNAMES - -#ifndef Q3_VM -#define ARGNAMES ,funcname,func -BUILTINR(qboolean, Plug_ExportNative, (const char *funcname, void *func)); -#undef ARGNAMES - -#define ARGNAMES ,funcname -BUILTINR(void *, Plug_GetNativePointer, (const char *funcname)); -#undef ARGNAMES -#endif - -#define ARGNAMES ,text -BUILTIN(void, Con_Print, (const char *text)); //on to main console. -#undef ARGNAMES - -#define ARGNAMES ,conname,flags -BUILTINR(qhandle_t, Con_POpen, (const char *conname, quintptr_t flags)); -#undef ARGNAMES -#define ARGNAMES ,conname,text -BUILTIN(void, Con_SubPrint, (const char *conname, const char *text)); //on to named sub console (creating it too). -#undef ARGNAMES -#define ARGNAMES ,old,newname -BUILTIN(void, Con_RenameSub, (const char *old, const char *newname)); //rename a subconsole -#undef ARGNAMES -#define ARGNAMES ,conname -BUILTINR(int, Con_IsActive, (const char *conname)); -#undef ARGNAMES -#define ARGNAMES ,conname -BUILTIN(void, Con_SetActive, (const char *conname)); -#undef ARGNAMES -#define ARGNAMES ,conname -BUILTIN(void, Con_Destroy, (const char *conname)); -#undef ARGNAMES -#define ARGNAMES ,connum,conname,connamelen -BUILTIN(void, Con_NameForNum, (qintptr_t connum, char *conname, quintptr_t connamelen)); -#undef ARGNAMES -#define ARGNAMES ,conname,attribname -BUILTINR(float, Con_GetConsoleFloat, (const char *conname, const char *attribname)); -#undef ARGNAMES -#define ARGNAMES ,conname,attribname,PASSFLOAT(newvalue) -BUILTIN(void, Con_SetConsoleFloat, (const char *conname, const char *attribname, float newvalue)); -#undef ARGNAMES -#define ARGNAMES ,conname,attribname,value,valuesize -BUILTINR(int, Con_GetConsoleString, (const char *conname, const char *attribname, const char *value, quintptr_t valuesize)); -#undef ARGNAMES -#define ARGNAMES ,conname,attribname,newvalue -BUILTIN(void, Con_SetConsoleString, (const char *conname, const char *attribname, const char *newvalue)); -#undef ARGNAMES - -#define ARGNAMES ,message -BUILTIN(void, Sys_Error, (const char *message)); //abort the entire engine. -#undef ARGNAMES -#define ARGNAMES -BUILTINR(quintptr_t, Sys_Milliseconds, (void)); //get the time the engine has been running. -#undef ARGNAMES - -#define ARGNAMES ,buffer -BUILTINR(int, Cmd_AddCommand, (const char *buffer)); //register a command. -#undef ARGNAMES -#define ARGNAMES ,buffer,bufsize -BUILTIN(void, Cmd_Args, (char *buffer, int bufsize)); //retrieve some arguments. -#undef ARGNAMES -#define ARGNAMES ,argnum,buffer,bufsize -BUILTIN(void, Cmd_Argv, (int argnum, char *buffer, int bufsize)); //retrieve a single argument at a time. -#undef ARGNAMES -#define ARGNAMES -BUILTINR(int, Cmd_Argc, (void)); //get the argument count. -#undef ARGNAMES -#define ARGNAMES ,msg -BUILTIN(void, Cmd_TokenizeString, (const char *msg)); //tokenize a string. -#undef ARGNAMES - -#define ARGNAMES ,text,insert -BUILTIN(void, Cmd_AddText, (const char *text, qboolean insert)); //add stuff to the console input. -#undef ARGNAMES - -#define ARGNAMES ,name,value -BUILTIN(void, Cvar_SetString, (const char *name, const char *value)); //set a cvar string -#undef ARGNAMES -#define ARGNAMES ,name,PASSFLOAT(value) -BUILTIN(void, Cvar_SetFloat, (const char *name, float value)); //set a cvar float -#undef ARGNAMES -#define ARGNAMES ,name,retstring,sizeofretstring -BUILTINR(qboolean, Cvar_GetString, (const char *name, char *retstring, quintptr_t sizeofretstring)); //retrieve a cvar string -#undef ARGNAMES -#define ARGNAMES ,name -BUILTINR(float, Cvar_GetFloat, (const char *name)); //get a cvar's value -#undef ARGNAMES -#define ARGNAMES ,name,defaultval,flags,grouphint -BUILTINR(qhandle_t, Cvar_Register, (const char *name, const char *defaultval, int flags, const char *grouphint)); //register a new cvar -#undef ARGNAMES -#define ARGNAMES ,handle,modificationcount,stringv,floatv -BUILTINR(int, Cvar_Update, (qhandle_t handle, int *modificationcount, char *stringv, float *floatv)); //stringv is 256 chars long, don't expect this function to do anything if modification count is unchanged. -#undef ARGNAMES -#if !defined(Q3_VM) && defined(FTEPLUGIN) -#define ARGNAMES ,name,defaultval,flags,description,groupname -BUILTINR(cvar_t*, Cvar_GetNVFDG, (const char *name, const char *defaultval, unsigned int flags, const char *description, const char *groupname)); -#undef ARGNAMES -#endif - -#define ARGNAMES ,pnum,stats,maxstats -BUILTINR(int, CL_GetStats, (int pnum, unsigned int *stats, int maxstats)); -#undef ARGNAMES -#define ARGNAMES ,pnum,info -BUILTINR(int, GetPlayerInfo, (int pnum, plugclientinfo_t *info)); -#undef ARGNAMES -#define ARGNAMES -BUILTINR(int, LocalPlayerNumber, (void)); -#undef ARGNAMES -#define ARGNAMES ,firstseat,numseats,playernums,spectracks -BUILTINR(int, GetLocalPlayerNumbers, (int firstseat, int numseats, int *playernums, int *spectracks)); -#undef ARGNAMES -#define ARGNAMES ,info,infolen -BUILTIN(void, GetServerInfo, (char *info, int infolen)); -#undef ARGNAMES -#define ARGNAMES ,key,value -BUILTIN(void, SetUserInfo, (const char *key, const char *value)); -#undef ARGNAMES -#ifdef FTEPLUGIN -#define ARGNAMES ,seat,playercmd -BUILTINR(int, GetLastInputFrame, (int seat, usercmd_t *playercmd)); -#undef ARGNAMES -#endif -#define ARGNAMES ,seat,text,textsize -BUILTINR(float, GetTrackerOwnFrags, (int seat, char *text, size_t textsize)); -#undef ARGNAMES - -#define ARGNAMES ,packagename,mapname,stats -BUILTINR(qboolean, MapLog_Query, (const char *packagename, const char *mapname, float *stats)); -#undef ARGNAMES - -#ifndef Q3_VM -#define ARGNAMES ,vmid -BUILTINR(struct pubprogfuncs_s*, PR_GetVMInstance, (int vmid/*0=ss,1=cs,2=m*/)); -#undef ARGNAMES -#ifdef MULTITHREAD -#define ARGNAMES ,threadingsize -BUILTINR(struct threading_s*, Sys_GetThreadingFuncs, (int threadingsize)); -#undef ARGNAMES -#endif -#define ARGNAMES ,version -BUILTINR(struct modplugfuncs_s*, Mod_GetPluginModelFuncs, (int version)); -#undef ARGNAMES -#endif - - -#define ARGNAMES ,pos,buffer,bufferlen -BUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen)); -#undef ARGNAMES - -#define ARGNAMES ,clients,maxclients,showenemies,showself -BUILTINR(int, GetTeamInfo, (teamplayerinfo_t *clients, unsigned int maxclients, int showenemies, int showself)); -#undef ARGNAMES -#define ARGNAMES ,player,result,maxresults -BUILTINR(int, GetWeaponStats, (int player, struct wstats_s *result, unsigned int maxresults)); -#undef ARGNAMES - -#define ARGNAMES ,soundname -BUILTIN(void, LocalSound, (const char *soundname)); -#undef ARGNAMES - -#define ARGNAMES ,plugnum, buffer, bufsize -BUILTIN(void, Plug_GetPluginName, (int plugnum, char *buffer, int bufsize)); -#undef ARGNAMES - -#define ARGNAMES ,ni,sizeofni -BUILTINR(int, GetNetworkInfo, (vmnetinfo_t *ni, unsigned int sizeofni)); -#undef ARGNAMES - -#define ARGNAMES ,name,mime,data,datalen -BUILTINR(qhandle_t, Draw_LoadImageData, (const char *name, const char *mime, const void *data, unsigned int datalen)); //force-replace a texture. -#undef ARGNAMES -#define ARGNAMES ,name,shaderscript -BUILTINR(qhandle_t, Draw_LoadImageShader, (const char *name, const char *shaderscript)); //some shader script -#undef ARGNAMES -#define ARGNAMES ,name,iswadimage -BUILTINR(qhandle_t, Draw_LoadImage, (const char *name, qboolean iswadimage)); //wad image is ONLY for loading out of q1 gfx.wad -#undef ARGNAMES -#define ARGNAMES ,PASSFLOAT(x),PASSFLOAT(y),PASSFLOAT(w),PASSFLOAT(h),PASSFLOAT(s1),PASSFLOAT(t1),PASSFLOAT(s2),PASSFLOAT(t2),image -BUILTINR(int, Draw_Image, (float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t image)); -#undef ARGNAMES -#define ARGNAMES ,image,x,y -BUILTINR(int, Draw_ImageSize, (qhandle_t image, float *x, float *y)); -#undef ARGNAMES -#define ARGNAMES ,PASSFLOAT(x1),PASSFLOAT(y1),PASSFLOAT(x2),PASSFLOAT(y2) -BUILTIN(void, Draw_Line, (float x1, float y1, float x2, float y2)); -#undef ARGNAMES -#define ARGNAMES ,PASSFLOAT(x),PASSFLOAT(y),PASSFLOAT(w),PASSFLOAT(h) -BUILTIN(void, Draw_Fill, (float x, float y, float w, float h)); -#undef ARGNAMES -#define ARGNAMES ,x,y,character -BUILTIN(void, Draw_Character, (int x, int y, unsigned int character)); -#undef ARGNAMES -#define ARGNAMES ,PASSFLOAT(x),PASSFLOAT(y),string -BUILTIN(void, Draw_String, (float x, float y, const char *string)); -#undef ARGNAMES -#define ARGNAMES ,PASSFLOAT(x),PASSFLOAT(y),PASSFLOAT(h),flags,character -BUILTIN(void, Draw_CharacterH, (float x, float y, float h, unsigned int flags, unsigned int character)); -#undef ARGNAMES -#define ARGNAMES ,PASSFLOAT(x),PASSFLOAT(y),PASSFLOAT(h),flags,string -BUILTIN(void, Draw_StringH, (float x, float y, float h, unsigned int flags, const char *string)); -#undef ARGNAMES -#define ARGNAMES ,PASSFLOAT(h),flags,string -BUILTINR(float, Draw_StringWidth, (float h, unsigned int flags, const char *string)); -#undef ARGNAMES -#define ARGNAMES ,palcol,PASSFLOAT(a) -BUILTIN(void, Draw_Colourpa, (int palcol, float a)); -#undef ARGNAMES -#define ARGNAMES ,palcol -BUILTIN(void, Draw_Colourp, (int palcol)); -#undef ARGNAMES -#define ARGNAMES ,PASSFLOAT(r),PASSFLOAT(g),PASSFLOAT(b) -BUILTIN(void, Draw_Colour3f, (float r, float g, float b)); -#undef ARGNAMES -#define ARGNAMES ,PASSFLOAT(r),PASSFLOAT(g),PASSFLOAT(b),PASSFLOAT(a) -BUILTIN(void, Draw_Colour4f, (float r, float g, float b, float a)); -#undef ARGNAMES - -#define ARGNAMES ,s -BUILTIN(void, SCR_CenterPrint, (const char *s)); -#undef ARGNAMES - -#define ARGNAMES ,mnum -BUILTIN(void, Menu_Control, (int mnum)); -#undef ARGNAMES - -#define ARGNAMES ,keyname -BUILTINR(int, Key_GetKeyCode, (const char *keyname)); -#undef ARGNAMES - -#if !defined(Q3_VM) && defined(FTEPLUGIN) -#define ARGNAMES ,name,handle,mode -BUILTINR(qboolean, VFS_Open, (const char *name, vfsfile_t **handle, const char *mode));//opens a direct vfs file. no access checks, and so can be used in threaded plugins -#undef ARGNAMES -#define ARGNAMES ,name,relativeto,out,outlen -BUILTINR(qboolean, FS_NativePath, (const char *name, enum fs_relative relativeto, char *out, int outlen)); -#undef ARGNAMES -#endif -#define ARGNAMES ,name,handle,mode -BUILTINR(int, FS_Open, (const char *name, qhandle_t *handle, int mode)); -#undef ARGNAMES -#define ARGNAMES ,handle -BUILTIN(void, FS_Close, (qhandle_t handle)); -#undef ARGNAMES -#define ARGNAMES ,handle,data,len -BUILTINR(int, FS_Write, (qhandle_t handle, void *data, int len)); -#undef ARGNAMES -#define ARGNAMES ,handle,data,len -BUILTINR(int, FS_Read, (qhandle_t handle, void *data, int len)); -#undef ARGNAMES -#define ARGNAMES ,handle,offsetlow,offsethigh -BUILTINR(int, FS_Seek, (qhandle_t handle, unsigned int offsetlow, unsigned int offsethigh)); -#undef ARGNAMES -#define ARGNAMES ,handle,sizelow,sizehigh -BUILTINR(qboolean, FS_GetLen, (qhandle_t handle, unsigned int *sizelow, unsigned int *sizehigh)); -#undef ARGNAMES - -#define ARGNAMES ,ip,port -BUILTINR(qhandle_t, Net_TCPConnect, (char *ip, int port)); -#undef ARGNAMES -#define ARGNAMES ,ip,port,maxcount -BUILTINR(qhandle_t, Net_TCPListen, (char *ip, int port, int maxcount)); -#undef ARGNAMES -#define ARGNAMES ,socket,address,addresslen -BUILTINR(qhandle_t, Net_Accept, (qhandle_t socket, char *address, int addresslen)); -#undef ARGNAMES -#define ARGNAMES ,socket,buffer,len -BUILTINR(int, Net_Recv, (qhandle_t socket, void *buffer, int len)); -#undef ARGNAMES -#define ARGNAMES ,socket,buffer,len -BUILTINR(int, Net_Send, (qhandle_t socket, void *buffer, int len)); -#undef ARGNAMES -#define ARGNAMES ,socket -BUILTIN(void, Net_Close, (qhandle_t socket)); -#undef ARGNAMES -#define ARGNAMES ,sock,certhostname -BUILTINR(int, Net_SetTLSClient, (qhandle_t sock, const char *certhostname)); -#undef ARGNAMES -#define ARGNAMES ,sock,outdata,datalen -BUILTINR(int, Net_GetTLSBinding, (qhandle_t sock, char *outdata, int *datalen)); -#undef ARGNAMES - -#define ARGNAMES ,inputbuffer,buffersize -BUILTINR(int, ReadInputBuffer, (void *inputbuffer, int buffersize)); -#undef ARGNAMES -#define ARGNAMES ,inputbuffer,bytes -BUILTINR(int, UpdateInputBuffer, (void *inputbuffer, int bytes)); -#undef ARGNAMES - -#ifdef Q3_VM -#define ARGNAMES ,out,in,len -BUILTIN(void, memcpy, (void *out, void *in, int len)); -#undef ARGNAMES -#define ARGNAMES ,out,in,len -BUILTIN(void, memset, (void *out, int in, int len)); -#undef ARGNAMES -#define ARGNAMES ,out,in,len -BUILTIN(void, memmove, (void *out, void *in, int len)); -#undef ARGNAMES -#define ARGNAMES ,PASSFLOAT(f) -BUILTINR(float, sqrt, (float f)); -BUILTINR(float, sin, (float f)); -BUILTINR(float, cos, (float f)); -#undef ARGNAMES -#endif - - char *va(const char *format, ...) //Identical in function to the one in Quake, though I can assure you that I wrote it... { //It's not exactly hard, just easy to use, so gets duplicated lots. va_list argptr; static char string[1024]; va_start (argptr, format); -#ifdef Q3_VM Q_vsnprintf (string, sizeof(string), format,argptr); -#else - #ifdef _WIN32 -#undef _vsnprintf - _vsnprintf (string, sizeof(string), format,argptr); - string[sizeof(string)-1] = 0; - #else - vsnprintf (string, sizeof(string), format,argptr); - #endif -#endif va_end (argptr); return string; @@ -381,21 +147,21 @@ void Con_Printf(const char *format, ...) Q_vsnprintf (string, sizeof(string), format,argptr); va_end (argptr); - pCon_Print(string); + plugfuncs->Print(string); } void Con_DPrintf(const char *format, ...) { va_list argptr; static char string[1024]; - if (!pCvar_GetFloat("developer")) + if (!cvarfuncs->GetFloat("developer")) return; va_start (argptr, format); Q_vsnprintf (string, sizeof(string), format,argptr); va_end (argptr); - pCon_Print(string); + plugfuncs->Print(string); } void Sys_Errorf(const char *format, ...) { @@ -406,185 +172,15 @@ void Sys_Errorf(const char *format, ...) Q_vsnprintf (string, sizeof(string), format,argptr); va_end (argptr); - pSys_Error(string); + plugfuncs->Error(string); } -static void Plug_InitStandardBuiltins(void) +qboolean NATIVEEXPORT FTEPlug_Init(plugcorefuncs_t *corefuncs) { - //con_print is used if the others don't exist, and MUST come first (for the sake of sanity) - CHECKBUILTIN(Con_Print); + plugfuncs = corefuncs; + cmdfuncs = plugfuncs->GetEngineInterface(plugcmdfuncs_name, sizeof(*cmdfuncs)); + cvarfuncs = plugfuncs->GetEngineInterface(plugcvarfuncs_name, sizeof(*cvarfuncs)); - CHECKBUILTIN(Plug_ExportToEngine); -#ifndef Q3_VM - CHECKBUILTIN(Plug_ExportNative); - CHECKBUILTIN(Plug_GetNativePointer); -#endif - CHECKBUILTIN(Sys_Error); - - CHECKBUILTIN(ReadInputBuffer); - CHECKBUILTIN(UpdateInputBuffer); - -#ifdef Q3_VM - CHECKBUILTIN(memcpy); - CHECKBUILTIN(memmove); - CHECKBUILTIN(memset); - CHECKBUILTIN(sqrt); - CHECKBUILTIN(sin); - CHECKBUILTIN(cos); -#endif - - CHECKBUILTIN(Sys_Milliseconds); - - //command execution - CHECKBUILTIN(Cmd_AddCommand); - CHECKBUILTIN(Cmd_Args); - CHECKBUILTIN(Cmd_Argv); - CHECKBUILTIN(Cmd_Argc); - CHECKBUILTIN(Cmd_AddText); - - //cvar stuff - CHECKBUILTIN(Cvar_SetString); - CHECKBUILTIN(Cvar_SetFloat); - CHECKBUILTIN(Cvar_GetString); - CHECKBUILTIN(Cvar_GetFloat); - CHECKBUILTIN(Cvar_Register); - CHECKBUILTIN(Cvar_Update); -#if !defined(Q3_VM) && defined(FTEPLUGIN) - CHECKBUILTIN(Cvar_GetNVFDG); -#endif - - //file system -#if !defined(Q3_VM) && defined(FTEPLUGIN) - CHECKBUILTIN(VFS_Open); -#endif - CHECKBUILTIN(FS_Open); - CHECKBUILTIN(FS_Read); - CHECKBUILTIN(FS_Write); - CHECKBUILTIN(FS_Close); - CHECKBUILTIN(FS_Seek); - CHECKBUILTIN(FS_GetLen); - - //networking - CHECKBUILTIN(Net_TCPConnect); - CHECKBUILTIN(Net_TCPListen); - CHECKBUILTIN(Net_Accept); - CHECKBUILTIN(Net_Recv); - CHECKBUILTIN(Net_Send); - CHECKBUILTIN(Net_Close); - CHECKBUILTIN(Net_SetTLSClient); - CHECKBUILTIN(Net_GetTLSBinding); - - //random things - CHECKBUILTIN(CL_GetStats); - CHECKBUILTIN(GetPlayerInfo); - CHECKBUILTIN(LocalPlayerNumber); - CHECKBUILTIN(GetLocalPlayerNumbers); -#ifdef FTEPLUGIN - CHECKBUILTIN(GetLastInputFrame); -#endif - CHECKBUILTIN(GetTrackerOwnFrags); - CHECKBUILTIN(GetServerInfo); - CHECKBUILTIN(SetUserInfo); - CHECKBUILTIN(LocalSound); - CHECKBUILTIN(Menu_Control); - CHECKBUILTIN(Key_GetKeyCode); - CHECKBUILTIN(GetLocationName); - CHECKBUILTIN(GetTeamInfo); - CHECKBUILTIN(GetWeaponStats); - CHECKBUILTIN(GetNetworkInfo); - -#ifndef Q3_VM - CHECKBUILTIN(PR_GetVMInstance); -#endif - - //drawing routines - CHECKBUILTIN(Draw_LoadImageData); - CHECKBUILTIN(Draw_LoadImageShader); - CHECKBUILTIN(Draw_LoadImage); - CHECKBUILTIN(Draw_Image); - CHECKBUILTIN(Draw_ImageSize); - CHECKBUILTIN(Draw_Line); - CHECKBUILTIN(Draw_Fill); - CHECKBUILTIN(Draw_Character); - CHECKBUILTIN(Draw_String); - CHECKBUILTIN(Draw_CharacterH); - CHECKBUILTIN(Draw_StringH); - CHECKBUILTIN(Draw_StringWidth); - CHECKBUILTIN(Draw_Colourpa); - CHECKBUILTIN(Draw_Colourp); - CHECKBUILTIN(Draw_Colour3f); - CHECKBUILTIN(Draw_Colour4f); - CHECKBUILTIN(SCR_CenterPrint); - - CHECKBUILTIN(Plug_GetPluginName); - - //sub consoles (optional) - CHECKBUILTIN(Con_SubPrint); - CHECKBUILTIN(Con_RenameSub); - CHECKBUILTIN(Con_IsActive); - CHECKBUILTIN(Con_SetActive); - CHECKBUILTIN(Con_Destroy); - CHECKBUILTIN(Con_NameForNum); - CHECKBUILTIN(Con_GetConsoleFloat); - CHECKBUILTIN(Con_SetConsoleFloat); - CHECKBUILTIN(Con_GetConsoleString); - CHECKBUILTIN(Con_SetConsoleString); - CHECKBUILTIN(Con_POpen); - - CHECKBUILTIN(MapLog_Query); + return Plug_Init(); } -#ifndef Q3_VM -NATIVEEXPORT void QDECL dllEntry(qintptr_t (QDECL *funcptr)(qintptr_t,...)) -{ - plugin_syscall = funcptr; -} -#endif - -vmvideo_t pvid; -static qintptr_t QDECL Plug_UpdateVideo(qintptr_t *args) -{ - pvid.width = args[0]; - pvid.height = args[1]; - - return true; -} - -static qintptr_t QDECL Plug_InitAPI(qintptr_t *args) -{ -#ifdef Q3_VM - Plug_GetEngineFunction = (void*)args[0]; -#else - BUILTIN_Plug_GetEngineFunction = args[0]; -#endif - - Plug_InitStandardBuiltins(); - - Plug_Export("UpdateVideo", Plug_UpdateVideo); - return Plug_Init(args); -} - -qboolean Plug_Export(const char *name, export_t func) -{ - size_t i; - for (i = 0; i < sizeof(exports)/sizeof(exports[0]); i++) - { - if (!exports[i].name) - { - exports[i].name = name; - exports[i].func = func; - return pPlug_ExportToEngine(name, i)?qtrue:qfalse; - } - } - pSys_Error("Plugin exports too many functions"); - return qfalse; -} - - -exports_t exports[sizeof(exports)/sizeof(exports[0])] = { - {"Plug_Init", Plug_InitAPI}, -}; - - - - diff --git a/plugins/plugin.h b/plugins/plugin.h index a26bdb0fb..743f8b39b 100644 --- a/plugins/plugin.h +++ b/plugins/plugin.h @@ -1,65 +1,35 @@ #ifndef __PLUGIN_H__ #define __PLUGIN_H__ -#ifdef FTEPLUGIN -#include "quakedef.h" -#define QPREFIX -#endif - -#if !defined(NOQPREFIX) && !defined(QPREFIX) -#define QPREFIX -#endif - -#ifdef Q3_VM - -typedef int qintptr_t; -typedef unsigned int quintptr_t; - -typedef unsigned int size_t; -typedef signed int ssize_t; - -#define TESTBI 1 -#ifdef TESTBI -# define EBUILTIN(t, n, args) extern t (*n) args -# define BUILTINR(t, n, args) t (*n) args -# define BUILTIN(t, n, args) t (*n) args -# define BUILTINISVALID(n) (n!=NULL && (funcptr_t)n != (funcptr_t)&BadBuiltin) -# define CHECKBUILTIN(n) n = (funcptr_t)Plug_GetEngineFunction(#n);if (n==NULL) {n = (funcptr_t)&BadBuiltin;Con_Print("Warning: builtin "#n" is not supported by the engine\n");} +#ifdef FTEENGINE + //included from fte itself, to borrow typedefs +#elif defined(FTEPLUGIN) + //plugin that needs fte internals + #include "quakedef.h" #else + //moderately generic plugin + #ifdef __cplusplus + typedef enum {qfalse, qtrue} qboolean; + #else + typedef enum {qfalse, qtrue} qboolean; + #define false qfalse + #define true qtrue + #endif + typedef float vec3_t[3]; + typedef unsigned char qbyte; -//qvms just call the return value, and the engine works out which one it called. -# define EBUILTIN(t, n, args) extern t (*n) args -# define BUILTINR(t, n, args) t (*n) args -# define BUILTIN(t, n, args) t (*n) args -# define CHECKBUILTIN(n) n = (funcptr_t)Plug_GetEngineFunction(#n); -# define BUILTINISVALID(n) (n!=NULL) + #include + #define quint64_t uint64_t + typedef quint64_t qofs_t; + + typedef struct cvar_s cvar_t; + typedef struct usercmd_s usercmd_t; + typedef struct vfsfile_s vfsfile_t; + typedef struct netadr_s netadr_t; + enum fs_relative; + struct searchpathfuncs_s; #endif -#define double float //all floats are 32bit, qvm stuff - -typedef char *va_list; -#define va_start(va,f) (va = (char *)&f + sizeof(int)) -#define va_arg(va, type) (*(type *)((va += sizeof(int)) - sizeof(int))) -#define va_end(va) (va = NULL) -#define NULL (void*)0 - - -void *malloc(int size); -void free(void *mem); -char *strstr(char *str, const char *sub); -void strlcpy(char *d, const char *s, int n); -char *strchr(char *str, char sub); - -float atof(char *str); -int atoi(char *str); - -#define strcasecmp stricmp -#define strncasecmp stricmp - -void BadBuiltin(void); - -#else - #ifdef _WIN32 # ifndef strcasecmp # define strcasecmp stricmp @@ -107,36 +77,11 @@ void BadBuiltin(void); #endif -#ifndef QPREFIX -#define pPlug_GetEngineFunction Plug_GetEngineFunction -#define pCon_Print Con_Print -#define pCvar_GetFloat Cvar_GetFloat -#define pSys_Error Sys_Error -#define pPlug_ExportToEngine Plug_ExportToEngine -#endif - - #ifdef __cplusplus extern "C" { #endif //DLLs need a wrapper to add the extra parameter and call a boring function. -#define TEST -#ifdef QPREFIX - #define EBUILTIN(t, n, args) extern qintptr_t BUILTIN_##n; t p##n args - #define BUILTINR(t, n, args) qintptr_t BUILTIN_##n; t p##n args {qintptr_t res; if (!BUILTINISVALID(n))pSys_Error("Builtin "#n" is not valid\n");res = plugin_syscall(BUILTIN_##n ARGNAMES); return *(t*)&res;} - #define BUILTIN(t, n, args) qintptr_t BUILTIN_##n; t p##n args {if (!BUILTINISVALID(n))pSys_Error("Builtin "#n" is not valid\n");plugin_syscall(BUILTIN_##n ARGNAMES);} -#elif defined(TEST) - #define EBUILTIN(t, n, args) extern qintptr_t BUILTIN_##n; t n args - #define BUILTINR(t, n, args) qintptr_t BUILTIN_##n; t n args {qintptr_t res; if (!BUILTINISVALID(n))Sys_Error("Builtin "#n" is not valid\n");res = plugin_syscall(BUILTIN_##n ARGNAMES); return *(t*)&res;} - #define BUILTIN(t, n, args) qintptr_t BUILTIN_##n; t n args {if (!BUILTINISVALID(n))Sys_Error("Builtin "#n" is not valid\n");plugin_syscall(BUILTIN_##n ARGNAMES);} -#else - #define EBUILTIN(t, n, args) extern qintptr_t BUILTIN_##n; t n args - #define BUILTINR(t, n, args) qintptr_t BUILTIN_##n; t n args {qintptr_t res = plugin_syscall(BUILTIN_##n ARGNAMES); return *(t*)&res;} - #define BUILTIN(t, n, args) qintptr_t BUILTIN_##n; t n args {plugin_syscall(BUILTIN_##n ARGNAMES);} -#endif -#define CHECKBUILTIN(n) ((BUILTIN_##n = (qintptr_t)pPlug_GetEngineFunction(#n))) -#define BUILTINISVALID(n) (BUILTIN_##n != 0) #ifndef QDECL #ifdef _WIN32 #define QDECL __cdecl @@ -153,32 +98,10 @@ extern "C" { #endif #endif -extern qintptr_t (QDECL *plugin_syscall)( qintptr_t arg, ... ); - -void Q_strlncpy(char *d, const char *s, int sizeofd, int lenofs); -void Q_strlcpy(char *d, const char *s, int n); -void Q_strlcat(char *d, const char *s, int n); -int Q_snprintf(char *buffer, size_t maxlen, const char *format, ...) LIKEPRINTF(3); -int Q_vsnprintf(char *buffer, size_t maxlen, const char *format, va_list vargs); - -#endif - #ifndef NATIVEEXPORT #define NATIVEEXPORT QDECL #endif - -#ifndef FTEPLUGIN -#ifdef __cplusplus -typedef enum {qfalse, qtrue} qboolean; -#else -typedef enum {qfalse, qtrue} qboolean; -#define false qfalse -#define true qtrue -#endif -typedef float vec3_t[3]; -typedef unsigned char qbyte; -#endif typedef int qhandle_t; typedef void* funcptr_t; @@ -191,86 +114,13 @@ typedef struct { char name[PLUGMAX_SCOREBOARDNAME]; int ping; int pl; - int starttime; + int activetime; int userid; int spectator; char userinfo[2048]; char team[64]; } plugclientinfo_t; - - -//Basic builtins: -EBUILTIN(funcptr_t, Plug_GetEngineFunction, (const char *funcname)); //set up in vmMain, use this to get all other builtins - -#ifdef FTEENGINE -#else -#ifndef Q3_VM -EBUILTIN(qboolean, Plug_ExportNative, (const char *funcname, void *func)); //set up in vmMain, use this to get all other builtins -EBUILTIN(void *, Plug_GetNativePointer, (const char *funcname)); -#endif -EBUILTIN(void, Con_Print, (const char *text)); //on to main console. - -EBUILTIN(qhandle_t, Con_POpen, (const char *conname, quintptr_t flags)); -EBUILTIN(void, Con_SubPrint, (const char *subname, const char *text)); //on to sub console. -EBUILTIN(void, Con_RenameSub, (const char *oldname, const char *newname)); //rename a console. -EBUILTIN(int, Con_IsActive, (const char *conname)); -EBUILTIN(void, Con_SetActive, (const char *conname)); -EBUILTIN(void, Con_Destroy, (const char *conname)); -EBUILTIN(void, Con_NameForNum, (qintptr_t connum, char *conname, quintptr_t connamelen)); -EBUILTIN(float, Con_GetConsoleFloat, (const char *conname, const char *attribname)); -EBUILTIN(void, Con_SetConsoleFloat, (const char *conname, const char *attribname, float newvalue)); -EBUILTIN(int, Con_GetConsoleString, (const char *conname, const char *attribname, const char *value, quintptr_t valuesize)); -EBUILTIN(void, Con_SetConsoleString, (const char *conname, const char *attribname, const char *newvalue)); - -EBUILTIN(void, Sys_Error, (const char *message)); //abort the entire engine. -EBUILTIN(quintptr_t, Sys_Milliseconds, (void)); - -EBUILTIN(int, Cmd_AddCommand, (const char *buffer)); //Registers a console command. -EBUILTIN(void, Cmd_Args, (char *buffer, int bufsize)); //abort the entire engine. -EBUILTIN(void, Cmd_Argv, (int argnum, char *buffer, int bufsize)); //abort the entire engine. -EBUILTIN(int, Cmd_Argc, (void)); //abort the entire engine. -EBUILTIN(void, Cmd_AddText, (const char *text, qboolean insert)); -EBUILTIN(void, Cmd_TokenizeString, (const char *msg)); //tokenize a string. - -EBUILTIN(void, Cvar_SetString, (const char *name, const char *value)); -EBUILTIN(void, Cvar_SetFloat, (const char *name, float value)); -EBUILTIN(qboolean, Cvar_GetString, (const char *name, char *retstring, quintptr_t sizeofretstring)); -EBUILTIN(float, Cvar_GetFloat, (const char *name)); -EBUILTIN(qhandle_t, Cvar_Register, (const char *name, const char *defaultval, int flags, const char *grouphint)); -EBUILTIN(int, Cvar_Update, (qhandle_t handle, int *modificationcount, char *stringv, float *floatv)); //stringv is 256 chars long, don't expect this function to do anything if modification count is unchanged. -#ifdef FTEPLUGIN -EBUILTIN(cvar_t*, Cvar_GetNVFDG, (const char *name, const char *defaultval, unsigned int flags, const char *description, const char *groupname)); -#endif - -EBUILTIN(void, Plug_GetPluginName, (int plugnum, char *buffer, int bufsize)); -EBUILTIN(void, LocalSound, (const char *soundname)); -EBUILTIN(int, CL_GetStats, (int pnum, unsigned int *stats, int maxstats)); -EBUILTIN(int, GetPlayerInfo, (int pnum, plugclientinfo_t *info)); - -EBUILTIN(int, LocalPlayerNumber, (void)); //deprecated -EBUILTIN(int, GetLocalPlayerNumbers, (int firstseat, int numseats, int *playernums, int *spectracks)); -EBUILTIN(void, GetServerInfo, (char *info, int infolen)); -EBUILTIN(void, SetUserInfo, (const char *key, const char *value)); -EBUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen)); -#ifdef FTEPLUGIN -EBUILTIN(int, GetLastInputFrame, (int seat, usercmd_t *playercmd)); -#endif -EBUILTIN(float, GetTrackerOwnFrags, (int seat, char *text, size_t textsize)); - -EBUILTIN(qboolean, MapLog_Query, (const char *packagename, const char *mapname, float *stats)); - -#ifndef Q3_VM -struct pubprogfuncs_s; -EBUILTIN(struct pubprogfuncs_s*, PR_GetVMInstance, (int vmid/*0=ss,1=cs,2=m*/)); -struct modplugfuncs_s; -EBUILTIN(struct modplugfuncs_s*, Mod_GetPluginModelFuncs, (int version)); -#ifdef MULTITHREAD -struct threading_s; -EBUILTIN(struct threading_s*, Sys_GetThreadingFuncs, (int threadingsize)); -#endif -#endif - typedef struct { unsigned int client; @@ -280,11 +130,9 @@ typedef struct vec3_t org; char nick[16]; } teamplayerinfo_t; -EBUILTIN(int, GetTeamInfo, (teamplayerinfo_t *clients, unsigned int maxclients, int showenemies, int showself)); -struct wstats_s; -EBUILTIN(int, GetWeaponStats, (int player, struct wstats_s *result, unsigned int maxresults)); typedef struct { + size_t structsize; int seats; struct { @@ -307,7 +155,7 @@ typedef struct { float vlatency; float vrate; vec3_t speed; //player speed - + struct { float in_pps; @@ -323,84 +171,193 @@ typedef struct { float out_bps; } svrate; int capturing; //avi capturing -} vmnetinfo_t; -EBUILTIN(int, GetNetworkInfo, (vmnetinfo_t *ni, unsigned int sizeofni)); +} plugnetinfo_t; + +struct wstats_s; -EBUILTIN(void, Menu_Control, (int mnum)); -#define MENU_CLEAR 0 -#define MENU_GRAB 1 -EBUILTIN(int, Key_GetKeyCode, (const char *keyname)); +#define F(t, n, args) t (QDECL *n) args; -EBUILTIN(qhandle_t, Draw_LoadImageData, (const char *name, const char *mime, const void *data, unsigned int datasize)); //load/replace a named texture -EBUILTIN(qhandle_t, Draw_LoadImageShader, (const char *name, const char *defaultshader)); //loads a shader. -EBUILTIN(qhandle_t, Draw_LoadImage, (const char *name, qboolean iswadimage)); //wad image is ONLY for loading out of q1 gfx.wad. loads a shader. -EBUILTIN(int, Draw_Image, (float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t image)); -EBUILTIN(int, Draw_ImageSize, (qhandle_t image, float *x, float *y)); -EBUILTIN(void, Draw_Fill, (float x, float y, float w, float h)); -EBUILTIN(void, Draw_Line, (float x1, float y1, float x2, float y2)); -EBUILTIN(void, Draw_Character, (int x, int y, unsigned int character)); -EBUILTIN(void, Draw_String, (float x, float y, const char *string)); -EBUILTIN(void, Draw_CharacterH, (float x, float y, float h, unsigned int flags, unsigned int character)); -EBUILTIN(void, Draw_StringH, (float x, float y, float h, unsigned int flags, const char *string)); //returns the vpixel width of the (coloured) string, in the current (variable-width) font. -EBUILTIN(float, Draw_StringWidth, (float h, unsigned int flags, const char *string)); -EBUILTIN(void, Draw_Colourpa, (int palcol, float a)); -EBUILTIN(void, Draw_Colourp, (int palcol)); -EBUILTIN(void, Draw_Colour3f, (float r, float g, float b)); -EBUILTIN(void, Draw_Colour4f, (float r, float g, float b, float a)); -EBUILTIN(void, SCR_CenterPrint, (const char *s)); +typedef struct //core stuff +{ + //Basic builtins: + F(void*, GetEngineInterface, (const char *interfacename, size_t structsize)); //retrieve a named interface struct from the engine + F(qboolean, ExportFunction, (const char *funcname, funcptr_t funcptr)); //export a named function to the engine + F(qboolean, ExportInterface, (const char *interfacename, void *interfaceptr, size_t structsize)); //export a named interface struct to the engine + F(qboolean, GetPluginName, (int plugnum, char *buffer, size_t bufsize)); //query loaded plugin names. -1 == active plugin + F(void, Print, (const char *message)); //print on (main) console. + F(void, Error, (const char *message)); //abort the entire engine. + F(quintptr_t,GetMilliseconds, (void)); +#define plugcorefuncs_name "Core" +} plugcorefuncs_t; -EBUILTIN(void, S_RawAudio, (int sourceid, void *data, int speed, int samples, int channels, int width, float volume)); +typedef struct //subconsole handling +{ + F(qhandle_t,POpen, (const char *conname)); + F(qboolean, SubPrint, (const char *subname, const char *text)); //on to sub console. + F(qboolean, RenameSub, (const char *oldname, const char *newname)); //rename a console. + F(qboolean, IsActive, (const char *conname)); + F(qboolean, SetActive, (const char *conname)); + F(qboolean, Destroy, (const char *conname)); + F(qboolean, NameForNum, (qintptr_t connum, char *conname, size_t connamelen)); + F(float, GetConsoleFloat, (const char *conname, const char *attribname)); + F(qboolean, SetConsoleFloat, (const char *conname, const char *attribname, float newvalue)); + F(qboolean, GetConsoleString, (const char *conname, const char *attribname, char *outvalue, size_t valuesize)); + F(qboolean, SetConsoleString, (const char *conname, const char *attribname, const char *newvalue)); +#define plugsubconsolefuncs_name "SubConsole" +} plugsubconsolefuncs_t; -EBUILTIN(int, ReadInputBuffer, (void *inputbuffer, int buffersize)); -EBUILTIN(int, UpdateInputBuffer, (void *inputbuffer, int bytes)); +typedef struct //console command/tokenizing/cbuf functions +{ + F(qboolean, AddCommand, (const char *buffer)); //Registers a console command. + F(void, TokenizeString, (const char *msg)); //tokenize a string. -#if !defined(Q3_VM) && defined(FTEPLUGIN) -EBUILTIN(qboolean, VFS_Open, (const char *name, vfsfile_t **handle, const char *mode));//opens a direct vfs file. no access checks, and so can be used in threaded plugins -EBUILTIN(qboolean, FS_NativePath, (const char *name, enum fs_relative relativeto, char *out, int outlen)); -#endif -EBUILTIN(int, FS_Open, (const char *name, qhandle_t *handle, int mode)); -EBUILTIN(void, FS_Close, (qhandle_t handle)); -EBUILTIN(int, FS_Write, (qhandle_t handle, void *data, int len)); -EBUILTIN(int, FS_Read, (qhandle_t handle, void *data, int len)); -EBUILTIN(int, FS_Seek, (qhandle_t handle, unsigned int offsetlow, unsigned int offsethigh)); -EBUILTIN(qboolean, FS_GetLen, (qhandle_t handle, unsigned int *sizelow, unsigned int *sizehigh)); + F(void, Args, (char *buffer, int bufsize)); //Gets the extra args + F(void, Argv, (int argnum, char *buffer, size_t bufsize)); //Gets a 0-based token + F(int, Argc, (void)); //gets the number of tokens available. -EBUILTIN(qhandle_t, Net_TCPConnect, (char *ip, int port)); -EBUILTIN(qhandle_t, Net_TCPListen, (char *ip, int port, int maxcount)); -EBUILTIN(qhandle_t, Net_Accept, (qhandle_t socket, char *address, int addresssize)); -EBUILTIN(int, Net_Recv, (qhandle_t socket, void *buffer, int len)); -EBUILTIN(int, Net_Send, (qhandle_t socket, void *buffer, int len)); -EBUILTIN(void, Net_Close, (qhandle_t socket)); -EBUILTIN(int, Net_SetTLSClient, (qhandle_t sock, const char *certhostname)); -EBUILTIN(int, Net_GetTLSBinding, (qhandle_t sock, char *outdata, int *datalen)); -#define N_WOULDBLOCK -1 -#define N_FATALERROR -2 -#define NET_CLIENTPORT -1 -#define NET_SERVERPORT -2 + F(void, AddText, (const char *text, qboolean insert)); +#define plugcmdfuncs_name "Cmd" +} plugcmdfuncs_t; -#ifdef Q3_VM -EBUILTIN(void, memcpy, (void *, void *, int len)); -EBUILTIN(void, memmove, (void *, void *, int len)); -EBUILTIN(void, memset, (void *, int, int len)); -EBUILTIN(float, sqrt, (float f)); -EBUILTIN(float, cos, (float f)); -EBUILTIN(float, sin, (float f)); -#endif +typedef struct //console command and cbuf functions +{ + F(void, SetString, (const char *name, const char *value)); + F(void, SetFloat, (const char *name, float value)); + F(qboolean, GetString, (const char *name, char *retstring, quintptr_t sizeofretstring)); + F(float, GetFloat, (const char *name)); + F(qhandle_t,Register, (const char *name, const char *defaultval, int flags, const char *grouphint)); + F(qboolean, Update, (qhandle_t handle, int *modificationcount, char *outstringv, size_t stringsize, float *outfloatv)); //stringv is 256 chars long, don't expect this function to do anything if modification count is unchanged. + F(cvar_t*, GetNVFDG, (const char *name, const char *defaultval, unsigned int flags, const char *description, const char *groupname)); +#define plugcvarfuncs_name "Cvar" +} plugcvarfuncs_t; + +typedef struct +{ + F(void, LocalSound, (const char *soundname, int channel, float volume)); + F(void, RawAudio, (int sourceid, void *data, int speed, int samples, int channels, int width, float volume)); +#define plugaudiofuncs_name "Audio" +} plugaudiofuncs_t; + +typedef struct //q1 client/network info +{ + F(int, GetStats, (int seat, unsigned int *stats, int maxstats)); + F(void, GetPlayerInfo, (int seat, plugclientinfo_t *info)); + F(size_t, GetTeamInfo, (teamplayerinfo_t *clients, size_t maxclients, qboolean showenemies, int seat)); + F(int, GetWeaponStats, (int player, struct wstats_s *result, size_t maxresults)); + F(size_t, GetNetworkInfo, (plugnetinfo_t *ni, size_t sizeofni)); + F(size_t, GetLocalPlayerNumbers,(size_t firstseat, size_t numseats, int *playernums, int *spectracks)); + F(void, GetLocationName, (const float *pos, char *outbuffer, size_t bufferlen)); + F(float, GetTrackerOwnFrags, (int seat, char *text, size_t textsize)); + F(qboolean, GetLastInputFrame, (int seat, usercmd_t *outcmd)); + F(void, GetServerInfo, (char *info, size_t infolen)); + + F(void, SetUserInfo, (int seat, const char *key, const char *value)); + //EBUILTIN(void, SCR_CenterPrint, (const char *s)); + + //FIXME: does this belong here? + F(qboolean, MapLog_Query, (const char *packagename, const char *mapname, float *stats)); +#define plugclientfuncs_name "Client" +} plugclientfuncs_t; + +typedef struct //for menu-like stuff +{ + //for menus + F(qboolean, SetMenuFocus, (qboolean wantkeyfocus, const char *cursorname, float hot_x, float hot_y, float scale)); //null cursorname=relmouse, set/empty cursorname=absmouse + F(qboolean, HasMenuFocus, (void)); + + //for menu input + F(int, GetKeyCode, (const char *keyname, int *out_modifier)); + F(const char*,GetKeyName, (int keycode, int modifier)); + F(int, FindKeysForCommand,(int bindmap, const char *command, int *out_keycodes, int *out_modifiers, int maxkeys)); + F(const char*,GetKeyBind, (int bindmap, int keynum, int modifier)); + F(void, SetKeyBind, (int bindmap, int keycode, int modifier, const char *newbinding)); + +#define pluginputfuncs_name "Input" +} pluginputfuncs_t; + +typedef struct //for huds and menus alike +{ + //note: these use handles instead of shaders, to make them persistent over renderer restarts. + F(qhandle_t,LoadImageData, (const char *name, const char *mime, void *data, size_t datasize)); //load/replace a named texture + F(qhandle_t,LoadImageShader,(const char *name, const char *defaultshader)); //loads a shader. + F(qhandle_t,LoadImage, (const char *name, qboolean iswadimage)); //wad image is ONLY for loading out of q1 gfx.wad. loads a shader. + F(void, UnloadImage, (qhandle_t image)); + F(int, Image, (float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t image)); + F(int, ImageSize, (qhandle_t image, float *x, float *y)); + F(void, Fill, (float x, float y, float w, float h)); + F(void, Line, (float x1, float y1, float x2, float y2)); + F(void, Character, (float x, float y, unsigned int character)); + F(void, String, (float x, float y, const char *string)); + F(void, CharacterH, (float x, float y, float h, unsigned int flags, unsigned int character)); + F(void, StringH, (float x, float y, float h, unsigned int flags, const char *string)); //returns the vpixel width of the (coloured) string, in the current (variable-width) font. + F(float, StringWidth, (float h, unsigned int flags, const char *string)); + F(void, Colourpa, (int palcol, float a)); //for legacy code + F(void, Colour4f, (float r, float g, float b, float a)); + + F(void, LocalSound, (const char *soundname, int channel, float volume)); +#define plug2dfuncs_name "2D" +} plug2dfuncs_t; + +typedef struct //for plugins that need to read/write files... +{ + F(int, Open, (const char *name, qhandle_t *handle, int mode)); + F(void, Close, (qhandle_t handle)); + F(int, Write, (qhandle_t handle, void *data, int len)); + F(int, Read, (qhandle_t handle, void *data, int len)); + F(int, Seek, (qhandle_t handle, qofs_t offset)); + F(qboolean, GetLen, (qhandle_t handle, qofs_t *outsize)); + + + F(vfsfile_t*,OpenVFS, (const char *filename, const char *mode, enum fs_relative relativeto)); //opens a direct vfs file, without any access checks, and so can be used in threaded plugins + F(qboolean, NativePath, (const char *name, enum fs_relative relativeto, char *out, int outlen)); + F(void, EnumerateFiles, (const char *match, int (QDECL *callback)(const char *fname, qofs_t fsize, time_t mtime, void *ctx, struct searchpathfuncs_s *package), void *ctx)); +#define plugfsfuncs_name "Filesystem" +} plugfsfuncs_t; + +typedef struct //for when you need basic socket access, hopefully rare... +{ + F(qhandle_t,TCPConnect, (const char *ip, int port)); + F(qhandle_t,TCPListen, (const char *localip, int port, int maxcount)); + F(qhandle_t,Accept, (qhandle_t socket, char *address, int addresssize)); + F(int, Recv, (qhandle_t socket, void *buffer, int len)); + F(int, Send, (qhandle_t socket, void *buffer, int len)); + F(int, SendTo, (qhandle_t handle, void *data, int datasize, netadr_t *dest)); + F(void, Close, (qhandle_t socket)); + F(int, SetTLSClient, (qhandle_t sock, const char *certhostname)); //adds a tls layer to the socket (and specifies the peer's required hostname) + F(int, GetTLSBinding, (qhandle_t sock, char *outdata, int *datalen)); //to avoid MITM attacks with compromised cert authorities + #define N_WOULDBLOCK -1 + #define N_FATALERROR -2 + #define NET_CLIENTPORT -1 + #define NET_SERVERPORT -2 +#define plugnetfuncs_name "Net" +} plugnetfuncs_t; + +#undef F + +extern plugcorefuncs_t *plugfuncs; +extern plugcmdfuncs_t *cmdfuncs; +extern plugcvarfuncs_t *cvarfuncs; + +#ifndef FTEENGINE +void Q_strlncpy(char *d, const char *s, int sizeofd, int lenofs); +void Q_strlcpy(char *d, const char *s, int n); +void Q_strlcat(char *d, const char *s, int n); +#if defined(_MSC_VER) && _MSC_VER < 2015 + int Q_snprintf(char *buffer, size_t maxlen, const char *format, ...) LIKEPRINTF(3); + int Q_vsnprintf(char *buffer, size_t maxlen, const char *format, va_list vargs); +#else + #define Q_snprintf snprintf + #define Q_vsnprintf vsnprintf #endif -typedef qintptr_t (QDECL *export_t) (qintptr_t *args); char *va(const char *format, ...); -qintptr_t Plug_Init(qintptr_t *args); -qboolean Plug_Export(const char *name, export_t func); +qboolean Plug_Init(void); void Con_Printf(const char *format, ...); void Con_DPrintf(const char *format, ...); //not a particuarly efficient implementation, so beware. void Sys_Errorf(const char *format, ...); void QDECL Q_strncpyz(char *d, const char *s, int n); -qintptr_t NATIVEEXPORT vmMain( qintptr_t command, qintptr_t arg0, qintptr_t arg1, qintptr_t arg2, qintptr_t arg3, qintptr_t arg4, qintptr_t arg5, qintptr_t arg6, qintptr_t arg7/*, qintptr_t arg8, qintptr_t arg9, qintptr_t arg10, qintptr_t arg11*/); -NATIVEEXPORT void QDECL dllEntry(qintptr_t (QDECL *funcptr)(qintptr_t,...)); - #define PLUG_SHARED_BEGIN(t,p,b) \ { \ t *p; \ @@ -412,12 +369,6 @@ NATIVEEXPORT void QDECL dllEntry(qintptr_t (QDECL *funcptr)(qintptr_t,...)); p = NULL; #define PLUG_SHARED_END(p,b) UpdateInputBuffer(inputbuffer, b);} - -// -// qvm_api.c -// -//int vsnprintf(char *buffer, size_t maxlen, const char *format, va_list vargs); - typedef struct { char *name; char string[256]; @@ -428,12 +379,8 @@ typedef struct { int modificationcount; } vmcvar_t; -typedef struct { - int width; - int height; -} vmvideo_t; -extern vmvideo_t pvid; - +#define VMCvar_Register(cv) (cv->handle=cvarfuncs->Register(cv->name, cv->string, cv->flags, cv->group)) +#define VMCvar_Update(cv) cvarfuncs->Update(handle, &cv->modcount, cv->string, sizeof(cv->string), &cv->value) #define VMCvar_SetString(c,v) \ do{ \ strcpy(c->string, v); \ @@ -448,18 +395,10 @@ extern vmvideo_t pvid; } while(0) \ -#ifndef MAX_INFO_KEY -#define MAX_INFO_KEY 64 -#endif char *Plug_Info_ValueForKey (const char *s, const char *key, char *out, size_t outsize); -void Info_RemoveKey (char *s, const char *key); -void Info_RemovePrefixedKeys (char *start, char prefix); -void Info_RemoveNonStarKeys (char *start); -void Info_SetValueForKey (char *s, const char *key, const char *value, int maxsize); -void Info_SetValueForStarKey (char *s, const char *key, const char *value, int maxsize); +#endif #ifdef __cplusplus } #endif - -#endif +#endif \ No newline at end of file diff --git a/plugins/plugins.dsw b/plugins/plugins.dsw deleted file mode 100644 index f8d53146f..000000000 --- a/plugins/plugins.dsw +++ /dev/null @@ -1,125 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "emailnot"=.\emailnot\emailnot.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "emailsv"=..\..\plugins\emailsv\emailsv.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "ezscript"=.\ezscript\ezscript.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "hud"=.\hud\hud.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "irc"=.\irc\irc.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "jabber"=.\jabber\jabber.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "serverb"=.\serverb\serverb.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "winamp"=.\winamp\winamp.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "xsv"=.\xsv\xsv.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/plugins/qi/qi.c b/plugins/qi/qi.c index 5cb4a7e1e..e1cd61854 100644 --- a/plugins/qi/qi.c +++ b/plugins/qi/qi.c @@ -1,4 +1,7 @@ #include "../plugin.h" +static plugsubconsolefuncs_t *confuncs; +static plugfsfuncs_t *filefuncs; +static plugclientfuncs_t *clientfuncs; #include "../jabber/xml.h" @@ -36,7 +39,18 @@ static struct int type; } filters; -static void Con_SubPrintf(const char *subname, char *format, ...) +static struct +{ + int width; + int height; +} pvid; +static void QDECL QI_UpdateVideo(int width, int height) +{ + pvid.width = width; + pvid.height = height; +} + +void Con_SubPrintf(const char *subname, char *format, ...) { va_list argptr; static char string[8192]; @@ -45,48 +59,47 @@ static void Con_SubPrintf(const char *subname, char *format, ...) Q_vsnprintf (string, sizeof(string), format,argptr); va_end (argptr); - pCon_SubPrint(subname, string); + confuncs->SubPrint(subname, string); } -static qintptr_t QI_Shutdown(qintptr_t *args) +static void QI_Shutdown(void) { if (dlcontext != -1) { //we're still downloading something? :o - pFS_Close(dlcontext); + filefuncs->Close(dlcontext); dlcontext = -1; } if (thedatabase) XML_Destroy(thedatabase); thedatabase = NULL; - return false; } static qboolean QI_SetupWindow(const char *console, qboolean force) { - if (!BUILTINISVALID(Con_GetConsoleFloat)) + if (!confuncs) return false; //only redraw the window if it actually exists. if they closed it, then don't mess things up. - if (!force && pCon_GetConsoleFloat(console, "iswindow") <= 0) + if (!force && confuncs->GetConsoleFloat(console, "iswindow") <= 0) return false; - if (pCon_GetConsoleFloat(console, "iswindow") != true) + if (confuncs->GetConsoleFloat(console, "iswindow") != true) { - pCon_SetConsoleString(console, "title", WINDOWTITLE); - pCon_SetConsoleFloat(console, "iswindow", true); - pCon_SetConsoleFloat(console, "forceutf8", true); - pCon_SetConsoleFloat(console, "linebuffered", false); - pCon_SetConsoleFloat(console, "maxlines", 16384); //the line limit is more a sanity thing than anything else. so long as we explicitly clear before spamming more, then its not an issue... - pCon_SetConsoleFloat(console, "wnd_x", 8); - pCon_SetConsoleFloat(console, "wnd_y", 8); - pCon_SetConsoleFloat(console, "wnd_w", pvid.width-16); - pCon_SetConsoleFloat(console, "wnd_h", pvid.height-16); - pCon_SetConsoleString(console, "footer", ""); + confuncs->SetConsoleString(console, "title", WINDOWTITLE); + confuncs->SetConsoleFloat(console, "iswindow", true); + confuncs->SetConsoleFloat(console, "forceutf8", true); + confuncs->SetConsoleFloat(console, "linebuffered", false); + confuncs->SetConsoleFloat(console, "maxlines", 16384); //the line limit is more a sanity thing than anything else. so long as we explicitly clear before spamming more, then its not an issue... + confuncs->SetConsoleFloat(console, "wnd_x", 8); + confuncs->SetConsoleFloat(console, "wnd_y", 8); + confuncs->SetConsoleFloat(console, "wnd_w", pvid.width-16); + confuncs->SetConsoleFloat(console, "wnd_h", pvid.height-16); + confuncs->SetConsoleString(console, "footer", ""); } - pCon_SetConsoleFloat(console, "linecount", 0); //clear it + confuncs->SetConsoleFloat(console, "linecount", 0); //clear it if (force) - pCon_SetActive(console); + confuncs->SetActive(console); return true; } static void QI_DeHTML(const char *in, char *out, size_t outsize) @@ -338,10 +351,10 @@ static void QI_RefreshMapList(qboolean forcedisplay) break; Q_snprintf(bspfile, sizeof(bspfile), "maps/%s.bsp", startmap->body); - if (BUILTINISVALID(MapLog_Query) && pMapLog_Query(va(FILEDOWNLOADURL, id), bspfile, donestats)) - Con_SubPrintf(console, " ^[^2[%s, complete %.1f]\\tip\\^7^aBest Time:^a ^2%.9f^7\n^aCompletion Time:^a %.9f\n^aKills:^a %.9f\n^aSecrets:^a %.9f\n\n\n%s\\tipimg\\"FILEIMAGEURL"\\id\\%s\\startmap\\%s^]", startmap->body, donestats[0], donestats[0], donestats[1], donestats[2], donestats[3], desc, id, id, startmap->body); + if (clientfuncs && clientfuncs->MapLog_Query(va(FILEDOWNLOADURL, id), bspfile, donestats)) + Con_SubPrintf(console, " ^[^2[%s, complete %.1f]\\tip\\^7^aBest Time:^a ^2%.9f^7\n^aCompletion Time:^a %.9f\n^aKills:^a %.9f\n^aSecrets:^a %.9f\n\n\n%s"/*"\\tipimg\\"FILEIMAGEURL*/"\\id\\%s\\startmap\\%s^]", startmap->body, donestats[0], donestats[0], donestats[1], donestats[2], donestats[3], desc, /*id,*/ id, startmap->body); else - Con_SubPrintf(console, " ^[^4[%s]\\tip\\%s\\tipimg\\"FILEIMAGEURL"\\id\\%s\\startmap\\%s^]", startmap->body, desc, id, id, startmap->body); + Con_SubPrintf(console, " ^[^4[%s]\\tip\\%s"/*"\\tipimg\\"FILEIMAGEURL*/"\\id\\%s\\startmap\\%s^]", startmap->body, desc, /*id,*/ id, startmap->body); } Con_SubPrintf(console, "\n"); } @@ -483,7 +496,7 @@ static void QI_AddPackages(xmltree_t *qifile) Q_snprintf(extra, sizeof(extra), " package \""FILEDOWNLOADURL"\" prefix \"%s\"", id, clean); - pCmd_AddText(extra, false); + cmdfuncs->AddText(extra, false); } static void QI_RunMap(xmltree_t *qifile, const char *map) { @@ -499,15 +512,15 @@ static void QI_RunMap(xmltree_t *qifile, const char *map) map = ""; - pCmd_AddText("fs_changemod spmap \"", false); - pCmd_AddText(map, false); - pCmd_AddText("\"", false); + cmdfuncs->AddText("fs_changemod spmap \"", false); + cmdfuncs->AddText(map, false); + cmdfuncs->AddText("\"", false); QI_AddPackages(qifile); // Con_Printf("Command: %s\n", cmd); - pCmd_AddText("\n", false); + cmdfuncs->AddText("\n", false); } -static qintptr_t QI_ConsoleLink(qintptr_t *args) +static qboolean QDECL QI_ConsoleLink(void) { xmltree_t *file; char *map; @@ -515,14 +528,14 @@ static qintptr_t QI_ConsoleLink(qintptr_t *args) char *e; char text[2048]; char link[8192]; - pCmd_Argv(0, text, sizeof(text)); - pCmd_Argv(1, link, sizeof(link)); + cmdfuncs->Argv(0, text, sizeof(text)); + cmdfuncs->Argv(1, link, sizeof(link)); if (!strcmp(text, "Change Filter") && !*link) { const char *console = WINDOWNAME; - pCon_SetConsoleFloat(console, "linebuffered", true); - pCon_SetConsoleString(console, "footer", "Please enter filter:"); + confuncs->SetConsoleFloat(console, "linebuffered", true); + confuncs->SetConsoleString(console, "footer", "Please enter filter:"); return true; } if (!strcmp(text, "Maps") && !*link) @@ -580,38 +593,38 @@ static qintptr_t QI_ConsoleLink(qintptr_t *args) } return false; } -static qintptr_t QI_Tick(qintptr_t *args) +static void QDECL QI_Tick(double realtime, double gametime) { if (dlcontext != -1) { - unsigned int flen; - if (pFS_GetLen(dlcontext, &flen, NULL)) + qofs_t flen; + if (filefuncs->GetLen(dlcontext, &flen)) { int ofs = 0; char *file; qboolean archive = true; if (flen == 0) { - pFS_Close(dlcontext); - flen = pFS_Open("**plugconfig", &dlcontext, 1); + filefuncs->Close(dlcontext); + flen = filefuncs->Open("**plugconfig", &dlcontext, 1); if (dlcontext == -1) { QI_RefreshMapList(false); - return false; + return; } archive = false; } file = malloc(flen+1); file[flen] = 0; - pFS_Read(dlcontext, file, flen); - pFS_Close(dlcontext); + filefuncs->Read(dlcontext, file, flen); + filefuncs->Close(dlcontext); if (archive) { - pFS_Open("**plugconfig", &dlcontext, 2); + filefuncs->Open("**plugconfig", &dlcontext, 2); if (dlcontext != -1) { - pFS_Write(dlcontext, file, flen); - pFS_Close(dlcontext); + filefuncs->Write(dlcontext, file, flen); + filefuncs->Close(dlcontext); } } dlcontext = -1; @@ -628,42 +641,46 @@ static qintptr_t QI_Tick(qintptr_t *args) // XML_ConPrintTree(thedatabase, "quadicted_xml", 0); } } - return false; } -static qintptr_t QI_ConExecuteCommand(qintptr_t *args) +static int QDECL QI_ConExecuteCommand(qboolean isinsecure) { char console[256]; char filter[256]; - pCmd_Argv(0, console, sizeof(console)); - pCmd_Args(filter, sizeof(filter)); + if (isinsecure) + return false; + + cmdfuncs->Argv(0, console, sizeof(console)); + cmdfuncs->Args(filter, sizeof(filter)); QI_UpdateFilter(filter); QI_RefreshMapList(true); - pCon_SetConsoleFloat(console, "linebuffered", false); - pCon_SetConsoleString(console, "footer", ""); + confuncs->SetConsoleFloat(console, "linebuffered", false); + confuncs->SetConsoleString(console, "footer", ""); return true; } -static qintptr_t QI_ExecuteCommand(qintptr_t *args) +static qboolean QI_ExecuteCommand(qboolean isinsecure) { char cmd[256]; - pCmd_Argv(0, cmd, sizeof(cmd)); + if (isinsecure) + return false; + cmdfuncs->Argv(0, cmd, sizeof(cmd)); if (!strcmp(cmd, "qi") || !strcmp(cmd, "quaddicted")) { - if (pCmd_Argc() > 1) + if (cmdfuncs->Argc() > 1) { - pCmd_Args(cmd, sizeof(cmd)); + cmdfuncs->Args(cmd, sizeof(cmd)); QI_UpdateFilter(cmd); } else if (QI_SetupWindow(WINDOWNAME, false)) { - pCon_SetActive(WINDOWNAME); + confuncs->SetActive(WINDOWNAME); return true; } if (!thedatabase && dlcontext == -1) - pFS_Open(DATABASEURL, &dlcontext, 1); + filefuncs->Open(DATABASEURL, &dlcontext, 1); QI_RefreshMapList(true); return true; @@ -671,22 +688,27 @@ static qintptr_t QI_ExecuteCommand(qintptr_t *args) return false; } -extern void (*Con_TrySubPrint)(const char *conname, const char *message); -qintptr_t Plug_Init(qintptr_t *args) +qboolean Plug_Init(void) { - filters.minrating = filters.maxrating = -1; - Con_TrySubPrint = pCon_SubPrint; - if (Plug_Export("Tick", QI_Tick) && - Plug_Export("Shutdown", QI_Shutdown) && - Plug_Export("ExecuteCommand", QI_ExecuteCommand) && - Plug_Export("ConExecuteCommand", QI_ConExecuteCommand) && - Plug_Export("ConsoleLink", QI_ConsoleLink)) + confuncs = plugfuncs->GetEngineInterface(plugsubconsolefuncs_name, sizeof(*confuncs)); + filefuncs = plugfuncs->GetEngineInterface(plugfsfuncs_name, sizeof(*filefuncs)); + clientfuncs = plugfuncs->GetEngineInterface(plugclientfuncs_name, sizeof(*clientfuncs)); + + if (confuncs && filefuncs && clientfuncs) { - if (!BUILTINISVALID(MapLog_Query)) - Con_Printf("QI: Engine does not support map times\n"); - pCmd_AddCommand("qi"); - pCmd_AddCommand("quaddicted"); - return true; + filters.minrating = filters.maxrating = -1; + plugfuncs->ExportFunction("UpdateVideo", QI_UpdateVideo); + if (plugfuncs->ExportFunction("Tick", QI_Tick) && + plugfuncs->ExportFunction("Shutdown", QI_Shutdown) && + plugfuncs->ExportFunction("ExecuteCommand", QI_ExecuteCommand) && + plugfuncs->ExportFunction("ConExecuteCommand", QI_ConExecuteCommand) && + plugfuncs->ExportFunction("ConsoleLink", QI_ConsoleLink)) + { + cmdfuncs->AddCommand("qi"); + cmdfuncs->AddCommand("quaddicted"); + return true; + } } + //else not available in dedicated servers return false; } \ No newline at end of file diff --git a/plugins/qvm_api.c b/plugins/qvm_api.c deleted file mode 100644 index df0443751..000000000 --- a/plugins/qvm_api.c +++ /dev/null @@ -1,724 +0,0 @@ -/* An implementation of some 'standard' functions */ - -/* We use this with msvc too, because msvc's implementations of - _snprintf and _vsnprint differ - besides, this way we can make - sure qvms handle all the printf stuff that dlls do*/ -#include "plugin.h" - -#define longlong long - -/* -this is a fairly basic implementation. -don't expect it to do much. -You can probably get a better version from somewhere. -*/ -int Q_vsnprintf(char *buffer, size_t maxlen, const char *format, va_list vargs) -{ - int tokens=0; - const char *string_; - char *string; - char tempbuffer[64]; - char sign; - unsigned longlong uint_; - longlong int_; - float float_; - int i; - int use0s; - int width, useprepad, plus; - int precision; - int lengthspec; - int base, firstletter; - - if (!maxlen) - return 0; -maxlen--; - - while(*format) - { - switch(*format) - { - case '%': - plus = 0; - width= 0; - precision=-1; - useprepad=0; - use0s= 0; - lengthspec = 0; -retry: - switch(*(++format)) - { - case '-': - useprepad=true; - goto retry; - case '+': - plus = true; - goto retry; - case '.': - precision = 0; - while (format[1] >= '0' && format[1] <= '9') - precision = precision*10+*++format-'0'; - goto retry; - case 'l': - case 'h': - case 'j': - case 'z': - case 't': - case 'L': - lengthspec = (lengthspec<<8) | *format; - goto retry; - case '0': - if (!width) - { - use0s=true; - goto retry; - } - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - width=width*10+*format-'0'; - goto retry; - case '%': /*emit a %*/ - if (maxlen-- == 0) - {*buffer++='\0';return tokens;} - *buffer++ = *format; - break; - case 's': - if (!lengthspec) - string_ = va_arg(vargs, char *); - else - goto badformat; - if (!string_) - string_ = "(null)"; - if (width) - { - while (*string_ && width--) - { - if (maxlen-- == 0) - {*buffer++='\0';return tokens;} - *buffer++ = *string_++; - } - } - else - { - while (*string_) - { - if (maxlen-- == 0) - {*buffer++='\0';return tokens;} - *buffer++ = *string_++; - } - } - tokens++; - break; - case 'c': - if (!lengthspec) - int_ = va_arg(vargs, int); - else - goto badformat; - if (maxlen-- == 0) - {*buffer++='\0';return tokens;} - *buffer++ = int_; - tokens++; - break; - case 'p': - if (1) - { - if (!lengthspec) - uint_ = (size_t)va_arg(vargs, void*); - else - goto badformat; - } - else - case 'x': - case 'X': - case 'u': - { - if (!lengthspec) - uint_ = va_arg(vargs, unsigned int); - else if (lengthspec == 'l') - uint_ = va_arg(vargs, long); - else if (lengthspec == (('l'<<8)|'l')) - uint_ = va_arg(vargs, longlong); - else if (lengthspec == 'z') - int_ = va_arg(vargs, size_t); - else - goto badformat; - } - base = (*format=='u')?10:16; - firstletter = (*format=='X')?'A':'a'; - i = sizeof(tempbuffer)-2; - tempbuffer[i+1] = '\0'; - while(uint_) - { - tempbuffer[i] = (uint_%base) + '0'; - if (tempbuffer[i] > '9') - tempbuffer[i] = tempbuffer[i] - ':' + firstletter; - uint_/=base; - i--; - } - string = tempbuffer+i+1; - - if (!*string) - { - i=61; - string = tempbuffer+i+1; - string[0] = '0'; - string[1] = '\0'; - } - - width -= 62-i; - while (width>0) - { - string--; - if (use0s) - *string = '0'; - else - *string = ' '; - width--; - } - - while (*string) - { - if (maxlen-- == 0) - {*buffer++='\0';return tokens;} - *buffer++ = *string++; - } - tokens++; - break; - case 'd': - case 'i': - if (!lengthspec) - int_ = va_arg(vargs, int); - else if (lengthspec == 'l') - int_ = va_arg(vargs, long); - else if (lengthspec == (('l'<<8)|'l')) - int_ = va_arg(vargs, longlong); -// else if (lengthspec == (('h'<<8)|'h')) -// int_ = va_arg(vargs, char); -// else if (lengthspec == 'h') -// int_ = va_arg(vargs, short); -// else if (lengthspec == 'j') -// int_ = va_arg(vargs, intmax_t); - else if (lengthspec == 'z') - int_ = va_arg(vargs, size_t); -// else if (lengthspec == 't') -// int_ = va_arg(vargs, ptrdiff_t); - else - goto badformat; - base = 10; - if (useprepad) - { -/* - if (int_ >= 1000) - useprepad = 4; - else if (int_ >= 100) - useprepad = 3; - else if (int_ >= 10) - useprepad = 2; - else if (int_ >= 0) - useprepad = 1; - else if (int_ <= -1000) - useprepad = 5; - else if (int_ <= -100) - useprepad = 4; - else if (int_ <= -10) - useprepad = 3; - else - useprepad = 2; - - useprepad = precision - useprepad; -Con_Printf("add %i chars\n", useprepad); - while (useprepad>0) - { - if (--maxlen < 0) - {*buffer++='\0';return tokens;} - *buffer++ = ' '; - useprepad--; - } -Con_Printf("%i bytes left\n", maxlen); -*/ - } - if (int_ < 0) - { - sign = '-'; - int_ *= -1; - } - else if (plus) - sign = '+'; - else - sign = 0; - i = sizeof(tempbuffer)-2; - tempbuffer[sizeof(tempbuffer)-1] = '\0'; - while(int_) - { - tempbuffer[i--] = int_%base + '0'; - if (tempbuffer[i] > '9') - tempbuffer[i] = tempbuffer[i] - ':' + 'a'; - int_/=base; - } - if (sign) - tempbuffer[i--] = sign; - string = tempbuffer+i+1; - - if (!*string) - { - i=61; - string = tempbuffer+i+1; - string[0] = '0'; - string[1] = '\0'; - } - - width -= 62-i; -/* while (width>0) - { - string--; - *string = ' '; - width--; - } -*/ - while(width>0) - { - if (maxlen-- == 0) - {*buffer++='\0';return tokens;} - if (use0s) - *buffer++ = '0'; - else - *buffer++ = ' '; - width--; - } - - while (*string) - { - if (maxlen-- == 0) - {*buffer++='\0';return tokens;} - *buffer++ = *string++; - } - tokens++; - break; - case 'f': - if (!lengthspec) - float_ = (float)va_arg(vargs, double); - else if (lengthspec == 'L') - float_ = (float)va_arg(vargs, long double); - else - goto badformat; -//integer part. - int_ = (longlong)float_; - if (int_ < 0) - { - if (maxlen-- == 0) - {*buffer++='\0';return tokens;} - *buffer++ = '-'; - int_ *= -1; - } - i = sizeof(tempbuffer)-2; - tempbuffer[sizeof(tempbuffer)-1] = '\0'; - if (!int_) - { - tempbuffer[i--] = '0'; - } - else - { - while(int_) - { - tempbuffer[i--] = int_%10 + '0'; - int_/=10; - } - } - string = tempbuffer+i+1; - while (*string) - { - if (maxlen-- == 0) - {*buffer++='\0';return tokens;} - *buffer++ = *string++; - } - - int_ = sizeof(tempbuffer)-2-i; - -//floating point part. - float_ -= (longlong)float_; - i = 0; - tempbuffer[i++] = '.'; - if (precision < 0) - precision = 7; - while(float_ - (longlong)float_) - { - if (i > precision) //remove the excess presision. - break; - - float_*=10; - tempbuffer[i++] = (longlong)float_%10 + '0'; - } - if (i == 1) //no actual fractional part - { - tokens++; - break; - } - - //concatinate to our string - tempbuffer[i] = '\0'; - string = tempbuffer; - while (*string) - { - if (maxlen-- == 0) - {*buffer++='\0';return tokens;} - *buffer++ = *string++; - } - - tokens++; - break; - default: -badformat: - string_ = "ERROR IN FORMAT"; - while (*string_) - { - if (maxlen-- == 0) - {*buffer++='\0';return tokens;} - *buffer++ = *string_++; - } - *buffer++='\0'; - return tokens; - } - break; - default: - if (maxlen-- == 0) - {*buffer++='\0';return tokens;} - *buffer++ = *format; - break; - } - format++; - } - {*buffer++='\0';return tokens;} -} - -int Q_snprintf(char *buffer, size_t maxlen, const char *format, ...) -{ - int p; - va_list argptr; - - va_start (argptr, format); - p = Q_vsnprintf (buffer, maxlen, format,argptr); - va_end (argptr); - - return p; -} - -#ifdef Q3_VM -//libc functions that are actually properly supported on all other platforms (c89) -int strlen(const char *s) -{ - int len = 0; - while(*s++) - len++; - return len; -} - -int strncmp (const char *s1, const char *s2, int count) -{ - while (1) - { - if (!count--) - return 0; - if (*s1 != *s2) - return -1; // strings not equal - if (!*s1) - return 0; // strings are equal - s1++; - s2++; - } - - return -1; -} - -int strnicmp(const char *s1, const char *s2, int count) -{ - char c1, c2; - char ct; - while(*s1) - { - if (!count--) - return 0; - c1 = *s1; - c2 = *s2; - if (c1 != c2) - { - if (c1 >= 'a' && c1 <= 'z') c1 = c1-'a' + 'A'; - if (c2 >= 'a' && c2 <= 'z') c2 = c2-'a' + 'A'; - if (c1 != c2) - return c1= 'a' && c1 <= 'z') c1 = c1-'a' + 'A'; - if (c2 >= 'a' && c2 <= 'z') c2 = c2-'a' + 'A'; - if (c1 != c2) - return c1= '0' && *str <= '9') - num = num*base + (*str - '0'); - else if (*str >= 'a' && *str <= 'a'+base-10) - num = num*base + (*str - 'a')+10; - else if (*str >= 'A' && *str <= 'A'+base-10) - num = num*base + (*str - 'A')+10; - else break; //bad char - str++; - } - return num*sign; -} - -float atof(char *str) -{ - int sign; - float num = 0.0f; - float unit = 1; - - while(*(unsigned char*)str < ' ' && *str) - str++; - - if (*str == '-') - { - sign = -1; - str++; - } - else sign = 1; - - while(1) - {//each time we find a new digit, increase the value of the previous digets by a factor of ten, and add the new - if (*str >= '0' && *str <= '9') - num = num*10 + (*str - '0'); - else break; //bad char - str++; - } - if (*str == '.') - { //each time we find a new digit, decrease the value of the following digits. - str++; - while(1) - { - if (*str >= '0' && *str <= '9') - { - unit /= 10; - num = num + (*str - '0')*unit; - } - else break; //bad char - str++; - } - } - return num*sign; -} - -void strcpy(char *d, const char *s) -{ - while (*s) - { - *d++ = *s++; - } - *d='\0'; -} - -static long randx = 1; -void srand(unsigned int x) -{ - randx = x; -} -int getseed(void) -{ - return randx; -} -int rand(void) -{ - return(((randx = randx*1103515245 + 12345)>>16) & 077777); -} -#endif - -void Q_strlncpy(char *d, const char *s, int sizeofd, int lenofs) -{ - int i; - sizeofd--; - if (sizeofd < 0) - return; //this could be an error - - for (i=0; lenofs-- > 0; i++) - { - if (i == sizeofd) - break; - *d++ = *s++; - } - *d='\0'; -} - -void Q_strlcpy(char *d, const char *s, int n) -{ - int i; - n--; - if (n < 0) - return; //this could be an error - - for (i=0; *s; i++) - { - if (i == n) - break; - *d++ = *s++; - } - *d='\0'; -} -void Q_strlcat(char *d, const char *s, int n) -{ - if (n) - { - int dlen = strlen(d); - int slen = strlen(s)+1; - if (slen > (n-1)-dlen) - slen = (n-1)-dlen; - memcpy(d+dlen, s, slen); - d[n - 1] = 0; - } -} - -char *Plug_Info_ValueForKey (const char *s, const char *key, char *out, size_t outsize) -{ - int isvalue = 0; - const char *start; - char *oout = out; - *out = 0; - if (*s != '\\') - return out; //gah, get lost with your corrupt infostrings. - - start = ++s; - while(1) - { - while(s[0] == '\\' && s[1] == '\\') - s+=2; - if (s[0] != '\\' && *s) - { - s++; - continue; - } - - //okay, it terminates here - isvalue = !isvalue; - if (isvalue) - { - if (strlen(key) == (size_t)(s - start) && !strncmp(start, key, s - start)) - { - s++; - while (outsize --> 1) - { - if (s[0] == '\\' && s[1] == '\\') - s++; - else if (s[0] == '\\' || !s[0]) - break; - *out++ = *s++; - } - *out++ = 0; - return oout; - } - } - if (*s) - start = ++s; - else - break; - } - return oout; -} diff --git a/plugins/readme-linux.txt b/plugins/readme-linux.txt deleted file mode 100755 index ffedf2c41..000000000 --- a/plugins/readme-linux.txt +++ /dev/null @@ -1,25 +0,0 @@ -To compile QVM's in Linux, you need the Quake3 Sourcecode to compile 4 binaries from it.. the Q3 sourcode can be fetched from google or here: http://www.idsoftware.com/business/techdownloads/ - -You also need "dos2unix" or anotherwise known as "fromdos" to modify some files which have DOS encoding in them that need to be changed to Linux style. (sudo apt-get install dos2unix or something like that anyway) - -In the "/quake3-1.32b/lcc/src/" directory, run "fromdos" on all the .md files (fromdos *.md) otherwise "rcc" will not compile. - -Now to the "/quake3-1.32b/lcc/" directory, need to build 3 targets: - -make rcc (once compiled will be in /tmp/ as "rcc", you need to rename it to "q3rcc" and move it somewhere Linux can see it like /usr/bin) - -make cpp (once compiled will be in /tmp/ as "cpp", you need to rename it to "q3cpp" and move it somewhere Linux can see it like /usr/bin/) - -make lcc (once compiled will be in /tmp/ as "lcc", dont rename it, but move it somewhere Linux can see it like /usr/bin/) - -Now to the "/quake3-1.32b/q3asm/" directory, the last target: - -make (will be compiled in the same directory, move it somewhere Linux can see it like /usr/bin/) - -With these 4 binaries built from the Quake3 source, should be able to now go to each Plugin's directory and type "make qvm"... if it works out you should have a "pluginname.qvm". - -NOTE: If you are using the Icculus q3asm tool, you must specify "-vq3" before building. -NOTE2: FTE now has its own q3asm tool called "q3asm2" which you can find in the SVN repository. - -~ Moodles (any questions about this guide ask me) - diff --git a/plugins/readme.txt b/plugins/readme.txt deleted file mode 100644 index eec219659..000000000 --- a/plugins/readme.txt +++ /dev/null @@ -1,36 +0,0 @@ -Plugins are a low priority. - -There are a few plugins at the moment: -emailnot: pop3/imap email notification. -emailsv: pop3/smtp email server functionality (a bit pointless - won't even compile) -ezscript: command remapping to make fte compatable with ezqauke/fuhquake/mqwcl configs. -hud: kinda cool. But use csqc instead. -irc: an irc client: use irc nick, irc open, that'll spawn a new console in quake which can accept irc commands naturally. ctrl+tab to switch consoles. Currently native only. -serverb: server browser. The one built in is better. This one was for the sake of it. Native only, could be rewritten for qvm. -winamp: greater winamp control, and general media menu. Native only. -xsv: An X windowing system server. Absolutly bug ridden. About the only thing it runs properly is Quake. Native only, for efficiency reasons. - - - -To compile a qvm version of a plugin, go to the root plugin directory. edit paths.bat to change the Q3SrcDir variable to point to where you have the q3 sourcecode installed (qvms require q3 tools). You should almost definatly be using the gpled sourcecode release, from which you will need to compile q3asm yourself. -If you also set the QuakeDir variable, the install.bat files will copy the newly compiled qvms to fte/plugins, which is rather convienient. - -Note that when building a qvm using id's version of lcc, you will be spammed by messages regarding compiler-dependant conversions. -There is no easy way to disable these messages without killing off all warnings (otherwise it would already be off). -The only way is to recompile the compiler. This requires msvc or a lot of C knoledge! -The actual sourcecode change is around line 621 or lcc/src/expr.c -Make it so it reads like this instead. - case POINTER: - if (src->op != dst->op) - p = simplify(CVP, dst, p, NULL); - else { -> if (Aflag >= 1) - if (isfunc(src->type) && !isfunc(dst->type) - || !isfunc(src->type) && isfunc(dst->type)) - warning("conversion from `%t' to `%t' is compiler dependent\n", p->type, type); -The > characture denotes the line to add. This will make the warning only appear when ansi compatability warnings are enabled. -You will then need to recompile. -With msvc installed, load up a command prompt, run vcvars32.bat (eg, with the quotes, type "c:\program files\microsoft visual studio\v98\bin\vcvars32.bat"), then go to the lcc directory (using the cd command) and type 'buildnt' (without quotes). You should now have a new lcc compiler without this pesky warning (by default). -This will then cause most of the qvm-compatable plugins to compile warning free. - -If you ask, I will send a copy of the required qvm-compiling files to you. They will be either copied directly from the q3 source release, or self built with no more changes than in this file. \ No newline at end of file diff --git a/plugins/spaceinv/Makefile b/plugins/spaceinv/Makefile deleted file mode 100644 index caced6142..000000000 --- a/plugins/spaceinv/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -LCC_FLAGS=-DQ3_VM -S -Wf-target=bytecode -Wf-g - -qvm: - lcc $(LCC_FLAGS) spaceinv.c; lcc $(LCC_FLAGS) ../memory.c -DMEMSIZE=1048576; lcc $(LCC_FLAGS) ../plugin.c; lcc $(LCC_FLAGS) ../qvm_api.c; q3asm -f spaceinv -clean: - rm -rf $(OBJECTS) $(OUTFILE) *.qvm *.asm diff --git a/plugins/spaceinv/compile.bat b/plugins/spaceinv/compile.bat deleted file mode 100644 index f2e9902f4..000000000 --- a/plugins/spaceinv/compile.bat +++ /dev/null @@ -1,22 +0,0 @@ -@echo off -call ..\paths.bat - -del vm\*.asm -rmdir vm -mkdir vm -cd vm -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../spaceinv.c -if errorlevel 1 goto end -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../memory.c -DMEMSIZE=1048576 -if errorlevel 1 goto end -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../plugin.c -if errorlevel 1 goto end -lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g ../../qvm_api.c -if errorlevel 1 goto end -q3asm -f ../spaceinv - -:end - -cd .. - -pause \ No newline at end of file diff --git a/plugins/terrorgen/terragen.c b/plugins/terrorgen/terragen.c index ff0d2d106..2a969107c 100644 --- a/plugins/terrorgen/terragen.c +++ b/plugins/terrorgen/terragen.c @@ -11,14 +11,135 @@ FIXME: no way to speciffy which gen plugin to use for a particular map #include "com_mesh.h" #include "gl_terrain.h" -static terrainfuncs_t *terr; -static modplugfuncs_t *modfuncs; +#define GENHIGHTSCALE 1024.0 -static void TerrorGen_GenerateOne(heightmap_t *hm, int sx, int sy, hmsection_t *s) +static plugterrainfuncs_t *terr; +static plugmodfuncs_t *modfuncs; + +struct rndctx_s +{ + unsigned int x, y, z, w; +}; +unsigned int myrand(struct rndctx_s *ctx) +{ //ripped from wikipedia (originally called xorshift128) + unsigned int t = ctx->x ^ (ctx->x << 11); + ctx->x = ctx->y; ctx->y = ctx->z; ctx->z = ctx->w; + return ctx->w = ctx->w ^ (ctx->w >> 19) ^ t ^ (t >> 8); +} +float TerrorGen_PredCRandom(heightmap_t *hm, int x, int y) +{ + int seed = atoi(hm->seed); + struct rndctx_s rctx = {x*3421 ^ y*35231, y*23423, seed, seed+seed*4321+x*432+y*423+x*y}; //overflows are fine + unsigned int r = myrand(&rctx); + return ((r & 0xffffff) / (float)0x800000)-1; +} + +float TerrorGen_CRandom(struct rndctx_s *rctx) +{ + unsigned int r = myrand(rctx); + return ((r & 0xffffff) / (float)0x800000)-1; +} + + +//the four corners are defined in advance. +//size is a power-of-two, h must be sized pow(size+1,2) +static void GenHeights(heightmap_t *hm, struct rndctx_s *rctx, float *h, int size, int sx, int sy, float scale) +{ + int stride = size+1; + int x, y; + //borders are left, right, top, bottom + while(size > 1) + { + int m = size/2; + + //find central points (diamond pattern) + for (x = 0; x < stride-1; x += size) + { + for (y = 0; y < stride-1; y += size) + { + float mid = (h[(x)+(y)*stride] + h[(x+size)+(y)*stride] + h[(x)+(y+size)*stride] + h[(x+size)+(y+size)*stride])/4; + mid += TerrorGen_CRandom(rctx)*scale; + h[(x+m) + (y+m)*stride] = mid; + } + } + + //find square points (square pattern) + for (x = 0; x < stride-1; x += size) + { + for (y = 0; y < stride-1; y += size) + { + float mid; + //left side + mid = h[(x)+(y)*stride]; + mid += h[(x)+(y+size)*stride]; + if (x != 0) //not an outer edges + { + mid += h[(x-m)+(y+m)*stride]; + mid += h[(x+m)+(y+m)*stride]; + mid = mid/4 + TerrorGen_CRandom(rctx)*scale; + } + else //outer edge doesn't look inwards, because any neighbouring block would not know it + mid = mid/2 + TerrorGen_PredCRandom(hm, sx+x, sy+y+m)*scale; + h[(x) + (y+m)*stride] = mid; + + //right + mid = h[(x+size)+(y)*stride]; + mid += h[(x+size)+(y+size)*stride]; + if (x+size != stride-1) //not an outer edges + { + mid += h[(x+size-m)+(y+m)*stride]; + mid += h[(x+size+m)+(y+m)*stride]; + mid = mid/4 + TerrorGen_CRandom(rctx)*scale; + } + else //outer edge doesn't look inwards, because any neighbouring block would not know it + mid = mid/2 + TerrorGen_PredCRandom(hm, sx+x+size, sy+y+m)*scale; + h[(x+size) + (y+m)*stride] = mid; + + //top + mid = h[(x)+(y)*stride]; + mid += h[(x+size)+(y)*stride]; + if (y != 0) //not an outer edges + { + mid += h[(x+m)+(y-m)*stride]; + mid += h[(x+m)+(y+m)*stride]; + mid = mid/4 + TerrorGen_CRandom(rctx)*scale; + } + else //outer edge doesn't look inwards, because any neighbouring block would not know it + mid = mid/2 + TerrorGen_PredCRandom(hm, sx+x+m, sy+y)*scale; + h[(x+m) + (y)*stride] = mid; + + //bottom + mid = h[(x)+(y+size)*stride]; + mid += h[(x+size)+(y+size)*stride]; + if (y+size != stride-1) //not an outer edges + { + mid += h[(x+m)+(y+size-m)*stride]; + mid += h[(x+m)+(y+size+m)*stride]; + mid = mid/4 + TerrorGen_CRandom(rctx)*scale; + } + else //outer edge doesn't look inwards, because any neighbouring block would not know it + mid = mid/2 + TerrorGen_PredCRandom(hm, sx+x+m, sy+y+size)*scale; + h[(x+m) + (y+size)*stride] = mid; + } + } + size = m; + scale /= 2; + } +} + + + +static void TerrorGen_GenerateOne(heightmap_t *hm, struct rndctx_s *rctx, int sx, int sy, hmsection_t *s, float tl,float tr,float bl,float br) { int x,y,i; qbyte *lm; + s->heights[0] = tl; + s->heights[SECTHEIGHTSIZE-1] = tr; + s->heights[0+(SECTHEIGHTSIZE-1)*SECTHEIGHTSIZE] = bl; + s->heights[SECTHEIGHTSIZE-1+(SECTHEIGHTSIZE-1)*SECTHEIGHTSIZE] = br; + GenHeights(hm, rctx, s->heights, SECTHEIGHTSIZE-1, sx*(SECTHEIGHTSIZE-1), sy*(SECTHEIGHTSIZE-1), GENHIGHTSCALE/16); + s->flags |= TSF_RELIGHT; //pick the textures to blend between. I'm just hardcoding shit here. this is meant to be some sort example. @@ -31,11 +152,8 @@ static void TerrorGen_GenerateOne(heightmap_t *hm, int sx, int sy, hmsection_t * for (x = 0; x < SECTHEIGHTSIZE; x++, i++) { //calculate where it is in worldspace, if that's useful to you. - float wx = hm->sectionsize*(sx + x/(float)(SECTHEIGHTSIZE-1)); - float wy = hm->sectionsize*(sy + y/(float)(SECTHEIGHTSIZE-1)); - - //many shallow mounds, on a grid. - s->heights[i] = 128*sin(wx * (2*M_PI/1024)) * sin(wy * (2*M_PI/1024)); +// float wx = hm->sectionsize*(sx + x/(float)(SECTHEIGHTSIZE-1)); +// float wy = hm->sectionsize*(sy + y/(float)(SECTHEIGHTSIZE-1)); //calculate the RGBA tint. these are floats, so you can oversaturate. s->colours[i][0] = 1; @@ -70,7 +188,7 @@ static void TerrorGen_GenerateOne(heightmap_t *hm, int sx, int sy, hmsection_t * } } - //insert the occasional mesh... +/* //insert the occasional mesh... if ((sx&3) == 0 && (sy&3) == 0) { vec3_t ang, org, axis[3]; @@ -84,20 +202,37 @@ static void TerrorGen_GenerateOne(heightmap_t *hm, int sx, int sy, hmsection_t * VectorNegate(axis[1],axis[1]); //axis[1] needs to be left, not right. silly quakeisms. //obviously you can insert mdls instead... preferably do that! - terr->AddMesh(hm, TGS_TRYLOAD, NULL, "maps/dm4.bsp", org, axis, 1); - } + terr->AddMesh(hm, TGS_NOLOAD, NULL, "maps/dm4.bsp", org, axis, 1); + }*/ } -#define GENBLOCKSIZE 1 +#define GENBLOCKSIZE 16 static qboolean QDECL TerrorGen_GenerateBlock(heightmap_t *hm, int sx, int sy, unsigned int tgsflags) { + float h[(GENBLOCKSIZE+1)*(GENBLOCKSIZE+1)]; hmsection_t *sect[GENBLOCKSIZE*GENBLOCKSIZE]; int mx = sx & ~(GENBLOCKSIZE-1); int my = sy & ~(GENBLOCKSIZE-1); + struct rndctx_s rctx; + int i; if (!terr->GenerateSections(hm, mx, my, GENBLOCKSIZE, sect)) return false; + for (i = 0; i < countof(h); i++) + h[i] = -1024; + + //generate global height values + h[ 0+ 0*(GENBLOCKSIZE+1)] = 0;//TerrorGen_PredRandom(hm, mx , my )*GENHIGHTSCALE*4; + h[GENBLOCKSIZE+ 0*(GENBLOCKSIZE+1)] = 0;//TerrorGen_PredRandom(hm, mx+GENBLOCKSIZE, my )*GENHIGHTSCALE*4; + h[ GENBLOCKSIZE*(GENBLOCKSIZE+1)] = 0;//TerrorGen_PredRandom(hm, mx , my+GENBLOCKSIZE)*GENHIGHTSCALE*4; + h[GENBLOCKSIZE+GENBLOCKSIZE*(GENBLOCKSIZE+1)] = 0;//TerrorGen_PredRandom(hm, mx+GENBLOCKSIZE, my+GENBLOCKSIZE)*GENHIGHTSCALE*4; + rctx.x = mx*4142^mx*523423; + rctx.y = mx*4323; + rctx.z = mx*234; + rctx.w = 2535; + GenHeights(hm, &rctx, h, GENBLOCKSIZE, (mx-CHUNKBIAS)*SECTHEIGHTSIZE, (my-CHUNKBIAS)*SECTHEIGHTSIZE, GENHIGHTSCALE); + for (sy = 0; sy < GENBLOCKSIZE; sy++) { for (sx = 0; sx < GENBLOCKSIZE; sx++) @@ -105,33 +240,38 @@ static qboolean QDECL TerrorGen_GenerateBlock(heightmap_t *hm, int sx, int sy, u if (!sect[sx + sy*GENBLOCKSIZE]) continue; //already in memory. - TerrorGen_GenerateOne(hm, mx+sx-CHUNKBIAS, my+sy-CHUNKBIAS, sect[sx + sy*GENBLOCKSIZE]); + //in case we skipped a section... + rctx.x = (mx*4141^mx*523423) + sx*4231 + sy*539; + rctx.y = mx*4323; + rctx.z = mx*231+sy; + rctx.w = 253553; + + TerrorGen_GenerateOne(hm, &rctx, mx+sx-CHUNKBIAS, my+sy-CHUNKBIAS, sect[sx + sy*GENBLOCKSIZE], + h[(sx )+(sy )*(GENBLOCKSIZE+1)], + h[(sx+1)+(sy )*(GENBLOCKSIZE+1)], + h[(sx )+(sy+1)*(GENBLOCKSIZE+1)], + h[(sx+1)+(sy+1)*(GENBLOCKSIZE+1)]); terr->FinishedSection(sect[sx + sy*GENBLOCKSIZE], true); } } return true; } -static qintptr_t TerrorGen_Shutdown(qintptr_t *args) +static qboolean TerrorGen_Shutdown(void) { //if its still us, make sure there's no dangling pointers. if (terr->AutogenerateSection == TerrorGen_GenerateBlock) terr->AutogenerateSection = NULL; return true; } -qintptr_t Plug_Init(qintptr_t *args) +qboolean Plug_Init(void) { - if (CHECKBUILTIN(Mod_GetPluginModelFuncs)) - { - modfuncs = pMod_GetPluginModelFuncs(sizeof(modplugfuncs_t)); - if (modfuncs && modfuncs->version < MODPLUGFUNCS_VERSION) - modfuncs = NULL; - } - - if (modfuncs && modfuncs->GetTerrainFuncs) - terr = modfuncs->GetTerrainFuncs(); + modfuncs = plugfuncs->GetEngineInterface(plugmodfuncs_name, sizeof(*modfuncs)); + if (modfuncs && modfuncs->version < MODPLUGFUNCS_VERSION) + modfuncs = NULL; + terr = plugfuncs->GetEngineInterface(plugterrainfuncs_name, sizeof(*terr)); if (!terr) return false; - if (!Plug_Export("Shutdown", TerrorGen_Shutdown)) + if (!plugfuncs->ExportFunction("Shutdown", TerrorGen_Shutdown)) return false; terr->AutogenerateSection = TerrorGen_GenerateBlock; diff --git a/plugins/xsv/m_x.c b/plugins/xsv/m_x.c index 6f2828a6b..a29a034ab 100644 --- a/plugins/xsv/m_x.c +++ b/plugins/xsv/m_x.c @@ -6,6 +6,9 @@ //wmaker -display :1 (or xterm or whatever) #include "../plugin.h" +static plugnetfuncs_t *netfuncs; +static plugsubconsolefuncs_t *confuncs; + #include "qux.h" #include "../engine.h" @@ -385,7 +388,7 @@ int X_SendInputNotification(xEvent *data, xwindow_t *window, unsigned int mask) if (!(nm->mask & mask)) continue; - Con_Printf("Sending input %i\n", data->u.u.type); +// Con_Printf("Sending input %i\n", data->u.u.type); if (data->u.u.type == FocusIn || data->u.u.type == FocusOut) { @@ -649,7 +652,7 @@ qboolean XWindows_TendToClient(xclient_t *cl) //true says drop } len = cl->inbuffermaxlen - cl->inbufferlen; //Con_Printf("recving\n"); - len = pNet_Recv(cl->socket, cl->inbuffer + cl->inbufferlen, len); + len = netfuncs->Recv(cl->socket, cl->inbuffer + cl->inbufferlen, len); //Con_Printf("recved %i\n", len); if (len == 0) //connection was closed. bummer. { @@ -806,7 +809,7 @@ nextmessage: len = cl->outbufferlen; if (len > 8000) len = 8000; - len = pNet_Send(cl->socket, cl->outbuffer, len); + len = netfuncs->Send(cl->socket, cl->outbuffer, len); if (len>0) { memmove(cl->outbuffer, cl->outbuffer+len, cl->outbufferlen - len); @@ -819,7 +822,7 @@ nextmessage: if (len != N_WOULDBLOCK) { Con_Printf("X send error %i\n", len); - cl->tobedropped = true; + return true; } } } @@ -940,7 +943,7 @@ void XWindows_TendToClients(void) if (xlistensocket >= 0) { - newclient = pNet_Accept(xlistensocket, NULL, 0); + newclient = netfuncs->Accept(xlistensocket, NULL, 0); if (newclient >= 0) { cl = malloc(sizeof(xclient_t)); @@ -986,7 +989,7 @@ void XWindows_TendToClients(void) break; } #endif - pNet_Close(cl->socket); + netfuncs->Close(cl->socket); if (cl->inbuffer) free(cl->inbuffer); if (cl->outbuffer) @@ -1027,7 +1030,7 @@ int XWindows_UnixListen(int x11display) // remove socket file unlink(socketfile); - return pNet_TCPListen(va("unix://%s", socketfile), baseport+x11display, 3); + return netfuncs->TCPListen(va("unix://%s", socketfile), baseport+x11display, 3); } #endif @@ -1046,7 +1049,7 @@ void XWindows_Startup(int x11display) //initialise the server socket and do any #else if (x11display < 0) x11display = 0; - xlistensocket = pNet_TCPListen(NULL, baseport+x11display, 3); + xlistensocket = netfuncs->TCPListen(NULL, baseport+x11display, 3); #endif if (xlistensocket < 0) { @@ -1058,7 +1061,7 @@ void XWindows_Startup(int x11display) //initialise the server socket and do any X_InitRequests(); XS_CreateInitialResources(); - system(va("DISPLAY=:%i /usr/bin/x-terminal-emulator &", x11display)); + system(va("DISPLAY=127.0.0.1:%i /usr/bin/x-terminal-emulator &", x11display)); } XS_CheckResourceSentinals(); @@ -1309,7 +1312,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode) //LeaveNotify with detail Inferior is generated on A. ev.u.u.type = LeaveNotify; ev.u.u.detail = NotifyInferior; - ev.u.enterLeave.time = pSys_Milliseconds(); + ev.u.enterLeave.time = plugfuncs->GetMilliseconds(); ev.u.enterLeave.root = rootwindow->res.id; ev.u.enterLeave.event = oc[0]->res.id; ev.u.enterLeave.child = None; @@ -1327,7 +1330,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode) { ev.u.u.type = EnterNotify; ev.u.u.detail = NotifyVirtual; - ev.u.enterLeave.time = pSys_Milliseconds(); + ev.u.enterLeave.time = plugfuncs->GetMilliseconds(); ev.u.enterLeave.root = rootwindow->res.id; ev.u.enterLeave.event = oc[i]->res.id; ev.u.enterLeave.child = oc[i-1]->res.id; @@ -1344,7 +1347,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode) //EnterNotify with detail Ancestor is generated on B. ev.u.u.type = EnterNotify; ev.u.u.detail = NotifyInferior; - ev.u.enterLeave.time = pSys_Milliseconds(); + ev.u.enterLeave.time = plugfuncs->GetMilliseconds(); ev.u.enterLeave.root = rootwindow->res.id; ev.u.enterLeave.event = nc[0]->res.id; ev.u.enterLeave.child = None; @@ -1363,7 +1366,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode) //LeaveNotify with detail Ancestor is generated on A. ev.u.u.type = LeaveNotify; ev.u.u.detail = NotifyAncestor; - ev.u.enterLeave.time = pSys_Milliseconds(); + ev.u.enterLeave.time = plugfuncs->GetMilliseconds(); ev.u.enterLeave.root = rootwindow->res.id; ev.u.enterLeave.event = oc[0]->res.id; ev.u.enterLeave.child = None; @@ -1381,7 +1384,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode) { ev.u.u.type = LeaveNotify; ev.u.u.detail = NotifyVirtual; - ev.u.enterLeave.time = pSys_Milliseconds(); + ev.u.enterLeave.time = plugfuncs->GetMilliseconds(); ev.u.enterLeave.root = rootwindow->res.id; ev.u.enterLeave.event = nc[i]->res.id; ev.u.enterLeave.child = nc[i-1]->res.id; @@ -1398,7 +1401,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode) //EnterNotify with detail Inferior is generated on B. ev.u.u.type = EnterNotify; ev.u.u.detail = NotifyInferior; - ev.u.enterLeave.time = pSys_Milliseconds(); + ev.u.enterLeave.time = plugfuncs->GetMilliseconds(); ev.u.enterLeave.root = rootwindow->res.id; ev.u.enterLeave.event = nc[0]->res.id; ev.u.enterLeave.child = None; @@ -1418,7 +1421,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode) //LeaveNotify with detail Nonlinear is generated on A. ev.u.u.type = LeaveNotify; ev.u.u.detail = NotifyNonlinear; - ev.u.enterLeave.time = pSys_Milliseconds(); + ev.u.enterLeave.time = plugfuncs->GetMilliseconds(); ev.u.enterLeave.root = rootwindow->res.id; ev.u.enterLeave.event = oc[0]->res.id; ev.u.enterLeave.child = None; @@ -1436,7 +1439,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode) { ev.u.u.type = LeaveNotify; ev.u.u.detail = NotifyNonlinearVirtual; - ev.u.enterLeave.time = pSys_Milliseconds(); + ev.u.enterLeave.time = plugfuncs->GetMilliseconds(); ev.u.enterLeave.root = rootwindow->res.id; ev.u.enterLeave.event = nc[i]->res.id; ev.u.enterLeave.child = nc[i-1]->res.id; @@ -1454,7 +1457,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode) { ev.u.u.type = EnterNotify; ev.u.u.detail = NotifyNonlinearVirtual; - ev.u.enterLeave.time = pSys_Milliseconds(); + ev.u.enterLeave.time = plugfuncs->GetMilliseconds(); ev.u.enterLeave.root = rootwindow->res.id; ev.u.enterLeave.event = oc[i]->res.id; ev.u.enterLeave.child = oc[i-1]->res.id; @@ -1471,7 +1474,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode) //EnterNotify with detail Nonlinear is generated on B. ev.u.u.type = EnterNotify; ev.u.u.detail = NotifyNonlinear; - ev.u.enterLeave.time = pSys_Milliseconds(); + ev.u.enterLeave.time = plugfuncs->GetMilliseconds(); ev.u.enterLeave.root = rootwindow->res.id; ev.u.enterLeave.event = nc[0]->res.id; ev.u.enterLeave.child = None; @@ -1601,7 +1604,7 @@ void X_EvalutateCursorOwner(int movemode) ev.u.u.type = MotionNotify; ev.u.u.detail = 0; ev.u.u.sequenceNumber = 0; - ev.u.keyButtonPointer.time = pSys_Milliseconds(); + ev.u.keyButtonPointer.time = plugfuncs->GetMilliseconds(); ev.u.keyButtonPointer.root = rootwindow->res.id; ev.u.keyButtonPointer.event = cursorowner->res.id; ev.u.keyButtonPointer.child = (x_windowwithcursor == cursorowner->res.id)?None:x_windowwithcursor; @@ -1929,7 +1932,7 @@ void XWindows_KeyDown(int key) if (key == K_MOUSE1) { ev.u.u.type = ButtonPress; - ev.u.u.detail = 1; + ev.u.u.detail = Button1; mousestate |= Button1Mask; ev.u.keyButtonPointer.state = mousestate; ev.u.keyButtonPointer.child = x_windowwithcursor; @@ -1937,7 +1940,7 @@ void XWindows_KeyDown(int key) else if (key == K_MOUSE3) { ev.u.u.type = ButtonPress; - ev.u.u.detail = 2; + ev.u.u.detail = Button2; mousestate |= Button2Mask; ev.u.keyButtonPointer.state = mousestate; ev.u.keyButtonPointer.child = x_windowwithcursor; @@ -1945,7 +1948,7 @@ void XWindows_KeyDown(int key) else if (key == K_MOUSE2) { ev.u.u.type = ButtonPress; - ev.u.u.detail = 3; + ev.u.u.detail = Button3; mousestate |= Button3Mask; ev.u.keyButtonPointer.state = mousestate; ev.u.keyButtonPointer.child = x_windowwithcursor; @@ -1953,7 +1956,7 @@ void XWindows_KeyDown(int key) else if (key == K_MOUSE4) { ev.u.u.type = ButtonPress; - ev.u.u.detail = 4; + ev.u.u.detail = Button4; mousestate |= Button4Mask; ev.u.keyButtonPointer.state = mousestate; ev.u.keyButtonPointer.child = x_windowwithcursor; @@ -1961,7 +1964,7 @@ void XWindows_KeyDown(int key) else if (key == K_MOUSE5) { ev.u.u.type = ButtonPress; - ev.u.u.detail = 5; + ev.u.u.detail = Button5; mousestate |= Button5Mask; ev.u.keyButtonPointer.state = mousestate; ev.u.keyButtonPointer.child = x_windowwithcursor; @@ -1976,7 +1979,7 @@ void XWindows_KeyDown(int key) ev.u.keyButtonPointer.child = x_windowwithfocus; } ev.u.u.sequenceNumber = 0; - ev.u.keyButtonPointer.time = pSys_Milliseconds(); + ev.u.keyButtonPointer.time = plugfuncs->GetMilliseconds(); ev.u.keyButtonPointer.rootX = x_mousex; ev.u.keyButtonPointer.rootY = x_mousey; ev.u.keyButtonPointer.sameScreen= true; @@ -2026,7 +2029,7 @@ void XWindows_Keyup(int key) { ev.u.u.type = ButtonRelease; ev.u.keyButtonPointer.state = mousestate; - ev.u.u.detail = 1; + ev.u.u.detail = Button1; mousestate &= ~Button1Mask; ev.u.keyButtonPointer.state = mousestate; ev.u.keyButtonPointer.child = x_windowwithcursor; @@ -2035,7 +2038,7 @@ void XWindows_Keyup(int key) { ev.u.u.type = ButtonRelease; ev.u.keyButtonPointer.state = mousestate; - ev.u.u.detail = 2; + ev.u.u.detail = Button2; mousestate &= ~Button2Mask; ev.u.keyButtonPointer.state = mousestate; ev.u.keyButtonPointer.child = x_windowwithcursor; @@ -2044,7 +2047,7 @@ void XWindows_Keyup(int key) { ev.u.u.type = ButtonRelease; ev.u.keyButtonPointer.state = mousestate; - ev.u.u.detail = 3; + ev.u.u.detail = Button3; mousestate &= ~Button3Mask; ev.u.keyButtonPointer.state = mousestate; ev.u.keyButtonPointer.child = x_windowwithcursor; @@ -2053,7 +2056,7 @@ void XWindows_Keyup(int key) { ev.u.u.type = ButtonRelease; ev.u.keyButtonPointer.state = mousestate; - ev.u.u.detail = 4; + ev.u.u.detail = Button4; mousestate &= ~Button4Mask; ev.u.keyButtonPointer.state = mousestate; ev.u.keyButtonPointer.child = x_windowwithcursor; @@ -2062,7 +2065,7 @@ void XWindows_Keyup(int key) { ev.u.u.type = ButtonRelease; ev.u.keyButtonPointer.state = mousestate; - ev.u.u.detail = 5; + ev.u.u.detail = Button5; mousestate &= ~Button5Mask; ev.u.keyButtonPointer.state = mousestate; ev.u.keyButtonPointer.child = x_windowwithcursor; @@ -2076,7 +2079,7 @@ void XWindows_Keyup(int key) ev.u.keyButtonPointer.child = x_windowwithfocus; } ev.u.u.sequenceNumber = 0; - ev.u.keyButtonPointer.time = pSys_Milliseconds(); + ev.u.keyButtonPointer.time = plugfuncs->GetMilliseconds(); ev.u.keyButtonPointer.rootX = x_mousex; ev.u.keyButtonPointer.rootY = x_mousey; ev.u.keyButtonPointer.state = 0; @@ -2110,7 +2113,7 @@ void XWindows_Keyup(int key) XS_CheckResourceSentinals(); } -/*static int X11_MenuEvent(int *args) +/*qboolean QDECL X11_MenuEvent(int eventtype, int param, float mousecursor_x, float mousecursor_y) { mousecursor_x = args[2]; mousecursor_y = args[3]; @@ -2132,23 +2135,44 @@ void XWindows_Keyup(int key) return 0; }*/ -static qintptr_t X11_ExecuteCommand(qintptr_t *args) +static int X11_ExecuteCommand(qboolean isinsecure) { char cmd[256]; - pCmd_Argv(0, cmd, sizeof(cmd)); + cmdfuncs->Argv(0, cmd, sizeof(cmd)); if (!strcmp("startx", cmd)) { - pCmd_Argv(1, cmd, sizeof(cmd)); - XWindows_Startup(*cmd?atoi(cmd):-1); + if (confuncs) + { + const char *console = "x11"; + if (confuncs->GetConsoleFloat(console, "iswindow") != true) + { + confuncs->SetConsoleString(console, "title", "X11"); + confuncs->SetConsoleFloat(console, "iswindow", true); + confuncs->SetConsoleFloat(console, "forceutf8", true); + confuncs->SetConsoleFloat(console, "linebuffered", false); + confuncs->SetConsoleFloat(console, "maxlines", 0); + confuncs->SetConsoleFloat(console, "wnd_x", 0); + confuncs->SetConsoleFloat(console, "wnd_y", 0); + confuncs->SetConsoleFloat(console, "wnd_w", 640); + confuncs->SetConsoleFloat(console, "wnd_h", 480); + confuncs->SetConsoleString(console, "footer", ""); + } + confuncs->SetConsoleString(console, "backvideomap", "x11"); + confuncs->SetActive(console); + } + else + { + cmdfuncs->Argv(1, cmd, sizeof(cmd)); + XWindows_Startup(*cmd?atoi(cmd):-1); + } return 1; } return 0; } -static qintptr_t X11_Tick(qintptr_t *args) +static void QDECL X11_Tick(double realtime, double gametime) { XWindows_TendToClients(); - return 0; } static void *XWindows_Create(const char *medianame) //initialise the server socket and do any initial setup as required. @@ -2174,7 +2198,7 @@ static qboolean VARGS XWindows_DisplayFrame(void *ctx, qboolean nosound, qboolea static void XWindows_Shutdown(void *ctx) { - pNet_Close(xlistensocket); + netfuncs->Close(xlistensocket); xlistensocket = -1; } @@ -2239,17 +2263,21 @@ media_decoder_funcs_t decoderfuncs = }; -qintptr_t Plug_Init(qintptr_t *args) +qboolean Plug_Init(void) { - if (!Plug_Export("ExecuteCommand", X11_ExecuteCommand) || -// !Plug_Export("MenuEvent", X11_MenuEvent) || - !Plug_Export("Tick", X11_Tick)) + netfuncs = plugfuncs->GetEngineInterface(plugnetfuncs_name, sizeof(*netfuncs)); + confuncs = plugfuncs->GetEngineInterface(plugsubconsolefuncs_name, sizeof(*confuncs)); + + if (!netfuncs || + !plugfuncs->ExportFunction("ExecuteCommand", X11_ExecuteCommand) || +// !plugfuncs->ExportFunction("MenuEvent", X11_MenuEvent) || + !plugfuncs->ExportFunction("Tick", X11_Tick)) { Con_Printf("XServer plugin failed\n"); return false; } - if (!pPlug_ExportNative("Media_VideoDecoder", &decoderfuncs)) + if (!plugfuncs->ExportInterface("Media_VideoDecoder", &decoderfuncs, sizeof(decoderfuncs))) { Con_Printf("XServer plugin failed: Engine doesn't support media decoder plugins\n"); return false; @@ -2257,7 +2285,7 @@ qintptr_t Plug_Init(qintptr_t *args) Con_Printf("XServer plugin started\n"); - pCmd_AddCommand("startx"); + cmdfuncs->AddCommand("startx"); #ifndef K_CTRL K_CTRL = pKey_GetKeyCode("ctrl"); diff --git a/plugins/xsv/x_reqs.c b/plugins/xsv/x_reqs.c index 2da25f602..a8865794a 100644 --- a/plugins/xsv/x_reqs.c +++ b/plugins/xsv/x_reqs.c @@ -107,7 +107,7 @@ void XR_QueryExtension (xclient_t *cl, xReq *request) else #endif { - Con_Printf("Extension %s not supported\n", extname); + Con_Printf("x11sv plugin: Extension %s not supported\n", extname); rep.major_opcode = 0; rep.present = false; rep.first_event = 0; @@ -383,7 +383,7 @@ void XR_GetProperty (xclient_t *cl, xReq *request) ev.u.u.sequenceNumber = 0; ev.u.property.window = req->window; ev.u.property.atom = req->property; - ev.u.property.time = pSys_Milliseconds(); + ev.u.property.time = plugfuncs->GetMilliseconds(); ev.u.property.state = PropertyDelete; ev.u.property.pad1 = 0; @@ -488,7 +488,7 @@ void XR_ChangeProperty (xclient_t *cl, xReq *request) ev.u.u.sequenceNumber = 0; ev.u.property.window = req->window; ev.u.property.atom = req->property; - ev.u.property.time = pSys_Milliseconds(); + ev.u.property.time = plugfuncs->GetMilliseconds(); ev.u.property.state = PropertyNewValue; ev.u.property.pad1 = 0; @@ -526,7 +526,7 @@ void XR_DeleteProperty(xclient_t *cl, xReq *request) ev.u.u.sequenceNumber = 0; ev.u.property.window = req->window; ev.u.property.atom = req->property; - ev.u.property.time = pSys_Milliseconds(); + ev.u.property.time = plugfuncs->GetMilliseconds(); ev.u.property.state = PropertyDelete; ev.u.property.pad1 = 0; @@ -3799,6 +3799,18 @@ void XR_UngrabPointer (xclient_t *cl, xReq *request) X_EvalutateCursorOwner(NotifyUngrab); } +void XR_SetClipRectangles (xclient_t *cl, xReq *request) +{ + xSetClipRectanglesReq *req = (xSetClipRectanglesReq*)request; + xgcontext_t *gc; + if (XS_GetResource(req->gc, (void**)&gc) != x_gcontext) + { + X_SendError(cl, BadGC, req->gc, X_FreeGC, 0); + return; + } + Con_DPrintf("XR_SetClipRectangles is not implemented\n"); +} + void XR_NoOperation (xclient_t *cl, xReq *request) { } @@ -3872,6 +3884,8 @@ void X_InitRequests(void) XRequests[X_ImageText8] = XR_PolyText; XRequests[X_ImageText16] = XR_PolyText; + XRequests[X_SetClipRectangles] = XR_SetClipRectangles; + XRequests[X_ConfigureWindow] = XR_ConfigureWindow; XRequests[X_ReparentWindow] = XR_ReparentWindow; diff --git a/plugins/xsv/x_res.c b/plugins/xsv/x_res.c index 52ef46675..0b4d99931 100644 --- a/plugins/xsv/x_res.c +++ b/plugins/xsv/x_res.c @@ -611,6 +611,8 @@ xfont_t *XS_CreateFont(int id, xclient_t *owner, char *fontname) fread(in, len, 1, f); fclose(f); } + else + memset(in, 0, len); out = newfont->data; for (i = 0; i < width*height; i++)