Compare commits

..

12 commits

Author SHA1 Message Date
2db14012f8
Remove all remaining traces of ImmutableHashMap
Some checks failed
build-and-test / build (push) Failing after 1m58s
build-and-test / test (push) Failing after 2m4s
build-and-test / generate-javadoc (push) Failing after 2m7s
2024-11-25 01:59:16 +01:00
7d15c5c73d
Cleanup rendering subsystem
Some checks failed
build-and-test / build (push) Failing after 2m4s
build-and-test / generate-javadoc (push) Failing after 2m5s
build-and-test / test (push) Failing after 2m6s
2024-11-25 01:47:00 +01:00
c89e65882c
Very experimental rendering subsystem changes
Some checks failed
build-and-test / build (push) Failing after 2m4s
build-and-test / test (push) Failing after 2m4s
build-and-test / generate-javadoc (push) Failing after 2m8s
2024-11-24 16:39:11 +01:00
45ec057457
Rename some Miscellaneous methods, add stacktraceAsStringRecursive
Some checks failed
build-and-test / build (push) Failing after 1m57s
build-and-test / generate-javadoc (push) Failing after 2m1s
build-and-test / test (push) Failing after 2m1s
2024-11-24 15:39:48 +01:00
c975c5adff
Update icon
Some checks failed
build-and-test / test (push) Failing after 1m56s
build-and-test / generate-javadoc (push) Failing after 2m11s
build-and-test / build (push) Failing after 2m13s
2024-11-24 13:28:28 +01:00
64f48a472f
Perform code maintenance
Please note that this commit may not fully compile as I'm currently working on a rendering subsystem rewrite.
2024-11-24 13:28:15 +01:00
8bd0896415
Ignore JVM segfault log files
Some checks failed
build-and-test / build (push) Failing after 59s
build-and-test / generate-javadoc (push) Failing after 1m31s
build-and-test / test (push) Successful in 1m37s
2024-11-10 20:56:52 +01:00
20580fb80b
Update documentation to reflect last commit 2024-11-10 20:56:35 +01:00
a45f010196
Merge and rename windowing subsystem 2024-11-10 20:55:01 +01:00
69cf668c4d
Heavily improve API doc of EngineConfiguration class
All checks were successful
build-and-test / test (push) Successful in 1m40s
build-and-test / generate-javadoc (push) Successful in 1m46s
build-and-test / build (push) Successful in 1m49s
2024-11-10 17:59:21 +01:00
7560e150af
Bump version
All checks were successful
build-and-test / test (push) Successful in 1m50s
build-and-test / build (push) Successful in 1m55s
build-and-test / generate-javadoc (push) Successful in 1m55s
2024-11-10 17:17:10 +01:00
b643735d0b
Update Docusaurus once again
All checks were successful
build-and-test / test (push) Successful in 1m18s
build-and-test / generate-javadoc (push) Successful in 1m22s
build-and-test / build (push) Successful in 1m24s
2024-11-09 16:16:34 +01:00
135 changed files with 4059 additions and 5786 deletions

3
.gitignore vendored
View file

@ -42,3 +42,6 @@ bin/
### Mac OS ### ### Mac OS ###
.DS_Store .DS_Store
### Java ###
hs_err_pid*.log

View file

@ -72,6 +72,8 @@ To change them, simply append `-P<property>` or `-P<property>=<value>`, like thi
#### Parallelism #### Parallelism
Use the `jobs` property to control how many jobs will get executed simultaneously. Use the `jobs` property to control how many jobs will get executed simultaneously.
On Linux, specify `-Pjobs=$(nproc)`. Defaults to `8`. On Linux, specify `-Pjobs=$(nproc)`. Defaults to `8`.
#### Rendering
You can use the `renderingPlatform` property to control which rendering platform to initialize for.
#### JVM Home #### JVM Home
You can use the `graalHome` property to specify the `$JAVA_HOME` of your local GraalVM installation. You can use the `graalHome` property to specify the `$JAVA_HOME` of your local GraalVM installation.
Only used in the `nativeImage` task. Useful if you aren't using GraalVM as your primary JDK. Only used in the `nativeImage` task. Useful if you aren't using GraalVM as your primary JDK.

View file

