Started making chunks asynchronous

This commit is contained in:
jsrobson10 2020-08-26 20:07:23 +10:00
parent 0cbb9c8551
commit 877c5371a0
18 changed files with 251 additions and 54 deletions

View File

@ -33,6 +33,7 @@ import projectzombie.settings.Environment;
import projectzombie.settings.Settings; import projectzombie.settings.Settings;
import projectzombie.time.GameTimer; import projectzombie.time.GameTimer;
import projectzombie.time.NoSleep; import projectzombie.time.NoSleep;
import projectzombie.worker.WorkerChunks;
import projectzombie.worker.WorkerLighting; import projectzombie.worker.WorkerLighting;
import projectzombie.world.World; import projectzombie.world.World;
import projectzombie.world.chunk.ChunkEventHandler; import projectzombie.world.chunk.ChunkEventHandler;
@ -48,6 +49,7 @@ public class Main
public static Random rand = new Random(); public static Random rand = new Random();
public static Menu menu; public static Menu menu;
public static WorkerLighting workerLighting; public static WorkerLighting workerLighting;
public static WorkerChunks workerChunks;
public static boolean game_paused = false; public static boolean game_paused = false;
public static int tickrate = 10; public static int tickrate = 10;
@ -57,7 +59,10 @@ public class Main
{ {
clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
workerChunks = new WorkerChunks();
workerLighting = new WorkerLighting(); workerLighting = new WorkerLighting();
workerChunks.start();
workerLighting.start(); workerLighting.start();
MathHelpers.init(); MathHelpers.init();
@ -113,6 +118,7 @@ public class Main
{ {
// Kill the worker thread // Kill the worker thread
workerLighting.kill(); workerLighting.kill();
workerChunks.kill();
} }
} }
} }

View File

@ -171,7 +171,7 @@ public class DisplayRenderUI
GL33.glDisable(GL33.GL_DEPTH_TEST); GL33.glDisable(GL33.GL_DEPTH_TEST);
if(Main.menu.doGameRender && Main.menu.showIngameGUI) { if(Main.menu.doGameRender && Main.menu.showIngameGUI && ChunkEventHandler.loaded) {
renderGameGui(); renderGameGui();
} }

View File

