Save and restore NetworkItemManager completely for live join

This commit is contained in:
Benau
2019-01-02 14:02:51 +08:00
parent 0e4424b3ea
commit 8332e0471e
7 changed files with 117 additions and 12 deletions

View File

@@ -26,6 +26,7 @@
#include "items/item_manager.hpp"
#include "karts/abstract_kart.hpp"
#include "modes/world.hpp"
#include "network/network_string.hpp"
#include "network/rewind_manager.hpp"
#include "tracks/arena_graph.hpp"
#include "tracks/drive_graph.hpp"
@@ -56,6 +57,25 @@ ItemState::ItemState(ItemType type, const AbstractKart *owner, int id)
setDeactivatedTicks(0);
} // ItemState(ItemType)
//-----------------------------------------------------------------------------
/** 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)
// ------------------------------------------------------------------------
/** Sets the disappear counter depending on type. */
void ItemState::setDisappearCounter()
@@ -145,6 +165,19 @@ Item::ItemType ItemState::getGrahpicalType() const
ITEM_BUBBLEGUM_NOLOK : getType();
} // getGrahpicalType
//-----------------------------------------------------------------------------
/** Save item state at current ticks in server for live join
*/
void ItemState::saveCompleteState(BareNetworkString* buffer) const
{
buffer->addUInt8((uint8_t)m_type).addUInt8((uint8_t)m_original_type)
.addUInt32(m_ticks_till_return).addUInt32(m_item_id)
.addUInt32(m_deactive_ticks).addUInt32(m_used_up_counter)
.add(m_xyz).add(m_original_rotation)
.addUInt8(m_previous_owner ?
(int8_t)m_previous_owner->getWorldKartId() : (int8_t)-1);
} // saveCompleteState
// ============================================================================
/** Constructor for an item.
* \param type Type of the item.
@@ -156,12 +189,10 @@ Item::ItemType ItemState::getGrahpicalType() const
* used to deactivate this item for the owner, i.e. avoid that a kart
* 'collects' its own bubble gum. NULL means no owner, and the item
* can be collected immediatley by any kart.
* \param is_predicted True if the creation of the item is predicted by
* a client. Only used in networking.
*/
Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
scene::IMesh* mesh, scene::IMesh* lowres_mesh,
const AbstractKart *owner, bool is_predicted)
const AbstractKart *owner)
: ItemState(type, owner)
{
assert(type != ITEM_TRIGGER); // use other constructor for that

View File

@@ -32,6 +32,7 @@
#include <line3d.h>
class BareNetworkString;
class AbstractKart;
class LODNode;
@@ -160,7 +161,11 @@ protected:
} // hitLine
public:
// ------------------------------------------------------------------------
ItemState(ItemType type, const AbstractKart *owner=NULL, int id = -1);
// ------------------------------------------------------------------------
ItemState(const BareNetworkString& buffer);
// ------------------------------------------------------------------------
void initItem(ItemType type, const Vec3& xyz, const Vec3& normal);
void update(int ticks);
void setDisappearCounter();
@@ -326,7 +331,8 @@ public:
{
return m_original_rotation;
}
// ------------------------------------------------------------------------
void saveCompleteState(BareNetworkString* buffer) const;
}; // class ItemState
// ============================================================================
@@ -371,8 +377,7 @@ private:
public:
Item(ItemType type, const Vec3& xyz, const Vec3& normal,
scene::IMesh* mesh, scene::IMesh* lowres_mesh,
const AbstractKart *owner,
bool is_predicted=false);
const AbstractKart *owner);
Item(const Vec3& xyz, float distance,
TriggerItemListener* trigger);
virtual ~Item ();

View File

@@ -538,3 +538,49 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
m_confirmed_state_time = world->getTicksSinceStart();
m_confirmed_switch_ticks = m_switch_ticks;
} // restoreState
//-----------------------------------------------------------------------------
/** Save all current items at current ticks in server for live join
*/
void NetworkItemManager::saveCompleteState(BareNetworkString* buffer) const
{
const uint32_t all_items = (uint32_t)m_all_items.size();
buffer->addUInt32(World::getWorld()->getTicksSinceStart())
.addUInt32(m_switch_ticks).addUInt32(all_items);
for (unsigned i = 0; i < all_items; i++)
{
if (m_all_items[i])
{
buffer->addUInt8(1);
m_all_items[i]->saveCompleteState(buffer);
}
else
buffer->addUInt8(0);
}
} // saveCompleteState
//-----------------------------------------------------------------------------
/** Restore all current items at current ticks in client for live join
*/
void NetworkItemManager::restoreCompleteState(const BareNetworkString& buffer)
{
m_confirmed_state_time = buffer.getUInt32();
m_confirmed_switch_ticks = buffer.getUInt32();
uint32_t all_items = buffer.getUInt32();
for (ItemState* is : m_confirmed_state)
{
delete is;
}
m_confirmed_state.clear();
for (unsigned i = 0; i < all_items; i++)
{
const bool has_item = buffer.getUInt8() == 1;
if (has_item)
{
ItemState* is = new ItemState(buffer);
m_confirmed_state.push_back(is);
}
else
m_confirmed_state.push_back(NULL);
}
} // restoreCompleteState

