mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2025-01-25 01:31:22 +01:00
Add mechanism for retrieving BlockEntity data (#524)
* 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. * Fix the coordinate-packing for block entity-loading This commit fixes the incorrect shifting of bits when packing the chunk-local coordinates of a block entity into a 64-bit long for lookups. * Change mapping type of BlockEntity lookups This commit changes the type stored for BlockEntity mappings from a class of the type associated with the ID to a method reference to its constructor. * Tidy BlockEntity mappings This commit introduces a small functional interface to make the type less ungodly. Also silences the warning about referencing subclasses in the superclass, it is fine in this case, we're just storing a reference to the constructor. * Add missing license headers The license headers were missing. Oops.
This commit is contained in:
parent
2689cd10e0
commit
a847e247e5
@ -56,6 +56,7 @@
|
||||
import de.bluecolored.bluemap.core.world.Chunk;
|
||||
import de.bluecolored.bluemap.core.world.World;
|
||||
import de.bluecolored.bluemap.core.world.block.Block;
|
||||
import de.bluecolored.bluemap.core.world.block.entity.BlockEntity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
@ -528,6 +529,11 @@ private Text formatBlock(Block<?> block) {
|
||||
lines.put("block-light", block.getBlockLightLevel());
|
||||
lines.put("sun-light", block.getSunLightLevel());
|
||||
|
||||
BlockEntity blockEntity = block.getBlockEntity();
|
||||
if (blockEntity != null) {
|
||||
lines.put("block-entity", blockEntity);
|
||||
}
|
||||
|
||||
Object[] textElements = lines.entrySet().stream()
|
||||
.flatMap(e -> Stream.of(TextColor.GRAY, e.getKey(), ": ", TextColor.WHITE, e.getValue(), "\n"))
|
||||
.toArray(Object[]::new);
|
||||
|
@ -24,6 +24,9 @@
|
||||
*/
|
||||
package de.bluecolored.bluemap.core.world;
|
||||
|
||||
import de.bluecolored.bluemap.core.world.block.entity.BlockEntity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface Chunk {
|
||||
|
||||
Chunk EMPTY_CHUNK = new Chunk() {};
|
||||
@ -72,4 +75,5 @@ default boolean hasOceanFloorHeights() {
|
||||
|
||||
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.LightData;
|
||||
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>> {
|
||||
|
||||
@ -147,6 +149,10 @@ public int getBlockLightLevel() {
|
||||
return getLightData().getBlockLight();
|
||||
}
|
||||
|
||||
public @Nullable BlockEntity getBlockEntity() {
|
||||
return getChunk().getBlockEntity(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (world != null) {
|
||||
@ -174,5 +180,4 @@ public String toString() {
|
||||
protected T self() {
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
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<>();
|
||||
|
||||
protected 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,137 @@
|
||||
/*
|
||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
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.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@NBTDeserializer(BlockEntity.BlockEntityDeserializer.class)
|
||||
public class BlockEntity {
|
||||
private static final BlueNBT BLUENBT = new BlueNBT();
|
||||
|
||||
@FunctionalInterface
|
||||
private interface BlockEntityInitializer {
|
||||
BlockEntity create(Map<String, Object> data);
|
||||
}
|
||||
|
||||
@SuppressWarnings("StaticInitializerReferencesSubClass")
|
||||
private static final Map<String, BlockEntityInitializer> ID_MAPPING = Map.of(
|
||||
"minecraft:sign", SignBlockEntity::new,
|
||||
"minecraft:skull", SkullBlockEntity::new,
|
||||
"minecraft:banner", BannerBlockEntity::new
|
||||
);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BlockEntityInitializer instance = ID_MAPPING.getOrDefault(id, BlockEntity::new);
|
||||
|
||||
try {
|
||||
return instance.create(data);
|
||||
} catch (Exception e) {
|
||||
Logger.global.logError("Failed to instantiate BlockEntity instance!", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
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")
|
||||
protected 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,137 @@
|
||||
/*
|
||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
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;
|
||||
|
||||
protected 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 de.bluecolored.bluemap.core.util.Key;
|
||||
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.KeyDeserializer;
|
||||
import de.bluecolored.bluenbt.BlueNBT;
|
||||
@ -37,6 +38,7 @@ public class MCAUtil {
|
||||
static {
|
||||
BLUENBT.register(TypeToken.get(BlockState.class), new BlockStateDeserializer());
|
||||
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.DimensionType;
|
||||
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.MCAWorld;
|
||||
import de.bluecolored.bluenbt.NBTName;
|
||||
import lombok.Getter;
|
||||
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 {
|
||||
|
||||
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;
|
||||
|
||||
final int[] biomes;
|
||||
private final Map<Long, BlockEntity> blockEntities;
|
||||
|
||||
public Chunk_1_13(MCAWorld world, Data data) {
|
||||
super(world, data);
|
||||
@ -113,6 +119,10 @@ public Chunk_1_13(MCAWorld world, Data data) {
|
||||
this.sectionMin = 0;
|
||||
this.sectionMax = 0;
|
||||
}
|
||||
|
||||
this.blockEntities = level.blockEntities.stream().collect(Collectors.toMap(
|
||||
it -> (long) it.getY() << 8 | (it.getX() & 0xF) << 4 | it.getZ() & 0xF, it -> it
|
||||
));
|
||||
}
|
||||
|
||||
@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 << 8 | (x & 0xF) << 4 | z & 0xF);
|
||||
}
|
||||
|
||||
private @Nullable Section getSection(int y) {
|
||||
y -= sectionMin;
|
||||
if (y < 0 || y >= this.sections.length) return null;
|
||||
@ -273,6 +288,7 @@ public static class Level {
|
||||
private HeightmapsData heightmaps = new HeightmapsData();
|
||||
private SectionData @Nullable [] sections = null;
|
||||
private int[] biomes = EMPTY_INT_ARRAY;
|
||||
@NBTName("TileEntities") private List<BlockEntity> blockEntities = List.of();
|
||||
}
|
||||
|
||||
@Getter
|
||||
|
@ -30,6 +30,7 @@
|
||||
import de.bluecolored.bluemap.core.world.BlockState;
|
||||
import de.bluecolored.bluemap.core.world.DimensionType;
|
||||
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.MCAWorld;
|
||||
import de.bluecolored.bluemap.core.world.mca.PackedIntArrayAccess;
|
||||
@ -37,6 +38,10 @@
|
||||
import lombok.Getter;
|
||||
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 {
|
||||
|
||||
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[] biomes;
|
||||
private final Map<Long, BlockEntity> blockEntities;
|
||||
|
||||
public Chunk_1_16(MCAWorld world, Data data) {
|
||||
super(world, data);
|
||||
@ -112,6 +118,10 @@ public Chunk_1_16(MCAWorld world, Data data) {
|
||||
this.sectionMin = 0;
|
||||
this.sectionMax = 0;
|
||||
}
|
||||
|
||||
this.blockEntities = level.blockEntities.stream().collect(Collectors.toMap(
|
||||
it -> (long) it.getY() << 8 | (it.getX() & 0xF) << 4 | it.getZ() & 0xF, it -> it
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -191,6 +201,11 @@ public int getOceanFloorY(int x, int z) {
|
||||
return oceanFloorHeights.get((z & 0xF) << 4 | x & 0xF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BlockEntity getBlockEntity(int x, int y, int z) {
|
||||
return blockEntities.get((long) y << 8 | (x & 0xF) << 4 | z & 0xF);
|
||||
}
|
||||
|
||||
private @Nullable Section getSection(int y) {
|
||||
y -= sectionMin;
|
||||
if (y < 0 || y >= this.sections.length) return null;
|
||||
@ -261,6 +276,7 @@ public static class Level {
|
||||
private HeightmapsData heightmaps = new HeightmapsData();
|
||||
private SectionData @Nullable [] sections = null;
|
||||
private int[] biomes = EMPTY_INT_ARRAY;
|
||||
@NBTName("TileEntities") private List<BlockEntity> blockEntities = List.of();
|
||||
}
|
||||
|
||||
@Getter
|
||||
|
@ -30,6 +30,7 @@
|
||||
import de.bluecolored.bluemap.core.world.BlockState;
|
||||
import de.bluecolored.bluemap.core.world.DimensionType;
|
||||
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.MCAWorld;
|
||||
import de.bluecolored.bluemap.core.world.mca.PackedIntArrayAccess;
|
||||
@ -37,6 +38,10 @@
|
||||
import lombok.Getter;
|
||||
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 {
|
||||
|
||||
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 int sectionMin, sectionMax;
|
||||
|
||||
private final Map<Long, BlockEntity> blockEntities;
|
||||
|
||||
public Chunk_1_18(MCAWorld world, Data data) {
|
||||
super(world, data);
|
||||
|
||||
@ -108,6 +115,10 @@ public Chunk_1_18(MCAWorld world, Data data) {
|
||||
this.sectionMin = 0;
|
||||
this.sectionMax = 0;
|
||||
}
|
||||
|
||||
this.blockEntities = data.blockEntities.stream().collect(Collectors.toMap(
|
||||
it -> (long) it.getY() << 8 | (it.getX() & 0xF) << 4 | it.getZ() & 0xF, it -> it
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -182,6 +193,11 @@ public int getOceanFloorY(int x, int z) {
|
||||
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 << 8 | (x & 0xF) << 4 | z & 0xF);
|
||||
}
|
||||
|
||||
private @Nullable Section getSection(int y) {
|
||||
y -= sectionMin;
|
||||
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 HeightmapsData heightmaps = new HeightmapsData();
|
||||
private SectionData @Nullable [] sections = null;
|
||||
@NBTName("block_entities") private List<BlockEntity> blockEntities = List.of();
|
||||
}
|
||||
|
||||
@Getter
|
||||
|
Loading…
Reference in New Issue
Block a user