Merge pull request #633 from VolmitSoftware/matter

Basic matter functions
This commit is contained in:
Dan 2021-09-11 13:16:54 -04:00 committed by GitHub
commit 3864708cf1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 471 additions and 4 deletions

View File

@ -54,6 +54,7 @@ import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.context.IrisContext; import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.util.format.C; import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.IrisMatter;
import com.volmit.iris.util.scheduling.ChronoLatch; import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
import lombok.Data; import lombok.Data;
@ -84,6 +85,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
private ResourceLoader<IrisExpression> expressionLoader; private ResourceLoader<IrisExpression> expressionLoader;
private ResourceLoader<IrisObject> objectLoader; private ResourceLoader<IrisObject> objectLoader;
private ResourceLoader<IrisScript> scriptLoader; private ResourceLoader<IrisScript> scriptLoader;
private ResourceLoader<IrisMatter> matterLoader;
private ResourceLoader<IrisCave> caveLoader; private ResourceLoader<IrisCave> caveLoader;
private ResourceLoader<IrisRavine> ravineLoader; private ResourceLoader<IrisRavine> ravineLoader;
private KMap<String, KList<String>> possibleSnippets; private KMap<String, KList<String>> possibleSnippets;
@ -167,6 +169,10 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
return loadAny(key, (dm) -> dm.getScriptLoader().load(key, false)); return loadAny(key, (dm) -> dm.getScriptLoader().load(key, false));
} }
public static IrisMatter loadAnyMatter(String key) {
return loadAny(key, (dm) -> dm.getMatterLoader().load(key, false));
}
public static IrisRavine loadAnyRavine(String key) { public static IrisRavine loadAnyRavine(String key) {
return loadAny(key, (dm) -> dm.getRavineLoader().load(key, false)); return loadAny(key, (dm) -> dm.getRavineLoader().load(key, false));
} }
@ -280,6 +286,8 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
ResourceLoader<T> r = null; ResourceLoader<T> r = null;
if (registrant.equals(IrisObject.class)) { if (registrant.equals(IrisObject.class)) {
r = (ResourceLoader<T>) new ObjectResourceLoader(dataFolder, this, rr.getFolderName(), rr.getTypeName()); r = (ResourceLoader<T>) new ObjectResourceLoader(dataFolder, this, rr.getFolderName(), rr.getTypeName());
} else if (registrant.equals(IrisMatter.class)) {
r = (ResourceLoader<T>) new MatterResourceLoader(dataFolder, this, rr.getFolderName(), rr.getTypeName());
} else if (registrant.equals(IrisScript.class)) { } else if (registrant.equals(IrisScript.class)) {
r = (ResourceLoader<T>) new ScriptResourceLoader(dataFolder, this, rr.getFolderName(), rr.getTypeName()); r = (ResourceLoader<T>) new ScriptResourceLoader(dataFolder, this, rr.getFolderName(), rr.getTypeName());
} else { } else {
@ -325,6 +333,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
this.blockLoader = registerLoader(IrisBlockData.class); this.blockLoader = registerLoader(IrisBlockData.class);
this.expressionLoader = registerLoader(IrisExpression.class); this.expressionLoader = registerLoader(IrisExpression.class);
this.objectLoader = registerLoader(IrisObject.class); this.objectLoader = registerLoader(IrisObject.class);
this.matterLoader = registerLoader(IrisMatter.class);
this.scriptLoader = registerLoader(IrisScript.class); this.scriptLoader = registerLoader(IrisScript.class);
gson = builder.create(); gson = builder.create();
} }

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
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<IrisMatter> {
private final ChronoLatch useFlip = new ChronoLatch(2222);
private final KMap<String, Long> 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<String> 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<String> 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;
}
}

View File

@ -0,0 +1,38 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.engine.object;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.Snippet;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Snippet("matter-placer")
@EqualsAndHashCode()
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Desc("Represents an iris object placer. It places objects.")
@Data
public class IrisMatterPlacement {
}

View File

