Skip to content

Commit a99d724

Browse files
committed
Experimenting with allowing custom DataProviders
1 parent f56e4a5 commit a99d724

16 files changed

Lines changed: 345 additions & 57 deletions

File tree

‎EntityCulling-Versionless/src/main/java/dev/tr7zw/entityculling/versionless/EntityCullingVersionlessBase.java‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import java.nio.file.Files;
77

88
import dev.tr7zw.entityculling.versionless.occlusionculling.cache.*;
9+
import dev.tr7zw.entityculling.versionless.occlusionculling.provider.*;
10+
import lombok.*;
911
import org.apache.logging.log4j.LogManager;
1012
import org.apache.logging.log4j.Logger;
1113

@@ -18,6 +20,8 @@ public abstract class EntityCullingVersionlessBase {
1820
public static final Logger LOGGER = LogManager.getLogger("EntityCulling");
1921
protected OcclusionCullingInstance culling;
2022
protected OcclusionCache cache;
23+
@Getter
24+
protected DataProvider dataProvider;
2125
public boolean debugHitboxes = false;
2226
public static boolean enabled = true;
2327
protected Thread cullThread;

‎EntityCulling-Versionless/src/main/java/dev/tr7zw/entityculling/versionless/occlusionculling/DataProvider.java‎

Lines changed: 0 additions & 31 deletions
This file was deleted.

‎EntityCulling-Versionless/src/main/java/dev/tr7zw/entityculling/versionless/occlusionculling/OcclusionCullingInstance.java‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
import java.util.Arrays;
44
import java.util.BitSet;
55

6-
import dev.tr7zw.entityculling.versionless.occlusionculling.cache.ArrayOcclusionCache;
76
import dev.tr7zw.entityculling.versionless.occlusionculling.cache.OcclusionCache;
7+
import dev.tr7zw.entityculling.versionless.occlusionculling.provider.*;
88
import dev.tr7zw.entityculling.versionless.occlusionculling.util.MathUtilities;
99
import dev.tr7zw.entityculling.versionless.occlusionculling.util.Vec3d;
1010

@@ -126,6 +126,7 @@ public boolean isAABBVisible(Vec3d aabbMin, Vec3d aabbMax, Vec3d viewerPosition)
126126
if (visibleOnFace != 0) {
127127
targetPos.set(x, y, z);
128128
if (isVoxelVisible(viewerPosition, targetPos, faceEdgeData, visibleOnFace)) {
129+
provider.postAABB();
129130
return true;
130131
}
131132
}
@@ -134,11 +135,13 @@ public boolean isAABBVisible(Vec3d aabbMin, Vec3d aabbMax, Vec3d viewerPosition)
134135
}
135136
}
136137

138+
provider.postAABB();
137139
return false;
138140
} catch (Throwable t) {
139141
// Failsafe
140142
t.printStackTrace();
141143
}
144+
provider.postAABB();
142145
return true;
143146
}
144147

