Search in sources :

Example 1 with FormationResult

use of mekanism.common.lib.multiblock.FormationProtocol.FormationResult in project Mekanism by mekanism.

the class CuboidStructureValidator method validate.

@Override
public FormationResult validate(FormationProtocol<T> ctx, Long2ObjectMap<IChunk> chunkMap) {
    BlockPos min = cuboid.getMinPos(), max = cuboid.getMaxPos();
    BlockPos.Mutable mutablePos = new BlockPos.Mutable();
    for (int x = min.getX(); x <= max.getX(); x++) {
        for (int y = min.getY(); y <= max.getY(); y++) {
            for (int z = min.getZ(); z <= max.getZ(); z++) {
                mutablePos.set(x, y, z);
                FormationResult ret = validateNode(ctx, chunkMap, mutablePos);
                if (!ret.isFormed()) {
                    return ret;
                }
            }
        }
    }
    return FormationResult.SUCCESS;
}
Also used : FormationResult(mekanism.common.lib.multiblock.FormationProtocol.FormationResult) BlockPos(net.minecraft.util.math.BlockPos)

Example 2 with FormationResult

use of mekanism.common.lib.multiblock.FormationProtocol.FormationResult in project Mekanism by mekanism.

the class CuboidStructureValidator method validateNode.

/**
 * @param pos Mutable BlockPos
 */
protected FormationResult validateNode(FormationProtocol<T> ctx, Long2ObjectMap<IChunk> chunkMap, BlockPos pos) {
    Optional<BlockState> optionalState = WorldUtils.getBlockState(world, chunkMap, pos);
    if (!optionalState.isPresent()) {
        // If the position is not in a loaded chunk or out of bounds of the world, fail
        return FormationResult.FAIL;
    }
    BlockState state = optionalState.get();
    StructureRequirement requirement = getStructureRequirement(pos);
    if (requirement.isCasing()) {
        CasingType type = getCasingType(state);
        FormationResult ret = validateFrame(ctx, pos, state, type, requirement.needsFrame());
        if (requirement != StructureRequirement.IGNORED && !ret.isFormed()) {
            return ret;
        }
    } else if (!validateInner(state, chunkMap, pos)) {
        return FormationResult.fail(MekanismLang.MULTIBLOCK_INVALID_INNER, pos);
    } else if (!state.isAir(world, pos)) {
        // Make sure the position is immutable before we store it
        ctx.innerNodes.add(pos.immutable());
    }
    return FormationResult.SUCCESS;
}
Also used : BlockState(net.minecraft.block.BlockState) CasingType(mekanism.common.lib.multiblock.FormationProtocol.CasingType) FormationResult(mekanism.common.lib.multiblock.FormationProtocol.FormationResult) StructureRequirement(mekanism.common.lib.multiblock.FormationProtocol.StructureRequirement)

Example 3 with FormationResult

use of mekanism.common.lib.multiblock.FormationProtocol.FormationResult in project Mekanism by mekanism.

the class TurbineValidator method postcheck.

