Skip to content

Commit

Permalink
Working towards fixing Immersive Engineering
Browse files Browse the repository at this point in the history
  • Loading branch information
BluSpring committed Oct 31, 2023
1 parent 01305f5 commit 059ddb0
Show file tree
Hide file tree
Showing 13 changed files with 298 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.ItemLike;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityDispatcher;
import net.minecraftforge.common.capabilities.CapabilityProvider;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.capabilities.*;
import net.minecraftforge.common.extensions.IForgeItemStack;
import net.minecraftforge.common.util.LazyOptional;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -125,6 +122,16 @@ public boolean areCapsCompatible(CapabilityProvider<ItemStack> other) {
return workaround.areCapsCompatible(other);
}

@Override
public boolean areCapsCompatible(ICapabilityProviderImpl<ItemStack> stack) {
if (stack instanceof ItemStackCapabilityProviderImpl stackWorkaround)
return workaround.areCapsCompatible(stackWorkaround.getWorkaround());
else if (stack instanceof CapabilityProvider<ItemStack> provider)
return workaround.areCapsCompatible(provider);
else
return false;
}

@Override
public boolean areCapsCompatible(@Nullable CapabilityDispatcher other) {
return workaround.areCapsCompatible(other);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package xyz.bluspring.kilt.forgeinjects.world.level.block.entity;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.item.crafting.AbstractCookingRecipe;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
import net.minecraft.world.level.block.entity.BaseContainerBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ForgeCapabilities;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.wrapper.SidedInvWrapper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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(AbstractFurnaceBlockEntity.class)
public abstract class AbstractFurnaceBlockEntityInject extends BaseContainerBlockEntity {
private RecipeType<? extends AbstractCookingRecipe> recipeType;

protected AbstractFurnaceBlockEntityInject(BlockEntityType<?> blockEntityType, BlockPos blockPos, BlockState blockState) {
super(blockEntityType, blockPos, blockState);
}

@Inject(method = "<init>", at = @At("TAIL"))
private void kilt$initRecipeType(BlockEntityType<?> blockEntityType, BlockPos blockPos, BlockState blockState, RecipeType<? extends AbstractCookingRecipe> recipeType, CallbackInfo ci) {
this.recipeType = recipeType;
}

LazyOptional<? extends IItemHandler>[] handlers = SidedInvWrapper.create((AbstractFurnaceBlockEntity) (Object) this, Direction.UP, Direction.DOWN, Direction.NORTH);

@Override
public @NotNull <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
if (!this.remove && side != null && cap == ForgeCapabilities.ITEM_HANDLER) {
if (side == Direction.UP)
return handlers[0].cast();
else if (side == Direction.DOWN)
return handlers[1].cast();
else
return handlers[2].cast();
}
return super.getCapability(cap, side);
}

@Override
public void invalidateCaps() {
super.invalidateCaps();
for (LazyOptional<? extends IItemHandler> handler : handlers) {
handler.invalidate();
}
}

@Override
public void reviveCaps() {
super.reviveCaps();
this.handlers = SidedInvWrapper.create((AbstractFurnaceBlockEntity) (Object) this, Direction.UP, Direction.DOWN, Direction.NORTH);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ public interface ItemStackCapabilityProviderImpl extends ICapabilityProviderImpl
default CapabilityProviderWorkaround<ItemStack> getWorkaround() {
throw new IllegalStateException();
}

default boolean areCapsCompatible(ICapabilityProviderImpl<ItemStack> stack) {
throw new IllegalStateException();
}
}
17 changes: 17 additions & 0 deletions src/main/kotlin/cpw/mods/modlauncher/api/ILaunchHandlerService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cpw.mods.modlauncher.api

/**
* A singleton instance of this is loaded by the system to designate the launch target
*/
interface ILaunchHandlerService {
fun name(): String

@Deprecated("")
fun configureTransformationClassLoader(builder: ITransformingClassLoaderBuilder)

fun launchService(arguments: Array<String>, gameLayer: ModuleLayer): ServiceRunner

fun getPaths(): Array<NamedPath> {
return arrayOf()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package cpw.mods.modlauncher.api

import java.net.URL
import java.nio.file.Path
import java.util.*
import java.util.function.Function


interface ITransformingClassLoaderBuilder {
fun addTransformationPath(path: Path)

fun setClassBytesLocator(additionalClassBytesLocator: Function<String, Optional<URL>>)

fun setResourceEnumeratorLocator(resourceEnumeratorLocator: Function<String?, Enumeration<URL>>)
}
8 changes: 8 additions & 0 deletions src/main/kotlin/cpw/mods/modlauncher/api/NamedPath.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package cpw.mods.modlauncher.api

import java.nio.file.Path

class NamedPath(
val name: String,
vararg paths: Path
)
11 changes: 11 additions & 0 deletions src/main/kotlin/cpw/mods/modlauncher/api/ServiceRunner.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package cpw.mods.modlauncher.api

fun interface ServiceRunner {
@Throws(Throwable::class)
fun run()

companion object {
@JvmField
val NOOP = ServiceRunner {}
}
}
9 changes: 9 additions & 0 deletions src/main/kotlin/net/minecraftforge/fml/loading/FMLLoader.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package net.minecraftforge.fml.loading

import net.fabricmc.loader.api.FabricLoader
import net.minecraftforge.fml.loading.targets.CommonLaunchHandler
import net.minecraftforge.fml.loading.targets.KnotLaunchHandler
import java.nio.file.Path

object FMLLoader {
Expand All @@ -9,6 +11,13 @@ object FMLLoader {
return !FabricLoader.getInstance().isDevelopmentEnvironment
}

private val handler = KnotLaunchHandler()

@JvmStatic
fun getLaunchHandler(): CommonLaunchHandler {
return this.handler
}

@JvmStatic
fun launcherHandlerName(): String {
return "kilt"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package net.minecraftforge.fml.loading.targets

import com.mojang.logging.LogUtils
import cpw.mods.modlauncher.api.ILaunchHandlerService
import cpw.mods.modlauncher.api.ITransformingClassLoaderBuilder
import net.minecraftforge.api.distmarker.Dist
import net.minecraftforge.fml.loading.LogMarkers
import org.slf4j.Logger
import java.io.File
import java.nio.file.Path
import java.nio.file.Paths
import java.util.*
import java.util.function.BiPredicate
import java.util.stream.Collectors


abstract class CommonLaunchHandler : ILaunchHandlerService {
data class LocatedPaths(
val minecraftPaths: List<Path>,
val minecraftFilter: BiPredicate<String, String>,
val otherModPaths: List<List<Path>>,
val otherArtifacts: List<Path>
)

abstract fun getDist(): Dist

abstract fun getNaming(): String

open fun isProduction(): Boolean {
return false
}

open fun isData(): Boolean {
return false
}

abstract fun getMinecraftPaths(): LocatedPaths

override fun configureTransformationClassLoader(builder: ITransformingClassLoaderBuilder) {}

protected fun getModClasses(): Map<String, List<Path>> {
val modClasses: String = Optional.ofNullable(System.getenv("MOD_CLASSES")).orElse("")
LOGGER.debug(LogMarkers.CORE, "Got mod coordinates {} from env", modClasses)
data class ExplodedModPath(val modid: String, val path: Path)

// "a/b/;c/d/;" -> "modid%%c:\fish\pepper;modid%%c:\fish2\pepper2\;modid2%%c:\fishy\bums;modid2%%c:\hmm"
val modClassPaths =
Arrays.stream(modClasses.split(File.pathSeparator.toRegex()).dropLastWhile { it.isEmpty() }
.toTypedArray())
.map { inp -> inp.split("%%", limit = 2) }
.map { splitString ->
ExplodedModPath(
if (splitString.size == 1) "defaultmodid" else splitString[0],
Paths.get(splitString[splitString.size - 1])
)
}
.collect(
Collectors.groupingBy(
ExplodedModPath::modid,
Collectors.mapping(ExplodedModPath::path, Collectors.toList())
)
)
LOGGER.debug(LogMarkers.CORE, "Found supplied mod coordinates [{}]", modClassPaths)

//final var explodedTargets = ((Map<String, List<ExplodedDirectoryLocator.ExplodedMod>>)arguments).computeIfAbsent("explodedTargets", a -> new ArrayList<>());
//modClassPaths.forEach((modlabel,paths) -> explodedTargets.add(new ExplodedDirectoryLocator.ExplodedMod(modlabel, paths)));
return modClassPaths
}

companion object {
protected val LOGGER: Logger = LogUtils.getLogger()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package net.minecraftforge.fml.loading.targets

import cpw.mods.modlauncher.api.ServiceRunner
import net.fabricmc.api.EnvType
import net.fabricmc.loader.api.FabricLoader
import net.minecraftforge.api.distmarker.Dist
import xyz.bluspring.kilt.loader.remap.KiltRemapper

class KnotLaunchHandler : CommonLaunchHandler() {
override fun getDist(): Dist {
return if (FabricLoader.getInstance().environmentType == EnvType.CLIENT)
Dist.CLIENT
else
Dist.DEDICATED_SERVER
}

override fun getNaming(): String {
return FabricLoader.getInstance().mappingResolver.currentRuntimeNamespace
}

private val paths = LocatedPaths(
KiltRemapper.getGameClassPath().toList(), { _, _ ->
true
},
listOf(), listOf()
)

override fun getMinecraftPaths(): LocatedPaths {
return paths
}

override fun name(): String {
return "knot"
}

override fun launchService(arguments: Array<String>, gameLayer: ModuleLayer): ServiceRunner {
return ServiceRunner.NOOP
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory
import xyz.bluspring.kilt.Kilt
import xyz.bluspring.kilt.loader.KiltLoader
import xyz.bluspring.kilt.loader.mod.ForgeMod
import xyz.bluspring.kilt.loader.remap.fixers.CompatibleCapabilityWorkaroundFixer
import xyz.bluspring.kilt.loader.remap.fixers.ConflictingStaticMethodFixer
import xyz.bluspring.kilt.loader.remap.fixers.EventClassVisibilityFixer
import xyz.bluspring.kilt.loader.remap.fixers.EventEmptyInitializerFixer
Expand All @@ -50,7 +51,7 @@ object KiltRemapper {
// Keeps track of the remapper changes, so every time I update the remapper,
// it remaps all the mods following the remapper changes.
// this can update by like 12 versions in 1 update, so don't worry too much about it.
const val REMAPPER_VERSION = 107
const val REMAPPER_VERSION = 110

val logConsumer = Consumer<String> {
logger.debug(it)
Expand Down Expand Up @@ -401,6 +402,9 @@ object KiltRemapper {
val visitor = EnhancedClassRemapper(classWriter, remapper, RenamingTransformer(remapper, false))
classNode.accept(visitor)

ConflictingStaticMethodFixer.fixClass(classNode)
CompatibleCapabilityWorkaroundFixer.fixClass(classNode)

jarOutput.putNextEntry(entry)
jarOutput.write(classWriter.toByteArray())
jarOutput.closeEntry()
Expand Down Expand Up @@ -468,7 +472,7 @@ object KiltRemapper {
return null
}

private fun getGameClassPath(): Array<out Path> {
fun getGameClassPath(): Array<out Path> {
return if (!FabricLoader.getInstance().isDevelopmentEnvironment)
arrayOf(
FabricLoader.getInstance().objectShare.get("fabric-loader:inputGameJar") as Path,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package xyz.bluspring.kilt.loader.remap.fixers

import net.fabricmc.loader.api.FabricLoader
import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.AbstractInsnNode
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.MethodInsnNode

object CompatibleCapabilityWorkaroundFixer {
private val mappingResolver = FabricLoader.getInstance().mappingResolver
private val workaroundClasses = listOf(
mappingResolver.mapClassName("intermediary", "net.minecraft.class_1799").replace(".", "/")
)

fun fixClass(classNode: ClassNode) {
for (method in classNode.methods) {
val newNodeMap = mutableMapOf<AbstractInsnNode, AbstractInsnNode>()

for (insnNode in method.instructions) {
// Target virtual invokes specifically
if (insnNode is MethodInsnNode && insnNode.opcode == Opcodes.INVOKEVIRTUAL) {
if (!workaroundClasses.contains(insnNode.owner))
continue

if (insnNode.name != "areCapsCompatible")
continue

val node = MethodInsnNode(insnNode.opcode, insnNode.owner, insnNode.name, "(Lnet/minecraftforge/common/capabilities/ICapabilityProviderImpl;)Z")
newNodeMap[insnNode] = node
}
}

if (newNodeMap.isNotEmpty()) {
for ((oldNode, newNode) in newNodeMap) {
method.instructions.set(oldNode, newNode)
}
}
}
}
}
1 change: 1 addition & 0 deletions src/main/resources/kilt_forge_injects.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
"world.level.block.LiquidBlockInject",
"world.level.block.PoweredRailBlockInject",
"world.level.block.StairBlockInject",
"world.level.block.entity.AbstractFurnaceBlockEntityInject",
"world.level.block.entity.BlockEntityInject",
"world.level.block.entity.HopperBlockEntityInject",
"world.level.block.state.BlockBehaviourInject",
Expand Down

0 comments on commit 059ddb0

Please sign in to comment.