start multithreading, the sane way

pull/12/head
SuperCoder7979 2020-02-29 22:08:50 -05:00
parent c3ae97b99d
commit d026feb525
3 changed files with 54 additions and 7 deletions

View File

@ -10,6 +10,7 @@ import it.unimi.dsi.fastutil.longs.*;
public class DynamicChunkLoader extends GingerThread public class DynamicChunkLoader extends GingerThread
{ {
private static int instances = 0;
public int chunkX, chunkY, chunkZ; public int chunkX, chunkY, chunkZ;
public World world; public World world;
@ -20,6 +21,8 @@ public class DynamicChunkLoader extends GingerThread
this.chunkZ = chunkZ; this.chunkZ = chunkZ;
this.world = world; this.world = world;
this.setName("Dynamic Chunk thread"); this.setName("Dynamic Chunk thread");
instances++;
System.out.println("allocations of dynamic chunk loader: " + instances);
} }
@Override @Override

View File

@ -1,6 +1,10 @@
package com.github.halotroop.litecraft.world; package com.github.halotroop.litecraft.world;
import java.util.ArrayList;
import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.LongConsumer; import java.util.function.LongConsumer;
import org.joml.Vector3f; import org.joml.Vector3f;
@ -11,7 +15,6 @@ import com.github.halotroop.litecraft.world.block.BlockRenderer;
import com.github.halotroop.litecraft.world.dimension.Dimension; import com.github.halotroop.litecraft.world.dimension.Dimension;
import com.github.halotroop.litecraft.world.gen.*; import com.github.halotroop.litecraft.world.gen.*;
import com.github.halotroop.litecraft.world.gen.modifier.WorldModifier; import com.github.halotroop.litecraft.world.gen.modifier.WorldModifier;
import com.github.hydos.ginger.engine.api.Ginger;
import com.github.hydos.ginger.engine.elements.objects.Player; import com.github.hydos.ginger.engine.elements.objects.Player;
import com.github.hydos.ginger.engine.obj.ModelLoader; import com.github.hydos.ginger.engine.obj.ModelLoader;
import com.github.hydos.ginger.engine.render.models.TexturedModel; import com.github.hydos.ginger.engine.render.models.TexturedModel;
@ -52,8 +55,10 @@ public class World implements BlockAccess, WorldGenConstants
this.renderBound = renderSize / 2; this.renderBound = renderSize / 2;
this.renderBoundVertical = this.renderBound / 2; this.renderBoundVertical = this.renderBound / 2;
if (this.renderBoundVertical < 2) if (this.renderBoundVertical < 2)
{
this.renderBoundVertical = 2; this.renderBoundVertical = 2;
} }
}
public int findAir(int x, int z) public int findAir(int x, int z)
{ {
@ -130,9 +135,12 @@ public class World implements BlockAccess, WorldGenConstants
// If the chunk is not in memory, it does not need to be unloaded // If the chunk is not in memory, it does not need to be unloaded
if (chunk == null) return false; if (chunk == null) return false;
// Otherwise save the chunk // Otherwise save the chunk
boolean result = this.save.saveChunk(chunk); AtomicBoolean result = new AtomicBoolean(false);
CompletableFuture.runAsync(() -> {
result.set(this.save.saveChunk(chunk));
this.chunks.remove(posHash); this.chunks.remove(posHash);
return result; });
return result.get();
} }
void populateChunk(Chunk chunk) void populateChunk(Chunk chunk)
@ -195,7 +203,43 @@ public class World implements BlockAccess, WorldGenConstants
public void updateLoadedChunks(int chunkX, int chunkY, int chunkZ) public void updateLoadedChunks(int chunkX, int chunkY, int chunkZ)
{ {
Ginger.getInstance().threading.registerChunkThreadToWaitlist(new DynamicChunkLoader(chunkX, chunkY, chunkZ, this)); //AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
//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))
toRemove.add((long) pos);
});
// unload unneccesary chunks from chunk array
toRemove.forEach((LongConsumer) this::unloadChunk);
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)
chunksList.put(this.posHash(chunk.chunkX, chunk.chunkY, chunk.chunkZ), chunk);
});
this.chunks = chunksList;
} }
private static final class GenerationWorld implements BlockAccess, WorldGenConstants private static final class GenerationWorld implements BlockAccess, WorldGenConstants

View File

@ -10,7 +10,7 @@ public class GingerThreading extends Thread
public List<GingerThread> worldChunkThreadWaitlist; public List<GingerThread> worldChunkThreadWaitlist;
public GingerThreading() public GingerThreading()
{ worldChunkThreadWaitlist = new ArrayList<GingerThread>(); } { worldChunkThreadWaitlist = new ArrayList<>(); }
public void registerChunkThreadToWaitlist(GingerThread thread) public void registerChunkThreadToWaitlist(GingerThread thread)
{ worldChunkThreadWaitlist.add(thread); } { worldChunkThreadWaitlist.add(thread); }