RyanHub – file viewer
filename: common/src/main/java/rearth/oritech/block/behavior/LaserArmBlockBehavior.java
branch: 1.21
back to repo
package rearth.oritech.block.behavior;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import rearth.oritech.api.energy.EnergyApi;
import rearth.oritech.api.energy.containers.DynamicEnergyStorage;
import rearth.oritech.block.blocks.interaction.LaserArmBlock;
import rearth.oritech.block.entity.interaction.DestroyerBlockEntity;
import rearth.oritech.block.entity.interaction.LaserArmBlockEntity;
import rearth.oritech.block.entity.storage.UnstableContainerBlockEntity;
import rearth.oritech.client.init.ParticleContent;
import rearth.oritech.init.BlockContent;
import rearth.oritech.init.TagContent;

public class LaserArmBlockBehavior {
    static private LaserArmBlockBehavior noop;
    static private LaserArmBlockBehavior transferPowerBehavior;
    static private LaserArmBlockBehavior energizeBuddingBehavior;
    
    /**
     * Perform laser behavior on block
     */
    public boolean fireAtBlock(World world, LaserArmBlockEntity laserEntity, Block block, BlockPos blockPos, BlockState blockState, BlockEntity blockEntity) {
        if (laserEntity.hasCropFilterAddon && DestroyerBlockEntity.isImmatureCrop(blockState))
            return false;
        
        // has an energy storage, try to transfer power to it
        var storageCandidate = EnergyApi.BLOCK.find(world, blockPos, blockState, blockEntity, null);
        // if the storage is not exposed (e.g. catalyst / deep drill / atomic forge), get it directly
        if (storageCandidate == null && blockEntity instanceof EnergyApi.BlockProvider provider)
            storageCandidate = provider.getEnergyStorage(null);
        if (storageCandidate != null)
            return transferPowerBehavior.fireAtBlock(world, laserEntity, block, blockPos, blockState, blockEntity);
        
        // an unregistered budding block, attempt to energize it
        if (blockState.isIn(TagContent.LASER_ACCELERATED))
            return energizeBuddingBehavior.fireAtBlock(world, laserEntity, block, blockPos, blockState, blockEntity);
        
        // passes through, stop targetting this block
        if (blockState.isIn(TagContent.LASER_PASSTHROUGH))
            return false;
        
        laserEntity.addBlockBreakProgress(laserEntity.energyRequiredToFire());
        if (laserEntity.getBlockBreakProgress() >= laserEntity.getTargetBlockEnergyNeeded())
            laserEntity.finishBlockBreaking(blockPos, blockState);
        return true;
    }
    
    public static void registerDefaults() {
        noop = new LaserArmBlockBehavior() {
            @Override
            public boolean fireAtBlock(World world, LaserArmBlockEntity laserEntity, Block block, BlockPos blockPos, BlockState blockState, BlockEntity blockEntity) {
                // don't do anything, and don't keep targetting this block
                return false;
            }
        };
        LaserArmBlock.registerBlockBehavior(Blocks.TARGET, noop);
        LaserArmBlock.registerBlockBehavior(Blocks.BEDROCK, noop);
        
        transferPowerBehavior = new LaserArmBlockBehavior() {
            @Override
            public boolean fireAtBlock(World world, LaserArmBlockEntity laserEntity, Block block, BlockPos blockPos, BlockState blockState, BlockEntity blockEntity) {
                var storageCandidate = EnergyApi.BLOCK.find(world, blockPos, blockState, blockEntity, null);
                
                if (storageCandidate == null && blockEntity instanceof EnergyApi.BlockProvider energyProvider)
                    storageCandidate = energyProvider.getEnergyStorage(null);
                
                if (blockEntity instanceof UnstableContainerBlockEntity unstableContainerBlockEntity)
                    storageCandidate = unstableContainerBlockEntity.laserInputStorage;
                
                var insertAmount = storageCandidate.getCapacity() - storageCandidate.getAmount();
                if (insertAmount <= 0)
                    return false;
                
                var transferCapacity = Math.min(insertAmount, laserEntity.energyRequiredToFire());
                
                if (storageCandidate instanceof DynamicEnergyStorage dynamicStorage) {
                    var inserted = dynamicStorage.insertIgnoringLimit(transferCapacity, true);
                    if (inserted > 0 && inserted <= transferCapacity) {
                        dynamicStorage.insertIgnoringLimit(transferCapacity, false);
                        dynamicStorage.update();
                        return true;
                    }
                    return false;
                } else {
                    var inserted = storageCandidate.insert(transferCapacity, true);
                    if (inserted > 0 && inserted <= transferCapacity) {
                        storageCandidate.insert(transferCapacity, false);
                        storageCandidate.update();
                        return true;
                    }
                    return false;
                }
            }
        };
        LaserArmBlock.registerBlockBehavior(BlockContent.ATOMIC_FORGE_BLOCK, transferPowerBehavior);
        LaserArmBlock.registerBlockBehavior(BlockContent.DEEP_DRILL_BLOCK, transferPowerBehavior);
        LaserArmBlock.registerBlockBehavior(BlockContent.ENCHANTMENT_CATALYST_BLOCK, transferPowerBehavior);
        
        energizeBuddingBehavior = new LaserArmBlockBehavior() {
            @Override
            public boolean fireAtBlock(World world, LaserArmBlockEntity laserEntity, Block block, BlockPos blockPos, BlockState blockState, BlockEntity blockEntity) {
                
                if (world.getTime() % 40 == 0) {    // periodically reset target
                    return false;
                }
                if (blockState.isAir() || blockState.getFluidState().isStill()) return false;
                
                blockState.randomTick((ServerWorld) world, blockPos, world.random);
                ParticleContent.ACCELERATING.spawn(world, Vec3d.of(blockPos));
                
                return true;
            }
        };
        
        LaserArmBlock.registerBlockBehavior(Blocks.BUDDING_AMETHYST, energizeBuddingBehavior);
    }
}