Compare commits

...

2 Commits

13 changed files with 234 additions and 30 deletions

View File

@ -1,17 +1,8 @@
package net.shadowfacts.phycon.api; package net.shadowfacts.phycon.api;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import java.util.Set;
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
public interface NetworkCable extends NetworkComponent { public interface NetworkCable extends NetworkComponent {
Set<Direction> getNetworkConnectedSides(BlockState state, World world, BlockPos pos);
} }

View File

@ -1,7 +1,17 @@
package net.shadowfacts.phycon.api; package net.shadowfacts.phycon.api;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import java.util.Collection;
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
public interface NetworkComponent { public interface NetworkComponent {
Collection<Direction> getNetworkConnectedSides(BlockState state, World world, BlockPos pos);
} }

View File

@ -0,0 +1,19 @@
package net.shadowfacts.phycon.network
import net.minecraft.block.BlockState
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
import net.shadowfacts.phycon.block.BlockWithEntity
/**
* @author shadowfacts
*/
abstract class DeviceBlock<T: DeviceBlockEntity>(settings: Settings): BlockWithEntity<T>(settings) {
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity) {
super.onBreak(world, pos, state, player)
getBlockEntity(world, pos)!!.onBreak()
}
}

View File

@ -7,6 +7,7 @@ import net.minecraft.util.Tickable
import net.shadowfacts.phycon.api.PacketSink import net.shadowfacts.phycon.api.PacketSink
import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.api.util.MACAddress import net.shadowfacts.phycon.api.util.MACAddress
import net.shadowfacts.phycon.network.packet.DeviceRemovedPacket
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.* import java.util.*
@ -84,4 +85,8 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type), T
macAddress = MACAddress(tag.getLong("MACAddress")) macAddress = MACAddress(tag.getLong("MACAddress"))
} }
fun onBreak() {
enqueueToAll(DeviceRemovedPacket(this))
}
} }

View File

