diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 4f78f52c1..f37358666 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -274,7 +274,7 @@ e8b0a401c10d1ba67ed71ba31bd5f9bc28571b65 assets\create\blockstates\powered_toggl c29213b77ac0c78d8979c5f6188d2b265696f9b9 assets\create\blockstates\redstone_link.json e2990fe70ad5d10437a376e70e167d1856277cc1 assets\create\blockstates\rope.json e14d5f7252105934295b4e156ec0e6d62d3d6b1c assets\create\blockstates\rope_pulley.json -e069278f8fb93cd4bb6afab3848e6f1560a04303 assets\create\blockstates\rotation_chassis.json +d42b4ead9307a83e2a106cfa440572575e8664b2 assets\create\blockstates\rotation_chassis.json cc4cf3420fa290cb844f9cf4dfdd836aa9b70500 assets\create\blockstates\rotation_speed_controller.json 56b63575c87065bc82eb9410175c501cdf959c66 assets\create\blockstates\saw.json 36592a6542332b35445931e8e9531adf786b63ba assets\create\blockstates\schematicannon.json @@ -324,7 +324,7 @@ c60c3115fd6eeaa3a696428a87a74d184ab7d62d assets\create\blockstates\weathered_lim 7f39521b211441f5c3e06d60c5978cebe16cacfb assets\create\blockstates\zinc_block.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets\create\blockstates\zinc_ore.json efa942851f247891194d2c6ecdd8724a23b05aa0 assets\create\lang\en_ud.json -fe4c49a84016a3861a86e116df2c7603d6d4b91f assets\create\lang\en_us.json +adb6af4aa68bac360242e78b9f883d94059b1df8 assets\create\lang\en_us.json 846200eb548d3bfa2e77b41039de159b4b6cfb45 assets\create\models\block\acacia_window.json 1930fa3a3c98d53dd19e4ee7f55bc27fd47aa281 assets\create\models\block\acacia_window_pane_noside.json 1763ea2c9b981d187f5031ba608f3d5d3be3986a assets\create\models\block\acacia_window_pane_noside_alt.json @@ -1369,7 +1369,7 @@ e4d0fe35d3441a5815bd4e1357329b284e63ecd8 data\create\loot_tables\blocks\fancy_we f37526c092c645045c22674dea6c7b1ec503c9c3 data\create\loot_tables\blocks\flywheel.json 8fbd865f350c615031ec3f56eb98b51ce3008de3 data\create\loot_tables\blocks\framed_glass.json 44c8bc7271fa367ff052bef242e1ae26fb435175 data\create\loot_tables\blocks\framed_glass_pane.json -205f5899101262f31f5c1a88bb7d954918d08d04 data\create\loot_tables\blocks\funnel.json +ed895ef7dcb97ad9b00d80a4fa9c331229dd532e data\create\loot_tables\blocks\funnel.json 4063880eda871fe63a4eb549a19daecabce849e5 data\create\loot_tables\blocks\furnace_engine.json 1070cba1c0f46cf7ebe31089f35333f5eadda6e4 data\create\loot_tables\blocks\gabbro.json 0356e003d8890d31b89d0ad98e32aae892da71f9 data\create\loot_tables\blocks\gabbro_bricks.json @@ -1419,8 +1419,8 @@ cb315814960850b5080598b89ee94c833b5048f7 data\create\loot_tables\blocks\limeston 8db1e3f0dac48b91a4839206a7d5a88cef415fdc data\create\loot_tables\blocks\limestone_cobblestone_stairs.json 92fb16606f289ad33860270d098fad2522b24e09 data\create\loot_tables\blocks\limestone_cobblestone_wall.json 371115e5ceb08c07a9ab2371509960c31e0baa8a data\create\loot_tables\blocks\limestone_pillar.json -dac789cf53b00eed34308848b5e267b7ccec090c data\create\loot_tables\blocks\linked_extractor.json -7af5a13c9e10903b11732fbc01ae3299328216f0 data\create\loot_tables\blocks\linked_transposer.json +205f5899101262f31f5c1a88bb7d954918d08d04 data\create\loot_tables\blocks\linked_extractor.json +205f5899101262f31f5c1a88bb7d954918d08d04 data\create\loot_tables\blocks\linked_transposer.json 90ddf7b5c3b61758a4ad12a1e6ef16fe6ebf7794 data\create\loot_tables\blocks\mechanical_bearing.json e93872a90e4f4642a003539e7db28fdacfdcd114 data\create\loot_tables\blocks\mechanical_crafter.json b12efeeef5682966016ce6ea2d171eecd33d9667 data\create\loot_tables\blocks\mechanical_mixer.json diff --git a/src/generated/resources/data/create/loot_tables/blocks/funnel.json b/src/generated/resources/data/create/loot_tables/blocks/funnel.json index 78793172c..34ac7539d 100644 --- a/src/generated/resources/data/create/loot_tables/blocks/funnel.json +++ b/src/generated/resources/data/create/loot_tables/blocks/funnel.json @@ -6,7 +6,7 @@ "entries": [ { "type": "minecraft:item", - "name": "minecraft:air" + "name": "create:funnel" } ], "conditions": [ diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 33f957fe8..2a8e598bd 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -13,6 +13,7 @@ import com.simibubi.create.content.contraptions.components.actors.HarvesterBlock import com.simibubi.create.content.contraptions.components.actors.PloughBlock; import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceBlock; import com.simibubi.create.content.contraptions.components.clock.CuckooClockBlock; +import com.simibubi.create.content.contraptions.components.crafter.CrafterCTBehaviour; import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterBlock; import com.simibubi.create.content.contraptions.components.crank.HandCrankBlock; import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelBlock; @@ -553,6 +554,7 @@ public class AllBlocks { .initialProperties(SharedProperties::softMetal) .blockstate(BlockStateGen.horizontalBlockProvider(true)) .transform(StressConfigDefaults.setImpact(2.0)) + .transform(CreateRegistrate.connectedTextures(new CrafterCTBehaviour())) .addLayer(() -> RenderType::getCutoutMipped) .item() .transform(customItemModel()) diff --git a/src/main/java/com/simibubi/create/CreateClient.java b/src/main/java/com/simibubi/create/CreateClient.java index f57d63885..2e95018d5 100644 --- a/src/main/java/com/simibubi/create/CreateClient.java +++ b/src/main/java/com/simibubi/create/CreateClient.java @@ -15,6 +15,7 @@ import com.simibubi.create.foundation.ResourceReloadHandler; import com.simibubi.create.foundation.block.render.CustomBlockModels; import com.simibubi.create.foundation.block.render.SpriteShifter; import com.simibubi.create.foundation.item.IHaveCustomItemModel; +import com.simibubi.create.foundation.tileEntity.behaviour.edgeInteraction.EdgeInteractionRenderer; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer; import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkRenderer; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueRenderer; @@ -92,6 +93,7 @@ public class CreateClient { LinkRenderer.tick(); ScrollValueRenderer.tick(); ChassisRangeDisplay.tick(); + EdgeInteractionRenderer.tick(); outliner.tickOutlines(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/ConnectedInputHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/ConnectedInputHandler.java index 2923d1da6..186b1bd1f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/ConnectedInputHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/ConnectedInputHandler.java @@ -12,117 +12,40 @@ import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; -import org.apache.commons.lang3.tuple.Pair; - import com.google.common.base.Predicates; import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.utility.RaycastHelper; -import com.simibubi.create.foundation.utility.VecHelper; -import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.NBTUtil; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.ActionResultType; import net.minecraft.util.Direction; -import net.minecraft.util.Hand; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraftforge.common.util.Constants.NBT; -import net.minecraftforge.event.entity.player.PlayerInteractEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.LogicalSide; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.wrapper.CombinedInvWrapper; -@EventBusSubscriber public class ConnectedInputHandler { - @SubscribeEvent - public static void onBlockActivated(PlayerInteractEvent.RightClickBlock event) { - World world = event.getWorld(); - BlockPos pos = event.getPos(); - PlayerEntity player = event.getPlayer(); - Hand hand = event.getHand(); - ItemStack heldItem = player.getHeldItem(hand); - - if (player.isSneaking()) - return; - if (!AllItems.WRENCH.typeOf(heldItem)) - return; - BlockState blockState = world.getBlockState(pos); - if (!AllBlocks.MECHANICAL_CRAFTER.has(blockState)) - return; - - BlockRayTraceResult ray = RaycastHelper.rayTraceRange(world, player, 10); - if (ray == null) - return; - if (ray.getFace() == blockState.get(MechanicalCrafterBlock.HORIZONTAL_FACING)) - return; - - Direction activatedDirection = getActivatedDirection(world, pos, ray.getFace(), ray.getHitVec()); - if (activatedDirection != null) { - if (event.getSide() != LogicalSide.CLIENT) - toggleConnection(world, pos, pos.offset(activatedDirection)); - event.setCanceled(true); - event.setCancellationResult(ActionResultType.SUCCESS); - world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, SoundCategory.BLOCKS, .25f, .1f); - } - } - - public static List> getConnectiveSides(World world, BlockPos pos, Direction face) { - List> sides = new ArrayList<>(6); + public static boolean shouldConnect(World world, BlockPos pos, Direction face, Direction direction) { BlockState refState = world.getBlockState(pos); + if (!refState.has(HORIZONTAL_FACING)) + return false; Direction refDirection = refState.get(HORIZONTAL_FACING); - Vec3d faceOffset = new Vec3d(face.getDirectionVec()).scale(.5).add(VecHelper.getCenterOf(BlockPos.ZERO)); - - if (Block.hasSolidSide(world.getBlockState(pos.offset(face)), world, pos.offset(face), face.getOpposite())) - return sides; - - for (Direction direction : Direction.values()) { - if (direction.getAxis() == face.getAxis()) - continue; - if (direction.getAxis() == refDirection.getAxis()) - continue; - BlockPos neighbourPos = pos.offset(direction); - BlockState neighbour = world.getBlockState(neighbourPos); - if (!AllBlocks.MECHANICAL_CRAFTER.has(neighbour)) - continue; - if (refDirection != neighbour.get(HORIZONTAL_FACING)) - continue; - if (Block.hasSolidSide(world.getBlockState(neighbourPos.offset(face)), world, neighbourPos.offset(face), - face.getOpposite())) - continue; - - Vec3d bbPos = new Vec3d(direction.getDirectionVec()).scale(.5).add(faceOffset); - sides.add(Pair.of(direction, bbPos)); - } - - return sides; - } - - public static Direction getActivatedDirection(World world, BlockPos pos, Direction face, Vec3d hit) { - Vec3d localHit = hit.subtract(pos.getX(), pos.getY(), pos.getZ()); - for (Pair pair : getConnectiveSides(world, pos, face)) { - Vec3d bbPos = pair.getRight(); - AxisAlignedBB bb = new AxisAlignedBB(bbPos, bbPos).grow(1 / 6f); - if (bb.contains(localHit)) - return pair.getKey(); - } - return null; + if (direction.getAxis() == refDirection.getAxis()) + return false; + if (face == refDirection) + return false; + BlockState neighbour = world.getBlockState(pos.offset(direction)); + if (!AllBlocks.MECHANICAL_CRAFTER.has(neighbour)) + return false; + if (refDirection != neighbour.get(HORIZONTAL_FACING)) + return false; + return true; } public static void toggleConnection(World world, BlockPos pos, BlockPos pos2) { @@ -132,14 +55,17 @@ public class ConnectedInputHandler { if (crafter1 == null || crafter2 == null) return; - BlockPos controllerPos1 = crafter1.getPos().add(crafter1.input.data.get(0)); - BlockPos controllerPos2 = crafter2.getPos().add(crafter2.input.data.get(0)); + BlockPos controllerPos1 = crafter1.getPos() + .add(crafter1.input.data.get(0)); + BlockPos controllerPos2 = crafter2.getPos() + .add(crafter2.input.data.get(0)); if (controllerPos1.equals(controllerPos2)) { MechanicalCrafterTileEntity controller = CrafterHelper.getCrafter(world, controllerPos1); - Set positions = - controller.input.data.stream().map(l -> controllerPos1.add(l)).collect(Collectors.toSet()); + Set positions = controller.input.data.stream() + .map(l -> controllerPos1.add(l)) + .collect(Collectors.toSet()); List frontier = new LinkedList<>(); List splitGroup = new ArrayList<>(); @@ -195,17 +121,20 @@ public class ConnectedInputHandler { } public static void connectControllers(World world, MechanicalCrafterTileEntity crafter1, - MechanicalCrafterTileEntity crafter2) { + MechanicalCrafterTileEntity crafter2) { crafter1.input.data.forEach(offset -> { - BlockPos connectedPos = crafter1.getPos().add(offset); - modifyAndUpdate(world, connectedPos, input -> {}); + BlockPos connectedPos = crafter1.getPos() + .add(offset); + modifyAndUpdate(world, connectedPos, input -> { + }); }); crafter2.input.data.forEach(offset -> { if (offset.equals(BlockPos.ZERO)) return; - BlockPos connectedPos = crafter2.getPos().add(offset); + BlockPos connectedPos = crafter2.getPos() + .add(offset); modifyAndUpdate(world, connectedPos, input -> { input.attachTo(crafter1.getPos(), connectedPos); crafter1.input.data.add(BlockPos.ZERO.subtract(input.data.get(0))); @@ -251,8 +180,11 @@ public class ConnectedInputHandler { return input.getItemHandler(world, controllerPos); } - List list = data.stream().map(l -> CrafterHelper.getCrafter(world, pos.add(l))) - .filter(Predicates.notNull()).map(crafter -> crafter.inventory).collect(Collectors.toList()); + List list = data.stream() + .map(l -> CrafterHelper.getCrafter(world, pos.add(l))) + .filter(Predicates.notNull()) + .map(crafter -> crafter.inventory) + .collect(Collectors.toList()); return new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); } @@ -266,7 +198,8 @@ public class ConnectedInputHandler { public void read(CompoundNBT nbt) { isController = nbt.getBoolean("Controller"); data.clear(); - nbt.getList("Data", NBT.TAG_COMPOUND).forEach(inbt -> data.add(NBTUtil.readBlockPos((CompoundNBT) inbt))); + nbt.getList("Data", NBT.TAG_COMPOUND) + .forEach(inbt -> data.add(NBTUtil.readBlockPos((CompoundNBT) inbt))); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/ConnectedInputRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/ConnectedInputRenderer.java deleted file mode 100644 index 91eac5084..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/ConnectedInputRenderer.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.simibubi.create.content.contraptions.components.crafter; - -import org.apache.commons.lang3.tuple.Pair; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.TessellatorHelper; - -import net.minecraft.block.BlockState; -import net.minecraft.client.Minecraft; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Direction; -import net.minecraft.util.Hand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.RayTraceResult.Type; -import net.minecraft.util.math.Vec3d; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.DrawHighlightEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; - -@EventBusSubscriber(value = Dist.CLIENT) -public class ConnectedInputRenderer { - - @SubscribeEvent - public static void renderHighlight(DrawHighlightEvent event) { - RayTraceResult target = event.getTarget(); - if (!(target instanceof BlockRayTraceResult)) - return; - - BlockRayTraceResult result = (BlockRayTraceResult) target; - ClientWorld world = Minecraft.getInstance().world; - BlockPos pos = result.getPos(); - BlockState blockState = world.getBlockState(pos); - PlayerEntity player = Minecraft.getInstance().player; - ItemStack heldItem = player.getHeldItem(Hand.MAIN_HAND); - Direction face = result.getFace(); - - if (player.isSneaking()) - return; - if (!AllItems.WRENCH.typeOf(heldItem)) - return; - if (!AllBlocks.MECHANICAL_CRAFTER.has(blockState)) - return; - if (target.getType() != Type.BLOCK) - return; - if (face == blockState.get(MechanicalCrafterBlock.HORIZONTAL_FACING)) - return; - - TessellatorHelper.prepareForDrawing(); - RenderSystem.translated(pos.getX(), pos.getY(), pos.getZ()); - Direction activatedDirection = ConnectedInputHandler.getActivatedDirection(world, pos, face, - result.getHitVec()); - - for (Pair pair : ConnectedInputHandler.getConnectiveSides(world, pos, face)) { - - int zRot = face == Direction.UP ? 90 : face == Direction.DOWN ? 270 : 0; - float yRot = AngleHelper.horizontalAngle(face.getOpposite()); - Vec3d rotation = new Vec3d(0, yRot, zRot); -// -// GlHelper.renderTransformed(pair.getValue(), rotation, .5f, () -> { -// -// String label = "Connect / Disconnect";// Lang.translate("crafter.connect"); -// AxisAlignedBB bb = new AxisAlignedBB(Vec3d.ZERO, Vec3d.ZERO).grow(1/3f); -// ValueBox box = new ValueBox(label, bb, pos); -// box.withColors(0x018383, 0x42e6a4).offsetLabel(new Vec3d(10, 0, 0)); -// ValueBoxRenderer.renderBox(box, activatedDirection == pair.getKey()); - -// }); - } - - TessellatorHelper.cleanUpAfterDrawing(); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterTileEntity.java index 3692ca43e..a1f9c8487 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterTileEntity.java @@ -9,6 +9,7 @@ import java.util.List; import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.components.crafter.ConnectedInputHandler.ConnectedInput; @@ -16,6 +17,7 @@ import com.simibubi.create.content.contraptions.components.crafter.MechanicalCra import com.simibubi.create.content.contraptions.components.crafter.RecipeGridHandler.GroupedItems; import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.edgeInteraction.EdgeInteractionBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InsertingBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InventoryManagementBehaviour.Attachments; import com.simibubi.create.foundation.utility.VecHelper; @@ -81,6 +83,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { protected GroupedItems groupedItemsBeforeCraft; // for rendering on client private InsertingBehaviour inserting; + private EdgeInteractionBehaviour connectivity; public MechanicalCrafterTileEntity() { super(AllTileEntities.MECHANICAL_CRAFTER.type); @@ -93,7 +96,11 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { public void addBehaviours(List behaviours) { super.addBehaviours(behaviours); inserting = new InsertingBehaviour(this, Attachments.toward(this::getTargetFacing)); + connectivity = new EdgeInteractionBehaviour(this, ConnectedInputHandler::toggleConnection) + .connectivity(ConnectedInputHandler::shouldConnect) + .require(AllItems.WRENCH.get()); behaviours.add(inserting); + behaviours.add(connectivity); } public void blockChanged() { @@ -153,7 +160,8 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { groupedItemsBeforeCraft = before; if (phaseBefore == Phase.EXPORTING && phase == Phase.WAITING) { Direction facing = getBlockState().get(MechanicalCrafterBlock.HORIZONTAL_FACING); - Vec3d vec = new Vec3d(facing.getDirectionVec()).scale(.75).add(VecHelper.getCenterOf(pos)); + Vec3d vec = new Vec3d(facing.getDirectionVec()).scale(.75) + .add(VecHelper.getCenterOf(pos)); Direction targetDirection = MechanicalCrafterBlock.getTargetDirection(getBlockState()); vec = vec.add(new Vec3d(targetDirection.getDirectionVec()).scale(1)); world.addParticle(ParticleTypes.CRIT, vec.x, vec.y, vec.z, 0, 0, 0); @@ -169,7 +177,8 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { phase = Phase.IDLE; String name = compound.getString("Phase"); for (Phase phase : Phase.values()) - if (phase.name().equals(name)) + if (phase.name() + .equals(name)) this.phase = phase; countDown = compound.getInt("CountDown"); covered = compound.getBoolean("Cover"); @@ -211,10 +220,12 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { if (result != null) { List containers = new ArrayList<>(); - groupedItems.grid.values().forEach(stack -> { - if (stack.hasContainerItem()) - containers.add(stack.getContainerItem().copy()); - }); + groupedItems.grid.values() + .forEach(stack -> { + if (stack.hasContainerItem()) + containers.add(stack.getContainerItem() + .copy()); + }); groupedItems = new GroupedItems(result); for (int i = 0; i < containers.size(); i++) { @@ -266,9 +277,13 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { Direction facing = getBlockState().get(MechanicalCrafterBlock.HORIZONTAL_FACING); float progress = countDown / 2000f; Vec3d facingVec = new Vec3d(facing.getDirectionVec()); - Vec3d vec = facingVec.scale(.65).add(VecHelper.getCenterOf(pos)); + Vec3d vec = facingVec.scale(.65) + .add(VecHelper.getCenterOf(pos)); Vec3d offset = VecHelper.offsetRandomly(Vec3d.ZERO, world.rand, .125f) - .mul(VecHelper.planeByNormal(facingVec)).normalize().scale(progress * .5f).add(vec); + .mul(VecHelper.planeByNormal(facingVec)) + .normalize() + .scale(progress * .5f) + .add(vec); if (progress > .5f) world.addParticle(ParticleTypes.CRIT, offset.x, offset.y, offset.z, 0, 0, 0); @@ -279,11 +294,13 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { for (int i = 0; i < 10; i++) { Vec3d randVec = VecHelper.offsetRandomly(Vec3d.ZERO, world.rand, .125f) - .mul(VecHelper.planeByNormal(facingVec)).normalize().scale(.25f); + .mul(VecHelper.planeByNormal(facingVec)) + .normalize() + .scale(.25f); Vec3d offset2 = randVec.add(vec); randVec = randVec.scale(.35f); world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), offset2.x, offset2.y, - offset2.z, randVec.x, randVec.y, randVec.z); + offset2.z, randVec.x, randVec.y, randVec.z); } } } @@ -362,10 +379,13 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { public void eject() { BlockState blockState = getBlockState(); boolean present = AllBlocks.MECHANICAL_CRAFTER.has(blockState); - Vec3d vec = present ? new Vec3d(blockState.get(HORIZONTAL_FACING).getDirectionVec()).scale(.75f) : Vec3d.ZERO; - Vec3d ejectPos = VecHelper.getCenterOf(pos).add(vec); + Vec3d vec = present ? new Vec3d(blockState.get(HORIZONTAL_FACING) + .getDirectionVec()).scale(.75f) : Vec3d.ZERO; + Vec3d ejectPos = VecHelper.getCenterOf(pos) + .add(vec); groupedItems.grid.forEach((pair, stack) -> dropItem(ejectPos, stack)); - if (!inventory.getStackInSlot(0).isEmpty()) + if (!inventory.getStackInSlot(0) + .isEmpty()) dropItem(ejectPos, inventory.getStackInSlot(0)); phase = Phase.IDLE; groupedItems = new GroupedItems(); @@ -391,7 +411,8 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { } public boolean craftingItemPresent() { - return !inventory.getStackInSlot(0).isEmpty() || covered; + return !inventory.getStackInSlot(0) + .isEmpty() || covered; } protected void checkCompletedRecipe() { @@ -410,7 +431,8 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { phase = Phase.ACCEPTING; groupedItems = new GroupedItems(inventory.getStackInSlot(0)); inventory.setStackInSlot(0, ItemStack.EMPTY); - if (RecipeGridHandler.getPrecedingCrafters(this).isEmpty()) { + if (RecipeGridHandler.getPrecedingCrafters(this) + .isEmpty()) { phase = Phase.ASSEMBLING; countDown = 500; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFilterSlot.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFilterSlot.java index f70fc3bfc..482228913 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFilterSlot.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFilterSlot.java @@ -13,7 +13,7 @@ import net.minecraft.util.math.Vec3d; public class DeployerFilterSlot extends ValueBoxTransform { @Override - protected Vec3d getLocation(BlockState state) { + protected Vec3d getLocalOffset(BlockState state) { Direction facing = state.get(DeployerBlock.FACING); Vec3d vec = VecHelper.voxelSpace(8f, 13.5f, 11.5f); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawFilterSlot.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawFilterSlot.java index bfef3be6b..404d8ec82 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawFilterSlot.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawFilterSlot.java @@ -11,7 +11,7 @@ import net.minecraft.util.math.Vec3d; public class SawFilterSlot extends ValueBoxTransform { @Override - protected Vec3d getLocation(BlockState state) { + protected Vec3d getLocalOffset(BlockState state) { if (state.get(SawBlock.FACING) != Direction.UP) return null; Vec3d x = VecHelper.voxelSpace(8f, 12.5f, 12.25f); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/DirectionalExtenderScrollOptionSlot.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/DirectionalExtenderScrollOptionSlot.java index 3077cda11..0b63e5f23 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/DirectionalExtenderScrollOptionSlot.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/DirectionalExtenderScrollOptionSlot.java @@ -19,8 +19,8 @@ public class DirectionalExtenderScrollOptionSlot extends CenteredSideValueBoxTra } @Override - protected Vec3d getLocation(BlockState state) { - return super.getLocation(state) + protected Vec3d getLocalOffset(BlockState state) { + return super.getLocalOffset(state) .add(new Vec3d(state.get(BlockStateProperties.FACING).getDirectionVec()).scale(-2 / 16f)); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/observer/BeltObserverFilterSlot.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/observer/BeltObserverFilterSlot.java index a94328b0d..8feb06955 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/observer/BeltObserverFilterSlot.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/belts/observer/BeltObserverFilterSlot.java @@ -14,7 +14,7 @@ public class BeltObserverFilterSlot extends ValueBoxTransform { Vec3d position = VecHelper.voxelSpace(8f, 14.5f, 16f); @Override - protected Vec3d getLocation(BlockState state) { + protected Vec3d getLocalOffset(BlockState state) { return rotateHorizontally(state, position); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterScrollSlot.java b/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterScrollSlot.java index 97e4ef07e..da4114ae8 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterScrollSlot.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterScrollSlot.java @@ -12,7 +12,7 @@ import net.minecraft.util.math.Vec3d; public class AdjustableRepeaterScrollSlot extends ValueBoxTransform { @Override - protected Vec3d getLocation(BlockState state) { + protected Vec3d getLocalOffset(BlockState state) { return VecHelper.voxelSpace(8, 3f, 8); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/extractor/ExtractorSlots.java b/src/main/java/com/simibubi/create/content/logistics/block/extractor/ExtractorSlots.java index f14289c90..78afa5fb4 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/extractor/ExtractorSlots.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/extractor/ExtractorSlots.java @@ -22,7 +22,7 @@ public class ExtractorSlots { Vec3d offsetForDownward = VecHelper.voxelSpace(8f, 1.85f, 3.5f); @Override - protected Vec3d getLocation(BlockState state) { + protected Vec3d getLocalOffset(BlockState state) { Vec3d location = offsetForHorizontal; if (state.getBlock() instanceof TransposerBlock) location = location.add(0, 2 / 16f, 0); @@ -52,7 +52,7 @@ public class ExtractorSlots { Vec3d offsetForDownward = VecHelper.voxelSpace(10f, 2f, 11.5f); @Override - protected Vec3d getLocation(BlockState state) { + protected Vec3d getLocalOffset(BlockState state) { Vec3d location = offsetForHorizontal; if (state.getBlock() instanceof TransposerBlock) location = location.add(0, 2 / 16f, 0); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelFilterSlot.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelFilterSlot.java index ca8c83f7e..4302d30db 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelFilterSlot.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelFilterSlot.java @@ -20,7 +20,7 @@ public class FunnelFilterSlot extends ValueBoxTransform { Vec3d offsetForDownward = VecHelper.voxelSpace(8f, 2.5f, 2f); @Override - protected Vec3d getLocation(BlockState state) { + protected Vec3d getLocalOffset(BlockState state) { Vec3d vec = offsetForHorizontal; float yRot = AngleHelper.horizontalAngle(state.get(ExtractorBlock.HORIZONTAL_FACING)); if (AttachedLogisticalBlock.isVertical(state)) diff --git a/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateTileEntity.java index 4163d7545..6b58c666c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateTileEntity.java @@ -94,7 +94,7 @@ public class CreativeCrateTileEntity extends CrateTileEntity { } @Override - protected Vec3d getLocation(BlockState state) { + protected Vec3d getLocalOffset(BlockState state) { return new Vec3d(0.5, 13 / 16d, 0.5); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkFrequencySlot.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkFrequencySlot.java index 5def8b916..0e0e8b7e5 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkFrequencySlot.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkFrequencySlot.java @@ -20,7 +20,7 @@ public class RedstoneLinkFrequencySlot extends ValueBoxTransform.Dual { Vec3d vertical = VecHelper.voxelSpace(10f, 2.5f, 5.5f); @Override - protected Vec3d getLocation(BlockState state) { + protected Vec3d getLocalOffset(BlockState state) { Direction facing = state.get(RedstoneLinkBlock.FACING); Vec3d location = vertical; diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java index 0d1d2df50..f16fe657b 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java @@ -73,21 +73,23 @@ public class ValueBox extends ChasingAABBOutline { @Override public void render(MatrixStack ms, IRenderTypeBuffer buffer) { + boolean hasTransform = transform != null; if (transform instanceof Sided && params.getHighlightedFace() != null) ((Sided) transform).fromSide(params.getHighlightedFace()); - if (!transform.shouldRender(blockState)) + if (hasTransform && !transform.shouldRender(blockState)) return; ms.push(); ms.translate(pos.getX(), pos.getY(), pos.getZ()); - transform.transform(blockState, ms); + if (hasTransform) + transform.transform(blockState, ms); transformNormals = ms.peek() .getNormal() .copy(); params.colored(isPassive ? passiveColor : highlightColor); super.render(ms, buffer); - float fontScale = -1 / 64f; + float fontScale = hasTransform ? -transform.getFontScale() : -1 / 64f; ms.scale(fontScale, fontScale, fontScale); ms.push(); diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxTransform.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxTransform.java index 9097e6a87..c8916363b 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxTransform.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxTransform.java @@ -19,19 +19,19 @@ public abstract class ValueBoxTransform { protected float scale = getScale(); - protected abstract Vec3d getLocation(BlockState state); + protected abstract Vec3d getLocalOffset(BlockState state); protected abstract void rotate(BlockState state, MatrixStack ms); public boolean testHit(BlockState state, Vec3d localHit) { - Vec3d offset = getLocation(state); + Vec3d offset = getLocalOffset(state); if (offset == null) return false; return localHit.distanceTo(offset) < scale / 2; } public void transform(BlockState state, MatrixStack ms) { - Vec3d position = getLocation(state); + Vec3d position = getLocalOffset(state); if (position == null) return; ms.translate(position.x, position.y, position.z); @@ -40,7 +40,7 @@ public abstract class ValueBoxTransform { } public boolean shouldRender(BlockState state) { - return state.getMaterial() != Material.AIR && getLocation(state) != null; + return state.getMaterial() != Material.AIR && getLocalOffset(state) != null; } protected Vec3d rotateHorizontally(BlockState state, Vec3d vec) { @@ -55,6 +55,10 @@ public abstract class ValueBoxTransform { protected float getScale() { return .4f; } + + protected float getFontScale() { + return 1 / 64f; + } public static abstract class Dual extends ValueBoxTransform { @@ -73,7 +77,7 @@ public abstract class ValueBoxTransform { } public boolean testHit(BlockState state, Vec3d localHit) { - Vec3d offset = getLocation(state); + Vec3d offset = getLocalOffset(state); if (offset == null) return false; return localHit.distanceTo(offset) < scale / 3.5f; @@ -91,7 +95,7 @@ public abstract class ValueBoxTransform { } @Override - protected Vec3d getLocation(BlockState state) { + protected Vec3d getLocalOffset(BlockState state) { Vec3d location = getSouthLocation(); location = VecHelper.rotateCentered(location, AngleHelper.horizontalAngle(direction), Axis.Y); location = VecHelper.rotateCentered(location, AngleHelper.verticalAngle(direction), Axis.Z); diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionBehaviour.java new file mode 100644 index 000000000..acc3eb9ef --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionBehaviour.java @@ -0,0 +1,55 @@ +package com.simibubi.create.foundation.tileEntity.behaviour.edgeInteraction; + +import java.util.Optional; + +import com.simibubi.create.foundation.tileEntity.SmartTileEntity; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.IBehaviourType; + +import net.minecraft.item.Item; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class EdgeInteractionBehaviour extends TileEntityBehaviour { + + public static IBehaviourType TYPE = new IBehaviourType() { + }; + + ConnectionCallback connectionCallback; + ConnectivityPredicate connectivityPredicate; + Optional requiredItem; + + public EdgeInteractionBehaviour(SmartTileEntity te, ConnectionCallback callback) { + super(te); + this.connectionCallback = callback; + requiredItem = Optional.empty(); + connectivityPredicate = (world, pos, face, face2) -> true; + } + + public EdgeInteractionBehaviour connectivity(ConnectivityPredicate pred) { + this.connectivityPredicate = pred; + return this; + } + + public EdgeInteractionBehaviour require(Item item) { + this.requiredItem = Optional.of(item); + return this; + } + + @Override + public IBehaviourType getType() { + return TYPE; + } + + @FunctionalInterface + public interface ConnectionCallback { + public void apply(World world, BlockPos clicked, BlockPos neighbour); + } + + @FunctionalInterface + public interface ConnectivityPredicate { + public boolean test(World world, BlockPos pos, Direction selectedFace, Direction connectedFace); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java new file mode 100644 index 000000000..972623a74 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java @@ -0,0 +1,110 @@ +package com.simibubi.create.foundation.tileEntity.behaviour.edgeInteraction; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.utility.RaycastHelper; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Direction; +import net.minecraft.util.Hand; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Vec3i; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber +public class EdgeInteractionHandler { + + @SubscribeEvent + public static void onBlockActivated(PlayerInteractEvent.RightClickBlock event) { + World world = event.getWorld(); + BlockPos pos = event.getPos(); + PlayerEntity player = event.getPlayer(); + Hand hand = event.getHand(); + ItemStack heldItem = player.getHeldItem(hand); + + if (player.isSneaking()) + return; + EdgeInteractionBehaviour behaviour = TileEntityBehaviour.get(world, pos, EdgeInteractionBehaviour.TYPE); + if (behaviour == null) + return; + BlockRayTraceResult ray = RaycastHelper.rayTraceRange(world, player, 10); + if (ray == null) + return; + if (behaviour.requiredItem.orElse(heldItem.getItem()) != heldItem.getItem()) + return; + + Direction activatedDirection = getActivatedDirection(world, pos, ray.getFace(), ray.getHitVec(), behaviour); + if (activatedDirection == null) + return; + + if (event.getSide() != LogicalSide.CLIENT) + behaviour.connectionCallback.apply(world, pos, pos.offset(activatedDirection)); + event.setCanceled(true); + event.setCancellationResult(ActionResultType.SUCCESS); + world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, SoundCategory.BLOCKS, .25f, .1f); + } + + public static List getConnectiveSides(World world, BlockPos pos, Direction face, + EdgeInteractionBehaviour behaviour) { + List sides = new ArrayList<>(6); + if (Block.hasSolidSide(world.getBlockState(pos.offset(face)), world, pos.offset(face), face.getOpposite())) + return sides; + + for (Direction direction : Direction.values()) { + if (direction.getAxis() == face.getAxis()) + continue; + BlockPos neighbourPos = pos.offset(direction); + if (Block.hasSolidSide(world.getBlockState(neighbourPos.offset(face)), world, neighbourPos.offset(face), + face.getOpposite())) + continue; + if (!behaviour.connectivityPredicate.test(world, pos, face, direction)) + continue; + sides.add(direction); + } + + return sides; + } + + public static Direction getActivatedDirection(World world, BlockPos pos, Direction face, Vec3d hit, + EdgeInteractionBehaviour behaviour) { + for (Direction facing : getConnectiveSides(world, pos, face, behaviour)) { + AxisAlignedBB bb = getBB(pos, facing); + if (bb.contains(hit)) + return facing; + } + return null; + } + + static AxisAlignedBB getBB(BlockPos pos, Direction direction) { + AxisAlignedBB bb = new AxisAlignedBB(pos); + Vec3i vec = direction.getDirectionVec(); + int x = vec.getX(); + int y = vec.getY(); + int z = vec.getZ(); + double margin = 12 / 16f; + double absX = Math.abs(x) * margin; + double absY = Math.abs(y) * margin; + double absZ = Math.abs(z) * margin; + + bb = bb.contract(absX, absY, absZ); + bb = bb.offset(absX / 2d, absY / 2d, absZ / 2d); + bb = bb.offset(x / 2d, y / 2d, z / 2d); + bb = bb.grow(1 / 256f); + return bb; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionRenderer.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionRenderer.java new file mode 100644 index 000000000..3211ee68a --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionRenderer.java @@ -0,0 +1,93 @@ +package com.simibubi.create.foundation.tileEntity.behaviour.edgeInteraction; + +import java.util.List; + +import com.simibubi.create.AllSpecialTextures; +import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Direction; +import net.minecraft.util.Direction.AxisDirection; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; + +public class EdgeInteractionRenderer { + + public static void tick() { + Minecraft mc = Minecraft.getInstance(); + RayTraceResult target = mc.objectMouseOver; + if (target == null || !(target instanceof BlockRayTraceResult)) + return; + + BlockRayTraceResult result = (BlockRayTraceResult) target; + ClientWorld world = mc.world; + BlockPos pos = result.getPos(); + PlayerEntity player = mc.player; + ItemStack heldItem = player.getHeldItemMainhand(); + + if (player.isSneaking()) + return; + EdgeInteractionBehaviour behaviour = TileEntityBehaviour.get(world, pos, EdgeInteractionBehaviour.TYPE); + if (behaviour == null) + return; + if (behaviour.requiredItem.orElse(heldItem.getItem()) != heldItem.getItem()) + return; + + Direction face = result.getFace(); + List connectiveSides = EdgeInteractionHandler.getConnectiveSides(world, pos, face, behaviour); + if (connectiveSides.isEmpty()) + return; + + Direction closestEdge = connectiveSides.get(0); + double bestDistance = Double.MAX_VALUE; + Vec3d center = VecHelper.getCenterOf(pos); + for (Direction direction : connectiveSides) { + double distance = new Vec3d(direction.getDirectionVec()).subtract(target.getHitVec() + .subtract(center)) + .length(); + if (distance > bestDistance) + continue; + bestDistance = distance; + closestEdge = direction; + } + + AxisAlignedBB bb = EdgeInteractionHandler.getBB(pos, closestEdge); + boolean hit = bb.contains(target.getHitVec()); + + ValueBox box = new ValueBox("", bb.offset(-pos.getX(), -pos.getY(), -pos.getZ()), pos); + Vec3d textOffset = Vec3d.ZERO; + + boolean positive = closestEdge.getAxisDirection() == AxisDirection.POSITIVE; + if (positive) { + if (face.getAxis() + .isHorizontal()) { + if (closestEdge.getAxis() + .isVertical()) + textOffset = textOffset.add(0, -128, 0); + else + textOffset = textOffset.add(-128, 0, 0); + } else + textOffset = textOffset.add(-128, 0, 0); + } + + box.offsetLabel(textOffset) + .withColors(0x7A6A2C, 0xB79D64) + .passive(!hit); + + CreateClient.outliner.showValueBox("edge", box) + .lineWidth(1 / 64f) + .withFaceTexture(hit ? AllSpecialTextures.THIN_CHECKERED : null) + .highlightFace(face); + + } + +}