Merge branch 'liteCraft' into Vulkan
commit
0c7925b280
|
@ -58,8 +58,10 @@ public class Litecraft extends Game
|
||||||
if (this.world != null)
|
if (this.world != null)
|
||||||
{
|
{
|
||||||
System.out.println("Saving chunks...");
|
System.out.println("Saving chunks...");
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
this.world.unloadAllChunks();
|
this.world.unloadAllChunks();
|
||||||
this.getSave().saveGlobalData(this.world.getSeed(), this.player);
|
this.getSave().saveGlobalData(this.world.getSeed(), this.player);
|
||||||
|
System.out.println("Saved world in " + (System.currentTimeMillis() - time) + " milliseconds");
|
||||||
}
|
}
|
||||||
engine.cleanup();
|
engine.cleanup();
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
|
|
|
@ -159,5 +159,5 @@ public final class LitecraftSave
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String SAVE_DIR = "./saves/";
|
private static final String SAVE_DIR = "./saves/";
|
||||||
private static final int RENDER_SIZE = 10;
|
private static final int RENDER_SIZE = 5;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,10 +32,14 @@ public class IngameHUD extends Screen
|
||||||
@Override
|
@Override
|
||||||
public void tick()
|
public void tick()
|
||||||
{
|
{
|
||||||
|
// long maxMemory = Runtime.getRuntime().maxMemory();
|
||||||
|
long totalMemory = Runtime.getRuntime().totalMemory();
|
||||||
|
long freeMemory = Runtime.getRuntime().freeMemory();
|
||||||
|
long usedMemory = totalMemory - freeMemory;
|
||||||
Vector4i dbg = litecraft.dbgStats;
|
Vector4i dbg = litecraft.dbgStats;
|
||||||
Vector3f position = GingerRegister.getInstance().game.data.player.getPosition();
|
Vector3f position = GingerRegister.getInstance().game.data.player.getPosition();
|
||||||
debugText.setText("FPS: " + dbg.x() + " UPS: " + dbg.y + " TPS: " + dbg.z);
|
debugText.setText("FPS: " + dbg.x() + " UPS: " + dbg.y + " TPS: " + dbg.z + " Mem: " + (usedMemory / 1024 / 1024) + "MB / " + (totalMemory / 1024 / 1024) + " MB");
|
||||||
positionText.setText("Position " + (int) position.x() + ", " + (int) position.y() + ", "+ (int) position.z());
|
positionText.setText("Position " + (int) position.x() + ", " + (int) position.y() + ", "+ (int) position.z() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.github.halotroop.litecraft.world;
|
package com.github.halotroop.litecraft.world;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.function.ToIntFunction;
|
import java.util.function.ToIntFunction;
|
||||||
|
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
@ -20,19 +20,24 @@ public class Chunk implements BlockAccess, WorldGenConstants, SODSerializable
|
||||||
* @param x in-chunk x coordinate.
|
* @param x in-chunk x coordinate.
|
||||||
* @param y in-chunk y coordinate.
|
* @param y in-chunk y coordinate.
|
||||||
* @param z in-chunk z coordinate.
|
* @param z in-chunk z coordinate.
|
||||||
* @return creates a long that represents a coordinate, for use as a key in the array.
|
* @return creates a long that represents a coordinate, for use as a key in arrays.
|
||||||
*/
|
*/
|
||||||
public static int index(int x, int y, int z)
|
public static int index(int x, int y, int z)
|
||||||
{ return (x & MAX_POS) | ((y & MAX_POS) << POS_SHIFT) | ((z & MAX_POS) << DOUBLE_SHIFT); }
|
{ return (x & MAX_POS) | ((y & MAX_POS) << POS_SHIFT) | ((z & MAX_POS) << DOUBLE_SHIFT); }
|
||||||
|
|
||||||
private final Block[] blocks = new Block[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
private final Block[] blocks = new Block[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
||||||
private BlockInstance[] blockEntities = new BlockInstance[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
private BlockInstance[] blockInstances = new BlockInstance[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
||||||
private boolean shouldRender = false;
|
private boolean shouldRender = false;
|
||||||
public final int chunkX, chunkY, chunkZ;
|
public final int chunkX, chunkY, chunkZ;
|
||||||
public final int chunkStartX, chunkStartY, chunkStartZ;
|
public final int chunkStartX, chunkStartY, chunkStartZ;
|
||||||
private boolean fullyGenerated = false;
|
private boolean fullyGenerated = false;
|
||||||
public final int dimension;
|
public final int dimension;
|
||||||
private boolean dirty = true;
|
private boolean dirty = true;
|
||||||
|
private World world;
|
||||||
|
/**
|
||||||
|
* A holder for the rendered blocks in this chunk. This array is *NOT* safe to use for getting BIs at a position!
|
||||||
|
* It can vary in size from 0 to 512 elements long and must only be read linearly.
|
||||||
|
*/
|
||||||
private BlockInstance[] renderedBlocks = new BlockInstance[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
private BlockInstance[] renderedBlocks = new BlockInstance[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
||||||
|
|
||||||
public Chunk(World world, int chunkX, int chunkY, int chunkZ, int dimension)
|
public Chunk(World world, int chunkX, int chunkY, int chunkZ, int dimension)
|
||||||
|
@ -63,8 +68,8 @@ public class Chunk implements BlockAccess, WorldGenConstants, SODSerializable
|
||||||
public BlockInstance getBlockInstance(int x, int y, int z)
|
public BlockInstance getBlockInstance(int x, int y, int z)
|
||||||
{
|
{
|
||||||
if (x > CHUNK_SIZE || y > CHUNK_SIZE || z > CHUNK_SIZE || x < 0 || y < 0 || z < 0)
|
if (x > CHUNK_SIZE || y > CHUNK_SIZE || z > CHUNK_SIZE || x < 0 || y < 0 || z < 0)
|
||||||
{ throw new RuntimeException("Block [" + x + ", " + y + ", " + z + "] out of chunk bounds!"); }
|
{ throw new RuntimeException("BlockInstance [" + x + ", " + y + ", " + z + "] out of chunk bounds!"); }
|
||||||
return this.blockEntities[index(x, y, z)];
|
return this.blockInstances[index(x, y, z)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(BlockRenderer blockRenderer)
|
public void render(BlockRenderer blockRenderer)
|
||||||
|
@ -72,7 +77,9 @@ public class Chunk implements BlockAccess, WorldGenConstants, SODSerializable
|
||||||
if (shouldRender)
|
if (shouldRender)
|
||||||
{
|
{
|
||||||
if (dirty)
|
if (dirty)
|
||||||
|
{
|
||||||
dirty = false;
|
dirty = false;
|
||||||
|
List<BlockInstance> tempList = new ArrayList<>();
|
||||||
Arrays.fill(renderedBlocks, null);
|
Arrays.fill(renderedBlocks, null);
|
||||||
for (int x = 0; x < CHUNK_SIZE; x++)
|
for (int x = 0; x < CHUNK_SIZE; x++)
|
||||||
for (int y = 0; y < CHUNK_SIZE; y++)
|
for (int y = 0; y < CHUNK_SIZE; y++)
|
||||||
|
@ -80,19 +87,35 @@ public class Chunk implements BlockAccess, WorldGenConstants, SODSerializable
|
||||||
{
|
{
|
||||||
BlockInstance block = getBlockInstance(x, y, z);
|
BlockInstance block = getBlockInstance(x, y, z);
|
||||||
|
|
||||||
// Why are we deliberately rendering blocks on the outside of the chunk???
|
// Check for chunk edges to avoid errors when get the neighboring blocks, TODO fix this
|
||||||
if (x == 0 || x == CHUNK_SIZE - 1 || z == 0 || z == CHUNK_SIZE - 1 || y == 0 || y == CHUNK_SIZE - 1)
|
if (x == 0 || x == CHUNK_SIZE - 1 || z == 0 || z == CHUNK_SIZE - 1 || y == 0 || y == CHUNK_SIZE - 1)
|
||||||
{
|
{
|
||||||
renderedBlocks[index(x, y, z)] = block;
|
tempList.add(block);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Check for non-full-cubes around the block
|
|
||||||
if ((!getBlock(x - 1, y, z).isFullCube() || !getBlock(x + 1, y, z).isFullCube() || !getBlock(x, y - 1, z).isFullCube()
|
// Check for air. Yes this is stupid, TODO fix this too
|
||||||
|| !getBlock(x, y + 1, z).isFullCube() || !getBlock(x, y, z - 1).isFullCube() || !getBlock(x, y, z + 1).isFullCube()))
|
try
|
||||||
renderedBlocks[index(x, y, z)] = block;
|
{
|
||||||
|
if (getBlockInstance(x - 1, y, z).getModel() == null || getBlockInstance(x + 1, y, z).getModel() == null ||
|
||||||
|
getBlockInstance(x, y - 1, z).getModel() == null || getBlockInstance(x, y + 1, z).getModel() == null ||
|
||||||
|
getBlockInstance(x, y, z - 1).getModel() == null || getBlockInstance(x, y, z + 1).getModel() == null)
|
||||||
|
{
|
||||||
|
tempList.add(block);
|
||||||
|
}
|
||||||
|
} catch (NullPointerException e)
|
||||||
|
{ // this seems to be a hotspot for errors
|
||||||
|
e.printStackTrace(); // so I can add a debug breakpoint on this line
|
||||||
|
throw e; // e
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
renderedBlocks = tempList.toArray(BlockInstance[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
blockRenderer.prepareRender();
|
||||||
blockRenderer.render(renderedBlocks);
|
blockRenderer.render(renderedBlocks);
|
||||||
|
blockRenderer.shader.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +136,7 @@ public class Chunk implements BlockAccess, WorldGenConstants, SODSerializable
|
||||||
else if (z < 0) z = 0;
|
else if (z < 0) z = 0;
|
||||||
//
|
//
|
||||||
this.blocks[index(x, y, z)] = block;
|
this.blocks[index(x, y, z)] = block;
|
||||||
if (this.shouldRender) this.blockEntities[index(x, y, z)] =
|
if (this.shouldRender) this.blockInstances[index(x, y, z)] =
|
||||||
new BlockInstance(block, new Vector3f(this.chunkStartX + x, this.chunkStartY + y, this.chunkStartZ + z));
|
new BlockInstance(block, new Vector3f(this.chunkStartX + x, this.chunkStartY + y, this.chunkStartZ + z));
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +153,7 @@ public class Chunk implements BlockAccess, WorldGenConstants, SODSerializable
|
||||||
{
|
{
|
||||||
Block block = this.blocks[index(x, y, z)];
|
Block block = this.blocks[index(x, y, z)];
|
||||||
|
|
||||||
this.blockEntities[index(x, y, z)] = new BlockInstance(block,
|
this.blockInstances[index(x, y, z)] = new BlockInstance(block,
|
||||||
new Vector3f(
|
new Vector3f(
|
||||||
this.chunkStartX + x,
|
this.chunkStartX + x,
|
||||||
this.chunkStartY + y,
|
this.chunkStartY + y,
|
||||||
|
@ -139,7 +162,7 @@ public class Chunk implements BlockAccess, WorldGenConstants, SODSerializable
|
||||||
else if (!render && this.shouldRender) // else if it has been changed to false.
|
else if (!render && this.shouldRender) // else if it has been changed to false.
|
||||||
// we need to check both variables because there are two cases that make
|
// we need to check both variables because there are two cases that make
|
||||||
// the if statement fall to here
|
// the if statement fall to here
|
||||||
blockEntities = new BlockInstance[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
blockInstances = new BlockInstance[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
||||||
this.shouldRender = render;
|
this.shouldRender = render;
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
package com.github.halotroop.litecraft.world;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.LongConsumer;
|
|
||||||
|
|
||||||
import com.github.hydos.multithreading.GingerThread;
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.longs.*;
|
|
||||||
|
|
||||||
public class DynamicChunkLoader extends GingerThread
|
|
||||||
{
|
|
||||||
|
|
||||||
private static int instances = 0;
|
|
||||||
public int chunkX, chunkY, chunkZ;
|
|
||||||
public World world;
|
|
||||||
|
|
||||||
public DynamicChunkLoader(int chunkX, int chunkY, int chunkZ, World world)
|
|
||||||
{
|
|
||||||
this.chunkX = chunkX;
|
|
||||||
this.chunkY = chunkY;
|
|
||||||
this.chunkZ = chunkZ;
|
|
||||||
this.world = world;
|
|
||||||
this.setName("Dynamic Chunk thread");
|
|
||||||
instances++;
|
|
||||||
System.out.println("allocations of dynamic chunk loader: " + instances);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
Long2ObjectMap<Chunk> chunks = world.chunks; //this is to seperate the lists so we dont create render bugs
|
|
||||||
|
|
||||||
started = true;
|
|
||||||
List<Chunk> toKeep = new ArrayList<>();
|
|
||||||
// loop over rendered area, adding chunks that are needed
|
|
||||||
for (int x = chunkX - this.world.renderBound; x < chunkX + this.world.renderBound; x++)
|
|
||||||
for (int z = chunkZ - this.world.renderBound; z < chunkZ + this.world.renderBound; z++)
|
|
||||||
for (int y = chunkY - this.world.renderBound; y < chunkY + this.world.renderBound; y++)
|
|
||||||
toKeep.add(this.world.getChunkToLoad(x, y, z));
|
|
||||||
// list of keys to remove
|
|
||||||
LongList toRemove = new LongArrayList();
|
|
||||||
// check which loaded chunks are not neccesary
|
|
||||||
chunks.forEach((pos, chunk) ->
|
|
||||||
{
|
|
||||||
if (!toKeep.contains(chunk))
|
|
||||||
toRemove.add((long) pos);
|
|
||||||
});
|
|
||||||
// unload unneccesary chunks from chunk array
|
|
||||||
toRemove.forEach((LongConsumer) pos -> this.world.unloadChunk(pos));
|
|
||||||
// populate chunks to render if they are not rendered, then render them
|
|
||||||
toKeep.forEach(chunk -> {
|
|
||||||
if (!chunk.isFullyGenerated())
|
|
||||||
{
|
|
||||||
this.world.populateChunk(chunk);
|
|
||||||
chunk.setFullyGenerated(true);
|
|
||||||
}
|
|
||||||
boolean alreadyRendering = chunk.doRender(); // if it's already rendering then it's most likely in the map
|
|
||||||
chunk.setRender(true);
|
|
||||||
if (!alreadyRendering)
|
|
||||||
chunks.put(this.world.posHash(chunk.chunkX, chunk.chunkY, chunk.chunkZ), chunk);
|
|
||||||
});
|
|
||||||
this.world.chunks = chunks;
|
|
||||||
this.finished = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -4,6 +4,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ForkJoinPool;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.function.LongConsumer;
|
import java.util.function.LongConsumer;
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@ public class World implements BlockAccess, WorldGenConstants
|
||||||
private final LitecraftSave save;
|
private final LitecraftSave save;
|
||||||
private final long seed;
|
private final long seed;
|
||||||
private final int dimension;
|
private final int dimension;
|
||||||
|
private final ForkJoinPool threadPool;
|
||||||
public Player player;
|
public Player player;
|
||||||
int renderBound;
|
int renderBound;
|
||||||
int renderBoundVertical;
|
int renderBoundVertical;
|
||||||
|
@ -37,7 +39,7 @@ public class World implements BlockAccess, WorldGenConstants
|
||||||
private final BlockInstance dummy;
|
private final BlockInstance dummy;
|
||||||
public World(long seed, int renderSize, Dimension<?> dim, LitecraftSave save)
|
public World(long seed, int renderSize, Dimension<?> dim, LitecraftSave save)
|
||||||
{
|
{
|
||||||
new DynamicChunkLoader(0, 0, 0, this);
|
this.threadPool = new ForkJoinPool(4, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true);
|
||||||
this.dummy = new BlockInstance(Blocks.ANDESITE, new Vector3f(0, 0, 0));
|
this.dummy = new BlockInstance(Blocks.ANDESITE, new Vector3f(0, 0, 0));
|
||||||
this.dummy.setVisible(false);
|
this.dummy.setVisible(false);
|
||||||
this.chunks = new Long2ObjectArrayMap<>();
|
this.chunks = new Long2ObjectArrayMap<>();
|
||||||
|
@ -65,7 +67,7 @@ public class World implements BlockAccess, WorldGenConstants
|
||||||
int y = SEA_LEVEL;
|
int y = SEA_LEVEL;
|
||||||
int attemptsRemaining = 255;
|
int attemptsRemaining = 255;
|
||||||
|
|
||||||
while (attemptsRemaining --> 0)
|
while (attemptsRemaining-- > 0)
|
||||||
{
|
{
|
||||||
// DO NOT CHANGE TO y++
|
// DO NOT CHANGE TO y++
|
||||||
if (this.getBlock(x, ++y, z) == Blocks.AIR)
|
if (this.getBlock(x, ++y, z) == Blocks.AIR)
|
||||||
|
@ -136,10 +138,11 @@ public class World implements BlockAccess, WorldGenConstants
|
||||||
if (chunk == null) return false;
|
if (chunk == null) return false;
|
||||||
// Otherwise save the chunk
|
// Otherwise save the chunk
|
||||||
AtomicBoolean result = new AtomicBoolean(false);
|
AtomicBoolean result = new AtomicBoolean(false);
|
||||||
CompletableFuture.runAsync(() -> {
|
CompletableFuture.runAsync(() ->
|
||||||
|
{
|
||||||
result.set(this.save.saveChunk(chunk));
|
result.set(this.save.saveChunk(chunk));
|
||||||
this.chunks.remove(posHash);
|
this.chunks.remove(posHash);
|
||||||
});
|
}, threadPool);
|
||||||
return result.get();
|
return result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,19 +183,33 @@ public class World implements BlockAccess, WorldGenConstants
|
||||||
public void render(BlockRenderer blockRenderer)
|
public void render(BlockRenderer blockRenderer)
|
||||||
{
|
{
|
||||||
blockRenderer.prepareModel(this.dummy.getModel());
|
blockRenderer.prepareModel(this.dummy.getModel());
|
||||||
this.chunks.forEach((pos, c) -> c.render(blockRenderer));
|
try
|
||||||
|
{
|
||||||
|
this.chunks.forEach((pos, c) -> c.render(blockRenderer));
|
||||||
|
}
|
||||||
|
catch (NullPointerException e)
|
||||||
|
{
|
||||||
|
System.out.println("Null chunk - we should look into fixing this");
|
||||||
|
}
|
||||||
blockRenderer.unbindModel();
|
blockRenderer.unbindModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unloadAllChunks()
|
public void unloadAllChunks()
|
||||||
{
|
{
|
||||||
LongList chunkPositions = new LongArrayList();
|
LongList chunkPositions = new LongArrayList();
|
||||||
|
List<CompletableFuture> futures = new ArrayList<>();
|
||||||
if (this.chunks != null)
|
if (this.chunks != null)
|
||||||
|
{
|
||||||
this.chunks.forEach((pos, chunk) ->
|
this.chunks.forEach((pos, chunk) ->
|
||||||
{ // for every chunk in memory
|
{ // for every chunk in memory
|
||||||
chunkPositions.add((long) pos); // add pos to chunk positions list for removal later
|
futures.add(CompletableFuture.runAsync(() ->
|
||||||
this.save.saveChunk(chunk); // save chunk
|
{
|
||||||
|
chunkPositions.add((long) pos); // add pos to chunk positions list for removal later
|
||||||
|
this.save.saveChunk(chunk); // save chunk
|
||||||
|
}, threadPool));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
futures.forEach(CompletableFuture::join);
|
||||||
chunkPositions.forEach((LongConsumer) (pos -> this.chunks.remove(pos))); // remove all chunks
|
chunkPositions.forEach((LongConsumer) (pos -> this.chunks.remove(pos))); // remove all chunks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,43 +220,38 @@ public class World implements BlockAccess, WorldGenConstants
|
||||||
|
|
||||||
public void updateLoadedChunks(int chunkX, int chunkY, int chunkZ)
|
public void updateLoadedChunks(int chunkX, int chunkY, int chunkZ)
|
||||||
{
|
{
|
||||||
//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
CompletableFuture.runAsync(() ->
|
||||||
//Ginger.getInstance().threading.registerChunkThreadToWaitlist(new DynamicChunkLoader(chunkX, chunkY, chunkZ, this));
|
|
||||||
|
|
||||||
Long2ObjectMap<Chunk> chunksList = this.chunks;
|
|
||||||
|
|
||||||
//FIXME completable futures
|
|
||||||
|
|
||||||
List<Chunk> toKeep = new ArrayList<>();
|
|
||||||
// loop over rendered area, adding chunks that are needed
|
|
||||||
for (int x = chunkX - this.renderBound; x < chunkX + this.renderBound; x++)
|
|
||||||
for (int z = chunkZ - this.renderBound; z < chunkZ + this.renderBound; z++)
|
|
||||||
for (int y = chunkY - this.renderBound; y < chunkY + this.renderBound; y++)
|
|
||||||
toKeep.add(this.getChunkToLoad(x, y, z));
|
|
||||||
|
|
||||||
LongList toRemove = new LongArrayList();
|
|
||||||
// check which loaded chunks are not neccesary
|
|
||||||
chunksList.forEach((pos, chunk) ->
|
|
||||||
{
|
{
|
||||||
if (!toKeep.contains(chunk))
|
List<Chunk> toKeep = new ArrayList<>();
|
||||||
toRemove.add((long) pos);
|
// loop over rendered area, adding chunks that are needed
|
||||||
});
|
for (int x = chunkX - this.renderBound; x < chunkX + this.renderBound; x++)
|
||||||
// unload unneccesary chunks from chunk array
|
for (int z = chunkZ - this.renderBound; z < chunkZ + this.renderBound; z++)
|
||||||
toRemove.forEach((LongConsumer) this::unloadChunk);
|
for (int y = chunkY - this.renderBound; y < chunkY + this.renderBound; y++)
|
||||||
|
toKeep.add(this.getChunkToLoad(x, y, z));
|
||||||
|
|
||||||
toKeep.forEach(chunk -> {
|
LongList toRemove = new LongArrayList();
|
||||||
if (!chunk.isFullyGenerated())
|
// check which loaded chunks are not neccesary
|
||||||
|
chunks.forEach((pos, chunk) ->
|
||||||
{
|
{
|
||||||
this.populateChunk(chunk);
|
if (!toKeep.contains(chunk))
|
||||||
chunk.setFullyGenerated(true);
|
toRemove.add((long) pos);
|
||||||
}
|
});
|
||||||
boolean alreadyRendering = chunk.doRender(); // if it's already rendering then it's most likely in the map
|
// unload unneccesary chunks from chunk array
|
||||||
chunk.setRender(true);
|
toRemove.forEach((LongConsumer) this::unloadChunk);
|
||||||
if (!alreadyRendering)
|
|
||||||
chunksList.put(this.posHash(chunk.chunkX, chunk.chunkY, chunk.chunkZ), chunk);
|
|
||||||
});
|
|
||||||
this.chunks = chunksList;
|
|
||||||
|
|
||||||
|
toKeep.forEach(chunk ->
|
||||||
|
{
|
||||||
|
if (!chunk.isFullyGenerated())
|
||||||
|
{
|
||||||
|
this.populateChunk(chunk);
|
||||||
|
chunk.setFullyGenerated(true);
|
||||||
|
}
|
||||||
|
boolean alreadyRendering = chunk.doRender(); // if it's already rendering then it's most likely in the map
|
||||||
|
chunk.setRender(true);
|
||||||
|
if (!alreadyRendering)
|
||||||
|
chunks.put(this.posHash(chunk.chunkX, chunk.chunkY, chunk.chunkZ), chunk);
|
||||||
|
});
|
||||||
|
}, threadPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class GenerationWorld implements BlockAccess, WorldGenConstants
|
private static final class GenerationWorld implements BlockAccess, WorldGenConstants
|
||||||
|
|
|
@ -4,7 +4,6 @@ import org.joml.Matrix4f;
|
||||||
import org.lwjgl.opengl.*;
|
import org.lwjgl.opengl.*;
|
||||||
|
|
||||||
import com.github.halotroop.litecraft.types.block.BlockInstance;
|
import com.github.halotroop.litecraft.types.block.BlockInstance;
|
||||||
import com.github.halotroop.litecraft.world.Chunk;
|
|
||||||
import com.github.halotroop.litecraft.world.gen.WorldGenConstants;
|
import com.github.halotroop.litecraft.world.gen.WorldGenConstants;
|
||||||
import com.github.hydos.ginger.engine.common.api.GingerRegister;
|
import com.github.hydos.ginger.engine.common.api.GingerRegister;
|
||||||
import com.github.hydos.ginger.engine.common.elements.objects.RenderObject;
|
import com.github.hydos.ginger.engine.common.elements.objects.RenderObject;
|
||||||
|
@ -17,7 +16,7 @@ import com.github.hydos.ginger.engine.opengl.utils.GlLoader;
|
||||||
|
|
||||||
public class BlockRenderer extends Renderer implements WorldGenConstants
|
public class BlockRenderer extends Renderer implements WorldGenConstants
|
||||||
{
|
{
|
||||||
private StaticShader shader;
|
public StaticShader shader;
|
||||||
public int atlasID;
|
public int atlasID;
|
||||||
|
|
||||||
public BlockRenderer(StaticShader shader, Matrix4f projectionMatrix)
|
public BlockRenderer(StaticShader shader, Matrix4f projectionMatrix)
|
||||||
|
@ -76,21 +75,17 @@ public class BlockRenderer extends Renderer implements WorldGenConstants
|
||||||
public void render(BlockInstance[] renderList)
|
public void render(BlockInstance[] renderList)
|
||||||
{
|
{
|
||||||
prepareRender();
|
prepareRender();
|
||||||
for (int x = 0; x < CHUNK_SIZE; x++)
|
|
||||||
for (int y = 0; y < CHUNK_SIZE; y++)
|
for (BlockInstance entity : renderList) {
|
||||||
for (int z = 0; z < CHUNK_SIZE; z++)
|
if (entity != null && entity.getModel() != null)
|
||||||
{
|
{
|
||||||
BlockInstance entity = renderList[Chunk.index(x, y, z)];
|
TexturedModel blockModel = entity.getModel();
|
||||||
if (entity != null && entity.getModel() != null)
|
GL11.glBindTexture(GL11.GL_TEXTURE_2D, blockModel.getTexture().getTextureID());
|
||||||
{
|
prepBlockInstance(entity);
|
||||||
TexturedModel blockModel = entity.getModel();
|
GL11.glDrawElements(GL11.GL_TRIANGLES, blockModel.getRawModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
|
||||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, blockModel.getTexture().getTextureID());
|
}
|
||||||
prepBlockInstance(entity);
|
}
|
||||||
GL11.glDrawElements(GL11.GL_TRIANGLES, blockModel.getRawModel().getVertexCount(),
|
// disableWireframe();
|
||||||
GL11.GL_UNSIGNED_INT, 0);
|
// shader.stop();
|
||||||
}
|
|
||||||
}
|
|
||||||
disableWireframe();
|
|
||||||
shader.stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package com.github.halotroop.litecraft.world.gen;
|
||||||
|
|
||||||
public interface WorldGenConstants
|
public interface WorldGenConstants
|
||||||
{
|
{
|
||||||
int POS_SHIFT = 3;
|
int POS_SHIFT = 4;
|
||||||
int DOUBLE_SHIFT = POS_SHIFT * 2;
|
int DOUBLE_SHIFT = POS_SHIFT * 2;
|
||||||
int CHUNK_SIZE = (int) Math.pow(2, POS_SHIFT);
|
int CHUNK_SIZE = (int) Math.pow(2, POS_SHIFT);
|
||||||
int MAX_POS = CHUNK_SIZE - 1;
|
int MAX_POS = CHUNK_SIZE - 1;
|
||||||
|
|
|
@ -10,7 +10,8 @@ import com.github.halotroop.litecraft.world.gen.WorldGenConstants;
|
||||||
public class CavesModifier implements WorldModifier, WorldGenConstants
|
public class CavesModifier implements WorldModifier, WorldGenConstants
|
||||||
{
|
{
|
||||||
private OctaveSimplexNoise caveNoise;
|
private OctaveSimplexNoise caveNoise;
|
||||||
//
|
private static final double THRESHOLD = 0.1;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(long seed)
|
public void initialize(long seed)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,7 +8,6 @@ import com.github.hydos.ginger.engine.common.font.GUIText;
|
||||||
import com.github.hydos.ginger.engine.common.screen.Screen;
|
import com.github.hydos.ginger.engine.common.screen.Screen;
|
||||||
import com.github.hydos.ginger.engine.opengl.postprocessing.Fbo;
|
import com.github.hydos.ginger.engine.opengl.postprocessing.Fbo;
|
||||||
import com.github.hydos.ginger.engine.opengl.render.MasterRenderer;
|
import com.github.hydos.ginger.engine.opengl.render.MasterRenderer;
|
||||||
import com.github.hydos.multithreading.GingerThreading;
|
|
||||||
|
|
||||||
/** Used if a game wants to access engine variables safely */
|
/** Used if a game wants to access engine variables safely */
|
||||||
public class GingerRegister
|
public class GingerRegister
|
||||||
|
@ -19,7 +18,6 @@ public class GingerRegister
|
||||||
public static GingerRegister getInstance()
|
public static GingerRegister getInstance()
|
||||||
{ return INSTANCE; }
|
{ return INSTANCE; }
|
||||||
|
|
||||||
public GingerThreading threadRegister;
|
|
||||||
public List<GUIText> texts;
|
public List<GUIText> texts;
|
||||||
public List<TextureButton> guiButtons;
|
public List<TextureButton> guiButtons;
|
||||||
public List<Fbo> fbos;
|
public List<Fbo> fbos;
|
||||||
|
@ -30,12 +28,11 @@ public class GingerRegister
|
||||||
public GingerRegister()
|
public GingerRegister()
|
||||||
{
|
{
|
||||||
INSTANCE = this;
|
INSTANCE = this;
|
||||||
threadRegister = new GingerThreading();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerButton(TextureButton button)
|
public void registerButton(TextureButton button)
|
||||||
{
|
{
|
||||||
if (guiButtons == null) guiButtons = new ArrayList<TextureButton>();
|
if (guiButtons == null) guiButtons = new ArrayList<>();
|
||||||
guiButtons.add(button);
|
guiButtons.add(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +41,7 @@ public class GingerRegister
|
||||||
|
|
||||||
public void registerText(GUIText guiText)
|
public void registerText(GUIText guiText)
|
||||||
{
|
{
|
||||||
if (texts == null) texts = new ArrayList<GUIText>();
|
if (texts == null) texts = new ArrayList<>();
|
||||||
texts.add(guiText);
|
texts.add(guiText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ import com.github.hydos.ginger.engine.opengl.postprocessing.*;
|
||||||
import com.github.hydos.ginger.engine.opengl.render.MasterRenderer;
|
import com.github.hydos.ginger.engine.opengl.render.MasterRenderer;
|
||||||
import com.github.hydos.ginger.engine.opengl.render.tools.MousePicker;
|
import com.github.hydos.ginger.engine.opengl.render.tools.MousePicker;
|
||||||
import com.github.hydos.ginger.engine.opengl.utils.GlLoader;
|
import com.github.hydos.ginger.engine.opengl.utils.GlLoader;
|
||||||
import com.github.hydos.multithreading.GingerThreading;
|
|
||||||
|
|
||||||
public class GingerGL
|
public class GingerGL
|
||||||
{
|
{
|
||||||
|
@ -25,7 +24,6 @@ public class GingerGL
|
||||||
public MousePicker picker;
|
public MousePicker picker;
|
||||||
public FontType globalFont;
|
public FontType globalFont;
|
||||||
public Fbo contrastFbo;
|
public Fbo contrastFbo;
|
||||||
public GingerThreading threading;
|
|
||||||
|
|
||||||
private Timer timer;
|
private Timer timer;
|
||||||
TickListener gameTickListener = new TickListener()
|
TickListener gameTickListener = new TickListener()
|
||||||
|
@ -102,7 +100,6 @@ public class GingerGL
|
||||||
{
|
{
|
||||||
INSTANCE = this;
|
INSTANCE = this;
|
||||||
registry = new GingerRegister();
|
registry = new GingerRegister();
|
||||||
threading = new GingerThreading();
|
|
||||||
registry.registerGame(game);
|
registry.registerGame(game);
|
||||||
timer = new Timer(game.data.tickSpeed);
|
timer = new Timer(game.data.tickSpeed);
|
||||||
timer.addTickListener(gameTickListener);
|
timer.addTickListener(gameTickListener);
|
||||||
|
@ -114,15 +111,11 @@ public class GingerGL
|
||||||
|
|
||||||
public void startGameLoop()
|
public void startGameLoop()
|
||||||
{
|
{
|
||||||
if (!threading.isAlive()) // Prevents this from accidentally being run twice
|
while (!Window.closed())
|
||||||
{
|
{
|
||||||
threading.start();
|
update(Litecraft.getInstance().data); // Run this regardless, (so as fast as possible)
|
||||||
while (!Window.closed())
|
if (timer.tick()) Litecraft.getInstance().tps += 1; // Run this only [ticklimit] times per second (This invokes gameTickListener.onTick!)
|
||||||
{
|
if (Window.shouldRender()) registry.game.render(); // Run this only [framelimit] times per second
|
||||||
update(Litecraft.getInstance().data); // Run this regardless, (so as fast as possible)
|
|
||||||
if (timer.tick()) Litecraft.getInstance().tps += 1; // Run this only [ticklimit] times per second (This invokes gameTickListener.onTick!)
|
|
||||||
if (Window.shouldRender()) registry.game.render(); // Run this only [framelimit] times per second
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
registry.game.exit();
|
registry.game.exit();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue