/* * Copyright (C) 2018 BARBOTIN Nicolas */ package net.montoyo.wd.utilities; import net.minecraft.core.BlockPos; import net.minecraft.world.level.LevelAccessor; import net.montoyo.wd.registry.BlockRegistry; public abstract class Multiblock { public enum OverrideAction { NONE, SIMULATE, IGNORE } public static class BlockOverride { final Vector3i pos; final OverrideAction action; public BlockOverride(Vector3i p, OverrideAction act) { pos = p; action = act; } public boolean apply(Vector3i bp, boolean originalResult) { if(action == OverrideAction.NONE || !bp.equals(pos)) return originalResult; else if(action == OverrideAction.SIMULATE) return true; else //action == OverrideAction.IGNORE return false; } } public static final BlockOverride NULL_OVERRIDE = new BlockOverride(null, OverrideAction.NONE); //Modifies pos public static void findOrigin(LevelAccessor world, Vector3i pos, BlockSide side, BlockOverride override) { if(override == null) override = NULL_OVERRIDE; BlockPos.MutableBlockPos bp = new BlockPos.MutableBlockPos(); //Go left do { pos.add(side.left); pos.toBlock(bp); } while(override.apply(pos, world.getBlockState(bp).getBlock() == BlockRegistry.SCREEN_BLOCk.get())); pos.add(side.right); //Go down do { pos.add(side.down); pos.toBlock(bp); } while(override.apply(pos, world.getBlockState(bp).getBlock() == BlockRegistry.SCREEN_BLOCk.get())); pos.add(side.up); } //Origin stays constant public static Vector2i measure(LevelAccessor world, Vector3i origin, BlockSide side) { Vector2i ret = new Vector2i(); Vector3i pos = origin.clone(); BlockPos.MutableBlockPos bp = new BlockPos.MutableBlockPos(); pos.toBlock(bp); //Go up do { pos.add(side.up); pos.toBlock(bp); ret.y++; } while(world.getBlockState(bp).getBlock() == BlockRegistry.SCREEN_BLOCk.get()); pos.add(side.down); //Go right do { pos.add(side.right); pos.toBlock(bp); ret.x++; } while(world.getBlockState(bp).getBlock() == BlockRegistry.SCREEN_BLOCk.get()); return ret; } //Origin and size stays constant. //Returns null if structure is okay, otherwise the erroring block pos. public static Vector3i check(LevelAccessor world, Vector3i origin, Vector2i size, BlockSide side) { Vector3i pos = origin.clone(); BlockPos.MutableBlockPos bp = new BlockPos.MutableBlockPos(); //Check inner for(int y = 0; y < size.y; y++) { for(int x = 0; x < size.x; x++) { pos.toBlock(bp); if(!(world.getBlockState(bp).getBlock() == BlockRegistry.SCREEN_BLOCk.get())) return pos; //Hole pos.add(side.forward); pos.toBlock(bp); if(world.getBlockState(bp).getBlock() == BlockRegistry.SCREEN_BLOCk.get()) return pos; //Back should be empty pos.addMul(side.backward, 2); pos.toBlock(bp); if(world.getBlockState(bp).getBlock() == BlockRegistry.SCREEN_BLOCk.get()) return pos; //Front should be empty pos.add(side.forward); pos.add(side.right); } pos.addMul(side.left, size.x); pos.add(side.up); } //Check left edge pos.set(origin); pos.add(side.left); for(int y = 0; y < size.y; y++) { pos.toBlock(bp); if(world.getBlockState(bp).getBlock() == BlockRegistry.SCREEN_BLOCk.get()) return pos; //Left edge should be empty pos.add(side.up); } //Check right edge pos.set(origin); pos.addMul(side.right, size.x); for(int y = 0; y < size.y; y++) { pos.toBlock(bp); if(world.getBlockState(bp).getBlock() == BlockRegistry.SCREEN_BLOCk.get()) return pos; //Left edge should be empty pos.add(side.up); } //Check bottom edge pos.set(origin); pos.add(side.down); for(int x = 0; x < size.x; x++) { pos.toBlock(bp); if(world.getBlockState(bp).getBlock() == BlockRegistry.SCREEN_BLOCk.get()) return pos; //Left edge should be empty pos.add(side.right); } //Check top edge pos.set(origin); pos.addMul(side.up, size.y); for(int x = 0; x < size.x; x++) { pos.toBlock(bp); if(world.getBlockState(bp).getBlock() == BlockRegistry.SCREEN_BLOCk.get()) return pos; //Left edge should be empty pos.add(side.right); } //All good. return null; } }