@ -2,6 +2,7 @@ package projectzombie.entity;
import mainloop.task.IMainloopTask; import mainloop.task.IMainloopTask;
import projectzombie.Main; import projectzombie.Main;
import projectzombie.world.chunk.ChunkEventHandler;
public class EntityEventHandler implements IMainloopTask public class EntityEventHandler implements IMainloopTask
{ {
@ -21,7 +22,8 @@ public class EntityEventHandler implements IMainloopTask
public void MainLoopUpdate() public void MainLoopUpdate()
{ {
Main.menu.update(); Main.menu.update();
if(!Main.menu.doGameloop) {
if(!Main.menu.doGameloop || !ChunkEventHandler.loaded) {
return; return;
} }

View File

@ -134,6 +134,7 @@ public class Models
public static final ModelGui UI_WATER = new ModelGui(Resources.ATLAS.get("/gui/water.png"), new Vec2d(0.75, 0.75)); public static final ModelGui UI_WATER = new ModelGui(Resources.ATLAS.get("/gui/water.png"), new Vec2d(0.75, 0.75));
public static final ModelGui UI_ITEM_HOVER = new ModelGui(Resources.ATLAS.get("/gui/pixel_black.png")).setOpacity(0.25); public static final ModelGui UI_ITEM_HOVER = new ModelGui(Resources.ATLAS.get("/gui/pixel_black.png")).setOpacity(0.25);
public static final ModelGui UI_TEXT_BG = new ModelGui(Resources.ATLAS.get("/gui/pixel_white.png")).setColor(0.5f, 0.5f, 0.5f); public static final ModelGui UI_TEXT_BG = new ModelGui(Resources.ATLAS.get("/gui/pixel_white.png")).setColor(0.5f, 0.5f, 0.5f);
public static final ModelGui UI_STONE_BG = new ModelGui(Resources.ATLAS.get("/tile/stone.png"));
public static final ModelItem UI_SLOT_ARMOR_HELMET = new ModelItem(Resources.ATLAS.get("/gui/slot_armor_helmet.png")); public static final ModelItem UI_SLOT_ARMOR_HELMET = new ModelItem(Resources.ATLAS.get("/gui/slot_armor_helmet.png"));
public static final ModelItem UI_SLOT_ARMOR_CHEST = new ModelItem(Resources.ATLAS.get("/gui/slot_armor_chest.png")); public static final ModelItem UI_SLOT_ARMOR_CHEST = new ModelItem(Resources.ATLAS.get("/gui/slot_armor_chest.png"));

View File

@ -0,0 +1,62 @@
package projectzombie.menu;
import gl_engine.matrix.Matrix4;
import gl_engine.vec.Vec3d;
import projectzombie.Main;
import projectzombie.init.Models;
import projectzombie.input.types.InputGUI;
import projectzombie.menu.gui.GUI;
import projectzombie.menu.gui.GUIAlignment;
import projectzombie.menu.gui.GUILabel;
import projectzombie.util.gl.GlHelpers;
import projectzombie.world.chunk.ChunkEventHandler;
public class MenuLoadingWorld extends Menu
{
private GUI gui;
public MenuLoadingWorld()
{
doGameloop = true;
doGameRender = true;
keepMouse = false;
showIngameGUI = false;
GUILabel label = new GUILabel();
label.setText("Loading world...");
label.setAlign(GUIAlignment.CENTRE);
gui = new GUI();
input = new InputGUI(gui);
gui.add(label);
}
@Override
public void render()
{
double a = GlHelpers.getAspectRatio();
for(int x = 0; x < 16; x ++) {
for(int y = 0; y < 16; y ++)
{
Models.UI_STONE_BG.setModel(Matrix4.multiply(
Matrix4.scale(new Vec3d(1.25 * a, 1.25 * a, 1)),
Matrix4.translate(new Vec3d(-10 * a + 1.25 * a * x, -10 * a + 1.25 * a * y, 0))));
Models.UI_STONE_BG.render();
}
}
gui.render();
}
@Override
public void update()
{
super.update();
if(ChunkEventHandler.loaded) {
Main.menu = new MenuGame();
}
}
}

View File

@ -109,7 +109,7 @@ public class MenuSaves extends Menu
reader.saveDatabase(); reader.saveDatabase();
Main.world = new World(saves.get(index).filename); Main.world = new World(saves.get(index).filename);
Main.menu = new MenuGame(); Main.menu = new MenuLoadingWorld();
} }
private void deleteSave(int index) private void deleteSave(int index)

View File

@ -158,7 +158,7 @@ public class MenuWorldNew extends Menu
reader.saveDatabase(); reader.saveDatabase();
World.createWorld(path_new, seed); World.createWorld(path_new, seed);
Main.menu = new MenuGame(); Main.menu = new MenuLoadingWorld();
} }
@Override @Override

View File

@ -0,0 +1,25 @@
package projectzombie.worker;
import java.util.Random;
import gl_engine.vec.Vec2i;
import projectzombie.world.chunk.Chunk;
import projectzombie.world.layer.Layer;
import projectzombie.world.layer.layergen.LayerGen;
class WorkerChunkTask
{
Chunk chunk;
LayerGen layergen;
Layer layer;
Random rand;
Vec2i pos;
public WorkerChunkTask(LayerGen layergen, Layer layer, Chunk chunk, Random rand, Vec2i pos) {
this.chunk = chunk;
this.layergen = layergen;
this.layer = layer;
this.rand = rand;
this.pos = pos;
}
}

View File

