start dynamic chunkloading. crashes.
parent
d1cc1443eb
commit
56d8c65e0e
|
@ -182,4 +182,9 @@ public class Litecraft extends Game
|
|||
ginger3D.setGingerPlayer(this.world.player);
|
||||
}
|
||||
}
|
||||
|
||||
public World getWorld()
|
||||
{
|
||||
return this.world;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package com.github.halotroop.litecraft.world;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.*;
|
||||
import java.util.function.LongConsumer;
|
||||
|
||||
import org.joml.Vector3f;
|
||||
|
@ -26,9 +26,9 @@ public class World implements BlockAccess, WorldGenConstants
|
|||
private final long seed;
|
||||
private final int dimension;
|
||||
public Player player;
|
||||
private final int renderSize;
|
||||
|
||||
// This will likely become the main public constructor after we add dynamic chunkloading
|
||||
private World(long seed, Dimension<?> dim, LitecraftSave save)
|
||||
public World(long seed, int renderSize, Dimension<?> dim, LitecraftSave save)
|
||||
{
|
||||
this.chunks = new Long2ObjectArrayMap<>();
|
||||
this.seed = seed;
|
||||
|
@ -37,36 +37,7 @@ public class World implements BlockAccess, WorldGenConstants
|
|||
this.genBlockAccess = new GenerationWorld(this);
|
||||
this.save = save;
|
||||
this.dimension = dim.id;
|
||||
}
|
||||
|
||||
public void spawnPlayer()
|
||||
{
|
||||
int y = this.findAir(0, 0);
|
||||
if (y == -1)
|
||||
y = 300; // yeet
|
||||
|
||||
this.spawnPlayer(0, y, -3);
|
||||
}
|
||||
|
||||
public Player spawnPlayer(float x, float y, float z)
|
||||
{
|
||||
TexturedModel dirtModel = ModelLoader.loadGenericCube("block/cubes/soil/dirt.png");
|
||||
this.player = new Player(dirtModel, new Vector3f(x, y, z), 0, 180f, 0, new Vector3f(0.2f, 0.2f, 0.2f));
|
||||
this.player.isVisible = false;
|
||||
return this.player;
|
||||
}
|
||||
|
||||
// this constructor will likely not be neccesary when we have dynamic chunkloading
|
||||
public World(long seed, int size, Dimension<?> dim, LitecraftSave save)
|
||||
{
|
||||
this(seed, dim, save);
|
||||
long time = System.currentTimeMillis();
|
||||
System.out.println("Generating world!");
|
||||
for (int i = (0 - (size / 2)); i < (size / 2); i++)
|
||||
for (int k = (0 - (size / 2)); k < (size / 2); k++)
|
||||
for (int y = -2; y < 2; ++y)
|
||||
this.loadChunk(i, y, k).setRender(true);
|
||||
System.out.println("Generated world in " + (System.currentTimeMillis() - time) + " milliseconds");
|
||||
this.renderSize = renderSize;
|
||||
}
|
||||
|
||||
public int findAir(int x, int z)
|
||||
|
@ -84,6 +55,30 @@ public class World implements BlockAccess, WorldGenConstants
|
|||
return -1; // if it fails, returns -1
|
||||
}
|
||||
|
||||
public void spawnPlayer()
|
||||
{
|
||||
int y = this.findAir(0, 0);
|
||||
if (y == -1)
|
||||
y = 300; // yeet
|
||||
|
||||
this.spawnPlayer(0, y, -3);
|
||||
}
|
||||
|
||||
public Player spawnPlayer(float x, float y, float z)
|
||||
{
|
||||
// Player model and stuff
|
||||
TexturedModel dirtModel = ModelLoader.loadGenericCube("block/cubes/soil/dirt.png");
|
||||
this.player = new Player(dirtModel, new Vector3f(x, y, z), 0, 180f, 0, new Vector3f(0.2f, 0.2f, 0.2f));
|
||||
this.player.isVisible = false;
|
||||
// Generate world around player
|
||||
long time = System.currentTimeMillis();
|
||||
System.out.println("Generating world!");
|
||||
this.updateLoadedChunks(this.player.getChunkX(), this.player.getChunkY(), this.player.getChunkZ());
|
||||
System.out.println("Generated world in " + (System.currentTimeMillis() - time) + " milliseconds");
|
||||
// return player
|
||||
return this.player;
|
||||
}
|
||||
|
||||
public Chunk getChunk(int chunkX, int chunkY, int chunkZ)
|
||||
{
|
||||
Chunk chunk = this.chunks.computeIfAbsent(posHash(chunkX, chunkY, chunkZ), pos ->
|
||||
|
@ -97,19 +92,21 @@ public class World implements BlockAccess, WorldGenConstants
|
|||
return chunk;
|
||||
}
|
||||
|
||||
public Chunk loadChunk(int chunkX, int chunkY, int chunkZ)
|
||||
public Chunk getChunkToLoad(int chunkX, int chunkY, int chunkZ)
|
||||
{
|
||||
return this.chunks.computeIfAbsent(posHash(chunkX, chunkY, chunkZ), pos ->
|
||||
{
|
||||
Chunk readChunk = save.readChunk(chunkX, chunkY, chunkZ, this.dimension);
|
||||
return readChunk == null ? this.chunkGenerator.generateChunk(chunkX, chunkY, chunkZ) : readChunk;
|
||||
});
|
||||
// try get an already loaded chunk
|
||||
Chunk result = this.chunks.get(posHash(chunkX, chunkY, chunkZ));
|
||||
if (result != null)
|
||||
return result;
|
||||
// try read a chunk from memory
|
||||
result = save.readChunk(chunkX, chunkY, chunkZ, this.dimension);
|
||||
// if neither of those work, generate the chunk
|
||||
return result == null ? this.chunkGenerator.generateChunk(chunkX, chunkY, chunkZ) : result;
|
||||
}
|
||||
|
||||
/** @return whether the chunk was unloaded without errors. Will often, but not always, be equal to whether the chunk was already in memory. */
|
||||
public boolean unloadChunk(int chunkX, int chunkY, int chunkZ)
|
||||
private boolean unloadChunk(long posHash)
|
||||
{
|
||||
long posHash = posHash(chunkX, chunkY, chunkZ);
|
||||
Chunk chunk = this.chunks.get(posHash);
|
||||
// If the chunk is not in memory, it does not need to be unloaded
|
||||
if (chunk == null) return false;
|
||||
|
@ -119,6 +116,11 @@ public class World implements BlockAccess, WorldGenConstants
|
|||
return result;
|
||||
}
|
||||
|
||||
private void populateChunk(Chunk chunk)
|
||||
{
|
||||
this.populateChunk(chunk.chunkX, chunk.chunkY, chunk.chunkZ, chunk.chunkStartX, chunk.chunkStartY, chunk.chunkStartZ);
|
||||
}
|
||||
|
||||
private void populateChunk(int chunkX, int chunkY, int chunkZ, int chunkStartX, int chunkStartY, int chunkStartZ)
|
||||
{
|
||||
Random rand = new Random(this.seed + 5828671L * chunkX + -47245139L * chunkY + 8972357 * (long) chunkZ);
|
||||
|
@ -176,6 +178,38 @@ public class World implements BlockAccess, WorldGenConstants
|
|||
|
||||
public static final int SEA_LEVEL = 0;
|
||||
|
||||
public void updateLoadedChunks(int newChunkX, int newChunkY, int newChunkZ)
|
||||
{
|
||||
List<Chunk> toKeep = new ArrayList<>();
|
||||
// loop over rendered area, adding chunks that are needed
|
||||
for (int x = -renderSize / 2; x < renderSize / 2; x++)
|
||||
for (int z = -renderSize / 2; z < renderSize / 2; z++)
|
||||
for (int y = -2; y < 2; ++y)
|
||||
toKeep.add(this.getChunkToLoad(x, y, z));
|
||||
// list of keys to remove
|
||||
LongList toRemove = new LongArrayList();
|
||||
// check which loaded chunks are not neccesary
|
||||
this.chunks.forEach((pos, chunk) ->
|
||||
{
|
||||
if (!toKeep.contains(chunk))
|
||||
toRemove.add((long) pos);
|
||||
});
|
||||
// unload unneccesary chunks from chunk array
|
||||
toRemove.forEach((LongConsumer) pos -> this.unloadChunk(pos));
|
||||
// populate chunks to render if they are not rendered, then render them
|
||||
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)
|
||||
this.chunks.put(posHash(chunk.chunkX, chunk.chunkY, chunk.chunkZ), chunk);
|
||||
});
|
||||
}
|
||||
|
||||
private static final class GenerationWorld implements BlockAccess, WorldGenConstants
|
||||
{
|
||||
GenerationWorld(World parent)
|
||||
|
|
|
@ -2,20 +2,29 @@ package com.github.hydos.ginger.engine.elements.objects;
|
|||
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import com.github.halotroop.litecraft.Litecraft;
|
||||
import com.github.halotroop.litecraft.util.RelativeDirection;
|
||||
import com.github.halotroop.litecraft.world.World;
|
||||
import com.github.halotroop.litecraft.world.gen.WorldGenConstants;
|
||||
import com.github.hydos.ginger.engine.api.GingerRegister;
|
||||
import com.github.hydos.ginger.engine.io.Window;
|
||||
import com.github.hydos.ginger.engine.render.models.TexturedModel;
|
||||
import com.github.hydos.ginger.main.settings.Constants;
|
||||
|
||||
public class Player extends RenderObject
|
||||
public class Player extends RenderObject implements WorldGenConstants
|
||||
{
|
||||
private boolean isInAir = false;
|
||||
private double upwardsSpeed;
|
||||
private boolean noWeight = true; // because the force of gravity on an object's mass is called WEIGHT, not gravity
|
||||
private int chunkX, chunkY, chunkZ;
|
||||
|
||||
public Player(TexturedModel model, Vector3f position, float rotX, float rotY, float rotZ, Vector3f scale)
|
||||
{ super(model, position, rotX, rotY, rotZ, scale); }
|
||||
{
|
||||
super(model, position, rotX, rotY, rotZ, scale);
|
||||
this.chunkX = (int) position.x >> POS_SHIFT;
|
||||
this.chunkY = (int) position.y >> POS_SHIFT;
|
||||
this.chunkZ = (int) position.z >> POS_SHIFT;
|
||||
}
|
||||
|
||||
public void move(RelativeDirection direction)
|
||||
{
|
||||
|
@ -32,12 +41,12 @@ public class Player extends RenderObject
|
|||
position.x -= Math.sin(ry) * Constants.movementSpeed;
|
||||
break;
|
||||
case LEFT:
|
||||
ry -= NINETY_DEGREES;
|
||||
ry -= RIGHT_ANGLE;
|
||||
position.z -= Math.cos(ry) * Constants.movementSpeed;
|
||||
position.x += Math.sin(ry) * Constants.movementSpeed;
|
||||
break;
|
||||
case RIGHT:
|
||||
ry += NINETY_DEGREES;
|
||||
ry += RIGHT_ANGLE;
|
||||
position.z -= Math.cos(ry) * Constants.movementSpeed;
|
||||
position.x += Math.sin(ry) * Constants.movementSpeed;
|
||||
break;
|
||||
|
@ -51,7 +60,7 @@ public class Player extends RenderObject
|
|||
}
|
||||
}
|
||||
|
||||
private static final float NINETY_DEGREES = (float) (Math.PI / 2f);
|
||||
private static final float RIGHT_ANGLE = (float) (Math.PI / 2f);
|
||||
|
||||
private void jump()
|
||||
{
|
||||
|
@ -62,11 +71,32 @@ public class Player extends RenderObject
|
|||
}
|
||||
}
|
||||
|
||||
public int getChunkX()
|
||||
{ return this.chunkX; }
|
||||
|
||||
public int getChunkY()
|
||||
{ return this.chunkY; }
|
||||
|
||||
public int getChunkZ()
|
||||
{ return this.chunkZ; }
|
||||
|
||||
public void updateMovement()
|
||||
{
|
||||
super.increasePosition(0, (float) (upwardsSpeed * (Window.getTime())), 0);
|
||||
upwardsSpeed += Constants.gravity.y() * Window.getTime();
|
||||
isInAir = false;
|
||||
upwardsSpeed = 0;
|
||||
|
||||
int newChunkX = (int) position.x >> POS_SHIFT;
|
||||
int newChunkY = (int) position.y >> POS_SHIFT;
|
||||
int newChunkZ = (int) position.z >> POS_SHIFT;
|
||||
|
||||
if (newChunkX != this.chunkX || newChunkY != this.chunkY || newChunkZ != this.chunkZ)
|
||||
{
|
||||
Litecraft.getInstance().getWorld().updateLoadedChunks(newChunkX, newChunkY, newChunkZ);
|
||||
this.chunkX = newChunkX;
|
||||
this.chunkY = newChunkY;
|
||||
this.chunkZ = newChunkZ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue