/** Saves a state using the GameProtocol function to combine several * independent rewinders to write one state. */ void RewindManager::saveState() { PROFILER_PUSH_CPU_MARKER("RewindManager - save state", 0x20, 0x7F, 0x20); auto gp = GameProtocol::lock(); if (!gp) return; gp->startNewState(); m_overall_state_size = 0; std::vector<std::string> rewinder_using; for (auto& p : m_all_rewinder) { // TODO: check if it's worth passing in a sufficiently large buffer from // GameProtocol - this would save the copy operation. BareNetworkString* buffer = NULL; if (auto r = p.second.lock()) buffer = r->saveState(&rewinder_using); if (buffer != NULL) { m_overall_state_size += buffer->size(); gp->addState(buffer); } delete buffer; // buffer can be freed } gp->finalizeState(rewinder_using); PROFILER_POP_CPU_MARKER(); } // saveState
// ---------------------------------------------------------------------------- BareNetworkString* Flyable::saveState(std::vector<std::string>* ru) { if (m_has_hit_something) return NULL; ru->push_back(getUniqueIdentity()); BareNetworkString *buffer = new BareNetworkString(); CompressNetworkBody::compress(m_body->getWorldTransform(), m_body->getLinearVelocity(), m_body->getAngularVelocity(), buffer, m_body.get(), m_motion_state.get()); buffer->addUInt16(m_ticks_since_thrown); return buffer; } // saveState
/** \brief Sends a packet whithout ENet adding its headers. * This function is used in particular to achieve the STUN protocol. * \param data : Data to send. * \param dst : Destination of the packet. */ void Network::sendRawPacket(const BareNetworkString &buffer, const TransportAddress& dst) { struct sockaddr_in to; int to_len = sizeof(to); memset(&to,0,to_len); to.sin_family = AF_INET; to.sin_port = htons(dst.getPort()); to.sin_addr.s_addr = htonl(dst.getIP()); sendto(m_host->socket, buffer.getData(), buffer.size(), 0, (sockaddr*)&to, to_len); Log::verbose("Network", "Raw packet sent to %s", dst.toString().c_str()); Network::logPacket(buffer, false); } // sendRawPacket
/** Constructor to restore item state at current ticks in client for live join */ ItemState::ItemState(const BareNetworkString& buffer) { m_type = (ItemType)buffer.getUInt8(); m_original_type = (ItemType)buffer.getUInt8(); m_ticks_till_return = buffer.getUInt32(); m_item_id = buffer.getUInt32(); m_deactive_ticks = buffer.getUInt32(); m_used_up_counter = buffer.getUInt32(); m_xyz = buffer.getVec3(); m_original_rotation = buffer.getQuat(); m_previous_owner = NULL; int8_t kart_id = buffer.getUInt8(); if (kart_id != -1) m_previous_owner = World::getWorld()->getKart(kart_id); } // ItemState(const BareNetworkString& buffer)
/** Saves a local state using the GameProtocol function to combine several * independent rewinders to write one state. Typically only the server needs * to save a state (which is then send to the clients), except that each * client needs one initial state (in case that it receives an event from * a client before a state from the serer). * \param allow_local_save Do a local save. */ void RewindManager::saveState(bool local_save) { PROFILER_PUSH_CPU_MARKER("RewindManager - save state", 0x20, 0x7F, 0x20); GameProtocol::lock()->startNewState(local_save); AllRewinder::const_iterator rewinder; for (rewinder = m_all_rewinder.begin(); rewinder != m_all_rewinder.end(); ++rewinder) { // TODO: check if it's worth passing in a sufficiently large buffer from // GameProtocol - this would save the copy operation. BareNetworkString *buffer = (*rewinder)->saveState(); if (buffer && buffer->size() >= 0) { m_overall_state_size += buffer->size(); GameProtocol::lock()->addState(buffer); } // size >= 0 delete buffer; // buffer can be freed } PROFILER_POP_CPU_MARKER(); } // saveState
// ---------------------------------------------------------------------------- void CheckLine::restoreCompleteState(const BareNetworkString& b) { CheckStructure::restoreCompleteState(b); m_previous_sign.clear(); World* world = World::getWorld(); for (unsigned int i = 0; i < world->getNumKarts(); i++) { bool previous_sign = b.getUInt8() == 1; m_previous_sign.push_back(previous_sign); } } // restoreCompleteState
/** Saves all state information for a kart in a memory buffer. The memory * is allocated here and the address returned. It will then be managed * by the RewindManager. The size is used to keep track of memory usage * for rewinding. * \param[out] buffer Address of the memory buffer. * \returns Size of allocated memory, or -1 in case of an error. */ BareNetworkString* KartRewinder::saveState() const { const int MEMSIZE = 17*sizeof(float) + 9+3; BareNetworkString *buffer = new BareNetworkString(MEMSIZE); const btRigidBody *body = getBody(); // 1) Physics values: transform and velocities // ------------------------------------------- const btTransform &t = body->getWorldTransform(); buffer->add(t.getOrigin()); btQuaternion q = t.getRotation(); buffer->add(q); buffer->add(body->getLinearVelocity()); buffer->add(body->getAngularVelocity()); buffer->addUInt8(m_has_started); // necessary for startup speed boost buffer->addFloat(m_vehicle->getMinSpeed()); buffer->addFloat(m_vehicle->getTimedRotationTime()); buffer->add(m_vehicle->getTimedRotation()); // 2) Steering and other player controls // ------------------------------------- getControls().saveState(buffer); getController()->saveState(buffer); // 3) Attachment // ------------- getAttachment()->saveState(buffer); // 4) Powerup // ---------- getPowerup()->saveState(buffer); // 5) Max speed info // ------------------ m_max_speed->saveState(buffer); // 6) Skidding // ----------- m_skidding->saveState(buffer); return buffer; } // saveState
/** \brief Log packets into a file * \param ns : The data in the packet * \param incoming : True if the packet comes from a peer. * False if it's sent to a peer. */ void Network::logPacket(const BareNetworkString &ns, bool incoming) { if (m_log_file.getData() == NULL) // read only access, no need to lock return; const char *arrow = incoming ? "<--" : "-->"; m_log_file.lock(); fprintf(m_log_file.getData(), "[%d\t] %s ", (int)(StkTime::getRealTime()), arrow); // Indentation for all lines after the first, so that the dump // is nicely aligned. std::string indent(" "); fprintf(m_log_file.getData(), "%s", ns.getLogMessage(indent).c_str()); m_log_file.unlock(); } // logPacket
/** This is called while going forwards in time again to reach current * time. Calls rewind() in the event rewinder. */ virtual void rewind() { // Make sure to reset the buffer so we read from the beginning m_buffer->reset(); m_event_rewinder->rewind(m_buffer); } // rewind
/** Called when going back in time to undo any rewind information. * It calls undoEvent in the rewinder. */ virtual void undo() { m_buffer->reset(); m_event_rewinder->undo(m_buffer); } // undo