diff --git a/MockSkript b/MockSkript index 95dfd95..2c72e6c 160000 --- a/MockSkript +++ b/MockSkript @@ -1 +1 @@ -Subproject commit 95dfd95b987fe4a08b81b3501b7d953163892edc +Subproject commit 2c72e6ccefa6d0d8c74e4297beb3035861412f77 diff --git a/MockSkriptBridge/src/main/java/me/glicz/skanalyzer/bridge/AnalyzerCommandSender.java b/MockSkriptBridge/src/main/java/me/glicz/skanalyzer/bridge/AnalyzerCommandSender.java index ca3a249..ca83285 100644 --- a/MockSkriptBridge/src/main/java/me/glicz/skanalyzer/bridge/AnalyzerCommandSender.java +++ b/MockSkriptBridge/src/main/java/me/glicz/skanalyzer/bridge/AnalyzerCommandSender.java @@ -3,6 +3,7 @@ import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import me.glicz.skanalyzer.SkAnalyzer; import me.glicz.skanalyzer.structure.StructureType; import me.glicz.skanalyzer.structure.data.StructureData; import org.bukkit.command.MessageCommandSender; @@ -45,7 +46,7 @@ public void finish(Map>> structur }); }); - System.out.println(jsonObject); + SkAnalyzer.get().getLogger().info(jsonObject); } private JsonObject getKeyObject(JsonObject jsonObject, String key) { diff --git a/MockSkriptBridge/src/main/java/me/glicz/skanalyzer/bridge/MockSkriptBridgeImpl.java b/MockSkriptBridge/src/main/java/me/glicz/skanalyzer/bridge/MockSkriptBridgeImpl.java index 5b6dd20..028c5ea 100644 --- a/MockSkriptBridge/src/main/java/me/glicz/skanalyzer/bridge/MockSkriptBridgeImpl.java +++ b/MockSkriptBridge/src/main/java/me/glicz/skanalyzer/bridge/MockSkriptBridgeImpl.java @@ -11,8 +11,10 @@ import ch.njol.skript.log.RedirectingLogHandler; import ch.njol.skript.structures.StructCommand; import ch.njol.skript.structures.StructFunction; +import me.glicz.skanalyzer.SkAnalyzer; import me.glicz.skanalyzer.structure.StructureType; import me.glicz.skanalyzer.structure.data.EventData; +import me.glicz.skanalyzer.structure.data.FunctionData; import me.glicz.skanalyzer.structure.data.StructureData; import org.bukkit.Bukkit; import org.skriptlang.skript.lang.script.Script; @@ -79,20 +81,18 @@ public void parseArgs(List args) { Skript.getAddonInstance().loadClasses(basePackage + ".economy"); Skript.getAddonInstance().loadClasses(basePackage + ".chat"); Skript.getAddonInstance().loadClasses(basePackage + ".permission"); - System.out.println("Force loaded Vault hook."); + SkAnalyzer.get().getLogger().info("Force loaded Vault hook"); } catch (IOException e) { - System.out.println("Something went wrong while trying to force load Vault hook"); - e.printStackTrace(System.out); + SkAnalyzer.get().getLogger().error("Something went wrong while trying to force load Vault hook", e); } } if (args.contains("--forceRegionsHook")) { try { String basePackage = RegionsPlugin.class.getPackage().getName(); Skript.getAddonInstance().loadClasses(basePackage); - System.out.println("Force loaded Regions hook."); + SkAnalyzer.get().getLogger().info("Force loaded regions hook"); } catch (IOException e) { - System.out.println("Something went wrong while trying to force load Regions hook"); - e.printStackTrace(System.out); + SkAnalyzer.get().getLogger().error("Something went wrong while trying to force load regions hook", e); } } } @@ -100,11 +100,17 @@ public void parseArgs(List args) { @Override public void parseScript(String path) { File file = new File(path); - if (!file.exists()) + if (!file.exists() || !file.getName().endsWith(".sk")) { + SkAnalyzer.get().getLogger().error("Invalid file path"); return; + } AnalyzerCommandSender sender = new AnalyzerCommandSender(); RedirectingLogHandler logHandler = new RedirectingLogHandler(sender, null).start(); - ScriptLoader.loadScripts(file, logHandler, false).thenRun(() -> { + ScriptLoader.loadScripts(file, logHandler, false).whenComplete((info, throwable) -> { + if (throwable != null) { + SkAnalyzer.get().getLogger().error("Something went wrong while trying to parse '%s'".formatted(path), throwable); + return; + } Map> structures = new HashMap<>(); Script script = ScriptLoader.getScript(file); if (script != null) { @@ -131,9 +137,10 @@ public void parseScript(String path) { Signature signature = getFunctionSignature(function); if (signature == null) return; structures.putIfAbsent(StructureType.FUNCTION, new ArrayList<>()); - structures.get(StructureType.FUNCTION).add(new StructureData( + structures.get(StructureType.FUNCTION).add(new FunctionData( function.getEntryContainer().getSource().getLine(), - signature.getName() + signature.getName(), + signature.isLocal() )); } }); diff --git a/build.gradle.kts b/build.gradle.kts index 4934ab0..227293a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,14 +10,13 @@ repositories { } dependencies { - compileOnly(project(":MockSkript")) { - exclude("*", "*") - } - api("com.github.seeseemelk:MockBukkit-v1.20:3.9.0") + compileOnly("org.projectlombok:lombok:1.18.30") + annotationProcessor("org.projectlombok:lombok:1.18.30") + api("com.github.seeseemelk:MockBukkit-v1.20:3.44.0") implementation("org.apache.logging.log4j:log4j-core:3.0.0-alpha1") + implementation("org.slf4j:slf4j-simple:2.0.9") implementation("commons-io:commons-io:2.14.0") implementation("commons-lang:commons-lang:2.6") - implementation("org.slf4j:slf4j-simple:2.0.9") } java { @@ -35,9 +34,8 @@ tasks { manifest.attributes["Main-Class"] = "me.glicz.skanalyzer.SkAnalyzer" manifest.attributes["Specification-Version"] = version - dependsOn(project(":MockSkriptBridge").tasks.jar) - subprojects.forEach { subproject -> + dependsOn(subproject.tasks.jar) from(subproject.tasks.jar.get().outputs.files.singleFile) { include("*.jar") rename { "${subproject.name}.jar.embedded" } diff --git a/gradle.properties b/gradle.properties index 826e458..e9e057e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ -version=1.0 +version=1.1 group=me.glicz org.gradle.caching=true \ No newline at end of file diff --git a/src/main/java/me/glicz/skanalyzer/SkAnalyzer.java b/src/main/java/me/glicz/skanalyzer/SkAnalyzer.java index a39af86..e9c492a 100644 --- a/src/main/java/me/glicz/skanalyzer/SkAnalyzer.java +++ b/src/main/java/me/glicz/skanalyzer/SkAnalyzer.java @@ -2,9 +2,12 @@ import be.seeseemelk.mockbukkit.MockBukkit; import com.google.common.base.Preconditions; +import lombok.Getter; import me.glicz.skanalyzer.loader.AddonsLoader; import me.glicz.skanalyzer.mockbukkit.AnalyzerServer; import org.apache.commons.io.FileUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.io.File; import java.io.IOException; @@ -12,24 +15,28 @@ import java.util.List; import java.util.Scanner; +@Getter public class SkAnalyzer { private static SkAnalyzer instance; private final AnalyzerServer server; + private final Logger logger; private SkAnalyzer(List args) { Preconditions.checkArgument(instance == null, "SkAnalyzer instance is already set!"); instance = this; + logger = LogManager.getLogger(args.contains("--enablePlainLogger") ? "PlainLogger" : "SkAnalyzer"); + System.out.printf("SkAnalyzer v%s - simple Skript parser. Created by Glicz.%n", getClass().getPackage().getSpecificationVersion()); extractEmbeddedAddons(); - System.out.println("Enabling..."); + logger.info("Enabling..."); server = MockBukkit.mock(new AnalyzerServer()); AddonsLoader.loadAddons(); AddonsLoader.getMockSkriptBridge().parseArgs(args); server.startTicking(); - System.out.println("Successfully enabled. Have fun!"); + logger.info("Successfully enabled. Have fun!"); startReadingInput(); } @@ -42,10 +49,6 @@ public static SkAnalyzer get() { return instance; } - public AnalyzerServer getServer() { - return server; - } - private void startReadingInput() { Thread thread = new Thread() { private final Scanner scanner = new Scanner(System.in); @@ -66,22 +69,20 @@ public void run() { } private void extractEmbeddedAddons() { - System.out.println("Extracting embedded addons..."); + logger.info("Extracting embedded addons..."); - try (InputStream embeddedJar = getClass().getClassLoader().getResourceAsStream("MockSkript.jar.embedded")) { - Preconditions.checkArgument(embeddedJar != null, "Couldn't find embedded MockSkript.jar"); - FileUtils.copyInputStreamToFile(embeddedJar, new File(AddonsLoader.ADDONS, "MockSkript.jar")); - } catch (IOException e) { - throw new RuntimeException(e); - } + extractEmbeddedAddon(AddonsLoader.MOCK_SKRIPT); + extractEmbeddedAddon(AddonsLoader.MOCK_SKRIPT_BRIDGE); + + logger.info("Successfully extracted embedded addons!"); + } - try (InputStream embeddedJar = getClass().getClassLoader().getResourceAsStream("MockSkriptBridge.jar.embedded")) { - Preconditions.checkArgument(embeddedJar != null, "Couldn't find embedded MockSkriptBridge.jar"); - FileUtils.copyInputStreamToFile(embeddedJar, new File(AddonsLoader.ADDONS, "MockSkriptBridge.jar")); + private void extractEmbeddedAddon(String name) { + try (InputStream embeddedJar = getClass().getClassLoader().getResourceAsStream(name + ".embedded")) { + Preconditions.checkArgument(embeddedJar != null, "Couldn't find embedded %s", name); + FileUtils.copyInputStreamToFile(embeddedJar, new File(AddonsLoader.ADDONS, name)); } catch (IOException e) { throw new RuntimeException(e); } - - System.out.println("Successfully extracted embedded addons!"); } } diff --git a/src/main/java/me/glicz/skanalyzer/loader/AddonsLoader.java b/src/main/java/me/glicz/skanalyzer/loader/AddonsLoader.java index 8f36e8e..541e672 100644 --- a/src/main/java/me/glicz/skanalyzer/loader/AddonsLoader.java +++ b/src/main/java/me/glicz/skanalyzer/loader/AddonsLoader.java @@ -1,33 +1,53 @@ package me.glicz.skanalyzer.loader; import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader; +import lombok.Getter; import me.glicz.skanalyzer.SkAnalyzer; import me.glicz.skanalyzer.bridge.MockSkriptBridge; import me.glicz.skanalyzer.mockbukkit.AnalyzerClassLoader; +import org.apache.commons.io.FileUtils; +import org.bukkit.Bukkit; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.java.JavaPlugin; import java.io.File; +import java.util.Arrays; import java.util.jar.JarFile; +import java.util.stream.Collectors; public class AddonsLoader { public static final File USER_HOME = new File(System.getProperty("user.home")); public static final File ADDONS = new File(USER_HOME, "SkAnalyzer/addons"); + public static final String MOCK_SKRIPT = "MockSkript.jar"; + public static final String MOCK_SKRIPT_BRIDGE = "MockSkriptBridge.jar"; private static JavaPlugin skript; + @Getter private static MockSkriptBridge mockSkriptBridge; + @SuppressWarnings("UnstableApiUsage") public static void loadAddons() { if (skript != null) throw new RuntimeException("Addons are already loaded!"); - skript = loadAddon(new File(ADDONS, "MockSkript.jar")); // currently only Skript support :( - mockSkriptBridge = (MockSkriptBridge) loadAddon(new File(ADDONS, "MockSkriptBridge.jar")); + skript = loadAddon(new File(ADDONS, MOCK_SKRIPT)); + mockSkriptBridge = (MockSkriptBridge) loadAddon(new File(ADDONS, MOCK_SKRIPT_BRIDGE)); + FileUtils.listFiles(ADDONS, new String[]{"jar"}, false).forEach(AddonsLoader::loadAddon); + SkAnalyzer.get().getLogger().info( + "Successfully loaded addons: {}", + Arrays.stream(Bukkit.getPluginManager().getPlugins()) + .map(plugin -> plugin.getPluginMeta().getName()) + .collect(Collectors.joining(", ")) + ); } @SuppressWarnings("UnstableApiUsage") private static JavaPlugin loadAddon(File file) { + if (skript != null && file.getName().equals(MOCK_SKRIPT)) return null; + if (mockSkriptBridge != null && file.getName().equals(MOCK_SKRIPT_BRIDGE)) return null; try { JarFile jarFile = new JarFile(file); PluginDescriptionFile description = new PluginDescriptionFile(jarFile.getInputStream(jarFile.getEntry("plugin.yml"))); + if (Bukkit.getServer().getPluginManager().isPluginEnabled(description.getName())) + throw new RuntimeException("Plugin named '%s' is already loaded".formatted(description.getName())); AnalyzerClassLoader classLoader = new AnalyzerClassLoader( SkAnalyzer.class.getClassLoader(), description, @@ -43,12 +63,8 @@ private static JavaPlugin loadAddon(File file) { SkAnalyzer.get().getServer().getPluginManager().enablePlugin(plugin); return plugin; } catch (Exception e) { - e.printStackTrace(System.out); + SkAnalyzer.get().getLogger().error("Something went wrong while trying to load %s".formatted(file.getPath()), e); } return null; } - - public static MockSkriptBridge getMockSkriptBridge() { - return mockSkriptBridge; - } } diff --git a/src/main/java/me/glicz/skanalyzer/mockbukkit/AnalyzerClassLoader.java b/src/main/java/me/glicz/skanalyzer/mockbukkit/AnalyzerClassLoader.java index 907d4ce..7bbe672 100644 --- a/src/main/java/me/glicz/skanalyzer/mockbukkit/AnalyzerClassLoader.java +++ b/src/main/java/me/glicz/skanalyzer/mockbukkit/AnalyzerClassLoader.java @@ -6,6 +6,7 @@ import io.papermc.paper.plugin.configuration.PluginMeta; import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader; import io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup; +import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.java.JavaPlugin; @@ -31,9 +32,11 @@ public class AnalyzerClassLoader extends URLClassLoader implements ConfiguredPlu ClassLoader.registerAsParallelCapable(); } - private final PluginClassLoaderGroup classLoaderGroup = new MockBukkitPluginClassLoaderGroup(); + @Getter(onMethod_ = {@NotNull}) + private final PluginClassLoaderGroup group = new MockBukkitPluginClassLoaderGroup(); private final Map> classes = new ConcurrentHashMap<>(); - private final PluginDescriptionFile description; + @Getter + private final PluginDescriptionFile configuration; private final File dataFolder, file; private final URL url; private final JarFile jarFile; @@ -41,7 +44,7 @@ public class AnalyzerClassLoader extends URLClassLoader implements ConfiguredPlu public AnalyzerClassLoader(ClassLoader parent, PluginDescriptionFile description, File dataFolder, File file, JarFile jarFile) throws Exception { super(file.getName(), new URL[]{file.toURI().toURL()}, parent); - this.description = description; + this.configuration = description; this.dataFolder = dataFolder; this.file = file; this.url = file.toURI().toURL(); @@ -49,11 +52,6 @@ public AnalyzerClassLoader(ClassLoader parent, PluginDescriptionFile description this.manifest = jarFile.getManifest(); } - @Override - public PluginMeta getConfiguration() { - return description; - } - @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { return loadClass0(name, resolve, true); @@ -73,7 +71,7 @@ private Class loadClass0(String name, boolean resolve, boolean checkGlobal) t } if (checkGlobal) { - Class result = this.classLoaderGroup.getClassByName(name, resolve, this); + Class result = group.getClassByName(name, resolve, this); if (result != null) return result; } @@ -136,7 +134,15 @@ else definePackage( @Override public void init(JavaPlugin plugin) { - plugin.init(Bukkit.getServer(), description, dataFolder, file, this, description, PaperPluginLogger.getLogger(getConfiguration())); + plugin.init( + Bukkit.getServer(), + configuration, + dataFolder, + file, + this, + configuration, + PaperPluginLogger.getLogger((PluginMeta) getConfiguration()) + ); } @Override @@ -144,11 +150,6 @@ public void init(JavaPlugin plugin) { return null; } - @Override - public @NotNull PluginClassLoaderGroup getGroup() { - return classLoaderGroup; - } - @Override public void close() throws IOException { try { diff --git a/src/main/java/me/glicz/skanalyzer/mockbukkit/AnalyzerServer.java b/src/main/java/me/glicz/skanalyzer/mockbukkit/AnalyzerServer.java index 7f611fc..d621605 100644 --- a/src/main/java/me/glicz/skanalyzer/mockbukkit/AnalyzerServer.java +++ b/src/main/java/me/glicz/skanalyzer/mockbukkit/AnalyzerServer.java @@ -2,6 +2,7 @@ import be.seeseemelk.mockbukkit.ServerMock; import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock; +import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.data.BlockData; @@ -10,8 +11,10 @@ import java.util.Timer; import java.util.TimerTask; +@Getter public class AnalyzerServer extends ServerMock { private final AnalyzerUnsafeValues unsafe = new AnalyzerUnsafeValues(); + private final AnalyzerStructureManager structureManager = new AnalyzerStructureManager(); public void startTicking() { new Timer().scheduleAtFixedRate(new TimerTask() { @@ -27,12 +30,6 @@ public void run() { return "SkAnalyzer"; } - @SuppressWarnings("deprecation") - @Override - public @NotNull AnalyzerUnsafeValues getUnsafe() { - return unsafe; - } - @SuppressWarnings("DataFlowIssue") @Override public @NotNull BlockData createBlockData(String data) { diff --git a/src/main/java/me/glicz/skanalyzer/mockbukkit/AnalyzerStructureManager.java b/src/main/java/me/glicz/skanalyzer/mockbukkit/AnalyzerStructureManager.java new file mode 100644 index 0000000..e7d4702 --- /dev/null +++ b/src/main/java/me/glicz/skanalyzer/mockbukkit/AnalyzerStructureManager.java @@ -0,0 +1,100 @@ +package me.glicz.skanalyzer.mockbukkit; + +import org.bukkit.NamespacedKey; +import org.bukkit.structure.Structure; +import org.bukkit.structure.StructureManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; + +public class AnalyzerStructureManager implements StructureManager { + @Override + public @NotNull Map getStructures() { + return Map.of(); + } + + @Override + public @Nullable Structure getStructure(@NotNull NamespacedKey structureKey) { + return null; + } + + @Override + public @Nullable Structure registerStructure(@NotNull NamespacedKey structureKey, @NotNull Structure structure) { + return null; + } + + @Override + public @Nullable Structure unregisterStructure(@NotNull NamespacedKey structureKey) { + return null; + } + + @Override + public @Nullable Structure loadStructure(@NotNull NamespacedKey structureKey, boolean register) { + return null; + } + + @Override + public @Nullable Structure loadStructure(@NotNull NamespacedKey structureKey) { + return null; + } + + @Override + public void saveStructure(@NotNull NamespacedKey structureKey) { + + } + + @Override + public void saveStructure(@NotNull NamespacedKey structureKey, @NotNull Structure structure) throws IOException { + + } + + @Override + public void deleteStructure(@NotNull NamespacedKey structureKey) throws IOException { + + } + + @Override + public void deleteStructure(@NotNull NamespacedKey structureKey, boolean unregister) throws IOException { + + } + + @Override + public @NotNull File getStructureFile(@NotNull NamespacedKey structureKey) { + return null; + } + + @Override + public @NotNull Structure loadStructure(@NotNull File file) throws IOException { + return null; + } + + @Override + public @NotNull Structure loadStructure(@NotNull InputStream inputStream) throws IOException { + return null; + } + + @Override + public void saveStructure(@NotNull File file, @NotNull Structure structure) throws IOException { + + } + + @Override + public void saveStructure(@NotNull OutputStream outputStream, @NotNull Structure structure) throws IOException { + + } + + @Override + public @NotNull Structure createStructure() { + return null; + } + + @Override + public @NotNull Structure copy(@NotNull Structure structure) { + return null; + } +} diff --git a/src/main/java/me/glicz/skanalyzer/structure/data/FunctionData.java b/src/main/java/me/glicz/skanalyzer/structure/data/FunctionData.java new file mode 100644 index 0000000..1a20d8a --- /dev/null +++ b/src/main/java/me/glicz/skanalyzer/structure/data/FunctionData.java @@ -0,0 +1,10 @@ +package me.glicz.skanalyzer.structure.data; + +public class FunctionData extends StructureData { + private final boolean local; + + public FunctionData(int line, String value, boolean local) { + super(line, value); + this.local = local; + } +} diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties new file mode 100644 index 0000000..0694b21 --- /dev/null +++ b/src/main/resources/log4j2.component.properties @@ -0,0 +1 @@ +log4j.skipJansi=true diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100644 index 0000000..ebff49c --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file