From 4ee31db7a03904570f4aea9f72647fd268e18b18 Mon Sep 17 00:00:00 2001 From: Daniel Mills Date: Mon, 9 Aug 2021 09:06:45 -0400 Subject: [PATCH] Mantle flagging --- .../iris/util/collection/StateList.java | 126 ++++++++++++++++++ .../com/volmit/iris/util/mantle/Mantle.java | 43 ++++++ .../volmit/iris/util/mantle/MantleChunk.java | 34 ++--- .../volmit/iris/util/mantle/MantleFlag.java | 33 +++++ 4 files changed, 220 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/volmit/iris/util/collection/StateList.java create mode 100644 src/main/java/com/volmit/iris/util/mantle/MantleFlag.java diff --git a/src/main/java/com/volmit/iris/util/collection/StateList.java b/src/main/java/com/volmit/iris/util/collection/StateList.java new file mode 100644 index 000000000..62490d7f2 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/collection/StateList.java @@ -0,0 +1,126 @@ +/* + * 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.util.collection; + +public class StateList +{ + private final KList states; + + public StateList(String... states) + { + this.states = new KList(states); + + if(getBits() > 64) + { + throw new RuntimeException("StateLists cannot exceed 64 bits! You are trying to use " + getBits() + " bits!"); + } + } + + public StateList(Enum... states) + { + this.states = new KList>().convert(Enum::name); + + if(getBits() > 64) + { + throw new RuntimeException("StateLists cannot exceed 64 bits! You are trying to use " + getBits() + " bits!"); + } + } + + public long max() + { + return (long) (Math.pow(2, getBits()) - 1); + } + + public KList getEnabled(long list) + { + KList f = new KList<>(); + + for(String i : states) + { + if(is(list, i)) + { + f.add(i); + } + } + + return f; + } + + public long of(String... enabledStates) + { + long b = 0; + + for(String i : enabledStates) + { + b |= getBit(i); + } + + return b; + } + + public long set(long list, String state, boolean enabled) + { + long bit = getBit(state); + boolean is = is(list, state); + + if(enabled && !is) + { + return list | bit; + } + + else if(!enabled && is) + { + return list ^ bit; + } + + return list; + } + + public boolean is(long list, String state) + { + long bit = getBit(state); + + return bit > 0 && (list & bit) == bit; + } + + public boolean hasBit(String state) + { + return getBit(state) > 0; + } + + public long getBit(String state) + { + return getBit(states.indexOf(state)); + } + + public long getBit(int index) + { + return (long) (index < 0 ? -1 : Math.pow(2, index)); + } + + public int getBytes() + { + return getBits() == 0 ? 0 : ((getBits() >> 2) + 1); + } + + public int getBits() + { + return states.size(); + } +} diff --git a/src/main/java/com/volmit/iris/util/mantle/Mantle.java b/src/main/java/com/volmit/iris/util/mantle/Mantle.java index f2026c452..f607a530d 100644 --- a/src/main/java/com/volmit/iris/util/mantle/Mantle.java +++ b/src/main/java/com/volmit/iris/util/mantle/Mantle.java @@ -23,6 +23,7 @@ import com.volmit.iris.engine.data.cache.Cache; import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.documentation.BlockCoordinates; +import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.documentation.RegionCoordinates; import com.volmit.iris.util.format.C; import com.volmit.iris.util.format.Form; @@ -77,6 +78,48 @@ public class Mantle { Iris.debug("Opened The Mantle " + C.DARK_AQUA + dataFolder.getAbsolutePath()); } + @ChunkCoordinates + public void raiseFlag(int x, int z, MantleFlag flag, Runnable r) + { + if(!hasFlag(x, z, flag)) + { + flag(x, z, flag, true); + r.run(); + } + } + + @ChunkCoordinates + public void lowerFlag(int x, int z, MantleFlag flag, Runnable r) + { + if(hasFlag(x, z, flag)) + { + flag(x, z, flag, false); + r.run(); + } + } + + @ChunkCoordinates + public void flag(int x, int z, MantleFlag flag, boolean flagged) + { + try { + get(x >> 5, z >> 5).get().get(x & 31, z & 31).flag(flag, flagged); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + + @ChunkCoordinates + public boolean hasFlag(int x, int z, MantleFlag flag) + { + try { + get(x >> 5, z >> 5).get().get(x & 31, z & 31).isFlagged(flag); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + + return false; + } + /** * Set data T at the given block position. This method will attempt to find a * Tectonic Plate either by loading it or creating a new one. This method uses diff --git a/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java b/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java index ebbd93916..28fd95243 100644 --- a/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java +++ b/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java @@ -19,6 +19,8 @@ package com.volmit.iris.util.mantle; import com.volmit.iris.util.collection.KSet; +import com.volmit.iris.util.collection.StateList; +import com.volmit.iris.util.data.Varint; import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.matter.IrisMatter; import com.volmit.iris.util.matter.Matter; @@ -26,6 +28,7 @@ import com.volmit.iris.util.matter.Matter; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.concurrent.atomic.AtomicIntegerArray; import java.util.concurrent.atomic.AtomicReferenceArray; /** @@ -33,7 +36,8 @@ import java.util.concurrent.atomic.AtomicReferenceArray; * Mantle Chunks are fully atomic & thread safe */ public class MantleChunk { - private final KSet flags; + private static final StateList state = MantleFlag.getStateList(); + private final AtomicIntegerArray flags; private final AtomicReferenceArray sections; /** @@ -44,7 +48,7 @@ public class MantleChunk { @ChunkCoordinates public MantleChunk(int sectionHeight) { sections = new AtomicReferenceArray<>(sectionHeight); - flags = new KSet<>(); + flags = new AtomicIntegerArray(MantleFlag.values().length); } /** @@ -58,10 +62,10 @@ public class MantleChunk { public MantleChunk(int sectionHeight, DataInputStream din) throws IOException, ClassNotFoundException { this(sectionHeight); int s = din.readByte(); - int f = din.readByte(); - for (int i = 0; i < f; i++) { - flags.add(din.readUTF()); + for(String i : state.getEnabled(Varint.readUnsignedVarLong(din))) + { + flags.set(MantleFlag.valueOf(i).ordinal(), 1); } for (int i = 0; i < s; i++) { @@ -71,16 +75,12 @@ public class MantleChunk { } } - public void flag(String s, boolean f) { - if (f) { - flags.add(s); - } else { - flags.remove(s); - } + public void flag(MantleFlag flag, boolean f) { + flags.set(flag.ordinal(), f ? 1 : 0); } - public boolean isFlagged(String s) { - return flags.contains(s); + public boolean isFlagged(MantleFlag flag) { + return flags.get(flags.get(flag.ordinal())) == 1; } /** @@ -150,12 +150,14 @@ public class MantleChunk { */ public void write(DataOutputStream dos) throws IOException { dos.writeByte(sections.length()); - dos.writeByte(flags.size()); + long data = 0; - for (String i : flags) { - dos.writeUTF(i); + for (int i = 0; i < flags.length(); i++) { + state.set(data, MantleFlag.values()[i].name(), flags.get(i) == 1); } + Varint.writeUnsignedVarLong(data, dos); + for (int i = 0; i < sections.length(); i++) { if (exists(i)) { dos.writeBoolean(true); diff --git a/src/main/java/com/volmit/iris/util/mantle/MantleFlag.java b/src/main/java/com/volmit/iris/util/mantle/MantleFlag.java new file mode 100644 index 000000000..128773092 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/mantle/MantleFlag.java @@ -0,0 +1,33 @@ +/* + * 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.util.mantle; + +import com.volmit.iris.util.collection.StateList; + +public enum MantleFlag { + OBJECT, + VACUUM, + JIGSAW, + FEATURE + ; + static StateList getStateList() + { + return new StateList(MantleFlag.values()); + } +}