Exemple #1
0
/**
 * @brief Writes a delta update of an entity_state_t list to the message.
 */
static void Sv_WriteEntities(sv_frame_t *from, sv_frame_t *to, mem_buf_t *msg) {
	entity_state_t *old_state = NULL, *new_state = NULL;
	uint32_t old_index, new_index;
	uint16_t old_num, new_num;
	uint16_t from_num_entities;

	if (!from) {
		from_num_entities = 0;
	} else {
		from_num_entities = from->num_entities;
	}

	new_index = 0;
	old_index = 0;
	while (new_index < to->num_entities || old_index < from_num_entities) {
		if (new_index >= to->num_entities) {
			new_num = 0xffff;
		} else {
			new_state = &svs.entity_states[(to->entity_state + new_index) % svs.num_entity_states];
			new_num = new_state->number;
		}

		if (old_index >= from_num_entities) {
			old_num = 0xffff;
		} else {
			old_state
			    = &svs.entity_states[(from->entity_state + old_index) % svs.num_entity_states];
			old_num = old_state->number;
		}

		if (new_num == old_num) { // delta update from old position
			Net_WriteDeltaEntity(msg, old_state, new_state, false);
			old_index++;
			new_index++;
			continue;
		}

		if (new_num < old_num) { // this is a new entity, send it from the baseline
			Net_WriteDeltaEntity(msg, &sv.baselines[new_num], new_state, true);
			new_index++;
			continue;
		}

		if (new_num > old_num) { // the old entity isn't present in the new message
			const int16_t bits = U_REMOVE;

			Net_WriteShort(msg, old_num);
			Net_WriteShort(msg, bits);

			old_index++;
			continue;
		}
	}

	Net_WriteShort(msg, 0); // end of entities
}
Exemple #2
0
/**
 * @brief Writes server_data, config_strings, and baselines once a non-delta
 * compressed frame arrives from the server.
 */
static void Cl_WriteDemoHeader(void) {
	static entity_state_t null_state;
	mem_buf_t msg;
	byte buffer[MAX_MSG_SIZE];

	// write out messages to hold the startup information
	Mem_InitBuffer(&msg, buffer, sizeof(buffer));

	// write the server data
	Net_WriteByte(&msg, SV_CMD_SERVER_DATA);
	Net_WriteShort(&msg, PROTOCOL_MAJOR);
	Net_WriteShort(&msg, cls.cgame->protocol);
	Net_WriteByte(&msg, 1); // demo_server byte
	Net_WriteString(&msg, Cvar_GetString("game"));
	Net_WriteShort(&msg, cl.client_num);
	Net_WriteString(&msg, cl.config_strings[CS_NAME]);

	// and config_strings
	for (int32_t i = 0; i < MAX_CONFIG_STRINGS; i++) {
		if (*cl.config_strings[i] != '\0') {
			if (msg.size + strlen(cl.config_strings[i]) + 32 > msg.max_size) { // write it out
				const int32_t len = LittleLong((int32_t) msg.size);
				Fs_Write(cls.demo_file, &len, sizeof(len), 1);
				Fs_Write(cls.demo_file, msg.data, msg.size, 1);
				msg.size = 0;
			}

			Net_WriteByte(&msg, SV_CMD_CONFIG_STRING);
			Net_WriteShort(&msg, i);
			Net_WriteString(&msg, cl.config_strings[i]);
		}
	}

	// and baselines
	for (size_t i = 0; i < lengthof(cl.entities); i++) {
		entity_state_t *ent = &cl.entities[i].baseline;
		if (!ent->number) {
			continue;
		}

		if (msg.size + 64 > msg.max_size) { // write it out
			const int32_t len = LittleLong((int32_t) msg.size);
			Fs_Write(cls.demo_file, &len, sizeof(len), 1);
			Fs_Write(cls.demo_file, msg.data, msg.size, 1);
			msg.size = 0;
		}

		Net_WriteByte(&msg, SV_CMD_BASELINE);
		Net_WriteDeltaEntity(&msg, &null_state, &cl.entities[i].baseline, true);
	}

	Net_WriteByte(&msg, SV_CMD_CBUF_TEXT);
	Net_WriteString(&msg, "precache 0\n");

	// write it to the demo file

	const int32_t len = LittleLong((int32_t) msg.size);

	Fs_Write(cls.demo_file, &len, sizeof(len), 1);
	Fs_Write(cls.demo_file, msg.data, msg.size, 1);

	Com_Debug(DEBUG_CLIENT, "Demo started\n");
	// the rest of the demo file will be individual frames
}