diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index b413405e2..c30c3e771 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -5639,14 +5639,15 @@ void CSQC_Shutdown(void) CSQC_ForgetThreads(); PR_ReleaseFonts(kdm_game); PR_Common_Shutdown(csqcprogs, false); + World_Destroy(&csqc_world); csqcprogs->CloseProgs(csqcprogs); + csqc_world.progs = csqcprogs = NULL; } - csqc_world.progs = csqcprogs = NULL; + else + World_Destroy(&csqc_world); Cmd_RemoveCommands(CS_ConsoleCommand_f); - if (csqc_world.rbe) - csqc_world.rbe->End(&csqc_world); Z_Free(csqcdelta_pack_new.e); memset(&csqcdelta_pack_new, 0, sizeof(csqcdelta_pack_new)); diff --git a/engine/common/fs.c b/engine/common/fs.c index 0216f08c7..7db0fd0fb 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -89,7 +89,7 @@ void FS_UnRegisterFileSystemModule(void *module) { int i; qboolean found = false; - if (Sys_LockMutex(fs_thread_mutex)) + if (!fs_thread_mutex || Sys_LockMutex(fs_thread_mutex)) { for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++) { @@ -100,10 +100,13 @@ void FS_UnRegisterFileSystemModule(void *module) found = true; } } - Sys_UnlockMutex(fs_thread_mutex); - if (found) + if (fs_thread_mutex) { - Cmd_ExecuteString("fs_restart", RESTRICT_LOCAL); + Sys_UnlockMutex(fs_thread_mutex); + if (found) + { + Cmd_ExecuteString("fs_restart", RESTRICT_LOCAL); + } } } } diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 951055422..00da309a2 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -23,7 +23,7 @@ struct sockaddr; #include "quakedef.h" #include "netinc.h" -#ifdef _WIN32 +#if defined(_WIN32) || defined(__linux__) && !defined(ANDROID) #define USE_GETHOSTNAME_LOCALLISTING #endif @@ -2256,7 +2256,7 @@ int FTENET_GetLocalAddress(int port, qboolean ipx, qboolean ipv4, qboolean ipv6, //in linux, looking up our own hostname to retrieve a list of local interface addresses will give no indication that other systems are able to do the same thing and is thus not supported. //there's some special api instead //glibc 2.3. -//also available with certain bsds. +//also available with certain bsds, I'm but unsure which preprocessor we can use. #include static struct ifaddrs *iflist; @@ -2290,7 +2290,7 @@ int FTENET_GetLocalAddress(int port, qboolean ipx, qboolean ipv4, qboolean ipv6, #ifdef HAVE_IPV4 (fam == AF_INET && ipv4) || #endif -#ifdef HAVE_IPV6 +#ifdef IPPROTO_IPV6 (fam == AF_INET6 && ipv6) || #endif #ifdef USEIPX @@ -2298,7 +2298,7 @@ int FTENET_GetLocalAddress(int port, qboolean ipx, qboolean ipv4, qboolean ipv6, #endif 0) { - SockadrToNetadr((struct sockaddr_qstorage*)&ifa->ifa_addr, &addresses[idx]); + SockadrToNetadr((struct sockaddr_qstorage*)ifa->ifa_addr, &addresses[idx]); addresses[idx].port = port; adrflags[idx] = 0; idx++; @@ -5013,66 +5013,53 @@ void NET_PrintAddresses(ftenet_connections_t *collection) { if (addr[i].type != NA_INVALID) { - warn = false; + char *scope = "net"; + char *desc = NULL; if (addr[i].type == NA_LOOPBACK) { //we don't list 127.0.0.1 or ::1, so don't bother with this either. its not interesting. -// Con_Printf("internal address (%s): %s\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i])); - continue; + scope = NULL/*"internal"*/, desc = "internal"; } - if (addr[i].type == NA_IPV6) + else if (addr[i].type == NA_IPV6) { if ((*(int*)addr[i].address.ip6&BigLong(0xffc00000)) == BigLong(0xfe800000)) //fe80::/10 - { - Con_Printf("lan address (%s): %s (link-local)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i])); - continue; - } - if ((*(int*)addr[i].address.ip6&BigLong(0xfe000000)) == BigLong(0xfc00000)) //fc::/7 - { - Con_Printf("lan address (%s): %s (ULA/private)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i])); - continue; - } - if (*(int*)addr[i].address.ip6 == BigLong(0x20010000)) //2001::/32 - { - Con_Printf("net address (%s): %s (toredo)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i])); - continue; - } - if ((*(int*)addr[i].address.ip6&BigLong(0xffff0000)) == BigLong(0x20020000)) //2002::/16 - { - Con_Printf("net address (%s): %s (6to4)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i])); - continue; - } + scope = "lan", desc = "link-local"; + else if ((*(int*)addr[i].address.ip6&BigLong(0xfe000000)) == BigLong(0xfc00000)) //fc::/7 + scope = "lan", desc = "ULA/private"; + else if (*(int*)addr[i].address.ip6 == BigLong(0x20010000)) //2001::/32 + scope = "net", desc = "toredo"; + else if ((*(int*)addr[i].address.ip6&BigLong(0xffff0000)) == BigLong(0x20020000)) //2002::/16 + scope = "net", desc = "6to4"; + else if (memcmp(addr[i].address.ip6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1", 16) == 0) //::1 + scope = "local", desc = "localhost"; + else if (memcmp(addr[i].address.ip6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0) //:: + scope = "net", desc = "any"; } - if (addr[i].type == NA_IP) + else if (addr[i].type == NA_IP) { if ((*(int*)addr[i].address.ip&BigLong(0xffff0000)) == BigLong(0xA9FE0000)) //169.254.x.x/16 - { - Con_Printf("lan address (%s): %s (link-local)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i])); - continue; - } - if ((*(int*)addr[i].address.ip&BigLong(0xff000000)) == BigLong(0x0a000000)) //10.x.x.x/8 - { - Con_Printf("lan address (%s): %s (private)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i])); - continue; - } - if ((*(int*)addr[i].address.ip&BigLong(0xfff00000)) == BigLong(0xac100000)) //172.16.x.x/12 - { - Con_Printf("lan address (%s): %s (private)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i])); - continue; - } - if ((*(int*)addr[i].address.ip&BigLong(0xffff0000)) == BigLong(0xc0a80000)) //192.168.x.x/16 - { - Con_Printf("lan address (%s): %s (private)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i])); - continue; - } - if ((*(int*)addr[i].address.ip&BigLong(0xffc00000)) == BigLong(0x64400000)) //10.64.x.x/10 - { - Con_Printf("lan address (%s): %s (CGNAT)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i])); - continue; - } + scope = "lan", desc = "link-local"; + else if ((*(int*)addr[i].address.ip&BigLong(0xff000000)) == BigLong(0x0a000000)) //10.x.x.x/8 + scope = "lan", desc = "private"; + else if ((*(int*)addr[i].address.ip&BigLong(0xff000000)) == BigLong(0x7f000000)) //127.x.x.x/8 + scope = "local", desc = "localhost"; + else if ((*(int*)addr[i].address.ip&BigLong(0xfff00000)) == BigLong(0xac100000)) //172.16.x.x/12 + scope = "lan", desc = "private"; + else if ((*(int*)addr[i].address.ip&BigLong(0xffff0000)) == BigLong(0xc0a80000)) //192.168.x.x/16 + scope = "lan", desc = "private"; + else if ((*(int*)addr[i].address.ip&BigLong(0xffc00000)) == BigLong(0x64400000)) //10.64.x.x/10 + scope = "lan", desc = "CGNAT"; + else if (*(int*)addr[i].address.ip == BigLong(0x00000000)) //0.0.0.0/32 + scope = "lan", desc = "any"; + } + if (scope) + { + warn = false; + if (desc) + Con_Printf("%s address (%s): %s (%s)\n", scope, con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]), desc); + else + Con_Printf("%s address (%s): %s\n", scope, con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i])); } - Con_Printf("net address (%s): %s\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i])); - } } diff --git a/engine/common/plugin.c b/engine/common/plugin.c index 19c767d6a..8909514a3 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -1884,7 +1884,7 @@ void Plug_Shutdown(qboolean preliminary) if ((*p)->blockcloses) p = &(*p)->next; else - Plug_Close(plugs); + Plug_Close(*p); } } else diff --git a/engine/common/world.h b/engine/common/world.h index 310d84a09..69792e858 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -251,7 +251,7 @@ void QDECL World_ReleaseCollisionMesh(wedict_t *ed); - +void World_Destroy (world_t *w); void World_RBE_Start(world_t *world); diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index a7aba38a9..13e333251 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -109,7 +109,6 @@ void Mod_UpdateLightmap(int snum) } #endif -#ifndef SERVERONLY static void Mod_MemList_f(void) { int m; @@ -123,7 +122,7 @@ static void Mod_MemList_f(void) } Con_Printf("Total: %i bytes\n", total); } - +#ifndef SERVERONLY static void Mod_BatchList_f(void) { int m, i; @@ -535,7 +534,8 @@ Mod_Init */ void Mod_Init (qboolean initial) { - mod_known = malloc(MAX_MOD_KNOWN * sizeof(*mod_known)); + if (!mod_known) + mod_known = malloc(MAX_MOD_KNOWN * sizeof(*mod_known)); if (!initial) { Mod_ClearAll(); //shouldn't be needed @@ -543,8 +543,8 @@ void Mod_Init (qboolean initial) mod_numknown = 0; Q1BSP_Init(); -#ifndef SERVERONLY Cmd_AddCommand("mod_memlist", Mod_MemList_f); +#ifndef SERVERONLY Cmd_AddCommand("mod_batchlist", Mod_BatchList_f); Cmd_AddCommand("mod_texturelist", Mod_TextureList_f); Cmd_AddCommand("mod_usetexture", Mod_BlockTextureColour_f); @@ -603,6 +603,9 @@ void Mod_Shutdown (qboolean final) { if (final) { + Mod_ClearAll(); + Mod_Purge(MP_RESET); + Mod_UnRegisterAllModelFormats(NULL); #ifdef Q2BSPS CM_Shutdown(); diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index 1c4132d3a..86cbd968a 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -80,9 +80,13 @@ void PRAddressableRelocate(progfuncs_t *progfuncs, char *oldb, char *newb, int o //for 64bit systems. :) //addressable memory is memory available to the vm itself for writing. //once allocated, it cannot be freed for the lifetime of the VM. -void *PRAddressableExtend(progfuncs_t *progfuncs, int ammount) +//if src is null, data srcsize is left uninitialised for speed. +//pad is always 0-filled. +void *PRAddressableExtend(progfuncs_t *progfuncs, void *src, size_t srcsize, int pad) { - ammount = (ammount + 4)&~3; //round up to 4 + char *ptr; + int ammount = (srcsize+pad + 4)&~3; //round up to 4 + pad = ammount - srcsize; if (prinst.addressableused + ammount > prinst.addressablesize) { /*only do this if the caller states that it can cope with addressable-block relocations/resizes*/ @@ -133,6 +137,10 @@ void *PRAddressableExtend(progfuncs_t *progfuncs, int ammount) Sys_Error("VirtualAlloc failed. Blame windows."); #endif + ptr = &prinst.addressablehunk[prinst.addressableused-ammount]; + if (src) + memcpy(ptr, src, srcsize); + memset(ptr+srcsize, 0, pad); return &prinst.addressablehunk[prinst.addressableused-ammount]; } @@ -265,13 +273,14 @@ static void *PDECL PR_memalloc (pubprogfuncs_t *ppf, unsigned int size) /*assign more space*/ if (!ub) { - ub = PRAddressableExtend(progfuncs, size); + ub = PRAddressableExtend(progfuncs, NULL, size, 0); if (!ub) { printf("PF_memalloc: memory exausted\n"); PR_StackTrace(&progfuncs->funcs, false); return NULL; } + //FIXME: merge with previous block } memset(ub, 0, size); ub->marker = MARKER; @@ -441,7 +450,7 @@ int PDECL PR_InitEnts(pubprogfuncs_t *ppf, int max_ents) prinst.edicttable = PRHunkAlloc(progfuncs, maxedicts*sizeof(struct edicts_s *), "edicttable"); sv_edicts = PRHunkAlloc(progfuncs, externs->edictsize, "edict0"); prinst.edicttable[0] = sv_edicts; - ((edictrun_t*)prinst.edicttable[0])->fields = PRAddressableExtend(progfuncs, max_fields_size); + ((edictrun_t*)prinst.edicttable[0])->fields = PRAddressableExtend(progfuncs, NULL, fields_size, max_fields_size-fields_size); QC_ClearEdict(&progfuncs->funcs, sv_edicts); sv_num_edicts = 1; @@ -498,6 +507,9 @@ static void PDECL PR_Configure (pubprogfuncs_t *ppf, size_t addressable_size, in maxprogs = max_progs; pr_typecurrent=-1; + prinst.nexttempstring = 0; + prinst.maxtempstrings = 0; + prinst.reorganisefields = false; prinst.profiling = profiling; diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index ab71e16d5..776e158b9 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -35,7 +35,7 @@ edictrun_t *ED_AllocIntoTable (progfuncs_t *progfuncs, int num) prinst.edicttable[num] = *(struct edict_s **)&e = (void*)externs->memalloc(externs->edictsize); memset(e, 0, externs->edictsize); - e->fields = PRAddressableExtend(progfuncs, fields_size); + e->fields = PRAddressableExtend(progfuncs, NULL, fields_size, 0); e->entnum = num; QC_ClearEdict(&progfuncs->funcs, (struct edict_s*)e); @@ -2883,13 +2883,11 @@ retry: } len=sizeof(char)*pr_progs->numstrings; - s = PRAddressableExtend(progfuncs, len); - memcpy(s, pr_strings, len); + s = PRAddressableExtend(progfuncs, pr_strings, len, 0); pr_strings = (char *)s; len=sizeof(float)*pr_progs->numglobals; - s = PRAddressableExtend(progfuncs, len + sizeof(float)*2); - memcpy(s, pr_globals, len); + s = PRAddressableExtend(progfuncs, pr_globals, len, sizeof(float)*2); glob = pr_globals = (float *)s; if (progfuncs->funcs.stringtable) diff --git a/engine/qclib/progsint.h b/engine/qclib/progsint.h index e48ec47fe..5292fb9bb 100644 --- a/engine/qclib/progsint.h +++ b/engine/qclib/progsint.h @@ -224,7 +224,7 @@ extern QCC_opcode_t pr_opcodes[]; // sized by initialization int PRHunkMark(progfuncs_t *progfuncs); void PRHunkFree(progfuncs_t *progfuncs, int mark); void *PRHunkAlloc(progfuncs_t *progfuncs, int size, char *name); -void *PRAddressableExtend(progfuncs_t *progfuncs, int ammount); +void *PRAddressableExtend(progfuncs_t *progfuncs, void *src, size_t srcsize, int pad); #ifdef printf #undef LIKEPRINTF diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 3268679cd..864faca50 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -623,6 +623,7 @@ void PR_Deinit(void) if (svprogfuncs) { PR_Common_Shutdown(svprogfuncs, false); + World_Destroy(&sv.world); if (svprogfuncs->CloseProgs) svprogfuncs->CloseProgs(svprogfuncs); sv.world.progs = NULL; @@ -641,8 +642,7 @@ void PR_Deinit(void) } } - if (sv.world.rbe) - sv.world.rbe->End(&sv.world); + World_Destroy(&sv.world); #ifdef SQL SQL_KillServers(); diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 40dc26b4a..53389901e 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -253,13 +253,20 @@ void SV_Shutdown (void) NET_Shutdown (); + Plug_Shutdown(true); + Mod_Shutdown(true); COM_DestroyWorkerThread(); + FS_Shutdown(); + Plug_Shutdown(false); + Cvar_Shutdown(); + Cmd_Shutdown(); #ifdef WEBSERVER IWebShutdown(); #endif COM_BiDi_Shutdown(); + TL_Shutdown(); Memory_DeInit(); } diff --git a/engine/server/world.c b/engine/server/world.c index e4a898da1..3691e817c 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -2097,18 +2097,21 @@ qboolean QDECL World_RegisterPhysicsEngine(const char *enginename, void(QDECL*st world_current_physics_engine = startupfunc; return true; } -void QDECL World_ShutdownPhysics(world_t *world) +static void World_ShutdownPhysics(world_t *world) { unsigned int u; wedict_t *ed; if (!world->rbe) return; - for (u = 0; u < world->num_edicts; u++) + if (world->progs) { - ed = WEDICT_NUM(world->progs, u); - world->rbe->RemoveJointFromEntity(world, ed); - world->rbe->RemoveFromEntity(world, ed); + for (u = 0; u < world->num_edicts; u++) + { + ed = WEDICT_NUM(world->progs, u); + world->rbe->RemoveJointFromEntity(world, ed); + world->rbe->RemoveFromEntity(world, ed); + } } world->rbe->End(world); } @@ -2136,6 +2139,16 @@ void World_RBE_Start(world_t *world) world_current_physics_engine(world); } +void World_Destroy(world_t *world) +{ + World_ShutdownPhysics(world); + + Z_Free(world->areanodes); + world->areanodes = NULL; + world->areanodedepth = 0; + + memset(world, 0, sizeof(*world)); +} #ifdef USERBE static qboolean GenerateCollisionMesh_BSP(world_t *world, model_t *mod, wedict_t *ed, vec3_t geomcenter)