diff --git a/flixelgdx/core/build.gradle b/flixelgdx/core/build.gradle index aee4fdf..42fa47f 100644 --- a/flixelgdx/core/build.gradle +++ b/flixelgdx/core/build.gradle @@ -3,6 +3,15 @@ eclipse.project.name = appName + '-flixelgdx-core' apply plugin: "java-library" +// Embed version from build so Flixel.getVersion() can read it at runtime (Gradle does not set JAR manifest like Maven). +def generateFlixelVersion = tasks.register('generateFlixelVersion', WriteProperties) { + outputFile = layout.buildDirectory.file("generated/version/version.properties") + property("version", project.version) +} +processResources.from(generateFlixelVersion) { + into "me/stringdotjar/flixelgdx" +} + java { sourceCompatibility = 17 targetCompatibility = 17 diff --git a/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/Flixel.java b/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/Flixel.java index 9ffcd3f..24f3790 100644 --- a/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/Flixel.java +++ b/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/Flixel.java @@ -1,5 +1,6 @@ package me.stringdotjar.flixelgdx; +import com.badlogic.gdx.Application.ApplicationType; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.assets.AssetManager; import com.badlogic.gdx.files.FileHandle; @@ -22,6 +23,9 @@ import me.stringdotjar.flixelgdx.signal.FlixelSignalData.SoundPlayedSignalData; import org.jetbrains.annotations.NotNull; +import java.io.InputStream; +import java.util.Properties; + /** * Global manager and utility class for Flixel. * @@ -479,6 +483,22 @@ public static boolean isFullscreen() { return Gdx.graphics.isFullscreen(); } + public static ApplicationType getPlatform() { + return Gdx.app.getType(); + } + + public static String getVersion() { + try (InputStream in = Flixel.class.getResourceAsStream("version.properties")) { + if (in != null) { + Properties p = new Properties(); + p.load(in); + String v = p.getProperty("version"); + if (v != null && !v.isEmpty()) return v; + } + } catch (Exception ignored) {} + return "Unknown"; + } + public static void setLogMode(@NotNull FlixelLogMode mode) { defaultLogger.setLogMode(mode); } diff --git a/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/logging/FlixelLogger.java b/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/logging/FlixelLogger.java index 1cf9760..985ef80 100644 --- a/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/logging/FlixelLogger.java +++ b/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/logging/FlixelLogger.java @@ -2,7 +2,6 @@ import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.utils.Array; import me.stringdotjar.flixelgdx.util.FlixelConstants; import me.stringdotjar.flixelgdx.util.FlixelRuntimeUtil; import org.jetbrains.annotations.NotNull; @@ -141,8 +140,8 @@ protected void outputLog(String tag, Object message, FlixelLogLevel level) { // Console: use current log mode. String coloredLog; if (logMode == FlixelLogMode.SIMPLE) { - coloredLog = colorText(simpleFile, color, true, false, underlineFile) - + ": " + coloredLog = colorText(simpleFile + ":", color, true, false, underlineFile) + + " " + colorText(rawMessage, color, false, true, false); } else { String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); diff --git a/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/util/FlixelGitUtil.java b/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/util/FlixelGitUtil.java new file mode 100644 index 0000000..091027d --- /dev/null +++ b/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/util/FlixelGitUtil.java @@ -0,0 +1,80 @@ +package me.stringdotjar.flixelgdx.util; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +/** + * Utility class for obtaining Git information about the current repository Flixel is being ran in. + */ +public final class FlixelGitUtil { + + /** + * A record holding all info about the current Git repository. + * + * @param commit The current commit. + * @param branch The current branch. + * @param remoteUrl The repository that Polyverse is being worked on. + * @param isModified Does the current repository have any changes made to it? + */ + public record RepoInfo(String commit, String branch, String remoteUrl, String isModified) { + @Override + public String commit() { + if (commit == null || commit.isBlank()) { + return "Could not determine Git commit."; + } + return commit.length() > 7 ? commit.substring(0, 8) : commit; + } + + @Override + public String branch() { + if (branch == null || branch.isBlank()) { + return "Could not determine Git branch."; + } + return branch; + } + + @Override + public String remoteUrl() { + if (remoteUrl == null || remoteUrl.isBlank()) { + return "Could not determine Git remote URL."; + } + return remoteUrl; + } + + @Override + public String isModified() { + return (isModified != null && !isModified.isBlank()) ? "Yes" : "No"; + } + } + + /** + * Gets basic Git info about the current app running. + * + * @return A {@code RepoInfo} record with basic info. + */ + public static RepoInfo getRepoInfo() { + String commit = runGitCommand("rev-parse", "HEAD"); + String branch = runGitCommand("rev-parse", "--abbrev-ref", "HEAD"); + String remoteUrl = runGitCommand("config", "--get", "remote.origin.url"); + String isModified = runGitCommand("status", "--porcelain"); + return new RepoInfo(commit, branch, remoteUrl, isModified); + } + + private static String runGitCommand(String... args) { + try { + String[] command = new String[args.length + 1]; + command[0] = "git"; + System.arraycopy(args, 0, command, 1, args.length); + ProcessBuilder pb = new ProcessBuilder(command); + pb.redirectErrorStream(true); + Process process = pb.start(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + return reader.readLine(); + } + } catch (Exception e) { + return null; + } + } + + private FlixelGitUtil() {} +} diff --git a/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/util/FlixelRuntimeUtil.java b/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/util/FlixelRuntimeUtil.java index be8f40f..9079425 100644 --- a/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/util/FlixelRuntimeUtil.java +++ b/flixelgdx/core/src/main/java/me/stringdotjar/flixelgdx/util/FlixelRuntimeUtil.java @@ -47,6 +47,69 @@ public static boolean isRunningFromJar() { } } + /** + * Returns {@code true} when the application is running inside an IDE (IntelliJ, Eclipse, Cursor, + * VS Code, etc.), and {@code false} when running from the distribution JAR or plain classpath. + * + *
Detection uses IDE-specific system properties, classpath hints, and the code source path. + * Gradle-based runs are detected via {@code build/classes} (exploded) or a JAR under + * {@code build/libs/} that is not the distribution JAR (no {@code Main-Class} in manifest). + * + * @return {@code true} if running in an IDE, {@code false} otherwise. + */ + public static boolean isRunningInIDE() { + // IntelliJ (run/debug). + if (System.getProperty("idea.launcher.port") != null) { + return true; + } + // IntelliJ fallback: idea_rt.jar on classpath (e.g. debug). + if (System.getProperty("java.class.path", "").contains("idea_rt.jar")) { + return true; + } + // Eclipse. + if (System.getProperty("eclipse.application") != null) { + return true; + } + var path = getWorkingDirectory(); + if (path == null) { + return false; + } + // IntelliJ default output. + if (path.contains("out/production")) { + return true; + } + // Eclipse default output. + if (path.contains("bin/")) { + return true; + } + // Gradle: exploded classes (e.g. build/classes/java/main). + if (path.contains("build/classes")) { + return true; + } + // Gradle: module JAR on classpath (build/libs/*.jar without Main-Class); distribution JAR has Main-Class. + if (path.contains("build/libs") && path.endsWith(".jar") && !isRunningFromJar()) { + return true; + } + return false; + } + + /** + * Detects the current runtime environment. + * + *
This method is used to determine if the application is running in the IDE, from a JAR, or from the classpath.
+ *
+ * @return The detected environment.
+ */
+ public static RunEnvironment detectEnvironment() {
+ if (isRunningInIDE()) {
+ return RunEnvironment.IDE;
+ }
+ if (isRunningFromJar()) {
+ return RunEnvironment.JAR;
+ }
+ return RunEnvironment.CLASSPATH;
+ }
+
/**
* Returns the working directory of the game.
*
@@ -72,8 +135,7 @@ public static String getWorkingDirectory() {
* @return The root package name of the library.
*/
public static String getLibraryRoot() {
- return FlixelRuntimeUtil.class.getPackageName()
- .replaceAll("\\.[^.]+$", "");
+ return FlixelRuntimeUtil.class.getPackageName().replaceAll("\\.[^.]+$", "");
}
/**
@@ -122,5 +184,14 @@ public static String getFullExceptionMessage(Throwable exception) {
return messageBuilder.toString();
}
+ /**
+ * Enum representing the environment in which Flixel is running in.
+ */
+ public enum RunEnvironment {
+ IDE,
+ JAR,
+ CLASSPATH
+ }
+
private FlixelRuntimeUtil() {}
}
diff --git a/polyverse/build.gradle b/polyverse/build.gradle
index 983a7e0..6c123dd 100644
--- a/polyverse/build.gradle
+++ b/polyverse/build.gradle
@@ -1,6 +1,15 @@
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
eclipse.project.name = appName + '-polyverse'
+// Embed version from gradle.properties (projectVersion) so Polyverse.getVersion() can read it at runtime.
+def generatePolyverseVersion = tasks.register('generatePolyverseVersion', WriteProperties) {
+ outputFile = layout.buildDirectory.file("generated/version/version.properties")
+ property("version", project.version)
+}
+processResources.from(generatePolyverseVersion) {
+ into "me/stringdotjar/polyverse"
+}
+
dependencies {
implementation project(":flixelgdx:core")
diff --git a/polyverse/src/main/java/me/stringdotjar/polyverse/Polyverse.java b/polyverse/src/main/java/me/stringdotjar/polyverse/Polyverse.java
index a58ceb9..1ec8ce5 100644
--- a/polyverse/src/main/java/me/stringdotjar/polyverse/Polyverse.java
+++ b/polyverse/src/main/java/me/stringdotjar/polyverse/Polyverse.java
@@ -3,14 +3,15 @@
import com.badlogic.gdx.files.FileHandle;
import groovy.lang.GroovyClassLoader;
import me.stringdotjar.flixelgdx.Flixel;
-import me.stringdotjar.flixelgdx.util.FlixelRuntimeUtil;
import me.stringdotjar.polyverse.script.type.Script;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Properties;
import java.util.function.Consumer;
/** Core manager class for managing the Polyverse modding environment. */
@@ -139,6 +140,23 @@ public static