]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
Merge MR 'Fix inability to access non-ascii path under Windows with WTF-8'
authorbones_was_here <bones_was_here@xonotic.au>
Fri, 21 Jul 2023 08:38:12 +0000 (08:38 +0000)
committerbones_was_here <bones_was_here@xonotic.au>
Fri, 21 Jul 2023 08:38:12 +0000 (08:38 +0000)
See https://gitlab.com/xonotic/darkplaces/-/merge_requests/142

Signed-off-by: bones_was_here <bones_was_here@xonotic.au>
19 files changed:
cl_main.c
clvm_cmds.c
cmd.h
collision.h
cvar.c
dpdefs/dpextensions.qc
fs.c
host.c
makefile.inc
model_brush.c
phys.c [new file with mode: 0644]
phys.h [new file with mode: 0644]
prvm_cmds.c
prvm_cmds.h
quakedef.h
server.h
sv_main.c
sv_phys.c
svvm_cmds.c

index c114156382440d2141c3ff6aaf4fa59442317802..fe1840aff42db97cb43db2ec931f381da739312b 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -108,6 +108,8 @@ cvar_t cl_maxfps_alwayssleep = {CF_CLIENT | CF_ARCHIVE, "cl_maxfps_alwayssleep",
 cvar_t cl_maxidlefps = {CF_CLIENT | CF_ARCHIVE, "cl_maxidlefps", "20", "maximum fps cap when the game is not the active window (makes cpu time available to other programs"};
 
 cvar_t cl_areagrid_link_SOLID_NOT = {CF_CLIENT, "cl_areagrid_link_SOLID_NOT", "1", "set to 0 to prevent SOLID_NOT entities from being linked to the area grid, and unlink any that are already linked (in the code paths that would otherwise link them), for better performance"};
+cvar_t cl_gameplayfix_nudgeoutofsolid_separation = {CF_CLIENT, "cl_gameplayfix_nudgeoutofsolid_separation", "0.03125", "keep objects this distance apart to prevent collision issues on seams"};
+
 
 client_static_t        cls;
 client_state_t cl;
@@ -3137,6 +3139,7 @@ void CL_Init (void)
                Cvar_RegisterVariable (&cl_maxidlefps);
 
                Cvar_RegisterVariable (&cl_areagrid_link_SOLID_NOT);
+               Cvar_RegisterVariable (&cl_gameplayfix_nudgeoutofsolid_separation);
 
                CL_Parse_Init();
                CL_Particles_Init();
index 587a31bb7db6ae2f25eef22d962ffc0f792478a4..05bb57a934d3f3cb743470fefbf7b6432771fd7c 100644 (file)
@@ -5545,7 +5545,7 @@ NULL,                                                     // #563
 NULL,                                                  // #564
 NULL,                                                  // #565
 VM_CL_findbox,                                 // #566 entity(vector mins, vector maxs) findbox = #566; (DP_QC_FINDBOX)
-NULL,                                                  // #567
+VM_nudgeoutofsolid,                            // #567 float(entity ent) nudgeoutofsolid = #567; (DP_QC_NUDGEOUTOFSOLID)
 NULL,                                                  // #568
 NULL,                                                  // #569
 NULL,                                                  // #570
diff --git a/cmd.h b/cmd.h
index bee0a1f36b520b0695e863e0cdeda6de942a3e3d..fddd2a08d88b25883264e9c9d6388401fcc59fd0 100644 (file)
--- a/cmd.h
+++ b/cmd.h
@@ -59,8 +59,9 @@ struct cmd_state_s;
 #define CF_PRIVATE              (1<<11) // cvar should not be $ expanded or sent to the server under any circumstances (rcon_password, etc)
 #define CF_MAXFLAGSVAL          ((1<<12) - 1)    // used to determine if flags is valid
 // for internal use only!
+#define CF_REGISTERED (1<<29)  // created by Cvar_RegisterVariable()
 #define CF_DEFAULTSET (1<<30)
-#define CF_ALLOCATED (1<<31)
+#define CF_ALLOCATED (1<<31)   // created by Cvar_Get() (console or QC)
 
 #define CF_SHARED 3
 
index f62356b02ca85eb6e1ae4381fd043bfa422e116e..71bc57f0caa81e8c99611804fbb2a7f5c5786ae1 100644 (file)
@@ -21,19 +21,19 @@ struct texture_s;
 typedef struct trace_s
 {
        // if true, the entire trace was in solid (see hitsupercontentsmask)
-       int allsolid;
+       qbool allsolid;
        // if true, the initial point was in solid (see hitsupercontentsmask)
-       int startsolid;
+       qbool startsolid;
        // this is set to true in world.c if startsolid was set in a trace against world
-       int worldstartsolid;
+       qbool worldstartsolid;
        // this is set to true in world.c if startsolid was set in a trace against a SOLID_BSP entity, in other words this is true if the entity is stuck in a door or wall, but not if stuck in another normal entity
-       int bmodelstartsolid;
+       qbool bmodelstartsolid;
        // if true, the trace passed through empty somewhere
        // (set only by Q1BSP tracing)
-       int inopen;
+       qbool inopen;
        // if true, the trace passed through water/slime/lava somewhere
        // (set only by Q1BSP tracing)
-       int inwater;
+       qbool inwater;
        // fraction of the total distance that was traveled before impact
        // in case of impact this is actually nudged a bit off the surface
        // (1.0 = did not hit anything)
@@ -62,7 +62,7 @@ typedef struct trace_s
        const struct texture_s *hittexture;
        // initially false, set when the start leaf is found
        // (set only by Q1BSP tracing and entity box tracing)
-       int startfound;
+       qbool startfound;
        // if startsolid, contains the minimum penetration depth found in the
        // trace, and the normal needed to push it out of that solid
        double startdepth;
diff --git a/cvar.c b/cvar.c
index 7936c92356be359c13748eca7afbec3250df8ac2..98f11e399ba6d924f9487dadf96b266d0e470d27 100644 (file)
--- a/cvar.c
+++ b/cvar.c
@@ -437,6 +437,12 @@ void Cvar_SetQuick (cvar_t *var, const char *value)
                return;
        }
 
+       if (!(var->flags & CF_REGISTERED) && !(var->flags & CF_ALLOCATED))
+       {
+               Con_Printf(CON_WARN "Warning: Cvar_SetQuick() cannot set unregistered cvar \"%s\"\n", var->name);
+               return; // setting an unregistered engine cvar crashes
+       }
+
        if (developer_extra.integer)
                Con_DPrintf("Cvar_SetQuick({\"%s\", \"%s\", %i, \"%s\"}, \"%s\");\n", var->name, var->string, var->flags, var->defstring, value);
 
@@ -498,22 +504,25 @@ void Cvar_RegisterVirtual(cvar_t *variable, const char *name )
        cvar_hash_t *hash;
        int hashindex;
 
+       if (cls.state == ca_dedicated && !(variable->flags & CF_SERVER))
+               return;
+
        if(!*name)
        {
-               Con_Printf("Cvar_RegisterVirtual: invalid virtual cvar name\n");
+               Con_Printf(CON_WARN "Cvar_RegisterVirtual: invalid virtual cvar name\n");
                return;
        }
 
        // check for overlap with a command
        if (Cmd_Exists(cmd_local, name))
        {
-               Con_Printf("Cvar_RegisterVirtual: %s is a command\n", name);
+               Con_Printf(CON_WARN "Cvar_RegisterVirtual: %s is a command\n", name);
                return;
        }
 
        if(Cvar_FindVar(&cvars_all, name, 0))
        {
-               Con_Printf("Cvar_RegisterVirtual: %s is a cvar\n", name);
+               Con_Printf(CON_WARN "Cvar_RegisterVirtual: %s is a cvar\n", name);
                return;
        }
 
@@ -579,7 +588,9 @@ void Cvar_RegisterVariable (cvar_t *variable)
 
        switch (variable->flags & (CF_CLIENT | CF_SERVER))
        {
-       case CF_CLIENT:
+       case CF_CLIENT: // client-only cvar
+               if (cls.state == ca_dedicated)
+                       return;
        case CF_SERVER:
        case CF_CLIENT | CF_SERVER:
                cvars = &cvars_all;
@@ -607,7 +618,7 @@ void Cvar_RegisterVariable (cvar_t *variable)
                        // (because the engine directly accesses fixed variables)
                        // NOTE: this isn't actually used currently
                        // (all cvars are registered before config parsing)
-                       variable->flags |= (cvar->flags & ~CF_ALLOCATED);
+                       variable->flags &= ~CF_ALLOCATED;
                        // cvar->string is now owned by variable instead
                        variable->string = cvar->string;
                        variable->defstring = cvar->defstring;
@@ -662,6 +673,9 @@ void Cvar_RegisterVariable (cvar_t *variable)
        for (i = 0;i < PRVM_PROG_MAX;i++)
                variable->globaldefindex[i] = -1;
 
+       // Safe for Cvar_SetQuick()
+       variable->flags |= CF_REGISTERED;
+
        Cvar_Link(variable, cvars);
 }
 
index 558a288e49dd1f9a9158fe497f41679a25120a91..73996cbf4eda687fcd986157a1e9a19a2cb277e6 100644 (file)
@@ -2644,7 +2644,6 @@ void(string cmdname) registercommand = #352;
 //description:
 //Adds a new console command which will take priority over a previous command of the same name (including engine commands) and in CSQC is removed when the VM shuts down. This will call CSQC_ConsoleCommand(string command) or ConsoleCmd(string command) in SVQC.  Return value should be true if QC handled the command, otherwise return false to have the engine handle it.
 
-
 //DP_QC_FINDBOX
 //idea: Mario
 //darkplaces implementation: bones_was_here
@@ -2654,4 +2653,16 @@ entity(vector mins, vector maxs, .entity tofield) findbox_tofield = #566;
 //description:
 //Returns a chain of entities that are touching a box (a simpler findradius); supports DP_QC_FINDCHAIN_TOFIELD
 
+//DP_QC_NUDGEOUTOFSOLID
+//idea: LadyHavoc, bones_was_here
+//darkplaces implementation: LadyHavoc, bones_was_here
+//builtin definitions:
+float(entity ent) nudgeoutofsolid = #567;
+//cvar definitions:
+//sv_gameplayfix_nudgeoutofsolid_separation
+//description:
+//Attempts to move a stuck entity out of solid brushes, returning 1 if successful, 0 if it remains stuck, -1 if it wasn't stuck.
+//Note: makes only one tracebox call if the entity isn't stuck, so don't call tracebox just to see if you should call nudgeoutofsolid.
+
+
 float(float dividend, float divisor) mod = #245;
diff --git a/fs.c b/fs.c
index 90b7e7c664d2a76dcad65ade63cd5dd42456e4a5..e7a001bff6ae84072dc98771493869537966b58f 100644 (file)
--- a/fs.c
+++ b/fs.c
@@ -1532,13 +1532,16 @@ void FS_Rescan (void)
        // add back the selfpack as new first item
        FS_AddSelfPack();
 
-       // set the default screenshot name to either the mod name or the
-       // gamemode screenshot name
-       if (strcmp(com_modname, gamedirname1))
-               Cvar_SetQuick (&scr_screenshot_name, com_modname);
-       else
-               Cvar_SetQuick (&scr_screenshot_name, gamescreenshotname);
-       
+       if (cls.state != ca_dedicated)
+       {
+               // set the default screenshot name to either the mod name or the
+               // gamemode screenshot name
+               if (strcmp(com_modname, gamedirname1))
+                       Cvar_SetQuick (&scr_screenshot_name, com_modname);
+               else
+                       Cvar_SetQuick (&scr_screenshot_name, gamescreenshotname);
+       }
+
        if((i = Sys_CheckParm("-modname")) && i < sys.argc - 1)
                strlcpy(com_modname, sys.argv[i+1], sizeof(com_modname));
 
diff --git a/host.c b/host.c
index e34f712bebb2e148456af2f1e7afe2a71adb7739..43bfb2ff9cdf39ebbf5fe350abc7c74497667d50 100644 (file)
--- a/host.c
+++ b/host.c
@@ -424,6 +424,10 @@ static void Host_Init (void)
        if (Sys_CheckParm("-nostdout"))
                sys_nostdout = 1;
 
+       // -dedicated is checked in SV_ServerOptions() but that's too late for Cvar_RegisterVariable() to skip all the client-only cvars
+       if (Sys_CheckParm ("-dedicated") || !cl_available)
+               cls.state = ca_dedicated;
+
        // initialize console command/cvar/alias/command execution systems
        Cmd_Init();
 
@@ -497,12 +501,15 @@ static void Host_Init (void)
 
        Log_Start();
 
-       // put up the loading image so the user doesn't stare at a black screen...
-       SCR_BeginLoadingPlaque(true);
-#ifdef CONFIG_MENU
        if (cls.state != ca_dedicated)
+       {
+               // put up the loading image so the user doesn't stare at a black screen...
+               SCR_BeginLoadingPlaque(true);
+#ifdef CONFIG_MENU
                MR_Init();
 #endif
+       }
+
        // check for special benchmark mode
 // COMMANDLINEOPTION: Client: -benchmark <demoname> runs a timedemo and quits, results of any timedemo can be found in gamedir/benchmark.log (for example id1/benchmark.log)
        i = Sys_CheckParm("-benchmark");
index 87b114ce50b58163acd101c018070cc25895c6fa..90e2bf86aaca8a5e9853a262f3a182c0b45a2a69 100644 (file)
@@ -116,6 +116,7 @@ OBJ_COMMON= \
        model_sprite.o \
        netconn.o \
        palette.o \
+       phys.o \
        polygon.o \
        portals.o \
        protocol.o \
index 4fbf53b5583fbc08fe043affefeb9bb2bd4c738e..bfed557107e7088e547dde9b614e80309d4f9c61 100644 (file)
@@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 
 //cvar_t r_subdivide_size = {CF_CLIENT | CF_ARCHIVE, "r_subdivide_size", "128", "how large water polygons should be (smaller values produce more polygons which give better warping effects)"};
-cvar_t mod_bsp_portalize = {CF_CLIENT | CF_SERVER, "mod_bsp_portalize", "1", "enables portal generation from BSP tree (may take several seconds per map), used by r_drawportals, r_useportalculling, r_shadow_realtime_world_compileportalculling, sv_cullentities_portal"};
+cvar_t mod_bsp_portalize = {CF_CLIENT, "mod_bsp_portalize", "1", "enables portal generation from BSP tree (may take several seconds per map), used by r_drawportals, r_useportalculling, r_shadow_realtime_dlight_portalculling, r_shadow_realtime_world_compileportalculling"};
 cvar_t r_novis = {CF_CLIENT, "r_novis", "0", "draws whole level, see also sv_cullentities_pvs 0"};
 cvar_t r_nosurftextures = {CF_CLIENT, "r_nosurftextures", "0", "pretends there was no texture lump found in the q1bsp/hlbsp loading (useful for debugging this rare case)"};
 cvar_t r_subdivisions_tolerance = {CF_CLIENT, "r_subdivisions_tolerance", "4", "maximum error tolerance on curve subdivision for rendering purposes (in other words, the curves will be given as many polygons as necessary to represent curves at this quality)"};
@@ -762,7 +762,7 @@ static int Mod_Q1BSP_RecursiveHullCheck(RecursiveHullCheckTraceInfo_t *t, int nu
                        // recurse both sides, front side first
                        ret = Mod_Q1BSP_RecursiveHullCheck(t, node->children[p1side], p1f, midf, p1, mid);
                        // if this side is not empty, return what it is (solid or done)
-                       if (ret != HULLCHECKSTATE_EMPTY)
+                       if (ret != HULLCHECKSTATE_EMPTY && !t->trace->allsolid)
                                return ret;
 
                        ret = Mod_Q1BSP_RecursiveHullCheck(t, node->children[p2side], midf, p2f, mid, p2);
diff --git a/phys.c b/phys.c
new file mode 100644 (file)
index 0000000..7128ea3
--- /dev/null
+++ b/phys.c
@@ -0,0 +1,71 @@
+// for physics functions shared by the client and server
+
+#include "phys.h"
+
+#include "quakedef.h"
+#include "cl_collision.h"
+
+
+int PHYS_NudgeOutOfSolid(prvm_prog_t *prog, prvm_edict_t *ent)
+{
+       int bump, pass;
+       trace_t stucktrace;
+       vec3_t stuckorigin;
+       vec3_t stuckmins, stuckmaxs;
+       vec_t separation;
+       model_t *worldmodel;
+
+       if (prog == SVVM_prog)
+       {
+               worldmodel = sv.worldmodel;
+               separation = sv_gameplayfix_nudgeoutofsolid_separation.value;
+       }
+       else if (prog == CLVM_prog)
+       {
+               worldmodel = cl.worldmodel;
+               separation = cl_gameplayfix_nudgeoutofsolid_separation.value;
+       }
+       else
+               Sys_Error("PHYS_NudgeOutOfSolid: cannot be called from %s VM\n", prog->name);
+
+       VectorCopy(PRVM_serveredictvector(ent, mins), stuckmins);
+       VectorCopy(PRVM_serveredictvector(ent, maxs), stuckmaxs);
+       if (worldmodel && worldmodel->brushq1.numclipnodes)
+               separation = 0.0f; // when using hulls, it can not be enlarged
+       else
+       {
+               stuckmins[0] -= separation;
+               stuckmins[1] -= separation;
+               stuckmins[2] -= separation;
+               stuckmaxs[0] += separation;
+               stuckmaxs[1] += separation;
+               stuckmaxs[2] += separation;
+       }
+
+       // first pass we try to get it out of brush entities
+       // second pass we try to get it out of world only (can't win them all)
+       for (pass = 0;pass < 2;pass++)
+       {
+               VectorCopy(PRVM_serveredictvector(ent, origin), stuckorigin);
+               for (bump = 0;bump < 10;bump++)
+               {
+                       if (prog == SVVM_prog) // TODO: can we refactor to use a shared TraceBox or at least a func ptr for these cases?
+                               stucktrace = SV_TraceBox(stuckorigin, stuckmins, stuckmaxs, stuckorigin, pass ? MOVE_WORLDONLY : MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
+                       else
+                               stucktrace = CL_TraceBox(stuckorigin, stuckmins, stuckmaxs, stuckorigin, pass ? MOVE_WORLDONLY : MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, pass ? false : true, false, NULL, false);
+
+                       // Separation compared here to ensure a good location will be recognised reliably.
+                       if (-stucktrace.startdepth <= separation
+                       || (!stucktrace.bmodelstartsolid && !stucktrace.worldstartsolid)
+                       || (pass && !stucktrace.worldstartsolid))
+                       {
+                               // found a good location, use it
+                               VectorCopy(stuckorigin, PRVM_serveredictvector(ent, origin));
+                               return bump || pass ? 1 : -1; // -1 means it wasn't stuck
+                       }
+
+                       VectorMA(stuckorigin, -stucktrace.startdepth, stucktrace.startdepthnormal, stuckorigin);
+               }
+       }
+       return 0;
+}
diff --git a/phys.h b/phys.h
new file mode 100644 (file)
index 0000000..d18cfb9
--- /dev/null
+++ b/phys.h
@@ -0,0 +1,14 @@
+#ifndef PHYS_H
+#define PHYS_H
+
+#include "quakedef.h"
+
+
+/*! move an entity that is stuck out of the surface it is stuck in (can move large amounts)
+ * returns 1 if it found a better place, 0 if it remains stuck, -1 if it wasn't stuck.
+ */
+int PHYS_NudgeOutOfSolid(prvm_prog_t *prog, prvm_edict_t *ent);
+extern cvar_t cl_gameplayfix_nudgeoutofsolid_separation;
+
+
+#endif // PHYS_H guard
index d362aa72aa7bb19aaa209de70e7eca25af4c3331..fc39fa33067c6ea2440d4f982835f2969dfcd062 100644 (file)
@@ -32,7 +32,7 @@ void VM_Warning(prvm_prog_t *prog, const char *fmt, ...)
        dpvsnprintf(msg,sizeof(msg),fmt,argptr);
        va_end(argptr);
 
-       Con_Printf(CON_WARN "%s", msg);
+       Con_Printf(CON_WARN "%s VM warning: %s", prog->name, msg);
 
        // TODO: either add a cvar/cmd to control the state dumping or replace some of the calls with Con_Printf [9/13/2006 Black]
        if(prvm_backtraceforwarnings.integer && recursive != host.realtime) // NOTE: this compares to the time, just in case if PRVM_PrintState causes a Host_Error and keeps recursive set
@@ -5563,6 +5563,41 @@ void VM_SV_getextresponse (prvm_prog_t *prog)
        }
 }
 
+// DP_QC_NUDGEOUTOFSOLID
+// float(entity ent) nudgeoutofsolid = #567;
+void VM_nudgeoutofsolid(prvm_prog_t *prog)
+{
+       prvm_edict_t *ent;
+
+       VM_SAFEPARMCOUNTRANGE(1, 1, VM_nudgeoutofsolid);
+
+       ent = PRVM_G_EDICT(OFS_PARM0);
+       if (ent == prog->edicts)
+       {
+               VM_Warning(prog, "nudgeoutofsolid: can not modify world entity\n");
+               PRVM_G_FLOAT(OFS_RETURN) = 0;
+               return;
+       }
+       if (ent->free)
+       {
+               VM_Warning(prog, "nudgeoutofsolid: can not modify free entity\n");
+               PRVM_G_FLOAT(OFS_RETURN) = 0;
+               return;
+       }
+
+       PRVM_G_FLOAT(OFS_RETURN) = PHYS_NudgeOutOfSolid(prog, ent);
+
+       if (PRVM_G_FLOAT(OFS_RETURN) > 0)
+       {
+               if (prog == SVVM_prog)
+                       SV_LinkEdict(ent);
+               else if (prog == CLVM_prog)
+                       CL_LinkEdict(ent);
+               else
+                       Sys_Error("PHYS_NudgeOutOfSolid: cannot be called from %s VM\n", prog->name);
+       }
+}
+
 /*
 =========
 Common functions between menu.dat and clsprogs
index a5555cde87db8ca68f0fb71380fcc4ada18f1842..81556d5cf9fe9bfa30293d7372c540b103afb3f0 100644 (file)
@@ -484,6 +484,7 @@ void VM_getsurfacetriangle(prvm_prog_t *prog);
 void VM_physics_enable(prvm_prog_t *prog);
 void VM_physics_addforce(prvm_prog_t *prog);
 void VM_physics_addtorque(prvm_prog_t *prog);
+void VM_nudgeoutofsolid(prvm_prog_t *prog);
 
 void VM_coverage(prvm_prog_t *prog);
 
index ec5c72b6efb29fbb305e5d0f0ed17bb542fd3a24..f423d5985aab35137cab98ed205e47f8c9f43a13 100644 (file)
@@ -140,6 +140,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "progs.h"
 #include "progsvm.h"
 #include "server.h"
+#include "phys.h"
 
 #include "input.h"
 #include "keys.h"
index 635eb72b29124dc199cfc0b51056ef5c7ebe8db4..5dfe2ac04aff7715a0f1ad747c1233af0f1d2b51 100644 (file)
--- a/server.h
+++ b/server.h
@@ -568,10 +568,6 @@ void SV_LinkEdict_TouchAreaGrid_Call(prvm_edict_t *touch, prvm_edict_t *ent); //
  * returns true if it found a better place
  */
 qbool SV_UnstickEntity (prvm_edict_t *ent);
-/*! move an entity that is stuck out of the surface it is stuck in (can move large amounts)
- * returns true if it found a better place
- */
-qbool SV_NudgeOutOfSolid(prvm_edict_t *ent);
 
 /// calculates hitsupercontentsmask for a generic qc entity
 int SV_GenericHitSuperContentsMask(const prvm_edict_t *edict);
index 16fd612b9af1fa942b8bec6658ed556ce8daaba7..ac35d949bd16b0b6323bfb13c8d8c0ee34437e5b 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -452,7 +452,6 @@ static void SV_ServerOptions (void)
        i = Sys_CheckParm ("-dedicated");
        if (i || !cl_available)
        {
-               cls.state = ca_dedicated;
                // check for -dedicated specifying how many players
                if (i && i + 1 < sys.argc && atoi (sys.argv[i+1]) >= 1)
                        svs.maxclients = atoi (sys.argv[i+1]);
@@ -2604,7 +2603,8 @@ double SV_Frame(double time)
                {
                        advancetime = sys_ticrate.value;
                        // listen servers can run multiple server frames per client frame
-                       framelimit = cl_maxphysicsframesperserverframe.integer;
+                       if (cl_maxphysicsframesperserverframe.integer > 0)
+                               framelimit = cl_maxphysicsframesperserverframe.integer;
                        aborttime = Sys_DirtyTime() + 0.1;
                }
 
index 96139467879a79e2dc211e0ced41e83ea08614f3..35bc3410cc7c7382710358a62afefad8606608a1 100644 (file)
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -1543,46 +1543,6 @@ static qbool SV_NudgeOutOfSolid_PivotIsKnownGood(prvm_edict_t *ent, vec3_t pivot
        return true;
 }
 
-qbool SV_NudgeOutOfSolid(prvm_edict_t *ent)
-{
-       prvm_prog_t *prog = SVVM_prog;
-       int bump, pass;
-       trace_t stucktrace;
-       vec3_t stuckorigin;
-       vec3_t stuckmins, stuckmaxs;
-       vec_t nudge;
-       vec_t separation = sv_gameplayfix_nudgeoutofsolid_separation.value;
-       if (sv.worldmodel && sv.worldmodel->brushq1.numclipnodes)
-               separation = 0.0f; // when using hulls, it can not be enlarged
-       VectorCopy(PRVM_serveredictvector(ent, mins), stuckmins);
-       VectorCopy(PRVM_serveredictvector(ent, maxs), stuckmaxs);
-       stuckmins[0] -= separation;
-       stuckmins[1] -= separation;
-       stuckmins[2] -= separation;
-       stuckmaxs[0] += separation;
-       stuckmaxs[1] += separation;
-       stuckmaxs[2] += separation;
-       // first pass we try to get it out of brush entities
-       // second pass we try to get it out of world only (can't win them all)
-       for (pass = 0;pass < 2;pass++)
-       {
-               VectorCopy(PRVM_serveredictvector(ent, origin), stuckorigin);
-               for (bump = 0;bump < 10;bump++)
-               {
-                       stucktrace = SV_TraceBox(stuckorigin, stuckmins, stuckmaxs, stuckorigin, pass ? MOVE_WORLDONLY : MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
-                       if (!stucktrace.bmodelstartsolid || stucktrace.startdepth >= 0)
-                       {
-                               // found a good location, use it
-                               VectorCopy(stuckorigin, PRVM_serveredictvector(ent, origin));
-                               return true;
-                       }
-                       nudge = -stucktrace.startdepth;
-                       VectorMA(stuckorigin, nudge, stucktrace.startdepthnormal, stuckorigin);
-               }
-       }
-       return false;
-}
-
 /*
 ============
 SV_PushEntity
@@ -1610,7 +1570,7 @@ static qbool SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qboo
        // move start position out of solids
        if (sv_gameplayfix_nudgeoutofsolid.integer && sv_gameplayfix_nudgeoutofsolid_separation.value >= 0)
        {
-               SV_NudgeOutOfSolid(ent);
+               PHYS_NudgeOutOfSolid(prog, ent);
        }
 
        VectorCopy(PRVM_serveredictvector(ent, origin), start);
index c04cd97fbe93be3561e6cd3d258a9490a887ee7f..3692bc2f42c588d099bdca2fdc12f3788fe50120 100644 (file)
@@ -100,6 +100,7 @@ const char *vm_sv_extensions[] = {
 "DP_QC_ENTITYSTRING",
 "DP_QC_ETOS",
 "DP_QC_EXTRESPONSEPACKET",
+"DP_QC_FINDBOX",
 "DP_QC_FINDCHAIN",
 "DP_QC_FINDCHAINFLAGS",
 "DP_QC_FINDCHAINFLOAT",
@@ -107,6 +108,7 @@ const char *vm_sv_extensions[] = {
 "DP_QC_FINDFLAGS",
 "DP_QC_FINDFLOAT",
 "DP_QC_FS_SEARCH",
+"DP_QC_FS_SEARCH_PACKFILE",
 "DP_QC_GETLIGHT",
 "DP_QC_GETSURFACE",
 "DP_QC_GETSURFACETRIANGLE",
@@ -119,6 +121,7 @@ const char *vm_sv_extensions[] = {
 "DP_QC_LOG",
 "DP_QC_MINMAXBOUND",
 "DP_QC_MULTIPLETEMPSTRINGS",
+"DP_QC_NUDGEOUTOFSOLID",
 "DP_QC_NUM_FOR_EDICT",
 "DP_QC_RANDOMVEC",
 "DP_QC_SINCOSSQRTPOW",
@@ -228,8 +231,6 @@ const char *vm_sv_extensions[] = {
 "TW_SV_STEPCONTROL",
 "ZQ_PAUSE",
 "DP_RM_CLIPGROUP",
-"DP_QC_FS_SEARCH_PACKFILE",
-"DP_QC_FINDBOX",
 NULL
 //"EXT_CSQC" // not ready yet
 };
@@ -1178,12 +1179,18 @@ VM_SV_droptofloor
 void() droptofloor
 ===============
 */
-
+inline static qbool droptofloor_bsp_failcond(trace_t *trace)
+{
+       if (sv.worldmodel->brush.isq3bsp || sv.worldmodel->brush.isq2bsp)
+               return trace->startsolid;
+       else
+               return trace->allsolid || trace->fraction == 1;
+}
 static void VM_SV_droptofloor(prvm_prog_t *prog)
 {
-       prvm_edict_t            *ent;
-       vec3_t          end, entorigin, entmins, entmaxs;
-       trace_t         trace;
+       prvm_edict_t *ent;
+       vec3_t        end;
+       trace_t       trace;
 
        VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
 
@@ -1202,6 +1209,15 @@ static void VM_SV_droptofloor(prvm_prog_t *prog)
                return;
        }
 
+       if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
+       {
+               int n = PHYS_NudgeOutOfSolid(prog, ent);
+               if (!n)
+                       VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid_nudgetocorrect COULD NOT FIX badly placed entity \"%s\" before drop\n", PRVM_gameedictvector(ent, origin)[0], PRVM_gameedictvector(ent, origin)[1], PRVM_gameedictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname)));
+               else if (n > 0)
+                       VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid_nudgetocorrect FIXED badly placed entity \"%s\" before drop\n", PRVM_gameedictvector(ent, origin)[0], PRVM_gameedictvector(ent, origin)[1], PRVM_gameedictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname)));
+       }
+
        VectorCopy (PRVM_serveredictvector(ent, origin), end);
        if (sv.worldmodel->brush.isq3bsp)
                end[2] -= 4096;