@ -0,0 +1,80 @@
package projectzombie.worker;
import java.util.Random;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import gl_engine.vec.Vec2i;
import projectzombie.world.chunk.Chunk;
import projectzombie.world.layer.Layer;
import projectzombie.world.layer.layergen.LayerGen;
public class WorkerChunks extends Thread
{
private boolean running = false;
private Vector<WorkerChunkTask> chunks_in = new Vector<WorkerChunkTask>();
private AtomicReference<Vector<Chunk>> chunks_out = new AtomicReference<Vector<Chunk>>();
public void generateChunk(LayerGen layergen, Layer layer, Chunk chunk, Random rand, Vec2i pos) {
chunks_in.add(new WorkerChunkTask(layergen, layer, chunk, rand, pos));
}
public Vector<Chunk> getChunks() {
return chunks_out.getAndSet(new Vector<Chunk>());
}
public boolean hasChunk(Vec2i cpos)
{
boolean has[] = {false};
chunks_in.forEach(c -> {
if(c.pos.equal(cpos)) {
has[0] = true;
}
});
return has[0];
}
public WorkerChunks() {
chunks_out.set(new Vector<Chunk>());
}
@Override
public void run()
{
running = true;
try
{
while(running)
{
if(chunks_in.size() == 0) {
Thread.sleep(1);
continue;
}
WorkerChunkTask ct = chunks_in.remove(0);
Chunk chunk = ct.chunk;
LayerGen layergen = ct.layergen;
Layer layer = ct.layer;
Random rand = ct.rand;
Vec2i pos = ct.pos;
layergen.generateChunk(chunk, layer, rand, pos);
chunks_out.get().add(chunk);
}
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
public void kill() {
running = false;
}
}

View File

@ -22,6 +22,7 @@ import projectzombie.display.bossbar.BossBars;
import projectzombie.entity.player.EntityPlayer; import projectzombie.entity.player.EntityPlayer;
import projectzombie.init.LayerGenerators; import projectzombie.init.LayerGenerators;
import projectzombie.init.Layers; import projectzombie.init.Layers;
import projectzombie.menu.MenuLoadingWorld;
import projectzombie.model.Model; import projectzombie.model.Model;
import projectzombie.time.GameTimer; import projectzombie.time.GameTimer;
import projectzombie.world.chunk.ChunkEventHandler; import projectzombie.world.chunk.ChunkEventHandler;
@ -197,6 +198,7 @@ public class World implements IBdfClassManager
public void setLayer(int id) public void setLayer(int id)
{ {
Main.menu = new MenuLoadingWorld();
ChunkEventHandler.loaded = false; ChunkEventHandler.loaded = false;
DisplayLighting.clearLighting(); DisplayLighting.clearLighting();
DisplayLighting.setDirty(); DisplayLighting.setDirty();

View File

@ -51,6 +51,8 @@ public class Chunk implements IBdfClassManager
private byte tiles_front_meta[] = new byte[CHUNK_INDEX]; private byte tiles_front_meta[] = new byte[CHUNK_INDEX];
private byte tiles_back_meta[] = new byte[CHUNK_INDEX]; private byte tiles_back_meta[] = new byte[CHUNK_INDEX];
private byte tiles_lighting[] = new byte[CHUNK_INDEX]; private byte tiles_lighting[] = new byte[CHUNK_INDEX];
private byte tiles_temperature[] = new byte[CHUNK_INDEX];
private byte tiles_humidity[] = new byte[CHUNK_INDEX];
public ArrayList<Entity> entities = new ArrayList<Entity>(); public ArrayList<Entity> entities = new ArrayList<Entity>();
private Layer layer; private Layer layer;
public Vec2i c_pos; public Vec2i c_pos;
@ -174,11 +176,6 @@ public class Chunk implements IBdfClassManager
// Make all these tiles void // Make all these tiles void
tiles_back[i] = Tiles.VOID; tiles_back[i] = Tiles.VOID;
tiles_front[i] = Tiles.VOID; tiles_front[i] = Tiles.VOID;
tiles_back_meta[i] = 0;
tiles_front_meta[i] = 0;
// Set the light level to 0
tiles_lighting[i] = 0;
} }
} }
@ -508,6 +505,36 @@ public class Chunk implements IBdfClassManager
return null; return null;
} }
public void setTemperature(double v, Vec2i pos)
{
// Get the id
Vec2i cpos = new Vec2i(0, 0);
cpos.x = MathHelpers.mod(pos.x, CHUNK_SIZE.mx);
cpos.y = MathHelpers.mod(pos.y, CHUNK_SIZE.my);
int id = cpos.getId(CHUNK_SIZE);
setTemperature(v, id);
}
public void setTemperature(double v, int id) {
tiles_temperature[id] = (byte)(v * 127);
}
public void setHumidity(double v, Vec2i pos)
{
// Get the id
Vec2i cpos = new Vec2i(0, 0);
cpos.x = MathHelpers.mod(pos.x, CHUNK_SIZE.mx);
cpos.y = MathHelpers.mod(pos.y, CHUNK_SIZE.my);
int id = cpos.getId(CHUNK_SIZE);
setHumidity(v, id);
}
public void setHumidity(double v, int id) {
tiles_humidity[id] = (byte)(v * 127);
}
public void setBackTile(TileState tile, Vec2i pos) public void setBackTile(TileState tile, Vec2i pos)
{ {
// Get the id // Get the id

View File

@ -30,7 +30,8 @@ public class ChunkEventHandler implements IMainloopTask
// Get the layer // Get the layer
Vec3d ppos = Main.player.getPos(); Vec3d ppos = Main.player.getPos();
Layer layer = Main.world.getLayer(); Layer layer = Main.world.getLayer();
loaded = true;
int loaded_count = 0;
// Loop over all the chunks in this layer // Loop over all the chunks in this layer
for(Map2DElement<Chunk> ce : layer.chunks) for(Map2DElement<Chunk> ce : layer.chunks)
@ -41,20 +42,30 @@ public class ChunkEventHandler implements IMainloopTask
if( if(
// Is this chunk beyond the simulation distance // Is this chunk beyond the simulation distance
px > ce.pos.x + Chunk.SIMULATION_DISTANCE || px > ce.pos.x + Chunk.SIMULATION_DISTANCE + 1 ||
px < ce.pos.x - Chunk.SIMULATION_DISTANCE || px < ce.pos.x - Chunk.SIMULATION_DISTANCE - 1 ||
py > ce.pos.y + Chunk.SIMULATION_DISTANCE || py > ce.pos.y + Chunk.SIMULATION_DISTANCE + 1 ||
py < ce.pos.y - Chunk.SIMULATION_DISTANCE py < ce.pos.y - Chunk.SIMULATION_DISTANCE - 1
) { ) {
// Unload the chunk // Unload the chunk
layer.unloadChunk(ce.pos); layer.unloadChunk(ce.pos);
ce.o.free(); ce.o.free();
} }
else {
loaded_count += 1;
}
} }
if(loaded_count >= 4 * Chunk.SIMULATION_DISTANCE * (Chunk.SIMULATION_DISTANCE + 1) + 1) {
loaded = true;
}
layer.loadChunks();
// Loop over the simulation distance // Loop over the simulation distance
for(int x=-Chunk.SIMULATION_DISTANCE;x<Chunk.SIMULATION_DISTANCE;x++) { for(int x=-Chunk.SIMULATION_DISTANCE;x<=Chunk.SIMULATION_DISTANCE;x++) {
for(int y=-Chunk.SIMULATION_DISTANCE;y<Chunk.SIMULATION_DISTANCE;y++) for(int y=-Chunk.SIMULATION_DISTANCE;y<=Chunk.SIMULATION_DISTANCE;y++)
{ {
// Get the chunk based on the player position // Get the chunk based on the player position
int cx = MathHelpers.floor(ppos.x / 16) + x; int cx = MathHelpers.floor(ppos.x / 16) + x;
@ -62,7 +73,7 @@ public class ChunkEventHandler implements IMainloopTask
Vec2i c_pos = new Vec2i(cx, cy); Vec2i c_pos = new Vec2i(cx, cy);
// Is this chunk not loaded // Is this chunk not loaded
if(!layer.chunkLoaded(c_pos)) if(!layer.chunkLoaded(c_pos) && !Main.workerChunks.hasChunk(c_pos))
{ {
// Load the chunk // Load the chunk
layer.loadChunk(c_pos); layer.loadChunk(c_pos);

View File

@ -230,6 +230,16 @@ public class Layer implements IBdfClassManager
chunks.get(c_pos).spawnEntity(entity); chunks.get(c_pos).spawnEntity(entity);
} }
public void loadChunks()
{
for(Chunk chunk : Main.workerChunks.getChunks())
{
Vec2i pos = chunk.c_pos;
chunks.set(pos, chunk);
chunk.clearDirty();
}
}
public void loadChunk(Vec2i pos) public void loadChunk(Vec2i pos)
{ {
// Has the chunk been saved for later // Has the chunk been saved for later
@ -244,9 +254,7 @@ public class Layer implements IBdfClassManager
// Create and generate the chunk // Create and generate the chunk
Chunk chunk = new Chunk(this, pos, rand); Chunk chunk = new Chunk(this, pos, rand);
chunks.set(pos, chunk); Main.workerChunks.generateChunk(layergen, this, chunk, new Random(cseed), pos);
layergen.generateChunk(chunk, this, new Random(cseed), pos);
chunk.clearDirty();
} }
} }

View File

@ -21,9 +21,7 @@ public abstract class LayerGen implements IMap2D<Chunk>
} }
public abstract void generateChunk(Chunk chunk, Layer layer, Random rand, Vec2i pos); public abstract void generateChunk(Chunk chunk, Layer layer, Random rand, Vec2i pos);
public abstract double getTemperatureStatic(Layer layer, Vec2d pos); public abstract double getTemperature(Layer layer, Vec2d pos);
public abstract double getTemperatureDynamic(Layer layer, Vec2d pos);
public abstract double getHumidity(Layer layer, Vec2d pos);
public abstract void spawnEntities(Layer layer, Random rand); public abstract void spawnEntities(Layer layer, Random rand);
public abstract TileState getTileDestroyed(Layer layer, Vec2i pos); public abstract TileState getTileDestroyed(Layer layer, Vec2i pos);
public abstract ColorRange getLightLevel(); public abstract ColorRange getLightLevel();

