Skip to content

Commit

Permalink
Remove Minecraft from classpath of the pre-launch source set
Browse files Browse the repository at this point in the history
This will help to avoid class-load issues and makes the code more
hygienic.
  • Loading branch information
jellysquid3 committed Oct 26, 2024
1 parent 65ff065 commit 24f77ee
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 72 deletions.
16 changes: 15 additions & 1 deletion common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ base {
archivesName = "sodium-common"
}

val configurationPreLaunch = configurations.create("preLaunchDeps") {
isCanBeResolved = true
}

sourceSets {
val main = getByName("main")
val api = create("api")
Expand All @@ -22,7 +26,7 @@ sourceSets {

workarounds.apply {
java {
compileClasspath += main.compileClasspath
compileClasspath += configurationPreLaunch
}
}

Expand Down Expand Up @@ -62,6 +66,16 @@ dependencies {
addDependentFabricModule("fabric-rendering-data-attachment-v1")

modCompileOnly("net.fabricmc.fabric-api:fabric-renderer-api-v1:3.2.9+1172e897d7")

// We need to be careful during pre-launch that we don't touch any Minecraft classes, since other mods
// will not yet have an opportunity to apply transformations.
configurationPreLaunch("org.apache.commons:commons-lang3:3.14.0")
configurationPreLaunch("commons-io:commons-io:2.15.1")
configurationPreLaunch("org.lwjgl:lwjgl:3.3.3")
configurationPreLaunch("net.java.dev.jna:jna:5.14.0")
configurationPreLaunch("net.java.dev.jna:jna-platform:5.14.0")
configurationPreLaunch("org.slf4j:slf4j-api:2.0.9")
configurationPreLaunch("org.jetbrains:annotations:25.0.0")
}

loom {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package net.caffeinemc.mods.sodium.client.compatibility.environment;
package net.caffeinemc.mods.sodium.client.gl;

import org.jetbrains.annotations.Nullable;
import org.lwjgl.opengl.GL11C;

public record GLContextInfo(String vendor, String renderer, String version) {
public record GlContextInfo(String vendor, String renderer, String version) {
@Nullable
public static GLContextInfo create() {

public static GlContextInfo create() {
String vendor = GL11C.glGetString(GL11C.GL_VENDOR);
String renderer = GL11C.glGetString(GL11C.GL_RENDERER);
String version = GL11C.glGetString(GL11C.GL_VERSION);
Expand All @@ -15,6 +14,6 @@ public static GLContextInfo create() {
return null;
}

return new GLContextInfo(vendor, renderer, version);
return new GlContextInfo(vendor, renderer, version);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.mojang.blaze3d.platform.Window;
import net.caffeinemc.mods.sodium.client.platform.NativeWindowHandle;
import net.caffeinemc.mods.sodium.client.SodiumClientMod;
import net.caffeinemc.mods.sodium.client.compatibility.workarounds.Workarounds;
import net.caffeinemc.mods.sodium.client.services.PlatformRuntimeInformation;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWNativeWin32;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(Window.class)
public class WindowMixin {
public class WindowMixin implements NativeWindowHandle {
@Shadow
@Final
private long window;

@WrapOperation(method = "<init>", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwCreateWindow(IILjava/lang/CharSequence;JJ)J"), require = 0)
public long setAdditionalWindowHints(int titleEncoded, int width, CharSequence height, long title, long monitor, Operation<Long> original) {
if (!PlatformRuntimeInformation.getInstance().platformHasEarlyLoadingScreen() && SodiumClientMod.options().performance.useNoErrorGLContext &&
Expand All @@ -22,4 +29,9 @@ public long setAdditionalWindowHints(int titleEncoded, int width, CharSequence h

return original.call(titleEncoded, width, height, title, monitor);
}

@Override
public long getWin32Handle() {
return GLFWNativeWin32.glfwGetWin32Window(this.window);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
import com.mojang.blaze3d.platform.WindowEventHandler;
import net.caffeinemc.mods.sodium.client.compatibility.checks.PostLaunchChecks;
import net.caffeinemc.mods.sodium.client.compatibility.checks.ModuleScanner;
import net.caffeinemc.mods.sodium.client.compatibility.environment.GLContextInfo;
import net.caffeinemc.mods.sodium.client.gl.GlContextInfo;
import net.caffeinemc.mods.sodium.client.compatibility.workarounds.Workarounds;
import net.caffeinemc.mods.sodium.client.compatibility.workarounds.nvidia.NvidiaWorkarounds;
import net.caffeinemc.mods.sodium.client.platform.NativeWindowHandle;
import net.caffeinemc.mods.sodium.client.services.PlatformRuntimeInformation;
import net.minecraft.Util;
import org.lwjgl.glfw.GLFW;
Expand Down Expand Up @@ -81,7 +82,7 @@ private long wrapGlfwCreateWindowForge(final IntSupplier width, final IntSupplie

@Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL;createCapabilities()Lorg/lwjgl/opengl/GLCapabilities;", shift = At.Shift.AFTER))
private void postContextReady(WindowEventHandler eventHandler, ScreenManager monitorTracker, DisplayData settings, String videoMode, String title, CallbackInfo ci) {
GLContextInfo driver = GLContextInfo.create();
GlContextInfo driver = GlContextInfo.create();

if (driver == null) {
LOGGER.warn("Could not retrieve identifying strings for OpenGL implementation");
Expand All @@ -99,7 +100,7 @@ private void postContextReady(WindowEventHandler eventHandler, ScreenManager mon
}

PostLaunchChecks.onContextInitialized();
ModuleScanner.checkModules(this.window);
ModuleScanner.checkModules((NativeWindowHandle) this);
}

@Inject(method = "updateDisplay", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;flipFrame(J)V", shift = At.Shift.AFTER))
Expand All @@ -121,7 +122,7 @@ private void preSwapBuffers(CallbackInfo ci) {

// Likely, this indicates a module was injected into the current process. We should check that
// nothing problematic was just installed.
ModuleScanner.checkModules(this.window);
ModuleScanner.checkModules((NativeWindowHandle) this);

// If we didn't find anything problematic (which would have thrown an exception), then let's just record
// the new context pointer and carry on.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package net.caffeinemc.mods.sodium.client.compatibility.checks;

import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.platform.Window;
import com.sun.jna.Platform;
import com.sun.jna.platform.win32.Kernel32Util;
import com.sun.jna.platform.win32.Tlhelp32;
import net.caffeinemc.mods.sodium.client.platform.MessageBox;
import net.caffeinemc.mods.sodium.client.platform.NativeWindowHandle;
import net.caffeinemc.mods.sodium.client.platform.windows.WindowsFileVersion;
import net.caffeinemc.mods.sodium.client.platform.windows.api.Kernel32;
import net.caffeinemc.mods.sodium.client.platform.windows.api.version.Version;
Expand All @@ -15,6 +13,8 @@

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
Expand All @@ -36,7 +36,7 @@ public class ModuleScanner {
"GTIII-OSD64.dll", "GTIII-OSD.dll"
};

public static void checkModules(long window) {
public static void checkModules(NativeWindowHandle window) {
List<String> modules;

try {
Expand Down Expand Up @@ -67,21 +67,20 @@ public static void checkModules(long window) {

private static List<String> listModules() {
if (!Platform.isWindows()) {
return ImmutableList.of();
} else {
int i = com.sun.jna.platform.win32.Kernel32.INSTANCE.GetCurrentProcessId();
ImmutableList.Builder<String> builder = ImmutableList.builder();
return List.of();
}

for(Tlhelp32.MODULEENTRY32W mODULEENTRY32W : Kernel32Util.getModules(i)) {
String string = mODULEENTRY32W.szModule();
builder.add(string);
}
var pid = com.sun.jna.platform.win32.Kernel32.INSTANCE.GetCurrentProcessId();
var modules = new ArrayList<String>();

return builder.build();
for (var module : Kernel32Util.getModules(pid)) {
modules.add(module.szModule());
}

return Collections.unmodifiableList(modules);
}

private static void checkRTSSModules(long window) {
private static void checkRTSSModules(NativeWindowHandle window) {
LOGGER.warn("RivaTuner Statistics Server (RTSS) has injected into the process! Attempting to apply workarounds for compatibility...");

@Nullable WindowsFileVersion version = null;
Expand Down Expand Up @@ -122,7 +121,7 @@ private static boolean isRTSSCompatible(WindowsFileVersion version) {
return x > 7 || (x == 7 && y > 3) || (x == 7 && y == 3 && z >= 4);
}

private static void checkASUSGpuTweakIII(long window) {
private static void checkASUSGpuTweakIII(NativeWindowHandle window) {
MessageBox.showMessageBox(window, MessageBox.IconType.ERROR, "Sodium Renderer",
"""
ASUS GPU Tweak III is not compatible with Minecraft, and causes extreme performance issues and severe graphical corruption when used with Minecraft.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package net.caffeinemc.mods.sodium.client.compatibility.checks;

import net.caffeinemc.mods.sodium.client.compatibility.workarounds.nvidia.NvidiaDriverVersion;
import net.caffeinemc.mods.sodium.client.console.Console;
import net.caffeinemc.mods.sodium.client.console.message.MessageLevel;
import net.caffeinemc.mods.sodium.client.compatibility.environment.GLContextInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import oshi.PlatformEnum;
import oshi.SystemInfo;

/**
* Performs OpenGL driver validation after the game creates an OpenGL context. This runs immediately after OpenGL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ private static void showCriticalErrorAndClose(String title, String message, Stri
.replace("###HELP_URL###", url == null ? "" : url));

// Try to show a graphical message box (if the platform supports it) and shut down the game.
MessageBox.showMessageBox(0L, MessageBox.IconType.ERROR, title, message, url);
MessageBox.showMessageBox(null, MessageBox.IconType.ERROR, title, message, url);
System.exit(1 /* failure code */);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import net.caffeinemc.mods.sodium.client.compatibility.environment.OsUtils;
import net.caffeinemc.mods.sodium.client.platform.windows.api.d3dkmt.D3DKMT;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import oshi.util.ExecutingCommand;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
Expand Down Expand Up @@ -82,6 +84,10 @@ public static void findAdapters() {
var adapterVendor = GraphicsAdapterVendor.fromPciVendorId(pciVendorId);
var adapterName = getPciDeviceName$Linux(pciVendorId, pciDeviceId);

if (adapterName == null) {
adapterName = "<unknown>";
}

var info = new GraphicsAdapterInfo.LinuxPciAdapterInfo(adapterVendor, adapterName, pciVendorId, pciDeviceId);
results.add(info);
}
Expand All @@ -90,21 +96,39 @@ public static void findAdapters() {
return results;
}

private static @NotNull String getPciDeviceName$Linux(String vendorId, String deviceId) {
private static @Nullable String getPciDeviceName$Linux(String vendorId, String deviceId) {
// The Linux kernel doesn't provide a way to get the device name, so we need to use lspci,
// since it comes with a list of known device names mapped to device IDs.
// See `man lspci` for more information

// [<vendor>]:[<device>][:<class>[:<prog-if>]]
var deviceFilter = vendorId.substring(2) + ":" + deviceId.substring(2);

return ExecutingCommand
.runNative("lspci -vmm -d " + deviceFilter)
.stream()
.filter(line -> line.startsWith("Device:"))
.map(line -> line.substring("Device:".length()).trim())
.findFirst()
.orElse("unknown");
try {
var process = Runtime.getRuntime()
.exec(new String[] { "lspci", "-vmm", "-d", deviceFilter });
var result = process.waitFor();

if (result != 0) {
throw new IOException("lspci exited with error code: %s".formatted(result));
}

try (var reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;

while ((line = reader.readLine()) != null) {
if (line.startsWith("Device:")) {
return line.substring("Device:".length()).trim();
}
}
}

throw new IOException("lspci did not return a device name");
} catch (Throwable e) {
LOGGER.warn("Failed to query PCI device name for %s:%s".formatted(vendorId, deviceId), e);
}

return null;
}

public static Collection<? extends GraphicsAdapterInfo> getAdapters() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package net.caffeinemc.mods.sodium.client.compatibility.environment.probe;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.file.PathUtils;
import org.jetbrains.annotations.NotNull;

public enum GraphicsAdapterVendor {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
package net.caffeinemc.mods.sodium.client.platform;

import net.caffeinemc.mods.sodium.client.compatibility.environment.OsUtils;
import net.caffeinemc.mods.sodium.client.platform.windows.api.msgbox.MsgBoxParamSw;
import net.caffeinemc.mods.sodium.client.platform.windows.api.msgbox.MsgBoxCallback;
import net.caffeinemc.mods.sodium.client.platform.windows.api.User32;
import net.caffeinemc.mods.sodium.client.platform.windows.api.msgbox.MsgBoxCallback;
import net.caffeinemc.mods.sodium.client.platform.windows.api.msgbox.MsgBoxParamSw;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFWNativeWin32;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.util.tinyfd.TinyFileDialogs;

import java.awt.*;
import java.io.IOException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Locale;
import java.util.Objects;

public class MessageBox {
private static final @Nullable MessageBoxImpl IMPL = MessageBoxImpl.chooseImpl();

public static void showMessageBox(long window,
public static void showMessageBox(NativeWindowHandle window,
IconType icon, String title,
String description,
@Nullable String helpUrl)
Expand All @@ -41,33 +38,15 @@ private interface MessageBoxImpl {
}
}

void showMessageBox(long window,
void showMessageBox(NativeWindowHandle window,
IconType icon, String title,
String description,
@Nullable String helpUrl);
}

private static class TFDMessageBoxImpl implements MessageBoxImpl {
// This adds information about how to open the help box, since we cannot change the buttons.
private static final String NOTICE = "\n\nFor more information, click OK; otherwise, click Cancel.";

@Override
public void showMessageBox(long window, IconType icon, String title, String description, @Nullable String helpUrl) {
boolean clicked = TinyFileDialogs.tinyfd_messageBox(title, helpUrl == null ? description : description + NOTICE, helpUrl == null ? "ok" : "okcancel", icon.name().toLowerCase(Locale.ROOT), false);

if (clicked && helpUrl != null) {
try {
Desktop.getDesktop().browse(URI.create(helpUrl));
} catch (IOException e) {
System.out.println("Failed to open! Giving up.");
}
}
}
}

private static class WindowsMessageBoxImpl implements MessageBoxImpl {
@Override
public void showMessageBox(long window,
public void showMessageBox(NativeWindowHandle window,
IconType icon, String title,
String description,
@Nullable String helpUrl) {
Expand All @@ -91,8 +70,8 @@ public void showMessageBox(long window,

final long hWndOwner;

if (window != 0L) {
hWndOwner = GLFWNativeWin32.glfwGetWin32Window(window);
if (window != null) {
hWndOwner = window.getWin32Handle();
} else {
hWndOwner = MemoryUtil.NULL;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package net.caffeinemc.mods.sodium.client.platform;

public interface NativeWindowHandle {
long getWin32Handle();
}
Loading

0 comments on commit 24f77ee

Please sign in to comment.