/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#include "EventMap.h"
#include "Random.h"
void EventMap::Reset()
{
_eventMap.clear();
_time = TimePoint::min();
_phaseMask = 0;
}
void EventMap::SetPhase(PhaseIndex phase)
{
if (!phase)
_phaseMask = 0;
else if (phase <= sizeof(PhaseMask) * 8)
_phaseMask = PhaseMask(1u << (phase - 1u));
}
void EventMap::ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group /*= 0*/, PhaseIndex phase /*= 0*/)
{
if (group > sizeof(GroupMask) * 8)
return;
if (phase > sizeof(PhaseMask) * 8)
return;
_eventMap.insert(EventStore::value_type(_time + time, Event(eventId, group, phase)));
}
void EventMap::ScheduleEvent(EventId eventId, Milliseconds minTime, Milliseconds maxTime, GroupIndex group /*= 0*/, PhaseIndex phase /*= 0*/)
{
ScheduleEvent(eventId, randtime(minTime, maxTime), group, phase);
}
void EventMap::RescheduleEvent(EventId eventId, Milliseconds time, GroupIndex group, PhaseIndex phase)
{
CancelEvent(eventId);
ScheduleEvent(eventId, time, group, phase);
}
void EventMap::RescheduleEvent(EventId eventId, Milliseconds minTime, Milliseconds maxTime, GroupIndex group /*= 0*/, PhaseIndex phase /*= 0*/)
{
RescheduleEvent(eventId, randtime(minTime, maxTime), group, phase);
}
void EventMap::Repeat(Milliseconds time)
{
_eventMap.insert(EventStore::value_type(_time + time, _lastEvent));
}
void EventMap::Repeat(Milliseconds minTime, Milliseconds maxTime)
{
Repeat(randtime(minTime, maxTime));
}
EventMap::EventId EventMap::ExecuteEvent()
{
while (!Empty())
{
auto itr = _eventMap.begin();
if (itr->first > _time)
return 0;
else if (_phaseMask && itr->second._phaseMask && !(itr->second._phaseMask & _phaseMask))
_eventMap.erase(itr);
else
{
auto eventId = itr->second._id;
_lastEvent = itr->second;
_eventMap.erase(itr);
return eventId;
}
}
return 0;
}
void EventMap::DelayEvents(Milliseconds delay)
{
if (Empty())
return;
EventStore delayed = std::move(_eventMap);
for (auto itr = delayed.begin(); itr != delayed.end();)
{
EventStore::node_type node = delayed.extract(itr++);
node.key() = node.key() + delay;
_eventMap.insert(_eventMap.end(), std::move(node));
}
}
void EventMap::DelayEvents(Milliseconds delay, GroupIndex group)
{
if (!group || group > sizeof(GroupMask) * 8 || Empty())
return;
EventStore delayed;
for (auto itr = _eventMap.begin(); itr != _eventMap.end();)
{
if (itr->second._groupMask & GroupMask(1u << (group - 1u)))
{
delayed.insert(EventStore::value_type(itr->first + delay, itr->second));
_eventMap.erase(itr++);
}
else
++itr;
}
_eventMap.insert(delayed.begin(), delayed.end());
}
void EventMap::SetMinimalDelay(EventId eventId, Milliseconds delay)
{
if (Empty())
return;
for (auto itr = _eventMap.begin(); itr != _eventMap.end();)
{
if (eventId == itr->second._id)
{
if (itr->first < (_time + delay))
{
_eventMap.insert(EventStore::value_type(_time + delay, itr->second));
itr = _eventMap.erase(itr);
continue;
}
}
++itr;
}
}
void EventMap::CancelEvent(EventId eventId)
{
if (Empty())
return;
for (auto itr = _eventMap.begin(); itr != _eventMap.end();)
{
if (eventId == itr->second._id)
_eventMap.erase(itr++);
else
++itr;
}
}
void EventMap::CancelEventGroup(GroupIndex group)
{
if (!group || group > sizeof(GroupMask) * 8 || Empty())
return;
for (auto itr = _eventMap.begin(); itr != _eventMap.end();)
{
if (itr->second._groupMask & GroupMask(1u << (group - 1u)))
_eventMap.erase(itr++);
else
++itr;
}
}
Milliseconds EventMap::GetTimeUntilEvent(EventId eventId) const
{
for (auto const& [time, event] : _eventMap)
if (eventId == event._id)
return std::chrono::duration_cast(time - _time);
return Milliseconds::max();
}
bool EventMap::HasEventScheduled(EventId eventId) const
{
return GetTimeUntilEvent(eventId) != Milliseconds::max();
}