Place face devices directly on cables

This commit is contained in:
Shadowfacts 2021-03-07 10:38:22 -05:00
parent eb1aa6cf19
commit 9acceeae3c
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
10 changed files with 149 additions and 10 deletions

View File

@ -60,7 +60,7 @@ abstract class FaceDeviceBlock<T: DeviceBlockEntity>(settings: Settings): Device
} }
protected abstract val faceThickness: Double protected abstract val faceThickness: Double
protected abstract val faceShapes: Map<Direction, VoxelShape> abstract val faceShapes: Map<Direction, VoxelShape>
private val centerShapes: Map<Direction, VoxelShape> by lazy { private val centerShapes: Map<Direction, VoxelShape> by lazy {
mapOf( mapOf(
Direction.DOWN to createCuboidShape(6.0, faceThickness, 6.0, 10.0, 10.0, 10.0), Direction.DOWN to createCuboidShape(6.0, faceThickness, 6.0, 10.0, 10.0, 10.0),

View File

@ -24,7 +24,9 @@ import net.shadowfacts.phycon.api.Interface
import net.shadowfacts.phycon.api.NetworkCableBlock import net.shadowfacts.phycon.api.NetworkCableBlock
import net.shadowfacts.phycon.api.NetworkComponentBlock import net.shadowfacts.phycon.api.NetworkComponentBlock
import net.shadowfacts.phycon.init.PhyItems import net.shadowfacts.phycon.init.PhyItems
import net.shadowfacts.phycon.item.FaceDeviceBlockItem
import net.shadowfacts.phycon.util.CableConnection import net.shadowfacts.phycon.util.CableConnection
import net.shadowfacts.phycon.util.containsInclusive
import java.util.* import java.util.*
/** /**
@ -87,12 +89,16 @@ class CableBlock: Block(
} }
} }
override fun getPlacementState(context: ItemPlacementContext): BlockState { fun getInitialState(world: World, pos: BlockPos): BlockState {
return CONNECTIONS.entries.fold(defaultState, { acc, (dir, prop) -> return CONNECTIONS.entries.fold(defaultState, { acc, (dir, prop) ->
acc.with(prop, getConnectionStateInDirection(context.world, context.blockPos, dir)) acc.with(prop, getConnectionStateInDirection(world, pos, dir))
}) })
} }
override fun getPlacementState(context: ItemPlacementContext): BlockState {
return getInitialState(context.world, context.blockPos)
}
override fun getStateForNeighborUpdate(state: BlockState, side: Direction, neighborState: BlockState, world: WorldAccess, blockPos_1: BlockPos, blockPos_2: BlockPos): BlockState { override fun getStateForNeighborUpdate(state: BlockState, side: Direction, neighborState: BlockState, world: WorldAccess, blockPos_1: BlockPos, blockPos_2: BlockPos): BlockState {
val prop = CONNECTIONS[side] val prop = CONNECTIONS[side]
val current = state[prop] val current = state[prop]
@ -141,8 +147,7 @@ class CableBlock: Block(
if (player.getStackInHand(hand).item == PhyItems.SCREWDRIVER) { if (player.getStackInHand(hand).item == PhyItems.SCREWDRIVER) {
val hitPos = Vec3d(hitResult.pos.x - pos.x, hitResult.pos.y - pos.y, hitResult.pos.z - pos.z) val hitPos = Vec3d(hitResult.pos.x - pos.x, hitResult.pos.y - pos.y, hitResult.pos.z - pos.z)
val hitConnection = SIDE_SHAPES.entries.firstOrNull { (_, shape) -> val hitConnection = SIDE_SHAPES.entries.firstOrNull { (_, shape) ->
val box = shape.boundingBox shape.boundingBox.containsInclusive(hitPos)
hitPos.x >= box.minX && hitPos.x <= box.maxX && hitPos.y >= box.minY && hitPos.y <= box.maxY && hitPos.z >= box.minZ && hitPos.z <= box.maxZ
} }
if (hitConnection != null) { if (hitConnection != null) {
val side = hitConnection.key val side = hitConnection.key
@ -169,6 +174,10 @@ class CableBlock: Block(
return ActionResult.PASS return ActionResult.PASS
} }
override fun canReplace(state: BlockState, context: ItemPlacementContext): Boolean {
return context.stack.item is FaceDeviceBlockItem
}
override fun isTranslucent(blockState_1: BlockState?, blockView_1: BlockView?, blockPos_1: BlockPos?): Boolean { override fun isTranslucent(blockState_1: BlockState?, blockView_1: BlockView?, blockPos_1: BlockPos?): Boolean {
return true return true
} }

View File

@ -17,21 +17,22 @@ import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlock
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterBlock import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterBlock
import net.shadowfacts.phycon.block.terminal.TerminalBlock import net.shadowfacts.phycon.block.terminal.TerminalBlock
import net.shadowfacts.phycon.item.DeviceBlockItem import net.shadowfacts.phycon.item.DeviceBlockItem
import net.shadowfacts.phycon.item.FaceDeviceBlockItem
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
object PhyItems { object PhyItems {
val INTERFACE = DeviceBlockItem(PhyBlocks.INTERFACE, Item.Settings()) val INTERFACE = FaceDeviceBlockItem(PhyBlocks.INTERFACE, Item.Settings())
val TERMINAL = DeviceBlockItem(PhyBlocks.TERMINAL, Item.Settings()) val TERMINAL = DeviceBlockItem(PhyBlocks.TERMINAL, Item.Settings())
val SWITCH = BlockItem(PhyBlocks.SWITCH, Item.Settings()) val SWITCH = BlockItem(PhyBlocks.SWITCH, Item.Settings())
val CABLE = BlockItem(PhyBlocks.CABLE, Item.Settings()) val CABLE = BlockItem(PhyBlocks.CABLE, Item.Settings())
val EXTRACTOR = DeviceBlockItem(PhyBlocks.EXTRACTOR, Item.Settings()) val EXTRACTOR = DeviceBlockItem(PhyBlocks.EXTRACTOR, Item.Settings())
val INSERTER = DeviceBlockItem(PhyBlocks.INSERTER, Item.Settings()) val INSERTER = DeviceBlockItem(PhyBlocks.INSERTER, Item.Settings())
val MINER = DeviceBlockItem(PhyBlocks.MINER, Item.Settings()) val MINER = DeviceBlockItem(PhyBlocks.MINER, Item.Settings())
val REDSTONE_CONTROLLER = DeviceBlockItem(PhyBlocks.REDSTONE_CONTROLLER, Item.Settings()) val REDSTONE_CONTROLLER = FaceDeviceBlockItem(PhyBlocks.REDSTONE_CONTROLLER, Item.Settings())
val REDSTONE_EMITTER = DeviceBlockItem(PhyBlocks.REDSTONE_EMITTER, Item.Settings()) val REDSTONE_EMITTER = FaceDeviceBlockItem(PhyBlocks.REDSTONE_EMITTER, Item.Settings())
val SCREWDRIVER = ScrewdriverItem() val SCREWDRIVER = ScrewdriverItem()
val CONSOLE = ConsoleItem() val CONSOLE = ConsoleItem()

View File

@ -12,7 +12,7 @@ import net.shadowfacts.phycon.util.text
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class DeviceBlockItem(block: DeviceBlock<*>, settings: Settings = Settings()): BlockItem(block, settings) { open class DeviceBlockItem(block: DeviceBlock<*>, settings: Settings = Settings()): BlockItem(block, settings) {
override fun appendTooltip(stack: ItemStack, world: World?, list: MutableList<Text>, context: TooltipContext) { override fun appendTooltip(stack: ItemStack, world: World?, list: MutableList<Text>, context: TooltipContext) {
val beTag = stack.getSubTag("BlockEntityTag") val beTag = stack.getSubTag("BlockEntityTag")

View File

@ -0,0 +1,40 @@
package net.shadowfacts.phycon.item
import net.minecraft.block.BlockState
import net.minecraft.item.ItemPlacementContext
import net.minecraft.util.math.Direction
import net.shadowfacts.phycon.block.FaceDeviceBlock
import net.shadowfacts.phycon.block.cable.CableBlock
import net.shadowfacts.phycon.init.PhyBlocks
import net.shadowfacts.phycon.util.CableConnection
/**
* @author shadowfacts
*/
class FaceDeviceBlockItem(block: FaceDeviceBlock<*>, settings: Settings = Settings()): DeviceBlockItem(block, settings) {
override fun getPlacementState(context: ItemPlacementContext): BlockState? {
val hitState = context.world.getBlockState(context.blockPos)
if (hitState.block == PhyBlocks.CABLE) {
val hitBlockEdge = context.hitPos.getComponentAlongAxis(context.side.axis) % 1 == 0.0
val placementSide = if (hitBlockEdge) context.side.opposite else context.side
if (hitState[CableBlock.CONNECTIONS[placementSide]] != CableConnection.ON) {
var connection = FaceDeviceBlock.FaceCableConnection.NONE
for (dir in Direction.values()) {
if (hitState[CableBlock.CONNECTIONS[dir]] == CableConnection.ON) {
connection = FaceDeviceBlock.FaceCableConnection.from(dir)
break
}
}
return block.defaultState
.with(FaceDeviceBlock.FACING, placementSide)
.with(FaceDeviceBlock.CABLE_CONNECTION, connection)
}
}
return null
}
}

View File

@ -9,9 +9,12 @@ import net.minecraft.sound.SoundCategory
import net.minecraft.sound.SoundEvents import net.minecraft.sound.SoundEvents
import net.minecraft.util.ActionResult import net.minecraft.util.ActionResult
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.math.Vec3d
import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.PhysicalConnectivity
import net.shadowfacts.phycon.block.DeviceBlock import net.shadowfacts.phycon.block.DeviceBlock
import net.shadowfacts.phycon.block.FaceDeviceBlock
import net.shadowfacts.phycon.init.PhyBlocks import net.shadowfacts.phycon.init.PhyBlocks
import net.shadowfacts.phycon.util.containsInclusive
/** /**
* @author shadowfacts * @author shadowfacts
@ -44,7 +47,21 @@ class ScrewdriverItem: Item(Settings()) {
val entity = ItemEntity(context.world, context.blockPos.x.toDouble(), context.blockPos.y.toDouble(), context.blockPos.z.toDouble(), stack) val entity = ItemEntity(context.world, context.blockPos.x.toDouble(), context.blockPos.y.toDouble(), context.blockPos.z.toDouble(), stack)
context.world.spawnEntity(entity) context.world.spawnEntity(entity)
context.world.setBlockState(context.blockPos, Blocks.AIR.defaultState, 3, 512) var newState = Blocks.AIR.defaultState
if (block is FaceDeviceBlock<*>) {
val hitInsideBlock = Vec3d(context.hitPos.x - context.blockPos.x, context.hitPos.y - context.blockPos.y, context.hitPos.z - context.blockPos.z)
val faceShape = block.faceShapes[state[FaceDeviceBlock.FACING]]!!
// if we hit the face part of block, leave the cable behind
if (faceShape.boundingBox.containsInclusive(hitInsideBlock)) {
newState = PhyBlocks.CABLE.getInitialState(context.world, context.blockPos)
} else {
val cable = ItemEntity(context.world, context.blockPos.x.toDouble(), context.blockPos.y.toDouble(), context.blockPos.z.toDouble(), ItemStack(PhyBlocks.CABLE))
context.world.spawnEntity(cable)
}
}
context.world.setBlockState(context.blockPos, newState, 3, 512)
} }
context.world.playSound(context.player, context.blockPos, SoundEvents.BLOCK_METAL_PLACE, SoundCategory.BLOCKS, 0.8f, 0.65f) context.world.playSound(context.player, context.blockPos, SoundEvents.BLOCK_METAL_PLACE, SoundCategory.BLOCKS, 0.8f, 0.65f)

View File

@ -0,0 +1,11 @@
package net.shadowfacts.phycon.util
import net.minecraft.util.math.Box
import net.minecraft.util.math.Vec3d
/**
* @author shadowfacts
*/
fun Box.containsInclusive(point: Vec3d): Boolean {
return point.x >= minX && point.x <= maxX && point.y >= minY && point.y <= maxY && point.z >= minZ && point.z <= maxZ
}

View File

@ -0,0 +1,33 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "phycon:network_interface"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "phycon:cable"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
]
}

View File

@ -14,6 +14,20 @@
"condition": "minecraft:survives_explosion" "condition": "minecraft:survives_explosion"
} }
] ]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "phycon:cable"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
} }
] ]
} }

View File

@ -14,6 +14,20 @@
"condition": "minecraft:survives_explosion" "condition": "minecraft:survives_explosion"
} }
] ]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "phycon:cable"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
} }
] ]
} }