Beispiel #1
0
/**
 * @sa gi.AddEvent
 * @param[in] mask The player bitmask to send the events to. Use @c PM_ALL to send to every connected player.
 */
static void SV_AddEvent (unsigned int mask, int eType, int entnum)
{
	pending_event_t *p = &sv->pendingEvent;
	const int rawType = eType &~ EVENT_INSTANTLY;

	if (rawType >= EV_NUM_EVENTS || rawType < 0)
		Com_Error(ERR_DROP, "SV_AddEvent: invalid event %i", rawType);

	const char *eventName = eventNames[rawType].name;
	Com_DPrintf(DEBUG_EVENTSYS, "Event type: %s (%i - %i) (mask %s) (entnum: %i)\n", eventName,
			rawType, eType, Com_UnsignedIntToBinary(mask), entnum);

	/* finish the last event */
	if (p->pending)
		SV_EndEvents();

	/* start the new event */
	p->pending = true;
	p->playerMask = mask;
	p->type = eType;
	p->entnum = entnum;
	p->buf = new dbuffer();

	/* write header */
	NET_WriteByte(p->buf, svc_event);
	NET_WriteByte(p->buf, eType);
	if (entnum != -1)
		NET_WriteShort(p->buf, entnum);
}
Beispiel #2
0
/**
 * @brief Search the index in the config strings relative to a given start
 * @param name The value of the config string to search the index for
 * @param start The relative start point for the search
 * @param max The max. searched entries in the config string before giving up
 * @param create if @c true the value will get written into the config strings (appended)
 * @return @c 0 if not found
 */
static unsigned int SV_FindIndex (const char *name, int start, int max, qboolean create)
{
	int i;

	if (!name || !name[0])
		return 0;

	for (i = 1; i < max && SV_GetConfigString(start + i)[0] != '\0'; i++) {
		const char *configString = SV_GetConfigString(start + i);
		if (Q_streq(configString, name))
			return i;
	}

	if (!create)
		return 0;

	if (i == max)
		Com_Error(ERR_DROP, "*Index: overflow '%s' start: %i, max: %i", name, start, max);

	SV_SetConfigString(start + i, name);

	if (Com_ServerState() != ss_loading) {	/* send the update to everyone */
		struct dbuffer *msg = new_dbuffer();
		NET_WriteByte(msg, svc_configstring);
		NET_WriteShort(msg, start + i);
		NET_WriteString(msg, name);
		SV_Multicast(~0, msg);
	}

	return i;
}
Beispiel #3
0
static void testDBufferNetHandling (void)
{
	dbuffer buf;
	NET_WriteByte(&buf, 'b');
	CU_ASSERT_EQUAL(1, buf.length());
	NET_WriteShort(&buf, 128);
	CU_ASSERT_EQUAL(3, buf.length());
	NET_WriteLong(&buf, 128);
	CU_ASSERT_EQUAL(7, buf.length());
}
Beispiel #4
0
/**
 * @brief Writes to buffer according to format; version without syntactic sugar
 * for variable arguments, to call it from other functions with variable arguments
 * @note short and char are promoted to int when passed to variadic functions!
 */
void NET_vWriteFormat (dbuffer* buf, const char* format, va_list ap)
{
    while (*format) {
        const char typeID = *format++;

        switch (typeID) {
        case 'c':
            NET_WriteChar(buf, va_arg(ap, int));
            break;
        case 'b':
            NET_WriteByte(buf, va_arg(ap, int));
            break;
        case 's':
            NET_WriteShort(buf, va_arg(ap, int));
            break;
        case 'l':
            NET_WriteLong(buf, va_arg(ap, int));
            break;
        case 'p':
            NET_WritePos(buf, va_arg(ap, float*));
            break;
        case 'g':
            NET_WriteGPos(buf, va_arg(ap, byte*));
            break;
        case 'd':
            NET_WriteDir(buf, va_arg(ap, float*));
            break;
        case 'a':
            /* NOTE: float is promoted to double through ... */
            NET_WriteAngle(buf, va_arg(ap, double));
            break;
        case '!':
            break;
        case '&':
            NET_WriteString(buf, va_arg(ap, char*));
            break;
        case '*': {
            const int n = va_arg(ap, int);
            const byte* p = va_arg(ap, byte*);
            NET_WriteShort(buf, n);
            for (int i = 0; i < n; i++)
                NET_WriteByte(buf, *p++);
            break;
        }
        default:
            Com_Error(ERR_DROP, "WriteFormat: Unknown type!");
        }
    }
    /* Too many arguments for the given format; too few cause crash above */
#ifdef PARANOID
    if (!ap)
        Com_Error(ERR_DROP, "WriteFormat: Too many arguments!");
#endif
}
Beispiel #5
0
static void testDBufferNetHandling (void)
{
	dbuffer* buf = new_dbuffer();
	NET_WriteByte(buf, 'b');
	CU_ASSERT_EQUAL(1, dbuffer_len(buf));
	NET_WriteShort(buf, 128);
	CU_ASSERT_EQUAL(3, dbuffer_len(buf));
	NET_WriteLong(buf, 128);
	CU_ASSERT_EQUAL(7, dbuffer_len(buf));
	free_dbuffer(buf);
}
Beispiel #6
0
/**
 * @sa G_SendInventory
 */