@Override
public FormationResult postcheck(TurbineMultiblockData structure, Set<BlockPos> innerNodes, Long2ObjectMap<IChunk> chunkMap) {
    if (structure.length() % 2 != 1 || structure.width() % 2 != 1) {
        return FormationResult.fail(GeneratorsLang.TURBINE_INVALID_EVEN_LENGTH);
    }
    int centerX = structure.getMinPos().getX() + (structure.length() - 1) / 2;
    int centerZ = structure.getMinPos().getZ() + (structure.width() - 1) / 2;
    BlockPos complex = null;
    Set<BlockPos> turbines = new ObjectOpenHashSet<>();
    Set<BlockPos> dispersers = new ObjectOpenHashSet<>();
    Set<BlockPos> coils = new ObjectOpenHashSet<>();
    Set<BlockPos> condensers = new ObjectOpenHashSet<>();
    // Scan for complex
    for (BlockPos pos : innerNodes) {
        TileEntity tile = WorldUtils.getTileEntity(world, chunkMap, pos);
        if (tile instanceof TileEntityRotationalComplex) {
            if (complex != null || pos.getX() != centerX || pos.getZ() != centerZ) {
                return FormationResult.fail(GeneratorsLang.TURBINE_INVALID_BAD_COMPLEX, pos);
            }
            structure.internalLocations.add(pos);
            complex = pos;
        } else if (tile instanceof TileEntityTurbineRotor) {
            if (pos.getX() != centerX || pos.getZ() != centerZ) {
                return FormationResult.fail(GeneratorsLang.TURBINE_INVALID_BAD_ROTOR, pos);
            }
            turbines.add(pos);
        } else if (tile instanceof TileEntityPressureDisperser) {
            dispersers.add(pos);
        } else if (tile instanceof TileEntityElectromagneticCoil) {
            coils.add(pos);
        } else if (tile instanceof TileEntitySaturatingCondenser) {
            condensers.add(pos);
        }
    }
    // Terminate if complex doesn't exist
    if (complex == null) {
        return FormationResult.fail(GeneratorsLang.TURBINE_INVALID_MISSING_COMPLEX);
    }
    int rotors = complex.getY() - structure.getMinPos().getY() + 1;
    int innerRadius = (Math.min(structure.length(), structure.width()) - 3) / 2;
    if (innerRadius < rotors / 4) {
        return FormationResult.fail(GeneratorsLang.TURBINE_INVALID_TOO_NARROW);
    }
    // Terminate if coils don't exist
    if (coils.isEmpty()) {
        return FormationResult.fail(GeneratorsLang.TURBINE_INVALID_MISSING_COILS);
    }
    BlockPos.Mutable mutablePos = new BlockPos.Mutable();
    // Make sure a flat, horizontal plane of dispersers exists within the multiblock around the complex
    for (int x = complex.getX() - innerRadius; x <= complex.getX() + innerRadius; x++) {
        for (int z = complex.getZ() - innerRadius; z <= complex.getZ() + innerRadius; z++) {
            if (x != centerX || z != centerZ) {
                mutablePos.set(x, complex.getY(), z);
                TileEntityPressureDisperser tile = WorldUtils.getTileEntity(TileEntityPressureDisperser.class, world, chunkMap, mutablePos);
                if (tile == null) {
                    return FormationResult.fail(GeneratorsLang.TURBINE_INVALID_MISSING_DISPERSER, mutablePos);
                }
                dispersers.remove(mutablePos);
            }
        }
    }
    // If any dispersers were not processed, they're in the wrong place
    if (!dispersers.isEmpty()) {
        return FormationResult.fail(GeneratorsLang.TURBINE_INVALID_MALFORMED_DISPERSERS);
    }
    // Make sure all condensers are in proper locations
    for (BlockPos coord : condensers) {
        if (coord.getY() <= complex.getY()) {
            return FormationResult.fail(GeneratorsLang.TURBINE_INVALID_CONDENSER_BELOW_COMPLEX, coord);
        }
    }
    structure.condensers = condensers.size();
    int turbineHeight = 0;
    int blades = 0;
    // Starting from the complex, walk down and count the number of rotors/blades in the structure
    for (int y = complex.getY() - 1; y > structure.getMinPos().getY(); y--) {
        mutablePos.set(centerX, y, centerZ);
        TileEntityTurbineRotor rotor = WorldUtils.getTileEntity(TileEntityTurbineRotor.class, world, chunkMap, mutablePos);
        if (rotor == null) {
            // Not a contiguous set of rotors
            return FormationResult.fail(GeneratorsLang.TURBINE_INVALID_ROTORS_NOT_CONTIGUOUS);
        }
        turbineHeight++;
        blades += rotor.getHousedBlades();
        structure.internalLocations.add(rotor.getBlockPos());
        turbines.remove(mutablePos);
    }
    // If there are any rotors left over, they are in the wrong place in the structure
    if (!turbines.isEmpty()) {
        return FormationResult.fail(GeneratorsLang.TURBINE_INVALID_BAD_ROTORS);
    }
    // Update the structure with number of blades found on rotors
    structure.blades = blades;
    BlockPos startCoord = complex.relative(Direction.UP);
    if (WorldUtils.getTileEntity(TileEntityElectromagneticCoil.class, world, chunkMap, startCoord) != null) {
        structure.coils = FormationProtocol.explore(startCoord, coord -> WorldUtils.getTileEntity(TileEntityElectromagneticCoil.class, world, chunkMap, coord) != null);
    }
    if (coils.size() > structure.coils) {
        return FormationResult.fail(GeneratorsLang.TURBINE_INVALID_MALFORMED_COILS);
    }
    for (BlockPos coord : structure.locations) {
        if (WorldUtils.getTileEntity(TileEntityTurbineVent.class, world, chunkMap, coord) != null) {
            if (coord.getY() < complex.getY()) {
                return FormationResult.fail(GeneratorsLang.TURBINE_INVALID_VENT_BELOW_COMPLEX, coord);
            }
            structure.vents++;
        }
    }
    structure.lowerVolume = structure.length() * structure.width() * turbineHeight;
    structure.complex = complex;
    return FormationResult.SUCCESS;
}
Also used : VoxelCuboid(mekanism.common.lib.math.voxel.VoxelCuboid) TileEntityTurbineRotor(mekanism.generators.common.tile.turbine.TileEntityTurbineRotor) TileEntitySaturatingCondenser(mekanism.generators.common.tile.turbine.TileEntitySaturatingCondenser) Direction(net.minecraft.util.Direction) CasingType(mekanism.common.lib.multiblock.FormationProtocol.CasingType) MekanismBlockTypes(mekanism.common.registries.MekanismBlockTypes) Block(net.minecraft.block.Block) BlockType(mekanism.common.content.blocktype.BlockType) FormationResult(mekanism.common.lib.multiblock.FormationProtocol.FormationResult) BlockState(net.minecraft.block.BlockState) TileEntityElectromagneticCoil(mekanism.generators.common.tile.turbine.TileEntityElectromagneticCoil) TileEntityRotationalComplex(mekanism.generators.common.tile.turbine.TileEntityRotationalComplex) TileEntityTurbineVent(mekanism.generators.common.tile.turbine.TileEntityTurbineVent) Set(java.util.Set) BlockPos(net.minecraft.util.math.BlockPos) FormationProtocol(mekanism.common.lib.multiblock.FormationProtocol) CuboidStructureValidator(mekanism.common.lib.multiblock.CuboidStructureValidator) ObjectOpenHashSet(it.unimi.dsi.fastutil.objects.ObjectOpenHashSet) GeneratorsLang(mekanism.generators.common.GeneratorsLang) TileEntityPressureDisperser(mekanism.common.tile.TileEntityPressureDisperser) WorldUtils(mekanism.common.util.WorldUtils) IChunk(net.minecraft.world.chunk.IChunk) TileEntity(net.minecraft.tileentity.TileEntity) Long2ObjectMap(it.unimi.dsi.fastutil.longs.Long2ObjectMap) GeneratorsBlockTypes(mekanism.generators.common.registries.GeneratorsBlockTypes) TileEntityPressureDisperser(mekanism.common.tile.TileEntityPressureDisperser) ObjectOpenHashSet(it.unimi.dsi.fastutil.objects.ObjectOpenHashSet) TileEntityTurbineVent(mekanism.generators.common.tile.turbine.TileEntityTurbineVent) TileEntityElectromagneticCoil(mekanism.generators.common.tile.turbine.TileEntityElectromagneticCoil) TileEntity(net.minecraft.tileentity.TileEntity) TileEntitySaturatingCondenser(mekanism.generators.common.tile.turbine.TileEntitySaturatingCondenser) TileEntityRotationalComplex(mekanism.generators.common.tile.turbine.TileEntityRotationalComplex) BlockPos(net.minecraft.util.math.BlockPos) TileEntityTurbineRotor(mekanism.generators.common.tile.turbine.TileEntityTurbineRotor)

