Esempio n. 1
0
static void ackClient(IPaddress clientAddr) {
  IPXHeader regHeader;
  UDPpacket regPacket;
  Bits result;

  SDLNet_Write16(0xffff, regHeader.checkSum);
  SDLNet_Write16(sizeof(regHeader), regHeader.length);
	
  SDLNet_Write32(0, regHeader.dest.network);
  PackIP(clientAddr, &regHeader.dest.addr.byIP);
  SDLNet_Write16(0x2, regHeader.dest.socket);

  SDLNet_Write32(1, regHeader.src.network);
  PackIP(ipxServerIp, &regHeader.src.addr.byIP);
  SDLNet_Write16(0x2, regHeader.src.socket);
  regHeader.transControl = 0;

  regPacket.data = (Uint8 *)&regHeader;
  regPacket.len = sizeof(regHeader);
  regPacket.maxlen = sizeof(regHeader);
  regPacket.address = clientAddr;
  // Send registration string to client.  If client doesn't get this, client will not be registered
  result = SDLNet_UDP_Send(ipxServerSocket,-1,&regPacket);

}
Esempio n. 2
0
static bool TryRecvSynAndSendSynAck(NetInput *n)
{
	// listen for SYN
	if (!NetInputRecvNonBlocking(&n->channel, TryParseSyn, &n->channel))
	{
		return false;
	}

	// Send SYN-ACK
	bool res = false;
	UDPpacket packet = NetInputNewPacket(&n->channel, sizeof(NetMsgSynAck));
	NetMsgSynAck *packetSyn = (NetMsgSynAck *)packet.data;
	n->channel.seq = rand() & (Uint16)-1;
	SDLNet_Write16(n->channel.seq, &packetSyn->seq);
	SDLNet_Write16(n->channel.ack, &packetSyn->ack);
	if (!NetInputTrySendPacket(&n->channel, packet))
	{
		goto bail;
	}
	n->channel.seq++;
	res = true;

bail:
	CFREE(packet.data);
	return res;
}
Esempio n. 3
0
void ClientConnection::send_scroll()
{
	int x = get_x();
	int y = get_y();
	int dx = World::difference(x, old_x);
	int dy = World::difference(y, old_y);
	old_x = x;
	old_y = y;

	for (typeof(client_entities.begin()) it = client_entities.begin(); it != client_entities.end(); ++it)
	{
		it->second.x -= dx;
		it->second.y -= dy;
	}

	static const int len = 5;
	DataPacket packet =
	{ len, new char[len] };

	packet.data[0] = 'S';
	SDLNet_Write16(dx, packet.data + 1);
	SDLNet_Write16(dy, packet.data + 3);

	SDL_LockMutex(send_mutex);
	data_to_send.push_back(packet);
	SDL_UnlockMutex(send_mutex);
}
Esempio n. 4
0
void actWallBuilder(Entity *my) {
	int c;

	if( !my->skill[28] )
		return;

	// received on signal
	if( my->skill[28] == 2) {
		playSoundEntity( my, 182, 64 );
		Uint16 x = std::min<Uint16>(std::max(0.0,my->x/16),map.width-1);
		Uint16 y = std::min<Uint16>(std::max(0.0,my->y/16),map.height-1);
		map.tiles[OBSTACLELAYER+y*MAPLAYERS+x*MAPLAYERS*map.height] = map.tiles[y*MAPLAYERS+x*MAPLAYERS*map.height];
		if( multiplayer==SERVER ) {
			for( c=0; c<MAXPLAYERS; c++ ) {
				if( client_disconnected[c]==TRUE )
					continue;
				strcpy((char *)net_packet->data,"WALC");
				SDLNet_Write16(x,&net_packet->data[4]);
				SDLNet_Write16(y,&net_packet->data[6]);
				net_packet->address.host = net_clients[c-1].host;
				net_packet->address.port = net_clients[c-1].port;
				net_packet->len = 8;
				sendPacketSafe(net_sock, -1, net_packet, c-1);
			}
		}
		list_RemoveNode(my->mynode);
	}
}
Esempio n. 5
0
bool Replay::StartRecording(const std::string& game_mode_name,
                            const std::string& game_mode,
                            const std::string& game_mode_objects)
{
  MSG_DEBUG("replay", "Asked to start recording\n");
  ASSERT(is_recorder && replay_state == PAUSED_RECORD);

  replay_state = RECORDING;
  start_time   = 0;
  old_time     = 0;

  // Write game mode rules at start of data
  uint total_size = game_mode_name.size() + game_mode.size()
                  + game_mode_objects.size() + 3*2;
  ChangeBufsize(total_size+30000); // twice the needed size

  Uint16 size = game_mode_name.size();
  SDLNet_Write16(size, ptr); ptr += 2;
  memcpy(ptr, game_mode_name.c_str(), size); ptr += size;

  size = game_mode.size();
  SDLNet_Write16(size, ptr); ptr += 2;
  memcpy(ptr, game_mode.c_str(), size); ptr += size;

  size = game_mode_objects.size();
  SDLNet_Write16(size, ptr); ptr += 2;
  memcpy(ptr, game_mode_objects.c_str(), size); ptr += size;

  MSG_DEBUG("replay", "Wrote game mode on %u bytes\n", total_size);
  count = 0;

  return true;
}
Esempio n. 6
0
// send acknowledgement packet
int network_acknowledge( Uint16 sync )
{
	SDLNet_Write16(PACKET_ACKNOWLEDGE, &packet_out_temp->data[0]);
	SDLNet_Write16(sync,               &packet_out_temp->data[2]);
	network_send_no_ack(4);

	return 0;
}
Esempio n. 7
0
// prepare new packet for sending
void network_prepare( Uint16 type )
{
#ifdef __BLACKBERRY__
#else
	SDLNet_Write16(type,          &packet_out_temp->data[0]);
	SDLNet_Write16(last_out_sync, &packet_out_temp->data[2]);
#endif
}
Esempio n. 8
0
bool PacketManager::Send(TCPsocket socket, Uint16 packetID){
  if(socket == NULL)return false;
  if((buffer == NULL)||(bufferSize < 4))if(!Allocate(4))return false;
  if(bufferSize < dataLength)return false;
  Uint16 len = dataLength - 4;
  SDLNet_Write16(packetID, buffer);
  SDLNet_Write16(len, buffer + sizeof(Uint16));
  lastPackID = packetID;
  return ((Uint32)SDLNet_TCP_Send(socket, buffer, dataLength) == dataLength);
}
Esempio n. 9
0
// prepare new state for sending
void network_state_prepare( void )
{
	if (packet_state_out[0])
	{
		fprintf(stderr, "warning: state packet overwritten (previous packet remains unsent)\n");
	} else {
		packet_state_out[0] = SDLNet_AllocPacket(NET_PACKET_SIZE);
		packet_state_out[0]->len = 28;
	}
	
	SDLNet_Write16(PACKET_STATE, &packet_state_out[0]->data[0]);
	SDLNet_Write16(last_state_out_sync, &packet_state_out[0]->data[2]);
	memset(&packet_state_out[0]->data[4], 0, 28 - 4);
}
Esempio n. 10
0
void NetInputClientConnect(NetInputClient *n, Uint32 host)
{
	if (!NetInputChannelTryOpen(&n->channel, 0, host))
	{
		printf("Failed to open channel\n");
		return;
	}
	n->channel.otherPort = NET_INPUT_UDP_PORT;

	// Handshake

	// Send SYN
	UDPpacket packet = NetInputNewPacket(&n->channel, sizeof(NetMsgSyn));
	NetMsgSyn *packetSyn = (NetMsgSyn *)packet.data;
	n->channel.seq = rand() & (Uint16)-1;
	SDLNet_Write16(n->channel.seq, &packetSyn->seq);
	if (!NetInputTrySendPacket(&n->channel, packet))
	{
		printf("Failed to send SYN\n");
		goto bail;
	}
	n->channel.seq++;

	// Wait for SYN-ACK
	// TODO: don't wait forever
	n->channel.state = CHANNEL_STATE_WAIT_HANDSHAKE;
	while (!NetInputRecvBlocking(&n->channel, TryParseSynAck, &n->channel))
	{
		// Spin
	}

	// Send ACK
	CFREE(packet.data);
	packet = NetInputNewPacket(&n->channel, sizeof(NetMsgAck));
	NetMsgAck *packetAck = (NetMsgAck *)packet.data;
	SDLNet_Write16(n->channel.ack, &packetAck->ack);
	if (!NetInputTrySendPacket(&n->channel, packet))
	{
		printf("Failed to send ACK\n");
		goto bail;
	}

	n->channel.state = CHANNEL_STATE_CONNECTED;
	return;

bail:
	CFREE(packet.data);
}
Esempio n. 11
0
/* Sends messages to remove old entities which were not sent since last call
 */