static void CL_NetSendInventory (struct dbuffer *buf, const inventory_t *i)
{
	containerIndex_t container;
	int nr = 0;
	const invList_t *ic;

	for (container = 0; container < csi.numIDs; container++) {
		for (ic = i->c[container]; ic; ic = ic->next)
			nr++;
	}

	NET_WriteShort(buf, nr * INV_INVENTORY_BYTES);
	for (container = 0; container < csi.numIDs; container++) {
		for (ic = i->c[container]; ic; ic = ic->next)
			CL_NetSendItem(buf, ic->item, container, ic->x, ic->y);
	}
}
Beispiel #7
0
/**
 * @sa CL_ParseConfigString
 */
static void SV_Configstring (int index, const char *fmt, ...)
{
	char val[MAX_TOKEN_CHARS * MAX_TILESTRINGS];
	va_list argptr;

	if (index < 0 || index >= MAX_CONFIGSTRINGS)
		Com_Error(ERR_DROP, "configstring: bad index %i", index);

	va_start(argptr, fmt);
	Q_vsnprintf(val, sizeof(val), fmt, argptr);
	va_end(argptr);

	SV_SetConfigString(index, val);

	if (Com_ServerState() != ss_loading) { /* send the update to everyone */
		struct dbuffer *msg = new_dbuffer();
		NET_WriteByte(msg, svc_configstring);
		NET_WriteShort(msg, index);
		NET_WriteString(msg, val);

		/* send to all clients */
		SV_Multicast(~0, msg);
	}
}
Beispiel #8
0
/**
 * @sa CL_ParseConfigString
 */
static void SV_Configstring (int index, const char *fmt, ...)
{
	char val[MAX_TOKEN_CHARS * MAX_TILESTRINGS];
	va_list argptr;

	if (!Com_CheckConfigStringIndex(index))
		SV_error("configstring: bad index %i", index);

	va_start(argptr, fmt);
	Q_vsnprintf(val, sizeof(val), fmt, argptr);
	va_end(argptr);

	SV_SetConfigString(index, val);

	if (Com_ServerState() != ss_loading) { /* send the update to everyone */
		dbuffer msg(4 + strlen(val));
		NET_WriteByte(&msg, svc_configstring);
		NET_WriteShort(&msg, index);
		NET_WriteString(&msg, val);

		/* send to all clients */
		SV_Multicast(~0, msg);
	}
}
Beispiel #9
0
/**
 * @brief Send the character information to the server that is needed to spawn the soldiers of the player.
 * @param[out] buf The net channel buffer to write the character data into.
 * @param[in] chr The character to get the data from.
 */
