Search in sources :

Example 1 with NbtDataContainerOutputStream

use of org.lanternpowered.server.data.persistence.nbt.NbtDataContainerOutputStream in project LanternServer by LanternPowered.

the class AnvilChunkIOService method write.

@Override
public void write(LanternChunk chunk) throws IOException {
    final int x = chunk.getX();
    final int z = chunk.getZ();
    final RegionFile region = this.cache.getRegionFileByChunk(x, z);
    final int regionX = x & REGION_MASK;
    final int regionZ = z & REGION_MASK;
    final DataContainer rootView = DataContainer.createNew(DataView.SafetyMode.NO_DATA_CLONED);
    final DataView levelDataView = rootView.createView(LEVEL);
    // Core properties
    levelDataView.set(VERSION, (byte) 1);
    levelDataView.set(X, chunk.getX());
    levelDataView.set(Z, chunk.getZ());
    levelDataView.set(TERRAIN_POPULATED, (byte) (chunk.isPopulated() ? 1 : 0));
    levelDataView.set(LIGHT_POPULATED, (byte) (chunk.isLightPopulated() ? 1 : 0));
    levelDataView.set(LAST_UPDATE, 0L);
    levelDataView.set(INHABITED_TIME, chunk.getLongInhabitedTime());
    // Chunk sections
    final ChunkSectionSnapshot[] sections = chunk.getSectionSnapshots(true);
    final List<DataView> sectionDataViews = new ArrayList<>();
    final List<DataView> tileEntityDataViews = new ArrayList<>();
    for (byte i = 0; i < sections.length; ++i) {
        final ChunkSectionSnapshot section = sections[i];
        if (section == null) {
            continue;
        }
        final DataContainer sectionDataView = DataContainer.createNew(DataView.SafetyMode.NO_DATA_CLONED);
        sectionDataView.set(Y, i);
        final byte[] rawTypes = new byte[section.types.length];
        final short[] types = section.types;
        NibbleArray extTypes = null;
        final NibbleArray data = new NibbleArray(rawTypes.length);
        for (int j = 0; j < rawTypes.length; j++) {
            rawTypes[j] = (byte) ((types[j] >> 4) & 0xff);
            byte extType = (byte) (types[j] >> 12);
            if (extType != 0) {
                if (extTypes == null) {
                    extTypes = new NibbleArray(rawTypes.length);
                }
                extTypes.set(j, extType);
            }
            data.set(j, (byte) (types[j] & 0xf));
        }
        sectionDataView.set(BLOCKS, rawTypes);
        if (extTypes != null) {
            sectionDataView.set(BLOCKS_EXTRA, extTypes.getPackedArray());
        }
        sectionDataView.set(DATA, data.getPackedArray());
        sectionDataView.set(BLOCK_LIGHT, section.lightFromBlock);
        final byte[] lightFromSky = section.lightFromSky;
        if (lightFromSky != null) {
            sectionDataView.set(SKY_LIGHT, lightFromSky);
        }
        sectionDataViews.add(sectionDataView);
        // noinspection unchecked
        final ObjectSerializer<LanternTileEntity> tileEntitySerializer = ObjectSerializerRegistry.get().get(LanternTileEntity.class).get();
        // Serialize the tile entities
        for (Short2ObjectMap.Entry<LanternTileEntity> tileEntityEntry : section.tileEntities.short2ObjectEntrySet()) {
            if (!tileEntityEntry.getValue().isValid()) {
                continue;
            }
            final DataView dataView = tileEntitySerializer.serialize(tileEntityEntry.getValue());
            final short pos = tileEntityEntry.getShortKey();
            dataView.set(TILE_ENTITY_X, x * 16 + (pos & 0xf));
            dataView.set(TILE_ENTITY_Y, (i << 4) | (pos >> 8));
            dataView.set(TILE_ENTITY_Z, z * 16 + ((pos >> 4) & 0xf));
            tileEntityDataViews.add(dataView);
        }
    }
    levelDataView.set(TILE_ENTITIES, tileEntityDataViews);
    levelDataView.set(SECTIONS, sectionDataViews);
    levelDataView.set(HEIGHT_MAP, chunk.getHeightMap());
    // noinspection unchecked
    final Short2ObjectMap<LanternChunk.TrackerData>[] trackerData = chunk.getTrackerData().getRawObjects();
    final List<DataView> trackerDataViews = new ArrayList<>();
    for (int i = 0; i < trackerData.length; i++) {
        final Short2ObjectMap<LanternChunk.TrackerData> trackerDataSection = trackerData[i];
        for (Short2ObjectMap.Entry<LanternChunk.TrackerData> entry : trackerDataSection.short2ObjectEntrySet()) {
            // index = y << 8 | z << 4 | x
            int index = entry.getShortKey() & 0xffff;
            // Convert the index to the column based system
            // index = z << 12 | y << 4 | x
            index = ((index >> 4) & 0xf) << 12 | i << 8 | (index >> 4) & 0xf0 | index & 0xf;
            final DataView trackerDataView = DataContainer.createNew(DataView.SafetyMode.NO_DATA_CLONED);
            trackerDataView.set(TRACKER_BLOCK_POS, (short) index);
            trackerDataView.set(TRACKER_ENTRY_NOTIFIER, entry.getValue().getNotifierId());
            trackerDataView.set(TRACKER_ENTRY_CREATOR, entry.getValue().getCreatorId());
            trackerDataViews.add(trackerDataView);
        }
    }
    if (!trackerDataViews.isEmpty()) {
        levelDataView.createView(DataQueries.SPONGE_DATA).set(TRACKER_DATA_TABLE, trackerDataViews);
    }
    final short[] biomes = chunk.getBiomes();
    final byte[] biomes0 = new byte[biomes.length];
    byte[] biomes1 = null;
    for (int i = 0; i < biomes.length; i++) {
        biomes0[i] = (byte) (biomes[i] & 0xff);
        byte value = (byte) ((biomes[i] >> 4) & 0xff);
        if (value != 0) {
            if (biomes1 == null) {
                biomes1 = new byte[biomes0.length];
            }
            biomes1[i] = value;
        }
    }
    levelDataView.set(BIOMES, biomes0);
    if (biomes1 != null) {
        levelDataView.set(BIOMES_EXTRA, biomes1);
    }
    // noinspection unchecked
    final List<LanternEntity> entities = new ArrayList(chunk.getEntities(entity -> !(entity instanceof Player)));
    final ObjectSerializer<LanternEntity> entitySerializer = ObjectSerializerRegistry.get().get(LanternEntity.class).get();
    final List<DataView> entityViews = new ArrayList<>();
    for (LanternEntity entity : entities) {
        if (entity.getRemoveState() == LanternEntity.RemoveState.DESTROYED) {
            continue;
        }
        final DataView entityView = entitySerializer.serialize(entity);
        entityViews.add(entityView);
    }
    levelDataView.set(ENTITIES, entityViews);
    try (NbtDataContainerOutputStream nbt = new NbtDataContainerOutputStream(region.getChunkDataOutputStream(regionX, regionZ))) {
        nbt.write(rootView);
        nbt.flush();
    }
}
Also used : DataInputStream(java.io.DataInputStream) REGION_SIZE(org.lanternpowered.server.data.io.anvil.RegionFileCache.REGION_SIZE) ObjectSerializerRegistry(org.lanternpowered.server.data.io.store.ObjectSerializerRegistry) LanternEntity(org.lanternpowered.server.entity.LanternEntity) LanternTileEntity(org.lanternpowered.server.block.tile.LanternTileEntity) ChunkSection(org.lanternpowered.server.world.chunk.LanternChunk.ChunkSection) Inject(com.google.inject.Inject) LanternChunk(org.lanternpowered.server.world.chunk.LanternChunk) CompletableFuture(java.util.concurrent.CompletableFuture) DataQuery(org.spongepowered.api.data.DataQuery) DataQueries(org.lanternpowered.server.data.DataQueries) ArrayList(java.util.ArrayList) Matcher(java.util.regex.Matcher) DirectoryKeys(org.lanternpowered.server.game.DirectoryKeys) LanternScheduler(org.lanternpowered.server.scheduler.LanternScheduler) ChunkIOService(org.lanternpowered.server.data.io.ChunkIOService) NoSuchElementException(java.util.NoSuchElementException) LanternChunk.fixEntityYSection(org.lanternpowered.server.world.chunk.LanternChunk.fixEntityYSection) Path(java.nio.file.Path) Nullable(javax.annotation.Nullable) Location(org.spongepowered.api.world.Location) Short2ObjectOpenHashMap(it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap) Logger(org.slf4j.Logger) ObjectSerializer(org.lanternpowered.server.data.io.store.ObjectSerializer) Files(java.nio.file.Files) NibbleArray(org.lanternpowered.server.util.collect.array.NibbleArray) DataContainer(org.spongepowered.api.data.DataContainer) InvalidDataException(org.spongepowered.api.data.persistence.InvalidDataException) IOException(java.io.IOException) REGION_AREA(org.lanternpowered.server.data.io.anvil.RegionFileCache.REGION_AREA) ChunkSectionSnapshot(org.lanternpowered.server.world.chunk.LanternChunk.ChunkSectionSnapshot) ChunkDataStream(org.spongepowered.api.world.storage.ChunkDataStream) List(java.util.List) Short2ObjectMap(it.unimi.dsi.fastutil.shorts.Short2ObjectMap) REGION_MASK(org.lanternpowered.server.data.io.anvil.RegionFileCache.REGION_MASK) NbtDataContainerInputStream(org.lanternpowered.server.data.persistence.nbt.NbtDataContainerInputStream) DataView(org.spongepowered.api.data.DataView) Vector3i(com.flowpowered.math.vector.Vector3i) World(org.spongepowered.api.world.World) WorldProperties(org.spongepowered.api.world.storage.WorldProperties) Optional(java.util.Optional) Named(com.google.inject.name.Named) Player(org.spongepowered.api.entity.living.player.Player) NbtDataContainerOutputStream(org.lanternpowered.server.data.persistence.nbt.NbtDataContainerOutputStream) Singleton(com.google.inject.Singleton) ArrayList(java.util.ArrayList) LanternChunk(org.lanternpowered.server.world.chunk.LanternChunk) DataContainer(org.spongepowered.api.data.DataContainer) NibbleArray(org.lanternpowered.server.util.collect.array.NibbleArray) NbtDataContainerOutputStream(org.lanternpowered.server.data.persistence.nbt.NbtDataContainerOutputStream) ChunkSectionSnapshot(org.lanternpowered.server.world.chunk.LanternChunk.ChunkSectionSnapshot) LanternEntity(org.lanternpowered.server.entity.LanternEntity) Player(org.spongepowered.api.entity.living.player.Player) Short2ObjectMap(it.unimi.dsi.fastutil.shorts.Short2ObjectMap) DataView(org.spongepowered.api.data.DataView) LanternTileEntity(org.lanternpowered.server.block.tile.LanternTileEntity)

Aggregations

Vector3i (com.flowpowered.math.vector.Vector3i)1 Inject (com.google.inject.Inject)1 Singleton (com.google.inject.Singleton)1 Named (com.google.inject.name.Named)1 Short2ObjectMap (it.unimi.dsi.fastutil.shorts.Short2ObjectMap)1 Short2ObjectOpenHashMap (it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap)1 DataInputStream (java.io.DataInputStream)1 IOException (java.io.IOException)1 Files (java.nio.file.Files)1 Path (java.nio.file.Path)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 NoSuchElementException (java.util.NoSuchElementException)1 Optional (java.util.Optional)1 CompletableFuture (java.util.concurrent.CompletableFuture)1 Matcher (java.util.regex.Matcher)1 Nullable (javax.annotation.Nullable)1 LanternTileEntity (org.lanternpowered.server.block.tile.LanternTileEntity)1 DataQueries (org.lanternpowered.server.data.DataQueries)1 ChunkIOService (org.lanternpowered.server.data.io.ChunkIOService)1