Search in sources :

Example 1 with LanternChunk

use of org.lanternpowered.server.world.chunk.LanternChunk in project LanternServer by LanternPowered.

the class AnvilChunkIOService method read.

@Override
public boolean read(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 DataInputStream is = region.getChunkDataInputStream(regionX, regionZ);
    if (is == null) {
        return false;
    }
    final DataView levelDataView;
    try (NbtDataContainerInputStream nbt = new NbtDataContainerInputStream(is)) {
        levelDataView = nbt.read().getView(LEVEL).get();
    }
    // read the vertical sections
    final List<DataView> sectionList = levelDataView.getViewList(SECTIONS).get();
    final ChunkSection[] sections = new ChunkSection[16];
    // noinspection unchecked
    final Short2ObjectOpenHashMap<LanternTileEntity>[] tileEntitySections = new Short2ObjectOpenHashMap[sections.length];
    for (DataView sectionTag : sectionList) {
        final int y = sectionTag.getInt(Y).get();
        final byte[] rawTypes = (byte[]) sectionTag.get(BLOCKS).get();
        final byte[] extTypes = sectionTag.contains(BLOCKS_EXTRA) ? (byte[]) sectionTag.get(BLOCKS_EXTRA).get() : null;
        final byte[] data = (byte[]) sectionTag.get(DATA).get();
        final byte[] blockLight = (byte[]) sectionTag.get(BLOCK_LIGHT).get();
        final byte[] skyLight = (byte[]) sectionTag.get(SKY_LIGHT).get();
        final NibbleArray dataArray = new NibbleArray(rawTypes.length, data, true);
        final NibbleArray extTypesArray = extTypes == null ? null : new NibbleArray(rawTypes.length, extTypes, true);
        final short[] types = new short[rawTypes.length];
        for (int i = 0; i < rawTypes.length; i++) {
            types[i] = (short) ((extTypesArray == null ? 0 : extTypesArray.get(i)) << 12 | ((rawTypes[i] & 0xff) << 4) | dataArray.get(i));
        }
        tileEntitySections[y] = new Short2ObjectOpenHashMap<>();
        sections[y] = new ChunkSection(types, new NibbleArray(rawTypes.length, skyLight, true), new NibbleArray(rawTypes.length, blockLight, true), tileEntitySections[y]);
    }
    levelDataView.getViewList(TILE_ENTITIES).ifPresent(tileEntityViews -> {
        final ObjectSerializer<LanternTileEntity> tileEntitySerializer = ObjectSerializerRegistry.get().get(LanternTileEntity.class).get();
        for (DataView tileEntityView : tileEntityViews) {
            final int tileY = tileEntityView.getInt(TILE_ENTITY_Y).get();
            final int section = tileY >> 4;
            if (tileEntitySections[section] == null) {
                continue;
            }
            final int tileZ = tileEntityView.getInt(TILE_ENTITY_Z).get();
            final int tileX = tileEntityView.getInt(TILE_ENTITY_X).get();
            try {
                final LanternTileEntity tileEntity = tileEntitySerializer.deserialize(tileEntityView);
                tileEntity.setLocation(new Location<>(this.world, tileX, tileY, tileZ));
                tileEntity.setValid(true);
                tileEntitySections[section].put((short) ChunkSection.index(tileX & 0xf, tileY & 0xf, tileZ & 0xf), tileEntity);
            } catch (InvalidDataException e) {
                this.logger.warn("Error loading tile entity at ({};{};{}) in the chunk ({},{}) in the world {}", tileX & 0xf, tileY & 0xf, tileZ & 0xf, x, z, getWorldProperties().getWorldName(), e);
            }
        }
    });
    final DataView spongeDataView = levelDataView.getView(DataQueries.SPONGE_DATA).orElse(null);
    final List<DataView> trackerDataViews = spongeDataView == null ? null : levelDataView.getViewList(TRACKER_DATA_TABLE).orElse(null);
    // noinspection unchecked
    final Short2ObjectMap<LanternChunk.TrackerData>[] trackerData = chunk.getTrackerData().getRawObjects();
    if (trackerDataViews != null) {
        for (DataView dataView : trackerDataViews) {
            final Optional<Short> optIndex = dataView.getShort(TRACKER_BLOCK_POS);
            if (!optIndex.isPresent()) {
                continue;
            }
            final int creatorId = dataView.getInt(TRACKER_ENTRY_CREATOR).orElse(-1);
            final int notifierId = dataView.getInt(TRACKER_ENTRY_NOTIFIER).orElse(-1);
            // index = z << 12 | y << 4 | x
            int index = optIndex.get() & 0xffff;
            final int section = (index >> 8) & 0xf;
            // Convert the index to the section based system
            // index = y << 8 | z << 4 | x
            index = ChunkSection.index(index & 0xf, (index >> 4) & 0xf, index >> 12);
            trackerData[section].put((short) index, new LanternChunk.TrackerData(creatorId, notifierId));
        }
    }
    // initialize the chunk
    chunk.initializeSections(sections);
    chunk.setPopulated(levelDataView.getInt(TERRAIN_POPULATED).orElse(0) > 0);
    if (levelDataView.contains(BIOMES)) {
        final byte[] biomes = (byte[]) levelDataView.get(BIOMES).get();
        final byte[] biomesExtra = (byte[]) (levelDataView.contains(BIOMES_EXTRA) ? levelDataView.get(BIOMES_EXTRA).get() : null);
        final short[] newBiomes = new short[biomes.length];
        for (int i = 0; i < biomes.length; i++) {
            newBiomes[i] = (short) ((biomesExtra == null ? 0 : biomesExtra[i]) << 8 | biomes[i]);
        }
        chunk.initializeBiomes(newBiomes);
    }
    final Object heightMap;
    if (levelDataView.contains(HEIGHT_MAP) && (heightMap = levelDataView.get(HEIGHT_MAP).get()) instanceof int[]) {
        chunk.initializeHeightMap((int[]) heightMap);
    } else {
        chunk.initializeHeightMap(null);
    }
    levelDataView.getLong(INHABITED_TIME).ifPresent(time -> chunk.setInhabitedTime(time.intValue()));
    chunk.setLightPopulated(levelDataView.getInt(LIGHT_POPULATED).orElse(0) > 0);
    chunk.initializeLight();
    levelDataView.getViewList(ENTITIES).ifPresent(entityViews -> {
        final ObjectSerializer<LanternEntity> entitySerializer = ObjectSerializerRegistry.get().get(LanternEntity.class).get();
        for (DataView entityView : entityViews) {
            try {
                final LanternEntity entity = entitySerializer.deserialize(entityView);
                final int ySection = fixEntityYSection(entity.getPosition().getFloorY() >> 4);
                chunk.addEntity(entity, ySection);
            } catch (InvalidDataException e) {
                this.logger.warn("Error loading entity in the chunk ({},{}) in the world {}", x, z, getWorldProperties().getWorldName(), e);
            }
        }
    });
    return true;
}
Also used : NbtDataContainerInputStream(org.lanternpowered.server.data.persistence.nbt.NbtDataContainerInputStream) Short2ObjectOpenHashMap(it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap) LanternChunk(org.lanternpowered.server.world.chunk.LanternChunk) NibbleArray(org.lanternpowered.server.util.collect.array.NibbleArray) InvalidDataException(org.spongepowered.api.data.persistence.InvalidDataException) LanternEntity(org.lanternpowered.server.entity.LanternEntity) DataInputStream(java.io.DataInputStream) Short2ObjectMap(it.unimi.dsi.fastutil.shorts.Short2ObjectMap) DataView(org.spongepowered.api.data.DataView) LanternTileEntity(org.lanternpowered.server.block.tile.LanternTileEntity) ChunkSection(org.lanternpowered.server.world.chunk.LanternChunk.ChunkSection)

