Files
Server/src/engine/server/world/WorldServer.java
T

746 lines
25 KiB
Java
Raw Normal View History

2022-04-30 09:41:17 -04:00
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.server.world;
import engine.InterestManagement.RealmMap;
import engine.InterestManagement.WorldGrid;
import engine.db.archive.DataWarehouse;
2024-03-15 10:58:01 -04:00
import engine.db.handlers.dbNPCHandler;
import engine.db.handlers.dbRuneBaseHandler;
2022-04-30 09:41:17 -04:00
import engine.exception.MsgSendException;
import engine.gameManager.*;
import engine.job.JobContainer;
import engine.job.JobScheduler;
import engine.jobs.LogoutCharacterJob;
2024-04-05 09:30:00 -04:00
import engine.mbEnums;
import engine.mbEnums.DispatchChannel;
import engine.mbEnums.MinionType;
import engine.mbEnums.SupportMsgType;
2023-08-03 08:27:08 -04:00
import engine.mobileAI.Threads.MobAIThread;
2024-05-04 13:18:34 -04:00
import engine.mobileAI.Threads.ReSpawner;
2022-04-30 09:41:17 -04:00
import engine.net.Network;
2024-04-06 15:30:35 -04:00
import engine.net.Protocol;
2022-04-30 09:41:17 -04:00
import engine.net.client.ClientConnection;
import engine.net.client.ClientConnectionManager;
import engine.net.client.msg.UpdateStateMsg;
import engine.net.client.msg.chat.ChatSystemMsg;
import engine.objects.*;
import engine.server.MBServerStatics;
2023-10-08 09:49:49 -04:00
import engine.util.MapLoader;
2022-04-30 09:41:17 -04:00
import engine.util.ThreadUtils;
import engine.workthreads.DisconnectTrashTask;
import engine.workthreads.HourlyJobThread;
import engine.workthreads.PurgeOprhans;
import engine.workthreads.WarehousePushThread;
import org.pmw.tinylog.Configurator;
import org.pmw.tinylog.Level;
import org.pmw.tinylog.Logger;
import org.pmw.tinylog.labelers.TimestampLabeler;
import org.pmw.tinylog.policies.StartupPolicy;
import org.pmw.tinylog.writers.RollingFileWriter;
import java.io.*;
import java.net.DatagramSocket;
2022-04-30 09:41:17 -04:00
import java.net.InetAddress;
import java.net.URL;
2022-04-30 09:41:17 -04:00
import java.nio.file.Files;
import java.nio.file.Paths;
2023-08-01 19:19:39 -05:00
import java.time.Duration;
2022-04-30 09:41:17 -04:00
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import static engine.gameManager.SimulationManager.SERVERHEARTBEAT;
import static java.lang.System.exit;
public class WorldServer {
2024-03-24 09:42:27 -04:00
public static int worldMapID = Integer.parseInt(ConfigManager.MB_WORLD_MAPID.getValue());
public static int worldRealmMap = Integer.parseInt(ConfigManager.MB_WORLD_REALMMAP.getValue());
2024-03-24 09:42:27 -04:00
public static int worldUUID = 1; // Root object in database
public static mbEnums.AccountStatus worldAccessLevel = mbEnums.AccountStatus.valueOf(ConfigManager.MB_WORLD_ACCESS_LVL.getValue());
2024-03-24 09:42:27 -04:00
private static LocalDateTime bootTime = LocalDateTime.now();
public boolean isRunning = false;
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Member variable declaration
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
public WorldServer() {
super();
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
public static void main(String[] args) {
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
WorldServer worldServer;
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Configure TinyLogger
Configurator.defaultConfig()
.addWriter(new RollingFileWriter("logs/world/world.txt", 30, new TimestampLabeler(), new StartupPolicy()))
.level(Level.DEBUG)
.formatPattern("{level} {date:yyyy-MM-dd HH:mm:ss.SSS} [{thread}] {class}.{method}({line}) : {message}")
.writingThread("main", 2)
.activate();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (ConfigManager.init() == false) {
Logger.error("ABORT! Missing config entry!");
return;
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
try {
2024-03-24 09:42:27 -04:00
worldServer = new WorldServer();
2022-04-30 09:41:17 -04:00
ConfigManager.serverType = mbEnums.ServerType.WORLDSERVER;
2024-03-24 09:42:27 -04:00
ConfigManager.worldServer = worldServer;
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
worldServer.init();
2024-03-24 09:42:27 -04:00
int retVal = worldServer.exec();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (retVal != 0)
Logger.error(
".exec() returned value: '" + retVal);
exit(retVal);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
} catch (Exception e) {
Logger.error(e.getMessage());
exit(1);
}
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
public static String getUptimeString() {
2024-03-24 09:42:27 -04:00
String outString = null;
java.time.Duration uptimeDuration;
String newLine = System.getProperty("line.separator");
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
try {
outString = "[LUA_UPTIME()]" + newLine;
uptimeDuration = java.time.Duration.between(LocalDateTime.now(), WorldServer.bootTime);
long uptimeSeconds = Math.abs(uptimeDuration.getSeconds());
String uptime = String.format("%d hours %02d minutes %02d seconds", uptimeSeconds / 3600, (uptimeSeconds % 3600) / 60, (uptimeSeconds % 60));
outString += "uptime: " + uptime;
outString += " pop: " + SessionManager.getActivePlayerCharacterCount() + " max pop: " + SessionManager._maxPopulation;
} catch (Exception e) {
Logger.error("Failed to build string");
}
return outString;
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
public static void writePopulationFile() {
2024-03-24 09:42:27 -04:00
int population = SessionManager.getActivePlayerCharacterCount();
try {
2024-03-24 09:42:27 -04:00
File populationFile = new File(ConfigManager.DEFAULT_DATA_DIR + ConfigManager.MB_WORLD_NAME.getValue().replaceAll("'", "") + ".pop");
FileWriter fileWriter;
2024-03-24 09:42:27 -04:00
try {
fileWriter = new FileWriter(populationFile, false);
fileWriter.write(Integer.toString(population));
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
2024-03-24 09:42:27 -04:00
} catch (Exception e) {
Logger.error(e);
}
}
2024-03-24 09:42:27 -04:00
private int exec() {
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
LocalDateTime nextHeartbeatTime = LocalDateTime.now();
LocalDateTime nextPopulationFileTime = LocalDateTime.now();
LocalDateTime nextFlashTrashCheckTime = LocalDateTime.now();
LocalDateTime nextHourlyJobTime = LocalDateTime.now().withMinute(0).withSecond(0).plusHours(1);
LocalDateTime nextWareHousePushTime = LocalDateTime.now();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Begin execution of main game loop
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
this.isRunning = true;
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
while (true) {
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (LocalDateTime.now().isAfter(nextHeartbeatTime)) {
SERVERHEARTBEAT.tick();
nextHeartbeatTime = LocalDateTime.now().plusNanos(50000000);
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (LocalDateTime.now().isAfter(nextPopulationFileTime)) {
writePopulationFile();
nextPopulationFileTime = LocalDateTime.now().plusMinutes(1);
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (LocalDateTime.now().isAfter(nextFlashTrashCheckTime)) {
processFlashFile();
processTrashFile();
nextFlashTrashCheckTime = LocalDateTime.now().plusSeconds(15);
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (LocalDateTime.now().isAfter(nextHourlyJobTime)) {
Thread hourlyJobThread = new Thread(new HourlyJobThread());
hourlyJobThread.setName("hourlyJob");
hourlyJobThread.start();
nextHourlyJobTime = LocalDateTime.now().withMinute(0).withSecond(0).plusHours(1);
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (LocalDateTime.now().isAfter(nextWareHousePushTime)) {
Thread warehousePushThread = new Thread(new WarehousePushThread());
warehousePushThread.setName("warehousePush");
warehousePushThread.start();
nextWareHousePushTime = LocalDateTime.now().plusMinutes(15);
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
ThreadUtils.sleep(50);
}
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
private void initClientConnectionManager() {
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
try {
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
String name = ConfigManager.MB_WORLD_NAME.getValue();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (ConfigManager.MB_EXTERNAL_ADDR.getValue().equals("0.0.0.0")) {
2024-03-24 09:42:27 -04:00
// Autoconfigure External IP address. Only used in loginserver but useful
// here for bootstrap display
2024-03-24 09:42:27 -04:00
Logger.info("AUTOCONFIG EXTERNAL IP ADDRESS");
URL whatismyip = new URL("http://checkip.amazonaws.com");
2024-03-24 09:42:27 -04:00
BufferedReader in = new BufferedReader(new InputStreamReader(
whatismyip.openStream()));
ConfigManager.MB_EXTERNAL_ADDR.setValue(in.readLine());
}
2024-03-24 09:42:27 -04:00
if (ConfigManager.MB_BIND_ADDR.getValue().equals("0.0.0.0")) {
2024-03-24 09:42:27 -04:00
try (final DatagramSocket socket = new DatagramSocket()) {
socket.connect(InetAddress.getByName("8.8.8.8"), 10002);
ConfigManager.MB_BIND_ADDR.setValue(socket.getLocalAddress().getHostAddress());
}
2024-03-24 09:42:27 -04:00
}
2024-03-24 09:42:27 -04:00
Logger.info("External address: " + ConfigManager.MB_EXTERNAL_ADDR.getValue() + ":" + ConfigManager.MB_WORLD_PORT.getValue());
Logger.info("Internal address: " + ConfigManager.MB_BIND_ADDR.getValue() + ":" + ConfigManager.MB_WORLD_PORT.getValue());
2024-03-24 09:42:27 -04:00
InetAddress addy = InetAddress.getByName(ConfigManager.MB_BIND_ADDR.getValue());
int port = Integer.parseInt(ConfigManager.MB_WORLD_PORT.getValue());
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
ClientConnectionManager connectionManager = new ClientConnectionManager(name + ".ClientConnMan", addy,
port);
connectionManager.startup();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
} catch (IOException e) {
Logger.error("Exception while creating a ClientConnectionManager.");
}
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
private boolean init() {
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("MAGICBANE SERVER GREETING:");
Logger.info(ConfigManager.MB_WORLD_GREETING.getValue());
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Initialize network protocol");
Protocol.initProtocolLookup();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Initialize database layer");
initDatabaselayer();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Starting network Dispatcher");
DispatchManager.startMessagePump();
2023-06-07 15:31:07 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Setting cross server session behavior");
SessionManager.setCrossServerBehavior(1); // Sets cross server behavior
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Initializing Errant Guild");
Guild.getErrantGuild();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading zone template data");
DbManager.ZoneQueries.LOAD_ALL_ZONE_TEMPLATES();
2023-10-20 16:33:33 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Initializing PowersManager.");
PowersManager.initPowersManager(true);
2024-03-24 09:42:27 -04:00
Logger.info("Loading granted Skills for Runes");
DbManager.SkillsBaseQueries.LOAD_ALL_RUNE_SKILLS();
2024-03-24 09:42:27 -04:00
Logger.info("Loading Player Friends");
DbManager.PlayerCharacterQueries.LOAD_PLAYER_FRIENDS();
2024-03-24 09:42:27 -04:00
Logger.info("Loading Building Friends");
DbManager.BuildingQueries.LOAD_BUILDING_FRIENDS();
2023-10-18 12:24:32 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Building Condemned");
DbManager.BuildingQueries.LOAD_BUILDING_CONDEMNED();
2024-03-24 09:42:27 -04:00
Logger.info("Loading Barracks Patrol Points");
DbManager.BuildingQueries.LOAD_BARRACKS_PATROL_POINTS();
2023-10-19 16:24:18 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Initializing NPC Profits");
DbManager.NPCQueries.LOAD_NPC_PROFITS();
2024-03-24 09:42:27 -04:00
Logger.info("Initializing Petition Table");
DbManager.PetitionQueries.CREATE_PETITION_TABLE();
2024-03-24 09:42:27 -04:00
Logger.info("Initializing MeshBounds");
MeshBounds.InitializeBuildingBounds();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Item Templates");
DbManager.ItemQueries.LOAD_ITEM_TEMPLATES();
2024-02-18 11:12:54 -05:00
2024-03-28 12:08:09 -04:00
Logger.info("Back fill template modTables");
DbManager.ItemQueries.LOAD_TEMPLATE_MODTABLES();
2024-03-24 09:42:27 -04:00
Logger.info("Loading PromotionClasses");
DbManager.PromotionQueries.GET_ALL_PROMOTIONS();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading NPC and Mob Rune Sets");
NPCManager._runeSetMap = dbNPCHandler.LOAD_RUNES_FOR_NPC_AND_MOBS();
2023-03-28 17:45:58 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Booty Sets");
LootManager._bootySetMap = DbManager.LootQueries.LOAD_BOOTY_TABLES();
2024-03-24 09:42:27 -04:00
// Load new loot system
Logger.info("Initializing Loot Manager");
LootManager.init();
2024-03-24 09:42:27 -04:00
RuneBaseAttribute.LoadAllAttributes();
RuneBase.LoadAllRuneBases();
BaseClass.LoadAllBaseClasses();
Race.loadAllRaces();
RuneBaseEffect.LoadRuneBaseEffects();
Logger.info("Loading MobBases.");
DbManager.MobBaseQueries.GET_ALL_MOBBASES();
2023-03-12 17:54:03 -05:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Rune Powers");
PowersManager._allRunePowers = dbRuneBaseHandler.LOAD_RUNE_POWERS();
2024-03-24 09:42:27 -04:00
Logger.info("Loading Rune Skill Adjusts");
PowersManager._allRuneSkillAdjusts = dbRuneBaseHandler.LOAD_RUNE_SKILL_ADJUSTS();
2024-03-24 09:42:27 -04:00
Logger.info("Loading item enchants");
DbManager.LootQueries.LOAD_ENCHANT_VALUES();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Realms");
Realm.loadAllRealms();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading RealmMap");
RealmMap.loadRealmImageMap();
2023-02-08 09:27:46 -05:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Kits");
DbManager.KitQueries.GET_ALL_KITS();
2024-03-24 09:42:27 -04:00
Logger.info("Loading World Grid");
WorldGrid.InitializeGridObjects();
2024-03-24 09:42:27 -04:00
Logger.info("Starting InterestManager.");
WorldGrid.startLoadJob();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading blueprint data.");
StaticColliders.loadAllStaticColliders();
BuildingRegions.loadAllStaticColliders();
Blueprint.loadAllDoorNumbers();
Blueprint.loadAllBlueprints();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Heightmap Pixel data");
MapLoader.loadAlHeightMaps();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Race data");
mbEnums.RaceType.initRaceTypeTables();
2024-03-24 09:42:27 -04:00
Race.loadAllRaces();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading building slot/stuck location data.");
BuildingLocation.loadBuildingLocations();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Starting before loading of structures/guilds/characters
// so the database connections are available to write
// historical data.
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Starting Data Warehouse");
DataWarehouse.bootStrap();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Minion Bases.");
MinionType.InitializeMinions();
2022-04-30 09:41:17 -04:00
2024-04-28 12:40:53 -05:00
Logger.info("Loading Charter Types.");
mbEnums.GuildCharterType.init();
2024-03-24 09:42:27 -04:00
Logger.info("Loading Pirate Names.");
NPCManager.loadAllPirateNames();
2023-05-01 14:43:06 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Support Types");
SupportMsgType.InitializeSupportMsgType();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
//Load Buildings, Mobs and NPCs for server
2024-03-24 09:42:27 -04:00
Logger.info("Populating world with objects");
2023-10-19 08:47:28 -04:00
2024-03-24 09:42:27 -04:00
long start = System.currentTimeMillis();
2023-10-19 08:47:28 -04:00
2024-04-27 09:32:25 -04:00
Logger.info("Loading all Zones");
2024-03-24 09:42:27 -04:00
DbManager.ZoneQueries.GET_ALL_ZONES();
2024-04-27 09:32:25 -04:00
Logger.info("Loading all Buildings");
2024-03-24 09:42:27 -04:00
DbManager.BuildingQueries.GET_ALL_BUILDINGS();
2024-04-27 09:32:25 -04:00
Logger.info("Loading all Cities");
2024-03-24 09:42:27 -04:00
DbManager.CityQueries.GET_ALL_CITIES();
2024-04-27 09:32:25 -04:00
Logger.info("Loading all NPCs");
2024-03-24 09:42:27 -04:00
DbManager.NPCQueries.GET_ALL_NPCS();
2024-04-27 09:32:25 -04:00
Logger.info("Loading all Mobiles");
2024-03-24 09:42:27 -04:00
DbManager.MobQueries.GET_ALL_MOBS();
2023-10-19 08:47:28 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("time to load World Objects: " + (System.currentTimeMillis() - start) + " ms");
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Configure realms for serialization
// Doing this after the world is loaded
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Configuring realm serialization data");
Realm.configureAllRealms();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Mine data.");
Mine.loadAllMines();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Shrine data.");
DbManager.ShrineQueries.LOAD_ALL_SHRINES();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Initialize Resource type lookup");
mbEnums.ResourceType.InitializeResourceTypes();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Warehouse data.");
DbManager.WarehouseQueries.LOAD_WAREHOUSES();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Runegate data.");
Runegate.loadAllRunegates();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Loading Max Skills for Trainers");
DbManager.SkillsBaseQueries.LOAD_ALL_MAX_SKILLS_FOR_CONTRACT();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
//pick a startup Hotzone
ZoneManager.generateAndSetRandomHotzone();
2024-03-24 09:42:27 -04:00
Logger.info("Loading Player Heraldries");
DbManager.PlayerCharacterQueries.LOAD_HERALDY();
2024-03-24 09:42:27 -04:00
Logger.info("Running Heraldry Audit for Deleted Players");
Heraldry.AuditHeraldry();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
//intiate mob ai thread
Logger.info("Starting Mob AI Thread");
MobAIThread.startAIThread();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("World data loaded.");
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
//set default accesslevel for server *** Refactor who two separate variables?
MBServerStatics.accessLevel = worldAccessLevel;
Logger.info("Default access level set to " + MBServerStatics.accessLevel);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Initializing Network");
Network.init();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Initializing Client Connection Manager");
initClientConnectionManager();
2023-08-25 14:08:43 -04:00
2024-03-24 09:42:27 -04:00
//intiate mob respawn thread
Logger.info("Starting Mob Respawn Thread");
2024-05-04 13:18:34 -04:00
ReSpawner.start();
2023-08-01 20:13:23 -05:00
2024-04-23 14:56:30 -04:00
Logger.info("Loading effect cost maps");
DbManager.EffectsResourceCostsQueries.LOAD_ALL_COSTMAPS();
2024-04-07 22:53:41 -04:00
Logger.info("Starting ForgeManager thread");
ForgeManager.start();
2024-04-22 16:12:26 -04:00
Logger.info("Restoring NPC workOrders");
DbManager.WarehouseQueries.LOAD_WORKORDERS();
2024-03-24 09:42:27 -04:00
// Run maintenance
2024-03-24 09:42:27 -04:00
MaintenanceManager.dailyMaintenance();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Starting Orphan Item Purge");
PurgeOprhans.startPurgeThread();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Open/Close mines for the current window
2024-03-24 09:42:27 -04:00
Logger.info("Processing mine window.");
HourlyJobThread.processMineWindow();
2023-01-19 16:12:18 -05:00
2024-03-24 09:42:27 -04:00
// Calculate bootstrap time and rest boot time to current time.
2024-03-24 09:42:27 -04:00
Duration bootDuration = Duration.between(LocalDateTime.now(), bootTime);
long bootSeconds = Math.abs(bootDuration.getSeconds());
String boottime = String.format("%d hours %02d minutes %02d seconds", bootSeconds / 3600, (bootSeconds % 3600) / 60, (bootSeconds % 60));
Logger.info("Bootstrap time was " + boottime);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
bootTime = LocalDateTime.now();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Running garbage collection...");
System.gc();
return true;
}
2024-03-24 09:42:27 -04:00
protected boolean initDatabaselayer() {
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Try starting a GOM <-> DB connection.
try {
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Configuring GameObjectManager to use Database: '"
+ ConfigManager.MB_DATABASE_NAME.getValue() + "' on "
+ ConfigManager.MB_DATABASE_ADDRESS.getValue() + ':'
+ ConfigManager.MB_DATABASE_PORT.getValue());
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
DbManager.configureConnectionPool();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
} catch (Exception e) {
Logger.error(e.getMessage());
return false;
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
return true;
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
/**
* Called to remove a client on "leave world", "quit game", killed client
* process, etc.
*/
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
public void removeClient(ClientConnection origin) {
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (origin == null) {
Logger.info(
"ClientConnection null in removeClient.");
return;
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
PlayerCharacter playerCharacter = SessionManager.getPlayerCharacter(
origin);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (playerCharacter == null)
// TODO log this
return;
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
//cancel any trade
2024-03-18 10:01:29 -04:00
if (playerCharacter.charItemManager != null)
playerCharacter.charItemManager.endTrade(true);
2023-01-20 13:45:46 -05:00
2024-03-24 09:42:27 -04:00
// Release any mine claims
2023-01-20 13:45:46 -05:00
2024-03-24 09:42:27 -04:00
Mine.releaseMineClaims(playerCharacter);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// logout
long delta = MBServerStatics.LOGOUT_TIMER_MS;
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (System.currentTimeMillis() - playerCharacter.getTimeStamp("LastCombatPlayer") < 60000) {
delta = 60000;
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
}
playerCharacter.stopMovement(playerCharacter.getLoc());
UpdateStateMsg updateStateMsg = new UpdateStateMsg();
updateStateMsg.setPlayer(playerCharacter);
2023-04-29 12:33:21 -04:00
2024-03-24 09:42:27 -04:00
updateStateMsg.setActivity(5);
DispatchManager.dispatchMsgToInterestArea(playerCharacter, updateStateMsg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
2023-04-29 12:33:21 -04:00
2024-03-24 09:42:27 -04:00
if (playerCharacter.region != null)
if (PlayerCharacter.CanBindToBuilding(playerCharacter, playerCharacter.region.parentBuildingID))
playerCharacter.bindBuilding = playerCharacter.region.parentBuildingID;
else
playerCharacter.bindBuilding = 0;
2023-04-29 12:33:21 -04:00
2024-03-24 09:42:27 -04:00
playerCharacter.getLoadedObjects().clear();
playerCharacter.getLoadedStaticObjects().clear();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
LogoutCharacterJob logoutJob = new LogoutCharacterJob(playerCharacter, this);
JobContainer jc = JobScheduler.getInstance().scheduleJob(logoutJob,
System.currentTimeMillis() + delta);
playerCharacter.getTimers().put("Logout", jc);
playerCharacter.getTimestamps().put("logout", System.currentTimeMillis());
2024-03-24 09:42:27 -04:00
//send update to friends that you are logged off.
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
PlayerFriends.SendFriendsStatus(playerCharacter, false);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
public void logoutCharacter(PlayerCharacter player) {
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (player == null) {
Logger.error("Unable to find PlayerCharacter to logout");
return;
}
//remove player from loaded mobs agro maps
for (AbstractWorldObject awo : WorldGrid.getObjectsInRangePartial(player.getLoc(), MBServerStatics.CHARACTER_LOAD_RANGE, MBServerStatics.MASK_MOB)) {
Mob loadedMob = (Mob) awo;
loadedMob.playerAgroMap.remove(player.getObjectUUID());
}
player.getTimestamps().put("logout", System.currentTimeMillis());
player.setEnteredWorld(false);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// remove from simulation and zero current loc
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
WorldGrid.RemoveWorldObject(player);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// clear Logout Timer
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (player.getTimers() != null)
player.getTimers().remove("Logout");
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (player.getPet() != null)
player.getPet().dismiss();
2024-03-24 09:42:27 -04:00
NPCManager.dismissNecroPets(player);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Set player inactive so they quit loading for other players
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
player.setActive(false);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Remove from group
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Group group = GroupManager.getGroup(player);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
try {
if (group != null)
GroupManager.LeaveGroup(player);
} catch (MsgSendException e) {
Logger.error(e.toString());
}
2024-03-24 09:42:27 -04:00
player.respawnLock.writeLock().lock();
try {
if (!player.isAlive())
player.respawn(false, false, true);
} catch (Exception e) {
Logger.error(e);
} finally {
player.respawnLock.writeLock().unlock();
}
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
private void processTrashFile() {
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
ArrayList<String> machineList;
ArrayList<PlayerCharacter> trashList = new ArrayList<>();
ArrayList<Integer> accountList = new ArrayList<>();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
File trashFile = new File("trash");
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (trashFile.exists() == false)
return;
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Build list of machineID's in the trash file
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
machineList = DbManager.AccountQueries.GET_TRASH_LIST();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Build list of trash characters associated with that machineID
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
for (String machineID : machineList) {
trashList = DbManager.AccountQueries.GET_ALL_CHARS_FOR_MACHINE(machineID);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Deactivate these players and add them to loginCache table
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
for (PlayerCharacter trashPlayer : trashList) {
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (trashPlayer == null)
continue;
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Need to collate accounts.
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (!accountList.contains(trashPlayer.getAccount().getObjectUUID()))
accountList.add(trashPlayer.getAccount().getObjectUUID());
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
DbManager.PlayerCharacterQueries.SET_ACTIVE(trashPlayer, false);
DbManager.AccountQueries.INVALIDATE_LOGIN_CACHE(trashPlayer.getObjectUUID(), "character");
}
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// delete vault of associated accounts and then invalidate them
// in the login cache.
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
for (Integer accountID : accountList) {
DbManager.AccountQueries.DELETE_VAULT_FOR_ACCOUNT(accountID);
DbManager.AccountQueries.INVALIDATE_LOGIN_CACHE(accountID, "account");
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Trigger the Login Server to invalidate these accounts in the cache..
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
try {
Files.write(Paths.get("cacheInvalid"), "".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// If any of these players are active disconnect them.
// The account and player should be removed from the login
// server cache file by now.
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Timer timer = new Timer("Disconnect Trash");
timer.schedule(new DisconnectTrashTask(trashList), 3000L);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Clean up after ourselves
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
try {
Files.deleteIfExists(Paths.get("trash"));
DbManager.AccountQueries.CLEAR_TRASH_TABLE();
} catch (IOException e) {
e.printStackTrace();
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
private void processFlashFile() {
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
File flashFile = new File("flash");
String flashString;
List<String> fileContents;
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (flashFile.exists() == false)
return;
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
try {
fileContents = Files.readAllLines(Paths.get("flash"));
} catch (IOException e) {
return;
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Flash file detected: read contents
// and send as a flash.
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
flashString = fileContents.toString();
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
if (flashString == null)
return;
2022-04-30 09:41:17 -04:00
2024-04-28 13:49:21 -04:00
if (flashString.equals(""))
2024-03-24 09:42:27 -04:00
flashString = "Rebooting for to fix bug.";
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
Logger.info("Sending flash from external interface");
Logger.info("Msg: " + flashString);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
ChatSystemMsg msg = new ChatSystemMsg(null, flashString);
msg.setChannel(mbEnums.ChatChannelType.FLASH.getChannelID());
msg.setMessageType(mbEnums.ChatMessageType.INFO.ordinal());
DispatchManager.dispatchMsgToAll(msg);
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
// Delete file
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
try {
Files.deleteIfExists(Paths.get("flash"));
} catch (IOException e) {
e.printStackTrace();
}
2022-04-30 09:41:17 -04:00
2024-03-24 09:42:27 -04:00
}
2022-04-30 09:41:17 -04:00
}