ソースを参照

Script Loading rework

Modified ScriptEngineManager to load scripts in different compilers
instead of a single static instance (this led to duplicated script
reload and performance issues), greatly simplified the code.
Split script loading in several sections.
Fixed minions not unspawning after boss death.

Reported by: FinalDestination, CostyKiller, L2jXorus, jonhanon, Edoogel
Fixes #182
Fixes #293
Zoey76 4 年 前
コミット
64861faded

+ 0 - 1
.gitignore

@@ -1,6 +1,5 @@
 .project
 .classpath
-.settings/
 .idea/
 target/
 logs/

+ 14 - 2
src/main/java/com/l2jserver/gameserver/GameServer.java

@@ -303,13 +303,25 @@ public final class GameServer {
 		CursedWeaponsManager.getInstance();
 		TransformData.getInstance();
 		BotReportTable.getInstance();
-		
-		printSection("Scripts");
 		QuestManager.getInstance();
 		BoatManager.getInstance();
 		AirShipManager.getInstance();
 		GraciaSeedsManager.getInstance();
 		
+		printSection("Handlers");
+		ScriptEngineManager.getInstance().executeScript("com/l2jserver/datapack/handlers/MasterHandler.java");
+		printSection("AI");
+		ScriptEngineManager.getInstance().executeScript("com/l2jserver/datapack/ai/AILoader.java");
+		printSection("Instances");
+		ScriptEngineManager.getInstance().executeScript("com/l2jserver/datapack/instances/InstanceLoader.java");
+		printSection("Gracia");
+		ScriptEngineManager.getInstance().executeScript("com/l2jserver/datapack/gracia/GraciaLoader.java");
+		printSection("Hellbound");
+		ScriptEngineManager.getInstance().executeScript("com/l2jserver/datapack/hellbound/HellboundLoader.java");
+		printSection("Quests");
+		ScriptEngineManager.getInstance().executeScript("com/l2jserver/datapack/quests/QuestMasterHandler.java");
+		ScriptEngineManager.getInstance().executeScript("com/l2jserver/datapack/quests/TerritoryWarScripts/TerritoryWarSuperClass.java");
+		printSection("Scripts");
 		ScriptEngineManager.getInstance().executeScriptList(new File(server().getDatapackRoot(), "data/scripts.cfg"));
 		
 		SpawnTable.getInstance().load();

+ 6 - 2
src/main/java/com/l2jserver/gameserver/instancemanager/RaidBossSpawnManager.java

@@ -45,6 +45,8 @@ public class RaidBossSpawnManager {
 	
 	private static final Logger LOG = LoggerFactory.getLogger(RaidBossSpawnManager.class);
 	
+	private static final int EILHALDER_VON_HELLMANN = 25328;
+	
 	protected static final Map<Integer, L2RaidBossInstance> _bosses = new ConcurrentHashMap<>();
 	
 	protected static final Map<Integer, L2Spawn> _spawns = new ConcurrentHashMap<>();
@@ -64,6 +66,8 @@ public class RaidBossSpawnManager {
 	}
 	
 	public void load() {
+		LOG.info("Spawning raid bosses...");
+		
 		_bosses.clear();
 		_spawns.clear();
 		_storedInfo.clear();
@@ -104,7 +108,7 @@ public class RaidBossSpawnManager {
 		public void run() {
 			L2RaidBossInstance raidboss = null;
 			
-			if (bossId == 25328) {
+			if (bossId == EILHALDER_VON_HELLMANN) {
 				raidboss = DayNightSpawnManager.getInstance().handleBoss(_spawns.get(bossId));
 			} else {
 				raidboss = (L2RaidBossInstance) _spawns.get(bossId).doSpawn();
@@ -194,7 +198,7 @@ public class RaidBossSpawnManager {
 		if ((respawnTime == 0L) || (time > respawnTime)) {
 			L2RaidBossInstance raidboss = null;
 			
-			if (bossId == 25328) {
+			if (bossId == EILHALDER_VON_HELLMANN) {
 				raidboss = DayNightSpawnManager.getInstance().handleBoss(spawnDat);
 			} else {
 				raidboss = (L2RaidBossInstance) spawnDat.doSpawn();

+ 80 - 89
src/main/java/com/l2jserver/gameserver/scripting/ScriptEngineManager.java

@@ -30,8 +30,6 @@ import java.io.LineNumberReader;
 import java.io.Reader;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.util.Map;
-import java.util.Map.Entry;
 
 import javax.script.ScriptException;
 
@@ -51,96 +49,90 @@ public final class ScriptEngineManager {
 	
 	private static final String MAIN = "main";
 	
-	private static final String[] EMPTY_STRING_ARRAY = new String[0];
+	private static final Object[] MAIN_METHOD_ARGS = new Object[] {
+		new String[0]
+	};
 	
 	private static final Class<?>[] ARG_MAIN = new Class[] {
 		String[].class
 	};
 	
-	private static final InMemoryJavaCompiler COMPILER = InMemoryJavaCompiler.newInstance() //
-		.useOptions("-classpath", CLASS_PATH, "-g") //
-		.ignoreWarnings();
+	private InMemoryJavaCompiler compiler() {
+		return InMemoryJavaCompiler.newInstance() //
+			.useOptions("-classpath", CLASS_PATH, "-g") //
+			.ignoreWarnings();
+	}
 	
 	public void executeScriptList(File list) throws Exception {
 		if (general().noQuests()) {
-			if (!general().noHandlers()) {
-				addSource(new File(server().getScriptRoot(), "com/l2jserver/datapack/handlers/MasterHandler.java"));
-				LOG.info("Handlers loaded, all other scripts skipped!");
-			}
 			return;
 		}
 		
-		if (list.isFile()) {
-			try (FileInputStream fis = new FileInputStream(list);
-				InputStreamReader isr = new InputStreamReader(fis);
-				LineNumberReader lnr = new LineNumberReader(isr)) {
-				String line;
-				while ((line = lnr.readLine()) != null) {
-					if (general().noHandlers() && line.contains("MasterHandler.java")) {
-						continue;
-					}
-					
-					String[] parts = line.trim().split("#");
-					
-					if ((parts.length > 0) && !parts[0].isEmpty() && (parts[0].charAt(0) != '#')) {
-						line = parts[0];
-						
-						if (line.endsWith("/**")) {
-							line = line.substring(0, line.length() - 3);
-						} else if (line.endsWith("/*")) {
-							line = line.substring(0, line.length() - 2);
-						}
-						
-						final File file = new File(server().getScriptRoot(), line);
-						if (file.isDirectory() && parts[0].endsWith("/**")) {
-							executeAllScriptsInDirectory(file, true);
-						} else if (file.isDirectory() && parts[0].endsWith("/*")) {
-							executeAllScriptsInDirectory(file, false);
-						} else if (file.isFile()) {
-							addSource(file);
-						} else {
-							LOG.warn("Failed loading: ({}) @ {}:{} - Reason: doesnt exists or is not a file.", file.getCanonicalPath(), list.getName(), lnr.getLineNumber());
-						}
-					}
-				}
-			}
-		} else {
+		if (!list.isFile()) {
 			throw new IllegalArgumentException("Argument must be an file containing a list of scripts to be loaded");
 		}
 		
-		final Map<String, Class<?>> classes = COMPILER.compileAll();
-		for (Entry<String, Class<?>> e : classes.entrySet()) {
-			runMain(e.getValue());
+		final var compiler = compiler();
+		try (var fis = new FileInputStream(list);
+			var isr = new InputStreamReader(fis);
+			var lnr = new LineNumberReader(isr)) {
+			String line;
+			while ((line = lnr.readLine()) != null) {
+				final var parts = line.trim().split("#");
+				if ((parts.length <= 0) || parts[0].trim().isEmpty() || (parts[0].charAt(0) == '#')) {
+					continue;
+				}
+				
+				line = parts[0].trim();
+				if (line.endsWith("/**")) {
+					line = line.substring(0, line.length() - 3);
+				} else if (line.endsWith("/*")) {
+					line = line.substring(0, line.length() - 2);
+				}
+				
+				final var file = new File(server().getScriptRoot(), line);
+				if (file.isDirectory() && parts[0].endsWith("/**")) {
+					executeAllScriptsInDirectory(compiler, file, true);
+				} else if (file.isDirectory() && parts[0].endsWith("/*")) {
+					executeAllScriptsInDirectory(compiler, file, false);
+				} else if (file.isFile()) {
+					addSource(compiler, file);
+				} else {
+					LOG.warn("Failed loading: ({}) @ {}:{} - Reason: doesnt exists or is not a file.", file.getCanonicalPath(), list.getName(), lnr.getLineNumber());
+				}
+			}
 		}
+		
+		compiler.compileAll().forEach((k, v) -> runMain(v));
 	}
 	
-	private void executeAllScriptsInDirectory(File dir, boolean recurseDown) {
-		if (dir.isDirectory()) {
-			final File[] files = dir.listFiles();
-			if (files == null) {
-				return;
-			}
-			
-			for (File file : files) {
-				if (file.isDirectory() && recurseDown) {
-					if (general().debug()) {
-						LOG.info("Entering folder: {}", file.getName());
-					}
-					executeAllScriptsInDirectory(file, recurseDown);
-				} else if (file.isFile()) {
-					addSource(file);
+	private void executeAllScriptsInDirectory(InMemoryJavaCompiler compiler, File dir, boolean recurseDown) {
+		if (!dir.isDirectory()) {
+			throw new IllegalArgumentException("The argument directory either doesnt exists or is not an directory.");
+		}
+		
+		final var files = dir.listFiles();
+		if (files == null) {
+			return;
+		}
+		
+		for (var file : files) {
+			if (file.isDirectory() && recurseDown) {
+				if (general().debug()) {
+					LOG.info("Entering folder: {}", file.getName());
 				}
+				executeAllScriptsInDirectory(compiler, file, recurseDown);
+			} else if (file.isFile()) {
+				addSource(compiler, file);
 			}
-		} else {
-			throw new IllegalArgumentException("The argument directory either doesnt exists or is not an directory.");
 		}
 	}
 	
 	public Class<?> compileScript(File file) {
-		try (FileInputStream fis = new FileInputStream(file);
-			InputStreamReader isr = new InputStreamReader(fis);
-			BufferedReader reader = new BufferedReader(isr)) {
-			return COMPILER.compile(getClassForFile(file), readerToString(reader));
+		try (var fis = new FileInputStream(file);
+			var isr = new InputStreamReader(fis);
+			var reader = new BufferedReader(isr)) {
+			return compiler().compile(getClassForFile(file), readerToString(reader));
 		} catch (Exception ex) {
 			LOG.warn("Error executing script!", ex);
 		}
@@ -149,7 +141,6 @@ public final class ScriptEngineManager {
 	
 	public void executeScript(File file) throws Exception {
 		final Class<?> clazz = compileScript(file);
-		
 		runMain(clazz);
 	}
 	
@@ -157,15 +148,15 @@ public final class ScriptEngineManager {
 		executeScript(new File(server().getScriptRoot(), file));
 	}
 	
-	public void addSource(File file) {
+	public void addSource(InMemoryJavaCompiler compiler, File file) {
 		if (general().debug()) {
 			LOG.info("Loading Script: {}", file.getAbsolutePath());
 		}
 		
-		try (FileInputStream fis = new FileInputStream(file);
-			InputStreamReader isr = new InputStreamReader(fis);
-			BufferedReader reader = new BufferedReader(isr)) {
-			COMPILER.addSource(getClassForFile(file), readerToString(reader));
+		try (var fis = new FileInputStream(file);
+			var isr = new InputStreamReader(fis);
+			var reader = new BufferedReader(isr)) {
+			compiler.addSource(getClassForFile(file), readerToString(reader));
 		} catch (Exception ex) {
 			LOG.warn("Error executing script!", ex);
 		}
@@ -181,23 +172,23 @@ public final class ScriptEngineManager {
 		return null;
 	}
 	
-	private static void runMain(Class<?> clazz) throws Exception {
-		final boolean isPublicClazz = Modifier.isPublic(clazz.getModifiers());
-		final Method mainMethod = findMethod(clazz, MAIN, ARG_MAIN);
-		if (mainMethod != null) {
-			if (!isPublicClazz) {
-				mainMethod.setAccessible(true);
-			}
-			
-			mainMethod.invoke(null, new Object[] {
-				EMPTY_STRING_ARRAY
-			});
+	private static void runMain(Class<?> clazz) {
+		final var mainMethod = findMethod(clazz, MAIN, ARG_MAIN);
+		if (mainMethod == null) {
+			LOG.warn("Unable to find main method in class {}!", clazz);
+			return;
+		}
+		
+		try {
+			mainMethod.invoke(null, MAIN_METHOD_ARGS);
+		} catch (Exception ex) {
+			LOG.error("Error loading script {}!", clazz);
 		}
 	}
 	
 	private static String readerToString(Reader reader) throws ScriptException {
-		try (BufferedReader in = new BufferedReader(reader)) {
-			final StringBuilder result = new StringBuilder();
+		try (var in = new BufferedReader(reader)) {
+			final var result = new StringBuilder();
 			String line;
 			while ((line = in.readLine()) != null) {
 				result.append(line).append(System.lineSeparator());
@@ -210,7 +201,7 @@ public final class ScriptEngineManager {
 	
 	private static Method findMethod(Class<?> clazz, String methodName, Class<?>[] args) {
 		try {
-			final Method mainMethod = clazz.getMethod(methodName, args);
+			final var mainMethod = clazz.getMethod(methodName, args);
 			final int modifiers = mainMethod.getModifiers();
 			if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)) {
 				return mainMethod;