diff --git a/OrionAPI/build.gradle b/OrionAPI/build.gradle index 817678f..3fa840b 100644 --- a/OrionAPI/build.gradle +++ b/OrionAPI/build.gradle @@ -1,21 +1,19 @@ dependencies { - // Instrumetnation tools will be bundled - compile group: 'eu.mikroskeem', name: 'shuriken.instrumentation', version: shuriken_version - // Dependencies what are present on runtime compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: log4j2_version + compile group: 'org.ow2.asm', name: 'asm', version: asm_version // Dependencies which will be downloaded - downloadDep group: 'javax.inject', name: 'javax.inject', version: '1' - downloadDep(group: 'eu.mikroskeem', name: 'legacylauncher', version: legacylauncher_version) { + compile group: 'javax.inject', name: 'javax.inject', version: '1' + compile(group: 'cpw.mods', name: 'modlauncher', version: modLauncherVersion) { exclude module: '*' } - downloadDep(group: 'ninja.leaping.configurate', name: 'configurate-hocon', version: hocon_version) { + compile(group: 'org.spongepowered', name: 'configurate-hocon', version: hocon_version) { exclude module: 'guava' } // TODO: way to disable Mixin AP - downloadDep(group: 'org.spongepowered', name: 'mixin', version: mixin_version) { + compile(group: 'org.spongepowered', name: 'mixin', version: mixin_version) { exclude module: 'commons-io' exclude module: 'guava' exclude module: 'launchwrapper' @@ -23,6 +21,8 @@ dependencies { exclude module: 'gson' } + compile group: 'org.checkerframework', name: 'checker-qual', version: checker_qual_version + // Required to get Mixin AP working compile group: 'com.google.code.gson', name: 'gson', version: gson_version compile group: 'com.google.guava', name: 'guava', version: guava_version diff --git a/OrionAPI/src/main/java/eu/mikroskeem/orion/api/CBVersion.java b/OrionAPI/src/main/java/eu/mikroskeem/orion/api/CBVersion.java deleted file mode 100644 index 929c123..0000000 --- a/OrionAPI/src/main/java/eu/mikroskeem/orion/api/CBVersion.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of project Orion, licensed under the MIT License (MIT). - * - * Copyright (c) 2017-2020 Mark Vainomaa - * Copyright (c) Contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package eu.mikroskeem.orion.api; - -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - - -/** - * Enum representing CraftBukkit relocation version - * - * @author Mark Vainomaa - * @deprecated Mostly useless API and annoying to maintain - */ -@Deprecated -public enum CBVersion { - /** Minecraft 1.12 */ - v1_12_R1(0, "v1_12_R1"), - - /** Minecraft 1.13 */ - v1_13_R1(1, "v1_13_R1"), - - /** Minecraft 1.13.1 */ - v1_13_R2(2, "v1_13_R2"), - - UNKNOWN(-1, ""), - ; - - private final int id; - private final String name; - - CBVersion(int id, String name) { - this.id = id; - this.name = name; - } - - /** - * Gets given CraftBukkit version id (used in Mixin environment) - * - * @return CraftBukkit version id - */ - @Contract(pure = true) - public int getId() { - return id; - } - - /** - * Gets given CraftBukkit version name - * - * @return CraftBukkit version name - */ - @NotNull - @Contract(pure = true) - public String getName() { - return name; - } -} diff --git a/OrionAPI/src/main/java/eu/mikroskeem/orion/api/Orion.java b/OrionAPI/src/main/java/eu/mikroskeem/orion/api/Orion.java index a04332c..7d2c324 100644 --- a/OrionAPI/src/main/java/eu/mikroskeem/orion/api/Orion.java +++ b/OrionAPI/src/main/java/eu/mikroskeem/orion/api/Orion.java @@ -28,11 +28,11 @@ import eu.mikroskeem.orion.api.asset.AssetManager; import eu.mikroskeem.orion.api.bytecode.OrionTransformer; import eu.mikroskeem.orion.api.mod.ModInfo; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import java.net.URL; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -47,8 +47,12 @@ public interface Orion { * Registers access transformer to be applied on server start. * * @param atUrl Resource {@link URL} of access transformer file (in other words {@link Class#getResource(String)}) + * @deprecated Deprecated without replacement */ - void registerAT(@NotNull URL atUrl); + @Deprecated + default void registerAT(@NonNull URL atUrl) { + throw new UnsupportedOperationException(); + } /** * Registers mixin config. @@ -57,46 +61,61 @@ public interface Orion { * * @param mixinConfigName Mixin configuration name in format:
mixins.MOD_ID.WHATEVER.json
*/ - void registerMixinConfig(@NotNull String mixinConfigName); + void registerMixinConfig(@NonNull String mixinConfigName); /** * Gets list of registered Maven repositories * * @return {@link List} of Maven repository {@link URL}s + * @deprecated Deprecated without replacement */ - @NotNull - List getRegisteredMavenRepositories(); + @NonNull + @Deprecated + default List getRegisteredMavenRepositories() { + return Collections.emptyList(); + } /** * Registers Maven repository where libraries can be downloaded * * @param url Maven repository url * @see Orion#registerLibrary(String) + * @deprecated Deprecated without replacement */ - void registerMavenRepository(@NotNull URL url); + @Deprecated + default void registerMavenRepository(@NonNull URL url) { + throw new UnsupportedOperationException(); + } /** * Gets list of registered mod libraries * * @return {@link List} of mod libraries * @see Orion#registerLibrary(String) + * @deprecated Deprecated without replacement */ - @NotNull - List getRegisteredLibraries(); + @NonNull + @Deprecated + default List getRegisteredLibraries() { + return Collections.emptyList(); + } /** * Add new library for downloading from Maven repository. * * @param dependencyString Dependency string, like
groupId:artifactId:version
+ * @deprecated Deprecated without replacement */ - void registerLibrary(@NotNull String dependencyString); + default void registerLibrary(@NonNull String dependencyString) { + throw new UnsupportedOperationException(); + } /** * Gets unmodifiable list of loaded mods * * @return Unmodifiable list of loaded mods */ - @NotNull + @NonNull List getMods(); /** @@ -107,14 +126,14 @@ public interface Orion { * @return Instance of {@link ModInfo} or null, if mod wasn't found */ @Nullable - ModInfo getMod(@NotNull String modId); + ModInfo getMod(@NonNull String modId); /** * Gets unmodifiable list of registered Mixin configurations * * @return Unmodifiable list of registered Mixin configurations */ - @NotNull + @NonNull List getMixinConfigurations(); /** @@ -123,7 +142,7 @@ public interface Orion { * @since 0.0.3-SNAPSHOT * @param transformer New transformer */ - void registerTransformer(@NotNull Class transformer); + void registerTransformer(@NonNull Class transformer); /** * Unregisters registered {@link OrionTransformer} class @@ -131,7 +150,7 @@ public interface Orion { * @since 0.0.3-SNAPSHOT * @param transformer Registered transformer. Check if transformer is registered with {@link #getRegisteredTransformers()} */ - void unregisterTransformer(@NotNull Class transformer); + void unregisterTransformer(@NonNull Class transformer); /** * Gets list of registered Orion bytecode transformers @@ -139,8 +158,8 @@ public interface Orion { * @since 0.0.3-SNAPSHOT * @return {@link List} of registered {@link OrionTransformer}s */ - @NotNull - Set> getRegisteredTransformers(); + @NonNull + Set<@NonNull Class> getRegisteredTransformers(); /** * Gets mod asset manager @@ -148,6 +167,5 @@ public interface Orion { * @since 0.0.4-SNAPSHOT * @return Mod asset manager */ - @NotNull - AssetManager.ForMod getAssetManager(); + AssetManager.@NonNull ForMod getAssetManager(); } diff --git a/OrionAPI/src/main/java/eu/mikroskeem/orion/api/OrionAPI.java b/OrionAPI/src/main/java/eu/mikroskeem/orion/api/OrionAPI.java index f5f1464..1b94dae 100644 --- a/OrionAPI/src/main/java/eu/mikroskeem/orion/api/OrionAPI.java +++ b/OrionAPI/src/main/java/eu/mikroskeem/orion/api/OrionAPI.java @@ -25,8 +25,7 @@ package eu.mikroskeem.orion.api; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; +import org.checkerframework.checker.nullness.qual.NonNull; import java.util.Objects; @@ -45,8 +44,7 @@ public final class OrionAPI { * * @return {@link Orion} instance */ - @NotNull - @Contract(pure = true) + @NonNull public static Orion getInstance() { return instance; } @@ -56,8 +54,7 @@ public static Orion getInstance() { * * @param instance {@link Orion} */ - @Contract("null -> fail") - public static void setInstance(@NotNull Orion instance) { + public static void setInstance(@NonNull Orion instance) { Objects.requireNonNull(instance, "Can not set Orion instance to null!"); if(OrionAPI.instance != null) throw new IllegalStateException("Orion instance is already set!"); OrionAPI.instance = instance; diff --git a/OrionAPI/src/main/java/eu/mikroskeem/orion/api/asset/AssetManager.java b/OrionAPI/src/main/java/eu/mikroskeem/orion/api/asset/AssetManager.java index 3c96b75..db655fc 100644 --- a/OrionAPI/src/main/java/eu/mikroskeem/orion/api/asset/AssetManager.java +++ b/OrionAPI/src/main/java/eu/mikroskeem/orion/api/asset/AssetManager.java @@ -26,8 +26,8 @@ package eu.mikroskeem.orion.api.asset; import eu.mikroskeem.orion.api.mod.ModInfo; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import java.io.InputStream; import java.io.UncheckedIOException; @@ -46,7 +46,7 @@ public interface AssetManager { * @return Instance of {@link InputStream} streaming asset contents or null, if asset couldn't be found */ @Nullable - InputStream getAsset(@NotNull String assetPath); + InputStream getAsset(@NonNull String assetPath); /** * Copies asset from mod jar to path @@ -57,7 +57,7 @@ public interface AssetManager { * @param assetPath Asset path * @throws UncheckedIOException If asset copying fails either because of filesystem or resource finding error */ - void copyAsset(@NotNull Path destination, @NotNull String assetPath) throws UncheckedIOException; + void copyAsset(@NonNull Path destination, @NonNull String assetPath) throws UncheckedIOException; /** * Copies asset from mod jar to path @@ -67,7 +67,7 @@ public interface AssetManager { * @param overwriteExisting Whether to overwrite destination file if present * @throws UncheckedIOException If asset copying fails either because of filesystem or resource finding error */ - void copyAsset(@NotNull Path destination, @NotNull String assetPath, boolean overwriteExisting) throws UncheckedIOException; + void copyAsset(@NonNull Path destination, @NonNull String assetPath, boolean overwriteExisting) throws UncheckedIOException; /** * Mod specific asset manager picker @@ -79,8 +79,8 @@ interface ForMod { * @param modInfo Instance of {@link ModInfo} * @return Mod specific {@link AssetManager} */ - @NotNull - AssetManager forMod(@NotNull ModInfo modInfo); + @NonNull + AssetManager forMod(@NonNull ModInfo modInfo); /** * Gets asset manager for mod specified with {@code modInfo} @@ -89,6 +89,6 @@ interface ForMod { * @return Mod specific {@link AssetManager} or null, if no such mod exists */ @Nullable - AssetManager forMod(@NotNull String modId); + AssetManager forMod(@NonNull String modId); } } diff --git a/OrionAPI/src/main/java/eu/mikroskeem/orion/api/bytecode/OrionTransformer.java b/OrionAPI/src/main/java/eu/mikroskeem/orion/api/bytecode/OrionTransformer.java index 8e305ce..da1d822 100644 --- a/OrionAPI/src/main/java/eu/mikroskeem/orion/api/bytecode/OrionTransformer.java +++ b/OrionAPI/src/main/java/eu/mikroskeem/orion/api/bytecode/OrionTransformer.java @@ -25,9 +25,8 @@ package eu.mikroskeem.orion.api.bytecode; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; /** * Orion bytecode transformer interface @@ -45,5 +44,5 @@ public interface OrionTransformer { * @return Transformed class or null */ @Nullable - byte[] transformClass(@Nullable byte[] source, @NotNull String className, @NotNull String remappedClassName); + byte[] transformClass(@Nullable byte[] source, @NonNull String className, @NonNull String remappedClassName); } diff --git a/OrionAPI/src/main/java/eu/mikroskeem/orion/api/configuration/ObjectConfigurationLoader.java b/OrionAPI/src/main/java/eu/mikroskeem/orion/api/configuration/ObjectConfigurationLoader.java index f38b737..0234ac4 100644 --- a/OrionAPI/src/main/java/eu/mikroskeem/orion/api/configuration/ObjectConfigurationLoader.java +++ b/OrionAPI/src/main/java/eu/mikroskeem/orion/api/configuration/ObjectConfigurationLoader.java @@ -26,7 +26,6 @@ package eu.mikroskeem.orion.api.configuration; import eu.mikroskeem.orion.api.annotations.ConfigurationBaseNode; -import eu.mikroskeem.shuriken.common.SneakyThrow; import ninja.leaping.configurate.ConfigurationOptions; import ninja.leaping.configurate.commented.CommentedConfigurationNode; import ninja.leaping.configurate.hocon.HoconConfigurationLoader; @@ -35,9 +34,8 @@ import ninja.leaping.configurate.objectmapping.ObjectMapper; import ninja.leaping.configurate.objectmapping.ObjectMappingException; import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import java.io.IOException; import java.io.UncheckedIOException; @@ -54,18 +52,18 @@ * @author Mark Vainomaa */ public class ObjectConfigurationLoader { - @NotNull private final String baseNodeName; - @NotNull private final Class configClass; + @NonNull private final String baseNodeName; + @NonNull private final Class configClass; @Nullable private final String header; /** Configuration file absolute location */ - @NotNull private final Path configurationPath; + @NonNull private final Path configurationPath; /** Configuration loader instance */ - @NotNull private final ConfigurationLoader loader; + @NonNull private final ConfigurationLoader loader; /** Object mapper instance for {@code T} */ - @NotNull private final ObjectMapper.BoundInstance mapper; + @NonNull private final ObjectMapper.BoundInstance mapper; /** Configuration lodaer base node */ @Nullable private CommentedConfigurationNode baseNode; @@ -81,8 +79,8 @@ private ConfigurationOptions getDefaultOptions() { return options; } - public ObjectConfigurationLoader(@NotNull Path configurationFile, @NotNull Class configClass, - @Nullable String baseNodeName, @Nullable String header) { + public ObjectConfigurationLoader(@NonNull Path configurationFile, @NonNull Class configClass, + @Nullable String baseNodeName, @Nullable String header) throws ObjectMappingException { this.configurationPath = configurationFile.toAbsolutePath(); this.configClass = configClass; this.header = header; @@ -126,15 +124,10 @@ public ObjectConfigurationLoader(@NotNull Path configurationFile, @NotNull Class .build(); // Build object mapper - try { - mapper = ObjectMapper.forClass(configClass).bindToNew(); - } catch (ObjectMappingException e) { - SneakyThrow.throwException(e); - throw null; - } + mapper = ObjectMapper.forClass(configClass).bindToNew(); } - public ObjectConfigurationLoader(@NotNull Path configurationFile, @NotNull Class configClass) { + public ObjectConfigurationLoader(@NonNull Path configurationFile, @NonNull Class configClass) throws ObjectMappingException { this(configurationFile, configClass, null, null); } @@ -167,7 +160,6 @@ public void save() { * * @return Instance of {@code T} */ - @Contract(pure = true) public T getConfiguration() { return Objects.requireNonNull(configuration); } @@ -177,7 +169,7 @@ public T getConfiguration() { * * @return Wrapped configuration loader instance */ - @NotNull + @NonNull public ConfigurationLoader getLoader() { return loader; } diff --git a/OrionAPI/src/main/java/eu/mikroskeem/orion/api/mod/ModInfo.java b/OrionAPI/src/main/java/eu/mikroskeem/orion/api/mod/ModInfo.java index 41dcbf1..f34932b 100644 --- a/OrionAPI/src/main/java/eu/mikroskeem/orion/api/mod/ModInfo.java +++ b/OrionAPI/src/main/java/eu/mikroskeem/orion/api/mod/ModInfo.java @@ -25,7 +25,7 @@ package eu.mikroskeem.orion.api.mod; -import org.jetbrains.annotations.NotNull; +import org.checkerframework.checker.nullness.qual.NonNull; import java.util.List; @@ -41,7 +41,7 @@ public interface ModInfo { * * @return Mod id */ - @NotNull + @NonNull String getId(); /** @@ -49,7 +49,7 @@ public interface ModInfo { * * @return Mod main class name */ - @NotNull + @NonNull String getClassName(); /** @@ -57,7 +57,7 @@ public interface ModInfo { * * @return Mod dependency list */ - @NotNull + @NonNull List getDependencies(); /** @@ -65,6 +65,6 @@ public interface ModInfo { * * @return Mod configuration class */ - @NotNull + @NonNull Class getConfigClass(); } diff --git a/OrionCore/build.gradle b/OrionCore/build.gradle deleted file mode 100644 index ac6e3d1..0000000 --- a/OrionCore/build.gradle +++ /dev/null @@ -1,17 +0,0 @@ -dependencies { - compile project(':OrionAPI') - - compile group: 'eu.mikroskeem', name: 'picomaven', version: picomaven_version - - downloadDep(group: 'com.google.inject', name: 'guice', version: guice_version) { - exclude group: 'com.google.guava', module: 'guava' // Supplied by Paper server - } - downloadDep(group: 'eu.mikroskeem', name: 'orion.at', version: orion_at_version) { - exclude group: 'org.jetbrains', module: 'annotations' - exclude group: 'org.ow2.asm', module: 'asm-all' - } -} - -compileJava { - options.compilerArgs += "-proc:none" -} \ No newline at end of file diff --git a/OrionCore/build.gradle.kts b/OrionCore/build.gradle.kts new file mode 100644 index 0000000..8937710 --- /dev/null +++ b/OrionCore/build.gradle.kts @@ -0,0 +1,11 @@ +dependencies { + compile(project(":OrionAPI")) + + compile("com.google.inject:guice:${rootProject.extra["guice_version"]}") { + exclude(group = "com.google.guava", module = "guava") // Supplied by Paper server + } +} + +val compileJava by tasks.getting(JavaCompile::class) { + options.compilerArgs.add("-proc:none") +} \ No newline at end of file diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/OrionAPIImpl.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/OrionAPIImpl.java index 7e07142..1c65fd7 100644 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/OrionAPIImpl.java +++ b/OrionCore/src/main/java/eu/mikroskeem/orion/core/OrionAPIImpl.java @@ -31,17 +31,13 @@ import eu.mikroskeem.orion.api.mod.ModInfo; import eu.mikroskeem.orion.core.mod.AssetManagerImpl; import eu.mikroskeem.orion.core.mod.ModContainer; -import eu.mikroskeem.picomaven.Dependency; -import eu.mikroskeem.shuriken.common.SneakyThrow; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixins; import java.lang.ref.SoftReference; -import java.net.MalformedURLException; -import java.net.URISyntaxException; import java.net.URL; import java.util.Collections; import java.util.List; @@ -71,11 +67,6 @@ final class OrionAPIImpl implements Orion { this.assetManager = new AssetManagerImpl(); } - @Override - public void registerAT(URL atUrl) { - OrionAccessTransformer.registerAT(atUrl); - } - @Override public void registerMixinConfig(String mixinConfigName) { if(!MIXIN_NAME_PATTERN.matcher(mixinConfigName).matches()) @@ -88,63 +79,10 @@ public void registerMixinConfig(String mixinConfigName) { orionCore.mixinConfigurations.add(mixinConfigName); Mixins.addConfiguration(mixinConfigName); } - - @NotNull - @Override - public List getRegisteredMavenRepositories() { - if(registeredMavenRepositories == null || registeredMavenRepositories.get() == null) { - registeredMavenRepositories = new SoftReference<>(Collections.unmodifiableList( - orionCore.modMavenRepositories.stream().map(u -> { - try { - return u.toURL(); - } catch (MalformedURLException e) { - SneakyThrow.throwException(e); - return null; - } - }) - .collect(Collectors.toList()) - )); - } - - return Objects.requireNonNull(registeredMavenRepositories.get()); // Should not throw NPE - } - - @Override - public void registerMavenRepository(URL url) { - Objects.requireNonNull(url, "Repository URL should not be null"); - try { - orionCore.modMavenRepositories.add(url.toURI()); - - if(registeredMavenRepositories != null) - registeredMavenRepositories.clear(); - } catch (URISyntaxException e) { - SneakyThrow.throwException(e); - } - } - - @Override - public void registerLibrary(String dependencyString) { - orionCore.modLibraries.add(Dependency.fromGradle(dependencyString)); - if(mods != null) - mods.clear(); - } - - @NotNull - @Override - public List getRegisteredLibraries() { - if(registeredLibraries == null || registeredLibraries.get() == null) { - registeredLibraries = new SoftReference<>(Collections.unmodifiableList( - orionCore.modLibraries.stream() - .map(d -> d.getGroupId() + ':' + d.getArtifactId() + ':' + d.getVersion()) - .collect(Collectors.toList()) - )); - } - - return Objects.requireNonNull(registeredLibraries.get()); - } + @Override - @NotNull + @NonNull public List getMods() { if(mods == null || mods.get() == null) { mods = new SoftReference<>(orionCore.mods.stream() @@ -158,35 +96,34 @@ public List getMods() { @Nullable @Override - public ModInfo getMod(@NotNull String modId) { + public ModInfo getMod(@NonNull String modId) { return getMods().stream().filter(m -> m.getId().equals(modId)).findFirst().orElse(null); } @Override - @NotNull + @NonNull public List getMixinConfigurations() { return Collections.unmodifiableList(orionCore.mixinConfigurations); } @Override - public void registerTransformer(@NotNull Class transformer) { + public void registerTransformer(@NonNull Class transformer) { orionCore.transformers.add(transformer); } @Override - public void unregisterTransformer(@NotNull Class transformer) { + public void unregisterTransformer(@NonNull Class transformer) { orionCore.transformers.remove(transformer); } @Override - @NotNull + @NonNull public Set> getRegisteredTransformers() { return Collections.unmodifiableSet(orionCore.transformers); } - @NotNull @Override - public AssetManager.ForMod getAssetManager() { + public AssetManager.@NonNull ForMod getAssetManager() { return assetManager; } } diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/OrionAccessTransformer.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/OrionAccessTransformer.java deleted file mode 100644 index 49a2696..0000000 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/OrionAccessTransformer.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * This file is part of project Orion, licensed under the MIT License (MIT). - * - * Copyright (c) 2017-2020 Mark Vainomaa - * Copyright (c) Contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package eu.mikroskeem.orion.core; - -import eu.mikroskeem.orion.api.bytecode.OrionTransformer; -import eu.mikroskeem.orion.at.AccessTransformer; -import eu.mikroskeem.orion.core.launcher.BlackboardKey; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.net.URL; -import java.net.URLConnection; -import java.util.ArrayList; -import java.util.List; - - -/** - * Orion Access Transformer library wrapper - * - * @author Mark Vainomaa - */ -public final class OrionAccessTransformer implements OrionTransformer { - private static final Logger logger = LogManager.getLogger("OrionAT"); - private final AccessTransformer at = new AccessTransformer(); - - public OrionAccessTransformer() { - List atUrls = BlackboardKey.getOr(BlackboardKey.AT_URLS, ArrayList::new); - logger.debug("Initializing OrionAT with {} access transformers", atUrls.size()); - - /* Load AT files to AT library */ - for(URL url : atUrls) { - try { - URLConnection urlConnection = url.openConnection(); - urlConnection.setUseCaches(false); - logger.debug("Processing AT {}", url); - at.loadAccessTransformers(urlConnection.getInputStream()); - } catch (IOException e) { - logger.warn("Skipping AT {}", e); - } - } - - logger.debug("OrionAT initialized"); - } - - /** - * Register access transformer from jar resource - * - * @param url AT url from {@link Class#getResource(String)} - */ - public static void registerAT(@NotNull URL url) { - try { - /* Test connection */ - URLConnection urlConnection = url.openConnection(); - urlConnection.setUseCaches(false); - urlConnection.connect(); - BlackboardKey.>getOr(BlackboardKey.AT_URLS, ArrayList::new).add(url); - logger.debug("Registered AT {}", url); - } catch (IOException e) { - logger.warn("Failed to register AT {}", url); - } - } - - @Nullable - @Override - public byte[] transformClass(@Nullable byte[] source, @NotNull String className, @NotNull String remappedClassName) { - if(source == null) - return null; - - logger.debug("Transforming class {}", className); - return at.transformClass(source); - } -} diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/OrionCore.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/OrionCore.java index 2548a14..7977aa5 100644 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/OrionCore.java +++ b/OrionCore/src/main/java/eu/mikroskeem/orion/core/OrionCore.java @@ -30,7 +30,6 @@ import com.google.inject.Injector; import com.google.inject.TypeLiteral; import com.google.inject.name.Names; -import eu.mikroskeem.orion.api.CBVersion; import eu.mikroskeem.orion.api.Orion; import eu.mikroskeem.orion.api.OrionAPI; import eu.mikroskeem.orion.api.asset.AssetManager; @@ -38,36 +37,21 @@ import eu.mikroskeem.orion.api.configuration.ObjectConfigurationLoader; import eu.mikroskeem.orion.api.events.ModLoadEvent; import eu.mikroskeem.orion.api.mod.ModInfo; -import eu.mikroskeem.orion.core.extensions.OrionMixinErrorHandler; -import eu.mikroskeem.orion.core.extensions.OrionTokenProvider; import eu.mikroskeem.orion.core.guice.TypeLiteralGenerator; -import eu.mikroskeem.orion.core.launcher.AbstractLauncherService; import eu.mikroskeem.orion.core.launcher.BlackboardKey; import eu.mikroskeem.orion.core.launcher.LauncherService; import eu.mikroskeem.orion.core.mod.ModClassVisitor; import eu.mikroskeem.orion.core.mod.ModContainer; -import eu.mikroskeem.picomaven.Dependency; -import eu.mikroskeem.picomaven.DownloaderCallbacks; -import eu.mikroskeem.picomaven.PicoMaven; -import eu.mikroskeem.shuriken.common.SneakyThrow; -import eu.mikroskeem.shuriken.common.ToURL; -import eu.mikroskeem.shuriken.common.data.Pair; -import eu.mikroskeem.shuriken.common.streams.ByteArrays; -import eu.mikroskeem.shuriken.reflect.ClassWrapper; -import eu.mikroskeem.shuriken.reflect.Reflect; import ninja.leaping.configurate.commented.CommentedConfigurationNode; import ninja.leaping.configurate.loader.ConfigurationLoader; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.launch.MixinBootstrap; import org.spongepowered.asm.mixin.MixinEnvironment; -import org.spongepowered.asm.mixin.Mixins; import java.io.IOException; -import java.net.URI; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; @@ -77,9 +61,7 @@ import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.Set; -import java.util.concurrent.Executors; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -102,57 +84,34 @@ public final class OrionCore { /** Static instance */ public final static OrionCore INSTANCE = new OrionCore(); - private final AbstractLauncherService launcherService; private OrionAPIImpl orionAPI; private Injector baseInjector; final List> mods = new ArrayList<>(); final List mixinConfigurations = new ArrayList<>(); - final List modMavenRepositories = new ArrayList<>(); - final List modLibraries = new ArrayList<>(); final Set> transformers = new HashSet<>(); /** * Private constructor to set up Mixin loader */ private OrionCore() { - launcherService = BlackboardKey.get(BlackboardKey.LAUNCHER_SERVICE); - logger.debug("Setting up SpongeMixin library..."); MixinBootstrap.init(); logger.debug("Setting Mixin Environment side to SERVER"); MixinEnvironment.getDefaultEnvironment().setSide(MixinEnvironment.Side.SERVER); - logger.debug("Setting up Mixin error handler"); - Mixins.registerErrorHandlerClass(OrionMixinErrorHandler.class.getName()); - - logger.debug("Setting up Mixin token provider"); - MixinEnvironment.getDefaultEnvironment().registerTokenProviderClass(OrionTokenProvider.class.getName()); - logger.debug("Mixin library initialization finished!"); } - /** - * Gets detected CraftBukkit version - * - * @return Detected {@link CBVersion} - */ - @NotNull - @Contract(pure = true) - public CBVersion getCBVersion() { - return CBVersion.UNKNOWN; - } - /** * Sets up Orion transformers */ public void setupTransformers() { - /* Access transformer */ - launcherService.registerTransformer(OrionAccessTransformer.class); - /* Mod provided transformers */ - transformers.forEach(launcherService::registerTransformer); + for (Class transformer : transformers) { + // TODO + } } /** @@ -168,9 +127,6 @@ public void setupCore() { /* API */ "eu.mikroskeem.orion.api", - /* Don't try to transform the access transformer */ - "eu.mikroskeem.orion.at", - /* Library packages */ "ninja.leaping.configurate", "javax.inject", @@ -214,7 +170,6 @@ public void setupCore() { * @param modsDirectory Directory where mods should reside * @throws IOException If {@link Files#list(Path)} fails */ - @Contract("null, null -> fail") public void setupMods(LauncherService launcherService, Path modsDirectory) throws IOException { Set modLoadOrder = new HashSet<>(); Map> foundMods = new LinkedHashMap<>(); @@ -377,39 +332,6 @@ public void setupMods(LauncherService launcherService, Path modsDirectory) throw mods.add(mod); } - /* Process mod requested libraries */ - if(modLibraries.size() > 0) { - logger.info("Setting up {} extra libraries requested by installed mods...", modLibraries.size()); - PicoMaven.Builder picoMavenBuilder = new PicoMaven.Builder() - .withExecutorService(Executors.newWorkStealingPool()) - .shouldCloseExecutorService(true) - .withDownloadPath(BlackboardKey.get(BlackboardKey.LIBRARIES_PATH)) - .withRepositories(modMavenRepositories) - .withDependencies(modLibraries) - .withDownloaderCallbacks(new DownloaderCallbacks() { - @Override - public void onSuccess(Dependency dependency, Path dependencyPath) { - logger.info("Dependency {} downloaded successfully!", dependency); - } - - @Override - public void onFailure(Dependency dependency, Exception exception) { - logger.error("Failed to download dependency {}! {}", dependency, exception); - } - }); - - try(PicoMaven picoMaven = picoMavenBuilder.build()) { - List downloadedLibraries = picoMaven.downloadAll(); - if(downloadedLibraries.size() != modLibraries.size()) - throw new IllegalStateException("Could not download all libraries!"); - - /* Add all libraries to LaunchClassLoader */ - downloadedLibraries.stream().map(ToURL::to).forEach(launcherService::addURLToClassLoader); - } catch (InterruptedException e) { - logger.error("Library download interrupted!", e); - } - } - /* Load mods */ for(ModContainer mod : mods) { mod.getEventBus().post(new ModLoadEvent()); @@ -454,7 +376,7 @@ private ModContainer initializeMod(ClassWrapper modClass, ModInfo modI } @Nullable - private Class findClass(@NotNull String className) { + private Class findClass(@NonNull String className) { try { return Class.forName(className, false, this.getClass().getClassLoader()); } catch (ClassNotFoundException e) { diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/extensions/OrionMixinErrorHandler.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/extensions/OrionMixinErrorHandler.java deleted file mode 100644 index 756a1bb..0000000 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/extensions/OrionMixinErrorHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This file is part of project Orion, licensed under the MIT License (MIT). - * - * Copyright (c) 2017-2020 Mark Vainomaa - * Copyright (c) Contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package eu.mikroskeem.orion.core.extensions; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.spongepowered.asm.mixin.extensibility.IMixinConfig; -import org.spongepowered.asm.mixin.extensibility.IMixinErrorHandler; -import org.spongepowered.asm.mixin.extensibility.IMixinInfo; - - -/** - * @author Mark Vainomaa - */ -public final class OrionMixinErrorHandler implements IMixinErrorHandler { - private static final Logger logger = LogManager.getLogger("Orion Mixin Error Handler"); - - @Override - public ErrorAction onPrepareError(IMixinConfig config, Throwable th, IMixinInfo mixin, ErrorAction action) { - return ErrorAction.ERROR; - } - - @Override - public ErrorAction onApplyError(String targetClassName, Throwable th, IMixinInfo mixin, ErrorAction action) { - return ErrorAction.ERROR; - } -} diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/extensions/OrionTokenProvider.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/extensions/OrionTokenProvider.java deleted file mode 100644 index 77a9c79..0000000 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/extensions/OrionTokenProvider.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of project Orion, licensed under the MIT License (MIT). - * - * Copyright (c) 2017-2020 Mark Vainomaa - * Copyright (c) Contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package eu.mikroskeem.orion.core.extensions; - -import eu.mikroskeem.orion.core.OrionCore; -import org.spongepowered.asm.mixin.MixinEnvironment; -import org.spongepowered.asm.mixin.extensibility.IEnvironmentTokenProvider; - - -/** - * Provides
CB_VERSION
token for {@link org.spongepowered.asm.mixin.Overwrite} constraint - * - * See constraints - * - * @author Mark Vainomaa - */ -public final class OrionTokenProvider implements IEnvironmentTokenProvider { - @Override - public int getPriority() { - return 0; - } - - @Override - public Integer getToken(String token, MixinEnvironment env) { - if(token.equals("CB_VERSION")) - return OrionCore.INSTANCE.getCBVersion().getId(); - - return null; - } -} diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/guice/TypeLiteralGenerator.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/guice/TypeLiteralGenerator.java index b56ad34..65b114e 100644 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/guice/TypeLiteralGenerator.java +++ b/OrionCore/src/main/java/eu/mikroskeem/orion/core/guice/TypeLiteralGenerator.java @@ -28,10 +28,7 @@ import com.google.inject.TypeLiteral; import eu.mikroskeem.orion.core.launcher.BlackboardKey; import eu.mikroskeem.orion.core.launcher.LauncherService; -import eu.mikroskeem.shuriken.instrumentation.ClassLoaderTools; -import eu.mikroskeem.shuriken.instrumentation.ClassTools; -import eu.mikroskeem.shuriken.reflect.Reflect; -import org.jetbrains.annotations.NotNull; +import org.checkerframework.checker.nullness.qual.NonNull; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; @@ -56,29 +53,30 @@ public final class TypeLiteralGenerator { private final static Type thisType = Type.getType(TypeLiteralGenerator.class); private final static Type typeLiteralType = Type.getType(TypeLiteral.class); - @NotNull + @NonNull @SuppressWarnings("unchecked") - public static TypeLiteral get(@NotNull SignatureBuilder signatureBuilder) { + public static TypeLiteral get(@NonNull SignatureBuilder signatureBuilder) { return (TypeLiteral) generated.computeIfAbsent(signatureBuilder, c -> generate(of(TypeLiteral.class, signatureBuilder).build())); } - @NotNull - private static TypeLiteral generate(@NotNull String signature) { + @NonNull + private static TypeLiteral generate(@NonNull String signature) { // Figure out new inner class name String className = TypeLiteralGenerator.class.getName() + "$g" + generatedCounter.incrementAndGet(); + String unqualifiedName = className.replace('.', '/'); // Start writing an inner class ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); cw.visit(Opcodes.V1_8, Opcodes.ACC_FINAL | Opcodes.ACC_SUPER, - ClassTools.unqualifyName(className), + unqualifiedName, signature, typeLiteralType.getInternalName(), null); cw.visitOuterClass(thisType.getInternalName(), null, null); - cw.visitInnerClass(ClassTools.unqualifyName(className), null, null, Opcodes.ACC_STATIC); + cw.visitInnerClass(unqualifiedName, null, null, Opcodes.ACC_STATIC); ClassTools.generateSimpleSuperConstructor(cw, TypeLiteral.class); cw.visitEnd(); @@ -90,19 +88,20 @@ private static TypeLiteral generate(@NotNull String signature) { Class> definedLiteral = (Class>) Objects.requireNonNull(ClassLoaderTools.defineClass(loader, className, classData), "Failed to define TypeLiteral class: " + className); - return Objects.requireNonNull(Reflect.wrapClass(definedLiteral).construct().getClassInstance(), "Class instance was null!"); + TypeLiteral literal = definedLiteral.getConstructor().newInstance(); + return literal; } public final static class SignatureBuilder { private final String base; private final List parameters; - private SignatureBuilder(@NotNull String base, @NotNull List parameters) { + private SignatureBuilder(@NonNull String base, @NonNull List parameters) { this.base = base; this.parameters = parameters; } - @NotNull + @NonNull public String build() { StringBuilder builder = new StringBuilder(); builder.append('L') @@ -131,13 +130,13 @@ public int hashCode() { return Objects.hash(base, parameters); } - @NotNull - public static SignatureBuilder of(@NotNull Class base, @NotNull SignatureBuilder... parameters) { + @NonNull + public static SignatureBuilder of(@NonNull Class base, @NonNull SignatureBuilder... parameters) { return of(Type.getType(base), parameters); } - @NotNull - public static SignatureBuilder of(@NotNull Type base, @NotNull SignatureBuilder... parameters) { + @NonNull + public static SignatureBuilder of(@NonNull Type base, @NonNull SignatureBuilder... parameters) { return new SignatureBuilder(base.getInternalName(), Arrays.asList(parameters)); } } diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/AbstractLauncherService.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/AbstractLauncherService.java deleted file mode 100644 index 728782b..0000000 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/AbstractLauncherService.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of project Orion, licensed under the MIT License (MIT). - * - * Copyright (c) 2017-2020 Mark Vainomaa - * Copyright (c) Contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package eu.mikroskeem.orion.core.launcher; - -import eu.mikroskeem.orion.api.bytecode.OrionTransformer; -import org.jetbrains.annotations.NotNull; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * @author Mark Vainomaa - */ -public abstract class AbstractLauncherService implements LauncherService { - private Map fallback$blackboard; - - @NotNull - @Override - public Map getBlackBoard() { - if(fallback$blackboard == null) fallback$blackboard = new HashMap<>(); - return fallback$blackboard; - } - - @Override - public abstract void registerTransformer(@NotNull Class transformer); - - @NotNull - @Override - public abstract Set getClassLoaderExclusions(); -} diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/BlackboardKey.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/BlackboardKey.java index a47a458..4ca3311 100644 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/BlackboardKey.java +++ b/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/BlackboardKey.java @@ -25,15 +25,12 @@ package eu.mikroskeem.orion.core.launcher; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import cpw.mods.modlauncher.Launcher; +import cpw.mods.modlauncher.api.TypesafeMap; +import org.checkerframework.checker.nullness.qual.NonNull; -import java.net.URL; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.function.Supplier; import static java.util.Objects.requireNonNull; @@ -43,87 +40,31 @@ * * @author Mark Vainomaa */ -public enum BlackboardKey { - LAUNCHER_SERVICE("orion.launch.service", AbstractLauncherService.class, false), +public final class BlackboardKey { + private BlackboardKey() {} - ORIGINAL_ARGUMENTS("orion.launch.arguments", List.class), - LAUNCH_TARGET("orion.launch.target", String.class), - - LIBRARIES_PATH("orion.path.libraries", Path.class, false), - MODS_PATH("orion.path.mods", Path.class, false), - MOD_CONFIGS_PATH("orion.path.modconfigs", Path.class, false), - - AT_URLS("orion.at.urls", List.class, ArrayList::new) - ; - - private final String key; - private final Class type; - private final boolean mutable; - @Nullable private final Supplier initializer; - - BlackboardKey(@NotNull String key, @NotNull Class type) { - this.key = key; - this.type = type; - this.mutable = true; - this.initializer = null; - } - - BlackboardKey(@NotNull String key, @NotNull Class type, boolean mutable) { - this.key = key; - this.type = type; - this.mutable = mutable; - this.initializer = null; - } - - BlackboardKey(@NotNull String key, @NotNull Class type, @Nullable Supplier initializer) { - this.key = key; - this.type = type; - this.mutable = true; - this.initializer = initializer; + private static TypesafeMap.Key create(@NonNull String name, @NonNull Class type) { + return TypesafeMap.Key.getOrCreate(() -> Launcher.INSTANCE.blackboard(), name, type).get(); } - private static Map blackboard = new HashMap<>(); + public static final TypesafeMap.Key ORIGINAL_ARGUMENTS = create("orion.launch.arguments", List.class); + public static final TypesafeMap.Key LAUNCH_TARGET = create("orion.launch.target", String.class); + public static final TypesafeMap.Key LIBRARIES_PATH = create("orion.path.libraries", Path.class); + public static final TypesafeMap.Key MODS_PATH = create("orion.path.mods", Path.class); + public static final TypesafeMap.Key MOD_CONFIGS_PATH = create("orion.path.modconfigs", Path.class); - public static void setBlackboard(@NotNull Map blackboard) { - if(!BlackboardKey.blackboard.isEmpty()) { - blackboard.putAll(BlackboardKey.blackboard); - } - BlackboardKey.blackboard = blackboard; - } - - @NotNull + @NonNull @SuppressWarnings("unchecked") - public static T get(@NotNull BlackboardKey key) { - if(key.initializer != null) - return (T) getOr(key, key.initializer); - return actualGet(key); - } - - @NotNull - public static T getOr(@NotNull BlackboardKey key, @NotNull Supplier def) { - try { - return actualGet(key); - } catch (NullPointerException e) { - T value = requireNonNull(def.get(), "Supplier should not return null!"); - set(key, value); - return value; - } + public static T get(TypesafeMap.@NonNull Key key) { + return Launcher.INSTANCE.blackboard().get(key).orElseThrow(() -> new IllegalStateException("Key '" + key.name() + "' is not set")); } - public static void set(@NotNull BlackboardKey key, @NotNull T value) { - if(blackboard.containsKey(key.key) && !key.mutable) - throw new IllegalArgumentException("Key " + key.key + " is not mutable"); - blackboard.put(key.key, requireNonNull(key.type.cast(value), "Value is null")); + @NonNull + public static T getOr(TypesafeMap.@NonNull Key key, @NonNull Supplier def) { + return Launcher.INSTANCE.blackboard().computeIfAbsent(key, (k) -> requireNonNull(def.get(), "Value is null")); } - public static void unset(@NotNull BlackboardKey key) { - if(!key.mutable) throw new IllegalArgumentException("Key " + key.key + " is not mutable"); - blackboard.remove(key.key); - } - - @SuppressWarnings("unchecked") - private static T actualGet(@NotNull BlackboardKey key) { - Object value = requireNonNull(blackboard.get(key.key), "No value in blackboard with key " + key.key); - return (T) key.type.cast(value); + public static void set(TypesafeMap.@NonNull Key key, @NonNull T value) { + getOr(key, () -> value); } -} +} \ No newline at end of file diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/LauncherService.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/LauncherService.java index a3cf5e3..835d43c 100644 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/LauncherService.java +++ b/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/LauncherService.java @@ -26,7 +26,7 @@ package eu.mikroskeem.orion.core.launcher; import eu.mikroskeem.orion.api.bytecode.OrionTransformer; -import org.jetbrains.annotations.NotNull; +import org.checkerframework.checker.nullness.qual.NonNull; import java.net.URL; import java.util.Map; @@ -36,16 +36,16 @@ * @author Mark Vainomaa */ public interface LauncherService { - @NotNull + @NonNull Map getBlackBoard(); - void registerTransformer(@NotNull Class transformer); + void registerTransformer(@NonNull Class transformer); - @NotNull + @NonNull Set getClassLoaderExclusions(); - @NotNull + @NonNull ClassLoader getClassLoader(); - void addURLToClassLoader(@NotNull URL url); + void addURLToClassLoader(@NonNull URL url); } diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/ClassTransformerConverter.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/ClassTransformerConverter.java deleted file mode 100644 index f5cca6a..0000000 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/ClassTransformerConverter.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * This file is part of project Orion, licensed under the MIT License (MIT). - * - * Copyright (c) 2017-2020 Mark Vainomaa - * Copyright (c) Contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package eu.mikroskeem.orion.core.launcher.legacylauncher; - -import eu.mikroskeem.orion.api.bytecode.OrionTransformer; -import eu.mikroskeem.shuriken.instrumentation.ClassLoaderTools; -import net.minecraft.launchwrapper.IClassTransformer; -import net.minecraft.launchwrapper.Launch; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.ClassNode; - -import java.util.Arrays; -import java.util.concurrent.atomic.AtomicInteger; - -import static eu.mikroskeem.shuriken.common.streams.ByteArrays.fromInputStream; -import static java.util.Objects.requireNonNull; -import static org.objectweb.asm.Opcodes.INVOKESPECIAL; -import static org.objectweb.asm.Opcodes.NEW; - -/** - * Wraps Orion transformer into LegacyLauncher-compatible transformer - * - * @author Mark Vainomaa - */ -final class ClassTransformerConverter { - private final static Logger log = LogManager.getLogger("ClassTransformerConverter"); - - private final static AtomicInteger COUNTER = new AtomicInteger(0); - private final static byte[] TW_DATA; - private final static Type TW_TYPE = Type.getType(TransformerWrapper.class); - private final static Type DT_TYPE = Type.getType(DummyTransformer.class); - - @NotNull - @SuppressWarnings("unchecked") - static Class convert(@NotNull Class transformer) { - if(IClassTransformer.class.isAssignableFrom(transformer)) - return (Class) transformer; /* no-op */ - - // Orion transformer name - String rawTransformerName = transformer.getName().replace('.', '/'); - - // New wrapper class name - String newWrapperName = getNewName(transformer); - - // Debug log - log.debug("Wrapping transformer class '{}' to '{}'", transformer.getName(), newWrapperName); - - // Start generating new TransformerWrapper - ClassReader cr = new ClassReader(TW_DATA); - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); - ClassNode cn = new ClassNode(); - cr.accept(cn, 0); - - cn.accept(new WrapperGenerator(cw, TW_TYPE.getInternalName(), newWrapperName.replace('.', '/'), rawTransformerName)); - - return requireNonNull((Class) ClassLoaderTools.defineClass(Launch.classLoader, newWrapperName, cw.toByteArray())); - } - - private static String getNewName(@NotNull Class clazz) { - String name = clazz.getName(); - return ClassTransformerConverter.class.getName() - .concat("$") - .concat("" + COUNTER.getAndIncrement()) - .concat("$") - .concat(name.substring(name.lastIndexOf('.') + 1)); - } - - static class WrapperGenerator extends ClassVisitor { - private final String oldName; - private final String newName; - private final String transformerName; - - WrapperGenerator(ClassVisitor cv, String oldName, String newName, String transformerName) { - super(Opcodes.ASM5, cv); - this.oldName = oldName; - this.newName = newName; - this.transformerName = transformerName; - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - if(oldName.equals(name)) name = newName; - super.visit(version, access, name, signature, superName, interfaces); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - MethodRemapper mr = new MethodRemapper(this, super.visitMethod(access, name, desc, signature, exceptions)); - if("".equals(name) && desc.equals("()V")) { - return new InitTransformer(this, mr, transformerName); - } - return mr; - } - - @Override - public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { - if(oldName.equals(name)) name = newName; - return super.visitField(access, name, desc, signature, value); - } - } - - static class MethodRemapper extends MethodVisitor { - private final WrapperGenerator sr; - - MethodRemapper(WrapperGenerator sr, MethodVisitor mv) { - super(Opcodes.ASM5, mv); - this.sr = sr; - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - if(sr.oldName.equals(owner)) owner = sr.newName; - super.visitMethodInsn(opcode, owner, name, desc, itf); - } - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String desc) { - if(sr.oldName.equals(owner)) owner = sr.newName; - super.visitFieldInsn(opcode, owner, name, desc); - } - } - - static class InitTransformer extends MethodVisitor { - private final WrapperGenerator sr; - private final String transformerName; - - InitTransformer(WrapperGenerator sr, MethodVisitor mv, String transformerName) { - super(Opcodes.ASM5, mv); - this.sr = sr; - this.transformerName = transformerName; - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - if(opcode == INVOKESPECIAL && owner.equals(DT_TYPE.getInternalName())) { - owner = transformerName; - } - super.visitMethodInsn(opcode, owner, name, desc, itf); - } - - @Override - public void visitTypeInsn(int opcode, String type) { - if(opcode == NEW && DT_TYPE.getInternalName().equals(type)) { - type = transformerName; - } - super.visitTypeInsn(opcode, type); - } - } - - static { - TW_DATA = fromInputStream(TransformerWrapper.class.getResourceAsStream('/' + - TransformerWrapper.class.getName().replace('.', '/').concat(".class") - )); - } -} diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/DummyTransformer.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/DummyTransformer.java deleted file mode 100644 index a613aa4..0000000 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/DummyTransformer.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of project Orion, licensed under the MIT License (MIT). - * - * Copyright (c) 2017-2020 Mark Vainomaa - * Copyright (c) Contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package eu.mikroskeem.orion.core.launcher.legacylauncher; - -import eu.mikroskeem.orion.api.bytecode.OrionTransformer; - -/** - * Dummy placeholder to generate copies of {@link TransformerWrapper} safely - * - * @author Mark Vainomaa - */ -public class DummyTransformer implements OrionTransformer { - @Override - public byte[] transformClass(byte[] source, String className, String remappedClassName) { - return new byte[0]; - } -} diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/LegacyLauncherService.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/LegacyLauncherService.java deleted file mode 100644 index a66ca96..0000000 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/LegacyLauncherService.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of project Orion, licensed under the MIT License (MIT). - * - * Copyright (c) 2017-2020 Mark Vainomaa - * Copyright (c) Contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package eu.mikroskeem.orion.core.launcher.legacylauncher; - -import eu.mikroskeem.orion.api.bytecode.OrionTransformer; -import eu.mikroskeem.orion.core.launcher.AbstractLauncherService; -import net.minecraft.launchwrapper.IClassTransformer; -import net.minecraft.launchwrapper.Launch; -import org.jetbrains.annotations.NotNull; - -import java.net.URL; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -public final class LegacyLauncherService extends AbstractLauncherService { - private Map, Class> convertedTransformers = new HashMap<>(); - - @NotNull - @Override - public Map getBlackBoard() { - return Launch.blackboard; - } - - @Override - public void registerTransformer(@NotNull Class transformer) { - Launch.classLoader.registerTransformer( - convertedTransformers.computeIfAbsent(transformer, ClassTransformerConverter::convert).getName() - ); - } - - @NotNull - @Override - public Set getClassLoaderExclusions() { - return Launch.classLoader.getClassLoaderExclusions(); - } - - @Override - @NotNull - public ClassLoader getClassLoader() { - return Launch.classLoader; - } - - @Override - public void addURLToClassLoader(@NotNull URL url) { - Launch.classLoader.addURL(url); - } -} diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/OrionTweakClass.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/OrionTweakClass.java index b7f76d9..2bfb4f1 100644 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/OrionTweakClass.java +++ b/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/OrionTweakClass.java @@ -31,7 +31,7 @@ import net.minecraft.launchwrapper.LaunchClassLoader; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; +import org.checkerframework.checker.nullness.qual.NonNull; import java.io.IOException; import java.util.List; @@ -48,7 +48,7 @@ public final class OrionTweakClass implements ITweaker { private static final Logger logger = LogManager.getLogger("OrionTweakClass"); @Override - public void injectIntoClassLoader(@NotNull LaunchClassLoader classLoader) { + public void injectIntoClassLoader(@NonNull LaunchClassLoader classLoader) { /* Set up Orion core */ OrionCore.INSTANCE.setupCore(); @@ -63,13 +63,13 @@ public void injectIntoClassLoader(@NotNull LaunchClassLoader classLoader) { OrionCore.INSTANCE.setupTransformers(); } - @NotNull + @NonNull @Override public String getLaunchTarget() { return BlackboardKey.get(BlackboardKey.LAUNCH_TARGET); } - @NotNull + @NonNull @Override public String[] getLaunchArguments() { List arguments = BlackboardKey.get(BlackboardKey.ORIGINAL_ARGUMENTS); @@ -77,5 +77,5 @@ public String[] getLaunchArguments() { } @Override - public void acceptOptions(@NotNull List args) {} + public void acceptOptions(@NonNull List args) {} } diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/TransformerWrapper.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/TransformerWrapper.java deleted file mode 100644 index cfea915..0000000 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/legacylauncher/TransformerWrapper.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of project Orion, licensed under the MIT License (MIT). - * - * Copyright (c) 2017-2020 Mark Vainomaa - * Copyright (c) Contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package eu.mikroskeem.orion.core.launcher.legacylauncher; - -import eu.mikroskeem.orion.api.bytecode.OrionTransformer; -import net.minecraft.launchwrapper.IClassTransformer; - -/** - * Orion Transformer wrapper used in LegacyLauncher - * - * @author Mark Vainomaa - */ -public final class TransformerWrapper implements IClassTransformer { - private final OrionTransformer delegate; - - public TransformerWrapper() { - this.delegate = new DummyTransformer(); - } - - @Override - public byte[] transform(String name, String transformedName, byte[] classData) { - return delegate.transformClass(classData, name, transformedName); - } -} diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/modlauncher/OrionLaunchHandlerService.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/modlauncher/OrionLaunchHandlerService.java new file mode 100644 index 0000000..de796f8 --- /dev/null +++ b/OrionCore/src/main/java/eu/mikroskeem/orion/core/launcher/modlauncher/OrionLaunchHandlerService.java @@ -0,0 +1,24 @@ +package eu.mikroskeem.orion.core.launcher.modlauncher; + +import cpw.mods.modlauncher.api.ILaunchHandlerService; +import cpw.mods.modlauncher.api.ITransformingClassLoader; +import cpw.mods.modlauncher.api.ITransformingClassLoaderBuilder; + +import java.util.concurrent.Callable; + +public final class OrionLaunchHandlerService implements ILaunchHandlerService { + @Override + public String name() { + return "orion"; + } + + @Override + public void configureTransformationClassLoader(ITransformingClassLoaderBuilder builder) { + + } + + @Override + public Callable launchService(String[] arguments, ITransformingClassLoader launchClassLoader) { + return null; + } +} diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/AssetManagerImpl.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/AssetManagerImpl.java index e1381f4..beffc34 100644 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/AssetManagerImpl.java +++ b/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/AssetManagerImpl.java @@ -28,11 +28,11 @@ import eu.mikroskeem.orion.api.OrionAPI; import eu.mikroskeem.orion.api.asset.AssetManager; import eu.mikroskeem.orion.api.mod.ModInfo; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; -import java.util.Map; import java.util.HashMap; +import java.util.Map; /** * @author Mark Vainomaa @@ -40,20 +40,20 @@ public final class AssetManagerImpl implements AssetManager.ForMod { private final Map assetManagers = new HashMap<>(); - @NotNull + @NonNull @Override - public AssetManager forMod(@NotNull ModInfo modInfo) { + public AssetManager forMod(@NonNull ModInfo modInfo) { return assetManagers.computeIfAbsent(modInfo.getId(), ModAssetManager::new); } @Override @Nullable - public AssetManager forMod(@NotNull String modId) { + public AssetManager forMod(@NonNull String modId) { ModInfo modInfo = OrionAPI.getInstance().getMod(modId); return modInfo != null ? forMod(modInfo) : null; } - public AssetManager createExplicitly(@NotNull String modId) { + public AssetManager createExplicitly(@NonNull String modId) { ModAssetManager assetManager = new ModAssetManager(modId); assetManagers.put(modId, assetManager); return assetManager; diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/ModAssetManager.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/ModAssetManager.java index b41ec29..439ece6 100644 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/ModAssetManager.java +++ b/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/ModAssetManager.java @@ -28,8 +28,8 @@ import eu.mikroskeem.orion.api.asset.AssetManager; import eu.mikroskeem.orion.core.launcher.BlackboardKey; import eu.mikroskeem.orion.core.launcher.LauncherService; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import java.io.IOException; import java.io.InputStream; @@ -48,17 +48,17 @@ final class ModAssetManager implements AssetManager { private final String modAssetPath; - ModAssetManager(@NotNull String modId) { + ModAssetManager(@NonNull String modId) { this.modAssetPath = String.format(PATH_FORMAT, modId); } - @NotNull - private String formatAssetPath(@NotNull String assetPath) { + @NonNull + private String formatAssetPath(@NonNull String assetPath) { return Paths.get(modAssetPath, assetPath).toString(); } - @NotNull - private InputStream getAssetInternal(@NotNull String assetPath) throws IOException { + @NonNull + private InputStream getAssetInternal(@NonNull String assetPath) throws IOException { String theAssetPath = formatAssetPath(assetPath); ClassLoader loader = BlackboardKey.get(BlackboardKey.LAUNCHER_SERVICE).getClassLoader(); @@ -71,7 +71,7 @@ private InputStream getAssetInternal(@NotNull String assetPath) throws IOExcepti @Nullable @Override - public InputStream getAsset(@NotNull String assetPath) { + public InputStream getAsset(@NonNull String assetPath) { try { return getAssetInternal(assetPath); } @@ -80,12 +80,12 @@ public InputStream getAsset(@NotNull String assetPath) { } @Override - public void copyAsset(@NotNull Path destination, @NotNull String assetPath) throws UncheckedIOException { + public void copyAsset(@NonNull Path destination, @NonNull String assetPath) throws UncheckedIOException { copyAsset(destination, assetPath, false); } @Override - public void copyAsset(@NotNull Path destination, @NotNull String assetPath, boolean overwriteExisting) throws UncheckedIOException { + public void copyAsset(@NonNull Path destination, @NonNull String assetPath, boolean overwriteExisting) throws UncheckedIOException { try { if(Files.exists(destination) && !overwriteExisting) return; diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/ModClassVisitor.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/ModClassVisitor.java index 6c091e7..2c92c79 100644 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/ModClassVisitor.java +++ b/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/ModClassVisitor.java @@ -28,7 +28,7 @@ import eu.mikroskeem.orion.api.annotations.OrionMod; import eu.mikroskeem.orion.api.configuration.DummyConfiguration; import eu.mikroskeem.orion.api.mod.ModInfo; -import org.jetbrains.annotations.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; @@ -51,11 +51,12 @@ public final class ModClassVisitor extends ClassVisitor { private final static Type ORIONMOD_ANNOTATION = Type.getType(OrionMod.class); private ModClassVisitor() { - super(Opcodes.ASM5); + super(Opcodes.ASM8); } /** Mod annotation visitor instance */ - @Nullable private ModAnnotationVisitor modAnnotationVisitor; + @Nullable + private ModAnnotationVisitor modAnnotationVisitor; /** Visitable class name */ @Nullable private String className; diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/ModContainer.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/ModContainer.java index aac2e66..adbf0a2 100644 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/ModContainer.java +++ b/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/ModContainer.java @@ -29,9 +29,7 @@ import com.google.inject.Injector; import eu.mikroskeem.orion.api.events.ModConstructEvent; import eu.mikroskeem.orion.api.mod.ModInfo; -import eu.mikroskeem.shuriken.reflect.ClassWrapper; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; +import org.checkerframework.checker.nullness.qual.NonNull; /** @@ -40,13 +38,14 @@ * @author Mark Vainomaa */ public final class ModContainer { - private final ClassWrapper modClass; + private final Class modClass; private final ModInfo modInfo; private final Injector injector; private final EventBus eventBus; + private T instance; - public ModContainer(@NotNull ClassWrapper modClass, @NotNull ModInfo modInfo, - @NotNull Injector injector, @NotNull EventBus eventBus) { + public ModContainer(@NonNull Class modClass, @NonNull ModInfo modInfo, + @NonNull Injector injector, @NonNull EventBus eventBus) { this.modClass = modClass; this.modInfo = modInfo; this.injector = injector; @@ -57,9 +56,8 @@ public ModContainer(@NotNull ClassWrapper modClass, @NotNull ModInfo modInfo, * Constructs mod's main class */ public void construct() { - if(modClass.getClassInstance() != null) throw new IllegalStateException("Mod is already initialized!"); - T instance = injector.getInstance(modClass.getWrappedClass()); - modClass.setClassInstance(instance); + if(instance != null) throw new IllegalStateException("Mod is already initialized!"); + this.instance = injector.getInstance(modClass); eventBus.register(instance); eventBus.post(new ModConstructEvent()); } @@ -69,8 +67,7 @@ public void construct() { * * @return instance of {@link ModInfo} */ - @NotNull - @Contract(pure = true) + @NonNull public ModInfo getModInfo() { return modInfo; } @@ -80,8 +77,7 @@ public ModInfo getModInfo() { * * @return {@link EventBus} of mod */ - @NotNull - @Contract(pure = true) + @NonNull public EventBus getEventBus() { return eventBus; } diff --git a/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/OrionModInfo.java b/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/OrionModInfo.java index 4a70384..f021728 100644 --- a/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/OrionModInfo.java +++ b/OrionCore/src/main/java/eu/mikroskeem/orion/core/mod/OrionModInfo.java @@ -28,9 +28,7 @@ import eu.mikroskeem.orion.api.mod.ModInfo; import eu.mikroskeem.orion.core.launcher.BlackboardKey; import eu.mikroskeem.orion.core.launcher.LauncherService; -import eu.mikroskeem.shuriken.common.SneakyThrow; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; +import org.checkerframework.checker.nullness.qual.NonNull; import java.util.List; import java.util.Objects; @@ -48,40 +46,34 @@ final class OrionModInfo implements ModInfo { private String configClassName; private Class configClass = null; - @NotNull - @Contract(pure = true) + @NonNull public String getId() { return id; } - @Contract("null -> fail") - void setId(@NotNull String id) { + void setId(@NonNull String id) { this.id = Objects.requireNonNull(id, "Id cannot be null!"); } - @NotNull - @Contract(pure = true) + @NonNull public String getClassName() { return className; } - @Contract("null -> fail") - void setClassName(@NotNull String className) { + void setClassName(@NonNull String className) { this.className = Objects.requireNonNull(className, "Class name cannot be null!"); } - @NotNull - @Contract(pure = true) - public List getDependencies() { + @NonNull + public List<@NonNull String> getDependencies() { return dependencies; } - @Contract("null -> fail") - void setDependencies(@NotNull List dependencies) { + void setDependencies(@NonNull List<@NonNull String> dependencies) { this.dependencies = Objects.requireNonNull(dependencies, "Dependencies cannot be null!"); } - @NotNull + @NonNull @Override public Class getConfigClass() { if(configClass == null) { @@ -89,13 +81,13 @@ public Class getConfigClass() { try { configClass = Class.forName(configClassName, true, loader); } catch (ClassNotFoundException e) { - SneakyThrow.throwException(new ClassNotFoundException("Failed to find specified configuration class!", e)); + throw new ClassNotFoundException("Failed to find specified configuration class!", e); } } return configClass; } - void setConfigClass(@NotNull String configClass) { + void setConfigClass(@NonNull String configClass) { this.configClassName = Objects.requireNonNull(configClass, "Configuration class name cannot be null!"); } diff --git a/OrionCore/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService b/OrionCore/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService new file mode 100644 index 0000000..e69de29 diff --git a/OrionLauncher/build.gradle b/OrionLauncher/build.gradle deleted file mode 100644 index a2aa172..0000000 --- a/OrionLauncher/build.gradle +++ /dev/null @@ -1,68 +0,0 @@ -dependencies { - compile(project(':OrionCore')) - - compile group: 'org.ow2.asm', name: 'asm-debug-all', version: '5.2' -} - -apply plugin: "net.kyori.blossom" - -compileJava { - options.compilerArgs += "-proc:none" -} - -jar { - manifest { - attributes( - "Main-Class": "eu.mikroskeem.orion.launcher.Bootstrap" - ) - } -} - -shadowJar { - dependencies { - // Tools - include dependency('org.ow2.asm:asm-debug-all') - include dependency('eu.mikroskeem:shuriken.common') - include dependency('eu.mikroskeem:shuriken.instrumentation') - include dependency('eu.mikroskeem:shuriken.reflect') - - // Dependency downloader - include dependency('eu.mikroskeem:picomaven') - include dependency('com.squareup.okhttp3:okhttp') - include dependency('com.squareup.okio:okio') - include dependency('org.apache.maven:maven-repository-metadata') - include dependency('org.codehaus.plexus:plexus-utils') - - // Orion - include project(':OrionAPI') - include project(':OrionCore') - } - - // PicoMaven & its dependencies - relocate 'eu.mikroskeem.picomaven', 'eu.mikroskeem.orion.internal.picomaven' - relocate 'org.codehaus.plexus.util', 'eu.mikroskeem.orion.internal.picomaven.plexusutil' - relocate 'org.apache.maven.artifact.repository.metadata', 'eu.mikroskeem.orion.internal.picomaven.mavenmetadata' - relocate 'okhttp3', 'eu.mikroskeem.orion.internal.picomaven.okhttp3' - relocate 'okio', 'eu.mikroskeem.orion.internal.picomaven.okio' - - relocate 'org.objectweb.asm', 'eu.mikroskeem.orion.internal.asm' - - // Exclude unneeded files - exclude 'licenses/**' - exclude 'publicsuffixes.gz' - exclude 'META-INF/maven/**' - - // Generate deps.txt - from collectDependencies -} - -blossom { - def constants = 'src/main/java/eu/mikroskeem/orion/launcher/VersionInfo.java' - replaceToken '@version@', version, constants - replaceToken '@gitBranch@', rootProject.ext.get("gitBranch"), constants - replaceToken '@gitCommitId@', rootProject.ext.get("gitCommitId"), constants - replaceToken '@gitRepository@', rootProject.ext.get("gitRepository"), constants -} - -compileJava.dependsOn 'blossomSourceReplacementJava' // TODO: might break, keep an eye on it. -build.dependsOn shadowJar diff --git a/OrionLauncher/build.gradle.kts b/OrionLauncher/build.gradle.kts new file mode 100644 index 0000000..8ea3765 --- /dev/null +++ b/OrionLauncher/build.gradle.kts @@ -0,0 +1,31 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +plugins { + java + id("com.github.johnrengelman.shadow") +} + +dependencies { + implementation(project(":OrionCore")) +} + +val compileJava by tasks.getting(JavaCompile::class) { + options.compilerArgs.add("-proc:none") +} + +val jar by tasks.getting(Jar::class) { + manifest { + attributes( + "Main-Class" to "eu.mikroskeem.orion.launcher.Bootstrap" + ) + } +} + +val shadowJar by tasks.getting(ShadowJar::class) { + // Exclude unneeded files + exclude("licenses/**") + exclude("publicsuffixes.gz") + exclude("META-INF/maven/**") +} + +tasks["build"].dependsOn(shadowJar) diff --git a/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/Bootstrap.java b/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/Bootstrap.java index d99414b..f0369b7 100644 --- a/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/Bootstrap.java +++ b/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/Bootstrap.java @@ -25,26 +25,15 @@ package eu.mikroskeem.orion.launcher; -import eu.mikroskeem.orion.core.launcher.AbstractLauncherService; +import cpw.mods.modlauncher.Launcher; import eu.mikroskeem.orion.core.launcher.BlackboardKey; -import eu.mikroskeem.orion.core.launcher.legacylauncher.LegacyLauncherService; import eu.mikroskeem.orion.core.launcher.legacylauncher.OrionTweakClass; -import eu.mikroskeem.picomaven.Dependency; -import eu.mikroskeem.picomaven.DownloaderCallbacks; -import eu.mikroskeem.picomaven.PicoMaven; -import eu.mikroskeem.shuriken.common.ToURL; -import eu.mikroskeem.shuriken.instrumentation.ClassLoaderTools; -import net.minecraft.launchwrapper.Launch; -import okhttp3.OkHttpClient; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; +import org.checkerframework.checker.nullness.qual.NonNull; -import java.io.BufferedReader; +import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URI; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; @@ -54,7 +43,6 @@ import java.util.Collections; import java.util.List; import java.util.Properties; -import java.util.concurrent.Executors; import java.util.function.Supplier; import java.util.stream.Stream; @@ -80,13 +68,13 @@ public final class Bootstrap { } } - @NotNull - private static String getProperty(@NotNull String key, @NotNull String def) { + @NonNull + private static String getProperty(@NonNull String key, @NonNull String def) { return getProperty(key, () -> def); } - @NotNull - private static String getProperty(@NotNull String key, @NotNull Supplier def) { + @NonNull + private static String getProperty(@NonNull String key, @NonNull Supplier def) { String value = System.getProperty(key); if (value == null || value.isEmpty()) { value = orionProperties.getProperty(key); @@ -97,7 +85,7 @@ private static String getProperty(@NotNull String key, @NotNull Supplier return value; } - private static boolean getBoolean(@NotNull String key) { + private static boolean getBoolean(@NonNull String key) { boolean result = false; try { result = Boolean.parseBoolean(orionProperties.getProperty(key, System.getProperty(key))); @@ -143,14 +131,7 @@ private static boolean getBoolean(@NotNull String key) { //private final static Boolean DONT_DIE_ON_MOD_LOAD_ERROR = getBoolean("orion.dontDieOnModLoadError"); public static void main(String... args) throws Exception { - if (!System.getProperty("java.version", "").startsWith("1.8.0")) { - System.out.println("Orion runs only on Java 8 currently, sorry."); - System.exit(1); - } - - ClassLoader cl = ClassLoader.getSystemClassLoader(); - ClassLoaderTools.URLClassLoaderTools uclTool = new ClassLoaderTools.URLClassLoaderTools(cl); - OkHttpClient httpClient = new OkHttpClient(); + ClassLoader classLoader = ClassLoader.getSystemClassLoader(); /* Load preload libraries, if allowed */ if(PRELOAD_ALLOWED) { @@ -162,15 +143,14 @@ public static void main(String... args) throws Exception { file.filter(Files::isRegularFile) .filter(f -> f.toString().endsWith(".jar")) .peek(f -> System.out.println("Preloading library: " + f)) - .map(ToURL::to) - .forEach(uclTool::addURL); + .forEach(path -> Utils.addURLToClassLoader(classLoader, path)); } } + /* Set up Paperclip manager */ - PaperclipManager paperclipManager = new PaperclipManager( - new URL(PAPERCLIP_URL), PAPERCLIP_JAR, - PAPER_SERVER_JAR, uclTool, httpClient); + PaperclipManager paperclipManager = new PaperclipManager(new URL(PAPERCLIP_URL), + PAPERCLIP_JAR, PAPER_SERVER_JAR, classLoader); /* Set up Paper server */ if(CHECK_FOR_SERVER_JAR_INSTEAD) { @@ -186,84 +166,18 @@ public static void main(String... args) throws Exception { /* Logger can be set up now */ Logger log = LogManager.getLogger("OrionBootstrap"); - log.info("Orion Launcher version {} (git: {}/{})", - VersionInfo.VERSION, - VersionInfo.GIT_BRANCH, - VersionInfo.GIT_COMMIT_ID - ); - - /* Maven repositories */ - List repositories = Arrays.asList( - URI.create("https://repo.maven.apache.org/maven2"), /* Central */ - URI.create("https://repo.wut.ee/repository/mikroskeem-repo"), /* Own repository */ - URI.create("https://repo.spongepowered.org/maven"), /* SpongePowered repository */ - URI.create("https://oss.sonatype.org/content/groups/public"), /* OSS Sonatype */ - URI.create("http://jcenter.bintray.com") - ); - - /* Download dependencies */ - InputStream depsStream = Bootstrap.class.getClassLoader().getResourceAsStream("deps.txt"); - if(depsStream != null) { - List dependencies = new ArrayList<>(); - try(BufferedReader depsReader = new BufferedReader(new InputStreamReader(depsStream))) { - String line; - while((line = depsReader.readLine()) != null) { - log.debug("Required dependency: {}", line); - dependencies.add(Dependency.fromGradle(line)); - } - } - - PicoMaven.Builder picoMavenBuilder = new PicoMaven.Builder() - .withOkHttpClient(httpClient) - .withDownloadPath(LIBRARIES_PATH) - .withRepositories(repositories) - .withDependencies(dependencies) - .withExecutorService(Executors.newWorkStealingPool()) - .shouldCloseExecutorService(true) - .withDebugLoggerImpl((format, contents) -> log.debug(format.replace("%s", "{}"), contents)) - .withDownloaderCallbacks(new DownloaderCallbacks() { - @Override - public void onSuccess(@NotNull Dependency dependency, @NotNull Path dependencyPath) { - log.info("{} download succeeded!", dependency); - } - - @Override - public void onFailure(@NotNull Dependency dependency, @NotNull Exception exception) { - log.warn("{} download failed! {}", dependency, exception); - } - }); - - log.info("Setting up Orion dependencies..."); - try(PicoMaven picoMaven = picoMavenBuilder.build()) { - List downloadedLibraries = picoMaven.downloadAll(); - if(downloadedLibraries.size() != dependencies.size()) - throw new IllegalStateException("Could not download all dependencies!"); - - downloadedLibraries.stream().map(ToURL::to).forEach(uclTool::addURL); - } - uclTool.resetCache(); - } else { - log.debug("deps.txt resource was not found, assuming no dependencies are needed on runtime."); - } /* Do tricks with command line arguments */ List arguments = Arrays.asList(args); List tweakArgs = new ArrayList<>(arguments); - if(!DONT_APPEND_TWEAK_CLASS_ARGUMENT) { - tweakArgs.add("--tweakClass"); - tweakArgs.add("eu.mikroskeem.orion.core.launcher.legacylauncher.OrionTweakClass"); + if (!DONT_APPEND_TWEAK_CLASS_ARGUMENT) { + tweakArgs.add("--launchTarget"); + tweakArgs.add("orion"); } - /* Set up LegacyLauncher */ - log.debug("Setting up LegacyLauncher platform"); - BlackboardKey.getOr(BlackboardKey.LAUNCHER_SERVICE, () -> { - AbstractLauncherService launcherService = new LegacyLauncherService(); - BlackboardKey.setBlackboard(launcherService.getBlackBoard()); - return launcherService; - }); - - /* Populate blackboard */ + /* Set up ModLauncher */ + log.debug("Setting up ModLauncher platform"); BlackboardKey.set(BlackboardKey.ORIGINAL_ARGUMENTS, Collections.unmodifiableList(arguments)); BlackboardKey.set(BlackboardKey.LAUNCH_TARGET, launchTarget); BlackboardKey.set(BlackboardKey.MODS_PATH, MODS_PATH); @@ -271,7 +185,7 @@ public void onFailure(@NotNull Dependency dependency, @NotNull Exception excepti BlackboardKey.set(BlackboardKey.LIBRARIES_PATH, LIBRARIES_PATH); /* Launch LegacyLauncher */ - log.info("Starting LegacyLauncher with arguments {}", tweakArgs); - Launch.main(tweakArgs.toArray(new String[0])); + log.info("Starting ModLauncher with arguments {}", tweakArgs); + Launcher.main(tweakArgs.toArray(new String[0])); } } diff --git a/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/GithubChecker.java b/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/GithubChecker.java deleted file mode 100644 index fb5a84d..0000000 --- a/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/GithubChecker.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This file is part of project Orion, licensed under the MIT License (MIT). - * - * Copyright (c) 2017-2020 Mark Vainomaa - * Copyright (c) Contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package eu.mikroskeem.orion.launcher; - -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; -import java.io.Reader; -import java.util.Properties; - -import static java.util.Objects.requireNonNull; - -/** - * @author Mark Vainomaa - */ -final class GithubChecker { - private final Logger log; - private final Properties ver; - private final OkHttpClient client; - - GithubChecker(@NotNull Logger log, @NotNull Properties ver, @NotNull OkHttpClient client) { - this.log = log; - this.ver = ver; - this.client = client; - } - - void check() { - HttpUrl url = HttpUrl.parse("https://api.github.com/repos/" + - ver.getProperty("gitRepository") + - "/compare/" + - ver.getProperty("gitBranch") + - "..." + - ver.getProperty("gitCommitId")); - Request request = new Request.Builder() - .get() - .url(requireNonNull(url)) - .build(); - client.newCall(request).enqueue(new Callback() { - @Override - public void onFailure(Call call, IOException e) { - log.warn("Failed to obtain latest version info from GitHub!", e); - } - - @Override - public void onResponse(Call call, Response response) throws IOException { - if(response.isSuccessful()) { - //noinspection ConstantConditions - try(Reader content = response.body().charStream()) { - JsonObject root = new JsonParser().parse(content).getAsJsonObject(); - boolean isBehind = root.get("status").getAsString().equals("behind"); - if(isBehind) { - log.info("This Orion version is behind by {} commits!", root.get("behind_by").getAsInt()); - } else { - log.info("This Orion version is up to date!"); - } - } - } else { - //noinspection ConstantConditions - if(response.body().contentType().toString().contains("application/json")) { - //noinspection ConstantConditions - try(Reader content = response.body().charStream()) { - JsonObject root = new JsonParser().parse(content).getAsJsonObject(); - String message = root.get("message").getAsString(); - if(message.equals("Not Found")) { - log.warn("Commit id {} not found, failed to obtain version information", - ver.getProperty("gitCommitId")); - return; - } else { - log.warn("Github response while trying to compare commits: {}", message); - return; - } - } - } - throw new IOException("HTTP code: " + response.code()); - } - } - }); - } -} \ No newline at end of file diff --git a/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/PaperclipManager.java b/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/PaperclipManager.java index a9f8584..750c8cf 100644 --- a/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/PaperclipManager.java +++ b/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/PaperclipManager.java @@ -25,17 +25,17 @@ package eu.mikroskeem.orion.launcher; -import eu.mikroskeem.shuriken.common.ToURL; -import eu.mikroskeem.shuriken.instrumentation.ClassLoaderTools; -import eu.mikroskeem.shuriken.reflect.Reflect; -import eu.mikroskeem.shuriken.reflect.wrappers.TypeWrapper; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import org.jetbrains.annotations.NotNull; +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.io.BufferedInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.HttpURLConnection; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Files; @@ -57,17 +57,15 @@ final class PaperclipManager { private final URL paperclipDownloadUrl; private final Path paperclipPath; private final Path serverPath; - private final ClassLoaderTools.URLClassLoaderTools uclTools; - private final OkHttpClient client; + private final ClassLoader classLoader; - PaperclipManager(@NotNull URL paperclipDownloadUrl, @NotNull Path paperclipPath, @NotNull Path serverPath, - @NotNull ClassLoaderTools.URLClassLoaderTools uclTools, @NotNull OkHttpClient httpClient) { + PaperclipManager(@NonNull URL paperclipDownloadUrl, @NonNull Path paperclipPath, + @NonNull Path serverPath, ClassLoader classLoader) { this.oldSecurityManager = System.getSecurityManager(); this.paperclipPath = paperclipPath; this.serverPath = serverPath; this.paperclipDownloadUrl = paperclipDownloadUrl; - this.uclTools = uclTools; - this.client = httpClient; + this.classLoader = classLoader; } /** @@ -82,12 +80,12 @@ boolean isServerAvailable() { /** * Sets up Orion Tweaker */ - @NotNull + @NonNull String setupServer() { if(!isServerAvailable()) throw new IllegalStateException("Paper server jar is not available! Check if '" + serverPath + "' is available."); /* Load server jar to system classloader */ - uclTools.addURL(ToURL.to(serverPath)); + Utils.addURLToClassLoader(classLoader, serverPath); /* Return server jar main class */ return requireNonNull(Utils.getMainClassFromJar(serverPath), "Failed to get server main class!"); @@ -100,17 +98,29 @@ void invoke() { /* Check if paperclip jar is present */ if(Files.notExists(paperclipPath)) { System.out.println("Downloading Paperclip..."); - Request request = new Request.Builder() - .url(paperclipDownloadUrl) - .get() - .build(); - try(Response response = client.newCall(request).execute()) { - if(response.code() != 200) + + try { + HttpURLConnection connection = + (HttpURLConnection) paperclipDownloadUrl.openConnection(); + + connection.addRequestProperty("User-Agent", "OrionMinecraft"); + + if (connection.getResponseCode() != 200) { throw new IOException(String.format("HTTP request to %s returned %s!%n", - paperclipDownloadUrl, response.cacheControl())); - Files.createDirectories(paperclipPath.getParent()); - //noinspection ConstantConditions - Files.copy(response.body().byteStream(), paperclipPath); + paperclipDownloadUrl, connection.getResponseMessage())); + } + + try (InputStream input = new BufferedInputStream(connection.getInputStream())) { + try (OutputStream output = new FileOutputStream(paperclipPath.toFile())) { + byte[] buffer = new byte[1024]; + int count; + while ((count = input.read(buffer)) != -1) { + output.write(buffer, 0, count); + } + } + } + + connection.disconnect(); } catch (IOException e) { throw new RuntimeException("Failed to download Paperclip, either download it yourself or try again later.", e); } @@ -120,13 +130,19 @@ void invoke() { System.out.println("Executing Paperclip... please wait"); try { System.setSecurityManager(new PaperclipExitCatcher()); - URLClassLoader ucl = new URLClassLoader(new URL[]{ToURL.to(paperclipPath)}); + URLClassLoader ucl = new URLClassLoader(new URL[]{paperclipPath.toUri().toURL()}); String paperclipTargetClass = Objects.requireNonNull(Utils.getMainClassFromJar(paperclipPath), "Failed to get Paperclip Main-Class from its manifest!"); System.setProperty("paperclip.patchonly", "true"); - Reflect.getClass(paperclipTargetClass, ucl) - .orElseThrow(() -> new RuntimeException("Failed to get class " + paperclipTargetClass)) - .invokeMethod("main", void.class, TypeWrapper.of(new String[0])); + + try { + Class clazz = Class.forName(paperclipTargetClass, true, ucl); + + Method method = clazz.getDeclaredMethod("main", String[].class); + method.invoke(null, new String[0]); + } catch (ClassNotFoundException exception) { + throw new RuntimeException("Failed to get class " + paperclipTargetClass); + } } catch (Throwable e) { if(!(e instanceof InvocationTargetException)) { throw new RuntimeException(e); @@ -157,7 +173,7 @@ class PaperclipExitException extends SecurityException { /** SecurityManager to catch Paperclip exit */ class PaperclipExitCatcher extends SecurityManager { @Override - public void checkPermission(@NotNull Permission perm) { + public void checkPermission(@NonNull Permission perm) { /* Check only exitVM, as this security manager needs to catch only System.exit(int) */ if(!perm.getName().startsWith("exitVM")) return; diff --git a/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/Utils.java b/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/Utils.java index 45548e7..0662514 100644 --- a/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/Utils.java +++ b/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/Utils.java @@ -25,10 +25,12 @@ package eu.mikroskeem.orion.launcher; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.util.jar.JarInputStream; @@ -39,11 +41,21 @@ */ final class Utils { @Nullable - static String getMainClassFromJar(@NotNull Path jarPath) { + static String getMainClassFromJar(@NonNull Path jarPath) { try(JarInputStream js = new JarInputStream(Files.newInputStream(jarPath))) { return js.getManifest().getMainAttributes().getValue("Main-Class"); } catch (IOException e) { throw new RuntimeException(e); } } + + static void addURLToClassLoader(@NonNull ClassLoader classLoader, Path path) { + try { + Method method = ClassLoader.class.getDeclaredMethod("addURL", URL.class); + method.setAccessible(true); + method.invoke(classLoader, path.toUri().toURL()); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } } diff --git a/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/VersionInfo.java b/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/VersionInfo.java deleted file mode 100644 index 699c93b..0000000 --- a/OrionLauncher/src/main/java/eu/mikroskeem/orion/launcher/VersionInfo.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of project Orion, licensed under the MIT License (MIT). - * - * Copyright (c) 2017-2020 Mark Vainomaa - * Copyright (c) Contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package eu.mikroskeem.orion.launcher; - -/** - * @author mark - */ -public final class VersionInfo { - private VersionInfo() {} - - public final static String VERSION = "@version@"; - public final static String GIT_BRANCH = "@gitBranch@"; - public final static String GIT_COMMIT_ID = "@gitCommitId@"; - public final static String GIT_REPOSITORY = "@gitRepository@"; -} diff --git a/build.gradle b/build.gradle deleted file mode 100644 index e95c070..0000000 --- a/build.gradle +++ /dev/null @@ -1,137 +0,0 @@ -// Buildscript configuration -buildscript { - repositories { - mavenLocal() - mavenCentral() - jcenter() - - maven { - name = 'gradle-plugins' - url = 'https://plugins.gradle.org/m2' - } - } - - dependencies { - classpath group: 'gradle.plugin.net.minecrell', name: 'licenser', version: minecrell_licenser_version - classpath group: 'com.github.jengelman.gradle.plugins', name: 'shadow', version: shadow_version - classpath group: 'org.ajoberstar', name: 'grgit', version: grgit_version - classpath group: 'gradle.plugin.net.kyori', name: 'blossom', version: blossom_version - } -} - -String obtainRepositoryPath(String url) { - if(url == null) return null - if(url.startsWith("ssh://") || url.startsWith("http")) { - def uri = URI.create url - return uri.path.substring(1).replace(".git", "") - } else if(url.matches("^[a-zA-Z0-9_\\-]+@[a-zA-Z0-9_\\-]+.[a-z]+:(.+?)")) { - return url.split(":", 2)[1].replace(".git", "") - } - return null -} - -def gitRepo = null - -try { - gitRepo = org.ajoberstar.grgit.Grgit.open(dir: ".") -} -catch (org.eclipse.jgit.errors.RepositoryNotFoundException ignored) {} - -project.ext.gitCommitId = gitRepo?.head()?.getAbbreviatedId(7) ?: "UNKNOWN" -project.ext.gitBranch = gitRepo?.branch?.current()?.name ?: "UNKNOWN" -project.ext.gitRepository = obtainRepositoryPath(gitRepo?.remote?.list()?.find { it.name == "origin" }?.url) ?: "UNKNOWN" - -// Subproject configurations -allprojects { - // Project information - group = 'eu.mikroskeem' - version = properties.version - description = properties.description - url = properties.url - - // Repositories - repositories { - mavenLocal() - mavenCentral() - - maven { - name = 'mikroskeem-repo' - url = 'https://repo.wut.ee/repository/mikroskeem-repo' - } - - maven { - name = 'destroystokyo-repo' - url = 'https://repo.destroystokyo.com/repository/maven-public' - } - - maven { - name = 'spongepowered-repo' - url = 'https://repo.spongepowered.org/maven' - } - } -} - -subprojects { - apply plugin: 'com.github.johnrengelman.shadow' - apply plugin: 'net.minecrell.licenser' - apply plugin: 'java' - - // Configurations - configurations { - downloadDep - - compile.extendsFrom downloadDep - } - - // Java compiler options - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - - // Licenser task - license { - header = rootProject.file('etc/HEADER') - ignoreFailures = false - include "**/*.java" - } - - java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - // downloadDep configuration collector - task collectDependencies { - subprojects { - inputs.file(configurations.downloadDep) - } - outputs.file(new File(temporaryDir, 'deps.txt')) - - doLast { - def outputFile = new File(temporaryDir, 'deps.txt') - def deps = [] as Set - rootProject.subprojects.each { subproject -> - subproject.configurations.downloadDep.resolvedConfiguration.resolvedArtifacts.each { dep -> - def depString = dep.id.componentIdentifier.toString() - def splitted = depString.split(':') - if(splitted.length > 3) { - depString = java.util.Arrays.copyOf(splitted, 3).join(":") - } - deps += depString - } - } - outputFile.createNewFile() - outputFile.withWriter { BufferedWriter writer -> - deps.each { - writer.writeLine it - } - } - } - } -} - -// Wrapper task -wrapper { - gradleVersion = gradle_version -} - -defaultTasks 'build' diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..c0714bd --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,55 @@ +plugins { + `java-library` + id("net.minecrell.licenser") version "0.4.1" + id("com.github.johnrengelman.shadow") version "5.2.0" apply false +} + +// Dependency versions +rootProject.extra["orion_at_version"] = "0.0.1-SNAPSHOT" +rootProject.extra["picomaven_version"] = "0.0.3-SNAPSHOT" +rootProject.extra["guice_version"] = "4.2.0" +rootProject.extra["gson_version"] = "2.8.0" +rootProject.extra["guava_version"] = "21.0" +rootProject.extra["shuriken_version"] = "0.0.1-SNAPSHOT" +rootProject.extra["hocon_version"] = "3.6.1" +rootProject.extra["mixin_version"] = "0.8.1-SNAPSHOT" +rootProject.extra["modLauncherVersion"] = "5.1.0" +rootProject.extra["log4j2_version"] = "2.8.1" +rootProject.extra["asm_version"] = "8.0.1" +rootProject.extra["checker_qual_version"] = "3.3.0" + +// Subproject configurations +allprojects { + // Project information + group = "eu.mikroskeem" + version = "0.0.4-SNAPSHOT" + description = "Orion" + + // Repositories + repositories { + mavenLocal() + mavenCentral() + + maven("https://repo.wut.ee/repository/mikroskeem-repo") + maven("https://papermc.io/repo/repository/maven-public") + maven("https://repo.spongepowered.org/maven") + } +} + +subprojects { + apply(plugin = "net.minecrell.licenser") + apply(plugin = "java-library") + + // Licenser task + license { + header = rootProject.file("etc/HEADER") + filter.include("**/*.java") + } + + java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } +} + +defaultTasks("build") \ No newline at end of file diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index f35d8b3..0000000 --- a/gradle.properties +++ /dev/null @@ -1,25 +0,0 @@ -# Project information -name=Orion -version=0.0.4-SNAPSHOT -description=Orion -url=https://github.com/OrionMinecraft -organization=OrionMinecraft - -# Gradle & its plugins -gradle_version=5.4.1 -minecrell_licenser_version=0.4.1 -grgit_version=2.3.0 -shadow_version=5.1.0 -blossom_version=1.1.0 - -# Dependency versions -orion_at_version=0.0.1-SNAPSHOT -picomaven_version=0.0.3-SNAPSHOT -guice_version=4.2.0 -gson_version=2.8.0 -guava_version=21.0 -shuriken_version=0.0.1-SNAPSHOT -hocon_version=3.3 -mixin_version=0.8-SNAPSHOT -legacylauncher_version=1.18-SNAPSHOT -log4j2_version=2.8.1