Skip to content

Commit 2e5ae96

Browse files
committed
Started work on ChunkScanning.kt
1 parent 18b6317 commit 2e5ae96

File tree

2 files changed

+78
-23
lines changed

2 files changed

+78
-23
lines changed

Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import at.petrak.hexcasting.api.misc.Result;
77
import at.petrak.hexcasting.api.mod.HexConfig;
88
import at.petrak.hexcasting.api.pigment.FrozenPigment;
9+
import at.petrak.hexcasting.api.utils.ChunkScanning;
910
import at.petrak.hexcasting.api.utils.HexUtils;
1011
import com.mojang.datafixers.util.Pair;
1112
import net.minecraft.ChatFormatting;
@@ -19,15 +20,10 @@
1920
import net.minecraft.server.level.*;
2021
import net.minecraft.world.item.ItemStack;
2122
import net.minecraft.world.item.Items;
22-
import net.minecraft.world.level.ChunkPos;
23-
import net.minecraft.world.level.block.state.BlockState;
24-
import net.minecraft.world.level.chunk.ChunkAccess;
25-
import net.minecraft.world.level.chunk.ChunkStatus;
2623
import net.minecraft.world.phys.AABB;
2724
import org.jetbrains.annotations.Nullable;
2825

2926
import java.util.*;
30-
import java.util.concurrent.ExecutionException;
3127

3228
/**
3329
* See {@link BlockEntityAbstractImpetus}, this is what's stored in it
@@ -113,30 +109,17 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir,
113109
var positiveBlock = new BlockPos.MutableBlockPos();
114110
var negativeBlock = new BlockPos.MutableBlockPos();
115111
var lastBlockPos = new BlockPos.MutableBlockPos();
112+
var scanning = new ChunkScanning(level);
116113
BlockPos firstBlock = null;
117-
HashMap<ChunkPos, ChunkAccess> chunkMap = new HashMap<>();
114+
118115
while (!todo.isEmpty()) {
119116
var pair = todo.pop();
120117
var enterDir = pair.getFirst();
121118
var herePos = pair.getSecond();
119+
var hereBs = scanning.getBlock(herePos);
122120

123-
BlockState hereBs;
124-
var chunkPos = new ChunkPos(herePos);
125-
126-
if (!chunkMap.containsKey(chunkPos)) { // Have we found/loaded this chunk yet?
127-
var z = level.getChunkSource().getChunkFuture(chunkPos.x,chunkPos.z, ChunkStatus.EMPTY,true); // For some reason, loads almost no chunks
128-
try {
129-
if (z.get().left().isPresent()){ // Has the Future computed yet?
130-
chunkMap.put(chunkPos,z.get().left().get());
131-
hereBs = z.get().left().get().getBlockState(herePos);
132-
} else { // If the future has not been somehow, run normal getBlockState
133-
hereBs = level.getLevel().getBlockState(herePos);
134-
}
135-
} catch (InterruptedException | ExecutionException e) { // If something goes *wrong*, run normal getBlockState
136-
hereBs = level.getLevel().getBlockState(herePos);
137-
}
138-
} else { // Oh good! We found this chunk already, get it from the HashMap
139-
hereBs = chunkMap.get(chunkPos).getBlockState(herePos);
121+
if (hereBs == null){
122+
continue;
140123
}
141124

142125
if (!(hereBs.getBlock() instanceof ICircleComponent cmp)) {
@@ -175,6 +158,8 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir,
175158
return new Result.Err<>(null);
176159
}
177160
}
161+
// Maybe not required, but still seems like a good idea
162+
scanning.clearCache();
178163

179164
if (firstBlock == null) {
180165
return new Result.Err<>(null);
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package at.petrak.hexcasting.api.utils
2+
3+
import at.petrak.hexcasting.api.HexAPI
4+
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap
5+
import net.minecraft.core.BlockPos
6+
import net.minecraft.server.level.ServerLevel
7+
import net.minecraft.world.level.ChunkPos
8+
import net.minecraft.world.level.block.entity.BlockEntity
9+
import net.minecraft.world.level.block.state.BlockState
10+
import net.minecraft.world.level.chunk.ChunkStatus
11+
import net.minecraft.world.level.chunk.ImposterProtoChunk
12+
13+
/**
14+
* This is a helper class to efficiently scan chunks in ways Minecraft did not intend for. This is for only reading chunks, not writing
15+
*
16+
* TODO: MAKE DOC THIS BETTER
17+
*/
18+
class ChunkScanning(var level: ServerLevel) {
19+
var chunks: Long2ObjectLinkedOpenHashMap<ImposterProtoChunk> = Long2ObjectLinkedOpenHashMap()
20+
21+
/**
22+
* This attempts to cache a chunk to the local [chunks]
23+
* @param ChunkPos the chunk to try to cache
24+
* @return If the function could cache the chunk or not
25+
*/
26+
fun cacheChunk(chunk: ChunkPos): Boolean {
27+
val chunkLong = chunk.toLong()
28+
// We have the chunk already, so we can skip it
29+
if (chunks.contains(chunkLong)){
30+
return true
31+
}
32+
val future = level.chunkSource.getChunkFuture(chunk.x,chunk.z, ChunkStatus.EMPTY,true).get()
33+
if (future.left().isPresent){
34+
chunks.put(chunkLong, future.left().get() as ImposterProtoChunk)
35+
return true
36+
}
37+
HexAPI.LOGGER.warn("Failed to get chunk at {}!",chunk)
38+
return false
39+
}
40+
41+
fun cacheChunk(chunk: Long): Boolean{
42+
return cacheChunk(ChunkPos(chunk))
43+
}
44+
45+
fun getBlock(blockPos: BlockPos): BlockState? {
46+
val chunkPos = ChunkPos(blockPos).toLong()
47+
if (!cacheChunk(chunkPos)){
48+
return null
49+
}
50+
return chunks.get(chunkPos).getBlockState(blockPos)
51+
}
52+
53+
fun getBlockEntity(blockPos: BlockPos): BlockEntity? {
54+
val chunkPos = ChunkPos(blockPos).toLong()
55+
if (!cacheChunk(chunkPos)){
56+
return null
57+
}
58+
return chunks.get(chunkPos).getBlockEntity(blockPos)
59+
}
60+
61+
// maybe not required, but still not a bad idea to have a Clear method
62+
fun clearCache(){
63+
chunks.clear()
64+
}
65+
66+
// TODO: Might not need this
67+
fun containsChunk(chunk: ChunkPos): Boolean{
68+
return chunks.contains(chunk.toLong())
69+
}
70+
}

0 commit comments

Comments
 (0)