void D_SendServerInfoChange (const FBaseCVar *cvar, UCVarValue value, ECVarType type)
{
    size_t namelen;

    namelen = strlen (cvar->GetName ());

    Net_WriteByte (DEM_SINFCHANGED);
    Net_WriteByte ((BYTE)(namelen | (type << 6)));
    Net_WriteBytes ((BYTE *)cvar->GetName (), (int)namelen);
    switch (type)
    {
    case CVAR_Bool:
        Net_WriteByte (value.Bool);
        break;
    case CVAR_Int:
        Net_WriteLong (value.Int);
        break;
    case CVAR_Float:
        Net_WriteFloat (value.Float);
        break;
    case CVAR_String:
        Net_WriteString (value.String);
        break;
    default:
        break; // Silence GCC
    }
}
void FWeaponSlots::SendDifferences(const FWeaponSlots &other)
{
	int i, j;

	for (i = 0; i < NUM_WEAPON_SLOTS; ++i)
	{
		if (other.Slots[i].Size() == Slots[i].Size())
		{
			for (j = (int)Slots[i].Size(); j-- > 0; )
			{
				if (other.Slots[i].GetWeapon(j) != Slots[i].GetWeapon(j))
				{
					break;
				}
			}
			if (j < 0)
			{ // The two slots are the same.
				continue;
			}
		}
		// The slots differ. Send mine.
		Net_WriteByte(DEM_SETSLOT);
		Net_WriteByte(i);
		Net_WriteByte(Slots[i].Size());
		for (j = 0; j < Slots[i].Size(); ++j)
		{
			Net_WriteWeapon(Slots[i].GetWeapon(j));
		}
	}
}
示例#3
0
/*
 * @brief Pumps the command cycle, sending the most recently gathered movement
 * to the server.
 */
