diff --git a/README.md b/README.md
index f677638..aaefb9b 100644
--- a/README.md
+++ b/README.md
@@ -3,10 +3,11 @@
Modern solution for minecraft resource pack development
## Features
-- [Resource pack obfuscation](#obfuscation)
-- [Auto CustomModelData Mapping](#autocmd)
-- [Auto fancyPants custom armor](#customarmor)
-- And much more...
+- [Models generating](#meshes--models)
+- [Auto CustomModelData](#auto-custommodeldata)
+- [Auto sounds FFmpeg conversion](#sounds)
+- [Auto fancyPants (custom armor)](#armor-textures)
+- [Obfuscation](#obfuscation)
## Example Project
Look at the [example project](https://github.com/Nelonn/ProPack/blob/master/propack-core/src/main/resources/example)
@@ -20,10 +21,11 @@ Json is used in lenient mode, possible file extensions:
Some futures from json 5 will not work due to [GSON](https://github.com/google/gson) flaws
## Meshes & Models
-[Java Block/Item models](https://minecraft.fandom.com/wiki/Model) in the ProPack are called meshes.
-Their files should end with `.mesh.json`
+[Java Block/Item models](https://minecraft.fandom.com/wiki/Model) in the ProPack are called *meshes*.
+Their files should end with `.mesh.json`.
+
+Models configuration file name should end with `.model.json`.
-Models file name should end with `.model.json`.
Currently implemented model types:
@@ -85,9 +87,9 @@ SlotItemModel, example:
}
```
-`Target` - this is an indication of the items for which you need to `Auto CustomModelData Mapping` of the specified model
+`Target` - this is an indication of the items for which you need to [Auto CustomModelData](#auto-custommodeldata) of the specified model.
-## Auto CustomModelData Mapping
+## Auto CustomModelData
When building resource pack ProPack takes the default model from the folder `include/assets/minecraft/models/item/- .json`
and adds the necessary elements to override.
@@ -106,18 +108,17 @@ Example NBT tag for SlotItemModel: `{CustomModel:"example:models/example_slotmod
## Sounds
-Sound files must ends with `.sound.json`
-- Example: `scream.sound.json`
+Sound files must ends with `.sound.json`, eg. `scream.sound.json`
Sound file paths can be relative, example `../folder/sound`.
FFmpeg auto conversion is supported. Use `-Dpropack.ffmpeg=path` to indicate its location,
by default it `ffmpeg`
-## Armor Textures
+## Armor Textures
Added an automatic builder of custom textures for leather armor for the [shader `fancyPants`](https://github.com/Ancientkingg/fancyPants)
-Armor file must ends with `.armor.json`
+Armor file must ends with `.armor.json`, eg. `emerald.armor.json`
[Example file]():
```json
@@ -146,32 +147,36 @@ The second animated version:
}
}
```
-`.png` is not required to be specified
+`.png` is not required to be specified.
+
For more information, see [README.md of fancyPants](https://github.com/Ancientkingg/fancyPants/blob/master/README.md)
`SaveImage` allows you to determine whether to save
the specified `Image` in the output resource pack
## Languages
-Language file must ends with `.lang.json`
-- Example: `en_us.lang.json`
+Language file must ends with `.lang.json`, eg. `en_us.lang.json`.
+
+Path in content doesn't matter.
-There is also a placeholder ``.
Multiple languages in the same namespace will be merged into one.
+There is also a placeholder ``.
+
## Fonts
Fonts work unchanged except for the file extension `.font.json`
-## Obfuscation
+## Obfuscation
It just obfuscates the entire resource pack, except for translations.
The settings for this function are in [`config/build.json5`](https://github.com/Nelonn/ProPack/blob/master/propack-core/src/main/resources/example/config/build.json5)
## Planned in the future
+- [ ] Rewrite builder to C++ or Golang as binary executable.
- [ ] Integration into [ItemsAdder](https://www.spigotmc.org/resources/%E2%9C%A8itemsadder%E2%AD%90emotes-mobs-items-armors-hud-gui-emojis-blocks-wings-hats-liquids.73355/), [Oraxen](https://www.spigotmc.org/resources/%E2%98%84%EF%B8%8F-oraxen-add-items-blocks-armors-hats-food-furnitures-plants-and-gui.72448/), [Model Engine](https://www.spigotmc.org/resources/conxeptworks-model-engine—ultimate-custom-entity-model-manager-1-16-5-1-19-3.79477/), etc.
-- [ ] Fonts generating
-- [ ] CI/CD using [Redis](https://redis.io/), etc.
-- [ ] Improve the quality of the code and API
-- [ ] Mod for [Fabric](https://fabricmc.net/)
+- [ ] Fonts generating.
+- [ ] Resource pack CI/CD using [Redis](https://redis.io/), etc. (for multi server)
+- [ ] Improve the quality of the code and API.
+- [ ] Mod for [Fabric](https://fabricmc.net/).
## License
*Click here to read [the entire license](https://github.com/Nelonn/ProPack/blob/master/LICENSE.txt).*
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 2e296a0..fb663fe 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,5 +1,5 @@
group=me.nelonn.propack
-version=0.0.7
+version=0.0.8
org.gradle.jvmargs=-Xmx2G
org.gradle.parallel=true
diff --git a/libs/flint-path-0.0.1.jar b/libs/lib-flint-path-0.0.1.jar
similarity index 76%
rename from libs/flint-path-0.0.1.jar
rename to libs/lib-flint-path-0.0.1.jar
index f43f0c9..5ebb571 100644
Binary files a/libs/flint-path-0.0.1.jar and b/libs/lib-flint-path-0.0.1.jar differ
diff --git a/propack-api/build.gradle.kts b/propack-api/build.gradle.kts
index d61b2e3..6db0184 100644
--- a/propack-api/build.gradle.kts
+++ b/propack-api/build.gradle.kts
@@ -12,7 +12,7 @@ repositories {
}
dependencies {
- "compileOnly"(files("../libs/flint-path-0.0.1.jar"))
+ "compileOnly"(files("../libs/lib-flint-path-0.0.1.jar"))
"compileOnly"("net.kyori:adventure-api:4.12.0")
"compileOnly"("org.jetbrains:annotations:23.1.0")
}
diff --git a/propack-bukkit/adapters/adapter-1.17.1/build.gradle.kts b/propack-bukkit/adapters/adapter-1.17.1/build.gradle.kts
index de034a0..f8731e3 100644
--- a/propack-bukkit/adapters/adapter-1.17.1/build.gradle.kts
+++ b/propack-bukkit/adapters/adapter-1.17.1/build.gradle.kts
@@ -11,7 +11,7 @@ java.toolchain.languageVersion.set(JavaLanguageVersion.of(17))
dependencies {
// https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/
paperDevBundle("1.17.1-R0.1-20220414.034903-210")
- "compileOnly"(files("../../../libs/flint-path-0.0.1.jar"))
+ "compileOnly"(files("../../../libs/lib-flint-path-0.0.1.jar"))
"compileOnly"(project(":propack-api"))
"compileOnly"(project(":propack-core"))
"compileOnly"(project(":propack-bukkit"))
diff --git a/propack-bukkit/adapters/adapter-1.18.2/build.gradle.kts b/propack-bukkit/adapters/adapter-1.18.2/build.gradle.kts
index 1147ff6..a920785 100644
--- a/propack-bukkit/adapters/adapter-1.18.2/build.gradle.kts
+++ b/propack-bukkit/adapters/adapter-1.18.2/build.gradle.kts
@@ -11,7 +11,7 @@ java.toolchain.languageVersion.set(JavaLanguageVersion.of(17))
dependencies {
// https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/
paperDevBundle("1.18.2-R0.1-20220304.102823-4")
- "compileOnly"(files("../../../libs/flint-path-0.0.1.jar"))
+ "compileOnly"(files("../../../libs/lib-flint-path-0.0.1.jar"))
"compileOnly"(project(":propack-api"))
"compileOnly"(project(":propack-core"))
"compileOnly"(project(":propack-bukkit"))
diff --git a/propack-bukkit/adapters/adapter-1.19.3/build.gradle.kts b/propack-bukkit/adapters/adapter-1.19.3/build.gradle.kts
index 2278b22..c65b1e0 100644
--- a/propack-bukkit/adapters/adapter-1.19.3/build.gradle.kts
+++ b/propack-bukkit/adapters/adapter-1.19.3/build.gradle.kts
@@ -11,7 +11,7 @@ java.toolchain.languageVersion.set(JavaLanguageVersion.of(17))
dependencies {
// https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/
paperDevBundle("1.19.3-R0.1-20221226.180038-55")
- "compileOnly"(files("../../../libs/flint-path-0.0.1.jar"))
+ "compileOnly"(files("../../../libs/lib-flint-path-0.0.1.jar"))
"compileOnly"(project(":propack-api"))
"compileOnly"(project(":propack-core"))
"compileOnly"(project(":propack-bukkit"))
diff --git a/propack-bukkit/adapters/adapter-1.19.4/build.gradle.kts b/propack-bukkit/adapters/adapter-1.19.4/build.gradle.kts
index 0409584..3bfea74 100644
--- a/propack-bukkit/adapters/adapter-1.19.4/build.gradle.kts
+++ b/propack-bukkit/adapters/adapter-1.19.4/build.gradle.kts
@@ -11,7 +11,7 @@ java.toolchain.languageVersion.set(JavaLanguageVersion.of(17))
dependencies {
// https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/
paperDevBundle("1.19.4-R0.1-20230315.180636-1")
- "compileOnly"(files("../../../libs/flint-path-0.0.1.jar"))
+ "compileOnly"(files("../../../libs/lib-flint-path-0.0.1.jar"))
"compileOnly"(project(":propack-api"))
"compileOnly"(project(":propack-core"))
"compileOnly"(project(":propack-bukkit"))
diff --git a/propack-bukkit/adapters/adapter-1.19/build.gradle.kts b/propack-bukkit/adapters/adapter-1.19/build.gradle.kts
index 30ee9db..f4ab445 100644
--- a/propack-bukkit/adapters/adapter-1.19/build.gradle.kts
+++ b/propack-bukkit/adapters/adapter-1.19/build.gradle.kts
@@ -11,7 +11,7 @@ java.toolchain.languageVersion.set(JavaLanguageVersion.of(17))
dependencies {
// https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/
paperDevBundle("1.19-R0.1-20220609.175204-1")
- "compileOnly"(files("../../../libs/flint-path-0.0.1.jar"))
+ "compileOnly"(files("../../../libs/lib-flint-path-0.0.1.jar"))
"compileOnly"(project(":propack-api"))
"compileOnly"(project(":propack-core"))
"compileOnly"(project(":propack-bukkit"))
diff --git a/propack-bukkit/build.gradle.kts b/propack-bukkit/build.gradle.kts
index 4ddc3ce..17f4eca 100644
--- a/propack-bukkit/build.gradle.kts
+++ b/propack-bukkit/build.gradle.kts
@@ -37,7 +37,7 @@ dependencies {
"implementation"(project(":propack-core")) {
exclude(group = "net.kyori")
}
- "compileOnly"(files("../libs/flint-path-0.0.1.jar"))
+ "compileOnly"(files("../libs/lib-flint-path-0.0.1.jar"))
/*"compileOnly"("org.spigotmc:spigot-api:1.17-R0.1-SNAPSHOT") {
exclude("junit", "junit")
diff --git a/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/ProPackPlugin.java b/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/ProPackPlugin.java
index 0628267..bb723cf 100644
--- a/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/ProPackPlugin.java
+++ b/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/ProPackPlugin.java
@@ -35,7 +35,7 @@
public final class ProPackPlugin extends JavaPlugin {
private static final Logger LOGGER = LogManagerCompat.getLogger();
- private static final SharedLoader.Library library = new SharedLoader.Library("flint-path-0.0.1.jar", "me.nelonn.flint.path.Path");
+ private static final SharedLoader.Library library = new SharedLoader.Library("lib-flint-path-0.0.1.jar", "me.nelonn.flint.path.Path");
public static ProPackPlugin getInstance() {
return (ProPackPlugin) Bukkit.getPluginManager().getPlugin("ProPack");
diff --git a/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/SharedLoader.java b/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/SharedLoader.java
index 52f7f9b..7999b36 100644
--- a/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/SharedLoader.java
+++ b/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/SharedLoader.java
@@ -25,8 +25,6 @@
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
-import java.net.URL;
-import java.net.URLClassLoader;
import java.nio.file.Files;
public final class SharedLoader {
@@ -56,8 +54,8 @@ public void loadIfNotExists(@NotNull Library library) {
in.transferTo(out);
}
}
- URLClassLoader loader = new URLClassLoader(new URL[]{file.toURI().toURL()}, Bukkit.class.getClassLoader());
- Class.forName(library.getCheckClass(), true, loader);
+ Bukkit.getPluginManager().loadPlugin(file);
+ Class.forName(library.getCheckClass());
} catch (Exception e) {
throw new RuntimeException("Unable to load shared library '" + library.getFileName() + "'", e);
}
diff --git a/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/command/BuildCommand.java b/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/command/BuildCommand.java
index 8085b76..85569d6 100644
--- a/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/command/BuildCommand.java
+++ b/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/command/BuildCommand.java
@@ -24,7 +24,6 @@
import me.nelonn.propack.bukkit.Util;
import me.nelonn.propack.bukkit.definition.PackDefinition;
import me.nelonn.propack.bukkit.definition.ProjectDefinition;
-import me.nelonn.propack.core.builder.InternalProject;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -56,9 +55,8 @@ protected void onCommand(@NotNull CommandSender sender, @NotNull String s, @NotN
}
new Thread(() -> {
try {
- InternalProject internalProject = (InternalProject) projectDefinition.getProject();
- internalProject.build();
- ResourcePack resourcePack = internalProject.getResourcePack().orElseThrow();
+ projectDefinition.build();
+ ResourcePack resourcePack = projectDefinition.getResourcePack().orElseThrow();
if (resourcePack.isUploaded()) {
for (Player player : Bukkit.getOnlinePlayers()) {
Optional playerPack = ProPack.getCore().getDispatcher().getAppliedResourcePack(player);
diff --git a/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/command/HelpCommand.java b/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/command/HelpCommand.java
index e74b278..a432399 100644
--- a/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/command/HelpCommand.java
+++ b/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/command/HelpCommand.java
@@ -35,5 +35,6 @@ public HelpCommand(@NotNull ProPackPlugin plugin) {
protected void onCommand(@NotNull CommandSender sender, @NotNull String command, @NotNull String[] args) {
Util.send(sender, "" + plugin.getDescription().getName() + " v" + plugin.getDescription().getVersion());
Util.send(sender, "/propack build ");
+ Util.send(sender, "/propack reload [config|modules|packs]");
}
}
diff --git a/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/definition/PackManager.java b/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/definition/PackManager.java
index 4b77cf2..a4c84c2 100644
--- a/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/definition/PackManager.java
+++ b/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/definition/PackManager.java
@@ -20,7 +20,6 @@
import com.google.gson.JsonObject;
import me.nelonn.propack.core.ProPackCore;
-import me.nelonn.propack.core.builder.InternalProject;
import me.nelonn.propack.core.loader.ProjectLoader;
import me.nelonn.propack.core.util.GsonHelper;
import me.nelonn.propack.core.util.LogManagerCompat;
@@ -65,12 +64,8 @@ public void loadAll() {
if (type.equalsIgnoreCase("Project")) {
boolean buildAtStartup = GsonHelper.getBoolean(jsonObject, "BuildAtStartup", false);
File projectFile = new File(directory, name + File.separatorChar + "project.json5");
- InternalProject internalProject = projectLoader.load(projectFile, !buildAtStartup);
- if (buildAtStartup || internalProject.getResourcePack().isEmpty()) {
- internalProject.build(); // TODO: improve
- }
- ProjectDefinition resourcePackDefinition = new ProjectDefinition(internalProject);
- definitions.put(name, resourcePackDefinition);
+ ProjectDefinition projectDefinition = new ProjectDefinition(projectFile, projectLoader, !buildAtStartup);
+ definitions.put(name, projectDefinition);
} else if (type.equalsIgnoreCase("File")) {
throw new UnsupportedOperationException("Resource pack definition type 'File' currently not supported");
}
diff --git a/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/definition/ProjectDefinition.java b/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/definition/ProjectDefinition.java
index e71b67d..43f15ae 100644
--- a/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/definition/ProjectDefinition.java
+++ b/propack-bukkit/src/main/java/me/nelonn/propack/bukkit/definition/ProjectDefinition.java
@@ -19,16 +19,26 @@
package me.nelonn.propack.bukkit.definition;
import me.nelonn.propack.ResourcePack;
-import me.nelonn.propack.builder.Project;
+import me.nelonn.propack.core.builder.InternalProject;
+import me.nelonn.propack.core.loader.ProjectLoader;
import org.jetbrains.annotations.NotNull;
+import java.io.File;
import java.util.Optional;
public class ProjectDefinition implements PackDefinition {
- private final Project project;
+ private final File file;
+ private InternalProject project;
+ private ProjectLoader projectLoader;
- public ProjectDefinition(@NotNull Project project) {
- this.project = project;
+ public ProjectDefinition(@NotNull File file, @NotNull ProjectLoader projectLoader, boolean tryLoadBuilt) {
+ this.file = file;
+ this.projectLoader = projectLoader;
+ if (tryLoadBuilt) {
+ loadOrBuild();
+ } else {
+ build();
+ }
}
@Override
@@ -41,7 +51,35 @@ public ProjectDefinition(@NotNull Project project) {
return project.getResourcePack();
}
- public @NotNull Project getProject() {
+ public @NotNull File getFile() {
+ return file;
+ }
+
+ public @NotNull InternalProject getProject() {
return project;
}
+
+ public @NotNull ProjectLoader getProjectLoader() {
+ return projectLoader;
+ }
+
+ public void setProjectLoader(@NotNull ProjectLoader projectLoader) {
+ this.projectLoader = projectLoader;
+ }
+
+ public void loadOrBuild() {
+ project = projectLoader.load(file, true);
+ if (project.getResourcePack().isEmpty()) {
+ build0();
+ }
+ }
+
+ public void build() {
+ project = projectLoader.load(file, false);
+ build0();
+ }
+
+ private void build0() {
+ project.build(); // TODO: improve
+ }
}
diff --git a/propack-bukkit/src/main/resources/flint-path-0.0.1.jar.shared b/propack-bukkit/src/main/resources/lib-flint-path-0.0.1.jar.shared
similarity index 76%
rename from propack-bukkit/src/main/resources/flint-path-0.0.1.jar.shared
rename to propack-bukkit/src/main/resources/lib-flint-path-0.0.1.jar.shared
index f43f0c9..5ebb571 100644
Binary files a/propack-bukkit/src/main/resources/flint-path-0.0.1.jar.shared and b/propack-bukkit/src/main/resources/lib-flint-path-0.0.1.jar.shared differ
diff --git a/propack-cli/build.gradle.kts b/propack-cli/build.gradle.kts
index ab03829..19a3995 100644
--- a/propack-cli/build.gradle.kts
+++ b/propack-cli/build.gradle.kts
@@ -16,7 +16,7 @@ repositories {
dependencies {
"implementation"(project(":propack-api"))
"implementation"(project(":propack-core"))
- "implementation"(files("../libs/flint-path-0.0.1.jar"))
+ "implementation"(files("../libs/lib-flint-path-0.0.1.jar"))
"implementation"("org.eclipse.jgit:org.eclipse.jgit:6.4.0.202211300538-r")
diff --git a/propack-core/build.gradle.kts b/propack-core/build.gradle.kts
index 6e35b5e..4374f58 100644
--- a/propack-core/build.gradle.kts
+++ b/propack-core/build.gradle.kts
@@ -16,7 +16,7 @@ repositories {
dependencies {
"implementation"(project(":propack-api"))
- "compileOnly"(files("../libs/flint-path-0.0.1.jar"))
+ "compileOnly"(files("../libs/lib-flint-path-0.0.1.jar"))
"compileOnly"("org.eclipse.jgit:org.eclipse.jgit:6.4.0.202211300538-r")
diff --git a/propack-core/src/main/java/me/nelonn/propack/core/loader/ProjectLoader.java b/propack-core/src/main/java/me/nelonn/propack/core/loader/ProjectLoader.java
index 29b5620..4272b04 100644
--- a/propack-core/src/main/java/me/nelonn/propack/core/loader/ProjectLoader.java
+++ b/propack-core/src/main/java/me/nelonn/propack/core/loader/ProjectLoader.java
@@ -81,7 +81,7 @@ public List getTextLoaders() {
return textLoaders;
}
- public @NotNull InternalProject load(@NotNull File projectFile, boolean loadBuilt) {
+ public @NotNull InternalProject load(@NotNull File projectFile, boolean tryLoadBuilt) {
String name;
VirtualFile packMeta;
VirtualFile packIcon;
@@ -287,7 +287,7 @@ public List getTextLoaders() {
ResourcePack resourcePack = null;
File builtResourcePack = new File(projectFile.getParentFile(), "build/" + name + ".propack");
- if (builtResourcePack.exists() && loadBuilt) {
+ if (builtResourcePack.exists() && tryLoadBuilt) {
try {
ResourcePackLoader resourcePackLoader = new ResourcePackLoader();
resourcePack = resourcePackLoader.load(builtResourcePack);
diff --git a/propack-core/src/main/java/me/nelonn/propack/module/JavaModuleManager.java b/propack-core/src/main/java/me/nelonn/propack/module/JavaModuleManager.java
index 704b702..9497cf7 100644
--- a/propack-core/src/main/java/me/nelonn/propack/module/JavaModuleManager.java
+++ b/propack-core/src/main/java/me/nelonn/propack/module/JavaModuleManager.java
@@ -19,6 +19,7 @@
package me.nelonn.propack.module;
import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
import me.nelonn.propack.core.util.GsonHelper;
import me.nelonn.propack.core.util.LogManagerCompat;
import org.apache.commons.io.IOUtils;
@@ -27,6 +28,7 @@
import org.jetbrains.annotations.Nullable;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
@@ -37,6 +39,8 @@
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
public class JavaModuleManager implements ModuleManager {
private static final Logger LOGGER = LogManagerCompat.getLogger();
@@ -65,31 +69,72 @@ public void loadAll() throws IOException {
});
for (Path path : stream) {
try {
- URLClassLoader child = new URLClassLoader(new URL[]{path.toUri().toURL()}, getClass().getClassLoader());
- InputStream inputStream = child.getResourceAsStream("module.json");
- if (inputStream == null) continue;
- String moduleDescriptionString = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
- JsonObject jsonObject = GsonHelper.deserialize(moduleDescriptionString);
- JsonModuleDescription moduleMeta = JsonModuleDescription.deserialize(jsonObject);
- try {
- Class> bootstrapper = Class.forName(moduleMeta.getBootstrapper(), true, child);
- if (!ModuleBootstrap.class.isAssignableFrom(bootstrapper)) {
- throw new IllegalArgumentException("Bootstrapper class must implement '" + ModuleBootstrap.class.getName() + "'");
- }
- ModuleBootstrap moduleBootstrap = (ModuleBootstrap) bootstrapper.getDeclaredConstructor().newInstance();
- File dataDir = new File(path.getParent().toFile(), moduleMeta.getName());
- ModuleProviderContext context = new ModuleProviderContextImpl(moduleMeta, dataDir.toPath());
- moduleBootstrap.bootstrap(context);
- JavaModule module = moduleBootstrap.createModule(context);
- module.enable();
- modules.put(moduleMeta.getName(), module);
- } catch (Exception e) {
- LOGGER.error("Error occurred while enabling " + moduleMeta.getDisplayName() + " (Is it up to date?)", e);
- }
+ loadModule(path.toFile());
} catch (Exception e) {
LOGGER.error("Unable to load module '" + path.getFileName() + "'", e);
}
}
+ stream.close();
+ }
+
+ public @NotNull Module loadModule(@NotNull File file) {
+ JsonModuleDescription description;
+ try {
+ description = getModuleDescription(file);
+ } catch (InvalidDescriptionException e) {
+ throw new IllegalArgumentException("Invalid module", e);
+ }
+ File dataFolder = new File(modulesDir, description.getName());
+ try {
+ URLClassLoader child = new URLClassLoader(new URL[]{file.toURI().toURL()}, getClass().getClassLoader());
+ Class> bootstrapper = Class.forName(description.getBootstrapper(), true, child);
+ if (!ModuleBootstrap.class.isAssignableFrom(bootstrapper)) {
+ throw new IllegalArgumentException("Bootstrapper class must implement '" + ModuleBootstrap.class.getName() + "'");
+ }
+ ModuleBootstrap moduleBootstrap = (ModuleBootstrap) bootstrapper.getDeclaredConstructor().newInstance();
+ ModuleProviderContext context = new ModuleProviderContextImpl(description, dataFolder.toPath());
+ moduleBootstrap.bootstrap(context);
+ JavaModule module = moduleBootstrap.createModule(context);
+ module.enable();
+ modules.put(description.getName(), module);
+ return module;
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Invalid module", e);
+ }
+ }
+
+ public @NotNull JsonModuleDescription getModuleDescription(@NotNull File file) throws InvalidDescriptionException {
+ JarFile jar = null;
+ InputStream stream = null;
+ try {
+ jar = new JarFile(file);
+ JarEntry entry = jar.getJarEntry("module.json");
+
+ if (entry == null) {
+ throw new InvalidDescriptionException(new FileNotFoundException("Jar does not contain module.json"));
+ }
+
+ stream = jar.getInputStream(entry);
+
+ String moduleDescriptionString = IOUtils.toString(stream, StandardCharsets.UTF_8);
+ JsonObject jsonObject = GsonHelper.deserialize(moduleDescriptionString);
+ return JsonModuleDescription.deserialize(jsonObject);
+ } catch (IOException | JsonParseException ex) {
+ throw new InvalidDescriptionException(ex);
+ } finally {
+ if (jar != null) {
+ try {
+ jar.close();
+ } catch (IOException ignored) {
+ }
+ }
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
}
@Override