Uint32 PacketSocket::write(Uint32 max, bt::TimeStamp now) { if (sock->state() == net::SocketDevice::CONNECTING && !sock->connectSuccesFull()) return 0; if (!curr_packet) curr_packet = selectPacket(); Uint32 written = 0; while (curr_packet && (written < max || max == 0)) { Uint32 limit = (max == 0) ? 0 : max - written; int ret = curr_packet->send(sock, limit); if (ret > 0) { written += ret; QMutexLocker locker(&mutex); if (curr_packet->getType() == PIECE) { up_speed->onData(ret, now); uploaded_data_bytes += ret; } } else break; // Socket buffer full, so stop sending for now if (curr_packet->isSent()) { // packet sent, so remove it if (curr_packet->getType() == PIECE) { QMutexLocker locker(&mutex); if (!data_packets.empty()) data_packets.pop_front(); // reset ctrl_packets_sent so the next packet should be a ctrl packet ctrl_packets_sent = 0; } else { QMutexLocker locker(&mutex); if (!control_packets.empty()) control_packets.pop_front(); ctrl_packets_sent++; } curr_packet = selectPacket(); } else { // we can't write it fully, so break out of loop break; } } return written; }
void PlayPG::render(float deltaTime) { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); switch (gameState) { case GameState::LOGIN: { if (inputManager->isKeyJustPressed(SDL_SCANCODE_SPACE)) { if (doLogin()) { gameState = GameState::CHARACTER_SELECT; } } else if (inputManager->isKeyJustPressed(SDL_SCANCODE_1)) { username = "******"; } break; } case GameState::CHARACTER_SELECT: { if (inputManager->isKeyJustPressed(SDL_SCANCODE_RETURN)) { socket.clear(); socket.putShort(util::to_integral(ClientOpcode::REQUEST_CHARACTERS)); socket.send(); socket.waitForActivity(); const auto charBytes = socket.recv(); if (charBytes == 0) { logger->error("Couldn't get characters from LoginServer"); break; } const auto charOpcode = socket.getShort(); if (charOpcode != util::to_integral(ServerOpcode::PLAYER_CHARACTERS)) { logger->error("Got invalid response from server."); break; } const auto jsonLength = socket.getShort(); const auto json = socket.getStringByLength(jsonLength); logger->info("Got %v.", json); APG::JSONSerializer<PlayerCharacters> charS11N; const auto charList = charS11N.fromJSON(json.c_str()); if (charList.characters.size() == 0) { logger->fatal("Server has no characters for this account. Exiting."); break; } currentCharacter = std::make_unique<Character>(charList.characters[0]); CharacterSelect selectPacket(*currentCharacter); socket.clear(); socket.put(&selectPacket.buffer); socket.send(); gameState = GameState::MAP_SERVER_CONNECT; } break; } case GameState::MAP_SERVER_CONNECT: { socket.clear(); socket.waitForActivity(); const auto bytesRec = socket.recv(); if(bytesRec == 0) { break; } const auto opcode = socket.getShort(); switch (opcode) { case util::to_integral(ServerOpcode::NO_MAP_SERVER_ERROR): { const auto messageLength = socket.getShort(); const auto message = socket.getStringByLength(messageLength); logger->error("Couldn't find an appropriate map server for that character. Error: %v", message); gameState = GameState::CHARACTER_SELECT; break; } case util::to_integral(ServerOpcode::MAP_SERVER_CONNECTION_INSTRUCTIONS): { // success; read the JSON provided const auto jsonLength = socket.getShort(); const auto jsonString = socket.getStringByLength(jsonLength); APG::JSONSerializer<MapServerConnectionInstructions> msciJSON; const MapServerConnectionInstructions msci = msciJSON.fromJSON(jsonString.c_str()); logger->info("Got map server details: %v:%v", msci.hostName, msci.port); gameState = GameState::PLAYING; break; } default: { logger->error("Invalid response from server for that character."); gameState = GameState::CHARACTER_SELECT; break; } } socket.clear(); break; } case GameState::PLAYING: { if (inputManager->isKeyJustPressed(SDL_SCANCODE_RETURN)) { if (indoor) { indoor = false; changeToWorld(mapOutdoor); } else { indoor = true; changeToWorld(mapIndoor); } } outdoorRenderer->update(deltaTime); engine->update(deltaTime); break; } } SDL_GL_SwapWindow(window.get()); }