Compare commits
No commits in common. "develop" and "v1-alpha8" have entirely different histories.
135 changed files with 5785 additions and 4058 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -42,6 +42,3 @@ bin/
|
|||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
|
||||
### Java ###
|
||||
hs_err_pid*.log
|
||||
|
|
|
@ -72,8 +72,6 @@ To change them, simply append `-P<property>` or `-P<property>=<value>`, like thi
|
|||
#### Parallelism
|
||||
Use the `jobs` property to control how many jobs will get executed simultaneously.
|
||||
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
|
||||
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.
|
||||
|
|
|
@ -35,9 +35,10 @@ import de.staropensource.engine.base.logging.backend.async.LoggingQueue;
|
|||
import de.staropensource.engine.base.logging.backend.async.LoggingThread;
|
||||
import de.staropensource.engine.base.type.DependencyVector;
|
||||
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.FileAccess;
|
||||
import de.staropensource.engine.base.utility.misc.Miscellaneous;
|
||||
import de.staropensource.engine.base.utility.Miscellaneous;
|
||||
import de.staropensource.engine.base.utility.PlaceholderEngine;
|
||||
import de.staropensource.engine.base.utility.information.EngineInformation;
|
||||
import de.staropensource.engine.base.utility.information.JvmInformation;
|
||||
|
@ -113,7 +114,7 @@ public final class Engine extends SubsystemClass {
|
|||
* @since v1-alpha1
|
||||
*/
|
||||
@Getter
|
||||
private @NotNull List<@NotNull DependencySubsystemVector> subsystems = Collections.emptyList();
|
||||
private @NotNull ImmutableLinkedList<@NotNull DependencySubsystemVector> subsystems = new ImmutableLinkedList<>();
|
||||
|
||||
/**
|
||||
* Contains the engine's shutdown handler.
|
||||
|
@ -290,8 +291,8 @@ public final class Engine extends SubsystemClass {
|
|||
new Engine();
|
||||
} catch (RuntimeException exception) {
|
||||
Logger.error("Engine initialization failed");
|
||||
Logger.error(Miscellaneous.throwableHeader(exception.getCause()));
|
||||
for (String line : Miscellaneous.stacktraceAsString(exception.getCause(), true).split("\n"))
|
||||
Logger.error(Miscellaneous.getStackTraceHeader(exception.getCause()));
|
||||
for (String line : Miscellaneous.getStackTraceAsString(exception.getCause(), true).split("\n"))
|
||||
Logger.error(line);
|
||||
|
||||
throw new RuntimeException("Engine initialization failed", exception.getCause());
|
||||
|
@ -365,6 +366,7 @@ public final class Engine extends SubsystemClass {
|
|||
EventHelper.cacheEvent(EngineSoftCrashEvent.class);
|
||||
EventHelper.cacheEvent(InternalEngineShutdownEvent.class);
|
||||
EventHelper.cacheEvent(LogEvent.class);
|
||||
EventHelper.cacheEvent(ThrowableCatchEvent.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -399,7 +401,7 @@ public final class Engine extends SubsystemClass {
|
|||
}
|
||||
|
||||
// Update 'subsystems'
|
||||
subsystems = Collections.unmodifiableList(subsystemsMutable);
|
||||
subsystems = new ImmutableLinkedList<>(subsystemsMutable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -486,7 +488,7 @@ public final class Engine extends SubsystemClass {
|
|||
}
|
||||
|
||||
// Update 'subsystems'
|
||||
subsystems = Collections.unmodifiableList(order);
|
||||
subsystems = new ImmutableLinkedList<>(order);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,11 +19,8 @@
|
|||
|
||||
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.ShortcodeParser;
|
||||
import de.staropensource.engine.base.implementable.SubsystemClass;
|
||||
import de.staropensource.engine.base.logging.Logger;
|
||||
import de.staropensource.engine.base.logging.backend.async.LoggingThread;
|
||||
import de.staropensource.engine.base.type.EngineState;
|
||||
|
@ -69,11 +66,11 @@ public final class EngineConfiguration extends Configuration {
|
|||
private static EngineConfiguration instance;
|
||||
|
||||
/**
|
||||
* Contains the configuration prefix.
|
||||
* Contains prefix properties must begin with.
|
||||
*
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* Returns the configuration prefix.
|
||||
* Returns prefix properties must begin with.
|
||||
*
|
||||
* @return property group
|
||||
* @since v1-alpha0
|
||||
|
@ -82,196 +79,132 @@ public final class EngineConfiguration extends Configuration {
|
|||
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
* If enabled, allows for unintentional behaviour
|
||||
* and excess logging. Unless you want to debug or work
|
||||
* on a sensitive part of the engine, don't enable this!
|
||||
*
|
||||
* @since v1-alpha0
|
||||
* -- 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}.
|
||||
* Gets the value for {@link #debug}.
|
||||
*
|
||||
* @return debugging enabled?
|
||||
* @return variable value
|
||||
* @see #debug
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private boolean debug;
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
* If enabled, all called events will be logged.
|
||||
*
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* 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}.
|
||||
* Gets the value for {@link #debugEvents}.
|
||||
*
|
||||
* @return detailed event logging enabled?
|
||||
* @return variable value
|
||||
* @see #debugEvents
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private boolean debugEvents;
|
||||
|
||||
|
||||
/**
|
||||
* Contains whether or not to automatically discover
|
||||
* and initialize any class extending {@link SubsystemClass}
|
||||
* whilst being annotated with {@link EngineSubsystem}.
|
||||
* If enabled, will try to automatically initialize every
|
||||
* subsystem found though reflection.
|
||||
* <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.
|
||||
* This however may fail in certain situation, where manual
|
||||
* subsystem initialization may be required. For this reason,
|
||||
* this can be turned off before the engine initializes. Please
|
||||
* note though that dependency resolution between subsystems
|
||||
* won't be performed, be careful when initializing subsystems manually.
|
||||
*
|
||||
* @see Engine
|
||||
* @since v1-alpha5
|
||||
* @since v1-alpha2
|
||||
* -- GETTER --
|
||||
* 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.
|
||||
* Gets the value for {@link #initialPerformSubsystemInitialization}.
|
||||
*
|
||||
* @return automatically discover and initialize subsystems?
|
||||
* @return variable value
|
||||
* @see #initialPerformSubsystemInitialization
|
||||
* @since v1-alpha5
|
||||
*/
|
||||
private boolean initialPerformSubsystemInitialization;
|
||||
|
||||
/**
|
||||
* Contains a set of class names to try to load
|
||||
* and initialize as subsystems. Will only take effect
|
||||
* if {@link #initialPerformSubsystemInitialization} is
|
||||
* turned off.
|
||||
* Will try to load the specified classes as subsystems,
|
||||
* if reflective classpath scanning is disabled.
|
||||
*
|
||||
* @since v1-alpha5
|
||||
* -- GETTER --
|
||||
* Returns a set of class names to try to load
|
||||
* and initialize as subsystems. Will only take effect
|
||||
* if {@link #getInitialIncludeSubsystemClasses()} is
|
||||
* turned off.
|
||||
* Gets the value for {@link #initialIncludeSubsystemClasses}.
|
||||
*
|
||||
* @return set of class names to try and initialize as subsystems
|
||||
* @return variable value
|
||||
* @see #initialIncludeSubsystemClasses
|
||||
* @since v1-alpha5
|
||||
*/
|
||||
private Set<@NotNull String> initialIncludeSubsystemClasses;
|
||||
|
||||
|
||||
/**
|
||||
* Contains 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.
|
||||
* If enabled, will cause {@link ShortcodeParser} to print
|
||||
* invalid shortcodes as {@link LogLevel#SILENT_WARNING}s.
|
||||
*
|
||||
* @see ShortcodeParser
|
||||
* @see #logLevel
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* 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.
|
||||
* Gets the value for {@link #errorShortcodeParser}.
|
||||
*
|
||||
* @return complain about invalid shortcodes?
|
||||
* @see #getLogLevel()
|
||||
* @return variable value
|
||||
* @see #errorShortcodeParser
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private boolean errorShortcodeParser;
|
||||
|
||||
|
||||
/**
|
||||
* Contains 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 #logPollingSpeed}).
|
||||
* Highly recommended to keep enabled, or
|
||||
* the performance of your application will
|
||||
* very likely suffer.
|
||||
* If enabled, will makes the {@link Logger} work asynchronous,
|
||||
* in a separate platform thread. Don't disable unless you want
|
||||
* your application to run <b>extremely</b> slowly.
|
||||
*
|
||||
* @see #logPollingSpeed
|
||||
* @see Thread
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* 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.
|
||||
* Gets the value for {@link #optimizeLogging}.
|
||||
*
|
||||
* @return log asynchronously?
|
||||
* @see #getLogPollingSpeed()
|
||||
* @return variable value
|
||||
* @see #optimizeLogging
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private boolean optimizeLogging;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* If enabled, will make all events asynchronous,
|
||||
* in separate virtual threads. Don't disable unless you
|
||||
* want your application to run slower.
|
||||
*
|
||||
* @see VirtualThread
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* 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.
|
||||
* Gets the value for {@link #optimizeEvents}.
|
||||
*
|
||||
* @return emit events asynchronously?
|
||||
* @return variable value
|
||||
* @see #optimizeEvents
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private boolean optimizeEvents;
|
||||
|
||||
|
||||
/**
|
||||
* Contains 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>
|
||||
* Contains which logger levels are allowed
|
||||
* by setting the minimum logger level.
|
||||
*
|
||||
* @see Logger
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* 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>
|
||||
* Gets the value for {@link #logLevel}.
|
||||
*
|
||||
* @return minimum allowed log level
|
||||
* @return variable value
|
||||
* @see #logLevel
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private LogLevel logLevel;
|
||||
|
@ -293,118 +226,75 @@ public final class EngineConfiguration extends Configuration {
|
|||
* <li><code>lineNumber</code></li>
|
||||
* </ul>
|
||||
*
|
||||
* @see Logger
|
||||
* @since v1-alpha8
|
||||
* -- GETTER --
|
||||
* 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>
|
||||
* Gets the value for {@link #logFeatures}
|
||||
*
|
||||
* @return optional features to enable
|
||||
* @return variable value
|
||||
* @see #logFeatures
|
||||
* @since v1-alpha8
|
||||
*/
|
||||
private Set<@NotNull String> logFeatures;
|
||||
|
||||
/**
|
||||
* Contains how fast the logging thread will
|
||||
* poll for queued messages in milliseconds.
|
||||
* This also causes messages to be buffered.
|
||||
* poll for queued messages. 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.
|
||||
* 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.
|
||||
*
|
||||
* @see #optimizeLogging
|
||||
* @since v1-alpha4
|
||||
* -- GETTER --
|
||||
* 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.
|
||||
* Gets the value for {@link #logPollingSpeed}.
|
||||
*
|
||||
* @return logging thread polling speed in milliseconds
|
||||
* @see #isOptimizeLogging()
|
||||
* @return variable value
|
||||
* @see #logPollingSpeed
|
||||
* @since v1-alpha4
|
||||
*/
|
||||
private int logPollingSpeed;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* If enabled, will force sos!engine's logging infrastructure to use
|
||||
* <a href="https://www.man7.org/linux/man-pages/man3/stderr.3.html">the standard output</a>
|
||||
* instead of <a href="https://www.man7.org/linux/man-pages/man3/stderr.3.html">the standard error</a>
|
||||
* for logging the {@code ERROR} and {@code CRASH} log levels.
|
||||
*
|
||||
* @see <a href="https://man7.org/linux/man-pages/man3/stderr.3.html">man page about standard streams</a>
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* 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.
|
||||
* Gets the value for {@link #logForceStandardOutput}.
|
||||
*
|
||||
* @return force use stdout?
|
||||
* @see <a href="https://man7.org/linux/man-pages/man3/stderr.3.html">man page about standard streams</a>
|
||||
* @return variable value
|
||||
* @see #logForceStandardOutput
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private boolean logForceStandardOutput;
|
||||
|
||||
|
||||
/**
|
||||
* Contains if to truncate the full path
|
||||
* of a class when invoking using their
|
||||
* {@link #toString()} method.
|
||||
* Will truncate the path of types when using
|
||||
* their {@code 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
|
||||
* Here's an example: Lets say that you
|
||||
* have a {@link Vec2f} and to convert it
|
||||
* to a String, which you can do with
|
||||
* {@link Vec2f#toString()}. With this flag
|
||||
* disabled it would return
|
||||
* {@code de.staropensource.engine.base.types.vectors.}{@link Vec2i}{@code (x=64 y=64)},
|
||||
* with it however it would just return
|
||||
* {@link Vec2i}{@code (x=64 y=64)},
|
||||
* which is much smaller.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
* -- GETTER --
|
||||
* 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.
|
||||
* Gets the value for {@link #hideFullTypePath}.
|
||||
*
|
||||
* @return truncate class paths?
|
||||
* @return variable value
|
||||
* @see #hideFullTypePath
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private boolean hideFullTypePath;
|
||||
|
|
|
@ -20,11 +20,11 @@
|
|||
package de.staropensource.engine.base;
|
||||
|
||||
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.ShutdownHandler;
|
||||
import de.staropensource.engine.base.implementable.helper.EventHelper;
|
||||
import de.staropensource.engine.base.logging.Logger;
|
||||
import de.staropensource.engine.base.type.EventPriority;
|
||||
import de.staropensource.engine.base.type.InternalAccessArea;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -77,7 +77,7 @@ public final class EngineInternals {
|
|||
* use case and application.
|
||||
*
|
||||
* @see EventHelper#registerEvent(Class, EventListenerCode)
|
||||
* @see EventHelper#registerEvent(Class, EventListenerCode, Event.Priority)
|
||||
* @see EventHelper#registerEvent(Class, EventListenerCode, EventPriority)
|
||||
* @since v1-alpha5
|
||||
*/
|
||||
private boolean reflectiveClasspathScanning = true;
|
||||
|
@ -191,7 +191,7 @@ public final class EngineInternals {
|
|||
* @return reflective classpath scanning flag state
|
||||
* @throws IllegalAccessException when restricted ({@link InternalAccessArea#REFLECTIVE_CLASSPATH_SCANNING_GET})
|
||||
* @see EventHelper#registerEvent(Class, EventListenerCode)
|
||||
* @see EventHelper#registerEvent(Class, EventListenerCode, Event.Priority)
|
||||
* @see EventHelper#registerEvent(Class, EventListenerCode, EventPriority)
|
||||
* @since v1-alpha5
|
||||
*/
|
||||
public boolean getReflectiveClasspathScanning() throws IllegalAccessException {
|
||||
|
@ -216,7 +216,7 @@ public final class EngineInternals {
|
|||
* @param reflectiveClasspathScanning new reflective classpath scanning
|
||||
* @throws IllegalAccessException when restricted ({@link InternalAccessArea#REFLECTIVE_CLASSPATH_SCANNING_OVERRIDE})
|
||||
* @see EventHelper#registerEvent(Class, EventListenerCode)
|
||||
* @see EventHelper#registerEvent(Class, EventListenerCode, Event.Priority)
|
||||
* @see EventHelper#registerEvent(Class, EventListenerCode, EventPriority)
|
||||
* @since v1-alpha5
|
||||
*/
|
||||
public void overrideReflectiveClasspathScanning(boolean reflectiveClasspathScanning) throws IllegalAccessException {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package de.staropensource.engine.base.annotation;
|
||||
|
||||
import de.staropensource.engine.base.implementable.Event;
|
||||
import de.staropensource.engine.base.type.EventPriority;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
@ -47,8 +48,8 @@ public @interface EventListener {
|
|||
* Specifies the priority of the event.
|
||||
*
|
||||
* @return event priority
|
||||
* @see Event.Priority
|
||||
* @see EventPriority
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
@NotNull Event.Priority priority() default Event.Priority.DEFAULT;
|
||||
@NotNull EventPriority priority() default EventPriority.DEFAULT;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
package de.staropensource.engine.base.exception.reflection;
|
||||
|
||||
import de.staropensource.engine.base.type.reflection.ClassType;
|
||||
import de.staropensource.engine.base.utility.misc.ListFormatter;
|
||||
import de.staropensource.engine.base.utility.ListFormatter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
package de.staropensource.engine.base.implementable;
|
||||
|
||||
import de.staropensource.engine.base.annotation.EventListener;
|
||||
import de.staropensource.engine.base.implementable.helper.EventHelper;
|
||||
|
||||
/**
|
||||
|
@ -35,76 +34,4 @@ public interface Event {
|
|||
* @since v1-alpha0
|
||||
*/
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package de.staropensource.engine.base.implementable;
|
||||
|
||||
import de.staropensource.engine.base.implementable.helper.EventHelper;
|
||||
import de.staropensource.engine.base.type.EventPriority;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
|
@ -38,7 +39,7 @@ public abstract class EventListenerCode {
|
|||
*
|
||||
* @since v1-alpha5
|
||||
*/
|
||||
public @NotNull Event.Priority priority = Event.Priority.DEFAULT;
|
||||
public @NotNull EventPriority priority = EventPriority.DEFAULT;
|
||||
|
||||
/**
|
||||
* Creates and initializes an instance of this abstract class.
|
||||
|
|
|
@ -32,7 +32,8 @@ import de.staropensource.engine.base.implementable.EventListenerCode;
|
|||
import de.staropensource.engine.base.internal.implementation.EventListenerMethod;
|
||||
|
||||
import de.staropensource.engine.base.logging.Logger;
|
||||
import de.staropensource.engine.base.utility.misc.ListFormatter;
|
||||
import de.staropensource.engine.base.type.EventPriority;
|
||||
import de.staropensource.engine.base.utility.ListFormatter;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -77,7 +78,7 @@ public final class EventHelper {
|
|||
* @see EngineInternals#getReflectiveClasspathScanning()
|
||||
* @since v1-alpha5
|
||||
*/
|
||||
public static synchronized void registerEvent(@NotNull Class<? extends Event> event, @NotNull EventListenerCode eventListener, @NotNull Event.Priority priority) {
|
||||
public static synchronized void registerEvent(@NotNull Class<? extends Event> event, @NotNull EventListenerCode eventListener, @NotNull EventPriority priority) {
|
||||
if (EngineInternals.getInstance().getReflectiveClasspathScanning())
|
||||
return;
|
||||
|
||||
|
@ -111,7 +112,7 @@ public final class EventHelper {
|
|||
* @since v1-alpha5
|
||||
*/
|
||||
public static void registerEvent(@NotNull Class<? extends Event> event, @NotNull EventListenerCode eventListener) {
|
||||
registerEvent(event, eventListener, Event.Priority.DEFAULT);
|
||||
registerEvent(event, eventListener, EventPriority.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,7 +22,7 @@ package de.staropensource.engine.base.implementation.versioning;
|
|||
import de.staropensource.engine.base.implementable.VersioningSystem;
|
||||
import de.staropensource.engine.base.exception.versioning.IncompatibleVersioningSystemException;
|
||||
import de.staropensource.engine.base.exception.versioning.InvalidVersionStringException;
|
||||
import de.staropensource.engine.base.utility.misc.StringUtil;
|
||||
import de.staropensource.engine.base.utility.Miscellaneous;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
@ -98,7 +98,7 @@ public final class FourNumberVersioningSystem implements VersioningSystem {
|
|||
*/
|
||||
public FourNumberVersioningSystem(@NotNull String versionString) throws InvalidVersionStringException {
|
||||
String[] separatorList = new String[]{ ".", "-" };
|
||||
String separator = StringUtil.getSeparatorRequired(versionString, separatorList, 3);
|
||||
String separator = Miscellaneous.getSeparator(versionString, separatorList, 3);
|
||||
|
||||
// Escape separator or throw error if invalid
|
||||
switch (separator) {
|
||||
|
|
|
@ -22,7 +22,7 @@ package de.staropensource.engine.base.implementation.versioning;
|
|||
import de.staropensource.engine.base.implementable.VersioningSystem;
|
||||
import de.staropensource.engine.base.exception.versioning.IncompatibleVersioningSystemException;
|
||||
import de.staropensource.engine.base.exception.versioning.InvalidVersionStringException;
|
||||
import de.staropensource.engine.base.utility.misc.StringUtil;
|
||||
import de.staropensource.engine.base.utility.Miscellaneous;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -117,7 +117,7 @@ public final class SemanticVersioningSystem implements VersioningSystem {
|
|||
*/
|
||||
public SemanticVersioningSystem(@NotNull String versionString) throws InvalidVersionStringException {
|
||||
String[] separatorList = new String[]{ "." };
|
||||
String separator = StringUtil.getSeparatorRequired(versionString, separatorList, 2);
|
||||
String separator = Miscellaneous.getSeparator(versionString, separatorList, 2);
|
||||
|
||||
// Escape separator or throw error if invalid
|
||||
switch (separator) {
|
||||
|
|
|
@ -22,7 +22,7 @@ package de.staropensource.engine.base.implementation.versioning;
|
|||
import de.staropensource.engine.base.implementable.VersioningSystem;
|
||||
import de.staropensource.engine.base.exception.versioning.IncompatibleVersioningSystemException;
|
||||
import de.staropensource.engine.base.exception.versioning.InvalidVersionStringException;
|
||||
import de.staropensource.engine.base.utility.misc.StringUtil;
|
||||
import de.staropensource.engine.base.utility.Miscellaneous;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
@ -86,7 +86,7 @@ public final class ThreeNumberVersioningSystem implements VersioningSystem {
|
|||
*/
|
||||
public ThreeNumberVersioningSystem(@NotNull String versionString) throws InvalidVersionStringException {
|
||||
String[] separatorList = new String[]{ ".", "-" };
|
||||
String separator = StringUtil.getSeparatorRequired(versionString, separatorList, 2);
|
||||
String separator = Miscellaneous.getSeparator(versionString, separatorList, 2);
|
||||
|
||||
// Escape separator or throw error if invalid
|
||||
switch (separator) {
|
||||
|
|
|
@ -22,7 +22,7 @@ package de.staropensource.engine.base.implementation.versioning;
|
|||
import de.staropensource.engine.base.implementable.VersioningSystem;
|
||||
import de.staropensource.engine.base.exception.versioning.IncompatibleVersioningSystemException;
|
||||
import de.staropensource.engine.base.exception.versioning.InvalidVersionStringException;
|
||||
import de.staropensource.engine.base.utility.misc.StringUtil;
|
||||
import de.staropensource.engine.base.utility.Miscellaneous;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
@ -74,7 +74,7 @@ public final class TwoNumberVersioningSystem implements VersioningSystem {
|
|||
*/
|
||||
public TwoNumberVersioningSystem(@NotNull String versionString) throws InvalidVersionStringException {
|
||||
String[] separatorList = new String[]{ ".", "-" };
|
||||
String separator = StringUtil.getSeparatorRequired(versionString, separatorList, 1);
|
||||
String separator = Miscellaneous.getSeparator(versionString, separatorList, 1);
|
||||
|
||||
// Escape separator or throw error if invalid
|
||||
switch (separator) {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
package de.staropensource.engine.base.internal.implementation.placeholder;
|
||||
|
||||
import de.staropensource.engine.base.implementable.Placeholder;
|
||||
import de.staropensource.engine.base.utility.misc.NumberUtil;
|
||||
import de.staropensource.engine.base.utility.Math;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
@ -43,6 +43,6 @@ public final class DateDay implements Placeholder {
|
|||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public @NotNull String replace(@NotNull String text) {
|
||||
return text.replace("%date_day%", NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.DAY_OF_MONTH), 2));
|
||||
return text.replace("%date_day%", Math.padNumbers(Calendar.getInstance().get(Calendar.DAY_OF_MONTH), 2));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
package de.staropensource.engine.base.internal.implementation.placeholder;
|
||||
|
||||
import de.staropensource.engine.base.implementable.Placeholder;
|
||||
import de.staropensource.engine.base.utility.misc.NumberUtil;
|
||||
import de.staropensource.engine.base.utility.Math;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
@ -43,6 +43,6 @@ public final class DateMonth implements Placeholder {
|
|||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public @NotNull String replace(@NotNull String text) {
|
||||
return text.replace("%date_month%", NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.MONTH), 2));
|
||||
return text.replace("%date_month%", Math.padNumbers(Calendar.getInstance().get(Calendar.MONTH), 2));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
package de.staropensource.engine.base.internal.implementation.placeholder;
|
||||
|
||||
import de.staropensource.engine.base.implementable.Placeholder;
|
||||
import de.staropensource.engine.base.utility.misc.NumberUtil;
|
||||
import de.staropensource.engine.base.utility.Math;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
@ -43,6 +43,6 @@ public final class DateYear implements Placeholder {
|
|||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public @NotNull String replace(@NotNull String text) {
|
||||
return text.replace("%date_year%", NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.YEAR), 4));
|
||||
return text.replace("%date_year%", Math.padNumbers(Calendar.getInstance().get(Calendar.YEAR), 4));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
package de.staropensource.engine.base.internal.implementation.placeholder;
|
||||
|
||||
import de.staropensource.engine.base.implementable.Placeholder;
|
||||
import de.staropensource.engine.base.utility.misc.NumberUtil;
|
||||
import de.staropensource.engine.base.utility.Math;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
|
@ -42,6 +42,6 @@ public final class TimeEpoch implements Placeholder {
|
|||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public @NotNull String replace(@NotNull String text) {
|
||||
return text.replace("%time_epoch%", NumberUtil.padNumbers(System.currentTimeMillis(), String.valueOf(Long.MAX_VALUE).length()));
|
||||
return text.replace("%time_epoch%", Math.padNumbers(System.currentTimeMillis(), String.valueOf(Long.MAX_VALUE).length()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
package de.staropensource.engine.base.internal.implementation.placeholder;
|
||||
|
||||
import de.staropensource.engine.base.implementable.Placeholder;
|
||||
import de.staropensource.engine.base.utility.misc.NumberUtil;
|
||||
import de.staropensource.engine.base.utility.Math;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
@ -43,6 +43,6 @@ public final class TimeHour implements Placeholder {
|
|||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public @NotNull String replace(@NotNull String text) {
|
||||
return text.replace("%time_hour%", NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.HOUR_OF_DAY), 2));
|
||||
return text.replace("%time_hour%", Math.padNumbers(Calendar.getInstance().get(Calendar.HOUR_OF_DAY), 2));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
package de.staropensource.engine.base.internal.implementation.placeholder;
|
||||
|
||||
import de.staropensource.engine.base.implementable.Placeholder;
|
||||
import de.staropensource.engine.base.utility.misc.NumberUtil;
|
||||
import de.staropensource.engine.base.utility.Math;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
@ -43,6 +43,6 @@ public final class TimeMinute implements Placeholder {
|
|||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public @NotNull String replace(@NotNull String text) {
|
||||
return text.replace("%time_minute%", NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.MINUTE), 2));
|
||||
return text.replace("%time_minute%", Math.padNumbers(Calendar.getInstance().get(Calendar.MINUTE), 2));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
package de.staropensource.engine.base.internal.implementation.placeholder;
|
||||
|
||||
import de.staropensource.engine.base.implementable.Placeholder;
|
||||
import de.staropensource.engine.base.utility.misc.NumberUtil;
|
||||
import de.staropensource.engine.base.utility.Math;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
@ -43,6 +43,6 @@ public final class TimeSecond implements Placeholder {
|
|||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public @NotNull String replace(@NotNull String text) {
|
||||
return text.replace("%time_second%", NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.SECOND), 2));
|
||||
return text.replace("%time_second%", Math.padNumbers(Calendar.getInstance().get(Calendar.SECOND), 2));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,12 +19,15 @@
|
|||
|
||||
package de.staropensource.engine.base.logging;
|
||||
|
||||
import de.staropensource.engine.base.EngineConfiguration;
|
||||
import de.staropensource.engine.base.implementable.LoggingAdapter;
|
||||
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.Filterer;
|
||||
import de.staropensource.engine.base.logging.backend.Processor;
|
||||
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 lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
@ -32,6 +35,8 @@ import org.intellij.lang.annotations.RegExp;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The frontend class for sos!engine's logging system.
|
||||
*
|
||||
|
|
|
@ -24,8 +24,8 @@ import de.staropensource.engine.base.EngineConfiguration;
|
|||
import de.staropensource.engine.base.EngineInternals;
|
||||
import de.staropensource.engine.base.logging.Logger;
|
||||
import de.staropensource.engine.base.type.logging.LogLevel;
|
||||
import de.staropensource.engine.base.utility.misc.NumberUtil;
|
||||
import de.staropensource.engine.base.utility.misc.Miscellaneous;
|
||||
import de.staropensource.engine.base.utility.Math;
|
||||
import de.staropensource.engine.base.utility.Miscellaneous;
|
||||
import de.staropensource.engine.base.utility.information.EngineInformation;
|
||||
import de.staropensource.engine.base.utility.information.JvmInformation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -107,13 +107,13 @@ public final class CrashHandler {
|
|||
output
|
||||
.append("\nCaused by:")
|
||||
.append("\nNo throwable has been passed.");
|
||||
else {
|
||||
|
||||
else
|
||||
output
|
||||
.append("\n")
|
||||
.append(Miscellaneous.stacktraceAsStringRecursive(throwable, true, true))
|
||||
.append(Miscellaneous.getStackTraceHeader(throwable))
|
||||
.append("\n")
|
||||
.append(Miscellaneous.getStackTraceAsString(throwable, true))
|
||||
.append("\n");
|
||||
}
|
||||
|
||||
output.append("\nMessage: \n")
|
||||
.append(message)
|
||||
|
@ -123,23 +123,23 @@ public final class CrashHandler {
|
|||
output
|
||||
.append("---- Environment ----")
|
||||
.append("\nTime and date: ")
|
||||
.append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.DAY_OF_MONTH), 2))
|
||||
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.DAY_OF_MONTH), 2))
|
||||
.append(".")
|
||||
.append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.MONTH), 2))
|
||||
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.MONTH), 2))
|
||||
.append(".")
|
||||
.append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.YEAR), 4))
|
||||
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.YEAR), 4))
|
||||
.append(" ")
|
||||
.append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.HOUR_OF_DAY), 2))
|
||||
.append(de.staropensource.engine.base.utility.Math.padNumbers(Calendar.getInstance().get(Calendar.HOUR_OF_DAY), 2))
|
||||
.append(":")
|
||||
.append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.MINUTE), 2))
|
||||
.append(de.staropensource.engine.base.utility.Math.padNumbers(Calendar.getInstance().get(Calendar.MINUTE), 2))
|
||||
.append(":")
|
||||
.append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.SECOND), 2))
|
||||
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.SECOND), 2))
|
||||
.append(" [")
|
||||
.append(TimeZone.getDefault().getDisplayName(false, TimeZone.SHORT, Locale.US))
|
||||
.append("]")
|
||||
|
||||
.append("\nUNIX Epoch: ")
|
||||
.append(NumberUtil.padNumbers(System.currentTimeMillis(), String.valueOf(Long.MAX_VALUE).length()))
|
||||
.append(Math.padNumbers(System.currentTimeMillis(), String.valueOf(Long.MAX_VALUE).length()))
|
||||
|
||||
.append("\nOperating system: ")
|
||||
.append(System.getProperty("os.name"))
|
||||
|
@ -293,7 +293,7 @@ public final class CrashHandler {
|
|||
.append(thread.isDaemon())
|
||||
.append("):")
|
||||
.append("\n")
|
||||
.append(Miscellaneous.stacktraceAsString(stacktraces.get(thread), false))
|
||||
.append(Miscellaneous.getStackTraceAsString(stacktraces.get(thread), false))
|
||||
.append("\n");
|
||||
}
|
||||
output.append("\n");
|
||||
|
|
|
@ -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.backend.async.LoggingQueue;
|
||||
import de.staropensource.engine.base.type.logging.LogLevel;
|
||||
import de.staropensource.engine.base.utility.misc.NumberUtil;
|
||||
import de.staropensource.engine.base.utility.Math;
|
||||
import de.staropensource.engine.base.utility.PlaceholderEngine;
|
||||
import de.staropensource.engine.base.utility.information.JvmInformation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -213,11 +213,11 @@ public final class Processor {
|
|||
private static void time(@NotNull StringBuilder builder) {
|
||||
if (isFeatureEnabled("time"))
|
||||
builder
|
||||
.append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.HOUR_OF_DAY), 2))
|
||||
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.HOUR_OF_DAY), 2))
|
||||
.append(":")
|
||||
.append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.MINUTE), 2))
|
||||
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.MINUTE), 2))
|
||||
.append(":")
|
||||
.append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.SECOND), 2));
|
||||
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.SECOND), 2));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -229,11 +229,11 @@ public final class Processor {
|
|||
private static void date(@NotNull StringBuilder builder) {
|
||||
if (isFeatureEnabled("date"))
|
||||
builder
|
||||
.append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.DAY_OF_MONTH), 2))
|
||||
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.DAY_OF_MONTH), 2))
|
||||
.append(".")
|
||||
.append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.MONTH), 2))
|
||||
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.MONTH), 2))
|
||||
.append(".")
|
||||
.append(NumberUtil.padNumbers(Calendar.getInstance().get(Calendar.YEAR), 4));
|
||||
.append(Math.padNumbers(Calendar.getInstance().get(Calendar.YEAR), 4));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,6 +21,7 @@ package de.staropensource.engine.base.logging.backend.async;
|
|||
|
||||
import de.staropensource.engine.base.internal.type.QueuedLogCall;
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
@ -66,8 +67,8 @@ public final class LoggingQueue {
|
|||
* @since v1-alpha8
|
||||
*/
|
||||
public static void flush() {
|
||||
// Get copy of and clear the queue
|
||||
List<@NotNull QueuedLogCall> queue = new ArrayList<>(LoggingQueue.queue);
|
||||
// Get copy of and clear queue
|
||||
List<@NotNull QueuedLogCall> queue = new ImmutableArrayList<>(LoggingQueue.queue);
|
||||
LoggingQueue.queue.clear();
|
||||
|
||||
for (QueuedLogCall queuedCall : queue)
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
package de.staropensource.engine.base.type;
|
||||
|
||||
import de.staropensource.engine.base.EngineConfiguration;
|
||||
import de.staropensource.engine.base.utility.misc.NumberUtil;
|
||||
import de.staropensource.engine.base.utility.Math;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.SneakyThrows;
|
||||
|
@ -42,7 +42,7 @@ import java.util.Locale;
|
|||
@Getter
|
||||
@Setter
|
||||
@SuppressWarnings({ "JavadocDeclaration" })
|
||||
public class Color {
|
||||
public final class Color {
|
||||
/**
|
||||
* Contains the red color value.
|
||||
*
|
||||
|
@ -118,10 +118,10 @@ public class Color {
|
|||
* @since v1-alpha6
|
||||
*/
|
||||
private Color(int red, int green, int blue, int alpha) {
|
||||
this.red = NumberUtil.limitNumber(0, 255, red);
|
||||
this.green = NumberUtil.limitNumber(0, 255, green);
|
||||
this.blue = NumberUtil.limitNumber(0, 255, blue);
|
||||
this.alpha = NumberUtil.limitNumber(0, 255, alpha);
|
||||
this.red = Math.boundNumber(0, 255, red);
|
||||
this.green = Math.boundNumber(0, 255, green);
|
||||
this.blue = Math.boundNumber(0, 255, blue);
|
||||
this.alpha = Math.boundNumber(0, 255, alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Represents various file types.
|
||||
*
|
||||
* @since v1-alpha8
|
||||
*/
|
||||
public enum FileType {
|
||||
/**
|
||||
* 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
|
||||
}
|
|
@ -29,32 +29,32 @@ import org.jetbrains.annotations.NotNull;
|
|||
*/
|
||||
public enum Tristate {
|
||||
/**
|
||||
* Defines an unset state.
|
||||
* An unset tristate.
|
||||
*
|
||||
* @since v1-alpha1
|
||||
*/
|
||||
UNSET,
|
||||
|
||||
/**
|
||||
* Defines a true state.
|
||||
* A true tristate.
|
||||
*
|
||||
* @since v1-alpha1
|
||||
*/
|
||||
TRUE,
|
||||
|
||||
/**
|
||||
* Defines a false state.
|
||||
* A false tristate.
|
||||
*
|
||||
* @since v1-alpha1
|
||||
*/
|
||||
FALSE;
|
||||
|
||||
/**
|
||||
* Converts the specified {@link Boolean} into a {@link Tristate}.
|
||||
* Converts the {@link Boolean} into a {@link Tristate}.
|
||||
*
|
||||
* @param bool boolean to convert
|
||||
* @return {@link Tristate} representation of the specified boolean
|
||||
* @since v1-alpha9
|
||||
* @return tristated boolean
|
||||
* @since v1-alpha5
|
||||
*/
|
||||
public static @NotNull Tristate toTristate(boolean bool) {
|
||||
if (bool) return Tristate.TRUE;
|
||||
|
@ -62,28 +62,12 @@ public enum Tristate {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
* Converts the {@link Tristate} into a {@link Boolean}.
|
||||
* Make sure to check for {@link #UNSET} first.
|
||||
*
|
||||
* @return trimmed boolean representation of this {@link Tristate}
|
||||
* @throws TristateConversionException on encountering {@link #UNSET}
|
||||
* @since v1-alpha9
|
||||
* @return booleanized {@link Tristate}
|
||||
* @throws TristateConversionException when encountering {@link #UNSET}
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public boolean toBoolean() {
|
||||
return switch (this) {
|
||||
|
@ -92,19 +76,4 @@ public enum Tristate {
|
|||
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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,7 @@ package de.staropensource.engine.base.type;
|
|||
import de.staropensource.engine.base.implementation.versioning.StarOpenSourceVersioningSystem;
|
||||
|
||||
/**
|
||||
* Provides all available version types as specified
|
||||
* by the StarOpenSource Versioning System v2.
|
||||
* Provides all available version types specified in the StarOpenSource Versioning System v2.
|
||||
*
|
||||
* @see StarOpenSourceVersioningSystem
|
||||
* @since v1-alpha0
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* 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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* 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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* 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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* 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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* 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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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;
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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
|
||||
}
|
|
@ -22,7 +22,7 @@ package de.staropensource.engine.base.utility;
|
|||
import de.staropensource.engine.base.Engine;
|
||||
import de.staropensource.engine.base.logging.Logger;
|
||||
import de.staropensource.engine.base.type.EngineState;
|
||||
import de.staropensource.engine.base.utility.misc.Miscellaneous;
|
||||
import de.staropensource.engine.base.type.FileType;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -190,7 +190,7 @@ public final class FileAccess {
|
|||
if (Files.exists(path))
|
||||
Logger.error("Deleting file or directory \"" + path + "\" failed");
|
||||
} catch (Exception exception) {
|
||||
Logger.error("File or directory \"" + path + "\" could not be deleted\n" + Miscellaneous.throwableHeader(exception) + "\n" + Miscellaneous.stacktraceAsString(exception, true));
|
||||
Logger.error("File or directory \"" + path + "\" could not be deleted\n" + Miscellaneous.getStackTraceHeader(exception) + "\n" + Miscellaneous.getStackTraceAsString(exception, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -267,15 +267,15 @@ public final class FileAccess {
|
|||
* @return file type
|
||||
* @since v1-alpha8
|
||||
*/
|
||||
public @NotNull FileAccess.Type getType() {
|
||||
public @NotNull FileType getType() {
|
||||
if (!exists())
|
||||
return Type.VOID;
|
||||
return FileType.VOID;
|
||||
else if (Files.isRegularFile(path))
|
||||
return Type.FILE;
|
||||
return FileType.FILE;
|
||||
else if (Files.isDirectory(path))
|
||||
return Type.DIRECTORY;
|
||||
return FileType.DIRECTORY;
|
||||
else
|
||||
return Type.UNKNOWN;
|
||||
return FileType.UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -309,7 +309,7 @@ public final class FileAccess {
|
|||
* @since v1-alpha8
|
||||
*/
|
||||
public @NotNull String @NotNull [] listContents() throws UnsupportedOperationException, IOException {
|
||||
if (getType() != Type.DIRECTORY)
|
||||
if (getType() != FileType.DIRECTORY)
|
||||
throw new UnsupportedOperationException("The file \"" + path + "\" is not a directory");
|
||||
|
||||
String[] list = file.list();
|
||||
|
@ -661,7 +661,7 @@ public final class FileAccess {
|
|||
* Returns the contents of this file.
|
||||
* <p>
|
||||
* Returns an empty array if this file
|
||||
* is not of type {@link Type#FILE}.
|
||||
* is not of type {@link FileType#FILE}.
|
||||
*
|
||||
* @return file contents in bytes
|
||||
* @throws IOException on an IO error
|
||||
|
@ -669,7 +669,7 @@ public final class FileAccess {
|
|||
* @since v1-alpha8
|
||||
*/
|
||||
public byte @NotNull [] readBytes() throws IOException, OutOfMemoryError {
|
||||
if (getType() != Type.FILE)
|
||||
if (getType() != FileType.FILE)
|
||||
return new byte[0];
|
||||
|
||||
Logger.diag("Reading file \"" + path + "\" (bytes)");
|
||||
|
@ -680,7 +680,7 @@ public final class FileAccess {
|
|||
* Returns the contents of this file.
|
||||
* <p>
|
||||
* Returns an empty list if this file
|
||||
* is not of type {@link Type#FILE}.
|
||||
* is not of type {@link FileType#FILE}.
|
||||
*
|
||||
* @return file contents in bytes
|
||||
* @throws IOException on an IO error
|
||||
|
@ -688,7 +688,7 @@ public final class FileAccess {
|
|||
* @since v1-alpha8
|
||||
*/
|
||||
public @NotNull List<@NotNull String> readLines() throws IOException, OutOfMemoryError {
|
||||
if (getType() != Type.FILE)
|
||||
if (getType() != FileType.FILE)
|
||||
return new ArrayList<>();
|
||||
|
||||
Logger.diag("Reading file \"" + path + "\" (lines)");
|
||||
|
@ -701,7 +701,7 @@ public final class FileAccess {
|
|||
* {@link StandardCharsets#UTF_8} character set.
|
||||
* <p>
|
||||
* Returns an empty string if this file
|
||||
* is not of type {@link Type#FILE}.
|
||||
* is not of type {@link FileType#FILE}.
|
||||
*
|
||||
* @return file contents as a string
|
||||
* @throws IOException on an IO error
|
||||
|
@ -716,7 +716,7 @@ public final class FileAccess {
|
|||
* Returns the contents of this file.
|
||||
* <p>
|
||||
* Returns an empty string if this file
|
||||
* is not of type {@link Type#FILE}.
|
||||
* is not of type {@link FileType#FILE}.
|
||||
*
|
||||
* @param charset charset to decode the bytes with
|
||||
* @return file contents as a string
|
||||
|
@ -725,7 +725,7 @@ public final class FileAccess {
|
|||
* @since v1-alpha8
|
||||
*/
|
||||
public @NotNull String readContent(@NotNull Charset charset) throws IOException, OutOfMemoryError {
|
||||
if (getType() != Type.FILE)
|
||||
if (getType() != FileType.FILE)
|
||||
return "";
|
||||
|
||||
Logger.diag("Reading file \"" + path + "\" (string)");
|
||||
|
@ -739,15 +739,15 @@ public final class FileAccess {
|
|||
*
|
||||
* @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}
|
||||
* @throws UnsupportedOperationException if the type of this file is neither {@link Type#VOID} or {@link Type#FILE}
|
||||
* @throws UnsupportedOperationException if the type of this file is neither {@link FileType#VOID} or {@link FileType#FILE}
|
||||
* @throws IOException on an IO error
|
||||
* @return this instance
|
||||
*/
|
||||
public @NotNull FileAccess writeBytes(byte @NotNull [] bytes, boolean async) throws UnsupportedOperationException, IOException {
|
||||
if (getType() == Type.VOID)
|
||||
if (getType() == FileType.VOID)
|
||||
createFile();
|
||||
else if (getType() != Type.FILE)
|
||||
throw new UnsupportedOperationException("File \"" + path + "\" is not of type Type.VOID or Type.FILE");
|
||||
else if (getType() != FileType.FILE)
|
||||
throw new UnsupportedOperationException("File \"" + path + "\" is not of type FileType.VOID or FileType.FILE");
|
||||
|
||||
createFile();
|
||||
Logger.diag("Writing file \"" + path + "\" (bytes, " + (async ? "async" : "dsync") + ")");
|
||||
|
@ -762,7 +762,7 @@ public final class FileAccess {
|
|||
*
|
||||
* @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}
|
||||
* @throws UnsupportedOperationException if the type of this file is neither {@link Type#VOID} or {@link Type#FILE}
|
||||
* @throws UnsupportedOperationException if the type of this file is neither {@link FileType#VOID} or {@link FileType#FILE}
|
||||
* @throws IOException on an IO error
|
||||
* @return this instance
|
||||
*/
|
||||
|
@ -776,15 +776,15 @@ public final class FileAccess {
|
|||
* @param string string to write
|
||||
* @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}
|
||||
* @throws UnsupportedOperationException if the type of this file is neither {@link Type#VOID} or {@link Type#FILE}
|
||||
* @throws UnsupportedOperationException if the type of this file is neither {@link FileType#VOID} or {@link FileType#FILE}
|
||||
* @throws IOException on an IO error
|
||||
* @return this instance
|
||||
*/
|
||||
public @NotNull FileAccess writeString(@NotNull String string, @NotNull Charset charset, boolean async) throws UnsupportedOperationException, IOException {
|
||||
if (getType() == Type.VOID)
|
||||
if (getType() == FileType.VOID)
|
||||
createFile();
|
||||
else if (getType() != Type.FILE)
|
||||
throw new UnsupportedOperationException("File \"" + path + "\" is not of type Type.VOID or Type.FILE");
|
||||
else if (getType() != FileType.FILE)
|
||||
throw new UnsupportedOperationException("File \"" + path + "\" is not of type FileType.VOID or FileType.FILE");
|
||||
|
||||
Logger.diag("Writing file \"" + path + "\" (string, " + (async ? "async" : "dsync") + ")");
|
||||
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 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 Type#VOID} or {@link Type#FILE}
|
||||
* @throws UnsupportedOperationException if the type of this file is neither {@link FileType#VOID} or {@link FileType#FILE}
|
||||
* @throws IOException on an IO error
|
||||
* @return this instance
|
||||
*/
|
||||
public @NotNull FileAccess appendBytes(byte @NotNull [] bytes, boolean async) throws UnsupportedOperationException, IOException {
|
||||
if (getType() == Type.VOID)
|
||||
if (getType() == FileType.VOID)
|
||||
createFile();
|
||||
else if (getType() != Type.FILE)
|
||||
throw new UnsupportedOperationException("File \"" + path + "\" is not of type Type.VOID or Type.FILE");
|
||||
else if (getType() != FileType.FILE)
|
||||
throw new UnsupportedOperationException("File \"" + path + "\" is not of type FileType.VOID or FileType.FILE");
|
||||
|
||||
Logger.diag("Appending file \"" + path + "\" (bytes, " + (async ? "async" : "dsync") + ")");
|
||||
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 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 Type#VOID} or {@link Type#FILE}
|
||||
* @throws UnsupportedOperationException if the type of this file is neither {@link FileType#VOID} or {@link FileType#FILE}
|
||||
* @throws IOException on an IO error
|
||||
* @return this instance
|
||||
*/
|
||||
|
@ -834,53 +834,18 @@ public final class FileAccess {
|
|||
* @param string string to append
|
||||
* @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}
|
||||
* @throws UnsupportedOperationException if the type of this file is neither {@link Type#VOID} or {@link Type#FILE}
|
||||
* @throws UnsupportedOperationException if the type of this file is neither {@link FileType#VOID} or {@link FileType#FILE}
|
||||
* @throws IOException on an IO error
|
||||
* @return this instance
|
||||
*/
|
||||
public @NotNull FileAccess appendString(@NotNull String string, @NotNull Charset charset, boolean async) throws UnsupportedOperationException, IOException {
|
||||
if (getType() == Type.VOID)
|
||||
if (getType() == FileType.VOID)
|
||||
createFile();
|
||||
else if (getType() != Type.FILE)
|
||||
throw new UnsupportedOperationException("File \"" + path + "\" is not of type Type.VOID or Type.FILE");
|
||||
else if (getType() != FileType.FILE)
|
||||
throw new UnsupportedOperationException("File \"" + path + "\" is not of type FileType.VOID or FileType.FILE");
|
||||
|
||||
Logger.diag("Appending file \"" + path + "\" (string, " + (async ? "async" : "dsync") + ")");
|
||||
Files.writeString(path, string, charset, StandardOpenOption.APPEND, async ? StandardOpenOption.DSYNC : StandardOpenOption.SYNC);
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,49 +17,43 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.base.utility.misc;
|
||||
package de.staropensource.engine.base.utility;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Converts arrays, arrays and maps to look like
|
||||
* nicely formatted lists (as {@link String}s).
|
||||
* Converts various data types to {@link String}s.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha4
|
||||
*/
|
||||
public final class ListFormatter {
|
||||
/**
|
||||
* Creates and initializes an instance of this class.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha6
|
||||
*/
|
||||
private ListFormatter() {}
|
||||
|
||||
/**
|
||||
* 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}
|
||||
* Converts an array to a {@link String}.
|
||||
*
|
||||
* @param array array to convert
|
||||
* @param itemSeparator string used to separate two items
|
||||
* @param finalSeparator string used to separate the final two items
|
||||
* @param array array to convert
|
||||
* @return formatted string
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha4
|
||||
*/
|
||||
public static @NotNull String formatArray(@NotNull Object @NotNull [] array, @NotNull String itemSeparator, @NotNull String finalSeparator) {
|
||||
public static @NotNull String formatArray(@NotNull Object @NotNull [] array) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
||||
for (int index = 0; index < array.length; index++) {
|
||||
if (!output.isEmpty())
|
||||
if (index == array.length - 1)
|
||||
output.append(finalSeparator);
|
||||
output.append(" & ");
|
||||
else
|
||||
output.append(itemSeparator);
|
||||
output.append(", ");
|
||||
|
||||
output.append(array[index]);
|
||||
}
|
||||
|
@ -68,50 +62,25 @@ public final class ListFormatter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Converts the specified array to a {@link String}.
|
||||
* <p>
|
||||
* This will produce something like this:
|
||||
* {@code element 1, element 2, element 3 & element 4}
|
||||
* Converts a {@link Set} to a {@link String}.
|
||||
*
|
||||
* @param array array to convert
|
||||
* @param set set to convert
|
||||
* @return formatted string
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha4
|
||||
*/
|
||||
public static @NotNull String formatArray(@NotNull Object @NotNull [] array) {
|
||||
return formatArray(array, ", ", " & ");
|
||||
public static @NotNull String formatSet(@NotNull Set<?> set) {
|
||||
return formatArray(set.toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* 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}
|
||||
* Converts a {@link List} to a {@link String}.
|
||||
*
|
||||
* @param collection collection to convert
|
||||
* @param itemSeparator string used to separate two items
|
||||
* @param finalSeparator string used to separate the final two items
|
||||
* @param list list to convert
|
||||
* @return formatted string
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha4
|
||||
*/
|
||||
public static @NotNull String formatCollection(@NotNull Collection<?> collection, @NotNull String itemSeparator, @NotNull String finalSeparator) {
|
||||
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());
|
||||
public static @NotNull String formatList(@NotNull List<?> list) {
|
||||
return formatArray(list.toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -119,7 +88,7 @@ public final class ListFormatter {
|
|||
*
|
||||
* @param map map to convert
|
||||
* @return formatted string
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha4
|
||||
*/
|
||||
public static @NotNull String formatMap(@NotNull Map<?, ?> map) {
|
||||
StringBuilder output = new StringBuilder();
|
|
@ -17,7 +17,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.base.utility.misc;
|
||||
package de.staropensource.engine.base.utility;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
@ -27,36 +27,31 @@ import java.util.LinkedList;
|
|||
/**
|
||||
* Utility class for math operations.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
// All mean and double methods have been sourced
|
||||
// from https://stackoverflow.com/a/4191729, tysm!
|
||||
@SuppressWarnings({ "unused" })
|
||||
public final class NumberUtil {
|
||||
public final class Math {
|
||||
/**
|
||||
* Creates and initializes an instance of this class
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha6
|
||||
*/
|
||||
private NumberUtil() {}
|
||||
private Math() {}
|
||||
|
||||
/**
|
||||
* Adds padding zeros to a number.
|
||||
* <p>
|
||||
* Example:
|
||||
* {@code padNumbers(505L, 5) = "00505"}
|
||||
*
|
||||
* @param number number
|
||||
* @param length length
|
||||
* @return the padded number
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public static @NotNull String padNumbers(long number, int length) {
|
||||
return String.format("%0" + length + "d", number);
|
||||
}
|
||||
|
||||
|
||||
// -----> Number limiting
|
||||
/**
|
||||
* Ensures the integer is inside the
|
||||
* specified bounds. If not, the
|
||||
|
@ -66,10 +61,10 @@ public final class NumberUtil {
|
|||
* @param max maximum value
|
||||
* @param value value
|
||||
* @return number in threshold
|
||||
* @throws IndexOutOfBoundsException if the minimum value is bigger than the maximum value
|
||||
* @since v1-alpha9
|
||||
* @throws IndexOutOfBoundsException when the minimum value is bigger than the maximum value
|
||||
* @since v1-alpha6
|
||||
*/
|
||||
public static int limitNumber(int min, int max, int value) throws IndexOutOfBoundsException {
|
||||
public static int boundNumber(int min, int max, int value) throws IndexOutOfBoundsException {
|
||||
if (min > max)
|
||||
throw new IndexOutOfBoundsException();
|
||||
|
||||
|
@ -90,10 +85,10 @@ public final class NumberUtil {
|
|||
* @param max maximum value
|
||||
* @param value value
|
||||
* @return number in threshold
|
||||
* @throws IndexOutOfBoundsException if the minimum value is bigger than the maximum value
|
||||
* @since v1-alpha9
|
||||
* @throws IndexOutOfBoundsException when the minimum value is bigger than the maximum value
|
||||
* @since v1-alpha6
|
||||
*/
|
||||
public static float limitNumber(float min, float max, float value) throws IndexOutOfBoundsException {
|
||||
public static float boundNumber(float min, float max, float value) throws IndexOutOfBoundsException {
|
||||
if (min > max)
|
||||
throw new IndexOutOfBoundsException();
|
||||
|
||||
|
@ -114,10 +109,10 @@ public final class NumberUtil {
|
|||
* @param max maximum value
|
||||
* @param value value
|
||||
* @return number in threshold
|
||||
* @throws IndexOutOfBoundsException if the minimum value is bigger than the maximum value
|
||||
* @since v1-alpha9
|
||||
* @throws IndexOutOfBoundsException when the minimum value is bigger than the maximum value
|
||||
* @since v1-alpha6
|
||||
*/
|
||||
public static double limitNumber(double min, double max, double value) throws IndexOutOfBoundsException {
|
||||
public static double boundNumber(double min, double max, double value) throws IndexOutOfBoundsException {
|
||||
if (min > max)
|
||||
throw new IndexOutOfBoundsException();
|
||||
|
||||
|
@ -129,16 +124,14 @@ public final class NumberUtil {
|
|||
return value;
|
||||
}
|
||||
|
||||
|
||||
// -----> Means and medians
|
||||
/**
|
||||
* Returns the mean of a collection of numbers.
|
||||
*
|
||||
* @param collection collection of {@code double}s
|
||||
* @return mean
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public static double calculateMeanDouble(@NotNull Collection<@NotNull Double> collection) {
|
||||
public static double getMeanDouble(@NotNull Collection<@NotNull Double> collection) {
|
||||
double sum = 0;
|
||||
|
||||
for (double number : collection)
|
||||
|
@ -152,9 +145,9 @@ public final class NumberUtil {
|
|||
*
|
||||
* @param collection collection of {@code float}s
|
||||
* @return mean
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public static double calculateMeanFloat(@NotNull Collection<@NotNull Float> collection) {
|
||||
public static double getMeanFloat(@NotNull Collection<@NotNull Float> collection) {
|
||||
double sum = 0;
|
||||
|
||||
for (float number : collection)
|
||||
|
@ -168,9 +161,9 @@ public final class NumberUtil {
|
|||
*
|
||||
* @param collection collection of {@code long}s
|
||||
* @return mean
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public static double calculateMeanLong(@NotNull Collection<@NotNull Long> collection) {
|
||||
public static double getMeanLong(@NotNull Collection<@NotNull Long> collection) {
|
||||
double sum = 0;
|
||||
|
||||
for (long number : collection)
|
||||
|
@ -184,9 +177,9 @@ public final class NumberUtil {
|
|||
*
|
||||
* @param collection collection of {@code int}s
|
||||
* @return mean
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public static double calculateMeanInt(@NotNull Collection<@NotNull Integer> collection) {
|
||||
public static double getMeanInt(@NotNull Collection<@NotNull Integer> collection) {
|
||||
double sum = 0;
|
||||
|
||||
for (int number : collection)
|
||||
|
@ -200,9 +193,9 @@ public final class NumberUtil {
|
|||
*
|
||||
* @param list linked list of {@code double}s
|
||||
* @return median
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public static double calculateMedianDouble(@NotNull LinkedList<@NotNull Double> list) {
|
||||
public static double getMedianDouble(@NotNull LinkedList<@NotNull Double> list) {
|
||||
int middle = list.size() / 2;
|
||||
if (list.size() % 2 == 1)
|
||||
return list.get(middle);
|
||||
|
@ -215,9 +208,9 @@ public final class NumberUtil {
|
|||
*
|
||||
* @param list linked list of {@code float}s
|
||||
* @return median
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public static double calculateMedianFloat(@NotNull LinkedList<@NotNull Float> list) {
|
||||
public static double getMedianFloat(@NotNull LinkedList<@NotNull Float> list) {
|
||||
int middle = list.size() / 2;
|
||||
if (list.size() % 2 == 1)
|
||||
return list.get(middle);
|
||||
|
@ -230,9 +223,9 @@ public final class NumberUtil {
|
|||
*
|
||||
* @param list linked list of {@code long}s
|
||||
* @return median
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public static double calculateMedianLong(@NotNull LinkedList<@NotNull Long> list) {
|
||||
public static double getMedianLong(@NotNull LinkedList<@NotNull Long> list) {
|
||||
int middle = list.size() / 2;
|
||||
if (list.size() % 2 == 1)
|
||||
return list.get(middle);
|
||||
|
@ -245,9 +238,9 @@ public final class NumberUtil {
|
|||
*
|
||||
* @param list linked list of {@code int}s
|
||||
* @return median
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public static double calculateMedianInt(@NotNull LinkedList<@NotNull Integer> list) {
|
||||
public static double getMedianInt(@NotNull LinkedList<@NotNull Integer> list) {
|
||||
int middle = list.size() / 2;
|
||||
if (list.size() % 2 == 1)
|
||||
return list.get(middle);
|
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
|
@ -20,11 +20,11 @@
|
|||
package de.staropensource.engine.base.utility.information;
|
||||
|
||||
import de.staropensource.engine.base.logging.Logger;
|
||||
import de.staropensource.engine.base.type.immutable.ImmutableArrayList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryUsage;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -114,7 +114,7 @@ public final class JvmInformation {
|
|||
* @since v1-alpha0
|
||||
*/
|
||||
public static @NotNull List<@NotNull String> getArguments() {
|
||||
return Collections.unmodifiableList(ManagementFactory.getRuntimeMXBean().getInputArguments());
|
||||
return new ImmutableArrayList<>(ManagementFactory.getRuntimeMXBean().getInputArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,77 +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.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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,211 +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.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();
|
||||
}
|
||||
}
|
|
@ -1,85 +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.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;
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
/**
|
||||
* Provides (utility) classes specifically made for one task.
|
||||
*
|
||||
* @see de.staropensource.engine.base.utility.misc.Miscellaneous
|
||||
* @see de.staropensource.engine.base.utility.Miscellaneous
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
package de.staropensource.engine.base.utility;
|
||||
|
|
|
@ -29,11 +29,11 @@ module sosengine.base {
|
|||
exports de.staropensource.engine.base.implementation.logging;
|
||||
exports de.staropensource.engine.base.reflection;
|
||||
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.reflection;
|
||||
exports de.staropensource.engine.base.type.vector;
|
||||
exports de.staropensource.engine.base.utility;
|
||||
exports de.staropensource.engine.base.utility.misc;
|
||||
|
||||
// Reflection access
|
||||
opens de.staropensource.engine.base;
|
||||
|
@ -52,9 +52,9 @@ module sosengine.base {
|
|||
opens de.staropensource.engine.base.implementation.logging;
|
||||
opens de.staropensource.engine.base.reflection;
|
||||
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.reflection;
|
||||
opens de.staropensource.engine.base.type.vector;
|
||||
opens de.staropensource.engine.base.utility;
|
||||
opens de.staropensource.engine.base.utility.misc;
|
||||
}
|
||||
|
|
|
@ -21,9 +21,11 @@ package de.staropensource.engine.base.srctests.utility;
|
|||
|
||||
import de.staropensource.engine.base.EngineConfiguration;
|
||||
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.base.utility.misc.NumberUtil;
|
||||
import de.staropensource.engine.base.utility.misc.Miscellaneous;
|
||||
import de.staropensource.engine.base.utility.Math;
|
||||
import de.staropensource.engine.base.utility.Miscellaneous;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -64,7 +66,7 @@ public class MiscellaneousTest extends TestBase {
|
|||
if (performMethodCalls("testPadNumbers", number, length, expected))
|
||||
return;
|
||||
|
||||
String result = NumberUtil.padNumbers(number, length);
|
||||
String result = Math.padNumbers(number, length);
|
||||
assertEquals(expected, result, "Result \"" + result + "\" does not match expected output \"" + expected + "\"");
|
||||
}
|
||||
|
||||
|
@ -96,7 +98,7 @@ public class MiscellaneousTest extends TestBase {
|
|||
*/
|
||||
@Test
|
||||
@DisplayName("getMapValues")
|
||||
void testSearchForValueInMap() {
|
||||
void testGetMapValues() {
|
||||
if (performMethodCalls("testGetMapValues"))
|
||||
return;
|
||||
|
||||
|
@ -107,13 +109,28 @@ public class MiscellaneousTest extends TestBase {
|
|||
testMap.put("keylast", "this is the last value");
|
||||
testMap.put("keylast2", "this is the last value");
|
||||
|
||||
Set<?> output = Miscellaneous.searchForValueInMap(testMap, "this value exists twice");
|
||||
Set<?> output = Miscellaneous.getMapValues(testMap, "this value exists twice");
|
||||
|
||||
assertTrue(output.contains("keytwo"), "Map key \"keytwo\" 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");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
*/
|
||||
|
|
|
@ -30,7 +30,8 @@ tasks.register("javadocAll", Javadoc) {
|
|||
":base",
|
||||
":ansi",
|
||||
":slf4j-compat",
|
||||
":rendering",
|
||||
":windowing",
|
||||
":windowing:glfw",
|
||||
":notification",
|
||||
]
|
||||
|
||||
|
|
2
dist/branding/current.png
vendored
2
dist/branding/current.png
vendored
|
@ -1 +1 @@
|
|||
icon1-transparent.png
|
||||
icon0.png
|
2
dist/branding/current.xcf
vendored
2
dist/branding/current.xcf
vendored
|
@ -1 +1 @@
|
|||
icon1.xcf
|
||||
icon0.xcf
|
BIN
dist/branding/icon1-rawcog.xcf
vendored
Normal file
BIN
dist/branding/icon1-rawcog.xcf
vendored
Normal file
Binary file not shown.
BIN
dist/branding/icon1-text-black.png
vendored
BIN
dist/branding/icon1-text-black.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 319 KiB |
BIN
dist/branding/icon1-text-brandcolor.png
vendored
BIN
dist/branding/icon1-text-brandcolor.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 369 KiB |
BIN
dist/branding/icon1-text-white.png
vendored
BIN
dist/branding/icon1-text-white.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 332 KiB |
BIN
dist/branding/icon1-text.xcf
vendored
BIN
dist/branding/icon1-text.xcf
vendored
Binary file not shown.
BIN
dist/branding/icon1-transparent.png
vendored
BIN
dist/branding/icon1-transparent.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 164 KiB |
BIN
dist/branding/icon1.png
vendored
BIN
dist/branding/icon1.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 171 KiB |
BIN
dist/branding/icon1.xcf
vendored
BIN
dist/branding/icon1.xcf
vendored
Binary file not shown.
|
@ -78,7 +78,7 @@ This avoids unnecessary bloat, having too many dependencies in your project whil
|
|||
size and memory footprint of your project.
|
||||
|
||||
## Official subsystems
|
||||
Besides the `base` engine, there are two stable subsystem and two experimental subsystems.
|
||||
Besides the `base` engine, there are two stable subsystem and three experimental subsystems.
|
||||
|
||||
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.
|
||||
|
@ -86,7 +86,8 @@ 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
|
||||
- [`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
|
||||
- [`rendering`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/rendering): Provides an API for creating, managing and rendering windows
|
||||
- [`windowing`](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/windowing): Provides abstract APIs for creating and managing windows as well as monitors
|
||||
- [`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
|
||||
|
||||
## API documentation
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
"typecheck": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "3.6.1",
|
||||
"@docusaurus/plugin-client-redirects": "^3.6.1",
|
||||
"@docusaurus/plugin-content-docs": "^3.6.1",
|
||||
"@docusaurus/plugin-sitemap": "^3.6.1",
|
||||
"@docusaurus/preset-classic": "3.6.1",
|
||||
"@docusaurus/core": "3.6.0",
|
||||
"@docusaurus/plugin-client-redirects": "^3.6.0",
|
||||
"@docusaurus/plugin-content-docs": "^3.6.0",
|
||||
"@docusaurus/plugin-sitemap": "^3.6.0",
|
||||
"@docusaurus/preset-classic": "3.6.0",
|
||||
"@mdx-js/react": "^3.0.1",
|
||||
"clsx": "^2.1.0",
|
||||
"prism-react-renderer": "^2.3.1",
|
||||
|
@ -27,9 +27,9 @@
|
|||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.6.1",
|
||||
"@docusaurus/tsconfig": "3.6.1",
|
||||
"@docusaurus/types": "3.6.1",
|
||||
"@docusaurus/module-type-aliases": "3.6.0",
|
||||
"@docusaurus/tsconfig": "3.6.0",
|
||||
"@docusaurus/types": "3.6.0",
|
||||
"@types/node": "^20.12.5",
|
||||
"typescript": "~5.4.4"
|
||||
},
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
versioningCodename=Sugarcookie
|
||||
versioningVersion=1
|
||||
versioningType=alpha
|
||||
versioningTyperelease=9
|
||||
versioningTyperelease=8
|
||||
versioningFork=
|
||||
|
||||
# Java
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
|
||||
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.NotificationState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -49,14 +49,14 @@ public final class NotificationManager {
|
|||
private NotificationManager() {}
|
||||
|
||||
/**
|
||||
* Returns an immutable map containing all
|
||||
* Returns an {@link ImmutableHashMap} containing all
|
||||
* registered notifications and their current states.
|
||||
*
|
||||
* @return map of registered notifications
|
||||
* @since v1-alpha6
|
||||
*/
|
||||
public static @NotNull Map<@NotNull Notification, @NotNull NotificationState> getNotifications() {
|
||||
return Collections.unmodifiableMap(notifications);
|
||||
return new ImmutableHashMap<>(notifications);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,240 +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.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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,365 +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.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; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,384 +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.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,93 +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.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
|
@ -1,76 +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.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,
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
|
@ -17,12 +17,13 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
rootProject.setName("sos!engine")
|
||||
rootProject.setName("sosengine")
|
||||
|
||||
include("base")
|
||||
include("testing")
|
||||
include("ansi")
|
||||
include("slf4j-compat")
|
||||
include("notification")
|
||||
include("rendering")
|
||||
include("windowing")
|
||||
include("windowing:glfw")
|
||||
include("testapp")
|
||||
|
|
|
@ -23,6 +23,7 @@ import de.staropensource.engine.base.Engine;
|
|||
import de.staropensource.engine.base.EngineConfiguration;
|
||||
import de.staropensource.engine.base.logging.Logger;
|
||||
import de.staropensource.engine.base.type.logging.LogLevel;
|
||||
import de.staropensource.engine.base.utility.Miscellaneous;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.event.Level;
|
||||
|
|
|
@ -39,9 +39,10 @@ dependencies {
|
|||
|
||||
// Project
|
||||
implementation(project(":base"))
|
||||
implementation(project(":rendering"))
|
||||
implementation(project(":windowing"))
|
||||
runtimeOnly(project(":ansi"))
|
||||
runtimeOnly(project(":slf4j-compat"))
|
||||
runtimeOnly(project(":windowing:glfw"))
|
||||
}
|
||||
|
||||
// Fix delombok task
|
||||
|
@ -86,9 +87,6 @@ application {
|
|||
// reflective sclasspath scanning is disabled.
|
||||
"-Dsosengine.base.initialIncludeSubsystemClasses=de.staropensource.engine.ansi.AnsiSubsystem,de.staropensource.engine.slf4j_compat.Slf4jCompatSubsystem,de.staropensource.engine.windowing.glfw.GlfwSubsystem",
|
||||
|
||||
// Force rendering platform
|
||||
"-Dsosengine.rendering.initialPlatform=" + (project.hasProperty("renderingPlatform") ? project.property("renderingPlatform") as String : "any"),
|
||||
|
||||
// Force Jansi to write escape sequences
|
||||
"-Djansi.mode=force",
|
||||
]
|
||||
|
@ -132,7 +130,6 @@ tasks.register('runNativeImage', Exec) {
|
|||
"-Dsosengine.base.logForceStandardOutput=true",
|
||||
"-Dsosengine.base.initialForceDisableClasspathScanning=true",
|
||||
"-Dsosengine.base.initialIncludeSubsystemClasses=de.staropensource.engine.ansi.AnsiSubsystem,de.staropensource.engine.slf4j_compat.Slf4jCompatSubsystem,de.staropensource.engine.windowing.glfw.GlfwSubsystem",
|
||||
"-Dsosengine.rendering.initialPlatform=" + (project.hasProperty("renderingPlatform") ? project.property("renderingPlatform") as String : "any"),
|
||||
"-Djansi.mode=force",
|
||||
)
|
||||
executable("build/bin/sosengine-testapp")
|
||||
|
|
|
@ -25,16 +25,18 @@ import de.staropensource.engine.base.implementable.EventListenerCode;
|
|||
import de.staropensource.engine.base.implementable.helper.EventHelper;
|
||||
import de.staropensource.engine.base.logging.Logger;
|
||||
import de.staropensource.engine.base.type.vector.Vec2i;
|
||||
import de.staropensource.engine.rendering.event.InputEvent;
|
||||
import de.staropensource.engine.rendering.renderer.Renderer;
|
||||
import de.staropensource.engine.rendering.type.FrameHandler;
|
||||
import de.staropensource.engine.rendering.type.Window;
|
||||
import de.staropensource.engine.rendering.type.input.Key;
|
||||
import de.staropensource.engine.rendering.type.input.KeyState;
|
||||
import de.staropensource.engine.base.utility.Miscellaneous;
|
||||
import de.staropensource.engine.windowing.WindowingSubsystem;
|
||||
import de.staropensource.engine.windowing.event.InputEvent;
|
||||
import de.staropensource.engine.windowing.implementable.Window;
|
||||
import de.staropensource.engine.windowing.type.input.Key;
|
||||
import de.staropensource.engine.windowing.type.input.KeyState;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* The main class of the sos!engine development application.
|
||||
*
|
||||
|
@ -117,6 +119,10 @@ public final class Main {
|
|||
// Say hello to the world!
|
||||
Logger.info("Hello world!");
|
||||
|
||||
// Choose windowing API to use
|
||||
if (!WindowingSubsystem.getInstance().setApi())
|
||||
Logger.crash("No windowing API is compatible");
|
||||
|
||||
// Create window
|
||||
Window window;
|
||||
try {
|
||||
|
@ -133,28 +139,31 @@ public final class Main {
|
|||
return;
|
||||
}
|
||||
|
||||
if (window == null) {
|
||||
Logger.crash("'window' is null");
|
||||
return;
|
||||
}
|
||||
// Render loop
|
||||
LinkedHashMap<@NotNull Window, @NotNull Throwable> renderLoopFailures = WindowingSubsystem
|
||||
.getInstance()
|
||||
.getApi()
|
||||
.getManagement()
|
||||
.runRenderLoopContinuously(() -> {
|
||||
if (shutdown || window.isClosureRequested())
|
||||
Engine.getInstance().shutdown();
|
||||
});
|
||||
|
||||
// Add frame handlers
|
||||
Renderer.addFrameHandler(new FrameHandler() {
|
||||
@Override
|
||||
public @NotNull FrameHandler.Priority getPriority() {
|
||||
return Priority.DEFAULT;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
if (shutdown || window.isClosureRequested())
|
||||
Engine.getInstance().shutdown();
|
||||
// Print render loop failures
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append("Render loop failed on some windows:\n");
|
||||
|
||||
//window.setPosition(new Vec2i((int) Renderer.getFrameCount() / 10, (int) Renderer.getFrameCount() / 10));
|
||||
}
|
||||
});
|
||||
for (Window windowFailed : renderLoopFailures.keySet())
|
||||
message
|
||||
.append("-> ")
|
||||
.append(window)
|
||||
.append(": ")
|
||||
.append(Miscellaneous.getStackTraceHeader(renderLoopFailures.get(windowFailed)))
|
||||
.append("\n")
|
||||
.append(Miscellaneous.getStackTraceAsString(renderLoopFailures.get(windowFailed), true))
|
||||
.append("\n");
|
||||
|
||||
// Start renderer
|
||||
Renderer.start();
|
||||
Logger.crash(message.toString());
|
||||
} catch (Exception exception) {
|
||||
Logger.crash("Caught throwable in main thread:", exception);
|
||||
}
|
||||
|
|
|
@ -7,5 +7,5 @@
|
|||
open module sosengine.testapp {
|
||||
// Dependencies
|
||||
// -> Engine
|
||||
requires sosengine.rendering;
|
||||
requires sosengine.windowing;
|
||||
}
|
||||
|
|
109
windowing/build.gradle
Normal file
109
windowing/build.gradle
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// Plugins
|
||||
plugins {
|
||||
id("java")
|
||||
id("io.freefair.lombok") version("${pluginLombok}")
|
||||
id("maven-publish")
|
||||
}
|
||||
|
||||
// Dependencies
|
||||
dependencies {
|
||||
// Lombok
|
||||
compileOnly("org.projectlombok:lombok:${dependencyLombok}")
|
||||
annotationProcessor("org.projectlombok:lombok:${dependencyLombok}")
|
||||
|
||||
// JetBrains Annotations
|
||||
compileOnly("org.jetbrains:annotations:${dependencyJetbrainsAnnotations}")
|
||||
|
||||
// Project
|
||||
implementation(project(":base"))
|
||||
}
|
||||
|
||||
// Javadoc configuration
|
||||
javadoc {
|
||||
outputs.upToDateWhen { false } // Force task execution
|
||||
dependsOn(delombok) // Make sure the source is delomboked first
|
||||
|
||||
javadoc {
|
||||
setClasspath(files(project.sourceSets.main.compileClasspath)) // Include dependencies
|
||||
|
||||
options {
|
||||
if (new File(projectDir, "src/main/javadoc/theme.css").exists())
|
||||
stylesheetFile = new File(projectDir, "src/main/javadoc/theme.css") // Theming is cool :3
|
||||
setMemberLevel(JavadocMemberLevel.PUBLIC) // Only display public stuff
|
||||
setOverview("src/main/javadoc/overview.html") // We want a custom overview page to greet the visitor
|
||||
setLocale("en_US") // 你好
|
||||
addStringOption("Xwerror", "-quiet") // Fail build on warning
|
||||
|
||||
setJFlags([
|
||||
"-Duser.language=en_US" // See above
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Include javadoc and source jar during publishing
|
||||
java {
|
||||
withJavadocJar()
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
// Build publishing configuration
|
||||
// Note: You can safely ignore any errors or warnings thrown by your IDE here
|
||||
publishing {
|
||||
repositories {
|
||||
maven {
|
||||
name = "staropensource"
|
||||
url = uri("https://mvn.staropensource.de/engine")
|
||||
credentials(org.gradle.api.credentials.PasswordCredentials)
|
||||
authentication {
|
||||
//noinspection GroovyAssignabilityCheck
|
||||
basic (BasicAuthentication)
|
||||
}
|
||||
}
|
||||
}
|
||||
publications {
|
||||
//noinspection GroovyAssignabilityCheck
|
||||
maven (MavenPublication) {
|
||||
groupId = group
|
||||
artifactId = project.getName()
|
||||
version = version
|
||||
//noinspection GroovyAssignabilityCheck
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fix delombok task
|
||||
delombok.doFirst {
|
||||
File target = file("${project.projectDir}/src/main/module-info.java")
|
||||
File source = file("${project.projectDir}/src/main/java/module-info.java")
|
||||
|
||||
target.delete()
|
||||
source.renameTo(target)
|
||||
}
|
||||
delombok.doLast {
|
||||
File target = file("${project.projectDir}/src/main/java/module-info.java")
|
||||
File source = file("${project.projectDir}/src/main/module-info.java")
|
||||
|
||||
target.delete()
|
||||
source.renameTo(target)
|
||||
}
|
2
windowing/glfw/README.md
Normal file
2
windowing/glfw/README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# The `glfw` subsystem
|
||||
This subsystem provides a Windowing API using [LWJGL](https://lwjgl.org)'s [GLFW](https://glfw.org) bindings.
|
|
@ -61,17 +61,16 @@ dependencies {
|
|||
// LWJGL
|
||||
implementation(platform("org.lwjgl:lwjgl-bom:${dependencyLwjgl}"))
|
||||
implementation("org.lwjgl:lwjgl")
|
||||
implementation("org.lwjgl:lwjgl-stb")
|
||||
implementation("org.lwjgl:lwjgl-glfw")
|
||||
implementation("org.lwjgl:lwjgl-bgfx")
|
||||
implementation("org.lwjgl:lwjgl-stb")
|
||||
runtimeOnly("org.lwjgl:lwjgl::${dependencyLwjglNatives}")
|
||||
runtimeOnly("org.lwjgl:lwjgl-stb::${dependencyLwjglNatives}")
|
||||
runtimeOnly("org.lwjgl:lwjgl-glfw::${dependencyLwjglNatives}")
|
||||
runtimeOnly("org.lwjgl:lwjgl-bgfx::${dependencyLwjglNatives}")
|
||||
runtimeOnly("org.lwjgl:lwjgl-stb::${dependencyLwjglNatives}")
|
||||
if (project.dependencyLwjglNatives == "natives-macos" || project.dependencyLwjglNatives == "natives-macos-arm64") runtimeOnly("org.lwjgl:lwjgl-vulkan::${dependencyLwjglNatives}")
|
||||
|
||||
// Project
|
||||
implementation(project(":base"))
|
||||
implementation(project(":windowing"))
|
||||
}
|
||||
|
||||
// Javadoc configuration
|
||||
|
@ -97,6 +96,26 @@ 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
|
||||
java {
|
||||
withJavadocJar()
|
1
windowing/glfw/gradle
Symbolic link
1
windowing/glfw/gradle
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../gradle
|
1
windowing/glfw/gradlew
vendored
Symbolic link
1
windowing/glfw/gradlew
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../gradlew
|
1
windowing/glfw/gradlew.bat
vendored
Symbolic link
1
windowing/glfw/gradlew.bat
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../gradlew.bat
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* 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.windowing.glfw;
|
||||
|
||||
import de.staropensource.engine.base.annotation.EngineSubsystem;
|
||||
import de.staropensource.engine.base.logging.Logger;
|
||||
import de.staropensource.engine.base.utility.information.EngineInformation;
|
||||
import de.staropensource.engine.base.implementation.versioning.StarOpenSourceVersioningSystem;
|
||||
import de.staropensource.engine.base.type.DependencyVector;
|
||||
import de.staropensource.engine.base.utility.Miscellaneous;
|
||||
import de.staropensource.engine.windowing.WindowingSubsystem;
|
||||
import de.staropensource.engine.windowing.implementable.api.ApiClass;
|
||||
import de.staropensource.engine.windowing.implementable.api.ApiInternalClass;
|
||||
import de.staropensource.engine.windowing.implementable.api.ApiManagementClass;
|
||||
import de.staropensource.engine.windowing.event.WindowingErrorEvent;
|
||||
import de.staropensource.engine.windowing.exception.NotOnMainThreadException;
|
||||
import de.staropensource.engine.windowing.glfw.implementation.GlfwInternalClass;
|
||||
import de.staropensource.engine.windowing.glfw.implementation.GlfwManagementClass;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFWErrorCallback;
|
||||
import org.lwjgl.glfw.GLFWErrorCallbackI;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
|
||||
/**
|
||||
* The main class of the GLFW subsystem.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@EngineSubsystem
|
||||
@SuppressWarnings({ "JavadocDeclaration" })
|
||||
public final class GlfwSubsystem extends ApiClass {
|
||||
/**
|
||||
* Contains the class instance.
|
||||
*
|
||||
* @since v1-alpha0
|
||||
* -- GETTER --
|
||||
* Returns the class instance.
|
||||
*
|
||||
* @return class instance unless the subsystem is uninitialized
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
@Getter
|
||||
private static GlfwSubsystem instance = null;
|
||||
|
||||
/**
|
||||
* Contains the internal API class.
|
||||
*
|
||||
* @see ApiInternalClass
|
||||
* @since v1-alpha4
|
||||
* -- GETTER --
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Getter
|
||||
private ApiInternalClass internalApi;
|
||||
|
||||
/**
|
||||
* Contains the management class.
|
||||
*
|
||||
* @see ApiManagementClass
|
||||
* @since v1-alpha4
|
||||
* -- GETTER --
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Getter
|
||||
private ApiManagementClass management;
|
||||
|
||||
/**
|
||||
* The {@link GLFWErrorCallback} to use.
|
||||
* <p>
|
||||
* Only declared publicly for freeing during engine shutdown.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private GLFWErrorCallback errorCallback = null;
|
||||
|
||||
/**
|
||||
* Initializes this subsystem.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public GlfwSubsystem() {
|
||||
// Check if subsystem has already initialized
|
||||
if (instance == null)
|
||||
instance = this;
|
||||
else
|
||||
Logger.crash("The subsystem tried to initialize twice");
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void initializeSubsystem() {
|
||||
// Initialize configuration
|
||||
new GlfwSubsystemConfiguration();
|
||||
|
||||
// Register API
|
||||
WindowingSubsystem.getInstance().registerApi(this);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void initializeApi() {
|
||||
Logger.verb("Initializing GLFW");
|
||||
try {
|
||||
if (!Miscellaneous.onMainThread()) {
|
||||
Logger.crash("Unable to initialize GLFW on a non-main thread", new NotOnMainThreadException(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set error callback
|
||||
errorCallback = GLFWErrorCallback.create(new GLFWErrorCallbackI() {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void invoke(int error, long description) {
|
||||
new WindowingErrorEvent().callEvent(description + " (" + error + ")");
|
||||
}
|
||||
}).set();
|
||||
|
||||
// Set init hints
|
||||
switch (GlfwSubsystemConfiguration.getInstance().getPlatform()) {
|
||||
case ANY -> glfwInitHint(GLFW_PLATFORM, GLFW_ANY_PLATFORM);
|
||||
case WAYLAND -> tryPlatform(GLFW_PLATFORM_WAYLAND);
|
||||
case X11 -> tryPlatform(GLFW_PLATFORM_X11);
|
||||
case WIN32 -> tryPlatform(GLFW_PLATFORM_WIN32);
|
||||
case COCOA -> tryPlatform(GLFW_PLATFORM_COCOA);
|
||||
case NONE -> glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_NULL);
|
||||
}
|
||||
glfwInitHint(GLFW_WAYLAND_LIBDECOR, GlfwSubsystemConfiguration.getInstance().isDisableLibdecor() ? GLFW_WAYLAND_DISABLE_LIBDECOR : GLFW_WAYLAND_PREFER_LIBDECOR);
|
||||
|
||||
// Initialize GLFW
|
||||
if (!glfwInit())
|
||||
Logger.crash("Failed to initialize GLFW");
|
||||
|
||||
// Initialize classes
|
||||
internalApi = new GlfwInternalClass();
|
||||
management = new GlfwManagementClass();
|
||||
} catch (UnsatisfiedLinkError error) {
|
||||
Logger.crash("Failed to load LWJGL native libraries", error);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void shutdownApi() {
|
||||
Logger.verb("Terminating GLFW");
|
||||
|
||||
errorCallback.free();
|
||||
|
||||
if (Miscellaneous.onMainThread())
|
||||
glfwTerminate();
|
||||
else
|
||||
Logger.crash("Unable to terminate GLFW on a non-main thread. Did you call Engine#shutdown or Logger#crash from another thread?", new NotOnMainThreadException(), true);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public @NotNull String getName() {
|
||||
return getApiName().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public String getApiName() {
|
||||
return "GLFW";
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public @NotNull DependencyVector getDependencyVector() {
|
||||
Set<@NotNull String> dependencies = new HashSet<>();
|
||||
dependencies.add("windowing");
|
||||
|
||||
return new DependencyVector.Builder()
|
||||
.setIdentifier(getName())
|
||||
.setVersioningSystem(StarOpenSourceVersioningSystem.class)
|
||||
.setVersion(EngineInformation.getVersioningString())
|
||||
.setDependencies(dependencies)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified platform is compatible,
|
||||
* and if so, specifies it as the platform to use.
|
||||
*
|
||||
* @param platform platform to try
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private void tryPlatform(int platform) {
|
||||
if (glfwPlatformSupported(platform))
|
||||
glfwInitHint(GLFW_PLATFORM, platform);
|
||||
else
|
||||
glfwInitHint(GLFW_PLATFORM, GLFW_ANY_PLATFORM);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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.windowing.glfw;
|
||||
|
||||
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.windowing.glfw.type.GlfwPlatform;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Provides the GLFW subsystem configuration.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Getter
|
||||
@SuppressWarnings({ "JavadocDeclaration" })
|
||||
public final class GlfwSubsystemConfiguration extends Configuration {
|
||||
/**
|
||||
* Contains the class instance.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
* -- GETTER --
|
||||
* Returns the class instance.
|
||||
*
|
||||
* @return class instance unless {@link GlfwSubsystem} is uninitialized
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Getter
|
||||
private static GlfwSubsystemConfiguration instance;
|
||||
|
||||
/**
|
||||
* Defines prefix properties must begin with.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
* -- GETTER --
|
||||
* Returns prefix properties must begin with.
|
||||
*
|
||||
* @return property group
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private final @NotNull String group = "sosengine.windowing.glfw.";
|
||||
|
||||
/**
|
||||
* Contains the platform GLFW will try to initialize with.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
* -- GETTER --
|
||||
* Gets the value for {@link #platform}.
|
||||
*
|
||||
* @return variable value
|
||||
* @see #platform
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private GlfwPlatform platform;
|
||||
|
||||
/**
|
||||
* If {@code true}, will disable support for
|
||||
* <a href="https://gitlab.freedesktop.org/libdecor/libdecor">libdecor</a>.
|
||||
* <p>
|
||||
* Only affects the {@link GlfwPlatform#WAYLAND} platform.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
* -- GETTER --
|
||||
* Gets the value for {@link #disableLibdecor}.
|
||||
*
|
||||
* @return variable value
|
||||
* @see #disableLibdecor
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private boolean disableLibdecor;
|
||||
|
||||
/**
|
||||
* Creates and initializes an instance of this class.
|
||||
*
|
||||
* @see GlfwSubsystem
|
||||
* @since v1-alpha6
|
||||
*/
|
||||
GlfwSubsystemConfiguration() {
|
||||
instance = this;
|
||||
|
||||
loadDefaultConfiguration();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected void matchProperty(@NotNull PropertiesReader parser, @NotNull String property) {
|
||||
switch (property) {
|
||||
case "platform" -> {
|
||||
try {
|
||||
platform = GlfwPlatform.valueOf(parser.getString(group + property).toUpperCase());
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
Logger.error("Platform " + parser.getString(group + property) + " is not valid");
|
||||
}
|
||||
}
|
||||
case "disableLibdecor" -> disableLibdecor = parser.getBoolean(group + property);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected void processSettings(@NotNull PropertiesReader parser) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void loadDefaultConfiguration() {
|
||||
platform = GlfwPlatform.ANY;
|
||||
disableLibdecor = false;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public @Nullable Object getSetting(@NotNull String setting) {
|
||||
return switch (setting) {
|
||||
case "platform" -> platform;
|
||||
case "disableLibdecor" -> disableLibdecor;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -17,12 +17,13 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.callback;
|
||||
package de.staropensource.engine.windowing.glfw.callback;
|
||||
|
||||
import de.staropensource.engine.rendering.type.Window;
|
||||
import de.staropensource.engine.rendering.event.InputEvent;
|
||||
import de.staropensource.engine.rendering.type.input.Key;
|
||||
import de.staropensource.engine.rendering.type.input.KeyState;
|
||||
import de.staropensource.engine.windowing.implementable.Window;
|
||||
import de.staropensource.engine.windowing.event.InputEvent;
|
||||
import de.staropensource.engine.windowing.glfw.implementable.WindowCallback;
|
||||
import de.staropensource.engine.windowing.type.input.Key;
|
||||
import de.staropensource.engine.windowing.type.input.KeyState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFWKeyCallbackI;
|
||||
|
||||
|
@ -31,7 +32,7 @@ import static org.lwjgl.glfw.GLFW.*;
|
|||
/**
|
||||
* A {@link GLFWKeyCallbackI} implementation, which emits {@link InputEvent}.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public final class KeyCallback extends WindowCallback implements GLFWKeyCallbackI {
|
||||
/**
|
||||
|
@ -39,7 +40,7 @@ public final class KeyCallback extends WindowCallback implements GLFWKeyCallback
|
|||
* and making too many allocations, which would potentially decrease
|
||||
* performance.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private static final InputEvent event = new InputEvent();
|
||||
|
||||
|
@ -47,7 +48,7 @@ public final class KeyCallback extends WindowCallback implements GLFWKeyCallback
|
|||
* Creates and initializes an instance of this class.
|
||||
*
|
||||
* @param window {@link Window} class
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public KeyCallback(@NotNull Window window) {
|
||||
super(window);
|
|
@ -17,12 +17,13 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.callback;
|
||||
package de.staropensource.engine.windowing.glfw.callback;
|
||||
|
||||
import de.staropensource.engine.rendering.type.Window;
|
||||
import de.staropensource.engine.rendering.event.InputEvent;
|
||||
import de.staropensource.engine.rendering.type.input.Key;
|
||||
import de.staropensource.engine.rendering.type.input.KeyState;
|
||||
import de.staropensource.engine.windowing.implementable.Window;
|
||||
import de.staropensource.engine.windowing.event.InputEvent;
|
||||
import de.staropensource.engine.windowing.glfw.implementable.WindowCallback;
|
||||
import de.staropensource.engine.windowing.type.input.Key;
|
||||
import de.staropensource.engine.windowing.type.input.KeyState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFWMouseButtonCallbackI;
|
||||
|
||||
|
@ -31,7 +32,7 @@ import static org.lwjgl.glfw.GLFW.*;
|
|||
/**
|
||||
* A {@link GLFWMouseButtonCallbackI} implementation, which forward them to {@link InputEvent}.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public final class MouseButtonCallback extends WindowCallback implements GLFWMouseButtonCallbackI {
|
||||
/**
|
||||
|
@ -39,7 +40,7 @@ public final class MouseButtonCallback extends WindowCallback implements GLFWMou
|
|||
* and making too many allocations, which would potentially decrease
|
||||
* performance.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private static final InputEvent event = new InputEvent();
|
||||
|
||||
|
@ -47,7 +48,7 @@ public final class MouseButtonCallback extends WindowCallback implements GLFWMou
|
|||
* Creates and initializes an instance of this class.
|
||||
*
|
||||
* @param window {@link Window} class
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public MouseButtonCallback(@NotNull Window window) {
|
||||
super(window);
|
||||
|
@ -71,7 +72,7 @@ public final class MouseButtonCallback extends WindowCallback implements GLFWMou
|
|||
case GLFW_MOUSE_BUTTON_RIGHT -> Key.MOUSE_RIGHT;
|
||||
case GLFW_MOUSE_BUTTON_4, GLFW_MOUSE_BUTTON_5,
|
||||
GLFW_MOUSE_BUTTON_6, GLFW_MOUSE_BUTTON_7,
|
||||
GLFW_MOUSE_BUTTON_8 -> Key.UNKNOWN_MOUSE_BUTTON;
|
||||
GLFW_MOUSE_BUTTON_8 -> Key.UNKNOWN_MOUSE;
|
||||
default -> throw new IllegalStateException("Mouse button " + key + " is invalid");
|
||||
},
|
||||
// Key state
|
|
@ -20,6 +20,6 @@
|
|||
/**
|
||||
* Callbacks, which emit {@link de.staropensource.engine.base.implementable.Event}s.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
package de.staropensource.engine.rendering.callback;
|
||||
package de.staropensource.engine.windowing.glfw.callback;
|
|
@ -17,9 +17,9 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.callback;
|
||||
package de.staropensource.engine.windowing.glfw.implementable;
|
||||
|
||||
import de.staropensource.engine.rendering.type.Window;
|
||||
import de.staropensource.engine.windowing.implementable.Window;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
@ -27,7 +27,7 @@ import org.jetbrains.annotations.NotNull;
|
|||
* Abstract class used for easily implementing
|
||||
* callbacks which require a {@link Window} instance.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Getter
|
||||
@SuppressWarnings({ "JavadocDeclaration" })
|
||||
|
@ -36,13 +36,13 @@ public class WindowCallback {
|
|||
* Refers to the {@link Window} instance
|
||||
* this callback is tied to.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
* -- GETTER --
|
||||
* Returns the {@link Window} instance
|
||||
* this callback is tied to.
|
||||
*
|
||||
* @return attached {@link Window} instance
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private final @NotNull Window attachedWindow;
|
||||
|
||||
|
@ -50,7 +50,7 @@ public class WindowCallback {
|
|||
* Creates and initializes an instance of this abstract class.
|
||||
*
|
||||
* @param window {@link Window} class
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public WindowCallback(@NotNull Window window) {
|
||||
this.attachedWindow = window;
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interfaces and abstract classes which can be used for implementing classes.
|
||||
*
|
||||
* @since v1-alpha6
|
||||
*/
|
||||
package de.staropensource.engine.windowing.glfw.implementable;
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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.windowing.glfw.implementation;
|
||||
|
||||
import de.staropensource.engine.windowing.implementable.Monitor;
|
||||
import de.staropensource.engine.windowing.implementable.api.ApiInternalClass;
|
||||
import de.staropensource.engine.windowing.exception.NoMonitorsFoundException;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.PointerBuffer;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.glfwGetMonitors;
|
||||
|
||||
/**
|
||||
* The internal API class for GLFW-powered windowing APIs.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@SuppressWarnings({ "JavadocDeclaration" })
|
||||
public final class GlfwInternalClass implements ApiInternalClass {
|
||||
/**
|
||||
* Contains a class which extends the {@link GlfwWindow} class.
|
||||
*
|
||||
* @since v1-alpha4
|
||||
* -- GETTER --
|
||||
* {@inheritDoc}
|
||||
* -- SETTER --
|
||||
* Sets a class which extends the {@link GlfwWindow} class.
|
||||
*
|
||||
* @param windowClass new window class
|
||||
* @since v1-alpha4
|
||||
*/
|
||||
private @NotNull Class<? extends GlfwWindow> windowClass = GlfwWindow.class;
|
||||
|
||||
/**
|
||||
* Creates and initializes an instance of this class.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public GlfwInternalClass() {}
|
||||
|
||||
/**
|
||||
* Returns all connected monitors.
|
||||
*
|
||||
* @return connected monitors
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Override
|
||||
public @NotNull LinkedHashSet<@NotNull Monitor> getMonitors() throws NoMonitorsFoundException {
|
||||
PointerBuffer monitors = glfwGetMonitors();
|
||||
LinkedHashSet<@NotNull Monitor> output = new LinkedHashSet<>();
|
||||
if (monitors == null)
|
||||
throw new NoMonitorsFoundException();
|
||||
|
||||
while (monitors.hasRemaining())
|
||||
output.add(new GlfwMonitor(monitors.get()));
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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.windowing.glfw.implementation;
|
||||
|
||||
import de.staropensource.engine.base.logging.Logger;
|
||||
import de.staropensource.engine.base.utility.Miscellaneous;
|
||||
import de.staropensource.engine.windowing.implementable.api.ApiManagementClass;
|
||||
import de.staropensource.engine.windowing.implementable.Window;
|
||||
import de.staropensource.engine.windowing.exception.NotOnMainThreadException;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
|
||||
/**
|
||||
* The abstract management class for GLFW-powered windowing APIs.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Getter
|
||||
public final class GlfwManagementClass extends ApiManagementClass {
|
||||
/**
|
||||
* Creates and initializes an instance of this class.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public GlfwManagementClass() {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean mustRunOnMainThread() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public @NotNull LinkedHashMap<@NotNull Window, @NotNull Throwable> runRenderLoop() {
|
||||
// Ensure running on the main thread
|
||||
if (!Miscellaneous.onMainThread())
|
||||
throw new NotOnMainThreadException();
|
||||
|
||||
LinkedHashMap<@NotNull Window, @NotNull Throwable> throwables = new LinkedHashMap<>();
|
||||
|
||||
// Update and render all windows
|
||||
for (Window window : Window.getWindows()) {
|
||||
if (!window.isRendering())
|
||||
continue;
|
||||
|
||||
try {
|
||||
window.updateState();
|
||||
window.render();
|
||||
} catch (Throwable throwable) {
|
||||
Logger.error("Rendering window " + window + " failed: Threw throwable " + throwable.getClass().getName() + (throwable.getMessage() == null ? "" : ": " + throwable.getMessage()));
|
||||
throwables.put(window, throwable);
|
||||
}
|
||||
}
|
||||
|
||||
// Poll for events
|
||||
glfwPollEvents();
|
||||
|
||||
return throwables;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public @NotNull LinkedHashMap<@NotNull Window, @NotNull Throwable> runRenderLoopContinuously(@NotNull Runnable frameCode) {
|
||||
// Ensure running on the main thread
|
||||
if (!Miscellaneous.onMainThread())
|
||||
throw new NotOnMainThreadException();
|
||||
|
||||
return super.runRenderLoopContinuously(frameCode);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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.windowing.glfw.implementation;
|
||||
|
||||
import de.staropensource.engine.base.type.vector.Vec2i;
|
||||
import de.staropensource.engine.windowing.implementable.Monitor;
|
||||
import de.staropensource.engine.windowing.exception.InvalidMonitorException;
|
||||
import lombok.SneakyThrows;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFWVidMode;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
|
||||
/**
|
||||
* Represents a monitor. A GLFW-powered monitor. Wait... aren't monitors powered by... power?
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@SuppressWarnings({ "JavadocDeclaration" })
|
||||
public final class GlfwMonitor extends Monitor {
|
||||
/**
|
||||
* Contains the {@link #identifier} as a long.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
* -- GETTER --
|
||||
* Returns the monitor identifier as a long.
|
||||
*
|
||||
* @return monitor identifier as a long
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private final long identifierLong;
|
||||
|
||||
/**
|
||||
* Creates and initializes an instance of this class.
|
||||
*
|
||||
* @param identifier glfw monitor pointer
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@SneakyThrows
|
||||
public GlfwMonitor(long identifier) throws InvalidMonitorException {
|
||||
// Set identifier
|
||||
setIdentifier(String.valueOf(identifier));
|
||||
identifierLong = identifier;
|
||||
|
||||
// Check if connected
|
||||
checkConnected();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@SneakyThrows
|
||||
public void checkConnected() throws InvalidMonitorException {
|
||||
super.checkConnected();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return glfwGetMonitorName(identifierLong) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the monitor name.
|
||||
*
|
||||
* @return monitor name
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Override
|
||||
public @NotNull String getName() throws InvalidMonitorException {
|
||||
checkConnected();
|
||||
return Objects.requireNonNull(glfwGetMonitorName(identifierLong));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the monitor size.
|
||||
*
|
||||
* @return monitor size
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Vec2i getSize() throws InvalidMonitorException {
|
||||
checkConnected();
|
||||
|
||||
GLFWVidMode videoMode = Objects.requireNonNull(glfwGetVideoMode(identifierLong));
|
||||
|
||||
return new Vec2i(videoMode.width(), videoMode.height());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the monitor refresh rate.
|
||||
*
|
||||
* @return monitor refresh rate
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Override
|
||||
public short getRefreshRate() throws InvalidMonitorException {
|
||||
checkConnected();
|
||||
return (short) Objects.requireNonNull(glfwGetVideoMode(identifierLong)).refreshRate();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,566 @@
|
|||
/*
|
||||
* 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.windowing.glfw.implementation;
|
||||
|
||||
import de.staropensource.engine.base.logging.Logger;
|
||||
import de.staropensource.engine.base.type.vector.Vec2i;
|
||||
import de.staropensource.engine.base.utility.Miscellaneous;
|
||||
import de.staropensource.engine.windowing.WindowingSubsystemConfiguration;
|
||||
import de.staropensource.engine.windowing.event.InputEvent;
|
||||
import de.staropensource.engine.windowing.event.RenderingErrorEvent;
|
||||
import de.staropensource.engine.windowing.exception.NotOnMainThreadException;
|
||||
import de.staropensource.engine.windowing.exception.WindowCreationFailureException;
|
||||
import de.staropensource.engine.windowing.glfw.callback.KeyCallback;
|
||||
import de.staropensource.engine.windowing.glfw.callback.MouseButtonCallback;
|
||||
import de.staropensource.engine.windowing.implementable.Monitor;
|
||||
import de.staropensource.engine.windowing.implementable.Window;
|
||||
import de.staropensource.engine.windowing.type.window.VsyncMode;
|
||||
import de.staropensource.engine.windowing.type.window.WindowMode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.glfw.GLFWImage;
|
||||
import org.lwjgl.glfw.GLFWKeyCallback;
|
||||
import org.lwjgl.glfw.GLFWMouseButtonCallback;
|
||||
import org.lwjgl.stb.STBImage;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
|
||||
/**
|
||||
* Abstract class for implementing GLFW-powered windows in a windowing API.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@SuppressWarnings({ "JavadocDeclaration" })
|
||||
public final class GlfwWindow extends Window {
|
||||
/**
|
||||
* Contains the {@link #identifier} used by GLFW.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
* -- GETTER --
|
||||
* Returns the window identifier used by GLFW.
|
||||
*
|
||||
* @return GLFW identifier
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Getter
|
||||
private long identifierLong;
|
||||
|
||||
/**
|
||||
* Contains the code to execute in {@link #render()}.
|
||||
*
|
||||
* @since v1-alpha8
|
||||
* -- GETTER --
|
||||
* Returns the code to execute in {@link #render()}.
|
||||
*
|
||||
* @return rendering code
|
||||
* @since v1-alpha8
|
||||
* -- SETTER --
|
||||
* Sets the code to execute in {@link #render()}
|
||||
*
|
||||
* @param renderCode new rendering code
|
||||
* @since v1-alpha8
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private @NotNull Runnable renderCode = () -> glfwSwapBuffers(identifierLong);
|
||||
|
||||
/**
|
||||
* Contains the {@link GLFWKeyCallback} used for emitting {@link InputEvent}s.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private GLFWKeyCallback keyCallback;
|
||||
|
||||
/**
|
||||
* Contains the {@link GLFWMouseButtonCallback} used for emitting {@link InputEvent}s.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private GLFWMouseButtonCallback mouseButtonCallback;
|
||||
|
||||
// ------------------------------------------------ [ Window (de)initialization ] ------------------------------------------------ //
|
||||
/**
|
||||
* Creates and initializes an instance of this class.
|
||||
*
|
||||
* @param name name
|
||||
* @param title title
|
||||
* @param icons icons
|
||||
* @param size size
|
||||
* @param minimumSize minimum size
|
||||
* @param maximumSize maximum size
|
||||
* @param position position
|
||||
* @param windowMode window mode
|
||||
* @param monitor monitor
|
||||
* @param resizable resizable flag
|
||||
* @param borderless borderless flag
|
||||
* @param focusable focusable flag
|
||||
* @param onTop on top flag
|
||||
* @param transparent transparency flag
|
||||
* @param rendering rendering flag
|
||||
* @throws Exception stuff thrown by the {@link #initializeWindow()} and {@link #render()} methods of the implementing windowing API
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public GlfwWindow(@NotNull String name, @NotNull String title, @NotNull Path @Nullable [] icons, @NotNull Vec2i size, @NotNull Vec2i minimumSize, @NotNull Vec2i maximumSize, @NotNull Vec2i position, @NotNull WindowMode windowMode, @NotNull Monitor monitor, boolean resizable, boolean borderless, boolean focusable, boolean onTop, boolean transparent, boolean rendering) throws Exception {
|
||||
super(name, title, icons, size, minimumSize, maximumSize, position, windowMode, monitor, resizable, borderless, focusable, onTop, transparent, rendering);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected void initializeWindow() {
|
||||
createGlfwWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
* (Re-)Creates the associated GLFW window.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public void createGlfwWindow() throws WindowCreationFailureException {
|
||||
// Ensure running on the main thread
|
||||
if (!Miscellaneous.onMainThread())
|
||||
throw new NotOnMainThreadException();
|
||||
|
||||
// Get current focus and destroy existing window
|
||||
boolean focused = true;
|
||||
if (getIdentifier() != null) {
|
||||
focused = isFocused();
|
||||
closeGlfwWindow();
|
||||
}
|
||||
|
||||
// Set window hints
|
||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // The window's visibility is later changed in setWindowState, this is just for setting up the window
|
||||
glfwWindowHint(GLFW_POSITION_X, getPosition().getX());
|
||||
glfwWindowHint(GLFW_POSITION_Y, getPosition().getY());
|
||||
glfwWindowHint(GLFW_CENTER_CURSOR, 0);
|
||||
glfwWindowHint(GLFW_FOCUSED, Miscellaneous.getIntegerizedBoolean(focused));
|
||||
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, Miscellaneous.getIntegerizedBoolean(isTransparent()));
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE);
|
||||
glfwWindowHintString(GLFW_WAYLAND_APP_ID, getName());
|
||||
glfwWindowHintString(GLFW_X11_CLASS_NAME, getName());
|
||||
glfwWindowHintString(GLFW_X11_INSTANCE_NAME, getName());
|
||||
|
||||
// Create window
|
||||
long identifier = glfwCreateWindow(getSize().getX(), getSize().getY(), getTitle(), MemoryUtil.NULL, MemoryUtil.NULL);
|
||||
if (identifier == MemoryUtil.NULL) {
|
||||
new RenderingErrorEvent().callEvent("Unable to create window: Identifier is null");
|
||||
throw new WindowCreationFailureException();
|
||||
}
|
||||
|
||||
// Set identifier
|
||||
identifierLong = identifier;
|
||||
setIdentifier(String.valueOf(identifier));
|
||||
|
||||
// Own context
|
||||
ownContext();
|
||||
|
||||
// Set swap interval based on V-Sync mode setting
|
||||
glfwSwapInterval(WindowingSubsystemConfiguration.getInstance().getVsyncMode() == VsyncMode.ON ? 1 : 0);
|
||||
|
||||
// Create callbacks
|
||||
keyCallback = GLFWKeyCallback.create(new KeyCallback(this));
|
||||
mouseButtonCallback = GLFWMouseButtonCallback.create(new MouseButtonCallback(this));
|
||||
|
||||
// Set callback
|
||||
glfwSetKeyCallback(identifierLong, keyCallback);
|
||||
glfwSetMouseButtonCallback(identifier, mouseButtonCallback);
|
||||
|
||||
// Update the window state
|
||||
setIcons(getIcons());
|
||||
setSize(getSize());
|
||||
setMinimumSize(getMinimumSize());
|
||||
setMaximumSize(getMaximumSize());
|
||||
setWindowMode(getWindowMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the associated GLFW window.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public void closeGlfwWindow() throws WindowCreationFailureException {
|
||||
// Ensure running on the main thread
|
||||
if (!Miscellaneous.onMainThread())
|
||||
throw new NotOnMainThreadException();
|
||||
|
||||
// Close callbacks
|
||||
keyCallback.close();
|
||||
mouseButtonCallback.close();
|
||||
|
||||
// Destroy the window
|
||||
glfwDestroyWindow(identifierLong);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void terminate() {
|
||||
setTerminated(true);
|
||||
closeGlfwWindow();
|
||||
}
|
||||
|
||||
// ------------------------------------------------ [ State updates ] ------------------------------------------------ //
|
||||
/**
|
||||
* Updates the window state.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Override
|
||||
public void updateState() {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
// Ensure running on the main thread
|
||||
if (!Miscellaneous.onMainThread())
|
||||
throw new NotOnMainThreadException();
|
||||
|
||||
// Update window mode
|
||||
if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_ICONIFIED)))
|
||||
super.setWindowMode(WindowMode.MINIMIZED);
|
||||
else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_MAXIMIZED)))
|
||||
super.setWindowMode(WindowMode.MAXIMIZED);
|
||||
else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_VISIBLE)))
|
||||
super.setWindowMode(WindowMode.WINDOWED);
|
||||
else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_VISIBLE)))
|
||||
super.setWindowMode(WindowMode.HIDDEN);
|
||||
|
||||
// Update monitor
|
||||
if (!getMonitor().isConnected()) {
|
||||
Monitor newMonitor = null;
|
||||
|
||||
for (Monitor monitor : Monitor.getMonitors())
|
||||
if (monitor.isConnected())
|
||||
newMonitor = monitor;
|
||||
|
||||
if (newMonitor == null)
|
||||
Logger.crash("Unable to set a new target monitor for window " + getUniqueIdentifier() + " as no monitors are connected to the system");
|
||||
|
||||
setMonitor(Objects.requireNonNull(newMonitor));
|
||||
}
|
||||
|
||||
// Update vectors
|
||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||
IntBuffer width = stack.mallocInt(2);
|
||||
IntBuffer height = stack.mallocInt(2);
|
||||
|
||||
glfwGetWindowSize(identifierLong, width, height);
|
||||
super.setSize(new Vec2i(width.get(), height.get()));
|
||||
|
||||
glfwGetWindowPos(identifierLong, width, height);
|
||||
super.setPosition(new Vec2i(width.get(), height.get()));
|
||||
}
|
||||
|
||||
// Update booleans
|
||||
super.setResizable(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_RESIZABLE)));
|
||||
super.setOnTop(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_FLOATING)));
|
||||
super.setTransparent(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_TRANSPARENT_FRAMEBUFFER)));
|
||||
}
|
||||
|
||||
// ------------------------------------------------ [ Rendering ] ------------------------------------------------ //
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void render() throws NotOnMainThreadException {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
// Ensure rendering is enabled
|
||||
if (!isRendering())
|
||||
return;
|
||||
|
||||
// Ensure running on the main thread
|
||||
if (!Miscellaneous.onMainThread())
|
||||
throw new NotOnMainThreadException();
|
||||
|
||||
renderCode.run();
|
||||
}
|
||||
|
||||
// ------------------------------------------------ [ GLFW handling ] ------------------------------------------------ //
|
||||
/**
|
||||
* Updates the OpenGL context.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public void ownContext() {
|
||||
glfwMakeContextCurrent(identifierLong);
|
||||
}
|
||||
|
||||
// ------------------------------------------------ [ Information/Action methods ] ------------------------------------------------ //
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isClosureRequested() {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return false;
|
||||
|
||||
return glfwWindowShouldClose(identifierLong);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isFocused() {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return false;
|
||||
|
||||
return Miscellaneous.getTristatedInteger(glfwGetWindowAttrib(identifierLong, GLFW_FOCUSED)).toBoolean();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void focus() {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
glfwFocusWindow(identifierLong);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void requestAttention() {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
glfwRequestWindowAttention(identifierLong);
|
||||
}
|
||||
|
||||
// ------------------------------------------------ [ Setter overrides ] ------------------------------------------------ //
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setName(@NotNull String name) {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
super.setName(name);
|
||||
createGlfwWindow();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setTitle(@NotNull String title) {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
super.setTitle(title);
|
||||
glfwSetWindowTitle(identifierLong, title);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@ApiStatus.Experimental
|
||||
@Override
|
||||
public void setIcons(@NotNull Path @Nullable [] icons) {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
this.icons = icons;
|
||||
if (icons != null)
|
||||
try (GLFWImage.Buffer iconsBuffer = GLFWImage.malloc(icons.length)) {
|
||||
Logger.warn("GlfwWindow#setIcons is experimental and may cause engine or JVM crashes. Here be dragons!");
|
||||
Logger.diag("icons.length = " + icons.length);
|
||||
|
||||
List<ByteBuffer> iconBuffers = new ArrayList<>();
|
||||
IntBuffer width = MemoryUtil.memAllocInt(1);
|
||||
IntBuffer height = MemoryUtil.memAllocInt(1);
|
||||
IntBuffer channels = MemoryUtil.memAllocInt(1);
|
||||
|
||||
for (Path filepath : icons) {
|
||||
Logger.diag("iterating icons » " + iconBuffers.size() + " » " + filepath);
|
||||
// Load icon
|
||||
Logger.diag("loading icon");
|
||||
iconBuffers.add(STBImage.stbi_load(filepath.toAbsolutePath().toString(), width, height, channels, 4));
|
||||
|
||||
if (iconBuffers.getLast() == null) {
|
||||
Logger.warn("Icon " + iconsBuffer.position() + " could not be loaded" + (STBImage.stbi_failure_reason() == null ? "" : ": " + STBImage.stbi_failure_reason()));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Save into 'iconsBuffer'
|
||||
Logger.diag("saving into buffer");
|
||||
iconsBuffer
|
||||
.position(iconsBuffer.position() + 1)
|
||||
.width(width.get(0))
|
||||
.height(height.get(0))
|
||||
.pixels(iconBuffers.getLast());
|
||||
}
|
||||
Logger.diag("out of iteration");
|
||||
|
||||
// Set icons
|
||||
Logger.diag("setting position");
|
||||
iconsBuffer.position(0);
|
||||
Logger.diag("setting icons");
|
||||
Logger.flush();
|
||||
glfwSetWindowIcon(identifierLong, iconsBuffer);
|
||||
|
||||
// Free icons
|
||||
Logger.diag("freeing icons");
|
||||
for (ByteBuffer buffer : iconBuffers)
|
||||
if (buffer != null) {
|
||||
Logger.diag("freeing buffer");
|
||||
STBImage.stbi_image_free(buffer);
|
||||
} else
|
||||
Logger.diag("skipping null buffer");
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setSize(@NotNull Vec2i size) {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
super.setSize(size);
|
||||
glfwSetWindowSize(identifierLong, size.getX(), size.getY());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setMinimumSize(@NotNull Vec2i minimumSize) {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
super.setMinimumSize(minimumSize);
|
||||
glfwSetWindowSizeLimits(identifierLong, minimumSize.getX(), minimumSize.getY(), getMaximumSize().getX(), getMaximumSize().getY());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setMaximumSize(@NotNull Vec2i maximumSize) {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
super.setMaximumSize(maximumSize);
|
||||
glfwSetWindowSizeLimits(identifierLong, getMinimumSize().getX(), getMinimumSize().getY(), maximumSize.getX(), maximumSize.getY());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setPosition(@NotNull Vec2i position) {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
super.setPosition(position);
|
||||
glfwSetWindowSize(identifierLong, position.getX(), position.getY());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setWindowMode(@NotNull WindowMode windowMode) {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
super.setWindowMode(windowMode);
|
||||
switch (windowMode) {
|
||||
case HIDDEN -> glfwHideWindow(identifierLong);
|
||||
case WINDOWED -> {
|
||||
glfwShowWindow(identifierLong);
|
||||
glfwRestoreWindow(identifierLong);
|
||||
}
|
||||
case MINIMIZED -> {
|
||||
glfwShowWindow(identifierLong);
|
||||
glfwIconifyWindow(identifierLong);
|
||||
}
|
||||
case MAXIMIZED -> {
|
||||
glfwShowWindow(identifierLong);
|
||||
glfwRestoreWindow(identifierLong);
|
||||
glfwMaximizeWindow(identifierLong);
|
||||
}
|
||||
case BORDERLESS_FULLSCREEN -> {
|
||||
glfwShowWindow(identifierLong);
|
||||
glfwRestoreWindow(identifierLong);
|
||||
// TODO
|
||||
}
|
||||
case EXCLUSIVE_FULLSCREEN -> {
|
||||
glfwShowWindow(identifierLong);
|
||||
glfwRestoreWindow(identifierLong);
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setResizable(boolean resizable) {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
super.setResizable(resizable);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setBorderless(boolean borderless) {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
super.setBorderless(borderless);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setFocusable(boolean focusable) {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
super.setFocusable(focusable);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setOnTop(boolean onTop) {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
super.setOnTop(onTop);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setTransparent(boolean transparent) {
|
||||
// Ensure the window is not terminated
|
||||
if (isTerminated())
|
||||
return;
|
||||
|
||||
super.setTransparent(transparent);
|
||||
createGlfwWindow();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementations for various interfaces and abstract classes.
|
||||
*
|
||||
* @since v1-alpha6
|
||||
*/
|
||||
package de.staropensource.engine.windowing.glfw.implementation;
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Miscellaneous utility classes.
|
||||
* Code of the GLFW subsystem.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
package de.staropensource.engine.base.utility.misc;
|
||||
package de.staropensource.engine.windowing.glfw;
|
|
@ -17,53 +17,53 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.rendering.type.window;
|
||||
package de.staropensource.engine.windowing.glfw.type;
|
||||
|
||||
/**
|
||||
* Represents all available rendering platforms.
|
||||
* Contains all available platforms which GLFW can be initialized with.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public enum RenderingPlatform {
|
||||
public enum GlfwPlatform {
|
||||
/**
|
||||
* Allows GLFW to autodetect the platform to use.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
ANY,
|
||||
|
||||
/**
|
||||
* Prefer initializing with the Wayland platform.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
WAYLAND,
|
||||
|
||||
/**
|
||||
* Prefer initializing with the X11 platform.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
X11,
|
||||
|
||||
/**
|
||||
* Prefer initializing with the Win32 platform.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
WIN32,
|
||||
|
||||
/**
|
||||
* Prefer initializing with the Cocoa platform.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
COCOA,
|
||||
|
||||
/**
|
||||
* Prefer initializing headless.
|
||||
* Prefer initializing without any platform.
|
||||
*
|
||||
* @since v1-alpha9
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
NONE
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data types in form of enums and classes.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
package de.staropensource.engine.windowing.glfw.type;
|
25
windowing/glfw/src/main/java/module-info.java
Normal file
25
windowing/glfw/src/main/java/module-info.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* The {@code glfw} subsystem and windowing API, which makes it
|
||||
* possible to create {@link Window} using the GLFW library.
|
||||
*
|
||||
* @since v1-alpha4
|
||||
*/
|
||||
module sosengine.windowing.glfw {
|
||||
// Dependencies
|
||||
// -> Engine
|
||||
requires transitive sosengine.base;
|
||||
requires transitive sosengine.windowing;
|
||||
// -> Libraries
|
||||
requires transitive static lombok;
|
||||
requires transitive org.jetbrains.annotations;
|
||||
requires org.lwjgl.glfw;
|
||||
requires org.lwjgl.stb;
|
||||
|
||||
// API access
|
||||
exports de.staropensource.engine.windowing.glfw;
|
||||
exports de.staropensource.engine.windowing.glfw.implementation;
|
||||
|
||||
// Reflection access
|
||||
opens de.staropensource.engine.windowing.glfw;
|
||||
opens de.staropensource.engine.windowing.glfw.implementation;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue