Follow-up to #126.
- Fix the XDG directory flag that got removed with JarSplice. To enable XDG directories, set the 'Use-XDG' property in either build file to 'true'. - Always re-build jars in the Gradle script (disable "up to date" for the task). - Delete JarSplicePlus.jar since it's no longer being used. Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
parent
fdf8e3caf3
commit
b54886a379
23
README.md
23
README.md
|
@ -40,22 +40,19 @@ the song menu.
|
||||||
## Building
|
## Building
|
||||||
opsu! is distributed as both a Maven and Gradle project.
|
opsu! is distributed as both a Maven and Gradle project.
|
||||||
|
|
||||||
|
### Maven
|
||||||
|
Maven builds are built to the `target` directory.
|
||||||
|
* To run the project, execute the Maven goal `compile`.
|
||||||
|
* To create a single executable JAR file, execute the Maven goal `package -Djar`.
|
||||||
|
This will compile a jar to `target/opsu-${version}.jar` with the libraries,
|
||||||
|
resources and natives packed inside the jar.
|
||||||
|
|
||||||
### Gradle
|
### Gradle
|
||||||
Gradle builds are built to the `build` directory.
|
Gradle builds are built to the `build` directory.
|
||||||
* To run the project, execute the Gradle task `run`.
|
* To run the project, execute the Gradle task `run`.
|
||||||
* To create a single executable JAR file, execute the Gradle task
|
* To create a single executable JAR file, execute the Gradle task `build`.
|
||||||
`build`. This will compile a jar to `build/libs/opsu-${version}.jar` with
|
This will compile a jar to `build/libs/opsu-${version}.jar` with the libraries,
|
||||||
the libraries, resources and natives packed inside the jar.
|
resources and natives packed inside the jar.
|
||||||
|
|
||||||
### Maven
|
|
||||||
Maven builds are built to the `target` directory.
|
|
||||||
* To run the project, execute the Maven goal `compile exec:exec`.
|
|
||||||
* To create a single executable JAR file, execute the Maven goal
|
|
||||||
`install -Djar`. This will link the LWJGL native libraries using a
|
|
||||||
[modified version](https://github.com/itdelatrisu/JarSplicePlus) of
|
|
||||||
[JarSplice](http://ninjacave.com/jarsplice), which is included in the
|
|
||||||
`tools` directory in both its original and modified forms. The resulting
|
|
||||||
file will be located in `target/opsu-${version}-runnable.jar`.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
This software was created by Jeffrey Han
|
This software was created by Jeffrey Han
|
||||||
|
|
|
@ -12,6 +12,8 @@ version = '0.10.1'
|
||||||
mainClassName = 'itdelatrisu.opsu.Opsu'
|
mainClassName = 'itdelatrisu.opsu.Opsu'
|
||||||
buildDir = new File(rootProject.projectDir, "build/")
|
buildDir = new File(rootProject.projectDir, "build/")
|
||||||
|
|
||||||
|
def useXDG = 'false'
|
||||||
|
|
||||||
sourceCompatibility = 1.7
|
sourceCompatibility = 1.7
|
||||||
targetCompatibility = 1.7
|
targetCompatibility = 1.7
|
||||||
|
|
||||||
|
@ -43,8 +45,6 @@ dependencies {
|
||||||
compile 'org.apache.commons:commons-compress:1.9'
|
compile 'org.apache.commons:commons-compress:1.9'
|
||||||
compile 'org.tukaani:xz:1.5'
|
compile 'org.tukaani:xz:1.5'
|
||||||
compile 'com.github.jponge:lzma-java:1.3'
|
compile 'com.github.jponge:lzma-java:1.3'
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def nativePlatforms = ['windows', 'linux', 'osx']
|
def nativePlatforms = ['windows', 'linux', 'osx']
|
||||||
|
@ -84,7 +84,8 @@ jar {
|
||||||
manifest {
|
manifest {
|
||||||
attributes 'Implementation-Title': 'opsu!',
|
attributes 'Implementation-Title': 'opsu!',
|
||||||
'Implementation-Version': version,
|
'Implementation-Version': version,
|
||||||
'Main-Class': mainClassName
|
'Main-Class': mainClassName,
|
||||||
|
'Use-XDG': useXDG
|
||||||
}
|
}
|
||||||
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
|
@ -92,6 +93,8 @@ jar {
|
||||||
|
|
||||||
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
|
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
|
||||||
exclude '**/Thumbs.db'
|
exclude '**/Thumbs.db'
|
||||||
|
|
||||||
|
outputs.upToDateWhen { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
run {
|
run {
|
||||||
|
|
6
pom.xml
6
pom.xml
|
@ -9,6 +9,7 @@
|
||||||
<timestamp>${maven.build.timestamp}</timestamp>
|
<timestamp>${maven.build.timestamp}</timestamp>
|
||||||
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
|
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
|
||||||
<mainClassName>itdelatrisu.opsu.Opsu</mainClassName>
|
<mainClassName>itdelatrisu.opsu.Opsu</mainClassName>
|
||||||
|
<useXDG>false</useXDG>
|
||||||
</properties>
|
</properties>
|
||||||
<build>
|
<build>
|
||||||
<sourceDirectory>src</sourceDirectory>
|
<sourceDirectory>src</sourceDirectory>
|
||||||
|
@ -107,7 +108,10 @@
|
||||||
</filters>
|
</filters>
|
||||||
<transformers>
|
<transformers>
|
||||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
<mainClass>${mainClassName}</mainClass>
|
<manifestEntries>
|
||||||
|
<Main-Class>${mainClassName}</Main-Class>
|
||||||
|
<Use-XDG>${useXDG}</Use-XDG>
|
||||||
|
</manifestEntries>
|
||||||
</transformer>
|
</transformer>
|
||||||
</transformers>
|
</transformers>
|
||||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
|
|
|
@ -23,9 +23,6 @@ import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.security.CodeSource;
|
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
@ -47,41 +44,32 @@ public class NativeLoader {
|
||||||
if (!NATIVE_DIR.exists())
|
if (!NATIVE_DIR.exists())
|
||||||
NATIVE_DIR.mkdir();
|
NATIVE_DIR.mkdir();
|
||||||
|
|
||||||
CodeSource src = NativeLoader.class.getProtectionDomain().getCodeSource();
|
JarFile jarFile = Utils.getJarFile();
|
||||||
if (src != null) {
|
if (jarFile == null)
|
||||||
URI jar = null;
|
return;
|
||||||
try {
|
|
||||||
jar = src.getLocation().toURI();
|
Enumeration<JarEntry> entries = jarFile.entries();
|
||||||
} catch (URISyntaxException e) {
|
while (entries.hasMoreElements()) {
|
||||||
e.printStackTrace();
|
JarEntry e = entries.nextElement();
|
||||||
return;
|
if (e == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
File f = new File(NATIVE_DIR, e.getName());
|
||||||
|
if (isNativeFile(e.getName()) && !e.isDirectory() && e.getName().indexOf('/') == -1 && !f.exists()) {
|
||||||
|
InputStream in = jarFile.getInputStream(jarFile.getEntry(e.getName()));
|
||||||
|
OutputStream out = new FileOutputStream(f);
|
||||||
|
|
||||||
|
byte[] buffer = new byte[65536];
|
||||||
|
int bufferSize;
|
||||||
|
while ((bufferSize = in.read(buffer, 0, buffer.length)) != -1)
|
||||||
|
out.write(buffer, 0, bufferSize);
|
||||||
|
|
||||||
|
in.close();
|
||||||
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
JarFile jarFile = new JarFile(new File(jar), false);
|
|
||||||
Enumeration<JarEntry> entries = jarFile.entries();
|
|
||||||
|
|
||||||
while (entries.hasMoreElements()) {
|
|
||||||
JarEntry e = entries.nextElement();
|
|
||||||
if (e == null)
|
|
||||||
break;
|
|
||||||
|
|
||||||
File f = new File(NATIVE_DIR, e.getName());
|
|
||||||
if (isNativeFile(e.getName()) && !e.isDirectory() && e.getName().indexOf('/') == -1 && !f.exists()) {
|
|
||||||
InputStream in = jarFile.getInputStream(jarFile.getEntry(e.getName()));
|
|
||||||
OutputStream out = new FileOutputStream(f);
|
|
||||||
|
|
||||||
byte[] buffer = new byte[65536];
|
|
||||||
int bufferSize;
|
|
||||||
while ((bufferSize = in.read(buffer, 0, buffer.length)) != -1)
|
|
||||||
out.write(buffer, 0, bufferSize);
|
|
||||||
|
|
||||||
in.close();
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jarFile.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jarFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,12 +18,16 @@
|
||||||
|
|
||||||
package itdelatrisu.opsu;
|
package itdelatrisu.opsu;
|
||||||
|
|
||||||
import itdelatrisu.opsu.audio.MusicController;
|
import java.io.File;
|
||||||
import itdelatrisu.opsu.db.DBController;
|
import java.io.FileNotFoundException;
|
||||||
import itdelatrisu.opsu.downloads.DownloadList;
|
import java.io.FileOutputStream;
|
||||||
import itdelatrisu.opsu.downloads.Updater;
|
import java.io.IOException;
|
||||||
import itdelatrisu.opsu.states.*;
|
import java.io.PrintStream;
|
||||||
import itdelatrisu.opsu.ui.UI;
|
import java.lang.reflect.Field;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
import org.newdawn.slick.Color;
|
import org.newdawn.slick.Color;
|
||||||
import org.newdawn.slick.GameContainer;
|
import org.newdawn.slick.GameContainer;
|
||||||
import org.newdawn.slick.SlickException;
|
import org.newdawn.slick.SlickException;
|
||||||
|
@ -35,11 +39,20 @@ import org.newdawn.slick.util.FileSystemLocation;
|
||||||
import org.newdawn.slick.util.Log;
|
import org.newdawn.slick.util.Log;
|
||||||
import org.newdawn.slick.util.ResourceLoader;
|
import org.newdawn.slick.util.ResourceLoader;
|
||||||
|
|
||||||
import java.io.*;
|
import itdelatrisu.opsu.audio.MusicController;
|
||||||
import java.lang.reflect.Field;
|
import itdelatrisu.opsu.db.DBController;
|
||||||
import java.net.InetAddress;
|
import itdelatrisu.opsu.downloads.DownloadList;
|
||||||
import java.net.ServerSocket;
|
import itdelatrisu.opsu.downloads.Updater;
|
||||||
import java.net.UnknownHostException;
|
import itdelatrisu.opsu.states.ButtonMenu;
|
||||||
|
import itdelatrisu.opsu.states.DownloadsMenu;
|
||||||
|
import itdelatrisu.opsu.states.Game;
|
||||||
|
import itdelatrisu.opsu.states.GamePauseMenu;
|
||||||
|
import itdelatrisu.opsu.states.GameRanking;
|
||||||
|
import itdelatrisu.opsu.states.MainMenu;
|
||||||
|
import itdelatrisu.opsu.states.OptionsMenu;
|
||||||
|
import itdelatrisu.opsu.states.SongMenu;
|
||||||
|
import itdelatrisu.opsu.states.Splash;
|
||||||
|
import itdelatrisu.opsu.ui.UI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main class.
|
* Main class.
|
||||||
|
@ -143,7 +156,6 @@ public class Opsu extends StateBasedGame {
|
||||||
Log.warn("Failed to set 'sys_paths' field.", e);
|
Log.warn("Failed to set 'sys_paths' field.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// set the resource paths
|
// set the resource paths
|
||||||
ResourceLoader.addResourceLocation(new FileSystemLocation(new File("./res/")));
|
ResourceLoader.addResourceLocation(new FileSystemLocation(new File("./res/")));
|
||||||
|
|
||||||
|
|
|
@ -18,13 +18,6 @@
|
||||||
|
|
||||||
package itdelatrisu.opsu;
|
package itdelatrisu.opsu;
|
||||||
|
|
||||||
import itdelatrisu.opsu.audio.MusicController;
|
|
||||||
import itdelatrisu.opsu.beatmap.Beatmap;
|
|
||||||
import itdelatrisu.opsu.skins.Skin;
|
|
||||||
import itdelatrisu.opsu.skins.SkinLoader;
|
|
||||||
import itdelatrisu.opsu.ui.Fonts;
|
|
||||||
import itdelatrisu.opsu.ui.UI;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -38,6 +31,9 @@ import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.jar.Attributes;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.jar.Manifest;
|
||||||
|
|
||||||
import org.lwjgl.input.Keyboard;
|
import org.lwjgl.input.Keyboard;
|
||||||
import org.newdawn.slick.GameContainer;
|
import org.newdawn.slick.GameContainer;
|
||||||
|
@ -48,10 +44,20 @@ import org.newdawn.slick.util.FileSystemLocation;
|
||||||
import org.newdawn.slick.util.Log;
|
import org.newdawn.slick.util.Log;
|
||||||
import org.newdawn.slick.util.ResourceLoader;
|
import org.newdawn.slick.util.ResourceLoader;
|
||||||
|
|
||||||
|
import itdelatrisu.opsu.audio.MusicController;
|
||||||
|
import itdelatrisu.opsu.beatmap.Beatmap;
|
||||||
|
import itdelatrisu.opsu.skins.Skin;
|
||||||
|
import itdelatrisu.opsu.skins.SkinLoader;
|
||||||
|
import itdelatrisu.opsu.ui.Fonts;
|
||||||
|
import itdelatrisu.opsu.ui.UI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles all user options.
|
* Handles all user options.
|
||||||
*/
|
*/
|
||||||
public class Options {
|
public class Options {
|
||||||
|
/** Whether to use XDG directories. */
|
||||||
|
private static final boolean USE_XDG = checkXDGFlag();
|
||||||
|
|
||||||
/** The config directory. */
|
/** The config directory. */
|
||||||
private static final File CONFIG_DIR = getXDGBaseDir("XDG_CONFIG_HOME", ".config");
|
private static final File CONFIG_DIR = getXDGBaseDir("XDG_CONFIG_HOME", ".config");
|
||||||
|
|
||||||
|
@ -120,15 +126,35 @@ public class Options {
|
||||||
/** Port binding. */
|
/** Port binding. */
|
||||||
private static int port = 49250;
|
private static int port = 49250;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the XDG flag in the manifest (if any) is set to "true".
|
||||||
|
* @return true if XDG directories are enabled, false otherwise
|
||||||
|
*/
|
||||||
|
private static boolean checkXDGFlag() {
|
||||||
|
JarFile jarFile = Utils.getJarFile();
|
||||||
|
if (jarFile == null)
|
||||||
|
return false;
|
||||||
|
try {
|
||||||
|
Manifest manifest = jarFile.getManifest();
|
||||||
|
if (manifest == null)
|
||||||
|
return false;
|
||||||
|
Attributes attributes = manifest.getMainAttributes();
|
||||||
|
String value = attributes.getValue("Use-XDG");
|
||||||
|
return (value != null && value.equalsIgnoreCase("true"));
|
||||||
|
} catch (IOException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the directory based on the XDG base directory specification for
|
* Returns the directory based on the XDG base directory specification for
|
||||||
* Unix-like operating systems, only if the system property "XDG" has been defined.
|
* Unix-like operating systems, only if the "XDG" flag is enabled.
|
||||||
* @param env the environment variable to check (XDG_*_*)
|
* @param env the environment variable to check (XDG_*_*)
|
||||||
* @param fallback the fallback directory relative to ~home
|
* @param fallback the fallback directory relative to ~home
|
||||||
* @return the XDG base directory, or the working directory if unavailable
|
* @return the XDG base directory, or the working directory if unavailable
|
||||||
*/
|
*/
|
||||||
private static File getXDGBaseDir(String env, String fallback) {
|
private static File getXDGBaseDir(String env, String fallback) {
|
||||||
if (System.getProperty("XDG") == null)
|
if (!USE_XDG)
|
||||||
return new File("./");
|
return new File("./");
|
||||||
|
|
||||||
String OS = System.getProperty("os.name").toLowerCase();
|
String OS = System.getProperty("os.name").toLowerCase();
|
||||||
|
|
|
@ -18,15 +18,6 @@
|
||||||
|
|
||||||
package itdelatrisu.opsu;
|
package itdelatrisu.opsu;
|
||||||
|
|
||||||
import itdelatrisu.opsu.audio.SoundController;
|
|
||||||
import itdelatrisu.opsu.audio.SoundEffect;
|
|
||||||
import itdelatrisu.opsu.beatmap.HitObject;
|
|
||||||
import itdelatrisu.opsu.downloads.Download;
|
|
||||||
import itdelatrisu.opsu.downloads.DownloadNode;
|
|
||||||
import itdelatrisu.opsu.replay.PlaybackSpeed;
|
|
||||||
import itdelatrisu.opsu.ui.Fonts;
|
|
||||||
import itdelatrisu.opsu.ui.UI;
|
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
@ -48,6 +39,7 @@ import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
@ -66,6 +58,15 @@ import org.newdawn.slick.util.Log;
|
||||||
|
|
||||||
import com.sun.jna.platform.FileUtils;
|
import com.sun.jna.platform.FileUtils;
|
||||||
|
|
||||||
|
import itdelatrisu.opsu.audio.SoundController;
|
||||||
|
import itdelatrisu.opsu.audio.SoundEffect;
|
||||||
|
import itdelatrisu.opsu.beatmap.HitObject;
|
||||||
|
import itdelatrisu.opsu.downloads.Download;
|
||||||
|
import itdelatrisu.opsu.downloads.DownloadNode;
|
||||||
|
import itdelatrisu.opsu.replay.PlaybackSpeed;
|
||||||
|
import itdelatrisu.opsu.ui.Fonts;
|
||||||
|
import itdelatrisu.opsu.ui.UI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains miscellaneous utilities.
|
* Contains miscellaneous utilities.
|
||||||
*/
|
*/
|
||||||
|
@ -564,8 +565,25 @@ public class Utils {
|
||||||
return Opsu.class.getResource(String.format("%s.class", Opsu.class.getSimpleName())).toString().startsWith("jar:");
|
return Opsu.class.getResource(String.format("%s.class", Opsu.class.getSimpleName())).toString().startsWith("jar:");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the JarFile for the application.
|
||||||
|
* @return the JAR file, or null if it could not be determined
|
||||||
|
*/
|
||||||
|
public static JarFile getJarFile() {
|
||||||
|
if (!isJarRunning())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new JarFile(new File(Opsu.class.getProtectionDomain().getCodeSource().getLocation().toURI()), false);
|
||||||
|
} catch (URISyntaxException | IOException e) {
|
||||||
|
Log.error("Could not determine the JAR file.", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the directory where the application is being run.
|
* Returns the directory where the application is being run.
|
||||||
|
* @return the directory, or null if it could not be determined
|
||||||
*/
|
*/
|
||||||
public static File getRunningDirectory() {
|
public static File getRunningDirectory() {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -150,6 +150,7 @@ public abstract class Curve {
|
||||||
* @param i the control point index
|
* @param i the control point index
|
||||||
*/
|
*/
|
||||||
public float getY(int i) { return (i == 0) ? y : sliderY[i - 1]; }
|
public float getY(int i) { return (i == 0) ? y : sliderY[i - 1]; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Discards the slider cache (only used for mmsliders).
|
* Discards the slider cache (only used for mmsliders).
|
||||||
*/
|
*/
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user