From 2c3f62cd0a25fa42f9118400fadcc13863e7d02b Mon Sep 17 00:00:00 2001 From: Tefek <31473117+493msi@users.noreply.github.com> Date: Mon, 21 Dec 2020 04:09:44 +0100 Subject: [PATCH] [PlutoLib] The initial implementation of the Version API --- UPDATE_NOTES.md | 50 ++-- plutolib/build.gradle | 29 +++ .../cz/tefek/pluto/PlutoVersionConfig.java | 11 + .../main/java/cz/tefek/pluto/IVersion.java | 13 ++ .../src/main/java/cz/tefek/pluto/Pluto.java | 111 ++++----- .../java/cz/tefek/pluto/PlutoVersion.java | 216 ++++++++++++++++++ 6 files changed, 354 insertions(+), 76 deletions(-) create mode 100644 plutolib/src/config/java/cz/tefek/pluto/PlutoVersionConfig.java create mode 100644 plutolib/src/main/java/cz/tefek/pluto/IVersion.java create mode 100644 plutolib/src/main/java/cz/tefek/pluto/PlutoVersion.java diff --git a/UPDATE_NOTES.md b/UPDATE_NOTES.md index 984155d..9c059e6 100644 --- a/UPDATE_NOTES.md +++ b/UPDATE_NOTES.md @@ -9,19 +9,23 @@ * `[PlutoLib]` The transitive dependency JOML is now provided by `PlutoLib` instead of `PlutoStatic` * `[PlutoLib]` Created a simple Color API * `[PlutoShader]` Added the 8-bit RGBA `Color` class as a counterpart to AWT's `Color` class - * `[PlutoShader]` Added the `RGBA` and `RGB` single precision float color objects + * `[PlutoShader]` Added the `RGBA` and `RGB` single precision float color objects * `[PlutoShader]` Added the respective `IRGBA` and `IRGB` read-only interfaces - * `[PlutoShader]` Added the `HSBA` and `HSB` single precision float color objects + * `[PlutoShader]` Added the `HSBA` and `HSB` single precision float color objects * `[PlutoShader]` Added methods to convert between HSBA, RGBA, HSB and RGB * `[PlutoShader]` Added the `UniformRGBA` and `UniformRGB` shader uniform types - +* `[PlutoLib]` Created the Version API + * Added the `IVersion` interface + * Added support for version objects + * As a result, all fields except the version string are no longer compile-time constants + Awaiting implementation: * `[PlutoLib]` Moved `cz.tefek.pluto.io.pluto.pp` to `cz.tefek.pluto.io.plutopackage` * `[PlutoLib]` Completely reworked the module system ## 20.2.0.0-alpha.2 * `build.gradle` Extracted the version numbers into separate variables -* `build.gradle` **[experimental]** `gradlew` should now automatically download JDK11 when needed +* `build.gradle` **[experimental]** `gradlew` should now automatically download JDK11 when needed * `build.gradle` Updated the build scripts and added source Maven publication * `[PlutoLib]` Renamed the `cz.tefek.pluto.eventsystem` package to `cz.tefek.pluto.event` * Moved all subpackages @@ -31,7 +35,7 @@ Awaiting implementation: * Renamed `VertexArray#createArrayAttrib` to `VertexArray#createArrayAttribute` * Renamed `VertexArray#getVertexAttribs` to `VertexArray#getVertexAttributes` * `[PlutoCore]` Made `PlutoApplication.StartupConfig` fields private, options -can now only be modified only through public setters + can now only be modified only through public setters * `[PlutoLib]` Added the `ThreadSensitive` annotation * `[PlutoLib]` Renamed `MiniTimeCouldNotBeParsedException` to `MiniTimeParseException` * `[PlutoCore]` Refactored `InputBus` and added several convenience methods @@ -40,26 +44,26 @@ can now only be modified only through public setters ## 20.2.0.0-alpha.1 * `[PlutoLib#cz.tefek.pluto.io.logger]` Refactored the Logger subsystem - * Renamed `Logger#logException` to `Logger#log` to match the rest - of log methods and updated references to this method accordingly - * Streamlined `StdOutSplitStream` and `StdErrSplitStream` into a more generalized - `OutputSplitStream` - * `Logger`'s output filenames now look cleaner with `log--YYYY-MM-DD--HH-MM-SS.txt` - * `[Logger#setup]` can now throw `IOException` - * `[PlutoCore]` As a result, `[PlutoApplication#run]` can now throw `Exception` + * Renamed `Logger#logException` to `Logger#log` to match the rest + of log methods and updated references to this method accordingly + * Streamlined `StdOutSplitStream` and `StdErrSplitStream` into a more generalized + `OutputSplitStream` + * `Logger`'s output filenames now look cleaner with `log--YYYY-MM-DD--HH-MM-SS.txt` + * `[Logger#setup]` can now throw `IOException` + * `[PlutoCore]` As a result, `[PlutoApplication#run]` can now throw `Exception` * `[PlutoLib]` Updated JavaDoc in `ResourceAddress`, `TPL`, `TPNImage` * `[PlutoLib]` Code cleanup in `MiniTime`, `TPL` - * `[PlutoLib]` Deprecated `TPL#load(String)` in favor of `TPL#load(ResourceAddress)`, - `TPL#load(File)` and `TPL#load(Path)` - * `[PlutoTexturing]` Deprecated the `String` variant of `Texture#load` - to reflect this change - * `[PlutoSpritesheet]` Removed the usage of this method - in `DisposablePlaceholderSprite` - * `[PlutoLib]` Added an option to flip loaded images with `TPL#loadImageSpecial` - and added respective `TPL#loadSpecial` for every `TPL#load` - * `[PlutoLib]` *Removed* `TPJImage` - * `[PlutoLib]` Removed `TPL#loadPixels` - * `[PlutoCore]` Updated `GLFWImageUtil` to remove the usage of `TPJImage` + * `[PlutoLib]` Deprecated `TPL#load(String)` in favor of `TPL#load(ResourceAddress)`, + `TPL#load(File)` and `TPL#load(Path)` + * `[PlutoTexturing]` Deprecated the `String` variant of `Texture#load` + to reflect this change + * `[PlutoSpritesheet]` Removed the usage of this method + in `DisposablePlaceholderSprite` + * `[PlutoLib]` Added an option to flip loaded images with `TPL#loadImageSpecial` + and added respective `TPL#loadSpecial` for every `TPL#load` + * `[PlutoLib]` *Removed* `TPJImage` + * `[PlutoLib]` Removed `TPL#loadPixels` + * `[PlutoCore]` Updated `GLFWImageUtil` to remove the usage of `TPJImage` * `[PlutoCore]` `[PlutoApplication]` now properly closes the `Logger` on exit * `[PlutoLib]` Various typo fixes * `[Pluto*]` Deprecated `Severity` for `SmartSeverity` and replaced all usages diff --git a/plutolib/build.gradle b/plutolib/build.gradle index 24d0e6f..1f43a6a 100644 --- a/plutolib/build.gradle +++ b/plutolib/build.gradle @@ -2,6 +2,35 @@ apply plugin: 'java-library' description = "" + +sourceSets { + config { + java { + srcDir "src/config/java" + } + } + + main { + java { + compileClasspath += config.output + } + } +} + +task generateConfigs(type: Copy) { + def projectVariables = [ + plutoVersion: project.version, + ] + + inputs.properties projectVariables + from 'src/config/java' + into "$buildDir/generated/java" + + expand projectVariables +} + +compileJava.dependsOn generateConfigs + dependencies { api platform("org.lwjgl:lwjgl-bom:$lwjglVersion") diff --git a/plutolib/src/config/java/cz/tefek/pluto/PlutoVersionConfig.java b/plutolib/src/config/java/cz/tefek/pluto/PlutoVersionConfig.java new file mode 100644 index 0000000..ee46790 --- /dev/null +++ b/plutolib/src/config/java/cz/tefek/pluto/PlutoVersionConfig.java @@ -0,0 +1,11 @@ +package cz.tefek.pluto; + +class PlutoVersionConfig +{ + /** + * The combined version string. + * + * @since 20.2.0.0-alpha.3 + * */ + protected static final String VERSION = "$plutoVersion"; +} diff --git a/plutolib/src/main/java/cz/tefek/pluto/IVersion.java b/plutolib/src/main/java/cz/tefek/pluto/IVersion.java new file mode 100644 index 0000000..4560c21 --- /dev/null +++ b/plutolib/src/main/java/cz/tefek/pluto/IVersion.java @@ -0,0 +1,13 @@ +package cz.tefek.pluto; + +public interface IVersion extends Comparable +{ + @Override + boolean equals(Object o); + + @Override + int hashCode(); + + @Override + String toString(); +} diff --git a/plutolib/src/main/java/cz/tefek/pluto/Pluto.java b/plutolib/src/main/java/cz/tefek/pluto/Pluto.java index 95cbf48..e6f5b62 100644 --- a/plutolib/src/main/java/cz/tefek/pluto/Pluto.java +++ b/plutolib/src/main/java/cz/tefek/pluto/Pluto.java @@ -7,65 +7,70 @@ package cz.tefek.pluto; * * @author 493msi */ -public class Pluto +public class Pluto extends PlutoVersionConfig { public static final boolean DEBUG_MODE = Boolean.parseBoolean(System.getProperty("cz.tefek.pluto.debug")); - // TODO: Automate setting the version numbers with gradle - - /** - * The year version number, changes with breaking API changes. - * - * @since pre-alpha - * */ - public static final int VERSION_YEAR = 20; - - /** - * The major version number, changes with breaking API changes. - * - * @since pre-alpha - * */ - public static final int VERSION_MAJOR = 2; - - /** - * The minor version number, changes with backwards-compatible API changes. - * - * @since pre-alpha - * */ - public static final int VERSION_MINOR = 0; - - /** - * The patch number, changes with backwards-compatible fixes and patches. - * - * @since pre-alpha - * */ - public static final int VERSION_PATCH = 0; - - /** - * Denotes whether this build is a pre-release build. - * - * @since pre-alpha - * */ - public static final boolean PRERELEASE = true; - - /** - * The name of this pre-release, e.g. alpha, beta, RC and similar. - * - * @since pre-alpha - * */ - public static final String PRERELEASE_NAME = "alpha"; - - /** - * The pre-release patch number, incremented by 1 with *any* pre-release update. - * - * @since pre-alpha - * */ - public static final int PRERELEASE_PATCH = 3; - /** * The combined version string. * * @since pre-alpha * */ - public static final String VERSION = VERSION_YEAR + "." + VERSION_MAJOR + "." + VERSION_MINOR + "." + VERSION_PATCH + (PRERELEASE ? "-" + PRERELEASE_NAME + "." + PRERELEASE_PATCH : ""); + public static final String VERSION = PlutoVersionConfig.VERSION; + + /** + * The version object. + * + * @since 20.2.0.0-alpha.3 + * */ + public static final PlutoVersion VERSION_OBJ = PlutoVersion.of(VERSION); + + /** + * The year version number, changes with breaking API changes. + * + * @since pre-alpha + * */ + public static final int VERSION_YEAR = VERSION_OBJ.getYear(); + + /** + * The major version number, changes with breaking API changes. + * + * @since pre-alpha + * */ + public static final int VERSION_MAJOR = VERSION_OBJ.getMajor(); + + /** + * The minor version number, changes with backwards-compatible API changes. + * + * @since pre-alpha + * */ + public static final int VERSION_MINOR = VERSION_OBJ.getMinor(); + + /** + * The patch number, changes with backwards-compatible fixes and patches. + * + * @since pre-alpha + * */ + public static final int VERSION_PATCH = VERSION_OBJ.getPatch(); + + /** + * Denotes whether this build is a pre-release build. + * + * @since pre-alpha + * */ + public static final boolean PRERELEASE = VERSION_OBJ.isPrerelease(); + + /** + * The name of this pre-release, e.g. alpha, beta, RC and similar. + * + * @since pre-alpha + * */ + public static final String PRERELEASE_NAME = VERSION_OBJ.getPrereleaseName(); + + /** + * The pre-release patch number, incremented by 1 with *any* pre-release update. + * + * @since pre-alpha + * */ + public static final int PRERELEASE_PATCH = VERSION_OBJ.getPrereleaseNumber(); } diff --git a/plutolib/src/main/java/cz/tefek/pluto/PlutoVersion.java b/plutolib/src/main/java/cz/tefek/pluto/PlutoVersion.java new file mode 100644 index 0000000..fddfc1b --- /dev/null +++ b/plutolib/src/main/java/cz/tefek/pluto/PlutoVersion.java @@ -0,0 +1,216 @@ +package cz.tefek.pluto; + +import javax.annotation.Nonnull; + +import java.util.Objects; + +import cz.tefek.pluto.annotation.ConstantExpression; + +public final class PlutoVersion implements IVersion +{ + private final int year; + private final int major; + private final int minor; + private final int patch; + + private final boolean prerelease; + private final String prereleaseName; + private final int prereleaseNumber; + + public PlutoVersion(int year, int major, int minor, int patch) + { + this.year = year; + this.major = major; + this.minor = minor; + this.patch = patch; + + this.prerelease = false; + this.prereleaseName = null; + this.prereleaseNumber = 0; + } + + public PlutoVersion(int year, int major, int minor, int patch, String prereleaseName, int prereleaseNumber) + { + this.year = year; + this.major = major; + this.minor = minor; + this.patch = patch; + + this.prerelease = true; + this.prereleaseName = prereleaseName; + this.prereleaseNumber = prereleaseNumber; + } + + public int getYear() + { + return this.year; + } + + public int getMajor() + { + return this.major; + } + + public int getMinor() + { + return this.minor; + } + + public int getPatch() + { + return this.patch; + } + + public boolean isPrerelease() + { + return this.prerelease; + } + + public String getPrereleaseName() + { + return this.prereleaseName; + } + + public int getPrereleaseNumber() + { + return this.prereleaseNumber; + } + + @ConstantExpression + public static PlutoVersion of(@Nonnull String str) + { + assert !str.isBlank(); + + assert str.matches("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+([+\\-][a-zA-Z0-9]+(\\.[0-9]+)?)?"); + + var parts = str.split("[+\\-]"); + + assert parts.length == 1 || parts.length == 2; + + var versionParts = parts[0].split("\\."); + + assert versionParts.length == 4; + + if (parts.length == 2) + { + var prereleaseParts = parts[1].split("\\."); + + assert prereleaseParts.length == 1 || prereleaseParts.length == 2; + + int prereleaseNumber; + + if (prereleaseParts.length == 2) + prereleaseNumber = Integer.parseInt(prereleaseParts[1]); + else + prereleaseNumber = 0; + + String prereleaseName = prereleaseParts[0]; + + return new PlutoVersion( + Integer.parseInt(versionParts[0]), + Integer.parseInt(versionParts[1]), + Integer.parseInt(versionParts[2]), + Integer.parseInt(versionParts[3]), + prereleaseName, + prereleaseNumber); + } + + return new PlutoVersion( + Integer.parseInt(versionParts[0]), + Integer.parseInt(versionParts[1]), + Integer.parseInt(versionParts[2]), + Integer.parseInt(versionParts[3])); + } + + @Override + public String toString() + { + if (prerelease) + return String.format("%d.%d.%d.%d-%s.%d", + this.year, + this.major, + this.minor, + this.patch, + this.prereleaseName, + this.prereleaseNumber); + else + return String.format("%d.%d.%d.%d", + this.year, + this.major, + this.minor, + this.patch); + } + + @Override + public int compareTo(@Nonnull PlutoVersion o) + { + int yearDiff = this.year - o.year; + if (yearDiff != 0) + return yearDiff; + + int majorDiff = this.major - o.major; + if (majorDiff != 0) + return majorDiff; + + int minorDiff = this.minor - o.minor; + if (minorDiff != 0) + return minorDiff; + + int patchDiff = this.patch - o.patch; + if (patchDiff != 0) + return patchDiff; + + if (!this.prerelease && !o.prerelease) + return 0; + + if (!this.prerelease) + return 1; + + if (!o.prerelease) + return -1; + + assert this.prereleaseName != null; + assert o.prereleaseName != null; + + int prereleaseNameDiff = this.prereleaseName.compareTo(o.prereleaseName); + + if (prereleaseNameDiff != 0) + return prereleaseNameDiff; + + return this.prereleaseNumber - o.prereleaseNumber; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + PlutoVersion that = (PlutoVersion) o; + + if (prerelease) + return year == that.year && + major == that.major && + minor == that.minor && + patch == that.patch && + prereleaseNumber == that.prereleaseNumber && + Objects.equals(prereleaseName, that.prereleaseName); + else + return year == that.year && + major == that.major && + minor == that.minor && + patch == that.patch; + } + + @Override + public int hashCode() + { + if (prerelease) + return Objects.hash(year, major, minor, patch); + else + return Objects.hash(year, major, minor, patch, prereleaseName, prereleaseNumber); + } +}