// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.npc.corecomponents.world;

import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.npc.util.BlockPlacementHelper;
import com.hypixel.hytale.server.npc.sensorinfo.CachedPositionProvider;
import com.hypixel.hytale.math.util.MathUtil;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.component.Store;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider;
import com.hypixel.hytale.server.npc.role.Role;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.npc.corecomponents.builders.BuilderActionBase;
import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderActionPlaceBlock;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.server.core.modules.entity.component.BoundingBox;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.server.npc.corecomponents.ActionBase;

public class ActionPlaceBlock extends ActionBase
{
    protected static final ComponentType<EntityStore, BoundingBox> BOUNDING_BOX_COMPONENT_TYPE;
    protected final double range;
    protected final boolean allowEmptyMaterials;
    protected final Vector3d target;
    
    public ActionPlaceBlock(@Nonnull final BuilderActionPlaceBlock builder, @Nonnull final BuilderSupport support) {
        super(builder);
        this.target = new Vector3d();
        this.range = builder.getRange(support);
        this.allowEmptyMaterials = builder.isAllowEmptyMaterials(support);
    }
    
    @Override
    public boolean canExecute(@Nonnull final Ref<EntityStore> ref, @Nonnull final Role role, @Nullable final InfoProvider sensorInfo, final double dt, @Nonnull final Store<EntityStore> store) {
        if (!super.canExecute(ref, role, sensorInfo, dt, store) || sensorInfo == null || !sensorInfo.hasPosition()) {
            return false;
        }
        final String blockToPlace = role.getWorldSupport().getBlockToPlace();
        if (blockToPlace == null) {
            return false;
        }
        final BlockType placedBlockType = BlockType.getAssetMap().getAsset(blockToPlace);
        if (placedBlockType == null) {
            return false;
        }
        sensorInfo.getPositionProvider().providePosition(this.target);
        final World world = store.getExternalData().getWorld();
        final TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType());
        assert transformComponent != null;
        double maxDistance = this.range;
        final BoundingBox hitBox = store.getComponent(ref, ActionPlaceBlock.BOUNDING_BOX_COMPONENT_TYPE);
        if (hitBox != null) {
            maxDistance += hitBox.getBoundingBox().getMaximumExtent();
        }
        final int x = MathUtil.floor(this.target.getX());
        final int y = MathUtil.floor(this.target.getY());
        final int z = MathUtil.floor(this.target.getZ());
        return transformComponent.getPosition().distanceSquaredTo(x, y, z) <= maxDistance * maxDistance && ((sensorInfo instanceof CachedPositionProvider && !((CachedPositionProvider)sensorInfo).isFromCache()) || (BlockPlacementHelper.canPlaceUnitBlock(world, placedBlockType, this.allowEmptyMaterials, x, y, z) && BlockPlacementHelper.canPlaceBlock(world, placedBlockType, 0, this.allowEmptyMaterials, x, y, z)));
    }
    
    @Override
    public boolean execute(@Nonnull final Ref<EntityStore> ref, @Nonnull final Role role, final InfoProvider sensorInfo, final double dt, @Nonnull final Store<EntityStore> store) {
        super.execute(ref, role, sensorInfo, dt, store);
        final World world = store.getExternalData().getWorld();
        final WorldChunk chunk = world.getNonTickingChunk(ChunkUtil.indexChunkFromBlock(this.target.getX(), this.target.getZ()));
        chunk.setBlock(MathUtil.floor(this.target.getX()), MathUtil.floor(this.target.getY()), MathUtil.floor(this.target.getZ()), role.getWorldSupport().getBlockToPlace());
        return true;
    }
    
    static {
        BOUNDING_BOX_COMPONENT_TYPE = BoundingBox.getComponentType();
    }
}
