Package org.terasology.world.internal

Source Code of org.terasology.world.internal.ChunkViewCoreImpl

/*
* Copyright 2013 MovingBlocks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.terasology.world.internal;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.math.Region3i;
import org.terasology.math.TeraMath;
import org.terasology.math.Vector3i;
import org.terasology.world.biomes.Biome;
import org.terasology.world.biomes.BiomeManager;
import org.terasology.world.block.Block;
import org.terasology.world.block.BlockManager;
import org.terasology.world.chunks.Chunk;
import org.terasology.world.chunks.ChunkConstants;
import org.terasology.world.chunks.RenderableChunk;
import org.terasology.world.liquid.LiquidData;

/**
* @author Immortius
*/
public class ChunkViewCoreImpl implements ChunkViewCore {

    private static final Logger logger = LoggerFactory.getLogger(ChunkViewCoreImpl.class);

    private Vector3i offset;
    private Region3i chunkRegion;
    private Region3i blockRegion;
    private Chunk[] chunks;

    private Vector3i chunkPower;
    private Vector3i chunkFilterSize;

    private ThreadLocal<Boolean> locked = new ThreadLocal<>();

    public ChunkViewCoreImpl(Chunk[] chunks, Region3i chunkRegion, Vector3i offset) {
        locked.set(false);
        this.chunkRegion = chunkRegion;
        this.chunks = chunks;
        this.offset = offset;
        setChunkSize(new Vector3i(ChunkConstants.SIZE_X, ChunkConstants.SIZE_Y, ChunkConstants.SIZE_Z));
    }

    @Override
    public Region3i getWorldRegion() {
        return blockRegion;
    }

    @Override
    public Region3i getChunkRegion() {
        return chunkRegion;
    }

    @Override
    public Block getBlock(float x, float y, float z) {
        return getBlock(TeraMath.floorToInt(x + 0.5f), TeraMath.floorToInt(y + 0.5f), TeraMath.floorToInt(z + 0.5f));
    }

    @Override
    public Block getBlock(Vector3i pos) {
        return getBlock(pos.x, pos.y, pos.z);
    }

    // TODO: Review
    @Override
    public Block getBlock(int blockX, int blockY, int blockZ) {
        if (!blockRegion.encompasses(blockX, blockY, blockZ)) {
            return BlockManager.getAir();
        }

        int chunkIndex = relChunkIndex(blockX, blockY, blockZ);
        return chunks[chunkIndex].getBlock(TeraMath.calcBlockPos(blockX, blockY, blockZ, chunkFilterSize));
    }

    @Override
    public Biome getBiome(float x, float y, float z) {
        return getBiome(TeraMath.floorToInt(x + 0.5f), TeraMath.floorToInt(y + 0.5f), TeraMath.floorToInt(z + 0.5f));
    }

    @Override
    public Biome getBiome(Vector3i pos) {
        return getBiome(pos.x, pos.y, pos.z);
    }

    @Override
    public Biome getBiome(int blockX, int blockY, int blockZ) {
        if (!blockRegion.encompasses(blockX, blockY, blockZ)) {
            return BiomeManager.getUnknownBiome();
        }

        int chunkIndex = relChunkIndex(blockX, blockY, blockZ);
        Vector3i blockPos = TeraMath.calcBlockPos(blockX, blockY, blockZ, chunkFilterSize);
        return chunks[chunkIndex].getBiome(blockPos.x, blockPos.y, blockPos.z);
    }

    @Override
    public byte getSunlight(float x, float y, float z) {
        return getSunlight(TeraMath.floorToInt(x + 0.5f), TeraMath.floorToInt(y + 0.5f), TeraMath.floorToInt(z + 0.5f));
    }

    @Override
    public byte getSunlight(Vector3i pos) {
        return getSunlight(pos.x, pos.y, pos.z);
    }

    @Override
    public byte getLight(float x, float y, float z) {
        return getLight(TeraMath.floorToInt(x + 0.5f), TeraMath.floorToInt(y + 0.5f), TeraMath.floorToInt(z + 0.5f));
    }

    @Override
    public byte getLight(Vector3i pos) {
        return getLight(pos.x, pos.y, pos.z);
    }