Example 2 with LanternChunk

use of org.lanternpowered.server.world.chunk.LanternChunk in project LanternServer by LanternPowered.

the class LightningSpawnerAction method run.

@Override
public void run(ScriptContext scriptContext) {
    final LanternWorld world = (LanternWorld) scriptContext.get(Parameters.WORLD).get();
    final Random random = RANDOM.get();
    final Iterable<Chunk> chunks = world.getLoadedChunks();
    final int chance = (int) (1f / Math.max(this.chance, 0.000000000001f));
    for (Chunk chunk : chunks) {
        for (int i = 0; i < this.attemptsPerChunk; i++) {
            final LanternChunk chunk1 = (LanternChunk) chunk;
            if (random.nextInt(chance) != 0) {
                continue;
            }
            final int value = random.nextInt(0x10000);
            final int x = chunk1.getX() << 4 | value & 0xf;
            final int z = chunk1.getZ() << 4 | (value >> 4) & 0xf;
            final Entity entity = world.createEntity(EntityTypes.LIGHTNING, new Vector3d(x, world.getHighestYAt(x, z), z));
            world.spawnEntity(entity);
        }
    }
}
Also used : Entity(org.spongepowered.api.entity.Entity) Random(java.util.Random) Vector3d(com.flowpowered.math.vector.Vector3d) LanternWorld(org.lanternpowered.server.world.LanternWorld) LanternChunk(org.lanternpowered.server.world.chunk.LanternChunk) Chunk(org.spongepowered.api.world.Chunk) LanternChunk(org.lanternpowered.server.world.chunk.LanternChunk)

