Merge remote-tracking branch 'origin/network-item-debugging'
This commit is contained in:
commit
abd3a79526
@ -37,6 +37,25 @@
|
||||
#include <ISceneManager.h>
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor.
|
||||
* \param type Type of the item.
|
||||
* \param owner If not NULL it is the kart that dropped this item; NULL
|
||||
* indicates an item that's part of the track.
|
||||
* \param id Index of this item in the array of all items.
|
||||
*/
|
||||
ItemState::ItemState(ItemType type, const AbstractKart *owner, int id)
|
||||
{
|
||||
setType(type);
|
||||
m_item_id = id;
|
||||
m_previous_owner = owner;
|
||||
m_used_up_counter = -1;
|
||||
if (owner)
|
||||
setDeactivatedTicks(stk_config->time2Ticks(1.5f));
|
||||
else
|
||||
setDeactivatedTicks(0);
|
||||
} // ItemState(ItemType)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the disappear counter depending on type. */
|
||||
void ItemState::setDisappearCounter()
|
||||
@ -52,9 +71,23 @@ void ItemState::setDisappearCounter()
|
||||
} // switch
|
||||
} // setDisappearCounter
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
/** Initialises an item.
|
||||
* \param type Type for this item.
|
||||
*/
|
||||
void ItemState::initItem(ItemType type, const Vec3& xyz)
|
||||
{
|
||||
m_xyz = xyz;
|
||||
m_original_type = ITEM_NONE;
|
||||
m_ticks_till_return = 0;
|
||||
setDisappearCounter();
|
||||
} // initItem
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Update the state of the item, called once per physics frame.
|
||||
* \param ticks Number of ticks to simulate (typically 1).
|
||||
* \param ticks Number of ticks to simulate. While this value is 1 when
|
||||
* called during the normal game loop, during a rewind this value
|
||||
* can be (much) larger than 1.
|
||||
*/
|
||||
void ItemState::update(int ticks)
|
||||
{
|
||||
@ -107,12 +140,17 @@ void ItemState::collected(const AbstractKart *kart)
|
||||
* \param normal The normal upon which the item is placed (so that it can
|
||||
* be aligned properly with the ground).
|
||||
* \param mesh The mesh to be used for this item.
|
||||
* \param owner 'Owner' of this item, i.e. the kart that drops it. This is
|
||||
* 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, bool is_predicted)
|
||||
: ItemState(type)
|
||||
scene::IMesh* mesh, scene::IMesh* lowres_mesh,
|
||||
const AbstractKart *owner, bool is_predicted)
|
||||
: ItemState(type, owner)
|
||||
{
|
||||
assert(type != ITEM_TRIGGER); // use other constructor for that
|
||||
|
||||
@ -190,7 +228,6 @@ Item::Item(const Vec3& xyz, float distance, TriggerItemListener* trigger)
|
||||
void Item::initItem(ItemType type, const Vec3 &xyz)
|
||||
{
|
||||
ItemState::initItem(type, xyz);
|
||||
m_previous_owner = NULL;
|
||||
m_rotate = (getType()!=ITEM_BUBBLEGUM) &&
|
||||
(getType()!=ITEM_TRIGGER );
|
||||
// Now determine in which quad this item is, and its distance
|
||||
@ -334,17 +371,6 @@ void Item::reset()
|
||||
}
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets which karts dropped an item. This is used to avoid that a kart is
|
||||
* affected by its own items.
|
||||
* \param parent Kart that dropped the item.
|
||||
*/
|
||||
void Item::setParent(const AbstractKart* parent)
|
||||
{
|
||||
m_previous_owner = parent;
|
||||
ItemState::setDeactivatedTicks(stk_config->time2Ticks(1.5f));
|
||||
} // setParent
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Updated the item - rotates it, takes care of items coming back into
|
||||
* the game after it has been collected.
|
||||
|
@ -122,35 +122,25 @@ private:
|
||||
* and then converting this value to a Vec3. */
|
||||
Vec3 m_xyz;
|
||||
|
||||
protected:
|
||||
/** The 'owner' of the item, i.e. the kart that dropped this item.
|
||||
* Is NULL if the item is part of the track. */
|
||||
* Is NULL if the item is part of the track. */
|
||||
const AbstractKart *m_previous_owner;
|
||||
|
||||
protected:
|
||||
|
||||
friend class ItemManager;
|
||||
friend class NetworkItemManager;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void setType(ItemType type) { m_type = type; }
|
||||
|
||||
public:
|
||||
/** Constructor.
|
||||
* \param type Type of the item.
|
||||
* \param id Index of this item in the array of all items.
|
||||
* \param kart_id If !=-1 the kart that dropped this item; -1
|
||||
* indicates an item that's part of the track. */
|
||||
ItemState(ItemType type, int id=-1, AbstractKart *kart=NULL)
|
||||
{
|
||||
setType(type);
|
||||
m_item_id = id;
|
||||
m_previous_owner = kart;
|
||||
} // ItemState(ItemType)
|
||||
|
||||
ItemState(ItemType type, const AbstractKart *owner=NULL, int id = -1);
|
||||
void initItem(ItemType type, const Vec3& xyz);
|
||||
void update(int ticks);
|
||||
void setDisappearCounter();
|
||||
virtual void collected(const AbstractKart *kart);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual ~ItemState() {}
|
||||
void setDisappearCounter();
|
||||
void update(int ticks);
|
||||
virtual void collected(const AbstractKart *kart);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
void reset()
|
||||
@ -166,19 +156,6 @@ public:
|
||||
}
|
||||
} // reset
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
/** Initialises an item.
|
||||
* \param type Type for this item.
|
||||
*/
|
||||
void initItem(ItemType type, const Vec3& xyz)
|
||||
{
|
||||
m_xyz = xyz;
|
||||
m_original_type = ITEM_NONE;
|
||||
m_deactive_ticks = 0;
|
||||
m_ticks_till_return = 0;
|
||||
setDisappearCounter();
|
||||
} // initItem
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Switches an item to be of a different type. Used for the switch
|
||||
* powerup.
|
||||
@ -329,20 +306,19 @@ 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);
|
||||
Item(const Vec3& xyz, float distance,
|
||||
TriggerItemListener* trigger);
|
||||
virtual ~Item ();
|
||||
void updateGraphics(float dt);
|
||||
virtual void collected(const AbstractKart *kart) OVERRIDE;
|
||||
void setParent(const AbstractKart* parent);
|
||||
void reset();
|
||||
void switchTo(ItemType type, scene::IMesh *mesh, scene::IMesh *lowmesh);
|
||||
void switchTo(ItemType type, scene::IMesh *mesh,
|
||||
scene::IMesh *lowmesh);
|
||||
void switchBack();
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if the Kart is close enough to hit this item, the item is
|
||||
* not deactivated anymore, and it wasn't placed by this kart (this is
|
||||
* e.g. used to avoid that a kart hits a bubble gum it just dropped).
|
||||
@ -352,7 +328,7 @@ public:
|
||||
*/
|
||||
bool hitKart(const Vec3 &xyz, const AbstractKart *kart=NULL) const
|
||||
{
|
||||
if (m_previous_owner == kart && getDeactivatedTicks() > 0)
|
||||
if (getPreviousOwner() == kart && getDeactivatedTicks() > 0)
|
||||
return false;
|
||||
Vec3 lc = quatRotate(m_original_rotation, xyz - getXYZ());
|
||||
// Don't be too strict if the kart is a bit above the item
|
||||
@ -373,7 +349,8 @@ protected:
|
||||
bool hitLine(const core::line3df &line,
|
||||
const AbstractKart *kart=NULL) const
|
||||
{
|
||||
if (m_previous_owner == kart && getDeactivatedTicks() >0) return false;
|
||||
if (getPreviousOwner() == kart && getDeactivatedTicks() > 0)
|
||||
return false;
|
||||
|
||||
Vec3 closest = line.getClosestPoint(getXYZ().toIrrVector());
|
||||
return hitKart(closest, kart);
|
||||
|
@ -31,6 +31,7 @@
|
||||
*/
|
||||
ItemEventInfo::ItemEventInfo(BareNetworkString *buffer, int *count)
|
||||
{
|
||||
m_ticks_till_return = 0;
|
||||
m_type = (EventType)buffer->getUInt8();
|
||||
m_ticks = buffer->getTime();
|
||||
m_kart_id = buffer->getInt8();
|
||||
@ -41,7 +42,11 @@ ItemEventInfo::ItemEventInfo(BareNetworkString *buffer, int *count)
|
||||
m_xyz = buffer->getVec3();
|
||||
*count -= 12;
|
||||
}
|
||||
|
||||
else if (m_type == IEI_COLLECT)
|
||||
{
|
||||
m_ticks_till_return = buffer->getUInt16();
|
||||
*count -= 2;
|
||||
}
|
||||
} // ItemEventInfo(BareNetworkString, int *count)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -55,7 +60,6 @@ void ItemEventInfo::saveState(BareNetworkString *buffer)
|
||||
.addUInt16(m_index);
|
||||
if(m_type == IEI_NEW)
|
||||
buffer->add(m_xyz);
|
||||
else if (m_type == IEI_COLLECT)
|
||||
buffer->addUInt16(m_ticks_till_return);
|
||||
} // saveState
|
||||
|
||||
|
||||
|
@ -51,13 +51,20 @@ private:
|
||||
/** In case of new items the position of the new item. */
|
||||
Vec3 m_xyz;
|
||||
|
||||
/** Ticks for the item to return, atm used by collecting banana
|
||||
* with bomb to delay the return for banana. */
|
||||
int16_t m_ticks_till_return;
|
||||
|
||||
public:
|
||||
/** Constructor for collecting an existing item.
|
||||
* \param ticks Time of the event.
|
||||
* \param item_id The index of the item that was collected.
|
||||
* \param kart_id the kart that collected the item. */
|
||||
ItemEventInfo(int ticks, int index, int kart_id)
|
||||
: m_ticks(ticks), m_index(index), m_kart_id(kart_id)
|
||||
* \param kart_id the kart that collected the item.
|
||||
* \param ttr Ticks till return after being collected. */
|
||||
|
||||
ItemEventInfo(int ticks, int index, int kart_id, int16_t ttr)
|
||||
: m_ticks(ticks), m_index(index), m_kart_id(kart_id),
|
||||
m_ticks_till_return(ttr)
|
||||
{
|
||||
m_type = IEI_COLLECT;
|
||||
} // ItemEventInfo(collected existing item)
|
||||
@ -69,14 +76,15 @@ public:
|
||||
*/
|
||||
ItemEventInfo(int ticks, ItemState::ItemType type, int index,
|
||||
int kart_id, const Vec3 &xyz)
|
||||
: m_ticks(ticks), m_index(index), m_kart_id(kart_id), m_xyz(xyz)
|
||||
: m_ticks(ticks), m_index(index), m_kart_id(kart_id), m_xyz(xyz),
|
||||
m_ticks_till_return(0)
|
||||
{
|
||||
m_type = IEI_NEW;
|
||||
} // ItemEventInfo(new item)
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/** Constructor for switching items. */
|
||||
ItemEventInfo(int ticks) : m_ticks(ticks)
|
||||
ItemEventInfo(int ticks) : m_ticks(ticks), m_ticks_till_return(0)
|
||||
{
|
||||
m_type = IEI_SWITCH;
|
||||
} // ItemEventInfo(switch)
|
||||
@ -116,6 +124,9 @@ public:
|
||||
return m_xyz;
|
||||
} // getXYZ
|
||||
// --------------------------------------------------------------------
|
||||
/** Returns the ticks till return, used only by collection events. */
|
||||
int getTicksTillReturn() const { return m_ticks_till_return; }
|
||||
// --------------------------------------------------------------------
|
||||
/** Returns the type of this item. Note at this stage only bubble gums
|
||||
* can be created during a race. */
|
||||
ItemState::ItemType getNewItemType() const
|
||||
|
@ -226,13 +226,15 @@ unsigned int ItemManager::insertItem(Item *item)
|
||||
// previously deleted entry, otherwise at the end.
|
||||
int index = -1;
|
||||
for(index=(int)m_all_items.size()-1; index>=0 && m_all_items[index]; index--) {}
|
||||
|
||||
if(index==-1) index = (int)m_all_items.size();
|
||||
|
||||
if(index<(int)m_all_items.size())
|
||||
m_all_items[index] = item;
|
||||
else
|
||||
if (index == -1)
|
||||
{
|
||||
index = (int)m_all_items.size();
|
||||
m_all_items.push_back(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_all_items[index] = item;
|
||||
}
|
||||
item->setItemId(index);
|
||||
|
||||
// Now insert into the appropriate quad list, if there is a quad list
|
||||
@ -286,9 +288,7 @@ Item* ItemManager::dropNewItem(ItemState::ItemType type,
|
||||
}
|
||||
|
||||
Item* item = new Item(type, pos, normal, m_item_mesh[mesh_type],
|
||||
m_item_lowres_mesh[mesh_type]);
|
||||
|
||||
if(kart != NULL) item->setParent(kart);
|
||||
m_item_lowres_mesh[mesh_type], /*prev_owner*/kart);
|
||||
insertItem(item);
|
||||
if(m_switch_ticks>=0)
|
||||
{
|
||||
@ -318,7 +318,7 @@ Item* ItemManager::placeItem(ItemState::ItemType type, const Vec3& xyz,
|
||||
ItemState::ItemType mesh_type = type;
|
||||
|
||||
Item* item = new Item(type, xyz, normal, m_item_mesh[mesh_type],
|
||||
m_item_lowres_mesh[mesh_type]);
|
||||
m_item_lowres_mesh[mesh_type], /*prev_owner*/NULL);
|
||||
|
||||
insertItem(item);
|
||||
if (m_switch_ticks >= 0)
|
||||
@ -354,7 +354,7 @@ Item* ItemManager::placeTrigger(const Vec3& xyz, float distance,
|
||||
* \param item The item that was collected.
|
||||
* \param kart The kart that collected the item.
|
||||
*/
|
||||
void ItemManager::collectedItem(Item *item, AbstractKart *kart)
|
||||
void ItemManager::collectedItem(ItemState *item, AbstractKart *kart)
|
||||
{
|
||||
assert(item);
|
||||
// Spare tire karts don't collect items
|
||||
|
@ -133,7 +133,7 @@ public:
|
||||
void updateGraphics (float dt);
|
||||
void checkItemHit (AbstractKart* kart);
|
||||
void reset ();
|
||||
virtual void collectedItem (Item *item, AbstractKart *kart);
|
||||
virtual void collectedItem (ItemState *item, AbstractKart *kart);
|
||||
void switchItems ();
|
||||
bool areItemSwitched() { return (m_switch_ticks > 0); }
|
||||
bool randomItemsForArena(const AlignedArray<btTransform>& pos);
|
||||
|
@ -95,17 +95,18 @@ void NetworkItemManager::initClientConfirmState()
|
||||
* \param item The item that was collected.
|
||||
* \param kart The kart that collected the item.
|
||||
*/
|
||||
void NetworkItemManager::collectedItem(Item *item, AbstractKart *kart)
|
||||
void NetworkItemManager::collectedItem(ItemState *item, AbstractKart *kart)
|
||||
{
|
||||
if(NetworkConfig::get()->isServer())
|
||||
{
|
||||
ItemManager::collectedItem(item, kart);
|
||||
// The server saves the collected item as item event info
|
||||
m_item_events.lock();
|
||||
m_item_events.getData().emplace_back(World::getWorld()->getTicksSinceStart(),
|
||||
item->getItemId(),
|
||||
kart->getWorldKartId());
|
||||
item->getItemId(),
|
||||
kart->getWorldKartId(),
|
||||
item->getTicksTillReturn());
|
||||
m_item_events.unlock();
|
||||
ItemManager::collectedItem(item, kart);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -142,7 +143,7 @@ Item* NetworkItemManager::dropNewItem(ItemState::ItemType type,
|
||||
kart->getXYZ() );
|
||||
m_item_events.unlock();
|
||||
return item;
|
||||
} // newItem
|
||||
} // dropNewItem
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called by the GameProtocol when a confirmation for an item event is
|
||||
@ -237,9 +238,9 @@ void NetworkItemManager::forwardTime(int ticks)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Restores the state of the items to the current world time. It takes the
|
||||
* last saved
|
||||
|
||||
* using exactly 'count' bytes of the message.
|
||||
* last saved confirmed state, applies any updates from the server, and
|
||||
* then syncs up the confirmed state to the in-race items.
|
||||
* It uses exactly 'count' bytes of the message.
|
||||
* \param buffer the state content.
|
||||
* \param count Number of bytes used for this state.
|
||||
*/
|
||||
@ -267,6 +268,7 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
// From here the replay can happen.
|
||||
|
||||
// 1) Remove predicted items:
|
||||
// --------------------------
|
||||
for (unsigned int i=0; i<m_all_items.size(); i++)
|
||||
{
|
||||
Item *item = m_all_items[i];
|
||||
@ -274,20 +276,22 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
{
|
||||
deleteItem(item);
|
||||
}
|
||||
}
|
||||
} // for i in m_all_items
|
||||
|
||||
// 2) Apply all events to current confirmed state:
|
||||
// -----------------------------------------------
|
||||
World *world = World::getWorld();
|
||||
int current_time = m_confirmed_state_time;
|
||||
bool has_state = count > 0;
|
||||
while(count > 0)
|
||||
{
|
||||
// 1) Decode the event in the message
|
||||
// ----------------------------------
|
||||
// 2.1) Decode the event in the message
|
||||
// ------------------------------------
|
||||
ItemEventInfo iei(buffer, &count);
|
||||
|
||||
// 2) If the event needs to be applied, forward
|
||||
// the time to the time of this event:
|
||||
// --------------------------------------------
|
||||
// 2.2) If the event needs to be applied, forward
|
||||
// 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
|
||||
// the server because it has not yet received confirmation from all
|
||||
@ -297,13 +301,35 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
// Forward the saved state:
|
||||
if (dt>0) forwardTime(dt);
|
||||
|
||||
// TODO: apply the various events types, atm only collection is supported:
|
||||
// TODO: apply the various events types, atm only collection
|
||||
// and new items are supported.
|
||||
if(iei.isItemCollection())
|
||||
{
|
||||
int index = iei.getIndex();
|
||||
// An item on the track was collected:
|
||||
AbstractKart *kart = World::getWorld()->getKart(iei.getKartId());
|
||||
m_confirmed_state[index]->collected(kart);
|
||||
AbstractKart *kart = world->getKart(iei.getKartId());
|
||||
|
||||
// The world clock was set by the RewindManager to be the time
|
||||
// of the state we are rewinding to. But this confirmed collection
|
||||
// event happened in the past (we are replaying item events since
|
||||
// the last confirmed state in order to get a new confirmed state).
|
||||
// So we need to reset the clock to the time at which this event
|
||||
// happened so that (e.g.) kart can use the right time (for
|
||||
// example, bubble gum torque depends on time, and would be wrong
|
||||
// otherwise resulting in stuttering).
|
||||
int old_time = world->getTicksSinceStart(); // Save time we rewind to
|
||||
world->setTicksForRewind(iei.getTicks()); // Set time of event
|
||||
|
||||
if (m_confirmed_state[index] != NULL)
|
||||
{
|
||||
m_confirmed_state[index]->collected(kart);// Collect item
|
||||
// Reset till ticks return from state (required for eating banana with bomb)
|
||||
int ttr = iei.getTicksTillReturn();
|
||||
m_confirmed_state[index]->setTicksTillReturn(ttr);
|
||||
}
|
||||
|
||||
world->setTicksForRewind(old_time); // Set time to rewind-to
|
||||
|
||||
if (m_confirmed_state[index]->isUsedUp())
|
||||
{
|
||||
delete m_confirmed_state[index];
|
||||
@ -312,9 +338,9 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
}
|
||||
else if(iei.isNewItem())
|
||||
{
|
||||
AbstractKart *kart = World::getWorld()->getKart(iei.getKartId());
|
||||
ItemState *is = new ItemState(iei.getNewItemType(), iei.getIndex(),
|
||||
kart);
|
||||
AbstractKart *kart = world->getKart(iei.getKartId());
|
||||
ItemState *is = new ItemState(iei.getNewItemType(), kart,
|
||||
iei.getIndex() );
|
||||
is->initItem(iei.getNewItemType(), iei.getXYZ());
|
||||
if (m_confirmed_state.size() <= is->getItemId())
|
||||
{
|
||||
@ -325,29 +351,34 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
if (m_confirmed_state[is->getItemId()] == NULL)
|
||||
m_confirmed_state[is->getItemId()] = is;
|
||||
else
|
||||
{
|
||||
*m_confirmed_state[is->getItemId()] = *is;
|
||||
delete is;
|
||||
}
|
||||
}
|
||||
}
|
||||
current_time = iei.getTicks();
|
||||
} // while count >0
|
||||
|
||||
// Inform the server which events have been received.
|
||||
// Inform the server which events have been received (if there has
|
||||
// been any updates - no need to send messages if nothing has changed)
|
||||
|
||||
if (has_state)
|
||||
{
|
||||
if (auto gp = GameProtocol::lock())
|
||||
gp->sendItemEventConfirmation(World::getWorld()->getTicksSinceStart());
|
||||
gp->sendItemEventConfirmation(world->getTicksSinceStart());
|
||||
}
|
||||
|
||||
// Forward the confirmed item state to the world time:
|
||||
int dt = World::getWorld()->getTicksSinceStart() - current_time;
|
||||
int dt = world->getTicksSinceStart() - current_time;
|
||||
if(dt>0) forwardTime(dt);
|
||||
|
||||
// Restore the state to the current world time:
|
||||
// ============================================
|
||||
// 3. Restore the state to the current world time:
|
||||
// ===============================================
|
||||
|
||||
for(unsigned int i=0; i<m_confirmed_state.size(); i++)
|
||||
{
|
||||
Item *item = m_all_items[i];
|
||||
Item *item = i < m_all_items.size() ? m_all_items[i] : NULL;
|
||||
const ItemState *is = m_confirmed_state[i];
|
||||
if (is && item)
|
||||
*(ItemState*)item = *is;
|
||||
@ -356,18 +387,33 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
Vec3 xyz = is->getXYZ();
|
||||
Item *item_new = dropNewItem(is->getType(), is->getPreviousOwner(),
|
||||
&xyz);
|
||||
if (i != item_new->getItemId())
|
||||
{
|
||||
// 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;
|
||||
m_all_items[i] = item_new;
|
||||
item_new->setItemId(i);
|
||||
}
|
||||
item_new->setPredicted(false);
|
||||
item_new->setItemId(i);
|
||||
m_all_items[i] = item_new;
|
||||
item_new->setDeactivatedTicks(is->getDeactivatedTicks());
|
||||
*((ItemState*)m_all_items[i]) = *is;
|
||||
}
|
||||
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::getWorld()->getTicksSinceStart();
|
||||
m_confirmed_state_time = world->getTicksSinceStart();
|
||||
} // restoreState
|
||||
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
virtual void reset() OVERRIDE;
|
||||
virtual void setItemConfirmationTime(std::weak_ptr<STKPeer> peer,
|
||||
int ticks) OVERRIDE;
|
||||
virtual void collectedItem(Item *item, AbstractKart *kart) OVERRIDE;
|
||||
virtual void collectedItem(ItemState *item, AbstractKart *kart) OVERRIDE;
|
||||
virtual Item* dropNewItem(ItemState::ItemType type, const AbstractKart *kart,
|
||||
const Vec3 *xyz=NULL) OVERRIDE;
|
||||
virtual BareNetworkString* saveState(std::vector<std::string>* ru)
|
||||
|
@ -561,11 +561,6 @@ void Powerup::hitBonusBox(const ItemState &item_state)
|
||||
|
||||
new_powerup = powerup_manager->getRandomPowerup(position, &n,
|
||||
random_number);
|
||||
// FIXME Disable switch and bubblegum for now in network
|
||||
if (NetworkConfig::get()->isNetworking() &&
|
||||
(new_powerup == PowerupManager::POWERUP_BUBBLEGUM ||
|
||||
new_powerup == PowerupManager::POWERUP_SWITCH))
|
||||
new_powerup = PowerupManager::POWERUP_BOWLING;
|
||||
|
||||
// Always add a new powerup in ITEM_MODE_NEW (or if the kart
|
||||
// doesn't have a powerup atm).
|
||||
|
@ -1554,7 +1554,7 @@ void Kart::update(int ticks)
|
||||
"v(16-18) %f %f %f steerf(20) %f maxangle(22) %f speed(24) %f "
|
||||
"steering(26-27) %f %f clock(29) %lf skidstate(31) %d factor(33) %f "
|
||||
"maxspeed(35) %f engf(37) %f braketick(39) %d brakes(41) %d heading(43) %f "
|
||||
"noderot(45) %f suslen %f",
|
||||
"bubticks(45) %d bubtor(47) %f",
|
||||
getIdent().c_str(),
|
||||
World::getWorld()->getTime(), World::getWorld()->getTicksSinceStart(),
|
||||
getXYZ().getX(), getXYZ().getY(), getXYZ().getZ(),
|
||||
@ -1575,8 +1575,8 @@ void Kart::update(int ticks)
|
||||
m_brake_ticks, //39
|
||||
m_controls.getButtonsCompressed(), //41
|
||||
getHeading(), //43
|
||||
m_node->getAbsoluteTransformation().getRotationDegrees().Y, //45
|
||||
m_vehicle->getWheelInfo(0).m_raycastInfo.m_suspensionLength
|
||||
m_bubblegum_ticks, // 45
|
||||
m_bubblegum_torque // 47
|
||||
);
|
||||
#endif
|
||||
// After the physics step was done, the position of the wheels (as stored
|
||||
|
@ -159,7 +159,8 @@ const std::string& EasterEggHunt::getIdent() const
|
||||
/** Called when a kart has collected an egg.
|
||||
* \param kart The kart that collected an egg.
|
||||
*/
|
||||
void EasterEggHunt::collectedItem(const AbstractKart *kart, const Item *item)
|
||||
void EasterEggHunt::collectedItem(const AbstractKart *kart,
|
||||
const ItemState *item )
|
||||
{
|
||||
if(item->getType() != ItemState::ITEM_EASTER_EGG) return;
|
||||
|
||||
|
@ -66,7 +66,7 @@ public:
|
||||
virtual void getKartsDisplayInfo(
|
||||
std::vector<RaceGUIBase::KartIconDisplayInfo> *info) OVERRIDE;
|
||||
virtual void collectedItem(const AbstractKart *kart,
|
||||
const Item *item ) OVERRIDE;
|
||||
const ItemState *item ) OVERRIDE;
|
||||
void collectedEasterEggGhost(int world_id);
|
||||
|
||||
const int numberOfEggsFound() { return m_eggs_found; }
|
||||
|
@ -42,7 +42,7 @@
|
||||
class AbstractKart;
|
||||
class btRigidBody;
|
||||
class Controller;
|
||||
class Item;
|
||||
class ItemState;
|
||||
class PhysicalObject;
|
||||
|
||||
namespace Scripting
|
||||
@ -263,7 +263,8 @@ public:
|
||||
int *amount );
|
||||
// ------------------------------------------------------------------------
|
||||
/** Receives notification if an item is collected. Used for easter eggs. */
|
||||
virtual void collectedItem(const AbstractKart *kart, const Item *item) {}
|
||||
virtual void collectedItem(const AbstractKart *kart,
|
||||
const ItemState *item ) {}
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void endRaceEarly() { return; }
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -154,8 +154,27 @@ void RewindManager::saveState()
|
||||
|
||||
m_overall_state_size = 0;
|
||||
std::vector<std::string> rewinder_using;
|
||||
|
||||
// We must save the item state first (so that it is restored first),
|
||||
// otherwise state updates for a kart could be overwritten by
|
||||
// e.g. simulating the item collection later (which resets bubblegum
|
||||
// counter).
|
||||
BareNetworkString* buffer = NULL;
|
||||
if(auto r = m_all_rewinder["N"].lock())
|
||||
buffer = r->saveState(&rewinder_using);
|
||||
if (buffer)
|
||||
{
|
||||
m_overall_state_size += buffer->size();
|
||||
gp->addState(buffer);
|
||||
}
|
||||
delete buffer; // buffer can be freed
|
||||
|
||||
for (auto& p : m_all_rewinder)
|
||||
{
|
||||
// The Network ItemManager was saved first before this loop,
|
||||
// so skip it here.
|
||||
if(p.first=="N") continue;
|
||||
|
||||
// TODO: check if it's worth passing in a sufficiently large buffer from
|
||||
// GameProtocol - this would save the copy operation.
|
||||
BareNetworkString* buffer = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user