Compare commits
No commits in common. "700817919ab4a2537c838b6ea390f3ca32f9ee5e" and "2981bdcb07c931f1d50504c6aafffbd5183dc734" have entirely different histories.
700817919a
...
2981bdcb07
|
@ -7,7 +7,6 @@ import net.shadowfacts.phycon.init.PhyBlocks
|
||||||
import net.shadowfacts.phycon.init.PhyItems
|
import net.shadowfacts.phycon.init.PhyItems
|
||||||
import net.shadowfacts.phycon.init.PhyScreens
|
import net.shadowfacts.phycon.init.PhyScreens
|
||||||
import net.shadowfacts.phycon.networking.C2STerminalRequestItem
|
import net.shadowfacts.phycon.networking.C2STerminalRequestItem
|
||||||
import net.shadowfacts.phycon.networking.C2STerminalUpdateDisplayedItems
|
|
||||||
import net.shadowfacts.phycon.networking.ServerReceiver
|
import net.shadowfacts.phycon.networking.ServerReceiver
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,7 +23,6 @@ object PhysicalConnectivity: ModInitializer {
|
||||||
PhyScreens.init()
|
PhyScreens.init()
|
||||||
|
|
||||||
registerGlobalReceiver(C2STerminalRequestItem)
|
registerGlobalReceiver(C2STerminalRequestItem)
|
||||||
registerGlobalReceiver(C2STerminalUpdateDisplayedItems)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerGlobalReceiver(receiver: ServerReceiver) {
|
private fun registerGlobalReceiver(receiver: ServerReceiver) {
|
||||||
|
|
|
@ -2,30 +2,19 @@ package net.shadowfacts.phycon
|
||||||
|
|
||||||
import net.fabricmc.api.ClientModInitializer
|
import net.fabricmc.api.ClientModInitializer
|
||||||
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap
|
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap
|
||||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking
|
|
||||||
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry
|
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry
|
||||||
import net.minecraft.client.render.RenderLayer
|
import net.minecraft.client.render.RenderLayer
|
||||||
import net.shadowfacts.phycon.init.PhyBlocks
|
import net.shadowfacts.phycon.init.PhyBlocks
|
||||||
import net.shadowfacts.phycon.init.PhyScreens
|
import net.shadowfacts.phycon.init.PhyScreens
|
||||||
import net.shadowfacts.phycon.network.block.terminal.TerminalScreen
|
import net.shadowfacts.phycon.network.block.terminal.TerminalScreen
|
||||||
import net.shadowfacts.phycon.networking.ClientReceiver
|
|
||||||
import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
object PhysicalConnectivityClient: ClientModInitializer {
|
object PhysicalConnectivityClient: ClientModInitializer {
|
||||||
|
|
||||||
override fun onInitializeClient() {
|
override fun onInitializeClient() {
|
||||||
BlockRenderLayerMap.INSTANCE.putBlock(PhyBlocks.CABLE, RenderLayer.getTranslucent())
|
BlockRenderLayerMap.INSTANCE.putBlock(PhyBlocks.CABLE, RenderLayer.getTranslucent())
|
||||||
|
|
||||||
ScreenRegistry.register(PhyScreens.TERMINAL_SCREEN_HANDLER, ::TerminalScreen)
|
ScreenRegistry.register(PhyScreens.TERMINAL_SCREEN_HANDLER, ::TerminalScreen)
|
||||||
|
|
||||||
registerGlobalReceiver(S2CTerminalUpdateDisplayedItems)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerGlobalReceiver(receiver: ClientReceiver) {
|
|
||||||
ClientPlayNetworking.registerGlobalReceiver(receiver.CHANNEL, receiver)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
package net.shadowfacts.phycon.network
|
|
||||||
|
|
||||||
import net.minecraft.block.Block
|
|
||||||
import net.minecraft.block.BlockState
|
|
||||||
import net.minecraft.block.ShapeContext
|
|
||||||
import net.minecraft.item.ItemPlacementContext
|
|
||||||
import net.minecraft.state.StateManager
|
|
||||||
import net.minecraft.state.property.EnumProperty
|
|
||||||
import net.minecraft.state.property.Properties
|
|
||||||
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.shadowfacts.phycon.api.Interface
|
|
||||||
import net.shadowfacts.phycon.api.NetworkComponentBlock
|
|
||||||
import net.shadowfacts.phycon.network.block.cable.CableBlock
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
abstract class FaceDeviceBlock<T: DeviceBlockEntity>(settings: Settings): DeviceBlock<T>(settings) {
|
|
||||||
companion object {
|
|
||||||
val FACING = Properties.FACING
|
|
||||||
val CABLE_CONNECTION = EnumProperty.of("cable_connection", Direction::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract val faceThickness: Double
|
|
||||||
protected abstract val faceShapes: Map<Direction, VoxelShape>
|
|
||||||
private val centerShapes: Map<Direction, VoxelShape> by lazy {
|
|
||||||
mapOf(
|
|
||||||
Direction.DOWN to createCuboidShape(6.0, faceThickness, 6.0, 10.0, 10.0, 10.0),
|
|
||||||
Direction.UP to createCuboidShape(6.0, 6.0, 6.0, 10.0, 16.0 - faceThickness, 10.0),
|
|
||||||
Direction.NORTH to createCuboidShape(6.0, 6.0, faceThickness, 10.0, 10.0, 10.0),
|
|
||||||
Direction.SOUTH to createCuboidShape(6.0, 6.0, 6.0, 10.0, 10.0, 16.0 - faceThickness),
|
|
||||||
Direction.WEST to createCuboidShape(faceThickness, 6.0, 6.0, 10.0, 10.0, 10.0),
|
|
||||||
Direction.EAST to createCuboidShape(6.0, 6.0, 6.0, 16.0 - faceThickness, 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(
|
|
||||||
faceShapes[facing],
|
|
||||||
centerShapes[facing],
|
|
||||||
CableBlock.SIDE_SHAPES[cableConnection]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getNetworkConnectedSides(state: BlockState, world: WorldAccess, pos: BlockPos): Collection<Direction> {
|
|
||||||
return EnumSet.of(state[CABLE_CONNECTION])
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getNetworkInterfaceForSide(side: Direction, state: BlockState, world: WorldAccess, pos: BlockPos): Interface? {
|
|
||||||
return if (side == state[FACING]) {
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
getBlockEntity(world, pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
|
||||||
super.appendProperties(builder)
|
|
||||||
builder.add(FACING)
|
|
||||||
builder.add(CABLE_CONNECTION)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getPlacementState(context: ItemPlacementContext): BlockState? {
|
|
||||||
val facing = if (context.player?.isSneaking == true) context.side.opposite else context.playerFacing.opposite
|
|
||||||
val cableConnection = getCableConnectedSide(context.world, context.blockPos) ?: facing.opposite
|
|
||||||
return defaultState
|
|
||||||
.with(FACING, facing)
|
|
||||||
.with(CABLE_CONNECTION, cableConnection)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun getCableConnectedSide(world: World, pos: BlockPos): Direction? {
|
|
||||||
for (side in Direction.values()) {
|
|
||||||
val offsetPos = pos.offset(side)
|
|
||||||
if (world.getBlockState(offsetPos) is NetworkComponentBlock) {
|
|
||||||
return side
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getStateForNeighborUpdate(state: BlockState, side: Direction, neighborState: BlockState, world: WorldAccess, pos: BlockPos, neighborPos: BlockPos): BlockState {
|
|
||||||
if (neighborState.block is NetworkComponentBlock && world.getBlockState(pos.offset(state[CABLE_CONNECTION])).block !is NetworkComponentBlock) {
|
|
||||||
return state.with(CABLE_CONNECTION, side)
|
|
||||||
}
|
|
||||||
return state
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape {
|
|
||||||
return getShape(state[FACING], state[CABLE_CONNECTION])
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,29 +4,38 @@ import alexiil.mc.lib.attributes.AttributeList
|
||||||
import alexiil.mc.lib.attributes.AttributeProvider
|
import alexiil.mc.lib.attributes.AttributeProvider
|
||||||
import net.minecraft.block.*
|
import net.minecraft.block.*
|
||||||
import net.minecraft.entity.LivingEntity
|
import net.minecraft.entity.LivingEntity
|
||||||
|
import net.minecraft.item.ItemPlacementContext
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.state.StateManager
|
||||||
|
import net.minecraft.state.property.EnumProperty
|
||||||
|
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.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.World
|
import net.minecraft.world.World
|
||||||
|
import net.minecraft.world.WorldAccess
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
import net.shadowfacts.phycon.api.NetworkComponentBlock
|
import net.shadowfacts.phycon.api.NetworkComponentBlock
|
||||||
import net.shadowfacts.phycon.network.FaceDeviceBlock
|
import net.shadowfacts.phycon.api.Interface
|
||||||
|
import net.shadowfacts.phycon.network.DeviceBlock
|
||||||
|
import net.shadowfacts.phycon.network.block.cable.CableBlock
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class InterfaceBlock: FaceDeviceBlock<InterfaceBlockEntity>(Settings.of(Material.METAL)),
|
class InterfaceBlock: DeviceBlock<InterfaceBlockEntity>(Settings.of(Material.METAL)),
|
||||||
NetworkComponentBlock,
|
NetworkComponentBlock,
|
||||||
AttributeProvider {
|
AttributeProvider {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val ID = Identifier(PhysicalConnectivity.MODID, "network_interface")
|
val ID = Identifier(PhysicalConnectivity.MODID, "network_interface")
|
||||||
}
|
val FACING = Properties.FACING
|
||||||
|
val CABLE_CONNECTION = EnumProperty.of("cable_connection", Direction::class.java)
|
||||||
override val faceThickness = 2.0
|
private val SIDE_SHAPES = mapOf<Direction, VoxelShape>(
|
||||||
override val faceShapes = mapOf(
|
|
||||||
Direction.DOWN to createCuboidShape(2.0, 0.0, 2.0, 14.0, 2.0, 14.0),
|
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.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.NORTH to createCuboidShape(2.0, 2.0, 0.0, 14.0, 14.0, 2.0),
|
||||||
|
@ -34,9 +43,64 @@ class InterfaceBlock: FaceDeviceBlock<InterfaceBlockEntity>(Settings.of(Material
|
||||||
Direction.WEST to createCuboidShape(0.0, 2.0, 2.0, 2.0, 14.0, 14.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)
|
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: WorldAccess, pos: BlockPos): Collection<Direction> {
|
||||||
|
val set = EnumSet.of(state[CABLE_CONNECTION])
|
||||||
|
set.remove(state[FACING])
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getNetworkInterfaceForSide(side: Direction, state: BlockState, world: WorldAccess, pos: BlockPos): Interface? {
|
||||||
|
return if (side == state[FACING]) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
getBlockEntity(world, pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||||
|
super.appendProperties(builder)
|
||||||
|
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 {
|
||||||
|
val facing = if (context.player?.isSneaking == true) context.side.opposite else context.playerFacing.opposite
|
||||||
|
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 NetworkComponentBlock) {
|
||||||
|
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) {
|
||||||
if (!world.isClient) {
|
if (!world.isClient) {
|
||||||
getBlockEntity(world, pos)!!.updateInventory()
|
getBlockEntity(world, pos)!!.updateInventory()
|
||||||
|
@ -49,8 +113,19 @@ class InterfaceBlock: FaceDeviceBlock<InterfaceBlockEntity>(Settings.of(Material
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getStateForNeighborUpdate(state: BlockState, side: Direction, neighborState: BlockState, world: WorldAccess, pos: BlockPos, neighborPos: BlockPos): BlockState {
|
||||||
|
if (neighborState.block is NetworkComponentBlock && world.getBlockState(pos.offset(state[CABLE_CONNECTION])).block !is NetworkComponentBlock) {
|
||||||
|
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: ShapeContext): VoxelShape {
|
||||||
|
return getShape(state[FACING], state[CABLE_CONNECTION])
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import net.minecraft.util.math.Direction
|
||||||
import net.shadowfacts.phycon.api.packet.Packet
|
import net.shadowfacts.phycon.api.packet.Packet
|
||||||
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.FaceDeviceBlock
|
|
||||||
import net.shadowfacts.phycon.network.component.ItemStackPacketHandler
|
import net.shadowfacts.phycon.network.component.ItemStackPacketHandler
|
||||||
import net.shadowfacts.phycon.network.component.NetworkStackProvider
|
import net.shadowfacts.phycon.network.component.NetworkStackProvider
|
||||||
import net.shadowfacts.phycon.network.component.NetworkStackReceiver
|
import net.shadowfacts.phycon.network.component.NetworkStackReceiver
|
||||||
|
@ -26,7 +25,7 @@ class InterfaceBlockEntity: DeviceBlockEntity(PhyBlockEntities.INTERFACE),
|
||||||
NetworkStackReceiver {
|
NetworkStackReceiver {
|
||||||
|
|
||||||
private val facing: Direction
|
private val facing: Direction
|
||||||
get() = cachedState[FaceDeviceBlock.FACING]
|
get() = cachedState[InterfaceBlock.FACING]
|
||||||
|
|
||||||
// todo: should this be a weak ref?
|
// todo: should this be a weak ref?
|
||||||
private var inventory: GroupedItemInv? = null
|
private var inventory: GroupedItemInv? = null
|
||||||
|
|
|
@ -56,6 +56,7 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
||||||
|
|
||||||
private var observers = 0
|
private var observers = 0
|
||||||
val cachedNetItems = ItemStackCollections.intMap()
|
val cachedNetItems = ItemStackCollections.intMap()
|
||||||
|
var cachedSortedNetItems = listOf<ItemStack>()
|
||||||
|
|
||||||
var netItemObserver: WeakReference<NetItemObserver>? = null
|
var netItemObserver: WeakReference<NetItemObserver>? = null
|
||||||
|
|
||||||
|
@ -85,12 +86,14 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
||||||
|
|
||||||
private fun handleReadInventory(packet: ReadInventoryPacket) {
|
private fun handleReadInventory(packet: ReadInventoryPacket) {
|
||||||
inventoryCache[packet.source] = packet.inventory
|
inventoryCache[packet.source] = packet.inventory
|
||||||
updateAndSync()
|
updateNetItems()
|
||||||
|
sync()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleDeviceRemoved(packet: DeviceRemovedPacket) {
|
private fun handleDeviceRemoved(packet: DeviceRemovedPacket) {
|
||||||
inventoryCache.remove(packet.source)
|
inventoryCache.remove(packet.source)
|
||||||
updateAndSync()
|
updateNetItems()
|
||||||
|
sync()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleStackLocation(packet: StackLocationPacket) {
|
private fun handleStackLocation(packet: StackLocationPacket) {
|
||||||
|
@ -110,15 +113,10 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
||||||
|
|
||||||
// this happens outside the normal update loop because by receiving the item stack packet
|
// this happens outside the normal update loop because by receiving the item stack packet
|
||||||
// we "know" how much the count in the source inventory has changed
|
// we "know" how much the count in the source inventory has changed
|
||||||
updateAndSync()
|
|
||||||
|
|
||||||
return remaining
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateAndSync() {
|
|
||||||
updateNetItems()
|
updateNetItems()
|
||||||
sync()
|
sync()
|
||||||
netItemObserver?.get()?.netItemsChanged()
|
|
||||||
|
return remaining
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateNetItems() {
|
private fun updateNetItems() {
|
||||||
|
@ -129,6 +127,12 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
||||||
cachedNetItems.mergeInt(stack, amount) { a, b -> a + b }
|
cachedNetItems.mergeInt(stack, amount) { a, b -> a + b }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// todo: is the map necessary or is just the sorted list enough?
|
||||||
|
cachedSortedNetItems = cachedNetItems.object2IntEntrySet().sortedByDescending { it.intValue }.map {
|
||||||
|
val stack = it.key.copy()
|
||||||
|
stack.count = it.intValue
|
||||||
|
stack
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun beginInsertions() {
|
private fun beginInsertions() {
|
||||||
|
@ -171,15 +175,21 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
||||||
finishTimedOutPendingInsertions()
|
finishTimedOutPendingInsertions()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (observers > 0 && !world!!.isClient) {
|
if (observers > 0) {
|
||||||
updateAndSync()
|
if (world!!.isClient) {
|
||||||
|
println(cachedNetItems)
|
||||||
|
} else {
|
||||||
|
updateNetItems()
|
||||||
|
sync()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onActivate(player: PlayerEntity) {
|
fun onActivate(player: PlayerEntity) {
|
||||||
if (!world!!.isClient) {
|
if (!world!!.isClient) {
|
||||||
updateAndSync()
|
updateNetItems()
|
||||||
|
sync()
|
||||||
|
|
||||||
inventoryCache.clear()
|
inventoryCache.clear()
|
||||||
sendPacket(RequestInventoryPacket(ipAddress))
|
sendPacket(RequestInventoryPacket(ipAddress))
|
||||||
|
@ -228,7 +238,8 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
||||||
internalBuffer.setStack(insertion.bufferSlot, remaining)
|
internalBuffer.setStack(insertion.bufferSlot, remaining)
|
||||||
|
|
||||||
// as with extracting, we "know" the new amounts and so can update instantly without actually sending out packets
|
// as with extracting, we "know" the new amounts and so can update instantly without actually sending out packets
|
||||||
updateAndSync()
|
updateNetItems()
|
||||||
|
sync()
|
||||||
|
|
||||||
return remaining
|
return remaining
|
||||||
}
|
}
|
||||||
|
@ -252,11 +263,31 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
||||||
|
|
||||||
override fun toClientTag(tag: CompoundTag): CompoundTag {
|
override fun toClientTag(tag: CompoundTag): CompoundTag {
|
||||||
tag.put("InternalBuffer", internalBuffer.toTag())
|
tag.put("InternalBuffer", internalBuffer.toTag())
|
||||||
|
val list = ListTag()
|
||||||
|
tag.put("CachedNetItems", list)
|
||||||
|
for ((stack, amount) in cachedNetItems) {
|
||||||
|
val entryTag = stack.toTag(CompoundTag())
|
||||||
|
entryTag.putInt("NetAmount", amount)
|
||||||
|
list.add(entryTag)
|
||||||
|
}
|
||||||
return tag
|
return tag
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun fromClientTag(tag: CompoundTag) {
|
override fun fromClientTag(tag: CompoundTag) {
|
||||||
internalBuffer.fromTag(tag.getCompound("InternalBuffer"))
|
internalBuffer.fromTag(tag.getCompound("InternalBuffer"))
|
||||||
|
val list = tag.getList("CachedNetItems", 10)
|
||||||
|
cachedNetItems.clear()
|
||||||
|
for (entryTag in list) {
|
||||||
|
val stack = ItemStack.fromTag(entryTag as CompoundTag)
|
||||||
|
val netAmount = entryTag.getInt("NetAmount")
|
||||||
|
cachedNetItems[stack] = netAmount
|
||||||
|
}
|
||||||
|
netItemObserver?.get()?.netItemsChanged()
|
||||||
|
cachedSortedNetItems = cachedNetItems.object2IntEntrySet().sortedByDescending { it.intValue }.map {
|
||||||
|
val stack = it.key.copy()
|
||||||
|
stack.count = it.intValue
|
||||||
|
stack
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NetItemObserver {
|
interface NetItemObserver {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import net.minecraft.client.MinecraftClient
|
||||||
import net.minecraft.client.gui.DrawableHelper
|
import net.minecraft.client.gui.DrawableHelper
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||||
import net.minecraft.client.gui.widget.AbstractButtonWidget
|
import net.minecraft.client.gui.widget.AbstractButtonWidget
|
||||||
import net.minecraft.client.gui.widget.AbstractPressableButtonWidget
|
|
||||||
import net.minecraft.client.gui.widget.ButtonWidget
|
import net.minecraft.client.gui.widget.ButtonWidget
|
||||||
import net.minecraft.client.gui.widget.TextFieldWidget
|
import net.minecraft.client.gui.widget.TextFieldWidget
|
||||||
import net.minecraft.client.util.math.MatrixStack
|
import net.minecraft.client.util.math.MatrixStack
|
||||||
|
@ -17,14 +16,10 @@ import net.minecraft.text.LiteralText
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
import net.shadowfacts.phycon.networking.C2STerminalRequestItem
|
|
||||||
import net.shadowfacts.phycon.networking.C2STerminalUpdateDisplayedItems
|
|
||||||
import net.shadowfacts.phycon.util.SortMode
|
|
||||||
import org.lwjgl.glfw.GLFW
|
import org.lwjgl.glfw.GLFW
|
||||||
import java.lang.NumberFormatException
|
import java.lang.NumberFormatException
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -37,7 +32,6 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var searchBox: TextFieldWidget
|
private lateinit var searchBox: TextFieldWidget
|
||||||
private lateinit var sortButton: SortButton
|
|
||||||
private lateinit var amountBox: TextFieldWidget
|
private lateinit var amountBox: TextFieldWidget
|
||||||
private var dialogStack = ItemStack.EMPTY
|
private var dialogStack = ItemStack.EMPTY
|
||||||
private var showingAmountDialog = false
|
private var showingAmountDialog = false
|
||||||
|
@ -79,12 +73,7 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
searchBox.isVisible = true
|
searchBox.isVisible = true
|
||||||
searchBox.setSelected(true)
|
searchBox.setSelected(true)
|
||||||
searchBox.setEditableColor(0xffffff)
|
searchBox.setEditableColor(0xffffff)
|
||||||
addChild(searchBox)
|
children.add(searchBox)
|
||||||
|
|
||||||
sortButton = SortButton(x + 256, y + 0, handler.sortMode, {
|
|
||||||
requestUpdatedItems()
|
|
||||||
}, ::renderTooltip)
|
|
||||||
addButton(sortButton)
|
|
||||||
|
|
||||||
val dialogMinX = width / 2 - dialogWidth / 2
|
val dialogMinX = width / 2 - dialogWidth / 2
|
||||||
val dialogMinY = height / 2 - dialogHeight / 2
|
val dialogMinY = height / 2 - dialogHeight / 2
|
||||||
|
@ -141,13 +130,6 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
doDialogRequest()
|
doDialogRequest()
|
||||||
}
|
}
|
||||||
dialogChildren.add(request)
|
dialogChildren.add(request)
|
||||||
|
|
||||||
requestUpdatedItems()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun requestUpdatedItems() {
|
|
||||||
val player = MinecraftClient.getInstance().player!!
|
|
||||||
player.networkHandler.sendPacket(C2STerminalUpdateDisplayedItems(handler.terminal, searchBox.text, sortButton.mode))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tick() {
|
override fun tick() {
|
||||||
|
@ -231,24 +213,12 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
// don't unfocus the search box on mouse click
|
// don't unfocus the search box on mouse click
|
||||||
searchBox.setSelected(true)
|
searchBox.setSelected(true)
|
||||||
|
|
||||||
if (slot != null && !slot.stack.isEmpty && handler.isNetworkSlot(slot.id)) {
|
if (type == SlotActionType.PICKUP && clickData == 0 && slot != null && handler.isNetworkSlot(slot.id) && !slot.stack.isEmpty) {
|
||||||
val stack = slot.stack
|
dialogStack = slot.stack
|
||||||
|
|
||||||
if (type == SlotActionType.QUICK_MOVE) {
|
|
||||||
// shift click, request full stack
|
|
||||||
requestItem(stack, min(stack.count, stack.maxCount))
|
|
||||||
} else if (type == SlotActionType.PICKUP) {
|
|
||||||
if (clickData == 1) {
|
|
||||||
// right click, request half stack
|
|
||||||
requestItem(stack, ceil(min(stack.count, stack.maxCount) / 2f).toInt())
|
|
||||||
} else {
|
|
||||||
dialogStack = stack
|
|
||||||
showingAmountDialog = true
|
showingAmountDialog = true
|
||||||
searchBox.setSelected(false)
|
searchBox.setSelected(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||||
if (showingAmountDialog) {
|
if (showingAmountDialog) {
|
||||||
|
@ -301,7 +271,7 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
val oldText = searchBox.text
|
val oldText = searchBox.text
|
||||||
if (searchBox.charTyped(c, i)) {
|
if (searchBox.charTyped(c, i)) {
|
||||||
if (searchBox.text != oldText) {
|
if (searchBox.text != oldText) {
|
||||||
requestUpdatedItems()
|
search()
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -329,7 +299,7 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
val oldText = searchBox.text
|
val oldText = searchBox.text
|
||||||
if (searchBox.keyPressed(key, j, k)) {
|
if (searchBox.keyPressed(key, j, k)) {
|
||||||
if (searchBox.text != oldText) {
|
if (searchBox.text != oldText) {
|
||||||
requestUpdatedItems()
|
search()
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -341,15 +311,13 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doDialogRequest() {
|
private fun search() {
|
||||||
showingAmountDialog = false
|
screenHandler.search(searchBox.text)
|
||||||
requestItem(dialogStack, amountBox.intValue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun requestItem(stack: ItemStack, amount: Int) {
|
private fun doDialogRequest() {
|
||||||
val netHandler = MinecraftClient.getInstance().player!!.networkHandler
|
showingAmountDialog = false
|
||||||
val packet = C2STerminalRequestItem(handler.terminal, stack, amount)
|
handler.requestItem(client!!.player!!, dialogStack, amountBox.intValue)
|
||||||
netHandler.sendPacket(packet)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private var TextFieldWidget.intValue: Int
|
private var TextFieldWidget.intValue: Int
|
||||||
|
@ -375,58 +343,4 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SortButton(
|
|
||||||
x: Int,
|
|
||||||
y: Int,
|
|
||||||
var mode: SortMode,
|
|
||||||
val onChange: (SortMode) -> Unit,
|
|
||||||
val doRenderTooltip: (MatrixStack, Text, Int, Int) -> Unit
|
|
||||||
): AbstractPressableButtonWidget(x, y, 20, 20, LiteralText("")) {
|
|
||||||
override fun onPress() {}
|
|
||||||
|
|
||||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
|
||||||
if ((button == 0 || button == 1) && clicked(mouseX, mouseY)) {
|
|
||||||
val newVal = if (button == 0) mode.next else mode.prev
|
|
||||||
mode = newVal
|
|
||||||
onChange(mode)
|
|
||||||
|
|
||||||
playDownSound(MinecraftClient.getInstance().soundManager)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun renderButton(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) {
|
|
||||||
val client = MinecraftClient.getInstance()
|
|
||||||
RenderSystem.color4f(1f, 1f, 1f, 1f)
|
|
||||||
RenderSystem.enableBlend()
|
|
||||||
RenderSystem.defaultBlendFunc()
|
|
||||||
RenderSystem.enableDepthTest()
|
|
||||||
|
|
||||||
client.textureManager.bindTexture(WIDGETS_LOCATION)
|
|
||||||
val k = getYImage(isHovered)
|
|
||||||
drawTexture(matrixStack, x, y, 0, 46 + k * 20, width / 2, height)
|
|
||||||
drawTexture(matrixStack, x + width / 2, y, 200 - width / 2, 46 + k * 20, width / 2, height)
|
|
||||||
|
|
||||||
client.textureManager.bindTexture(BACKGROUND)
|
|
||||||
val u: Int = when (mode) {
|
|
||||||
SortMode.COUNT_HIGH_FIRST -> 0
|
|
||||||
SortMode.COUNT_LOW_FIRST -> 16
|
|
||||||
SortMode.ALPHABETICAL -> 32
|
|
||||||
}
|
|
||||||
drawTexture(matrixStack, x + 2, y + 2, u, 230, 16, 16)
|
|
||||||
|
|
||||||
if (isHovered) {
|
|
||||||
renderToolTip(matrixStack, mouseX, mouseY)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun renderToolTip(matrixStack: MatrixStack, mouseX: Int, mouseY: Int) {
|
|
||||||
val text = LiteralText("")
|
|
||||||
text.append("Sort by: ")
|
|
||||||
text.append(mode.tooltip)
|
|
||||||
doRenderTooltip(matrixStack, text, mouseX, mouseY)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,15 +8,12 @@ import net.minecraft.entity.player.PlayerInventory
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.network.PacketByteBuf
|
import net.minecraft.network.PacketByteBuf
|
||||||
import net.minecraft.screen.ScreenHandler
|
import net.minecraft.screen.ScreenHandler
|
||||||
import net.minecraft.server.network.ServerPlayerEntity
|
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import net.minecraft.util.registry.Registry
|
import net.minecraft.util.registry.Registry
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
import net.shadowfacts.phycon.init.PhyBlocks
|
import net.shadowfacts.phycon.init.PhyBlocks
|
||||||
import net.shadowfacts.phycon.init.PhyScreens
|
import net.shadowfacts.phycon.init.PhyScreens
|
||||||
import net.shadowfacts.phycon.networking.C2STerminalRequestItem
|
import net.shadowfacts.phycon.networking.C2STerminalRequestItem
|
||||||
import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems
|
|
||||||
import net.shadowfacts.phycon.util.SortMode
|
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
@ -24,7 +21,7 @@ import kotlin.math.min
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val terminal: TerminalBlockEntity): ScreenHandler(PhyScreens.TERMINAL_SCREEN_HANDLER, syncId),
|
class TerminalScreenHandler(syncId: Int, playerInv: PlayerInventory, val terminal: TerminalBlockEntity): ScreenHandler(PhyScreens.TERMINAL_SCREEN_HANDLER, syncId),
|
||||||
TerminalBlockEntity.NetItemObserver {
|
TerminalBlockEntity.NetItemObserver {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -33,19 +30,6 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
|
|
||||||
private val fakeInv = FakeInventory(this)
|
private val fakeInv = FakeInventory(this)
|
||||||
private var searchQuery: String = ""
|
private var searchQuery: String = ""
|
||||||
var sortMode = SortMode.COUNT_HIGH_FIRST
|
|
||||||
private set
|
|
||||||
private var itemEntries = listOf<Entry>()
|
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
if (terminal.world!!.isClient) {
|
|
||||||
itemsForDisplay = value.map {
|
|
||||||
val stack = it.stack.copy()
|
|
||||||
stack.count = it.amount
|
|
||||||
stack
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var itemsForDisplay = listOf<ItemStack>()
|
var itemsForDisplay = listOf<ItemStack>()
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
@ -53,10 +37,8 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
this(syncId, playerInv, PhyBlocks.TERMINAL.getBlockEntity(playerInv.player.world, buf.readBlockPos())!!)
|
this(syncId, playerInv, PhyBlocks.TERMINAL.getBlockEntity(playerInv.player.world, buf.readBlockPos())!!)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (!terminal.world!!.isClient) {
|
|
||||||
terminal.netItemObserver = WeakReference(this)
|
terminal.netItemObserver = WeakReference(this)
|
||||||
netItemsChanged()
|
netItemsChanged()
|
||||||
}
|
|
||||||
|
|
||||||
// network
|
// network
|
||||||
for (y in 0 until 6) {
|
for (y in 0 until 6) {
|
||||||
|
@ -85,10 +67,7 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun netItemsChanged() {
|
override fun netItemsChanged() {
|
||||||
val player = playerInv.player
|
itemsForDisplay = terminal.cachedNetItems.object2IntEntrySet().filter {
|
||||||
assert(player is ServerPlayerEntity)
|
|
||||||
|
|
||||||
val filtered = terminal.cachedNetItems.object2IntEntrySet().filter {
|
|
||||||
if (searchQuery.isBlank()) return@filter true
|
if (searchQuery.isBlank()) return@filter true
|
||||||
if (searchQuery.startsWith('@')) {
|
if (searchQuery.startsWith('@')) {
|
||||||
val unprefixed = searchQuery.drop(1)
|
val unprefixed = searchQuery.drop(1)
|
||||||
|
@ -98,34 +77,20 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
it.key.name.string.contains(searchQuery, true)
|
it.key.name.string.contains(searchQuery, true)
|
||||||
|
}.sortedByDescending {
|
||||||
|
it.intValue
|
||||||
|
}.map {
|
||||||
|
val stack = it.key.copy()
|
||||||
|
stack.count = it.intValue
|
||||||
|
stack
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val sorted =
|
fun search(query: String) {
|
||||||
when (sortMode) {
|
searchQuery = query
|
||||||
SortMode.COUNT_HIGH_FIRST -> filtered.sortedByDescending { it.intValue }
|
|
||||||
SortMode.COUNT_LOW_FIRST -> filtered.sortedBy { it.intValue }
|
|
||||||
SortMode.ALPHABETICAL -> filtered.sortedBy { it.key.name.string }
|
|
||||||
}
|
|
||||||
|
|
||||||
itemEntries = sorted.map { Entry(it.key, it.intValue) }
|
|
||||||
|
|
||||||
(player as ServerPlayerEntity).networkHandler.sendPacket(S2CTerminalUpdateDisplayedItems(terminal, itemEntries, searchQuery, sortMode))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sendUpdatedItemsToClient(player: ServerPlayerEntity, query: String, sortMode: SortMode) {
|
|
||||||
this.searchQuery = query
|
|
||||||
this.sortMode = sortMode
|
|
||||||
netItemsChanged()
|
netItemsChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun receivedUpdatedItemsFromServer(entries: List<Entry>, query: String, sortMode: SortMode) {
|
|
||||||
assert(playerInv.player.world.isClient)
|
|
||||||
|
|
||||||
this.searchQuery = query
|
|
||||||
this.sortMode = sortMode
|
|
||||||
itemEntries = entries
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canUse(player: PlayerEntity): Boolean {
|
override fun canUse(player: PlayerEntity): Boolean {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -137,7 +102,28 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSlotClick(slotId: Int, clickData: Int, actionType: SlotActionType, player: PlayerEntity): ItemStack {
|
override fun onSlotClick(slotId: Int, clickData: Int, actionType: SlotActionType, player: PlayerEntity): ItemStack {
|
||||||
if (isBufferSlot(slotId)) {
|
if (isNetworkSlot(slotId)) {
|
||||||
|
// the slot clicked was one of the network stacks
|
||||||
|
if (actionType == SlotActionType.QUICK_MOVE) {
|
||||||
|
val stack = slots[slotId].stack
|
||||||
|
if (!stack.isEmpty && player.world.isClient) {
|
||||||
|
requestItem(player, stack, min(stack.count, stack.maxCount))
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if (actionType == SlotActionType.PICKUP && clickData == 1) {
|
||||||
|
if (clickData == 1) {
|
||||||
|
// right click, request half stack
|
||||||
|
val stack = slots[slotId].stack
|
||||||
|
if (!stack.isEmpty && player.world.isClient) {
|
||||||
|
requestItem(player, stack, ceil(min(stack.count, stack.maxCount) / 2f).toInt())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// todo: left click, show amount dialog
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
} else if (isBufferSlot(slotId)) {
|
||||||
|
// internal buffer
|
||||||
// todo: why does this think it's quick_craft sometimes?
|
// todo: why does this think it's quick_craft sometimes?
|
||||||
if ((actionType == SlotActionType.PICKUP || actionType == SlotActionType.QUICK_CRAFT) && !player.inventory.cursorStack.isEmpty) {
|
if ((actionType == SlotActionType.PICKUP || actionType == SlotActionType.QUICK_CRAFT) && !player.inventory.cursorStack.isEmpty) {
|
||||||
// placing cursor stack into buffer
|
// placing cursor stack into buffer
|
||||||
|
@ -148,6 +134,13 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
return super.onSlotClick(slotId, clickData, actionType, player)
|
return super.onSlotClick(slotId, clickData, actionType, player)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun requestItem(player: PlayerEntity, stack: ItemStack, amount: Int) {
|
||||||
|
if (!player.world.isClient) return
|
||||||
|
val handler = (player as ClientPlayerEntity).networkHandler
|
||||||
|
val packet = C2STerminalRequestItem(terminal, stack, amount)
|
||||||
|
handler.sendPacket(packet)
|
||||||
|
}
|
||||||
|
|
||||||
override fun transferSlot(player: PlayerEntity, slotId: Int): ItemStack {
|
override fun transferSlot(player: PlayerEntity, slotId: Int): ItemStack {
|
||||||
if (isNetworkSlot(slotId)) {
|
if (isNetworkSlot(slotId)) {
|
||||||
return ItemStack.EMPTY;
|
return ItemStack.EMPTY;
|
||||||
|
@ -161,8 +154,7 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
val result = slot.stack.copy()
|
val result = slot.stack.copy()
|
||||||
|
|
||||||
if (isBufferSlot(slotId)) {
|
if (isBufferSlot(slotId)) {
|
||||||
// last boolean param is fromLast
|
if (!insertItem(slot.stack, playerSlotsStart, playerSlotsEnd, false)) {
|
||||||
if (!insertItem(slot.stack, playerSlotsStart, playerSlotsEnd, true)) {
|
|
||||||
return ItemStack.EMPTY
|
return ItemStack.EMPTY
|
||||||
}
|
}
|
||||||
if (slot.stack.isEmpty) {
|
if (slot.stack.isEmpty) {
|
||||||
|
@ -212,6 +204,4 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
fun isNetworkSlot(id: Int) = id in 0 until bufferSlotsStart
|
fun isNetworkSlot(id: Int) = id in 0 until bufferSlotsStart
|
||||||
fun isBufferSlot(id: Int) = id in bufferSlotsStart until playerSlotsStart
|
fun isBufferSlot(id: Int) = id in bufferSlotsStart until playerSlotsStart
|
||||||
fun isPlayerSlot(id: Int) = id >= playerSlotsStart
|
fun isPlayerSlot(id: Int) = id >= playerSlotsStart
|
||||||
|
|
||||||
data class Entry(val stack: ItemStack, val amount: Int)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
package net.shadowfacts.phycon.networking
|
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking
|
|
||||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs
|
|
||||||
import net.fabricmc.fabric.api.networking.v1.PacketSender
|
|
||||||
import net.minecraft.network.Packet
|
|
||||||
import net.minecraft.network.PacketByteBuf
|
|
||||||
import net.minecraft.server.MinecraftServer
|
|
||||||
import net.minecraft.server.network.ServerPlayNetworkHandler
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity
|
|
||||||
import net.minecraft.util.Identifier
|
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
|
||||||
import net.shadowfacts.phycon.network.block.terminal.TerminalBlockEntity
|
|
||||||
import net.shadowfacts.phycon.network.block.terminal.TerminalScreenHandler
|
|
||||||
import net.shadowfacts.phycon.util.SortMode
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
object C2STerminalUpdateDisplayedItems: ServerReceiver {
|
|
||||||
|
|
||||||
override val CHANNEL = Identifier(PhysicalConnectivity.MODID, "terminal_update_displayed")
|
|
||||||
|
|
||||||
operator fun invoke(terminal: TerminalBlockEntity, query: String, sortMode: SortMode): Packet<*> {
|
|
||||||
val buf = PacketByteBufs.create()
|
|
||||||
|
|
||||||
buf.writeIdentifier(terminal.world!!.registryKey.value)
|
|
||||||
buf.writeBlockPos(terminal.pos)
|
|
||||||
|
|
||||||
buf.writeString(query)
|
|
||||||
buf.writeVarInt(sortMode.ordinal)
|
|
||||||
|
|
||||||
return ClientPlayNetworking.createC2SPacket(CHANNEL, buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun receive(server: MinecraftServer, player: ServerPlayerEntity, handler: ServerPlayNetworkHandler, buf: PacketByteBuf, responseSender: PacketSender) {
|
|
||||||
val dimID = buf.readIdentifier()
|
|
||||||
val pos = buf.readBlockPos()
|
|
||||||
val query = buf.readString()
|
|
||||||
val sortMode = SortMode.values()[buf.readVarInt()]
|
|
||||||
|
|
||||||
server.execute {
|
|
||||||
if (player.world.registryKey.value != dimID) return@execute
|
|
||||||
val screenHandler = player.currentScreenHandler
|
|
||||||
if (screenHandler !is TerminalScreenHandler) return@execute
|
|
||||||
if (screenHandler.terminal.pos != pos) return@execute
|
|
||||||
screenHandler.sendUpdatedItemsToClient(player, query, sortMode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package net.shadowfacts.phycon.networking
|
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking
|
|
||||||
import net.minecraft.util.Identifier
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
interface ClientReceiver: ClientPlayNetworking.PlayChannelHandler {
|
|
||||||
val CHANNEL: Identifier
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
package net.shadowfacts.phycon.networking
|
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs
|
|
||||||
import net.fabricmc.fabric.api.networking.v1.PacketSender
|
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking
|
|
||||||
import net.minecraft.client.MinecraftClient
|
|
||||||
import net.minecraft.client.network.ClientPlayNetworkHandler
|
|
||||||
import net.minecraft.network.Packet
|
|
||||||
import net.minecraft.network.PacketByteBuf
|
|
||||||
import net.shadowfacts.phycon.network.block.terminal.TerminalBlockEntity
|
|
||||||
import net.shadowfacts.phycon.network.block.terminal.TerminalScreenHandler
|
|
||||||
import net.shadowfacts.phycon.util.SortMode
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
object S2CTerminalUpdateDisplayedItems: ClientReceiver {
|
|
||||||
override val CHANNEL = C2STerminalUpdateDisplayedItems.CHANNEL
|
|
||||||
|
|
||||||
operator fun invoke(terminal: TerminalBlockEntity, entries: List<TerminalScreenHandler.Entry>, query: String, sortMode: SortMode): Packet<*> {
|
|
||||||
val buf = PacketByteBufs.create()
|
|
||||||
|
|
||||||
buf.writeIdentifier(terminal.world!!.registryKey.value)
|
|
||||||
buf.writeBlockPos(terminal.pos)
|
|
||||||
|
|
||||||
buf.writeVarInt(entries.size)
|
|
||||||
for (e in entries) {
|
|
||||||
buf.writeItemStack(e.stack)
|
|
||||||
buf.writeVarInt(e.amount)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.writeString(query)
|
|
||||||
buf.writeVarInt(sortMode.ordinal)
|
|
||||||
|
|
||||||
return ServerPlayNetworking.createS2CPacket(CHANNEL, buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun receive(client: MinecraftClient, handler: ClientPlayNetworkHandler, buf: PacketByteBuf, responseSender: PacketSender) {
|
|
||||||
val dimID = buf.readIdentifier()
|
|
||||||
val pos = buf.readBlockPos()
|
|
||||||
val entryCount = buf.readVarInt()
|
|
||||||
val entries = ArrayList<TerminalScreenHandler.Entry>(entryCount)
|
|
||||||
for (i in 0 until entryCount) {
|
|
||||||
entries.add(TerminalScreenHandler.Entry(buf.readItemStack(), buf.readVarInt()))
|
|
||||||
}
|
|
||||||
val query = buf.readString()
|
|
||||||
val sortMode = SortMode.values()[buf.readVarInt()]
|
|
||||||
|
|
||||||
client.execute {
|
|
||||||
if (client.player!!.world.registryKey.value != dimID) return@execute
|
|
||||||
val screenHandler = client.player!!.currentScreenHandler
|
|
||||||
if (screenHandler !is TerminalScreenHandler) return@execute
|
|
||||||
if (screenHandler.terminal.pos != pos) return@execute
|
|
||||||
screenHandler.receivedUpdatedItemsFromServer(entries, query, sortMode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package net.shadowfacts.phycon.util
|
|
||||||
|
|
||||||
import net.minecraft.text.LiteralText
|
|
||||||
import net.minecraft.text.Text
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
enum class SortMode {
|
|
||||||
COUNT_HIGH_FIRST,
|
|
||||||
COUNT_LOW_FIRST,
|
|
||||||
ALPHABETICAL;
|
|
||||||
|
|
||||||
val prev: SortMode
|
|
||||||
get() = values()[(ordinal - 1 + values().size) % values().size]
|
|
||||||
|
|
||||||
val next: SortMode
|
|
||||||
get() = values()[(ordinal + 1) % values().size]
|
|
||||||
|
|
||||||
val tooltip: Text
|
|
||||||
get() = when (this) {
|
|
||||||
COUNT_HIGH_FIRST -> LiteralText("Count, highest first")
|
|
||||||
COUNT_LOW_FIRST -> LiteralText("Count, lowest first")
|
|
||||||
ALPHABETICAL -> LiteralText("Name")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -140,6 +140,7 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
"when": {"cable_connection": "down", "facing": "east"},
|
"when": {"cable_connection": "down", "facing": "east"},
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 90, "y": 270 }
|
"apply": { "model": "phycon:block/interface_cable_corner", "x": 90, "y": 270 }
|
||||||
},
|
},
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 9.9 KiB |
Loading…
Reference in New Issue