From 6cd2c083b7f937866d4c0f64a8e18173f88738b5 Mon Sep 17 00:00:00 2001
From: lieght <49651652+BAFGdeJong@users.noreply.github.com>
Date: Wed, 1 Oct 2025 00:12:38 +0200
Subject: [PATCH] Refactored to have assets use self reflection to identify
with certain extensions
---
app/src/main/java/org/toop/Main.java | 4 +-
framework/pom.xml | 7 ++
.../org/toop/framework/asset/AssetLoader.java | 112 +++++++++++-------
.../framework/asset/resources/AudioAsset.java | 1 +
.../asset/resources/FileExtension.java | 12 ++
.../framework/asset/resources/ImageAsset.java | 3 +-
6 files changed, 95 insertions(+), 44 deletions(-)
create mode 100644 framework/src/main/java/org/toop/framework/asset/resources/FileExtension.java
diff --git a/app/src/main/java/org/toop/Main.java b/app/src/main/java/org/toop/Main.java
index 508d1d8..8fb2f17 100644
--- a/app/src/main/java/org/toop/Main.java
+++ b/app/src/main/java/org/toop/Main.java
@@ -16,7 +16,9 @@ import java.nio.file.NotDirectoryException;
public class Main {
static void main(String[] args) throws IOException, UnsupportedAudioFileException, LineUnavailableException, InterruptedException {
- AssetManager.loadAssets(new AssetLoader("app/src/main/resources/assets"));
+ AssetLoader.initialize("app/src/main/resources/assets");
+ AssetManager.loadAssets(AssetLoader.getInstance());
+
var b = new NetworkingClientManager();
var c = new SoundManager();
diff --git a/framework/pom.xml b/framework/pom.xml
index ae47b55..5e84787 100644
--- a/framework/pom.xml
+++ b/framework/pom.xml
@@ -102,6 +102,13 @@
25
+
+
+ org.reflections
+ reflections
+ 0.10.2
+
+
diff --git a/framework/src/main/java/org/toop/framework/asset/AssetLoader.java b/framework/src/main/java/org/toop/framework/asset/AssetLoader.java
index 620c77e..1c77c72 100644
--- a/framework/src/main/java/org/toop/framework/asset/AssetLoader.java
+++ b/framework/src/main/java/org/toop/framework/asset/AssetLoader.java
@@ -1,74 +1,102 @@
package org.toop.framework.asset;
-import org.toop.framework.asset.resources.AudioAsset;
import org.toop.framework.asset.resources.BaseResource;
-import org.toop.framework.asset.resources.ImageAsset;
import java.io.File;
-import java.io.FileNotFoundException;
-import java.util.ArrayList;
-import java.util.Objects;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Function;
+
+import org.reflections.Reflections;
+import org.toop.framework.asset.resources.FileExtension;
public class AssetLoader {
- private final File rootFolder;
- private final ArrayList> assets = new ArrayList<>();
- public AssetLoader(File rootFolder) {
+ private static AssetLoader INSTANCE;
+
+ private final File rootFolder;
+ private final List> assets = new CopyOnWriteArrayList<>();
+ private final Map> registry = new ConcurrentHashMap<>();
+
+ private AssetLoader(File rootFolder) {
this.rootFolder = rootFolder;
+ autoRegisterResources();
fileSearcher(rootFolder);
}
- public AssetLoader(String rootFolder) {
- this.rootFolder = new File(rootFolder);
- fileSearcher(this.rootFolder);
+ public static synchronized void initialize(String rootFolderPath) {
+ if (INSTANCE == null) {
+ INSTANCE = new AssetLoader(new File(rootFolderPath));
+ }
}
- public File getRootFolder() {
- return this.rootFolder;
+ public static AssetLoader getInstance() {
+ if (INSTANCE == null) {
+ throw new IllegalStateException("AssetLoader not initialized. Call initialize() first.");
+ }
+ return INSTANCE;
}
- public ArrayList> getAssets() {
- return this.assets;
+ public List> getAssets() {
+ return new ArrayList<>(assets);
}
- private T resourceMapper(Class type, File file) throws FileNotFoundException {
- BaseResource resource = switch (getExtension(file.getName())) {
- case "wav" -> new AudioAsset(file);
- case "png" -> new ImageAsset(file);
- default -> null;
- };
+ public void register(String extension, Function factory) {
+ registry.put(extension, factory);
+ }
+
+ private T resourceMapper(File file, Class type) {
+ String ext = getExtension(file.getName());
+ Function factory = registry.get(ext);
+
+ if (factory == null) return null;
+
+ BaseResource resource = factory.apply(file);
+
+ if (!type.isInstance(resource)) {
+ throw new IllegalArgumentException(
+ "File " + file.getName() + " is not of type " + type.getSimpleName()
+ );
+ }
- if (resource == null) return null;
- if (!type.isInstance(resource))
- throw new IllegalArgumentException("File " + file.getName() + " is not of type " + type);
return type.cast(resource);
}
- public static String getExtension(String name) {
- String extension = "";
-
- int i = name.lastIndexOf('.');
- if (i > 0) {
- extension = name.substring(i+1);
- }
- return extension;
- }
-
private void fileSearcher(final File folder) {
- for (final File fileEntry : Objects.requireNonNull(folder.listFiles())) {
+ for (File fileEntry : Objects.requireNonNull(folder.listFiles())) {
if (fileEntry.isDirectory()) {
fileSearcher(fileEntry);
} else {
- try {
- BaseResource resource = resourceMapper(BaseResource.class, fileEntry); // generic token
- if (resource != null) {
- this.assets.add(new Asset<>(fileEntry.getName(), resource));
- }
- } catch (FileNotFoundException e) {
- throw new RuntimeException(e);
+ BaseResource resource = resourceMapper(fileEntry, BaseResource.class);
+ if (resource != null) {
+ assets.add(new Asset<>(fileEntry.getName(), resource));
}
}
}
}
+ private void autoRegisterResources() {
+ Reflections reflections = new Reflections("org.toop.framework.asset.resources");
+ Set> classes = reflections.getSubTypesOf(BaseResource.class);
+
+ for (Class extends BaseResource> cls : classes) {
+ if (!cls.isAnnotationPresent(FileExtension.class)) continue;
+ FileExtension annotation = cls.getAnnotation(FileExtension.class);
+ for (String ext : annotation.value()) {
+ registry.put(ext, file -> {
+ try {
+ return cls.getConstructor(File.class).newInstance(file);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+ }
+ }
+
+ public static String getExtension(String name) {
+ int i = name.lastIndexOf('.');
+ return (i > 0) ? name.substring(i + 1) : "";
+ }
}
diff --git a/framework/src/main/java/org/toop/framework/asset/resources/AudioAsset.java b/framework/src/main/java/org/toop/framework/asset/resources/AudioAsset.java
index e6fbaf8..6bcd809 100644
--- a/framework/src/main/java/org/toop/framework/asset/resources/AudioAsset.java
+++ b/framework/src/main/java/org/toop/framework/asset/resources/AudioAsset.java
@@ -3,6 +3,7 @@ package org.toop.framework.asset.resources;
import javax.sound.sampled.*;
import java.io.*;
+@FileExtension({"wav"})
public class AudioAsset extends BaseResource implements LoadableResource {
private AudioInputStream audioInputStream = null;
diff --git a/framework/src/main/java/org/toop/framework/asset/resources/FileExtension.java b/framework/src/main/java/org/toop/framework/asset/resources/FileExtension.java
new file mode 100644
index 0000000..4aceb00
--- /dev/null
+++ b/framework/src/main/java/org/toop/framework/asset/resources/FileExtension.java
@@ -0,0 +1,12 @@
+package org.toop.framework.asset.resources;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface FileExtension {
+ String[] value();
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/toop/framework/asset/resources/ImageAsset.java b/framework/src/main/java/org/toop/framework/asset/resources/ImageAsset.java
index 4670600..0524bda 100644
--- a/framework/src/main/java/org/toop/framework/asset/resources/ImageAsset.java
+++ b/framework/src/main/java/org/toop/framework/asset/resources/ImageAsset.java
@@ -4,11 +4,12 @@ import javafx.scene.image.Image;
import java.io.File;
import java.io.FileNotFoundException;
+@FileExtension({"png"})
public class ImageAsset extends BaseResource implements LoadableResource {
private Image image;
private boolean isLoaded = false;
- public ImageAsset(final File file) throws FileNotFoundException {
+ public ImageAsset(final File file) {
super(file);
}