aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/makamys
diff options
context:
space:
mode:
authormakamys <makamys@outlook.com>2023-02-09 20:58:39 +0100
committermakamys <makamys@outlook.com>2023-02-09 21:11:50 +0100
commitcd5305c6a383ebb8bf530d0f909c2d32c2ab6723 (patch)
tree49543a15ebf05d061d55fcb1016c1ec18146e032 /src/main/java/makamys
parent3ab7b45318086b26b7e3b8b50be1adc6e1906e08 (diff)
downloadNeodymium-cd5305c6a383ebb8bf530d0f909c2d32c2ab6723.tar.gz
Neodymium-cd5305c6a383ebb8bf530d0f909c2d32c2ab6723.tar.bz2
Neodymium-cd5305c6a383ebb8bf530d0f909c2d32c2ab6723.zip
Add FastCraft compat by pretending to be OptiFine
Diffstat (limited to 'src/main/java/makamys')
-rw-r--r--src/main/java/makamys/neodymium/Compat.java36
-rw-r--r--src/main/java/makamys/neodymium/Constants.java13
-rw-r--r--src/main/java/makamys/neodymium/MixinConfigPlugin.java36
-rw-r--r--src/main/java/makamys/neodymium/util/virtualjar/IVirtualJar.java11
-rw-r--r--src/main/java/makamys/neodymium/util/virtualjar/URLStreamHandlerHelper.java49
-rw-r--r--src/main/java/makamys/neodymium/util/virtualjar/VirtualJar.java100
-rw-r--r--src/main/java/makamys/neodymium/util/virtualjar/protocol/neodymiumvirtualjar/Handler.java24
7 files changed, 252 insertions, 17 deletions
diff --git a/src/main/java/makamys/neodymium/Compat.java b/src/main/java/makamys/neodymium/Compat.java
index 56b5360..35eac6b 100644
--- a/src/main/java/makamys/neodymium/Compat.java
+++ b/src/main/java/makamys/neodymium/Compat.java
@@ -2,6 +2,8 @@ package makamys.neodymium;
import static makamys.neodymium.Neodymium.LOGGER;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
import java.util.List;
import org.lwjgl.opengl.GLContext;
@@ -9,6 +11,8 @@ import org.lwjgl.opengl.GLContext;
import com.falsepattern.triangulator.api.ToggleableTessellator;
import cpw.mods.fml.common.Loader;
import makamys.neodymium.util.OFUtil;
+import makamys.neodymium.util.virtualjar.IVirtualJar;
+import makamys.neodymium.util.virtualjar.VirtualJar;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Tessellator;
@@ -31,10 +35,6 @@ public class Compat {
warns.add("Advanced OpenGL is enabled, performance may be poor.");
}
- if(Loader.isModLoaded("FastCraft") && !OFUtil.isOptiFinePresent()) {
- criticalWarns.add("FastCraft is present without OptiFine, this is not supported.");
- }
-
try {
Class<?> shaders = Class.forName("shadersmod.client.Shaders");
try {
@@ -66,4 +66,32 @@ public class Compat {
return changed;
}
+
+ public static void forceEnableOptiFineDetectionOfFastCraft() {
+ if(Compat.class.getResource("/fastcraft/Tweaker.class") != null) {
+ // If OptiFine is present, it's already on the class path at this point, so our virtual jar won't override it.
+ LOGGER.info("FastCraft is present, applying hack to forcingly enable FastCraft's OptiFine compat");
+ VirtualJar.add(new OptiFineStubVirtualJar());
+ }
+ }
+
+ private static class OptiFineStubVirtualJar implements IVirtualJar {
+
+ @Override
+ public String getName() {
+ return "optifine-stub";
+ }
+
+ @Override
+ public InputStream getInputStream(String path) {
+ if(path.equals("/optifine/OptiFineForgeTweaker.class")) {
+ // Dummy file to make FastCraft think OptiFine is present.
+ LOGGER.info("Returning a dummy /optifine/OptiFineForgeTweaker.class to force FastCraft compat.");
+ return new ByteArrayInputStream(new byte[0]);
+ } else {
+ return null;
+ }
+ }
+
+ }
}
diff --git a/src/main/java/makamys/neodymium/Constants.java b/src/main/java/makamys/neodymium/Constants.java
new file mode 100644
index 0000000..f8eb12b
--- /dev/null
+++ b/src/main/java/makamys/neodymium/Constants.java
@@ -0,0 +1,13 @@
+package makamys.neodymium;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class Constants {
+
+ public static final String MODID = "neodymium";
+ public static final Logger LOGGER = LogManager.getLogger(MODID);
+
+ public static final String PROTOCOL = "neodymiumvirtualjar";
+
+}
diff --git a/src/main/java/makamys/neodymium/MixinConfigPlugin.java b/src/main/java/makamys/neodymium/MixinConfigPlugin.java
index 678fadd..df3c76c 100644
--- a/src/main/java/makamys/neodymium/MixinConfigPlugin.java
+++ b/src/main/java/makamys/neodymium/MixinConfigPlugin.java
@@ -6,6 +6,8 @@ import java.util.List;
import java.util.Set;
import org.spongepowered.asm.lib.tree.ClassNode;
+import org.spongepowered.asm.mixin.MixinEnvironment;
+import org.spongepowered.asm.mixin.MixinEnvironment.Phase;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
@@ -17,6 +19,11 @@ public class MixinConfigPlugin implements IMixinConfigPlugin {
@Override
public void onLoad(String mixinPackage) {
Config.reloadConfig();
+
+ Phase phase = MixinEnvironment.getCurrentEnvironment().getPhase();
+ if(phase == Phase.INIT) {
+ Compat.forceEnableOptiFineDetectionOfFastCraft();
+ }
}
@Override
@@ -35,19 +42,22 @@ public class MixinConfigPlugin implements IMixinConfigPlugin {
@Override
public List<String> getMixins() {
List<String> mixins = new ArrayList<>();
- mixins.addAll(Arrays.asList(
- "MixinRenderGlobal",
- "MixinWorldRenderer",
- "MixinTessellator"));
-
- if (OFUtil.isOptiFinePresent()) {
- System.out.println("Detected OptiFine");
- mixins.add("MixinRenderGlobal_OptiFine");
- mixins.add("MixinGameSettings_OptiFine");
- }
-
- if(Config.replaceOpenGLSplash) {
- mixins.add("MixinGuiMainMenu");
+ Phase phase = MixinEnvironment.getCurrentEnvironment().getPhase();
+ if(phase == Phase.DEFAULT) {
+ mixins.addAll(Arrays.asList(
+ "MixinRenderGlobal",
+ "MixinWorldRenderer",
+ "MixinTessellator"));
+
+ if (OFUtil.isOptiFinePresent()) {
+ System.out.println("Detected OptiFine");
+ mixins.add("MixinRenderGlobal_OptiFine");
+ mixins.add("MixinGameSettings_OptiFine");
+ }
+
+ if(Config.replaceOpenGLSplash) {
+ mixins.add("MixinGuiMainMenu");
+ }
}
return mixins;
diff --git a/src/main/java/makamys/neodymium/util/virtualjar/IVirtualJar.java b/src/main/java/makamys/neodymium/util/virtualjar/IVirtualJar.java
new file mode 100644
index 0000000..11cef7e
--- /dev/null
+++ b/src/main/java/makamys/neodymium/util/virtualjar/IVirtualJar.java
@@ -0,0 +1,11 @@
+package makamys.neodymium.util.virtualjar;
+
+import java.io.InputStream;
+
+public interface IVirtualJar {
+
+ public String getName();
+
+ public InputStream getInputStream(String path);
+
+}
diff --git a/src/main/java/makamys/neodymium/util/virtualjar/URLStreamHandlerHelper.java b/src/main/java/makamys/neodymium/util/virtualjar/URLStreamHandlerHelper.java
new file mode 100644
index 0000000..7a8bef6
--- /dev/null
+++ b/src/main/java/makamys/neodymium/util/virtualjar/URLStreamHandlerHelper.java
@@ -0,0 +1,49 @@
+// From jimfs, adapted into a helper class
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package makamys.neodymium.util.virtualjar;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.net.URLStreamHandler;
+
+public class URLStreamHandlerHelper {
+
+ private static final String JAVA_PROTOCOL_HANDLER_PACKAGES = "java.protocol.handler.pkgs";
+
+ /**
+ * Generic method that would allow registration of any properly placed {@code Handler} class.
+ */
+ public static void register(Class<? extends URLStreamHandler> handlerClass) {
+ checkArgument("Handler".equals(handlerClass.getSimpleName()));
+
+ String pkg = handlerClass.getPackage().getName();
+ int lastDot = pkg.lastIndexOf('.');
+ checkArgument(lastDot > 0, "package for Handler (%s) must have a parent package", pkg);
+
+ String parentPackage = pkg.substring(0, lastDot);
+
+ String packages = System.getProperty(JAVA_PROTOCOL_HANDLER_PACKAGES);
+ if (packages == null) {
+ packages = parentPackage;
+ } else {
+ packages += "|" + parentPackage;
+ }
+ System.setProperty(JAVA_PROTOCOL_HANDLER_PACKAGES, packages);
+ }
+
+}
diff --git a/src/main/java/makamys/neodymium/util/virtualjar/VirtualJar.java b/src/main/java/makamys/neodymium/util/virtualjar/VirtualJar.java
new file mode 100644
index 0000000..8350d6f
--- /dev/null
+++ b/src/main/java/makamys/neodymium/util/virtualjar/VirtualJar.java
@@ -0,0 +1,100 @@
+package makamys.neodymium.util.virtualjar;
+
+import static makamys.neodymium.Constants.MODID;
+import static makamys.neodymium.Constants.PROTOCOL;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashMap;
+import java.util.Map;
+
+import static makamys.neodymium.Constants.LOGGER;
+
+import makamys.neodymium.util.virtualjar.protocol.neodymiumvirtualjar.Handler;
+import net.minecraft.launchwrapper.Launch;
+
+
+public class VirtualJar {
+
+ private static boolean registered;
+
+ private static Map<String, IVirtualJar> jars = new HashMap<>();
+
+ public static void registerHandler() {
+ if(registered) return;
+
+ LOGGER.debug("Registering URL protocol handler: " + PROTOCOL);
+
+ // We want the Handler to always be loaded by the same class loader.
+ Launch.classLoader.addClassLoaderExclusion("makamys." + MODID + ".util.virtualjar.protocol." + PROTOCOL);
+
+ // The Handler is loaded by the AppClassLoader, but it needs to access the state of VirtualJar, which is loaded
+ // by the LaunchClassLoader. The solution? Make the Handler just a proxy that delegates the real work to
+ // VirtualJar.StreamHandlerImpl. We use the blackboard as a class loader-agnostic way of sharing information.
+ Handler.IURLStreamHandlerImpl streamHandlerImpl = new StreamHandlerImpl();
+ Launch.blackboard.put(MODID + "." + PROTOCOL + ".impl", streamHandlerImpl);
+ URLStreamHandlerHelper.register(Handler.class);
+
+ registered = true;
+ }
+
+ public static void add(IVirtualJar jar) {
+ registerHandler();
+
+ LOGGER.trace("Adding virtual jar to class path: " + PROTOCOL + ":" + jar.getName() + ".jar");
+
+ String urlStr = PROTOCOL + ":" + jar.getName() + ".jar!/";
+
+ try {
+ URL url = new URL(urlStr);
+ Launch.classLoader.addURL(url);
+ // Forge expects all URLs in the sources list to be convertible to File objects, so we must remove it to
+ // avoid a crash.
+ Launch.classLoader.getSources().remove(url);
+
+ jars.put(jar.getName(), jar);
+ } catch(MalformedURLException e) {
+ LOGGER.fatal("Failed to add virtual jar to class path");
+ e.printStackTrace();
+ }
+ }
+
+ public static class StreamHandlerImpl implements Handler.IURLStreamHandlerImpl {
+
+ @Override
+ public URLConnection openConnection(URL url) {
+ return new URLConnection(url) {
+ public void connect() {
+
+ }
+
+ public Object getContent() throws IOException {
+ return super.getContent();
+ }
+
+ public String getHeaderField(String name) {
+ return super.getHeaderField(name);
+ }
+
+ public InputStream getInputStream() {
+ String path = getURL().getPath();
+ String nameSuffix = ".jar!";
+ int nameEnd = path.indexOf(nameSuffix);
+ String name = path.substring(0, nameEnd);
+
+ IVirtualJar jar = jars.get(name);
+
+ return jar.getInputStream(path.substring(nameEnd + nameSuffix.length()));
+ }
+
+ public java.io.OutputStream getOutputStream() throws IOException {
+ return super.getOutputStream();
+ }
+ };
+ }
+ }
+
+}
diff --git a/src/main/java/makamys/neodymium/util/virtualjar/protocol/neodymiumvirtualjar/Handler.java b/src/main/java/makamys/neodymium/util/virtualjar/protocol/neodymiumvirtualjar/Handler.java
new file mode 100644
index 0000000..9f0fe66
--- /dev/null
+++ b/src/main/java/makamys/neodymium/util/virtualjar/protocol/neodymiumvirtualjar/Handler.java
@@ -0,0 +1,24 @@
+package makamys.neodymium.util.virtualjar.protocol.neodymiumvirtualjar;
+
+import static makamys.neodymium.Constants.MODID;
+import static makamys.neodymium.Constants.PROTOCOL;
+
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+import net.minecraft.launchwrapper.Launch;
+
+public class Handler extends URLStreamHandler {
+
+ private static final IURLStreamHandlerImpl impl = (IURLStreamHandlerImpl)Launch.blackboard.get(MODID + "." + PROTOCOL + ".impl");
+
+ @Override
+ protected URLConnection openConnection(URL url) {
+ return impl.openConnection(url);
+ }
+
+ public interface IURLStreamHandlerImpl {
+ URLConnection openConnection(URL url);
+ }
+}