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) { + + } }