View File

@ -109,18 +109,8 @@ public class LayerGenBossArena extends LayerGen implements LayerGenRememberPlaye
} }
@Override @Override
public double getTemperatureStatic(Layer layer, Vec2d pos) { public double getTemperature(Layer layer, Vec2d pos) {
return 0.8; return 0.8;
} }
@Override
public double getTemperatureDynamic(Layer layer, Vec2d pos) {
return 0.8;
}
@Override
public double getHumidity(Layer layer, Vec2d pos) {
return 0;
}
} }

View File

@ -22,8 +22,6 @@ import projectzombie.world.layer.Layer;
public class LayerGenCaves extends LayerGen public class LayerGenCaves extends LayerGen
{ {
@Override
public double getTemperatureStatic(Layer layer, Vec2d pos) public double getTemperatureStatic(Layer layer, Vec2d pos)
{ {
// Get the noise generator // Get the noise generator
@ -32,11 +30,10 @@ public class LayerGenCaves extends LayerGen
} }
@Override @Override
public double getTemperatureDynamic(Layer layer, Vec2d pos) { public double getTemperature(Layer layer, Vec2d pos) {
return getTemperatureStatic(layer, pos); return getTemperatureStatic(layer, pos);
} }
@Override
public double getHumidity(Layer layer, Vec2d pos) public double getHumidity(Layer layer, Vec2d pos)
{ {
// Get the noise generator // Get the noise generator

View File

@ -30,7 +30,6 @@ public class LayerGenEarth extends LayerGen
layer.noise_gens[3].eval(pos.x / 64.0, pos.y / 64.0, t) * 0.02); layer.noise_gens[3].eval(pos.x / 64.0, pos.y / 64.0, t) * 0.02);
} }
@Override
public double getTemperatureStatic(Layer layer, Vec2d pos) public double getTemperatureStatic(Layer layer, Vec2d pos)
{ {
// Get the noise generator // Get the noise generator
@ -39,7 +38,7 @@ public class LayerGenEarth extends LayerGen
} }
@Override @Override
public double getTemperatureDynamic(Layer layer, Vec2d pos) public double getTemperature(Layer layer, Vec2d pos)
{ {
// Get the noise generator // Get the noise generator
double humidity = getHumidity(layer, pos); double humidity = getHumidity(layer, pos);
@ -50,7 +49,6 @@ public class LayerGenEarth extends LayerGen
return MathHelpers.map(terrain_noise.eval(pos.x / World.BIOME_SIZE, pos.y / World.BIOME_SIZE), -1, 1, 0, 0.5 + light); return MathHelpers.map(terrain_noise.eval(pos.x / World.BIOME_SIZE, pos.y / World.BIOME_SIZE), -1, 1, 0, 0.5 + light);
} }
@Override
public double getHumidity(Layer layer, Vec2d pos) public double getHumidity(Layer layer, Vec2d pos)
{ {
// Get the noise generator // Get the noise generator
@ -67,8 +65,8 @@ public class LayerGenEarth extends LayerGen
layer.noise_gens = new NoiseGenerator[] layer.noise_gens = new NoiseGenerator[]
{ {
new NoiseGeneratorSimplex(rand, 64), // Temperature new NoiseGeneratorSimplex(rand, 4), // Temperature
new NoiseGeneratorSimplex(rand, 64), // Humidity new NoiseGeneratorSimplex(rand, 4), // Humidity
new NoiseGeneratorSimplex(lrand), // Wind new NoiseGeneratorSimplex(lrand), // Wind
new NoiseGeneratorSimplex(lrand), // Wind new NoiseGeneratorSimplex(lrand), // Wind

View File

@ -178,18 +178,8 @@ public class LayerGenLavaCaves extends LayerGen
} }
@Override @Override
public double getTemperatureStatic(Layer layer, Vec2d pos) { public double getTemperature(Layer layer, Vec2d pos) {
return MathHelpers.map(layer.noise_gens[0].eval(pos.x / 128, pos.y / 128), -1, 1, 0.8, 1); return MathHelpers.map(layer.noise_gens[0].eval(pos.x / 128, pos.y / 128), -1, 1, 0.8, 1);
} }
@Override
public double getTemperatureDynamic(Layer layer, Vec2d pos) {
return getTemperatureStatic(layer, pos);
}
@Override
public double getHumidity(Layer layer, Vec2d pos) {
return 0;
}
} }