diff options
Diffstat (limited to 'src/main')
-rw-r--r-- | src/main/java/moe/nea/ultranotifier/init/NeaMixinConfig.java | 185 | ||||
-rw-r--r-- | src/main/java/moe/nea/ultranotifier/mixin/ChatHudMessageAdded.java | 41 | ||||
-rw-r--r-- | src/main/kotlin/Constants.kt | 27 | ||||
-rw-r--r-- | src/main/kotlin/UltraNotifier.kt | 24 | ||||
-rw-r--r-- | src/main/kotlin/UltraNotifierEntryPoint.kt | 25 | ||||
-rw-r--r-- | src/main/kotlin/UltraNotifierEvents.kt | 53 | ||||
-rw-r--r-- | src/main/resources/mixins.ultranotifier.json | 7 |
7 files changed, 362 insertions, 0 deletions
diff --git a/src/main/java/moe/nea/ultranotifier/init/NeaMixinConfig.java b/src/main/java/moe/nea/ultranotifier/init/NeaMixinConfig.java new file mode 100644 index 0000000..a3fc4fc --- /dev/null +++ b/src/main/java/moe/nea/ultranotifier/init/NeaMixinConfig.java @@ -0,0 +1,185 @@ +package moe.nea.ultranotifier.init; + +//#if MC < 11404 +//$$import org.spongepowered.asm.lib.tree.ClassNode; +//#else +import org.objectweb.asm.tree.ClassNode; +//#endif +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +public class NeaMixinConfig implements IMixinConfigPlugin { + + private static final List<NeaMixinConfig> mixinPlugins = new ArrayList<>(); + + public static List<NeaMixinConfig> getMixinPlugins() { + return mixinPlugins; + } + + private String mixinPackage; + + @Override + public void onLoad(String mixinPackage) { + this.mixinPackage = mixinPackage; + mixinPlugins.add(this); + } + + /** + * Resolves the base class root for a given class URL. This resolves either the JAR root, or the class file root. + * In either case the return value of this + the class name will resolve back to the original class url, or to other + * class urls for other classes. + */ + public URL getBaseUrlForClassUrl(URL classUrl) { + String string = classUrl.toString(); + if (classUrl.getProtocol().equals("jar")) { + try { + return new URL(string.substring(4).split("!")[0]); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + if (string.endsWith(".class")) { + try { + return new URL(string.replace("\\", "/") + .replace(getClass().getCanonicalName() + .replace(".", "/") + ".class", "")); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + return classUrl; + } + + /** + * Get the package that contains all the mixins. This value is set by mixin itself using {@link #onLoad}. + */ + public String getMixinPackage() { + return mixinPackage; + } + + /** + * Get the path inside the class root to the mixin package + */ + public String getMixinBaseDir() { + return mixinPackage.replace(".", "/"); + } + + /** + * A list of all discovered mixins. + */ + private List<String> mixins = null; + + /** + * Try to add mixin class ot the mixins based on the filepath inside of the class root. + * Removes the {@code .class} file suffix, as well as the base mixin package. + * <p><b>This method cannot be called after mixin initialization.</p> + * + * @param className the name or path of a class to be registered as a mixin. + */ + public void tryAddMixinClass(String className) { + String norm = (className.endsWith(".class") ? className.substring(0, className.length() - ".class".length()) : className) + .replace("\\", "/") + .replace("/", "."); + if (norm.startsWith(getMixinPackage() + ".") && !norm.endsWith(".")) { + mixins.add(norm.substring(getMixinPackage().length() + 1)); + } + } + + /** + * Search through the JAR or class directory to find mixins contained in {@link #getMixinPackage()} + */ + @Override + public List<String> getMixins() { + if (mixins != null) return mixins; + System.out.println("Trying to discover mixins"); + mixins = new ArrayList<>(); + URL classUrl = getClass().getProtectionDomain().getCodeSource().getLocation(); + System.out.println("Found classes at " + classUrl); + Path file; + try { + file = Paths.get(getBaseUrlForClassUrl(classUrl).toURI()); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + System.out.println("Base directory found at " + file); + if (Files.isDirectory(file)) { + walkDir(file); + } else { + walkJar(file); + } + System.out.println("Found mixins: " + mixins); + + return mixins; + } + + /** + * Search through directory for mixin classes based on {@link #getMixinBaseDir}. + * + * @param classRoot The root directory in which classes are stored for the default package. + */ + private void walkDir(Path classRoot) { + System.out.println("Trying to find mixins from directory"); + try (Stream<Path> classes = Files.walk(classRoot.resolve(getMixinBaseDir()))) { + classes.map(it -> classRoot.relativize(it).toString()) + .forEach(this::tryAddMixinClass); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Read through a JAR file, trying to find all mixins inside. + */ + private void walkJar(Path file) { + System.out.println("Trying to find mixins from jar file"); + try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(file))) { + ZipEntry next; + while ((next = zis.getNextEntry()) != null) { + tryAddMixinClass(next.getName()); + zis.closeEntry(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + return true; + } + + @Override + public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) { + + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } +} diff --git a/src/main/java/moe/nea/ultranotifier/mixin/ChatHudMessageAdded.java b/src/main/java/moe/nea/ultranotifier/mixin/ChatHudMessageAdded.java new file mode 100644 index 0000000..b8239d3 --- /dev/null +++ b/src/main/java/moe/nea/ultranotifier/mixin/ChatHudMessageAdded.java @@ -0,0 +1,41 @@ +package moe.nea.ultranotifier.mixin; + +import moe.nea.ultranotifier.ChatLineAddedEvent; +import moe.nea.ultranotifier.UltraNotifierEvents; +import net.minecraft.client.gui.hud.ChatHud; +//#if MC > 11404 +import net.minecraft.client.gui.hud.MessageIndicator; +import net.minecraft.network.message.MessageSignatureData; +//#endif +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin( + ChatHud.class +) +public class ChatHudMessageAdded { + @Inject( +//#if MC <= 11404 +//$$ method = "printChatMessageWithOptionalDeletion", +//#else + method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;Lnet/minecraft/client/gui/hud/MessageIndicator;)V", +//#endif + at = @At("HEAD"), cancellable = true) + private void onAddMessage( + Text message, +//#if MC <= 11404 +//$$ int chatLineId, +//#else + MessageSignatureData signatureData, MessageIndicator indicator, +//#endif + CallbackInfo ci + ) { + if (UltraNotifierEvents.post(new ChatLineAddedEvent()).isCancelled()) { + ci.cancel(); + } + } + +} diff --git a/src/main/kotlin/Constants.kt b/src/main/kotlin/Constants.kt new file mode 100644 index 0000000..a1903ce --- /dev/null +++ b/src/main/kotlin/Constants.kt @@ -0,0 +1,27 @@ +package moe.nea.ultranotifier + + +object Constants { + const val MOD_ID = "ultranotifier" + const val VERSION = "1.0.0" + + enum class Platform { + FORGE, FABRIC + } + + val PLATFORM: Platform = +//#if FORGE +//$$ Platform.FORGE +//#else + Platform.FABRIC +//#endif + + const val MINECRAFT_VERSION: String = +//#if MC == 10809 +//$$ "1.8.9" +//#elseif MC == 12006 + "1.20.6" +//#elseif MC == 11404 +//$$ "1.14.4" +//#endif +} diff --git a/src/main/kotlin/UltraNotifier.kt b/src/main/kotlin/UltraNotifier.kt new file mode 100644 index 0000000..e6ce590 --- /dev/null +++ b/src/main/kotlin/UltraNotifier.kt @@ -0,0 +1,24 @@ +package moe.nea.ultranotifier + +import moe.nea.ultranotifier.init.NeaMixinConfig +import java.io.File + +object UltraNotifier { + val logger = +//#if MC == 10809 +//$$ org.apache.logging.log4j.LogManager.getLogger("UltraNotifier")!! +//#else + org.slf4j.LoggerFactory.getLogger("UltraNotifier")!! +//#endif + + fun onStartup() { + logger.info("Started on ${Constants.MINECRAFT_VERSION} ${Constants.PLATFORM} with version ${Constants.VERSION}!") + for (mixinPlugin in NeaMixinConfig.getMixinPlugins()) { + logger.info("Loaded ${mixinPlugin.mixins.size} mixins for ${mixinPlugin.mixinPackage}.") + } + } + + val configFolder = File("config/ultra-notifier").also { + it.mkdirs() + } +} diff --git a/src/main/kotlin/UltraNotifierEntryPoint.kt b/src/main/kotlin/UltraNotifierEntryPoint.kt new file mode 100644 index 0000000..34525ea --- /dev/null +++ b/src/main/kotlin/UltraNotifierEntryPoint.kt @@ -0,0 +1,25 @@ +package moe.nea.ultranotifier + +//#if FORGE +//$$ import net.minecraftforge.fml.common.Mod +//$$ +//#if MC == 10809 +//$$ import net.minecraftforge.fml.common.event.FMLInitializationEvent +//$$ @Mod(modid = Constants.MOD_ID, version = Constants.VERSION, useMetadata = true) +//#else +//$$ @Mod(Constants.MOD_ID) +//#endif +//$$ class UltraNotifierEntryPoint { +//$$ @Mod.EventHandler +//$$ fun onInit(@Suppress("UNUSED_PARAMETER") event: FMLInitializationEvent) { +//$$ UltraNotifier.onStartup() +//$$ } +//$$ } +//#else +import net.fabricmc.api.ModInitializer +object UltraNotifierEntryPoint : ModInitializer { + override fun onInitialize() { + UltraNotifier.onStartup() + } +} +//#endif diff --git a/src/main/kotlin/UltraNotifierEvents.kt b/src/main/kotlin/UltraNotifierEvents.kt new file mode 100644 index 0000000..eb0d71f --- /dev/null +++ b/src/main/kotlin/UltraNotifierEvents.kt @@ -0,0 +1,53 @@ +package moe.nea.ultranotifier + +object UltraNotifierEvents { + val eventBus = +//#if FORGE +//$$ net.minecraftforge.common.MinecraftForge.EVENT_BUS +//#else + me.bush.eventbus.bus.EventBus { UltraNotifier.logger.warn("EventBus: $it") } +//#endif + @JvmStatic + fun <T : UltraEvent> post(event: T): T { + UltraNotifier.logger.info("Posting $event") + eventBus.post(event) + return event + } +} + +abstract class UltraEvent : +//#if FORGE +//$$ net.minecraftforge.fml.common.eventhandler.Event() +//#else + me.bush.eventbus.event.Event() +//#endif +{ +//#if FORGE +//$$ override fun isCancelable(): Boolean { +//$$ return this.isCancellable() +//$$ } +//$$ fun isCancelled(): Boolean { +//$$ return isCanceled() +//$$ } +//$$ fun setCancelled(value: Boolean) { +//$$ setCanceled(value) +//$$ } +//#else + override +//#endif + + fun isCancellable(): Boolean { + return true + } + +//#if FORGE == 0 + override +//#endif + fun cancel() { + setCancelled(true) + } + +} + + +class ChatLineAddedEvent() : UltraEvent() diff --git a/src/main/resources/mixins.ultranotifier.json b/src/main/resources/mixins.ultranotifier.json new file mode 100644 index 0000000..03c353c --- /dev/null +++ b/src/main/resources/mixins.ultranotifier.json @@ -0,0 +1,7 @@ +{ + "compatibilityLevel": "JAVA_8", + "package": "moe.nea.ultranotifier.mixin", + "plugin": "moe.nea.ultranotifier.init.NeaMixinConfig", + "refmap": "mixins.ultranotifier.refmap.json", + "minVersion": "0.7" +}
\ No newline at end of file |