package server;
import client.SkillFactory;
import client.ZZMSEvent;
import client.inventory.MapleAndroid;
import client.inventory.MaplePet;
import constants.GameConstants;
import constants.ServerConfig;
import constants.ServerConstants;
import constants.WorldConstants;
import database.DatabaseConnection;
import handling.cashshop.CashShopServer;
import handling.channel.ChannelServer;
import handling.channel.MapleDojoRanking;
import handling.channel.MapleGuildRanking;
import handling.farm.FarmServer;
import handling.login.LoginServer;
import handling.world.World;
import handling.world.guild.MapleGuild;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.concurrent.atomic.AtomicInteger;
import server.Timer.BuffTimer;
import server.Timer.CloneTimer;
import server.Timer.EtcTimer;
import server.Timer.EventTimer;
import server.Timer.MapTimer;
import server.Timer.PingTimer;
import server.Timer.WorldTimer;
import server.life.MapleLifeFactory;
import server.life.MapleMonsterInformationProvider;
import server.life.PlayerNPC;
import server.maps.MapleMapFactory;
import server.quest.MapleQuest;
import tools.MapleAESOFB;
public class Start {
public static long startTime = System.currentTimeMillis();
public static final Start instance = new Start();
public static AtomicInteger CompletedLoadingThreads = new AtomicInteger(0);
public void run() throws InterruptedException, IOException {
long start = System.currentTimeMillis();
if (ServerConfig.ADMIN_ONLY || ServerConstants.USE_LOCALHOST) {
System.out.println("Admin Only mode is active.");
}
try (PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("UPDATE accounts SET loggedin = 0")) {
ps.executeUpdate();
} catch (SQLException ex) {
throw new RuntimeException("運行時錯誤: 無法連接到MySQL數據庫服務器 - " + ex);
}
System.out.println("正在加載" + ServerConfig.SERVER_NAME + "伺服器");
World.init();
System.out.println("\r\n主機: " + ServerConfig.IP + ":" + LoginServer.PORT);
System.out.println("支援遊戲版本: " + ServerConstants.MAPLE_TYPE + "的" + ServerConstants.MAPLE_VERSION + "." + ServerConstants.MAPLE_PATCH + "版本" + (ServerConstants.TESPIA ? "測試機" : "") + "用戶端");
System.out.println("主伺服器名稱: " + WorldConstants.getMainWorld().name());
System.out.println("");
if (ServerConstants.MAPLE_TYPE == ServerConstants.MapleType.GLOBAL) {
boolean encryptionfound = false;
for (MapleAESOFB.EncryptionKey encryptkey : MapleAESOFB.EncryptionKey.values()) {
if (("V" + ServerConstants.MAPLE_VERSION).equals(encryptkey.name())) {
System.out.println("Packet Encryption: Up-To-Date!");
encryptionfound = true;
break;
}
}
if (!encryptionfound) {
System.out.println("Cannot find the packet encryption for the Maple Version you entered. Using the previous packet encryption instead.");
}
}
runThread();
loadData(false);
LoginServer.run_startup_configurations();
ChannelServer.startChannel_Main();
CashShopServer.run_startup_configurations();
if (ServerConstants.MAPLE_TYPE == ServerConstants.MapleType.GLOBAL) {
FarmServer.run_startup_configurations();
}
World.registerRespawn();
Runtime.getRuntime().addShutdownHook(new Thread(new Shutdown()));
System.out.println("加載地圖元素");
//加載自訂地圖元素
MapleMapFactory.loadCustomLife(false);
//加載玩家NPC
PlayerNPC.loadAll();
LoginServer.setOn();
//System.out.println("Event Script List: " + ServerConfig.getEventList());
if (ServerConfig.LOG_PACKETS) {
System.out.println("數據包日誌模式已啟用");
}
if (ServerConfig.USE_FIXED_IV) {
System.out.println("反抓包功能已啟用");
}
long now = System.currentTimeMillis() - start;
long seconds = now / 1000;
long ms = now % 1000;
System.out.println("\r\n加載完成, 耗時: " + seconds + "秒" + ms + "毫秒");
System.gc();
PingTimer.getInstance().register(System::gc, 1800000); // 每30分鐘釋放一次記憶體
}
public static void runThread() {
System.out.print("正在加載線程");
WorldTimer.getInstance().start();
EtcTimer.getInstance().start();
MapTimer.getInstance().start();
CloneTimer.getInstance().start();
System.out.print(/*"\u25CF"*/".");
EventTimer.getInstance().start();
BuffTimer.getInstance().start();
PingTimer.getInstance().start();
ZZMSEvent.start();
System.out.println("完成!\r\n");
}
public static void loadData(boolean reload) {
System.out.println("載入數據(因為數據量大可能比較久而且記憶體消耗會飆升)");
//加載等級經驗
System.out.println("加載等級經驗數據");
GameConstants.LoadEXP();
System.out.println("加載排名訊息數據");
//加載道場拍排名
MapleDojoRanking.getInstance().load(reload);
//加載公會排名
MapleGuildRanking.getInstance().load(reload);
//加載排名
RankingWorker.run();
System.out.println("加載公會數據并清理不存在公會/寵物/機器人");
//清理已經刪除的寵物
MaplePet.clearPet();
//清理已經刪除的機器人
MapleAndroid.clearAndroid();
//加載公會並且清理無人公會
MapleGuild.loadAll();
//加載家族(家族功能已去掉)
// MapleFamily.loadAll();
System.out.println("加載任務數據");
//加載任務訊息
MapleLifeFactory.loadQuestCounts(reload);
//加載轉存到數據庫的任務訊息
MapleQuest.initQuests(reload);
System.out.println("加載掉寶數據");
//加載掉寶訊息
MapleMonsterInformationProvider.getInstance().addExtra();
//加載全域掉寶數據
MapleMonsterInformationProvider.getInstance().load();
System.out.println("加載道具數據");
//加載道具訊息(從WZ)
MapleItemInformationProvider.getInstance().runEtc(reload);
//加載道具訊息(從SQL)
MapleItemInformationProvider.getInstance().runItems(reload);
//加載髮型臉型
MapleItemInformationProvider.getInstance().loadHairFace(reload);
System.out.println("加載技能數據");
//加載技能
SkillFactory.load(reload);
System.out.println("加載角色卡數據");
//加載角色卡訊息
CharacterCardFactory.getInstance().initialize(reload);
System.out.println("loadSpeedRuns");
//?
SpeedRunner.loadSpeedRuns(reload);
System.out.println("加載商城道具數據");
//加載商城道具訊息
CashItemFactory.getInstance().initialize(reload);
System.out.println("數據載入完成!\r\n");
}
public static class Shutdown implements Runnable {
@Override
public void run() {
ShutdownServer.getInstance().run();
}
}
public static void main(final String args[]) throws InterruptedException, IOException {
instance.run();
}
}