Renamed asset folder to resource, made resourceLoader more robust. Completed some TODO's, formatting

This commit is contained in:
Bas de Jong
2025-10-07 23:54:33 +02:00
parent 72e322675e
commit e9dfbbd150
32 changed files with 289 additions and 264 deletions

View File

@@ -13,6 +13,7 @@
<w>toop</w>
<w>vmoptions</w>
<w>xplugin</w>
<w>yourturn</w>
</words>
</dictionary>
</component>

View File

@@ -1,11 +1,11 @@
package org.toop;
import org.toop.app.App;
import org.toop.framework.asset.ResourceLoader;
import org.toop.framework.asset.ResourceManager;
import org.toop.framework.audio.SoundManager;
import org.toop.framework.networking.NetworkingClientManager;
import org.toop.framework.networking.NetworkingInitializationException;
import org.toop.framework.resource.ResourceLoader;
import org.toop.framework.resource.ResourceManager;
public final class Main {
static void main(String[] args) {

View File

@@ -9,10 +9,10 @@ import javafx.stage.Stage;
import org.toop.app.layer.Layer;
import org.toop.app.layer.layers.MainLayer;
import org.toop.app.layer.layers.QuitPopup;
import org.toop.framework.asset.ResourceManager;
import org.toop.framework.asset.resources.CssAsset;
import org.toop.framework.audio.events.AudioEvents;
import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.resource.ResourceManager;
import org.toop.framework.resource.resources.CssAsset;
import org.toop.local.AppContext;
import org.toop.local.AppSettings;
@@ -107,7 +107,7 @@ public final class App extends Application {
try {
root.getChildren().removeLast();
} catch (Exception e) {
IO.println(e);
IO.println(e); // TODO: Use logger
}
}

View File

@@ -10,9 +10,9 @@ import org.toop.app.layer.Container;
import org.toop.app.layer.NodeBuilder;
import org.toop.app.layer.Popup;
import org.toop.app.layer.containers.VerticalContainer;
import org.toop.framework.asset.resources.SettingsAsset;
import org.toop.framework.audio.events.AudioEvents;
import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.resource.resources.SettingsAsset;
import org.toop.local.AppContext;
import org.toop.local.AppSettings;

View File

@@ -1,8 +1,8 @@
package org.toop.local;
import java.util.Locale;
import org.toop.framework.asset.ResourceManager;
import org.toop.framework.asset.resources.LocalizationAsset;
import org.toop.framework.resource.ResourceManager;
import org.toop.framework.resource.resources.LocalizationAsset;
public class AppContext {
private static final LocalizationAsset localization = ResourceManager.get("localization");

View File

@@ -3,9 +3,9 @@ package org.toop.local;
import java.io.File;
import java.util.Locale;
import org.toop.app.App;
import org.toop.framework.asset.resources.SettingsAsset;
import org.toop.framework.audio.events.AudioEvents;
import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.resource.resources.SettingsAsset;
import org.toop.framework.settings.Settings;
public class AppSettings {

View File

@@ -12,7 +12,6 @@ import org.apache.logging.log4j.core.config.LoggerConfig;
* <p>Provides methods to enable or disable logs globally or per class, with support for specifying
* log levels either via {@link Level} enums or string names.
*/
// Todo: refactor
public final class Logging {
/** Disables all logging globally by setting the root logger level to {@link Level#OFF}. */

View File

@@ -68,8 +68,6 @@ public class AudioVolumeManager {
private void handleMusicVolumeChange(AudioEvents.ChangeMusicVolume event) {
this.musicVolume = limitVolume(event.newVolume() / 100);
System.out.println(this.musicVolume);
System.out.println(this.volume);
for (MediaPlayer mediaPlayer : sM.getActiveMusic()) {
this.updateMusicVolume(mediaPlayer);
}

View File

@@ -7,12 +7,12 @@ import javax.sound.sampled.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.toop.framework.SnowflakeGenerator;
import org.toop.framework.asset.ResourceManager;
import org.toop.framework.asset.ResourceMeta;
import org.toop.framework.asset.resources.MusicAsset;
import org.toop.framework.asset.resources.SoundEffectAsset;
import org.toop.framework.audio.events.AudioEvents;
import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.resource.ResourceManager;
import org.toop.framework.resource.ResourceMeta;
import org.toop.framework.resource.resources.MusicAsset;
import org.toop.framework.resource.resources.SoundEffectAsset;
public class SoundManager {
private static final Logger logger = LogManager.getLogger(SoundManager.class);
@@ -20,8 +20,6 @@ public class SoundManager {
private final Queue<MusicAsset> backgroundMusicQueue = new LinkedList<>();
private final Map<Long, Clip> activeSoundEffects = new HashMap<>();
private final HashMap<String, SoundEffectAsset> audioResources = new HashMap<>();
private final SnowflakeGenerator idGenerator =
new SnowflakeGenerator(); // TODO: Don't create a new generator
private final AudioVolumeManager audioVolumeManager = new AudioVolumeManager(this);
public SoundManager() {
@@ -120,7 +118,9 @@ public class SoundManager {
logger.info("Playing background music: {}", ma.getFile().getName());
logger.info(
"Background music next in line: {}",
backgroundMusicQueue.peek() != null ? backgroundMusicQueue.peek().getFile().getName() : null);
backgroundMusicQueue.peek() != null
? backgroundMusicQueue.peek().getFile().getName()
: null);
}
private long playSound(String audioFileName, boolean loop)
@@ -149,10 +149,10 @@ public class SoundManager {
logger.debug("Playing sound: {}", asset.getFile().getName());
// Generate id for clip
long clipId = idGenerator.nextId();
long clipId = new SnowflakeGenerator().nextId();
// store it so we can stop it later
activeSoundEffects.put(clipId, clip); // TODO: Do on snowflake for specific sound to stop
activeSoundEffects.put(clipId, clip);
// remove when finished (only for non-looping sounds)
clip.addLineListener(

View File

@@ -45,8 +45,8 @@ public class NetworkingClientManager {
}
long startClientRequest(String ip, int port) {
long connectionId = new SnowflakeGenerator().nextId(); // TODO: Maybe use the one generated
try { // With EventFlow
long connectionId = new SnowflakeGenerator().nextId();
try {
NetworkingClient client =
new NetworkingClient(
() -> new NetworkingGameClientHandler(connectionId),
@@ -81,19 +81,13 @@ public class NetworkingClientManager {
void handleStartClient(NetworkEvents.StartClient event) {
long id = this.startClientRequest(event.ip(), event.port());
new Thread(
() -> {
try {
Thread.sleep(100); // TODO: Is this a good idea?
() ->
new EventFlow()
.addPostEvent(
NetworkEvents.StartClientResponse.class,
id,
event.eventSnowflake())
.asyncPostEvent();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
})
.asyncPostEvent())
.start();
}
@@ -185,7 +179,7 @@ public class NetworkingClientManager {
void handleCloseClient(NetworkEvents.CloseClient event) {
NetworkingClient client = this.networkClients.get(event.clientId());
client.closeConnection(); // TODO: Check if not blocking, what if error, mb not remove?
client.closeConnection();
this.networkClients.remove(event.clientId());
logger.info("Client {} closed successfully.", event.clientId());
}

View File

@@ -74,7 +74,7 @@ public class NetworkingGameClientHandler extends ChannelInboundHandlerAdapter {
gameWinConditionHandler(recSrvRemoved);
return;
default:
return;
// return
}
} else {
@@ -93,10 +93,10 @@ public class NetworkingGameClientHandler extends ChannelInboundHandlerAdapter {
helpHandler(recSrvRemoved);
return;
default:
return;
// return
}
} else {
return; // TODO: Should be an error.
logger.error("Could not parse: {}", rec);
}
}
}

View File

@@ -1,4 +1,4 @@
package org.toop.framework.asset;
package org.toop.framework.resource;
import java.io.File;
import java.util.*;
@@ -9,12 +9,13 @@ import java.util.function.Function;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.reflections.Reflections;
import org.toop.framework.asset.events.AssetLoaderEvents;
import org.toop.framework.asset.resources.*;
import org.toop.framework.asset.types.BundledResource;
import org.toop.framework.asset.types.FileExtension;
import org.toop.framework.asset.types.PreloadResource;
import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.resource.events.AssetLoaderEvents;
import org.toop.framework.resource.exceptions.CouldNotCreateResourceFactoryException;
import org.toop.framework.resource.resources.*;
import org.toop.framework.resource.types.BundledResource;
import org.toop.framework.resource.types.FileExtension;
import org.toop.framework.resource.types.PreloadResource;
/**
* Responsible for loading assets from a file system directory into memory.
@@ -141,19 +142,24 @@ public class ResourceLoader {
}
/** Maps a file to a resource instance based on its extension and registered factories. */
private <T extends BaseResource> T resourceMapper(File file, Class<T> type) {
private <T extends BaseResource> T resourceMapper(File file)
throws CouldNotCreateResourceFactoryException, IllegalArgumentException {
String ext = getExtension(file.getName());
Function<File, ? extends BaseResource> factory = registry.get(ext);
if (factory == null) return null;
if (factory == null)
throw new CouldNotCreateResourceFactoryException(registry, file.getName());
BaseResource resource = factory.apply(file);
if (!type.isInstance(resource)) {
if (resource == null) {
throw new IllegalArgumentException(
"File " + file.getName() + " is not of type " + type.getSimpleName());
"File "
+ file.getName()
+ " is not of type "
+ BaseResource.class.getSimpleName());
}
return type.cast(resource);
return ((Class<T>) BaseResource.class).cast(resource);
}
/** Loads the given list of files into assets, handling bundled and preload resources. */
@@ -162,7 +168,14 @@ public class ResourceLoader {
for (File file : files) {
boolean skipAdd = false;
BaseResource resource = resourceMapper(file, BaseResource.class);
BaseResource resource = null;
try {
resource = resourceMapper(file);
} catch (CouldNotCreateResourceFactoryException _) {
logger.warn("Could not create resource for: {}", file);
} catch (IllegalArgumentException e) {
logger.error(e);
}
switch (resource) {
case null -> {
continue;
@@ -216,7 +229,7 @@ public class ResourceLoader {
* {@link FileExtension}.
*/
private void autoRegisterResources() {
Reflections reflections = new Reflections("org.toop.framework.asset.resources");
Reflections reflections = new Reflections("org.toop.framework.resource.resources");
Set<Class<? extends BaseResource>> classes = reflections.getSubTypesOf(BaseResource.class);
for (Class<? extends BaseResource> cls : classes) {

View File

@@ -1,16 +1,15 @@
package org.toop.framework.asset;
package org.toop.framework.resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.toop.framework.asset.resources.*;
import org.toop.framework.resource.exceptions.ResourceNotFoundException;
import org.toop.framework.resource.resources.*;
/**
* Centralized manager for all loaded assets in the application.
*
* <p>{@code ResourceManager} maintains a thread-safe registry of {@link ResourceMeta} objects and provides
* utility methods to retrieve assets by name, ID, or type. It works together with {@link
* <p>{@code ResourceManager} maintains a thread-safe registry of {@link ResourceMeta} objects and
* provides utility methods to retrieve assets by name, ID, or type. It works together with {@link
* ResourceLoader} to register assets automatically when they are loaded from the file system.
*
* <p>Key responsibilities:
@@ -49,7 +48,7 @@ import org.toop.framework.asset.resources.*;
* </ul>
*/
public class ResourceManager {
private static final Logger logger = LogManager.getLogger(ResourceManager.class);
// private static final Logger logger = LogManager.getLogger(ResourceManager.class);
private static final Map<String, ResourceMeta<? extends BaseResource>> assets =
new ConcurrentHashMap<>();
@@ -61,7 +60,7 @@ public class ResourceManager {
* @param loader the loader that has already loaded assets
*/
public static synchronized void loadAssets(ResourceLoader loader) {
for (var asset : loader.getAssets()) {
for (ResourceMeta<? extends BaseResource> asset : loader.getAssets()) {
assets.put(asset.getName(), asset);
}
}
@@ -77,12 +76,7 @@ public class ResourceManager {
public static <T extends BaseResource> T get(String name) {
ResourceMeta<T> asset = (ResourceMeta<T>) assets.get(name);
if (asset == null) {
throw new TypeNotPresentException(
name,
new RuntimeException(
String.format(
"Type %s not present",
name))); // TODO: Create own exception, BAM
throw new ResourceNotFoundException(name);
}
return asset.getResource();
}

View File

@@ -1,7 +1,7 @@
package org.toop.framework.asset;
package org.toop.framework.resource;
import org.toop.framework.SnowflakeGenerator;
import org.toop.framework.asset.resources.BaseResource;
import org.toop.framework.resource.resources.BaseResource;
public class ResourceMeta<T extends BaseResource> {
private final Long id;

View File

@@ -1,4 +1,4 @@
package org.toop.framework.asset.events;
package org.toop.framework.resource.events;
import org.toop.framework.eventbus.events.EventWithoutSnowflake;

View File

@@ -0,0 +1,12 @@
package org.toop.framework.resource.exceptions;
import java.util.Map;
public class CouldNotCreateResourceFactoryException extends RuntimeException {
public CouldNotCreateResourceFactoryException(Map<?, ?> registry, String fileName) {
super(
String.format(
"Could not create resource factory for: %s, isRegistryEmpty: %b",
fileName, registry.isEmpty()));
}
}

View File

@@ -0,0 +1,7 @@
package org.toop.framework.resource.exceptions;
public class IsNotAResourceException extends RuntimeException {
public <T> IsNotAResourceException(Class<T> clazz, String message) {
super(clazz.getName() + " does not implement BaseResource");
}
}

View File

@@ -0,0 +1,7 @@
package org.toop.framework.resource.exceptions;
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String name) {
super("Could not find resource: " + name);
}
}

View File

@@ -1,4 +1,4 @@
package org.toop.framework.asset.resources;
package org.toop.framework.resource.resources;
import java.io.*;

View File

@@ -1,7 +1,7 @@
package org.toop.framework.asset.resources;
package org.toop.framework.resource.resources;
import java.io.File;
import org.toop.framework.asset.types.FileExtension;
import org.toop.framework.resource.types.FileExtension;
@FileExtension({"css"})
public class CssAsset extends BaseResource {

View File

@@ -1,11 +1,11 @@
package org.toop.framework.asset.resources;
package org.toop.framework.resource.resources;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javafx.scene.text.Font;
import org.toop.framework.asset.types.FileExtension;
import org.toop.framework.asset.types.PreloadResource;
import org.toop.framework.resource.types.FileExtension;
import org.toop.framework.resource.types.PreloadResource;
@FileExtension({"ttf", "otf"})
public class FontAsset extends BaseResource implements PreloadResource {

View File

@@ -1,10 +1,10 @@
package org.toop.framework.asset.resources;
package org.toop.framework.resource.resources;
import java.io.File;
import java.io.FileInputStream;
import javafx.scene.image.Image;
import org.toop.framework.asset.types.FileExtension;
import org.toop.framework.asset.types.LoadableResource;
import org.toop.framework.resource.types.FileExtension;
import org.toop.framework.resource.types.LoadableResource;
@FileExtension({"png", "jpg", "jpeg"})
public class ImageAsset extends BaseResource implements LoadableResource {

View File

@@ -1,4 +1,4 @@
package org.toop.framework.asset.resources;
package org.toop.framework.resource.resources;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -6,8 +6,8 @@ import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import org.toop.framework.asset.types.FileExtension;
import org.toop.framework.asset.types.LoadableResource;
import org.toop.framework.resource.types.FileExtension;
import org.toop.framework.resource.types.LoadableResource;
@FileExtension({"json"})
public class JsonAsset<T> extends BaseResource implements LoadableResource {

View File

@@ -1,11 +1,11 @@
package org.toop.framework.asset.resources;
package org.toop.framework.resource.resources;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import org.toop.framework.asset.types.BundledResource;
import org.toop.framework.asset.types.FileExtension;
import org.toop.framework.asset.types.LoadableResource;
import org.toop.framework.resource.types.BundledResource;
import org.toop.framework.resource.types.FileExtension;
import org.toop.framework.resource.types.LoadableResource;
/**
* Represents a localization resource asset that loads and manages property files containing
@@ -38,7 +38,7 @@ public class LocalizationAsset extends BaseResource implements LoadableResource,
private final String baseName = "localization";
/** Fallback locale used when no matching locale is found. */
private final Locale fallback = Locale.forLanguageTag("en_US");
private final Locale fallback = Locale.forLanguageTag("en");
/**
* Constructs a new LocalizationAsset for the specified file.

View File

@@ -1,9 +1,9 @@
package org.toop.framework.asset.resources;
package org.toop.framework.resource.resources;
import java.io.*;
import javafx.scene.media.Media;
import org.toop.framework.asset.types.FileExtension;
import org.toop.framework.asset.types.LoadableResource;
import org.toop.framework.resource.types.FileExtension;
import org.toop.framework.resource.types.LoadableResource;
@FileExtension({"mp3"})
public class MusicAsset extends BaseResource implements LoadableResource {

View File

@@ -1,4 +1,4 @@
package org.toop.framework.asset.resources;
package org.toop.framework.resource.resources;
import java.io.File;
import java.util.Locale;

View File

@@ -1,10 +1,10 @@
package org.toop.framework.asset.resources;
package org.toop.framework.resource.resources;
import java.io.*;
import java.nio.file.Files;
import javax.sound.sampled.*;
import org.toop.framework.asset.types.FileExtension;
import org.toop.framework.asset.types.LoadableResource;
import org.toop.framework.resource.types.FileExtension;
import org.toop.framework.resource.types.LoadableResource;
@FileExtension({"wav"})
public class SoundEffectAsset extends BaseResource implements LoadableResource {

View File

@@ -1,11 +1,11 @@
package org.toop.framework.asset.resources;
package org.toop.framework.resource.resources;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import org.toop.framework.asset.types.FileExtension;
import org.toop.framework.asset.types.LoadableResource;
import org.toop.framework.resource.types.FileExtension;
import org.toop.framework.resource.types.LoadableResource;
@FileExtension({"txt", "json", "xml"})
public class TextAsset extends BaseResource implements LoadableResource {

View File

@@ -1,7 +1,7 @@
package org.toop.framework.asset.types;
package org.toop.framework.resource.types;
import java.io.File;
import org.toop.framework.asset.ResourceLoader;
import org.toop.framework.resource.ResourceLoader;
/**
* Represents a resource that can be composed of multiple files, or "bundled" together under a

View File

@@ -1,11 +1,11 @@
package org.toop.framework.asset.types;
package org.toop.framework.resource.types;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.toop.framework.asset.ResourceLoader;
import org.toop.framework.asset.resources.BaseResource;
import org.toop.framework.resource.ResourceLoader;
import org.toop.framework.resource.resources.BaseResource;
/**
* Annotation to declare which file extensions a {@link BaseResource} subclass can handle.

View File

@@ -1,6 +1,6 @@
package org.toop.framework.asset.types;
package org.toop.framework.resource.types;
import org.toop.framework.asset.ResourceLoader;
import org.toop.framework.resource.ResourceLoader;
/**
* Represents a resource that can be explicitly loaded and unloaded.

View File

@@ -1,6 +1,6 @@
package org.toop.framework.asset.types;
package org.toop.framework.resource.types;
import org.toop.framework.asset.ResourceLoader;
import org.toop.framework.resource.ResourceLoader;
/**
* Marker interface for resources that should be **automatically loaded** by the {@link