/* * @brief Called when the player is totally leaving the server, either willingly * or unwillingly. This is NOT called if the entire server is quitting * or crashing. */ void Sv_DropClient(sv_client_t *cl) { g_edict_t *ent; if (cl->state > SV_CLIENT_FREE) { // send the disconnect if (cl->state == SV_CLIENT_ACTIVE) { // after informing the game module svs.game->ClientDisconnect(cl->edict); } Net_WriteByte(&cl->net_chan.message, SV_CMD_DISCONNECT); Netchan_Transmit(&cl->net_chan, cl->net_chan.message.data, cl->net_chan.message.size); } if (cl->download.buffer) { Fs_Free(cl->download.buffer); } ent = cl->edict; memset(cl, 0, sizeof(*cl)); cl->edict = ent; cl->last_frame = -1; }
/* * @brief Loads the model by the specified name. */ r_model_t *R_LoadModel(const char *name) { r_model_t *mod; char key[MAX_QPATH]; size_t i; if (!name || !name[0]) { Com_Error(ERR_DROP, "R_LoadModel: NULL name\n"); } if (*name == '*') { g_snprintf(key, sizeof(key), "%s#%s", r_model_state.world->media.name, name + 1); } else { StripExtension(name, key); } if (!(mod = (r_model_t *) R_FindMedia(key))) { void *buf; const r_model_format_t *format = r_model_formats; for (i = 0; i < lengthof(r_model_formats); i++, format++) { StripExtension(name, key); strcat(key, format->extension); if (Fs_Load(key, &buf) != -1) break; } if (i == lengthof(r_model_formats)) { // not found if (strstr(name, "players/")) { Com_Debug("Failed to load player %s\n", name); } else { Com_Warn("Failed to load %s\n", name); } return NULL; } StripExtension(name, key); mod = (r_model_t *) R_AllocMedia(key, sizeof(r_model_t)); mod->media.Register = R_RegisterModel; mod->media.Free = R_FreeModel; mod->type = format->type; // load the materials first, so that we can resolve surfaces lists R_LoadMaterials(mod); // load it format->Load(mod, buf); // free the file Fs_Free(buf); // assemble vertex buffer objects from static arrays R_LoadVertexBuffers(mod); // calculate an approximate radius from the bounding box vec3_t tmp; VectorSubtract(mod->maxs, mod->mins, tmp); mod->radius = VectorLength(tmp) / 2.0; R_RegisterMedia((r_media_t *) mod); } return mod; }
/* * @brief */ static void LoadPortals(const char *filename) { uint32_t i; portal_t *p; leaf_t *l; char magic[80]; char *buffer, *s; int32_t len; int32_t num_points; winding_t *w; int32_t leaf_nums[2]; plane_t plane; if (Fs_Load(filename, (void **) &buffer) == -1) Com_Error(ERR_FATAL, "Could not open %s\n", filename); s = buffer; memset(&map_vis, 0, sizeof(map_vis)); if (sscanf(s, "%79s\n%u\n%u\n%n", magic, &map_vis.portal_clusters, &map_vis.num_portals, &len) != 3) Com_Error(ERR_FATAL, "Failed to read header: %s\n", filename); s += len; if (g_strcmp0(magic, PORTALFILE)) Com_Error(ERR_FATAL, "Not a portal file: %s\n", filename); Com_Verbose("Loading %4u portals, %4u clusters from %s...\n", map_vis.num_portals, map_vis.portal_clusters, filename); // these counts should take advantage of 64 bit systems automatically map_vis.leaf_bytes = ((map_vis.portal_clusters + 63) & ~63) >> 3; map_vis.leaf_longs = map_vis.leaf_bytes / sizeof(long); map_vis.portal_bytes = ((map_vis.num_portals * 2 + 63) & ~63) >> 3; map_vis.portal_longs = map_vis.portal_bytes / sizeof(long); // each file portal is split into two memory portals map_vis.portals = Mem_Malloc(2 * map_vis.num_portals * sizeof(portal_t)); // allocate the leafs map_vis.leafs = Mem_Malloc(map_vis.portal_clusters * sizeof(leaf_t)); map_vis.uncompressed_size = map_vis.portal_clusters * map_vis.leaf_bytes; map_vis.uncompressed = Mem_Malloc(map_vis.uncompressed_size); map_vis.base = map_vis.pointer = d_bsp.vis_data; d_vis->num_clusters = map_vis.portal_clusters; map_vis.pointer = (byte *) &d_vis->bit_offsets[map_vis.portal_clusters]; map_vis.end = map_vis.base + MAX_BSP_VISIBILITY; for (i = 0, p = map_vis.portals; i < map_vis.num_portals; i++) { int32_t j; if (sscanf(s, "%i %i %i %n", &num_points, &leaf_nums[0], &leaf_nums[1], &len) != 3) { Com_Error(ERR_FATAL, "Failed to read portal %i\n", i); } s += len; if (num_points > MAX_POINTS_ON_WINDING) { Com_Error(ERR_FATAL, "Portal %i has too many points\n", i); } if ((uint32_t) leaf_nums[0] > map_vis.portal_clusters || (uint32_t) leaf_nums[1] > map_vis.portal_clusters) { Com_Error(ERR_FATAL, "Portal %i has invalid leafs\n", i); } w = p->winding = NewWinding(num_points); w->original = true; w->num_points = num_points; for (j = 0; j < num_points; j++) { double v[3]; int32_t k; // scanf into double, then assign to vec_t // so we don't care what size vec_t is if (sscanf(s, "(%lf %lf %lf ) %n", &v[0], &v[1], &v[2], &len) != 3) Com_Error(ERR_FATAL, "Failed to read portal vertex definition %i:%i\n", i, j); s += len; for (k = 0; k < 3; k++) w->points[j][k] = v[k]; } if (sscanf(s, "\n%n", &len)) { s += len; } // calc plane PlaneFromWinding(w, &plane); // create forward portal l = &map_vis.leafs[leaf_nums[0]]; if (l->num_portals == MAX_PORTALS_ON_LEAF) Com_Error(ERR_FATAL, "MAX_PORTALS_ON_LEAF\n"); l->portals[l->num_portals] = p; l->num_portals++; p->winding = w; VectorSubtract(vec3_origin, plane.normal, p->plane.normal); p->plane.dist = -plane.dist; p->leaf = leaf_nums[1]; SetPortalSphere(p); p++; // create backwards portal l = &map_vis.leafs[leaf_nums[1]]; if (l->num_portals == MAX_PORTALS_ON_LEAF) Com_Error(ERR_FATAL, "MAX_PORTALS_ON_LEAF\n"); l->portals[l->num_portals] = p; l->num_portals++; p->winding = NewWinding(w->num_points); p->winding->num_points = w->num_points; for (j = 0; j < w->num_points; j++) { VectorCopy(w->points[w->num_points - 1 - j], p->winding->points[j]); } p->plane = plane; p->leaf = leaf_nums[0]; SetPortalSphere(p); p++; } Fs_Free(buffer); }
/* * @brief Loads in the BSP and all sub-models for collision detection. This * function can also be used to initialize or clean up the collision model by * invoking with NULL. */ cm_bsp_model_t *Cm_LoadBspModel(const char *name, int64_t *size) { void *buf; memset(&cm_bsp, 0, sizeof(cm_bsp)); cm_vis = (d_bsp_vis_t *) cm_bsp.visibility; // clean up and return if (!name) { if (size) { *size = 0; } return &cm_bsp.models[0]; } // load the file const int64_t s = Fs_Load(name, &buf); if (s == -1) { Com_Error(ERR_DROP, "Couldn't load %s\n", name); } if (size) { *size = s; } // byte-swap the entire header d_bsp_header_t header = *(d_bsp_header_t *) buf; for (size_t i = 0; i < sizeof(d_bsp_header_t) / sizeof(int32_t); i++) { ((int32_t *) &header)[i] = LittleLong(((int32_t *) &header)[i]); } if (header.version != BSP_VERSION && header.version != BSP_VERSION_QUETOO) { Com_Error(ERR_DROP, "%s has unsupported version: %d\n", name, header.version); } g_strlcpy(cm_bsp.name, name, sizeof(cm_bsp.name)); cm_bsp.base = (byte *) buf; // load into heap Cm_LoadEntityString(&header.lumps[BSP_LUMP_ENTITIES]); Cm_LoadBspPlanes(&header.lumps[BSP_LUMP_PLANES]); Cm_LoadBspNodes(&header.lumps[BSP_LUMP_NODES]); Cm_LoadBspSurfaces(&header.lumps[BSP_LUMP_TEXINFO]); Cm_LoadBspLeafs(&header.lumps[BSP_LUMP_LEAFS]); Cm_LoadBspLeafBrushes(&header.lumps[BSP_LUMP_LEAF_BRUSHES]); Cm_LoadBspInlineModels(&header.lumps[BSP_LUMP_MODELS]); Cm_LoadBspBrushes(&header.lumps[BSP_LUMP_BRUSHES]); Cm_LoadBspBrushSides(&header.lumps[BSP_LUMP_BRUSH_SIDES]); Cm_LoadBspVisibility(&header.lumps[BSP_LUMP_VISIBILITY]); Cm_LoadBspAreas(&header.lumps[BSP_LUMP_AREAS]); Cm_LoadBspAreaPortals(&header.lumps[BSP_LUMP_AREA_PORTALS]); Fs_Free(buf); Cm_SetupBspBrushes(); Cm_InitBoxHull(); Cm_FloodAreas(); return &cm_bsp.models[0]; }
/** * @brief Loads in the BSP and all sub-models for collision detection. This * function can also be used to initialize or clean up the collision model by * invoking with NULL. */ cm_bsp_model_t *Cm_LoadBspModel(const char *name, int64_t *size) { // don't re-load if we don't have to if (name && !g_strcmp0(name, cm_bsp.name)) { if (size) { *size = cm_bsp.size; } return &cm_bsp.models[0]; } Cm_UnloadBspMaterials(); Bsp_UnloadLumps(&cm_bsp.bsp, BSP_LUMPS_ALL); // free dynamic memory Mem_Free(cm_bsp.planes); Mem_Free(cm_bsp.nodes); Mem_Free(cm_bsp.texinfos); Mem_Free(cm_bsp.leafs); Mem_Free(cm_bsp.leaf_brushes); Mem_Free(cm_bsp.models); Mem_Free(cm_bsp.brushes); Mem_Free(cm_bsp.brush_sides); Mem_Free(cm_bsp.areas); Mem_Free(cm_bsp.portal_open); memset(&cm_bsp, 0, sizeof(cm_bsp)); // clean up and return if (!name) { if (size) { *size = 0; } return &cm_bsp.models[0]; } // load the common BSP structure and the lumps we need bsp_header_t *file; if (!Fs_Load(name, (void **) &file)) { Com_Error(ERROR_DROP, "Couldn't load %s\n", name); } int32_t version = Bsp_Verify(file); if (version != BSP_VERSION && version != BSP_VERSION_QUETOO) { Fs_Free(file); Com_Error(ERROR_DROP, "%s has unsupported version: %d\n", name, version); } if (!Bsp_LoadLumps(file, &cm_bsp.bsp, CM_BSP_LUMPS)) { Fs_Free(file); Com_Error(ERROR_DROP, "Lump error loading %s\n", name); } // in theory, by this point the BSP is valid - now we have to create the cm_ // structures out of the raw file data if (size) { cm_bsp.size = *size = Bsp_Size(file); } g_strlcpy(cm_bsp.name, name, sizeof(cm_bsp.name)); Fs_Free(file); cm_bsp.materials = Cm_LoadBspMaterials(name); Cm_LoadBspPlanes(); Cm_LoadBspNodes(); Cm_LoadBspSurfaces(); Cm_LoadBspLeafs(); Cm_LoadBspLeafBrushes(); Cm_LoadBspInlineModels(); Cm_LoadBspBrushes(); Cm_LoadBspBrushSides(); Cm_LoadBspVisibility(); Cm_LoadBspAreas(); Cm_LoadBspAreaPortals(); Cm_SetupBspBrushes(); Cm_InitBoxHull(); Cm_FloodAreas(); return &cm_bsp.models[0]; }
/* * @brief */ static r_shader_t *R_LoadShader(GLenum type, const char *name) { r_shader_t *sh; char path[MAX_QPATH], *src[1], log[MAX_STRING_CHARS]; uint32_t e, length[1]; void *buf; int32_t i, len; g_snprintf(path, sizeof(path), "shaders/%s", name); if ((len = Fs_Load(path, &buf)) == -1) { Com_Warn("Failed to load %s\n", name); return NULL; } src[0] = (char *) buf; length[0] = len; for (i = 0; i < MAX_SHADERS; i++) { sh = &r_state.shaders[i]; if (!sh->id) break; } if (i == MAX_SHADERS) { Com_Warn("MAX_SHADERS reached\n"); Fs_Free(buf); return NULL; } g_strlcpy(sh->name, name, sizeof(sh->name)); sh->type = type; sh->id = qglCreateShader(sh->type); if (!sh->id) { Fs_Free(buf); return NULL; } // upload the shader source qglShaderSource(sh->id, 1, src, length); // compile it and check for errors qglCompileShader(sh->id); qglGetShaderiv(sh->id, GL_COMPILE_STATUS, &e); if (!e) { qglGetShaderInfoLog(sh->id, sizeof(log) - 1, NULL, log); Com_Warn("%s: %s\n", sh->name, log); qglDeleteShader(sh->id); memset(sh, 0, sizeof(*sh)); Fs_Free(buf); return NULL; } Fs_Free(buf); return sh; }