void ClientConnection::send_entity_removals()
{
	std::vector<Uint32> old_entities;

	for (typeof(client_entities.begin()) it = client_entities.begin(); it != client_entities.end(); ++it)
	{
		if (it->second.old)
		{
			// This entity is old and should be removed
			old_entities.push_back(it->first);

			static const int len = 3;
			DataPacket packet =
			{ len, new char[len] };

			packet.data[0] = 'r';
			SDLNet_Write16(it->second.id, packet.data + 1);

			SDL_LockMutex(send_mutex);
			data_to_send.push_back(packet);
			SDL_UnlockMutex(send_mutex);

			continue;
		}
		else
		{
			// Next time this will be old if it hasn't been seen again
			it->second.old = true;
		}
	}

	// Forget the old entities
	for (typeof(old_entities.begin()) it = old_entities.begin(); it != old_entities.end(); ++it)
		client_entities.erase(*it);
}
Esempio n. 12
0
// send state packet, xor packet if applicable
int network_state_send( void )
{
#ifdef __BLACKBERRY__
#else
	if (!SDLNet_UDP_Send(socket, 0, packet_state_out[0]))
	{
		printf("SDLNet_UDP_Send: %s\n", SDL_GetError());
		return -1;
	}

	// send xor of last network_delay packets
	if (network_delay > 1 && (last_state_out_sync + 1) % network_delay == 0 && packet_state_out[network_delay - 1] != NULL)
	{
		packet_copy(packet_temp, packet_state_out[0]);
		SDLNet_Write16(PACKET_STATE_XOR, &packet_temp->data[0]);
		for (int i = 1; i < network_delay; i++)
			for (int j = 4; j < packet_temp->len; j++)
				packet_temp->data[j] ^= packet_state_out[i]->data[j];

		if (!SDLNet_UDP_Send(socket, 0, packet_temp))
		{
			printf("SDLNet_UDP_Send: %s\n", SDL_GetError());
			return -1;
		}
	}

	packets_shift_down(packet_state_out, NET_PACKET_QUEUE);

	last_state_out_sync++;
#endif
	return 0;
}
Esempio n. 13
0
bool PacketManager::Write16(Uint16 val){
  Uint32 size = dataPos + sizeof(Uint16);
  if(bufferSize < size)if(!Allocate(size))return false;
  SDLNet_Write16(val, buffer + dataPos);
  dataPos += sizeof(Uint16);
  if(dataLength < dataPos)dataLength = dataPos;
  return true;
}
Esempio n. 14
0
/* Sends an entity with coordinates relative to our entity
 */