@@ -1210,55 +1226,54 @@ static void VM_SV_droptofloor(prvm_prog_t *prog)
        else
                end[2] -= 256; // Quake, QuakeWorld
 
-       if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
-               SV_NudgeOutOfSolid(ent);
-
-       VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
-       VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
-       VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
-       trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
-       if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
-       {
-               vec3_t offset, org;
-               VectorSet(offset, 0.5f * (PRVM_serveredictvector(ent, mins)[0] + PRVM_serveredictvector(ent, maxs)[0]), 0.5f * (PRVM_serveredictvector(ent, mins)[1] + PRVM_serveredictvector(ent, maxs)[1]), PRVM_serveredictvector(ent, mins)[2]);
-               VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
-               trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
-               VectorSubtract(trace.endpos, offset, trace.endpos);
-               if (trace.startsolid)
+       /* bones_was_here: not using SV_GenericHitSuperContentsMask(ent) anymore because it was setting:
+        * items:    SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY
+        * monsters: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP
+        * explobox: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE
+        * which caused (startsolid == true) when, for example, a health was touching a monster.
+        * Changing MOVE_NORMAL also fixes that, but other engines are using MOVE_NORMAL here.
+        */
+       trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value);
+       if (droptofloor_bsp_failcond(&trace))
+       {
+               if (sv_gameplayfix_droptofloorstartsolid.integer)
                {
-                       Con_DPrintf("droptofloor at %f %f %f - COULD NOT FIX BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
-                       SV_LinkEdict(ent);
-                       PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
-                       PRVM_serveredictedict(ent, groundentity) = 0;
-                       PRVM_G_FLOAT(OFS_RETURN) = 1;
-               }
-               else if (trace.fraction < 1)
-               {
-                       Con_DPrintf("droptofloor at %f %f %f - FIXED BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
-                       VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
+                       vec3_t offset, org;
+
+                       offset[0] = 0.5f * (PRVM_serveredictvector(ent, mins)[0] + PRVM_serveredictvector(ent, maxs)[0]);
+                       offset[1] = 0.5f * (PRVM_serveredictvector(ent, mins)[1] + PRVM_serveredictvector(ent, maxs)[1]);
+                       offset[2] = PRVM_serveredictvector(ent, mins)[2];
+                       VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
+                       VectorAdd(end, offset, end);
+
+                       trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value);
+                       if (droptofloor_bsp_failcond(&trace))
+                       {
+                               VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid COULD NOT FIX badly placed entity \"%s\"\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname)));
+                               return;
+                       }
+                       VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid FIXED badly placed entity \"%s\"\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname)));
+                       VectorSubtract(trace.endpos, offset, PRVM_serveredictvector(ent, origin));
+
+                       // only because we dropped it without considering its bbox
                        if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
-                               SV_NudgeOutOfSolid(ent);
-                       SV_LinkEdict(ent);
-                       PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
-                       PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
-                       PRVM_G_FLOAT(OFS_RETURN) = 1;
-                       // if support is destroyed, keep suspended (gross hack for floating items in various maps)
-                       ent->priv.server->suspendedinairflag = true;
+                               PHYS_NudgeOutOfSolid(prog, ent);
                }
-       }
-       else
-       {
-               if (!trace.allsolid && trace.fraction < 1)
+               else
                {
-                       VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
-                       SV_LinkEdict(ent);
-                       PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
-                       PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
-                       PRVM_G_FLOAT(OFS_RETURN) = 1;
-                       // if support is destroyed, keep suspended (gross hack for floating items in various maps)
-                       ent->priv.server->suspendedinairflag = true;
+                       VM_Warning(prog, "droptofloor at \"%f %f %f\": badly placed entity \"%s\", startsolid: %d allsolid: %d\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname)), trace.startsolid, trace.allsolid);
+                       return;
                }
        }
+       else
+               VectorCopy(trace.endpos, PRVM_serveredictvector(ent, origin));
+
+       SV_LinkEdict(ent);
+       PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
+       PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
+       PRVM_G_FLOAT(OFS_RETURN) = 1;
+       // if support is destroyed, keep suspended (gross hack for floating items in various maps)
+       ent->priv.server->suspendedinairflag = true;
 }
 
 /*
@@ -3819,7 +3834,7 @@ NULL,                                                     // #563
 NULL,                                                  // #564
 NULL,                                                  // #565
 VM_SV_findbox,                                 // #566 entity(vector mins, vector maxs) findbox = #566; (DP_QC_FINDBOX)
-NULL,                                                  // #567
+VM_nudgeoutofsolid,                            // #567 float(entity ent) nudgeoutofsolid = #567; (DP_QC_NUDGEOUTOFSOLID)
 NULL,                                                  // #568
 NULL,                                                  // #569
 NULL,                                                  // #570