@@ -382,7 +385,7 @@ && rayIntersection(lastHitBlock, start, new Vec3d(relativeX, relativeY, relative
382385

383386
boolean finished = stepRay(start, x, y, z, dimFracX, dimFracY, dimFracZ, intersectCount, x_inc, y_inc,
384387
z_inc, t_next_y, t_next_x, t_next_z);
385-
provider.cleanup();
388+
provider.postRay();
386389
if (finished) {
387390
cache.cacheResult(cameraPos, targets[0], true);
388391
return true;
@@ -415,9 +418,10 @@ private boolean stepRay(Vec3d start, int currentX, int currentY, int currentZ, d
415418
if (cVal == 0) {
416419
// save current cell
417420
int chunkX = currentX >> 4;
421+
int chunkY = currentY >> 4;
418422
int chunkZ = currentZ >> 4;
419-
if (!provider.prepareChunk(chunkX, chunkZ)) { // Chunk not ready
420-
return false;
423+
if (!provider.prepareChunk(chunkX, chunkY, chunkZ)) { // Chunk not ready
424+
return true;
421425
}
422426

423427
if (provider.isOpaqueFullCube(currentX, currentY, currentZ)) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package dev.tr7zw.entityculling.versionless.occlusionculling.provider;
2+
3+
public interface ChunkSectionProvider {
4+
5+
void ec$setProviderData(Object data);
6+
7+
<T> T ec$getProviderData(Class<T> clazz);
8+
9+
boolean ec$isDirty();
10+
11+
void ec$setDirty(boolean dirty);
12+
13+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package dev.tr7zw.entityculling.versionless.occlusionculling.provider;
2+
3+
public interface DataProvider {
4+
5+
/**
6+
* Prepares the requested chunk. Returns true if the chunk is ready, false when
7+
* not loaded. Should not reload the chunk when the x y z are the same as the
8+
* last request!
9+
*
10+
* @param chunkX
11+
* @param chunkY
12+
* @param chunkZ
13+
* @return
14+
*/
15+
boolean prepareChunk(int chunkX, int chunkY, int chunkZ);
16+
17+
/**
18+
* Location is inside the chunk.
19+
*
20+
* @param x
21+
* @param y
22+
* @param z
23+
* @return
24+
*/
25+
boolean isOpaqueFullCube(int x, int y, int z);
26+
27+
default void onChange(ChunkSectionProvider chunk, int x, int y, int z, boolean isOpaque) {
28+
};
29+
30+
default void recalcBlockCounts(ChunkSectionProvider chunk) {
31+
};
32+
33+
default void postRay() {
34+
}
35+
36+
default void postAABB() {
37+
}
38+
39+
default void postRun() {
40+
}
41+
42+
}

‎src/main/java/dev/tr7zw/entityculling/CullTask.java‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import dev.tr7zw.entityculling.versionless.occlusionculling.*;
1010
import dev.tr7zw.entityculling.versionless.occlusionculling.cache.*;
11+
import dev.tr7zw.entityculling.versionless.occlusionculling.provider.*;
1112
import dev.tr7zw.entityculling.versionless.occlusionculling.util.Vec3d;
1213

1314
import dev.tr7zw.entityculling.versionless.EntityCullingVersionlessBase;
@@ -46,10 +47,12 @@ public class CullTask implements Runnable {
4647
private List<Cullable> blockEntities = new ArrayList<>();
4748
@Setter
4849
private Vec3 cameraMC = new Vec3(0, 0, 0);
50+
private DataProvider dataProvider;
4951

50-
public CullTask(OcclusionCulling culling, OcclusionCache cache) {
52+
public CullTask(OcclusionCulling culling, OcclusionCache cache, DataProvider dataProvider) {
5153
this.culling = culling;
5254
this.cache = cache;
55+
this.dataProvider = dataProvider;
5356
}
5457

5558
@Override
@@ -74,6 +77,7 @@ public void run() {
7477
}
7578
cullBlockEntities(cameraMC, camera);
7679
cullEntities(cameraMC, camera);
80+
dataProvider.postRun();
7781
lastTime = (System.nanoTime() - start) / 1_000_000.0;
7882
}
7983
} else {

‎src/main/java/dev/tr7zw/entityculling/EntityCullingModBase.java‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import java.util.concurrent.locks.LockSupport;
55
import java.util.function.Function;
66

7+
import dev.tr7zw.entityculling.provider.*;
8+
import dev.tr7zw.entityculling.util.*;
79
import dev.tr7zw.entityculling.versionless.occlusionculling.OcclusionCullingInstance;
810

911
import dev.tr7zw.entityculling.access.*;
@@ -51,8 +53,9 @@ public void onInitialize() {
5153
instance = this;
5254
super.onInitialize();
5355
cache = new OptimisticArrayCache(config.tracingDistance);
54-
culling = new OcclusionCullingInstance(config.tracingDistance, new Provider(), cache);
55-
cullTask = new CullTask(culling, cache);
56+
dataProvider = new DirectProvider();
57+
culling = new OcclusionCullingInstance(config.tracingDistance, dataProvider, cache);
58+
cullTask = new CullTask(culling, cache, dataProvider);
5659

5760
cullThread = new Thread(cullTask, "CullThread");
5861
cullThread.setDaemon(true); // may be parked for up to a second, don't hold up the shutdown
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package dev.tr7zw.entityculling.access;
2+
3+
import dev.tr7zw.entityculling.versionless.occlusionculling.provider.*;
4+
import net.minecraft.world.level.block.state.*;
5+
import net.minecraft.world.level.chunk.*;
6+
7+
public interface ChunkSectionAccess extends ChunkSectionProvider {
8+
PalettedContainer<BlockState> entityCulling$getStates();
9+
}

‎src/main/java/dev/tr7zw/entityculling/mixin/ClientWorldMixin.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
77

88
import dev.tr7zw.entityculling.EntityCullingModBase;
9-
import dev.tr7zw.entityculling.NMSCullingHelper;
9+
import dev.tr7zw.entityculling.util.NMSCullingHelper;
1010
import dev.tr7zw.entityculling.access.Cullable;
1111
import dev.tr7zw.transition.mc.GeneralUtil;
1212
import net.minecraft.client.Minecraft;
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package dev.tr7zw.entityculling.mixin;
2+
3+
import dev.tr7zw.entityculling.*;
4+
import dev.tr7zw.entityculling.access.*;
5+
import dev.tr7zw.entityculling.util.*;
6+
import dev.tr7zw.entityculling.versionless.occlusionculling.provider.*;
7+
import net.minecraft.world.level.block.*;
8+
import net.minecraft.world.level.block.state.*;
9+
import net.minecraft.world.level.chunk.*;
10+
import org.spongepowered.asm.mixin.*;
11+
import org.spongepowered.asm.mixin.injection.*;
12+
import org.spongepowered.asm.mixin.injection.callback.*;
13+
14+
@Mixin(LevelChunkSection.class)
15+
public class LevelChunkSectionMixin implements ChunkSectionAccess {
16+
17+
@Unique
18+
private volatile Object entityCulling$providerData;
19+
20+
@Unique
21+
private volatile boolean entityCulling$Dirty = true;
22+
23+
@Override
24+
public void ec$setProviderData(Object data) {
25+
this.entityCulling$providerData = data;
26+
}
27+
28+
@Override
29+
public <T> T ec$getProviderData(Class<T> clazz) {
30+
if (clazz.isInstance(entityCulling$providerData)) {
31+
return clazz.cast(entityCulling$providerData);
32+
}
33+
return null;
34+
}
35+
36+
@Override
37+
public boolean ec$isDirty() {
38+
return entityCulling$Dirty;
39+
}
40+
41+
@Override
42+
public void ec$setDirty(boolean dirty) {
43+
this.entityCulling$Dirty = dirty;
44+
}
45+
46+
@Override
47+
public PalettedContainer<BlockState> entityCulling$getStates() {
48+
return getStates();
49+
}
50+
51+
@Shadow
52+
private PalettedContainer<BlockState> getStates() {
53+
throw new AssertionError();
54+
}
55+
56+
@Inject(method = "setBlockState(IIILnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/world/level/block/state/BlockState;", at = @At("RETURN"), require = 0)
57+
public void setBlockState(final int sectionX, final int sectionY, final int sectionZ, final BlockState state,
58+
CallbackInfoReturnable<BlockState> ci) {
59+
onSetBlockState(sectionX, sectionY, sectionZ, state);
60+
}
61+
62+
@Inject(method = "setBlockState(IIILnet/minecraft/world/level/block/state/BlockState;Z)Lnet/minecraft/world/level/block/state/BlockState;", at = @At("RETURN"), require = 0)
63+
public void setBlockStateLegacy(final int sectionX, final int sectionY, final int sectionZ, final BlockState state,
64+
final boolean checkThreading, CallbackInfoReturnable<BlockState> ci) {
65+
onSetBlockState(sectionX, sectionY, sectionZ, state);
66+
}
67+
68+
@Inject(method = "recalcBlockCounts", at = @At("HEAD"))
69+
public void recalcBlockCounts(CallbackInfo ci) {
70+
entityCulling$Dirty = true;
71+
if (EntityCullingModBase.instance != null) {
72+
EntityCullingModBase.instance.getDataProvider().recalcBlockCounts(this);
73+
}
74+
}
75+
76+
@Unique
77+
private void onSetBlockState(int sectionX, int sectionY, int sectionZ, BlockState state) {
78+
if (EntityCullingModBase.instance != null) {
79+
EntityCullingModBase.instance.getDataProvider().onChange(this, sectionX, sectionY, sectionZ,
80+
ECUtil.isOpaqueFullCube(state));
81+
}
82+
}
83+
84+
}

0 commit comments

Comments
 (0)