Example 4 with FormationResult

use of mekanism.common.lib.multiblock.FormationProtocol.FormationResult in project Mekanism by mekanism.

the class FissionReactorValidator method postcheck.

@Override
public FormationResult postcheck(FissionReactorMultiblockData structure, Set<BlockPos> innerNodes, Long2ObjectMap<IChunk> chunkMap) {
    Map<AssemblyPos, FuelAssembly> map = new HashMap<>();
    Set<BlockPos> fuelAssemblyCoords = new HashSet<>();
    int assemblyCount = 0, surfaceArea = 0;
    for (BlockPos coord : innerNodes) {
        TileEntity tile = WorldUtils.getTileEntity(world, chunkMap, coord);
        AssemblyPos pos = new AssemblyPos(coord.getX(), coord.getZ());
        FuelAssembly assembly = map.get(pos);
        if (tile instanceof TileEntityFissionFuelAssembly) {
            if (assembly == null) {
                map.put(pos, new FuelAssembly(coord, false));
            } else {
                assembly.fuelAssemblies.add(coord);
            }
            assemblyCount++;
            // compute surface area
            surfaceArea += 6;
            for (Direction side : EnumUtils.DIRECTIONS) {
                if (fuelAssemblyCoords.contains(coord.relative(side))) {
                    surfaceArea -= 2;
                }
            }
            fuelAssemblyCoords.add(coord);
            structure.internalLocations.add(coord);
        } else if (tile instanceof TileEntityControlRodAssembly) {
            if (assembly == null) {
                map.put(pos, new FuelAssembly(coord, true));
            } else if (assembly.controlRodAssembly != null) {
                // only one control rod per assembly
                return FormationResult.fail(GeneratorsLang.FISSION_INVALID_EXTRA_CONTROL_ROD, coord);
            } else {
                assembly.controlRodAssembly = coord;
            }
        }
    }
    // require at least one fuel assembly
    if (map.isEmpty()) {
        return FormationResult.fail(GeneratorsLang.FISSION_INVALID_MISSING_FUEL_ASSEMBLY);
    }
    for (Entry<AssemblyPos, FuelAssembly> entry : map.entrySet()) {
        FuelAssembly assembly = entry.getValue();
        FormationResult result = assembly.validate(entry.getKey());
        if (!result.isFormed()) {
            return result;
        }
        structure.assemblies.add(assembly.build());
    }
    structure.fuelAssemblies = assemblyCount;
    structure.surfaceArea = surfaceArea;
    return FormationResult.SUCCESS;
}
Also used : TileEntityControlRodAssembly(mekanism.generators.common.tile.fission.TileEntityControlRodAssembly) HashMap(java.util.HashMap) TileEntityFissionFuelAssembly(mekanism.generators.common.tile.fission.TileEntityFissionFuelAssembly) FormationResult(mekanism.common.lib.multiblock.FormationProtocol.FormationResult) Direction(net.minecraft.util.Direction) TileEntity(net.minecraft.tileentity.TileEntity) TileEntityFissionFuelAssembly(mekanism.generators.common.tile.fission.TileEntityFissionFuelAssembly) BlockPos(net.minecraft.util.math.BlockPos) HashSet(java.util.HashSet)

