diff --git a/src/main/java/com/volmit/iris/core/loader/MatterResourceLoader.java b/src/main/java/com/volmit/iris/core/loader/MatterResourceLoader.java
new file mode 100644
index 000000000..a87db59d9
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/loader/MatterResourceLoader.java
@@ -0,0 +1,229 @@
+/*
+ * Iris is a World Generator for Minecraft Bukkit Servers
+ * Copyright (c) 2021 Arcane Arts (Volmit Software)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.volmit.iris.core.loader;
+
+import com.volmit.iris.Iris;
+import com.volmit.iris.engine.object.IrisObject;
+import com.volmit.iris.util.collection.KList;
+import com.volmit.iris.util.collection.KMap;
+import com.volmit.iris.util.collection.KSet;
+import com.volmit.iris.util.format.C;
+import com.volmit.iris.util.format.Form;
+import com.volmit.iris.util.math.M;
+import com.volmit.iris.util.matter.IrisMatter;
+import com.volmit.iris.util.matter.Matter;
+import com.volmit.iris.util.scheduling.ChronoLatch;
+import com.volmit.iris.util.scheduling.J;
+import com.volmit.iris.util.scheduling.PrecisionStopwatch;
+
+import java.io.File;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class MatterResourceLoader extends ResourceLoader {
+ private final ChronoLatch useFlip = new ChronoLatch(2222);
+ private final KMap useCache = new KMap<>();
+ private final ChronoLatch cl;
+ private final AtomicInteger unload;
+
+ public MatterResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
+ super(root, idm, folderName, resourceTypeName, IrisMatter.class);
+ cl = new ChronoLatch(30000);
+ unload = new AtomicInteger(0);
+ }
+
+ public boolean supportsSchemas() {
+ return false;
+ }
+
+ public int getSize() {
+ return loadCache.size();
+ }
+
+ public int getTotalStorage() {
+ return getSize();
+ }
+
+ public void clean() {
+ if (useFlip.flip()) {
+ unloadLast(30000);
+ }
+ }
+
+ public void unloadLast(long age) {
+ String v = getOldest();
+
+ if (v == null) {
+ return;
+ }
+
+ if (M.ms() - useCache.get(v) > age) {
+ unload(v);
+ }
+ }
+
+ private String getOldest() {
+ long min = M.ms();
+ String v = null;
+
+ for (String i : useCache.k()) {
+ long t = useCache.get(i);
+ if (t < min) {
+ min = t;
+ v = i;
+ }
+ }
+
+ return v;
+ }
+
+ private void unload(String v) {
+ lock.lock();
+ useCache.remove(v);
+ loadCache.remove(v);
+ lock.unlock();
+ unload.getAndIncrement();
+
+ if (unload.get() == 1) {
+ cl.flip();
+ }
+
+ if (cl.flip()) {
+ J.a(() -> {
+ Iris.verbose("Unloaded " + C.WHITE + unload.get() + " " + resourceTypeName + (unload.get() == 1 ? "" : "s") + C.GRAY + " to optimize memory usage." + " (" + Form.f(getLoadCache().size()) + " " + resourceTypeName + (loadCache.size() == 1 ? "" : "s") + " Loaded)");
+ unload.set(0);
+ });
+ }
+ }
+
+ public IrisMatter loadFile(File j, String key, String name) {
+ lock.lock();
+ try {
+ PrecisionStopwatch p = PrecisionStopwatch.start();
+ IrisMatter t = (IrisMatter) Matter.read(j);
+ loadCache.put(key, t);
+ t.setLoadKey(name);
+ t.setLoader(manager);
+ t.setLoadFile(j);
+ logLoad(j, t);
+ lock.unlock();
+ tlt.addAndGet(p.getMilliseconds());
+ return t;
+ } catch (Throwable e) {
+ Iris.reportError(e);
+ lock.unlock();
+ Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
+ return null;
+ }
+ }
+
+ public String[] getPossibleKeys() {
+ if (possibleKeys != null) {
+ return possibleKeys;
+ }
+
+ Iris.debug("Building " + resourceTypeName + " Possibility Lists");
+ KSet m = new KSet<>();
+
+ for (File i : getFolders()) {
+ for (File j : i.listFiles()) {
+ if (j.isFile() && j.getName().endsWith(".matter")) {
+ m.add(j.getName().replaceAll("\\Q.matter\\E", ""));
+ } else if (j.isDirectory()) {
+ for (File k : j.listFiles()) {
+ if (k.isFile() && k.getName().endsWith(".matter")) {
+ m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.matter\\E", ""));
+ } else if (k.isDirectory()) {
+ for (File l : k.listFiles()) {
+ if (l.isFile() && l.getName().endsWith(".matter")) {
+ m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.matter\\E", ""));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ KList v = new KList<>(m);
+ possibleKeys = v.toArray(new String[0]);
+ return possibleKeys;
+ }
+
+ public File findFile(String name) {
+ lock.lock();
+ for (File i : getFolders(name)) {
+ for (File j : i.listFiles()) {
+ if (j.isFile() && j.getName().endsWith(".matter") && j.getName().split("\\Q.\\E")[0].equals(name)) {
+ lock.unlock();
+ return j;
+ }
+ }
+
+ File file = new File(i, name + ".matter");
+
+ if (file.exists()) {
+ lock.unlock();
+ return file;
+ }
+ }
+
+ Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
+
+ lock.unlock();
+ return null;
+ }
+
+ public IrisMatter load(String name) {
+ return load(name, true);
+ }
+
+ public IrisMatter load(String name, boolean warn) {
+ String key = name + "-" + objectClass.getCanonicalName();
+
+ if (loadCache.containsKey(key)) {
+ IrisMatter t = loadCache.get(key);
+ useCache.put(key, M.ms());
+ return t;
+ }
+
+ lock.lock();
+ for (File i : getFolders(name)) {
+ for (File j : i.listFiles()) {
+ if (j.isFile() && j.getName().endsWith(".matter") && j.getName().split("\\Q.\\E")[0].equals(name)) {
+ useCache.put(key, M.ms());
+ lock.unlock();
+ return loadFile(j, key, name);
+ }
+ }
+
+ File file = new File(i, name + ".matter");
+
+ if (file.exists()) {
+ useCache.put(key, M.ms());
+ lock.unlock();
+ return loadFile(file, key, name);
+ }
+ }
+
+ Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
+
+ lock.unlock();
+ return null;
+ }
+}
diff --git a/src/main/java/com/volmit/iris/util/matter/IrisMatter.java b/src/main/java/com/volmit/iris/util/matter/IrisMatter.java
index d52052418..f8ccd8692 100644
--- a/src/main/java/com/volmit/iris/util/matter/IrisMatter.java
+++ b/src/main/java/com/volmit/iris/util/matter/IrisMatter.java
@@ -19,10 +19,13 @@
package com.volmit.iris.util.matter;
import com.volmit.iris.Iris;
+import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.util.collection.KMap;
+import com.volmit.iris.util.json.JSONObject;
+import com.volmit.iris.util.plugin.VolmitSender;
import lombok.Getter;
-public class IrisMatter implements Matter {
+public class IrisMatter extends IrisRegistrant implements Matter {
protected static final KMap, MatterSlice>> slicers = buildSlicers();
@Getter
@@ -74,4 +77,19 @@ public class IrisMatter implements Matter {
return null;
}
+
+ @Override
+ public String getFolderName() {
+ return "matter";
+ }
+
+ @Override
+ public String getTypeName() {
+ return "matter";
+ }
+
+ @Override
+ public void scanForErrors(JSONObject p, VolmitSender sender) {
+
+ }
}