diff options
author | Linnea Gräf <nea@nea.moe> | 2024-03-30 19:44:32 +0100 |
---|---|---|
committer | Linnea Gräf <nea@nea.moe> | 2024-03-30 19:44:32 +0100 |
commit | 0414b87e02e51b51cf9ef0c165e5ed61e5193160 (patch) | |
tree | 0d1a0144c44b252dcabc2c1d685a7d2b27e6adee /src/main/java/moe/nea/caelo | |
download | veloxcaelo-0414b87e02e51b51cf9ef0c165e5ed61e5193160.tar.gz veloxcaelo-0414b87e02e51b51cf9ef0c165e5ed61e5193160.tar.bz2 veloxcaelo-0414b87e02e51b51cf9ef0c165e5ed61e5193160.zip |
Initial commit
Diffstat (limited to 'src/main/java/moe/nea/caelo')
-rw-r--r-- | src/main/java/moe/nea/caelo/Caelo.kt | 44 | ||||
-rw-r--r-- | src/main/java/moe/nea/caelo/CaeloCommand.kt | 54 | ||||
-rw-r--r-- | src/main/java/moe/nea/caelo/event/NeaTickEvent.kt | 7 | ||||
-rw-r--r-- | src/main/java/moe/nea/caelo/init/MixinPlugin.java | 47 | ||||
-rw-r--r-- | src/main/java/moe/nea/caelo/mixin/PatchCustomItemModelCache.java | 42 | ||||
-rw-r--r-- | src/main/java/moe/nea/caelo/optifine/OptifineCustomItemCache.kt | 78 | ||||
-rw-r--r-- | src/main/java/moe/nea/caelo/util/Histogram.kt | 17 | ||||
-rw-r--r-- | src/main/java/moe/nea/caelo/util/InterModUtil.kt | 8 | ||||
-rw-r--r-- | src/main/java/moe/nea/caelo/util/MC.kt | 13 |
9 files changed, 310 insertions, 0 deletions
diff --git a/src/main/java/moe/nea/caelo/Caelo.kt b/src/main/java/moe/nea/caelo/Caelo.kt new file mode 100644 index 0000000..76e56bf --- /dev/null +++ b/src/main/java/moe/nea/caelo/Caelo.kt @@ -0,0 +1,44 @@ +package moe.nea.caelo + +import moe.nea.caelo.event.NeaTickEvent +import moe.nea.caelo.init.MixinPlugin +import moe.nea.caelo.optifine.OptifineCustomItemCache +import moe.nea.caelo.util.InterModUtil +import moe.nea.caelo.util.MC +import net.minecraft.client.Minecraft +import net.minecraftforge.client.ClientCommandHandler +import net.minecraftforge.common.MinecraftForge +import net.minecraftforge.fml.common.Mod +import net.minecraftforge.fml.common.event.FMLInitializationEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.TickEvent +import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent + +@Mod(modid = "veloxcaelo", useMetadata = true) +class Caelo { + @SubscribeEvent + fun onTick(tick: ClientTickEvent) { + if (tick.phase != TickEvent.Phase.END) + return + if (Minecraft.getMinecraft().thePlayer == null) + return + MinecraftForge.EVENT_BUS.post(NeaTickEvent(tickCount++)) + } + + var tickCount = 0 + + @Mod.EventHandler + fun onInit(event: FMLInitializationEvent) { + if (InterModUtil.isOptifineLoaded) { + MinecraftForge.EVENT_BUS.register(OptifineCustomItemCache) + } + MinecraftForge.EVENT_BUS.register(this) + ClientCommandHandler.instance.registerCommand(CaeloCommand) + CaeloCommand.subcommand("mixins") { args -> + MC.display("Injected mixins:") + MixinPlugin.loadedMixinClasses.forEach { + MC.display(" - $it") + } + } + } +}
\ No newline at end of file diff --git a/src/main/java/moe/nea/caelo/CaeloCommand.kt b/src/main/java/moe/nea/caelo/CaeloCommand.kt new file mode 100644 index 0000000..b5a1688 --- /dev/null +++ b/src/main/java/moe/nea/caelo/CaeloCommand.kt @@ -0,0 +1,54 @@ +package moe.nea.caelo + +import moe.nea.caelo.util.MC +import net.minecraft.command.CommandBase +import net.minecraft.command.ICommandSender +import net.minecraft.util.BlockPos + +object CaeloCommand : CommandBase() { + override fun getCommandName(): String { + return "veloxcaelo" + } + + override fun getCommandAliases(): List<String> { + return listOf("velox") + } + + override fun canCommandSenderUseCommand(sender: ICommandSender?): Boolean { + return true + } + + override fun getCommandUsage(sender: ICommandSender?): String { + return "" + } + + override fun addTabCompletionOptions( + sender: ICommandSender?, + args: Array<out String>, + pos: BlockPos? + ): List<String> { + if (args.size == 1) { + return getListOfStringsMatchingLastWord(args, subcommands.keys) + } + return emptyList() + } + + private val subcommands = mutableMapOf<String, (args: Array<String>) -> Unit>() + + fun subcommand(name: String, function: (args: Array<String>) -> Unit) { + subcommands[name] = function + } + + override fun processCommand(iCommandSender: ICommandSender?, args: Array<String>) { + if (args.isEmpty()) { + MC.display("§cMissing subcommand. Check the tab completions.") + return + } + val subCommand = subcommands[args[0]] + if (subCommand == null) { + MC.display("§cInvalid subcommand. Check the tab completions.") + return + } + subCommand.invoke(args) + } +}
\ No newline at end of file diff --git a/src/main/java/moe/nea/caelo/event/NeaTickEvent.kt b/src/main/java/moe/nea/caelo/event/NeaTickEvent.kt new file mode 100644 index 0000000..6121203 --- /dev/null +++ b/src/main/java/moe/nea/caelo/event/NeaTickEvent.kt @@ -0,0 +1,7 @@ +package moe.nea.caelo.event + +import net.minecraftforge.fml.common.eventhandler.Event + +data class NeaTickEvent( + val tickCounter: Int, +) : Event()
\ No newline at end of file diff --git a/src/main/java/moe/nea/caelo/init/MixinPlugin.java b/src/main/java/moe/nea/caelo/init/MixinPlugin.java new file mode 100644 index 0000000..fafc55d --- /dev/null +++ b/src/main/java/moe/nea/caelo/init/MixinPlugin.java @@ -0,0 +1,47 @@ +package moe.nea.caelo.init; + +import org.spongepowered.asm.lib.tree.ClassNode; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class MixinPlugin implements IMixinConfigPlugin { + @Override + public void onLoad(String mixinPackage) { + } + + @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 List<String> getMixins() { + return null; + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } + + public static Set<String> loadedMixinClasses = new HashSet<>(); + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + loadedMixinClasses.add(mixinClassName); + } +} diff --git a/src/main/java/moe/nea/caelo/mixin/PatchCustomItemModelCache.java b/src/main/java/moe/nea/caelo/mixin/PatchCustomItemModelCache.java new file mode 100644 index 0000000..afeafef --- /dev/null +++ b/src/main/java/moe/nea/caelo/mixin/PatchCustomItemModelCache.java @@ -0,0 +1,42 @@ +package moe.nea.caelo.mixin; + +import moe.nea.caelo.optifine.OptifineCustomItemCache; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.optifine.CustomItemProperties; +import net.optifine.CustomItems; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +@Pseudo +@Mixin(value = CustomItems.class, remap = false) +public class PatchCustomItemModelCache { + + @SuppressWarnings("InvalidInjectorMethodSignature") + @Inject(method = "getCustomItemProperties", at = @At("HEAD"), cancellable = true) + private static void overrideCustomItemProperties( + ItemStack itemStack, int type, + CallbackInfoReturnable<CustomItemProperties> cir) { + OptifineCustomItemCache.retrieveCacheHit(itemStack, type, cir); + } + + @Inject(method = "getCustomItemProperties", at = @At(value = "RETURN", ordinal = 2), + locals = LocalCapture.CAPTURE_FAILHARD) + private static void storeCustomItemProperties( + ItemStack itemStack, int type, CallbackInfoReturnable<CustomItemProperties> cir, + Item item, int itemId, CustomItemProperties[] cips, int i, CustomItemProperties cip) { + OptifineCustomItemCache.storeCustomItemProperties(itemStack, type, cip); + } + + @Inject(method = "getCustomItemProperties", at = @At(value = "RETURN", ordinal = 3)) + private static void storeCustomItemProperties( + ItemStack itemStack, int type, CallbackInfoReturnable<CustomItemProperties> cir) { + OptifineCustomItemCache.storeNoCustomItemProperties(itemStack, type); + } + + +}
\ No newline at end of file diff --git a/src/main/java/moe/nea/caelo/optifine/OptifineCustomItemCache.kt b/src/main/java/moe/nea/caelo/optifine/OptifineCustomItemCache.kt new file mode 100644 index 0000000..0bd6d78 --- /dev/null +++ b/src/main/java/moe/nea/caelo/optifine/OptifineCustomItemCache.kt @@ -0,0 +1,78 @@ +package moe.nea.caelo.optifine + +import moe.nea.caelo.CaeloCommand +import moe.nea.caelo.event.NeaTickEvent +import moe.nea.caelo.util.Histogram +import moe.nea.caelo.util.MC +import net.minecraft.item.ItemStack +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.optifine.CustomItemProperties +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable + +object OptifineCustomItemCache { + + init { + CaeloCommand.subcommand("opticache") { args -> + val cache = cacheSizeHistory.lastOrNull() ?: CacheStats() + MC.display("OptiCache stats:") + MC.display("- History: §3${cacheSizeHistory.size}") + MC.display("- Misses: §c${cache.cacheMisses}") + MC.display("- Hits: §a${cache.cacheHits}") + MC.display("- Entries: §b${cache.uniquePropertyBearingStacks}") + } + } + + class CacheKey(val itemStack: ItemStack, val type: Int) { + override fun equals(other: Any?): Boolean { + if (other !is CacheKey) return false + return itemStack === other.itemStack && type == other.type + } + + override fun hashCode(): Int { + return System.identityHashCode(itemStack) + type * 31 + } + } + + data class CacheStats( + var cacheHits: Int = 0, + var cacheMisses: Int = 0, + var uniquePropertyBearingStacks: Int = 0, + ) + + private val map = mutableMapOf<CacheKey, CustomItemProperties?>() + private val cacheSizeHistory = Histogram<CacheStats>(1000) + private var cacheStats = CacheStats() + + @SubscribeEvent + fun onTick(event: NeaTickEvent) { + cacheSizeHistory.append(cacheStats) + cacheStats = CacheStats() + map.clear() + } + + @JvmStatic + fun retrieveCacheHit( + itemStack: ItemStack, + type: Int, + cir: CallbackInfoReturnable<CustomItemProperties?> + ) { + val key = CacheKey(itemStack, type) + if (!map.containsKey(key)) { + cacheStats.cacheMisses++ + return + } + cacheStats.cacheHits++ + cir.returnValue = map[key] + } + + @JvmStatic + fun storeCustomItemProperties(itemStack: ItemStack, type: Int, cip: CustomItemProperties) { + map[CacheKey(itemStack, type)] = cip + cacheStats.uniquePropertyBearingStacks++ + } + + @JvmStatic + fun storeNoCustomItemProperties(itemStack: ItemStack, type: Int) { + map[CacheKey(itemStack, type)] = null + } +}
\ No newline at end of file diff --git a/src/main/java/moe/nea/caelo/util/Histogram.kt b/src/main/java/moe/nea/caelo/util/Histogram.kt new file mode 100644 index 0000000..6c4add1 --- /dev/null +++ b/src/main/java/moe/nea/caelo/util/Histogram.kt @@ -0,0 +1,17 @@ +package moe.nea.caelo.util + +class Histogram<T>(val maxSize: Int) : Iterable<T> { + private val dequeue = ArrayDeque<T>() + fun append(element: T) { + dequeue.addLast(element) + if (dequeue.size > maxSize) { + dequeue.removeFirst() + } + } + + val size get() = dequeue.size + + override fun iterator(): Iterator<T> { + return dequeue.iterator() + } +}
\ No newline at end of file diff --git a/src/main/java/moe/nea/caelo/util/InterModUtil.kt b/src/main/java/moe/nea/caelo/util/InterModUtil.kt new file mode 100644 index 0000000..d7b4e90 --- /dev/null +++ b/src/main/java/moe/nea/caelo/util/InterModUtil.kt @@ -0,0 +1,8 @@ +package moe.nea.caelo.util + +import net.minecraftforge.fml.client.FMLClientHandler + +object InterModUtil { + val isOptifineLoaded get() = FMLClientHandler.instance().hasOptifine() + +} diff --git a/src/main/java/moe/nea/caelo/util/MC.kt b/src/main/java/moe/nea/caelo/util/MC.kt new file mode 100644 index 0000000..f05c217 --- /dev/null +++ b/src/main/java/moe/nea/caelo/util/MC.kt @@ -0,0 +1,13 @@ +package moe.nea.caelo.util + +import net.minecraft.client.Minecraft +import net.minecraft.client.entity.EntityPlayerSP +import net.minecraft.util.ChatComponentText + +object MC { + fun display(text: String) { + player?.addChatMessage(ChatComponentText("§b[Velox] §f$text")) + } + + val player: EntityPlayerSP? get() = Minecraft.getMinecraft().thePlayer +}
\ No newline at end of file |