diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 1ca48f97..fe769478 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -3584,16 +3584,20 @@ void CL_ConnectionlessPacket (void) { //c2s getchallenge //s2c c%u\0DTLS=$candtls - //c2s dtlsconnect %u <> + //<> + //c2s dtlsconnect %u //s2c dtlsopened //c2s DTLS(getchallenge) //DTLS(etc) + //NOTE: the dtlsconnect/dtlsopened parts are redundant and the non-dtls parts are entirely optional (and should be skipped the client requries/knows the server supports dtls) + //the challenge response includes server capabilities, so we still need the getchallenge/response part of the handshake despite dtls making the actual challenge part redundant. + //getchallenge has to be done twice, with the outer one only reporting whether dtls can/should be used. //this means the actual connect packet is already over dtls, which protects the user's userinfo. //FIXME: do rcon via dtls too, but requires tracking pending rcon packets until the handshake completes. - //server says it can do tls. + //server says it can do dtls, but will still need to ask it to allocate extra resources for us. char *pkt; //qwfwd proxy routing @@ -4030,7 +4034,7 @@ void CLNQ_ConnectionlessPacket(void) port = htons((unsigned short)MSG_ReadLong()); //this is the port that we're meant to respond to. - if (port) + if (port && !msg_badread) { char buf[256]; net_from.port = port; diff --git a/engine/client/m_items.c b/engine/client/m_items.c index 5a25bef4..e2c86872 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -764,6 +764,9 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, emenu_t *men int x = xpos+option->common.posx; int y = ypos+option->common.posy; + if (!option->edit.slim) + y += (16-8)/2; //fat ones are twice the height on account of the text box's borders. + Draw_FunStringWidth(x, y, option->edit.caption, option->edit.captionwidth, true, !menu->cursoritem && menu->selecteditem == option); x += option->edit.captionwidth + 3*8; if (option->edit.slim) @@ -2708,14 +2711,13 @@ int MC_AddBulk(struct emenu_s *menu, menuresel_t *resel, menubulk_t *bulk, int x { default: case 0: - y += 4; control = (union menuoption_s *)MC_AddEditCvar(menu, xleft, xtextend, y, bulk->text, bulk->cvarname, false); - spacing += 4; break; case 1: control = (union menuoption_s *)MC_AddEditCvar(menu, xleft, xtextend, y, bulk->text, bulk->cvarname, true); break; } + spacing = control->common.height; break; default: Con_Printf(CON_ERROR "Invalid type in bulk menu!\n"); diff --git a/engine/client/m_multi.c b/engine/client/m_multi.c index a200aca3..f567bf4b 100644 --- a/engine/client/m_multi.c +++ b/engine/client/m_multi.c @@ -569,6 +569,7 @@ static const char *numplayeroptions[] = { qboolean MultiBeginGame (union menuoption_s *option,struct emenu_s *menu, int key) { newmultimenu_t *info = menu->data; + char quoted[1024]; if (key != K_ENTER && key != K_KP_ENTER && key != K_GP_START && key != K_MOUSE1) return false; @@ -579,7 +580,7 @@ qboolean MultiBeginGame (union menuoption_s *option,struct emenu_s *menu, int ke Cbuf_AddText(va("maxclients \"%s\"\n", numplayeroptions[info->numplayers->selectedoption]), RESTRICT_LOCAL); if (info->rundedicated->value) Cbuf_AddText("setrenderer dedicated\n", RESTRICT_LOCAL); - Cbuf_AddText(va("hostname \"%s\"\n", info->hostnameedit->text), RESTRICT_LOCAL); + Cbuf_AddText(va("hostname %s\n", COM_QuotedString(info->hostnameedit->text, quoted, sizeof(quoted), false)), RESTRICT_LOCAL); Cbuf_AddText(va("deathmatch %i\n", info->deathmatch->selectedoption), RESTRICT_LOCAL); if (!info->deathmatch->selectedoption) Cbuf_AddText("coop 1\n", RESTRICT_LOCAL); @@ -589,7 +590,30 @@ qboolean MultiBeginGame (union menuoption_s *option,struct emenu_s *menu, int ke Cbuf_AddText(va("skill %i\n", info->skill->selectedoption), RESTRICT_LOCAL); Cbuf_AddText(va("timelimit %i\n", info->timelimit->selectedoption*5), RESTRICT_LOCAL); Cbuf_AddText(va("fraglimit %i\n", info->fraglimit->selectedoption*10), RESTRICT_LOCAL); - Cbuf_AddText(va("sv_public %i\n", info->publicgame->selectedoption-1), RESTRICT_LOCAL); + + if (info->publicgame->selectedoption-1 == 2) + { + const char *hostname = info->hostnameedit->text; + const char *shn; + for (shn = hostname; *shn; shn++) + { + if (*shn >= 'a' && *shn <= 'z') + continue; + if (*shn >= 'A' && *shn <= 'Z') + continue; + if (*shn >= '0' && *shn <= '9') + continue; + if (*shn == '-' || *shn <= '_') + continue; + break; + } + if (*shn || !*hostname || !strcasecmp(hostname, "player") || !strcasecmp(hostname, "unnamed")) //not simple enough... + Cbuf_AddText(va("sv_public \"/\"\n"), RESTRICT_LOCAL); + else + Cbuf_AddText(va("sv_public \"/%s\"\n", info->hostnameedit->text), RESTRICT_LOCAL); + } + else + Cbuf_AddText(va("sv_public %i\n", info->publicgame->selectedoption-1), RESTRICT_LOCAL); Cbuf_AddText(va("map \"%s\"\n", info->mapnameedit->text), RESTRICT_LOCAL); if (info->rundedicated->value) @@ -657,7 +681,7 @@ void M_Menu_GameOptions_f (void) NULL }; static const char *publicoptions[] = { - "Disabled", + "Splitscreen Only", "Private/LAN", "Public (Manual)", "Public (Holepunch)", diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 3da6c54d..3fbe4435 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -2367,7 +2367,36 @@ uploadfmt_t PR_TranslateTextureFormat(int qcformat) case 13: return PTI_RG8; case 14: return PTI_RGB32F; - default:return PTI_INVALID; + default: + qcformat = -qcformat; + if (qcformat < PTI_MAX) + return qcformat; + return PTI_INVALID; + } +} +int PR_UnTranslateTextureFormat(uploadfmt_t pixelformat) +{ + switch(pixelformat) + { + case PTI_RGBA8: return 1; + case PTI_RGBA16F: return 2; + case PTI_RGBA32F: return 3; + + case PTI_DEPTH16: return 4; + case PTI_DEPTH24: return 5; + case PTI_DEPTH32: return 6; + + case PTI_R8: return 7; + case PTI_R16F: return 8; + case PTI_R32F: return 9; + + case PTI_A2BGR10: return 10; + case PTI_RGB565: return 11; + case PTI_RGBA4444: return 12; + case PTI_RG8: return 13; + case PTI_RGB32F: return 14; + + default:return -pixelformat; } } void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index a87d09f2..bb7fbcd2 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -939,6 +939,7 @@ void QCBUILTIN PF_CL_readimage (pubprogfuncs_t *prinst, struct globalvars_s *pr_ G_INT(OFS_RETURN) = (char*)ptr - prinst->stringtable; G_INT(OFS_PARM1) = imagewidth; //out width G_INT(OFS_PARM2) = imageheight; //out height + G_INT(OFS_PARM3) = PR_UnTranslateTextureFormat(format); //out format... } BZ_Free(imagedata); } diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 31448395..9951ec15 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -584,6 +584,7 @@ const void *PR_GetReadQCPtr(pubprogfuncs_t *prinst, int qcptr, int qcsize); void *PR_GetWriteQCPtr(pubprogfuncs_t *prinst, int qcptr, int qcsize); uploadfmt_t PR_TranslateTextureFormat(int qcformat); +int PR_UnTranslateTextureFormat(uploadfmt_t fteformat); //FIXME pbool PR_RunWarning (pubprogfuncs_t *ppf, char *error, ...); diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 20e0c9c3..fb6539a8 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -39,7 +39,6 @@ cvar_t mod_warnmodels = CVARD("mod_warnmodels", "1", "Warn if any models fa cvar_t mod_litsprites_force = CVARD("mod_litsprites_force", "0", "If set to 1, sprites will be lit according to world lighting (including rtlights), like Tenebrae. Ideally use EF_ADDITIVE or EF_FULLBRIGHT to make emissive sprites instead."); cvar_t mod_loadmappackages = CVARD ("mod_loadmappackages", "1", "Load additional content embedded within bsp files."); cvar_t mod_lightscale_broken = CVARFD("mod_lightscale_broken", "0", CVAR_RENDERERLATCH, "When active, replicates a bug from vanilla - the radius of r_dynamic lights is scaled by per-surface texture scale rather than using actual distance."); -cvar_t temp_lit2support = CVARD("temp_mod_lit2support", "0", "Set to 1 to enable lit2 support. This cvar will be removed once the format is finalised."); cvar_t mod_lightpoint_distance = CVARD("mod_lightpoint_distance", "8192", "This is the maximum distance to trace when searching for a ground surface for lighting info on map formats without light more fancy lighting info. Use 2048 for full compat with Quake."); #ifdef SPRMODELS cvar_t r_sprite_backfacing = CVARD ("r_sprite_backfacing", "0", "Make oriented sprites face backwards relative to their orientation, for compat with q1."); @@ -663,7 +662,6 @@ void Mod_Init (qboolean initial) Cvar_Register(&mod_loadmappackages, NULL); Cvar_Register(&mod_lightscale_broken, NULL); Cvar_Register(&mod_lightpoint_distance, NULL); - Cvar_Register(&temp_lit2support, NULL); Cvar_Register (&r_meshpitch, "Gamecode"); Cvar_Register (&r_meshroll, "Gamecode"); #ifdef RTLIGHTS @@ -1706,13 +1704,12 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base, struct { char *pattern; - int type; } litnames[] = { - {"%s.lit2",2}, - {"%s.hdr",1}, - {"%s.lit",0}, - {"lits/%s.lit2",2}, - {"lits/%s.lit",0}, + {"%s.hdr"}, + {"%s.lit"}, +#ifdef HAVE_LEGACY + {"lits/%s.lit"}, +#endif }; char litbasep[MAX_QPATH]; char litbase[MAX_QPATH]; @@ -1728,8 +1725,6 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base, COM_FileBase(loadmodel->name, litbase, sizeof(litbase)); for (i = 0; i < countof(litnames); i++) { - if (!temp_lit2support.ival && litnames[i].type==2) - continue; if (strchr(litnames[i].pattern, '/')) Q_snprintfz(litname, sizeof(litname), litnames[i].pattern, litbase); else @@ -1788,12 +1783,7 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base, unsigned short *extents = (unsigned short*)(offsets+ql2->numsurfs); unsigned char *styles = (unsigned char*)(extents+ql2->numsurfs*2); unsigned char *shifts = (unsigned char*)(styles+ql2->numsurfs*4); - if (!temp_lit2support.ival) - { - litdata = NULL; - Con_Printf("lit2 support is disabled, pending format finalisation (%s).\n", litname); - } - else if (loadmodel->numsurfaces != ql2->numsurfs) + if (loadmodel->numsurfaces != ql2->numsurfs) { litdata = NULL; Con_Printf("lit \"%s\" doesn't match level. Ignored.\n", litname); @@ -1805,6 +1795,8 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base, } else { + Con_Printf("%s: lit2 support is unstandardised and may change in future.\n", litname); + inhibitvalidation = true; //surface code needs to know the overrides. diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 2f01090f..3808ae7a 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -11523,7 +11523,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"iscachedpic", PF_Fixme, 0, 0, 0, 316, D("float(string name)", "Checks to see if the image is currently loaded. Engines might lie, or cache between maps.")},// (EXT_CSQC) {"precache_pic", PF_Fixme, 0, 0, 0, 317, D("string(string name, optional float flags)", "Forces the engine to load the named image. Flags are a bitmask of the PRECACHE_PIC_* flags.")},// (EXT_CSQC) {"r_uploadimage", PF_Fixme, 0, 0, 0, 0, D("void(string imagename, int width, int height, void *pixeldata, optional int datasize, optional int format)", "Updates a texture with the specified rgba data (uploading it to the gpu). Will be created if needed. If datasize is specified then the image is decoded (eg .ktx or .dds data) instead of being raw R8G8B8A data. You'll typically want shaderforname to also generate a shader to use the texture.")}, - {"r_readimage", PF_Fixme, 0, 0, 0, 0, D("int*(string filename, __out int width, __out int height)", "Reads and decodes an image from disk, providing raw R8G8B8A8 pixel data. Should not be used for dds or ktx etc formats. Returns __NULL__ if the image could not be read for any reason. Use memfree to free the data once you're done with it.")}, + {"r_readimage", PF_Fixme, 0, 0, 0, 0, D("int*(string filename, __out int width, __out int height, __out int format)", "Reads and decodes an image from disk, providing raw R8G8B8A8 pixel data. Should not be used for dds or ktx etc formats. Returns __NULL__ if the image could not be read for any reason. Use memfree to free the data once you're done with it.")}, {"drawgetimagesize",PF_Fixme, 0, 0, 0, 318, D("#define draw_getimagesize drawgetimagesize\nvector(string picname)", "Returns the dimensions of the named image. Images specified with .lmp should give the original .lmp's dimensions even if texture replacements use a different resolution. WARNING: this function may be slow if used without or directly after its initial precache_pic.")},// (EXT_CSQC) {"freepic", PF_Fixme, 0, 0, 0, 319, D("void(string name)", "Tells the engine that the image is no longer needed. The image will appear to be new the next time its needed.")},// (EXT_CSQC) {"spriteframe", PF_Fixme, 0, 0, 0, 0, D("string(string modelname, int frame, float frametime)", "Obtains a suitable shader name to draw a sprite's shader via drawpic/R_BeginPolygon/etc, instead of needing to create a scene.")}, diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 03a3f26e..d87ac91a 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -4129,7 +4129,7 @@ qboolean SV_ConnectionlessPacket (void) } } else if (!strcmp(c,"dtlsconnect")) - { + { //NOTE: redundant. if the server has dtls enabled then it'll respond to dtls hellos with its own stateless cookies #ifdef HAVE_DTLS if (net_from.prot == NP_DGRAM && (net_enable_dtls.ival /*|| !*net_enable_dtls.ival*/)) {