Skip to content

Commit

Permalink
block NBT data is now properly saved/reconstituted
Browse files Browse the repository at this point in the history
  • Loading branch information
Steanky committed Jan 24, 2024
1 parent d3448e4 commit 7aee232
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package org.phantazm.core.instance;

import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minestom.server.coordinate.Point;
import net.minestom.server.instance.*;
import net.minestom.server.instance.block.Block;
import net.minestom.server.utils.chunk.ChunkSupplier;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.world.DimensionType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.UnmodifiableView;
import org.jglrxavpok.hephaistos.nbt.*;
import org.phantazm.commons.FileUtils;
import org.phantazm.commons.FutureUtils;
import org.slf4j.Logger;
Expand Down Expand Up @@ -52,12 +56,34 @@ private InstanceDataChunkLoader(InstanceData instanceData) {
}

long chunkKey = ChunkUtils.getChunkIndex(chunkX, chunkZ);
Section[] sections = instanceData.chunkData().get(chunkKey);
if (sections == null) {
InstanceData.ChunkData chunkData = instanceData.chunkData().get(chunkKey);
if (chunkData == null) {
return FutureUtils.nullCompletedFuture();
}

return CompletableFuture.completedFuture(new DynamicChunk(instance, chunkX, chunkZ, sections));
Int2ObjectMap<InstanceData.NBTBlock> blockData = chunkData.entries();
Int2ObjectMap<Block> blocks = new Int2ObjectOpenHashMap<>(blockData.size());
for (Int2ObjectMap.Entry<InstanceData.NBTBlock> entry : blockData.int2ObjectEntrySet()) {
int key = entry.getIntKey();
InstanceData.NBTBlock nbtData = entry.getValue();

Block block = Block.fromBlockId(nbtData.id());
if (block == null) {
continue;
}

NBT nbt;
try (NBTReader nbtReader = NBTReader.fromArray(nbtData.nbt())) {
nbt = nbtReader.readNamed().component2();
} catch (IOException | NBTException e) {
continue;
}

blocks.put(key, nbt instanceof NBTCompound compound ? block.withNbt(compound) : block);
}

return CompletableFuture.completedFuture(new DynamicChunk(instance, chunkX, chunkZ, chunkData.sections(),
blocks));
}

@Override
Expand Down
48 changes: 45 additions & 3 deletions core/src/main/java/org/phantazm/core/instance/InstanceData.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,65 @@
package org.phantazm.core.instance;

import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.Section;
import net.minestom.server.instance.block.Block;
import net.minestom.server.utils.chunk.ChunkUtils;
import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.*;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collection;

public record InstanceData(@NotNull Long2ObjectMap<Section[]> chunkData) implements Serializable {
public record InstanceData(@NotNull Long2ObjectMap<ChunkData> chunkData) implements Serializable {
public record ChunkData(Section[] sections,
Int2ObjectMap<NBTBlock> entries) implements Serializable {
}

public record NBTBlock(int id,
byte[] nbt) implements Serializable {
}

@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
public static @NotNull InstanceData of(@NotNull Instance instance) {
Collection<Chunk> chunks = instance.getChunks();

Long2ObjectMap<Section[]> data = new Long2ObjectOpenHashMap<>(chunks.size());
Long2ObjectMap<ChunkData> data = new Long2ObjectOpenHashMap<>(chunks.size());
for (Chunk chunk : chunks) {
data.put(ChunkUtils.getChunkIndex(chunk), chunk.sectionCopy());
synchronized (chunk) {
long index = ChunkUtils.getChunkIndex(chunk);
Section[] sections = chunk.sectionCopy();
Int2ObjectMap<Block> entries = chunk.getEntries();

Int2ObjectMap<NBTBlock> outputMappings = new Int2ObjectOpenHashMap<>(entries.size());
for (Int2ObjectMap.Entry<Block> entry : entries.int2ObjectEntrySet()) {
int key = entry.getIntKey();
Block value = entry.getValue();
if (!value.hasNbt()) {
continue;
}

NBTCompound nbt = value.nbt();
assert nbt != null;

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (NBTWriter writer = new NBTWriter(outputStream, CompressedProcesser.NONE)) {
writer.writeNamed("", nbt);
} catch (IOException e) {
continue;
}

outputMappings.put(key, new NBTBlock(value.id(), outputStream.toByteArray()));
}

data.put(index, new ChunkData(sections, outputMappings));
}
}

return new InstanceData(data);
Expand Down

0 comments on commit 7aee232

Please sign in to comment.