void ClientConnection::send_hud()
{
	std::vector<Entity::HudIcon> icons = entity->get_hud_icons();

	int i = 0;
	for (typeof(icons.begin()) it = icons.begin(); it != icons.end(); ++it)
	{
		static const int len = 15;
		DataPacket packet =
		{ len, new char[len] };

		packet.data[0] = 'h';
		SDLNet_Write16(i++, packet.data + 1); // id
		SDLNet_Write16(it->x, packet.data + 3); // x
		SDLNet_Write16(it->y, packet.data + 5); // y
		SDLNet_Write16(0, packet.data + 7); // z
		SDLNet_Write16(it->width, packet.data + 9); // width
		SDLNet_Write16(it->height, packet.data + 11); // height
		SDLNet_Write16(it->tex, packet.data + 13); // texture

		SDL_LockMutex(send_mutex);
		data_to_send.push_back(packet);
		SDL_UnlockMutex(send_mutex);
	}
}
Esempio n. 15
0
UDPpacket NetInputNewPacket(NetInputChannel *n, size_t len)
{
	UDPpacket packet;
	SDLNet_Write32(n->otherHost, &packet.address.host);
	SDLNet_Write16(n->otherPort, &packet.address.port);
	packet.maxlen = packet.len = len;
	CMALLOC(packet.data, len);
	return packet;
}
    void splitForSend(const INFPacket& src, PacketList& destList){
        //clear out queue
        destList.clear();

        //segments
        std::vector<Uint8> tmp;
        tmp.reserve(maxSendSize);

        size_t dataIndex = 0;
        Uint16 len = 0;
        Uint8 len_buff[2];
        unsigned int remaining = 0;
        while( dataIndex < src.data.size() ){
            //  Packet header
            if( dataIndex == 0 ){
                tmp.push_back(ControlByte::START.getVal() );
            } else {
                tmp.push_back(ControlByte::CONTINUE.getVal() );
            }

            //  data
            //minus 2 from maxSendSize for the START/END
            //minus 2 again, becuase 2 bytes are used to store the length
            //  of this segment

            //how much of the input data is left to be packed
            remaining = src.data.size() - dataIndex;
            //the length of the next segment
            if( remaining > (maxSendSize-4) ){
                len = (maxSendSize-4);
            } else {
                len = remaining;
            }
            //insert the length of this segment
            SDLNet_Write16(len, len_buff);
            tmp.push_back( len_buff[0] );
            tmp.push_back( len_buff[1] );

            //write the actual data
            for(int i = 0; i < len; ++i){
                tmp.push_back( src.data[dataIndex] );
                ++dataIndex;
            }

            //  Packet footer
            if( dataIndex == src.getLength() ){
                tmp.push_back(ControlByte::END.getVal() );
            } else {
                tmp.push_back(ControlByte::WAIT_MORE.getVal() );
            }

            //  Put the packet on the list
            destList.push_back(tmp);
            tmp.clear();
        }
    }
