diff --git a/core/src/main/java/de/bluecolored/bluemap/core/map/hires/HiresModelRenderer.java b/core/src/main/java/de/bluecolored/bluemap/core/map/hires/HiresModelRenderer.java
index e082df07..a25a76e9 100644
--- a/core/src/main/java/de/bluecolored/bluemap/core/map/hires/HiresModelRenderer.java
+++ b/core/src/main/java/de/bluecolored/bluemap/core/map/hires/HiresModelRenderer.java
@@ -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()
+ );
});
}
diff --git a/core/src/main/java/de/bluecolored/bluemap/core/map/hires/entity/EntityModelRenderer.java b/core/src/main/java/de/bluecolored/bluemap/core/map/hires/entity/EntityModelRenderer.java
index 73efa4e1..344a9100 100644
--- a/core/src/main/java/de/bluecolored/bluemap/core/map/hires/entity/EntityModelRenderer.java
+++ b/core/src/main/java/de/bluecolored/bluemap/core/map/hires/entity/EntityModelRenderer.java
@@ -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);
}
}
diff --git a/core/src/main/java/de/bluecolored/bluemap/core/map/hires/entity/EntityRenderer.java b/core/src/main/java/de/bluecolored/bluemap/core/map/hires/entity/EntityRenderer.java
index 931defd1..c42f9c22 100644
--- a/core/src/main/java/de/bluecolored/bluemap/core/map/hires/entity/EntityRenderer.java
+++ b/core/src/main/java/de/bluecolored/bluemap/core/map/hires/entity/EntityRenderer.java
@@ -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.
*
* Implementation Note:
- * This method is guaranteed to be called only on one thread per BlockRenderer instance, so you can use this
+ * This method is guaranteed to be called only on one thread per EntityRenderer instance, so you can use this
* for optimizations.
* 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.
diff --git a/core/src/main/java/de/bluecolored/bluemap/core/world/mca/MCAUtil.java b/core/src/main/java/de/bluecolored/bluemap/core/world/mca/MCAUtil.java
index 4a680ea0..42c00bfa 100644
--- a/core/src/main/java/de/bluecolored/bluemap/core/world/mca/MCAUtil.java
+++ b/core/src/main/java/de/bluecolored/bluemap/core/world/mca/MCAUtil.java
@@ -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());
diff --git a/core/src/main/java/de/bluecolored/bluemap/core/world/mca/MCAWorld.java b/core/src/main/java/de/bluecolored/bluemap/core/world/mca/MCAWorld.java
index 29fc9919..d423adc8 100644
--- a/core/src/main/java/de/bluecolored/bluemap/core/world/mca/MCAWorld.java
+++ b/core/src/main/java/de/bluecolored/bluemap/core/world/mca/MCAWorld.java
@@ -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 blockChunkGrid;
+ private final ChunkGrid 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 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 {
diff --git a/core/src/main/java/de/bluecolored/bluemap/core/world/mca/data/Vector2fDeserializer.java b/core/src/main/java/de/bluecolored/bluemap/core/world/mca/data/Vector2fDeserializer.java
index 36375bef..235493a8 100644
--- a/core/src/main/java/de/bluecolored/bluemap/core/world/mca/data/Vector2fDeserializer.java
+++ b/core/src/main/java/de/bluecolored/bluemap/core/world/mca/data/Vector2fDeserializer.java
@@ -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();
}
}
diff --git a/core/src/main/java/de/bluecolored/bluemap/core/world/mca/data/Vector2iDeserializer.java b/core/src/main/java/de/bluecolored/bluemap/core/world/mca/data/Vector2iDeserializer.java
new file mode 100644
index 00000000..7cb0b113
--- /dev/null
+++ b/core/src/main/java/de/bluecolored/bluemap/core/world/mca/data/Vector2iDeserializer.java
@@ -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 {
+
+ @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);
+
+ };
+ }
+
+}
diff --git a/core/src/main/java/de/bluecolored/bluemap/core/world/mca/entity/chunk/MCAEntityChunk.java b/core/src/main/java/de/bluecolored/bluemap/core/world/mca/entity/chunk/MCAEntityChunk.java
new file mode 100644
index 00000000..b299a815
--- /dev/null
+++ b/core/src/main/java/de/bluecolored/bluemap/core/world/mca/entity/chunk/MCAEntityChunk.java
@@ -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;
+
+}
diff --git a/core/src/main/java/de/bluecolored/bluemap/core/world/mca/entity/chunk/MCAEntityChunkLoader.java b/core/src/main/java/de/bluecolored/bluemap/core/world/mca/entity/chunk/MCAEntityChunkLoader.java
new file mode 100644
index 00000000..8377cd2c
--- /dev/null
+++ b/core/src/main/java/de/bluecolored/bluemap/core/world/mca/entity/chunk/MCAEntityChunkLoader.java
@@ -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 {
+
+ @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;
+ }
+
+}
diff --git a/implementations/fabric/build.gradle.kts b/implementations/fabric/build.gradle.kts
index d7e833d1..f3a6d6ed 100644
--- a/implementations/fabric/build.gradle.kts
+++ b/implementations/fabric/build.gradle.kts
@@ -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")
diff --git a/implementations/forge/build.gradle.kts b/implementations/forge/build.gradle.kts
index 2aa25706..cfe7bb2d 100644
--- a/implementations/forge/build.gradle.kts
+++ b/implementations/forge/build.gradle.kts
@@ -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")
diff --git a/implementations/neoforge/build.gradle.kts b/implementations/neoforge/build.gradle.kts
index 8960713b..3cba674e 100644
--- a/implementations/neoforge/build.gradle.kts
+++ b/implementations/neoforge/build.gradle.kts
@@ -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")
diff --git a/implementations/paper/build.gradle.kts b/implementations/paper/build.gradle.kts
index 433ee8fc..4f6b03c7 100644
--- a/implementations/paper/build.gradle.kts
+++ b/implementations/paper/build.gradle.kts
@@ -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")
diff --git a/implementations/spigot/build.gradle.kts b/implementations/spigot/build.gradle.kts
index 028bb127..828f1d4b 100644
--- a/implementations/spigot/build.gradle.kts
+++ b/implementations/spigot/build.gradle.kts
@@ -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")
diff --git a/implementations/sponge/build.gradle.kts b/implementations/sponge/build.gradle.kts
index 641364bd..dc54cdc4 100644
--- a/implementations/sponge/build.gradle.kts
+++ b/implementations/sponge/build.gradle.kts
@@ -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")