void Cl_SendCmd(void) {
	mem_buf_t buf;
	byte data[128];

	if (cls.state <= CL_CONNECTING)
		return;

	if (cls.state == CL_CONNECTED) {
		// send any reliable messages and / or don't timeout
		if (cls.net_chan.message.size || cls.real_time - cls.net_chan.last_sent > 1000)
			Netchan_Transmit(&cls.net_chan, NULL, 0);
		return;
	}

	// send a user info update if needed
	if (cvar_user_info_modified) {
		Net_WriteByte(&cls.net_chan.message, CL_CMD_USER_INFO);
		Net_WriteString(&cls.net_chan.message, Cvar_UserInfo());

		cvar_user_info_modified = false;
	}

	// finalize the current command
	Cl_FinalizeCmd();

	// and write it out
	Mem_InitBuffer(&buf, data, sizeof(data));

	Net_WriteByte(&buf, CL_CMD_MOVE);

	// let the server know what the last frame we got was, so the next
	// message can be delta compressed
	if (!cl.frame.valid || (cls.demo_file && Fs_Tell(cls.demo_file) == 0))
		Net_WriteLong(&buf, -1); // no compression
	else
		Net_WriteLong(&buf, cl.frame.frame_num);

	// send this and the previous two cmds in the message, so
	// if the last packet was dropped, it can be recovered
	static user_cmd_t null_cmd;

	cl_cmd_t *cmd = &cl.cmds[(cls.net_chan.outgoing_sequence - 2) & CMD_MASK];
	Net_WriteDeltaUserCmd(&buf, &null_cmd, &cmd->cmd);

	user_cmd_t *old_cmd = &cmd->cmd;
	cmd = &cl.cmds[(cls.net_chan.outgoing_sequence - 1) & CMD_MASK];
	Net_WriteDeltaUserCmd(&buf, old_cmd, &cmd->cmd);

	old_cmd = &cmd->cmd;
	cmd = &cl.cmds[(cls.net_chan.outgoing_sequence) & CMD_MASK];
	Net_WriteDeltaUserCmd(&buf, old_cmd, &cmd->cmd);

	// deliver the message
	Netchan_Transmit(&cls.net_chan, buf.data, buf.size);

	cl.packet_counter++;

	// initialize the next command
	Cl_InitCmd();
}
示例#4
0
void Net_WriteWeapon(PClassWeapon *type)
{
	int index, *index_p;

	index_p = Weapons_hton.CheckKey(type);
	if (index_p == NULL)
	{
		index = 0;
	}
	else
	{
		index = *index_p;
	}
	// 32767 weapons better be enough for anybody.
	assert(index >= 0 && index <= 32767);
	if (index < 128)
	{
		Net_WriteByte(index);
	}
	else
	{
		Net_WriteByte(0x80 | index);
		Net_WriteByte(index >> 7);
	}
}
示例#5
0
static void SummonActor (int command, int command2, FCommandLine argv)
{
	if (CheckCheatmode ())
		return;

	if (argv.argc() > 1)
	{
		const PClass *type = PClass::FindClass (argv[1]);
		if (type == NULL)
		{
			Printf ("Unknown class '%s'\n", argv[1]);
			return;
		}
		Net_WriteByte (argv.argc() > 2 ? command2 : command);
		Net_WriteString (type->TypeName.GetChars());

		if (argv.argc () > 2) {
			Net_WriteWord (atoi (argv[2])); // angle
			if (argv.argc () > 3) Net_WriteWord (atoi (argv[3])); // TID
			else Net_WriteWord (0);
			if (argv.argc () > 4) Net_WriteByte (atoi (argv[4])); // special
			else Net_WriteByte (0);
			for(int i = 5; i < 10; i++) { // args[5]
				if(i < argv.argc()) Net_WriteLong (atoi (argv[i]));
				else Net_WriteLong (0);
			}
		}
	}
}
示例#6
0
static void SummonActor (int command, int command2, FCommandLine argv)
{
	if (CheckCheatmode ())
		return;

	if (argv.argc() > 1)
	{
		PClassActor *type = PClass::FindActor(argv[1]);
		if (type == NULL)
		{
			Printf ("Unknown actor '%s'\n", argv[1]);
			return;
		}
		Net_WriteByte (argv.argc() > 2 ? command2 : command);
		Net_WriteString (type->TypeName.GetChars());

		if (argv.argc () > 2)
		{
			Net_WriteWord (atoi (argv[2])); // angle
			Net_WriteWord ((argv.argc() > 3) ? atoi(argv[3]) : 0); // TID
			Net_WriteByte ((argv.argc() > 4) ? atoi(argv[4]) : 0); // special
			for (int i = 5; i < 10; i++)
			{ // args[5]
				Net_WriteLong((i < argv.argc()) ? atoi(argv[i]) : 0);
			}
		}
	}
}
示例#7
0
void D_SendServerFlagChange (const FBaseCVar *cvar, int bitnum, bool set)
{
	int namelen;

	namelen = (int)strlen (cvar->GetName ());

	Net_WriteByte (DEM_SINFCHANGEDXOR);
	Net_WriteByte ((BYTE)namelen);
	Net_WriteBytes ((BYTE *)cvar->GetName (), namelen);
	Net_WriteByte (BYTE(bitnum | (set << 5)));
}
示例#8
0
文件: sv_main.c 项目: chrisnew/quetoo
/*
 * @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_entity_t *ent;

	Mem_ClearBuffer(&cl->net_chan.message);
	Mem_ClearBuffer(&cl->datagram.buffer);

	if (cl->datagram.messages) {
		g_list_free_full(cl->datagram.messages, Mem_Free);
	}

	if (cl->state > SV_CLIENT_FREE) { // send the disconnect

		if (cl->state == SV_CLIENT_ACTIVE) { // after informing the game module
			svs.game->ClientDisconnect(cl->entity);
		}

		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->entity;

	memset(cl, 0, sizeof(*cl));

	cl->entity = ent;
	cl->last_frame = -1;
}
示例#9
0
void D_UserInfoChanged (FBaseCVar *cvar)
{
	UCVarValue val;
	FString escaped_val;
	char foo[256];

	if (cvar == &autoaim)
	{
		if (autoaim < 0.0f)
		{
			autoaim = 0.0f;
			return;
		}
		else if (autoaim > 5000.0f)
		{
			autoaim = 5000.f;
			return;
		}
	}

	val = cvar->GetGenericRep (CVAR_String);
	escaped_val = D_EscapeUserInfo(val.String);
	if (4 + strlen(cvar->GetName()) + escaped_val.Len() > 256)
		I_Error ("User info descriptor too big");

	mysnprintf (foo, countof(foo), "\\%s\\%s", cvar->GetName(), escaped_val.GetChars());

	Net_WriteByte (DEM_UINFCHANGED);
	Net_WriteString (foo);
}
示例#10
0
bool DIntermissionController::Responder (event_t *ev)
{
	if (mScreen != NULL)
	{
		if (!mScreen->mPaletteChanged && ev->type == EV_KeyDown)
		{
			const char *cmd = Bindings.GetBind (ev->data1);

			if (cmd != NULL &&
				(!stricmp(cmd, "toggleconsole") ||
				 !stricmp(cmd, "screenshot")))
			{
				return false;
			}
		}

		if (mScreen->mTicker < 2) return false;	// prevent some leftover events from auto-advancing
		int res = mScreen->Responder(ev);
		if (res == -1 && !mSentAdvance)
		{
			Net_WriteByte(DEM_ADVANCEINTER);
			mSentAdvance = true;
		}
		return !!res;
	}
	return false;
}
示例#11
0
文件: cl_cmd.c 项目: jdolan/quetoo
/**
 * @brief Sends the user info string to the server over the reliable channel.
 */