Esempio n. 17
0
void Framework::sendPacket(Peer* receiver, char* data, int size)
{
	unsigned short shorty;
	// we need the port number in network byte order, otherwise it would be the wrong port
	SDLNet_Write16(sendport, &shorty);
	IPaddress ip = {
		receiver->host,
		shorty
	};
	NET2_UDPSend(&ip, data, size);
}
Esempio n. 18
0
void
sendshort(TCPsocket sock, Uint16 i)
{
   Uint16 cmd;
   int bytes_sent;
   SDLNet_Write16(i, &cmd);
   if ((bytes_sent = SDLNet_TCP_Send(sock, &cmd, sizeof(cmd))) != sizeof(cmd))
   {
      fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
   }
}
Esempio n. 19
0
// The Replay packet header:
// u32: time (ms => 2^16=65s => u16 sufficient)
// Packet is directly an action:
//   . u32 => type
//   . u32 => length
//   . data
void Replay::StoreAction(const Action* a)
{
  uint          size;

  ASSERT(is_recorder && replay_state==RECORDING);

  Action::Action_t type = a->GetType();
  if ((type!=Action::ACTION_CHAT_INGAME_MESSAGE && a->IsFrameLess()) ||
      type == Action::ACTION_NETWORK_PING ||
      type == Action::ACTION_NETWORK_VERIFY_RANDOM_SYNC ||
      type == Action::ACTION_TIME_VERIFY_SYNC ||
      type == Action::ACTION_RULES_SET_GAME_MODE)
    return;

  // Special case to convert into local packet
  if (type == Action::ACTION_REQUEST_BONUS_BOX_DROP) {
    // The timestamp shouldn't have moved
    Action a(Action::ACTION_DROP_BONUS_BOX);
    StoreAction(&a);
    return;
  }

  size = a->GetSize();
  // Enlarge buffer if it can't contain max packet size
  if (MemUsed() > bufsize - size + 2)
    ChangeBufsize(bufsize+30000);

  if (type != Action::ACTION_GAME_CALCULATE_FRAME) {
    if (count) {
      count--;
      MSG_DEBUG("replay", "Calculate frame repeated %u\n", count);
      // 16 bits is sufficient, around 22 minutes without other actions
      SDLNet_Write16(count, ptr); ptr += 2;
    }
    MSG_DEBUG("replay", "Storing action %s: type=%i length=%i\n",
              ActionHandler::GetActionName(type).c_str(), type, size);
    a->Write((char*)ptr);
    ptr += size;
    count = 0;
  } else {
    if (!count) {
      // Packet body
      a->Write((char*)ptr);
      ptr += size;
    }
    count++;
  }

  // Check time
  if (start_time == 0)
    start_time = GameTime::GetInstance()->Read();
  else
    old_time = GameTime::GetInstance()->Read();
}
Esempio n. 20
0
unsigned short host_to_net16(unsigned int value)
{
  union
  {
    unsigned short s;
    char b[2];
  } data;

  SDLNet_Write16(value, data.b);

  return data.s;
}
Esempio n. 21
0
  TCP_Listener::TCP_Listener(const Uint16 &port)
    : sock(0)
  {
    get_Net();

    IPaddress ip = {0, 0};
    SDLNet_Write16(port, &ip.port);

    sock = SDLNet_TCP_Open(&ip);
    if(!sock)
      throw TCP_Socket_Init_Failure();
  }
Esempio n. 22
0
bool PacketManager::WriteChunk(const Uint8 *chunk, Uint16 length){
  if(chunk == NULL)length = 0;
  Uint32 size = dataPos + length + sizeof(Uint16);
  if(bufferSize < size)if(!Allocate(size))return false;
  SDLNet_Write16(length, buffer + dataPos);
  dataPos += sizeof(Uint16);
  for(size_t n = 0; n<length; n++){
    buffer[dataPos] = chunk[n];
    dataPos++;
  }
  if(dataLength < dataPos)dataLength = dataPos;
  return true;
}
Esempio n. 23
0
    void Client::send(Uint16 number)
    {
        char data[2];
        const int len = sizeof(data);
        SDLNet_Write16(number, (Uint16 *)data); // to network byte order

        int result = SDLNet_TCP_Send(sock, data, len);
        if (result < len)
        {
            printf("%s:%d SDLNet_TCP_Send: %s\n", __FILE__, __LINE__, SDLNet_GetError());
            // It may be good to disconnect sock because it is likely invalid now.
        }
    }
