Example #1
0
/*
 * @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;
}
Example #2
0
/*
 * @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;
}
Example #3
0
/*
 * @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);
}
Example #4
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) {
	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];
}
Example #5
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];
}
Example #6
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;
}