    @Override
    public byte getSunlight(int blockX, int blockY, int blockZ) {
        if (!blockRegion.encompasses(blockX, blockY, blockZ)) {
            return 0;
        }

        int chunkIndex = relChunkIndex(blockX, blockY, blockZ);
        return chunks[chunkIndex].getSunlight(TeraMath.calcBlockPos(blockX, blockY, blockZ, chunkFilterSize));
    }

    @Override
    public byte getLight(int blockX, int blockY, int blockZ) {
        if (!blockRegion.encompasses(blockX, blockY, blockZ)) {
            return 0;
        }

        int chunkIndex = relChunkIndex(blockX, blockY, blockZ);
        return chunks[chunkIndex].getLight(TeraMath.calcBlockPos(blockX, blockY, blockZ, chunkFilterSize));
    }

    @Override
    public void setBlock(Vector3i pos, Block type) {
        setBlock(pos.x, pos.y, pos.z, type);
    }

    @Override
    public void setBlock(int blockX, int blockY, int blockZ, Block type) {
        if (!locked.get()) {
            throw new IllegalStateException("Attempted to modify block though an unlocked view");
        } else if (blockRegion.encompasses(blockX, blockY, blockZ)) {
            int chunkIndex = relChunkIndex(blockX, blockY, blockZ);
            chunks[chunkIndex].setBlock(TeraMath.calcBlockPos(blockX, blockY, blockZ, chunkFilterSize), type);
        } else {
            logger.warn("Attempt to modify block outside of the view");
        }
    }

    @Override
    public void setBiome(Vector3i pos, Biome biome) {
        setBiome(pos.x, pos.y, pos.z, biome);
    }

    @Override
    public void setBiome(int blockX, int blockY, int blockZ, Biome biome) {
        if (!locked.get()) {
            throw new IllegalStateException("Attempted to modify biome though an unlocked view");
        } else if (blockRegion.encompasses(blockX, blockY, blockZ)) {
            int chunkIndex = relChunkIndex(blockX, blockY, blockZ);
            Vector3i pos = TeraMath.calcBlockPos(blockX, blockY, blockZ, chunkFilterSize);
            chunks[chunkIndex].setBiome(pos.x, pos.y, pos.z, biome);
        } else {
            logger.warn("Attempt to modify biome outside of the view");
        }
    }

    @Override
    public LiquidData getLiquid(Vector3i pos) {
        return getLiquid(pos.x, pos.y, pos.z);
    }

    @Override
    public LiquidData getLiquid(int x, int y, int z) {
        if (!blockRegion.encompasses(x, y, z)) {
            return new LiquidData();
        }

        int chunkIndex = relChunkIndex(x, y, z);
        return chunks[chunkIndex].getLiquid(TeraMath.calcBlockPos(x, y, z, chunkFilterSize));
    }

    @Override
    public void setLiquid(Vector3i pos, LiquidData newState) {
        setLiquid(pos.x, pos.y, pos.z, newState);
    }

    @Override
    public void setLiquid(int x, int y, int z, LiquidData newState) {
        if (locked.get() && blockRegion.encompasses(x, y, z)) {
            int chunkIndex = relChunkIndex(x, y, z);
            chunks[chunkIndex].setLiquid(TeraMath.calcBlockPos(x, y, z, chunkFilterSize), newState);
        } else {
            throw new IllegalStateException("Attempted to modify liquid data though an unlocked view");
        }
    }

    @Override
    public void setLight(Vector3i pos, byte light) {
        setLight(pos.x, pos.y, pos.z, light);
    }

    @Override
    public void setLight(int blockX, int blockY, int blockZ, byte light) {
        if (locked.get() && blockRegion.encompasses(blockX, blockY, blockZ)) {
            int chunkIndex = relChunkIndex(blockX, blockY, blockZ);
            chunks[chunkIndex].setLight(TeraMath.calcBlockPos(blockX, blockY, blockZ, chunkFilterSize), light);
        } else if (!locked.get()) {
            throw new IllegalStateException("Attempted to modify light though an unlocked view");
        } else {
            logger.warn("Attempted to set light at a position not encompassed by the view");
        }
    }