Example 5 with FormationResult

use of mekanism.common.lib.multiblock.FormationProtocol.FormationResult in project Mekanism by mekanism.

the class BoilerValidator method postcheck.

@Override
public FormationResult postcheck(BoilerMultiblockData structure, Set<BlockPos> innerNodes, Long2ObjectMap<IChunk> chunkMap) {
    Set<BlockPos> dispersers = new ObjectOpenHashSet<>();
    Set<BlockPos> elements = new ObjectOpenHashSet<>();
    for (BlockPos pos : innerNodes) {
        TileEntity tile = WorldUtils.getTileEntity(world, chunkMap, pos);
        if (tile instanceof TileEntityPressureDisperser) {
            dispersers.add(pos);
        } else if (tile instanceof TileEntitySuperheatingElement) {
            structure.internalLocations.add(pos);
            elements.add(pos);
        }
    }
    // Ensure at least one disperser exists
    if (dispersers.isEmpty()) {
        return FormationResult.fail(MekanismLang.BOILER_INVALID_NO_DISPERSER);
    }
    // Ensure that at least one superheating element exists
    if (elements.isEmpty()) {
        return FormationResult.fail(MekanismLang.BOILER_INVALID_SUPERHEATING);
    }
    // Find a single disperser contained within this multiblock
    final BlockPos initDisperser = dispersers.iterator().next();
    // Ensure that a full horizontal plane of dispersers exists, surrounding the found disperser
    BlockPos.Mutable mutablePos = new BlockPos.Mutable();
    for (int x = 1; x < structure.length() - 1; x++) {
        for (int z = 1; z < structure.width() - 1; z++) {
            mutablePos.set(structure.renderLocation.getX() + x, initDisperser.getY(), structure.renderLocation.getZ() + z);
            TileEntityPressureDisperser tile = WorldUtils.getTileEntity(TileEntityPressureDisperser.class, world, chunkMap, mutablePos);
            if (tile == null) {
                return FormationResult.fail(MekanismLang.BOILER_INVALID_MISSING_DISPERSER, mutablePos);
            }
            dispersers.remove(mutablePos);
        }
    }
    // If there are more dispersers than those on the plane found, the structure is invalid
    if (!dispersers.isEmpty()) {
        return FormationResult.fail(MekanismLang.BOILER_INVALID_EXTRA_DISPERSER);
    }
    structure.superheatingElements = FormationProtocol.explore(elements.iterator().next(), coord -> coord.getY() < initDisperser.getY() && WorldUtils.getTileEntity(TileEntitySuperheatingElement.class, world, chunkMap, coord) != null);
    if (elements.size() > structure.superheatingElements) {
        return FormationResult.fail(MekanismLang.BOILER_INVALID_SUPERHEATING);
    }
    BlockPos initAir = null;
    BlockPos.Mutable mutableAir = new BlockPos.Mutable();
    int totalAir = 0;
    // Find the first available block in the structure for water storage (including casings)
    for (int x = structure.renderLocation.getX(); x < structure.renderLocation.getX() + structure.length(); x++) {
        for (int y = structure.renderLocation.getY(); y < initDisperser.getY(); y++) {
            for (int z = structure.renderLocation.getZ(); z < structure.renderLocation.getZ() + structure.width(); z++) {
                mutableAir.set(x, y, z);
                if (isAirOrFrame(chunkMap, mutableAir)) {
                    initAir = mutableAir.immutable();
                    totalAir++;
                }
            }
        }
    }
    // Gradle build requires these fields to be final
    final BlockPos renderLocation = structure.renderLocation;
    final int volLength = structure.length();
    final int volWidth = structure.width();
    structure.setWaterVolume(FormationProtocol.explore(initAir, coord -> coord.getY() >= renderLocation.getY() - 1 && coord.getY() < initDisperser.getY() && coord.getX() >= renderLocation.getX() && coord.getX() < renderLocation.getX() + volLength && coord.getZ() >= renderLocation.getZ() && coord.getZ() < renderLocation.getZ() + volWidth && isAirOrFrame(chunkMap, coord)));
    // Make sure all air blocks are connected
    if (totalAir > structure.getWaterVolume()) {
        return FormationResult.fail(MekanismLang.BOILER_INVALID_AIR_POCKETS);
    }
    int steamHeight = (structure.renderLocation.getY() + structure.height() - 2) - initDisperser.getY();
    structure.setSteamVolume(structure.width() * structure.length() * steamHeight);
    structure.upperRenderLocation = new BlockPos(structure.renderLocation.getX(), initDisperser.getY() + 1, structure.renderLocation.getZ());
    return FormationResult.SUCCESS;
}
Also used : TileEntity(net.minecraft.tileentity.TileEntity) Set(java.util.Set) BlockPos(net.minecraft.util.math.BlockPos) FormationProtocol(mekanism.common.lib.multiblock.FormationProtocol) CuboidStructureValidator(mekanism.common.lib.multiblock.CuboidStructureValidator) CasingType(mekanism.common.lib.multiblock.FormationProtocol.CasingType) ObjectOpenHashSet(it.unimi.dsi.fastutil.objects.ObjectOpenHashSet) MekanismBlockTypes(mekanism.common.registries.MekanismBlockTypes) Block(net.minecraft.block.Block) BlockType(mekanism.common.content.blocktype.BlockType) TileEntityPressureDisperser(mekanism.common.tile.TileEntityPressureDisperser) WorldUtils(mekanism.common.util.WorldUtils) FormationResult(mekanism.common.lib.multiblock.FormationProtocol.FormationResult) Optional(java.util.Optional) IChunk(net.minecraft.world.chunk.IChunk) MekanismLang(mekanism.common.MekanismLang) TileEntity(net.minecraft.tileentity.TileEntity) Long2ObjectMap(it.unimi.dsi.fastutil.longs.Long2ObjectMap) BlockState(net.minecraft.block.BlockState) TileEntitySuperheatingElement(mekanism.common.tile.multiblock.TileEntitySuperheatingElement) TileEntityPressureDisperser(mekanism.common.tile.TileEntityPressureDisperser) ObjectOpenHashSet(it.unimi.dsi.fastutil.objects.ObjectOpenHashSet) BlockPos(net.minecraft.util.math.BlockPos) TileEntitySuperheatingElement(mekanism.common.tile.multiblock.TileEntitySuperheatingElement)

