Ejemplo n.º 1
0
/**
 * @brief Creates a server's entity / program execution context by
 * parsing textual entity definitions out of an ent file.
 */
void G_SpawnEntities(const char *name, const char *entities) {

	gi.FreeTag(MEM_TAG_GAME_LEVEL);

	memset(&g_level, 0, sizeof(g_level));

	g_strlcpy(g_level.name, name, sizeof(g_level.name));

	// see if we have bots to keep
	if (aix) {
		g_game.ai_fill_slots = 0;
		g_game.ai_left_to_spawn = 0;

		if (g_ai_max_clients->integer) {
			if (g_ai_max_clients->integer == -1) {
				g_game.ai_fill_slots = sv_max_clients->integer;
			} else {
				g_game.ai_fill_slots = Clamp(g_ai_max_clients->integer, 0, sv_max_clients->integer);
			}

			g_game.ai_left_to_spawn = g_game.ai_fill_slots;
			g_ai_max_clients->modified = false;
		} else {
			for (int32_t i = 0; i < sv_max_clients->integer; i++) {
				if (g_game.entities[i + 1].client && g_game.entities[i + 1].client->ai) {
					g_game.ai_left_to_spawn++;
				}
			}
		}
	}
	
	memset(g_game.entities, 0, g_max_entities->value * sizeof(g_entity_t));
	memset(g_game.clients, 0, sv_max_clients->value * sizeof(g_client_t));

	for (int32_t i = 0; i < sv_max_clients->integer; i++) {
		g_game.entities[i + 1].client = g_game.clients + i;
	}

	ge.num_entities = sv_max_clients->integer + 1;

	g_entity_t *ent = NULL;

	gchar **inhibit = g_strsplit(g_inhibit->string, " ", -1);
	int32_t inhibited = 0;
	
	parser_t parser;
	char tok[MAX_QPATH];
	Parse_Init(&parser, entities, PARSER_NO_COMMENTS);

	// parse the entity definition string
	while (true) {

		if (!Parse_Token(&parser, PARSE_DEFAULT, tok, sizeof(tok))) {
			break;
		}

		if (tok[0] != '{') {
			gi.Error("Found \"%s\" when expecting \"{\"", tok);
		}

		if (ent == NULL) {
			ent = g_game.entities;
		} else {
			ent = G_AllocEntity();
		}

		G_ParseEntity(&parser, ent);

		if (ent != g_game.entities) {

			// enforce entity inhibiting
			for (size_t i = 0; i < g_strv_length(inhibit); i++) {
				if (g_strcmp0(ent->class_name, inhibit[i]) == 0) {
					G_FreeEntity(ent);
					inhibited++;
					continue;
				}
			}

			// handle legacy spawn flags
			if (ent->locals.spawn_flags & SF_NOT_DEATHMATCH) {
				G_FreeEntity(ent);
				inhibited++;
				continue;
			}

			// strip away unsupported flags
			ent->locals.spawn_flags &= ~(SF_NOT_EASY | SF_NOT_MEDIUM | SF_NOT_HARD | SF_NOT_COOP);
		}

		if (!G_SpawnEntity(ent)) {
			G_FreeEntity(ent);
			inhibited++;
		}
	}

	g_strfreev(inhibit);

	gi.Debug("%i entities inhibited\n", inhibited);

	G_InitMedia();

	G_InitEntityTeams();

	G_CheckHook();

	G_CheckTechs();

	G_ResetTeams();

	G_InitSpawnPoints();

	G_ResetSpawnPoints();

	G_ResetVote();

	G_ResetItems();
}
Ejemplo n.º 2
0
/*
 * @brief Creates a server's entity / program execution context by
 * parsing textual entity definitions out of an ent file.
 */
void G_SpawnEntities(const char *name, const char *entities) {
	g_edict_t *ent;
	int32_t inhibit;
	char *com_token;
	int32_t i;

	gi.FreeTag(Z_TAG_GAME_LEVEL);

	memset(&g_level, 0, sizeof(g_level));
	memset(g_game.edicts, 0, g_max_entities->value * sizeof(g_game.edicts[0]));

	g_strlcpy(g_level.name, name, sizeof(g_level.name));

	// set client fields on player ents
	for (i = 0; i < sv_max_clients->integer; i++) {
		g_game.edicts[i + 1].client = g_game.clients + i;
	}
	ge.num_edicts = sv_max_clients->integer + 1;

	ent = NULL;
	inhibit = 0;

	// parse ents
	while (true) {
		// parse the opening brace
		com_token = ParseToken(&entities);

		if (!entities)
			break;

		if (com_token[0] != '{')
			gi.Error("Found \"%s\" when expecting \"{\"", com_token);

		if (!ent)
			ent = g_game.edicts;
		else
			ent = G_Spawn();

		entities = G_ParseEntity(entities, ent);

		// some ents don't belong in deathmatch
		if (ent != g_game.edicts) {

			// legacy levels may require this
			if (ent->locals.spawn_flags & SF_NOT_DEATHMATCH) {
				G_FreeEdict(ent);
				inhibit++;
				continue;
			}

			// emits and models are client sided
			if (!g_strcmp0(ent->class_name, "misc_emit") || !g_strcmp0(ent->class_name, "misc_model")) {
				G_FreeEdict(ent);
				inhibit++;
				continue;
			}

			// lights aren't even used
			if (!g_strcmp0(ent->class_name, "light") || !g_strcmp0(ent->class_name, "light_spot")) {
				G_FreeEdict(ent);
				inhibit++;
				continue;
			}

			// strip away unsupported flags
			ent->locals.spawn_flags &= ~(SF_NOT_EASY | SF_NOT_MEDIUM | SF_NOT_HARD | SF_NOT_COOP
					| SF_NOT_DEATHMATCH);
		}

		// retain the map-specified origin for respawns
		VectorCopy(ent->s.origin, ent->locals.map_origin);

		G_SpawnEntity(ent);

		if (g_level.gameplay > 1 && ent->locals.item) { // now that we've spawned them, hide them
			ent->sv_flags |= SVF_NO_CLIENT;
			ent->solid = SOLID_NOT;
			ent->locals.next_think = 0;
		}
	}

	gi.Debug("%i entities inhibited\n", inhibit);

	G_InitEntityTeams();

	G_InitMedia();

	G_ResetTeams();

	G_ResetVote();
}