diff --git a/pom.xml b/pom.xml
index 9ace1338..0ee28eb1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -187,6 +187,15 @@
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 21
+ --enable-preview
+
+
diff --git a/src/main/java/dev/hilligans/ourcraft/Block/BlockState/NewBlockState.java b/src/main/java/dev/hilligans/ourcraft/Block/BlockState/NewBlockState.java
index 4aeed7e1..faece03f 100644
--- a/src/main/java/dev/hilligans/ourcraft/Block/BlockState/NewBlockState.java
+++ b/src/main/java/dev/hilligans/ourcraft/Block/BlockState/NewBlockState.java
@@ -80,4 +80,13 @@ public IBlockState setBlockStateID(int val) {
this.blockStateReferenceID = val;
return this;
}
+
+ @Override
+ public String toString() {
+ return "NewBlockState{" +
+ "blockStateReferenceID=" + blockStateReferenceID +
+ ", blockData=" + blockData +
+ ", block=" + block +
+ '}';
+ }
}
diff --git a/src/main/java/dev/hilligans/ourcraft/ClientMain.java b/src/main/java/dev/hilligans/ourcraft/ClientMain.java
index dd8cf35e..2f67c20b 100644
--- a/src/main/java/dev/hilligans/ourcraft/ClientMain.java
+++ b/src/main/java/dev/hilligans/ourcraft/ClientMain.java
@@ -1,13 +1,21 @@
package dev.hilligans.ourcraft;
+import dev.hilligans.ourcraft.Block.Blocks;
import dev.hilligans.ourcraft.Client.Client;
import dev.hilligans.ourcraft.Client.Rendering.Graphics.API.IGraphicsEngine;
import dev.hilligans.ourcraft.Util.ArgumentContainer;
import dev.hilligans.ourcraft.Util.Side;
+import dev.hilligans.ourcraft.World.NewWorldSystem.GlobalPaletteAtomicSubChunk;
+import org.lwjgl.system.MemoryUtil;
+import sun.misc.Unsafe;
import java.io.IOException;
+import java.lang.invoke.VarHandle;
+import java.lang.reflect.Field;
import java.util.concurrent.locks.LockSupport;
+import static java.lang.StringTemplate.STR;
+
public class ClientMain {
public static Client client;
@@ -49,6 +57,38 @@ public static void main(String[] args) throws IOException {
client.startClient();
}
+ private static sun.misc.Unsafe getUnsafeInstance() {
+ java.lang.reflect.Field[] fields = sun.misc.Unsafe.class.getDeclaredFields();
+
+ /*
+ Different runtimes use different names for the Unsafe singleton,
+ so we cannot use .getDeclaredField and we scan instead. For example:
+
+ Oracle: theUnsafe
+ PERC : m_unsafe_instance
+ Android: THE_ONE
+ */
+ for (java.lang.reflect.Field field : fields) {
+ if (!field.getType().equals(sun.misc.Unsafe.class)) {
+ continue;
+ }
+
+ int modifiers = field.getModifiers();
+ if (!(java.lang.reflect.Modifier.isStatic(modifiers) && java.lang.reflect.Modifier.isFinal(modifiers))) {
+ continue;
+ }
+
+ try {
+ field.setAccessible(true);
+ return (sun.misc.Unsafe)field.get(null);
+ } catch (Exception ignored) {
+ }
+ break;
+ }
+
+ throw new UnsupportedOperationException("LWJGL requires sun.misc.Unsafe to be available.");
+ }
+
public static int getWindowX() {
return client == null ? 0 : client.windowX;
}
diff --git a/src/main/java/dev/hilligans/ourcraft/Server/Concurrent/IAtomicSubChunk.java b/src/main/java/dev/hilligans/ourcraft/Server/Concurrent/IAtomicSubChunk.java
new file mode 100644
index 00000000..13aac0ab
--- /dev/null
+++ b/src/main/java/dev/hilligans/ourcraft/Server/Concurrent/IAtomicSubChunk.java
@@ -0,0 +1,22 @@
+package dev.hilligans.ourcraft.Server.Concurrent;
+
+import dev.hilligans.ourcraft.Block.BlockState.IBlockState;
+import dev.hilligans.ourcraft.World.NewWorldSystem.ISubChunk;
+
+public interface IAtomicSubChunk extends ISubChunk {
+
+ IBlockState setBlockStateAtomic(int x, int y, int z, IBlockState blockState);
+
+
+ /**
+ * Used to replace an old blockstate with a new one
+ * useful if you want to do say a plant growing, so you can change the blockstate without having to grab the write lock
+ * @param x x pos in subchunk
+ * @param y y pos in subchunk
+ * @param z z pos in subchunk
+ * @param expected the blockstate to replace if it still exists
+ * @param to the new blockstate
+ * @return true if the expected blockstate match and the block was set, false otherwise
+ */
+ boolean swapBlockStateAtomic(int x, int y, int z, IBlockState expected, IBlockState to);
+}
diff --git a/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/CubicChunk.java b/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/CubicChunk.java
index 95da8f1f..f009a6cf 100644
--- a/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/CubicChunk.java
+++ b/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/CubicChunk.java
@@ -64,7 +64,7 @@ public IBlockState getBlockState1(long x, long y, long z) {
if(subChunks[index] == null) {
return Blocks.AIR.getDefaultState1();
}
- return subChunks[index].getBlockState(x & 15, y & 15, z & 15);
+ return subChunks[index].getBlockState((int) (x & 15), (int) (y & 15), (int) (z & 15));
}
@Override
@@ -80,7 +80,7 @@ public void setBlockState(long x, long y, long z, IBlockState blockState) {
subChunk = new GlobalPaletteImpl(16,16);
subChunks[index] = subChunk;
}
- subChunk.setBlockState(x & 15, y & 15, z & 15, blockState);
+ subChunk.setBlockState((int) (x & 15), (int) (y & 15), (int) (z & 15), blockState);
}
@Override
diff --git a/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/GlobalPaletteAtomicSubChunk.java b/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/GlobalPaletteAtomicSubChunk.java
new file mode 100644
index 00000000..91a2f8c1
--- /dev/null
+++ b/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/GlobalPaletteAtomicSubChunk.java
@@ -0,0 +1,89 @@
+package dev.hilligans.ourcraft.World.NewWorldSystem;
+
+import dev.hilligans.ourcraft.Block.BlockState.IBlockState;
+import dev.hilligans.ourcraft.Server.Concurrent.IAtomicSubChunk;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+
+public class GlobalPaletteAtomicSubChunk implements IAtomicSubChunk {
+
+ static final VarHandle ARRAY_HANDLE = MethodHandles.arrayElementVarHandle(int[].class);
+ public ArrayList blockStates;
+ public int[] blocks = new int[16 * 16 * 16 / 4];
+
+ public GlobalPaletteAtomicSubChunk(ArrayList blockStates) {
+ this.blockStates = blockStates;
+ if(blockStates.size() > Short.MAX_VALUE * 2) {
+ throw new RuntimeException("Unable to use this subchunk impl");
+ }
+ }
+
+
+ @Override
+ public int getWidth() {
+ return 16;
+ }
+
+ @Override
+ public int getHeight() {
+ return 16;
+ }
+
+ @Override
+ public IBlockState getBlockState(int x, int y, int z) {
+ return blockStates.get((blocks[getIndex(x, y, z)] >> 16 * (z & 0b11)) & 0xFFFF);
+ }
+
+ @Override
+ public IBlockState setBlockState(int x, int y, int z, IBlockState blockState) {
+ int shift = 16 * (z & 0b11);
+ int id = blockState.getBlockStateID() << shift;
+ int and = 0xFFFF << shift;
+ int index = getIndex(x, y, z);
+ int v = blocks[index];
+ blocks[index] = v & and | id;
+ return blockStates.get((v >> shift) & 0xFFFF);
+ }
+
+ @Override
+ public IBlockState setBlockStateAtomic(int x, int y, int z, IBlockState blockState) {
+ int shift = 16 * (z & 0b11);
+ int id = blockState.getBlockStateID() << shift;
+ int and = 0xFFFF << shift;
+ int index = getIndex(x, y, z);
+ int v;
+ do {
+ v = (int) ARRAY_HANDLE.getVolatile(blocks, index);
+ } while (!ARRAY_HANDLE.weakCompareAndSet(blocks, index, v, v & and | id));
+
+ return blockStates.get((v >> shift) & 0xFFFF);
+ }
+
+ @Override
+ public boolean swapBlockStateAtomic(int x, int y, int z, IBlockState expected, IBlockState to) {
+ int shift = 16 * (z & 0b11);
+ int newID = to.getBlockStateID() << shift;
+ int oldID = expected.getBlockStateID() << shift;
+ int and = 0xFFFF << shift;
+ int index = getIndex(x, y, z);
+ int v;
+ do {
+ v = (int) ARRAY_HANDLE.getVolatile(blocks, index);
+ if((v & and) != oldID) {
+ return false;
+ }
+ } while (!ARRAY_HANDLE.weakCompareAndSet(blocks, index, v, v & and | newID));
+ return true;
+ }
+
+ public static int getIndex(int x, int y, int z) {
+ return ((x * 16) + y) * 4 + (z >> 2);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+}
diff --git a/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/GlobalPaletteImpl.java b/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/GlobalPaletteImpl.java
index e584a317..be5c379e 100644
--- a/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/GlobalPaletteImpl.java
+++ b/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/GlobalPaletteImpl.java
@@ -28,12 +28,12 @@ public int getHeight() {
}
@Override
- public IBlockState getBlockState(long x, long y, long z) {
+ public IBlockState getBlockState(int x, int y, int z) {
if(blockStates == null) {
return Blocks.AIR.getDefaultState1();
}
try {
- short b = blockStates[(int) ((x * width + y) * height + z)];
+ short b = blockStates[((x * width + y) * height + z)];
return b == 0 ? Blocks.AIR.getDefaultState1() : Ourcraft.GAME_INSTANCE.BLOCK_STATES.get(b);
} catch (Exception e) {
// e.printStackTrace();
@@ -42,7 +42,7 @@ public IBlockState getBlockState(long x, long y, long z) {
}
@Override
- public IBlockState setBlockState(long x, long y, long z, IBlockState blockState) {
+ public IBlockState setBlockState(int x, int y, int z, IBlockState blockState) {
if(blockStates == null) {
if(blockState.getBlock() != Blocks.AIR) {
blockStates = new short[width * height * width];
diff --git a/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/ISubChunk.java b/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/ISubChunk.java
index 574bce25..6cd7e02f 100644
--- a/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/ISubChunk.java
+++ b/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/ISubChunk.java
@@ -9,9 +9,9 @@ public interface ISubChunk {
int getHeight();
- IBlockState getBlockState(long x, long y, long z);
+ IBlockState getBlockState(int x, int y, int z);
- IBlockState setBlockState(long x, long y, long z, IBlockState blockState);
+ IBlockState setBlockState(int x, int y, int z, IBlockState blockState);
boolean isEmpty();
diff --git a/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/PalettedSubChunk.java b/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/PalettedSubChunk.java
index 5296cc98..e09a0aef 100644
--- a/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/PalettedSubChunk.java
+++ b/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/PalettedSubChunk.java
@@ -20,12 +20,12 @@ public int getHeight() {
}
@Override
- public IBlockState getBlockState(long x, long y, long z) {
+ public IBlockState getBlockState(int x, int y, int z) {
return null;
}
@Override
- public IBlockState setBlockState(long x, long y, long z, IBlockState blockState) {
+ public IBlockState setBlockState(int x, int y, int z, IBlockState blockState) {
return null;
}
diff --git a/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/SimpleSubChunkImpl.java b/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/SimpleSubChunkImpl.java
index d63faf0f..b2c1cc1b 100644
--- a/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/SimpleSubChunkImpl.java
+++ b/src/main/java/dev/hilligans/ourcraft/World/NewWorldSystem/SimpleSubChunkImpl.java
@@ -26,7 +26,7 @@ public int getHeight() {
}
@Override
- public IBlockState getBlockState(long x, long y, long z) {
+ public IBlockState getBlockState(int x, int y, int z) {
if(blockStates == null) {
return Blocks.AIR.getDefaultState1();
}
@@ -40,7 +40,7 @@ public IBlockState getBlockState(long x, long y, long z) {
}
@Override
- public IBlockState setBlockState(long x, long y, long z, IBlockState blockState) {
+ public IBlockState setBlockState(int x, int y, int z, IBlockState blockState) {
if(blockStates == null) {
if(blockState.getBlock() != Blocks.AIR) {
blockStates = new IBlockState[width * height * width];