Handle copying ItemState to Item properly (esp in live join)

This commit is contained in:
Benau 2019-01-24 14:01:04 +08:00
parent 6ecd606e3f
commit 664129e448
3 changed files with 42 additions and 31 deletions

View File

@ -235,9 +235,18 @@ unsigned int ItemManager::insertItem(Item *item)
m_all_items[index] = item;
}
item->setItemId(index);
insertItemInQuad(item);
// Now insert into the appropriate quad list, if there is a quad list
// (i.e. race mode has a quad graph).
return index;
} // insertItem
//-----------------------------------------------------------------------------
/** Insert into the appropriate quad list, if there is a quad list
* (i.e. race mode has a quad graph).
*/
void ItemManager::insertItemInQuad(Item *item)
{
if(m_items_in_quads)
{
int graph_node = item->getGraphNode();
@ -249,8 +258,7 @@ unsigned int ItemManager::insertItem(Item *item)
else // otherwise store it in the 'outside' index
(*m_items_in_quads)[m_items_in_quads->size()-1].push_back(item);
} // if m_items_in_quads
return index;
} // insertItem
} // insertItemInQuad
//-----------------------------------------------------------------------------
/** Creates a new item at the location of the kart (e.g. kart drops a
@ -303,7 +311,10 @@ Item* ItemManager::dropNewItem(ItemState::ItemType type,
Item* item = new Item(type, pos, normal, m_item_mesh[mesh_type],
m_item_lowres_mesh[mesh_type], /*prev_owner*/kart);
insertItem(item);
// restoreState in NetworkItemManager will handle the insert item
if (!server_xyz)
insertItem(item);
if(m_switch_ticks>=0)
{
ItemState::ItemType new_type = m_switch_to[item->getType()];
@ -522,6 +533,18 @@ void ItemManager::updateGraphics(float dt)
void ItemManager::deleteItem(ItemState *item)
{
// First check if the item needs to be removed from the items-in-quad list
deleteItemInQuad(item);
int index = item->getItemId();
m_all_items[index] = NULL;
delete item;
} // delete item
//-----------------------------------------------------------------------------
/** Removes an items from the items-in-quad list only
* \param The item to delete.
*/
void ItemManager::deleteItemInQuad(ItemState* item)
{
if(m_items_in_quads)
{
int sector = item->getGraphNode();
@ -533,11 +556,7 @@ void ItemManager::deleteItem(ItemState *item)
assert(it!=items.end());
items.erase(it);
} // if m_items_in_quads
int index = item->getItemId();
m_all_items[index] = NULL;
delete item;
} // delete item
} // deleteItemInQuad
//-----------------------------------------------------------------------------
/** Switches all items: boxes become bananas and vice versa for a certain

View File

@ -125,7 +125,8 @@ protected:
virtual unsigned int insertItem(Item *item);
void switchItemsInternal(std::vector < ItemState*> &all_items);
void setSwitchItems(const std::vector<int> &switch_items);
void insertItemInQuad(Item *item);
void deleteItemInQuad(ItemState *item);
ItemManager();
public:
virtual ~ItemManager();

View File

@ -492,12 +492,15 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
// the client, but not yet confirmed). So
unsigned int max_index = std::max(m_confirmed_state.size(),
m_all_items.size() );
m_all_items.resize(max_index, NULL);
for(unsigned int i=0; i<max_index; i++)
{
ItemState *item = i < m_all_items.size() ? m_all_items[i] : NULL;
ItemState *item = m_all_items[i];
const ItemState *is = i < m_confirmed_state.size()
? m_confirmed_state[i] : NULL;
// For every *(ItemState*)item = *is, all deactivated ticks, item id
// ... will be copied from item state to item
if (is && item)
{
*(ItemState*)item = *is;
@ -510,31 +513,19 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
Vec3 normal = is->getNormal();
Item *item_new = dropNewItem(is->getType(), is->getPreviousOwner(),
&xyz, &normal );
if (i != item_new->getItemId())
{
// The newly created item on the client has been given a
// different index than the one given by the server. This
// indicates that this client has either a different item
// at the index that the server sent (i.e. client predicted
// an item, which the server has not confirmed), or the
// client found an empty slot that the server did not have
// (so an earlier index was found).
if(i < m_all_items.size() && m_all_items[i])
deleteItem(m_all_items[i]);
// Move item_new from its position to the index given
// by the server
m_all_items[item_new->getItemId()] = NULL;
m_all_items[i] = item_new;
item_new->setItemId(i);
}
item_new->setDeactivatedTicks(is->getDeactivatedTicks());
*((ItemState*)m_all_items[i]) = *is;
*((ItemState*)item_new) = *is;
m_all_items[i] = item_new;
insertItemInQuad(item_new);
}
else if (!is && item)
{
deleteItem(m_all_items[i]);
deleteItemInQuad(item);
delete item;
m_all_items[i] = NULL;
}
} // for i < max_index
// Clean up the rest
m_all_items.resize(m_confirmed_state.size());
// Now set the clock back to the 'rewindto' time:
world->setTicksForRewind(rewind_to_time);