TCP_NetServer::TCP_NetServer(ushort port) : TCP_NetBase(),
		remoteMutex(SDL_CreateMutex())
{
	memset(&remote, 0, sizeof(remote));

	IPaddress addr;
	addr.host = INADDR_ANY;
	SDLNet_Write16(port, &addr.port);
	mySocket = SDLNet_TCP_Open(&addr);
	if (mySocket == NULL) {
		NETMSG("Failed to initialize TCP server socket");
		setErrorFlag();
		return;
	}
}
Esempio n. 25
0
void Action::Push(const std::string& m_val)
{
  // First, write the size of the string (assume len<65536):
  uint16_t size = m_val.size();
  if (MemWriteLeft() < uint(size+2))
    Increase(size+2);
  SDLNet_Write16(size, m_write); m_write += 2;

  // Then write the actual string
  if (size) {
    memcpy(m_write, m_val.c_str(), size);
    m_write += size;
  }
  m_header.len += size+2;
}
void BomberNetClient::sendKeystate() {
	char data[38];
	memset(data, 0, sizeof data);
	SDLNet_Write32(requestNumber, data);
	data[4] = 0x02;
	data[5] = GameConfig::Instance().getNbPlayerOfClient();
	int pos = 6;
	for (int i = 0; i < GameConfig::Instance().getNbPlayerOfClient(); i++) {
		SDLNet_Write16(keystate[i], data + pos);
		pos += 2;
	}
	data[pos] = '\0';
	if (SDLNet_CheckSockets(BomberNetClient::socketset, 0) >= 0) {
		SDLNet_TCP_Send(BomberNetClient::tcpsock, &data, pos);
		requestNumber++;
	}
}
Esempio n. 27
0
// attempt to punch through firewall by firing off UDP packets at the opponent
// exchange game information
int network_connect( void )
{
#ifdef __BLACKBERRY__
#else
	SDLNet_ResolveHost(&ip, network_opponent_host, network_opponent_port);

	SDLNet_UDP_Bind(socket, 0, &ip);

	Uint16 episodes = 0, episodes_local = 0;
	assert(EPISODE_MAX <= 16);
	for (int i = EPISODE_MAX - 1; i >= 0; i--)
	{
		episodes <<= 1;
		episodes |= (episodeAvail[i] != 0);
	}
	episodes_local = episodes;

	assert(NET_PACKET_SIZE - 12 >= 20 + 1);
	if (strlen(network_player_name) > 20)
		network_player_name[20] = '\0';

connect_reset:
	network_prepare(PACKET_CONNECT);
	SDLNet_Write16(NET_VERSION, &packet_out_temp->data[4]);
	SDLNet_Write16(network_delay,   &packet_out_temp->data[6]);
	SDLNet_Write16(episodes_local,  &packet_out_temp->data[8]);
	SDLNet_Write16(thisPlayerNum,   &packet_out_temp->data[10]);
	strcpy((char *)&packet_out_temp->data[12], network_player_name);
	network_send(12 + strlen(network_player_name) + 1); // PACKET_CONNECT

	// until opponent sends connect packet
	while (true)
	{
		push_joysticks_as_keyboard();
		service_SDL_events(false);

		if (newkey && lastkey_sym == SDLK_ESCAPE)
			network_tyrian_halt(0, false);

		// never timeout
		last_in_tick = SDL_GetTicks();

		if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_CONNECT)
			break;

		network_update();
		network_check();

		SDL_Delay(16);
	}

