Support Forge for Minecraft 1.15.x (#77)

This commit is contained in:
ZekerZhayard authored and Alexander Xia committed 2019-12-18 15:07:46 +08:00
1 parent e19b9d860f
commit 6fab945eb1
8 files changed
+69 -164

No files matched your search

@@ -85,5 +85,9 @@ public class FakeClientPlayer {
CustomSkinLoader.logger.debug("Legacy Texture (" + resourceLocationIn + ") Loaded as " +
ito.toString() + " (" + location + ")");
}
public void onSkinTextureAvailable(MinecraftProfileTexture.Type typeIn, ResourceLocation location, MinecraftProfileTexture profileTexture) {
this.skinAvailable(typeIn, location, profileTexture);
}
}
}
@@ -19,7 +19,7 @@ import customskinloader.utils.HttpTextureUtil.HttpTextureInfo;
import customskinloader.utils.MinecraftUtil;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IImageBuffer;
import net.minecraft.client.renderer.ThreadDownloadImageData;
import net.minecraft.client.renderer.texture.SimpleTexture;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.resources.DefaultPlayerSkin;
import net.minecraft.client.resources.SkinManager.SkinAvailableCallback;
@@ -49,7 +49,7 @@ public class FakeSkinManager {
if (this.textureManager.getTexture(resourcelocation) != null)//Have already loaded
makeCallback(skinAvailableCallback, textureType, resourcelocation, profileTexture);
else {
ThreadDownloadImageData threaddownloadimagedata = MinecraftUtil.createThreadDownloadImageData(info.cacheFile, info.url, DefaultPlayerSkin.getDefaultSkinLegacy(), new BaseBuffer(skinAvailableCallback, textureType, resourcelocation, profileTexture), textureType);
SimpleTexture threaddownloadimagedata = MinecraftUtil.createThreadDownloadImageData(info.cacheFile, info.url, DefaultPlayerSkin.getDefaultSkinLegacy(), new BaseBuffer(skinAvailableCallback, textureType, resourcelocation, profileTexture), textureType);
if (skinAvailableCallback instanceof FakeClientPlayer.LegacyBuffer)//Cache for client player
FakeClientPlayer.textureCache.put(resourcelocation, threaddownloadimagedata);
this.textureManager.loadTexture(resourcelocation, threaddownloadimagedata);
@@ -13,6 +13,7 @@ import com.mojang.authlib.minecraft.MinecraftProfileTexture;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IImageBuffer;
import net.minecraft.client.renderer.ThreadDownloadImageData;
import net.minecraft.client.renderer.texture.SimpleTexture;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.resources.SkinManager;
import net.minecraft.util.ResourceLocation;
@@ -36,15 +37,25 @@ public class MinecraftUtil {
}
private static boolean is_1_15_plus = false;
private static Constructor<ThreadDownloadImageData> constructor = null;
public static ThreadDownloadImageData createThreadDownloadImageData(File cacheFileIn, String imageUrlIn, ResourceLocation textureResourceLocation, IImageBuffer imageBufferIn, MinecraftProfileTexture.Type textureType) {
private static Constructor<?> constructor = null;
public static SimpleTexture createThreadDownloadImageData(File cacheFileIn, String imageUrlIn, ResourceLocation textureResourceLocation, IImageBuffer imageBufferIn, MinecraftProfileTexture.Type textureType) {
if (constructor == null) {
Class<?> c;
try {
constructor = ThreadDownloadImageData.class.getConstructor(File.class, String.class, ResourceLocation.class, boolean.class, Runnable.class); // For 1.15+
c = Class.forName("net.minecraft.client.renderer.texture.ThreadDownloadImageData", false, MinecraftUtil.class.getClassLoader()); // Forge 1.13
} catch (ClassNotFoundException e1) {
try {
c = Class.forName("net.minecraft.client.renderer.texture.DownloadingTexture", false, MinecraftUtil.class.getClassLoader()); // Forge 1.14+
} catch (ClassNotFoundException e2) {
c = ThreadDownloadImageData.class; // Forge 1.12- or Fabric or Vanilla
}
}
try {
constructor = c.getConstructor(File.class, String.class, ResourceLocation.class, boolean.class, Runnable.class); // For 1.15+
is_1_15_plus = true;
} catch (NoSuchMethodException e1) {
try {
constructor = ThreadDownloadImageData.class.getConstructor(File.class, String.class, ResourceLocation.class, IImageBuffer.class); // For 1.15-
constructor = c.getConstructor(File.class, String.class, ResourceLocation.class, IImageBuffer.class); // For 1.15-
} catch (NoSuchMethodException e2) {
throw new RuntimeException(e2);
}
@@ -52,9 +63,9 @@ public class MinecraftUtil {
}
try {
if (is_1_15_plus) {
return constructor.newInstance(cacheFileIn, imageUrlIn, textureResourceLocation, textureType == MinecraftProfileTexture.Type.SKIN, imageBufferIn);
return (SimpleTexture) constructor.newInstance(cacheFileIn, imageUrlIn, textureResourceLocation, textureType == MinecraftProfileTexture.Type.SKIN, imageBufferIn);
} else {
return constructor.newInstance(cacheFileIn, imageUrlIn, textureResourceLocation, imageBufferIn);
return (SimpleTexture) constructor.newInstance(cacheFileIn, imageUrlIn, textureResourceLocation, imageBufferIn);
}
} catch (Exception e) {
throw new RuntimeException(e);
@@ -15,7 +15,7 @@ public abstract class MixinGuiPlayerTabOverlay {
target = "Lnet/minecraft/client/Minecraft;isIntegratedServerRunning()Z"
)
)
private boolean modifyVariable_renderPlayerlist(Minecraft mc) {
private boolean redirect_renderPlayerlist(Minecraft mc) {
return true;
}
}
+33 -133
View File
@@ -1,65 +1,11 @@
var AbstractInsnNode = Java.type('org.objectweb.asm.tree.AbstractInsnNode');
var FieldInsnNode = Java.type('org.objectweb.asm.tree.FieldInsnNode');
var FieldNode = Java.type('org.objectweb.asm.tree.FieldNode');
var InsnNode = Java.type('org.objectweb.asm.tree.InsnNode');
var MethodInsnNode = Java.type('org.objectweb.asm.tree.MethodInsnNode');
var MethodNode = Java.type('org.objectweb.asm.tree.MethodNode');
var TypeInsnNode = Java.type('org.objectweb.asm.tree.TypeInsnNode');
var VarInsnNode = Java.type('org.objectweb.asm.tree.VarInsnNode');
var Opcodes = Java.type('org.objectweb.asm.Opcodes');
function SkinManagerTransformer() {
return {
'InitTransformer': function (cn, mn) {
cn.fields.add(new FieldNode(Opcodes.ACC_PRIVATE, "fakeManager", "Lcustomskinloader/fake/FakeSkinManager;", null, null));
mn.instructions.clear();
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
mn.instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false));
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
mn.instructions.add(new TypeInsnNode(Opcodes.NEW, "customskinloader/fake/FakeSkinManager"));
mn.instructions.add(new InsnNode(Opcodes.DUP));
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1));
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 2));
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 3));
mn.instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "customskinloader/fake/FakeSkinManager", "<init>",
"(Lnet/minecraft/client/renderer/texture/TextureManager;Ljava/io/File;Lcom/mojang/authlib/minecraft/MinecraftSessionService;)V", false));
mn.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, "net/minecraft/client/resources/SkinManager", "fakeManager", "Lcustomskinloader/fake/FakeSkinManager;"));
mn.instructions.add(new InsnNode(Opcodes.RETURN));
},
'LoadSkinTransformer': function (cn, mn) {
mn.instructions.clear();
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
mn.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, "net/minecraft/client/resources/SkinManager", "fakeManager", "Lcustomskinloader/fake/FakeSkinManager;"));
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1));
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 2));
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 3));
mn.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "customskinloader/fake/FakeSkinManager", "loadSkin",
"(Lcom/mojang/authlib/minecraft/MinecraftProfileTexture;Lcom/mojang/authlib/minecraft/MinecraftProfileTexture$Type;Lnet/minecraft/client/resources/SkinManager$SkinAvailableCallback;)Lnet/minecraft/util/ResourceLocation;", false));
mn.instructions.add(new InsnNode(Opcodes.ARETURN));
},
'LoadProfileTexturesTransformer': function (cn, mn) {
mn.instructions.clear();
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
mn.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, "net/minecraft/client/resources/SkinManager", "fakeManager", "Lcustomskinloader/fake/FakeSkinManager;"));
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1));
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 2));
mn.instructions.add(new VarInsnNode(Opcodes.ILOAD, 3));
mn.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "customskinloader/fake/FakeSkinManager", "loadProfileTextures",
"(Lcom/mojang/authlib/GameProfile;Lnet/minecraft/client/resources/SkinManager$SkinAvailableCallback;Z)V", false));
mn.instructions.add(new InsnNode(Opcodes.RETURN));
},
'LoadSkinFromCacheTransformer': function (cn, mn) {
mn.instructions.clear();
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
mn.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, "net/minecraft/client/resources/SkinManager", "fakeManager", "Lcustomskinloader/fake/FakeSkinManager;"));
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1));
mn.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "customskinloader/fake/FakeSkinManager", "loadSkinFromCache",
"(Lcom/mojang/authlib/GameProfile;)Ljava/util/Map;", false));
mn.instructions.add(new InsnNode(Opcodes.ARETURN));
}
};
}
var hasITextureObject = true;
function PlayerTabTransformer(cn, mn) {
var iterator = mn.instructions.iterator();
@@ -74,62 +20,14 @@ function PlayerTabTransformer(cn, mn) {
}
}
var hasDownloadingTexture = false;
function FakeSkinManagerTransformer(cn, mn) {
var TARGET_CLASS = "net/minecraft/client/renderer/ThreadDownloadImageData";
var NEW_TARGET_CLASS = hasDownloadingTexture ? "net/minecraft/client/renderer/texture/DownloadingTexture" : "net/minecraft/client/renderer/texture/ThreadDownloadImageData";
var CALLBACK_CLASS = "net/minecraft/client/resources/SkinManager$SkinAvailableCallback";
var il = mn.instructions;
var li = il.iterator();
while (li.hasNext()) {
var ain = li.next();
if (ain instanceof MethodInsnNode) {
var min = ain;
if (min.owner.equals(TARGET_CLASS)) {
min.owner = NEW_TARGET_CLASS;
//il.set(min, new MethodInsnNode(min.getOpcode(), NEW_TARGET_CLASS, min.name, min.desc, false));
}
if (min.owner.equals(CALLBACK_CLASS) && min.name.equals("func_180521_a")) {
min.name = "onSkinTextureAvailable";
//il.set(min, new MethodInsnNode(min.getOpcode(), min.owner, "onSkinTextureAvailable", min.desc, false));
}
} else if (ain instanceof TypeInsnNode) {
var tin = ain;
if (tin.desc.equals(TARGET_CLASS)) {
tin.desc = NEW_TARGET_CLASS;
}
}
}
}
function initializeCoreMod() {
return {
'SkinManagerTransformer': {
'target': {
'type': 'CLASS',
'name': 'net/minecraft/client/resources/SkinManager'
},
'transformer': function (cn) {
cn.methods.forEach(function (mn) {
if (mn.name === '<init>')
SkinManagerTransformer()['InitTransformer'](cn, mn);
else if(mn.name === 'func_152789_a')
SkinManagerTransformer()['LoadSkinTransformer'](cn, mn);
else if(mn.name === 'func_152790_a')
SkinManagerTransformer()['LoadProfileTexturesTransformer'](cn, mn);
else if(mn.name === 'func_152788_a')
SkinManagerTransformer()['LoadSkinFromCacheTransformer'](cn, mn);
});
return cn;
}
},
'PlayerTabTransformer': {
'target': {
'type': 'CLASS',
'name': 'net/minecraft/client/gui/GuiPlayerTabOverlay'
'names': function (target) {
return ['net/minecraft/client/gui/GuiPlayerTabOverlay', 'net/minecraft/client/gui/overlay/PlayerTabOverlayGui'];
}
},
'transformer': function (cn) {
cn.methods.forEach(function (mn) {
@@ -139,28 +37,20 @@ function initializeCoreMod() {
return cn;
}
},
'PlayerTabTransformer2': {
'SkinAvailableCallbackTransformer': {
'target': {
'type': 'CLASS',
'name': 'net/minecraft/client/gui/overlay/PlayerTabOverlayGui'
'name': 'net/minecraft/client/resources/SkinManager$SkinAvailableCallback'
},
'transformer': function (cn) {
cn.version = Opcodes.V1_8;
cn.methods.forEach(function (mn) {
if (mn.name === 'func_175249_a')
PlayerTabTransformer(cn, mn);
});
return cn;
}
},
'FakeSkinManagerTransformer': {
'target': {
'type': 'CLASS',
'name': 'customskinloader/fake/FakeSkinManager'
},
'transformer': function (cn) {
cn.methods.forEach(function (mn) {
//if (mn.name === '<init>')
FakeSkinManagerTransformer(cn, mn);
mn.access -= Opcodes.ACC_ABSTRACT;
for (var j = 0; j < 4; j++) {
mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, j));
}
mn.instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, cn.name, mn.name.equals("func_180521_a") ? "onSkinTextureAvailable" : "func_180521_a", mn.desc, true));
mn.instructions.add(new InsnNode(Opcodes.RETURN));
});
return cn;
}
@@ -187,27 +77,37 @@ function initializeCoreMod() {
return cn;
}
},
'DownloadingTextureTransformer': {
// For 1.15+
'ITextureObjectTransformer': {
'target': {
'type': 'CLASS',
'name': 'net/minecraft/client/renderer/texture/DownloadingTexture'
'name': 'net/minecraft/client/renderer/texture/ITextureObject'
},
'transformer': function (cn) {
hasDownloadingTexture = true;
hasITextureObject = !cn.methods.isEmpty();
return cn;
}
},
'SkinAvailableCallbackTransformer': {
'FakeSkinManagerTransformer': {
'target': {
'type': 'CLASS',
'name': 'net/minecraft/client/resources/SkinManager$SkinAvailableCallback'
'name': 'customskinloader/fake/FakeSkinManager'
},
'transformer': function (cn) {
cn.methods.forEach(function (mn) {
if (mn.name.equals("func_180521_a")) {
mn.name = "onSkinTextureAvailable";
}
});
if (!hasITextureObject) {
cn.methods.stream().filter(function (mn) {
return mn.name.equals("loadSkin") && mn.desc.equals("(Lcom/mojang/authlib/minecraft/MinecraftProfileTexture;Lcom/mojang/authlib/minecraft/MinecraftProfileTexture$Type;Lnet/minecraft/client/resources/SkinManager$SkinAvailableCallback;)Lnet/minecraft/util/ResourceLocation;");
}).forEach(function (mn) {
mn.instructions.iterator().forEachRemaining(function (ain) {
if (ain instanceof MethodInsnNode && ain.owner.equals("net/minecraft/client/renderer/texture/TextureManager")) {
if (ain.name.equals("func_110579_a")) ain.name = "func_229263_a_";
if (ain.name.equals("func_110581_b")) ain.name = "func_229267_b_";
ain.desc = ain.desc.replace("Lnet/minecraft/client/renderer/texture/ITextureObject;", "Lnet/minecraft/client/renderer/texture/Texture;");
}
});
});
}
return cn;
}
}
@@ -6,22 +6,18 @@ import java.util.Map;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import customskinloader.fake.FakeSkinManager;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.versions.mcp.MCPVersion;
public class SkinManager {
static {
if (!MCPVersion.getMCVersion().startsWith("1.13")) {
try {
// Make sure that DownloadingTexture is initialized earlier than FakeSkinManager.
Class.forName("net.minecraft.client.renderer.texture.DownloadingTexture");
} catch (ClassNotFoundException e) {}
}
}
private FakeSkinManager fakeManager;
public SkinManager(TextureManager textureManagerInstance, File skinCacheDirectory, MinecraftSessionService sessionService) {
throw new RuntimeException("This method must be transformed!");
try {
Class.forName("net.minecraft.client.renderer.texture.ITextureObject", false, SkinManager.class.getClassLoader());
} catch (ClassNotFoundException ignore) {}
this.fakeManager = new FakeSkinManager(textureManagerInstance, skinCacheDirectory, sessionService);
}
public ResourceLocation loadSkin(MinecraftProfileTexture profileTexture, MinecraftProfileTexture.Type textureType) {
@@ -29,7 +25,7 @@ public class SkinManager {
}
public ResourceLocation loadSkin(MinecraftProfileTexture profileTexture, MinecraftProfileTexture.Type textureType, SkinManager.SkinAvailableCallback skinAvailableCallback) {
throw new RuntimeException("This method must be transformed!");
return this.fakeManager.loadSkin(profileTexture, textureType, skinAvailableCallback);
}
// For 1.14+
@@ -38,7 +34,7 @@ public class SkinManager {
}
public void loadProfileTextures(GameProfile profile, SkinManager.SkinAvailableCallback skinAvailableCallback, boolean requireSecure) {
throw new RuntimeException("This method must be transformed!");
this.fakeManager.loadProfileTextures(profile, skinAvailableCallback, requireSecure);
}
// For 1.14+
@@ -47,14 +43,16 @@ public class SkinManager {
}
public Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> loadSkinFromCache(GameProfile profile) {
throw new RuntimeException("This method must be transformed!");
return this.fakeManager.loadSkinFromCache(profile);
}
public interface SkinAvailableCallback {
void skinAvailable(MinecraftProfileTexture.Type typeIn, ResourceLocation location, MinecraftProfileTexture profileTexture);
void onSkinTextureAvailable(MinecraftProfileTexture.Type typeIn, ResourceLocation location, MinecraftProfileTexture profileTexture);
}
public interface ISkinAvailableCallback extends SkinAvailableCallback {
void onSkinTextureAvailable(MinecraftProfileTexture.Type typeIn, ResourceLocation location, MinecraftProfileTexture profileTexture);
}
}
@@ -1,7 +0,0 @@
package net.minecraftforge.versions.mcp;
public class MCPVersion {
public static String getMCVersion() {
return null;
}
}
-1
View File
@@ -3,7 +3,6 @@ include "1.14.4"
//Universal Forge Edition for [1.8,)
include "Forge"
include "Forge1.14"
//Fabric Edition for [1.14,)
include "Fabric"