static void Cl_WriteUserInfoCommand(void) {

	if (cvar_user_info_modified) {
		cvar_user_info_modified = false;

		Net_WriteByte(&cls.net_chan.message, CL_CMD_USER_INFO);
		Net_WriteString(&cls.net_chan.message, Cvar_UserInfo());
	}
}
示例#12
0
/*
 * @brief A download message has been received from the server.
 */
static void Cl_ParseDownload(void) {
	int32_t size, percent;

	// read the data
	size = Net_ReadShort(&net_message);
	percent = Net_ReadByte(&net_message);
	if (size < 0) {
		Com_Debug("Server does not have this file\n");
		if (cls.download.file) {
			// if here, we tried to resume a file but the server said no
			Fs_Close(cls.download.file);
			cls.download.file = NULL;
		}
		Cl_RequestNextDownload();
		return;
	}

	// open the file if not opened yet
	if (!cls.download.file) {

		if (!(cls.download.file = Fs_OpenWrite(cls.download.tempname))) {
			net_message.read += size;
			Com_Warn("Failed to open %s\n", cls.download.tempname);
			Cl_RequestNextDownload();
			return;
		}
	}

	Fs_Write(cls.download.file, net_message.data + net_message.read, 1, size);

	net_message.read += size;

	if (percent != 100) {
		Net_WriteByte(&cls.net_chan.message, CL_CMD_STRING);
		Net_WriteString(&cls.net_chan.message, "nextdl");
	} else {
		Fs_Close(cls.download.file);
		cls.download.file = NULL;

		// add new archives to the search path
		if (Fs_Rename(cls.download.tempname, cls.download.name)) {
			if (strstr(cls.download.name, ".zip")) {
				Fs_AddToSearchPath(cls.download.name);
			}
		} else {
			Com_Error(ERR_DROP, "Failed to rename %s\n", cls.download.name);
		}

		// get another file if needed
		Cl_RequestNextDownload();
	}
}
示例#13
0
//*****************************************************************************
//
void chat_SendMessage( ULONG ulMode, const char *pszString )
{
	FString ChatMessage = pszString;

	// [CW] Substitute the message if necessary.
	chat_DoSubstitution( ChatMessage );

	// If we're the client, let the server handle formatting/sending the msg to other players.
	if ( NETWORK_GetState( ) == NETSTATE_CLIENT )
	{
		CLIENTCOMMANDS_Say( ulMode, ChatMessage.GetChars( ));
		return;
	}

	if ( demorecording )
	{
		Net_WriteByte( DEM_SAY );
		Net_WriteByte( ulMode );
		Net_WriteString( ChatMessage.GetChars( ));
	}
	else
		CHAT_PrintChatString( consoleplayer, ulMode, ChatMessage.GetChars( ));
}
示例#14
0
/**
 * @brief
 */
