package events.base;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import events.base.data.EventHolder;
import events.base.instances.PvPEventInstance;
import events.base.instances.PvPEventInstance.EventStatus;
import l2p.commons.threading.RunnableImpl;
import l2p.commons.time.cron.SchedulingPattern;
import l2p.commons.util.Rnd;
import l2p.gameserver.ThreadPoolManager;
import l2p.gameserver.model.entity.events.EventType;
import l2p.gameserver.model.entity.olympiad.Olympiad;
import l2p.gameserver.scripts.ScriptFile;
import l2p.gameserver.utils.Util;
/**
* @author Gaikotsu
*/
public class PvPEventManager implements ScriptFile
{
private static final Logger _log = LoggerFactory.getLogger(PvPEventManager.class);
// Список классов всех PvP-эвентов с их текущим статусом для проверок на то, не запущен ли в данный момент какой-то из них
private static Map<String, EventStatus> _status = new HashMap<>();
private static ScheduledFuture<?> _startEventTask = null;
@Override
public void onLoad()
{
scheduleNextStart();
}
@Override
public void onShutdown()
{
stopTask();
}
/*
* Проверяет возможность запуска эвента в данный момент времени
*/
public static boolean checkStartConditions()
{
if (_status.values().stream().anyMatch(s -> s != EventStatus.IDLE))
{
_log.info("PvPEventManager: Event not started, reason - other event is in progress.");
return false;
}
if (EventHolder.getInstance().getParam("checkOlympiad", false) && Olympiad.inCompPeriod())
{
_log.info("PvPEventManager: Event not started, reason - olympiad is in progress.");
return false;
}
return true;
}
public static void setStatus(String name, EventStatus status)
{
_status.put(name, status);
}
private static void stopTask()
{
if (_startEventTask != null)
{
_startEventTask.cancel(false);
_startEventTask = null;
}
}
/*
* Возвращает время следующего запуска эвента
*/
private static long getNextStartTime()
{
if (EventHolder.getInstance().getTimes().isEmpty())
return 0;
long time = Long.MAX_VALUE;
for (String pattern : EventHolder.getInstance().getTimes())
time = Math.min(time, new SchedulingPattern(pattern).next(System.currentTimeMillis()));
if (time == Long.MAX_VALUE)
{
_log.warn("WTF? Next start time equals max long value.");
return 0;
}
return time;
}
private static void scheduleNextStart()
{
long nextTime = getNextStartTime();
if (nextTime > 0)
{
stopTask();
_startEventTask = ThreadPoolManager.getInstance().schedule(new StartEventTask(), nextTime - System.currentTimeMillis());
_log.info("PvPEventManager: Next event started on " + Util.formatDate(nextTime));
}
}
private static class StartEventTask extends RunnableImpl
{
@Override
public void runImpl()
{
ThreadPoolManager.getInstance().schedule(() -> {
scheduleNextStart();
}, 90000L);
if (!Rnd.chance(EventHolder.getInstance().getParam("startChance", 0)))
{
_log.info("PvPEventManager: Event not started, reason - starting chance failed.");
return;
}
List<PvPEventInstance> activeEvents = new ArrayList<>();
EventHolder.getInstance().getEvents(EventType.PVP_EVENT).stream().filter(e -> e.getEvent().isActive()).forEach(e -> activeEvents.add((PvPEventInstance) e.getEvent()));
if (activeEvents.isEmpty())
{
_log.info("PvPEventManager: Event not started, reason - no enabled events.");
return;
}
if (!checkStartConditions())
return;
PvPEventInstance event = activeEvents.get(Rnd.get(activeEvents.size()));
if (event.getConfig().isUseRounds())
event.startRound(null, 1, 2, true);
else
event.startRound(null, 0, 0, true);
_log.info("PvPEventManager: Event '" + event.getName(true) + "' started.");
}
}
}