Example 3 with LanternChunk

use of org.lanternpowered.server.world.chunk.LanternChunk in project LanternServer by LanternPowered.

the class LanternWorld method removePlayer.

public void removePlayer(LanternPlayer player) {
    this.players.remove(player);
    this.entitiesByUniqueId.remove(player.getUniqueId());
    final Vector3i lastChunkSection = player.getLastChunkSectionCoords();
    LanternChunk chunk;
    if (lastChunkSection != null && (chunk = this.chunkManager.getChunkIfLoaded(lastChunkSection.getX(), lastChunkSection.getZ())) != null) {
        chunk.removeEntity(player, lastChunkSection.getY());
    }
    this.entityProtocolManager.remove(player);
}
Also used : Vector3i(com.flowpowered.math.vector.Vector3i) LanternChunk(org.lanternpowered.server.world.chunk.LanternChunk)

Example 4 with LanternChunk

use of org.lanternpowered.server.world.chunk.LanternChunk in project LanternServer by LanternPowered.

the class LanternWorld method getIntersectingBlockCollisionBoxes.

public Set<AABB> getIntersectingBlockCollisionBoxes(AABB box, @Nullable Predicate<Entity> filter) {
    checkNotNull(box, "box");
    final ImmutableSet.Builder<AABB> boxes = ImmutableSet.builder();
    int minY = box.getMin().getFloorY();
    final int maxY = box.getMax().getFloorY();
    if (minY >= LanternWorld.BLOCK_MAX.getY() || maxY < 0) {
        return boxes.build();
    }
    minY = Math.max(0, minY);
    final int maxX = box.getMax().getFloorX();
    final int minX = box.getMin().getFloorX();
    final int maxZ = box.getMax().getFloorZ();
    final int minZ = box.getMin().getFloorZ();
    final int maxChunkX = maxX >> 4;
    final int minChunkX = minX >> 4;
    final int maxChunkZ = maxZ >> 4;
    final int minChunkZ = minZ >> 4;
    final int maxChunkSection = maxY >> 4;
    final int minChunkSection = minY >> 4;
    for (int chunkX = minChunkX; chunkX <= maxChunkX; chunkX++) {
        for (int chunkZ = minChunkZ; chunkZ <= maxChunkZ; chunkZ++) {
            final LanternChunk chunk = getChunkManager().getChunkIfLoaded(chunkX, chunkZ);
            if (chunk == null) {
                continue;
            }
            final int startX = Math.max(minX, chunkX << 4);
            final int endX = Math.min(maxX, (chunkX << 4) | 0xf);
            final int startZ = Math.max(minZ, chunkZ << 4);
            final int endZ = Math.min(maxZ, (chunkZ << 4) | 0xf);
            for (int x = startX; x <= endX; x++) {
                for (int z = startZ; z <= endZ; z++) {
                    for (int y = minY; y <= maxY; y++) {
                        final Optional<AABB> boundingBox = chunk.getBlockSelectionBox(x, y, z);
                        if (boundingBox.isPresent() && boundingBox.get().intersects(box)) {
                            boxes.add(boundingBox.get());
                        }
                    }
                }
            }
            if (filter != null) {
                chunk.addIntersectingEntitiesBoxes(boxes, maxChunkSection, minChunkSection, box, filter);
            }
        }
    }
    return boxes.build();
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) AABB(org.spongepowered.api.util.AABB) LanternChunk(org.lanternpowered.server.world.chunk.LanternChunk)