static void GAME_NetSendCharacter (struct dbuffer * buf, const character_t *chr)
{
	int j;

	if (!chr)
		Com_Error(ERR_DROP, "No character given");
	if (chr->fieldSize != ACTOR_SIZE_2x2 && chr->fieldSize != ACTOR_SIZE_NORMAL)
		Com_Error(ERR_DROP, "Invalid character size given for character '%s': %i",
				chr->name, chr->fieldSize);
	if (chr->teamDef == NULL)
		Com_Error(ERR_DROP, "Character with no teamdef set (%s)", chr->name);

	NET_WriteByte(buf, chr->fieldSize);
	NET_WriteShort(buf, chr->ucn);
	NET_WriteString(buf, chr->name);

	/* model */
	NET_WriteString(buf, chr->path);
	NET_WriteString(buf, chr->body);
	NET_WriteString(buf, chr->head);
	NET_WriteByte(buf, chr->skin);

	NET_WriteShort(buf, chr->HP);
	NET_WriteShort(buf, chr->maxHP);
	NET_WriteByte(buf, chr->teamDef->idx);
	NET_WriteByte(buf, chr->gender);
	NET_WriteByte(buf, chr->STUN);
	NET_WriteByte(buf, chr->morale);

	for (j = 0; j < SKILL_NUM_TYPES + 1; j++)
		NET_WriteLong(buf, chr->score.experience[j]);
	for (j = 0; j < SKILL_NUM_TYPES; j++)
		NET_WriteByte(buf, chr->score.skills[j]);
	for (j = 0; j < SKILL_NUM_TYPES + 1; j++)
		NET_WriteByte(buf, chr->score.initialSkills[j]);
	for (j = 0; j < KILLED_NUM_TYPES; j++)
		NET_WriteShort(buf, chr->score.kills[j]);
	for (j = 0; j < KILLED_NUM_TYPES; j++)
		NET_WriteShort(buf, chr->score.stuns[j]);
	NET_WriteShort(buf, chr->score.assignedMissions);
}
Beispiel #10
0
/**
 * @brief Sends the first message from the server to a connected client.
 * This will be sent on the initial connection and upon each server load.
 * Client reads via CL_ParseServerData in cl_parse.c
 * @sa CL_Reconnect_f
 * @sa CL_ConnectionlessPacket
 */
static void SV_New_f (client_t *cl)
{
	Com_DPrintf(DEBUG_SERVER, "New() from %s\n", cl->name);

	if (cl->state != cs_connected) {
		if (cl->state == cs_spawning) {
			/* client typed 'reconnect/new' while connecting. */
			Com_Printf("SV_New_f: client typed 'reconnect/new' while connecting\n");
			SV_ClientCommand(cl, "\ndisconnect\nreconnect\n");
			SV_DropClient(cl, "");
		} else
			Com_DPrintf(DEBUG_SERVER, "WARNING: Illegal 'new' from %s, client state %d. This shouldn't happen...\n", cl->name, cl->state);
		return;
	}

	/* client state to prevent multiple new from causing high cpu / overflows. */
	SV_SetClientState(cl, cs_spawning);

	/* serverdata needs to go over for all types of servers
	 * to make sure the protocol is right, and to set the gamedir */

	/* send the serverdata */
	{
		const int playernum = cl - SV_GetClient(0);
		struct dbuffer *msg = new_dbuffer();
		NET_WriteByte(msg, svc_serverdata);
		NET_WriteLong(msg, PROTOCOL_VERSION);

		NET_WriteShort(msg, playernum);

		/* send full levelname */
		NET_WriteString(msg, SV_GetConfigString(CS_NAME));

		NET_WriteMsg(cl->stream, msg);
	}

	/* game server */
	if (Com_ServerState() == ss_game) {
		int i;
		for (i = 0; i < MAX_CONFIGSTRINGS; i++) {
			const char *configString;
			/* CS_TILES and CS_POSITIONS can stretch over multiple configstrings,
			 * so don't send the middle parts again. */
			if (i > CS_TILES && i < CS_POSITIONS)
				continue;
			if (i > CS_POSITIONS && i < CS_MODELS)
				continue;

			configString = SV_GetConfigString(i);
			if (configString[0] != '\0') {
				struct dbuffer *msg = new_dbuffer();
				Com_DPrintf(DEBUG_SERVER, "sending configstring %d: %s\n", i, configString);
				NET_WriteByte(msg, svc_configstring);
				NET_WriteShort(msg, i);
				NET_WriteString(msg, configString);
				/* enqueue and free msg */
				NET_WriteMsg(cl->stream, msg);
			}
		}
	}

	SV_ClientCommand(cl, "precache\n");
}
Beispiel #11
0
static void SV_WriteShort (int c)
{
	NET_WriteShort(sv->pendingEvent.buf, c);
}
Beispiel #12
0
void NET_WriteAngle16 (dbuffer* buf, float f)
{
    NET_WriteShort(buf, ANGLE2SHORT(f));
}