Add entity ChunkGrid

This commit is contained in:
Lukas Rieger (Blue) 2025-01-20 15:27:34 +01:00
parent d1a36e5816
commit 19d3c321dc
No known key found for this signature in database
GPG Key ID: AA33883B1BBA03E6
15 changed files with 158 additions and 39 deletions

View File

@ -125,7 +125,12 @@ public void render(World world, Vector3i modelMin, Vector3i modelMax, TileModel
world.iterateEntities(min.getX(), min.getZ(), max.getX(), max.getZ(), entity -> {
Vector3d pos = entity.getPos();
block.set(pos.getFloorX(), pos.getFloorY(), pos.getFloorZ());
entityRenderer.render(entity, block, tileModelView);
entityRenderer.render(entity, block, tileModelView.initialize());
tileModelView.translate(
(float) pos.getX() - modelAnchor.getX(),
(float) pos.getY() - modelAnchor.getY(),
(float) pos.getZ() - modelAnchor.getZ()
);
});
}

View File

@ -23,12 +23,13 @@ public EntityModelRenderer(ResourcePack resourcePack, TextureGallery textureGall
}
public void render(Entity entity, BlockNeighborhood block, TileModelView tileModel) {
int modelStart = tileModel.getStart();
EntityState stateResource = resourcePack.getEntityState(entity.getId());
if (stateResource == null) return;
Part[] parts = stateResource.getParts();
if (parts.length == 0) return;
int modelStart = tileModel.getStart();
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < parts.length; i++) {
@ -38,6 +39,9 @@ public void render(Entity entity, BlockNeighborhood block, TileModelView tileMod
}
tileModel.initialize(modelStart);
// apply entity rotation
tileModel.rotate(entity.getRotation().getY(), entity.getRotation().getX(), 0f);
}
}

View File

