package server; import java.io.FileInputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.security.KeyStore; import java.text.DecimalFormat; import java.util.logging.Logger; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.filter.ssl.SslFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import server.database.DatabaseManager; import server.database.MongoCopy; import server.model.players.PlayerManager; import server.networking.ConnectionHandler; import server.util.ShutDownHook; import server.util.SimpleTimer; import server.util.SwConfig; import server.SpecialWeaponConfig; import server.model.players.Player; import server.model.players.PlayerManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; public class Server { public Server() { debugPercentFormat = new DecimalFormat("0.0#%"); engineTimer = new SimpleTimer(); debugTimer = new SimpleTimer(); acceptor.setHandler(new ConnectionHandler()); } public Server bind(int port) throws IOException { acceptor.bind(new InetSocketAddress(port)); return this; } public static void main(String[] args) throws IOException { SpecialWeaponConfig.loadConfig(); // Load JSON startPeriodicCheck(); // Start timer try { if (args[0].contains("live")) { Config.LIVE_SERVER = true; } } catch (Exception e) { } try { new Server().bind(PORT).start(); } catch (Exception e) { e.printStackTrace(); } Thread savePlayers = new Thread(() -> gameEngine.destruct()); Runtime.getRuntime().addShutdownHook(savePlayers); gameEngine = new GameEngine(); gameEngine.init(); System.out.println("Listening for connections on port " + Config.SERVER_PORT + "..."); try { while (!shutdownServer) { long startTime = System.currentTimeMillis(); engineTimer.reset(); if (updateTicks > 0) updateTicks--; if (updateTicks == 0) { shutdownServer = true; } gameEngine.update(); cycleTime = engineTimer.elapsed(); sleepTime = Config.SERVER_TICK_RATE - cycleTime; totalCycleTime += cycleTime; cycles++; debug(); long timeElapsed = System.currentTimeMillis() - startTime; if (timeElapsed < 100) { Thread.sleep(Config.SERVER_TICK_RATE - timeElapsed); } } } catch (Exception e) { e.printStackTrace(); } finally { gameEngine.destruct(); } } private static long cycleTime, cycles, totalCycleTime, sleepTime; private static SimpleTimer engineTimer, debugTimer; private static DecimalFormat debugPercentFormat; private static void debug() { if (debugTimer.elapsed() > 100*1000) { long averageCycleTime = totalCycleTime / cycles; System.out.println("Average Cycle Time: " + averageCycleTime + "ms"); double engineLoad = ((double) averageCycleTime / (double) Config.SERVER_TICK_RATE); System.out.println("Players online: " + PlayerManager.getInstance().getPlayerCount()+ ", engine load: "+ debugPercentFormat.format(engineLoad)); totalCycleTime = 0; cycles = 0; System.gc(); debugTimer.reset(); } } public void start() { logger.info("Starting server version "+Config.CLIENT_VERSION); } private static void startPeriodicCheck() { new Thread(() -> { while (true) { try { Thread.sleep(30000); // 30 seconds for (Player player : PlayerManager.getInstance().players) { if (player != null) { player.currentWeaponBonus = SpecialWeaponConfig.getDamageMultiplier( player.getEquipment().getPlayerWeapon(), player.skin); // Cache for applyDamage } } } catch (InterruptedException e) { System.err.println("Periodic check error: " + e); } } }).start(); } //provide logging details public static final Logger logger = Logger.getLogger(Server.class.getName()); //the port the server runs on private static final int PORT = Config.SERVER_PORT; //Socket acceptor private final IoAcceptor acceptor = new NioSocketAcceptor(); //main gameengine instance public static GameEngine gameEngine; //count down for updating server public static int updateTicks = -1; //shut down when set to true public static boolean shutdownServer = false; }