Aggregations

FormationResult (mekanism.common.lib.multiblock.FormationProtocol.FormationResult)5 BlockPos (net.minecraft.util.math.BlockPos)4 CasingType (mekanism.common.lib.multiblock.FormationProtocol.CasingType)3 BlockState (net.minecraft.block.BlockState)3 TileEntity (net.minecraft.tileentity.TileEntity)3 Long2ObjectMap (it.unimi.dsi.fastutil.longs.Long2ObjectMap)2 ObjectOpenHashSet (it.unimi.dsi.fastutil.objects.ObjectOpenHashSet)2 Set (java.util.Set)2 BlockType (mekanism.common.content.blocktype.BlockType)2 CuboidStructureValidator (mekanism.common.lib.multiblock.CuboidStructureValidator)2 FormationProtocol (mekanism.common.lib.multiblock.FormationProtocol)2 MekanismBlockTypes (mekanism.common.registries.MekanismBlockTypes)2 TileEntityPressureDisperser (mekanism.common.tile.TileEntityPressureDisperser)2 WorldUtils (mekanism.common.util.WorldUtils)2 Block (net.minecraft.block.Block)2 Direction (net.minecraft.util.Direction)2 IChunk (net.minecraft.world.chunk.IChunk)2 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Optional (java.util.Optional)1