From cdaf2fcbdd64efe7e1a90ca901fcfe9f77c22914 Mon Sep 17 00:00:00 2001 From: Rizato Date: Wed, 21 Jun 2023 10:40:59 -0400 Subject: [PATCH 1/3] Add 1.9.0 SteamSharedLibraryLoader as SteamLibraryLoaderLegacy Restores the mac & gradle compatible loader from previous versions as a legacy loader. Uses the new SteamLibraryLoader interface --- loader/legacy/pom.xml | 156 ++++++++++ .../steamworks/SteamLibraryLoaderLegacy.java | 273 ++++++++++++++++++ pom.xml | 1 + tests/pom.xml | 5 + .../steamworks/test/SteamTestApp.java | 4 + 5 files changed, 439 insertions(+) create mode 100644 loader/legacy/pom.xml create mode 100644 loader/legacy/src/main/java/com/codedisaster/steamworks/SteamLibraryLoaderLegacy.java diff --git a/loader/legacy/pom.xml b/loader/legacy/pom.xml new file mode 100644 index 00000000..83e1c500 --- /dev/null +++ b/loader/legacy/pom.xml @@ -0,0 +1,156 @@ + + + 4.0.0 + + com.code-disaster.steamworks4j + steamworks4j-legacy + 1.10.0-SNAPSHOT + + jar + + Steam API Java Wrapper - Legacy library loader + Java wrapper to access the Steamworks API. + http://github.com/code-disaster/steamworks4j + + + http://github.com/code-disaster/steamworks4j/issues + + + + + MIT License + http://www.opensource.org/licenses/mit-license.php + + + + + + Daniel Ludwig + codi@code-disaster.com + +1 + + + + + scm:git:https://github.com/code-disaster/steamworks4j.git + scm:git:https://github.com/code-disaster/steamworks4j.git + http://github.com/code-disaster/steamworks4j + + + + + release + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.0.1 + + + sign-artifacts + verify + + sign + + + + + + + + + snapshot + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + + + java-8-api + + [9,) + + + 8 + + + + + + UTF-8 + UTF-8 + + + + + com.code-disaster.steamworks4j + steamworks4j + 1.10.0-SNAPSHOT + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + + + maven-compiler-plugin + 3.11.0 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-source-plugin + 3.3.0 + + true + + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.5.0 + + + attach-javadocs + + jar + + + none + + + + + + + diff --git a/loader/legacy/src/main/java/com/codedisaster/steamworks/SteamLibraryLoaderLegacy.java b/loader/legacy/src/main/java/com/codedisaster/steamworks/SteamLibraryLoaderLegacy.java new file mode 100644 index 00000000..e36564b3 --- /dev/null +++ b/loader/legacy/src/main/java/com/codedisaster/steamworks/SteamLibraryLoaderLegacy.java @@ -0,0 +1,273 @@ +package com.codedisaster.steamworks; + +import java.io.*; +import java.util.UUID; + +public class SteamLibraryLoaderLegacy implements SteamLibraryLoader { + + enum PLATFORM { + Windows, + Linux, + MacOS + } + + private String libraryPath; + + private static final PLATFORM OS; + private static final boolean IS_64_BIT; + + private static final String SHARED_LIBRARY_EXTRACT_DIRECTORY = System.getProperty( + "com.codedisaster.steamworks.SharedLibraryExtractDirectory", "steamworks4j"); + + private static final String SHARED_LIBRARY_EXTRACT_PATH = System.getProperty( + "com.codedisaster.steamworks.SharedLibraryExtractPath", null); + + private static final String SDK_REDISTRIBUTABLE_BIN_PATH = System.getProperty( + "com.codedisaster.steamworks.SDKRedistributableBinPath", "sdk/redistributable_bin"); + + private static final String SDK_LIBRARY_PATH = System.getProperty( + "com.codedisaster.steamworks.SDKLibraryPath", "sdk/public/steam/lib"); + + static final boolean DEBUG = Boolean.parseBoolean(System.getProperty( + "com.codedisaster.steamworks.Debug", "false")); + + static { + String osName = System.getProperty("os.name"); + String osArch = System.getProperty("os.arch"); + + if (osName.contains("Windows")) { + OS = PLATFORM.Windows; + } else if (osName.contains("Linux")) { + OS = PLATFORM.Linux; + } else if (osName.contains("Mac")) { + OS = PLATFORM.MacOS; + } else { + throw new RuntimeException("Unknown host architecture: " + osName + ", " + osArch); + } + + IS_64_BIT = osArch.equals("amd64") || osArch.equals("x86_64"); + } + + private static String getPlatformLibName(String libName) { + switch (OS) { + case Windows: + return libName + (IS_64_BIT ? "64" : "") + ".dll"; + case Linux: + return "lib" + libName + ".so"; + case MacOS: + return "lib" + libName + ".dylib"; + } + + throw new RuntimeException("Unknown host architecture"); + } + + static String getSdkRedistributableBinPath() { + File path; + switch (OS) { + case Windows: + path = new File(SDK_REDISTRIBUTABLE_BIN_PATH, IS_64_BIT ? "win64" : ""); + break; + case Linux: + path = new File(SDK_REDISTRIBUTABLE_BIN_PATH, "linux64"); + break; + case MacOS: + path = new File(SDK_REDISTRIBUTABLE_BIN_PATH, "osx"); + break; + default: + return null; + } + + return path.exists() ? path.getPath() : null; + } + + static String getSdkLibraryPath() { + File path; + switch (OS) { + case Windows: + path = new File(SDK_LIBRARY_PATH, IS_64_BIT ? "win64" : "win32"); + break; + case Linux: + path = new File(SDK_LIBRARY_PATH, "linux64"); + break; + case MacOS: + path = new File(SDK_LIBRARY_PATH, "osx"); + break; + default: + return null; + } + + return path.exists() ? path.getPath() : null; + } + + @Override + public void setLibraryPath(String libraryPath) { + this.libraryPath = libraryPath; + } + + @Override + public boolean loadLibrary(String libraryName) { + try { + String librarySystemName = getPlatformLibName(libraryName); + + File librarySystemPath = discoverExtractLocation( + SHARED_LIBRARY_EXTRACT_DIRECTORY + "/" + Version.getVersion(), librarySystemName); + + if (libraryPath == null) { + // extract library from resource + extractLibrary(librarySystemPath, librarySystemName); + } else { + // read library from given path + File librarySourcePath = new File(libraryPath, librarySystemName); + + if (OS != PLATFORM.Windows) { + // on MacOS & Linux, "extract" (copy) from source location + extractLibrary(librarySystemPath, librarySourcePath); + } else { + // on Windows, load the library from the source location + librarySystemPath = librarySourcePath; + } + } + + String absolutePath = librarySystemPath.getCanonicalPath(); + System.load(absolutePath); + } catch (IOException e) { + return false; + } + return true; + } + + private static void extractLibrary(File librarySystemPath, String librarySystemName) throws IOException { + extractLibrary(librarySystemPath, + SteamLibraryLoaderLegacy.class.getResourceAsStream("/" + librarySystemName)); + } + + private static void extractLibrary(File librarySystemPath, File librarySourcePath) throws IOException { + extractLibrary(librarySystemPath, new FileInputStream(librarySourcePath)); + } + + private static void extractLibrary(File librarySystemPath, InputStream input) throws IOException { + if (input != null) { + try (FileOutputStream output = new FileOutputStream(librarySystemPath)) { + byte[] buffer = new byte[4096]; + while (true) { + int length = input.read(buffer); + if (length == -1) break; + output.write(buffer, 0, length); + } + output.close(); + } catch (IOException e) { + /* + Extracting the library may fail, for example because 'nativeFile' already exists and is in + use by another process. In this case, we fail silently and just try to load the existing file. + */ + if (!librarySystemPath.exists()) { + throw e; + } + } finally { + input.close(); + } + } else { + throw new IOException("Failed to read input stream for " + librarySystemPath.getCanonicalPath()); + } + } + + private static File discoverExtractLocation(String folderName, String fileName) throws IOException { + + File path; + + // system property + + if (SHARED_LIBRARY_EXTRACT_PATH != null) { + path = new File(SHARED_LIBRARY_EXTRACT_PATH, fileName); + if (canWrite(path)) { + return path; + } + } + + // Java tmpdir + + path = new File(System.getProperty("java.io.tmpdir") + "/" + folderName, fileName); + if (canWrite(path)) { + return path; + } + + // NIO temp file + + try { + File file = File.createTempFile(folderName, null); + if (file.delete()) { + // uses temp file path as destination folder + path = new File(file, fileName); + if (canWrite(path)) { + return path; + } + } + } catch (IOException ignored) { + + } + + // user home + + path = new File(System.getProperty("user.home") + "/." + folderName, fileName); + if (canWrite(path)) { + return path; + } + + // working directory + + path = new File(".tmp/" + folderName, fileName); + if (canWrite(path)) { + return path; + } + + throw new IOException("No suitable extraction path found"); + } + + private static boolean canWrite(File file) { + + File folder = file.getParentFile(); + + if (file.exists()) { + if (!file.canWrite() || !canExecute(file)) { + return false; + } + } else { + if (!folder.exists()) { + if (!folder.mkdirs()) { + return false; + } + } + if (!folder.isDirectory()) { + return false; + } + } + + File testFile = new File(folder, UUID.randomUUID().toString()); + + try { + new FileOutputStream(testFile).close(); + return canExecute(testFile); + } catch (IOException e) { + return false; + } finally { + testFile.delete(); + } + } + + private static boolean canExecute(File file) { + + try { + if (file.canExecute()) { + return true; + } + + if (file.setExecutable(true)) { + return file.canExecute(); + } + } catch (Exception ignored) { + + } + + return false; + } +} diff --git a/pom.xml b/pom.xml index 665a56d8..6b17ff8e 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,7 @@ jnigen loader/gdx loader/lwjgl3 + loader/legacy server tests diff --git a/tests/pom.xml b/tests/pom.xml index 86582b1c..83ecf6d5 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -49,6 +49,11 @@ steamworks4j-lwjgl3 1.10.0-SNAPSHOT + + com.code-disaster.steamworks4j + steamworks4j-legacy + 1.10.0-SNAPSHOT + com.code-disaster.steamworks4j steamworks4j-server diff --git a/tests/src/main/java/com/codedisaster/steamworks/test/SteamTestApp.java b/tests/src/main/java/com/codedisaster/steamworks/test/SteamTestApp.java index 6e6872ca..b6dd5b05 100644 --- a/tests/src/main/java/com/codedisaster/steamworks/test/SteamTestApp.java +++ b/tests/src/main/java/com/codedisaster/steamworks/test/SteamTestApp.java @@ -263,6 +263,10 @@ private static SteamLibraryLoader createLibraryLoader(String[] arguments) { loader = new SteamLibraryLoaderGdx(); break; } + if (arg.equals("--legacy")) { + loader = new SteamLibraryLoaderLegacy(); + break; + } } if (loader == null) { From c65bb6a7be66b7d4f2306d6b3c56f6641bba7f47 Mon Sep 17 00:00:00 2001 From: Rizato Date: Fri, 15 Sep 2023 12:51:10 -0400 Subject: [PATCH 2/3] Set Legacy loader deprecated --- .../com/codedisaster/steamworks/SteamLibraryLoaderLegacy.java | 1 + 1 file changed, 1 insertion(+) diff --git a/loader/legacy/src/main/java/com/codedisaster/steamworks/SteamLibraryLoaderLegacy.java b/loader/legacy/src/main/java/com/codedisaster/steamworks/SteamLibraryLoaderLegacy.java index e36564b3..8c65f51b 100644 --- a/loader/legacy/src/main/java/com/codedisaster/steamworks/SteamLibraryLoaderLegacy.java +++ b/loader/legacy/src/main/java/com/codedisaster/steamworks/SteamLibraryLoaderLegacy.java @@ -3,6 +3,7 @@ import java.io.*; import java.util.UUID; +@Deprecated public class SteamLibraryLoaderLegacy implements SteamLibraryLoader { enum PLATFORM { From 3446406fca371dcf50de0d79f566b12d4ed4652d Mon Sep 17 00:00:00 2001 From: Rizato Date: Fri, 15 Sep 2023 12:51:37 -0400 Subject: [PATCH 3/3] Remove unneeded close() --- .../com/codedisaster/steamworks/SteamLibraryLoaderLegacy.java | 1 - 1 file changed, 1 deletion(-) diff --git a/loader/legacy/src/main/java/com/codedisaster/steamworks/SteamLibraryLoaderLegacy.java b/loader/legacy/src/main/java/com/codedisaster/steamworks/SteamLibraryLoaderLegacy.java index 8c65f51b..21821ff7 100644 --- a/loader/legacy/src/main/java/com/codedisaster/steamworks/SteamLibraryLoaderLegacy.java +++ b/loader/legacy/src/main/java/com/codedisaster/steamworks/SteamLibraryLoaderLegacy.java @@ -155,7 +155,6 @@ private static void extractLibrary(File librarySystemPath, InputStream input) th if (length == -1) break; output.write(buffer, 0, length); } - output.close(); } catch (IOException e) { /* Extracting the library may fail, for example because 'nativeFile' already exists and is in