Hopefully fixed switch in networking mode.

This commit is contained in:
hiker 2018-10-03 08:51:19 +10:00
parent c2d0ac4a61
commit 76dc8c8763
3 changed files with 94 additions and 25 deletions

View File

@ -33,15 +33,23 @@ ItemEventInfo::ItemEventInfo(BareNetworkString *buffer, int *count)
{
m_type = (EventType)buffer->getUInt8();
m_ticks = buffer->getTime();
m_kart_id = buffer->getInt8();
m_index = buffer->getUInt16();
*count -= 8;
if (m_type == IEI_NEW)
*count -= 5;
if (m_type != IEI_SWITCH)
{
m_xyz = buffer->getVec3();
*count -= 12;
}
m_kart_id = buffer->getInt8();
m_index = buffer->getUInt16();
*count -= 3;
if (m_type == IEI_NEW)
{
m_xyz = buffer->getVec3();
*count -= 12;
}
} // is not switch
else // switch
{
m_kart_id = -1;
}
} // ItemEventInfo(BareNetworkString, int *count)
//-----------------------------------------------------------------------------
@ -51,10 +59,14 @@ ItemEventInfo::ItemEventInfo(BareNetworkString *buffer, int *count)
void ItemEventInfo::saveState(BareNetworkString *buffer)
{
assert(NetworkConfig::get()->isServer());
buffer->addUInt8(m_type).addTime(m_ticks).addUInt8(m_kart_id)
.addUInt16(m_index);
if(m_type == IEI_NEW)
buffer->add(m_xyz);
buffer->addUInt8(m_type).addTime(m_ticks);
if (m_type != IEI_SWITCH)
{
// Only new item and collecting items need the index and kart id:
buffer->addUInt8(m_kart_id).addUInt16(m_index);
if (m_type == IEI_NEW)
buffer->add(m_xyz);
}
} // saveState

78
src/items/network_item_manager.cpp Normal file → Executable file
View File

