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")