void Sv_WriteClientFrame(sv_client_t *client, mem_buf_t *msg) {
	sv_frame_t *frame, *delta_frame;
	int32_t delta_frame_num;

	// this is the frame we are creating
	frame = &client->frames[sv.frame_num & PACKET_MASK];

	if (client->last_frame < 0) {
		// client is asking for a retransmit
		delta_frame = NULL;
		delta_frame_num = -1;
	} else if (sv.frame_num - client->last_frame >= (PACKET_BACKUP - 3)) {
		// client hasn't gotten a good message through in a long time
		delta_frame = NULL;
		delta_frame_num = -1;
	} else {
		// we have a valid message to delta from
		delta_frame = &client->frames[client->last_frame & PACKET_MASK];
		delta_frame_num = client->last_frame;
	}

	Net_WriteByte(msg, SV_CMD_FRAME);
	Net_WriteLong(msg, sv.frame_num);
	Net_WriteLong(msg, delta_frame_num); // what we are delta'ing from
	Net_WriteByte(msg, client->suppress_count); // rate dropped packets
	client->suppress_count = 0;

	// send over the area bits
	Net_WriteByte(msg, frame->area_bytes);
	Net_WriteData(msg, frame->area_bits, frame->area_bytes);

	// delta encode the player state
	Sv_WritePlayerState(delta_frame, frame, msg);

	// delta encode the entities
	Sv_WriteEntities(delta_frame, frame, msg);
}
示例#15
0
文件: cl_main.c 项目: chrisnew/quetoo
/*
 * @brief Client implementation of Cmd_ForwardToServer. Any commands not recognized
 * locally by the client will be sent to the server. Some will undergo parameter
 * expansion so that players can use macros for locations, weapons, etc.
 */
static void Cl_ForwardCmdToServer(void) {

	if (cls.state <= CL_DISCONNECTED) {
		Com_Print("%s: Not connected\n", Cmd_Argv(0));
		return;
	}

	const char *cmd = Cmd_Argv(0);
	const char *args = Cmd_Args();

	Net_WriteByte(&cls.net_chan.message, CL_CMD_STRING);
	Net_WriteString(&cls.net_chan.message, va("%s %s", cmd, args));

	//Com_Debug("Forwarding '%s %s'\n", cmd, args);
}
示例#16
0
static void ShoveChatStr (const char *str, BYTE who)
{
	FString substBuff;

	if (str[0] == '/' &&
		(str[1] == 'm' || str[1] == 'M') &&
		(str[2] == 'e' || str[2] == 'E'))
	{ // This is a /me message
		str += 3;
		who |= 2;
	}

	Net_WriteByte (DEM_SAY);
	Net_WriteByte (who);

	if (!chat_substitution || !DoSubstitution (substBuff, str))
	{
		Net_WriteString (str);
	}
	else
	{
		Net_WriteString (substBuff);
	}
}
示例#17
0
文件: cl_cmd.c 项目: jdolan/quetoo
/**
 * @brief Writes the most recent movement command(s) using delta-compression if available.
 */
static void Cl_WriteMovementCommand(mem_buf_t *buf) {
	static cl_cmd_t null_cmd;

	Net_WriteByte(buf, CL_CMD_MOVE);

	if (!cl.frame.valid || (cls.demo_file && Fs_Tell(cls.demo_file) == 0)) {
		Net_WriteLong(buf, -1);
	} else {
		Net_WriteLong(buf, cl.frame.frame_num);
	}

	cl_cmd_t *from = &null_cmd, *to = &cl.cmds[(cls.net_chan.outgoing_sequence - 2) & CMD_MASK];
	Net_WriteDeltaMoveCmd(buf, &from->cmd, &to->cmd);

	from = to; to = &cl.cmds[(cls.net_chan.outgoing_sequence - 1) & CMD_MASK];
	Net_WriteDeltaMoveCmd(buf, &from->cmd, &to->cmd);

	from = to;  to = &cl.cmds[(cls.net_chan.outgoing_sequence) & CMD_MASK];
	Net_WriteDeltaMoveCmd(buf, &from->cmd, &to->cmd);
}
示例#18
0
void DAutosaver::Tick ()
{
	Net_WriteByte (DEM_CHECKAUTOSAVE);
	Destroy ();
}
示例#19
0
static bool Cht_Generic (cheatseq_t *cheat)
{
	Net_WriteByte (DEM_GENERICCHEAT);
	Net_WriteByte (cheat->Args[0]);
	return true;
}
示例#20
0
/*
 * @brief Tries to send an unreliable message to a connection, and handles the
 * transmission / retransmission of the reliable messages.
 *
 * A 0 size will still generate a packet and deal with the reliable messages.
 */