@ -42,6 +42,7 @@ void NetworkItemManager::create()
NetworkItemManager::NetworkItemManager()
: Rewinder("N"), ItemManager()
{
m_confirmed_switch_ticks = -1;
m_last_confirmed_item_ticks.clear();
if (NetworkConfig::get()->isServer())
@ -71,6 +72,7 @@ NetworkItemManager::~NetworkItemManager()
//-----------------------------------------------------------------------------
void NetworkItemManager::reset()
{
m_confirmed_switch_ticks = -1;
ItemManager::reset();
} // reset
@ -114,6 +116,25 @@ void NetworkItemManager::collectedItem(ItemState *item, AbstractKart *kart)
}
} // collectedItem
// ----------------------------------------------------------------------------
/** Called when a switch is activated. On the server adds this information to
* the item state so it can be sent to all clients.
*/
void NetworkItemManager::switchItems()
{
if (NetworkConfig::get()->isServer())
{
// The server saves the collected item as item event info
m_item_events.lock();
// Create a switch event - the constructor called determines
// the type of the event automatically.
m_item_events.getData()
.emplace_back(World::getWorld()->getTicksSinceStart());
m_item_events.unlock();
}
ItemManager::switchItems();
} // switchItems
// ----------------------------------------------------------------------------
/** Called when a new item is created, e.g. bubble gum.
* \param type Type of the item.
@ -233,6 +254,13 @@ void NetworkItemManager::forwardTime(int ticks)
{
if (i) i->update(ticks);
} // for m_all_items
if(m_switch_ticks>ticks)
m_switch_ticks -= ticks;
else if (m_switch_ticks >= 0)
{
switchItemsInternal(m_confirmed_state);
m_switch_ticks = -1;
}
} // forwardTime
//-----------------------------------------------------------------------------
@ -245,6 +273,7 @@ void NetworkItemManager::forwardTime(int ticks)
*/
void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
{
assert(NetworkConfig::get()->isClient());
// The state at World::getTicksSinceStart() needs to be restored. The confirmed
// state in this instance was taken at m_confirmed_state_time. First
@ -270,18 +299,34 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
// --------------------------
for (unsigned int i=0; i<m_all_items.size(); i++)
{
Item *item = m_all_items[i];
ItemState *item = m_all_items[i];
if(item && item->isPredicted())
{
deleteItem(item);
}
} // for i in m_all_items
// Reset a predicted switch time: if the items are currently
// predicted to be switched, but not switched at the confirmed
// state time or vice versa, we need to switch them back. This
// is tested by seeing if the signs of the switch_ticks and
// confirmed switch_ticks are opposite:
if(m_switch_ticks * m_confirmed_switch_ticks < 0)
{
switchItemsInternal(m_all_items);
}
m_switch_ticks = m_confirmed_switch_ticks;
// 2) Apply all events to current confirmed state:
// -----------------------------------------------
World *world = World::getWorld();
int current_time = m_confirmed_state_time;
bool has_state = count > 0;
// Note that the actual ItemManager states must NOT be changed here, only
// the confirmed states in the Network manager are allowed to be modified.
// They will all be copied to the ItemManager states after the loop.
while(count > 0)
{
// 2.1) Decode the event in the message
@ -292,16 +337,14 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
// the time to the time of this event:
// ----------------------------------------------
int dt = iei.getTicks() - current_time;
// Skip an event that are 'in the past' (i.e. have been sent again by
// Skip an event that is 'in the past' (i.e. have been sent again by
// the server because it has not yet received confirmation from all
// clients.
// clients).
if(dt<0) continue;
// Forward the saved state:
if (dt>0) forwardTime(dt);
// TODO: apply the various events types, atm only collection
// and new items are supported.
if(iei.isItemCollection())
{
int index = iei.getIndex();
@ -348,6 +391,19 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
}
}
}
else if(iei.isSwitch())
{
// Reset current switch ticks
m_switch_ticks = -1;
ItemManager::switchItemsInternal(m_confirmed_state);
m_confirmed_switch_ticks = m_switch_ticks;
}
else
{
Log::error("NetworkItemManager",
"Received unknown event type at %d",
iei.getTicks());
}
current_time = iei.getTicks();
} // while count >0
@ -360,6 +416,8 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
gp->sendItemEventConfirmation(world->getTicksSinceStart());
}
m_switch_ticks = m_confirmed_switch_ticks;
// Forward the confirmed item state to the world time:
int dt = world->getTicksSinceStart() - current_time;
if(dt>0) forwardTime(dt);
@ -369,7 +427,7 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
for(unsigned int i=0; i<m_confirmed_state.size(); i++)
{
Item *item = i < m_all_items.size() ? m_all_items[i] : NULL;
ItemState *item = i < m_all_items.size() ? m_all_items[i] : NULL;
const ItemState *is = m_confirmed_state[i];
if (is && item)
*(ItemState*)item = *is;
@ -383,8 +441,6 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
// The server has this item at a different index in the list
// of all items, which means the client has an incorrect
// item at the index given by the server - delete that item
Log::info("nim", "about to delete item with not matching index i %d item %d",
i, item_new->getItemId());
if(m_all_items[i])
deleteItem(m_all_items[i]);
m_all_items[item_new->getItemId()] = NULL;
@ -397,14 +453,12 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
}
else if (!is && item)
{
Log::info("nim", "About to delete item index %d i %d",
item->getItemId(), i);
deleteItem(m_all_items[i]);
}
}
// Now we save the current local
m_confirmed_state_time = world->getTicksSinceStart();
m_confirmed_state_time = world->getTicksSinceStart();
m_confirmed_switch_ticks = m_switch_ticks;
} // restoreState

View File

@ -48,6 +48,9 @@ private:
* server data. This is used in case of rewind. */
std::vector<ItemState*> m_confirmed_state;
/** The switch ticks value at the lime of the last confirmed state. */
int m_confirmed_switch_ticks;
/** Time at which m_confirmed_state was taken. */
int m_confirmed_state_time;
@ -66,14 +69,14 @@ public:
static void create();
virtual ~NetworkItemManager();
void setSwitchItems(const std::vector<int> &switch_items);
void sendItemUpdate();
void initClientConfirmState();
virtual void reset() OVERRIDE;
virtual void setItemConfirmationTime(std::weak_ptr<STKPeer> peer,
int ticks) OVERRIDE;
virtual void collectedItem(ItemState *item, AbstractKart *kart) OVERRIDE;
virtual void collectedItem(ItemState *item, AbstractKart *kart) OVERRIDE;
virtual void switchItems() OVERRIDE;
virtual Item* dropNewItem(ItemState::ItemType type, const AbstractKart *kart,
const Vec3 *xyz=NULL) OVERRIDE;
virtual BareNetworkString* saveState(std::vector<std::string>* ru)