View File

@@ -97,6 +97,14 @@ public:
virtual void undoState(BareNetworkString *buffer) OVERRIDE {};
// ------------------------------------------------------------------------
virtual void undoEvent(BareNetworkString*) OVERRIDE {};
// ------------------------------------------------------------------------
void addLiveJoinPeer(std::weak_ptr<STKPeer> peer)
{ m_last_confirmed_item_ticks[peer] = 0; }
// ------------------------------------------------------------------------
void saveCompleteState(BareNetworkString* buffer) const;
// ------------------------------------------------------------------------
void restoreCompleteState(const BareNetworkString& buffer);
}; // NetworkItemManager
#endif

View File

@@ -25,7 +25,7 @@
#include "guiengine/message_queue.hpp"
#include "guiengine/screen_keyboard.hpp"
#include "input/device_manager.hpp"
#include "items/item_manager.hpp"
#include "items/network_item_manager.hpp"
#include "items/powerup_manager.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/controller/controller.hpp"
@@ -1008,6 +1008,12 @@ void ClientLobby::liveJoinAcknowledged(Event* event)
if (k->getController()->isLocalPlayerController())
k->setLiveJoinKart(m_live_join_ticks);
}
NetworkItemManager* nim =
dynamic_cast<NetworkItemManager*>(ItemManager::get());
assert(nim);
nim->restoreCompleteState(data);
} // liveJoinAcknowledged
//-----------------------------------------------------------------------------

View File

@@ -19,7 +19,7 @@
#include "network/protocols/server_lobby.hpp"
#include "config/user_config.hpp"
#include "items/item_manager.hpp"
#include "items/network_item_manager.hpp"
#include "items/powerup_manager.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/controller/player_controller.hpp"
@@ -814,10 +814,10 @@ int ServerLobby::getReservedId(std::shared_ptr<NetworkPlayerProfile>& p,
*/
void ServerLobby::finishedLoadingLiveJoinClient(Event* event)
{
STKPeer* peer = event->getPeer();
std::shared_ptr<STKPeer> peer = event->getPeerSP();
if (!canLiveJoinNow())
{
rejectLiveJoin(peer, BLR_NO_GAME_FOR_LIVE_JOIN);
rejectLiveJoin(peer.get(), BLR_NO_GAME_FOR_LIVE_JOIN);
return;
}
bool live_joined_in_time = true;
@@ -834,7 +834,7 @@ void ServerLobby::finishedLoadingLiveJoinClient(Event* event)
{
Log::warn("ServerLobby", "%s can't live-join in time.",
peer->getAddress().toString().c_str());
rejectLiveJoin(peer, BLR_NO_GAME_FOR_LIVE_JOIN);
rejectLiveJoin(peer.get(), BLR_NO_GAME_FOR_LIVE_JOIN);
return;
}
World* w = World::getWorld();
@@ -860,7 +860,16 @@ void ServerLobby::finishedLoadingLiveJoinClient(Event* event)
ns->setSynchronous(true);
ns->addUInt8(LE_LIVE_JOIN_ACK).addUInt64(m_client_starting_time)
.addUInt64(live_join_start_time).addUInt32(live_join_util_ticks);
NetworkItemManager* nim =
dynamic_cast<NetworkItemManager*>(ItemManager::get());
assert(nim);
nim->saveCompleteState(ns);
nim->addLiveJoinPeer(peer);
m_peers_ready[peer] = false;
peer->setWaitingForGame(false);
peer->sendPacket(ns, true/*reliable*/);
delete ns;
updatePlayerList();

View File

@@ -244,7 +244,7 @@ void NetworkingLobby::addMoreServerInfo(core::stringw info)
// ----------------------------------------------------------------------------
void NetworkingLobby::onUpdate(float delta)
{
if (NetworkConfig::get()->isServer())
if (NetworkConfig::get()->isServer() || !STKHost::existHost())
return;
m_ping_update_timer += delta;