diff --git a/common/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/Rapier3D.java b/common/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/Rapier3D.java index de0bf136..086acaff 100644 --- a/common/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/Rapier3D.java +++ b/common/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/Rapier3D.java @@ -6,6 +6,7 @@ import dev.ryanhcode.sable.api.physics.mass.MassData; import dev.ryanhcode.sable.mixinterface.physics.ServerLevelSceneExtension; import dev.ryanhcode.sable.physics.impl.rapier.collider.RapierVoxelColliderData; +import dev.ryanhcode.sable.platform.SableLoaderPlatform; import net.jpountz.lz4.LZ4FrameInputStream; import net.minecraft.CrashReport; import net.minecraft.CrashReportCategory; @@ -19,6 +20,7 @@ import java.io.FileNotFoundException; import java.io.InputStream; +import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -32,7 +34,7 @@ @ApiStatus.Internal public class Rapier3D { - private static final String NATIVE_DIR = ".sable/natives"; + private static final Path NATIVE_DIR = resolveNativeDir(); private static final String LIB_NAME = "sable_rapier"; public static final String NATIVE_NAME = getNativeName(); @@ -44,6 +46,23 @@ public class Rapier3D { loadLibrary(); } + private static Path resolveNativeDir() { + // Trying to get game directory + final Path gameDir = SableLoaderPlatform.INSTANCE.getGameDirectory(); + if (gameDir != null) { + final Path gameDirRelativeDir = gameDir.resolve(".sable").resolve("natives").normalize(); + Sable.LOGGER.info("Using game-dir-relative Rapier native directory {}", + gameDirRelativeDir.toAbsolutePath()); + return gameDirRelativeDir; + } + + // Using a bit overly generic ~/.sable directory as a fallback + final Path fallbackDir = Paths.get(System.getProperty("user.home", System.getProperty("user.dir")), ".sable", + "natives"); + Sable.LOGGER.info("Using fallback Rapier native directory {}", fallbackDir.toAbsolutePath()); + return fallbackDir; + } + private static String getNativeName() { final String arch; if (System.getProperty("os.arch").equals("arm") || System.getProperty("os.arch").startsWith("aarch64")) { @@ -71,11 +90,13 @@ private static void loadLibrary() { throw new FileNotFoundException("sable_rapier_binaries.zip.l4z"); } - final Path dir = Paths.get(NATIVE_DIR); + final Path dir = NATIVE_DIR; if (!Files.exists(dir)) { Files.createDirectories(dir); } + Sable.LOGGER.info("Using Rapier native directory {}", dir.toAbsolutePath()); + try (final LZ4FrameInputStream is2 = new LZ4FrameInputStream(is); final ZipInputStream ti = new ZipInputStream(is2)) { diff --git a/common/src/main/java/dev/ryanhcode/sable/platform/SableLoaderPlatform.java b/common/src/main/java/dev/ryanhcode/sable/platform/SableLoaderPlatform.java index 174e3946..5671d445 100644 --- a/common/src/main/java/dev/ryanhcode/sable/platform/SableLoaderPlatform.java +++ b/common/src/main/java/dev/ryanhcode/sable/platform/SableLoaderPlatform.java @@ -1,10 +1,19 @@ package dev.ryanhcode.sable.platform; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.nio.file.Path; @ApiStatus.Internal public interface SableLoaderPlatform { SableLoaderPlatform INSTANCE = SablePlatformUtil.load(SableLoaderPlatform.class); String getModVersion(String modId); + + /** + * @return the absolute game directory for the current loader, or {@code null} if it is unavailable. + */ + @Nullable + Path getGameDirectory(); } diff --git a/fabric/src/main/java/dev/ryanhcode/sable/fabric/platform/SableLoaderPlatformImpl.java b/fabric/src/main/java/dev/ryanhcode/sable/fabric/platform/SableLoaderPlatformImpl.java index c5711e91..dfb9c1cd 100644 --- a/fabric/src/main/java/dev/ryanhcode/sable/fabric/platform/SableLoaderPlatformImpl.java +++ b/fabric/src/main/java/dev/ryanhcode/sable/fabric/platform/SableLoaderPlatformImpl.java @@ -2,6 +2,9 @@ import dev.ryanhcode.sable.platform.SableLoaderPlatform; import net.fabricmc.loader.api.FabricLoader; +import org.jetbrains.annotations.Nullable; + +import java.nio.file.Path; public class SableLoaderPlatformImpl implements SableLoaderPlatform { @Override @@ -13,4 +16,10 @@ public String getModVersion(final String modId) { .getVersion() .getFriendlyString(); } + + @Override + @Nullable + public Path getGameDirectory() { + return FabricLoader.getInstance().getGameDir(); + } } diff --git a/neoforge/src/main/java/dev/ryanhcode/sable/neoforge/platform/SableLoaderPlatformImpl.java b/neoforge/src/main/java/dev/ryanhcode/sable/neoforge/platform/SableLoaderPlatformImpl.java index d06c1563..3432d513 100644 --- a/neoforge/src/main/java/dev/ryanhcode/sable/neoforge/platform/SableLoaderPlatformImpl.java +++ b/neoforge/src/main/java/dev/ryanhcode/sable/neoforge/platform/SableLoaderPlatformImpl.java @@ -1,11 +1,21 @@ package dev.ryanhcode.sable.neoforge.platform; import dev.ryanhcode.sable.platform.SableLoaderPlatform; +import net.neoforged.fml.loading.FMLPaths; import net.neoforged.fml.loading.LoadingModList; +import org.jetbrains.annotations.Nullable; + +import java.nio.file.Path; public class SableLoaderPlatformImpl implements SableLoaderPlatform { @Override public String getModVersion(final String modId) { return LoadingModList.get().getModFileById(modId).versionString(); } + + @Override + @Nullable + public Path getGameDirectory() { + return FMLPaths.GAMEDIR.get(); + } }