Пример #1
0
/*
 * @brief Returns true if the specified server has been blacklisted, false otherwise.
 * The format of the blacklist file is one-IP-per-line, with wildcards. Ex:
 *
 * // This guy is a joker
 * 66.182.58.*
 *
 * Ensure that the file is new-line terminated for all rules to be evaluated.
 * TODO This is entirely untested
 */
static _Bool Ms_BlacklistServer(struct sockaddr_in *from) {
	void *buf;
	int32_t len;

	if ((len = Fs_Load("servers-blacklist", &buf)) == -1) {
		return false;
	}

	char *c = (char *) buf;
	char *ip = inet_ntoa(from->sin_addr);

	while ((c - (char *) buf) < len) {
		char line[256];

		sscanf(c, "%s\n", line);

		if (strncmp(line, "//", 2)) {
			if (GlobMatch(line, ip)) {
				return true;
			}
		}

		c += strlen(line) + 1;
	}

	return false;
}
Пример #2
0
/*
 * @brief Handles the actual loading of .ogg music files.
 */
static _Bool S_LoadMusicFile(const char *name, void **buffer, SDL_RWops **rw, Mix_Music **music) {
	char path[MAX_QPATH];

	*music = NULL;

	StripExtension(name, path);
	g_snprintf(path, sizeof(path), "music/%s.ogg", name);

	int32_t len;
	if ((len = Fs_Load(path, buffer)) != -1) {

		if ((*rw = SDL_RWFromMem(*buffer, len))) {

			if ((*music = Mix_LoadMUS_RW(*rw))) {
				Com_Debug("Loaded %s\n", name);
			} else {
				Com_Warn("Failed to load %s: %s\n", name, Mix_GetError());
				SDL_FreeRW(*rw);
			}
		} else {
			Com_Warn("Failed to create SDL_RWops for %s\n", name);
			Fs_Free(*buffer);
		}
	} else {
		Com_Debug("Failed to load %s\n", name);
	}

	return *music != NULL;
}
Пример #3
0
/**
 * @brief Returns true if the specified server has been blacklisted, false otherwise.
 * The format of the blacklist file is one-IP-per-line, with wildcards. Ex:
 *
 * // This guy is a joker
 * 66.182.58.*
 *
 * Ensure that the file is new-line terminated for all rules to be evaluated.
 */
static _Bool Ms_BlacklistServer(struct sockaddr_in *from) {
	char *buffer;
	int64_t len;

	if ((len = Fs_Load("servers-blacklist", (void *) &buffer)) == -1) {
		return false;
	}

	char *c = buffer;
	char *ip = inet_ntoa(from->sin_addr);

	_Bool blacklisted = false;

	while ((c - buffer) < len) {
		char line[256];

		sscanf(c, "%s\n", line);
		c += strlen(line) + 1;

		const char *l = g_strstrip(line);

		if (!strlen(l) || g_str_has_prefix(l, "//") || g_str_has_prefix(l, "#")) {
			continue;
		}

		if (GlobMatch(l, ip)) {
			blacklisted = true;
			break;
		}
	}

	Fs_Free((void *) buffer);

	return blacklisted;
}
Пример #4
0
/*
 * @brief
 */
static void S_LoadSampleChunk(s_sample_t *sample) {
	char path[MAX_QPATH];
	void *buf;
	int32_t i, len;
	SDL_RWops *rw;

	if (sample->media.name[0] == '*') // place holder
		return;

	if (sample->media.name[0] == '#') { // global path
		g_strlcpy(path, (sample->media.name + 1), sizeof(path));
	} else { // or relative
		g_snprintf(path, sizeof(path), "sounds/%s", sample->media.name);
	}

	buf = NULL;
	rw = NULL;

	i = 0;
	while (SAMPLE_TYPES[i]) {

		StripExtension(path, path);
		g_strlcat(path, SAMPLE_TYPES[i++], sizeof(path));

		if ((len = Fs_Load(path, &buf)) == -1)
			continue;

		if (!(rw = SDL_RWFromMem(buf, len))) {
			Fs_Free(buf);
			continue;
		}

		if (!(sample->chunk = Mix_LoadWAV_RW(rw, false)))
			Com_Warn("%s\n", Mix_GetError());

		Fs_Free(buf);

		SDL_FreeRW(rw);

		if (sample->chunk) { // success
			break;
		}
	}

	if (sample->chunk) {
		Mix_VolumeChunk(sample->chunk, s_volume->value * MIX_MAX_VOLUME);
		Com_Debug("Loaded %s\n", path);
	} else {
		if (g_str_has_prefix(sample->media.name, "#players")) {
			Com_Debug("Failed to load player sample %s\n", sample->media.name);
		} else {
			Com_Warn("Failed to load %s\n", sample->media.name);
		}
	}
}
Пример #5
0
	}END_TEST

