Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions voxels-client/src/main/java/client/app/GameClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import client.ui.View;
import client.world.ChunkManager;
import client.world.ClientWorld;
import client.world.ClientWorldOrigin;
import common.network.NetworkPackets;
import engine.application.BasicApplication;
import engine.scene.camera.Camera;
Expand Down Expand Up @@ -77,6 +78,10 @@ public ClientWorld getWorld() {
return world;
}

public ClientWorldOrigin getWorldOrigin() {
return world.getOrigin();
}

public ClientPlayer getPlayer() {
return player;
}
Expand Down
25 changes: 25 additions & 0 deletions voxels-client/src/main/java/client/world/ChunkManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
*/
public class ChunkManager extends AbstractComponent implements RenderableComponent {

private static final int DEFAULT_ORIGIN_SHIFT_THRESHOLD_CHUNKS = 4;

private int renderDistance;
private int bufferDistance;

Expand All @@ -52,13 +54,16 @@ public class ChunkManager extends AbstractComponent implements RenderableCompone
private ChunkRenderer chunkRenderer;

private ClientWorld world;
private final ClientWorldOrigin origin;
private int originShiftThresholdChunks = DEFAULT_ORIGIN_SHIFT_THRESHOLD_CHUNKS;

// Füge eine Map für den Lösch-Timer hinzu
private final Map<Long, Long> deletionQueue = new ConcurrentHashMap<>();
private static final long DELETION_DELAY_MS = 2000; // 2 Sekunden Puffer

public ChunkManager(GameClient client) {
this.world = client.getWorld();
this.origin = world.getOrigin();
this.chunkRenderer = new BasicChunkRenderer(client);
setRenderDistance(GameSettings.renderDistance);
}
Expand All @@ -72,6 +77,11 @@ public void onUpdate(float tpf) {
playerChunkX = WorldMath.worldToChunkX(playerPosition);
playerChunkZ = WorldMath.worldToChunkZ(playerPosition);

if (origin.isOutsideShiftThreshold(
playerChunkX, playerChunkZ, originShiftThresholdChunks)) {
origin.setOriginChunk(playerChunkX, playerChunkZ);
}

if (playerChunkX != lastPlayerChunkX || playerChunkZ != lastPlayerChunkZ) {

lastPlayerChunkX = playerChunkX;
Expand Down Expand Up @@ -399,6 +409,21 @@ public void updatePlayerPosition(float x, float y, float z) {
playerPosition.set(x, y, z);
}

public ClientWorldOrigin getOrigin() {
return origin;
}

public int getOriginShiftThresholdChunks() {
return originShiftThresholdChunks;
}

public void setOriginShiftThresholdChunks(int originShiftThresholdChunks) {
if (originShiftThresholdChunks < 0) {
throw new IllegalArgumentException("Origin shift threshold must be >= 0.");
}
this.originShiftThresholdChunks = originShiftThresholdChunks;
}

@Override
public void onAttach() {}

Expand Down
5 changes: 5 additions & 0 deletions voxels-client/src/main/java/client/world/ClientWorld.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class ClientWorld extends World {
public static final int TICKS_PER_SECOND = 20;

private float fractionalTickCounter = 0;
private final ClientWorldOrigin origin = new ClientWorldOrigin();

private ChunkManager chunkManager;
// Warteschlange für Datenpakete vom Server
Expand Down Expand Up @@ -55,6 +56,10 @@ public void setChunkManager(ChunkManager chunkManager) {
this.chunkManager = chunkManager;
}

public ClientWorldOrigin getOrigin() {
return origin;
}

public void update(float tpf) {
// Wir addieren den Fortschritt auf einen float-Counter
fractionalTickCounter += tpf * TICKS_PER_SECOND;
Expand Down
66 changes: 66 additions & 0 deletions voxels-client/src/main/java/client/world/ClientWorldOrigin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package client.world;

import common.world.ChunkData;

/**
* Maintains the client-side floating-origin anchor.
*
* <p>The server and world simulation continue to use absolute world/chunk coordinates. The client
* can rebase rendering-related systems around the current origin chunk to keep local coordinates
* numerically stable.
*/
public class ClientWorldOrigin {

private int originChunkX;
private int originChunkZ;

public int getOriginChunkX() {
return originChunkX;
}

public int getOriginChunkZ() {
return originChunkZ;
}

public void setOriginChunk(int chunkX, int chunkZ) {
this.originChunkX = chunkX;
this.originChunkZ = chunkZ;
}

public float getOriginWorldX() {
return originChunkX * (float) ChunkData.WIDTH;
}

public float getOriginWorldZ() {
return originChunkZ * (float) ChunkData.DEPTH;
}

public float toLocalX(float absoluteX) {
return absoluteX - getOriginWorldX();
}

public float toLocalY(float absoluteY) {
return absoluteY;
}

public float toLocalZ(float absoluteZ) {
return absoluteZ - getOriginWorldZ();
}

public float toAbsoluteX(float localX) {
return getOriginWorldX() + localX;
}

public float toAbsoluteY(float localY) {
return localY;
}

public float toAbsoluteZ(float localZ) {
return getOriginWorldZ() + localZ;
}

public boolean isOutsideShiftThreshold(int chunkX, int chunkZ, int thresholdInChunks) {
return Math.abs(chunkX - originChunkX) > thresholdInChunks
|| Math.abs(chunkZ - originChunkZ) > thresholdInChunks;
}
}
Loading