fix: Accidental hard dependency on sodium in mixins
This commit is contained in:
@@ -8,7 +8,6 @@
|
||||
|
||||
import com.google.common.hash.Hashing
|
||||
import com.google.devtools.ksp.gradle.KspAATask
|
||||
import com.google.devtools.ksp.gradle.KspTaskJvm
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonObject
|
||||
import moe.nea.licenseextractificator.LicenseDiscoveryTask
|
||||
@@ -16,7 +15,6 @@ import moe.nea.mcautotranslations.gradle.CollectTranslations
|
||||
import net.fabricmc.loom.LoomGradleExtension
|
||||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.util.Base64
|
||||
@@ -166,14 +164,16 @@ fun createIsolatedSourceSet(name: String, path: String = "compat/$name", isEnabl
|
||||
extendsFrom(getByName(mainSS.annotationProcessorConfigurationName))
|
||||
}
|
||||
(mainSS.runtimeOnlyConfigurationName) {
|
||||
extendsFrom(getByName(ss.runtimeClasspathConfigurationName))
|
||||
if (isEnabled)
|
||||
extendsFrom(getByName(ss.runtimeClasspathConfigurationName))
|
||||
}
|
||||
("ksp$upperName") {
|
||||
extendsFrom(ksp.get())
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
runtimeOnly(ss.output)
|
||||
if (isEnabled)
|
||||
runtimeOnly(ss.output)
|
||||
(ss.implementationConfigurationName)(project.files(tasks.compileKotlin.map { it.destinationDirectory }))
|
||||
(ss.implementationConfigurationName)(project.files(tasks.compileJava.map { it.destinationDirectory }))
|
||||
}
|
||||
@@ -337,6 +337,7 @@ loom {
|
||||
File(it.output.classesDirs.asPath).absolutePath
|
||||
})
|
||||
property("mixin.debug.export", "true")
|
||||
property("mixin.debug", "true")
|
||||
|
||||
parseEnvFile(file(".env")).forEach { (t, u) ->
|
||||
environmentVariable(t, u)
|
||||
|
||||
@@ -15,11 +15,13 @@ import java.util.stream.Collectors;
|
||||
public class MixinPlugin implements IMixinConfigPlugin {
|
||||
|
||||
AutoDiscoveryPlugin autoDiscoveryPlugin = new AutoDiscoveryPlugin();
|
||||
public static String mixinPackage;
|
||||
public static List<MixinPlugin> instances = new ArrayList<>();
|
||||
public String mixinPackage;
|
||||
@Override
|
||||
public void onLoad(String mixinPackage) {
|
||||
MixinExtrasBootstrap.init();
|
||||
MixinPlugin.mixinPackage = mixinPackage;
|
||||
instances.add(this);
|
||||
this.mixinPackage = mixinPackage;
|
||||
autoDiscoveryPlugin.setMixinPackage(mixinPackage);
|
||||
}
|
||||
|
||||
@@ -52,7 +54,7 @@ public class MixinPlugin implements IMixinConfigPlugin {
|
||||
|
||||
}
|
||||
|
||||
public static List<String> appliedMixins = new ArrayList<>();
|
||||
public List<String> appliedMixins = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.block.BlockRenderManager;
|
||||
import net.minecraft.client.render.chunk.SectionBuilder;
|
||||
import net.minecraft.client.render.model.BlockStateModel;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
@@ -18,100 +19,100 @@ import org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
public class SectionBuilderRiser extends RiserUtils {
|
||||
|
||||
@IntermediaryName(SectionBuilder.class)
|
||||
String SectionBuilder;
|
||||
@IntermediaryName(BlockPos.class)
|
||||
String BlockPos;
|
||||
@IntermediaryName(BlockRenderManager.class)
|
||||
String BlockRenderManager;
|
||||
@IntermediaryName(BlockState.class)
|
||||
String BlockState;
|
||||
// @IntermediaryName(BakedModel.class)
|
||||
// String BakedModel;
|
||||
String CustomBlockTextures = "moe.nea.firmament.features.texturepack.CustomBlockTextures";
|
||||
@IntermediaryName(SectionBuilder.class)
|
||||
String SectionBuilder;
|
||||
@IntermediaryName(BlockPos.class)
|
||||
String BlockPos;
|
||||
@IntermediaryName(BlockRenderManager.class)
|
||||
String BlockRenderManager;
|
||||
@IntermediaryName(BlockState.class)
|
||||
String BlockState;
|
||||
@IntermediaryName(BlockStateModel.class)
|
||||
String BlockStateModel;
|
||||
String CustomBlockTextures = "moe.nea.firmament.features.texturepack.CustomBlockTextures";
|
||||
|
||||
Type getModelDesc = Type.getMethodType(
|
||||
getTypeForClassName(BlockRenderManager),
|
||||
getTypeForClassName(BlockState)
|
||||
);
|
||||
String getModel = remapper.mapMethodName(
|
||||
"intermediary",
|
||||
Intermediary.<BlockRenderManager>className(),
|
||||
Intermediary.methodName(net.minecraft.client.render.block.BlockRenderManager::getModel),
|
||||
Type.getMethodDescriptor(
|
||||
// TODO: fix this riser
|
||||
// getTypeForClassName(Intermediary.<BakedModel>className()),
|
||||
getTypeForClassName(Intermediary.<BlockState>className())
|
||||
)
|
||||
);
|
||||
Type getModelDesc = Type.getMethodType(
|
||||
getTypeForClassName(BlockRenderManager),
|
||||
getTypeForClassName(BlockState)
|
||||
);
|
||||
String getModel = remapper.mapMethodName(
|
||||
"intermediary",
|
||||
Intermediary.<BlockRenderManager>className(),
|
||||
Intermediary.methodName(net.minecraft.client.render.block.BlockRenderManager::getModel),
|
||||
Type.getMethodDescriptor(
|
||||
getTypeForClassName(Intermediary.<BlockStateModel>className()),
|
||||
getTypeForClassName(Intermediary.<BlockState>className())
|
||||
)
|
||||
);
|
||||
|
||||
@Override
|
||||
public void addTinkerers() {
|
||||
if (FabricLoader.getInstance().isModLoaded("fabric-renderer-indigo"))
|
||||
ClassTinkerers.addTransformation(SectionBuilder, this::handle, true);
|
||||
}
|
||||
@Override
|
||||
public void addTinkerers() {
|
||||
if (FabricLoader.getInstance().isModLoaded("fabric-renderer-indigo"))
|
||||
ClassTinkerers.addTransformation(SectionBuilder, this::handle, true);
|
||||
}
|
||||
|
||||
private void handle(ClassNode classNode) {
|
||||
for (MethodNode method : classNode.methods) {
|
||||
if ((method.name.endsWith("$fabric-renderer-indigo$hookBuildRenderBlock")
|
||||
|| method.name.endsWith("$fabric-renderer-indigo$hookChunkBuildTessellate")) &&
|
||||
method.name.startsWith("redirect$")) {
|
||||
handleIndigo(method);
|
||||
return;
|
||||
}
|
||||
}
|
||||
System.err.println("Could not inject indigo rendering hook. Is a custom renderer installed (e.g. sodium)?");
|
||||
}
|
||||
private void handle(ClassNode classNode) {
|
||||
System.out.println("AVAST! "+ getModel);
|
||||
for (MethodNode method : classNode.methods) {
|
||||
if ((method.name.endsWith("$fabric-renderer-indigo$hookBuildRenderBlock")
|
||||
|| method.name.endsWith("$fabric-renderer-indigo$hookChunkBuildTessellate")) &&
|
||||
method.name.startsWith("redirect$")) {
|
||||
handleIndigo(method);
|
||||
return;
|
||||
}
|
||||
}
|
||||
System.err.println("Could not inject indigo rendering hook. Is a custom renderer installed (e.g. sodium)?");
|
||||
}
|
||||
|
||||
private void handleIndigo(MethodNode method) {
|
||||
LocalVariableNode blockPosVar = null, blockStateVar = null;
|
||||
for (LocalVariableNode localVariable : method.localVariables) {
|
||||
if (Type.getType(localVariable.desc).equals(getTypeForClassName(BlockPos))) {
|
||||
blockPosVar = localVariable;
|
||||
}
|
||||
if (Type.getType(localVariable.desc).equals(getTypeForClassName(BlockState))) {
|
||||
blockStateVar = localVariable;
|
||||
}
|
||||
}
|
||||
if (blockPosVar == null || blockStateVar == null) {
|
||||
System.err.println("Firmament could inject into indigo: missing either block pos or blockstate");
|
||||
return;
|
||||
}
|
||||
for (AbstractInsnNode instruction : method.instructions) {
|
||||
if (instruction.getOpcode() != Opcodes.INVOKEVIRTUAL) continue;
|
||||
var methodInsn = (MethodInsnNode) instruction;
|
||||
if (!(methodInsn.name.equals(getModel) && Type.getObjectType(methodInsn.owner).equals(getTypeForClassName(BlockRenderManager))))
|
||||
continue;
|
||||
method.instructions.insertBefore(
|
||||
methodInsn,
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
getTypeForClassName(CustomBlockTextures).getInternalName(),
|
||||
"enterFallbackCall",
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE)
|
||||
));
|
||||
private void handleIndigo(MethodNode method) {
|
||||
LocalVariableNode blockPosVar = null, blockStateVar = null;
|
||||
for (LocalVariableNode localVariable : method.localVariables) {
|
||||
if (Type.getType(localVariable.desc).equals(getTypeForClassName(BlockPos))) {
|
||||
blockPosVar = localVariable;
|
||||
}
|
||||
if (Type.getType(localVariable.desc).equals(getTypeForClassName(BlockState))) {
|
||||
blockStateVar = localVariable;
|
||||
}
|
||||
}
|
||||
if (blockPosVar == null || blockStateVar == null) {
|
||||
System.err.println("Firmament could inject into indigo: missing either block pos or blockstate");
|
||||
return;
|
||||
}
|
||||
for (AbstractInsnNode instruction : method.instructions) {
|
||||
if (instruction.getOpcode() != Opcodes.INVOKEVIRTUAL) continue;
|
||||
var methodInsn = (MethodInsnNode) instruction;
|
||||
if (!(methodInsn.name.equals(getModel) && Type.getObjectType(methodInsn.owner).equals(getTypeForClassName(BlockRenderManager))))
|
||||
continue;
|
||||
method.instructions.insertBefore(
|
||||
methodInsn,
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
getTypeForClassName(CustomBlockTextures).getInternalName(),
|
||||
"enterFallbackCall",
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE)
|
||||
));
|
||||
|
||||
var insnList = new InsnList();
|
||||
insnList.add(new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
getTypeForClassName(CustomBlockTextures).getInternalName(),
|
||||
"exitFallbackCall",
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE)
|
||||
));
|
||||
insnList.add(new VarInsnNode(Opcodes.ALOAD, blockPosVar.index));
|
||||
insnList.add(new VarInsnNode(Opcodes.ALOAD, blockStateVar.index));
|
||||
insnList.add(new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
getTypeForClassName(CustomBlockTextures).getInternalName(),
|
||||
"patchIndigo",
|
||||
Type.getMethodDescriptor(
|
||||
// getTypeForClassName(BakedModel),
|
||||
// getTypeForClassName(BakedModel),
|
||||
getTypeForClassName(BlockPos),
|
||||
getTypeForClassName(BlockState)),
|
||||
false
|
||||
));
|
||||
method.instructions.insert(methodInsn, insnList);
|
||||
}
|
||||
}
|
||||
var insnList = new InsnList();
|
||||
insnList.add(new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
getTypeForClassName(CustomBlockTextures).getInternalName(),
|
||||
"exitFallbackCall",
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE)
|
||||
));
|
||||
insnList.add(new VarInsnNode(Opcodes.ALOAD, blockPosVar.index));
|
||||
insnList.add(new VarInsnNode(Opcodes.ALOAD, blockStateVar.index));
|
||||
insnList.add(new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
getTypeForClassName(CustomBlockTextures).getInternalName(),
|
||||
"patchIndigo",
|
||||
Type.getMethodDescriptor(
|
||||
getTypeForClassName(BlockStateModel),
|
||||
getTypeForClassName(BlockStateModel),
|
||||
getTypeForClassName(BlockPos),
|
||||
getTypeForClassName(BlockState)),
|
||||
false
|
||||
));
|
||||
method.instructions.insert(methodInsn, insnList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import net.fabricmc.loader.api.Version
|
||||
import net.fabricmc.loader.api.metadata.ModMetadata
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.apache.logging.log4j.Logger
|
||||
import org.spongepowered.asm.launch.MixinBootstrap
|
||||
import kotlinx.coroutines.CoroutineName
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
|
||||
@@ -262,7 +262,8 @@ fun firmamentCommand() = literal("firmament") {
|
||||
source.sendFeedback(Text.stringifiedTranslatable("firmament.sbinfo.gametype", locrawInfo.gametype))
|
||||
source.sendFeedback(Text.stringifiedTranslatable("firmament.sbinfo.mode", locrawInfo.mode))
|
||||
source.sendFeedback(Text.stringifiedTranslatable("firmament.sbinfo.map", locrawInfo.map))
|
||||
source.sendFeedback(tr("firmament.sbinfo.custommining", "Custom Mining: ${formatBool(locrawInfo.skyblockLocation?.hasCustomMining ?: false)}"))
|
||||
source.sendFeedback(tr("firmament.sbinfo.custommining",
|
||||
"Custom Mining: ${formatBool(locrawInfo.skyblockLocation?.hasCustomMining ?: false)}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,13 +314,15 @@ fun firmamentCommand() = literal("firmament") {
|
||||
}
|
||||
thenLiteral("mixins") {
|
||||
thenExecute {
|
||||
source.sendFeedback(Text.translatable("firmament.mixins.start"))
|
||||
MixinPlugin.appliedMixins
|
||||
.map { it.removePrefix(MixinPlugin.mixinPackage) }
|
||||
.forEach {
|
||||
source.sendFeedback(Text.literal(" - ").withColor(0xD020F0)
|
||||
.append(Text.literal(it).withColor(0xF6BA20)))
|
||||
}
|
||||
MixinPlugin.instances.forEach { plugin ->
|
||||
source.sendFeedback(tr("firmament.mixins.start.package", "Mixins (base ${plugin.mixinPackage}):"))
|
||||
plugin.appliedMixins
|
||||
.map { it.removePrefix(plugin.mixinPackage) }
|
||||
.forEach {
|
||||
source.sendFeedback(Text.literal(" - ").withColor(0xD020F0)
|
||||
.append(Text.literal(it).withColor(0xF6BA20)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
thenLiteral("repo") {
|
||||
|
||||
@@ -3,6 +3,10 @@ package moe.nea.firmament.features.debug
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import org.objectweb.asm.ClassReader
|
||||
import org.objectweb.asm.Type
|
||||
import org.objectweb.asm.tree.ClassNode
|
||||
import org.spongepowered.asm.mixin.Mixin
|
||||
import kotlinx.serialization.json.encodeToStream
|
||||
import kotlin.io.path.absolute
|
||||
import kotlin.io.path.exists
|
||||
@@ -10,11 +14,14 @@ import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.annotations.Subscribe
|
||||
import moe.nea.firmament.events.DebugInstantiateEvent
|
||||
import moe.nea.firmament.events.TickEvent
|
||||
import moe.nea.firmament.features.FirmamentFeature
|
||||
import moe.nea.firmament.gui.config.ManagedConfig
|
||||
import moe.nea.firmament.init.MixinPlugin
|
||||
import moe.nea.firmament.util.MC
|
||||
import moe.nea.firmament.util.TimeMark
|
||||
import moe.nea.firmament.util.asm.AsmAnnotationUtil
|
||||
import moe.nea.firmament.util.iterate
|
||||
|
||||
object DeveloperFeatures : FirmamentFeature {
|
||||
@@ -41,6 +48,42 @@ object DeveloperFeatures : FirmamentFeature {
|
||||
this.missingTranslations = missingTranslations
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun loadAllMixinClasses(event: DebugInstantiateEvent) {
|
||||
val allMixinClasses = mutableSetOf<String>()
|
||||
MixinPlugin.instances.forEach { plugin ->
|
||||
val prefix = plugin.mixinPackage + "."
|
||||
val classes = plugin.mixins.map { prefix + it }
|
||||
allMixinClasses.addAll(classes)
|
||||
for (cls in classes) {
|
||||
val targets = javaClass.classLoader.getResourceAsStream("${cls.replace(".", "/")}.class").use {
|
||||
val node = ClassNode()
|
||||
ClassReader(it).accept(node, 0)
|
||||
val mixins = mutableListOf<Mixin>()
|
||||
(node.visibleAnnotations.orEmpty() + node.invisibleAnnotations.orEmpty()).forEach {
|
||||
val annotationType = Type.getType(it.desc)
|
||||
val mixinType = Type.getType(Mixin::class.java)
|
||||
if (mixinType == annotationType) {
|
||||
mixins.add(AsmAnnotationUtil.createProxy(Mixin::class.java, it))
|
||||
}
|
||||
}
|
||||
mixins.flatMap { it.targets.toList() } + mixins.flatMap { it.value.map { it.java.name } }
|
||||
}
|
||||
for (target in targets)
|
||||
try {
|
||||
Firmament.logger.debug("Loading ${target} to force instantiate ${cls}")
|
||||
Class.forName(target, true, javaClass.classLoader)
|
||||
} catch (ex: Throwable) {
|
||||
Firmament.logger.error("Could not load class ${target} that has been mixind by $cls", ex)
|
||||
}
|
||||
}
|
||||
}
|
||||
Firmament.logger.info("Forceloaded all Firmament mixins:")
|
||||
val applied = MixinPlugin.instances.flatMap { it.appliedMixins }.toSet()
|
||||
applied.forEach { Firmament.logger.info(" - ${it}") }
|
||||
require(allMixinClasses == applied)
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun dumpMissingTranslations(tickEvent: TickEvent) {
|
||||
val toDump = missingTranslations ?: return
|
||||
|
||||
89
src/main/kotlin/util/asm/AsmAnnotationUtil.kt
Normal file
89
src/main/kotlin/util/asm/AsmAnnotationUtil.kt
Normal file
@@ -0,0 +1,89 @@
|
||||
package moe.nea.firmament.util.asm
|
||||
|
||||
import com.google.common.base.Defaults
|
||||
import java.lang.reflect.InvocationHandler
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Proxy
|
||||
import org.objectweb.asm.Type
|
||||
import org.objectweb.asm.tree.AnnotationNode
|
||||
|
||||
object AsmAnnotationUtil {
|
||||
class AnnotationProxy(
|
||||
val originalType: Class<out Annotation>,
|
||||
val annotationNode: AnnotationNode,
|
||||
) : InvocationHandler {
|
||||
val offsets = annotationNode.values.withIndex()
|
||||
.chunked(2)
|
||||
.map { it.first() }
|
||||
.associate { (idx, value) -> value as String to idx + 1 }
|
||||
|
||||
fun nestArrayType(depth: Int, comp: Class<*>): Class<*> =
|
||||
if (depth == 0) comp
|
||||
else java.lang.reflect.Array.newInstance(nestArrayType(depth - 1, comp), 0).javaClass
|
||||
|
||||
fun unmap(
|
||||
value: Any?,
|
||||
comp: Class<*>,
|
||||
depth: Int,
|
||||
): Any? {
|
||||
value ?: return null
|
||||
if (depth > 0)
|
||||
return ((value as List<Any>)
|
||||
.map { unmap(it, comp, depth - 1) } as java.util.List<Any>)
|
||||
.toArray(java.lang.reflect.Array.newInstance(nestArrayType(depth - 1, comp), 0) as Array<*>)
|
||||
if (comp.isEnum) {
|
||||
comp as Class<out Enum<*>>
|
||||
when (value) {
|
||||
is String -> return java.lang.Enum.valueOf(comp, value)
|
||||
is List<*> -> return java.lang.Enum.valueOf(comp, value[1] as String)
|
||||
else -> error("Unknown enum variant $value for $comp")
|
||||
}
|
||||
}
|
||||
when (value) {
|
||||
is Type -> return Class.forName(value.className)
|
||||
is AnnotationNode -> return createProxy(comp as Class<out Annotation>, value)
|
||||
is String, is Boolean, is Byte, is Double, is Int, is Float, is Long, is Short, is Char -> return value
|
||||
}
|
||||
error("Unknown enum variant $value for $comp")
|
||||
}
|
||||
|
||||
fun defaultFor(fullType: Class<*>): Any? {
|
||||
if (fullType.isArray) return java.lang.reflect.Array.newInstance(fullType.componentType, 0)
|
||||
if (fullType.isPrimitive) {
|
||||
return Defaults.defaultValue(fullType)
|
||||
}
|
||||
if (fullType == String::class.java)
|
||||
return ""
|
||||
return null
|
||||
}
|
||||
|
||||
override fun invoke(
|
||||
proxy: Any,
|
||||
method: Method,
|
||||
args: Array<out Any?>?
|
||||
): Any? {
|
||||
val name = method.name
|
||||
val ret = method.returnType
|
||||
val retU = generateSequence(ret) { if (it.isArray) it.componentType else null }
|
||||
.toList()
|
||||
val arrayDepth = retU.size - 1
|
||||
val componentType = retU.last()
|
||||
|
||||
val off = offsets[name]
|
||||
if (off == null) {
|
||||
return defaultFor(ret)
|
||||
}
|
||||
return unmap(annotationNode.values[off], componentType, arrayDepth)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Annotation> createProxy(
|
||||
annotationClass: Class<T>,
|
||||
annotationNode: AnnotationNode
|
||||
): T {
|
||||
require(Type.getType(annotationClass) == Type.getType(annotationNode.desc))
|
||||
return Proxy.newProxyInstance(javaClass.classLoader,
|
||||
arrayOf(annotationClass),
|
||||
AnnotationProxy(annotationClass, annotationNode)) as T
|
||||
}
|
||||
}
|
||||
@@ -316,6 +316,15 @@ object CustomBlockTextures {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by [moe.nea.firmament.init.SectionBuilderRiser]
|
||||
*/
|
||||
|
||||
@JvmStatic
|
||||
fun patchIndigo(original: BlockStateModel, pos: BlockPos?, state: BlockState): BlockStateModel {
|
||||
return getReplacementModel(state, pos) ?: original
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun collectExtraModels(modelsCollector: ReferencedModelsCollector) {
|
||||
preparationFuture.join().collectAllReplacements()
|
||||
|
||||
@@ -26,7 +26,6 @@ public class PatchLegacyTexturePathsIntoArmorLayers {
|
||||
// legacy format: "assets/{identifier.namespace}/textures/models/armor/{identifier.path}_layer_{isLegs ? 2 : 1}{suffix}.png"
|
||||
// suffix is sadly not available to us here. this means leather armor will look a bit shite
|
||||
var legacyIdentifier = this.textureId.withPath((textureName) -> {
|
||||
String var10000 = layerType.asString();
|
||||
return "textures/models/armor/" + textureName + "_layer_" +
|
||||
(layerType == EquipmentModel.LayerType.HUMANOID_LEGGINGS ? 2 : 1)
|
||||
+ ".png";
|
||||
|
||||
@@ -26,7 +26,7 @@ public class ReplaceItemModelPatch implements IntrospectableItemModelManager {
|
||||
private Function<Identifier, ItemModel> modelGetter;
|
||||
|
||||
@WrapOperation(
|
||||
method = "update(Lnet/minecraft/client/render/item/ItemRenderState;Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ModelTransformationMode;Lnet/minecraft/world/World;Lnet/minecraft/entity/LivingEntity;I)V",
|
||||
method = "update",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;get(Lnet/minecraft/component/ComponentType;)Ljava/lang/Object;"))
|
||||
private Object replaceItemModelByIdentifier(ItemStack instance, ComponentType componentType, Operation<Object> original) {
|
||||
var override = CustomItemModelEvent.getModelIdentifier(instance, this);
|
||||
|
||||
@@ -301,7 +301,6 @@
|
||||
"firmament.inventory-buttons.save-preset": "Save Preset",
|
||||
"firmament.key.category": "Firmament",
|
||||
"firmament.keybinding.external": "%s",
|
||||
"firmament.mixins.start": "Applied firmament mixins:",
|
||||
"firmament.modapi.event": "Received mod API event: %s",
|
||||
"firmament.poweruser.entity.armor": "Entity Armor:",
|
||||
"firmament.poweruser.entity.armor.item": " - %s",
|
||||
|
||||
Reference in New Issue
Block a user