Example 5 with LanternChunk

use of org.lanternpowered.server.world.chunk.LanternChunk in project LanternServer by LanternPowered.

the class LanternWorld method getIntersectingEntities.

@Override
public Set<Entity> getIntersectingEntities(AABB box, Predicate<Entity> filter) {
    checkNotNull(box, "box");
    checkNotNull(filter, "filter");
    final ImmutableSet.Builder<Entity> entities = ImmutableSet.builder();
    final int maxX = ((int) Math.ceil(box.getMax().getX() + 2.0)) >> 4;
    final int minX = ((int) Math.floor(box.getMin().getX() - 2.0)) >> 4;
    final int maxYSection = fixEntityYSection(((int) Math.round(box.getMax().getY() + 2.0)) >> 4);
    final int minYSection = fixEntityYSection(((int) Math.round(box.getMin().getY() - 2.0)) >> 4);
    final int maxZ = ((int) Math.ceil(box.getMax().getZ() + 2.0)) >> 4;
    final int minZ = ((int) Math.floor(box.getMin().getZ() - 2.0)) >> 4;
    for (int x = minX; x <= maxX; x++) {
        for (int z = minZ; z <= maxZ; z++) {
            final LanternChunk chunk = getChunkManager().getChunkIfLoaded(x, z);
            if (chunk != null) {
                chunk.addIntersectingEntities(entities, maxYSection, minYSection, box, filter);
            }
        }
    }
    return entities.build();
}
Also used : LanternEntity(org.lanternpowered.server.entity.LanternEntity) Entity(org.spongepowered.api.entity.Entity) TileEntity(org.spongepowered.api.block.tileentity.TileEntity) ImmutableSet(com.google.common.collect.ImmutableSet) LanternChunk(org.lanternpowered.server.world.chunk.LanternChunk)

Aggregations

LanternChunk (org.lanternpowered.server.world.chunk.LanternChunk)8 LanternEntity (org.lanternpowered.server.entity.LanternEntity)5 Vector3i (com.flowpowered.math.vector.Vector3i)4 ImmutableSet (com.google.common.collect.ImmutableSet)2 Short2ObjectMap (it.unimi.dsi.fastutil.shorts.Short2ObjectMap)2 Short2ObjectOpenHashMap (it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap)2 DataInputStream (java.io.DataInputStream)2 ArrayList (java.util.ArrayList)2 LanternTileEntity (org.lanternpowered.server.block.tile.LanternTileEntity)2 NbtDataContainerInputStream (org.lanternpowered.server.data.persistence.nbt.NbtDataContainerInputStream)2 NibbleArray (org.lanternpowered.server.util.collect.array.NibbleArray)2 ChunkSection (org.lanternpowered.server.world.chunk.LanternChunk.ChunkSection)2 DataView (org.spongepowered.api.data.DataView)2 InvalidDataException (org.spongepowered.api.data.persistence.InvalidDataException)2 Entity (org.spongepowered.api.entity.Entity)2 Vector3d (com.flowpowered.math.vector.Vector3d)1 Inject (com.google.inject.Inject)1 Singleton (com.google.inject.Singleton)1 Named (com.google.inject.name.Named)1 IOException (java.io.IOException)1