START_TEST(check_Fs_LoadFile)
	{
		void *buffer;
		int64_t len = Fs_Load("quetoo.cfg", &buffer);

		ck_assert_msg(len > 0, "Failed to load quetoo.cfg");

		const char *prefix = "// generated by Quetoo, do not modify\n";
		ck_assert(g_str_has_prefix((const char *) buffer, prefix));

		Fs_Free(buffer);

	}END_TEST
Пример #6
0
/*
 * @brief
 */
static void AddScriptToStack(const char *file_name) {
	int64_t size;

	script++;
	if (script == &scriptstack[MAX_INCLUDES])
		Com_Error(ERR_FATAL, "Script file exceeded MAX_INCLUDES\n");

	strcpy(script->file_name, file_name);

	size = Fs_Load(script->file_name, (void **) (char *) &script->buffer);

	if (size == -1)
		Com_Error(ERR_FATAL, "Could not load %s\n", script->file_name);

	Com_Verbose("Loading %s (%u bytes)\n", script->file_name, (uint32_t) size);

	script->line = 1;

	script->script_p = script->buffer;
	script->end_p = script->buffer + size;
}
Пример #7
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;
}
Пример #8
0
/*
 * @brief Returns true if the file exists, otherwise it attempts to start a download
 * from the server.
 */
_Bool Cl_CheckOrDownloadFile(const char *filename) {
	char cmd[MAX_STRING_CHARS];

	if (cls.state == CL_DISCONNECTED) {
		Com_Print("Not connected\n");
		return true;
	}

	if (IS_INVALID_DOWNLOAD(filename)) {
		Com_Warn("Refusing to download \"%s\"\n", filename);
		return true;
	}

	Com_Debug("Checking for %s\n", filename);

	if (Fs_Exists(filename)) { // it exists, no need to download
		return true;
	}

	Com_Debug("Attempting to download %s\n", filename);

	strncpy(cls.download.name, filename, sizeof(cls.download.name));

	// udp downloads to a temp name, and only renames when done
	StripExtension(cls.download.name, cls.download.tempname);
	g_strlcat(cls.download.tempname, ".tmp", sizeof(cls.download.tempname));

	// attempt an http download if available
	if (cls.download_url[0] && Cl_HttpDownload())
		return false;

	// check to see if we already have a tmp for this file, if so, try to resume
	// open the file if not opened yet

	if (Fs_Exists(cls.download.tempname)) { // a temp file exists, resume download
		int64_t len = Fs_Load(cls.download.tempname, NULL);

		if ((cls.download.file = Fs_OpenAppend(cls.download.tempname))) {

			if (Fs_Seek(cls.download.file, len - 1)) {
				// give the server the offset to start the download
				Com_Debug("Resuming %s...\n", cls.download.name);

				g_snprintf(cmd, sizeof(cmd), "download %s %u", cls.download.name, (uint32_t) len);
				Net_WriteByte(&cls.net_chan.message, CL_CMD_STRING);
				Net_WriteString(&cls.net_chan.message, cmd);

				return false;
			}
		}
	}

	// or start if from the beginning
	Com_Debug("Downloading %s...\n", cls.download.name);

	g_snprintf(cmd, sizeof(cmd), "download %s", cls.download.name);
	Net_WriteByte(&cls.net_chan.message, CL_CMD_STRING);
	Net_WriteString(&cls.net_chan.message, cmd);

	return false;
}
Пример #9
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);
}
Пример #10
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];
}
Пример #11
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];
}
Пример #12
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;
}