filename:
common/src/main/java/rearth/oritech/block/blocks/addons/MachineAddonBlock.java
branch:
1.21
back to repo
package rearth.oritech.block.blocks.addons;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.enums.BlockFace;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.tooltip.TooltipType;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.text.Text;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import rearth.oritech.Oritech;
import rearth.oritech.block.entity.addons.AddonBlockEntity;
import rearth.oritech.block.entity.addons.EnergyAcceptorAddonBlockEntity;
import rearth.oritech.init.BlockContent;
import rearth.oritech.util.Geometry;
import rearth.oritech.util.MachineAddonController;
import rearth.oritech.util.TooltipHelper;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Objects;
public class MachineAddonBlock extends WallMountedBlock implements BlockEntityProvider {
public static final Boolean USE_ACCURATE_OUTLINES = Oritech.CONFIG.tightMachineAddonHitboxes();
public static final BooleanProperty ADDON_USED = BooleanProperty.of("addon_used");
protected final AddonSettings addonSettings;
// Bounding shapes for each type of addon, with rotations for all of their facing/face combinations
// This is intended to work for "needsSupport" addon blocks, which have the FACING and FACE state properties
// If any block does not have a boundingShape set, this will default to a full cube
public static VoxelShape[][] MACHINE_ACCEPTOR_ADDON_SHAPE;
public static VoxelShape[][] MACHINE_CAPACITOR_ADDON_SHAPE;
public static VoxelShape[][] MACHINE_PROCESSING_ADDON_SHAPE;
public static VoxelShape[][] CROP_FILTER_ADDON_SHAPE;
public static VoxelShape[][] MACHINE_EFFICIENCY_ADDON_SHAPE;
public static VoxelShape[][] MACHINE_FLUID_ADDON_SHAPE;
public static VoxelShape[][] MACHINE_INVENTORY_PROXY_ADDON_SHAPE;
public static VoxelShape[][] QUARRY_ADDON_SHAPE;
public static VoxelShape[][] MACHINE_HUNTER_ADDON_SHAPE;
public static VoxelShape[][] MACHINE_REDSTONE_ADDON_SHAPE;
public static VoxelShape[][] MACHINE_SPEED_ADDON_SHAPE;
public static VoxelShape[][] MACHINE_ULTIMATE_ADDON_SHAPE;
public static VoxelShape[][] STEAM_BOILER_ADDON_SHAPE;
public static VoxelShape[][] MACHINE_YIELD_ADDON_SHAPE;
// because this parameter is needed in appendProperties, but we can't initialize or pass it to that
private static boolean constructorAssignmentSupportWorkaround = false;
private static Settings doConstructorWorkaround(Settings settings, boolean needsSupport) {
constructorAssignmentSupportWorkaround = needsSupport;
return settings;
}
public MachineAddonBlock(Settings settings, AddonSettings addonSettings) {
super(doConstructorWorkaround(settings, addonSettings.needsSupport()));
this.addonSettings = addonSettings;
if (addonSettings.needsSupport()) {
this.setDefaultState(getDefaultState()
.with(ADDON_USED, false)
.with(FACING, Direction.NORTH)
.with(FACE, BlockFace.FLOOR)
);
} else {
this.setDefaultState(getDefaultState().with(ADDON_USED, false));
}
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) {
super.onPlaced(world, pos, state, placer, itemStack);
// search for addon extender or machine at neighbor
// if addon extender, check if its connected to a machine, if so then init it
// if machine then init it
if (world.isClient) return;
for (var direction : Direction.values()) {
var checkPos = pos.add(direction.getVector());
var checkEntity = world.getBlockEntity(checkPos);
if (checkEntity instanceof MachineAddonController machineEntity) {
AddonBlockEntity.pendingInits.add(machineEntity);
break;
} else if (checkEntity instanceof AddonBlockEntity addonEntity) {
var addonState = addonEntity.getCachedState();
var addonConnected = addonState.get(ADDON_USED);
if (!addonConnected) continue;
var controllerPos = addonEntity.getControllerPos();
if (world.getBlockEntity(controllerPos) instanceof MachineAddonController controllerEntity) {
AddonBlockEntity.pendingInits.add(controllerEntity);
break;
}
}
}
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(ADDON_USED);
if (constructorAssignmentSupportWorkaround) {
builder.add(FACING);
builder.add(FACE);
}
}
@Override
protected BlockState rotate(BlockState state, BlockRotation rotation) {
if (!state.contains(FACING)) return state;
return super.rotate(state, rotation);
}
@Override
protected BlockState mirror(BlockState state, BlockMirror mirror) {
if (!state.contains(FACING)) return state;
return super.mirror(state, mirror);
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
if (addonSettings.needsSupport)
return super.getPlacementState(ctx);
return getDefaultState();
}
@Override
public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) {
if (addonSettings.needsSupport)
return super.canPlaceAt(state, world, pos);
return true;
}
@Override
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) {
if (addonSettings.needsSupport) {
return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos);
} else {
return state;
}
}
@Override
protected MapCodec<? extends WallMountedBlock> getCodec() {
return null;
}
@Override
public BlockRenderType getRenderType(BlockState state) {
return BlockRenderType.MODEL;
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
if (!USE_ACCURATE_OUTLINES || !addonSettings.needsSupport() || addonSettings.boundingShape() == null)
return super.getOutlineShape(state, world, pos, context);
return addonSettings.boundingShape()[state.get(FACING).ordinal()][state.get(FACE).ordinal()];
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getOutlineShape(state, world, pos, context);
}
@Nullable
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
try {
return getBlockEntityType().getDeclaredConstructor(BlockPos.class, BlockState.class).newInstance(pos, state);
} catch (InstantiationException | InvocationTargetException | NoSuchMethodException |
IllegalAccessException e) {
Oritech.LOGGER.error("Unable to create blockEntity for " + getBlockEntityType().getSimpleName() + " at " + this);
return new AddonBlockEntity(pos, state);
}
}
@NotNull
public Class<? extends BlockEntity> getBlockEntityType() {
return addonSettings.acceptEnergy ? EnergyAcceptorAddonBlockEntity.class : AddonBlockEntity.class;
}
@Override
public BlockState onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) {
if (!world.isClient() && state.get(ADDON_USED)) {
var ownEntity = (AddonBlockEntity) world.getBlockEntity(pos);
var controllerEntity = world.getBlockEntity(Objects.requireNonNull(ownEntity).getControllerPos());
if (controllerEntity instanceof MachineAddonController machineEntity) {
machineEntity.initAddons(pos);
}
}
return super.onBreak(world, pos, state, player);
}
public AddonSettings getAddonSettings() {
return addonSettings;
}
@Override
public void appendTooltip(ItemStack stack, Item.TooltipContext context, List<Text> tooltip, TooltipType options) {
super.appendTooltip(stack, context, tooltip, options);
var showExtra = Screen.hasControlDown();
if (showExtra) {
if (addonSettings.speedMultiplier() != 1) {
var displayedNumber = Math.round((1 - addonSettings.speedMultiplier()) * 100);
tooltip.add(Text.translatable("tooltip.oritech.addon_speed_desc").formatted(Formatting.DARK_GRAY)
.append(TooltipHelper.getFormattedValueChangeTooltip(displayedNumber)));
}
if (addonSettings.efficiencyMultiplier() != 1) {
var displayedNumber = Math.round((1 - addonSettings.efficiencyMultiplier()) * 100);
tooltip.add(Text.translatable("tooltip.oritech.addon_efficiency_desc").formatted(Formatting.DARK_GRAY)
.append(TooltipHelper.getFormattedValueChangeTooltip(displayedNumber)));
}
if (addonSettings.addedCapacity() != 0) {
tooltip.add(
Text.translatable("tooltip.oritech.addon_capacity_desc").formatted(Formatting.DARK_GRAY)
.append(TooltipHelper.getFormattedEnergyChangeTooltip(addonSettings.addedCapacity(), " RF")));
}
if (addonSettings.addedInsert() != 0) {
tooltip.add(Text.translatable("tooltip.oritech.addon_transfer_desc").formatted(Formatting.DARK_GRAY)
.append(TooltipHelper.getFormattedEnergyChangeTooltip(addonSettings.addedInsert(), " RF/t")));
}
var item = (BlockItem) stack.getItem();
var blockType = item.getBlock();
if (blockType == BlockContent.MACHINE_YIELD_ADDON)
tooltip.add(Text.translatable("tooltip.oritech.addon_yield_desc").formatted(Formatting.GRAY));
if (blockType == BlockContent.MACHINE_FLUID_ADDON)
tooltip.add(Text.translatable("tooltip.oritech.addon_fluid_desc").formatted(Formatting.GRAY));
if (blockType == BlockContent.MACHINE_ACCEPTOR_ADDON)
tooltip.add(Text.translatable("tooltip.oritech.addon_acceptor_desc").formatted(Formatting.GRAY));
if (blockType == BlockContent.STEAM_BOILER_ADDON)
tooltip.add(Text.translatable("tooltip.oritech.addon_boiler_desc").formatted(Formatting.GRAY));
if (blockType == BlockContent.CROP_FILTER_ADDON)
tooltip.add(Text.translatable("tooltip.oritech.addon_crop_desc").formatted(Formatting.GRAY));
if (blockType == BlockContent.MACHINE_INVENTORY_PROXY_ADDON)
tooltip.add(Text.translatable("tooltip.oritech.addon_proxy_desc").formatted(Formatting.GRAY));
if (blockType == BlockContent.QUARRY_ADDON)
tooltip.add(Text.translatable("tooltip.oritech.addon_quarry_desc").formatted(Formatting.GRAY));
if (blockType == BlockContent.MACHINE_HUNTER_ADDON)
tooltip.add(Text.translatable("tooltip.oritech.addon_hunter_desc").formatted(Formatting.GRAY));
if (blockType == BlockContent.MACHINE_REDSTONE_ADDON)
tooltip.add(Text.translatable("tooltip.oritech.addon_redstone_desc").formatted(Formatting.GRAY));
if (blockType == BlockContent.MACHINE_PROCESSING_ADDON)
tooltip.add(Text.translatable("tooltip.oritech.processing_addon_desc").formatted(Formatting.GRAY));
if (addonSettings.extender()) {
tooltip.add(Text.translatable("tooltip.oritech.addon_extender_desc").formatted(Formatting.GRAY));
}
} else {
tooltip.add(Text.translatable("tooltip.oritech.item_extra_info").formatted(Formatting.GRAY).formatted(Formatting.ITALIC));
}
}
static {
MACHINE_ACCEPTOR_ADDON_SHAPE = new VoxelShape[Direction.values().length][BlockFace.values().length];
MACHINE_CAPACITOR_ADDON_SHAPE = new VoxelShape[Direction.values().length][BlockFace.values().length];
MACHINE_PROCESSING_ADDON_SHAPE = new VoxelShape[Direction.values().length][BlockFace.values().length];
MACHINE_ULTIMATE_ADDON_SHAPE = new VoxelShape[Direction.values().length][BlockFace.values().length];
CROP_FILTER_ADDON_SHAPE = new VoxelShape[Direction.values().length][BlockFace.values().length];
MACHINE_EFFICIENCY_ADDON_SHAPE = new VoxelShape[Direction.values().length][BlockFace.values().length];
MACHINE_FLUID_ADDON_SHAPE = new VoxelShape[Direction.values().length][BlockFace.values().length];
MACHINE_INVENTORY_PROXY_ADDON_SHAPE = new VoxelShape[Direction.values().length][BlockFace.values().length];
QUARRY_ADDON_SHAPE = new VoxelShape[Direction.values().length][BlockFace.values().length];
MACHINE_HUNTER_ADDON_SHAPE = new VoxelShape[Direction.values().length][BlockFace.values().length];
MACHINE_REDSTONE_ADDON_SHAPE = new VoxelShape[Direction.values().length][BlockFace.values().length];
MACHINE_SPEED_ADDON_SHAPE = new VoxelShape[Direction.values().length][BlockFace.values().length];
STEAM_BOILER_ADDON_SHAPE = new VoxelShape[Direction.values().length][BlockFace.values().length];
MACHINE_YIELD_ADDON_SHAPE = new VoxelShape[Direction.values().length][BlockFace.values().length];
for (var facing : Direction.values()) {
if (!facing.getAxis().isHorizontal()) continue;
for (var face : BlockFace.values()) {
MACHINE_ACCEPTOR_ADDON_SHAPE[facing.ordinal()][face.ordinal()] = VoxelShapes.union(
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.25, 0.625, 0.25, 0.75, 0.75, 0.75), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.25, 0.125, 0.875, 0.375, 0.875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.375, 0.125, 0.875, 0.5, 0.875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.5, 0.125, 0.875, 0.625, 0.875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0, 0.75, 0, 1, 0.875, 1), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0, 0, 0, 1, 0.125, 1), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.875, 0.125, 0.875, 1, 0.875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.1875, 0.625, 0.1875, 0.8125, 0.75, 0.8125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.1875, 0.125, 0.1875, 0.8125, 0.25, 0.8125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.3125, 0.0625, 0.0625, 0.6875, 0.8125, 0.1875), facing, face));
MACHINE_CAPACITOR_ADDON_SHAPE[facing.ordinal()][face.ordinal()] = VoxelShapes.union(
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0625, 0, 0.0625, 0.9375, 0.125, 0.9375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.1875, 0.1875, 0.3125, 0.25, 0.375, 0.6875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.25, 0.125, 0.25, 0.75, 0.4375, 0.75), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.75, 0.125, 0.1875, 0.8125, 0.5, 0.8125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.5625, 0.4375, 0.25, 0.625, 0.5, 0.75), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.6875, 0.4375, 0.25, 0.75, 0.5, 0.75), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.3125, 0.4375, 0.25, 0.375, 0.5, 0.75), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.4375, 0.4375, 0.25, 0.5, 0.5, 0.75), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.5625, 0.125, 0.1875, 0.625, 0.5, 0.25), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.6875, 0.125, 0.1875, 0.75, 0.5, 0.25), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.3125, 0.125, 0.1875, 0.375, 0.5, 0.25), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.4375, 0.125, 0.1875, 0.5, 0.5, 0.25), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.25, 0.125, 0.75, 0.75, 0.5, 0.8125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.8125, 0.25, 0.5625, 0.875, 0.4375, 0.6875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.8125, 0.25, 0.3125, 0.875, 0.4375, 0.4375), facing, face));
CROP_FILTER_ADDON_SHAPE[facing.ordinal()][face.ordinal()] = VoxelShapes.union(
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0625, 0, 0.0625, 0.9375, 0.125, 0.9375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.4375, 0.125, 0.1875, 0.875, 0.25, 0.6875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.4375, 0.25, 0.1875, 0.875, 0.5625, 0.6875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.5625, 0.3125, 0.1875, 0.75, 0.4375, 0.8125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.5625, 0.125, 0.8125, 0.75, 0.4375, 0.9375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.125, 0.125, 0.375, 0.25, 0.875), facing, face));
MACHINE_EFFICIENCY_ADDON_SHAPE[facing.ordinal()][face.ordinal()] = VoxelShapes.union(
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0625, 0, 0.0625, 0.9375, 0.125, 0.9375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.25, 0.125, 0.1875, 0.75, 0.4375, 0.8125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.75, 0.125, 0.125, 0.875, 0.5, 0.875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.125, 0.125, 0.25, 0.5, 0.875), facing, face));
MACHINE_PROCESSING_ADDON_SHAPE[facing.ordinal()][face.ordinal()] = VoxelShapes.union(
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0625, 0, 0.0625, 0.9375, 0.125, 0.9375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.25, 0.25, 0.875, 0.75, 0.75), facing, face));
MACHINE_ULTIMATE_ADDON_SHAPE[facing.ordinal()][face.ordinal()] = VoxelShapes.union(
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0625, 0, 0.0625, 0.9375, 0.125, 0.9375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.1875, 0.125, 0.1875, 0.875, 1, 0.75), facing, face));
MACHINE_FLUID_ADDON_SHAPE[facing.ordinal()][face.ordinal()] = VoxelShapes.union(
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0, 0.125, 0.875, 0.125, 0.875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0625, 0.3125, 0.1875, 0.375, 0.625, 0.5625), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.625, 0.3125, 0.1875, 1, 0.625, 0.5625), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.4375, 0.5, 0.6875, 0.5625, 1, 0.8125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.4375, 0.375, 0.6875, 0.875, 0.5, 0.8125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.75, 0.375, 0.5625, 0.875, 0.5, 0.6875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.46875, 0.125, 0.71875, 0.59375, 0.375, 0.78125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.734375, 0.125, 0.625, 0.859375, 0.375, 0.8125), facing, face), // angled post
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.125, 0.25, 0.3125, 0.3125, 0.5), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.375, 0.375, 0.25, 0.625, 0.5625, 0.5), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.6875, 0.125, 0.25, 0.875, 0.3125, 0.5), facing, face));
MACHINE_INVENTORY_PROXY_ADDON_SHAPE[facing.ordinal()][face.ordinal()] = VoxelShapes.union(
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0625, 0, 0.0625, 0.9375, 0.125, 0.9375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.125, 0.125, 0.875, 0.875, 0.875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.875, 0.375, 0.375, 1, 0.625, 0.625), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0, 0.375, 0.375, 0.125, 0.625, 0.625), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.375, 0.375, 0, 0.625, 0.625, 0.125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.375, 0.375, 0.875, 0.625, 0.625, 1), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.375, 0.8125, 0.375, 0.625, 1, 0.625), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0, 0.00125, 0.3125, 1, 0.93875, 0.375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0, 0.00125, 0.625, 1, 0.93875, 0.6875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.3125, 0.000625, 0, 0.375, 0.938125, 1), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.625, 0.000625, 0, 0.6875, 0.938125, 1), facing, face));
QUARRY_ADDON_SHAPE[facing.ordinal()][face.ordinal()] = VoxelShapes.union(
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0625, 0, 0.0625, 0.9375, 0.125, 0.9375), facing, face), // base
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.125, 0.125, 0.375, 0.25, 0.875), facing, face), // status bar
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.625, 0.125, 0.3125, 0.6875, 0.1875, 0.8125), facing, face), // pickaxe handle
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.4375, 0.125, 0.25, 0.875, 0.1875, 0.4375), facing, face)); // pickaxe head
MACHINE_HUNTER_ADDON_SHAPE[facing.ordinal()][face.ordinal()] = VoxelShapes.union(
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0625, 0, 0.0625, 0.9375, 0.125, 0.9375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.125, 0.125, 0.375, 0.25, 0.875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.5, 0.1875, 0.4375, 0.75, 0.25, 0.5625), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.4375, 0.125, 0.375, 0.8125, 0.1875, 0.625), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.5625, 0.1875, 0.375, 0.6875, 0.25, 0.4375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.5, 0.125, 0.3125, 0.75, 0.1875, 0.375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.5, 0.125, 0.625, 0.75, 0.1875, 0.6875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.5625, 0.1875, 0.5625, 0.6875, 0.25, 0.625), facing, face));
MACHINE_REDSTONE_ADDON_SHAPE[facing.ordinal()][face.ordinal()] = VoxelShapes.union(
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0625, 0, 0.0625, 0.9375, 0.125, 0.9375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.1875, 0.125, 0, 0.4375, 0.25, 0.8125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.1875, 0, 0.0015625, 0.6875, 0.1875, 0.0640625), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.625, 0.125, 0.1875, 0.75, 0.25, 0.3125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.625, 0.125, 0.5, 0.75, 0.25, 0.625), facing, face));
MACHINE_SPEED_ADDON_SHAPE[facing.ordinal()][face.ordinal()] = VoxelShapes.union(
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0625, 0, 0.0625, 0.9375, 0.125, 0.9375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.3125, 0.125, 0.6875, 0.8125, 0.25, 0.8125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.1875, 0.125, 0.1875, 0.3125, 0.25, 0.8125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.125, 0.3125, 0.1875, 0.25, 0.4375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.125, 0.5625, 0.1875, 0.25, 0.6875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.5625, 0.125, 0.8125, 0.6875, 0.25, 0.875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.3125, 0.125, 0.8125, 0.4375, 0.25, 0.875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.3125, 0.125, 0.25, 0.75, 0.1875, 0.6875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.4375, 0.1875, 0.375, 0.625, 0.625, 0.5625), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.375, 0.1875, 0.4375, 0.6875, 0.5625, 0.5), facing, face));
STEAM_BOILER_ADDON_SHAPE[facing.ordinal()][face.ordinal()] = VoxelShapes.union(
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0, 0.125, 0.875, 0.125, 0.875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.125, 0.3125, 0.25, 0.25, 0.4375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.75, 0.125, 0.3125, 0.875, 0.25, 0.4375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.4375, 0.125, 0.5625, 0.5625, 0.25, 0.6875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0000625, 0.25, 0.3125, 1.000125, 0.625, 0.6875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0, 0.1875, 0.375, 1, 0.6875, 0.625), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.000125, 0.3125, 0.25, 1.00025, 0.5625, 0.75), facing, face));
MACHINE_YIELD_ADDON_SHAPE[facing.ordinal()][face.ordinal()] = VoxelShapes.union(
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0625, 0, 0.0625, 0.9375, 0.125, 0.9375), facing, face), // base
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.125, 0.125, 0.125, 0.25, 0.375, 0.875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.75, 0.125, 0.125, 0.875, 0.375, 0.875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.25, 0.125, 0.125, 0.75, 0.375, 0.25), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.3125, 0.125, 0.3125, 0.6875, 0.25, 0.8125), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0625, 0.125, 0.5625, 0.3125, 0.4375, 0.6875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.6875, 0.125, 0.5625, 0.9375, 0.4375, 0.6875), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.0625, 0.125, 0.3125, 0.3125, 0.4375, 0.4375), facing, face),
Geometry.rotateVoxelShape(VoxelShapes.cuboid(0.6875, 0.125, 0.3125, 0.9375, 0.4375, 0.4375), facing, face));
}
}
}
// AddonSettings is an immutable configuration record for a machine addon, and should be constructed in BlockContent
public record AddonSettings(boolean extender, float speedMultiplier, float efficiencyMultiplier, long addedCapacity,
long addedInsert, boolean acceptEnergy, boolean needsSupport, int chamberCount,
VoxelShape[][] boundingShape) {
public static AddonSettings getDefaultSettings() {
return new AddonSettings(false, 1.0f, 1.0f, 0, 0, false, true, 0, null);
}
// extender and needsSupport aren't strictly exclusive, but are unlikely to be used together
public AddonSettings withExtender(boolean newExtender) {
return new AddonSettings(newExtender, speedMultiplier, efficiencyMultiplier, addedCapacity, addedInsert, acceptEnergy, needsSupport, chamberCount, boundingShape);
}
public AddonSettings withSpeedMultiplier(float newMultiplier) {
return new AddonSettings(extender, newMultiplier, efficiencyMultiplier, addedCapacity, addedInsert, acceptEnergy, needsSupport, chamberCount, boundingShape);
}
public AddonSettings withEfficiencyMultiplier(float newMultiplier) {
return new AddonSettings(extender, speedMultiplier, newMultiplier, addedCapacity, addedInsert, acceptEnergy, needsSupport, chamberCount, boundingShape);
}
public AddonSettings withAddedCapacity(long newCapacity) {
return new AddonSettings(extender, speedMultiplier, efficiencyMultiplier, newCapacity, addedInsert, acceptEnergy, needsSupport, chamberCount, boundingShape);
}
public AddonSettings withAddedInsert(long newInsert) {
return new AddonSettings(extender, speedMultiplier, efficiencyMultiplier, addedCapacity, newInsert, acceptEnergy, needsSupport, chamberCount, boundingShape);
}
public AddonSettings withAcceptEnergy(boolean newAccept) {
return new AddonSettings(extender, speedMultiplier, efficiencyMultiplier, addedCapacity, addedInsert, newAccept, needsSupport, chamberCount, boundingShape);
}
public AddonSettings withNeedsSupport(boolean newSupport) {
return new AddonSettings(extender, speedMultiplier, efficiencyMultiplier, addedCapacity, addedInsert, acceptEnergy, newSupport, chamberCount, boundingShape);
}
public AddonSettings withChambers(int chambers) {
return new AddonSettings(extender, speedMultiplier, efficiencyMultiplier, addedCapacity, addedInsert, acceptEnergy, needsSupport, chambers, boundingShape);
}
// boundingShape should only be set if needsSupport is also set
public AddonSettings withBoundingShape(VoxelShape[][] newShape) {
return new AddonSettings(extender, speedMultiplier, efficiencyMultiplier, addedCapacity, addedInsert, acceptEnergy, needsSupport, chamberCount, newShape);
}
}
}