// Spawns a player at a particular spawn point void _Server::SpawnPlayer(_Object *Player, NetworkIDType MapID, uint32_t EventType) { if(!ValidatePeer(Player->Peer) || !Player->Peer->CharacterID || !MapID) return; // Get map _Map *Map = MapManager->GetObject(MapID); // Load map if(!Map) { Map = MapManager->CreateWithID(MapID); Map->Clock = Clock; Map->Server = this; Map->Load(Stats->GetMap(MapID)->File); } // Get old map _Map *OldMap = Player->Map; // Place player in new map if(Map != OldMap) { if(OldMap) { OldMap->RemoveObject(Player); } Player->Map = Map; // Find spawn point in map uint32_t SpawnPoint = Player->SpawnPoint; if(EventType == _Map::EVENT_MAPENTRANCE) SpawnPoint = OldMap->NetworkID; // Default to mapchange event if entrance not found if(!Map->FindEvent(_Event(EventType, SpawnPoint), Player->Position)) Map->FindEvent(_Event(_Map::EVENT_MAPCHANGE, SpawnPoint), Player->Position); // Add player to map Map->AddObject(Player); // Send new map id _Buffer Packet; Packet.Write<PacketType>(PacketType::WORLD_CHANGEMAPS); Packet.Write<uint32_t>(MapID); Packet.Write<double>(Clock); Network->SendPacket(Packet, Player->Peer); // Set player object list Map->SendObjectList(Player->Peer); // Set full player data to peer SendPlayerInfo(Player->Peer); } else { Map->FindEvent(_Event(EventType, Player->SpawnPoint), Player->Position); SendPlayerPosition(Player->Peer); SendHUD(Player->Peer); } }
void TClient::OnDataReceived(const QByteArray &data) { EPacketType packetType; quint16 packedDataSize; quint16 originDataSize; QByteArray content; QByteArray receivedPacket = data; const int midSize = sizeof(quint16); const int posOrigin = sizeof(char); const int posPacked = posOrigin + midSize; const int posContent = posPacked + midSize; try { while (receivedPacket.size() > 0) { packetType = (EPacketType)(char)(receivedPacket[0]); originDataSize = qFromBigEndian<quint16>( (const uchar*)receivedPacket.mid(posOrigin, midSize).constData()); packedDataSize = qFromBigEndian<quint16>( (const uchar*)receivedPacket.mid(posPacked, midSize).constData()); content = qUncompress(receivedPacket.mid(posContent, packedDataSize)); if( content.isEmpty() && (originDataSize || packedDataSize) ) throw UException("Wrong packet: cannot unpack data"); // Retrieve another packet from current. // We can receive more than one packet at once receivedPacket = receivedPacket.mid( packedDataSize + sizeof(char) + 2*midSize); switch (packetType) { case PT_Control: { if (!(PlayerStatus == PS_Spawned || PlayerStatus == PS_Dead)) { throw UException("Player not spawned!"); } Epsilon5::Control control; if (control.ParseFromArray(content.data(), content.size())) { size_t currentPacket = control.packet_number(); if (control.has_need_full()) { if (control.need_full()) { Server()->NeedFullPacket(Id); } } Server()->Application()->GetWorld()->SetPingForPlayer(Id, currentPacket); SetSeen(); emit ControlReceived(control); } else { throw UException("Parse error: control packet"); } } break; case PT_PlayerAuth: { if (PlayerStatus != PS_AuthWait) { throw UException("Player not waiting for auth!"); } Epsilon5::Auth auth; if (auth.ParseFromArray(content.data(), content.size())) { try { SetSeen(); NickName = auth.name().c_str(); SendPlayerInfo(); QTime dieTime= QTime::currentTime().addSecs(1); while( QTime::currentTime() < dieTime ) { QCoreApplication::processEvents(QEventLoop::AllEvents, 100); } qDebug() << "Player " << NickName << "(" << Addr.toString() << ") connected"; Team = rand() % 2 == 1 ? T_One : T_Second; // throw to random team ETeam NewTeam = Server()->AutoBalance(); if (NewTeam != T_Neutral) { Team = NewTeam; } emit PlayerConnected(); ReSpawn(true); } catch (const std::exception& e){ qDebug() << "Exceptiong: " << Q_FUNC_INFO << ": Error spawning player: " << e.what(); } } else { throw UException("Parse error: auth packet"); } } break; default: throw UException("Unknown packet type!"); break; } } } catch (const UException& e) { qDebug() << "Exceptiong: " << Q_FUNC_INFO << ": " << e.what(); } }