mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-09-27 06:42:42 +02:00
Add mechanism for retrieving BlockEntity data
This commit adds a mechanism for retrieving block entity data. Block entity data is required to support for example text on signs, banner patterns, or mods such as Domum Ornamentum.
This commit is contained in:
parent
10fb88df4b
commit
b10d15657a
@ -56,6 +56,7 @@
|
|||||||
import de.bluecolored.bluemap.core.world.Chunk;
|
import de.bluecolored.bluemap.core.world.Chunk;
|
||||||
import de.bluecolored.bluemap.core.world.World;
|
import de.bluecolored.bluemap.core.world.World;
|
||||||
import de.bluecolored.bluemap.core.world.block.Block;
|
import de.bluecolored.bluemap.core.world.block.Block;
|
||||||
|
import de.bluecolored.bluemap.core.world.block.entity.BlockEntity;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@ -528,6 +529,11 @@ private Text formatBlock(Block<?> block) {
|
|||||||
lines.put("block-light", block.getBlockLightLevel());
|
lines.put("block-light", block.getBlockLightLevel());
|
||||||
lines.put("sun-light", block.getSunLightLevel());
|
lines.put("sun-light", block.getSunLightLevel());
|
||||||
|
|
||||||
|
BlockEntity blockEntity = block.getBlockEntity();
|
||||||
|
if (blockEntity != null) {
|
||||||
|
lines.put("block-entity", blockEntity);
|
||||||
|
}
|
||||||
|
|
||||||
Object[] textElements = lines.entrySet().stream()
|
Object[] textElements = lines.entrySet().stream()
|
||||||
.flatMap(e -> Stream.of(TextColor.GRAY, e.getKey(), ": ", TextColor.WHITE, e.getValue(), "\n"))
|
.flatMap(e -> Stream.of(TextColor.GRAY, e.getKey(), ": ", TextColor.WHITE, e.getValue(), "\n"))
|
||||||
.toArray(Object[]::new);
|
.toArray(Object[]::new);
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.world;
|
package de.bluecolored.bluemap.core.world;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.core.world.block.entity.BlockEntity;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public interface Chunk {
|
public interface Chunk {
|
||||||
|
|
||||||
Chunk EMPTY_CHUNK = new Chunk() {};
|
Chunk EMPTY_CHUNK = new Chunk() {};
|
||||||
@ -72,4 +75,5 @@ default boolean hasOceanFloorHeights() {
|
|||||||
|
|
||||||
default int getOceanFloorY(int x, int z) { return 0; }
|
default int getOceanFloorY(int x, int z) { return 0; }
|
||||||
|
|
||||||
|
default @Nullable BlockEntity getBlockEntity(int x, int y, int z) { return null; };
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
import de.bluecolored.bluemap.core.world.Chunk;
|
import de.bluecolored.bluemap.core.world.Chunk;
|
||||||
import de.bluecolored.bluemap.core.world.LightData;
|
import de.bluecolored.bluemap.core.world.LightData;
|
||||||
import de.bluecolored.bluemap.core.world.World;
|
import de.bluecolored.bluemap.core.world.World;
|
||||||
|
import de.bluecolored.bluemap.core.world.block.entity.BlockEntity;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class Block<T extends Block<T>> {
|
public class Block<T extends Block<T>> {
|
||||||
|
|
||||||
@ -147,6 +149,10 @@ public int getBlockLightLevel() {
|
|||||||
return getLightData().getBlockLight();
|
return getLightData().getBlockLight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @Nullable BlockEntity getBlockEntity() {
|
||||||
|
return getChunk().getBlockEntity(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (world != null) {
|
if (world != null) {
|
||||||
@ -174,5 +180,4 @@ public String toString() {
|
|||||||
protected T self() {
|
protected T self() {
|
||||||
return (T) this;
|
return (T) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
package de.bluecolored.bluemap.core.world.block.entity;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class BannerBlockEntity extends BlockEntity {
|
||||||
|
private final List<Pattern> patterns = new ArrayList<>();
|
||||||
|
|
||||||
|
private BannerBlockEntity(Map<String, Object> data) {
|
||||||
|
super(data);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Map<String, Object>> patterns = (List<Map<String, Object>>) data.getOrDefault("Patterns", List.of());
|
||||||
|
|
||||||
|
for (Map<String, Object> compound : patterns) {
|
||||||
|
this.patterns.add(new Pattern(compound));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Pattern> getPatterns() {
|
||||||
|
return patterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "BannerBlockEntity{" +
|
||||||
|
"patterns=" + patterns +
|
||||||
|
"} " + super.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Pattern {
|
||||||
|
private final String code;
|
||||||
|
private final Color color;
|
||||||
|
|
||||||
|
private Pattern(Map<String, Object> data) {
|
||||||
|
this.code = (String) data.get("Pattern");
|
||||||
|
this.color = Color.values()[(int) data.get("Color")];
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getColor() {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Pattern{" +
|
||||||
|
"code='" + code + '\'' +
|
||||||
|
", color=" + color +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Color {
|
||||||
|
WHITE, ORANGE, MAGENTA, LIGHT_BLUE, YELLOW, LIME, PINK, GRAY, LIGHT_GRAY, CYAN, PURPLE, BLUE, BROWN, GREEN,
|
||||||
|
RED, BLACK
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,111 @@
|
|||||||
|
package de.bluecolored.bluemap.core.world.block.entity;
|
||||||
|
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
|
import de.bluecolored.bluenbt.BlueNBT;
|
||||||
|
import de.bluecolored.bluenbt.NBTDeserializer;
|
||||||
|
import de.bluecolored.bluenbt.NBTReader;
|
||||||
|
import de.bluecolored.bluenbt.TypeDeserializer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.StringJoiner;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@NBTDeserializer(BlockEntity.BlockEntityDeserializer.class)
|
||||||
|
public class BlockEntity {
|
||||||
|
private static final BlueNBT BLUENBT = new BlueNBT();
|
||||||
|
private static final Map<String, Class<? extends BlockEntity>> ID_MAPPING = Map.of(
|
||||||
|
"minecraft:sign", SignBlockEntity.class,
|
||||||
|
"minecraft:skull", SkullBlockEntity.class,
|
||||||
|
"minecraft:banner", BannerBlockEntity.class
|
||||||
|
);
|
||||||
|
|
||||||
|
protected final String id;
|
||||||
|
protected final int x, y, z;
|
||||||
|
protected final boolean keepPacked;
|
||||||
|
|
||||||
|
protected BlockEntity(Map<String, Object> data) {
|
||||||
|
this.id = (String) data.get("id");
|
||||||
|
this.x = (int) data.get("x");
|
||||||
|
this.y = (int) data.get("y");
|
||||||
|
this.z = (int) data.get("z");
|
||||||
|
this.keepPacked = (byte) data.getOrDefault("keepPacked", (byte) 0) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isKeepPacked() {
|
||||||
|
return keepPacked;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
BlockEntity that = (BlockEntity) o;
|
||||||
|
return x == that.x && y == that.y && z == that.z && keepPacked == that.keepPacked && Objects.equals(id, that.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id, x, y, z, keepPacked);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "BlockEntity{" +
|
||||||
|
"id='" + id + '\'' +
|
||||||
|
", x=" + x +
|
||||||
|
", y=" + y +
|
||||||
|
", z=" + z +
|
||||||
|
", keepPacked=" + keepPacked +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BlockEntityDeserializer implements TypeDeserializer<BlockEntity> {
|
||||||
|
@Override
|
||||||
|
public BlockEntity read(NBTReader reader) throws IOException {
|
||||||
|
@SuppressWarnings("unchecked") Map<String, Object> data =
|
||||||
|
(Map<String, Object>) BLUENBT.read(reader, TypeToken.getParameterized(Map.class, String.class, Object.class));
|
||||||
|
|
||||||
|
String id = (String) data.get("id");
|
||||||
|
if (id == null || id.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<? extends BlockEntity> dataClass = ID_MAPPING.getOrDefault(id, BlockEntity.class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Constructor<? extends BlockEntity> constructor = dataClass.getDeclaredConstructor(Map.class);
|
||||||
|
if (constructor.trySetAccessible()) {
|
||||||
|
return constructor.newInstance(data);
|
||||||
|
}
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
Logger.global.logError(
|
||||||
|
String.format("No constructor in %s that takes a Map!", dataClass.getCanonicalName()), e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Logger.global.logError("Failed to instantiate BlockEntity instance!", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
package de.bluecolored.bluemap.core.world.block.entity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class SignBlockEntity extends BlockEntity {
|
||||||
|
private final TextData frontText;
|
||||||
|
private final TextData backText;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private SignBlockEntity(Map<String, Object> data) {
|
||||||
|
super(data);
|
||||||
|
|
||||||
|
// Versions before 1.20 used a different format
|
||||||
|
if (data.containsKey("front_text")) {
|
||||||
|
this.frontText = new TextData((Map<String, Object>) data.getOrDefault("front_text", Map.of()));
|
||||||
|
this.backText = new TextData((Map<String, Object>) data.getOrDefault("back_text", Map.of()));
|
||||||
|
} else {
|
||||||
|
this.frontText = new TextData(
|
||||||
|
(byte) data.getOrDefault("GlowingText", (byte) 0) == 1,
|
||||||
|
(String) data.getOrDefault("Color", ""),
|
||||||
|
List.of(
|
||||||
|
(String) data.getOrDefault("Text1", ""),
|
||||||
|
(String) data.getOrDefault("Text2", ""),
|
||||||
|
(String) data.getOrDefault("Text3", ""),
|
||||||
|
(String) data.getOrDefault("Text4", "")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.backText = new TextData(false, "", List.of());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextData getFrontText() {
|
||||||
|
return frontText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextData getBackText() {
|
||||||
|
return backText;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SignBlockEntity{" +
|
||||||
|
"frontText=" + frontText +
|
||||||
|
", backText=" + backText +
|
||||||
|
"} " + super.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TextData {
|
||||||
|
private final boolean hasGlowingText;
|
||||||
|
private final String color;
|
||||||
|
private final List<String> messages;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private TextData(Map<String, Object> data) {
|
||||||
|
this.hasGlowingText = (byte) data.getOrDefault("has_glowing_text", (byte) 0) == 1;
|
||||||
|
this.color = (String) data.getOrDefault("color", "");
|
||||||
|
this.messages = (List<String>) data.getOrDefault("messages", List.of());
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextData(boolean hasGlowingText, String color, List<String> messages) {
|
||||||
|
this.hasGlowingText = hasGlowingText;
|
||||||
|
this.color = color;
|
||||||
|
this.messages = messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHasGlowingText() {
|
||||||
|
return hasGlowingText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColor() {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getMessages() {
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TextData{" +
|
||||||
|
"hasGlowingText=" + hasGlowingText +
|
||||||
|
", color='" + color + '\'' +
|
||||||
|
", messages=" + messages +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
package de.bluecolored.bluemap.core.world.block.entity;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class SkullBlockEntity extends BlockEntity {
|
||||||
|
private final @Nullable String noteBlockSound;
|
||||||
|
private final @Nullable String extraType;
|
||||||
|
private final @Nullable SkullOwner skullOwner;
|
||||||
|
|
||||||
|
private SkullBlockEntity(Map<String, Object> data) {
|
||||||
|
super(data);
|
||||||
|
|
||||||
|
this.noteBlockSound = (String) data.get("note_block_sound");
|
||||||
|
this.extraType = (String) data.get("ExtraType");
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> ownerData = (Map<String, Object>) data.get("SkullOwner");
|
||||||
|
this.skullOwner = ownerData != null ? new SkullOwner(ownerData) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable String getNoteBlockSound() {
|
||||||
|
return noteBlockSound;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable String getExtraType() {
|
||||||
|
return extraType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkullOwner getSkullOwner() {
|
||||||
|
return skullOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SkullBlockEntity{" +
|
||||||
|
"noteBlockSound='" + noteBlockSound + '\'' +
|
||||||
|
", extraType='" + extraType + '\'' +
|
||||||
|
", skullOwner=" + skullOwner +
|
||||||
|
"} " + super.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SkullOwner {
|
||||||
|
private final @Nullable UUID id;
|
||||||
|
private final @Nullable String name;
|
||||||
|
private final List<Texture> textures = new ArrayList<>();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private SkullOwner(Map<String, Object> data) {
|
||||||
|
int[] uuidInts = (int[]) data.get("Id");
|
||||||
|
this.id = new UUID((long) uuidInts[0] << 32 | uuidInts[1], (long) uuidInts[2] << 32 | uuidInts[3]);
|
||||||
|
this.name = (String) data.get("Name");
|
||||||
|
|
||||||
|
Map<String, Object> properties = (Map<String, Object>) data.getOrDefault("Properties", Map.of());
|
||||||
|
List<Map<String, Object>> textures = (List<Map<String, Object>>) properties.getOrDefault("textures", List.of());
|
||||||
|
|
||||||
|
for (Map<String, Object> compound : textures) {
|
||||||
|
this.textures.add(new Texture(compound));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Texture> getTextures() {
|
||||||
|
return textures;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SkullOwner{" +
|
||||||
|
"id=" + id +
|
||||||
|
", name='" + name + '\'' +
|
||||||
|
", textures=" + textures +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Texture {
|
||||||
|
private final @Nullable String signature;
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private Texture(Map<String, Object> data) {
|
||||||
|
this.signature = (String) data.get("signature");
|
||||||
|
this.value = (String) data.getOrDefault("value", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSignature() {
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Texture{" +
|
||||||
|
"signature='" + signature + '\'' +
|
||||||
|
", value='" + value + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -27,6 +27,7 @@
|
|||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import de.bluecolored.bluemap.core.util.Key;
|
import de.bluecolored.bluemap.core.util.Key;
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
|
import de.bluecolored.bluemap.core.world.block.entity.BlockEntity;
|
||||||
import de.bluecolored.bluemap.core.world.mca.data.BlockStateDeserializer;
|
import de.bluecolored.bluemap.core.world.mca.data.BlockStateDeserializer;
|
||||||
import de.bluecolored.bluemap.core.world.mca.data.KeyDeserializer;
|
import de.bluecolored.bluemap.core.world.mca.data.KeyDeserializer;
|
||||||
import de.bluecolored.bluenbt.BlueNBT;
|
import de.bluecolored.bluenbt.BlueNBT;
|
||||||
@ -37,6 +38,7 @@ public class MCAUtil {
|
|||||||
static {
|
static {
|
||||||
BLUENBT.register(TypeToken.get(BlockState.class), new BlockStateDeserializer());
|
BLUENBT.register(TypeToken.get(BlockState.class), new BlockStateDeserializer());
|
||||||
BLUENBT.register(TypeToken.get(Key.class), new KeyDeserializer());
|
BLUENBT.register(TypeToken.get(Key.class), new KeyDeserializer());
|
||||||
|
BLUENBT.register(TypeToken.get(BlockEntity.class), new BlockEntity.BlockEntityDeserializer());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,12 +30,17 @@
|
|||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
import de.bluecolored.bluemap.core.world.DimensionType;
|
import de.bluecolored.bluemap.core.world.DimensionType;
|
||||||
import de.bluecolored.bluemap.core.world.LightData;
|
import de.bluecolored.bluemap.core.world.LightData;
|
||||||
|
import de.bluecolored.bluemap.core.world.block.entity.BlockEntity;
|
||||||
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
|
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
|
||||||
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
|
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
|
||||||
import de.bluecolored.bluenbt.NBTName;
|
import de.bluecolored.bluenbt.NBTName;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class Chunk_1_13 extends MCAChunk {
|
public class Chunk_1_13 extends MCAChunk {
|
||||||
|
|
||||||
private static final Key STATUS_EMPTY = new Key("minecraft", "empty");
|
private static final Key STATUS_EMPTY = new Key("minecraft", "empty");
|
||||||
@ -58,6 +63,7 @@ public class Chunk_1_13 extends MCAChunk {
|
|||||||
private final int sectionMin, sectionMax;
|
private final int sectionMin, sectionMax;
|
||||||
|
|
||||||
final int[] biomes;
|
final int[] biomes;
|
||||||
|
private final Map<Long, BlockEntity> blockEntities;
|
||||||
|
|
||||||
public Chunk_1_13(MCAWorld world, Data data) {
|
public Chunk_1_13(MCAWorld world, Data data) {
|
||||||
super(world, data);
|
super(world, data);
|
||||||
@ -113,6 +119,10 @@ public Chunk_1_13(MCAWorld world, Data data) {
|
|||||||
this.sectionMin = 0;
|
this.sectionMin = 0;
|
||||||
this.sectionMax = 0;
|
this.sectionMax = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.blockEntities = level.blockEntities.stream().collect(Collectors.toMap(
|
||||||
|
it -> (long) it.getY() << 40 | (it.getX() & 0xF) << 4 | it.getZ() & 0xF, it -> it
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -195,6 +205,11 @@ public int getOceanFloorY(int x, int z) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable BlockEntity getBlockEntity(int x, int y, int z) {
|
||||||
|
return blockEntities.get((long) y << 40 | (x & 0xF) << 4 | z & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
private @Nullable Section getSection(int y) {
|
private @Nullable Section getSection(int y) {
|
||||||
y -= sectionMin;
|
y -= sectionMin;
|
||||||
if (y < 0 || y >= this.sections.length) return null;
|
if (y < 0 || y >= this.sections.length) return null;
|
||||||
@ -273,6 +288,7 @@ public static class Level {
|
|||||||
private HeightmapsData heightmaps = new HeightmapsData();
|
private HeightmapsData heightmaps = new HeightmapsData();
|
||||||
private SectionData @Nullable [] sections = null;
|
private SectionData @Nullable [] sections = null;
|
||||||
private int[] biomes = EMPTY_INT_ARRAY;
|
private int[] biomes = EMPTY_INT_ARRAY;
|
||||||
|
@NBTName("TileEntities") private List<BlockEntity> blockEntities = List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
import de.bluecolored.bluemap.core.world.DimensionType;
|
import de.bluecolored.bluemap.core.world.DimensionType;
|
||||||
import de.bluecolored.bluemap.core.world.LightData;
|
import de.bluecolored.bluemap.core.world.LightData;
|
||||||
|
import de.bluecolored.bluemap.core.world.block.entity.BlockEntity;
|
||||||
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
|
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
|
||||||
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
|
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
|
||||||
import de.bluecolored.bluemap.core.world.mca.PackedIntArrayAccess;
|
import de.bluecolored.bluemap.core.world.mca.PackedIntArrayAccess;
|
||||||
@ -37,6 +38,10 @@
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class Chunk_1_16 extends MCAChunk {
|
public class Chunk_1_16 extends MCAChunk {
|
||||||
|
|
||||||
private static final Key STATUS_EMPTY = new Key("minecraft", "empty");
|
private static final Key STATUS_EMPTY = new Key("minecraft", "empty");
|
||||||
@ -57,6 +62,7 @@ public class Chunk_1_16 extends MCAChunk {
|
|||||||
private final int sectionMin, sectionMax;
|
private final int sectionMin, sectionMax;
|
||||||
|
|
||||||
private final int[] biomes;
|
private final int[] biomes;
|
||||||
|
private final Map<Long, BlockEntity> blockEntities;
|
||||||
|
|
||||||
public Chunk_1_16(MCAWorld world, Data data) {
|
public Chunk_1_16(MCAWorld world, Data data) {
|
||||||
super(world, data);
|
super(world, data);
|
||||||
@ -112,6 +118,10 @@ public Chunk_1_16(MCAWorld world, Data data) {
|
|||||||
this.sectionMin = 0;
|
this.sectionMin = 0;
|
||||||
this.sectionMax = 0;
|
this.sectionMax = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.blockEntities = level.blockEntities.stream().collect(Collectors.toMap(
|
||||||
|
it -> (long) it.getY() << 40 | (it.getX() & 0xF) << 4 | it.getZ() & 0xF, it -> it
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -191,6 +201,11 @@ public int getOceanFloorY(int x, int z) {
|
|||||||
return oceanFloorHeights.get((z & 0xF) << 4 | x & 0xF);
|
return oceanFloorHeights.get((z & 0xF) << 4 | x & 0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable BlockEntity getBlockEntity(int x, int y, int z) {
|
||||||
|
return blockEntities.get((long) y << 40 | (x & 0xF) << 4 | z & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
private @Nullable Section getSection(int y) {
|
private @Nullable Section getSection(int y) {
|
||||||
y -= sectionMin;
|
y -= sectionMin;
|
||||||
if (y < 0 || y >= this.sections.length) return null;
|
if (y < 0 || y >= this.sections.length) return null;
|
||||||
@ -261,6 +276,7 @@ public static class Level {
|
|||||||
private HeightmapsData heightmaps = new HeightmapsData();
|
private HeightmapsData heightmaps = new HeightmapsData();
|
||||||
private SectionData @Nullable [] sections = null;
|
private SectionData @Nullable [] sections = null;
|
||||||
private int[] biomes = EMPTY_INT_ARRAY;
|
private int[] biomes = EMPTY_INT_ARRAY;
|
||||||
|
@NBTName("TileEntities") private List<BlockEntity> blockEntities = List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
import de.bluecolored.bluemap.core.world.DimensionType;
|
import de.bluecolored.bluemap.core.world.DimensionType;
|
||||||
import de.bluecolored.bluemap.core.world.LightData;
|
import de.bluecolored.bluemap.core.world.LightData;
|
||||||
|
import de.bluecolored.bluemap.core.world.block.entity.BlockEntity;
|
||||||
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
|
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
|
||||||
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
|
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
|
||||||
import de.bluecolored.bluemap.core.world.mca.PackedIntArrayAccess;
|
import de.bluecolored.bluemap.core.world.mca.PackedIntArrayAccess;
|
||||||
@ -37,6 +38,10 @@
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class Chunk_1_18 extends MCAChunk {
|
public class Chunk_1_18 extends MCAChunk {
|
||||||
|
|
||||||
private static final Key STATUS_EMPTY = new Key("minecraft", "empty");
|
private static final Key STATUS_EMPTY = new Key("minecraft", "empty");
|
||||||
@ -57,6 +62,8 @@ public class Chunk_1_18 extends MCAChunk {
|
|||||||
private final Section[] sections;
|
private final Section[] sections;
|
||||||
private final int sectionMin, sectionMax;
|
private final int sectionMin, sectionMax;
|
||||||
|
|
||||||
|
private final Map<Long, BlockEntity> blockEntities;
|
||||||
|
|
||||||
public Chunk_1_18(MCAWorld world, Data data) {
|
public Chunk_1_18(MCAWorld world, Data data) {
|
||||||
super(world, data);
|
super(world, data);
|
||||||
|
|
||||||
@ -108,6 +115,10 @@ public Chunk_1_18(MCAWorld world, Data data) {
|
|||||||
this.sectionMin = 0;
|
this.sectionMin = 0;
|
||||||
this.sectionMax = 0;
|
this.sectionMax = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.blockEntities = data.blockEntities.stream().collect(Collectors.toMap(
|
||||||
|
it -> (long) it.getY() << 40 | (it.getX() & 0xF) << 4 | it.getZ() & 0xF, it -> it
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -182,6 +193,11 @@ public int getOceanFloorY(int x, int z) {
|
|||||||
return oceanFloorHeights.get((z & 0xF) << 4 | x & 0xF) + worldMinY;
|
return oceanFloorHeights.get((z & 0xF) << 4 | x & 0xF) + worldMinY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable BlockEntity getBlockEntity(int x, int y, int z) {
|
||||||
|
return blockEntities.get((long) y << 40 | (x & 0xF) << 4 | z & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
private @Nullable Section getSection(int y) {
|
private @Nullable Section getSection(int y) {
|
||||||
y -= sectionMin;
|
y -= sectionMin;
|
||||||
if (y < 0 || y >= this.sections.length) return null;
|
if (y < 0 || y >= this.sections.length) return null;
|
||||||
@ -263,6 +279,7 @@ public static class Data extends MCAChunk.Data {
|
|||||||
private long inhabitedTime = 0;
|
private long inhabitedTime = 0;
|
||||||
private HeightmapsData heightmaps = new HeightmapsData();
|
private HeightmapsData heightmaps = new HeightmapsData();
|
||||||
private SectionData @Nullable [] sections = null;
|
private SectionData @Nullable [] sections = null;
|
||||||
|
@NBTName("block_entities") private List<BlockEntity> blockEntities = List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
|
Loading…
Reference in New Issue
Block a user