diff --git a/L2J_Mobius_HighFive/dist/game/config/ScriptEngines.ini b/L2J_Mobius_HighFive/dist/game/config/ScriptEngines.ini new file mode 100644 index 0000000000..98284c5b95 --- /dev/null +++ b/L2J_Mobius_HighFive/dist/game/config/ScriptEngines.ini @@ -0,0 +1,39 @@ +############################################################################### +# Properties retrived with System.getProperty(String) can be used as values +# by enclosing the property name with %. Eg.: %java.class.path% +# +# You can set a property for a scripting engine by language name. +# +# Examples: +# language.Java.source=1.8 +############################################################################### + + +####################################### +# L2J_JavaEngine ##################### +####################################### + +# The prefered java compiler api to use. +# The value is a fully qualified name of a class which implements the javax.toold.JavaCompiler and has a zero argument constructor. +# When the prefered compiler is not set, the first found compiler is used. +# When the prefered compiler is not found, the last found compiler is used. +language.Java.preferedCompiler=com.sun.tools.javac.api.JavacTool +language.Java.preferedCompiler=org.eclipse.jdt.internal.compiler.tool.EclipseCompiler + +# The parent class loader for isolated script class loaders. +# When this property is not specified, has an invalid value or is a class name which could not be found, the System classloader is used. +# Values: System, ThreadContext or a fully qualified java class name +language.Java.classloader=System +#language.Java.classloader=ThreadContext + +# Source compatibility +language.Java.source=1.8 + +# The java sourcepath, when you have a different datapack root, you must change this too. +language.Java.sourcepath=data/scripts + +# The java classpath +language.Java.cp=%java.class.path% + +# The debug informations to generate for compiled class files +language.Java.g=source,lines,vars \ No newline at end of file diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/fantasy_isle/HandysBlockCheckerEvent.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/fantasy_isle/HandysBlockCheckerEvent.java index 91cedbe974..487857618e 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/fantasy_isle/HandysBlockCheckerEvent.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/fantasy_isle/HandysBlockCheckerEvent.java @@ -31,7 +31,7 @@ import com.l2jmobius.gameserver.network.serverpackets.ExCubeGameTeamList; * Handys Block Checker Event AI. * @authors BiggBoss, Gigiikun */ -final class HandysBlockCheckerEvent extends Quest +public final class HandysBlockCheckerEvent extends Quest { // Arena Managers private static final int A_MANAGER_1 = 32521; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/fantasy_isle/Parade.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/fantasy_isle/Parade.java index 62e62c7254..09fb9623b0 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/fantasy_isle/Parade.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/fantasy_isle/Parade.java @@ -32,7 +32,7 @@ import ai.npc.AbstractNpcAI; * Fantasy Isle Parade * @author JOJO, Pandragon */ -final class Parade extends AbstractNpcAI +public final class Parade extends AbstractNpcAI { // @formatter:off final int[] ACTORS = diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/fantasy_isle/TalentShow.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/fantasy_isle/TalentShow.java index 9bf4085aab..cd8b7add5f 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/fantasy_isle/TalentShow.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/fantasy_isle/TalentShow.java @@ -36,7 +36,7 @@ import ai.npc.AbstractNpcAI; * Talent Show AI. * @author Kerberos */ -final class TalentShow extends AbstractNpcAI +public final class TalentShow extends AbstractNpcAI { private static int MC = 32433; // @formatter:off diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Anais.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Anais.java index daf54a221f..b1f0d64258 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Anais.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Anais.java @@ -32,7 +32,7 @@ import ai.npc.AbstractNpcAI; * Anais AI. * @author nonom */ -final class Anais extends AbstractNpcAI +public final class Anais extends AbstractNpcAI { // NPCs private static final int ANAIS = 25701; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Ballista.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Ballista.java index b29f75793f..d4bf15c407 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Ballista.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Ballista.java @@ -30,7 +30,7 @@ import ai.npc.AbstractNpcAI; * Ballista AI. * @author St3eT */ -final class Ballista extends AbstractNpcAI +public final class Ballista extends AbstractNpcAI { // NPCs private static final int[] BALLISTA = diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Beleth.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Beleth.java index 61937d3c83..b6bfe6b27f 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Beleth.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Beleth.java @@ -54,7 +54,7 @@ import ai.npc.AbstractNpcAI; * Beleth's AI. * @author Treat, Sahar */ -final class Beleth extends AbstractNpcAI +public final class Beleth extends AbstractNpcAI { // Status private static final int ALIVE = 0; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Core.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Core.java index 6adcb6e346..d689f46022 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Core.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Core.java @@ -37,7 +37,7 @@ import ai.npc.AbstractNpcAI; * Core AI. * @author DrLecter, Emperorc */ -final class Core extends AbstractNpcAI +public final class Core extends AbstractNpcAI { private static final int CORE = 29006; private static final int DEATH_KNIGHT = 29007; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/CrimsonHatuOtis.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/CrimsonHatuOtis.java index 27232b7e4d..b4e3499fc0 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/CrimsonHatuOtis.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/CrimsonHatuOtis.java @@ -28,7 +28,7 @@ import ai.npc.AbstractNpcAI; * AI for Kamaloka (33) - Crimson Hatu Otis * @author Gladicek */ -final class CrimsonHatuOtis extends AbstractNpcAI +public final class CrimsonHatuOtis extends AbstractNpcAI { // Npc private static final int CRIMSON_HATU_OTIS = 18558; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/DarkWaterDragon.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/DarkWaterDragon.java index 5614ede74c..8e3575e552 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/DarkWaterDragon.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/DarkWaterDragon.java @@ -32,7 +32,7 @@ import ai.npc.AbstractNpcAI; /** * Dark Water Dragon's AI. */ -final class DarkWaterDragon extends AbstractNpcAI +public final class DarkWaterDragon extends AbstractNpcAI { private static final int DRAGON = 22267; private static final int SHADE1 = 22268; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/DivineBeast.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/DivineBeast.java index e76ee1736e..3b36dfc24d 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/DivineBeast.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/DivineBeast.java @@ -26,7 +26,7 @@ import ai.npc.AbstractNpcAI; * Simple AI that manages special conditions for Divine Beast summon. * @author UnAfraid */ -final class DivineBeast extends AbstractNpcAI +public final class DivineBeast extends AbstractNpcAI { private static final int DIVINE_BEAST = 14870; private static final int TRANSFORMATION_ID = 258; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Epidos.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Epidos.java index 8c768d85ba..94f95598d2 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Epidos.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Epidos.java @@ -32,7 +32,7 @@ import ai.npc.AbstractNpcAI; * Manages minion's spawn, idle despawn and Teleportation Cube spawn. * @author GKR */ -final class Epidos extends AbstractNpcAI +public final class Epidos extends AbstractNpcAI { private static final int[] EPIDOSES = { diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/EvasGiftBox.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/EvasGiftBox.java index 1392f577b6..f20e972e1f 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/EvasGiftBox.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/EvasGiftBox.java @@ -27,7 +27,7 @@ import ai.npc.AbstractNpcAI; * Eva's Gift Box AI. * @author St3eT */ -final class EvasGiftBox extends AbstractNpcAI +public final class EvasGiftBox extends AbstractNpcAI { // NPC private static final int BOX = 32342; // Eva's Gift Box diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/FrightenedRagnaOrc.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/FrightenedRagnaOrc.java index 14a3343a2e..0adfa7299b 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/FrightenedRagnaOrc.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/FrightenedRagnaOrc.java @@ -32,7 +32,7 @@ import ai.npc.AbstractNpcAI; * Frightened Ragna Orc AI. * @author Gladicek, malyelfik */ -final class FrightenedRagnaOrc extends AbstractNpcAI +public final class FrightenedRagnaOrc extends AbstractNpcAI { // NPC ID private static final int MOB_ID = 18807; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Gordon.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Gordon.java index 50cbbc7f39..c3df1132cc 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Gordon.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Gordon.java @@ -27,7 +27,7 @@ import ai.npc.AbstractNpcAI; * Gordon AI * @author TOFIZ, malyelfik */ -final class Gordon extends AbstractNpcAI +public final class Gordon extends AbstractNpcAI { private static final int GORDON = 29095; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/GraveRobbers.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/GraveRobbers.java index 44057120b6..88a9e75cc2 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/GraveRobbers.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/GraveRobbers.java @@ -28,7 +28,7 @@ import ai.npc.AbstractNpcAI; * * @author Zealar */ -final class GraveRobbers extends AbstractNpcAI +public final class GraveRobbers extends AbstractNpcAI { private static final int GRAVE_ROBBER_SUMMONER = 22678; private static final int GRAVE_ROBBER_MEGICIAN = 22679; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Orfen.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Orfen.java index fa7802876c..4104d51d64 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Orfen.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Orfen.java @@ -45,7 +45,7 @@ import ai.npc.AbstractNpcAI; * Orfen's AI * @author Emperorc */ -final class Orfen extends AbstractNpcAI +public final class Orfen extends AbstractNpcAI { private static final Location[] POS = { diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/QueenAnt.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/QueenAnt.java index 00afded4a0..91d9fce71a 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/QueenAnt.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/QueenAnt.java @@ -45,7 +45,7 @@ import ai.npc.AbstractNpcAI; * Queen Ant's AI * @author Emperorc */ -final class QueenAnt extends AbstractNpcAI +public final class QueenAnt extends AbstractNpcAI { private static final int QUEEN = 29001; private static final int LARVA = 29002; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/QueenShyeed.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/QueenShyeed.java index 9c24466563..758a7b0e88 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/QueenShyeed.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/QueenShyeed.java @@ -30,7 +30,7 @@ import ai.npc.AbstractNpcAI; * Queen Shyeed AI * @author malyelfik */ -final class QueenShyeed extends AbstractNpcAI +public final class QueenShyeed extends AbstractNpcAI { // NPC private static final int SHYEED = 25671; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/RagnaOrcCommander.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/RagnaOrcCommander.java index 1256d4bb1c..fceb577d8e 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/RagnaOrcCommander.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/RagnaOrcCommander.java @@ -24,7 +24,7 @@ import ai.npc.AbstractNpcAI; * Ragna Orc Commander AI. * @author Zealar */ -final class RagnaOrcCommander extends AbstractNpcAI +public final class RagnaOrcCommander extends AbstractNpcAI { private static final int RAGNA_ORC_COMMANDER = 22694; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/RagnaOrcHero.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/RagnaOrcHero.java index f18e7d9235..8877867714 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/RagnaOrcHero.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/RagnaOrcHero.java @@ -24,7 +24,7 @@ import ai.npc.AbstractNpcAI; * Ragna Orc Hero AI. * @author Zealar */ -final class RagnaOrcHero extends AbstractNpcAI +public final class RagnaOrcHero extends AbstractNpcAI { private static final int RAGNA_ORC_HERO = 22693; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/RagnaOrcSeer.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/RagnaOrcSeer.java index 86b9f437dc..6a36b601e1 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/RagnaOrcSeer.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/RagnaOrcSeer.java @@ -24,7 +24,7 @@ import ai.npc.AbstractNpcAI; * Ragna Orc Seer AI. * @author Zealar */ -final class RagnaOrcSeer extends AbstractNpcAI +public final class RagnaOrcSeer extends AbstractNpcAI { private static final int RAGNA_ORC_SEER = 22697; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/ScarletVanHalisha.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/ScarletVanHalisha.java index b299349b09..70e97bfc3d 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/ScarletVanHalisha.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/ScarletVanHalisha.java @@ -39,7 +39,7 @@ import ai.npc.AbstractNpcAI; /** * @author Micr0, Zerox */ -final class ScarletVanHalisha extends AbstractNpcAI +public final class ScarletVanHalisha extends AbstractNpcAI { private L2Character _target; private Skill _skill; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/SinEater.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/SinEater.java index d08bee9e16..9b6b37815d 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/SinEater.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/SinEater.java @@ -36,7 +36,7 @@ import ai.npc.AbstractNpcAI; * Sin Eater AI. * @author St3eT. */ -final class SinEater extends AbstractNpcAI +public final class SinEater extends AbstractNpcAI { // NPCs private static final int SIN_EATER = 12564; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/SinWardens.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/SinWardens.java index 6be9d4a1d7..615881ac35 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/SinWardens.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/SinWardens.java @@ -32,7 +32,7 @@ import ai.npc.AbstractNpcAI; * Manages Sin Wardens disappearing and chat. * @author GKR */ -final class SinWardens extends AbstractNpcAI +public final class SinWardens extends AbstractNpcAI { private static final int[] SIN_WARDEN_MINIONS = { diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Venom/Venom.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Venom/Venom.java index 3672583f29..f5e3a23a3f 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Venom/Venom.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/individual/Venom/Venom.java @@ -41,7 +41,7 @@ import ai.npc.AbstractNpcAI; * Venom AI on Rune Castle. * @author nonom, MELERIX */ -final class Venom extends AbstractNpcAI +public final class Venom extends AbstractNpcAI { private static final int CASTLE = 8; // Rune diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Alarm/Alarm.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Alarm/Alarm.java index 416a9cdd06..0f1196856e 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Alarm/Alarm.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Alarm/Alarm.java @@ -31,7 +31,7 @@ import quests.Q00185_NikolasCooperation.Q00185_NikolasCooperation; * Alarm AI for quests Art of Persuasion (184) and Nikola's Cooperation (185). * @author Zoey76 */ -final class Alarm extends AbstractNpcAI +public final class Alarm extends AbstractNpcAI { // NPC private static final int ALARM = 32367; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Alexandria/Alexandria.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Alexandria/Alexandria.java index 7f88626f63..0e7456c13a 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Alexandria/Alexandria.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Alexandria/Alexandria.java @@ -32,7 +32,7 @@ import ai.npc.AbstractNpcAI; * Alexandria (Armor Merchant) AI. * @author xban1x */ -final class Alexandria extends AbstractNpcAI +public final class Alexandria extends AbstractNpcAI { // NPC private static final int ALEXANDRIA = 30098; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ArenaManager/ArenaManager.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ArenaManager/ArenaManager.java index e1f267517c..1d80da1070 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ArenaManager/ArenaManager.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ArenaManager/ArenaManager.java @@ -29,7 +29,7 @@ import ai.npc.AbstractNpcAI; * Arena Manager AI. * @author St3eT */ -final class ArenaManager extends AbstractNpcAI +public final class ArenaManager extends AbstractNpcAI { // NPCs private static final int[] ARENA_MANAGER = diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleAmbassador/CastleAmbassador.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleAmbassador/CastleAmbassador.java index 6188fd97e1..0f7cfc1711 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleAmbassador/CastleAmbassador.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleAmbassador/CastleAmbassador.java @@ -29,7 +29,7 @@ import ai.npc.AbstractNpcAI; * Castle Ambassador AI. * @author St3eT */ -final class CastleAmbassador extends AbstractNpcAI +public final class CastleAmbassador extends AbstractNpcAI { // NPCs // @formatter:off diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleBlacksmith/CastleBlacksmith.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleBlacksmith/CastleBlacksmith.java index 8927132bb4..96e6a77a4e 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleBlacksmith/CastleBlacksmith.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleBlacksmith/CastleBlacksmith.java @@ -27,7 +27,7 @@ import ai.npc.AbstractNpcAI; * Castle Blacksmith AI. * @author malyelfik */ -final class CastleBlacksmith extends AbstractNpcAI +public final class CastleBlacksmith extends AbstractNpcAI { // Blacksmith IDs private static final int[] NPCS = diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleSiegeManager/CastleSiegeManager.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleSiegeManager/CastleSiegeManager.java index 6b815c411c..925e005046 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleSiegeManager/CastleSiegeManager.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleSiegeManager/CastleSiegeManager.java @@ -25,7 +25,7 @@ import ai.npc.AbstractNpcAI; * Castle Siege Manager AI. * @author St3eT */ -final class CastleSiegeManager extends AbstractNpcAI +public final class CastleSiegeManager extends AbstractNpcAI { // NPCs private static final int[] SIEGE_MANAGER = diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleTeleporter/CastleTeleporter.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleTeleporter/CastleTeleporter.java index 0af8f806e3..e8711feb3b 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleTeleporter/CastleTeleporter.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleTeleporter/CastleTeleporter.java @@ -31,7 +31,7 @@ import ai.npc.AbstractNpcAI; * Castle Teleporter AI. * @author malyelfik */ -final class CastleTeleporter extends AbstractNpcAI +public final class CastleTeleporter extends AbstractNpcAI { // Teleporter IDs private static final int[] NPCS = diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleWarehouse/CastleWarehouse.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleWarehouse/CastleWarehouse.java index a29d8a28d9..0b064a561e 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleWarehouse/CastleWarehouse.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/CastleWarehouse/CastleWarehouse.java @@ -25,7 +25,7 @@ import ai.npc.AbstractNpcAI; * Castle Warehouse Keeper AI. * @author malyelfik */ -final class CastleWarehouse extends AbstractNpcAI +public final class CastleWarehouse extends AbstractNpcAI { // NPCs private static final int[] NPCS = diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ClanTrader/ClanTrader.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ClanTrader/ClanTrader.java index 3ff75b30a4..8de30f5ab2 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ClanTrader/ClanTrader.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ClanTrader/ClanTrader.java @@ -29,7 +29,7 @@ import ai.npc.AbstractNpcAI; * Clan Trader AI. * @author St3eT */ -final class ClanTrader extends AbstractNpcAI +public final class ClanTrader extends AbstractNpcAI { // Npc private static final int[] CLAN_TRADER = diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FameManager/FameManager.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FameManager/FameManager.java index 727c4b07db..e046ee0b16 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FameManager/FameManager.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FameManager/FameManager.java @@ -27,7 +27,7 @@ import ai.npc.AbstractNpcAI; * Fame Manager AI. * @author St3eT */ -final class FameManager extends AbstractNpcAI +public final class FameManager extends AbstractNpcAI { // Npc private static final int[] FAME_MANAGER = diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ForgeOfTheGods/ForgeOfTheGods.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ForgeOfTheGods/ForgeOfTheGods.java index 648cbad958..fad3142d1c 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ForgeOfTheGods/ForgeOfTheGods.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ForgeOfTheGods/ForgeOfTheGods.java @@ -27,7 +27,7 @@ import ai.npc.AbstractNpcAI; * Forge of the Gods AI * @author nonom, malyelfik */ -final class ForgeOfTheGods extends AbstractNpcAI +public final class ForgeOfTheGods extends AbstractNpcAI { // NPCs private static final int[] FOG_MOBS = diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ForgeOfTheGods/Rooney.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ForgeOfTheGods/Rooney.java index 4ceb43de24..fefefec534 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ForgeOfTheGods/Rooney.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/ForgeOfTheGods/Rooney.java @@ -29,7 +29,7 @@ import ai.npc.AbstractNpcAI; * Rooney AI * @author malyelfik */ -final class Rooney extends AbstractNpcAI +public final class Rooney extends AbstractNpcAI { // NPC private static final int ROONEY = 32049; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FortressArcherCaptain/FortressArcherCaptain.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FortressArcherCaptain/FortressArcherCaptain.java index c52233cb41..7286e73158 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FortressArcherCaptain/FortressArcherCaptain.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FortressArcherCaptain/FortressArcherCaptain.java @@ -25,7 +25,7 @@ import ai.npc.AbstractNpcAI; * Fortress Archer Captain AI. * @author St3eT */ -final class FortressArcherCaptain extends AbstractNpcAI +public final class FortressArcherCaptain extends AbstractNpcAI { // NPCs private static final int[] ARCHER_CAPTAIN = diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FortressSiegeManager/FortressSiegeManager.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FortressSiegeManager/FortressSiegeManager.java index fb01b85f50..a8938fa460 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FortressSiegeManager/FortressSiegeManager.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FortressSiegeManager/FortressSiegeManager.java @@ -33,7 +33,7 @@ import ai.npc.AbstractNpcAI; * Fortress Siege Manager AI. * @author St3eT */ -final class FortressSiegeManager extends AbstractNpcAI +public final class FortressSiegeManager extends AbstractNpcAI { // NPCs private static final int[] MANAGERS = diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FreyasSteward/FreyasSteward.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FreyasSteward/FreyasSteward.java index 3583cb747b..ef5a5d9cd9 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FreyasSteward/FreyasSteward.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/FreyasSteward/FreyasSteward.java @@ -26,7 +26,7 @@ import ai.npc.AbstractNpcAI; * Freya's Steward AI. * @author Adry_85 */ -final class FreyasSteward extends AbstractNpcAI +public final class FreyasSteward extends AbstractNpcAI { // NPC private static final int FREYAS_STEWARD = 32029; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Jinia/Jinia.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Jinia/Jinia.java index 31ee3f1fc5..be7405cf7e 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Jinia/Jinia.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Jinia/Jinia.java @@ -27,7 +27,7 @@ import quests.Q10286_ReunionWithSirra.Q10286_ReunionWithSirra; * Jinia AI. * @author Adry_85 */ -final class Jinia extends AbstractNpcAI +public final class Jinia extends AbstractNpcAI { // NPC private static final int JINIA = 32781; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/KetraOrcSupport/KetraOrcSupport.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/KetraOrcSupport/KetraOrcSupport.java index 61e9aafae1..944f884d03 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/KetraOrcSupport/KetraOrcSupport.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/KetraOrcSupport/KetraOrcSupport.java @@ -32,7 +32,7 @@ import ai.npc.AbstractNpcAI; * Original Jython script by Emperorc and Kerberos_20. * @authors Nyaran */ -final class KetraOrcSupport extends AbstractNpcAI +public final class KetraOrcSupport extends AbstractNpcAI { private static class BuffsData { diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Minigame/Minigame.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Minigame/Minigame.java index bd92e93fc6..038fe3ba99 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Minigame/Minigame.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/Minigame/Minigame.java @@ -39,7 +39,7 @@ import ai.npc.AbstractNpcAI; * Monastery Minigame AI. * @author nonom */ -final class Minigame extends AbstractNpcAI +public final class Minigame extends AbstractNpcAI { private static final int SUMIEL = 32758; private static final int BURNER = 18913; diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/VarkaSilenosSupport/VarkaSilenosSupport.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/VarkaSilenosSupport/VarkaSilenosSupport.java index e9aeca1a40..4ee1dd9a5b 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/VarkaSilenosSupport/VarkaSilenosSupport.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/VarkaSilenosSupport/VarkaSilenosSupport.java @@ -32,7 +32,7 @@ import ai.npc.AbstractNpcAI; * Original Jython script by Emperorc and Kerberos_20. * @author Nyaran */ -final class VarkaSilenosSupport extends AbstractNpcAI +public final class VarkaSilenosSupport extends AbstractNpcAI { private static class BuffsData { diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/VillageMasters/FirstClassTransferTalk/FirstClassTransferTalk.java b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/VillageMasters/FirstClassTransferTalk/FirstClassTransferTalk.java index 4f589dfa90..84513206fa 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/VillageMasters/FirstClassTransferTalk/FirstClassTransferTalk.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/ai/npc/VillageMasters/FirstClassTransferTalk/FirstClassTransferTalk.java @@ -32,7 +32,7 @@ import ai.npc.AbstractNpcAI; * None of them provide actual class transfers, they only talk about it. * @author jurchiks, xban1x */ -final class FirstClassTransferTalk extends AbstractNpcAI +public final class FirstClassTransferTalk extends AbstractNpcAI { private static final Map MASTERS = new HashMap<>(); static diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/conquerablehalls/flagwar/FlagWar.java b/L2J_Mobius_HighFive/dist/game/data/scripts/conquerablehalls/flagwar/FlagWar.java index 90fcc63e8c..78059d9766 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/conquerablehalls/flagwar/FlagWar.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/conquerablehalls/flagwar/FlagWar.java @@ -40,6 +40,7 @@ import com.l2jmobius.gameserver.model.Location; import com.l2jmobius.gameserver.model.TeleportWhereType; import com.l2jmobius.gameserver.model.actor.L2Npc; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.entity.Siegable; import com.l2jmobius.gameserver.model.entity.clanhall.ClanHallSiegeEngine; import com.l2jmobius.gameserver.model.entity.clanhall.SiegeStatus; import com.l2jmobius.gameserver.model.zone.type.L2ResidenceHallTeleportZone; @@ -498,17 +499,20 @@ public abstract class FlagWar extends ClanHallSiegeEngine } // Schedule open doors closement and siege start in 2 minutes - ThreadPoolManager.getInstance().scheduleGeneral(new CloseOutterDoorsTask(), 300000); + ThreadPoolManager.getInstance().scheduleGeneral(new CloseOutterDoorsTask(this), 300000); } /** * Runnable class to schedule doors closing and siege start. * @author Zoey76 */ - private class CloseOutterDoorsTask implements Runnable + protected class CloseOutterDoorsTask implements Runnable { - public CloseOutterDoorsTask() + private final Siegable _siegable; + + protected CloseOutterDoorsTask(Siegable clanHallSiege) { + _siegable = clanHallSiege; } @Override @@ -520,7 +524,8 @@ public abstract class FlagWar extends ClanHallSiegeEngine } _hall.getZone().banishNonSiegeParticipants(); - _hall.getSiege().startSiege(); + + _siegable.startSiege(); } } diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/handlers/admincommandhandlers/AdminQuest.java b/L2J_Mobius_HighFive/dist/game/data/scripts/handlers/admincommandhandlers/AdminQuest.java index b79052db66..20ec604b83 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/handlers/admincommandhandlers/AdminQuest.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/handlers/admincommandhandlers/AdminQuest.java @@ -16,12 +16,13 @@ */ package handlers.admincommandhandlers; -import java.io.File; +import java.nio.file.Paths; import java.util.List; import java.util.Set; +import java.util.StringTokenizer; import java.util.TreeSet; - -import javax.script.ScriptException; +import java.util.logging.Level; +import java.util.logging.Logger; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.instancemanager.QuestManager; @@ -33,11 +34,12 @@ import com.l2jmobius.gameserver.model.events.listeners.AbstractEventListener; import com.l2jmobius.gameserver.model.quest.Quest; import com.l2jmobius.gameserver.model.quest.QuestTimer; import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; -import com.l2jmobius.gameserver.scripting.L2ScriptEngineManager; +import com.l2jmobius.gameserver.scripting.ScriptEngineManager; import com.l2jmobius.gameserver.util.Util; public class AdminQuest implements IAdminCommandHandler { + public static final Logger LOGGER = Logger.getLogger(AdminQuest.class.getName()); private static final String[] ADMIN_COMMANDS = { "admin_quest_reload", @@ -47,139 +49,89 @@ public class AdminQuest implements IAdminCommandHandler "admin_quest_info" }; + private Quest findScript(String script) + { + if (Util.isDigit(script)) + { + return QuestManager.getInstance().getQuest(Integer.parseInt(script)); + } + return QuestManager.getInstance().getQuest(script); + } + @Override public boolean useAdminCommand(String command, L2PcInstance activeChar) { - if (activeChar == null) - { - return false; - } - - // syntax will either be: - // //quest_reload - // //quest_reload - // The questName MUST start with a non-numeric character for this to work, - // regardless which of the two formats is used. - // Example: //quest_reload orc_occupation_change_1 - // Example: //quest_reload chests - // Example: //quest_reload SagasSuperclass - // Example: //quest_reload 12 if (command.startsWith("admin_quest_reload")) { - final String[] parts = command.split(" "); - if (parts.length < 2) + StringTokenizer st = new StringTokenizer(command); + st.nextToken(); // skip command token + + if (!st.hasMoreTokens()) { - activeChar.sendMessage("Usage: //quest_reload ..questName> or //quest_reload "); - } - else - { - // try the first param as id - try - { - final int questId = Integer.parseInt(parts[1]); - if (QuestManager.getInstance().reload(questId)) - { - activeChar.sendMessage("Quest Reloaded Successfully."); - } - else - { - activeChar.sendMessage("Quest Reloaded Failed"); - } - } - catch (NumberFormatException e) - { - if (QuestManager.getInstance().reload(parts[1])) - { - activeChar.sendMessage("Quest Reloaded Successfully."); - } - else - { - activeChar.sendMessage("Quest Reloaded Failed"); - } - } - } - } - // script load should NOT be used in place of reload. If a script is already loaded - // successfully, quest_reload ought to be used. The script_load command should only - // be used for scripts that failed to load altogether (eg. due to errors) or that - // did not at all exist during server boot. Using script_load to re-load a previously - // loaded script may cause unpredictable script flow, minor loss of data, and more. - // This provides a way to load new scripts without having to reboot the server. - else if (command.startsWith("admin_script_load")) - { - final String[] parts = command.split(" "); - if (parts.length < 2) - { - // activeChar.sendMessage("Example: //script_load //. "); - activeChar.sendMessage("Example: //script_load quests/SagasSuperclass/__init__.py"); - } - else - { - File file = new File(L2ScriptEngineManager.SCRIPT_FOLDER, parts[1]); - // Trying to reload by script name. - if (!file.exists()) - { - final Quest quest = QuestManager.getInstance().getQuest(parts[1]); - if (quest != null) - { - file = new File(L2ScriptEngineManager.SCRIPT_FOLDER, quest.getClass().getName().replaceAll("\\.", "/") + ".java"); - } - } - - // Reloading by full path - if (file.isFile()) - { - try - { - L2ScriptEngineManager.getInstance().executeScript(file); - - // This part should be called only when the script is successfully loaded. - activeChar.sendMessage("Script Successfully Loaded."); - } - catch (ScriptException e) - { - activeChar.sendMessage("Failed loading: " + parts[1]); - L2ScriptEngineManager.getInstance().reportScriptFileError(file, e); - } - catch (Exception e) - { - activeChar.sendMessage("Failed loading: " + parts[1]); - } - } - else - { - activeChar.sendMessage("File Not Found: " + parts[1]); - } + activeChar.sendMessage("Usage: //quest_reload or "); + return false; } + String script = st.nextToken(); + Quest quest = findScript(script); + if (quest == null) + { + activeChar.sendMessage("The script " + script + " couldn't be found!"); + return false; + } + + if (!quest.reload()) + { + activeChar.sendMessage("Failed to reload " + script + "!"); + return false; + } + + activeChar.sendMessage("Script successful reloaded."); + } + else if (command.startsWith("admin_script_load")) + { + StringTokenizer st = new StringTokenizer(command); + st.nextToken(); // skip command token + + if (!st.hasMoreTokens()) + { + activeChar.sendMessage("Usage: //script_load path/to/script.java"); + return false; + } + + String script = st.nextToken(); + try + { + ScriptEngineManager.getInstance().executeScript(Paths.get(script)); + activeChar.sendMessage("Script loaded seccessful!"); + } + catch (Exception e) + { + activeChar.sendMessage("Failed to load script!"); + LOGGER.log(Level.WARNING, "Failed to load script " + script + "!", e); + } } else if (command.startsWith("admin_script_unload")) { - final String[] parts = command.split(" "); - if (parts.length < 2) + StringTokenizer st = new StringTokenizer(command); + st.nextToken(); // skip command token + + if (!st.hasMoreTokens()) { - activeChar.sendMessage("Example: //script_unload questName/questId"); + activeChar.sendMessage("Usage: //script_load path/to/script.java"); + return false; } - else + + String script = st.nextToken(); + Quest quest = findScript(script); + if (quest == null) { - final Quest q = Util.isDigit(parts[1]) ? QuestManager.getInstance().getQuest(Integer.parseInt(parts[1])) : QuestManager.getInstance().getQuest(parts[1]); - - if (q != null) - { - if (q.unload()) - { - activeChar.sendMessage("Script Successfully Unloaded [" + q.getName() + "/" + q.getId() + "]"); - } - else - { - activeChar.sendMessage("Failed unloading [" + q.getName() + "/" + q.getId() + "]."); - } - } - else - { - activeChar.sendMessage("The quest [" + parts[1] + "] was not found!."); - } + activeChar.sendMessage("The script " + script + " couldn't be found!"); + return false; } + + quest.unload(); + activeChar.sendMessage("Script successful unloaded!"); } else if (command.startsWith("admin_show_quests")) { diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/handlers/admincommandhandlers/AdminReload.java b/L2J_Mobius_HighFive/dist/game/data/scripts/handlers/admincommandhandlers/AdminReload.java index 016bdcc2e0..0e8bf36248 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/handlers/admincommandhandlers/AdminReload.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/handlers/admincommandhandlers/AdminReload.java @@ -18,8 +18,8 @@ package handlers.admincommandhandlers; import java.io.File; import java.util.StringTokenizer; - -import javax.script.ScriptException; +import java.util.logging.Level; +import java.util.logging.Logger; import com.l2jmobius.Config; import com.l2jmobius.gameserver.cache.HtmCache; @@ -41,7 +41,7 @@ import com.l2jmobius.gameserver.instancemanager.QuestManager; import com.l2jmobius.gameserver.instancemanager.WalkingManager; import com.l2jmobius.gameserver.instancemanager.ZoneManager; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.scripting.L2ScriptEngineManager; +import com.l2jmobius.gameserver.scripting.ScriptEngineManager; import com.l2jmobius.gameserver.util.Util; /** @@ -49,6 +49,8 @@ import com.l2jmobius.gameserver.util.Util; */ public class AdminReload implements IAdminCommandHandler { + private static final Logger LOGGER = Logger.getLogger(AdminReload.class.getName()); + private static final String[] ADMIN_COMMANDS = { "admin_reload" @@ -204,31 +206,29 @@ public class AdminReload implements IAdminCommandHandler } case "effect": { - final File file = new File(L2ScriptEngineManager.SCRIPT_FOLDER, "handlers/EffectMasterHandler.java"); try { - L2ScriptEngineManager.getInstance().executeScript(file); - AdminData.getInstance().broadcastMessageToGMs(activeChar.getName() + ": Reloaded Effects."); + ScriptEngineManager.getInstance().executeEffectMasterHandler(); + AdminData.getInstance().broadcastMessageToGMs(activeChar.getName() + ": Reloaded effect master handler."); } - catch (ScriptException e) + catch (Exception e) { - L2ScriptEngineManager.getInstance().reportScriptFileError(file, e); - activeChar.sendMessage("There was an error while loading handlers."); + LOGGER.log(Level.WARNING, "Failed executing effect master handler!", e); + activeChar.sendMessage("Error reloading effect master handler!"); } break; } case "handler": { - final File file = new File(L2ScriptEngineManager.SCRIPT_FOLDER, "handlers/MasterHandler.java"); try { - L2ScriptEngineManager.getInstance().executeScript(file); - AdminData.getInstance().broadcastMessageToGMs(activeChar.getName() + ": Reloaded Handlers."); + ScriptEngineManager.getInstance().executeMasterHandler(); + AdminData.getInstance().broadcastMessageToGMs(activeChar.getName() + ": Reloaded master handler."); } - catch (ScriptException e) + catch (Exception e) { - L2ScriptEngineManager.getInstance().reportScriptFileError(file, e); - activeChar.sendMessage("There was an error while loading handlers."); + LOGGER.log(Level.WARNING, "Failed executing master handler!", e); + activeChar.sendMessage("Error reloading master handler!"); } break; } @@ -261,5 +261,4 @@ public class AdminReload implements IAdminCommandHandler { return ADMIN_COMMANDS; } - } diff --git a/L2J_Mobius_HighFive/dist/game/data/scripts/handlers/telnethandlers/ReloadHandler.java b/L2J_Mobius_HighFive/dist/game/data/scripts/handlers/telnethandlers/ReloadHandler.java index d26aa63de6..519407f644 100644 --- a/L2J_Mobius_HighFive/dist/game/data/scripts/handlers/telnethandlers/ReloadHandler.java +++ b/L2J_Mobius_HighFive/dist/game/data/scripts/handlers/telnethandlers/ReloadHandler.java @@ -16,12 +16,11 @@ */ package handlers.telnethandlers; -import java.io.File; import java.io.PrintWriter; import java.net.Socket; +import java.nio.file.Paths; import java.util.StringTokenizer; - -import javax.script.ScriptException; +import java.util.logging.Level; import com.l2jmobius.gameserver.cache.HtmCache; import com.l2jmobius.gameserver.data.sql.impl.TeleportLocationTable; @@ -36,7 +35,7 @@ import com.l2jmobius.gameserver.instancemanager.QuestManager; import com.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager; import com.l2jmobius.gameserver.instancemanager.ZoneManager; import com.l2jmobius.gameserver.model.L2World; -import com.l2jmobius.gameserver.scripting.L2ScriptEngineManager; +import com.l2jmobius.gameserver.scripting.ScriptEngineManager; /** * @author UnAfraid @@ -116,29 +115,16 @@ public class ReloadHandler implements ITelnetHandler { try { - final String questPath = st.hasMoreTokens() ? st.nextToken() : ""; + String questPath = st.hasMoreTokens() ? st.nextToken() : ""; - final File file = new File(L2ScriptEngineManager.SCRIPT_FOLDER, questPath); - if (file.isFile()) + try { - try - { - L2ScriptEngineManager.getInstance().executeScript(file); - _print.println(file.getName() + " was successfully loaded!\n"); - } - catch (ScriptException e) - { - _print.println("Failed loading: " + questPath); - L2ScriptEngineManager.getInstance().reportScriptFileError(file, e); - } - catch (Exception e) - { - _print.println("Failed loading: " + questPath); - } + ScriptEngineManager.getInstance().executeScript(Paths.get(questPath)); + _print.println(questPath + " was successfully loaded!\n"); } - else + catch (Exception e) { - _print.println(file.getName() + " is not a file in: " + questPath); + _log.log(Level.WARNING, "Failed to execute script!", e); } } catch (StringIndexOutOfBoundsException e) diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/GameServer.java index a5d6afdd9a..ea54388540 100644 --- a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/GameServer.java +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/GameServer.java @@ -134,7 +134,7 @@ import com.l2jmobius.gameserver.model.olympiad.Olympiad; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.L2GamePacketHandler; import com.l2jmobius.gameserver.pathfinding.PathFinding; -import com.l2jmobius.gameserver.scripting.L2ScriptEngineManager; +import com.l2jmobius.gameserver.scripting.ScriptEngineManager; import com.l2jmobius.gameserver.taskmanager.KnownListUpdateTaskManager; import com.l2jmobius.gameserver.taskmanager.TaskManager; import com.l2jmobius.status.Status; @@ -171,8 +171,8 @@ public final class GameServer new File("log/game").mkdirs(); // load script engines - printSection("Engines"); - L2ScriptEngineManager.getInstance(); + printSection("Scripting Engines"); + ScriptEngineManager.getInstance(); printSection("World"); // start game time control early @@ -294,15 +294,12 @@ public final class GameServer try { - _log.info(getClass().getSimpleName() + ": Loading server scripts:"); - if (!Config.ALT_DEV_NO_HANDLERS || !Config.ALT_DEV_NO_QUESTS) - { - L2ScriptEngineManager.getInstance().executeScriptList(new File(Config.DATAPACK_ROOT, "data/scripts.cfg")); - } + _log.info("Loading server scripts..."); + ScriptEngineManager.getInstance().executeScriptList(); } - catch (IOException ioe) + catch (Exception e) { - _log.severe(getClass().getSimpleName() + ": Failed loading scripts.cfg, scripts are not going to be loaded!"); + _log.log(Level.WARNING, "Failed to execute script list!", e); } SpawnTable.getInstance().load(); diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/handler/EffectHandler.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/handler/EffectHandler.java index d770e06630..ff66b7e86e 100644 --- a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/handler/EffectHandler.java +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/handler/EffectHandler.java @@ -16,12 +16,11 @@ */ package com.l2jmobius.gameserver.handler; -import java.io.File; import java.util.HashMap; import java.util.Map; import com.l2jmobius.gameserver.model.effects.AbstractEffect; -import com.l2jmobius.gameserver.scripting.L2ScriptEngineManager; +import com.l2jmobius.gameserver.scripting.ScriptEngineManager; /** * @author BiggBoss, UnAfraid @@ -63,7 +62,7 @@ public final class EffectHandler implements IHandler +public final class QuestManager { protected static final Logger _log = Logger.getLogger(QuestManager.class.getName()); @@ -93,9 +90,9 @@ public final class QuestManager extends ScriptManager try { - L2ScriptEngineManager.getInstance().executeScriptList(new File(Config.DATAPACK_ROOT, "data/scripts.cfg")); + ScriptEngineManager.getInstance().executeScriptList(); } - catch (IOException e) + catch (Exception e) { _log.log(Level.SEVERE, getClass().getSimpleName() + ": Failed loading scripts.cfg, no script going to be loaded!", e); } @@ -216,24 +213,16 @@ public final class QuestManager extends ScriptManager return _quests; } - @Override public boolean unload(Quest ms) { ms.saveGlobalData(); return removeScript(ms); } - @Override - public String getScriptManagerName() - { - return getClass().getSimpleName(); - } - /** * Gets all the registered scripts. * @return all the scripts */ - @Override public Map getScripts() { return _scripts; diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/model/events/AbstractScript.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/model/events/AbstractScript.java index 2897ae3f05..6450b74e05 100644 --- a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/model/events/AbstractScript.java +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/model/events/AbstractScript.java @@ -16,7 +16,6 @@ */ package com.l2jmobius.gameserver.model.events; -import java.io.File; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; @@ -33,8 +32,6 @@ import java.util.function.Function; import java.util.logging.Level; import java.util.logging.Logger; -import javax.script.ScriptException; - import com.l2jmobius.Config; import com.l2jmobius.gameserver.GameTimeController; import com.l2jmobius.gameserver.ai.CtrlIntention; @@ -112,7 +109,6 @@ import com.l2jmobius.gameserver.model.events.returns.AbstractEventReturn; import com.l2jmobius.gameserver.model.events.returns.TerminateReturn; import com.l2jmobius.gameserver.model.holders.ItemHolder; import com.l2jmobius.gameserver.model.holders.SkillHolder; -import com.l2jmobius.gameserver.model.interfaces.INamable; import com.l2jmobius.gameserver.model.interfaces.IPositionable; import com.l2jmobius.gameserver.model.itemcontainer.Inventory; import com.l2jmobius.gameserver.model.itemcontainer.PcInventory; @@ -130,26 +126,21 @@ import com.l2jmobius.gameserver.network.serverpackets.InventoryUpdate; import com.l2jmobius.gameserver.network.serverpackets.SpecialCamera; import com.l2jmobius.gameserver.network.serverpackets.StatusUpdate; import com.l2jmobius.gameserver.network.serverpackets.SystemMessage; -import com.l2jmobius.gameserver.scripting.L2ScriptEngineManager; -import com.l2jmobius.gameserver.scripting.ScriptManager; +import com.l2jmobius.gameserver.scripting.ManagedScript; import com.l2jmobius.gameserver.util.MinionList; import com.l2jmobius.util.Rnd; /** - * Abstract script. - * @author KenM, UnAfraid, Zoey76 + * @author UnAfraid */ -public abstract class AbstractScript implements INamable +public abstract class AbstractScript extends ManagedScript { public static final Logger _log = Logger.getLogger(AbstractScript.class.getName()); private final Map> _registeredIds = new ConcurrentHashMap<>(); private final List _listeners = new CopyOnWriteArrayList<>(); - private final File _scriptFile; - private boolean _isActive; public AbstractScript() { - _scriptFile = L2ScriptEngineManager.getInstance().getCurrentLoadingScript(); initializeAnnotationListeners(); } @@ -295,38 +286,11 @@ public abstract class AbstractScript implements INamable } } - public void setActive(boolean status) - { - _isActive = status; - } - - public boolean isActive() - { - return _isActive; - } - - public File getScriptFile() - { - return _scriptFile; - } - - public boolean reload() - { - try - { - L2ScriptEngineManager.getInstance().executeScript(getScriptFile()); - return true; - } - catch (ScriptException e) - { - return false; - } - } - /** * Unloads all listeners registered by this class. * @return {@code true} */ + @Override public boolean unload() { _listeners.forEach(AbstractEventListener::unregisterMe); @@ -334,8 +298,6 @@ public abstract class AbstractScript implements INamable return true; } - public abstract ScriptManager getManager(); - // --------------------------------------------------------------------------------------------------------------------------- /** diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/model/quest/Quest.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/model/quest/Quest.java index 420fafcfde..68e22ff2fd 100644 --- a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/model/quest/Quest.java +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/model/quest/Quest.java @@ -63,7 +63,6 @@ import com.l2jmobius.gameserver.model.zone.L2ZoneType; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; import com.l2jmobius.gameserver.network.serverpackets.NpcQuestHtmlMessage; -import com.l2jmobius.gameserver.scripting.ScriptManager; import com.l2jmobius.util.Rnd; import com.l2jmobius.util.Util; @@ -203,7 +202,6 @@ public class Quest extends AbstractScript implements IIdentifiable return _initialState; } - @Override public String getName() { return _name; @@ -1385,7 +1383,7 @@ public class Quest extends AbstractScript implements IIdentifiable */ public boolean showError(L2PcInstance player, Throwable t) { - _log.log(Level.WARNING, getScriptFile().getAbsolutePath(), t); + _log.log(Level.WARNING, getScriptFile().toAbsolutePath().toString(), t); if (t.getMessage() == null) { _log.warning(getClass().getSimpleName() + ": " + t.getMessage()); @@ -2595,6 +2593,12 @@ public class Quest extends AbstractScript implements IIdentifiable takeItems(player, -1, questItemIds); } + @Override + public String getScriptName() + { + return getName(); + } + @Override public void setActive(boolean status) { @@ -2652,12 +2656,6 @@ public class Quest extends AbstractScript implements IIdentifiable return super.unload(); } - @Override - public ScriptManager getManager() - { - return QuestManager.getInstance(); - } - public void setOnEnterWorld(boolean state) { if (state) diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/script/Expression.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/script/Expression.java deleted file mode 100644 index ce89b9eb74..0000000000 --- a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/script/Expression.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of the L2J Mobius project. - * - * This program 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. - * - * This program 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.l2jmobius.gameserver.script; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.script.ScriptContext; - -public class Expression -{ - protected static final Logger _log = Logger.getLogger(Expression.class.getName()); - private final ScriptContext _context; - @SuppressWarnings("unused") - private final String _lang; - @SuppressWarnings("unused") - private final String _code; - - public static Expression create(ScriptContext context, String lang, String code) - { - try - { - return new Expression(context, lang, code); - } - catch (Exception e) - { - _log.log(Level.WARNING, "", e); - return null; - } - } - - private Expression(ScriptContext pContext, String pLang, String pCode) - { - _context = pContext; - _lang = pLang; - _code = pCode; - } - - public void addDynamicVariable(String name, T value) - { - try - { - _context.setAttribute(name, value, ScriptContext.ENGINE_SCOPE); - } - catch (Exception e) - { - _log.log(Level.WARNING, "", e); - } - } - - public void removeDynamicVariable(String name) - { - try - { - _context.removeAttribute(name, ScriptContext.ENGINE_SCOPE); - } - catch (Exception e) - { - _log.log(Level.WARNING, "", e); - } - } -} diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/AbstractExecutionContext.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/AbstractExecutionContext.java new file mode 100644 index 0000000000..8b8fa93a47 --- /dev/null +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/AbstractExecutionContext.java @@ -0,0 +1,75 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program 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. + * + * This program 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.l2jmobius.gameserver.scripting; + +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +/** + * @author HorridoJoho + * @param + */ +public abstract class AbstractExecutionContext implements IExecutionContext +{ + private final T _engine; + private final Map _properties; + private volatile Path _currentExecutingScipt; + + protected AbstractExecutionContext(final T engine) + { + if (engine == null) + { + throw new IllegalArgumentException(); + } + _engine = engine; + _properties = new HashMap<>(); + } + + protected final void setCurrentExecutingScript(final Path currentExecutingScript) + { + _currentExecutingScipt = currentExecutingScript; + } + + @Override + public final String setProperty(final String key, final String value) + { + return _properties.put(key, value); + } + + @Override + public final String getProperty(final String key) + { + if (!_properties.containsKey(key)) + { + return _engine.getProperty(key); + } + return _properties.get(key); + } + + @Override + public final Path getCurrentExecutingScript() + { + return _currentExecutingScipt; + } + + @Override + public final T getScriptingEngine() + { + return _engine; + } +} diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/AbstractScriptingEngine.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/AbstractScriptingEngine.java new file mode 100644 index 0000000000..d98234cc36 --- /dev/null +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/AbstractScriptingEngine.java @@ -0,0 +1,74 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program 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. + * + * This program 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.l2jmobius.gameserver.scripting; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * @author HorridoJoho + */ +public abstract class AbstractScriptingEngine implements IScriptingEngine +{ + private final String _engineName; + private final String _engineVersion; + private final String[] _commonFileExtensions; + private final Map _properties; + + protected AbstractScriptingEngine(final String engineName, final String engineVersion, final String... commonFileExtensions) + { + if ((engineName == null) || engineName.isEmpty() || (engineVersion == null) || engineVersion.isEmpty() || (commonFileExtensions == null) || (commonFileExtensions.length == 0)) + { + throw new IllegalArgumentException(); + } + _engineName = engineName; + _engineVersion = engineVersion; + _commonFileExtensions = commonFileExtensions; + _properties = new HashMap<>(); + } + + @Override + public final String setProperty(final String key, final String value) + { + return _properties.put(key, value); + } + + @Override + public final String getProperty(final String key) + { + return _properties.get(key); + } + + @Override + public final String getEngineName() + { + return _engineName; + } + + @Override + public final String getEngineVersion() + { + return _engineVersion; + } + + @Override + public final String[] getCommonFileExtensions() + { + return Arrays.copyOf(_commonFileExtensions, _commonFileExtensions.length); + } +} diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/IExecutionContext.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/IExecutionContext.java new file mode 100644 index 0000000000..057ba793e7 --- /dev/null +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/IExecutionContext.java @@ -0,0 +1,71 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program 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. + * + * This program 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.l2jmobius.gameserver.scripting; + +import java.nio.file.Path; +import java.util.Map; +import java.util.Map.Entry; + +/** + * @author HorridoJoho + */ +public interface IExecutionContext +{ + /** + * Properties set here override the settings from the IScriptEngine
+ * this class was created from. + * @param key the key + * @param value the value + * @return the previous value, or null when this key was not present before + */ + String setProperty(String key, String value); + + /** + * Executes all script in the iterable. + * @param sourcePaths the scripts to execute + * @return map of failed executions, Path=source file Throwable=thrown exception + * @throws Exception preparation for script execution failed + */ + Map executeScripts(Iterable sourcePaths) throws Exception; + + /** + * Executes a single file. + * @param sourcePath the script to execute + * @return entry of failed execution, Path=source file Throwable=thrown exception + * @throws Exception preparation for script execution failed + */ + Entry executeScript(Path sourcePath) throws Exception; + + /** + * Method to get the specified property value. + * @param key the key + * @return the value, or null if the key is not present + */ + String getProperty(String key); + + /** + * Method to get the current executing script file. + * @return the currently executing script file, null if non + */ + Path getCurrentExecutingScript(); + + /** + * Method to get the script engine this execution context belongs to. + * @return the script engine this execution context belongs to + */ + IScriptingEngine getScriptingEngine(); +} diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/IScriptingEngine.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/IScriptingEngine.java new file mode 100644 index 0000000000..520d8622bb --- /dev/null +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/IScriptingEngine.java @@ -0,0 +1,75 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program 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. + * + * This program 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.l2jmobius.gameserver.scripting; + +/** + * @author HorridoJoho + */ +public interface IScriptingEngine +{ + /** + * Sets script engine properties. The script values will be available
+ * to the the insatnces created {@link IExecutionContext} implementation. + * @param key the key + * @param value the value + * @return the previous value, or null when this key was not present before + */ + String setProperty(String key, String value); + + /** + * Creates an execution context. + * @return the created execution context. + */ + IExecutionContext createExecutionContext(); + + /** + * Method to get the specified property value. + * @param key the key + * @return the value,or null if the key is not present + */ + String getProperty(String key); + + /** + * Method to get the engine name. + * @return the engine name + */ + String getEngineName(); + + /** + * Method to get the engine version. + * @return the engine version + */ + String getEngineVersion(); + + /** + * Method to get the scripting language name. + * @return the scripting engine name + */ + String getLanguageName(); + + /** + * Method to get the the language version. + * @return the language version + */ + String getLanguageVersion(); + + /** + * Method to retrive the commonly used file extensions for the language. + * @return the commonly used file extensions for the language + */ + String[] getCommonFileExtensions(); +} diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/L2ScriptEngineManager.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/L2ScriptEngineManager.java deleted file mode 100644 index 4e59c1bf3b..0000000000 --- a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/L2ScriptEngineManager.java +++ /dev/null @@ -1,363 +0,0 @@ -/* - * This file is part of the L2J Mobius project. - * - * This program 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. - * - * This program 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.l2jmobius.gameserver.scripting; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.LineNumberReader; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.script.Compilable; -import javax.script.CompiledScript; -import javax.script.ScriptContext; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineFactory; -import javax.script.ScriptEngineManager; -import javax.script.ScriptException; -import javax.script.SimpleScriptContext; - -import com.l2jmobius.Config; -import com.l2jmobius.commons.javaengine.JavaScriptEngineFactory; - -/** - * Caches script engines and provides functionality for executing and managing scripts. - * @author KenM - */ -public final class L2ScriptEngineManager -{ - private static final Logger _log = Logger.getLogger(L2ScriptEngineManager.class.getName()); - - public static final File SCRIPT_FOLDER = new File(Config.DATAPACK_ROOT.getAbsolutePath(), "data/scripts"); - - public static L2ScriptEngineManager getInstance() - { - return SingletonHolder._instance; - } - - private final Map _extEngines = new HashMap<>(); - private final List> _scriptManagers = new LinkedList<>(); - - private File _currentLoadingScript; - - /** - * If the script engine supports compilation the script is compiled before execution.
- */ - private static final boolean ATTEMPT_COMPILATION = true; - - protected L2ScriptEngineManager() - { - final ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); - final ScriptEngineFactory factory = new JavaScriptEngineFactory(); - scriptEngineManager.registerEngineExtension("java", factory); - _extEngines.put("java", factory.getScriptEngine()); - _log.info("Script Engine: " + factory.getEngineName() + " " + factory.getEngineVersion() + " - Language: " + factory.getLanguageName() + " - Language Version: " + factory.getLanguageVersion()); - } - - private ScriptEngine getEngineByExtension(String ext) - { - return _extEngines.get(ext); - } - - public void executeScriptList(File list) throws IOException - { - if (Config.ALT_DEV_NO_QUESTS) - { - if (!Config.ALT_DEV_NO_HANDLERS) - { - try - { - executeScript(new File(SCRIPT_FOLDER, "handlers/MasterHandler.java")); - _log.info("Handlers loaded, all other scripts skipped"); - } - catch (ScriptException se) - { - _log.log(Level.WARNING, "", se); - } - } - return; - } - - if (!list.isFile()) - { - throw new IllegalArgumentException("Argument must be an file containing a list of scripts to be loaded"); - } - - try (FileInputStream fis = new FileInputStream(list); - InputStreamReader isr = new InputStreamReader(fis); - LineNumberReader lnr = new LineNumberReader(isr)) - { - String line; - while ((line = lnr.readLine()) != null) - { - if (Config.ALT_DEV_NO_HANDLERS && line.contains("MasterHandler.java")) - { - continue; - } - - final 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(SCRIPT_FOLDER, line); - - if (file.isDirectory() && parts[0].endsWith("/**")) - { - executeAllScriptsInDirectory(file, true, 32); - } - else if (file.isDirectory() && parts[0].endsWith("/*")) - { - executeAllScriptsInDirectory(file); - } - else if (file.isFile()) - { - try - { - executeScript(file); - } - catch (ScriptException e) - { - reportScriptFileError(file, e); - } - } - else - { - _log.warning("Failed loading: (" + file.getCanonicalPath() + ") @ " + list.getName() + ":" + lnr.getLineNumber() + " - Reason: doesnt exists or is not a file."); - } - } - } - } - } - - public void executeAllScriptsInDirectory(File dir) - { - executeAllScriptsInDirectory(dir, false, 0); - } - - public void executeAllScriptsInDirectory(File dir, boolean recurseDown, int maxDepth) - { - executeAllScriptsInDirectory(dir, recurseDown, maxDepth, 0); - } - - private void executeAllScriptsInDirectory(File dir, boolean recurseDown, int maxDepth, int currentDepth) - { - if (!dir.isDirectory()) - { - throw new IllegalArgumentException("The argument directory either doesnt exists or is not an directory."); - } - - final File[] files = dir.listFiles(); - if (files == null) - { - return; - } - - for (File file : files) - { - if (file.isDirectory() && recurseDown && (maxDepth > currentDepth)) - { - executeAllScriptsInDirectory(file, recurseDown, maxDepth, currentDepth + 1); - } - else if (file.isFile()) - { - try - { - final String name = file.getName(); - final int lastIndex = name.lastIndexOf('.'); - String extension; - if (lastIndex != -1) - { - extension = name.substring(lastIndex + 1); - final ScriptEngine engine = getEngineByExtension(extension); - if (engine != null) - { - executeScript(engine, file); - } - } - } - catch (ScriptException e) - { - reportScriptFileError(file, e); - } - } - } - } - - public void executeScript(File file) throws ScriptException - { - final String name = file.getName(); - final int lastIndex = name.lastIndexOf('.'); - String extension; - if (lastIndex == -1) - { - throw new ScriptException("Script file (" + name + ") doesnt has an extension that identifies the ScriptEngine to be used."); - } - extension = name.substring(lastIndex + 1); - final ScriptEngine engine = getEngineByExtension(extension); - if (engine == null) - { - throw new ScriptException("No engine registered for extension (" + extension + ")"); - } - executeScript(engine, file); - } - - public void executeScript(ScriptEngine engine, File file) throws ScriptException - { - { - final String name = file.getAbsolutePath() + ".error.log"; - final File errorLog = new File(name); - if (errorLog.isFile()) - { - errorLog.delete(); - } - } - - final String relativeName = file.getAbsolutePath().substring(SCRIPT_FOLDER.getAbsolutePath().length() + 1).replace('\\', '/'); - try (FileInputStream fis = new FileInputStream(file); - InputStreamReader isr = new InputStreamReader(fis); - BufferedReader reader = new BufferedReader(isr)) - { - final ScriptContext context = new SimpleScriptContext(); - context.setAttribute("mainClass", getClassForFile(file).replace('/', '.').replace('\\', '.'), ScriptContext.ENGINE_SCOPE); - context.setAttribute(ScriptEngine.FILENAME, relativeName, ScriptContext.ENGINE_SCOPE); - context.setAttribute("classpath", SCRIPT_FOLDER.getAbsolutePath(), ScriptContext.ENGINE_SCOPE); - context.setAttribute("sourcepath", SCRIPT_FOLDER.getAbsolutePath(), ScriptContext.ENGINE_SCOPE); - setCurrentLoadingScript(file); - try - { - engine.eval(reader, context); - } - finally - { - setCurrentLoadingScript(null); - engine.getContext().removeAttribute(ScriptEngine.FILENAME, ScriptContext.ENGINE_SCOPE); - engine.getContext().removeAttribute("mainClass", ScriptContext.ENGINE_SCOPE); - } - } - catch (IOException e) - { - _log.log(Level.WARNING, "Error executing script!", e); - } - } - - public static String getClassForFile(File script) - { - final String path = script.getAbsolutePath(); - final String scpPath = SCRIPT_FOLDER.getAbsolutePath(); - return path.startsWith(scpPath) ? path.substring(scpPath.length() + 1, path.lastIndexOf('.')) : null; - } - - public ScriptContext getScriptContext(ScriptEngine engine) - { - return engine.getContext(); - } - - public Object eval(ScriptEngine engine, String script, ScriptContext context) throws ScriptException - { - if (!(engine instanceof Compilable) || !ATTEMPT_COMPILATION) - { - return context != null ? engine.eval(script, context) : engine.eval(script); - } - final Compilable eng = (Compilable) engine; - final CompiledScript cs = eng.compile(script); - return context != null ? cs.eval(context) : cs.eval(); - } - - public Object eval(ScriptEngine engine, String script) throws ScriptException - { - return eval(engine, script, null); - } - - public void reportScriptFileError(File script, ScriptException e) - { - final String dir = script.getParent(); - if (dir != null) - { - final File file = new File(dir + "/" + script.getName() + ".error.log"); - try (FileOutputStream fos = new FileOutputStream(file)) - { - final String errorHeader = "Error on: " + file.getCanonicalPath() + Config.EOL + "Line: " + e.getLineNumber() + " - Column: " + e.getColumnNumber() + Config.EOL + Config.EOL; - fos.write(errorHeader.getBytes()); - fos.write(e.getMessage().getBytes()); - _log.warning("Failed executing script: " + script.getAbsolutePath() + ". See " + file.getName() + " for details."); - } - catch (IOException ioe) - { - _log.log(Level.WARNING, "Failed executing script: " + script.getAbsolutePath() + Config.EOL + e.getMessage() + "Additionally failed when trying to write an error report on script directory. Reason: " + ioe.getMessage(), ioe); - } - } - else - { - _log.log(Level.WARNING, "Failed executing script: " + script.getAbsolutePath() + Config.EOL + e.getMessage() + "Additionally failed when trying to write an error report on script directory.", e); - } - } - - public void registerScriptManager(ScriptManager manager) - { - _scriptManagers.add(manager); - } - - public void removeScriptManager(ScriptManager manager) - { - _scriptManagers.remove(manager); - } - - public List> getScriptManagers() - { - return _scriptManagers; - } - - /** - * @param currentLoadingScript The currentLoadingScript to set. - */ - protected void setCurrentLoadingScript(File currentLoadingScript) - { - _currentLoadingScript = currentLoadingScript; - } - - /** - * @return Returns the currentLoadingScript. - */ - public File getCurrentLoadingScript() - { - return _currentLoadingScript; - } - - private static class SingletonHolder - { - protected static final L2ScriptEngineManager _instance = new L2ScriptEngineManager(); - } -} diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/ManagedScript.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/ManagedScript.java new file mode 100644 index 0000000000..dc6f1e5196 --- /dev/null +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/ManagedScript.java @@ -0,0 +1,97 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program 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. + * + * This program 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.l2jmobius.gameserver.scripting; + +import java.nio.file.Path; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Abstract class for classes that are meant to be implemented by scripts.
+ * @author KenM + */ +public abstract class ManagedScript +{ + private static final Logger LOGGER = Logger.getLogger(ManagedScript.class.getName()); + + private final Path _scriptFile; + private long _lastLoadTime; + private boolean _isActive; + + public ManagedScript() + { + _scriptFile = ScriptEngineManager.getInstance().getCurrentLoadingScript(); + setLastLoadTime(System.currentTimeMillis()); + } + + /** + * Attempts to reload this script and to refresh the necessary bindings with it ScriptControler.
+ * Subclasses of this class should override this method to properly refresh their bindings when necessary. + * @return true if and only if the script was reloaded, false otherwise. + */ + public boolean reload() + { + try + { + ScriptEngineManager.getInstance().executeScript(getScriptFile()); + return true; + } + catch (Exception e) + { + LOGGER.log(Level.WARNING, "Failed to reload script!", e); + return false; + } + } + + public abstract boolean unload(); + + public void setActive(boolean status) + { + _isActive = status; + } + + public boolean isActive() + { + return _isActive; + } + + /** + * @return Returns the scriptFile. + */ + public Path getScriptFile() + { + return _scriptFile; + } + + /** + * @param lastLoadTime The lastLoadTime to set. + */ + protected void setLastLoadTime(long lastLoadTime) + { + _lastLoadTime = lastLoadTime; + } + + /** + * @return Returns the lastLoadTime. + */ + protected long getLastLoadTime() + { + return _lastLoadTime; + } + + public abstract String getScriptName(); +} diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/ScriptEngineManager.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/ScriptEngineManager.java new file mode 100644 index 0000000000..d189975808 --- /dev/null +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/ScriptEngineManager.java @@ -0,0 +1,287 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program 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. + * + * This program 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.l2jmobius.gameserver.scripting; + +import java.io.FileInputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Properties; +import java.util.ServiceLoader; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.l2jmobius.Config; +import com.l2jmobius.gameserver.scripting.java.JavaScriptingEngine; + +/** + * Caches script engines and provides functionality for executing and managing scripts. + * @author KenM, HorridoJoho + */ +public final class ScriptEngineManager +{ + private static final Logger _log = Logger.getLogger(ScriptEngineManager.class.getName()); + public static final Path SCRIPT_LIST_FILE = Paths.get(Config.DATAPACK_ROOT.getAbsolutePath(), "data", "scripts.cfg"); + public static final Path SCRIPT_FOLDER = Paths.get(Config.DATAPACK_ROOT.getAbsolutePath(), "data", "scripts"); + public static final Path MASTER_HANDLER_FILE = Paths.get(SCRIPT_FOLDER.toString(), "handlers", "MasterHandler.java"); + public static final Path EFFECT_MASTER_HANDLER_FILE = Paths.get(SCRIPT_FOLDER.toString(), "handlers", "EffectMasterHandler.java"); + + private final Map _extEngines = new HashMap<>(); + private IExecutionContext _currentExecutionContext = null; + + protected ScriptEngineManager() + { + final Properties props = loadProperties(); + + // Default java engine implementation + registerEngine(new JavaScriptingEngine(), props); + + // Load external script engines + ServiceLoader.load(IScriptingEngine.class).forEach(engine -> registerEngine(engine, props)); + } + + private Properties loadProperties() + { + Properties props = null; + try (FileInputStream fis = new FileInputStream("config/ScriptEngines.ini")) + { + props = new Properties(); + props.load(fis); + } + catch (Exception e) + { + props = null; + _log.warning("Couldn't load ScriptEngines.ini: " + e.getMessage()); + } + return props; + } + + private void registerEngine(IScriptingEngine engine, Properties props) + { + maybeSetProperties("language." + engine.getLanguageName() + ".", props, engine); + final IExecutionContext context = engine.createExecutionContext(); + for (String commonExtension : engine.getCommonFileExtensions()) + { + _extEngines.put(commonExtension, context); + } + + _log.info("ScriptEngine: " + engine.getEngineName() + " " + engine.getEngineVersion() + " (" + engine.getLanguageName() + " " + engine.getLanguageVersion() + ")"); + } + + private void maybeSetProperties(String propPrefix, Properties props, IScriptingEngine engine) + { + if (props == null) + { + return; + } + + for (final Entry prop : props.entrySet()) + { + String key = (String) prop.getKey(); + String value = (String) prop.getValue(); + + if (key.startsWith(propPrefix)) + { + key = key.substring(propPrefix.length()); + if (value.startsWith("%") && value.endsWith("%")) + { + value = System.getProperty(value.substring(1, value.length() - 1)); + } + + engine.setProperty(key, value); + } + } + } + + private IExecutionContext getEngineByExtension(String ext) + { + return _extEngines.get(ext); + } + + private String getFileExtension(Path p) + { + final String name = p.getFileName().toString(); + final int lastDotIdx = name.lastIndexOf('.'); + if (lastDotIdx == -1) + { + return null; + } + + final String extension = name.substring(lastDotIdx + 1); + if (extension.isEmpty()) + { + return null; + } + + return extension; + } + + private void checkExistingFile(String messagePre, Path filePath) throws Exception + { + if (!Files.exists(filePath)) + { + throw new Exception(messagePre + ": " + filePath + " does not exists!"); + } + else if (!Files.isRegularFile(filePath)) + { + throw new Exception(messagePre + ": " + filePath + " is not a file!"); + } + } + + public void executeMasterHandler() throws Exception + { + executeScript(MASTER_HANDLER_FILE); + } + + public void executeEffectMasterHandler() throws Exception + { + executeScript(EFFECT_MASTER_HANDLER_FILE); + } + + public void executeScriptList() throws Exception + { + if (Config.ALT_DEV_NO_QUESTS) + { + return; + } + + // throws exception if not exists or not file + checkExistingFile("ScriptList", SCRIPT_LIST_FILE); + + final LinkedHashMap> files = new LinkedHashMap<>(); + final LinkedList extWithoutEngine = new LinkedList<>(); + + Files.lines(SCRIPT_LIST_FILE).forEach(line -> + { + line = line.trim(); + if (line.isEmpty() || (line.charAt(0) == '#')) + { + return; + } + + Path sourceFile = SCRIPT_FOLDER.resolve(line); + try + { + checkExistingFile("ScriptFile", sourceFile); + } + catch (Exception e) + { + _log.warning(e.getMessage()); + return; + } + + sourceFile = sourceFile.toAbsolutePath(); + final String ext = getFileExtension(sourceFile); + if (ext == null) + { + _log.warning("ScriptFile: " + sourceFile + " does not have an extension to determine the script engine!"); + return; + } + + final IExecutionContext engine = getEngineByExtension(ext); + if (engine == null) + { + if (!extWithoutEngine.contains(ext)) + { + extWithoutEngine.add(ext); + _log.warning("ScriptEngine: No engine registered for extension " + ext + "!"); + } + return; + } + + LinkedList ll = files.get(engine); + if (ll == null) + { + ll = new LinkedList<>(); + files.put(engine, ll); + } + ll.add(sourceFile); + }); + + for (Entry> entry : files.entrySet()) + { + _currentExecutionContext = entry.getKey(); + try + { + Map invokationErrors = entry.getKey().executeScripts(entry.getValue()); + for (Entry entry2 : invokationErrors.entrySet()) + { + _log.log(Level.WARNING, "ScriptEngine: " + entry2.getKey() + " failed execution!", entry2.getValue()); + } + } + finally + { + _currentExecutionContext = null; + } + } + } + + public void executeScript(Path sourceFile) throws Exception + { + Objects.requireNonNull(sourceFile); + + if (!sourceFile.isAbsolute()) + { + sourceFile = SCRIPT_FOLDER.resolve(sourceFile); + } + + // throws exception if not exists or not file + checkExistingFile("ScriptFile", sourceFile); + + sourceFile = sourceFile.toAbsolutePath(); + String ext = getFileExtension(sourceFile); + Objects.requireNonNull(sourceFile, "ScriptFile: " + sourceFile + " does not have an extension to determine the script engine!"); + + IExecutionContext engine = getEngineByExtension(ext); + Objects.requireNonNull(engine, "ScriptEngine: No engine registered for extension " + ext + "!"); + + _currentExecutionContext = engine; + try + { + Entry error = engine.executeScript(sourceFile); + if (error != null) + { + throw new Exception("ScriptEngine: " + error.getKey() + " failed execution!", error.getValue()); + } + } + finally + { + _currentExecutionContext = null; + } + } + + protected Path getCurrentLoadingScript() + { + return _currentExecutionContext.getCurrentExecutingScript(); + } + + public static ScriptEngineManager getInstance() + { + return SingletonHolder._instance; + } + + private static class SingletonHolder + { + protected static final ScriptEngineManager _instance = new ScriptEngineManager(); + } +} \ No newline at end of file diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/JavaCompilerException.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/JavaCompilerException.java new file mode 100644 index 0000000000..6bff868b95 --- /dev/null +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/JavaCompilerException.java @@ -0,0 +1,30 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program 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. + * + * This program 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.l2jmobius.gameserver.scripting.java; + +/** + * @author HorridoJoho + */ +public final class JavaCompilerException extends RuntimeException +{ + private static final long serialVersionUID = -8330513514176036095L; + + public JavaCompilerException(String diagnostics) + { + super(diagnostics); + } +} diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/JavaExecutionContext.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/JavaExecutionContext.java new file mode 100644 index 0000000000..df80d6699f --- /dev/null +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/JavaExecutionContext.java @@ -0,0 +1,239 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program 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. + * + * This program 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.l2jmobius.gameserver.scripting.java; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Map.Entry; +import java.util.logging.Logger; + +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaFileObject; + +import com.l2jmobius.gameserver.scripting.AbstractExecutionContext; + +/** + * @author HorridoJoho + */ +public final class JavaExecutionContext extends AbstractExecutionContext +{ + private static final Logger LOGGER = Logger.getLogger(JavaExecutionContext.class.getName()); + + JavaExecutionContext(final JavaScriptingEngine engine) + { + super(engine); + } + + private boolean addOptionIfNotNull(final LinkedList list, final String nullChecked, final String before) + { + if (nullChecked == null) + { + return false; + } + + if (before.endsWith(":")) + { + list.add(before + nullChecked); + } + else + { + list.add(before); + list.add(nullChecked); + } + + return true; + } + + private ClassLoader determineScriptParentClassloader() + { + String classloader = getProperty("classloader"); + if (classloader == null) + { + return ClassLoader.getSystemClassLoader(); + } + + switch (classloader) + { + case "ThreadContext": + return Thread.currentThread().getContextClassLoader(); + case "System": + return ClassLoader.getSystemClassLoader(); + default: + try + { + return Class.forName(classloader).getClassLoader(); + } + catch (ClassNotFoundException e) + { + return ClassLoader.getSystemClassLoader(); + } + } + } + + @Override + public Map executeScripts(final Iterable sourcePaths) throws Exception + { + final DiagnosticCollector fileManagerDiagnostics = new DiagnosticCollector<>(); + final DiagnosticCollector compilationDiagnostics = new DiagnosticCollector<>(); + + try (final ScriptingFileManager fileManager = new ScriptingFileManager(getScriptingEngine().getCompiler().getStandardFileManager(fileManagerDiagnostics, null, StandardCharsets.UTF_8))) + { + final StringWriter strOut = new StringWriter(); + final PrintWriter out = new PrintWriter(strOut); + final LinkedList options = new LinkedList<>(); + + addOptionIfNotNull(options, getProperty("source"), "-source"); + addOptionIfNotNull(options, getProperty("sourcepath"), "-sourcepath"); + if (!addOptionIfNotNull(options, getProperty("cp"), "-cp") && !addOptionIfNotNull(options, getProperty("classpath"), "-classpath")) + { + addOptionIfNotNull(options, System.getProperty("java.class.path"), "-cp"); + } + addOptionIfNotNull(options, getProperty("g"), "-g:"); + + // we always add the target JVM to the current running version + final String targetVersion = System.getProperty("java.specification.version"); + if (!targetVersion.contains(".")) + { + options.add("-target"); + options.add(targetVersion); + } + else + { + String[] versionSplit = targetVersion.split("\\."); + if (versionSplit.length > 1) + { + options.add("-target"); + options.add(versionSplit[0] + '.' + versionSplit[1]); + } + else + { + throw new JavaCompilerException("Could not determine target version!"); + } + } + + // we really need an iterable of files or strings + final LinkedList sourcePathStrings = new LinkedList<>(); + for (Path sourcePath : sourcePaths) + { + sourcePathStrings.add(sourcePath.toString()); + } + + final boolean compilationSuccess = getScriptingEngine().getCompiler().getTask(out, fileManager, compilationDiagnostics, options, null, fileManager.getJavaFileObjectsFromStrings(sourcePathStrings)).call(); + if (!compilationSuccess) + { + out.println(); + out.println("----------------"); + out.println("File diagnostics"); + out.println("----------------"); + for (Diagnostic diagnostic : fileManagerDiagnostics.getDiagnostics()) + { + out.println("\t" + diagnostic.getKind().toString() + ": " + diagnostic.getSource().getName() + ", Line " + diagnostic.getLineNumber() + ", Column " + diagnostic.getColumnNumber()); + out.println("\t\tcode: " + diagnostic.getCode()); + out.println("\t\tmessage: " + diagnostic.getMessage(null)); + } + + out.println(); + out.println("-----------------------"); + out.println("Compilation diagnostics"); + out.println("-----------------------"); + for (Diagnostic diagnostic : compilationDiagnostics.getDiagnostics()) + { + out.println("\t" + diagnostic.getKind().toString() + ": " + diagnostic.getSource().getName() + ", Line " + diagnostic.getLineNumber() + ", Column " + diagnostic.getColumnNumber()); + out.println("\t\tcode: " + diagnostic.getCode()); + out.println("\t\tmessage: " + diagnostic.getMessage(null)); + } + + throw new JavaCompilerException(strOut.toString()); + } + + final ClassLoader parentClassLoader = determineScriptParentClassloader(); + + LinkedHashMap executionFailures = new LinkedHashMap<>(); + Iterable compiledClasses = fileManager.getCompiledClasses(); + for (final Path sourcePath : sourcePaths) + { + boolean found = false; + + for (final ScriptingOutputFileObject compiledClass : compiledClasses) + { + Path compiledSourcePath = compiledClass.getSourcePath(); + // sourePath can be relative, so we have to use endsWith + if ((compiledSourcePath != null) && (compiledSourcePath.equals(sourcePath) || compiledSourcePath.endsWith(sourcePath))) + { + String javaName = compiledClass.getJavaName(); + if (javaName.indexOf('$') != -1) + { + continue; + } + + found = true; + setCurrentExecutingScript(compiledSourcePath); + try + { + ScriptingClassLoader loader = new ScriptingClassLoader(parentClassLoader, compiledClasses); + Class javaCls = loader.loadClass(javaName); + javaCls.getMethod("main", String[].class).invoke(null, (Object) new String[] + { + compiledSourcePath.toString() + }); + } + catch (Exception e) + { + executionFailures.put(compiledSourcePath, e); + } + finally + { + setCurrentExecutingScript(null); + } + + break; + } + } + + if (!found) + { + LOGGER.severe("Compilation successfull, but class coresponding to " + sourcePath.toString() + " not found!"); + } + } + + return executionFailures; + } + } + + @Override + public Entry executeScript(final Path sourcePath) throws Exception + { + @SuppressWarnings("serial") + Map executionFailures = executeScripts(new LinkedList() + { + { + add(sourcePath); + } + }); + if (!executionFailures.isEmpty()) + { + return executionFailures.entrySet().iterator().next(); + } + return null; + } +} diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/JavaScriptingEngine.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/JavaScriptingEngine.java new file mode 100644 index 0000000000..c5a84ac340 --- /dev/null +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/JavaScriptingEngine.java @@ -0,0 +1,138 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program 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. + * + * This program 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.l2jmobius.gameserver.scripting.java; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.ServiceLoader; + +import javax.lang.model.SourceVersion; +import javax.tools.JavaCompiler; +import javax.tools.ToolProvider; + +import com.l2jmobius.gameserver.scripting.AbstractScriptingEngine; +import com.l2jmobius.gameserver.scripting.IExecutionContext; + +/** + * @author HorridoJoho + */ +public final class JavaScriptingEngine extends AbstractScriptingEngine +{ + private volatile JavaCompiler _compiler; + + public JavaScriptingEngine() + { + super("L2J Java Engine", "1.0", "java"); + } + + private void determineCompilerOrThrow() + { + final String preferedCompiler = getProperty("preferedCompiler"); + LinkedList allCompilers = null; + + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler != null) + { + if ((preferedCompiler == null) || compiler.getClass().getName().equals(preferedCompiler)) + { + _compiler = compiler; + return; + } + + allCompilers = new LinkedList<>(); + allCompilers.add(compiler); + } + + final ServiceLoader thirdPartyCompilers = ServiceLoader.load(JavaCompiler.class); + Iterator compilersIterator = thirdPartyCompilers.iterator(); + while (compilersIterator.hasNext()) + { + compiler = compilersIterator.next(); + if ((preferedCompiler == null) || compiler.getClass().getName().equals(preferedCompiler)) + { + _compiler = compiler; + return; + } + + if (allCompilers == null) + { + allCompilers = new LinkedList<>(); + } + allCompilers.add(compilersIterator.next()); + } + + if (allCompilers != null) + { + compilersIterator = allCompilers.iterator(); + while (compilersIterator.hasNext()) + { + compiler = compilersIterator.next(); + if ((preferedCompiler == null) || compiler.getClass().getName().equals(preferedCompiler)) + { + break; + } + } + } + + if (compiler == null) + { + throw new IllegalStateException("No javax.tools.JavaCompiler service installed!"); + } + + _compiler = compiler; + } + + private void ensureCompilerOrThrow() + { + if (_compiler == null) + { + synchronized (this) + { + if (_compiler == null) + { + determineCompilerOrThrow(); + } + } + } + } + + JavaCompiler getCompiler() + { + return _compiler; + } + + @Override + public IExecutionContext createExecutionContext() + { + ensureCompilerOrThrow(); + return new JavaExecutionContext(this); + } + + @Override + public String getLanguageName() + { + return "Java"; + } + + @Override + public String getLanguageVersion() + { + ensureCompilerOrThrow(); + return Arrays.deepToString(_compiler.getSourceVersions().toArray(new SourceVersion[0])).replace("RELEASE_", ""); + } +} \ No newline at end of file diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/ScriptingClassLoader.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/ScriptingClassLoader.java new file mode 100644 index 0000000000..1bfae7f1ea --- /dev/null +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/ScriptingClassLoader.java @@ -0,0 +1,55 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program 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. + * + * This program 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.l2jmobius.gameserver.scripting.java; + +import java.util.logging.Logger; + +/** + * @author HorridoJoho + */ +public final class ScriptingClassLoader extends ClassLoader +{ + public static final Logger LOGGER = Logger.getLogger(ScriptingClassLoader.class.getName()); + + private Iterable _compiledClasses; + + ScriptingClassLoader(final ClassLoader parent, final Iterable compiledClasses) + { + super(parent); + _compiledClasses = compiledClasses; + } + + void removeCompiledClasses() + { + _compiledClasses = null; + } + + @Override + protected Class findClass(final String name) throws ClassNotFoundException + { + for (final ScriptingOutputFileObject compiledClass : _compiledClasses) + { + if (compiledClass.getJavaName().equals(name)) + { + final byte[] classBytes = compiledClass.getJavaData(); + return defineClass(name, classBytes, 0, classBytes.length); + } + } + + return super.findClass(name); + } +} diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/ScriptingFileManager.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/ScriptingFileManager.java new file mode 100644 index 0000000000..5c1d089e84 --- /dev/null +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/ScriptingFileManager.java @@ -0,0 +1,185 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program 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. + * + * This program 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.l2jmobius.gameserver.scripting.java; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Set; + +import javax.tools.FileObject; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.StandardJavaFileManager; + +/** + * @author HorridoJoho + */ +final class ScriptingFileManager implements StandardJavaFileManager +{ + private final StandardJavaFileManager _wrapped; + private final LinkedList _classOutputs = new LinkedList<>(); + + public ScriptingFileManager(StandardJavaFileManager wrapped) + { + _wrapped = wrapped; + } + + Iterable getCompiledClasses() + { + return Collections.unmodifiableCollection(_classOutputs); + } + + @Override + public int isSupportedOption(String option) + { + return _wrapped.isSupportedOption(option); + } + + @Override + public ClassLoader getClassLoader(Location location) + { + return _wrapped.getClassLoader(location); + } + + @Override + public Iterable list(Location location, String packageName, Set kinds, boolean recurse) throws IOException + { + return _wrapped.list(location, packageName, kinds, recurse); + } + + @Override + public String inferBinaryName(Location location, JavaFileObject file) + { + return _wrapped.inferBinaryName(location, file); + } + + @Override + public boolean isSameFile(FileObject a, FileObject b) + { + return _wrapped.isSameFile(a, b); + } + + @Override + public boolean handleOption(String current, Iterator remaining) + { + return _wrapped.handleOption(current, remaining); + } + + @Override + public boolean hasLocation(Location location) + { + return _wrapped.hasLocation(location); + } + + @Override + public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException + { + return _wrapped.getJavaFileForInput(location, className, kind); + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException + { + if (kind != Kind.CLASS) + { + return _wrapped.getJavaFileForOutput(location, className, kind, sibling); + } + + if (className.contains("/")) + { + className = className.replace('/', '.'); + } + + ScriptingOutputFileObject fileObject; + if (sibling != null) + { + fileObject = new ScriptingOutputFileObject(Paths.get(sibling.getName()), className, className.substring(className.lastIndexOf('.') + 1)); + } + else + { + fileObject = new ScriptingOutputFileObject(null, className, className.substring(className.lastIndexOf('.') + 1)); + } + + _classOutputs.add(fileObject); + return fileObject; + } + + @Override + public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException + { + return _wrapped.getFileForInput(location, packageName, relativeName); + } + + @Override + public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException + { + return _wrapped.getFileForOutput(location, packageName, relativeName, sibling); + } + + @Override + public void flush() throws IOException + { + _wrapped.flush(); + } + + @Override + public void close() throws IOException + { + _wrapped.close(); + } + + @Override + public Iterable getJavaFileObjectsFromFiles(Iterable files) + { + return _wrapped.getJavaFileObjectsFromFiles(files); + } + + @Override + public Iterable getJavaFileObjects(File... files) + { + return _wrapped.getJavaFileObjects(files); + } + + @Override + public Iterable getJavaFileObjectsFromStrings(Iterable names) + { + return _wrapped.getJavaFileObjectsFromStrings(names); + } + + @Override + public Iterable getJavaFileObjects(String... names) + { + return _wrapped.getJavaFileObjects(names); + } + + @Override + public void setLocation(Location location, Iterable path) throws IOException + { + _wrapped.setLocation(location, path); + + } + + @Override + public Iterable getLocation(Location location) + { + return _wrapped.getLocation(location); + } +} diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/ScriptingOutputFileObject.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/ScriptingOutputFileObject.java new file mode 100644 index 0000000000..87f19dc268 --- /dev/null +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/scripting/java/ScriptingOutputFileObject.java @@ -0,0 +1,147 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program 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. + * + * This program 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.l2jmobius.gameserver.scripting.java; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.net.URI; +import java.nio.file.Path; + +import javax.lang.model.element.Modifier; +import javax.lang.model.element.NestingKind; +import javax.tools.JavaFileObject; + +/** + * @author HorridoJoho + */ +final class ScriptingOutputFileObject implements JavaFileObject +{ + private final Path _sourcePath; + private final String _javaName; + private final String _javaSimpleName; + private final ByteArrayOutputStream _out; + + public ScriptingOutputFileObject(Path sourcePath, String javaName, String javaSimpleName) + { + _sourcePath = sourcePath; + _javaName = javaName; + _javaSimpleName = javaSimpleName; + _out = new ByteArrayOutputStream(); + } + + public Path getSourcePath() + { + return _sourcePath; + } + + public String getJavaName() + { + return _javaName; + } + + public String getJavaSimpleName() + { + return _javaSimpleName; + } + + public byte[] getJavaData() + { + return _out.toByteArray(); + } + + @Override + public URI toUri() + { + return null; + } + + @Override + public String getName() + { + return null; + } + + @Override + public InputStream openInputStream() + { + return null; + } + + @Override + public OutputStream openOutputStream() + { + return _out; + } + + @Override + public Reader openReader(boolean ignoreEncodingErrors) + { + return null; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) + { + return null; + } + + @Override + public Writer openWriter() + { + return null; + } + + @Override + public long getLastModified() + { + return 0; + } + + @Override + public boolean delete() + { + return false; + } + + @Override + public Kind getKind() + { + return Kind.CLASS; + } + + @Override + public boolean isNameCompatible(String simpleName, Kind kind) + { + return (kind == Kind.CLASS) && (_javaSimpleName == simpleName); + } + + @Override + public NestingKind getNestingKind() + { + return NestingKind.TOP_LEVEL; + } + + @Override + public Modifier getAccessLevel() + { + return null; + } + +} diff --git a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/taskmanager/tasks/TaskScript.java b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/taskmanager/tasks/TaskScript.java index c333b9f538..c291c910e7 100644 --- a/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/taskmanager/tasks/TaskScript.java +++ b/L2J_Mobius_HighFive/java/com/l2jmobius/gameserver/taskmanager/tasks/TaskScript.java @@ -16,11 +16,10 @@ */ package com.l2jmobius.gameserver.taskmanager.tasks; -import java.io.File; +import java.nio.file.Paths; +import java.util.logging.Level; -import javax.script.ScriptException; - -import com.l2jmobius.gameserver.scripting.L2ScriptEngineManager; +import com.l2jmobius.gameserver.scripting.ScriptEngineManager; import com.l2jmobius.gameserver.taskmanager.Task; import com.l2jmobius.gameserver.taskmanager.TaskManager.ExecutedTask; @@ -40,26 +39,13 @@ public class TaskScript extends Task @Override public void onTimeElapsed(ExecutedTask task) { - final File file = new File(L2ScriptEngineManager.SCRIPT_FOLDER, "cron/" + task.getParams()[2]); - if (file.isFile()) + try { - try - { - L2ScriptEngineManager.getInstance().executeScript(file); - } - catch (ScriptException e) - { - _log.warning("Failed loading: " + task.getParams()[2]); - L2ScriptEngineManager.getInstance().reportScriptFileError(file, e); - } - catch (Exception e) - { - _log.warning("Failed loading: " + task.getParams()[2]); - } + ScriptEngineManager.getInstance().executeScript(Paths.get("cron", task.getParams()[2])); } - else + catch (Exception e) { - _log.warning("File Not Found: " + task.getParams()[2]); + _log.log(Level.WARNING, "Script execution failed!", e); } } }