/* * Copyright (C) 2004-2015 L2J Server * * This file is part of L2J Server. * * L2J Server 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 3 of the License, or * (at your option) any later version. * * L2J Server 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 . */ package com.l2jserver.gameserver; import java.util.Calendar; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; import com.l2jserver.gameserver.instancemanager.DayNightSpawnManager; import com.l2jserver.gameserver.model.actor.L2Character; /** * Game Time controller class. * @author Forsaiken */ public final class GameTimeController extends Thread { private static final Logger _log = Logger.getLogger(GameTimeController.class.getName()); public static final int TICKS_PER_SECOND = 10; // not able to change this without checking through code public static final int MILLIS_IN_TICK = 1000 / TICKS_PER_SECOND; public static final int IG_DAYS_PER_DAY = 6; public static final int MILLIS_PER_IG_DAY = (3600000 * 24) / IG_DAYS_PER_DAY; public static final int SECONDS_PER_IG_DAY = MILLIS_PER_IG_DAY / 1000; public static final int MINUTES_PER_IG_DAY = SECONDS_PER_IG_DAY / 60; public static final int TICKS_PER_IG_DAY = SECONDS_PER_IG_DAY * TICKS_PER_SECOND; public static final int TICKS_SUN_STATE_CHANGE = TICKS_PER_IG_DAY / 4; private static GameTimeController _instance; private final Set _movingObjects = ConcurrentHashMap.newKeySet(); private final long _referenceTime; private GameTimeController() { super("GameTimeController"); super.setDaemon(true); super.setPriority(MAX_PRIORITY); final Calendar c = Calendar.getInstance(); c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); _referenceTime = c.getTimeInMillis(); super.start(); } public static final void init() { _instance = new GameTimeController(); } public final int getGameTime() { return (getGameTicks() % TICKS_PER_IG_DAY) / MILLIS_IN_TICK; } public final int getGameHour() { return getGameTime() / 60; } public final int getGameMinute() { return getGameTime() % 60; } public final boolean isNight() { return getGameHour() < 6; } /** * The true GameTime tick. Directly taken from current time. This represents the tick of the time. * @return */ public final int getGameTicks() { return (int) ((System.currentTimeMillis() - _referenceTime) / MILLIS_IN_TICK); } /** * Add a L2Character to movingObjects of GameTimeController. * @param cha The L2Character to add to movingObjects of GameTimeController */ public final void registerMovingObject(final L2Character cha) { if (cha == null) { return; } _movingObjects.add(cha); } /** * Move all L2Characters contained in movingObjects of GameTimeController.
* Concept :
* All L2Character in movement are identified in movingObjects of GameTimeController.
* Actions :
* */ private final void moveObjects() { _movingObjects.removeIf(L2Character::updatePosition); } public final void stopTimer() { super.interrupt(); _log.log(Level.INFO, "Stopping " + getClass().getSimpleName()); } @Override public final void run() { _log.log(Level.CONFIG, getClass().getSimpleName() + ": Started."); long nextTickTime, sleepTime; boolean isNight = isNight(); if (isNight) { ThreadPoolManager.getInstance().executeAi(() -> DayNightSpawnManager.getInstance().notifyChangeMode()); } while (true) { nextTickTime = ((System.currentTimeMillis() / MILLIS_IN_TICK) * MILLIS_IN_TICK) + 100; try { moveObjects(); } catch (final Throwable e) { _log.log(Level.WARNING, "", e); } sleepTime = nextTickTime - System.currentTimeMillis(); if (sleepTime > 0) { try { Thread.sleep(sleepTime); } catch (final InterruptedException e) { } } if (isNight() != isNight) { isNight = !isNight; ThreadPoolManager.getInstance().executeAi(() -> DayNightSpawnManager.getInstance().notifyChangeMode()); } } } public static final GameTimeController getInstance() { return _instance; } }