org.terasology.world.block.internal.BlockBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.terasology.world.block.internal.BlockBuilder.java

Source

/*
 * Copyright 2016 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.block.internal;

import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import org.terasology.utilities.Assets;
import org.terasology.math.Rotation;
import org.terasology.math.Side;
import org.terasology.math.geom.Vector2f;
import org.terasology.world.block.Block;
import org.terasology.world.block.BlockAppearance;
import org.terasology.world.block.BlockBuilderHelper;
import org.terasology.world.block.BlockPart;
import org.terasology.world.block.loader.BlockFamilyDefinition;
import org.terasology.world.block.loader.SectionDefinitionData;
import org.terasology.world.block.shapes.BlockMeshPart;
import org.terasology.world.block.shapes.BlockShape;
import org.terasology.world.block.tiles.BlockTile;
import org.terasology.world.block.tiles.WorldAtlas;

import java.util.Map;

public class BlockBuilder implements BlockBuilderHelper {

    private WorldAtlas worldAtlas;

    private BlockShape cubeShape;
    private BlockShape loweredShape;

    public BlockBuilder(WorldAtlas worldAtlas) {
        this.worldAtlas = worldAtlas;

        cubeShape = Assets.get("engine:cube", BlockShape.class).get();
        loweredShape = Assets.get("engine:loweredCube", BlockShape.class).get();
    }

    @Override
    public Block constructSimpleBlock(BlockFamilyDefinition definition) {
        BlockShape shape = definition.getData().getBaseSection().getShape();
        if (shape == null) {
            shape = cubeShape;
        }

        Block block = constructCustomBlock(definition.getUrn().getResourceName().toString(), shape, Rotation.none(),
                definition.getData().getBaseSection());

        // Lowered mesh for liquids
        if (block.isLiquid()) {
            applyLoweredShape(block, loweredShape, definition.getData().getBaseSection().getBlockTiles());
        }
        return block;
    }

    @Override
    public Block constructSimpleBlock(BlockFamilyDefinition definition, BlockShape shape) {
        return constructCustomBlock(definition.getUrn().getResourceName().toString(), shape, Rotation.none(),
                definition.getData().getBaseSection());
    }

    @Override
    public Block constructSimpleBlock(BlockFamilyDefinition definition, String section) {
        BlockShape shape = definition.getData().getSection(section).getShape();
        if (shape == null) {
            shape = cubeShape;
        }

        return constructCustomBlock(definition.getUrn().getResourceName().toString(), shape, Rotation.none(),
                definition.getData().getSection(section));
    }

    @Override
    public Block constructSimpleBlock(BlockFamilyDefinition definition, BlockShape shape, String section) {
        return constructCustomBlock(definition.getUrn().getResourceName().toString(), shape, Rotation.none(),
                definition.getData().getSection(section));
    }

    @Override
    public Block constructTransformedBlock(BlockFamilyDefinition definition, Rotation rotation) {
        BlockShape shape = definition.getData().getBaseSection().getShape();
        if (shape == null) {
            shape = cubeShape;
        }

        return constructCustomBlock(definition.getUrn().getResourceName().toString(), shape, rotation,
                definition.getData().getBaseSection());
    }

    @Override
    public Block constructTransformedBlock(BlockFamilyDefinition definition, String section, Rotation rotation) {
        BlockShape shape = definition.getData().getSection(section).getShape();
        if (shape == null) {
            shape = cubeShape;
        }

        return constructCustomBlock(definition.getUrn().getResourceName().toString(), shape, rotation,
                definition.getData().getSection(section));
    }

    @Override
    public Block constructTransformedBlock(BlockFamilyDefinition definition, BlockShape shape, Rotation rotation) {
        return constructCustomBlock(definition.getUrn().getResourceName().toString(), shape, rotation,
                definition.getData().getBaseSection());
    }

    @Override
    public Block constructTransformedBlock(BlockFamilyDefinition definition, BlockShape shape, String section,
            Rotation rotation) {
        return constructCustomBlock(definition.getUrn().getResourceName().toString(), shape, rotation,
                definition.getData().getSection(section));
    }

    @Override
    public Block constructCustomBlock(String defaultName, BlockShape shape, Rotation rotation,
            SectionDefinitionData section) {
        Block block = createRawBlock(defaultName, section);
        block.setDirection(rotation.rotate(Side.FRONT));
        block.setPrimaryAppearance(createAppearance(shape, section.getBlockTiles(), rotation));
        setBlockFullSides(block, shape, rotation);
        block.setCollision(shape.getCollisionOffset(rotation), shape.getCollisionShape(rotation));

        for (BlockPart part : BlockPart.values()) {
            block.setColorSource(part, section.getColorSources().get(part));
            block.setColorOffset(part, section.getColorOffsets().get(part));
        }

        return block;
    }

    private Block createRawBlock(String defaultName, SectionDefinitionData def) {
        Block block = new Block();
        block.setLiquid(def.isLiquid());
        block.setWater(def.isWater());
        block.setLava(def.isLava());
        block.setGrass(def.isGrass());
        block.setIce(def.isIce());
        block.setHardness(def.getHardness());
        block.setAttachmentAllowed(def.isAttachmentAllowed());
        block.setReplacementAllowed(def.isReplacementAllowed());
        block.setSupportRequired(def.isSupportRequired());
        block.setPenetrable(def.isPenetrable());
        block.setTargetable(def.isTargetable());
        block.setClimbable(def.isClimbable());
        block.setTranslucent(def.isTranslucent());
        block.setDoubleSided(def.isDoubleSided());
        block.setShadowCasting(def.isShadowCasting());
        block.setWaving(def.isWaving());
        block.setLuminance(def.getLuminance());
        block.setTint(def.getTint());
        if (Strings.isNullOrEmpty(def.getDisplayName())) {
            block.setDisplayName(properCase(defaultName));
        } else {
            block.setDisplayName(def.getDisplayName());
        }
        block.setSounds(def.getSounds());

        block.setMass(def.getMass());
        block.setDebrisOnDestroy(def.isDebrisOnDestroy());

        if (def.getEntity() != null) {
            block.setPrefab(def.getEntity().getPrefab());
            block.setKeepActive(def.getEntity().isKeepActive());
        }

        if (def.getInventory() != null) {
            block.setStackable(def.getInventory().isStackable());
            block.setDirectPickup(def.getInventory().isDirectPickup());
        }

        return block;
    }

    private BlockAppearance createAppearance(BlockShape shape, Map<BlockPart, BlockTile> tiles, Rotation rot) {
        Map<BlockPart, BlockMeshPart> meshParts = Maps.newEnumMap(BlockPart.class);
        Map<BlockPart, Vector2f> textureAtlasPositions = Maps.newEnumMap(BlockPart.class);
        for (BlockPart part : BlockPart.values()) {
            // TODO: Need to be more sensible with the texture atlas. Because things like block particles read from a part that may not exist, we're being fairly lenient
            Vector2f atlasPos;
            if (tiles.get(part) == null) {
                atlasPos = new Vector2f();
            } else {
                atlasPos = worldAtlas.getTexCoords(tiles.get(part), shape.getMeshPart(part) != null);
            }
            BlockPart targetPart = part.rotate(rot);
            textureAtlasPositions.put(targetPart, atlasPos);
            if (shape.getMeshPart(part) != null) {
                meshParts.put(targetPart, shape.getMeshPart(part).rotate(rot.getQuat4f()).mapTexCoords(atlasPos,
                        worldAtlas.getRelativeTileSize()));
            }
        }
        return new BlockAppearance(meshParts, textureAtlasPositions);
    }

    private void setBlockFullSides(Block block, BlockShape shape, Rotation rot) {
        for (Side side : Side.values()) {
            BlockPart targetPart = BlockPart.fromSide(rot.rotate(side));
            block.setFullSide(targetPart.getSide(), shape.isBlockingSide(side));
        }
    }

    private void applyLoweredShape(Block block, BlockShape shape, Map<BlockPart, BlockTile> tiles) {
        for (Side side : Side.values()) {
            BlockPart part = BlockPart.fromSide(side);
            BlockTile blockTile = tiles.get(part);
            if (blockTile != null) {
                BlockMeshPart meshPart = shape.getMeshPart(part).rotate(Rotation.none().getQuat4f())
                        .mapTexCoords(worldAtlas.getTexCoords(blockTile, true), worldAtlas.getRelativeTileSize());
                block.setLoweredLiquidMesh(part.getSide(), meshPart);
            }
        }
    }

    private String properCase(String s) {
        if (s.length() > 1) {
            return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
        } else {
            return s.toUpperCase();
        }
    }

}