    @Override
    public void setSunlight(Vector3i pos, byte light) {
        setSunlight(pos.x, pos.y, pos.z, light);
    }

    @Override
    public void setSunlight(int blockX, int blockY, int blockZ, byte light) {
        if (locked.get() && blockRegion.encompasses(blockX, blockY, blockZ)) {
            int chunkIndex = relChunkIndex(blockX, blockY, blockZ);
            chunks[chunkIndex].setSunlight(TeraMath.calcBlockPos(blockX, blockY, blockZ, chunkFilterSize), light);
        } else {
            throw new IllegalStateException("Attempted to modify sunlight though an unlocked view");
        }
    }

    @Override
    public void setDirtyAround(Vector3i blockPos) {
        for (Vector3i pos : TeraMath.getChunkRegionAroundWorldPos(blockPos, 1)) {
            chunks[pos.x + offset.x + chunkRegion.size().x * (pos.z + offset.z)].setDirty(true);
        }
    }

    @Override
    public void setDirtyAround(Region3i region) {
        Vector3i minPos = new Vector3i(region.min());
        minPos.sub(1, 1, 1);
        Vector3i maxPos = new Vector3i(region.max());
        maxPos.add(1, 1, 1);

        Vector3i minChunk = TeraMath.calcChunkPos(minPos, chunkPower);
        Vector3i maxChunk = TeraMath.calcChunkPos(maxPos, chunkPower);

        for (Vector3i pos : Region3i.createFromMinMax(minChunk, maxChunk)) {
            chunks[pos.x + offset.x + chunkRegion.size().x * (pos.z + offset.z)].setDirty(true);
        }
    }

    @Override
    public void lock() {
        if (!locked.get()) {
            for (RenderableChunk chunk : chunks) {
                chunk.lock();
            }
            locked.set(true);
        }
    }

    @Override
    public void unlock() {
        if (locked.get()) {
            locked.set(false);
            for (RenderableChunk chunk : chunks) {
                chunk.unlock();
            }
        }
    }

    @Override
    public boolean isLocked() {
        return locked.get();
    }

    @Override
    public boolean isValidView() {
        for (Chunk chunk : chunks) {
            if (chunk.isDisposed()) {
                return false;
            }
        }
        return true;
    }

    protected int relChunkIndex(int x, int y, int z) {
        return TeraMath.calculate3DArrayIndex(TeraMath.calcChunkPosX(x, chunkPower.x) + offset.x,
                TeraMath.calcChunkPosY(y, chunkPower.y) + offset.y,
                TeraMath.calcChunkPosZ(z, chunkPower.z) + offset.z, chunkRegion.size());
    }

    public void setChunkSize(Vector3i chunkSize) {
        this.chunkFilterSize = new Vector3i(TeraMath.ceilPowerOfTwo(chunkSize.x) - 1, TeraMath.ceilPowerOfTwo(chunkSize.y) - 1, TeraMath.ceilPowerOfTwo(chunkSize.z) - 1);
        this.chunkPower = new Vector3i(TeraMath.sizeOfPower(chunkSize.x), TeraMath.sizeOfPower(chunkSize.y), TeraMath.sizeOfPower(chunkSize.z));

        Vector3i blockMin = new Vector3i();
        blockMin.sub(offset);
        blockMin.mult(chunkSize.x, chunkSize.y, chunkSize.z);
        Vector3i blockSize = chunkRegion.size();
        blockSize.mult(chunkSize.x, chunkSize.y, chunkSize.z);
        this.blockRegion = Region3i.createFromMinAndSize(blockMin, blockSize);
    }

    @Override
    public Vector3i toWorldPos(Vector3i localPos) {
        return new Vector3i(localPos.x + (offset.x + chunkRegion.min().x) * ChunkConstants.SIZE_X, localPos.y + (offset.y + chunkRegion.min().y) * ChunkConstants.SIZE_Y,
                localPos.z + (offset.z + chunkRegion.min().z) * ChunkConstants.SIZE_Z);
    }
}
TOP

Related Classes of org.terasology.world.internal.ChunkViewCoreImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.