connect_again:
	if (SDLNet_Read16(&packet_in[0]->data[4]) != NET_VERSION)
	{
		fprintf(stderr, "error: network version did not match opponent's\n");
		network_tyrian_halt(4, true);
	}
	if (SDLNet_Read16(&packet_in[0]->data[6]) != network_delay)
	{
		fprintf(stderr, "error: network delay did not match opponent's\n");
		network_tyrian_halt(5, true);
	}
	if (SDLNet_Read16(&packet_in[0]->data[10]) == thisPlayerNum)
	{
		fprintf(stderr, "error: player number conflicts with opponent's\n");
		network_tyrian_halt(6, true);
	}

	episodes = SDLNet_Read16(&packet_in[0]->data[8]);
	for (int i = 0; i < EPISODE_MAX; i++) {
		episodeAvail[i] &= (episodes & 1);
		episodes >>= 1;
	}

	network_opponent_name = malloc(packet_in[0]->len - 12 + 1);
	strcpy(network_opponent_name, (char *)&packet_in[0]->data[12]);

	network_update();

	// until opponent has acknowledged
	while (!network_is_sync())
	{
		service_SDL_events(false);

		// got a duplicate packet; process it again (but why?)
		if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_CONNECT)
			goto connect_again;

		network_check();

		// maybe opponent didn't get our packet
		if (SDL_GetTicks() - last_out_tick > NET_RETRY)
			goto connect_reset;

		SDL_Delay(16);
	}

	// send another packet since sometimes the network syncs without both connect packets exchanged
	// there should be a better way to handle this
	network_prepare(PACKET_CONNECT);
	SDLNet_Write16(NET_VERSION, &packet_out_temp->data[4]);
	SDLNet_Write16(network_delay,   &packet_out_temp->data[6]);
	SDLNet_Write16(episodes_local,  &packet_out_temp->data[8]);
	SDLNet_Write16(thisPlayerNum,   &packet_out_temp->data[10]);
	strcpy((char *)&packet_out_temp->data[12], network_player_name);
	network_send(12 + strlen(network_player_name) + 1); // PACKET_CONNECT

	connected = true;