@ -392,6 +392,24 @@ public class IrisObject extends IrisRegistrant {
out.close(); out.close();
} }
public void shrinkwrap() {
BlockVector min = new BlockVector();
BlockVector max = new BlockVector();
for (BlockVector i : getBlocks().keySet()) {
min.setX(Math.min(min.getX(), i.getX()));
min.setY(Math.min(min.getY(), i.getY()));
min.setZ(Math.min(min.getZ(), i.getZ()));
max.setX(Math.max(max.getX(), i.getX()));
max.setY(Math.max(max.getY(), i.getY()));
max.setZ(Math.max(max.getZ(), i.getZ()));
}
w = max.getBlockX() - min.getBlockX();
h = max.getBlockY() - min.getBlockY();
d = max.getBlockZ() - min.getBlockZ();
}
public void clean() { public void clean() {
KMap<BlockVector, BlockData> d = new KMap<>(); KMap<BlockVector, BlockData> d = new KMap<>();

View File

@ -28,6 +28,7 @@ import com.volmit.iris.util.function.Consumer5;
import com.volmit.iris.util.function.Consumer6; import com.volmit.iris.util.function.Consumer6;
import com.volmit.iris.util.function.Consumer8; import com.volmit.iris.util.function.Consumer8;
import com.volmit.iris.util.function.Function3; import com.volmit.iris.util.function.Function3;
import com.volmit.iris.util.function.Function4;
import com.volmit.iris.util.function.NoiseProvider; import com.volmit.iris.util.function.NoiseProvider;
import com.volmit.iris.util.function.NoiseProvider3; import com.volmit.iris.util.function.NoiseProvider3;
import com.volmit.iris.util.function.Supplier3R; import com.volmit.iris.util.function.Supplier3R;
@ -749,6 +750,18 @@ public interface Hunk<T> {
return this; return this;
} }
default Hunk<T> updateSync(Function4<Integer, Integer, Integer, T, T> c) {
for (int i = 0; i < getWidth(); i++) {
for (int j = 0; j < getHeight(); j++) {
for (int k = 0; k < getDepth(); k++) {
set(i,j,k,c.apply(i, j, k, get(i, j, k)));
}
}
}
return this;
}
default Hunk<T> iterateSyncIO(Consumer4IO<Integer, Integer, Integer, T> c) throws IOException { default Hunk<T> iterateSyncIO(Consumer4IO<Integer, Integer, Integer, T> c) throws IOException {
for (int i = 0; i < getWidth(); i++) { for (int i = 0; i < getWidth(); i++) {
for (int j = 0; j < getHeight(); j++) { for (int j = 0; j < getHeight(); j++) {

View File

@ -31,8 +31,10 @@ import com.volmit.iris.util.documentation.RegionCoordinates;
import com.volmit.iris.util.format.C; import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form; import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.function.Consumer4; import com.volmit.iris.util.function.Consumer4;
import com.volmit.iris.util.math.AxisAlignedBB;
import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.M;
import com.volmit.iris.util.matter.Matter; import com.volmit.iris.util.matter.Matter;
import com.volmit.iris.util.matter.MatterSlice;
import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.HyperLock; import com.volmit.iris.util.parallel.HyperLock;
import com.volmit.iris.util.parallel.MultiBurst; import com.volmit.iris.util.parallel.MultiBurst;
@ -504,4 +506,13 @@ public class Mantle {
public int getLoadedRegionCount() { public int getLoadedRegionCount() {
return loadedRegions.size(); return loadedRegions.size();
} }
public <T> void set(int x, int y, int z, MatterSlice<T> slice) {
if(slice.isEmpty())
{
return;
}
slice.iterateSync((xx,yy,zz,t) -> set(x+xx,y+yy,z+zz,t));
}
} }

View File

@ -19,10 +19,13 @@
package com.volmit.iris.util.matter; package com.volmit.iris.util.matter;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.plugin.VolmitSender;
import lombok.Getter; import lombok.Getter;
public class IrisMatter implements Matter { public class IrisMatter extends IrisRegistrant implements Matter {
protected static final KMap<Class<?>, MatterSlice<?>> slicers = buildSlicers(); protected static final KMap<Class<?>, MatterSlice<?>> slicers = buildSlicers();
@Getter @Getter
@ -74,4 +77,19 @@ public class IrisMatter implements Matter {
return null; return null;
} }
@Override
public String getFolderName() {
return "matter";
}
@Override
public String getTypeName() {
return "matter";
}
@Override
public void scanForErrors(JSONObject p, VolmitSender sender) {
}
} }

View File

@ -18,14 +18,18 @@
package com.volmit.iris.util.matter; package com.volmit.iris.util.matter;
import com.volmit.iris.engine.object.IrisObject;
import com.volmit.iris.engine.object.IrisPosition; import com.volmit.iris.engine.object.IrisPosition;
import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.Varint; import com.volmit.iris.util.data.Varint;
import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.hunk.Hunk; import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.BlockPosition; import com.volmit.iris.util.math.BlockPosition;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.util.BlockVector;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
@ -36,6 +40,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
@ -57,6 +62,26 @@ import java.util.function.Function;
public interface Matter { public interface Matter {
int VERSION = 1; int VERSION = 1;
static Matter from(IrisObject object)
{
object.clean();
object.shrinkwrap();
BlockVector min = new BlockVector();
Matter m = new IrisMatter(object.getW(), object.getH(), object.getD());
for (BlockVector i : object.getBlocks().keySet()) {
min.setX(Math.min(min.getX(), i.getX()));
min.setY(Math.min(min.getY(), i.getY()));
min.setZ(Math.min(min.getZ(), i.getZ()));
}
for (BlockVector i : object.getBlocks().keySet()) {
m.slice(BlockData.class).set(i.getBlockX() - min.getBlockX(), i.getBlockY() - min.getBlockY(), i.getBlockZ() - min.getBlockZ(), object.getBlocks().get(i));
}
return m;
}
static Matter read(File f) throws IOException, ClassNotFoundException { static Matter read(File f) throws IOException, ClassNotFoundException {
FileInputStream in = new FileInputStream(f); FileInputStream in = new FileInputStream(f);
Matter m = read(in); Matter m = read(in);
@ -64,6 +89,13 @@ public interface Matter {
return m; return m;
} }
default Matter copy()
{
Matter m = new IrisMatter(getWidth(), getHeight(), getDepth());
getSliceMap().forEach((k,v) -> m.slice(k).forceInject(v));
return m;
}
static Matter read(InputStream in) throws IOException, ClassNotFoundException { static Matter read(InputStream in) throws IOException, ClassNotFoundException {
return read(in, (b) -> new IrisMatter(b.getX(), b.getY(), b.getZ())); return read(in, (b) -> new IrisMatter(b.getX(), b.getY(), b.getZ()));
} }
@ -164,7 +196,7 @@ public interface Matter {
* @return the center X * @return the center X
*/ */
default int getCenterX() { default int getCenterX() {
return Math.round(getWidth() / 2); return (int) Math.round(getWidth() / 2D);
} }
/** /**
@ -173,7 +205,7 @@ public interface Matter {
* @return the center Y * @return the center Y
*/ */
default int getCenterY() { default int getCenterY() {
return Math.round(getHeight() / 2); return (int) Math.round(getHeight() / 2D);
} }
/** /**
@ -182,7 +214,7 @@ public interface Matter {
* @return the center Z * @return the center Z
*/ */
default int getCenterZ() { default int getCenterZ() {
return Math.round(getDepth() / 2); return (int) Math.round(getDepth() / 2D);
} }
/** /**

View File

@ -0,0 +1,24 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter;
@FunctionalInterface
public interface MatterFilter<T> {
T update(int x, int y, int z, T t);
}

View File

@ -0,0 +1,60 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter;
import com.volmit.iris.util.mantle.Mantle;
public interface MatterPlacer {
int getHeight(int x, int z, boolean ignoreFluid);
Mantle getMantle();
default <T> void set(int x, int y, int z, T t)
{
getMantle().set(x,y,z,t);
}
default <T> T get(int x, int y, int z, Class<T> t)
{
return getMantle().get(x, y, z, t);
}
default void set(int x, int y, int z, Matter matter)
{
for(MatterSlice<?> i : matter.getSliceMap().values())
{
set(x, y, z, i);
}
}
default <T> void set(int x, int y, int z, MatterSlice<T> slice)
{
getMantle().set(x, y, z, slice);
}
default int getHeight(int x, int z)
{
return getHeight(x, z, true);
}
default int getHeightOrFluid(int x, int z)
{
return getHeight(x, z, false);
}
}

View File

@ -34,6 +34,21 @@ import java.io.IOException;
public interface MatterSlice<T> extends Hunk<T> { public interface MatterSlice<T> extends Hunk<T> {
Class<T> getType(); Class<T> getType();
default void applyFilter(MatterFilter<T> filter)
{
updateSync(filter::update);
}
default void inject(MatterSlice<T> slice)
{
iterateSync(slice::set);
}
default void forceInject(MatterSlice<?> slice)
{
inject((MatterSlice<T>) slice);
}
void writeNode(T b, DataOutputStream dos) throws IOException; void writeNode(T b, DataOutputStream dos) throws IOException;
T readNode(DataInputStream din) throws IOException; T readNode(DataInputStream din) throws IOException;