diff --git a/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/MinecraftGameProvider.java b/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/MinecraftGameProvider.java index c4f714034..a2c739aca 100644 --- a/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/MinecraftGameProvider.java +++ b/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/MinecraftGameProvider.java @@ -77,6 +77,7 @@ public class MinecraftGameProvider implements GameProvider { private EnvType envType; private String entrypoint; + private boolean usesApplet; private Arguments arguments; private final List gameJars = new ArrayList<>(2); // env game jar and potentially common game jar private Path realmsJar; @@ -87,6 +88,8 @@ public class MinecraftGameProvider implements GameProvider { private Collection validParentClassPath; // computed parent class path restriction (loader+deps) private McVersion versionData; private boolean hasModLoader = false; + private Set gameTransforms; + private Set modTransforms; private final GameTransformer transformer = new GameTransformer( new EntrypointPatch(this), @@ -164,19 +167,12 @@ public Set getBuiltinTransforms(String className) { || className.indexOf('.') < 0; // obf classes if (isMinecraftClass) { - if (FabricLoaderImpl.INSTANCE.isDevelopmentEnvironment()) { // combined client+server jar, strip back down to production equivalent - return TRANSFORM_WIDENALL_STRIPENV_CLASSTWEAKS; - } else { // environment specific jar, inherently env stripped - return TRANSFORM_WIDENALL_CLASSTWEAKS; - } - } else { // mod class TODO: exclude game libs - return TRANSFORM_STRIPENV; + return gameTransforms; } - } - private static final Set TRANSFORM_WIDENALL_STRIPENV_CLASSTWEAKS = EnumSet.of(BuiltinTransform.WIDEN_ALL_PACKAGE_ACCESS, BuiltinTransform.STRIP_ENVIRONMENT, BuiltinTransform.CLASS_TWEAKS); - private static final Set TRANSFORM_WIDENALL_CLASSTWEAKS = EnumSet.of(BuiltinTransform.WIDEN_ALL_PACKAGE_ACCESS, BuiltinTransform.CLASS_TWEAKS); - private static final Set TRANSFORM_STRIPENV = EnumSet.of(BuiltinTransform.STRIP_ENVIRONMENT); + // mod class TODO: exclude game libs + return modTransforms; + } @Override public boolean isEnabled() { @@ -234,10 +230,14 @@ public boolean locateGame(FabricLauncher launcher, String[] args) { } entrypoint = classifier.getClassName(envGameLib); + usesApplet = envType == EnvType.CLIENT && entrypoint != null && entrypoint.contains("Applet"); realmsJar = classifier.getOrigin(McLibrary.REALMS); hasModLoader = classifier.has(McLibrary.MODLOADER); log4jAvailable = classifier.has(McLibrary.LOG4J_API) && classifier.has(McLibrary.LOG4J_CORE); slf4jAvailable = classifier.has(McLibrary.SLF4J_API) && classifier.has(McLibrary.SLF4J_CORE); + gameTransforms = getGameTransforms(FabricLoaderImpl.INSTANCE.isDevelopmentEnvironment(), usesApplet); + modTransforms = EnumSet.of(BuiltinTransform.STRIP_ENVIRONMENT); + boolean hasLogLib = log4jAvailable || slf4jAvailable; Log.configureBuiltin(hasLogLib, !hasLogLib); @@ -489,7 +489,7 @@ public void unlockClassPath(FabricLauncher launcher) { public void launch(ClassLoader loader) { String targetClass = entrypoint; - if (envType == EnvType.CLIENT && targetClass.contains("Applet")) { + if (usesApplet) { targetClass = "net.fabricmc.loader.impl.game.minecraft.applet.AppletMain"; } @@ -508,4 +508,18 @@ public void launch(ClassLoader loader) { throw FormattedException.ofLocalized("exception.minecraft.generic", t); } } + + private static Set getGameTransforms(boolean devEnv, boolean applet) { + EnumSet transforms = EnumSet.of(BuiltinTransform.WIDEN_ALL_PACKAGE_ACCESS, BuiltinTransform.CLASS_TWEAKS); + + if (devEnv) { + transforms.add(BuiltinTransform.STRIP_ENVIRONMENT); + } + + if (applet) { + transforms.add(BuiltinTransform.MINECRAFT_APPLET_STUB); + } + + return Collections.unmodifiableSet(transforms); + } } diff --git a/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/applet/AppletLauncher.java b/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/applet/AppletLauncher.java index ed4c0adc0..01fb2f2aa 100644 --- a/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/applet/AppletLauncher.java +++ b/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/applet/AppletLauncher.java @@ -16,8 +16,6 @@ package net.fabricmc.loader.impl.game.minecraft.applet; -import java.applet.Applet; -import java.applet.AppletStub; import java.awt.BorderLayout; import java.awt.Dimension; import java.io.File; @@ -28,6 +26,8 @@ import java.util.Map; import net.fabricmc.loader.impl.game.minecraft.Hooks; +import net.fabricmc.loader.impl.game.minecraft.applet.stub.Applet; +import net.fabricmc.loader.impl.game.minecraft.applet.stub.AppletStub; import net.fabricmc.loader.impl.launch.FabricLauncherBase; /** @@ -38,7 +38,6 @@ * *

It has been adapted here for the purposes of the Fabric loader. */ -@SuppressWarnings("serial") public class AppletLauncher extends Applet implements AppletStub { public static File gameDir; @@ -95,11 +94,6 @@ public void replace(Applet applet) { } } - @Override - public void appletResize(int width, int height) { - mcApplet.resize(width, height); - } - @Override public void resize(int width, int height) { mcApplet.resize(width, height); diff --git a/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/applet/AppletMain.java b/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/applet/AppletMain.java index 3e7eb627e..f545cf221 100644 --- a/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/applet/AppletMain.java +++ b/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/applet/AppletMain.java @@ -35,6 +35,9 @@ public static File hookGameDir(File file) { } public static void main(String[] args) { + // Fix for border when using a HiDPI display + System.setProperty("sun.java2d.uiScale", "1.0"); + java.awt.EventQueue.invokeLater(new AppletMain(args)); } diff --git a/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/applet/stub/Applet.java b/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/applet/stub/Applet.java new file mode 100644 index 000000000..29bf9fe71 --- /dev/null +++ b/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/applet/stub/Applet.java @@ -0,0 +1,101 @@ +/* + * Copyright 2016 FabricMC + * + * 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 net.fabricmc.loader.impl.game.minecraft.applet.stub; + +import java.awt.Dimension; +import java.awt.Panel; +import java.net.URL; +import java.util.Locale; + +import org.jetbrains.annotations.Nullable; + +import net.fabricmc.loader.impl.game.minecraft.applet.AppletLauncher; + +/** + * A minimal stub implementation of an Applet, just enough to make Minecraft happy. + */ +public class Applet extends Panel { + private @Nullable AppletLauncher appletLauncher; + + public final void setStub(AppletLauncher appletLauncher) { + this.appletLauncher = appletLauncher; + } + + public boolean isActive() { + if (appletLauncher != null) { + return appletLauncher.isActive(); + } else { + return false; + } + } + + public URL getDocumentBase() { + return appletLauncher.getDocumentBase(); + } + + public URL getCodeBase() { + return appletLauncher.getCodeBase(); + } + + public String getParameter(String name) { + return appletLauncher.getParameter(name); + } + + @SuppressWarnings("deprecation") + @Override + public void resize(int width, int height) { + Dimension d = size(); + + if ((d.width != width) || (d.height != height)) { + super.resize(width, height); + } + } + + @SuppressWarnings("deprecation") + @Override + public void resize(Dimension d) { + resize(d.width, d.height); + } + + @Override + public boolean isValidateRoot() { + return true; + } + + @Override + public Locale getLocale() { + Locale locale = super.getLocale(); + + if (locale == null) { + return Locale.getDefault(); + } + + return locale; + } + + public void init() { + } + + public void start() { + } + + public void stop() { + } + + public void destroy() { + } +} diff --git a/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/applet/stub/AppletStub.java b/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/applet/stub/AppletStub.java new file mode 100644 index 000000000..33ad2031b --- /dev/null +++ b/minecraft/src/main/java/net/fabricmc/loader/impl/game/minecraft/applet/stub/AppletStub.java @@ -0,0 +1,20 @@ +/* + * Copyright 2016 FabricMC + * + * 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 net.fabricmc.loader.impl.game.minecraft.applet.stub; + +public interface AppletStub { +} diff --git a/src/main/java/net/fabricmc/loader/impl/game/GameProvider.java b/src/main/java/net/fabricmc/loader/impl/game/GameProvider.java index 464ed75c2..41791c6b5 100644 --- a/src/main/java/net/fabricmc/loader/impl/game/GameProvider.java +++ b/src/main/java/net/fabricmc/loader/impl/game/GameProvider.java @@ -57,6 +57,10 @@ enum BuiltinTransform { * Applies class tweakers, including access wideners, as supplied by mods. */ CLASS_TWEAKS, + /** + * Redirect Java applet usage to Fabric Loader's own stub classes, used to support Java 26+ for Minecraft versions that use applets. + */ + MINECRAFT_APPLET_STUB, } boolean isEnabled(); diff --git a/src/main/java/net/fabricmc/loader/impl/transformer/FabricTransformer.java b/src/main/java/net/fabricmc/loader/impl/transformer/FabricTransformer.java index 9085f4eab..2818cbf69 100644 --- a/src/main/java/net/fabricmc/loader/impl/transformer/FabricTransformer.java +++ b/src/main/java/net/fabricmc/loader/impl/transformer/FabricTransformer.java @@ -34,8 +34,9 @@ public static byte[] transform(boolean isDevelopment, EnvType envType, String na boolean transformAccess = transforms.contains(BuiltinTransform.WIDEN_ALL_PACKAGE_ACCESS) && FabricLauncherBase.getLauncher().getMappingConfiguration().requiresPackageAccessHack(); boolean environmentStrip = transforms.contains(BuiltinTransform.STRIP_ENVIRONMENT); boolean applyAccessWidener = transforms.contains(BuiltinTransform.CLASS_TWEAKS) && FabricLoaderImpl.INSTANCE.getAccessWidener().getTargets().contains(name); + boolean appletStub = transforms.contains(BuiltinTransform.MINECRAFT_APPLET_STUB); - if (!transformAccess && !environmentStrip && !applyAccessWidener) { + if (!transformAccess && !environmentStrip && !applyAccessWidener && !appletStub) { return bytes; } @@ -68,6 +69,11 @@ public static byte[] transform(boolean isDevelopment, EnvType envType, String na } } + if (appletStub) { + visitor = new MinecraftAppletTransformer(visitor); + visitorCount++; + } + if (visitorCount <= 0) { return bytes; } diff --git a/src/main/java/net/fabricmc/loader/impl/transformer/MinecraftAppletTransformer.java b/src/main/java/net/fabricmc/loader/impl/transformer/MinecraftAppletTransformer.java new file mode 100644 index 000000000..fd5e83c9a --- /dev/null +++ b/src/main/java/net/fabricmc/loader/impl/transformer/MinecraftAppletTransformer.java @@ -0,0 +1,46 @@ +/* + * Copyright 2016 FabricMC + * + * 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 net.fabricmc.loader.impl.transformer; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.commons.ClassRemapper; +import org.objectweb.asm.commons.Remapper; +import org.objectweb.asm.commons.SimpleRemapper; + +import net.fabricmc.loader.impl.FabricLoaderImpl; + +public class MinecraftAppletTransformer extends ClassRemapper { + private static final Remapper REMAPPER = new SimpleRemapper(getRenames()); + + private static Map getRenames() { + Map renames = new HashMap<>(); + + // TODO move this transformer into the minecraft specific code. + renames.put("java/applet/Applet", "net/fabricmc/loader/impl/game/minecraft/applet/stub/Applet"); + renames.put("java/applet/AppletStub", "net/fabricmc/loader/impl/game/minecraft/applet/stub/AppletStub"); + + return Collections.unmodifiableMap(renames); + } + + public MinecraftAppletTransformer(ClassVisitor classVisitor) { + super(FabricLoaderImpl.ASM_VERSION, classVisitor, REMAPPER); + } +}