Core/Vehicles: Fixed crash in RemovePendingEventsForSeat - changed _pendingJoinEvents container from deque to list as deque invalidates all iterators pointing to the container (including .end()) when performing erase

This commit is contained in:
Shauren
2013-02-23 19:24:59 +01:00
parent 49b609d2e4
commit b1d43f837a
2 changed files with 14 additions and 42 deletions

View File

@@ -436,10 +436,6 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId)
// exits the vehicle will dismiss. That's why the actual adding the passenger to the vehicle is scheduled
// asynchronously, so it can be cancelled easily in case the vehicle is uninstalled meanwhile.
SeatMap::iterator seat;
VehicleJoinEvent* e = new VehicleJoinEvent(this, unit);
unit->m_Events.AddEvent(e, unit->m_Events.CalculateTime(0));
_pendingJoinEvents.push_back(e);
if (seatId < 0) // no specific seat requirement
{
for (seat = Seats.begin(); seat != Seats.end(); ++seat)
@@ -447,23 +443,22 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId)
break;
if (seat == Seats.end()) // no available seat
{
CancelJoinEvent(e);
return false;
}
e->Seat = seat;
VehicleJoinEvent* e = new VehicleJoinEvent(this, unit, seat);
_pendingJoinEvents.push_back(e);
unit->m_Events.AddEvent(e, unit->m_Events.CalculateTime(0));
}
else
{
seat = Seats.find(seatId);
if (seat == Seats.end())
{
CancelJoinEvent(e);
return false;
}
e->Seat = seat;
VehicleJoinEvent* e = new VehicleJoinEvent(this, unit, seat);
_pendingJoinEvents.push_back(e);
unit->m_Events.AddEvent(e, unit->m_Events.CalculateTime(0));
if (seat->second.Passenger)
{
Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger);
@@ -687,25 +682,6 @@ void Vehicle::CalculatePassengerOffset(float& x, float& y, float& z, float& o)
x = (inx + iny * tan(GetBase()->GetOrientation())) / (cos(GetBase()->GetOrientation()) + std::sin(GetBase()->GetOrientation()) * tan(GetBase()->GetOrientation()));
}
/**
* @fn void Vehicle::CancelJoinEvent(VehicleJoinEvent* e)
*
* @brief Aborts delayed @VehicleJoinEvent objects.
* Implies that the related unit will not be boarding the vehicle after all.
*
* @author Machiavelli
* @date 17-2-2013
*
* @param [in,out] e The VehicleJoinEvent* to process.
*/
void Vehicle::CancelJoinEvent(VehicleJoinEvent* e)
{
ASSERT(_pendingJoinEvents.back() == e);
e->to_Abort = true;
_pendingJoinEvents.pop_back();
}
/**
* @fn void Vehicle::RemovePendingEvent(VehicleJoinEvent* e)
*
@@ -721,7 +697,7 @@ void Vehicle::CancelJoinEvent(VehicleJoinEvent* e)
void Vehicle::RemovePendingEvent(VehicleJoinEvent* e)
{
for (std::deque<VehicleJoinEvent*>::iterator itr = _pendingJoinEvents.begin(); itr != _pendingJoinEvents.end(); ++itr)
for (PendingJoinEventContainer::iterator itr = _pendingJoinEvents.begin(); itr != _pendingJoinEvents.end(); ++itr)
{
if (*itr == e)
{
@@ -744,7 +720,7 @@ void Vehicle::RemovePendingEvent(VehicleJoinEvent* e)
void Vehicle::RemovePendingEventsForSeat(int8 seatId)
{
for (std::deque<VehicleJoinEvent*>::iterator itr = _pendingJoinEvents.begin(); itr != _pendingJoinEvents.end();)
for (PendingJoinEventContainer::iterator itr = _pendingJoinEvents.begin(); itr != _pendingJoinEvents.end();)
{
if ((*itr)->Seat->first == seatId)
{

View File

@@ -23,7 +23,7 @@
#include "Object.h"
#include "VehicleDefines.h"
#include "Unit.h"
#include <deque>
#include <list>
struct VehicleEntry;
class Unit;
@@ -63,12 +63,8 @@ class Vehicle : public TransportBase
void RelocatePassengers();
void RemoveAllPassengers();
void Dismiss();
void TeleportVehicle(float x, float y, float z, float ang);
bool IsVehicleInUse() { return Seats.begin() != Seats.end(); }
void SetLastShootPos(Position const& pos) { m_lastShootPos.Relocate(pos); }
Position GetLastShootPos() { return m_lastShootPos; }
SeatMap Seats; ///< The collection of all seats on the vehicle. Including vacant ones.
VehicleSeatEntry const* GetSeatForPassenger(Unit* passenger);
@@ -94,7 +90,6 @@ class Vehicle : public TransportBase
/// This method transforms supplied global coordinates into local offsets
void CalculatePassengerOffset(float& x, float& y, float& z, float& o);
void CancelJoinEvent(VehicleJoinEvent* e);
void RemovePendingEvent(VehicleJoinEvent* e);
void RemovePendingEventsForSeat(int8 seatId);
@@ -105,15 +100,16 @@ class Vehicle : public TransportBase
uint32 _creatureEntry; ///< Can be different than the entry of _me in case of players
Status _status; ///< Internal variable for sanity checks
Position m_lastShootPos;
std::deque<VehicleJoinEvent*> _pendingJoinEvents; ///< Collection of delayed join events for prospective passengers
typedef std::list<VehicleJoinEvent*> PendingJoinEventContainer;
PendingJoinEventContainer _pendingJoinEvents; ///< Collection of delayed join events for prospective passengers
};
class VehicleJoinEvent : public BasicEvent
{
friend class Vehicle;
protected:
VehicleJoinEvent(Vehicle* v, Unit* u) : Target(v), Passenger(u), Seat(Target->Seats.end()) {}
VehicleJoinEvent(Vehicle* v, Unit* u, SeatMap::iterator seat) : Target(v), Passenger(u), Seat(seat) {}
~VehicleJoinEvent() { Target->RemovePendingEvent(this); }
bool Execute(uint64, uint32);
void Abort(uint64);