@ -4,6 +4,7 @@ import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Direction import net.minecraft.util.math.Direction
import net.minecraft.world.World import net.minecraft.world.World
import net.shadowfacts.phycon.api.NetworkCable import net.shadowfacts.phycon.api.NetworkCable
import net.shadowfacts.phycon.api.NetworkComponent
import net.shadowfacts.phycon.api.PacketSink import net.shadowfacts.phycon.api.PacketSink
import net.shadowfacts.phycon.api.PhyAttributes import net.shadowfacts.phycon.api.PhyAttributes
import java.util.* import java.util.*
@ -20,7 +21,7 @@ object NetworkUtil {
if (direction != null) { if (direction != null) {
queue.add(startPos.offset(direction)) queue.add(startPos.offset(direction))
} else { } else {
addAdjacent(queue, visited, startPos) findEdges(queue, visited, world, startPos, includeNonCables = true)
} }
while (queue.isNotEmpty()) { while (queue.isNotEmpty()) {
@ -39,10 +40,10 @@ object NetworkUtil {
return results return results
} }
private fun findEdges(queue: MutableList<BlockPos>, visited: Set<BlockPos>, world: World, pos: BlockPos) { private fun findEdges(queue: MutableList<BlockPos>, visited: Set<BlockPos>, world: World, pos: BlockPos, includeNonCables: Boolean = false) {
val state = world.getBlockState(pos) val state = world.getBlockState(pos)
val block = state.block val block = state.block
if (block is NetworkCable) { if (block is NetworkComponent && (includeNonCables || block is NetworkCable)) {
val connections = block.getNetworkConnectedSides(state, world, pos) val connections = block.getNetworkConnectedSides(state, world, pos)
for (side in connections) { for (side in connections) {
val newPos = pos.offset(side) val newPos = pos.offset(side)
@ -53,13 +54,4 @@ object NetworkUtil {
} }
} }
private fun addAdjacent(queue: MutableList<BlockPos>, visited: Set<BlockPos>, pos: BlockPos) {
for (dir in Direction.values()) {
val newPos = pos.offset(dir)
if (newPos !in visited) {
queue.add(newPos)
}
}
}
} }

View File

@ -65,7 +65,7 @@ class CableBlock: Block(Settings.of(CABLE_MATERIAL)), NetworkCable {
} }
} }
override fun getNetworkConnectedSides(state: BlockState, world: World, pos: BlockPos): Set<Direction> { override fun getNetworkConnectedSides(state: BlockState, world: World, pos: BlockPos): Collection<Direction> {
val set = EnumSet.noneOf(Direction::class.java) val set = EnumSet.noneOf(Direction::class.java)
for ((side, prop) in CONNECTIONS) { for ((side, prop) in CONNECTIONS) {
if (state[prop] == CableConnection.ON) { if (state[prop] == CableConnection.ON) {

View File

@ -5,18 +5,27 @@ import alexiil.mc.lib.attributes.AttributeProvider
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.Material import net.minecraft.block.Material
import net.minecraft.entity.EntityContext
import net.minecraft.entity.LivingEntity import net.minecraft.entity.LivingEntity
import net.minecraft.item.ItemPlacementContext import net.minecraft.item.ItemPlacementContext
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.state.StateFactory import net.minecraft.state.StateFactory
import net.minecraft.state.property.EnumProperty
import net.minecraft.state.property.Properties import net.minecraft.state.property.Properties
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos 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.BlockView
import net.minecraft.world.IWorld
import net.minecraft.world.World import net.minecraft.world.World
import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.PhysicalConnectivity
import net.shadowfacts.phycon.api.NetworkComponent import net.shadowfacts.phycon.api.NetworkComponent
import net.shadowfacts.phycon.block.BlockWithEntity import net.shadowfacts.phycon.block.BlockWithEntity
import net.shadowfacts.phycon.network.block.cable.CableBlock
import java.net.NoRouteToHostException
import java.util.*
/** /**
* @author shadowfacts * @author shadowfacts
@ -25,18 +34,61 @@ class InterfaceBlock: BlockWithEntity<InterfaceBlockEntity>(Settings.of(Material
companion object { companion object {
val ID = Identifier(PhysicalConnectivity.MODID, "network_interface") val ID = Identifier(PhysicalConnectivity.MODID, "network_interface")
val FACING = Properties.FACING val FACING = Properties.FACING
val CABLE_CONNECTION = EnumProperty.of("cable_connection", Direction::class.java)
private val SIDE_SHAPES = mapOf<Direction, VoxelShape>(
Direction.DOWN to createCuboidShape(2.0, 0.0, 2.0, 14.0, 2.0, 14.0),
Direction.UP to createCuboidShape(2.0, 14.0, 2.0, 14.0, 16.0, 14.0),
Direction.NORTH to createCuboidShape(2.0, 2.0, 0.0, 14.0, 14.0, 2.0),
Direction.SOUTH to createCuboidShape(2.0, 2.0, 14.0, 14.0, 14.0, 16.0),
Direction.WEST to createCuboidShape(0.0, 2.0, 2.0, 2.0, 14.0, 14.0),
Direction.EAST to createCuboidShape(14.0, 2.0, 2.0, 16.0, 14.0, 14.0)
)
private val CENTER_SHAPES = mapOf<Direction, VoxelShape>(
Direction.DOWN to createCuboidShape(6.0, 2.0, 6.0, 10.0, 10.0, 10.0),
Direction.UP to createCuboidShape(6.0, 6.0, 6.0, 10.0, 14.0, 10.0),
Direction.NORTH to createCuboidShape(6.0, 6.0, 2.0, 10.0, 10.0, 10.0),
Direction.SOUTH to createCuboidShape(6.0, 6.0, 6.0, 10.0, 10.0, 14.0),
Direction.WEST to createCuboidShape(2.0, 6.0, 6.0, 10.0, 10.0, 10.0),
Direction.EAST to createCuboidShape(6.0, 6.0, 6.0, 14.0, 10.0, 10.0)
)
private val shapeCache = mutableMapOf<Pair<Direction, Direction>, VoxelShape>()
fun getShape(facing: Direction, cableConnection: Direction): VoxelShape {
return shapeCache.getOrPut(facing to cableConnection) {
VoxelShapes.union(
VoxelShapes.union(SIDE_SHAPES[facing], CENTER_SHAPES[facing]),
CableBlock.SIDE_SHAPES[cableConnection]
)
}
}
}
override fun getNetworkConnectedSides(state: BlockState, world: World, pos: BlockPos): Collection<Direction> {
return EnumSet.of(state[CABLE_CONNECTION])
} }
override fun appendProperties(builder: StateFactory.Builder<Block, BlockState>) { override fun appendProperties(builder: StateFactory.Builder<Block, BlockState>) {
super.appendProperties(builder) super.appendProperties(builder)
builder.add(FACING) builder.add(FACING)
builder.add(CABLE_CONNECTION)
} }
override fun createBlockEntity(world: BlockView) = InterfaceBlockEntity() override fun createBlockEntity(world: BlockView) = InterfaceBlockEntity()
override fun getPlacementState(context: ItemPlacementContext): BlockState { override fun getPlacementState(context: ItemPlacementContext): BlockState {
val facing = if (context.player?.isSneaking == true) context.playerFacing else context.playerFacing.opposite val facing = if (context.player?.isSneaking == true) context.side.opposite else context.playerFacing.opposite
return defaultState.with(FACING, facing) val cableConnection = getCableConnectionSide(context.world, context.blockPos) ?: facing.opposite
return defaultState.with(FACING, facing).with(CABLE_CONNECTION, cableConnection)
}
private fun getCableConnectionSide(world: World, pos: BlockPos): Direction? {
for (side in Direction.values()) {
val offsetPos = pos.offset(side)
if (world.getBlockState(offsetPos).block is NetworkComponent) {
return side
}
}
return null
} }
override fun onPlaced(world: World, pos: BlockPos, state: BlockState, placer: LivingEntity?, stack: ItemStack) { override fun onPlaced(world: World, pos: BlockPos, state: BlockState, placer: LivingEntity?, stack: ItemStack) {
@ -51,8 +103,19 @@ class InterfaceBlock: BlockWithEntity<InterfaceBlockEntity>(Settings.of(Material
} }
} }
override fun getStateForNeighborUpdate(state: BlockState, side: Direction, neighborState: BlockState, world: IWorld, pos: BlockPos, neighborPos: BlockPos): BlockState {
if (neighborState.block is NetworkComponent && world.getBlockState(pos.offset(state[CABLE_CONNECTION])).block !is NetworkComponent) {
return state.with(CABLE_CONNECTION, side)
}
return state
}
override fun addAllAttributes(world: World, pos: BlockPos, state: BlockState, to: AttributeList<*>) { override fun addAllAttributes(world: World, pos: BlockPos, state: BlockState, to: AttributeList<*>) {
to.offer(getBlockEntity(world, pos)) to.offer(getBlockEntity(world, pos))
} }
override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, context: EntityContext): VoxelShape {
return getShape(state[FACING], state[CABLE_CONNECTION])
}
} }

View File

@ -6,11 +6,13 @@ import net.minecraft.block.BlockState
import net.minecraft.block.Material import net.minecraft.block.Material
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Direction
import net.minecraft.world.BlockView import net.minecraft.world.BlockView
import net.minecraft.world.World import net.minecraft.world.World
import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.PhysicalConnectivity
import net.shadowfacts.phycon.api.NetworkComponent import net.shadowfacts.phycon.api.NetworkComponent
import net.shadowfacts.phycon.block.BlockWithEntity import net.shadowfacts.phycon.block.BlockWithEntity
import java.util.*
/** /**
* @author shadowfacts * @author shadowfacts
@ -20,6 +22,10 @@ class SwitchBlock: BlockWithEntity<SwitchBlockEntity>(Settings.of(Material.METAL
val ID = Identifier(PhysicalConnectivity.MODID, "switch") val ID = Identifier(PhysicalConnectivity.MODID, "switch")
} }
override fun getNetworkConnectedSides(state: BlockState, world: World, pos: BlockPos): Collection<Direction> {
return EnumSet.allOf(Direction::class.java)
}
override fun createBlockEntity(world: BlockView) = SwitchBlockEntity() override fun createBlockEntity(world: BlockView) = SwitchBlockEntity()
override fun addAllAttributes(world: World, pos: BlockPos, state: BlockState, to: AttributeList<*>) { override fun addAllAttributes(world: World, pos: BlockPos, state: BlockState, to: AttributeList<*>) {

View File

@ -9,11 +9,13 @@ import net.minecraft.util.Hand
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.hit.BlockHitResult import net.minecraft.util.hit.BlockHitResult
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Direction
import net.minecraft.world.BlockView import net.minecraft.world.BlockView
import net.minecraft.world.World import net.minecraft.world.World
import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.PhysicalConnectivity
import net.shadowfacts.phycon.api.NetworkComponent import net.shadowfacts.phycon.api.NetworkComponent
import net.shadowfacts.phycon.block.BlockWithEntity import net.shadowfacts.phycon.block.BlockWithEntity
import java.util.*
/** /**
* @author shadowfacts * @author shadowfacts
@ -23,6 +25,10 @@ class TerminalBlock: BlockWithEntity<TerminalBlockEntity>(Settings.of(Material.M
val ID = Identifier(PhysicalConnectivity.MODID, "terminal") val ID = Identifier(PhysicalConnectivity.MODID, "terminal")
} }
override fun getNetworkConnectedSides(state: BlockState, world: World, pos: BlockPos): Collection<Direction> {
return EnumSet.allOf(Direction::class.java)
}
override fun createBlockEntity(world: BlockView) = TerminalBlockEntity() override fun createBlockEntity(world: BlockView) = TerminalBlockEntity()
override fun activate(blockState_1: BlockState?, world_1: World?, blockPos_1: BlockPos?, playerEntity_1: PlayerEntity?, hand_1: Hand?, blockHitResult_1: BlockHitResult?): Boolean { override fun activate(blockState_1: BlockState?, world_1: World?, blockPos_1: BlockPos?, playerEntity_1: PlayerEntity?, hand_1: Hand?, blockHitResult_1: BlockHitResult?): Boolean {

View File

@ -1,36 +1,55 @@
package net.shadowfacts.phycon.network.block.terminal package net.shadowfacts.phycon.network.block.terminal
import alexiil.mc.lib.attributes.item.ItemStackCollections import alexiil.mc.lib.attributes.item.ItemStackCollections
import it.unimi.dsi.fastutil.objects.Object2IntMap
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.api.util.MACAddress
import net.shadowfacts.phycon.init.PhyBlockEntities import net.shadowfacts.phycon.init.PhyBlockEntities
import net.shadowfacts.phycon.network.DeviceBlockEntity import net.shadowfacts.phycon.network.DeviceBlockEntity
import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlockEntity
import net.shadowfacts.phycon.network.packet.DeviceRemovedPacket
import net.shadowfacts.phycon.network.packet.ReadAllPacket import net.shadowfacts.phycon.network.packet.ReadAllPacket
import net.shadowfacts.phycon.network.packet.RequestReadAllPacket import net.shadowfacts.phycon.network.packet.RequestReadAllPacket
import java.util.*
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL) { class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL) {
private var cachedItems = ItemStackCollections.intMap() private val inventoryCache = mutableMapOf<MACAddress, Map<ItemStack, Int>>()
override fun handlePacket(packet: Packet) { override fun handlePacket(packet: Packet) {
when (packet) { when (packet) {
is ReadAllPacket -> handleReadAll(packet) is ReadAllPacket -> handleReadAll(packet)
is DeviceRemovedPacket -> handleDeviceRemoved(packet)
} }
} }
fun handleReadAll(packet: ReadAllPacket) { private fun handleReadAll(packet: ReadAllPacket) {
packet.items.forEach { (stack, amount) -> inventoryCache[packet.source] = packet.items
cachedItems.mergeInt(stack, amount) { a, b -> a + b }
println("new items: ${computeNetItems()}")
}
private fun handleDeviceRemoved(packet: DeviceRemovedPacket) {
inventoryCache.remove(packet.source)
}
fun computeNetItems(): Map<ItemStack, Int> {
val net = ItemStackCollections.intMap()
for (map in inventoryCache.values) {
for ((stack, amount) in map) {
net.mergeInt(stack, amount) { a, b -> a + b }
}
} }
println("new cached items: $cachedItems") return net
} }
fun onActivate() { fun onActivate() {
if (!world!!.isClient) { if (!world!!.isClient) {
cachedItems.clear() inventoryCache.clear()
enqueueToSingle(RequestReadAllPacket(macAddress)) enqueueToSingle(RequestReadAllPacket(macAddress))
} }
} }

View File

@ -0,0 +1,11 @@
package net.shadowfacts.phycon.network.packet
import net.shadowfacts.phycon.api.util.MACAddress
import net.shadowfacts.phycon.network.DeviceBlockEntity
/**
* @author shadowfacts
*/
class DeviceRemovedPacket(source: MACAddress, destination: MACAddress = MACAddress.BROADCAST): BasePacket(source, destination) {
constructor(device: DeviceBlockEntity): this(device.macAddress)
}

View File

@ -0,0 +1,55 @@
{
"multipart": [
{
"apply": { "model": "phycon:block/cable_center" }
},
{
"when": { "facing": "down" },
"apply": { "model": "phycon:block/interface_side" }
},
{
"when": { "facing": "up" },
"apply": { "model": "phycon:block/interface_side", "x": 180 }
},
{
"when": { "facing": "north" },
"apply": { "model": "phycon:block/interface_side", "x": 270 }
},
{
"when": { "facing": "south" },
"apply": { "model": "phycon:block/interface_side", "x": 90 }
},
{
"when": { "facing": "west" },
"apply": { "model": "phycon:block/interface_side", "x": 90, "y": 90 }
},
{
"when": { "facing": "east" },
"apply": { "model": "phycon:block/interface_side", "x": 90, "y": 270 }
},
{
"when": { "cable_connection": "down" },
"apply": { "model": "phycon:block/cable_side" }
},
{
"when": { "cable_connection": "up" },
"apply": { "model": "phycon:block/cable_side", "x": 180 }
},
{
"when": { "cable_connection": "north" },
"apply": { "model": "phycon:block/cable_side", "x": 270 }
},
{
"when": { "cable_connection": "south" },
"apply": { "model": "phycon:block/cable_side", "x": 90 }
},
{
"when": { "cable_connection": "west" },
"apply": { "model": "phycon:block/cable_side", "x": 90, "y": 90 }
},
{
"when": { "cable_connection": "east" },
"apply": { "model": "phycon:block/cable_side", "x": 90, "y": 270 }
}
]
}

View File

@ -0,0 +1,27 @@
{
"parent": "block/block",
"elements": [
{
"from": [2, 0, 2],
"to": [14, 2, 14],
"faces": {
"down": { "texture": "phycon:block/interface_front" },
"up": { "texture": "phycon:block/interface_back" },
"north": { "texture": "phycon:block/interface_side" },
"south": { "texture": "phycon:block/interface_side" },
"west": { "texture": "phycon:block/interface_side" },
"east": { "texture": "phycon:block/interface_side" }
}
},
{
"from": [6, 2, 6],
"to": [10, 6, 10],
"faces": {
"north": { "texture": "phycon:block/cable_side" },
"south": { "texture": "phycon:block/cable_side" },
"west": { "texture": "phycon:block/cable_side" },
"east": { "texture": "phycon:block/cable_side" }
}
}
]
}