@ -35,11 +35,10 @@
public interface EntityRenderer {
/**
* Renders the given entities part into the given model, and sets the given blockColor to the
* color that represents the rendered block.
* Renders the given entities part into the given model.
* <p>
* <b>Implementation Note:</b><br>
* This method is guaranteed to be called only on <b>one thread per BlockRenderer instance</b>, so you can use this
* This method is guaranteed to be called only on <b>one thread per EntityRenderer instance</b>, so you can use this
* for optimizations.<br>
* Keep in mind this method will be called once for every block that is being rendered, so be very careful
* about performance and instance-creations.

View File

@ -24,6 +24,8 @@
*/
package de.bluecolored.bluemap.core.world.mca;
import com.flowpowered.math.vector.Vector2f;
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3d;
import de.bluecolored.bluemap.core.util.Key;
import de.bluecolored.bluemap.core.world.BlockState;
@ -51,6 +53,8 @@ public static BlueNBT addCommonNbtSettings(BlueNBT nbt) {
nbt.register(TypeToken.of(Key.class), new KeyDeserializer());
nbt.register(TypeToken.of(UUID.class), new UUIDDeserializer());
nbt.register(TypeToken.of(Vector3d.class), new Vector3dDeserializer());
nbt.register(TypeToken.of(Vector2i.class), new Vector2iDeserializer());
nbt.register(TypeToken.of(Vector2f.class), new Vector2fDeserializer());
nbt.register(TypeToken.of(BlockEntity.class), new BlockEntityTypeResolver());
nbt.register(TypeToken.of(SignBlockEntity.class), new SignBlockEntityTypeResolver());

View File

@ -26,21 +26,18 @@
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3i;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import de.bluecolored.bluemap.core.BlueMap;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.resources.pack.datapack.DataPack;
import de.bluecolored.bluemap.core.storage.compression.Compression;
import de.bluecolored.bluemap.core.util.Grid;
import de.bluecolored.bluemap.core.util.Key;
import de.bluecolored.bluemap.core.util.Vector2iCache;
import de.bluecolored.bluemap.core.util.WatchService;
import de.bluecolored.bluemap.core.world.*;
import de.bluecolored.bluemap.core.world.mca.chunk.MCAChunkLoader;
import de.bluecolored.bluemap.core.world.mca.data.DimensionTypeDeserializer;
import de.bluecolored.bluemap.core.world.mca.data.LevelData;
import de.bluecolored.bluemap.core.world.mca.region.RegionType;
import de.bluecolored.bluemap.core.world.mca.entity.chunk.MCAEntityChunk;
import de.bluecolored.bluemap.core.world.mca.entity.chunk.MCAEntityChunkLoader;
import de.bluecolored.bluenbt.BlueNBT;
import de.bluecolored.bluenbt.TypeToken;
import lombok.Getter;
@ -51,13 +48,8 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
@Getter
@ToString
@ -74,6 +66,7 @@ public class MCAWorld implements World {
private final Path dimensionFolder;
private final ChunkGrid<Chunk> blockChunkGrid;
private final ChunkGrid<MCAEntityChunk> entityChunkGrid;
private MCAWorld(Path worldFolder, Key dimension, DataPack dataPack, LevelData levelData) {
this.id = World.id(worldFolder, dimension);
@ -103,6 +96,7 @@ private MCAWorld(Path worldFolder, Key dimension, DataPack dataPack, LevelData l
this.dimensionFolder = resolveDimensionFolder(worldFolder, dimension);
this.blockChunkGrid = new ChunkGrid<>(new MCAChunkLoader(this), dimensionFolder.resolve("region"));
this.entityChunkGrid = new ChunkGrid<>(new MCAEntityChunkLoader(), dimensionFolder.resolve("entities"));
}
@ -163,7 +157,18 @@ public void invalidateChunkCache(int x, int z) {
@Override
public void iterateEntities(int minX, int minZ, int maxX, int maxZ, Consumer<Entity> entityConsumer) {
//TODO
int minChunkX = minX >> 4, minChunkZ = minZ >> 4;
int maxChunkX = maxX >> 4, maxChunkZ = maxZ >> 4;
for (int x = minChunkX; x <= maxChunkX; x++) {
for (int z = minChunkZ; z <= maxChunkZ; z++) {
Entity[] entities = entityChunkGrid.getChunk(x, z).getEntities();
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < entities.length; i++) {
entityConsumer.accept(entities[i]);
}
}
}
}
public static MCAWorld load(Path worldFolder, Key dimension, DataPack dataPack) throws IOException, InterruptedException {

View File

@ -28,8 +28,8 @@ yield new Vector2f(
case LIST -> {
reader.beginList();
Vector2f value = new Vector2f(
reader.nextDouble(),
reader.nextDouble()
reader.nextFloat(),
reader.nextFloat()
);
reader.endList();
yield value;
@ -40,8 +40,8 @@ yield new Vector2f(
reader.beginCompound();
while (reader.peek() != TagType.END) {
switch (reader.name()) {
case "x", "yaw": x = reader.nextDouble(); break;
case "y", "pitch": y = reader.nextDouble(); break;
case "x", "yaw": x = reader.nextFloat(); break;
case "y", "z", "pitch": y = reader.nextFloat(); break;
default: reader.skip();
}
}

View File

@ -0,0 +1,56 @@
package de.bluecolored.bluemap.core.world.mca.data;
import com.flowpowered.math.vector.Vector2i;
import de.bluecolored.bluenbt.NBTReader;
import de.bluecolored.bluenbt.TagType;
import de.bluecolored.bluenbt.TypeDeserializer;
import java.io.IOException;
public class Vector2iDeserializer implements TypeDeserializer<Vector2i> {
@Override
public Vector2i read(NBTReader reader) throws IOException {
TagType tag = reader.peek();
return switch (tag) {
case INT_ARRAY, LONG_ARRAY, BYTE_ARRAY -> {
long[] values = reader.nextArrayAsLongArray();
if (values.length != 2) throw new IllegalStateException("Unexpected array length: " + values.length);
yield new Vector2i(
values[0],
values[1]
);
}
case LIST -> {
reader.beginList();
Vector2i value = new Vector2i(
reader.nextDouble(),
reader.nextDouble()
);
reader.endList();
yield value;
}
case COMPOUND -> {
double x = 0, y = 0;
reader.beginCompound();
while (reader.peek() != TagType.END) {
switch (reader.name()) {
case "x": x = reader.nextDouble(); break;
case "y", "z": y = reader.nextDouble(); break;
default: reader.skip();
}
}
reader.endCompound();
yield new Vector2i(x, y);
}
case null, default -> throw new IllegalStateException("Unexpected tag-type: " + tag);
};
}
}

View File

@ -0,0 +1,25 @@
package de.bluecolored.bluemap.core.world.mca.entity.chunk;
import com.flowpowered.math.vector.Vector2i;
import de.bluecolored.bluemap.core.world.Entity;
import de.bluecolored.bluenbt.NBTName;
import lombok.Getter;
@Getter
public class MCAEntityChunk {
private static final Entity[] EMPTY_ENTITIES = new Entity[0];
public static final MCAEntityChunk EMPTY_CHUNK = new MCAEntityChunk();
public static final MCAEntityChunk ERRORED_CHUNK = new MCAEntityChunk();
@NBTName("Entities")
public Entity[] entities = EMPTY_ENTITIES;
@NBTName("DataVersion")
public int dataVersion = -1;
@NBTName("Position")
public Vector2i position = Vector2i.ZERO;
}

View File

@ -0,0 +1,33 @@
package de.bluecolored.bluemap.core.world.mca.entity.chunk;
import de.bluecolored.bluemap.core.storage.compression.Compression;
import de.bluecolored.bluemap.core.world.mca.ChunkLoader;
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
public class MCAEntityChunkLoader implements ChunkLoader<MCAEntityChunk> {
@Override
public MCAEntityChunk load(byte[] data, int offset, int length, Compression compression) throws IOException {
try (
InputStream in = new ByteArrayInputStream(data, offset, length);
InputStream decompressedIn = compression.decompress(in)
) {
return MCAUtil.BLUENBT.read(decompressedIn, MCAEntityChunk.class);
}
}
@Override
public MCAEntityChunk emptyChunk() {
return MCAEntityChunk.EMPTY_CHUNK;
}
@Override
public MCAEntityChunk erroredChunk() {
return MCAEntityChunk.ERRORED_CHUNK;
}
}

View File

@ -34,6 +34,7 @@ dependencies {
// jarInJar
include ( libs.flow.math )
include ( libs.bluenbt )
}
@ -43,14 +44,12 @@ tasks.shadowJar {
// exclude jarInJar
dependencies {
exclude( dependency ( libs.flow.math.get() ) )
exclude( dependency ( libs.bluenbt.get() ) )
}
// airlift
relocate ("io.airlift", "de.bluecolored.shadow.airlift")
// bluenbt
relocate ("de.bluecolored.bluenbt", "de.bluecolored.shadow.bluenbt")
// caffeine
relocate ("com.github.benmanes.caffeine", "de.bluecolored.shadow.caffeine")
relocate ("org.checkerframework", "de.bluecolored.shadow.checkerframework")

View File

@ -26,6 +26,7 @@ dependencies {
minecraft ( "net.minecraftforge", "forge", "$minecraftVersion-$forgeVersion" )
jarJar ( libs.flow.math.get().group, libs.flow.math.get().name , "[${libs.flow.math.get().version},)" )
jarJar ( libs.bluenbt.get().group, libs.bluenbt.get().name , "[${libs.bluenbt.get().version},)" )
}
@ -40,14 +41,12 @@ tasks.shadowJar {
// exclude jarInJar
dependencies {
exclude( dependency ( libs.flow.math.get() ) )
exclude( dependency ( libs.bluenbt.get() ) )
}
// airlift
relocate ("io.airlift", "de.bluecolored.shadow.airlift")
// bluenbt
relocate ("de.bluecolored.bluenbt", "de.bluecolored.shadow.bluenbt")
// caffeine
relocate ("com.github.benmanes.caffeine", "de.bluecolored.shadow.caffeine")
relocate ("org.checkerframework", "de.bluecolored.shadow.checkerframework")

View File

@ -27,6 +27,7 @@ dependencies {
}
jarJar ( libs.flow.math.get().group, libs.flow.math.get().name , "[${libs.flow.math.get().version},)" )
jarJar ( libs.bluenbt.get().group, libs.bluenbt.get().name , "[${libs.bluenbt.get().version},)" )
}
tasks.shadowJar {
@ -35,14 +36,12 @@ tasks.shadowJar {
// exclude jarInJar
dependencies {
exclude( dependency ( libs.flow.math.get() ) )
exclude( dependency ( libs.bluenbt.get() ) )
}
// airlift
relocate ("io.airlift", "de.bluecolored.shadow.airlift")
// bluenbt
relocate ("de.bluecolored.bluenbt", "de.bluecolored.shadow.bluenbt")
// caffeine
relocate ("com.github.benmanes.caffeine", "de.bluecolored.shadow.caffeine")
relocate ("org.checkerframework", "de.bluecolored.shadow.checkerframework")

View File

@ -32,9 +32,6 @@ tasks.shadowJar {
// airlift
relocate ("io.airlift", "de.bluecolored.shadow.airlift")
// bluenbt
relocate ("de.bluecolored.bluenbt", "de.bluecolored.shadow.bluenbt")
// brigadier
relocate ("com.mojang.brigadier", "de.bluecolored.shadow.brigadier")

View File

@ -28,9 +28,6 @@ tasks.shadowJar {
// brigadier
relocate ("com.mojang.brigadier", "de.bluecolored.shadow.brigadier")
// bluenbt
relocate ("de.bluecolored.bluenbt", "de.bluecolored.shadow.bluenbt")
// caffeine
relocate ("com.github.benmanes.caffeine", "de.bluecolored.shadow.caffeine")
relocate ("org.checkerframework", "de.bluecolored.shadow.checkerframework")

View File

@ -48,9 +48,6 @@ tasks.shadowJar {
// brigadier
relocate ("com.mojang.brigadier", "de.bluecolored.shadow.brigadier")
// bluenbt
relocate ("de.bluecolored.bluenbt", "de.bluecolored.shadow.bluenbt")
// caffeine
relocate ("com.github.benmanes.caffeine", "de.bluecolored.shadow.caffeine")
relocate ("org.checkerframework", "de.bluecolored.shadow.checkerframework")