void Netchan_Transmit(net_chan_t *chan, byte *data, size_t len) {
	mem_buf_t send;
	byte send_buffer[MAX_MSG_SIZE];

	// check for message overflow
	if (chan->message.overflowed) {
		chan->fatal_error = true;
		Com_Print("%s:Outgoing message overflow\n", Net_NetaddrToString(&chan->remote_address));
		return;
	}

	const _Bool send_reliable = Netchan_NeedReliable(chan);

	if (!chan->reliable_size && chan->message.size) {
		memcpy(chan->reliable_buffer, chan->message_buffer, chan->message.size);
		chan->reliable_size = chan->message.size;
		chan->message.size = 0;
		chan->reliable_sequence ^= 1;
	}

	// write the packet header
	Mem_InitBuffer(&send, send_buffer, sizeof(send_buffer));

	const uint32_t w1 = (chan->outgoing_sequence & ~(1 << 31)) | (send_reliable << 31);
	const uint32_t w2 = (chan->incoming_sequence & ~(1 << 31)) | (chan->incoming_reliable_sequence
			<< 31);

	chan->outgoing_sequence++;
	chan->last_sent = quake2world.time;

	Net_WriteLong(&send, w1);
	Net_WriteLong(&send, w2);

	// send the qport if we are a client
	if (chan->source == NS_UDP_CLIENT)
		Net_WriteByte(&send, chan->qport);

	// copy the reliable message to the packet first
	if (send_reliable) {
		Mem_WriteBuffer(&send, chan->reliable_buffer, chan->reliable_size);
		chan->last_reliable_sequence = chan->outgoing_sequence;
	}

	// add the unreliable part if space is available
	if (send.max_size - send.size >= len)
		Mem_WriteBuffer(&send, data, len);
	else
		Com_Warn("Netchan_Transmit: dumped unreliable\n");

	// send the datagram
	Net_SendDatagram(chan->source, &chan->remote_address, send.data, send.size);

	if (net_showpackets->value) {
		if (send_reliable)
			Com_Print("Send %u bytes: s=%i reliable=%i ack=%i rack=%i\n", (uint32_t) send.size,
					chan->outgoing_sequence - 1, chan->reliable_sequence, chan->incoming_sequence,
					chan->incoming_reliable_sequence);
		else
			Com_Print("Send %u bytes : s=%i ack=%i rack=%i\n", (uint32_t) send.size,
					chan->outgoing_sequence - 1, chan->incoming_sequence,
					chan->incoming_reliable_sequence);
	}
}
示例#21
0
文件: b_game.cpp 项目: rsrsps/gzdoom
bool FCajunMaster::SpawnBot (const char *name, int color)
{
    //COLORS
    static const char colors[11][17] =
    {
        "\\color\\40 cf 00",	//0  = Green
        "\\color\\b0 b0 b0",	//1  = Gray
        "\\color\\50 50 60",	//2  = Indigo
        "\\color\\8f 00 00",	//3  = Deep Red
        "\\color\\ff ff ff",	//4  = White
        "\\color\\ff af 3f",	//5  = Bright Brown
        "\\color\\bf 00 00",	//6  = Red
        "\\color\\00 00 ff",	//7  = Blue
        "\\color\\00 00 7f",	//8  = Dark Blue
        "\\color\\ff ff 00",	//9  = Yellow
        "\\color\\cf df 90"		//10 = Bleached Bone
    };

    botinfo_t *thebot = botinfo;
    int botshift = 0;

    if (name)
    {
        // Check if exist or already in the game.
        while (thebot && stricmp (name, thebot->name))
        {
            botshift++;
            thebot = thebot->next;
        }

        if (thebot == NULL)
        {
            Printf ("couldn't find %s in %s\n", name, BOTFILENAME);
            return false;
        }
        else if (thebot->inuse == BOTINUSE_Waiting)
        {
            return false;
        }
        else if (thebot->inuse == BOTINUSE_Yes)
        {
            Printf ("%s is already in the thick\n", name);
            return false;
        }
    }
    else
    {
        //Spawn a random bot from bots.cfg if no name given.
        TArray<botinfo_t *> BotInfoAvailable;

        while (thebot)
        {
            if (thebot->inuse == BOTINUSE_No)
                BotInfoAvailable.Push (thebot);

            thebot = thebot->next;
        }

        if (BotInfoAvailable.Size () == 0)
        {
            Printf ("Couldn't spawn bot; no bot left in %s\n", BOTFILENAME);
            return false;
        }

        thebot = BotInfoAvailable[pr_botspawn() % BotInfoAvailable.Size ()];

        botinfo_t *thebot2 = botinfo;
        while (thebot2)
        {
            if (thebot == thebot2)
                break;

            botshift++;
            thebot2 = thebot2->next;
        }
    }

    thebot->inuse = BOTINUSE_Waiting;

    Net_WriteByte (DEM_ADDBOT);
    Net_WriteByte (botshift);
    {
        //Set color.
        char concat[512];
        strcpy (concat, thebot->info);
        if (color == NOCOLOR && bot_next_color < NOCOLOR && bot_next_color >= 0)
        {
            strcat (concat, colors[bot_next_color]);
        }
        if (TeamLibrary.IsValidTeam (thebot->lastteam))
        {   // Keep the bot on the same team when switching levels
            mysnprintf (concat + strlen(concat), countof(concat) - strlen(concat),
                        "\\team\\%d\n", thebot->lastteam);
        }
        Net_WriteString (concat);
    }
    Net_WriteByte(thebot->skill.aiming);
    Net_WriteByte(thebot->skill.perfection);
    Net_WriteByte(thebot->skill.reaction);
    Net_WriteByte(thebot->skill.isp);

    return true;
}
示例#22
0
bool FCajunMaster::SpawnBot (const char *name, int color)
{
	int playernumber;

	//COLORS
	static const char colors[11][17] =
	{
		"\\color\\40 cf 00",	//0  = Green
		"\\color\\b0 b0 b0",	//1  = Gray
		"\\color\\50 50 60",	//2  = Indigo
		"\\color\\8f 00 00",	//3  = Deep Red
		"\\color\\ff ff ff",	//4  = White
		"\\color\\ff af 3f",	//5  = Bright Brown
		"\\color\\bf 00 00",	//6  = Red
		"\\color\\00 00 ff",	//7  = Blue
		"\\color\\00 00 7f",	//8  = Dark Blue
		"\\color\\ff ff 00",	//9  = Yellow
		"\\color\\cf df 90"		//10 = Bleached Bone
	};

	for (playernumber = 0; playernumber < MAXPLAYERS; playernumber++)
	{
		if (!playeringame[playernumber] && !waitingforspawn[playernumber])
		{
			break;
		}
	}

	if (playernumber == MAXPLAYERS)
	{
		Printf ("The maximum of %d players/bots has been reached\n", MAXPLAYERS);
		return false;
	}

	botinfo_t *thebot;

	if (name)
	{
		thebot = botinfo;

		// Check if exist or already in the game.
		while (thebot && stricmp (name, thebot->name))
			thebot = thebot->next;

		if (thebot == NULL)
		{
   		 	Printf ("couldn't find %s in %s\n", name, BOTFILENAME);
			return false;
		}
		else if (thebot->inuse)
		{
   		 	Printf ("%s is already in the thick\n", name);
			return false;
		}
	}
	else if (botnum < loaded_bots)
	{
		bool vacant = false;  //Spawn a random bot from bots.cfg if no name given.
		while (!vacant)
		{
			int rnum = (pr_botspawn() % loaded_bots);
			thebot = botinfo;
			while (rnum)
				--rnum, thebot = thebot->next;
			if (!thebot->inuse)
				vacant = true;
		}
	}
	else
	{
		Printf ("Couldn't spawn bot; no bot left in %s\n", BOTFILENAME);
		return false;
	}

	waitingforspawn[playernumber] = true;

	Net_WriteByte (DEM_ADDBOT);
	Net_WriteByte (playernumber);
	{
		//Set color.
		char concat[512];
		strcpy (concat, thebot->info);
		if (color == NOCOLOR && bot_next_color < NOCOLOR && bot_next_color >= 0)
		{
			strcat (concat, colors[bot_next_color]);
		}
		if (TeamLibrary.IsValidTeam (thebot->lastteam))
		{ // Keep the bot on the same team when switching levels
			mysnprintf (concat + strlen(concat), countof(concat) - strlen(concat),
				"\\team\\%d\n", thebot->lastteam);
		}
		Net_WriteString (concat);
	}

	players[playernumber].skill = thebot->skill;

	thebot->inuse = true;

	//Increment this.
	botnum++;

	return true;
}
示例#23
0
文件: cl_demo.c 项目: jdolan/quetoo
/**
 * @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
}
示例#24
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;
}