#endif

	return 0;
}
Esempio n. 28
0
void ClientConnection::send_entity(Uint32 eid, const Entity *ent)
{
	DataEntity dent = {
			eid, ent->world->difference(ent->get_x(), get_x()) * 64 + ent->get_offset_x(),
			ent->world->difference(ent->get_y(), get_y()) * 64 + ent->get_offset_y(),
			ent->get_z() + ent->get_offset_z(),
			ent->get_w(),
			ent->get_h(),
			ent->get_tex(),
			false
	};

	// Check if the entity exists allready
	typeof(client_entities.begin()) it = client_entities.find(eid);

	if (it != client_entities.end())
	{
		DataEntity &itde = it->second;

		// Check bounds
		if ((dent.x + dent.w < -1024 || dent.x > 1024 || dent.y + dent.h < -1024
				|| dent.y > 1024)
				&& (itde.x + itde.w < -1024 || itde.x > 1024
						|| itde.y + itde.h < -1024 || itde.y > 1024))
			return;
		// FIXME: If the entity moves across a corner, it will never be sent

		// If it exists send only modifications
		bool move = itde.x != dent.x || itde.y != dent.y || itde.z != dent.z;
		bool resize = itde.w != dent.w || itde.h != dent.h;
		bool change_tex = itde.tex != dent.tex;

		itde = dent;

		if (!move && !resize && !change_tex)
			return; // Nothing has changed, send nothing

		if (move && !resize && !change_tex)
		{
			// Only move the entity
			static const int len = 9;
			DataPacket packet =
			{ len, new char[len] };

			packet.data[0] = 'M';
			SDLNet_Write16(dent.id, packet.data + 1);
			SDLNet_Write16(dent.x, packet.data + 3);
			SDLNet_Write16(dent.y, packet.data + 5);
			SDLNet_Write16(dent.z, packet.data + 7);

			SDL_LockMutex(send_mutex);
			data_to_send.push_back(packet);
			SDL_UnlockMutex(send_mutex);
			return;
		}

		if (!move && (resize || change_tex))
		{
			// Only send width height and texture
			static const int len = 9;
			DataPacket packet =
			{ len, new char[len] };

			packet.data[0] = 'i';
			SDLNet_Write16(dent.id, packet.data + 1);
			SDLNet_Write16(dent.w, packet.data + 3);
			SDLNet_Write16(dent.h, packet.data + 5);
			SDLNet_Write16(dent.tex, packet.data + 7);

			SDL_LockMutex(send_mutex);
			data_to_send.push_back(packet);
			SDL_UnlockMutex(send_mutex);
			return;
		}

		{
			// Otherwise send everything
			static const int len = 15;
			DataPacket packet =
			{ len, new char[len] };

			packet.data[0] = 'a';
			SDLNet_Write16(dent.id, packet.data + 1);
			SDLNet_Write16(dent.x, packet.data + 3);
			SDLNet_Write16(dent.y, packet.data + 5);
			SDLNet_Write16(dent.z, packet.data + 7);
			SDLNet_Write16(dent.w, packet.data + 9);
			SDLNet_Write16(dent.h, packet.data + 11);
			SDLNet_Write16(dent.tex, packet.data + 13);

			SDL_LockMutex(send_mutex);
			data_to_send.push_back(packet);
			SDL_UnlockMutex(send_mutex);
		}
	}
	else
	{
		// If it's new, send it as a new entity
		// Check bounds
		if (dent.x + dent.w < -1024 || dent.x > 1024 || dent.y + dent.h < -1024 || dent.y > 1024)
			return;

		// Store it
		client_entities[eid] = dent;

		static const int len = 15;
		DataPacket packet =
		{ len, new char[len] };

		packet.data[0] = 'a';
		SDLNet_Write16(dent.id, packet.data + 1);
		SDLNet_Write16(dent.x, packet.data + 3);
		SDLNet_Write16(dent.y, packet.data + 5);
		SDLNet_Write16(dent.z, packet.data + 7);
		SDLNet_Write16(dent.w, packet.data + 9);
		SDLNet_Write16(dent.h, packet.data + 11);
		SDLNet_Write16(dent.tex, packet.data + 13);

		SDL_LockMutex(send_mutex);
		data_to_send.push_back(packet);
		SDL_UnlockMutex(send_mutex);
	}
}
Esempio n. 29
0
// poll for new packets received, check that connection is alive, resend queued packets if necessary
int network_check( void )
{
#ifdef __BLACKBERRY__
#else
	if (!net_initialized)
		return -1;

	if (connected)
	{
		// timeout
		if (!network_is_alive())
		{
			if (!quit)
				network_tyrian_halt(2, false);
		}

		// keep-alive
		static Uint32 keep_alive_tick = 0;
		if (SDL_GetTicks() - keep_alive_tick > NET_KEEP_ALIVE)
		{
			network_prepare(PACKET_KEEP_ALIVE);
			network_send_no_ack(4);

			keep_alive_tick = SDL_GetTicks();
		}
	}

	// retry
	if (packet_out[0] && SDL_GetTicks() - last_out_tick > NET_RETRY)
	{
		if (!SDLNet_UDP_Send(socket, 0, packet_out[0]))
		{
			printf("SDLNet_UDP_Send: %s\n", SDL_GetError());
			return -1;
		}

		last_out_tick = SDL_GetTicks();
	}

	switch (SDLNet_UDP_Recv(socket, packet_temp))
	{
		case -1:
			printf("SDLNet_UDP_Recv: %s\n", SDL_GetError());
			return -1;
			break;
		case 0:
			break;
		default:
			if (packet_temp->channel == 0 && packet_temp->len >= 4)
			{
				switch (SDLNet_Read16(&packet_temp->data[0]))
				{
					case PACKET_ACKNOWLEDGE:
						if ((Uint16)(SDLNet_Read16(&packet_temp->data[2]) - last_ack_sync) < NET_PACKET_QUEUE)
						{
							last_ack_sync = SDLNet_Read16(&packet_temp->data[2]);
						}

						{
							Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - queue_out_sync;
							if (i < NET_PACKET_QUEUE)
							{
								if (packet_out[i])
								{
									SDLNet_FreePacket(packet_out[i]);
									packet_out[i] = NULL;
								}
							}
						}

						// remove acknowledged packets from queue
						while (packet_out[0] == NULL && (Uint16)(last_ack_sync - queue_out_sync) < NET_PACKET_QUEUE)
						{
							packets_shift_up(packet_out, NET_PACKET_QUEUE);

							queue_out_sync++;
						}

						last_in_tick = SDL_GetTicks();
						break;

					case PACKET_CONNECT:
						queue_in_sync = SDLNet_Read16(&packet_temp->data[2]);

						for (int i = 0; i < NET_PACKET_QUEUE; i++)
						{
							if (packet_in[i])
							{
								SDLNet_FreePacket(packet_in[i]);
								packet_in[i] = NULL;
							}
						}

					case PACKET_DETAILS:
					case PACKET_WAITING:
					case PACKET_BUSY:
					case PACKET_GAME_QUIT:
					case PACKET_GAME_PAUSE:
					case PACKET_GAME_MENU:
						{
							Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - queue_in_sync;
							if (i < NET_PACKET_QUEUE)
							{
								if (packet_in[i] == NULL)
									packet_in[i] = SDLNet_AllocPacket(NET_PACKET_SIZE);
								packet_copy(packet_in[i], packet_temp);
							} else {
								// inbound packet queue overflow/underflow
								// under normal circumstances, this is okay
							}
						}

						network_acknowledge(SDLNet_Read16(&packet_temp->data[2]));

					case PACKET_KEEP_ALIVE:
						last_in_tick = SDL_GetTicks();
						break;

					case PACKET_QUIT:
						if (!quit)
						{
							network_prepare(PACKET_QUIT);
							network_send(4);  // PACKET_QUIT
						}

						network_acknowledge(SDLNet_Read16(&packet_temp->data[2]));

						if (!quit)
							network_tyrian_halt(1, true);
						break;

					case PACKET_STATE:
						// place packet in queue if within limits
						{
							Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - last_state_in_sync + 1;
							if (i < NET_PACKET_QUEUE)
							{
								if (packet_state_in[i] == NULL)
									packet_state_in[i] = SDLNet_AllocPacket(NET_PACKET_SIZE);
								packet_copy(packet_state_in[i], packet_temp);
							}
						}
						break;

					case PACKET_STATE_XOR:
						// place packet in queue if within limits
						{
							Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - last_state_in_sync + 1;
							if (i < NET_PACKET_QUEUE)
							{
								if (packet_state_in_xor[i] == NULL)
								{
									packet_state_in_xor[i] = SDLNet_AllocPacket(NET_PACKET_SIZE);
									packet_copy(packet_state_in_xor[i], packet_temp);
								} else if (SDLNet_Read16(&packet_state_in_xor[i]->data[0]) != PACKET_STATE_XOR) {
									for (int j = 4; j < packet_state_in_xor[i]->len; j++)
										packet_state_in_xor[i]->data[j] ^= packet_temp->data[j];
									SDLNet_Write16(PACKET_STATE_XOR, &packet_state_in_xor[i]->data[0]);
								}
							}
						}
						break;

					case PACKET_STATE_RESEND:
						// resend requested state packet if still available
						{
							Uint16 i = last_state_out_sync - SDLNet_Read16(&packet_temp->data[2]);
							if (i > 0 && i < NET_PACKET_QUEUE)
							{
								if (packet_state_out[i])
								{
									if (!SDLNet_UDP_Send(socket, 0, packet_state_out[i]))
									{
										printf("SDLNet_UDP_Send: %s\n", SDL_GetError());
										return -1;
									}
								}
							}
						}
						break;

					default:
						fprintf(stderr, "warning: bad packet %d received\n", SDLNet_Read16(&packet_temp->data[0]));
						return 0;
						break;
				}

				return 1;
			}
			break;
	}
#endif
	return 0;
}
Esempio n. 30
0
// receive state packet, wait until received
bool network_state_update( void )
{
#ifdef __BLACKBERRY__
	return false;
#else
	if (network_state_is_reset())
	{
		return 0;
	} else {
		packets_shift_up(packet_state_in, NET_PACKET_QUEUE);

		packets_shift_up(packet_state_in_xor, NET_PACKET_QUEUE);

		last_state_in_sync++;

		// current xor packet index
		int x = network_delay - (last_state_in_sync - 1) % network_delay - 1;

		// loop until needed packet is available
		while (!packet_state_in[0])
		{
			// xor the packet from thin air, if possible
			if (packet_state_in_xor[x] && SDLNet_Read16(&packet_state_in_xor[x]->data[0]) == PACKET_STATE_XOR)
			{
				// check for all other required packets
				bool okay = true;
				for (int i = 1; i <= x; i++)
				{
					if (packet_state_in[i] == NULL)
					{
						okay = false;
						break;
					}
				}
				if (okay)
				{
					packet_state_in[0] = SDLNet_AllocPacket(NET_PACKET_SIZE);
					packet_copy(packet_state_in[0], packet_state_in_xor[x]);
					for (int i = 1; i <= x; i++)
						for (int j = 4; j < packet_state_in[0]->len; j++)
							packet_state_in[0]->data[j] ^= packet_state_in[i]->data[j];
					break;
				}
			}

			static Uint32 resend_tick = 0;
			if (SDL_GetTicks() - last_state_in_tick > NET_RESEND && SDL_GetTicks() - resend_tick > NET_RESEND)
			{
				SDLNet_Write16(PACKET_STATE_RESEND,    &packet_out_temp->data[0]);
				SDLNet_Write16(last_state_in_sync - 1, &packet_out_temp->data[2]);
				network_send_no_ack(4);  // PACKET_RESEND

				resend_tick = SDL_GetTicks();
			}

			if (network_check() == 0)
				SDL_Delay(1);
		}

		if (network_delay > 1)
		{
			// process the current in packet against the xor queue
			if (packet_state_in_xor[x] == NULL)
			{
				packet_state_in_xor[x] = SDLNet_AllocPacket(NET_PACKET_SIZE);
				packet_copy(packet_state_in_xor[x], packet_state_in[0]);
				packet_state_in_xor[x]->status = 0;
			} else {
				for (int j = 4; j < packet_state_in_xor[x]->len; j++)
					packet_state_in_xor[x]->data[j] ^= packet_state_in[0]->data[j];
			}
		}

		last_state_in_tick = SDL_GetTicks();
	}

	return 1;
#endif
}