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 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); }