aboutsummaryrefslogtreecommitdiffstats
path: root/src/ru/olamedia/olacraft/world
diff options
context:
space:
mode:
Diffstat (limited to 'src/ru/olamedia/olacraft/world')
-rw-r--r--src/ru/olamedia/olacraft/world/World.java12
-rw-r--r--src/ru/olamedia/olacraft/world/WorldInfo.java11
-rw-r--r--src/ru/olamedia/olacraft/world/block/Block.java111
-rw-r--r--src/ru/olamedia/olacraft/world/block/BlockRegistry.java46
-rw-r--r--src/ru/olamedia/olacraft/world/block/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/blockStack/BlockStack.java63
-rw-r--r--src/ru/olamedia/olacraft/world/blockStack/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java86
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/BlockType.java21
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/EmptyBlockType.java23
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java28
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/GravelBlockType.java23
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/BlockSlice.java164
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/Chunk.java290
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java47
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java114
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/data/ChunkData.java86
-rw-r--r--src/ru/olamedia/olacraft/world/data/ChunkLightData.java102
-rw-r--r--src/ru/olamedia/olacraft/world/data/HeightMap.java42
-rw-r--r--src/ru/olamedia/olacraft/world/data/RegionData.java57
-rw-r--r--src/ru/olamedia/olacraft/world/data/SectorData.java33
-rw-r--r--src/ru/olamedia/olacraft/world/data/UnavailableDataException.java23
-rw-r--r--src/ru/olamedia/olacraft/world/data/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/AbstractChunkDataProvider.java60
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java70
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/LocalChunkDataProvider.java218
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/LocalRegionDataProvider.java57
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java75
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/generator/HeightMapGenerator.java157
-rw-r--r--src/ru/olamedia/olacraft/world/generator/ImprovedNoise.java61
-rw-r--r--src/ru/olamedia/olacraft/world/generator/Lerp.java27
-rw-r--r--src/ru/olamedia/olacraft/world/generator/RegionGenerator.java71
-rw-r--r--src/ru/olamedia/olacraft/world/generator/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/location/BlockLocation.java37
-rw-r--r--src/ru/olamedia/olacraft/world/location/ChunkLocation.java40
-rw-r--r--src/ru/olamedia/olacraft/world/location/RegionLocation.java29
-rw-r--r--src/ru/olamedia/olacraft/world/location/SectorLocation.java29
-rw-r--r--src/ru/olamedia/olacraft/world/location/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/provider/IChunkProvider.java8
-rw-r--r--src/ru/olamedia/olacraft/world/provider/WorldProvider.java130
-rw-r--r--src/ru/olamedia/olacraft/world/provider/blockData/BlockData.java5
-rw-r--r--src/ru/olamedia/olacraft/world/provider/blockData/EmptyBlockData.java5
-rw-r--r--src/ru/olamedia/olacraft/world/provider/blockData/IBlockData.java5
-rw-r--r--src/ru/olamedia/olacraft/world/provider/blockData/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/provider/package-info.java8
49 files changed, 2554 insertions, 0 deletions
diff --git a/src/ru/olamedia/olacraft/world/World.java b/src/ru/olamedia/olacraft/world/World.java
new file mode 100644
index 0000000..e3d25f2
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/World.java
@@ -0,0 +1,12 @@
+package ru.olamedia.olacraft.world;
+
+import ru.olamedia.olacraft.world.block.BlockRegistry;
+import ru.olamedia.olacraft.world.blockTypes.GrassBlockType;
+
+public class World {
+ private BlockRegistry blockRegistry;
+ public void setup() {
+ blockRegistry = new BlockRegistry();
+ blockRegistry.registerBlockType(GrassBlockType.class);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/WorldInfo.java b/src/ru/olamedia/olacraft/world/WorldInfo.java
new file mode 100644
index 0000000..797339f
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/WorldInfo.java
@@ -0,0 +1,11 @@
+package ru.olamedia.olacraft.world;
+
+import java.io.Serializable;
+
+public class WorldInfo implements Serializable {
+ private static final long serialVersionUID = -3669317489158639456L;
+ public String name = "world";
+ public int minHeight = -128;
+ public int maxHeight = 127;
+ public float gravity = 9.81f;
+}
diff --git a/src/ru/olamedia/olacraft/world/block/Block.java b/src/ru/olamedia/olacraft/world/block/Block.java
new file mode 100644
index 0000000..a48c9df
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/block/Block.java
@@ -0,0 +1,111 @@
+package ru.olamedia.olacraft.world.block;
+
+import ru.olamedia.olacraft.world.blockTypes.BlockType;
+import ru.olamedia.olacraft.world.blockTypes.EmptyBlockType;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class Block {
+ private WorldProvider provider;
+ private int x;
+ private int y;
+ private int z;
+
+ /**
+ * Inventory block
+ */
+ public Block() {
+ this.provider = null;
+ this.x = 0;
+ this.y = 0;
+ this.z = 0;
+ }
+
+ public void putIntoWorld(WorldProvider worldProvider, int x, int y, int z) {
+ this.provider = worldProvider;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public Block(WorldProvider worldProvider, int x, int y, int z) {
+ putIntoWorld(worldProvider, x, y, z);
+ }
+
+ /**
+ * @return the x
+ */
+ public int getX() {
+ return x;
+ }
+
+ /**
+ * @param x
+ * the x to set
+ */
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ /**
+ * @return the y
+ */
+ public int getY() {
+ return y;
+ }
+
+ /**
+ * @param y
+ * the y to set
+ */
+ public void setY(int y) {
+ this.y = y;
+ }
+
+ /**
+ * @return the z
+ */
+ public int getZ() {
+ return z;
+ }
+
+ /**
+ * @param z
+ * the z to set
+ */
+ public void setZ(int z) {
+ this.z = z;
+ }
+
+ public boolean isEmpty() {
+ return provider.isEmptyBlock(x, y, z);
+ }
+
+ public Block getNeighbor(int dx, int dy, int dz) {
+ return new Block(provider, x + dx, y + dy, z + dz);
+ }
+
+ public Block[] getNeighbors() {
+ return new Block[] {
+ //
+ getNeighbor(1, 0, 0),//
+ getNeighbor(0, 1, 0),//
+ getNeighbor(0, 0, 1),//
+ getNeighbor(-1, 0, 0),//
+ getNeighbor(0, -1, 0),//
+ getNeighbor(0, 0, -1),//
+ };
+ }
+
+ private BlockType type;
+
+ public void setType(BlockType type) {
+ this.type = type;
+ }
+
+ public BlockType getType() {
+ if (null == type) {
+ type = new EmptyBlockType();
+ }
+ return type;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/block/BlockRegistry.java b/src/ru/olamedia/olacraft/world/block/BlockRegistry.java
new file mode 100644
index 0000000..19ccc94
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/block/BlockRegistry.java
@@ -0,0 +1,46 @@
+package ru.olamedia.olacraft.world.block;
+
+import java.util.HashMap;
+
+import ru.olamedia.olacraft.world.blockTypes.BlockType;
+
+public class BlockRegistry {
+
+ private HashMap<Integer, String> names = new HashMap<Integer, String>();
+ private HashMap<Integer, BlockType> types = new HashMap<Integer, BlockType>();
+ private int autoincrement = 0;
+
+ private BlockRegistry worldRegistry;
+
+ public BlockRegistry() {
+ }
+
+ public BlockType getBlockType(int id) {
+ return types.get(id);
+ }
+
+ public String getBlockHumanId(int id) {
+ return names.get(id);
+ }
+
+ public int registerBlockType(@SuppressWarnings("rawtypes") Class type) {
+ if (type.isInstance(BlockType.class)) {
+ autoincrement++;
+ int id = autoincrement;
+ String classId = type.getName();
+ names.put(id, classId);
+ // types.put(id, type);
+ return autoincrement;
+ }
+ return 0;
+ }
+
+ public BlockRegistry getWorldRegistry() {
+ return worldRegistry;
+ }
+
+ public void setWorldRegistry(BlockRegistry worldRegistry) {
+ this.worldRegistry = worldRegistry;
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/block/package-info.java b/src/ru/olamedia/olacraft/world/block/package-info.java
new file mode 100644
index 0000000..0924926
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/block/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.block; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/blockStack/BlockStack.java b/src/ru/olamedia/olacraft/world/blockStack/BlockStack.java
new file mode 100644
index 0000000..57258ef
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockStack/BlockStack.java
@@ -0,0 +1,63 @@
+package ru.olamedia.olacraft.world.blockStack;
+
+import ru.olamedia.olacraft.world.block.Block;
+
+public class BlockStack {
+ public Block block;
+ public int count;
+
+ public BlockStack(Block block, int count) {
+ this.block = block;
+ this.count = count;
+ }
+
+ public BlockStack get() {
+ return get(1);
+ }
+
+ public BlockStack get(int getcount) {
+ int c = 0;
+ if (count >= getcount) {
+ c = getcount;
+ count -= getcount;
+ } else {
+ c = count;
+ count = 0;
+ }
+ return new BlockStack(block, c);
+ }
+
+ public BlockStack getAll() {
+ int c = count;
+ count = 0;
+ return new BlockStack(block, c);
+ }
+
+ /**
+ *
+ * @return Remaining BlockStack
+ */
+ public BlockStack putStack(BlockStack stack) {
+
+ if (block.getType() == stack.block.getType()) {
+ int max = block.getType().getMaxStack();
+ // Stack
+ int total = count + stack.count;
+ if (total < max) {
+ count = total;
+ return new BlockStack(block, 0);
+ } else {
+ BlockStack remains = new BlockStack(block, total - max);
+ count = max;
+ return remains;
+ }
+ } else {
+ // Replace
+ BlockStack remains = new BlockStack(block, count);
+ block = stack.block;
+ count = stack.count;
+ return remains;
+ }
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/blockStack/package-info.java b/src/ru/olamedia/olacraft/world/blockStack/package-info.java
new file mode 100644
index 0000000..933dc87
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockStack/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.blockStack; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java
new file mode 100644
index 0000000..6e2a86f
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java
@@ -0,0 +1,86 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+import com.jogamp.opengl.util.texture.Texture;
+
+import ru.olamedia.texture.TextureManager;
+
+public abstract class AbstractBlockType implements BlockType {
+
+ @Override
+ abstract public String getName();
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ abstract public String getStackTextureFile();
+
+ @Override
+ abstract public String getTopTextureFile();
+
+ @Override
+ public String getBottomTextureFile() {
+ return this.getTopTextureFile();
+ }
+
+ @Override
+ public String getLeftTextureFile() {
+ return this.getFrontTextureFile();
+ }
+
+ @Override
+ public String getRightTextureFile() {
+ return this.getFrontTextureFile();
+ }
+
+ @Override
+ public String getFrontTextureFile() {
+ return this.getTopTextureFile();
+ }
+
+ @Override
+ public String getBackTextureFile() {
+ return this.getFrontTextureFile();
+ }
+
+ @Override
+ public Texture getTopTexture() {
+ return TextureManager.get(this.getTopTextureFile());
+ }
+
+ @Override
+ public Texture getBottomTexture() {
+ return TextureManager.get(this.getBottomTextureFile());
+ }
+
+ @Override
+ public Texture getLeftTexture() {
+ return TextureManager.get(this.getLeftTextureFile());
+ }
+
+ @Override
+ public Texture getRightTexture() {
+ return TextureManager.get(this.getRightTextureFile());
+ }
+
+ @Override
+ public Texture getFrontTexture() {
+ return TextureManager.get(this.getFrontTextureFile());
+ }
+
+ @Override
+ public Texture getBackTexture() {
+ return TextureManager.get(this.getBackTextureFile());
+ }
+
+ public void register(){
+ getBackTexture();
+ getBottomTexture();
+ getFrontTexture();
+ getLeftTexture();
+ getRightTexture();
+ getTopTexture();
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/BlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/BlockType.java
new file mode 100644
index 0000000..0bda2eb
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/BlockType.java
@@ -0,0 +1,21 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+import com.jogamp.opengl.util.texture.Texture;
+
+public interface BlockType {
+ public String getName();
+ public int getMaxStack();
+ public String getStackTextureFile();
+ public String getTopTextureFile();
+ public String getBottomTextureFile();
+ public String getLeftTextureFile();
+ public String getRightTextureFile();
+ public String getFrontTextureFile();
+ public String getBackTextureFile();
+ public Texture getTopTexture();
+ public Texture getBottomTexture();
+ public Texture getLeftTexture();
+ public Texture getRightTexture();
+ public Texture getFrontTexture();
+ public Texture getBackTexture();
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/EmptyBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/EmptyBlockType.java
new file mode 100644
index 0000000..4073356
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/EmptyBlockType.java
@@ -0,0 +1,23 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+public class EmptyBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/empty.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/empty.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java
new file mode 100644
index 0000000..816b283
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java
@@ -0,0 +1,28 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+public class GrassBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Grass";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/terrain-grassdarkgreen.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/terrain-grassdarkgreen.png";
+ }
+
+ @Override
+ public String getFrontTextureFile() {
+ return "texture/terrain-glong-darkgreen-dirt.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/GravelBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/GravelBlockType.java
new file mode 100644
index 0000000..354d383
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/GravelBlockType.java
@@ -0,0 +1,23 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+public class GravelBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Gravel";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/gravel.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/gravel.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/package-info.java b/src/ru/olamedia/olacraft/world/blockTypes/package-info.java
new file mode 100644
index 0000000..a49dda8
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.blockTypes; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/chunk/BlockSlice.java b/src/ru/olamedia/olacraft/world/chunk/BlockSlice.java
new file mode 100644
index 0000000..ca4c92a
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/chunk/BlockSlice.java
@@ -0,0 +1,164 @@
+package ru.olamedia.olacraft.world.chunk;
+
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class BlockSlice {
+ protected WorldProvider provider;
+ protected int leftX;
+ protected int bottomY;
+ protected int backZ;
+ protected int width;
+ protected int height;
+ protected int depth;
+
+ protected ChunkSlice chunkSlice;
+
+ // Memory leak:
+ //protected int[][] highest = new int[256][256];
+
+ public void invalidateCache(){
+ //highest = new int[256][256];
+ }
+
+/* public int getHighest(int blockX, int blockZ) {
+ if (highest[blockX - leftX][blockZ - backZ] > 0){
+ return highest[blockX - leftX][blockZ - backZ];
+ }
+ for (int y = 0; y < 128; y++) {
+ if (provider.isEmptyBlock(blockX, y, blockZ)){
+ highest[blockX - leftX][blockZ - backZ] = y;
+ return y;
+ }
+ }
+ return 0;
+ }*/
+
+ /**
+ *
+ * @param provider
+ * @param width
+ * (blocks)
+ * @param height
+ * (blocks)
+ * @param depth
+ * (blocks)
+ */
+ public BlockSlice(WorldProvider provider, int width, int height, int depth) {
+ this.provider = provider;
+ this.width = width;
+ this.height = height;
+ this.depth = depth;
+ }
+
+ public ChunkSlice getChunkSlice() {
+ if (null == chunkSlice) {
+ chunkSlice = new ChunkSlice(provider, width / 16, height / 16, depth / 16);
+ }
+ int x = Chunk.v(leftX);
+ int y = Chunk.v(bottomY);
+ int z = Chunk.v(backZ);
+ chunkSlice.setLocation(x, y, z);
+ return chunkSlice;
+ }
+
+ public int getTotalBlocks() {
+ return getWidth() * getHeight() * getDepth();
+ }
+
+ /**
+ * @return the width (blocks)
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * @param width
+ * (blocks)
+ */
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ /**
+ * @return the height (blocks)
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * @param height
+ * (blocks)
+ */
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ /**
+ * @return the depth (blocks)
+ */
+ public int getDepth() {
+ return depth;
+ }
+
+ /**
+ * @param depth
+ * (blocks)
+ */
+ public void setDepth(int depth) {
+ this.depth = depth;
+ }
+
+ /**
+ *
+ * @param x
+ * (blocks)
+ * @param y
+ * (blocks)
+ * @param z
+ * (blocks)
+ */
+ public void setLocation(int x, int y, int z) {
+ if (x != leftX || y != bottomY || z != backZ){
+ invalidateCache();
+ }
+ leftX = x;
+ bottomY = y;
+ backZ = z;
+ }
+
+ /**
+ *
+ * @param x
+ * (blocks)
+ * @param y
+ * (blocks)
+ * @param z
+ * (blocks)
+ */
+ public void setCenter(int x, int y, int z) {
+ setLocation(x - width / 2, y - height / 2, z - depth / 2);
+ }
+
+ /**
+ * @return the left x (blocks)
+ */
+ public int getX() {
+ return leftX;
+ }
+
+ /**
+ * @return the bottom y (blocks)
+ */
+ public int getY() {
+ return bottomY;
+ }
+
+ /**
+ * @return the back z (blocks)
+ */
+ public int getZ() {
+ return backZ;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/chunk/Chunk.java b/src/ru/olamedia/olacraft/world/chunk/Chunk.java
new file mode 100644
index 0000000..ca2d4bf
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/chunk/Chunk.java
@@ -0,0 +1,290 @@
+package ru.olamedia.olacraft.world.chunk;
+
+import ru.olamedia.geom.SimpleQuadMesh;
+import ru.olamedia.olacraft.world.blockTypes.GrassBlockType;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class Chunk extends BlockSlice {
+ public boolean isMeshCostructed = false;
+ public SimpleQuadMesh mesh;
+
+ public int visibleTop = 0;
+ public int visibleBottom = 0;
+ public int visibleLeft = 0;
+ public int visibleRight = 0;
+ public int visibleFront = 0;
+ public int visibleBack = 0;
+
+ public Chunk(WorldProvider provider) {
+ super(provider, 16, 16, 16);
+ }
+
+ /**
+ * Convert block coordinate into chunk coordinate
+ *
+ * @param v
+ * block coordinate along one axis
+ * @return
+ */
+ public static int v(int v) {
+ if (v >= 0) {
+ return v / 16;
+ } else {
+ return (v + 1) / 16 - 1;
+ }
+ }
+
+ /**
+ * Convert block coordinate into block position inside of chunk
+ *
+ * @param v
+ * block coordinate along one axis
+ * @return
+ */
+ public static int in(int v) {
+ int tmp = v - v(v) * 16;
+ return tmp >= 0 ? tmp : 16 + tmp; // block location minus chunk base
+ // location
+ // (lower-left-back corner)
+ // if (v >= 0) {
+ // return v % 16;
+ // } else {
+ // int in = v + 1; // shift up so -1 will be 0
+ // in %= 16; // get remaining -15..0
+ // in += 15; // revert 0..15
+ // return in;
+ // }
+ }
+
+ public void setMeshColor(SimpleQuadMesh mesh, int x, int y, int z, boolean isSide) {
+ float level = 1f;// ((float) getProvider().getBlockLightLevel(x, y, z) -
+ // (isSide ? 2 : 0)) / 15.0f;
+ mesh.setColor4f(level, level, level, 1);
+ if (y < 0) {
+ mesh.setColor4f(0, 0, 1, 1);
+ } else if (y > 30) {
+ mesh.setColor4f(1, 1, 1, 1);
+ } else {
+ mesh.setColor4f(1, 1, 0, 1);
+ }
+ }
+
+ /**
+ * @return the mesh
+ */
+ public SimpleQuadMesh getMesh() {
+ if (isMeshCostructed) {
+ return mesh;
+ }
+ if (getY() > provider.getInfo().maxHeight) {
+ isMeshCostructed = true;
+ return null;
+ }
+ if (getY() < provider.getInfo().minHeight) {
+ isMeshCostructed = true;
+ return null;
+ }
+ if (null == mesh) {
+ mesh = new SimpleQuadMesh(14739); // unindexed
+ // 17x17x17
+ // vertices
+ mesh.useColor();
+ mesh.useTexture();
+ // gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_FASTEST);
+ // gl.glHint(GL2.GL_LINE_SMOOTH_HINT, GL2.GL_NICEST);
+ GrassBlockType grass = new GrassBlockType();
+ for (int x = getX(); x < getX() + getWidth(); x++) {
+ for (int y = getY(); y < getY() + getHeight(); y++) {
+ for (int z = getZ(); z < getZ() + getDepth(); z++) {
+ //
+
+ if (!isEmptyBlock(x, y, z)) {
+ mesh.setTranslation(x, y, z);
+ // mesh.setColor4f(0, 1, 0, 1);
+ float cbase = (float) (y / 200.0) * (float) (7.0 / 10.0);
+ if (cbase > 9 / 10) {
+ cbase = (float) (9.0 / 10.0);
+ }
+ // cbase = (float) (9.0 / 10.0);
+ float cred, cgreen, cblue;
+ // cbase;
+ cred = cgreen = cblue = getLightLevel256(x, y, z);
+ if (x == 1) {
+ mesh.setColor4f(1, 0, 0, 1);
+ // red to the right
+ }
+ if (x == 0 || z == 0) {
+ if (y == 6) {
+ mesh.setColor4f(1, 0, 0, 1);
+ } else if (y % 2 == 0) {
+ mesh.setColor4f(1, 0, 1, 1);
+ } else {
+ mesh.setColor4f(1, 1, 0, 1);
+ }
+ }
+ if (z == 1) {
+ mesh.setColor4f(0, 0, 1, 1);
+ // blue to the bottom
+ }
+ if (renderBottom(x, y, z)) {
+ setMeshColor(mesh, x, y - 1, z, false);
+ mesh.setTexture(grass.getBottomTexture());
+ mesh.addBottomQuad();
+ visibleBottom++;
+ }
+ if (renderTop(x, y, z)) {
+ if (x == 15 || z == 15) {
+ // debug: show through..
+ } else {
+ setMeshColor(mesh, x, y + 1, z, false);
+ mesh.setTexture(grass.getTopTexture());
+ mesh.addTopQuad();
+ }
+ visibleTop++;
+ }
+ if (renderLeft(x, y, z)) {
+ setMeshColor(mesh, x - 1, y, z, true);
+ mesh.setTexture(grass.getLeftTexture());
+ mesh.addLeftQuad();
+ visibleLeft++;
+ }
+ if (renderRight(x, y, z)) {
+ setMeshColor(mesh, x + 1, y, z, true);
+ mesh.setTexture(grass.getRightTexture());
+ mesh.addRightQuad();
+ visibleRight++;
+ }
+ if (renderBack(x, y, z)) {
+ setMeshColor(mesh, x, y, z - 1, true);
+ mesh.setTexture(grass.getBackTexture());
+ mesh.addBackQuad();
+ visibleBack++;
+ }
+ if (renderFront(x, y, z)) {
+ setMeshColor(mesh, x, y, z + 1, true);
+ mesh.setTexture(grass.getFrontTexture());
+ mesh.addFrontQuad();
+ visibleFront++;
+ }
+ }
+ }
+ }
+ }
+ mesh.endMesh();
+ isMeshCostructed = true;
+ return null;
+ }
+ return mesh;
+ }
+
+ /**
+ * @param mesh
+ * the mesh to set
+ */
+ public void setMesh(SimpleQuadMesh mesh) {
+ this.mesh = mesh;
+ }
+
+ public boolean isEmpty() {
+ // MUST BE LOADED
+ return provider.getChunk(getBlockLocation().getChunkLocation()).isEmpty();
+ }
+
+ private BlockLocation getBlockLocation() {
+ return new BlockLocation(getX(), getY(), getZ());
+ }
+
+ public boolean isAvailable() {
+ return provider.isChunkAvailable(getBlockLocation().getChunkLocation());
+ }
+
+ public boolean isNeighborsAvailable() {
+ int x = Chunk.v(getX());
+ int y = Chunk.v(getY());
+ int z = Chunk.v(getZ());
+ return provider.isChunkAvailable(new ChunkLocation(x - 1, y, z))
+ && provider.isChunkAvailable(new ChunkLocation(x + 1, y, z))
+ && provider.isChunkAvailable(new ChunkLocation(x, y - 1, z))
+ && provider.isChunkAvailable(new ChunkLocation(x, y + 1, z))
+ && provider.isChunkAvailable(new ChunkLocation(x, y, z - 1))
+ && provider.isChunkAvailable(new ChunkLocation(x, y, z + 1));
+ }
+
+ public void requestNeighbors() {
+ int x = Chunk.v(getX());
+ int y = Chunk.v(getY());
+ int z = Chunk.v(getZ());
+ if (!provider.isChunkAvailable(new ChunkLocation(x - 1, y, z))) {
+ provider.loadChunk(new ChunkLocation(x - 1, y, z));
+ }
+ if (!provider.isChunkAvailable(new ChunkLocation(x + 1, y, z))) {
+ provider.loadChunk(new ChunkLocation(x + 1, y, z));
+ }
+ if (!provider.isChunkAvailable(new ChunkLocation(x, y - 1, z))) {
+ provider.loadChunk(new ChunkLocation(x, y - 1, z));
+ }
+ if (!provider.isChunkAvailable(new ChunkLocation(x, y + 1, z))) {
+ provider.loadChunk(new ChunkLocation(x, y + 1, z));
+ }
+ if (!provider.isChunkAvailable(new ChunkLocation(x, y, z - 1))) {
+ provider.loadChunk(new ChunkLocation(x, y, z - 1));
+ }
+ if (!provider.isChunkAvailable(new ChunkLocation(x, y, z + 1))) {
+ provider.loadChunk(new ChunkLocation(x, y, z + 1));
+ }
+ }
+
+ public void request() {
+ BlockLocation blockLocation = new BlockLocation(getX(), getY(), getZ());
+ // System.out.println("provider.requestChunk(" +
+ // blockLocation.getRegionLocation() + blockLocation.getChunkLocation()
+ // + ")");
+ provider.loadChunk(blockLocation.getChunkLocation());
+ }
+
+ // public BlockType getBlockType(int x, int y, int z) {
+ // return provider.getBlockType(int x, int y, int z);
+ // }
+
+ public boolean isEmptyBlock(int x, int y, int z) {
+ return provider.isEmptyBlock(x, y, z);
+ }
+
+ public float getLightLevel256(int x, int y, int z) {
+ return ((float) getLightLevel(x, y, z)) / 15.0f;// * 255.0f
+ }
+
+ public int getLightLevel(int x, int y, int z) {
+ return 15;
+ }
+
+ public boolean renderBottom(int x, int y, int z) {
+ return provider.renderBottom(x, y, z);
+ }
+
+ public boolean renderTop(int x, int y, int z) {
+ return provider.renderTop(x, y, z);
+ }
+
+ public boolean renderLeft(int x, int y, int z) {
+ return provider.renderLeft(x, y, z);
+ }
+
+ public boolean renderRight(int x, int y, int z) {
+ return provider.renderRight(x, y, z);
+ }
+
+ public boolean renderFront(int x, int y, int z) {
+ return provider.renderFront(x, y, z);
+ }
+
+ public boolean renderBack(int x, int y, int z) {
+ return provider.renderBack(x, y, z);
+ }
+
+ public WorldProvider getProvider() {
+ return provider;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java b/src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java
new file mode 100644
index 0000000..d362199
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java
@@ -0,0 +1,47 @@
+package ru.olamedia.olacraft.world.chunk;
+
+import java.util.concurrent.ArrayBlockingQueue;
+
+public class ChunkMeshBulder extends Thread {
+ public static ChunkMeshBulder instance = new ChunkMeshBulder("Mesh builder");
+ private ArrayBlockingQueue<Chunk> chunks = new ArrayBlockingQueue<Chunk>(16);
+
+ public ChunkMeshBulder(String name) {
+ super(name);
+ }
+
+ public boolean isFull() {
+ return chunks.remainingCapacity() == 0;
+ }
+
+ public void add(Chunk chunk) {
+ chunks.offer(chunk);
+ }
+
+ public void clear() {
+ chunks.clear();
+ }
+
+ public void tick() throws InterruptedException {
+ if (!chunks.isEmpty()) {
+ Chunk chunk = chunks.take();
+ chunk.getMesh();
+ }
+ }
+
+ @Override
+ public void run() {
+ // glc.makeCurrent();
+ while (true) {
+ // main loop
+ try {
+ tick();
+ // Thread.sleep(10); // or wait/join etc
+ } catch (InterruptedException ex) {
+ // cleanup here
+ Thread.currentThread().interrupt(); // for nested loops
+ break;
+ }
+ }
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java b/src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java
new file mode 100644
index 0000000..e440740
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java
@@ -0,0 +1,114 @@
+package ru.olamedia.olacraft.world.chunk;
+
+import java.util.HashMap;
+
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class ChunkSlice {
+ private WorldProvider provider;
+ private int leftX;
+ private int bottomY;
+ private int backZ;
+ private int width;
+ private int height;
+ private int depth;
+
+ public ChunkSlice(WorldProvider provider, int width, int height, int depth) {
+ this.provider = provider;
+ this.width = width;
+ this.height = height;
+ this.depth = depth;
+ }
+
+ protected HashMap<String, Chunk> chunks = new HashMap<String, Chunk>();
+
+ public Chunk getChunk(int x, int y, int z) {
+ String key = x + ";" + y + ";" + z;
+ if (chunks.containsKey(key)) {
+ return chunks.get(key);
+ } else {
+ Chunk chunk = new Chunk(provider);
+ chunk.setLocation(x * 16, y * 16, z * 16);
+ chunks.put(key, chunk);
+ return chunk;
+ }
+ }
+
+ /**
+ * @return the width
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * @param width
+ * the width to set
+ */
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ /**
+ * @return the height
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * @param height
+ * the height to set
+ */
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ /**
+ * @return the depth
+ */
+ public int getDepth() {
+ return depth;
+ }
+
+ /**
+ * @param depth
+ * the depth to set
+ */
+ public void setDepth(int depth) {
+ this.depth = depth;
+ }
+
+ public void setLocation(int x, int y, int z) {
+ leftX = x;
+ bottomY = y;
+ backZ = z;
+ }
+
+ public void setCenter(int x, int y, int z) {
+ leftX = x - width / 2;
+ bottomY = y - height / 2;
+ backZ = z - depth / 2;
+ }
+
+ /**
+ * @return the leftX
+ */
+ public int getX() {
+ return leftX;
+ }
+
+ /**
+ * @return the bottomY
+ */
+ public int getY() {
+ return bottomY;
+ }
+
+ /**
+ * @return the backZ
+ */
+ public int getZ() {
+ return backZ;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/chunk/package-info.java b/src/ru/olamedia/olacraft/world/chunk/package-info.java
new file mode 100644
index 0000000..314ea35
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/chunk/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.chunk; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/data/ChunkData.java b/src/ru/olamedia/olacraft/world/data/ChunkData.java
new file mode 100644
index 0000000..a1abc9e
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/ChunkData.java
@@ -0,0 +1,86 @@
+package ru.olamedia.olacraft.world.data;
+
+import java.io.Serializable;
+import java.util.BitSet;
+
+import ru.olamedia.olacraft.world.chunk.Chunk;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+
+public class ChunkData implements Serializable {
+ private static final long serialVersionUID = -5704237444737895501L;
+ public ChunkLocation location;
+ public static transient int SIZE = 4096;
+ // private boolean[] notEmpty = new boolean[SIZE];
+ private BitSet emptyBlocks = new BitSet(4096);
+ public int notEmptyCount = 0;
+
+ // public transient int[] type = new int[SIZE];
+ // /public transient ChunkLightData light;
+
+ public ChunkData() {
+ // light = new ChunkLightData();
+ }
+
+ public void compact() {
+ if (notEmptyCount == 0) {
+ emptyBlocks = null;
+ }
+ }
+
+ public static int normalize(int v) {
+ int n = v;
+ if (n > 15) {
+ n = n % 16;
+ }
+ if (n < 0) {
+ n = 16 + n % 16 - 1;
+ // v = 15 - v;
+ }
+ // System.out.println("normalize(" + v + ") = " + n);
+ return n;
+ }
+
+ public static int getId(int xInsideChunk, int yInsideChunk, int zInsideChunk) {
+ xInsideChunk = normalize(xInsideChunk);
+ yInsideChunk = normalize(yInsideChunk);
+ zInsideChunk = normalize(zInsideChunk);
+ int id = xInsideChunk * 16 * 16 + yInsideChunk * 16 + zInsideChunk;
+ if (id > SIZE) {
+ System.err.println("Exception while getID(" + xInsideChunk + "," + yInsideChunk + "," + zInsideChunk + ")");
+ throw new ArrayIndexOutOfBoundsException(id);
+ }
+ return id;
+ }
+
+ public boolean isEmpty(BlockLocation blockLocation) {
+ if (notEmptyCount == 0) {
+ return true;
+ }
+ int id = getId(Chunk.in(blockLocation.x), Chunk.in(blockLocation.y), Chunk.in(blockLocation.z));
+ return isEmpty(id);
+ // return !notEmpty[id];
+ }
+
+ public boolean isEmpty(int id) {
+ if (notEmptyCount == 0) {
+ return true;
+ }
+ return emptyBlocks.get(id);
+ }
+
+ public void setEmpty(int id, boolean isEmpty) {
+ if (isEmpty(id) != isEmpty) {
+ if (!isEmpty) {
+ notEmptyCount++;
+ } else {
+ notEmptyCount--;
+ }
+ }
+ emptyBlocks.set(id, isEmpty);
+ }
+
+ public boolean isEmpty() {
+ return notEmptyCount == 0;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/data/ChunkLightData.java b/src/ru/olamedia/olacraft/world/data/ChunkLightData.java
new file mode 100644
index 0000000..f574420
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/ChunkLightData.java
@@ -0,0 +1,102 @@
+package ru.olamedia.olacraft.world.data;
+
+import ru.olamedia.olacraft.world.dataProvider.AbstractChunkDataProvider;
+
+/**
+ * The daylight calculated as sum of sunlight + emitted light
+ * The nightlight calculated as sum of emitted light
+ *
+ * The light at some time of a day calculated as part of daylight + part of
+ * nightlight (ex 30% of night + 70% of daylight) - sum of two array's elements
+ */
+public class ChunkLightData {
+ public static int SIZE = 4096;
+ /**
+ * Constant sunlight level
+ */
+ public byte[] sunLevel = new byte[SIZE];
+ /**
+ * Constant sunlight level
+ */
+ public byte[] emittedLevel = new byte[SIZE];
+ /**
+ * Constant light level during middle of a day
+ */
+ public byte[] daytimeLevel = new byte[SIZE];
+ /**
+ * Constant light level during midnight
+ */
+ public byte[] nighttimeLevel = new byte[SIZE];
+ public boolean isCalculated = false;
+ public boolean isSunlevelCalculated = false;
+ public byte[] level = new byte[SIZE];
+
+ public static int normalize(int v) {
+ int n = v;
+ if (n > 15) {
+ n = n % 16;
+ }
+ if (n < 0) {
+ n = 16 + n % 16 - 1;
+ // v = 15 - v;
+ }
+ // System.out.println("normalize(" + v + ") = " + n);
+ return n;
+ }
+
+ public static int getId(int xInsideChunk, int yInsideChunk, int zInsideChunk) {
+ xInsideChunk = normalize(xInsideChunk);
+ yInsideChunk = normalize(yInsideChunk);
+ zInsideChunk = normalize(zInsideChunk);
+ int id = xInsideChunk * 16 * 16 + yInsideChunk * 16 + zInsideChunk;
+ if (id > SIZE) {
+ System.err.println("Exception while getID(" + xInsideChunk + "," + yInsideChunk + "," + zInsideChunk + ")");
+ throw new ArrayIndexOutOfBoundsException(id);
+ }
+ return id;
+ }
+
+ private static byte sunlight = 15;
+
+ public void fillSunlight() {
+ // simplify: straight from top to bottom, utility to fill top layer
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ sunLevel[getId(x, 15, z)] = sunlight;
+ }
+ }
+ }
+
+ public void copySunlightFromAbove(ChunkLightData above) {
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ sunLevel[getId(x, 15, z)] = above.sunLevel[getId(x, 0, z)];
+ }
+ }
+ System.out.print("Copy sunlight");
+ }
+
+ /**
+ * Sunlight falling down until meets nonempty block from data
+ *
+ * @param data
+ */
+ public void falldownSunlight(ChunkData data) {
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ for (int y = 14; y >= 0; y--) {
+ if (!data.isEmpty(getId(x, y, z))) {
+ break;
+ } else {
+ sunLevel[getId(x, y, z)] = sunLevel[getId(x, y + 1, z)];
+ }
+ }
+ }
+ }
+ }
+
+ public void receiveNeighborLight(AbstractChunkDataProvider abstractChunkDataProvider) {
+
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/data/HeightMap.java b/src/ru/olamedia/olacraft/world/data/HeightMap.java
new file mode 100644
index 0000000..b2c0a63
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/HeightMap.java
@@ -0,0 +1,42 @@
+package ru.olamedia.olacraft.world.data;
+
+import java.io.Serializable;
+
+/**
+ * Heightmap
+ * Useful when looking for spawn location, calculating light
+ *
+ * @author olamedia
+ *
+ */
+public class HeightMap implements Serializable {
+ private static final long serialVersionUID = -6777972159522169977L;
+ public byte[][] map; // -128..127
+ public HeightMap(){
+
+ }
+ public HeightMap(int width, int height) {
+ map = new byte[width][height];
+ }
+
+ public void setHeight(int x, int y, int height) {
+ map[x][y] = (byte) height;
+ }
+
+ public int getHeight(int x, int y) {
+ return map[x][y];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder b = new StringBuilder();
+ for (int x = 0; x < map.length; x++){
+ for (int z = 0; z < map[x].length; z++){
+ b.append(map[x][z]);
+ b.append(",");
+ }
+ b.append("\n");
+ }
+ return b.toString();
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/data/RegionData.java b/src/ru/olamedia/olacraft/world/data/RegionData.java
new file mode 100644
index 0000000..fa292d2
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/RegionData.java
@@ -0,0 +1,57 @@
+package ru.olamedia.olacraft.world.data;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+
+import ru.olamedia.olacraft.world.chunk.Chunk;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+import ru.olamedia.olacraft.world.location.SectorLocation;
+
+/**
+ * Region is a 16x16 range of sectors. (256x256x256 blocks)
+ *
+ * @author olamedia
+ *
+ */
+public class RegionData implements Serializable {
+ private static final long serialVersionUID = 7449677895073874520L;
+ public RegionLocation location;
+ public HeightMap heightMap = new HeightMap(256, 256);
+ public SectorData[][] sectorData = new SectorData[16][16];
+
+ public void writeTo(OutputStream stream) throws IOException {
+ ObjectOutputStream out = new ObjectOutputStream(stream);
+ out.writeObject(this);
+ out.close();
+ }
+
+ public static RegionData loadFrom(InputStream stream) throws IOException, ClassNotFoundException {
+ ObjectInputStream in = new ObjectInputStream(stream);
+ RegionData data = (RegionData) in.readObject();
+ in.close();
+ return data;
+ }
+
+ public static RegionData createEmpty(RegionLocation location) {
+ RegionData data = new RegionData();
+ data.location = location;
+ return data;
+ }
+
+ public ChunkData getChunkData(ChunkLocation chunkLocation) {
+ SectorData sector = getSectorData(chunkLocation.getSectorLocation());
+ int y = Chunk.in(chunkLocation.y + 128); // minHeight = -128
+ return sector.chunkData[y];
+ }
+
+ public SectorData getSectorData(SectorLocation sectorLocation) {
+ int x = Chunk.in(sectorLocation.x);
+ int z = Chunk.in(sectorLocation.z);
+ return sectorData[x][z];
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/data/SectorData.java b/src/ru/olamedia/olacraft/world/data/SectorData.java
new file mode 100644
index 0000000..12a97cd
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/SectorData.java
@@ -0,0 +1,33 @@
+package ru.olamedia.olacraft.world.data;
+
+import java.io.Serializable;
+
+import ru.olamedia.olacraft.world.location.SectorLocation;
+
+/**
+ * Sector: set of all chunks by one x,z vertical
+ *
+ * @author olamedia
+ *
+ */
+public class SectorData implements Serializable{
+ private static final long serialVersionUID = 5304471397211814748L;
+ public HeightMap heightMap; // locations of highest nonempty blocks
+ public ChunkData[] chunkData; // 256/16 = 16
+ public SectorLocation location;
+
+ public static int yIndex(int y) {
+ return (y + 128) / 16;
+ // 1: (-128 + 128) / 16 = 0
+ // ......
+ // 15: (-114 + 128) / 16 = 14/16 = 0
+ // 16: (-113 + 128) / 16 = 15/16 = 0
+ // 17: (-112 + 128) / 16 = 16/16 = 1
+ }
+ public static SectorData generate(){
+ SectorData data = new SectorData();
+ data.heightMap = new HeightMap(16, 16);
+ data.chunkData = new ChunkData[16];
+ return data;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/data/UnavailableDataException.java b/src/ru/olamedia/olacraft/world/data/UnavailableDataException.java
new file mode 100644
index 0000000..a75a42e
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/UnavailableDataException.java
@@ -0,0 +1,23 @@
+package ru.olamedia.olacraft.world.data;
+
+public class UnavailableDataException extends Exception {
+
+ public UnavailableDataException() {
+ super();
+ }
+
+ public UnavailableDataException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public UnavailableDataException(String message) {
+ super(message);
+ }
+
+ public UnavailableDataException(Throwable cause) {
+ super(cause);
+ }
+
+ private static final long serialVersionUID = -8955947061088863309L;
+
+}
diff --git a/src/ru/olamedia/olacraft/world/data/package-info.java b/src/ru/olamedia/olacraft/world/data/package-info.java
new file mode 100644
index 0000000..2a171a6
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.data; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/AbstractChunkDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/AbstractChunkDataProvider.java
new file mode 100644
index 0000000..1670ef3
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/dataProvider/AbstractChunkDataProvider.java
@@ -0,0 +1,60 @@
+package ru.olamedia.olacraft.world.dataProvider;
+
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.data.SectorData;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+import ru.olamedia.olacraft.world.location.SectorLocation;
+
+abstract public class AbstractChunkDataProvider {
+ /**
+ * is data already available or we should wait
+ *
+ * @param RegionLocation
+ * @return
+ */
+ public boolean isChunkAvailable(ChunkLocation chunkLocation) {
+ return this.isRegionAvailable(chunkLocation.getRegionLocation());
+ }
+
+ public boolean isSectorAvailable(SectorLocation sectorLocation) {
+ return this.isRegionAvailable(sectorLocation.getRegionLocation());
+ }
+
+ abstract public boolean isRegionAvailable(RegionLocation regionLocation);
+
+ /**
+ * we need this chunk now, send request to server or preload
+ *
+ * @param RegionLocation
+ */
+ public void loadChunk(ChunkLocation chunkLocation) {
+ //System.out.println("loadChunk(" + chunkLocation + ")");
+ this.loadRegion(chunkLocation.getRegionLocation());
+ //System.out.println("loadChunk(" + chunkLocation + ")--");
+ }
+
+ public void loadSector(SectorLocation sectorLocation) {
+ this.loadRegion(sectorLocation.getRegionLocation());
+ }
+
+ abstract public void loadRegion(RegionLocation regionLocation);
+
+ /**
+ * Get data if already available
+ *
+ * @param RegionLocation
+ * @return
+ */
+ public ChunkData getChunk(ChunkLocation chunkLocation) {
+ return this.getRegion(chunkLocation.getRegionLocation()).getChunkData(chunkLocation);
+ }
+
+ public SectorData getSector(SectorLocation sectorLocation) {
+ return this.getRegion(sectorLocation.getRegionLocation()).getSectorData(sectorLocation);
+ }
+
+ abstract public RegionData getRegion(RegionLocation regionLocation);
+
+}
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java
new file mode 100644
index 0000000..23270a7
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java
@@ -0,0 +1,70 @@
+package ru.olamedia.olacraft.world.dataProvider;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+
+public class CachedChunkDataProvider extends AbstractChunkDataProvider {
+ private AbstractChunkDataProvider provider;
+ private HashMap<String, RegionData> regionMap = new HashMap<String, RegionData>();
+ private List<String> loading = new ArrayList<String>();
+
+ public CachedChunkDataProvider(AbstractChunkDataProvider provider) {
+ this.provider = provider;
+ }
+
+ private static boolean DEBUG = true;
+
+ private void debug(String s) {
+ if (DEBUG) {
+ System.out.println("[CachedChunkDataProvider] " + s);
+ }
+ }
+
+ @Override
+ public boolean isRegionAvailable(RegionLocation regionLocation) {
+ String key = regionLocation.toString();// regionLocation.x + "-" +
+ // regionLocation.z;
+ if (regionMap.containsKey(key)) {
+ return true;
+ }
+ if (loading.contains(key)) {
+ // return false;
+ }
+ return provider.isRegionAvailable(regionLocation);
+ }
+
+ @Override
+ public void loadRegion(RegionLocation regionLocation) {
+ String key = regionLocation.toString();
+ //debug("loadRegion(" + regionLocation + ")");
+ if (!regionMap.containsKey(key)) {
+ if (!loading.contains(key)) {
+ debug("load()");
+ loading.add(key);
+ provider.loadRegion(regionLocation);
+ }else{
+ //debug("loadRegion(" + regionLocation + ") already in loading");
+ }
+ }else{
+ debug("error: loadRegion(" + regionLocation + ") already in regionMap");
+ }
+ }
+
+ @Override
+ public RegionData getRegion(RegionLocation regionLocation) {
+ String key = regionLocation.toString();
+ if (regionMap.containsKey(key)) {
+ return regionMap.get(key);
+ } else {
+ RegionData data = provider.getRegion(regionLocation);
+ regionMap.put(key, data);
+ loading.remove(key);
+ return data;
+ }
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/LocalChunkDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/LocalChunkDataProvider.java
new file mode 100644
index 0000000..514081f
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/dataProvider/LocalChunkDataProvider.java
@@ -0,0 +1,218 @@
+package ru.olamedia.olacraft.world.dataProvider;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.generator.HeightMapGenerator;
+import ru.olamedia.olacraft.world.generator.RegionGenerator;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+
+public class LocalChunkDataProvider extends AbstractChunkDataProvider {
+ private String worldName;
+ private String path;
+
+ private static boolean DEBUG = true;
+
+ private void debug(String s) {
+ if (DEBUG) {
+ System.out.println("[LocalChunkDataProvider] " + s);
+ }
+ }
+
+ public LocalChunkDataProvider(String worldName) {
+ this.worldName = worldName;
+ path = "data" + File.separator + this.worldName;
+ File worldDir = new File(path);
+ if (!worldDir.isDirectory()) {
+ worldDir.mkdirs();
+ }
+ }
+
+ private int[] seed;
+
+ private int[] getSeed() throws IOException {
+ if (null == seed) {
+ String filename = path + File.separator + "world.seed";
+ File seedFile = new File(filename);
+ // md5 - 32x0-f = 16 bytes or 8 short int
+ seed = new int[8];
+ if (seedFile.exists()) {
+ InputStream in = null;
+ DataInputStream din = null;
+ in = new FileInputStream(seedFile);
+ din = new DataInputStream(in);
+ for (int i = 0; i < 8; i++) {
+ seed[i] = din.readShort();
+ }
+ din.close();
+ in.close();
+ } else {
+ OutputStream out = new FileOutputStream(seedFile);
+ DataOutputStream dout = new DataOutputStream(out);
+ for (int i = 0; i < 8; i++) {
+ seed[i] = (int) (Integer.MAX_VALUE * Math.random());
+ dout.writeShort(seed[i]);
+ }
+ dout.close();
+ out.close();
+ }
+ }
+ return seed;
+ }
+
+ @Override
+ public boolean isRegionAvailable(RegionLocation regionLocation) {
+ return true;
+ }
+
+ @Override
+ public void loadRegion(RegionLocation regionLocation) {
+ // do nothing...
+ debug("loadRegion(" + regionLocation + ")");
+ }
+
+ private ChunkData createChunk(int chunkX, int chunkY, int chunkZ) {
+ debug("createChunk " + chunkX + " " + chunkY + " " + chunkZ);
+ ChunkData data = new ChunkData();
+ try {
+ getSeed();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ HeightMapGenerator.minValue = 1;
+ HeightMapGenerator.maxValue = 64;
+ HeightMapGenerator.init();
+ HeightMapGenerator.seed = seed[0];
+ int[][] heightMap = HeightMapGenerator.getChunkHeightMap(chunkX, chunkZ);
+ for (int y = 0; y < 16; y++) {
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ data.setEmpty(ChunkData.getId(x, y, z), (heightMap[x][z] < chunkY * 16 + y));
+ }
+ }
+ }
+ return data;
+ }
+
+ @Override
+ public RegionData getRegion(RegionLocation regionLocation) {
+ String filename = path + File.separator + regionLocation.getFilename();
+ RegionData data = null;
+ // TODO READ/WRITE FILE
+ File chunkFile = new File(filename);
+ if (chunkFile.exists()) {
+ InputStream in;
+ try {
+ in = new FileInputStream(chunkFile);
+ data = RegionData.loadFrom(in);
+ in.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ } else {
+ data = generateRegion(regionLocation);
+ try {
+ chunkFile.createNewFile();
+ FileOutputStream out = new FileOutputStream(chunkFile);
+ data.writeTo(out);
+ out.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return data;
+ }
+
+ public RegionData generateRegion(RegionLocation regionLocation) {
+ RegionData data = new RegionData();
+ data.location = regionLocation;
+ // TODO FILL HERE
+ RegionGenerator generator = new RegionGenerator();
+ try {
+ generator.setSeed(getSeed());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ generator.generate(data);
+ return data;
+ }
+
+ public ChunkData get(int chunkX, int chunkY, int chunkZ) {
+ debug("get " + chunkX + " " + chunkY + " " + chunkZ);
+ ChunkData data = null;
+ String filename = path + File.separator + chunkX + "_" + chunkY + "_" + chunkZ + ".chunk";
+ /*
+ * File chunkFile = new File(filename);
+ * if (chunkFile.exists()) {
+ * try {
+ * InputStream in = new FileInputStream(chunkFile);
+ * DataInputStream din = new DataInputStream(in);
+ * data = new ChunkData();
+ * data.readFrom(din);
+ * din.close();
+ * in.close();
+ * } catch (FileNotFoundException e) {
+ * e.printStackTrace();
+ * } catch (IOException e) {
+ * e.printStackTrace();
+ * }
+ * } else {
+ */
+ data = createChunk(chunkX, chunkY, chunkZ);
+ /*
+ * OutputStream out = null;
+ * ByteArrayOutputStream bout = null;
+ * DataOutputStream dout = null;
+ * try {
+ * chunkFile.createNewFile();
+ * out = new FileOutputStream(chunkFile);
+ * // bout = new ByteArrayOutputStream(4096);
+ * dout = new DataOutputStream(out);
+ * data.writeTo(dout);
+ * // dout.flush();
+ * // out.write(bout.toByteArray());
+ * out.flush();
+ * } catch (IOException e) {
+ * e.printStackTrace();
+ * } finally {
+ * if (null != dout) {
+ * try {
+ * dout.close();
+ * } catch (IOException e) {
+ * e.printStackTrace();
+ * }
+ * }
+ * if (null != bout) {
+ * try {
+ * bout.close();
+ * } catch (IOException e) {
+ * e.printStackTrace();
+ * }
+ * }
+ * if (null != out) {
+ * try {
+ * out.close();
+ * } catch (IOException e) {
+ * e.printStackTrace();
+ * }
+ * }
+ * }
+ * }
+ */
+ return data;
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/LocalRegionDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/LocalRegionDataProvider.java
new file mode 100644
index 0000000..447bcc3
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/dataProvider/LocalRegionDataProvider.java
@@ -0,0 +1,57 @@
+package ru.olamedia.olacraft.world.dataProvider;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class LocalRegionDataProvider {
+ private String worldName;
+ private String path;
+
+ public LocalRegionDataProvider(String worldName) {
+ this.worldName = worldName;
+ path = "data" + File.separator + this.worldName;
+ File worldDir = new File(path);
+ if (!worldDir.isDirectory()) {
+ worldDir.mkdirs();
+ }
+ }
+
+ private int[] seed;
+
+ private int[] getSeed() throws IOException {
+ if (null == seed) {
+ String filename = path + File.separator + "world.seed";
+ File seedFile = new File(filename);
+ // md5 - 32x0-f = 16 bytes or 8 short int
+ seed = new int[8];
+ if (seedFile.exists()) {
+ InputStream in = null;
+ DataInputStream din = null;
+ in = new FileInputStream(seedFile);
+ din = new DataInputStream(in);
+ for (int i = 0; i < 8; i++) {
+ seed[i] = din.readShort();
+ }
+ din.close();
+ in.close();
+ } else {
+ OutputStream out = new FileOutputStream(seedFile);
+ DataOutputStream dout = new DataOutputStream(out);
+ for (int i = 0; i < 8; i++) {
+ seed[i] = (int) (Integer.MAX_VALUE * Math.random());
+ dout.writeShort(seed[i]);
+ }
+ dout.close();
+ out.close();
+ }
+ }
+ return seed;
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java
new file mode 100644
index 0000000..8284ff9
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java
@@ -0,0 +1,75 @@
+package ru.olamedia.olacraft.world.dataProvider;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import com.esotericsoftware.kryonet.Connection;
+
+import ru.olamedia.olacraft.network.GameClient;
+import ru.olamedia.olacraft.network.packet.GetRegionPacket;
+import ru.olamedia.olacraft.network.packet.IPacket;
+import ru.olamedia.olacraft.network.packet.IPacketListener;
+import ru.olamedia.olacraft.network.packet.RegionDataPacket;
+import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+
+public class RemoteChunkDataProvider extends AbstractChunkDataProvider implements IPacketListener {
+
+ private GameClient client;
+ private HashMap<String, RegionData> map = new HashMap<String, RegionData>();
+ private List<String> loading = new ArrayList<String>();
+
+ public RemoteChunkDataProvider(GameClient client) {
+ this.client = client;
+ this.client.addPacketListener(this);
+ }
+
+ private static boolean DEBUG = true;
+
+ private void debug(String s) {
+ if (DEBUG) {
+ System.out.println("[RemoteChunkDataProvider] " + s);
+ }
+ }
+
+ @Override
+ public void loadRegion(RegionLocation regionLocation) {
+ String key = regionLocation.toString();
+ debug("loadRegion(" + key + ")");
+ if (!loading.contains(key)) {
+ loading.add(key);
+ client.send(new GetRegionPacket(regionLocation));
+ debug("sent packet: GetRegionPacket");
+ }
+ }
+
+ @Override
+ public boolean isRegionAvailable(RegionLocation regionLocation) {
+ String key = regionLocation.toString();
+ if (loading.contains(key)) {
+ return false;
+ }
+ return map.containsKey(key);
+ }
+
+ @Override
+ public RegionData getRegion(RegionLocation regionLocation) {
+ String key = regionLocation.toString();
+ RegionData data = map.get(key);
+ map.remove(key);
+ return data;
+ }
+
+ @Override
+ public void onPacket(Connection connection, IPacket p) {
+ if (p instanceof RegionDataPacket) {
+ debug("received packet [conn " + connection.getID() + "]: ChunkDataPacket");
+ RegionData data = ((RegionDataPacket) p).data;
+ String key = data.location.toString();
+ map.put(key, data);
+ loading.remove(key);
+ }
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/package-info.java b/src/ru/olamedia/olacraft/world/dataProvider/package-info.java
new file mode 100644
index 0000000..6a411e6
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/dataProvider/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.dataProvider; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/generator/HeightMapGenerator.java b/src/ru/olamedia/olacraft/world/generator/HeightMapGenerator.java
new file mode 100644
index 0000000..c3e32b5
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/HeightMapGenerator.java
@@ -0,0 +1,157 @@
+package ru.olamedia.olacraft.world.generator;
+
+import ru.olamedia.olacraft.world.chunk.Chunk;
+import ru.olamedia.olacraft.world.data.HeightMap;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+import libnoiseforjava.NoiseGen.NoiseQuality;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.module.Billow;
+import libnoiseforjava.module.Blend;
+import libnoiseforjava.module.Max;
+import libnoiseforjava.module.Perlin;
+import libnoiseforjava.module.RidgedMulti;
+import libnoiseforjava.module.ScaleBias;
+import libnoiseforjava.module.Select;
+import libnoiseforjava.module.Turbulence;
+import libnoiseforjava.util.NoiseMap;
+import libnoiseforjava.util.NoiseMapBuilderPlane;
+
+public class HeightMapGenerator {
+ public static int minValue;
+ public static int maxValue;
+
+ public static int seed = (int) (Integer.MAX_VALUE * Math.random());
+
+ private static Billow plainsNoise;
+ private static ScaleBias plains;
+ private static RidgedMulti hillsNoise;
+ private static ScaleBias hills;
+ private static RidgedMulti mountainsNoise;
+ private static ScaleBias mountains;
+ private static Perlin terrainType;
+ private static Blend blendedTerrain;
+ private static Select selectedTerrain;
+ private static Max maxTerrain;
+ private static Turbulence turbulence;
+ private static ScaleBias finalTerrain;
+
+ private static boolean isInitialized = false;
+
+ public static void init() {
+ if (isInitialized) {
+ return;
+ }
+ isInitialized = true;
+ try {
+ // PLAINS
+ plainsNoise = new Billow();
+ plainsNoise.setFrequency(0.01);
+ plains = new ScaleBias(plainsNoise);
+ plains.setScale(0.05);
+ plains.setBias(-0.75);
+ // HILLS
+ hillsNoise = new RidgedMulti();
+ hillsNoise.setFrequency(0.01);
+ hills = new ScaleBias(hillsNoise);
+ hills.setScale(0.5);
+ hills.setBias(-0.75);
+ // MOUNTAINS
+ mountainsNoise = new RidgedMulti();
+ mountainsNoise.setFrequency(0.04);
+ mountainsNoise.setOctaveCount(6);
+ turbulence = new Turbulence(mountainsNoise);
+ turbulence.setFrequency(0.2);
+ turbulence.setPower(1);
+ mountains = new ScaleBias(turbulence);
+ mountains.setScale(1.0);
+ mountains.setBias(-1.25);
+ terrainType = new Perlin();
+ terrainType.setOctaveCount(6);
+ terrainType.setFrequency(0.06);
+ terrainType.setPersistence(0.25);
+ terrainType.setNoiseQuality(NoiseQuality.QUALITY_BEST);
+ selectedTerrain = new Select(plains, mountains, terrainType);
+ selectedTerrain.setBounds(0, 1);
+ selectedTerrain.setEdgeFalloff(0.125);
+ blendedTerrain = new Blend(plains, mountains, terrainType);
+ maxTerrain = new Max(plains, turbulence);
+ finalTerrain = new ScaleBias(maxTerrain);
+ finalTerrain.setBias(2);
+ setSeed(seed);
+ } catch (ExceptionInvalidParam e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void setSeed(int newseed) {
+ seed = newseed;
+ plainsNoise.setSeed(seed);
+ hillsNoise.setSeed(seed);
+ mountainsNoise.setSeed(seed);
+ terrainType.setSeed(seed);
+ }
+
+ public static int[][] getChunkHeightMap(int chunkX, int chunkZ) {
+ init();
+ try {
+ NoiseMapBuilderPlane builder = new NoiseMapBuilderPlane(16, 16);
+ // builder.enableSeamless(true);
+ // Perlin plains = new Perlin();
+
+ // Select finalTerrain = new Select(plains, mountains, null);
+ // finalTerrain.setControlModule(terrainType);
+ // finalTerrain.setBounds(0.0, 1000);
+ // finalTerrain.setEdgeFalloff(1.25);
+
+ NoiseMap heightMap = new NoiseMap(16, 16);
+ builder.setSourceModule(maxTerrain);
+ builder.setDestNoiseMap(heightMap);
+ double bx = chunkX;
+ double bz = chunkZ;
+ builder.setDestSize(16, 16);
+ builder.setBounds(bx, bx + 1, bz, bz + 1);
+ builder.build();
+ double[][] heights = heightMap.getNoiseMap();
+ int[][] ints = new int[16][16];
+ // System.out.print("heightmap:");
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ // System.out.print(((float) heights[x][z]) + ";");
+ ints[x][z] = (int) (minValue + (maxValue - minValue) * (heights[x][z] + 1) / 2);
+ }
+ }
+ // System.out.println("");
+ return ints;
+ } catch (ExceptionInvalidParam e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static HeightMap getHeightMap(RegionLocation location) {
+ init();
+ HeightMap map = new HeightMap(256, 256);
+ try {
+ NoiseMapBuilderPlane builder = new NoiseMapBuilderPlane(256, 256);
+ NoiseMap heightMap = new NoiseMap(256, 256);
+ builder.setSourceModule(finalTerrain);
+ builder.setDestNoiseMap(heightMap);
+ builder.setDestSize(256, 256);
+ float bx = location.x;
+ float bz = location.z;
+ builder.setBounds(bx, bx + 1, bz, bz + 1);
+ builder.build();
+ double[][] heights = heightMap.getNoiseMap();
+ for (int x = 0; x < 256; x++) {
+ for (int z = 0; z < 256; z++) {
+ map.setHeight(x, z, 0);
+ //(int) (minValue + (maxValue - minValue) * (heights[x][z] + 1) / 2)
+ }
+ }
+ return map;
+ } catch (ExceptionInvalidParam e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/generator/ImprovedNoise.java b/src/ru/olamedia/olacraft/world/generator/ImprovedNoise.java
new file mode 100644
index 0000000..365aa12
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/ImprovedNoise.java
@@ -0,0 +1,61 @@
+package ru.olamedia.olacraft.world.generator;
+
+//JAVA REFERENCE IMPLEMENTATION OF IMPROVED NOISE - COPYRIGHT 2002 KEN PERLIN.
+
+public final class ImprovedNoise {
+ static public double noise(double x, double y, double z) {
+ int X = (int) Math.floor(x) & 255, // FIND UNIT CUBE THAT
+ Y = (int) Math.floor(y) & 255, // CONTAINS POINT.
+ Z = (int) Math.floor(z) & 255;
+ x -= Math.floor(x); // FIND RELATIVE X,Y,Z
+ y -= Math.floor(y); // OF POINT IN CUBE.
+ z -= Math.floor(z);
+ double u = fade(x), // COMPUTE FADE CURVES
+ v = fade(y), // FOR EACH OF X,Y,Z.
+ w = fade(z);
+ int A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z, // HASH COORDINATES
+ // OF
+ B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z; // THE 8 CUBE
+ // CORNERS,
+
+ return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z), // AND ADD
+ grad(p[BA], x - 1, y, z)), // BLENDED
+ lerp(u, grad(p[AB], x, y - 1, z), // RESULTS
+ grad(p[BB], x - 1, y - 1, z))),// FROM 8
+ lerp(v, lerp(u, grad(p[AA + 1], x, y, z - 1), // CORNERS
+ grad(p[BA + 1], x - 1, y, z - 1)), // OF CUBE
+ lerp(u, grad(p[AB + 1], x, y - 1, z - 1), grad(p[BB + 1], x - 1, y - 1, z - 1))));
+ }
+
+ static double fade(double t) {
+ return t * t * t * (t * (t * 6 - 15) + 10);
+ }
+
+ static double lerp(double t, double a, double b) {
+ return a + t * (b - a);
+ }
+
+ static double grad(int hash, double x, double y, double z) {
+ int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE
+ double u = h < 8 ? x : y, // INTO 12 GRADIENT DIRECTIONS.
+ v = h < 4 ? y : h == 12 || h == 14 ? x : z;
+ return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
+ }
+
+ static final int p[] = new int[512], permutation[] = { 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194,
+ 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26,
+ 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171,
+ 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230,
+ 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187,
+ 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226,
+ 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189,
+ 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129,
+ 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193,
+ 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199,
+ 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24,
+ 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180 };
+ static {
+ for (int i = 0; i < 256; i++)
+ p[256 + i] = p[i] = permutation[i];
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/generator/Lerp.java b/src/ru/olamedia/olacraft/world/generator/Lerp.java
new file mode 100644
index 0000000..cc009fe
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/Lerp.java
@@ -0,0 +1,27 @@
+package ru.olamedia.olacraft.world.generator;
+
+public class Lerp {
+ public static float lerp(float x, float x1, float x2, float q00, float q01) {
+ return ((x2 - x) / (x2 - x1)) * q00 + ((x - x1) / (x2 - x1)) * q01;
+ }
+
+ public static float biLerp(float x, float y, float q11, float q12, float q21, float q22, float x1, float x2,
+ float y1, float y2) {
+ float r1 = lerp(x, x1, x2, q11, q21);
+ float r2 = lerp(x, x1, x2, q12, q22);
+
+ return lerp(y, y1, y2, r1, r2);
+ }
+
+ public static float triLerp(float x, float y, float z, float q000, float q001, float q010, float q011, float q100,
+ float q101, float q110, float q111, float x1, float x2, float y1, float y2, float z1, float z2) {
+ float x00 = lerp(x, x1, x2, q000, q100);
+ float x10 = lerp(x, x1, x2, q010, q110);
+ float x01 = lerp(x, x1, x2, q001, q101);
+ float x11 = lerp(x, x1, x2, q011, q111);
+ float r0 = lerp(y, y1, y2, x00, x01);
+ float r1 = lerp(y, y1, y2, x10, x11);
+
+ return lerp(z, z1, z2, r0, r1);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/generator/RegionGenerator.java b/src/ru/olamedia/olacraft/world/generator/RegionGenerator.java
new file mode 100644
index 0000000..9657e32
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/RegionGenerator.java
@@ -0,0 +1,71 @@
+package ru.olamedia.olacraft.world.generator;
+
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.data.HeightMap;
+import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.data.SectorData;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.location.SectorLocation;
+
+public class RegionGenerator {
+ private int[] seed;
+
+ public void setSeed(int[] seed) {
+ this.seed = seed;
+ }
+
+ public void debug(String s) {
+ System.out.println("[RegionGenerator] " + s);
+ }
+
+ public void generate(RegionData data) {
+ HeightMapGenerator.minValue = -5;
+ HeightMapGenerator.maxValue = 100;
+ HeightMapGenerator.init();
+ HeightMapGenerator.seed = seed[0];
+ BlockLocation offset = data.location.getBlockLocation();
+ // int[][] heightMap =
+ // HeightMapGenerator.getHeightMap(data.location.getBlockLocation().x,
+ // data.location.getBlockLocation().z, 256, 256);
+ debug(data.location.toString());
+ data.heightMap = HeightMapGenerator.getHeightMap(data.location);
+ //debug(data.heightMap.toString());
+ data.sectorData = new SectorData[16][16];
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ // CREATE SECTOR
+ SectorData sector = new SectorData();
+ sector.location = new SectorLocation(offset.x + x * 16, offset.z + z * 16);
+ sector.heightMap = new HeightMap(16, 16);
+ sector.chunkData = new ChunkData[16];
+ for (int y = 0; y < 16; y++) {
+ // CREATE CHUNK
+ ChunkData chunk = new ChunkData();
+ chunk.location = new ChunkLocation(sector.location.x, y, sector.location.z);
+ int chunkOffsetY = y * 16 - 128;
+ for (int inChunkX = 0; inChunkX < 16; inChunkX++) {
+ for (int inChunkZ = 0; inChunkZ < 16; inChunkZ++) {
+ int height = data.heightMap.getHeight(x * 16 + inChunkX, z * 16 + inChunkZ);
+ //System.out.println("height: " + height);
+ sector.heightMap.setHeight(inChunkX, inChunkZ, height);
+ for (int inChunkY = 0; inChunkY < 16; inChunkY++) {
+ //height = sector.heightMap.getHeight(inChunkX, inChunkZ);
+ int id = ChunkData.getId(inChunkX, inChunkY, inChunkZ);
+ if (chunkOffsetY + inChunkY > height) {
+ chunk.setEmpty(id, true);
+ } else {
+ //System.out.println("not empty, height: " + height);
+ chunk.setEmpty(id, false);
+ }
+ }
+ }
+ }
+ chunk.compact();
+ sector.chunkData[y] = chunk;
+ }
+ data.sectorData[x][z] = sector;
+ }
+ }
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/generator/package-info.java b/src/ru/olamedia/olacraft/world/generator/package-info.java
new file mode 100644
index 0000000..2f62117
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.generator; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/location/BlockLocation.java b/src/ru/olamedia/olacraft/world/location/BlockLocation.java
new file mode 100644
index 0000000..b104bad
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/location/BlockLocation.java
@@ -0,0 +1,37 @@
+package ru.olamedia.olacraft.world.location;
+
+import java.io.Serializable;
+
+import ru.olamedia.olacraft.world.chunk.Chunk;
+
+public class BlockLocation implements Serializable {
+ private static final long serialVersionUID = -4987461467575474762L;
+ public int x;
+ public int y;
+ public int z;
+
+ public BlockLocation() {
+ }
+
+ public BlockLocation(int x, int y, int z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public ChunkLocation getChunkLocation() {
+ return new ChunkLocation(Chunk.v(x), Chunk.v(y + 128), Chunk.v(z));
+ }
+
+ public RegionLocation getRegionLocation() {
+ return new RegionLocation(Chunk.v(Chunk.v(x)), Chunk.v(Chunk.v(z)));
+ }
+
+ public SectorLocation getSectorLocation() {
+ return new SectorLocation(Chunk.v(x), Chunk.v(z));
+ }
+
+ public String toString() {
+ return "blockLocation[" + x + "," + y + "," + z + "]";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/location/ChunkLocation.java b/src/ru/olamedia/olacraft/world/location/ChunkLocation.java
new file mode 100644
index 0000000..57acc52
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/location/ChunkLocation.java
@@ -0,0 +1,40 @@
+package ru.olamedia.olacraft.world.location;
+
+import java.io.Serializable;
+
+import ru.olamedia.olacraft.world.chunk.Chunk;
+
+public class ChunkLocation implements Serializable {
+ private static final long serialVersionUID = -3620722885522274470L;
+
+ public ChunkLocation() {
+
+ }
+
+ public ChunkLocation(int x, int y, int z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public int x;
+ public int y;
+ public int z;
+
+ public SectorLocation getSectorLocation() {
+ return new SectorLocation(x, z);
+ }
+
+ public RegionLocation getRegionLocation() {
+ return new RegionLocation(Chunk.v(x), Chunk.v(z));
+ }
+
+ public String toString() {
+ return "chunkLocation[" + x + "," + y + "," + z + "]";
+ }
+ /*
+ * public BlockSlice getSlice(){
+ *
+ * }
+ */
+}
diff --git a/src/ru/olamedia/olacraft/world/location/RegionLocation.java b/src/ru/olamedia/olacraft/world/location/RegionLocation.java
new file mode 100644
index 0000000..59a57ec
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/location/RegionLocation.java
@@ -0,0 +1,29 @@
+package ru.olamedia.olacraft.world.location;
+
+import java.io.Serializable;
+
+public class RegionLocation implements Serializable {
+ private static final long serialVersionUID = -141619138379029773L;
+ public int x;
+ public int z;
+
+ public RegionLocation() {
+ }
+
+ public RegionLocation(int x, int z) {
+ this.x = x;
+ this.z = z;
+ }
+
+ public String toString() {
+ return "regionLocation[" + x + "," + z + "]";
+ }
+
+ public String getFilename() {
+ return "" + x + "_" + z + ".region";
+ }
+
+ public BlockLocation getBlockLocation() {
+ return new BlockLocation(x * 256, 0, z * 256);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/location/SectorLocation.java b/src/ru/olamedia/olacraft/world/location/SectorLocation.java
new file mode 100644
index 0000000..59390b8
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/location/SectorLocation.java
@@ -0,0 +1,29 @@
+package ru.olamedia.olacraft.world.location;
+
+import java.io.Serializable;
+
+import ru.olamedia.olacraft.world.chunk.Chunk;
+
+public class SectorLocation implements Serializable {
+ private static final long serialVersionUID = 4500216114186249375L;
+
+ public SectorLocation() {
+
+ }
+
+ public SectorLocation(int x, int z) {
+ this.x = x;
+ this.z = z;
+ }
+
+ public int x;
+ public int z;
+
+ public RegionLocation getRegionLocation() {
+ return new RegionLocation(Chunk.v(x), Chunk.v(z));
+ }
+
+ public String toString() {
+ return "sectorLocation[" + x + "," + z + "]";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/location/package-info.java b/src/ru/olamedia/olacraft/world/location/package-info.java
new file mode 100644
index 0000000..37f205d
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/location/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.location; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/package-info.java b/src/ru/olamedia/olacraft/world/package-info.java
new file mode 100644
index 0000000..914d8d2
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/provider/IChunkProvider.java b/src/ru/olamedia/olacraft/world/provider/IChunkProvider.java
new file mode 100644
index 0000000..5076c75
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/IChunkProvider.java
@@ -0,0 +1,8 @@
+package ru.olamedia.olacraft.world.provider;
+
+import ru.olamedia.olacraft.world.block.Block;
+
+public interface IChunkProvider {
+ public boolean isEmptyBlock(int x, int y, int z);
+ public Block getBlock(int x, int y, int z);
+}
diff --git a/src/ru/olamedia/olacraft/world/provider/WorldProvider.java b/src/ru/olamedia/olacraft/world/provider/WorldProvider.java
new file mode 100644
index 0000000..8dacce9
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/WorldProvider.java
@@ -0,0 +1,130 @@
+package ru.olamedia.olacraft.world.provider;
+
+import ru.olamedia.olacraft.game.SpawnLocation;
+import ru.olamedia.olacraft.world.WorldInfo;
+import ru.olamedia.olacraft.world.block.Block;
+import ru.olamedia.olacraft.world.chunk.Chunk;
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.dataProvider.AbstractChunkDataProvider;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+
+public class WorldProvider {
+ private WorldInfo info = new WorldInfo();
+ private AbstractChunkDataProvider dataProvider;
+
+ public WorldInfo getInfo() {
+ return info;
+ }
+
+ public void setInfo(WorldInfo worldInfo) {
+ info = worldInfo;
+ }
+
+ /*
+ * public AbstractChunkDataProvider getChunkDataProvider() {
+ * return dataProvider;
+ * }
+ */
+
+ public void setChunkDataProvider(AbstractChunkDataProvider provider) {
+ dataProvider = provider;
+ }
+
+ public SpawnLocation getSpawnLocation(int connectionId) {
+ SpawnLocation l = new SpawnLocation();
+ int maxShift = 10;
+ l.x = (int) (maxShift - Math.random() * 2 * maxShift);
+ l.z = (int) (maxShift - Math.random() * 2 * maxShift);
+ System.out.print("Searching spawn Y");
+ BlockLocation spawnLocation = new BlockLocation(l.x, 0, l.z);
+ for (int y = info.maxHeight; y > info.minHeight; y--) {
+ // search for floor block
+ spawnLocation.y = y;
+ System.out.print(y + ". ");
+ ChunkData chunk = dataProvider.getChunk(spawnLocation.getChunkLocation());
+ boolean notEmpty = !chunk.isEmpty(ChunkData.getId(Chunk.in(spawnLocation.x), Chunk.in(spawnLocation.y),
+ Chunk.in(spawnLocation.z)));
+ if (notEmpty) {
+ // found
+ l.y = y + 1;
+ System.out.println("found: " + y);
+ return l;
+ }
+ }
+ System.out.println("not found ");
+ // not found
+ l.y = info.maxHeight;
+ return l;
+ }
+
+ public boolean renderBottom(int x, int y, int z) {
+ return (!isEmptyBlock(x, y, z)) && (isEmptyBlock(x, y - 1, z));
+ }
+
+ public boolean renderTop(int x, int y, int z) {
+ return (!isEmptyBlock(x, y, z)) && (isEmptyBlock(x, y + 1, z));
+ }
+
+ public boolean renderLeft(int x, int y, int z) {
+ return (!isEmptyBlock(x, y, z)) && (isEmptyBlock(x - 1, y, z));
+ }
+
+ public boolean renderRight(int x, int y, int z) {
+ return (!isEmptyBlock(x, y, z)) && (isEmptyBlock(x + 1, y, z));
+ }
+
+ public boolean renderBack(int x, int y, int z) {
+ return (!isEmptyBlock(x, y, z)) && (isEmptyBlock(x, y, z - 1));
+ }
+
+ public boolean renderFront(int x, int y, int z) {
+ return (!isEmptyBlock(x, y, z)) && (isEmptyBlock(x, y, z + 1));
+ }
+
+ public boolean isEmptyBlock(int x, int y, int z) {
+ BlockLocation blockLocation = new BlockLocation(x, y, z);
+
+ if (isChunkAvailable(blockLocation.getChunkLocation())) {
+ ChunkData data = dataProvider.getChunk(blockLocation.getChunkLocation());
+ if (null != data) {
+ return data.isEmpty(blockLocation);
+ }
+ }
+ return false;
+ }
+
+ public void requestChunk(int chunkX, int chunkY, int chunkZ) {
+ ChunkLocation chunkLocation = new ChunkLocation(chunkX, chunkY, chunkZ);
+ // getChunkDataProvider().loadRegion(chunkLocation.getRegionLocation());
+ loadChunk(chunkLocation);
+ }
+
+ public boolean isChunkAvailable(ChunkLocation chunkLocation) {
+ return dataProvider.isChunkAvailable(chunkLocation);
+ }
+
+ public boolean isAvailableBlock(int x, int y, int z) {
+ BlockLocation blockLocation = new BlockLocation(x, y, z);
+ return dataProvider.isChunkAvailable(blockLocation.getChunkLocation());
+ }
+
+ public void loadChunk(ChunkLocation chunkLocation) {
+ dataProvider.loadChunk(chunkLocation);
+ }
+
+ public RegionData getRegion(RegionLocation regionLocation) {
+ return dataProvider.getRegion(regionLocation);
+ }
+
+ public Block getBlock(int x, int y, int z) {
+ BlockLocation blockLocation = new BlockLocation(x, y, z);
+ return new Block(this, x, y, z);
+ }
+
+ public ChunkData getChunk(ChunkLocation chunkLocation) {
+ return dataProvider.getChunk(chunkLocation);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/provider/blockData/BlockData.java b/src/ru/olamedia/olacraft/world/provider/blockData/BlockData.java
new file mode 100644
index 0000000..94be4d7
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/blockData/BlockData.java
@@ -0,0 +1,5 @@
+package ru.olamedia.olacraft.world.provider.blockData;
+
+public class BlockData {
+
+}
diff --git a/src/ru/olamedia/olacraft/world/provider/blockData/EmptyBlockData.java b/src/ru/olamedia/olacraft/world/provider/blockData/EmptyBlockData.java
new file mode 100644
index 0000000..ab17107
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/blockData/EmptyBlockData.java
@@ -0,0 +1,5 @@
+package ru.olamedia.olacraft.world.provider.blockData;
+
+public class EmptyBlockData implements IBlockData{
+ public boolean notEmpty = false;
+}
diff --git a/src/ru/olamedia/olacraft/world/provider/blockData/IBlockData.java b/src/ru/olamedia/olacraft/world/provider/blockData/IBlockData.java
new file mode 100644
index 0000000..95dfb35
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/blockData/IBlockData.java
@@ -0,0 +1,5 @@
+package ru.olamedia.olacraft.world.provider.blockData;
+
+public interface IBlockData {
+ public boolean notEmpty = false;
+}
diff --git a/src/ru/olamedia/olacraft/world/provider/blockData/package-info.java b/src/ru/olamedia/olacraft/world/provider/blockData/package-info.java
new file mode 100644
index 0000000..0fa952a
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/blockData/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.provider.blockData; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/provider/package-info.java b/src/ru/olamedia/olacraft/world/provider/package-info.java
new file mode 100644
index 0000000..c43643a
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.provider; \ No newline at end of file