@ -35,10 +35,9 @@ import de.staropensource.engine.base.logging.backend.async.LoggingQueue;
import de.staropensource.engine.base.logging.backend.async.LoggingThread; import de.staropensource.engine.base.logging.backend.async.LoggingThread;
import de.staropensource.engine.base.type.DependencyVector; import de.staropensource.engine.base.type.DependencyVector;
import de.staropensource.engine.base.type.EngineState; import de.staropensource.engine.base.type.EngineState;
import de.staropensource.engine.base.type.immutable.ImmutableLinkedList;
import de.staropensource.engine.base.utility.DependencyResolver; import de.staropensource.engine.base.utility.DependencyResolver;
import de.staropensource.engine.base.utility.FileAccess; import de.staropensource.engine.base.utility.FileAccess;
import de.staropensource.engine.base.utility.Miscellaneous; import de.staropensource.engine.base.utility.misc.Miscellaneous;
import de.staropensource.engine.base.utility.PlaceholderEngine; import de.staropensource.engine.base.utility.PlaceholderEngine;
import de.staropensource.engine.base.utility.information.EngineInformation; import de.staropensource.engine.base.utility.information.EngineInformation;
import de.staropensource.engine.base.utility.information.JvmInformation; import de.staropensource.engine.base.utility.information.JvmInformation;
@ -114,7 +113,7 @@ public final class Engine extends SubsystemClass {
* @since v1-alpha1 * @since v1-alpha1
*/ */
@Getter @Getter
private @NotNull ImmutableLinkedList<@NotNull DependencySubsystemVector> subsystems = new ImmutableLinkedList<>(); private @NotNull List<@NotNull DependencySubsystemVector> subsystems = Collections.emptyList();
/** /**
* Contains the engine's shutdown handler. * Contains the engine's shutdown handler.
@ -291,8 +290,8 @@ public final class Engine extends SubsystemClass {
new Engine(); new Engine();
} catch (RuntimeException exception) { } catch (RuntimeException exception) {
Logger.error("Engine initialization failed"); Logger.error("Engine initialization failed");
Logger.error(Miscellaneous.getStackTraceHeader(exception.getCause())); Logger.error(Miscellaneous.throwableHeader(exception.getCause()));
for (String line : Miscellaneous.getStackTraceAsString(exception.getCause(), true).split("\n")) for (String line : Miscellaneous.stacktraceAsString(exception.getCause(), true).split("\n"))
Logger.error(line); Logger.error(line);
throw new RuntimeException("Engine initialization failed", exception.getCause()); throw new RuntimeException("Engine initialization failed", exception.getCause());
@ -366,7 +365,6 @@ public final class Engine extends SubsystemClass {
EventHelper.cacheEvent(EngineSoftCrashEvent.class); EventHelper.cacheEvent(EngineSoftCrashEvent.class);
EventHelper.cacheEvent(InternalEngineShutdownEvent.class); EventHelper.cacheEvent(InternalEngineShutdownEvent.class);
EventHelper.cacheEvent(LogEvent.class); EventHelper.cacheEvent(LogEvent.class);
EventHelper.cacheEvent(ThrowableCatchEvent.class);
} }
/** /**
@ -401,7 +399,7 @@ public final class Engine extends SubsystemClass {
} }
// Update 'subsystems' // Update 'subsystems'
subsystems = new ImmutableLinkedList<>(subsystemsMutable); subsystems = Collections.unmodifiableList(subsystemsMutable);
} }
/** /**
@ -488,7 +486,7 @@ public final class Engine extends SubsystemClass {
} }
// Update 'subsystems' // Update 'subsystems'
subsystems = new ImmutableLinkedList<>(order); subsystems = Collections.unmodifiableList(order);
} }
/** /**

View file

@ -19,8 +19,11 @@
package de.staropensource.engine.base; package de.staropensource.engine.base;
import de.staropensource.engine.base.annotation.EngineSubsystem;
import de.staropensource.engine.base.event.LogEvent;
import de.staropensource.engine.base.implementable.Configuration; import de.staropensource.engine.base.implementable.Configuration;
import de.staropensource.engine.base.implementable.ShortcodeParser; import de.staropensource.engine.base.implementable.ShortcodeParser;
import de.staropensource.engine.base.implementable.SubsystemClass;
import de.staropensource.engine.base.logging.Logger; import de.staropensource.engine.base.logging.Logger;
import de.staropensource.engine.base.logging.backend.async.LoggingThread; import de.staropensource.engine.base.logging.backend.async.LoggingThread;
import de.staropensource.engine.base.type.EngineState; import de.staropensource.engine.base.type.EngineState;
@ -66,11 +69,11 @@ public final class EngineConfiguration extends Configuration {
private static EngineConfiguration instance; private static EngineConfiguration instance;
/** /**
* Contains prefix properties must begin with. * Contains the configuration prefix.
* *
* @since v1-alpha0 * @since v1-alpha0
* -- GETTER -- * -- GETTER --
* Returns prefix properties must begin with. * Returns the configuration prefix.
* *
* @return property group * @return property group
* @since v1-alpha0 * @since v1-alpha0
@ -79,132 +82,196 @@ public final class EngineConfiguration extends Configuration {
/** /**
* If enabled, allows for unintentional behaviour * Contains if debugging options should be allowed.
* and excess logging. Unless you want to debug or work * All debugging options will be forcefully set to
* on a sensitive part of the engine, don't enable this! * {@code false} if this option is set to {@code false}.
* *
* @since v1-alpha0 * @since v1-alpha0
* -- GETTER -- * -- GETTER --
* Gets the value for {@link #debug}. * Returns if debugging options should be allowed.
* All debugging options will be forcefully set to
* {@code false} if this option is set to {@code false}.
* *
* @return variable value * @return debugging enabled?
* @see #debug
* @since v1-alpha0 * @since v1-alpha0
*/ */
private boolean debug; private boolean debug;
/** /**
* If enabled, all called events will be logged. * Contains whether or not to log
* events being emitted.
* <p>
* This will cause all events to
* be logged, with the exception
* of the {@link LogEvent}.
* *
* @since v1-alpha0 * @since v1-alpha0
* -- GETTER -- * -- GETTER --
* Gets the value for {@link #debugEvents}. * Returns whether or not to log
* events being emitted.
* <p>
* This will cause all events to
* be logged, with the exception
* of the {@link LogEvent}.
* *
* @return variable value * @return detailed event logging enabled?
* @see #debugEvents
* @since v1-alpha0 * @since v1-alpha0
*/ */
private boolean debugEvents; private boolean debugEvents;
/** /**
* If enabled, will try to automatically initialize every * Contains whether or not to automatically discover
* subsystem found though reflection. * and initialize any class extending {@link SubsystemClass}
* whilst being annotated with {@link EngineSubsystem}.
* <p> * <p>
* This however may fail in certain situation, where manual * This mechanism may fail in certain situations, where
* subsystem initialization may be required. For this reason, * manual subsystem initialization may be desired. Make
* this can be turned off before the engine initializes. Please * sure to disable this setting before engine startup
* note though that dependency resolution between subsystems * and then initialize all subsystems manually.
* won't be performed, be careful when initializing subsystems manually.
* *
* @see Engine * @see Engine
* @since v1-alpha2 * @since v1-alpha5
* -- GETTER -- * -- GETTER --
* Gets the value for {@link #initialPerformSubsystemInitialization}. * Returns whether or not to automatically discover
* and initialize any class extending {@link SubsystemClass}
* whilst being annotated with {@link EngineSubsystem}.
* <p>
* This mechanism may fail in certain situations, where
* manual subsystem initialization may be desired. Make
* sure to disable this setting before engine startup
* and then initialize all subsystems manually.
* *
* @return variable value * @return automatically discover and initialize subsystems?
* @see #initialPerformSubsystemInitialization
* @since v1-alpha5 * @since v1-alpha5
*/ */
private boolean initialPerformSubsystemInitialization; private boolean initialPerformSubsystemInitialization;
/** /**
* Will try to load the specified classes as subsystems, * Contains a set of class names to try to load
* if reflective classpath scanning is disabled. * and initialize as subsystems. Will only take effect
* if {@link #initialPerformSubsystemInitialization} is
* turned off.
* *
* @since v1-alpha5 * @since v1-alpha5
* -- GETTER -- * -- GETTER --
* Gets the value for {@link #initialIncludeSubsystemClasses}. * Returns a set of class names to try to load
* and initialize as subsystems. Will only take effect
* if {@link #getInitialIncludeSubsystemClasses()} is
* turned off.
* *
* @return variable value * @return set of class names to try and initialize as subsystems
* @see #initialIncludeSubsystemClasses
* @since v1-alpha5 * @since v1-alpha5
*/ */
private Set<@NotNull String> initialIncludeSubsystemClasses; private Set<@NotNull String> initialIncludeSubsystemClasses;
/** /**
* If enabled, will cause {@link ShortcodeParser} to print * Contains whether or not to complain about invalid
* invalid shortcodes as {@link LogLevel#SILENT_WARNING}s. * shortcodes.
* <p>
* Requires the active log level to be set at least
* to {@link LogLevel#SILENT_WARNING} to have effect.
* *
* @see ShortcodeParser
* @see #logLevel * @see #logLevel
* @since v1-alpha0 * @since v1-alpha0
* -- GETTER -- * -- GETTER --
* Gets the value for {@link #errorShortcodeParser}. * Returns whether or not to complain about invalid
* shortcodes.
* <p>
* Requires the active log level to be set at least
* to {@link LogLevel#SILENT_WARNING} to have effect.
* *
* @return variable value * @return complain about invalid shortcodes?
* @see #errorShortcodeParser * @see #getLogLevel()
* @since v1-alpha0 * @since v1-alpha0
*/ */
private boolean errorShortcodeParser; private boolean errorShortcodeParser;
/** /**
* If enabled, will makes the {@link Logger} work asynchronous, * Contains if to log asynchronously.
* in a separate platform thread. Don't disable unless you want * <p>
* your application to run <b>extremely</b> slowly. * If enabled, will cause a logging thread
* to spawn. All log messages will be queued
* and printed after a set delay
* ({@link #logPollingSpeed}).
* Highly recommended to keep enabled, or
* the performance of your application will
* very likely suffer.
* *
* @see #logPollingSpeed * @see #logPollingSpeed
* @see Thread
* @since v1-alpha0 * @since v1-alpha0
* -- GETTER -- * -- GETTER --
* Gets the value for {@link #optimizeLogging}. * Returns if to log asynchronously.
* <p>
* If enabled, will cause a logging thread
* to spawn. All log messages will be queued
* and printed after a set delay
* ({@link #getLogPollingSpeed()}).
* Highly recommended to keep enabled, or
* the performance of your application will
* very likely suffer.
* *
* @return variable value * @return log asynchronously?
* @see #optimizeLogging * @see #getLogPollingSpeed()
* @since v1-alpha0 * @since v1-alpha0
*/ */
private boolean optimizeLogging; private boolean optimizeLogging;
/** /**
* If enabled, will make all events asynchronous, * Contains whether or not to emit events
* in separate virtual threads. Don't disable unless you * asynchronously.
* want your application to run slower. * <p>
* This will cause a
* <a href="https://openjdk.org/jeps/444">VirtualThread</a>
* to spawn every time an event is emitted.
* *
* @see VirtualThread
* @since v1-alpha0 * @since v1-alpha0
* -- GETTER -- * -- GETTER --
* Gets the value for {@link #optimizeEvents}. * Contains whether or not to emit events
* asynchronously.
* <p>
* This will cause a
* <a href="https://openjdk.org/jeps/444">VirtualThread</a>
* to spawn every time an event is emitted.
* *
* @return variable value * @return emit events asynchronously?
* @see #optimizeEvents
* @since v1-alpha0 * @since v1-alpha0
*/ */
private boolean optimizeEvents; private boolean optimizeEvents;
/** /**
* Contains which logger levels are allowed * Contains the minimum allowed log level.
* by setting the minimum logger level. * <p>
* The priority list is as follows (from high to low priority):
* <ul>
* <li>{@link LogLevel#CRASH}</li>
* <li>{@link LogLevel#ERROR}</li>
* <li>{@link LogLevel#WARNING}</li>
* <li>{@link LogLevel#INFORMATIONAL}</li>
* <li>{@link LogLevel#SILENT_WARNING}</li>
* <li>{@link LogLevel#VERBOSE}</li>
* <li>{@link LogLevel#DIAGNOSTIC}</li>
* </ul>
* *
* @see Logger
* @since v1-alpha0 * @since v1-alpha0
* -- GETTER -- * -- GETTER --
* Gets the value for {@link #logLevel}. * Returns the minimum allowed log level.
* <p>
* The priority list is as follows (from high to low priority):
* <ul>
* <li>{@link LogLevel#CRASH}</li>
* <li>{@link LogLevel#ERROR}</li>
* <li>{@link LogLevel#WARNING}</li>
* <li>{@link LogLevel#INFORMATIONAL}</li>
* <li>{@link LogLevel#SILENT_WARNING}</li>
* <li>{@link LogLevel#VERBOSE}</li>
* <li>{@link LogLevel#DIAGNOSTIC}</li>
* </ul>
* *
* @return variable value * @return minimum allowed log level
* @see #logLevel
* @since v1-alpha0 * @since v1-alpha0
*/ */
private LogLevel logLevel; private LogLevel logLevel;
@ -226,75 +293,118 @@ public final class EngineConfiguration extends Configuration {
* <li><code>lineNumber</code></li> * <li><code>lineNumber</code></li>
* </ul> * </ul>
* *
* @see Logger
* @since v1-alpha8 * @since v1-alpha8
* -- GETTER -- * -- GETTER --
* Gets the value for {@link #logFeatures} * Returns a comma-separated list of optional
* features to add to the final log output.
* <p>
* Available features (in order of appearance):
* <ul>
* <li><code>formatting</code></li>
* <li><code>runtime</code></li>
* <li><code>date</code></li>
* <li><code>time</code></li>
* <li><code>shortIssuerClass</code></li>
* <li><code>moduleName</code></li>
* <li><code>moduleVersion</code> (requires <code>moduleName</code>)</li>
* <li><code>methodName</code></li>
* <li><code>lineNumber</code></li>
* </ul>
* *
* @return variable value * @return optional features to enable
* @see #logFeatures
* @since v1-alpha8 * @since v1-alpha8
*/ */
private Set<@NotNull String> logFeatures; private Set<@NotNull String> logFeatures;
/** /**
* Contains how fast the logging thread will * Contains how fast the logging thread will
* poll for queued messages. This also causes * poll for queued messages in milliseconds.
* messages to be buffered. * This also causes messages to be buffered.
* <p> * <p>
* Only applies if {@code optimizeLogging} is turned on. * Only applies if {@code optimizeLogging} is turned on.
* Values below {@code 1} will poll for queued * Values below {@code 1} will poll for queued messages
* messages as fast as it can. This however has pretty much * as fast as it can. This however has pretty much no
* no benefit. Leave it at {@code 5}, it works quite well. * benefit. Leave it at {@code 5}, it works quite well.
* *
* @see #optimizeLogging * @see #optimizeLogging
* @since v1-alpha4 * @since v1-alpha4
* -- GETTER -- * -- GETTER --
* Gets the value for {@link #logPollingSpeed}. * Contains how fast the logging thread will
* poll for queued messages, in milliseconds.
* This also causes messages to be buffered.
* <p>
* Only applies if {@code optimizeLogging} is turned on.
* Values below {@code 1} will poll for queued messages
* as fast as it can. This however has pretty much no
* benefit. Leave it at {@code 5}, it works quite well.
* *
* @return variable value * @return logging thread polling speed in milliseconds
* @see #logPollingSpeed * @see #isOptimizeLogging()
* @since v1-alpha4 * @since v1-alpha4
*/ */
private int logPollingSpeed; private int logPollingSpeed;
/** /**
* If enabled, will force sos!engine's logging infrastructure to use * Contains whether or not to forcefully write
* <a href="https://www.man7.org/linux/man-pages/man3/stderr.3.html">the standard output</a> * to the standard output instead of the
* instead of <a href="https://www.man7.org/linux/man-pages/man3/stderr.3.html">the standard error</a> * standard error stream.
* for logging the {@code ERROR} and {@code CRASH} log levels. * <p>
* This only applies to the {@link LogLevel#ERROR} and
* {@link LogLevel#CRASH} log levels, as these use
* the standard error stream by default.
* *
* @see <a href="https://man7.org/linux/man-pages/man3/stderr.3.html">man page about standard streams</a>
* @since v1-alpha0 * @since v1-alpha0
* -- GETTER -- * -- GETTER --
* Gets the value for {@link #logForceStandardOutput}. * Contains whether or not to forcefully write
* to the standard output instead of the
* standard error stream.
* <p>
* This only applies to the {@link LogLevel#ERROR} and
* {@link LogLevel#CRASH} log levels, as these use
* the standard error stream by default.
* *
* @return variable value * @return force use stdout?
* @see #logForceStandardOutput * @see <a href="https://man7.org/linux/man-pages/man3/stderr.3.html">man page about standard streams</a>
* @since v1-alpha0 * @since v1-alpha0
*/ */
private boolean logForceStandardOutput; private boolean logForceStandardOutput;
/** /**
* Will truncate the path of types when using * Contains if to truncate the full path
* their {@code toString} method. * of a class when invoking using their
* {@link #toString()} method.
* <p> * <p>
* Here's an example: Lets say that you * Here's an example: Lets say that you have a
* have a {@link Vec2f} and to convert it * {@link Vec2f} instance and want to convert
* to a String, which you can do with * it to a String. You can do that by using
* {@link Vec2f#toString()}. With this flag * {@link Vec2f}'s {@link Vec2f#toString()}
* disabled it would return * method. With this flag disabled it will
* {@code de.staropensource.engine.base.types.vectors.}{@link Vec2i}{@code (x=64 y=64)}, * return
* with it however it would just return * {@code de.staropensource.engine.base.types.vectors.}{@link Vec2i}{@code (x=64 y=64)}.
* With this flag enabled however the method will return
* {@link Vec2i}{@code (x=64 y=64)}, * {@link Vec2i}{@code (x=64 y=64)},
* which is much smaller. * which is much smaller.
* *
* @since v1-alpha2 * @since v1-alpha2
* -- GETTER -- * -- GETTER --
* Gets the value for {@link #hideFullTypePath}. * Returns if to truncate the full path
* of a class when invoking using their
* {@link #toString()} method.
* <p>
* Here's an example: Lets say that you have a
* {@link Vec2f} instance and want to convert
* it to a String. You can do that by using
* {@link Vec2f}'s {@link Vec2f#toString()}
* method. With this flag disabled it will
* return
* {@code de.staropensource.engine.base.types.vectors.}{@link Vec2i}{@code (x=64 y=64)}.
* With this flag enabled however the method will return
* {@link Vec2i}{@code (x=64 y=64)},
* which is much smaller.
* *
* @return variable value * @return truncate class paths?
* @see #hideFullTypePath
* @since v1-alpha2 * @since v1-alpha2
*/ */
private boolean hideFullTypePath; private boolean hideFullTypePath;

View file

@ -20,11 +20,11 @@
package de.staropensource.engine.base; package de.staropensource.engine.base;
import de.staropensource.engine.base.exception.IllegalAccessException; import de.staropensource.engine.base.exception.IllegalAccessException;
import de.staropensource.engine.base.implementable.Event;
import de.staropensource.engine.base.implementable.EventListenerCode; import de.staropensource.engine.base.implementable.EventListenerCode;
import de.staropensource.engine.base.implementable.ShutdownHandler; import de.staropensource.engine.base.implementable.ShutdownHandler;
import de.staropensource.engine.base.implementable.helper.EventHelper; import de.staropensource.engine.base.implementable.helper.EventHelper;
import de.staropensource.engine.base.logging.Logger; import de.staropensource.engine.base.logging.Logger;
import de.staropensource.engine.base.type.EventPriority;
import de.staropensource.engine.base.type.InternalAccessArea; import de.staropensource.engine.base.type.InternalAccessArea;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -77,7 +77,7 @@ public final class EngineInternals {
* use case and application. * use case and application.
* *
* @see EventHelper#registerEvent(Class, EventListenerCode) * @see EventHelper#registerEvent(Class, EventListenerCode)
* @see EventHelper#registerEvent(Class, EventListenerCode, EventPriority) * @see EventHelper#registerEvent(Class, EventListenerCode, Event.Priority)
* @since v1-alpha5 * @since v1-alpha5
*/ */
private boolean reflectiveClasspathScanning = true; private boolean reflectiveClasspathScanning = true;
@ -191,7 +191,7 @@ public final class EngineInternals {
* @return reflective classpath scanning flag state * @return reflective classpath scanning flag state
* @throws IllegalAccessException when restricted ({@link InternalAccessArea#REFLECTIVE_CLASSPATH_SCANNING_GET}) * @throws IllegalAccessException when restricted ({@link InternalAccessArea#REFLECTIVE_CLASSPATH_SCANNING_GET})
* @see EventHelper#registerEvent(Class, EventListenerCode) * @see EventHelper#registerEvent(Class, EventListenerCode)
* @see EventHelper#registerEvent(Class, EventListenerCode, EventPriority) * @see EventHelper#registerEvent(Class, EventListenerCode, Event.Priority)
* @since v1-alpha5 * @since v1-alpha5
*/ */
public boolean getReflectiveClasspathScanning() throws IllegalAccessException { public boolean getReflectiveClasspathScanning() throws IllegalAccessException {
@ -216,7 +216,7 @@ public final class EngineInternals {
* @param reflectiveClasspathScanning new reflective classpath scanning * @param reflectiveClasspathScanning new reflective classpath scanning
* @throws IllegalAccessException when restricted ({@link InternalAccessArea#REFLECTIVE_CLASSPATH_SCANNING_OVERRIDE}) * @throws IllegalAccessException when restricted ({@link InternalAccessArea#REFLECTIVE_CLASSPATH_SCANNING_OVERRIDE})
* @see EventHelper#registerEvent(Class, EventListenerCode) * @see EventHelper#registerEvent(Class, EventListenerCode)
* @see EventHelper#registerEvent(Class, EventListenerCode, EventPriority) * @see EventHelper#registerEvent(Class, EventListenerCode, Event.Priority)
* @since v1-alpha5 * @since v1-alpha5
*/ */
public void overrideReflectiveClasspathScanning(boolean reflectiveClasspathScanning) throws IllegalAccessException { public void overrideReflectiveClasspathScanning(boolean reflectiveClasspathScanning) throws IllegalAccessException {

View file

@ -20,7 +20,6 @@
package de.staropensource.engine.base.annotation; package de.staropensource.engine.base.annotation;
import de.staropensource.engine.base.implementable.Event; import de.staropensource.engine.base.implementable.Event;
import de.staropensource.engine.base.type.EventPriority;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.lang.annotation.*; import java.lang.annotation.*;
@ -48,8 +47,8 @@ public @interface EventListener {
* Specifies the priority of the event. * Specifies the priority of the event.
* *
* @return event priority * @return event priority
* @see EventPriority * @see Event.Priority
* @since v1-alpha0 * @since v1-alpha0
*/ */
@NotNull EventPriority priority() default EventPriority.DEFAULT; @NotNull Event.Priority priority() default Event.Priority.DEFAULT;
} }

View file

@ -1,61 +0,0 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.base.event;
import de.staropensource.engine.base.implementable.Event;
import de.staropensource.engine.base.implementable.helper.EventHelper;
import de.staropensource.engine.base.utility.Miscellaneous;
import org.jetbrains.annotations.NotNull;
/**
* Called when an exception is caught by {@link Miscellaneous#executeSafely(Runnable, String)}.
*
* @see Miscellaneous#executeSafely(Runnable, String)
* @since v1-alpha0
*/
public final class ThrowableCatchEvent implements Event {
/**
* Creates and initializes an instance of this event.
*
* @since v1-alpha0
*/
public ThrowableCatchEvent() {}
/**
* {@inheritDoc}
*
* @deprecated use the {@code callEvent} method with arguments
* @see ThrowableCatchEvent#callEvent(Throwable, String)
*/
@Deprecated
@Override
public void callEvent() {}
/**
* Emits the event and calls all event listeners.
*
* @param throwable caught throwable
* @param identifier an identifier given to the runnable
* @since v1-alpha0
*/
public void callEvent(@NotNull Throwable throwable, @NotNull String identifier) {
EventHelper.invokeAnnotatedMethods(getClass(), throwable, identifier);
}
}

View file

@ -20,7 +20,7 @@
package de.staropensource.engine.base.exception.reflection; package de.staropensource.engine.base.exception.reflection;
import de.staropensource.engine.base.type.reflection.ClassType; import de.staropensource.engine.base.type.reflection.ClassType;
import de.staropensource.engine.base.utility.ListFormatter; import de.staropensource.engine.base.utility.misc.ListFormatter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**

View file

@ -19,6 +19,7 @@
package de.staropensource.engine.base.implementable; package de.staropensource.engine.base.implementable;
import de.staropensource.engine.base.annotation.EventListener;
import de.staropensource.engine.base.implementable.helper.EventHelper; import de.staropensource.engine.base.implementable.helper.EventHelper;
/** /**
@ -34,4 +35,76 @@ public interface Event {
* @since v1-alpha0 * @since v1-alpha0
*/ */
void callEvent(); void callEvent();
/**
* Specifies in which order {@link EventListener}s shall be called.
*
* @since v1-alpha9
*/
@SuppressWarnings({ "unused" })
enum Priority {
/**
* {@link EventListener}s with this
* priority are called before all others.
* <p>
* This priority is exclusive to the
* engine and subsystems and should
* not be used by applications.
*
* @since v1-alpha9
*/
EXCLUSIVELY_IMPORTANT,
/**
* {@link EventListener}s with
* this priority are called 2nd.
*
* @since v1-alpha9
*/
VERY_IMPORTANT,
/**
* {@link EventListener}s with
* this priority are called 3rd.
*
* @since v1-alpha9
*/
IMPORTANT,
/**
* {@link EventListener}s with
* this priority are called 4th.
*
* @since v1-alpha9
*/
DEFAULT,
/**
* {@link EventListener}s with
* this priority are called 5th.
*
* @since v1-alpha9
*/
UNIMPORTANT,
/**
* {@link EventListener}s with
* this priority are called 6th.
*
* @since v1-alpha9
*/
VERY_UNIMPORTANT,
/**
* {@link EventListener}s with this
* priority are called after all others.
* <p>
* This priority is exclusive to the
* engine and subsystems and should
* not be used by applications.
*
* @since v1-alpha9
*/
EXCLUSIVELY_UNIMPORTANT
}
} }

View file

@ -20,7 +20,6 @@
package de.staropensource.engine.base.implementable; package de.staropensource.engine.base.implementable;
import de.staropensource.engine.base.implementable.helper.EventHelper; import de.staropensource.engine.base.implementable.helper.EventHelper;
import de.staropensource.engine.base.type.EventPriority;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
@ -39,7 +38,7 @@ public abstract class EventListenerCode {
* *
* @since v1-alpha5 * @since v1-alpha5
*/ */
public @NotNull EventPriority priority = EventPriority.DEFAULT; public @NotNull Event.Priority priority = Event.Priority.DEFAULT;
/** /**
* Creates and initializes an instance of this abstract class. * Creates and initializes an instance of this abstract class.

View file

@ -32,8 +32,7 @@ import de.staropensource.engine.base.implementable.EventListenerCode;
import de.staropensource.engine.base.internal.implementation.EventListenerMethod; import de.staropensource.engine.base.internal.implementation.EventListenerMethod;
import de.staropensource.engine.base.logging.Logger; import de.staropensource.engine.base.logging.Logger;
import de.staropensource.engine.base.type.EventPriority; import de.staropensource.engine.base.utility.misc.ListFormatter;
import de.staropensource.engine.base.utility.ListFormatter;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -78,7 +77,7 @@ public final class EventHelper {
* @see EngineInternals#getReflectiveClasspathScanning() * @see EngineInternals#getReflectiveClasspathScanning()
* @since v1-alpha5 * @since v1-alpha5
*/ */
public static synchronized void registerEvent(@NotNull Class<? extends Event> event, @NotNull EventListenerCode eventListener, @NotNull EventPriority priority) { public static synchronized void registerEvent(@NotNull Class<? extends Event> event, @NotNull EventListenerCode eventListener, @NotNull Event.Priority priority) {
if (EngineInternals.getInstance().getReflectiveClasspathScanning()) if (EngineInternals.getInstance().getReflectiveClasspathScanning())
return; return;
@ -112,7 +111,7 @@ public final class EventHelper {
* @since v1-alpha5 * @since v1-alpha5
*/ */
public static void registerEvent(@NotNull Class<? extends Event> event, @NotNull EventListenerCode eventListener) { public static void registerEvent(@NotNull Class<? extends Event> event, @NotNull EventListenerCode eventListener) {
registerEvent(event, eventListener, EventPriority.DEFAULT); registerEvent(event, eventListener, Event.Priority.DEFAULT);
} }
/** /**

View file

@ -22,7 +22,7 @@ package de.staropensource.engine.base.implementation.versioning;
import de.staropensource.engine.base.implementable.VersioningSystem; import de.staropensource.engine.base.implementable.VersioningSystem;
import de.staropensource.engine.base.exception.versioning.IncompatibleVersioningSystemException; import de.staropensource.engine.base.exception.versioning.IncompatibleVersioningSystemException;
import de.staropensource.engine.base.exception.versioning.InvalidVersionStringException; import de.staropensource.engine.base.exception.versioning.InvalidVersionStringException;
import de.staropensource.engine.base.utility.Miscellaneous; import de.staropensource.engine.base.utility.misc.StringUtil;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Range; import org.jetbrains.annotations.Range;
@ -98,7 +98,7 @@ public final class FourNumberVersioningSystem implements VersioningSystem {
*/ */
public FourNumberVersioningSystem(@NotNull String versionString) throws InvalidVersionStringException { public FourNumberVersioningSystem(@NotNull String versionString) throws InvalidVersionStringException {
String[] separatorList = new String[]{ ".", "-" }; String[] separatorList = new String[]{ ".", "-" };
String separator = Miscellaneous.getSeparator(versionString, separatorList, 3); String separator = StringUtil.getSeparatorRequired(versionString, separatorList, 3);
// Escape separator or throw error if invalid // Escape separator or throw error if invalid
switch (separator) { switch (separator) {

View file

@ -22,7 +22,7 @@ package de.staropensource.engine.base.implementation.versioning;
import de.staropensource.engine.base.implementable.VersioningSystem; import de.staropensource.engine.base.implementable.VersioningSystem;
import de.staropensource.engine.base.exception.versioning.IncompatibleVersioningSystemException; import de.staropensource.engine.base.exception.versioning.IncompatibleVersioningSystemException;
import de.staropensource.engine.base.exception.versioning.InvalidVersionStringException; import de.staropensource.engine.base.exception.versioning.InvalidVersionStringException;
import de.staropensource.engine.base.utility.Miscellaneous; import de.staropensource.engine.base.utility.misc.StringUtil;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -117,7 +117,7 @@ public final class SemanticVersioningSystem implements VersioningSystem {
*/ */
public SemanticVersioningSystem(@NotNull String versionString) throws InvalidVersionStringException { public SemanticVersioningSystem(@NotNull String versionString) throws InvalidVersionStringException {
String[] separatorList = new String[]{ "." }; String[] separatorList = new String[]{ "." };
String separator = Miscellaneous.getSeparator(versionString, separatorList, 2); String separator = StringUtil.getSeparatorRequired(versionString, separatorList, 2);
// Escape separator or throw error if invalid // Escape separator or throw error if invalid
switch (separator) { switch (separator) {

View file

@ -22,7 +22,7 @@ package de.staropensource.engine.base.implementation.versioning;
import de.staropensource.engine.base.implementable.VersioningSystem; import de.staropensource.engine.base.implementable.VersioningSystem;
import de.staropensource.engine.base.exception.versioning.IncompatibleVersioningSystemException; import de.staropensource.engine.base.exception.versioning.IncompatibleVersioningSystemException;
import de.staropensource.engine.base.exception.versioning.InvalidVersionStringException; import de.staropensource.engine.base.exception.versioning.InvalidVersionStringException;
import de.staropensource.engine.base.utility.Miscellaneous; import de.staropensource.engine.base.utility.misc.StringUtil;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Range; import org.jetbrains.annotations.Range;
@ -86,7 +86,7 @@ public final class ThreeNumberVersioningSystem implements VersioningSystem {
*/ */
public ThreeNumberVersioningSystem(@NotNull String versionString) throws InvalidVersionStringException { public ThreeNumberVersioningSystem(@NotNull String versionString) throws InvalidVersionStringException {
String[] separatorList = new String[]{ ".", "-" }; String[] separatorList = new String[]{ ".", "-" };
String separator = Miscellaneous.getSeparator(versionString, separatorList, 2); String separator = StringUtil.getSeparatorRequired(versionString, separatorList, 2);
// Escape separator or throw error if invalid // Escape separator or throw error if invalid
switch (separator) { switch (separator) {

View file

@ -22,7 +22,7 @@ package de.staropensource.engine.base.implementation.versioning;
import de.staropensource.engine.base.implementable.VersioningSystem; import de.staropensource.engine.base.implementable.VersioningSystem;
import de.staropensource.engine.base.exception.versioning.IncompatibleVersioningSystemException; import de.staropensource.engine.base.exception.versioning.IncompatibleVersioningSystemException;
import de.staropensource.engine.base.exception.versioning.InvalidVersionStringException; import de.staropensource.engine.base.exception.versioning.InvalidVersionStringException;
import de.staropensource.engine.base.utility.Miscellaneous; import de.staropensource.engine.base.utility.misc.StringUtil;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Range; import org.jetbrains.annotations.Range;
@ -74,7 +74,7 @@ public final class TwoNumberVersioningSystem implements VersioningSystem {
*/ */
public TwoNumberVersioningSystem(@NotNull String versionString) throws InvalidVersionStringException { public TwoNumberVersioningSystem(@NotNull String versionString) throws InvalidVersionStringException {
String[] separatorList = new String[]{ ".", "-" }; String[] separatorList = new String[]{ ".", "-" };
String separator = Miscellaneous.getSeparator(versionString, separatorList, 1); String separator = StringUtil.getSeparatorRequired(versionString, separatorList, 1);
// Escape separator or throw error if invalid // Escape separator or throw error if invalid
switch (separator) { switch (separator) {

View file

@ -20,7 +20,7 @@
package de.staropensource.engine.base.internal.implementation.placeholder; package de.staropensource.engine.base.internal.implementation.placeholder;
import de.staropensource.engine.base.implementable.Placeholder; import de.staropensource.engine.base.implementable.Placeholder;
import de.staropensource.engine.base.utility.Math; import de.staropensource.engine.base.utility.misc.NumberUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Calendar; import java.util.Calendar;
@ -43,6 +43,6 @@ public final class DateDay implements Placeholder {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public @NotNull String replace(@NotNull String text) { public @NotNull String replace(@NotNull String text) {
return text.replace("%date_day%", Math.padNumbers(Calendar.getInstance().get(Calendar.DAY_OF_MONTH), 2)); return text.replace("%date_day%", NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.DAY_OF_MONTH), 2));
} }
} }

View file

@ -20,7 +20,7 @@
package de.staropensource.engine.base.internal.implementation.placeholder; package de.staropensource.engine.base.internal.implementation.placeholder;
import de.staropensource.engine.base.implementable.Placeholder; import de.staropensource.engine.base.implementable.Placeholder;
import de.staropensource.engine.base.utility.Math; import de.staropensource.engine.base.utility.misc.NumberUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Calendar; import java.util.Calendar;
@ -43,6 +43,6 @@ public final class DateMonth implements Placeholder {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public @NotNull String replace(@NotNull String text) { public @NotNull String replace(@NotNull String text) {
return text.replace("%date_month%", Math.padNumbers(Calendar.getInstance().get(Calendar.MONTH), 2)); return text.replace("%date_month%", NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.MONTH), 2));
} }
} }

View file

@ -20,7 +20,7 @@
package de.staropensource.engine.base.internal.implementation.placeholder; package de.staropensource.engine.base.internal.implementation.placeholder;
import de.staropensource.engine.base.implementable.Placeholder; import de.staropensource.engine.base.implementable.Placeholder;
import de.staropensource.engine.base.utility.Math; import de.staropensource.engine.base.utility.misc.NumberUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Calendar; import java.util.Calendar;
@ -43,6 +43,6 @@ public final class DateYear implements Placeholder {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public @NotNull String replace(@NotNull String text) { public @NotNull String replace(@NotNull String text) {
return text.replace("%date_year%", Math.padNumbers(Calendar.getInstance().get(Calendar.YEAR), 4)); return text.replace("%date_year%", NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.YEAR), 4));
} }
} }

View file

@ -20,7 +20,7 @@
package de.staropensource.engine.base.internal.implementation.placeholder; package de.staropensource.engine.base.internal.implementation.placeholder;
import de.staropensource.engine.base.implementable.Placeholder; import de.staropensource.engine.base.implementable.Placeholder;
import de.staropensource.engine.base.utility.Math; import de.staropensource.engine.base.utility.misc.NumberUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
@ -42,6 +42,6 @@ public final class TimeEpoch implements Placeholder {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public @NotNull String replace(@NotNull String text) { public @NotNull String replace(@NotNull String text) {
return text.replace("%time_epoch%", Math.padNumbers(System.currentTimeMillis(), String.valueOf(Long.MAX_VALUE).length())); return text.replace("%time_epoch%", NumberUtil.padNumbers(System.currentTimeMillis(), String.valueOf(Long.MAX_VALUE).length()));
} }
} }

View file

@ -20,7 +20,7 @@
package de.staropensource.engine.base.internal.implementation.placeholder; package de.staropensource.engine.base.internal.implementation.placeholder;
import de.staropensource.engine.base.implementable.Placeholder; import de.staropensource.engine.base.implementable.Placeholder;
import de.staropensource.engine.base.utility.Math; import de.staropensource.engine.base.utility.misc.NumberUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Calendar; import java.util.Calendar;
@ -43,6 +43,6 @@ public final class TimeHour implements Placeholder {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public @NotNull String replace(@NotNull String text) { public @NotNull String replace(@NotNull String text) {
return text.replace("%time_hour%", Math.padNumbers(Calendar.getInstance().get(Calendar.HOUR_OF_DAY), 2)); return text.replace("%time_hour%", NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.HOUR_OF_DAY), 2));
} }
} }

View file

@ -20,7 +20,7 @@
package de.staropensource.engine.base.internal.implementation.placeholder; package de.staropensource.engine.base.internal.implementation.placeholder;
import de.staropensource.engine.base.implementable.Placeholder; import de.staropensource.engine.base.implementable.Placeholder;
import de.staropensource.engine.base.utility.Math; import de.staropensource.engine.base.utility.misc.NumberUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Calendar; import java.util.Calendar;
@ -43,6 +43,6 @@ public final class TimeMinute implements Placeholder {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public @NotNull String replace(@NotNull String text) { public @NotNull String replace(@NotNull String text) {
return text.replace("%time_minute%", Math.padNumbers(Calendar.getInstance().get(Calendar.MINUTE), 2)); return text.replace("%time_minute%", NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.MINUTE), 2));
} }
} }

View file

@ -20,7 +20,7 @@
package de.staropensource.engine.base.internal.implementation.placeholder; package de.staropensource.engine.base.internal.implementation.placeholder;
import de.staropensource.engine.base.implementable.Placeholder; import de.staropensource.engine.base.implementable.Placeholder;
import de.staropensource.engine.base.utility.Math; import de.staropensource.engine.base.utility.misc.NumberUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Calendar; import java.util.Calendar;
@ -43,6 +43,6 @@ public final class TimeSecond implements Placeholder {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public @NotNull String replace(@NotNull String text) { public @NotNull String replace(@NotNull String text) {
return text.replace("%time_second%", Math.padNumbers(Calendar.getInstance().get(Calendar.SECOND), 2)); return text.replace("%time_second%", NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.SECOND), 2));
} }
} }

View file

@ -19,15 +19,12 @@
package de.staropensource.engine.base.logging; package de.staropensource.engine.base.logging;
import de.staropensource.engine.base.EngineConfiguration;
import de.staropensource.engine.base.implementable.LoggingAdapter; import de.staropensource.engine.base.implementable.LoggingAdapter;
import de.staropensource.engine.base.implementation.logging.PlainLoggingAdapter; import de.staropensource.engine.base.implementation.logging.PlainLoggingAdapter;
import de.staropensource.engine.base.internal.type.QueuedLogCall;
import de.staropensource.engine.base.logging.backend.CrashHandler; import de.staropensource.engine.base.logging.backend.CrashHandler;
import de.staropensource.engine.base.logging.backend.Filterer; import de.staropensource.engine.base.logging.backend.Filterer;
import de.staropensource.engine.base.logging.backend.Processor; import de.staropensource.engine.base.logging.backend.Processor;
import de.staropensource.engine.base.logging.backend.async.LoggingQueue; import de.staropensource.engine.base.logging.backend.async.LoggingQueue;
import de.staropensource.engine.base.type.immutable.ImmutableArrayList;
import de.staropensource.engine.base.type.logging.LogLevel; import de.staropensource.engine.base.type.logging.LogLevel;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@ -35,8 +32,6 @@ import org.intellij.lang.annotations.RegExp;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.List;
/** /**
* The frontend class for sos!engine's logging system. * The frontend class for sos!engine's logging system.
* *

View file

@ -24,8 +24,8 @@ import de.staropensource.engine.base.EngineConfiguration;
import de.staropensource.engine.base.EngineInternals; import de.staropensource.engine.base.EngineInternals;
import de.staropensource.engine.base.logging.Logger; import de.staropensource.engine.base.logging.Logger;
import de.staropensource.engine.base.type.logging.LogLevel; import de.staropensource.engine.base.type.logging.LogLevel;
import de.staropensource.engine.base.utility.Math; import de.staropensource.engine.base.utility.misc.NumberUtil;
import de.staropensource.engine.base.utility.Miscellaneous; import de.staropensource.engine.base.utility.misc.Miscellaneous;
import de.staropensource.engine.base.utility.information.EngineInformation; import de.staropensource.engine.base.utility.information.EngineInformation;
import de.staropensource.engine.base.utility.information.JvmInformation; import de.staropensource.engine.base.utility.information.JvmInformation;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -107,13 +107,13 @@ public final class CrashHandler {
output output
.append("\nCaused by:") .append("\nCaused by:")
.append("\nNo throwable has been passed."); .append("\nNo throwable has been passed.");
else else {
output output
.append("\n") .append("\n")
.append(Miscellaneous.getStackTraceHeader(throwable)) .append(Miscellaneous.stacktraceAsStringRecursive(throwable, true, true))
.append("\n")
.append(Miscellaneous.getStackTraceAsString(throwable, true))
.append("\n"); .append("\n");
}
output.append("\nMessage: \n") output.append("\nMessage: \n")
.append(message) .append(message)
@ -123,23 +123,23 @@ public final class CrashHandler {
output output
.append("---- Environment ----") .append("---- Environment ----")
.append("\nTime and date: ") .append("\nTime and date: ")
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.DAY_OF_MONTH), 2)) .append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.DAY_OF_MONTH), 2))
.append(".") .append(".")
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.MONTH), 2)) .append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.MONTH), 2))
.append(".") .append(".")
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.YEAR), 4)) .append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.YEAR), 4))
.append(" ") .append(" ")
.append(de.staropensource.engine.base.utility.Math.padNumbers(Calendar.getInstance().get(Calendar.HOUR_OF_DAY), 2)) .append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.HOUR_OF_DAY), 2))
.append(":") .append(":")
.append(de.staropensource.engine.base.utility.Math.padNumbers(Calendar.getInstance().get(Calendar.MINUTE), 2)) .append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.MINUTE), 2))
.append(":") .append(":")
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.SECOND), 2)) .append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.SECOND), 2))
.append(" [") .append(" [")
.append(TimeZone.getDefault().getDisplayName(false, TimeZone.SHORT, Locale.US)) .append(TimeZone.getDefault().getDisplayName(false, TimeZone.SHORT, Locale.US))
.append("]") .append("]")
.append("\nUNIX Epoch: ") .append("\nUNIX Epoch: ")
.append(Math.padNumbers(System.currentTimeMillis(), String.valueOf(Long.MAX_VALUE).length())) .append(NumberUtil.padNumbers(System.currentTimeMillis(), String.valueOf(Long.MAX_VALUE).length()))
.append("\nOperating system: ") .append("\nOperating system: ")
.append(System.getProperty("os.name")) .append(System.getProperty("os.name"))
@ -293,7 +293,7 @@ public final class CrashHandler {
.append(thread.isDaemon()) .append(thread.isDaemon())
.append("):") .append("):")
.append("\n") .append("\n")
.append(Miscellaneous.getStackTraceAsString(stacktraces.get(thread), false)) .append(Miscellaneous.stacktraceAsString(stacktraces.get(thread), false))
.append("\n"); .append("\n");
} }
output.append("\n"); output.append("\n");

View file

@ -24,7 +24,7 @@ import de.staropensource.engine.base.implementation.shortcode.EmptyShortcodePars
import de.staropensource.engine.base.logging.Logger; import de.staropensource.engine.base.logging.Logger;
import de.staropensource.engine.base.logging.backend.async.LoggingQueue; import de.staropensource.engine.base.logging.backend.async.LoggingQueue;
import de.staropensource.engine.base.type.logging.LogLevel; import de.staropensource.engine.base.type.logging.LogLevel;
import de.staropensource.engine.base.utility.Math; import de.staropensource.engine.base.utility.misc.NumberUtil;
import de.staropensource.engine.base.utility.PlaceholderEngine; import de.staropensource.engine.base.utility.PlaceholderEngine;
import de.staropensource.engine.base.utility.information.JvmInformation; import de.staropensource.engine.base.utility.information.JvmInformation;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -213,11 +213,11 @@ public final class Processor {
private static void time(@NotNull StringBuilder builder) { private static void time(@NotNull StringBuilder builder) {
if (isFeatureEnabled("time")) if (isFeatureEnabled("time"))
builder builder
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.HOUR_OF_DAY), 2)) .append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.HOUR_OF_DAY), 2))
.append(":") .append(":")
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.MINUTE), 2)) .append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.MINUTE), 2))
.append(":") .append(":")
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.SECOND), 2)); .append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.SECOND), 2));
} }
/** /**
@ -229,11 +229,11 @@ public final class Processor {
private static void date(@NotNull StringBuilder builder) { private static void date(@NotNull StringBuilder builder) {
if (isFeatureEnabled("date")) if (isFeatureEnabled("date"))
builder builder
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.DAY_OF_MONTH), 2)) .append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.DAY_OF_MONTH), 2))
.append(".") .append(".")
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.MONTH), 2)) .append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.MONTH), 2))
.append(".") .append(".")
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.YEAR), 4)); .append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.YEAR), 4));
} }
/** /**

View file

@ -21,7 +21,6 @@ package de.staropensource.engine.base.logging.backend.async;
import de.staropensource.engine.base.internal.type.QueuedLogCall; import de.staropensource.engine.base.internal.type.QueuedLogCall;
import de.staropensource.engine.base.logging.backend.Processor; import de.staropensource.engine.base.logging.backend.Processor;
import de.staropensource.engine.base.type.immutable.ImmutableArrayList;
import de.staropensource.engine.base.type.logging.LogLevel; import de.staropensource.engine.base.type.logging.LogLevel;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -67,8 +66,8 @@ public final class LoggingQueue {
* @since v1-alpha8 * @since v1-alpha8
*/ */
public static void flush() { public static void flush() {
// Get copy of and clear queue // Get copy of and clear the queue
List<@NotNull QueuedLogCall> queue = new ImmutableArrayList<>(LoggingQueue.queue); List<@NotNull QueuedLogCall> queue = new ArrayList<>(LoggingQueue.queue);
LoggingQueue.queue.clear(); LoggingQueue.queue.clear();
for (QueuedLogCall queuedCall : queue) for (QueuedLogCall queuedCall : queue)

View file

@ -20,7 +20,7 @@
package de.staropensource.engine.base.type; package de.staropensource.engine.base.type;
import de.staropensource.engine.base.EngineConfiguration; import de.staropensource.engine.base.EngineConfiguration;
import de.staropensource.engine.base.utility.Math; import de.staropensource.engine.base.utility.misc.NumberUtil;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.SneakyThrows; import lombok.SneakyThrows;
@ -42,7 +42,7 @@ import java.util.Locale;
@Getter @Getter
@Setter @Setter
@SuppressWarnings({ "JavadocDeclaration" }) @SuppressWarnings({ "JavadocDeclaration" })
public final class Color { public class Color {
/** /**
* Contains the red color value. * Contains the red color value.
* *
@ -118,10 +118,10 @@ public final class Color {
* @since v1-alpha6 * @since v1-alpha6
*/ */
private Color(int red, int green, int blue, int alpha) { private Color(int red, int green, int blue, int alpha) {
this.red = Math.boundNumber(0, 255, red); this.red = NumberUtil.limitNumber(0, 255, red);
this.green = Math.boundNumber(0, 255, green); this.green = NumberUtil.limitNumber(0, 255, green);
this.blue = Math.boundNumber(0, 255, blue); this.blue = NumberUtil.limitNumber(0, 255, blue);
this.alpha = Math.boundNumber(0, 255, alpha); this.alpha = NumberUtil.limitNumber(0, 255, alpha);
} }
/** /**

View file

@ -1,81 +0,0 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.base.type;
import de.staropensource.engine.base.annotation.EventListener;
/**
* Allows an {@link EventListener} method to specify when it should be invoked.
*
* @since v1-alpha0
*/
@SuppressWarnings({ "unused" })
public enum EventPriority {
/**
* {@link EventListener}s with this priority are processed first, even before {@link #VERY_IMPORTANT}.
* This event is exclusive to subsystems and should not be used by applications.
*
* @since v1-alpha0
*/
EXCLUSIVELY_IMPORTANT,
/**
* {@link EventListener}s with this priority are invoked first.
*
* @since v1-alpha0
*/
VERY_IMPORTANT,
/**
* {@link EventListener}s with this priority are invoked second.
*
* @since v1-alpha0
*/
IMPORTANT,
/**
* The default event priority, {@link EventListener}s with this priority are invoked third.
*
* @since v1-alpha0
*/
DEFAULT,
/**
* {@link EventListener}s with this priority are invoked fourth.
*
* @since v1-alpha0
*/
UNIMPORTANT,
/**
* {@link EventListener}s with this priority are invoked last.
*
* @since v1-alpha0
*/
VERY_UNIMPORTANT,
/**
* {@link EventListener}s with this priority are invoked last, even after {@link #VERY_UNIMPORTANT}.
* This event is exclusive to subsystems and should not be used by applications.
*
* @since v1-alpha0
*/
EXCLUSIVELY_UNIMPORTANT
}

View file

@ -29,32 +29,32 @@ import org.jetbrains.annotations.NotNull;
*/ */
public enum Tristate { public enum Tristate {
/** /**
* An unset tristate. * Defines an unset state.
* *
* @since v1-alpha1 * @since v1-alpha1
*/ */
UNSET, UNSET,
/** /**
* A true tristate. * Defines a true state.
* *
* @since v1-alpha1 * @since v1-alpha1
*/ */
TRUE, TRUE,
/** /**
* A false tristate. * Defines a false state.
* *
* @since v1-alpha1 * @since v1-alpha1
*/ */
FALSE; FALSE;
/** /**
* Converts the {@link Boolean} into a {@link Tristate}. * Converts the specified {@link Boolean} into a {@link Tristate}.
* *
* @param bool boolean to convert * @param bool boolean to convert
* @return tristated boolean * @return {@link Tristate} representation of the specified boolean
* @since v1-alpha5 * @since v1-alpha9
*/ */
public static @NotNull Tristate toTristate(boolean bool) { public static @NotNull Tristate toTristate(boolean bool) {
if (bool) return Tristate.TRUE; if (bool) return Tristate.TRUE;
@ -62,12 +62,28 @@ public enum Tristate {
} }
/** /**
* Converts the {@link Tristate} into a {@link Boolean}. * Converts the specified {@link Integer} into a {@link Tristate}.
*
* @param integer integer to convert
* @return {@link Tristate} representation of the specified integer
* @since v1-alpha9
*/
public static @NotNull Tristate toTristate(int integer) {
return switch (integer) {
case 0 -> Tristate.FALSE;
case 1 -> Tristate.TRUE;
case 2 -> Tristate.UNSET;
default -> throw new IndexOutOfBoundsException("Supplied integer '" + integer + "' is not in range 0-2");
};
}
/**
* Converts this {@link Tristate} into a {@link Boolean}.
* Make sure to check for {@link #UNSET} first. * Make sure to check for {@link #UNSET} first.
* *
* @return booleanized {@link Tristate} * @return trimmed boolean representation of this {@link Tristate}
* @throws TristateConversionException when encountering {@link #UNSET} * @throws TristateConversionException on encountering {@link #UNSET}
* @since v1-alpha2 * @since v1-alpha9
*/ */
public boolean toBoolean() { public boolean toBoolean() {
return switch (this) { return switch (this) {
@ -76,4 +92,19 @@ public enum Tristate {
case FALSE -> false; case FALSE -> false;
}; };
} }
/**
* Converts this {@link Tristate} into an {@link Integer}.
*
* @return integer representation of this {@link Tristate}
* @throws TristateConversionException when encountering {@link #UNSET}
* @since v1-alpha9
*/
public int toInteger() {
return switch (this) {
case FALSE -> 0;
case TRUE -> 1;
case UNSET -> 2;
};
}
} }

View file

@ -22,7 +22,8 @@ package de.staropensource.engine.base.type;
import de.staropensource.engine.base.implementation.versioning.StarOpenSourceVersioningSystem; import de.staropensource.engine.base.implementation.versioning.StarOpenSourceVersioningSystem;
/** /**
* Provides all available version types specified in the StarOpenSource Versioning System v2. * Provides all available version types as specified
* by the StarOpenSource Versioning System v2.
* *
* @see StarOpenSourceVersioningSystem * @see StarOpenSourceVersioningSystem
* @since v1-alpha0 * @since v1-alpha0

View file

@ -1,222 +0,0 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.base.type.immutable;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.function.UnaryOperator;
/**
* An unmodifiable {@link ArrayList}.
*
* @param <E> contained type
* @since v1-alpha1
*/
@SuppressWarnings({ "unused" })
public class ImmutableArrayList<E> extends ArrayList<E> {
/**
* Creates and initializes an instance of this class.
*
* @since v1-alpha1
*/
public ImmutableArrayList() {}
/**
* Creates and initializes an instance of this class.
* Converts a {@link LinkedList} into an {@link ImmutableArrayList}.
*
* @param list {@link List} to convert
* @since v1-alpha1
*/
public ImmutableArrayList(@NotNull List<E> list) {
super.addAll(list);
}
/**
* Converts the {@link ImmutableArrayList} into a regular {@link ArrayList}.
*
* @return mutable {@link ArrayList}
* @since v1-alpha2
*/
public @NotNull ArrayList<E> toMutable() {
return new ArrayList<>(this);
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public boolean add(E e) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public boolean addAll(@NotNull Collection<? extends E> c) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public boolean addAll(int index, @NotNull Collection<? extends E> c) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public boolean removeAll(@NotNull Collection<?> c) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public boolean retainAll(@NotNull Collection<?> c) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public void replaceAll(UnaryOperator<E> operator) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public void sort(Comparator<? super E> c) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public void clear() {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public E set(int index, E element) throws UnsupportedOperationException {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public void add(int index, E element) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public E remove(int index) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public void addFirst(E e) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public void addLast(E e) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public E removeFirst() {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public E removeLast() {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableArrayList");
}
}

View file

@ -1,167 +0,0 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.base.type.immutable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
/**
* An unmodifiable {@link HashMap}.
*
* @param <K> contained key type
* @param <V> contained value type
* @since v1-alpha1
*/
@SuppressWarnings({ "unused" })
public class ImmutableHashMap<K, V> extends HashMap<K, V> {
/**
* Creates and initializes an instance of this class.
*
* @since v1-alpha1
*/
public ImmutableHashMap() {}
/**
* Creates and initializes an instance of this class.
* Converts a {@link Map} into an {@link ImmutableHashMap}.
*
* @param map {@link Map} to convert
* @since v1-alpha1
*/
public ImmutableHashMap(@NotNull Map<K, V> map) {
for (K key : map.keySet())
super.put(key, map.get(key));
}
/**
* Converts the {@link ImmutableHashMap} into a regular {@link HashMap}.
*
* @return mutable {@link HashMap}
* @since v1-alpha2
*/
public @NotNull HashMap<K, V> toMutable() {
return new HashMap<>(this);
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, hash map is immutable
*/
@Override
public @Nullable V put(K key, V value) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, hash map is immutable
*/
@Override
public @Nullable V remove(Object key) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, hash map is immutable
*/
@Override
public void putAll(@NotNull Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, hash map is immutable
*/
@Override
public void clear() {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, hash map is immutable
*/
@Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, hash map is immutable
*/
@Override
public @Nullable V putIfAbsent(K key, V value) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, hash map is immutable
*/
@Override
public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, hash map is immutable
*/
@Override
public boolean replace(K key, V oldValue, V newValue) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, hash map is immutable
*/
@Override
public @Nullable V replace(K key, V value) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, hash map is immutable
*/
@Override
public @Nullable V merge(K key, @NotNull V value, @NotNull BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashMap");
}
}

View file

@ -1,134 +0,0 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.base.type.immutable;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
/**
* An unmodifiable {@link HashSet}.
*
* @param <E> contained type
* @since v1-alpha2
*/
@SuppressWarnings({ "unused" })
public class ImmutableHashSet<E> extends HashSet<E> {
/**
* Creates and initializes an instance of this class.
*
* @since v1-alpha2
*/
public ImmutableHashSet() {}
/**
* Creates and initializes an instance of this class.
* Converts a {@link Set} into an {@link ImmutableHashSet}.
*
* @param set {@link Set} to convert
* @since v1-alpha2
*/
public ImmutableHashSet(@NotNull Set<E> set) {
super.addAll(set);
}
/**
* Converts the {@link ImmutableHashSet} into a regular {@link HashSet}.
*
* @return mutable {@link HashSet}
* @since v1-alpha2
*/
public @NotNull HashSet<E> toMutable() {
return new HashSet<>(this);
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public boolean add(Object o) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashSet");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashSet");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public boolean addAll(@NotNull Collection collection) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashSet");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public boolean retainAll(@NotNull Collection collection) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashSet");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public boolean removeIf(Predicate filter) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashSet");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public void clear() {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashSet");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, array list is immutable
*/
@Override
public boolean removeAll(@NotNull Collection collection) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableHashSet");
}
}

View file

@ -1,167 +0,0 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.base.type.immutable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiFunction;
/**
* An unmodifiable {@link Map}.
*
* @param <K> contained key type
* @param <V> contained value type
* @since v1-alpha1
*/
@SuppressWarnings({ "unused" })
public class ImmutableLinkedHashMap<K, V> extends LinkedHashMap<K, V> {
/**
* Creates and initializes an instance of this class.
*
* @since v1-alpha1
*/
public ImmutableLinkedHashMap() {}
/**
* Creates and initializes an instance of this class.
* Converts a {@link Map} into an {@link ImmutableLinkedHashMap}.
*
* @param map {@link Map} to convert
* @since v1-alpha1
*/
public ImmutableLinkedHashMap(@NotNull Map<K, V> map) {
for (K key : map.keySet())
super.put(key, map.get(key));
}
/**
* Converts the {@link ImmutableLinkedHashMap} into a regular {@link LinkedHashMap}.
*
* @return mutable {@link LinkedHashMap}
* @since v1-alpha2
*/
public @NotNull LinkedHashMap<K, V> toMutable() {
return new LinkedHashMap<>(this);
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked hash map is immutable
*/
@Override
public @Nullable V put(K key, V value) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked hash map is immutable
*/
@Override
public @Nullable V remove(Object key) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked hash map is immutable
*/
@Override
public void putAll(@NotNull Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked hash map is immutable
*/
@Override
public void clear() {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked hash map is immutable
*/
@Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked hash map is immutable
*/
@Override
public @Nullable V putIfAbsent(K key, V value) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked hash map is immutable
*/
@Override
public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked hash map is immutable
*/
@Override
public boolean replace(K key, V oldValue, V newValue) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked hash map is immutable
*/
@Override
public @Nullable V replace(K key, V value) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedHashMap");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked hash map is immutable
*/
@Override
public @Nullable V merge(K key, @NotNull V value, @NotNull BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedHashMap");
}
}

View file

@ -1,222 +0,0 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.base.type.immutable;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.function.UnaryOperator;
/**
* An unmodifiable {@link LinkedList}.
*
* @param <E> contained type
* @since v1-alpha1
*/
@SuppressWarnings({ "unused" })
public class ImmutableLinkedList<E> extends LinkedList<E> {
/**
* Creates and initializes an instance of this class.
*
* @since v1-alpha1
*/
public ImmutableLinkedList() {}
/**
* Creates and initializes an instance of this class.
* Converts a {@link LinkedList} into an {@link ImmutableLinkedList}.
*
* @param list {@link List} to convert
* @since v1-alpha1
*/
public ImmutableLinkedList(@NotNull List<E> list) {
super.addAll(size(), list);
}
/**
* Converts the {@link ImmutableLinkedList} into a regular {@link LinkedList}.
*
* @return mutable {@link LinkedList}
* @since v1-alpha2
*/
public @NotNull LinkedList<E> toMutable() {
return new LinkedList<>(this);
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public boolean add(E e) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public boolean addAll(@NotNull Collection<? extends E> c) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public boolean addAll(int index, @NotNull Collection<? extends E> c) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public boolean removeAll(@NotNull Collection<?> c) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public boolean retainAll(@NotNull Collection<?> c) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public void replaceAll(UnaryOperator<E> operator) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public void sort(Comparator<? super E> c) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public void clear() {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public E set(int index, E element) throws UnsupportedOperationException {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public void add(int index, E element) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public E remove(int index) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public void addFirst(E e) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public void addLast(E e) {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public E removeFirst() {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always, linked list is immutable
*/
@Override
public E removeLast() {
throw new UnsupportedOperationException("This method cannot be executed on an ImmutableLinkedList");
}
}

View file

@ -1,25 +0,0 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Immutable variations of regular Java data types.
*
* @since v1-alpha1
*/
package de.staropensource.engine.base.type.immutable;

View file

@ -1,68 +0,0 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.base.type.logging;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Defines a rule used during logging to allow or prevent certain log calls.
*
* @since v1-alpha1
*/
@Getter
@SuppressWarnings({ "JavadocDeclaration" })
public abstract class LogRule {
/**
* Contains if the log rule should disallow or permit matching log calls.
*
* @see LogRuleType
* @since v1-alpha1
* -- GETTER --
* Returns if the log rule should disallow or permit matching log calls.
*
* @return rule type
* @see LogRuleType
* @since v1-alpha1
*/
private final @NotNull LogRuleType type;
/**
* Creates and initializes an instance of this abstract class.
*
* @param type rule type
*/
public LogRule(@NotNull LogRuleType type) {
this.type = type;
}
/**
* Evaluates the rule and returns if the rule matches.
*
* @param level level
* @param issuerClass class of the issuer
* @param issuerOrigin origin of the issuer
* @param issuerMetadata metadata about the issuer
* @param message raw message
* @return if the rule matches
*/
public abstract boolean evaluate(@NotNull LogLevel level, @NotNull Class<?> issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message);
}

View file

@ -1,43 +0,0 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.base.type.logging;
/**
* Used for determining if a {@link LogRule} should allow (whitelist) or prevent (blacklist) log call processing.
*
* @since v1-alpha1
*/
public enum LogRuleType {
/**
* Indicates that log calls matching this rule will always be allowed, even if blacklisted.
*
* @see #BLACKLIST
* @since v1-alpha1
*/
WHITELIST,
/**
* Indicates that log calls matching this will always be disallowed except when whitelisted.
*
* @see #WHITELIST
* @since v1-alpha1
*/
BLACKLIST
}

View file

@ -22,7 +22,7 @@ package de.staropensource.engine.base.utility;
import de.staropensource.engine.base.Engine; import de.staropensource.engine.base.Engine;
import de.staropensource.engine.base.logging.Logger; import de.staropensource.engine.base.logging.Logger;
import de.staropensource.engine.base.type.EngineState; import de.staropensource.engine.base.type.EngineState;
import de.staropensource.engine.base.type.FileType; import de.staropensource.engine.base.utility.misc.Miscellaneous;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -190,7 +190,7 @@ public final class FileAccess {
if (Files.exists(path)) if (Files.exists(path))
Logger.error("Deleting file or directory \"" + path + "\" failed"); Logger.error("Deleting file or directory \"" + path + "\" failed");
} catch (Exception exception) { } catch (Exception exception) {
Logger.error("File or directory \"" + path + "\" could not be deleted\n" + Miscellaneous.getStackTraceHeader(exception) + "\n" + Miscellaneous.getStackTraceAsString(exception, true)); Logger.error("File or directory \"" + path + "\" could not be deleted\n" + Miscellaneous.throwableHeader(exception) + "\n" + Miscellaneous.stacktraceAsString(exception, true));
} }
} }
} }
@ -267,15 +267,15 @@ public final class FileAccess {
* @return file type * @return file type
* @since v1-alpha8 * @since v1-alpha8
*/ */
public @NotNull FileType getType() { public @NotNull FileAccess.Type getType() {
if (!exists()) if (!exists())
return FileType.VOID; return Type.VOID;
else if (Files.isRegularFile(path)) else if (Files.isRegularFile(path))
return FileType.FILE; return Type.FILE;
else if (Files.isDirectory(path)) else if (Files.isDirectory(path))
return FileType.DIRECTORY; return Type.DIRECTORY;
else else
return FileType.UNKNOWN; return Type.UNKNOWN;
} }
/** /**
@ -309,7 +309,7 @@ public final class FileAccess {
* @since v1-alpha8 * @since v1-alpha8
*/ */
public @NotNull String @NotNull [] listContents() throws UnsupportedOperationException, IOException { public @NotNull String @NotNull [] listContents() throws UnsupportedOperationException, IOException {
if (getType() != FileType.DIRECTORY) if (getType() != Type.DIRECTORY)
throw new UnsupportedOperationException("The file \"" + path + "\" is not a directory"); throw new UnsupportedOperationException("The file \"" + path + "\" is not a directory");
String[] list = file.list(); String[] list = file.list();
@ -661,7 +661,7 @@ public final class FileAccess {
* Returns the contents of this file. * Returns the contents of this file.
* <p> * <p>
* Returns an empty array if this file * Returns an empty array if this file
* is not of type {@link FileType#FILE}. * is not of type {@link Type#FILE}.
* *
* @return file contents in bytes * @return file contents in bytes
* @throws IOException on an IO error * @throws IOException on an IO error
@ -669,7 +669,7 @@ public final class FileAccess {
* @since v1-alpha8 * @since v1-alpha8
*/ */
public byte @NotNull [] readBytes() throws IOException, OutOfMemoryError { public byte @NotNull [] readBytes() throws IOException, OutOfMemoryError {
if (getType() != FileType.FILE) if (getType() != Type.FILE)
return new byte[0]; return new byte[0];
Logger.diag("Reading file \"" + path + "\" (bytes)"); Logger.diag("Reading file \"" + path + "\" (bytes)");
@ -680,7 +680,7 @@ public final class FileAccess {
* Returns the contents of this file. * Returns the contents of this file.
* <p> * <p>
* Returns an empty list if this file * Returns an empty list if this file
* is not of type {@link FileType#FILE}. * is not of type {@link Type#FILE}.
* *
* @return file contents in bytes * @return file contents in bytes
* @throws IOException on an IO error * @throws IOException on an IO error
@ -688,7 +688,7 @@ public final class FileAccess {
* @since v1-alpha8 * @since v1-alpha8
*/ */
public @NotNull List<@NotNull String> readLines() throws IOException, OutOfMemoryError { public @NotNull List<@NotNull String> readLines() throws IOException, OutOfMemoryError {
if (getType() != FileType.FILE) if (getType() != Type.FILE)
return new ArrayList<>(); return new ArrayList<>();
Logger.diag("Reading file \"" + path + "\" (lines)"); Logger.diag("Reading file \"" + path + "\" (lines)");
@ -701,7 +701,7 @@ public final class FileAccess {
* {@link StandardCharsets#UTF_8} character set. * {@link StandardCharsets#UTF_8} character set.
* <p> * <p>
* Returns an empty string if this file * Returns an empty string if this file
* is not of type {@link FileType#FILE}. * is not of type {@link Type#FILE}.
* *
* @return file contents as a string * @return file contents as a string
* @throws IOException on an IO error * @throws IOException on an IO error
@ -716,7 +716,7 @@ public final class FileAccess {
* Returns the contents of this file. * Returns the contents of this file.
* <p> * <p>
* Returns an empty string if this file * Returns an empty string if this file
* is not of type {@link FileType#FILE}. * is not of type {@link Type#FILE}.
* *
* @param charset charset to decode the bytes with * @param charset charset to decode the bytes with
* @return file contents as a string * @return file contents as a string
@ -725,7 +725,7 @@ public final class FileAccess {
* @since v1-alpha8 * @since v1-alpha8
*/ */
public @NotNull String readContent(@NotNull Charset charset) throws IOException, OutOfMemoryError { public @NotNull String readContent(@NotNull Charset charset) throws IOException, OutOfMemoryError {
if (getType() != FileType.FILE) if (getType() != Type.FILE)
return ""; return "";
Logger.diag("Reading file \"" + path + "\" (string)"); Logger.diag("Reading file \"" + path + "\" (string)");
@ -739,15 +739,15 @@ public final class FileAccess {
* *
* @param bytes bytes to write * @param bytes bytes to write
* @param async allows the operating system to decide when to flush the file to disk if {@code true}, flushes the data to disk immediately if {@code false} * @param async allows the operating system to decide when to flush the file to disk if {@code true}, flushes the data to disk immediately if {@code false}
* @throws UnsupportedOperationException if the type of this file is neither {@link FileType#VOID} or {@link FileType#FILE} * @throws UnsupportedOperationException if the type of this file is neither {@link Type#VOID} or {@link Type#FILE}
* @throws IOException on an IO error * @throws IOException on an IO error
* @return this instance * @return this instance
*/ */
public @NotNull FileAccess writeBytes(byte @NotNull [] bytes, boolean async) throws UnsupportedOperationException, IOException { public @NotNull FileAccess writeBytes(byte @NotNull [] bytes, boolean async) throws UnsupportedOperationException, IOException {
if (getType() == FileType.VOID) if (getType() == Type.VOID)
createFile(); createFile();
else if (getType() != FileType.FILE) else if (getType() != Type.FILE)
throw new UnsupportedOperationException("File \"" + path + "\" is not of type FileType.VOID or FileType.FILE"); throw new UnsupportedOperationException("File \"" + path + "\" is not of type Type.VOID or Type.FILE");
createFile(); createFile();
Logger.diag("Writing file \"" + path + "\" (bytes, " + (async ? "async" : "dsync") + ")"); Logger.diag("Writing file \"" + path + "\" (bytes, " + (async ? "async" : "dsync") + ")");
@ -762,7 +762,7 @@ public final class FileAccess {
* *
* @param string string to write * @param string string to write
* @param async allows the operating system to decide when to flush the file to disk if {@code true}, flushes the data to disk immediately if {@code false} * @param async allows the operating system to decide when to flush the file to disk if {@code true}, flushes the data to disk immediately if {@code false}
* @throws UnsupportedOperationException if the type of this file is neither {@link FileType#VOID} or {@link FileType#FILE} * @throws UnsupportedOperationException if the type of this file is neither {@link Type#VOID} or {@link Type#FILE}
* @throws IOException on an IO error * @throws IOException on an IO error
* @return this instance * @return this instance
*/ */
@ -776,15 +776,15 @@ public final class FileAccess {
* @param string string to write * @param string string to write
* @param charset charset to encode the string in * @param charset charset to encode the string in
* @param async allows the operating system to decide when to flush the file to disk if {@code true}, flushes the data to disk immediately if {@code false} * @param async allows the operating system to decide when to flush the file to disk if {@code true}, flushes the data to disk immediately if {@code false}
* @throws UnsupportedOperationException if the type of this file is neither {@link FileType#VOID} or {@link FileType#FILE} * @throws UnsupportedOperationException if the type of this file is neither {@link Type#VOID} or {@link Type#FILE}
* @throws IOException on an IO error * @throws IOException on an IO error
* @return this instance * @return this instance
*/ */
public @NotNull FileAccess writeString(@NotNull String string, @NotNull Charset charset, boolean async) throws UnsupportedOperationException, IOException { public @NotNull FileAccess writeString(@NotNull String string, @NotNull Charset charset, boolean async) throws UnsupportedOperationException, IOException {
if (getType() == FileType.VOID) if (getType() == Type.VOID)
createFile(); createFile();
else if (getType() != FileType.FILE) else if (getType() != Type.FILE)
throw new UnsupportedOperationException("File \"" + path + "\" is not of type FileType.VOID or FileType.FILE"); throw new UnsupportedOperationException("File \"" + path + "\" is not of type Type.VOID or Type.FILE");
Logger.diag("Writing file \"" + path + "\" (string, " + (async ? "async" : "dsync") + ")"); Logger.diag("Writing file \"" + path + "\" (string, " + (async ? "async" : "dsync") + ")");
Files.writeString(path, string, charset, StandardOpenOption.WRITE, async ? StandardOpenOption.DSYNC : StandardOpenOption.SYNC); Files.writeString(path, string, charset, StandardOpenOption.WRITE, async ? StandardOpenOption.DSYNC : StandardOpenOption.SYNC);
@ -798,15 +798,15 @@ public final class FileAccess {
* *
* @param bytes bytes to append * @param bytes bytes to append
* @param async allows the operating system to decide when to flush the file to disk if {@code true}, flushes the data to disk immediately if {@code false} * @param async allows the operating system to decide when to flush the file to disk if {@code true}, flushes the data to disk immediately if {@code false}
* @throws UnsupportedOperationException if the type of this file is neither {@link FileType#VOID} or {@link FileType#FILE} * @throws UnsupportedOperationException if the type of this file is neither {@link Type#VOID} or {@link Type#FILE}
* @throws IOException on an IO error * @throws IOException on an IO error
* @return this instance * @return this instance
*/ */
public @NotNull FileAccess appendBytes(byte @NotNull [] bytes, boolean async) throws UnsupportedOperationException, IOException { public @NotNull FileAccess appendBytes(byte @NotNull [] bytes, boolean async) throws UnsupportedOperationException, IOException {
if (getType() == FileType.VOID) if (getType() == Type.VOID)
createFile(); createFile();
else if (getType() != FileType.FILE) else if (getType() != Type.FILE)
throw new UnsupportedOperationException("File \"" + path + "\" is not of type FileType.VOID or FileType.FILE"); throw new UnsupportedOperationException("File \"" + path + "\" is not of type Type.VOID or Type.FILE");
Logger.diag("Appending file \"" + path + "\" (bytes, " + (async ? "async" : "dsync") + ")"); Logger.diag("Appending file \"" + path + "\" (bytes, " + (async ? "async" : "dsync") + ")");
Files.write(path, bytes, StandardOpenOption.APPEND, async ? StandardOpenOption.DSYNC : StandardOpenOption.SYNC); Files.write(path, bytes, StandardOpenOption.APPEND, async ? StandardOpenOption.DSYNC : StandardOpenOption.SYNC);
@ -820,7 +820,7 @@ public final class FileAccess {
* *
* @param string string to append * @param string string to append
* @param async allows the operating system to decide when to flush the file to disk if {@code true}, flushes the data to disk immediately if {@code false} * @param async allows the operating system to decide when to flush the file to disk if {@code true}, flushes the data to disk immediately if {@code false}
* @throws UnsupportedOperationException if the type of this file is neither {@link FileType#VOID} or {@link FileType#FILE} * @throws UnsupportedOperationException if the type of this file is neither {@link Type#VOID} or {@link Type#FILE}
* @throws IOException on an IO error * @throws IOException on an IO error
* @return this instance * @return this instance
*/ */
@ -834,18 +834,53 @@ public final class FileAccess {
* @param string string to append * @param string string to append
* @param charset charset to encode the string in * @param charset charset to encode the string in
* @param async allows the operating system to decide when to flush the file to disk if {@code true}, flushes the data to disk immediately if {@code false} * @param async allows the operating system to decide when to flush the file to disk if {@code true}, flushes the data to disk immediately if {@code false}
* @throws UnsupportedOperationException if the type of this file is neither {@link FileType#VOID} or {@link FileType#FILE} * @throws UnsupportedOperationException if the type of this file is neither {@link Type#VOID} or {@link Type#FILE}
* @throws IOException on an IO error * @throws IOException on an IO error
* @return this instance * @return this instance
*/ */
public @NotNull FileAccess appendString(@NotNull String string, @NotNull Charset charset, boolean async) throws UnsupportedOperationException, IOException { public @NotNull FileAccess appendString(@NotNull String string, @NotNull Charset charset, boolean async) throws UnsupportedOperationException, IOException {
if (getType() == FileType.VOID) if (getType() == Type.VOID)
createFile(); createFile();
else if (getType() != FileType.FILE) else if (getType() != Type.FILE)
throw new UnsupportedOperationException("File \"" + path + "\" is not of type FileType.VOID or FileType.FILE"); throw new UnsupportedOperationException("File \"" + path + "\" is not of type Type.VOID or Type.FILE");
Logger.diag("Appending file \"" + path + "\" (string, " + (async ? "async" : "dsync") + ")"); Logger.diag("Appending file \"" + path + "\" (string, " + (async ? "async" : "dsync") + ")");
Files.writeString(path, string, charset, StandardOpenOption.APPEND, async ? StandardOpenOption.DSYNC : StandardOpenOption.SYNC); Files.writeString(path, string, charset, StandardOpenOption.APPEND, async ? StandardOpenOption.DSYNC : StandardOpenOption.SYNC);
return this; return this;
} }
/**
* Represents various file types.
*
* @since v1-alpha8
*/
public enum Type {
/**
* The path does not exist.
*
* @since v1-alpha8
*/
VOID,
/**
* It's a regular file.
*
* @since v1-alpha8
*/
FILE,
/**
* It's a directory containing files.
*
* @since v1-alpha8
*/
DIRECTORY,
/**
* The file type is unknown to the sos!engine.
*
* @since v1-alpha8
*/
UNKNOWN
}
} }

View file

@ -1,254 +0,0 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.base.utility;
import de.staropensource.engine.base.event.ThrowableCatchEvent;
import de.staropensource.engine.base.exception.TristateConversionException;
import de.staropensource.engine.base.type.Tristate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Range;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.stream.Collectors;
/**
* Contains smaller functions that don't fit into other utility classes.
*
* @since v1-alpha0
*/
@SuppressWarnings({ "unused" })
public final class Miscellaneous {
/**
* Creates and initializes an instance of this class.
*
* @since v1-alpha6
*/
private Miscellaneous() {}
/**
* Converts a boolean into an integer.
*
* @param bool boolean to convert
* @return converted integer
* @since v1-alpha2
*/
@Range(from = 0, to = 1)
public static int getIntegerizedBoolean(boolean bool) {
return bool ? 1 : 0;
}
/**
* Converts an integer into a {@link Tristate}.
*
* @param integer integer to convert
* @return expected boolean result, except if neither {@code 0} or {@code 1}, in which case {@link Tristate#UNSET} is returned
* @since v1-alpha2
*/
public static Tristate getTristatedInteger(@Range(from = 0, to = 1) int integer) {
return switch (integer) {
case 0 -> Tristate.TRUE;
case 1 -> Tristate.FALSE;
default -> Tristate.UNSET;
};
}
/**
* Converts an integer into a {@link Tristate} and then into a boolean.
*
* @param integer integer to convert
* @return booleanized integer
* @throws TristateConversionException when encountering {@link Tristate#UNSET}.
* @since v1-alpha2
*/
public static boolean getBooleanizedInteger(@Range(from = 0, to = 1) int integer) throws TristateConversionException {
return getTristatedInteger(integer).toBoolean();
}
/**
* Searches for a value in a {@link Map}.
*
* @param map map to use
* @param value value to search for
* @return all keys matching the specified value
* @since v1-alpha0
*/
public static Set<?> getMapValues(@NotNull Map<?, ?> map, @Nullable Object value) {
return map
.entrySet().stream()
.filter(entry -> Objects.equals(entry.getValue(), value))
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
}
/**
* Counts the occurrences of a substring inside of a string.
*
* @param string string to search
* @param substring substring to search for
* @return occurrences
*/
public static long countOccurrences(@NotNull String string, @NotNull String substring) {
return (string.length() - string.replace(substring, "").length()) / substring.length();
}
/**
* Returns the correct separator to use when splitting a string.
*
* @param string string to split
* @param separators separators to check
* @param requiredOccurrences exact amount of occurrences for a separator to be deemed valid
* @return separator to use or {@code null}
* @since v1-alpha1
*/
public static @Nullable String getSeparator(@NotNull String string, @NotNull String @NotNull [] separators, int requiredOccurrences) {
if (string.isBlank() || separators.length == 0 || requiredOccurrences == 0)
return null;
for (String separator : separators)
if (countOccurrences(string, separator) == requiredOccurrences)
return separator;
return null;
}
/**
* Returns the correct separator to use when splitting a string.
*
* @param string string to split
* @param separators separators to check
* @param minimumOccurrences minimum amount of occurrences for a separator to be deemed valid
* @return separator to use or {@code null}
* @since v1-alpha1
*/
public static @Nullable String getSeparator(@NotNull String string, List<String> separators, Integer minimumOccurrences) {
for (String separator : separators)
if (countOccurrences(string, separator) >= minimumOccurrences)
return separator;
return null;
}
/**
* Measures the execution time of a {@link Runnable}.
*
* @param runnable {@link Runnable} to execute
* @return execution time in milliseconds
* @see Runnable
* @since v1-alpha0
*/
public static long measureExecutionTime(@NotNull Runnable runnable) {
long initTime = System.currentTimeMillis();
runnable.run();
return System.currentTimeMillis() - initTime;
}
/**
* Executes a {@link Runnable} and emits {@link ThrowableCatchEvent} if a throwable is caught.
*
* @param runnable {@link Runnable} to execute
* @param identifier some identifier to distinguish {@link Runnable}s
* @since v1-alpha1
*/
public static void executeSafely(@NotNull Runnable runnable, @NotNull String identifier) {
try {
runnable.run();
} catch (Throwable throwable) {
new ThrowableCatchEvent().callEvent(throwable, identifier);
}
}
/**
* Forcefully invokes the garbage collector
* and blocks execution until finished.
* If you want to run it in parallel to your
* program, consider running it in a {@code VirtualThread}.
* <p>
* This method does not guarantee full garbage collection,
* as the JVM only hints the garbage collector to do it's job.
* This is because all garbage collectors are non-deterministic.
*
* @since v1-alpha0
*/
@SuppressWarnings("UnusedAssignment")
public static void invokeGarbageCollector() {
Object object = new Object();
WeakReference<Object> weakReference = new WeakReference<>(object);
object = null;
while(weakReference.get() != null) System.gc();
}
/**
* Ensures that the code is running on the main thread.
*
* @return {@code true} if running on the main thread, {@code false} otherwise
* @since v1-alpha2
*/
public static boolean onMainThread() {
return Thread.currentThread().threadId() == 1;
}
/**
* Returns the {@code Caused by} message usually found when the JVM prints a throwable.
*
* @param throwable {@link Throwable} to use
* @return stack trace header
* @since v1-alpha4
*/
public static @NotNull String getStackTraceHeader(@NotNull Throwable throwable) {
return "Caused by: " + throwable.getClass().getName() + (throwable.getMessage() == null ? "" : ": " + throwable.getMessage());
}
/**
* Converts an array of {@link StackTraceElement}s into a regular string.
*
* @param stacktrace array of {@link StackTraceElement}s to convert
* @param indent if all lines should be indented with a single {@code \t} character, like in regular stack traces
* @return converted stacktrace string
* @since v1-alpha4
*/
public static @NotNull String getStackTraceAsString(@NotNull StackTraceElement @NotNull [] stacktrace, boolean indent) {
StringBuilder output = new StringBuilder();
for (StackTraceElement element : stacktrace) {
if (!output.isEmpty())
output.append("\n");
if (indent)
output.append("\t");
output.append("at ").append(element);
}
return output.toString();
}
/**
* Converts the stacktrace of a throwable into a regular string.
*
* @param throwable throwable to derive the stacktrace from
* @param indent if all lines should be indented with a single {@code \t} character, like in regular stack traces
* @return converted stacktrace string
* @since v1-alpha4
*/
public static @NotNull String getStackTraceAsString(@NotNull Throwable throwable, boolean indent) {
return getStackTraceAsString(throwable.getStackTrace(), indent);
}
}

View file

@ -20,11 +20,11 @@
package de.staropensource.engine.base.utility.information; package de.staropensource.engine.base.utility.information;
import de.staropensource.engine.base.logging.Logger; import de.staropensource.engine.base.logging.Logger;
import de.staropensource.engine.base.type.immutable.ImmutableArrayList;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage; import java.lang.management.MemoryUsage;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -114,7 +114,7 @@ public final class JvmInformation {
* @since v1-alpha0 * @since v1-alpha0
*/ */
public static @NotNull List<@NotNull String> getArguments() { public static @NotNull List<@NotNull String> getArguments() {
return new ImmutableArrayList<>(ManagementFactory.getRuntimeMXBean().getInputArguments()); return Collections.unmodifiableList(ManagementFactory.getRuntimeMXBean().getInputArguments());
} }
/** /**

View file

@ -0,0 +1,77 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.base.utility.misc;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collections;
/**
* Manipulates arrays.
*
* @since v1-alpha9
*/
public final class ArrayUtil {
/**
* Removes the first {@code n} elements
* from the specified array.
* <p>
* If {@code n} is bigger than the
* amount of elements in the
* specified array, an empty array
* will be returned.
*
* @param array array to operate on
* @param n amount to remove
* @return array with the first elements removed
* @since v1-alpha9
*/
public static <T> @Nullable T @NotNull [] removeFirst(@Nullable T @NotNull [] array, int n) {
try {
return Arrays.copyOfRange(array, n, array.length);
} catch (ArrayIndexOutOfBoundsException | IllegalArgumentException exception) {
return Collections.emptyList().toArray(array);
}
}
/**
* Removes the last {@code n} elements
* from the specified array.
* <p>
* If {@code n} is bigger than the
* amount of elements in the
* specified array, an empty array
* will be returned.
*
* @param array array to operate on
* @param n amount to remove
* @return array with the last elements removed
* @since v1-alpha9
*/
public static <T> @Nullable T @NotNull [] removeLast(@Nullable T @NotNull [] array, int n) {
try {
return Arrays.copyOfRange(array, 0, array.length-n);
} catch (ArrayIndexOutOfBoundsException | IllegalArgumentException exception) {
return Collections.emptyList().toArray(array);
}
}
}

View file

@ -17,43 +17,49 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.base.utility; package de.staropensource.engine.base.utility.misc;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.List; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* Converts various data types to {@link String}s. * Converts arrays, arrays and maps to look like
* nicely formatted lists (as {@link String}s).
* *
* @since v1-alpha4 * @since v1-alpha9
*/ */
public final class ListFormatter { public final class ListFormatter {
/** /**
* Creates and initializes an instance of this class. * Creates and initializes an instance of this class.
* *
* @since v1-alpha6 * @since v1-alpha9
*/ */
private ListFormatter() {} private ListFormatter() {}
/** /**
* Converts an array to a {@link String}. * Converts the specified array to a {@link String}.
* <p>
* For {@code formatArray(array, ", ", " & ")} the
* something like following string will be returned:
* {@code element 1, element 2, element 3 & element 4}
* *
* @param array array to convert * @param array array to convert
* @param itemSeparator string used to separate two items
* @param finalSeparator string used to separate the final two items
* @return formatted string * @return formatted string
* @since v1-alpha4 * @since v1-alpha9
*/ */
public static @NotNull String formatArray(@NotNull Object @NotNull [] array) { public static @NotNull String formatArray(@NotNull Object @NotNull [] array, @NotNull String itemSeparator, @NotNull String finalSeparator) {
StringBuilder output = new StringBuilder(); StringBuilder output = new StringBuilder();
for (int index = 0; index < array.length; index++) { for (int index = 0; index < array.length; index++) {
if (!output.isEmpty()) if (!output.isEmpty())
if (index == array.length - 1) if (index == array.length - 1)
output.append(" & "); output.append(finalSeparator);
else else
output.append(", "); output.append(itemSeparator);
output.append(array[index]); output.append(array[index]);
} }
@ -62,25 +68,50 @@ public final class ListFormatter {
} }
/** /**
* Converts a {@link Set} to a {@link String}. * Converts the specified array to a {@link String}.
* <p>
* This will produce something like this:
* {@code element 1, element 2, element 3 & element 4}
* *
* @param set set to convert * @param array array to convert
* @return formatted string * @return formatted string
* @since v1-alpha4 * @since v1-alpha9
*/ */
public static @NotNull String formatSet(@NotNull Set<?> set) { public static @NotNull String formatArray(@NotNull Object @NotNull [] array) {
return formatArray(set.toArray()); return formatArray(array, ", ", " & ");
} }
/** /**
* Converts a {@link List} to a {@link String}.
/**
* Converts the specified array to a {@link String}.
* <p>
* For {@code formatArray(array, ", ", " & ")} the
* something like following string will be returned:
* {@code element 1, element 2, element 3 & element 4}
* *
* @param list list to convert * @param collection collection to convert
* @param itemSeparator string used to separate two items
* @param finalSeparator string used to separate the final two items
* @return formatted string * @return formatted string
* @since v1-alpha4 * @since v1-alpha9
*/ */
public static @NotNull String formatList(@NotNull List<?> list) { public static @NotNull String formatCollection(@NotNull Collection<?> collection, @NotNull String itemSeparator, @NotNull String finalSeparator) {
return formatArray(list.toArray()); return formatArray(collection.toArray(), itemSeparator, finalSeparator);
}
/**
* Converts the specified {@link Collection} to a {@link String}.
* <p>
* This will produce something like this:
* {@code element 1, element 2, element 3 & element 4}
*
* @param collection collection to convert
* @return formatted string
* @since v1-alpha9
*/
public static @NotNull String formatCollection(@NotNull Collection<?> collection) {
return formatArray(collection.toArray());
} }
/** /**
@ -88,7 +119,7 @@ public final class ListFormatter {
* *
* @param map map to convert * @param map map to convert
* @return formatted string * @return formatted string
* @since v1-alpha4 * @since v1-alpha9
*/ */
public static @NotNull String formatMap(@NotNull Map<?, ?> map) { public static @NotNull String formatMap(@NotNull Map<?, ?> map) {
StringBuilder output = new StringBuilder(); StringBuilder output = new StringBuilder();

View file

@ -0,0 +1,211 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.base.utility.misc;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;
/**
* Contains the most miscellaneous of all miscellaneous methods.
*
* @since v1-alpha9
*/
@SuppressWarnings({ "unused" })
public final class Miscellaneous {
/**
* Creates and initializes an instance of this class.
*
* @since v1-alpha9
*/
private Miscellaneous() {}
/**
* Searches for a value in a {@link Map}.
*
* @param map map to use
* @param value value to search for
* @return all keys matching the specified value
* @since v1-alpha9
*/
public static Set<?> searchForValueInMap(@NotNull Map<?, ?> map, @Nullable Object value) {
return map
.entrySet().stream()
.filter(entry -> Objects.equals(entry.getValue(), value))
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
}
/**
* Measures the execution time of
* the specified {@link Runnable}.
*
* @param runnable {@link Runnable} to execute
* @return execution time in milliseconds
* @see Runnable
* @since v1-alpha9
*/
public static long measureExecutionTime(@NotNull Runnable runnable) {
long initTime = System.currentTimeMillis();
runnable.run();
return System.currentTimeMillis() - initTime;
}
/**
* Forcefully invokes the garbage collector
* and blocks execution until finished.
* If you want to run it in parallel to your
* program, consider running it in a thread.
* <p>
* This method does not guarantee full garbage collection,
* as the JVM only hints the garbage collector to do it's
* job. All garbage collectors are non-deterministic and
* cannot be invoked by force. And even if this method
* manages to invoke the garbage collector, a full garbage
* collection likely will never be archived. This is because
* the garbage collector will never throw everything into
* the trash. In addition, this method will only return if
* it's {@link WeakReference} becomes null. The garbage
* collector may or may not do more afterwards. This method
* just exists if someone wants to at least try to
* forcefully invoke the garbage collector. If you want
* a somewhat more reliable method, use Java Agents.
*
* @since v1-alpha9
*/
@SuppressWarnings("UnusedAssignment")
public static void invokeGarbageCollector() {
Object object = new Object();
WeakReference<Object> weakReference = new WeakReference<>(object);
object = null;
while(weakReference.get() != null) System.gc();
}
/**
* Returns if the code it is invoked by
* is running on the Java main thread.
*
* @return running on main thread?
* @since v1-alpha9
*/
public static boolean onMainThread() {
return Thread.currentThread().threadId() == 1;
}
/**
* Returns the {@code Caused by} message
* usually found in JVM stack traces.
*
* @param throwable {@link Throwable} to use
* @return {@link Throwable} header
* @since v1-alpha9
*/
public static @NotNull String throwableHeader(@NotNull Throwable throwable) {
return "Caused by: " + throwable.getClass().getName() + (throwable.getMessage() == null ? "" : ": " + throwable.getMessage());
}
/**
* Converts an array of {@link StackTraceElement}s into a regular string.
*
* @param stacktrace array of {@link StackTraceElement}s to convert
* @param indent if all lines shall be indented with a single tab.
* Enabling this will cause the output of this method
* to mimic the JVM's throwable handling output.
* @return specified stack trace as a String
* @since v1-alpha9
*/
public static @NotNull String stacktraceAsString(@NotNull StackTraceElement @NotNull [] stacktrace, boolean indent) {
StringBuilder output = new StringBuilder();
for (StackTraceElement element : stacktrace) {
if (!output.isEmpty())
output.append("\n");
if (indent)
output.append("\t");
output.append("at ").append(element);
}
return output.toString();
}
/**
* Converts an array of {@link StackTraceElement}s into a regular string.
*
* @param throwable throwable to derive the stacktrace from
* @param indent if all lines shall be indented with a single tab.
* Enabling this will cause the output of this method
* to mimic the JVM's throwable handling output.
* @return specified stack trace as a String
* @since v1-alpha9
*/
public static @NotNull String stacktraceAsString(@NotNull Throwable throwable, boolean indent) {
return stacktraceAsString(throwable.getStackTrace(), indent);
}
/**
* Returns the full stack trace of a {@link Throwable}.
* <p>
* This method recursively resolves, converts and then
* returns every {@link Throwable} and stacktrace found.
*
* @param throwable throwable to recursively convert
* @param indent if all lines shall be indented with a single tab.
* Enabling this will cause the output of this method
* to mimic the JVM's throwable handling output.
* @param includeHeader if to include the throwable header (see {@link #throwableHeader(Throwable)})
* @return full stack trace
* @since v1-alpha9
*/
public static @NotNull String stacktraceAsStringRecursive(@NotNull Throwable throwable, boolean indent, boolean includeHeader) {
StringBuilder output = new StringBuilder();
// Append header and stacktrace
if (includeHeader)
output
.append(throwableHeader(throwable))
.append("\n");
output.append(stacktraceAsString(throwable, indent));
// Process recursively
if (throwable.getCause() != null)
output
.append("\n")
.append(stacktraceAsStringRecursive(throwable.getCause(), indent, includeHeader));
if (throwable instanceof ClassNotFoundException exception)
output
.append("\n")
.append(stacktraceAsStringRecursive(exception.getException(), indent, includeHeader));
if (throwable instanceof ExceptionInInitializerError exception)
output
.append("\n")
.append(stacktraceAsStringRecursive(exception.getException(), indent, includeHeader));
if (throwable instanceof InvocationTargetException exception)
output
.append("\n")
.append(stacktraceAsStringRecursive(exception.getTargetException(), indent, includeHeader));
return output.toString();
}
}

View file

@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.base.utility; package de.staropensource.engine.base.utility.misc;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -27,31 +27,36 @@ import java.util.LinkedList;
/** /**
* Utility class for math operations. * Utility class for math operations.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
// All mean and double methods have been sourced // All mean and double methods have been sourced
// from https://stackoverflow.com/a/4191729, tysm! // from https://stackoverflow.com/a/4191729, tysm!
@SuppressWarnings({ "unused" }) @SuppressWarnings({ "unused" })
public final class Math { public final class NumberUtil {
/** /**
* Creates and initializes an instance of this class * Creates and initializes an instance of this class
* *
* @since v1-alpha6 * @since v1-alpha9
*/ */
private Math() {} private NumberUtil() {}
/** /**
* Adds padding zeros to a number. * Adds padding zeros to a number.
* <p>
* Example:
* {@code padNumbers(505L, 5) = "00505"}
* *
* @param number number * @param number number
* @param length length * @param length length
* @return the padded number * @return the padded number
* @since v1-alpha2 * @since v1-alpha9
*/ */
public static @NotNull String padNumbers(long number, int length) { public static @NotNull String padNumbers(long number, int length) {
return String.format("%0" + length + "d", number); return String.format("%0" + length + "d", number);
} }
// -----> Number limiting
/** /**
* Ensures the integer is inside the * Ensures the integer is inside the
* specified bounds. If not, the * specified bounds. If not, the
@ -61,10 +66,10 @@ public final class Math {
* @param max maximum value * @param max maximum value
* @param value value * @param value value
* @return number in threshold * @return number in threshold
* @throws IndexOutOfBoundsException when the minimum value is bigger than the maximum value * @throws IndexOutOfBoundsException if the minimum value is bigger than the maximum value
* @since v1-alpha6 * @since v1-alpha9
*/ */
public static int boundNumber(int min, int max, int value) throws IndexOutOfBoundsException { public static int limitNumber(int min, int max, int value) throws IndexOutOfBoundsException {
if (min > max) if (min > max)
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
@ -85,10 +90,10 @@ public final class Math {
* @param max maximum value * @param max maximum value
* @param value value * @param value value
* @return number in threshold * @return number in threshold
* @throws IndexOutOfBoundsException when the minimum value is bigger than the maximum value * @throws IndexOutOfBoundsException if the minimum value is bigger than the maximum value
* @since v1-alpha6 * @since v1-alpha9
*/ */
public static float boundNumber(float min, float max, float value) throws IndexOutOfBoundsException { public static float limitNumber(float min, float max, float value) throws IndexOutOfBoundsException {
if (min > max) if (min > max)
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
@ -109,10 +114,10 @@ public final class Math {
* @param max maximum value * @param max maximum value
* @param value value * @param value value
* @return number in threshold * @return number in threshold
* @throws IndexOutOfBoundsException when the minimum value is bigger than the maximum value * @throws IndexOutOfBoundsException if the minimum value is bigger than the maximum value
* @since v1-alpha6 * @since v1-alpha9
*/ */
public static double boundNumber(double min, double max, double value) throws IndexOutOfBoundsException { public static double limitNumber(double min, double max, double value) throws IndexOutOfBoundsException {
if (min > max) if (min > max)
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
@ -124,14 +129,16 @@ public final class Math {
return value; return value;
} }
// -----> Means and medians
/** /**
* Returns the mean of a collection of numbers. * Returns the mean of a collection of numbers.
* *
* @param collection collection of {@code double}s * @param collection collection of {@code double}s
* @return mean * @return mean
* @since v1-alpha2 * @since v1-alpha9
*/ */
public static double getMeanDouble(@NotNull Collection<@NotNull Double> collection) { public static double calculateMeanDouble(@NotNull Collection<@NotNull Double> collection) {
double sum = 0; double sum = 0;
for (double number : collection) for (double number : collection)
@ -145,9 +152,9 @@ public final class Math {
* *
* @param collection collection of {@code float}s * @param collection collection of {@code float}s
* @return mean * @return mean
* @since v1-alpha2 * @since v1-alpha9
*/ */
public static double getMeanFloat(@NotNull Collection<@NotNull Float> collection) { public static double calculateMeanFloat(@NotNull Collection<@NotNull Float> collection) {
double sum = 0; double sum = 0;
for (float number : collection) for (float number : collection)
@ -161,9 +168,9 @@ public final class Math {
* *
* @param collection collection of {@code long}s * @param collection collection of {@code long}s
* @return mean * @return mean
* @since v1-alpha2 * @since v1-alpha9
*/ */
public static double getMeanLong(@NotNull Collection<@NotNull Long> collection) { public static double calculateMeanLong(@NotNull Collection<@NotNull Long> collection) {
double sum = 0; double sum = 0;
for (long number : collection) for (long number : collection)
@ -177,9 +184,9 @@ public final class Math {
* *
* @param collection collection of {@code int}s * @param collection collection of {@code int}s
* @return mean * @return mean
* @since v1-alpha2 * @since v1-alpha9
*/ */
public static double getMeanInt(@NotNull Collection<@NotNull Integer> collection) { public static double calculateMeanInt(@NotNull Collection<@NotNull Integer> collection) {
double sum = 0; double sum = 0;
for (int number : collection) for (int number : collection)
@ -193,9 +200,9 @@ public final class Math {
* *
* @param list linked list of {@code double}s * @param list linked list of {@code double}s
* @return median * @return median
* @since v1-alpha2 * @since v1-alpha9
*/ */
public static double getMedianDouble(@NotNull LinkedList<@NotNull Double> list) { public static double calculateMedianDouble(@NotNull LinkedList<@NotNull Double> list) {
int middle = list.size() / 2; int middle = list.size() / 2;
if (list.size() % 2 == 1) if (list.size() % 2 == 1)
return list.get(middle); return list.get(middle);
@ -208,9 +215,9 @@ public final class Math {
* *
* @param list linked list of {@code float}s * @param list linked list of {@code float}s
* @return median * @return median
* @since v1-alpha2 * @since v1-alpha9
*/ */
public static double getMedianFloat(@NotNull LinkedList<@NotNull Float> list) { public static double calculateMedianFloat(@NotNull LinkedList<@NotNull Float> list) {
int middle = list.size() / 2; int middle = list.size() / 2;
if (list.size() % 2 == 1) if (list.size() % 2 == 1)
return list.get(middle); return list.get(middle);
@ -223,9 +230,9 @@ public final class Math {
* *
* @param list linked list of {@code long}s * @param list linked list of {@code long}s
* @return median * @return median
* @since v1-alpha2 * @since v1-alpha9
*/ */
public static double getMedianLong(@NotNull LinkedList<@NotNull Long> list) { public static double calculateMedianLong(@NotNull LinkedList<@NotNull Long> list) {
int middle = list.size() / 2; int middle = list.size() / 2;
if (list.size() % 2 == 1) if (list.size() % 2 == 1)
return list.get(middle); return list.get(middle);
@ -238,9 +245,9 @@ public final class Math {
* *
* @param list linked list of {@code int}s * @param list linked list of {@code int}s
* @return median * @return median
* @since v1-alpha2 * @since v1-alpha9
*/ */
public static double getMedianInt(@NotNull LinkedList<@NotNull Integer> list) { public static double calculateMedianInt(@NotNull LinkedList<@NotNull Integer> list) {
int middle = list.size() / 2; int middle = list.size() / 2;
if (list.size() % 2 == 1) if (list.size() % 2 == 1)
return list.get(middle); return list.get(middle);

View file

@ -0,0 +1,85 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.base.utility.misc;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Manipulates strings and characters.
*
* @since v1-alpha9
*/
public final class StringUtil {
/**
* Counts the number of occurrences of the specified substring inside the specified string.
*
* @param string string to search in
* @param substring substring to count occurrences for
* @return number of times the specified substring was found inside the specified string
* @since v1-alpha9
*/
public static long count(@NotNull String string, @NotNull String substring) {
return (string.length() - string.replace(substring, "").length()) / substring.length();
}
/**
* Searches for the specified separators
* in the specified string and returns
* the first separator which matches the
* specified amount of required occurrences.
*
* @param string string to operate on
* @param separators separators to check for
* @param requiredOccurrences exact amount of occurrences for a separator to be deemed valid
* @return separator to use or {@code null}
* @since v1-alpha9
*/
public static @Nullable String getSeparatorRequired(@NotNull String string, @NotNull String @NotNull [] separators, int requiredOccurrences) {
if (string.isBlank() || separators.length == 0 || requiredOccurrences == 0)
return null;
for (String separator : separators)
if (count(string, separator) == requiredOccurrences)
return separator;
return null;
}
/**
* Searches for the specified separators
* in the specified string and returns
* the first separator which matches the
* specified amount of minimum occurrences.
*
* @param string string to operate on
* @param separators separators to check for
* @param minimumOccurrences minimum amount of occurrences for a separator to be deemed valid
* @return separator to use or {@code null}
* @since v1-alpha9
*/
public static @Nullable String getSeparatorMinimum(@NotNull String string, @NotNull String @NotNull [] separators, int minimumOccurrences) {
for (String separator : separators)
if (count(string, separator) >= minimumOccurrences)
return separator;
return null;
}
}

View file

@ -17,39 +17,37 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.base.type; package de.staropensource.engine.base.utility.misc;
import de.staropensource.engine.base.type.Tristate;
import org.jetbrains.annotations.Range;
/** /**
* Represents various file types. * Converts various data types into other data types.
* *
* @since v1-alpha8 * @since v1-alpha9
*/ */
public enum FileType { public final class TypeConversion {
/** /**
* The path does not exist. * Converts a boolean into an integer.
* *
* @since v1-alpha8 * @param bool boolean to convert
* @return converted integer
* @since v1-alpha9
*/ */
VOID, @Range(from = 0, to = 1)
public static int booleanToInteger(boolean bool) {
/** return bool ? 1 : 0;
* It's a regular file. }
*
* @since v1-alpha8 /**
*/ * Converts an integer into a {@link Tristate} and then into a boolean.
FILE, *
* @param integer integer to convert
/** * @return booleanized integer
* It's a directory containing files. * @since v1-alpha9
* */
* @since v1-alpha8 public static boolean integerToBoolean(@Range(from = 0, to = 1) int integer) throws IndexOutOfBoundsException {
*/ return integer != 0;
DIRECTORY, }
/**
* The file type is unknown to the sos!engine.
*
* @since v1-alpha8
*/
UNKNOWN
} }

View file

@ -18,8 +18,8 @@
*/ */
/** /**
* Code of the GLFW subsystem. * Miscellaneous utility classes.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
package de.staropensource.engine.windowing.glfw; package de.staropensource.engine.base.utility.misc;

View file

@ -20,7 +20,7 @@
/** /**
* Provides (utility) classes specifically made for one task. * Provides (utility) classes specifically made for one task.
* *
* @see de.staropensource.engine.base.utility.Miscellaneous * @see de.staropensource.engine.base.utility.misc.Miscellaneous
* @since v1-alpha0 * @since v1-alpha0
*/ */
package de.staropensource.engine.base.utility; package de.staropensource.engine.base.utility;

View file

@ -29,11 +29,11 @@ module sosengine.base {
exports de.staropensource.engine.base.implementation.logging; exports de.staropensource.engine.base.implementation.logging;
exports de.staropensource.engine.base.reflection; exports de.staropensource.engine.base.reflection;
exports de.staropensource.engine.base.type; exports de.staropensource.engine.base.type;
exports de.staropensource.engine.base.type.immutable;
exports de.staropensource.engine.base.type.logging; exports de.staropensource.engine.base.type.logging;
exports de.staropensource.engine.base.type.reflection; exports de.staropensource.engine.base.type.reflection;
exports de.staropensource.engine.base.type.vector; exports de.staropensource.engine.base.type.vector;
exports de.staropensource.engine.base.utility; exports de.staropensource.engine.base.utility;
exports de.staropensource.engine.base.utility.misc;
// Reflection access // Reflection access
opens de.staropensource.engine.base; opens de.staropensource.engine.base;
@ -52,9 +52,9 @@ module sosengine.base {
opens de.staropensource.engine.base.implementation.logging; opens de.staropensource.engine.base.implementation.logging;
opens de.staropensource.engine.base.reflection; opens de.staropensource.engine.base.reflection;
opens de.staropensource.engine.base.type; opens de.staropensource.engine.base.type;
opens de.staropensource.engine.base.type.immutable;
opens de.staropensource.engine.base.type.logging; opens de.staropensource.engine.base.type.logging;
opens de.staropensource.engine.base.type.reflection; opens de.staropensource.engine.base.type.reflection;
opens de.staropensource.engine.base.type.vector; opens de.staropensource.engine.base.type.vector;
opens de.staropensource.engine.base.utility; opens de.staropensource.engine.base.utility;
opens de.staropensource.engine.base.utility.misc;
} }

View file

@ -21,11 +21,9 @@ package de.staropensource.engine.base.srctests.utility;
import de.staropensource.engine.base.EngineConfiguration; import de.staropensource.engine.base.EngineConfiguration;
import de.staropensource.engine.base.annotation.EventListener; import de.staropensource.engine.base.annotation.EventListener;
import de.staropensource.engine.base.event.ThrowableCatchEvent;
import de.staropensource.engine.base.logging.Logger;
import de.staropensource.engine.testing.TestBase; import de.staropensource.engine.testing.TestBase;
import de.staropensource.engine.base.utility.Math; import de.staropensource.engine.base.utility.misc.NumberUtil;
import de.staropensource.engine.base.utility.Miscellaneous; import de.staropensource.engine.base.utility.misc.Miscellaneous;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -66,7 +64,7 @@ public class MiscellaneousTest extends TestBase {
if (performMethodCalls("testPadNumbers", number, length, expected)) if (performMethodCalls("testPadNumbers", number, length, expected))
return; return;
String result = Math.padNumbers(number, length); String result = NumberUtil.padNumbers(number, length);
assertEquals(expected, result, "Result \"" + result + "\" does not match expected output \"" + expected + "\""); assertEquals(expected, result, "Result \"" + result + "\" does not match expected output \"" + expected + "\"");
} }
@ -98,7 +96,7 @@ public class MiscellaneousTest extends TestBase {
*/ */
@Test @Test
@DisplayName("getMapValues") @DisplayName("getMapValues")
void testGetMapValues() { void testSearchForValueInMap() {
if (performMethodCalls("testGetMapValues")) if (performMethodCalls("testGetMapValues"))
return; return;
@ -109,28 +107,13 @@ public class MiscellaneousTest extends TestBase {
testMap.put("keylast", "this is the last value"); testMap.put("keylast", "this is the last value");
testMap.put("keylast2", "this is the last value"); testMap.put("keylast2", "this is the last value");
Set<?> output = Miscellaneous.getMapValues(testMap, "this value exists twice"); Set<?> output = Miscellaneous.searchForValueInMap(testMap, "this value exists twice");
assertTrue(output.contains("keytwo"), "Map key \"keytwo\" not found in output Set"); assertTrue(output.contains("keytwo"), "Map key \"keytwo\" not found in output Set");
assertTrue(output.contains("keydrei"), "Map key \"keydrei\" not found in output Set"); assertTrue(output.contains("keydrei"), "Map key \"keydrei\" not found in output Set");
assertEquals(2, output.size(), "There are more or less than two keys in the output Set"); assertEquals(2, output.size(), "There are more or less than two keys in the output Set");
} }
/**
* Tests the method {@code executeSafely}.
*/
@Test
@DisplayName("executeSafely (test 0)")
void testExecuteSafely0() {
if (performMethodCalls("testExecuteSafely0"))
return;
throwableCaught = false;
Miscellaneous.executeSafely(() -> Logger.info("You can safely ignore this message (this comes from MiscellaneousTest#testExecuteSafely0)"), "MiscellaneousTest#testExecuteSafely0");
assertFalse(throwableCaught, "Event was triggered");
}
/** /**
* Tests the method {@code executeSafely}. * Tests the method {@code executeSafely}.
*/ */

View file

@ -30,8 +30,7 @@ tasks.register("javadocAll", Javadoc) {
":base", ":base",
":ansi", ":ansi",
":slf4j-compat", ":slf4j-compat",
":windowing", ":rendering",
":windowing:glfw",
":notification", ":notification",
] ]

View file

@ -1 +1 @@
icon0.png icon1-transparent.png

View file

@ -1 +1 @@
icon0.xcf icon1.xcf

Binary file not shown.

BIN
dist/branding/icon1-text-black.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 KiB

BIN
dist/branding/icon1-text-brandcolor.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 KiB

BIN
dist/branding/icon1-text-white.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 KiB

BIN
dist/branding/icon1-text.xcf vendored Normal file

Binary file not shown.

BIN
dist/branding/icon1-transparent.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

BIN
dist/branding/icon1.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

View file

@ -78,7 +78,7 @@ This avoids unnecessary bloat, having too many dependencies in your project whil
size and memory footprint of your project. size and memory footprint of your project.
## Official subsystems ## Official subsystems
Besides the `base` engine, there are two stable subsystem and three experimental subsystems. Besides the `base` engine, there are two stable subsystem and two experimental subsystems.
There may be other subsystems out there. Please note though that they are not maintained There may be other subsystems out there. Please note though that they are not maintained
by the StarOpenSource Project directly and are not automatically updated with the engine. by the StarOpenSource Project directly and are not automatically updated with the engine.
@ -86,8 +86,7 @@ by the StarOpenSource Project directly and are not automatically updated with th
- [`ansi`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/ansi): Provides an ANSI logger and a ShortcodeParserSkeleton implementation for all your terminal formatting needs - [`ansi`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/ansi): Provides an ANSI logger and a ShortcodeParserSkeleton implementation for all your terminal formatting needs
- [`slf4j-compat`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/slf4j-compat): Provides a [SLF4J](https://slf4j.org/) compatibility logger for redirecting all log calls to the engine's logging system - [`slf4j-compat`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/slf4j-compat): Provides a [SLF4J](https://slf4j.org/) compatibility logger for redirecting all log calls to the engine's logging system
### Experimental ### Experimental
- [`windowing`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/windowing): Provides abstract APIs for creating and managing windows as well as monitors - [`rendering`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/rendering): Provides an API for creating, managing and rendering windows
- [`windowing-glfw`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/windowing/glfw): Windowing API; allows using [GLFW](https://glfw.org) for creating windows
- [`notification`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/notification): Provides an API for sending and receiving notifications inside a program - [`notification`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/notification): Provides an API for sending and receiving notifications inside a program
## API documentation ## API documentation

View file

@ -15,11 +15,11 @@
"typecheck": "tsc" "typecheck": "tsc"
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "3.6.0", "@docusaurus/core": "3.6.1",
"@docusaurus/plugin-client-redirects": "^3.6.0", "@docusaurus/plugin-client-redirects": "^3.6.1",
"@docusaurus/plugin-content-docs": "^3.6.0", "@docusaurus/plugin-content-docs": "^3.6.1",
"@docusaurus/plugin-sitemap": "^3.6.0", "@docusaurus/plugin-sitemap": "^3.6.1",
"@docusaurus/preset-classic": "3.6.0", "@docusaurus/preset-classic": "3.6.1",
"@mdx-js/react": "^3.0.1", "@mdx-js/react": "^3.0.1",
"clsx": "^2.1.0", "clsx": "^2.1.0",
"prism-react-renderer": "^2.3.1", "prism-react-renderer": "^2.3.1",
@ -27,9 +27,9 @@
"react-dom": "^18.2.0" "react-dom": "^18.2.0"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/module-type-aliases": "3.6.0", "@docusaurus/module-type-aliases": "3.6.1",
"@docusaurus/tsconfig": "3.6.0", "@docusaurus/tsconfig": "3.6.1",
"@docusaurus/types": "3.6.0", "@docusaurus/types": "3.6.1",
"@types/node": "^20.12.5", "@types/node": "^20.12.5",
"typescript": "~5.4.4" "typescript": "~5.4.4"
}, },

View file

@ -21,7 +21,7 @@
versioningCodename=Sugarcookie versioningCodename=Sugarcookie
versioningVersion=1 versioningVersion=1
versioningType=alpha versioningType=alpha
versioningTyperelease=8 versioningTyperelease=9
versioningFork= versioningFork=
# Java # Java

View file

@ -19,12 +19,12 @@
package de.staropensource.engine.notification; package de.staropensource.engine.notification;
import de.staropensource.engine.base.type.immutable.ImmutableHashMap;
import de.staropensource.engine.notification.type.Notification; import de.staropensource.engine.notification.type.Notification;
import de.staropensource.engine.notification.type.NotificationState; import de.staropensource.engine.notification.type.NotificationState;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -49,14 +49,14 @@ public final class NotificationManager {
private NotificationManager() {} private NotificationManager() {}
/** /**
* Returns an {@link ImmutableHashMap} containing all * Returns an immutable map containing all
* registered notifications and their current states. * registered notifications and their current states.
* *
* @return map of registered notifications * @return map of registered notifications
* @since v1-alpha6 * @since v1-alpha6
*/ */
public static @NotNull Map<@NotNull Notification, @NotNull NotificationState> getNotifications() { public static @NotNull Map<@NotNull Notification, @NotNull NotificationState> getNotifications() {
return new ImmutableHashMap<>(notifications); return Collections.unmodifiableMap(notifications);
} }
/** /**

View file

@ -61,16 +61,17 @@ dependencies {
// LWJGL // LWJGL
implementation(platform("org.lwjgl:lwjgl-bom:${dependencyLwjgl}")) implementation(platform("org.lwjgl:lwjgl-bom:${dependencyLwjgl}"))
implementation("org.lwjgl:lwjgl") implementation("org.lwjgl:lwjgl")
implementation("org.lwjgl:lwjgl-glfw")
implementation("org.lwjgl:lwjgl-stb") implementation("org.lwjgl:lwjgl-stb")
implementation("org.lwjgl:lwjgl-glfw")
implementation("org.lwjgl:lwjgl-bgfx")
runtimeOnly("org.lwjgl:lwjgl::${dependencyLwjglNatives}") runtimeOnly("org.lwjgl:lwjgl::${dependencyLwjglNatives}")
runtimeOnly("org.lwjgl:lwjgl-glfw::${dependencyLwjglNatives}")
runtimeOnly("org.lwjgl:lwjgl-stb::${dependencyLwjglNatives}") runtimeOnly("org.lwjgl:lwjgl-stb::${dependencyLwjglNatives}")
runtimeOnly("org.lwjgl:lwjgl-glfw::${dependencyLwjglNatives}")
runtimeOnly("org.lwjgl:lwjgl-bgfx::${dependencyLwjglNatives}")
if (project.dependencyLwjglNatives == "natives-macos" || project.dependencyLwjglNatives == "natives-macos-arm64") runtimeOnly("org.lwjgl:lwjgl-vulkan::${dependencyLwjglNatives}") if (project.dependencyLwjglNatives == "natives-macos" || project.dependencyLwjglNatives == "natives-macos-arm64") runtimeOnly("org.lwjgl:lwjgl-vulkan::${dependencyLwjglNatives}")
// Project // Project
implementation(project(":base")) implementation(project(":base"))
implementation(project(":windowing"))
} }
// Javadoc configuration // Javadoc configuration
@ -96,26 +97,6 @@ javadoc {
} }
} }
// Unit testing configuration
test {
useJUnitPlatform()
// Pass test configuration to test VMs
Map<String, String> testConfiguration = new HashMap<>()
for (String property : project.properties.keySet())
if (property.startsWith("test."))
testConfiguration.put(property, project.properties.get(property).toString())
systemProperties(testConfiguration)
setMaxParallelForks(project.hasProperty("jobs") ? Integer.parseInt((String) project.property("jobs")) : 8)
setForkEvery(1)
setFailFast(true)
testLogging {
events("passed", "skipped", "failed")
}
}
// Include javadoc and source jar during publishing // Include javadoc and source jar during publishing
java { java {
withJavadocJar() withJavadocJar()

View file

@ -0,0 +1,240 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.rendering;
import de.staropensource.engine.base.annotation.EngineSubsystem;
import de.staropensource.engine.base.annotation.EventListener;
import de.staropensource.engine.base.implementable.Event;
import de.staropensource.engine.base.implementable.SubsystemClass;
import de.staropensource.engine.base.implementable.helper.EventHelper;
import de.staropensource.engine.base.logging.Logger;
import de.staropensource.engine.base.utility.misc.NumberUtil;
import de.staropensource.engine.base.utility.information.EngineInformation;
import de.staropensource.engine.base.implementation.versioning.StarOpenSourceVersioningSystem;
import de.staropensource.engine.base.event.InternalEngineShutdownEvent;
import de.staropensource.engine.base.type.DependencyVector;
import de.staropensource.engine.base.utility.misc.Miscellaneous;
import de.staropensource.engine.rendering.event.InputEvent;
import de.staropensource.engine.rendering.event.RenderingErrorEvent;
import de.staropensource.engine.rendering.exception.NotOnMainThreadException;
import de.staropensource.engine.rendering.renderer.Renderer;
import de.staropensource.engine.rendering.type.Window;
import de.staropensource.engine.rendering.type.window.RenderingPlatform;
import de.staropensource.engine.rendering.type.window.VsyncMode;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicReference;
import static org.lwjgl.glfw.GLFW.*;
/**
* Main class of the {@code rendering} subsystem.
*
* @since v1-alpha9
*/
@EngineSubsystem
@SuppressWarnings({ "JavadocDeclaration" })
public final class RenderingSubsystem extends SubsystemClass {
/**
* Contains the class instance.
*
* @since v1-alpha9
* -- GETTER --
* Returns the class instance.
*
* @return class instance unless the subsystem is uninitialized
* @since v1-alpha9
*/
@Getter
private static RenderingSubsystem instance = null;
/**
* The {@link GLFWErrorCallback} to use.
* <p>
* Only declared publicly for freeing during engine shutdown.
*
* @since v1-alpha2
*/
private GLFWErrorCallback errorCallback = null;
// -----> Subsystem
/**
* Initializes this subsystem.
*
* @since v1-alpha9
*/
public RenderingSubsystem() {
// Only allow one instance
if (instance == null)
instance = this;
else
Logger.crash("Only one instance of this class is allowed, use getInstance() instead of creating a new instance");
}
/** {@inheritDoc} */
@Override
public @NotNull String getName() {
return "rendering";
}
/** {@inheritDoc} */
@Override
public @NotNull DependencyVector getDependencyVector() {
return new DependencyVector.Builder()
.setIdentifier(getName())
.setVersioningSystem(StarOpenSourceVersioningSystem.class)
.setVersion(EngineInformation.getVersioningString())
.build();
}
/** {@inheritDoc} */
@Override
public void initializeSubsystem() {
if (!Miscellaneous.onMainThread())
Logger.crash("Unable to initialize the rendering subsystem whilst running on a non-main thread", new NotOnMainThreadException());
// Initialize WindowingSubsystemConfiguration and load it
new RenderingSubsystemConfiguration().loadConfiguration();
// Precompute event listeners
cacheEvents();
// Initialize GLFW
initGlfw();
// Initialize renderer
Renderer.initialize();
// Warn about subsystem and API instability
Logger.warn("The rendering subsystem is experimental. Subsystem and API stability are not guaranteed.");
}
/**
* Caches all windowing subsystem events.
*
* @since v1-alpha9
*/
private void cacheEvents() {
EventHelper.cacheEvent(RenderingErrorEvent.class);
EventHelper.cacheEvent(InputEvent.class);
}
/**
* Initializes GLFW.
*
* @since v1-alpha9
*/
private void initGlfw() {
try {
Logger.verb("Initializing GLFW");
// Set error callback
Logger.diag("Setting error callback");
errorCallback = GLFWErrorCallback.create((error, description) -> new RenderingErrorEvent().callEvent("GLFW: " + GLFWErrorCallback.getDescription(description) + " [" + error + "]")).set();
// Set init hints
Logger.diag("Setting initialization hints");
switch (RenderingSubsystemConfiguration.getInstance().getInitialPlatform()) {
case ANY -> glfwInitHint(GLFW_PLATFORM, GLFW_ANY_PLATFORM);
case WAYLAND -> tryPlatform(GLFW_PLATFORM_WAYLAND, RenderingPlatform.WAYLAND);
case X11 -> tryPlatform(GLFW_PLATFORM_X11, RenderingPlatform.X11);
case WIN32 -> tryPlatform(GLFW_PLATFORM_WIN32, RenderingPlatform.WIN32);
case COCOA -> tryPlatform(GLFW_PLATFORM_COCOA, RenderingPlatform.COCOA);
case NONE -> glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_NULL);
}
glfwInitHint(GLFW_WAYLAND_LIBDECOR, RenderingSubsystemConfiguration.getInstance().isInitialDisableLibdecor() ? GLFW_WAYLAND_DISABLE_LIBDECOR : GLFW_WAYLAND_PREFER_LIBDECOR);
// Initialize GLFW
Logger.diag("Invoking glfwInit");
if (!glfwInit())
Logger.crash("Failed to initialize GLFW");
} catch (UnsatisfiedLinkError error) {
Logger.crash("Failed to load LWJGL native libraries", error);
}
}
/**
* Shuts the subsystem down.
*
* @since v1-alpha9
*/
@EventListener(event = InternalEngineShutdownEvent.class)
@SuppressWarnings({ "unused" })
protected static void shutdownSubsystem() {
if (instance == null)
return;
Logger.verb("Shutting down");
long shutdownTime = Miscellaneous.measureExecutionTime(() -> {
// Close all windows
for (Window window : new ArrayList<>(Window.getWindows()))
window.close();
instance.errorCallback.free();
glfwTerminate();
});
Logger.info("Shut down in " + shutdownTime + "ms");
}
/**
* Logs about rendering errors.
*
* @see RenderingSubsystemConfiguration#errorRenderingFailures
* @since v1-alpha9
*/
@EventListener(event = RenderingErrorEvent.class, priority = Event.Priority.EXCLUSIVELY_IMPORTANT)
private static void logRenderingError(@NotNull String error) {
Logger.error("Rendering error occurred: " + error);
}
// -----> Utility methods
/**
* Checks if the specified platform is compatible,
* and if so, specifies it as the platform to use.
*
* @param platform platform to try
* @param renderingPlatform {@link RenderingPlatform} used to log that the platform is unsupported (set to {@code null} to disable)
* @since v1-alpha9
*/
private void tryPlatform(int platform, @Nullable RenderingPlatform renderingPlatform) {
if (glfwPlatformSupported(platform))
if (platform != GLFW_PLATFORM_WAYLAND)
glfwInitHint(GLFW_PLATFORM, platform);
else {
Logger.warn("Wayland is not supported by the StarOpenSource Engine due to various issues with it, sorry.");
tryPlatform(GLFW_PLATFORM_X11, RenderingPlatform.X11);
}
else {
if (renderingPlatform != null)
Logger.warn("Platform RenderingPlatform." + renderingPlatform.name() + " is not supported GLFW. Using RenderingPlatform.ANY instead");
glfwInitHint(GLFW_PLATFORM, GLFW_ANY_PLATFORM);
}
}
}

View file

@ -0,0 +1,365 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.rendering;
import de.staropensource.engine.base.implementable.Configuration;
import de.staropensource.engine.base.logging.Logger;
import de.staropensource.engine.base.utility.PropertiesReader;
import de.staropensource.engine.rendering.event.RenderingErrorEvent;
import de.staropensource.engine.rendering.type.window.RenderingAdapter;
import de.staropensource.engine.rendering.type.window.RenderingPlatform;
import de.staropensource.engine.rendering.type.window.VsyncMode;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Provides the configuration for the rendering subsystem.
*
* @since v1-alpha9
*/
@Getter
@SuppressWarnings({ "JavadocDeclaration" })
public final class RenderingSubsystemConfiguration extends Configuration {
/**
* Contains the class instance.
*
* @since v1-alpha9
* -- GETTER --
* Returns the class instance.
*
* @return class instance unless {@link RenderingSubsystem} is uninitialized
* @since v1-alpha9
*/
@Getter
private static RenderingSubsystemConfiguration instance;
/**
* Contains the configuration prefix.
*
* @since v1-alpha9
* -- GETTER --
* Returns the configuration prefix.
*
* @return property group
* @since v1-alpha9
*/
@Getter
public final @NotNull String group = "sosengine.rendering.";
/**
* Contains if debugging options should be allowed.
* All debugging options will be forcefully set to
* {@code false} if this option is set to {@code false}.
*
* @since v1-alpha9
* -- GETTER --
* Returns if debugging options should be allowed.
* All debugging options will be forcefully set to
* {@code false} if this option is set to {@code false}.
*
* @return debugging enabled?
* @since v1-alpha9
*/
private boolean debug;
/**
* Contains whether or not key presses
* and releases should be logged.
*
* @since v1-alpha9
* -- GETTER --
* Returns whether or not key presses
* and releases should be logged.
*
* @return log key presses and releases?
* @since v1-alpha9
*/
private boolean debugInput;
/**
* Contains whether or not the delta time and
* FPS count should be logged to the console
* every second.
*
* @since v1-alpha9
* -- GETTER --
* Returns whether or not the delta time and
* FPS count should be logged to the console
* every second.
*
* @return print delta time and FPS count?
* @since v1-alpha9
*/
private boolean debugFrames;
/**
* Contains if to log the state of all
* windows every second.
*
* @since v1-alpha9
* -- GETTER --
* Returns if to log the state of all
* windows every second.
*
* @return log states of all windows?
* @since v1-alpha9
*/
private boolean debugWindowStates;
/**
* Contains if to allow updates to a window's
* position. May cause errors and crashes to
* appear, we do not know why.
*
* @since v1-alpha9
* -- GETTER --
* Returns if to allow updates to a window's
* position. May cause errors and crashes to
* appear, we do not know why.
*
* @return allow window position updates?
* @since v1-alpha9
*/
private boolean debugAllowPositionUpdates;
/**
* Contains the platform GLFW shall try initialising.
*
* @since v1-alpha9
* -- GETTER --
* Returns the platform GLFW shall try initialising.
*
* @return GLFW platform
* @since v1-alpha9
*/
private RenderingPlatform initialPlatform;
/**
* Contains whether or not to disable support for
* <a href="https://gitlab.freedesktop.org/libdecor/libdecor">libdecor</a>.
* <p>
* Only affects the {@link RenderingPlatform#WAYLAND} platform.
*
* @since v1-alpha9
* -- GETTER --
* Returns whether or not to disable support for
* <a href="https://gitlab.freedesktop.org/libdecor/libdecor">libdecor</a>.
* <p>
* Only affects the {@link RenderingPlatform#WAYLAND} platform.
*
* @return libdecor support disabled?
* @since v1-alpha9
*/
private boolean initialDisableLibdecor;
/**
* Contains whether or not rendering
* errors should be logged.
* <p>
* The {@link RenderingErrorEvent} will
* be emitted anyway, regardless of the
* value of this variable.
*
* @see RenderingErrorEvent
* @since v1-alpha9
* -- GETTER --
* Returns whether or not rendering
* errors should be logged.
* <p>
* The {@link RenderingErrorEvent} will
* be emitted anyway, regardless of the
* value of this variable.
*
* @return log rendering failures?
* @see RenderingErrorEvent
* @since v1-alpha9
*/
private boolean errorRenderingFailures;
/**
* Contains the adapter bgfx shall use.
*
* @since v1-alpha9
* -- GETTER --
* Returns the adapter bgfx shall use.
*
* @return bgfx adapter
* @since v1-alpha9
*/
private RenderingAdapter renderingAdapter;
/**
* Contains which {@link VsyncMode} to use.
* <p>
* This setting determines if and how V-Sync
* will operate, which (if enabled) tries to
* synchronize the frame rate to the monitor's
* refresh rate. See {@link VsyncMode}
* for more information.
*
* @see VsyncMode
* @since v1-alpha9
* -- GETTER --
* Returns which {@link VsyncMode} to use.
* <p>
* This setting determines if and how V-Sync
* will operate, which (if enabled) tries to
* synchronize the frame rate to the monitor's
* refresh rate. See {@link VsyncMode}
* for more information.
*
* @return active V-Sync mode
* @see VsyncMode
* @since v1-alpha9
*/
private VsyncMode vsyncMode;
/**
* Contains the maximum value of frames
* which can be rendered per second.
* <p>
* This value will have no effect on
* windows with V-Sync enabled.
* Set to {@code 0} for effectively
* no limit. Not recommended.
*
* @since v1-alpha9
* -- GETTER --
* Returns the maximum value of frames
* which can be rendered per second.
* <p>
* This value will have no effect on
* windows with V-Sync enabled.
* Set to {@code 0} for effectively
* no limit. Not recommended.
*
* @return maximum amount of frames per second
* @since v1-alpha9
*/
private int maximumFramesPerSecond;
/**
* Creates and initializes an instance of this class.
*
* @see RenderingSubsystem
* @since v1-alpha9
*/
RenderingSubsystemConfiguration() {
instance = this;
loadDefaultConfiguration();
}
/** {@inheritDoc} */
@Override
protected void matchProperty(@NotNull PropertiesReader parser, @NotNull String property) {
switch (property) {
case "debug" -> debug = parser.getBoolean(group + property);
case "debugInput" -> debugInput = parser.getBoolean(group + property);
case "debugFrames" -> debugFrames = parser.getBoolean(group + property);
case "debugWindowStates" -> debugWindowStates = parser.getBoolean(group + property);
case "debugAllowPositionUpdates" -> debugAllowPositionUpdates = parser.getBoolean(group + property);
case "initialPlatform" -> {
try {
initialPlatform = RenderingPlatform.valueOf(parser.getString(group + property).toUpperCase());
} catch (IllegalArgumentException ignored) {
Logger.error("Rendering platform " + parser.getString(group + property) + " is not valid");
}
}
case "initialDisableLibdecor" -> initialDisableLibdecor = parser.getBoolean(group + property);
case "errorRenderingFailures" -> errorRenderingFailures = parser.getBoolean(group + property);
case "renderingAdapter" -> {
try {
renderingAdapter = RenderingAdapter.valueOf(parser.getString(group + property).toUpperCase());
} catch (IllegalArgumentException exception) {
Logger.error("Rendering adapter " + parser.getString(group + property) + " is not valid");
}
}
case "vsyncMode" -> {
try {
vsyncMode = VsyncMode.valueOf(parser.getString(group + property).toUpperCase());
} catch (IllegalArgumentException exception) {
Logger.error("V-Sync mode " + parser.getString(group + property) + " is not valid");
}
}
case "maximumFramesPerSecond" -> maximumFramesPerSecond = parser.getInteger(group + property, true);
}
}
/** {@inheritDoc} */
@Override
protected void processSettings(@NotNull PropertiesReader parser) {
// Disable all debug options if 'debug' is disabled
if (!debug) {
debugInput = false;
debugFrames = false;
debugWindowStates = false;
debugAllowPositionUpdates = false;
}
}
/** {@inheritDoc} */
@Override
public void loadDefaultConfiguration() {
debug = true;
debugInput = false;
debugFrames = true;
debugWindowStates = true;
debugAllowPositionUpdates = false;
initialPlatform = RenderingPlatform.ANY;
initialDisableLibdecor = false;
errorRenderingFailures = true;
renderingAdapter = RenderingAdapter.ANY;
vsyncMode = VsyncMode.OFF;
maximumFramesPerSecond = 0;
}
/** {@inheritDoc} */
@Override
public @Nullable Object getSetting(@NotNull String setting) {
switch (setting) {
case "debug" -> { return debug; }
case "debugInput" -> { return debugInput; }
case "debugFrames" -> { return debugFrames; }
case "debugWindowStates" -> { return debugWindowStates; }
case "debugAllowPositionUpdates" -> { return debugAllowPositionUpdates; }
case "initialPlatform" -> { return initialPlatform; }
case "disableLibdecor" -> { return initialDisableLibdecor; }
case "errorRenderingFailures" -> { return errorRenderingFailures; }
case "renderingAdapter" -> { return renderingAdapter; }
case "vsyncMode" -> { return vsyncMode; }
case "maximumFramesPerSecond" -> { return maximumFramesPerSecond; }
default -> { return null; }
}
}
}

View file

@ -17,13 +17,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.windowing.glfw.callback; package de.staropensource.engine.rendering.callback;
import de.staropensource.engine.windowing.implementable.Window; import de.staropensource.engine.rendering.type.Window;
import de.staropensource.engine.windowing.event.InputEvent; import de.staropensource.engine.rendering.event.InputEvent;
import de.staropensource.engine.windowing.glfw.implementable.WindowCallback; import de.staropensource.engine.rendering.type.input.Key;
import de.staropensource.engine.windowing.type.input.Key; import de.staropensource.engine.rendering.type.input.KeyState;
import de.staropensource.engine.windowing.type.input.KeyState;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFWKeyCallbackI; import org.lwjgl.glfw.GLFWKeyCallbackI;
@ -32,7 +31,7 @@ import static org.lwjgl.glfw.GLFW.*;
/** /**
* A {@link GLFWKeyCallbackI} implementation, which emits {@link InputEvent}. * A {@link GLFWKeyCallbackI} implementation, which emits {@link InputEvent}.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
public final class KeyCallback extends WindowCallback implements GLFWKeyCallbackI { public final class KeyCallback extends WindowCallback implements GLFWKeyCallbackI {
/** /**
@ -40,7 +39,7 @@ public final class KeyCallback extends WindowCallback implements GLFWKeyCallback
* and making too many allocations, which would potentially decrease * and making too many allocations, which would potentially decrease
* performance. * performance.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
private static final InputEvent event = new InputEvent(); private static final InputEvent event = new InputEvent();
@ -48,7 +47,7 @@ public final class KeyCallback extends WindowCallback implements GLFWKeyCallback
* Creates and initializes an instance of this class. * Creates and initializes an instance of this class.
* *
* @param window {@link Window} class * @param window {@link Window} class
* @since v1-alpha2 * @since v1-alpha9
*/ */
public KeyCallback(@NotNull Window window) { public KeyCallback(@NotNull Window window) {
super(window); super(window);

View file

@ -17,13 +17,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.windowing.glfw.callback; package de.staropensource.engine.rendering.callback;
import de.staropensource.engine.windowing.implementable.Window; import de.staropensource.engine.rendering.type.Window;
import de.staropensource.engine.windowing.event.InputEvent; import de.staropensource.engine.rendering.event.InputEvent;
import de.staropensource.engine.windowing.glfw.implementable.WindowCallback; import de.staropensource.engine.rendering.type.input.Key;
import de.staropensource.engine.windowing.type.input.Key; import de.staropensource.engine.rendering.type.input.KeyState;
import de.staropensource.engine.windowing.type.input.KeyState;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFWMouseButtonCallbackI; import org.lwjgl.glfw.GLFWMouseButtonCallbackI;
@ -32,7 +31,7 @@ import static org.lwjgl.glfw.GLFW.*;
/** /**
* A {@link GLFWMouseButtonCallbackI} implementation, which forward them to {@link InputEvent}. * A {@link GLFWMouseButtonCallbackI} implementation, which forward them to {@link InputEvent}.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
public final class MouseButtonCallback extends WindowCallback implements GLFWMouseButtonCallbackI { public final class MouseButtonCallback extends WindowCallback implements GLFWMouseButtonCallbackI {
/** /**
@ -40,7 +39,7 @@ public final class MouseButtonCallback extends WindowCallback implements GLFWMou
* and making too many allocations, which would potentially decrease * and making too many allocations, which would potentially decrease
* performance. * performance.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
private static final InputEvent event = new InputEvent(); private static final InputEvent event = new InputEvent();
@ -48,7 +47,7 @@ public final class MouseButtonCallback extends WindowCallback implements GLFWMou
* Creates and initializes an instance of this class. * Creates and initializes an instance of this class.
* *
* @param window {@link Window} class * @param window {@link Window} class
* @since v1-alpha2 * @since v1-alpha9
*/ */
public MouseButtonCallback(@NotNull Window window) { public MouseButtonCallback(@NotNull Window window) {
super(window); super(window);
@ -72,7 +71,7 @@ public final class MouseButtonCallback extends WindowCallback implements GLFWMou
case GLFW_MOUSE_BUTTON_RIGHT -> Key.MOUSE_RIGHT; case GLFW_MOUSE_BUTTON_RIGHT -> Key.MOUSE_RIGHT;
case GLFW_MOUSE_BUTTON_4, GLFW_MOUSE_BUTTON_5, case GLFW_MOUSE_BUTTON_4, GLFW_MOUSE_BUTTON_5,
GLFW_MOUSE_BUTTON_6, GLFW_MOUSE_BUTTON_7, GLFW_MOUSE_BUTTON_6, GLFW_MOUSE_BUTTON_7,
GLFW_MOUSE_BUTTON_8 -> Key.UNKNOWN_MOUSE; GLFW_MOUSE_BUTTON_8 -> Key.UNKNOWN_MOUSE_BUTTON;
default -> throw new IllegalStateException("Mouse button " + key + " is invalid"); default -> throw new IllegalStateException("Mouse button " + key + " is invalid");
}, },
// Key state // Key state

View file

@ -17,9 +17,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.windowing.glfw.implementable; package de.staropensource.engine.rendering.callback;
import de.staropensource.engine.windowing.implementable.Window; import de.staropensource.engine.rendering.type.Window;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -27,7 +27,7 @@ import org.jetbrains.annotations.NotNull;
* Abstract class used for easily implementing * Abstract class used for easily implementing
* callbacks which require a {@link Window} instance. * callbacks which require a {@link Window} instance.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
@Getter @Getter
@SuppressWarnings({ "JavadocDeclaration" }) @SuppressWarnings({ "JavadocDeclaration" })
@ -36,13 +36,13 @@ public class WindowCallback {
* Refers to the {@link Window} instance * Refers to the {@link Window} instance
* this callback is tied to. * this callback is tied to.
* *
* @since v1-alpha2 * @since v1-alpha9
* -- GETTER -- * -- GETTER --
* Returns the {@link Window} instance * Returns the {@link Window} instance
* this callback is tied to. * this callback is tied to.
* *
* @return attached {@link Window} instance * @return attached {@link Window} instance
* @since v1-alpha2 * @since v1-alpha9
*/ */
private final @NotNull Window attachedWindow; private final @NotNull Window attachedWindow;
@ -50,7 +50,7 @@ public class WindowCallback {
* Creates and initializes an instance of this abstract class. * Creates and initializes an instance of this abstract class.
* *
* @param window {@link Window} class * @param window {@link Window} class
* @since v1-alpha2 * @since v1-alpha9
*/ */
public WindowCallback(@NotNull Window window) { public WindowCallback(@NotNull Window window) {
this.attachedWindow = window; this.attachedWindow = window;

View file

@ -20,6 +20,6 @@
/** /**
* Callbacks, which emit {@link de.staropensource.engine.base.implementable.Event}s. * Callbacks, which emit {@link de.staropensource.engine.base.implementable.Event}s.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
package de.staropensource.engine.windowing.glfw.callback; package de.staropensource.engine.rendering.callback;

View file

@ -17,28 +17,28 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.windowing.event; package de.staropensource.engine.rendering.event;
import de.staropensource.engine.base.implementable.Event; import de.staropensource.engine.base.implementable.Event;
import de.staropensource.engine.base.implementable.helper.EventHelper; import de.staropensource.engine.base.implementable.helper.EventHelper;
import de.staropensource.engine.base.logging.Logger; import de.staropensource.engine.base.logging.Logger;
import de.staropensource.engine.windowing.WindowingSubsystemConfiguration; import de.staropensource.engine.rendering.RenderingSubsystemConfiguration;
import de.staropensource.engine.windowing.implementable.Window; import de.staropensource.engine.rendering.type.Window;
import de.staropensource.engine.windowing.type.input.Key; import de.staropensource.engine.rendering.type.input.Key;
import de.staropensource.engine.windowing.type.input.KeyState; import de.staropensource.engine.rendering.type.input.KeyState;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
/** /**
* Called when a key or button is pressed. * Called when a key or button is pressed.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
public final class InputEvent implements Event { public final class InputEvent implements Event {
/** /**
* Creates and initializes an instance of this event. * Creates and initializes an instance of this event.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
public InputEvent() {} public InputEvent() {}
@ -57,10 +57,10 @@ public final class InputEvent implements Event {
* @param window window the input originated from. May be {@code null}, depending on the windowing API * @param window window the input originated from. May be {@code null}, depending on the windowing API
* @param key key * @param key key
* @param state key state * @param state key state
* @since v1-alpha0 * @since v1-alpha9
*/ */
public void callEvent(@Nullable Window window, @NotNull Key key, @NotNull KeyState state) { public void callEvent(@Nullable Window window, @NotNull Key key, @NotNull KeyState state) {
if (WindowingSubsystemConfiguration.getInstance().isDebugInput()) if (RenderingSubsystemConfiguration.getInstance().isDebugInput())
Logger.diag("Got input event: window=" + (window == null ? "\\<null>" : window.getUniqueIdentifier()) + " key=" + key.name() + " state=" + state.name()); Logger.diag("Got input event: window=" + (window == null ? "\\<null>" : window.getUniqueIdentifier()) + " key=" + key.name() + " state=" + state.name());
EventHelper.invokeAnnotatedMethods(getClass(), window, key, state); EventHelper.invokeAnnotatedMethods(getClass(), window, key, state);

View file

@ -17,27 +17,28 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.windowing.event; package de.staropensource.engine.rendering.event;
import de.staropensource.engine.base.implementable.Event; import de.staropensource.engine.base.implementable.Event;
import de.staropensource.engine.base.implementable.helper.EventHelper; import de.staropensource.engine.base.implementable.helper.EventHelper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
* Called when an error occurs in the renderer API (e.g. OpenGL, Vulkan). * Emitted when a rendering error occurs.
* *
* @since v1-alpha0 * @since v1-alpha9
*/ */
public final class RenderingErrorEvent implements Event { public final class RenderingErrorEvent implements Event {
/** /**
* Creates and initializes an instance of this event. * Creates and initializes an instance of this event.
* *
* @since v1-alpha0 * @since v1-alpha9
*/ */
public RenderingErrorEvent() {} public RenderingErrorEvent() {}
/** /**
* {@inheritDoc} * {@inheritDoc}
*
* @deprecated use the {@code callEvent} method with arguments * @deprecated use the {@code callEvent} method with arguments
* @see #callEvent(String) * @see #callEvent(String)
*/ */
@ -49,7 +50,7 @@ public final class RenderingErrorEvent implements Event {
* Emits the event and calls all event listeners. * Emits the event and calls all event listeners.
* *
* @param error error description * @param error error description
* @since v1-alpha0 * @since v1-alpha9
*/ */
public void callEvent(@NotNull String error) { public void callEvent(@NotNull String error) {
EventHelper.invokeAnnotatedMethods(getClass(), error); EventHelper.invokeAnnotatedMethods(getClass(), error);

View file

@ -17,30 +17,30 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.windowing.event; package de.staropensource.engine.rendering.event;
import de.staropensource.engine.base.implementable.Event; import de.staropensource.engine.base.implementable.Event;
import de.staropensource.engine.base.implementable.helper.EventHelper; import de.staropensource.engine.base.implementable.helper.EventHelper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
* Called when an error occurs in the windowing API. * Emitted when the rendering thread exits due to an unhandled exception.
* *
* @since v1-alpha0 * @since v1-alpha9
*/ */
public final class WindowingErrorEvent implements Event { public final class RenderingThreadThrowableEvent implements Event {
/** /**
* Creates and initializes an instance of this event. * Creates and initializes an instance of this event.
* *
* @since v1-alpha0 * @since v1-alpha9
*/ */
public WindowingErrorEvent() {} public RenderingThreadThrowableEvent() {}
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
* @deprecated use the {@code callEvent} method with arguments * @deprecated use the {@code callEvent} method with arguments
* @see #callEvent(String) * @see #callEvent(Throwable)
*/ */
@Deprecated @Deprecated
@Override @Override
@ -49,10 +49,10 @@ public final class WindowingErrorEvent implements Event {
/** /**
* Emits the event and calls all event listeners. * Emits the event and calls all event listeners.
* *
* @param error error description * @param throwable thrown {@link Throwable}
* @since v1-alpha0 * @since v1-alpha9
*/ */
public void callEvent(@NotNull String error) { public void callEvent(@NotNull Throwable throwable) {
EventHelper.invokeAnnotatedMethods(getClass(), error); EventHelper.invokeAnnotatedMethods(getClass(), throwable);
} }
} }

View file

@ -20,6 +20,6 @@
/** /**
* Events. There's nothing more to say. * Events. There's nothing more to say.
* *
* @since v1-alpha0 * @since v1-alpha9
*/ */
package de.staropensource.engine.windowing.event; package de.staropensource.engine.rendering.event;

View file

@ -17,18 +17,18 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.windowing.exception; package de.staropensource.engine.rendering.exception;
/** /**
* Thrown when the specified monitor does not exist. * Thrown when the specified monitor does not exist.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
public final class InvalidMonitorException extends RuntimeException { public final class InvalidMonitorException extends RuntimeException {
/** /**
* Creates and initializes an instance of this exception. * Creates and initializes an instance of this exception.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
public InvalidMonitorException() {} public InvalidMonitorException() {}
} }

View file

@ -17,18 +17,18 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.windowing.exception; package de.staropensource.engine.rendering.exception;
/** /**
* Thrown when trying to access one or more monitors but none are found. * Thrown when trying to access one or more monitors but none are found.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
public final class NoMonitorsFoundException extends RuntimeException { public final class NoMonitorsFoundException extends RuntimeException {
/** /**
* Creates and initializes an instance of this exception. * Creates and initializes an instance of this exception.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
public NoMonitorsFoundException() {} public NoMonitorsFoundException() {}
} }

View file

@ -17,18 +17,18 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.windowing.exception; package de.staropensource.engine.rendering.exception;
/** /**
* Thrown when trying to communicate with a windowing API over a non-main thread. * Thrown when trying to communicate with a windowing API over a non-main thread.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
public final class NotOnMainThreadException extends RuntimeException { public final class NotOnMainThreadException extends RuntimeException {
/** /**
* Creates and initializes an instance of this exception. * Creates and initializes an instance of this exception.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
public NotOnMainThreadException() {} public NotOnMainThreadException() {}
} }

View file

@ -17,21 +17,21 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.windowing.exception; package de.staropensource.engine.rendering.exception;
import de.staropensource.engine.windowing.implementable.Window; import de.staropensource.engine.rendering.type.Window;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
* Thrown when a {@link Window} cannot be created. * Thrown when a {@link Window} cannot be created.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
public final class WindowCreationFailureException extends RuntimeException { public final class WindowCreationFailureException extends RuntimeException {
/** /**
* Creates and initializes an instance of this exception. * Creates and initializes an instance of this exception.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
public WindowCreationFailureException() {} public WindowCreationFailureException() {}
@ -39,7 +39,7 @@ public final class WindowCreationFailureException extends RuntimeException {
* Creates and initializes an instance of this exception. * Creates and initializes an instance of this exception.
* *
* @param message error message * @param message error message
* @since v1-alpha2 * @since v1-alpha9
*/ */
public WindowCreationFailureException(@NotNull String message) { public WindowCreationFailureException(@NotNull String message) {
super(message); super(message);

View file

@ -23,6 +23,6 @@
* These aren't meant for the windowing subsystem, * These aren't meant for the windowing subsystem,
* but instead for windowing APIs, which may throw them. * but instead for windowing APIs, which may throw them.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
package de.staropensource.engine.windowing.exception; package de.staropensource.engine.rendering.exception;

View file

@ -20,6 +20,6 @@
/** /**
* Code of the windowing subsystem. * Code of the windowing subsystem.
* *
* @since v1-alpha0 * @since v1-alpha9
*/ */
package de.staropensource.engine.windowing; package de.staropensource.engine.rendering;

View file

@ -0,0 +1,384 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.rendering.renderer;
import de.staropensource.engine.base.logging.Logger;
import de.staropensource.engine.base.utility.misc.Miscellaneous;
import de.staropensource.engine.base.utility.misc.NumberUtil;
import de.staropensource.engine.rendering.RenderingSubsystemConfiguration;
import de.staropensource.engine.rendering.exception.NotOnMainThreadException;
import de.staropensource.engine.rendering.type.FrameHandler;
import de.staropensource.engine.rendering.type.Window;
import de.staropensource.engine.rendering.type.window.VsyncMode;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import java.time.LocalTime;
import java.util.*;
import static org.lwjgl.bgfx.BGFX.*;
import static org.lwjgl.glfw.GLFW.*;
/**
* Renders all windows out.
*
* @since v1-alpha9
*/
@SuppressWarnings({ "JavadocDeclaration" })
public final class Renderer {
/**
* Contains all frame handlers.
* <p>
* Frame handlers are invoked before
* all windows are rendered, allowing
* the application or game to respond
* to frame renders.
*
* @since v1-alpha9
*/
private static final @NotNull List<@NotNull FrameHandler> frameHandlers = Collections.synchronizedList(new ArrayList<>());
/**
* Contains if the renderer has been initialized.
*
* @since v1-alpha9
* -- GETTER --
* Returns if the renderer has been initialized.
*
* @return renderer initialized?
* @since v1-alpha9
*/
@Getter
private static boolean initialized = false;
/**
* Contains if the renderer is running.
*
* @since v1-alpha9
* -- GETTER --
* Returns if the renderer is running.
*
* @return renderer running?
* @since v1-alpha9
*/
@Getter
private static boolean running = false;
/**
* Contains the frame count aka.
* the amount of frames rendered.
* <p>
* Updated every frame.
*
* @since v1-alpha9
* -- GETTER --
* Returns the frame count aka.
* the amount of frames rendered.
* <p>
* Updated every frame.
*
* @return amount of frames rendered
* @since v1-alpha9
*/
@Getter
private static long frameCount = 0L;
/**
* Contains the delta time, also
* known as the render time.
* <p>
* Updated every second.
*
* @since v1-alpha9
* -- GETTER --
* Returns the delta time, also
* known as the render time.
* <p>
* Updated every second.
*
* @return delta time
* @since v1-alpha9
*/
@Getter
private static double deltaTime = 0d;
/**
* Contains the frames per second (FPS) count.
* <p>
* Updated every second.
*
* @since v1-alpha9
* -- GETTER --
* Returns the frames per second (FPS) count.
* <p>
* Updated every second.
*
* @return frames per second
* @since v1-alpha9
*/
@Getter
private static double framesPerSecond = 0d;
/**
* Contains the time it took
* to calculate the last frame.
* <p>
* Updated every frame.
*
* @since v1-alpha9
* -- GETTER --
* Contains the time it took
* to calculate the last frame.
* <p>
* Updated every frame.
*
* @return last frame time
* @since v1-alpha9
*/
@Getter
private static Map<@NotNull String, @NotNull Long> lastFrameTime = Collections.unmodifiableMap(new HashMap<>());
// ----> Initialization
/**
* Initializes the renderer.
*
* @since v1-alpha9
*/
public static void initialize() {
if (initialized)
return;
addFrameHandler(new FrameHandler() {
@Override
public @NotNull FrameHandler.Priority getPriority() {
return Priority.VERY_IMPORTANT;
}
@Override
public void run() {
bgfx_set_view_clear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0);
}
});
addFrameHandler(new FrameHandler() {
/** {@inheritDoc} */
@Override
public @NotNull FrameHandler.Priority getPriority() {
return Priority.VERY_UNIMPORTANT;
}
/** {@inheritDoc} */
@Override
public void run() {
int offset = 2;
bgfx_dbg_text_clear(0, false);
bgfx_dbg_text_printf(0, 0, 0x0f, "It's " + NumberUtil.padNumbers(LocalTime.now().getHour(), 2) + ":" + NumberUtil.padNumbers(LocalTime.now().getMinute(), 2) + ":" + NumberUtil.padNumbers(LocalTime.now().getSecond(), 2));
bgfx_dbg_text_printf(0, 1, 0x0f, "LFT.size(): " + lastFrameTime.size());
for (String item : lastFrameTime.keySet()) {
bgfx_dbg_text_printf(0, offset, 0x0f, item + ": " + lastFrameTime.get(item) + "ms");
offset += 1;
}
}
});
initialized = true;
}
// -----> Frame handler management
/**
* Adds the specified frame handler.
*
* @param frameHandler {@link FrameHandler} to add
* @since v1-alpha9
*/
public static void addFrameHandler(@NotNull FrameHandler frameHandler) {
frameHandlers.add(frameHandler);
frameHandlers.sort(Comparator.comparing(FrameHandler::getPriority));
}
/**
* Removes the specified frame handler.
*
* @param frameHandler {@link FrameHandler} to remove
* @since v1-alpha9
*/
public static void removeFrameHandler(@NotNull FrameHandler frameHandler) {
frameHandlers.remove(frameHandler);
}
// -----> Rendering logic
/**
* Starts the renderer.
*
* @throws NotOnMainThreadException if not running on the main thread
* @throws RuntimeException on major rendering error
* @since v1-alpha9
*/
public static void start() throws RuntimeException {
// Check if running on main thread
if (!Miscellaneous.onMainThread())
throw new NotOnMainThreadException();
String threadName = Thread.currentThread().getName();
int threadPriority = Thread.currentThread().getPriority();
RuntimeException exception = null;
// Update thread
Thread.currentThread().setName("Rendering thread");
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
// Start renderer
running = true;
try {
render();
} catch (Throwable throwable) {
exception = new RuntimeException("Renderer failed", throwable);
}
// Revert thread changes
Thread.currentThread().setName(threadName);
Thread.currentThread().setPriority(threadPriority);
// Throw if necessary
if (exception != null)
throw exception;
}
/**
* Renders all windows.
*
* @since v1-alpha9
*/
@SuppressWarnings({ "InfiniteLoopStatement" })
private static void render() throws Throwable {
long previousFrameCount = 0L; // Frame count one second ago
LinkedList<Long> deltaTimeFractions = new LinkedList<>(); // Contains all delta time fractions
Map<String, Long> execTimes = new LinkedHashMap<>(); // Contains the amount of time of all rendering operations
long timesWait; // Time to wait until the next frame
long timesPSO = System.currentTimeMillis() + 1000; // Time to wait until invoking per-second operations
while (true) {
// Invoke frame handlers
for (FrameHandler frameHandler : frameHandlers)
execTimes.put("Frame handler '" + frameHandler.getClass().getName() + "'", Miscellaneous.measureExecutionTime(frameHandler::run));
// Perform rendering
execTimes.put("Rendering", Miscellaneous.measureExecutionTime(() -> {
// Poll for events
glfwPollEvents();
// Reset backbuffer
int resetSettings = 0;
if (RenderingSubsystemConfiguration.getInstance().getVsyncMode() == VsyncMode.ON)
resetSettings |= BGFX_RESET_TRANSPARENT_BACKBUFFER;
for (Window window : Window.getWindows())
if (window.isTransparent())
resetSettings |= BGFX_RESET_TRANSPARENT_BACKBUFFER;
bgfx_reset(
Window.getWindows().getFirst().getSize().getX(),
Window.getWindows().getFirst().getSize().getY(),
resetSettings,
BGFX_TEXTURE_FORMAT_RGBA4
);
// Render all windows
for (Window window : Window.getWindows())
if (window.isRendering()) {
window.updateState();
window.render();
}
// Advance to next frame
bgfx_frame(false);
}));
// Determine time to wait for the next frame
execTimes.put("Waiting", 0L);
if (RenderingSubsystemConfiguration.getInstance().getVsyncMode() == VsyncMode.OFF && RenderingSubsystemConfiguration.getInstance().getMaximumFramesPerSecond() > 0) {
execTimes.replace("Waiting", (long) (1d / RenderingSubsystemConfiguration.getInstance().getMaximumFramesPerSecond() * 1000d));
for (String time : execTimes.keySet())
if (!time.equals("Waiting"))
execTimes.replace("Waiting", execTimes.get("Waiting") - execTimes.get(time));
// Wait until next frame
if (execTimes.get("Waiting") > 0) {
timesWait = execTimes.get("Waiting") + System.currentTimeMillis();
while (System.currentTimeMillis() < timesWait)
Thread.onSpinWait();
}
}
// Perform per-frame operations
frameCount += 1;
lastFrameTime = new HashMap<>(execTimes);
deltaTimeFractions.add(execTimes.get("Rendering") + execTimes.get("Waiting"));
execTimes.clear();
// Perform per-second operations
if (System.currentTimeMillis() >= timesPSO) {
// Calculate delta time and FPS count
deltaTime = NumberUtil.calculateMeanLong(deltaTimeFractions);
framesPerSecond = 1000 / deltaTime;
// Log frame count
if (RenderingSubsystemConfiguration.getInstance().isDebugFrames())
Logger.diag("Frames " + previousFrameCount + "-" + frameCount + "\n-> Frames/s: " + framesPerSecond + "\n-> Delta time: " + deltaTime);
// Log window states
if (RenderingSubsystemConfiguration.getInstance().isDebugWindowStates())
for (Window window : Window.getWindows())
Logger.diag(
"Window state for " + window.getUniqueIdentifier() + "\n" +
"-> Terminated: " + window.isTerminated() + "\n" +
"-> Name: " + window.getName() + "\n" +
"-> Title: " + window.getTitle() + "\n" +
"-> Size: " + window.getSize() + "\n" +
" -> Minimum: " + window.getMinimumSize() + "\n" +
" -> Maximum: " + window.getMaximumSize() + "\n" +
"-> Position: " + window.getPosition() + "\n" +
"-> Mode: " + window.getMode() + "\n" +
"-> Resizable: " + window.isResizable() + "\n" +
"-> Borderless: " + window.isBorderless() + "\n" +
"-> Focused: " + window.isFocused() + "\n" +
"-> On top: " + window.isOnTop() + "\n" +
"-> Transparent: " + window.isTransparent() + "\n" +
"-> Rendering: " + window.isRendering()
);
// Reset per-second variables
previousFrameCount = frameCount;
deltaTimeFractions.clear();
timesPSO = System.currentTimeMillis() + 1000;
}
}
}
}

View file

@ -0,0 +1,93 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.rendering.type;
import org.jetbrains.annotations.NotNull;
/**
* Used for performing actions
* before a frame is rendered.
*
* @since v1-alpha9
*/
public interface FrameHandler {
/**
* Returns the priority this frame handler has.
*
* @return priority
* @since v1-alpha9
*/
@NotNull FrameHandler.Priority getPriority();
/**
* Invokes this frame handler.
*
* @since v1-alpha9
*/
void run();
/**
* Contains all priority levels
* a {@link FrameHandler} can have.
*
* @since v1-alpha9
*/
enum Priority {
/**
* {@link FrameHandler}s with
* this priority are called first.
*
* @since v1-alpha9
*/
VERY_IMPORTANT,
/**
* {@link FrameHandler}s with
* this priority are called 2nd.
*
* @since v1-alpha9
*/
IMPORTANT,
/**
* {@link FrameHandler}s with
* this priority are called 3rd.
*
* @since v1-alpha9
*/
DEFAULT,
/**
* {@link FrameHandler}s with
* this priority are called 4th.
*
* @since v1-alpha9
*/
UNIMPORTANT,
/**
* {@link FrameHandler}s with
* this priority are called last.
*
* @since v1-alpha9
*/
VERY_UNIMPORTANT,
}
}

File diff suppressed because it is too large Load diff

View file

@ -17,590 +17,590 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.windowing.type.input; package de.staropensource.engine.rendering.type.input;
/** /**
* Contains a list of keys which can be recognized by the engine. * Contains a list of keys which can be recognized by the engine.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
public enum Key { public enum Key {
/** /**
* An unknown key. * An unknown key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
UNKNOWN_KEY, UNKNOWN_KEY,
/** /**
* An unknown mouse button. * An unknown mouse button.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
UNKNOWN_MOUSE, UNKNOWN_MOUSE_BUTTON,
/** /**
* The left mouse button. * The left mouse button.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
MOUSE_LEFT, MOUSE_LEFT,
/** /**
* The middle mouse button. * The middle mouse button.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
MOUSE_MIDDLE, MOUSE_MIDDLE,
/** /**
* The right mouse button. * The right mouse button.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
MOUSE_RIGHT, MOUSE_RIGHT,
/** /**
* The {@code ALT} modifier key. * The {@code ALT} modifier key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
ALT, ALT,
/** /**
* The {@code '} key. * The {@code '} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
APOSTROPHE, APOSTROPHE,
/** /**
* The {@code DOWN} arrow key. * The {@code DOWN} arrow key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
ARROW_DOWN, ARROW_DOWN,
/** /**
* The {@code LEFT} arrow key. * The {@code LEFT} arrow key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
ARROW_LEFT, ARROW_LEFT,
/** /**
* The {@code RIGHT} arrow key. * The {@code RIGHT} arrow key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
ARROW_RIGHT, ARROW_RIGHT,
/** /**
* The {@code UP} arrow key. * The {@code UP} arrow key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
ARROW_UP, ARROW_UP,
/** /**
* The {@code \} key. * The {@code \} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
BACKSLASH, BACKSLASH,
/** /**
* The {@code BACKSPACE} key. * The {@code BACKSPACE} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
BACKSPACE, BACKSPACE,
/** /**
* The left {@code [} key. * The left {@code [} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
BRACKET_LEFT, BRACKET_LEFT,
/** /**
* The right {@code ]} key. * The right {@code ]} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
BRACKET_RIGHT, BRACKET_RIGHT,
/** /**
* THE {@code CAPSLOCK} KEY. * THE {@code CAPSLOCK} KEY.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
CAPS_LOCK, CAPS_LOCK,
/** /**
* The {@code ,} key. * The {@code ,} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
COMMA, COMMA,
/** /**
* The left {@code CTRL} modifier key. * The left {@code CTRL} modifier key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
CONTROL_LEFT, CONTROL_LEFT,
/** /**
* The right {@code CTRL} modifier key. * The right {@code CTRL} modifier key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
CONTROL_RIGHT, CONTROL_RIGHT,
/** /**
* The {@code DEL} key. * The {@code DEL} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
DELETE, DELETE,
/** /**
* The {@code END} key. * The {@code END} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
END, END,
/** /**
* The {@code ENTER} key. * The {@code ENTER} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
ENTER, ENTER,
/** /**
* The {@code =} key. * The {@code =} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
EQUAL, EQUAL,
/** /**
* The {@code ESC} key. * The {@code ESC} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
ESCAPE, ESCAPE,
/** /**
* The {@code F1} key. * The {@code F1} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_1, FUNCTION_1,
/** /**
* The {@code F2} key. * The {@code F2} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_2, FUNCTION_2,
/** /**
* The {@code F3} key. * The {@code F3} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_3, FUNCTION_3,
/** /**
* The {@code F4} key. * The {@code F4} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_4, FUNCTION_4,
/** /**
* The {@code F5} key. * The {@code F5} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_5, FUNCTION_5,
/** /**
* The {@code F6} key. * The {@code F6} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_6, FUNCTION_6,
/** /**
* The {@code F7} key. * The {@code F7} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_7, FUNCTION_7,
/** /**
* The {@code F8} key. * The {@code F8} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_8, FUNCTION_8,
/** /**
* The {@code F9} key. * The {@code F9} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_9, FUNCTION_9,
/** /**
* The {@code F10} key. * The {@code F10} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_10, FUNCTION_10,
/** /**
* The {@code F11} key. * The {@code F11} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_11, FUNCTION_11,
/** /**
* The {@code F12} key. * The {@code F12} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_12, FUNCTION_12,
/** /**
* The {@code F13} key. * The {@code F13} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_13, FUNCTION_13,
/** /**
* The {@code F14} key. * The {@code F14} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_14, FUNCTION_14,
/** /**
* The {@code F15} key. * The {@code F15} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_15, FUNCTION_15,
/** /**
* The {@code F16} key. * The {@code F16} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_16, FUNCTION_16,
/** /**
* The {@code F17} key. * The {@code F17} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_17, FUNCTION_17,
/** /**
* The {@code F18} key. * The {@code F18} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_18, FUNCTION_18,
/** /**
* The {@code F19} key. * The {@code F19} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_19, FUNCTION_19,
/** /**
* The {@code F20} key. * The {@code F20} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_20, FUNCTION_20,
/** /**
* The {@code F21} key. * The {@code F21} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_21, FUNCTION_21,
/** /**
* The {@code F22} key. * The {@code F22} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_22, FUNCTION_22,
/** /**
* The {@code F23} key. * The {@code F23} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_23, FUNCTION_23,
/** /**
* The {@code F24} key. * The {@code F24} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_24, FUNCTION_24,
/** /**
* The {@code F25} key. * The {@code F25} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
FUNCTION_25, FUNCTION_25,
/** /**
* The {@code `} key. * The {@code `} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
GRAVE, GRAVE,
/** /**
* The {@code HOME} key. * The {@code HOME} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
HOME, HOME,
/** /**
* THe {@code INS} key. * THe {@code INS} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
INSERT, INSERT,
/** /**
* The {@code +} key on your keypad. * The {@code +} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_ADD, KEYPAD_ADD,
/** /**
* The {@code -} key on your keypad. * The {@code -} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_DECIMAL, KEYPAD_DECIMAL,
/** /**
* The {@code /} key on your keypad. * The {@code /} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_DIVIDE, KEYPAD_DIVIDE,
/** /**
* The {@code ENTER} key on your keypad. * The {@code ENTER} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_ENTER, KEYPAD_ENTER,
/** /**
* The {@code =} key on your keypad. * The {@code =} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_EQUAL, KEYPAD_EQUAL,
/** /**
* The {@code *} key on your keypad. * The {@code *} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_MULTIPLY, KEYPAD_MULTIPLY,
/** /**
* The number {@code 0} key on your keypad. * The number {@code 0} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_NUMBER_0, KEYPAD_NUMBER_0,
/** /**
* The number {@code 1} key on your keypad. * The number {@code 1} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_NUMBER_1, KEYPAD_NUMBER_1,
/** /**
* The number {@code 2} key on your keypad. * The number {@code 2} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_NUMBER_2, KEYPAD_NUMBER_2,
/** /**
* The number {@code 3} key on your keypad. * The number {@code 3} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_NUMBER_3, KEYPAD_NUMBER_3,
/** /**
* The number {@code 4} key on your keypad. * The number {@code 4} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_NUMBER_4, KEYPAD_NUMBER_4,
/** /**
* The number {@code 5} key on your keypad. * The number {@code 5} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_NUMBER_5, KEYPAD_NUMBER_5,
/** /**
* The number {@code 6} key on your keypad. * The number {@code 6} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_NUMBER_6, KEYPAD_NUMBER_6,
/** /**
* The number {@code 7} key on your keypad. * The number {@code 7} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_NUMBER_7, KEYPAD_NUMBER_7,
/** /**
* The number {@code 8} key on your keypad. * The number {@code 8} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_NUMBER_8, KEYPAD_NUMBER_8,
/** /**
* The number {@code 9} key on your keypad. * The number {@code 9} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_NUMBER_9, KEYPAD_NUMBER_9,
/** /**
* The {@code -} key on your keypad. * The {@code -} key on your keypad.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
KEYPAD_SUBTRACT, KEYPAD_SUBTRACT,
/** /**
* The letter {@code A} key. * The letter {@code A} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_A, LETTER_A,
/** /**
* The letter {@code B} key. * The letter {@code B} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_B, LETTER_B,
/** /**
* The letter {@code C} key. * The letter {@code C} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_C, LETTER_C,
/** /**
* The letter {@code D} key. * The letter {@code D} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_D, LETTER_D,
/** /**
* The letter {@code E} key. * The letter {@code E} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_E, LETTER_E,
/** /**
* The letter {@code F} key. * The letter {@code F} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_F, LETTER_F,
/** /**
* The letter {@code G} key. * The letter {@code G} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_G, LETTER_G,
/** /**
* The letter {@code H} key. * The letter {@code H} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_H, LETTER_H,
/** /**
* The letter {@code I} key. * The letter {@code I} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_I, LETTER_I,
/** /**
* The letter {@code J} key. * The letter {@code J} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_J, LETTER_J,
/** /**
* The letter {@code K} key. * The letter {@code K} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_K, LETTER_K,
/** /**
* The letter {@code L} key. * The letter {@code L} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_L, LETTER_L,
/** /**
* The letter {@code M} key. * The letter {@code M} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_M, LETTER_M,
/** /**
* The letter {@code N} key. * The letter {@code N} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_N, LETTER_N,
/** /**
* The letter {@code O} key. * The letter {@code O} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_O, LETTER_O,
/** /**
* The letter {@code P} key. * The letter {@code P} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_P, LETTER_P,
/** /**
* The letter {@code Q} key. * The letter {@code Q} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_Q, LETTER_Q,
/** /**
* The letter {@code R} key. * The letter {@code R} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_R, LETTER_R,
/** /**
* The letter {@code S} key. * The letter {@code S} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_S, LETTER_S,
/** /**
* The letter {@code T} key. * The letter {@code T} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_T, LETTER_T,
/** /**
* The letter {@code U} key. * The letter {@code U} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_U, LETTER_U,
/** /**
* The letter {@code V} key. * The letter {@code V} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_V, LETTER_V,
/** /**
* The letter {@code W} key. * The letter {@code W} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_W, LETTER_W,
/** /**
* The letter {@code X} key. * The letter {@code X} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_X, LETTER_X,
/** /**
* The letter {@code Y} key. * The letter {@code Y} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_Y, LETTER_Y,
/** /**
* The letter {@code Z} key. * The letter {@code Z} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
LETTER_Z, LETTER_Z,
/** /**
* The {@code MENU} key, which brings up the right click menu. * The {@code MENU} key, which brings up the right click menu.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
MENU, MENU,
/** /**
@ -608,151 +608,151 @@ public enum Key {
* <p> * <p>
* Windows users will recognize this key as the Windows key. * Windows users will recognize this key as the Windows key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
META, META,
/** /**
* The {@code -} key. * The {@code -} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
MINUS, MINUS,
/** /**
* The number {@code 0}. * The number {@code 0}.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
NUMBER_0, NUMBER_0,
/** /**
* The number {@code 1}. * The number {@code 1}.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
NUMBER_1, NUMBER_1,
/** /**
* The number {@code 2}. * The number {@code 2}.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
NUMBER_2, NUMBER_2,
/** /**
* The number {@code 3}. * The number {@code 3}.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
NUMBER_3, NUMBER_3,
/** /**
* The number {@code 4}. * The number {@code 4}.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
NUMBER_4, NUMBER_4,
/** /**
* The number {@code 5}. * The number {@code 5}.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
NUMBER_5, NUMBER_5,
/** /**
* The number {@code 6}. * The number {@code 6}.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
NUMBER_6, NUMBER_6,
/** /**
* The number {@code 7}. * The number {@code 7}.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
NUMBER_7, NUMBER_7,
/** /**
* The number {@code 8}. * The number {@code 8}.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
NUMBER_8, NUMBER_8,
/** /**
* The number {@code 9}. * The number {@code 9}.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
NUMBER_9, NUMBER_9,
/** /**
* The {@code NUM} key. * The {@code NUM} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
NUM_LOCK, NUM_LOCK,
/** /**
* The {@code PAGE DOWN} key. * The {@code PAGE DOWN} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
PAGE_DOWN, PAGE_DOWN,
/** /**
* The {@code PAGE UP} key. * The {@code PAGE UP} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
PAGE_UP, PAGE_UP,
/** /**
* The {@code PAUSE} key. * The {@code PAUSE} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
PAUSE, PAUSE,
/** /**
* The {@code .} key. * The {@code .} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
PERIOD, PERIOD,
/** /**
* The {@code PRINT} key. * The {@code PRINT} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
PRINT, PRINT,
/** /**
* The {@code SCROLL} key. * The {@code SCROLL} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
SCROLL_LOCK, SCROLL_LOCK,
/** /**
* The {@code ;} key. * The {@code ;} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
SEMICOLON, SEMICOLON,
/** /**
* The left {@code SHIFT} modifier key. * The left {@code SHIFT} modifier key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
SHIFT_LEFT, SHIFT_LEFT,
/** /**
* The right {@code SHIFT} modifier key. * The right {@code SHIFT} modifier key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
SHIFT_RIGHT, SHIFT_RIGHT,
/** /**
* The {@code /} key. * The {@code /} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
SLASH, SLASH,
/** /**
* The {@code ENTER} key. * The {@code ENTER} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
SPACE, SPACE,
/** /**
* The {@code TAB} key. * The {@code TAB} key.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
TAB, TAB,
} }

View file

@ -17,26 +17,26 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.windowing.type.input; package de.staropensource.engine.rendering.type.input;
/** /**
* Contains in which state a key is. * Contains in which state a key is.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
@SuppressWarnings({ "unused" }) @SuppressWarnings({ "unused" })
public enum KeyState { public enum KeyState {
/** /**
* Indicates that a key is pressed. * Indicates that a key is pressed.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
PRESSED, PRESSED,
/** /**
* Indicates that a key is released. * Indicates that a key is released.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
RELEASED, RELEASED,
} }

View file

@ -20,6 +20,6 @@
/** /**
* Data types related to input. * Data types related to input.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
package de.staropensource.engine.windowing.type.input; package de.staropensource.engine.rendering.type.input;

View file

@ -20,6 +20,6 @@
/** /**
* Data types in form of enums and classes. * Data types in form of enums and classes.
* *
* @since v1-alpha1 * @since v1-alpha9
*/ */
package de.staropensource.engine.windowing.type; package de.staropensource.engine.rendering.type;

View file

@ -0,0 +1,76 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.rendering.type.window;
/**
* Represents all available rendering adapters.
*
* @since v1-alpha9
*/
public enum RenderingAdapter {
/**
* Allows the bgfx to autodetect the adapter to use.
*
* @since v1-alpha9
*/
ANY,
/**
* Tells bgfx to use the CPU for rendering.
*
* @since v1-alpha9
*/
SOFTWARE,
/**
* Tells bgfx to use AMD graphics cards for rendering.
*
* @since v1-alpha9
*/
AMD,
/**
* Tells bgfx to use Apple's SOC for rendering.
*
* @since v1-alpha9
*/
APPLE,
/**
* Tells bgfx to use Intel graphics cards for rendering.
*
* @since v1-alpha9
*/
INTEL,
/**
* Tells bgfx to use NVIDIA graphics cards for rendering.
*
* @since v1-alpha9
*/
NVIDIA,
/**
* Tells bgfx to use Windows' integrated graphics driver for rendering.
*
* @since v1-alpha9
*/
MICROSOFT,
}

View file

@ -17,53 +17,53 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.windowing.glfw.type; package de.staropensource.engine.rendering.type.window;
/** /**
* Contains all available platforms which GLFW can be initialized with. * Represents all available rendering platforms.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
public enum GlfwPlatform { public enum RenderingPlatform {
/** /**
* Allows GLFW to autodetect the platform to use. * Allows GLFW to autodetect the platform to use.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
ANY, ANY,
/** /**
* Prefer initializing with the Wayland platform. * Prefer initializing with the Wayland platform.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
WAYLAND, WAYLAND,
/** /**
* Prefer initializing with the X11 platform. * Prefer initializing with the X11 platform.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
X11, X11,
/** /**
* Prefer initializing with the Win32 platform. * Prefer initializing with the Win32 platform.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
WIN32, WIN32,
/** /**
* Prefer initializing with the Cocoa platform. * Prefer initializing with the Cocoa platform.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
COCOA, COCOA,
/** /**
* Prefer initializing without any platform. * Prefer initializing headless.
* *
* @since v1-alpha2 * @since v1-alpha9
*/ */
NONE NONE
} }

View file

@ -17,29 +17,30 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.staropensource.engine.windowing.type.window; package de.staropensource.engine.rendering.type.window;
import de.staropensource.engine.windowing.WindowingSubsystemConfiguration; import de.staropensource.engine.rendering.RenderingSubsystemConfiguration;
/** /**
* Controls how <a href="https://en.wikipedia.org/wiki/Screen_tearing#Vertical_synchronization">V-Sync</a> operates. * Controls how <a href="https://en.wikipedia.org/wiki/Screen_tearing#Vertical_synchronization">V-Sync</a> operates.
* *
* @since v1-alpha1 * @since v1-alpha9
*/ */
public enum VsyncMode { public enum VsyncMode {
/** /**
* Disables V-Sync. The frame rate will be uncapped and will allow * Disables V-Sync. The frame rate will be uncapped and will allow
* for processing an unlimited amount of frames (if not limited by * for processing an unlimited amount of frames (if not limited by
* {@link WindowingSubsystemConfiguration#maximumFramesPerSecond}). * {@link RenderingSubsystemConfiguration#maximumFramesPerSecond}).
* *
* @since v1-alpha1 * @since v1-alpha9
*/ */
OFF, OFF,
/** /**
* Enables V-Sync and will cap the window's frame rate at the refresh rate of the target monitor. * Enables V-Sync and will cap the window's frame rate
* at the refresh rate of the target monitor.
* *
* @since v1-alpha1 * @since v1-alpha9
*/ */
ON ON
} }

View file

@ -20,6 +20,6 @@
/** /**
* Data types related to windows. * Data types related to windows.
* *
* @since v1-alpha1 * @since v1-alpha9
*/ */
package de.staropensource.engine.windowing.type.window; package de.staropensource.engine.rendering.type.window;

View file

@ -0,0 +1,36 @@
/**
* The {@code rendering} subsystem, responsible for
* initializing and managing windows and rendering APIs.
*
* @since v1-alpha9
*/
module sosengine.rendering {
// Dependencies
// -> Engine
requires transitive sosengine.base;
// -> Libraries
requires transitive static lombok;
requires transitive org.jetbrains.annotations;
requires org.lwjgl.stb;
requires org.lwjgl.glfw;
requires org.lwjgl.bgfx;
requires java.desktop;
// API access
exports de.staropensource.engine.rendering;
exports de.staropensource.engine.rendering.event;
exports de.staropensource.engine.rendering.exception;
exports de.staropensource.engine.rendering.renderer;
exports de.staropensource.engine.rendering.type;
exports de.staropensource.engine.rendering.type.input;
exports de.staropensource.engine.rendering.type.window;
// Reflection access
opens de.staropensource.engine.rendering;
opens de.staropensource.engine.rendering.event;
opens de.staropensource.engine.rendering.exception;
opens de.staropensource.engine.rendering.renderer;
opens de.staropensource.engine.rendering.type;
opens de.staropensource.engine.rendering.type.input;
opens de.staropensource.engine.rendering.type.window;
}

Some files were not shown because too many files have changed in this diff Show more