Compare commits

...

6 Commits

27 changed files with 341 additions and 203 deletions

View File

@ -20,6 +20,9 @@ repositories {
maven { maven {
url = "https://mod-buildcraft.com/maven" url = "https://mod-buildcraft.com/maven"
} }
maven {
url = "http://server.bbkr.space:8081/artifactory/libs-release/"
}
jcenter() jcenter()
} }
@ -39,6 +42,8 @@ dependencies {
include "alexiil.mc.lib:libblockattributes-core:${project.libblockattributes_version}" include "alexiil.mc.lib:libblockattributes-core:${project.libblockattributes_version}"
include "alexiil.mc.lib:libblockattributes-items:${project.libblockattributes_version}" include "alexiil.mc.lib:libblockattributes-items:${project.libblockattributes_version}"
modImplementation "io.github.cottonmc:cotton-resources:${project.cotton_resources_version}"
shadow project(":kiwi-java") shadow project(":kiwi-java")
testImplementation "org.junit.jupiter:junit-jupiter:${project.junit_version}" testImplementation "org.junit.jupiter:junit-jupiter:${project.junit_version}"

View File

@ -13,5 +13,6 @@ fabric_version=0.30.0+1.16
fabric_kotlin_version=1.4.30+build.2 fabric_kotlin_version=1.4.30+build.2
libblockattributes_version=0.8.5 libblockattributes_version=0.8.5
cotton_resources_version=1.7.4
junit_version = 5.4.0 junit_version = 5.4.0

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

@ -1,5 +1,6 @@
package net.shadowfacts.phycon.block.cable package net.shadowfacts.phycon.block.cable
import net.fabricmc.fabric.api.`object`.builder.v1.block.FabricBlockSettings
import net.minecraft.block.* import net.minecraft.block.*
import net.minecraft.block.piston.PistonBehavior import net.minecraft.block.piston.PistonBehavior
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity
@ -23,20 +24,23 @@ 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.*
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class CableBlock: Block( class CableBlock: Block(
Settings.of(CABLE_MATERIAL) FabricBlockSettings.of(CABLE_MATERIAL)
.strength(1f) .strength(0.3f)
.nonOpaque() .nonOpaque()
.breakByHand(true)
), NetworkCableBlock { ), NetworkCableBlock {
companion object { companion object {
val ID = Identifier(PhysicalConnectivity.MODID, "cable") val ID = Identifier(PhysicalConnectivity.MODID, "cable")
val CABLE_MATERIAL = Material(MaterialColor.IRON, false, false, true, false, true, false, PistonBehavior.NORMAL) val CABLE_MATERIAL = Material.Builder(MaterialColor.BLUE).build()
val CENTER_SHAPE = createCuboidShape(6.0, 6.0, 6.0, 10.0, 10.0, 10.0) val CENTER_SHAPE = createCuboidShape(6.0, 6.0, 6.0, 10.0, 10.0, 10.0)
val SIDE_SHAPES = mapOf<Direction, VoxelShape>( val SIDE_SHAPES = mapOf<Direction, VoxelShape>(
Direction.DOWN to createCuboidShape(6.0, 0.0, 6.0, 10.0, 6.0, 10.0), Direction.DOWN to createCuboidShape(6.0, 0.0, 6.0, 10.0, 6.0, 10.0),
@ -85,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]
@ -139,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
@ -167,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

@ -3,13 +3,9 @@ package net.shadowfacts.phycon.block.extractor
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.block.ShapeContext
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.sound.BlockSoundGroup import net.minecraft.sound.BlockSoundGroup
import net.minecraft.state.StateManager
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
@ -17,16 +13,13 @@ import net.minecraft.util.shape.VoxelShape
import net.minecraft.util.shape.VoxelShapes 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.Interface import net.shadowfacts.phycon.block.FaceDeviceBlock
import net.shadowfacts.phycon.block.DeviceBlock
import java.util.*
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class ExtractorBlock: DeviceBlock<ExtractorBlockEntity>( class ExtractorBlock: FaceDeviceBlock<ExtractorBlockEntity>(
Settings.of(Material.METAL) Settings.of(Material.METAL)
.strength(1.5f) .strength(1.5f)
.sounds(BlockSoundGroup.METAL) .sounds(BlockSoundGroup.METAL)
@ -34,7 +27,6 @@ class ExtractorBlock: DeviceBlock<ExtractorBlockEntity>(
companion object { companion object {
val ID = Identifier(PhysicalConnectivity.MODID, "extractor") val ID = Identifier(PhysicalConnectivity.MODID, "extractor")
val FACING = Properties.FACING
private val EXTRACTOR_SHAPES = mutableMapOf<Direction, VoxelShape>() private val EXTRACTOR_SHAPES = mutableMapOf<Direction, VoxelShape>()
init { init {
@ -42,7 +34,6 @@ class ExtractorBlock: DeviceBlock<ExtractorBlockEntity>(
doubleArrayOf(0.0, 0.0, 0.0, 16.0, 2.0, 16.0), doubleArrayOf(0.0, 0.0, 0.0, 16.0, 2.0, 16.0),
doubleArrayOf(2.0, 2.0, 2.0, 14.0, 4.0, 14.0), doubleArrayOf(2.0, 2.0, 2.0, 14.0, 4.0, 14.0),
doubleArrayOf(4.0, 4.0, 4.0, 12.0, 6.0, 12.0), doubleArrayOf(4.0, 4.0, 4.0, 12.0, 6.0, 12.0),
doubleArrayOf(6.0, 6.0, 6.0, 10.0, 16.0, 10.0)
) )
val directions = arrayOf( val directions = arrayOf(
Triple(Direction.DOWN, null, false), Triple(Direction.DOWN, null, false),
@ -73,34 +64,11 @@ class ExtractorBlock: DeviceBlock<ExtractorBlockEntity>(
} }
} }
override fun getNetworkConnectedSides(state: BlockState, world: WorldAccess, pos: BlockPos): Collection<Direction> { override val faceThickness = 6.0
return EnumSet.of(state[FACING].opposite) override val faceShapes: Map<Direction, VoxelShape> = EXTRACTOR_SHAPES
}
override fun getNetworkInterfaceForSide(side: Direction, state: BlockState, world: WorldAccess, pos: BlockPos): Interface? {
return if (side == state[FACING].opposite) {
getBlockEntity(world, pos)
} else {
null
}
}
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
super.appendProperties(builder)
builder.add(FACING)
}
override fun createBlockEntity(world: BlockView) = ExtractorBlockEntity() override fun createBlockEntity(world: BlockView) = ExtractorBlockEntity()
override fun getPlacementState(context: ItemPlacementContext): BlockState {
val facing = if (context.player?.isSneaking == true) context.side.opposite else context.playerLookDirection.opposite
return defaultState.with(FACING, facing)
}
override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape {
return EXTRACTOR_SHAPES[state[FACING]]!!
}
override fun onPlaced(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity?, stack: ItemStack) { override fun onPlaced(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity?, stack: ItemStack) {
if (!world.isClient) { if (!world.isClient) {
getBlockEntity(world, pos)!!.updateInventory() getBlockEntity(world, pos)!!.updateInventory()

View File

@ -5,13 +5,13 @@ import alexiil.mc.lib.attributes.Simulation
import alexiil.mc.lib.attributes.item.FixedItemInv import alexiil.mc.lib.attributes.item.FixedItemInv
import alexiil.mc.lib.attributes.item.ItemAttributes import alexiil.mc.lib.attributes.item.ItemAttributes
import alexiil.mc.lib.attributes.item.filter.ExactItemStackFilter import alexiil.mc.lib.attributes.item.filter.ExactItemStackFilter
import net.minecraft.block.BlockState
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.util.math.Direction 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.block.DeviceBlockEntity import net.shadowfacts.phycon.block.DeviceBlockEntity
import net.shadowfacts.phycon.block.FaceDeviceBlock
import net.shadowfacts.phycon.component.ActivationController import net.shadowfacts.phycon.component.ActivationController
import net.shadowfacts.phycon.component.NetworkStackDispatcher import net.shadowfacts.phycon.component.NetworkStackDispatcher
import net.shadowfacts.phycon.component.finishTimedOutPendingInsertions import net.shadowfacts.phycon.component.finishTimedOutPendingInsertions
@ -36,7 +36,7 @@ class ExtractorBlockEntity: DeviceBlockEntity(PhyBlockEntities.EXTRACTOR),
} }
private val facing: Direction private val facing: Direction
get() = cachedState[ExtractorBlock.FACING] get() = cachedState[FaceDeviceBlock.FACING]
private var inventory: FixedItemInv? = null private var inventory: FixedItemInv? = null
override val pendingInsertions = mutableListOf<PendingInsertion>() override val pendingInsertions = mutableListOf<PendingInsertion>()

View File

@ -4,19 +4,14 @@ import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory
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.block.ShapeContext
import net.minecraft.entity.LivingEntity import net.minecraft.entity.LivingEntity
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity
import net.minecraft.entity.player.PlayerInventory import net.minecraft.entity.player.PlayerInventory
import net.minecraft.item.ItemPlacementContext
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.server.network.ServerPlayerEntity
import net.minecraft.sound.BlockSoundGroup import net.minecraft.sound.BlockSoundGroup
import net.minecraft.state.StateManager
import net.minecraft.state.property.Properties
import net.minecraft.text.Text
import net.minecraft.util.ActionResult import net.minecraft.util.ActionResult
import net.minecraft.util.Hand import net.minecraft.util.Hand
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
@ -27,24 +22,20 @@ import net.minecraft.util.shape.VoxelShape
import net.minecraft.util.shape.VoxelShapes 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.Interface import net.shadowfacts.phycon.block.FaceDeviceBlock
import net.shadowfacts.phycon.block.DeviceBlock
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
import java.util.* import java.util.*
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class InserterBlock: DeviceBlock<InserterBlockEntity>( class InserterBlock: FaceDeviceBlock<InserterBlockEntity>(
Settings.of(Material.METAL) Settings.of(Material.METAL)
.strength(1.5f) .strength(1.5f)
.sounds(BlockSoundGroup.METAL) .sounds(BlockSoundGroup.METAL)
) { ) {
companion object { companion object {
val ID = Identifier(PhysicalConnectivity.MODID, "inserter") val ID = Identifier(PhysicalConnectivity.MODID, "inserter")
val FACING = Properties.FACING
private val INSERTER_SHAPES = mutableMapOf<Direction, VoxelShape>() private val INSERTER_SHAPES = mutableMapOf<Direction, VoxelShape>()
init { init {
@ -52,7 +43,6 @@ class InserterBlock: DeviceBlock<InserterBlockEntity>(
doubleArrayOf(4.0, 0.0, 4.0, 12.0, 2.0, 12.0), doubleArrayOf(4.0, 0.0, 4.0, 12.0, 2.0, 12.0),
doubleArrayOf(2.0, 2.0, 2.0, 14.0, 4.0, 14.0), doubleArrayOf(2.0, 2.0, 2.0, 14.0, 4.0, 14.0),
doubleArrayOf(0.0, 4.0, 0.0, 16.0, 6.0, 16.0), doubleArrayOf(0.0, 4.0, 0.0, 16.0, 6.0, 16.0),
doubleArrayOf(6.0, 6.0, 6.0, 10.0, 16.0, 10.0)
) )
val directions = arrayOf( val directions = arrayOf(
Triple(Direction.DOWN, null, false), Triple(Direction.DOWN, null, false),
@ -83,34 +73,11 @@ class InserterBlock: DeviceBlock<InserterBlockEntity>(
} }
} }
override fun getNetworkConnectedSides(state: BlockState, world: WorldAccess, pos: BlockPos): Collection<Direction> { override val faceThickness = 6.0
return EnumSet.of(state[FACING].opposite) override val faceShapes: Map<Direction, VoxelShape> = INSERTER_SHAPES
}
override fun getNetworkInterfaceForSide(side: Direction, state: BlockState, world: WorldAccess, pos: BlockPos): Interface? {
return if (side == state[FACING].opposite) {
getBlockEntity(world, pos)
} else {
null
}
}
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
super.appendProperties(builder)
builder.add(FACING)
}
override fun createBlockEntity(world: BlockView) = InserterBlockEntity() override fun createBlockEntity(world: BlockView) = InserterBlockEntity()
override fun getPlacementState(context: ItemPlacementContext): BlockState {
val facing = if (context.player?.isSneaking == true) context.side.opposite else context.playerLookDirection.opposite
return defaultState.with(FACING, facing)
}
override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape {
return INSERTER_SHAPES[state[FACING]]!!
}
override fun onPlaced(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity?, stack: ItemStack) { override fun onPlaced(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity?, stack: ItemStack) {
if (!world.isClient) { if (!world.isClient) {
getBlockEntity(world, pos)!!.updateInventory() getBlockEntity(world, pos)!!.updateInventory()

View File

@ -10,6 +10,7 @@ import net.minecraft.nbt.CompoundTag
import net.minecraft.util.math.Direction import net.minecraft.util.math.Direction
import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.block.DeviceBlockEntity import net.shadowfacts.phycon.block.DeviceBlockEntity
import net.shadowfacts.phycon.block.FaceDeviceBlock
import net.shadowfacts.phycon.component.ActivationController import net.shadowfacts.phycon.component.ActivationController
import net.shadowfacts.phycon.component.ItemStackPacketHandler import net.shadowfacts.phycon.component.ItemStackPacketHandler
import net.shadowfacts.phycon.component.NetworkStackProvider import net.shadowfacts.phycon.component.NetworkStackProvider
@ -34,7 +35,7 @@ class InserterBlockEntity: DeviceBlockEntity(PhyBlockEntities.INSERTER),
} }
private val facing: Direction private val facing: Direction
get() = cachedState[InserterBlock.FACING] get() = cachedState[FaceDeviceBlock.FACING]
private var inventory: ItemInsertable? = null private var inventory: ItemInsertable? = null
private var currentRequest: PendingExtractRequest? = null private var currentRequest: PendingExtractRequest? = null

View File

@ -18,7 +18,6 @@ import net.minecraft.world.WorldAccess
import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.PhysicalConnectivity
import net.shadowfacts.phycon.api.Interface import net.shadowfacts.phycon.api.Interface
import net.shadowfacts.phycon.block.DeviceBlock import net.shadowfacts.phycon.block.DeviceBlock
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
import java.util.* import java.util.*
/** /**
@ -56,7 +55,7 @@ class MinerBlock: DeviceBlock<MinerBlockEntity>(
override fun getPlacementState(context: ItemPlacementContext): BlockState? { override fun getPlacementState(context: ItemPlacementContext): BlockState? {
val facing = if (context.player?.isSneaking == true) context.side.opposite else context.playerFacing.opposite val facing = if (context.player?.isSneaking == true) context.side.opposite else context.playerFacing.opposite
return defaultState.with(ExtractorBlock.FACING, facing) return defaultState.with(FACING, facing)
} }
override fun onPlaced(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity?, itemStack: ItemStack) { override fun onPlaced(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity?, itemStack: ItemStack) {

View File

@ -17,6 +17,7 @@ import net.minecraft.text.LiteralText
import net.minecraft.text.Text import net.minecraft.text.Text
import net.minecraft.text.TranslatableText import net.minecraft.text.TranslatableText
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.math.MathHelper
import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.PhysicalConnectivity
import net.shadowfacts.phycon.networking.C2STerminalRequestItem import net.shadowfacts.phycon.networking.C2STerminalRequestItem
import net.shadowfacts.phycon.networking.C2STerminalUpdateDisplayedItems import net.shadowfacts.phycon.networking.C2STerminalUpdateDisplayedItems
@ -28,6 +29,7 @@ import java.lang.NumberFormatException
import kotlin.math.ceil import kotlin.math.ceil
import kotlin.math.floor import kotlin.math.floor
import kotlin.math.min import kotlin.math.min
import kotlin.math.roundToInt
/** /**
* @author shadowfacts * @author shadowfacts
@ -59,6 +61,15 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
} }
private var dialogChildren = mutableListOf<AbstractButtonWidget>() private var dialogChildren = mutableListOf<AbstractButtonWidget>()
private var scrollPosition = 0f
private var isDraggingScrollThumb = false
private val trackMinY = 18
private val trackHeight = 106
private val thumbHeight = 15
private val thumbWidth = 12
private val scrollThumbTop: Int
get() = trackMinY + (scrollPosition * (trackHeight - thumbHeight)).roundToInt()
private val dialogWidth = 158 private val dialogWidth = 158
private val dialogHeight = 62 private val dialogHeight = 62
@ -150,7 +161,7 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
private fun requestUpdatedItems() { private fun requestUpdatedItems() {
val player = MinecraftClient.getInstance().player!! val player = MinecraftClient.getInstance().player!!
player.networkHandler.sendPacket(C2STerminalUpdateDisplayedItems(handler.terminal, searchBox.text, sortButton.mode)) player.networkHandler.sendPacket(C2STerminalUpdateDisplayedItems(handler.terminal, searchBox.text, sortButton.mode, scrollPosition))
} }
override fun tick() { override fun tick() {
@ -176,6 +187,9 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
val x = (width - backgroundWidth) / 2 val x = (width - backgroundWidth) / 2
val y = (height - backgroundHeight) / 2 val y = (height - backgroundHeight) / 2
drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight) drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight)
// scroll thumb
drawTexture(matrixStack, x + 232, y + scrollThumbTop, 52, 230, thumbWidth, thumbHeight)
} }
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
@ -227,6 +241,16 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
DrawableHelper.fill(matrixStack, slot.x, slot.y, slot.x + 16, slot.y + 16, color.toInt()) DrawableHelper.fill(matrixStack, slot.x, slot.y, slot.x + 16, slot.y + 16, color.toInt())
} }
private fun isPointInsScrollThumb(mouseX: Double, mouseY: Double): Boolean {
val x = (width - backgroundWidth) / 2
val y = (height - backgroundHeight) / 2
val thumbMinX = x + 232
val thumbMaxX = thumbMinX + thumbWidth
val thumbMinY = y + scrollThumbTop
val thumbMaxY = thumbMinY + thumbHeight
return mouseX >= thumbMinX && mouseX < thumbMaxX && mouseY >= thumbMinY && mouseY < thumbMaxY
}
override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, type: SlotActionType?) { override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, type: SlotActionType?) {
super.onMouseClick(slot, invSlot, clickData, type) super.onMouseClick(slot, invSlot, clickData, type)
@ -261,15 +285,25 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
} }
return false return false
} else { } else {
if (isPointInsScrollThumb(mouseX, mouseY)) {
isDraggingScrollThumb = true
return true
}
return super.mouseClicked(mouseX, mouseY, button) return super.mouseClicked(mouseX, mouseY, button)
} }
} }
override fun mouseDragged(d: Double, e: Double, i: Int, f: Double, g: Double): Boolean { override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
if (showingAmountDialog) { if (showingAmountDialog) {
return false return false
} else if (isDraggingScrollThumb) {
scrollPosition = (mouseY.toFloat() - (y + trackMinY) - 7.5f) / (trackHeight - 15)
scrollPosition = MathHelper.clamp(scrollPosition, 0f, 1f)
requestUpdatedItems()
return true
} else { } else {
return super.mouseDragged(d, e, i, f, g) return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
} }
} }
@ -284,15 +318,23 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
if (showingAmountDialog) { if (showingAmountDialog) {
return false return false
} else { } else {
isDraggingScrollThumb = false
return super.mouseReleased(d, e, i) return super.mouseReleased(d, e, i)
} }
} }
override fun mouseScrolled(d: Double, e: Double, f: Double): Boolean { override fun mouseScrolled(mouseX: Double, mouseY: Double, amount: Double): Boolean {
if (showingAmountDialog) { if (showingAmountDialog) {
return false return false
} else { } else {
return super.mouseScrolled(d, e, f) var newOffsetInRows = handler.currentScrollOffsetInRows() - amount.toInt()
newOffsetInRows = MathHelper.clamp(newOffsetInRows, 0, handler.maxScrollOffsetInRows())
val newScrollPosition = newOffsetInRows / handler.maxScrollOffsetInRows().toFloat()
scrollPosition = newScrollPosition
requestUpdatedItems()
return super.mouseScrolled(mouseX, mouseY, amount)
} }
} }
@ -303,6 +345,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) {
scrollPosition = 0f
requestUpdatedItems() requestUpdatedItems()
} }
return true return true
@ -331,6 +374,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) {
scrollPosition = 0f
requestUpdatedItems() requestUpdatedItems()
} }
return true return true

View File

@ -17,7 +17,10 @@ import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems
import net.shadowfacts.phycon.util.SortMode import net.shadowfacts.phycon.util.SortMode
import net.shadowfacts.phycon.util.copyWithCount import net.shadowfacts.phycon.util.copyWithCount
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.min import kotlin.math.min
import kotlin.math.roundToInt
/** /**
* @author shadowfacts * @author shadowfacts
@ -29,10 +32,15 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
val ID = Identifier(PhysicalConnectivity.MODID, "terminal") val ID = Identifier(PhysicalConnectivity.MODID, "terminal")
} }
private val rowsDisplayed = 6
private val fakeInv = FakeInventory(this) private val fakeInv = FakeInventory(this)
private var searchQuery: String = "" private var searchQuery: String = ""
var sortMode = SortMode.COUNT_HIGH_FIRST var sortMode = SortMode.COUNT_HIGH_FIRST
private set private set
var totalEntries = 0
private set
private var scrollPosition = 0f
private var itemEntries = listOf<Entry>() private var itemEntries = listOf<Entry>()
set(value) { set(value) {
field = value field = value
@ -96,6 +104,8 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
it.key.name.string.contains(searchQuery, true) it.key.name.string.contains(searchQuery, true)
} }
totalEntries = filtered.size
val sorted = val sorted =
when (sortMode) { when (sortMode) {
SortMode.COUNT_HIGH_FIRST -> filtered.sortedByDescending { it.intValue } SortMode.COUNT_HIGH_FIRST -> filtered.sortedByDescending { it.intValue }
@ -103,22 +113,46 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
SortMode.ALPHABETICAL -> filtered.sortedBy { it.key.name.string } 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)) val offsetInItems = currentScrollOffsetInItems()
val end = min(offsetInItems + rowsDisplayed * 9, sorted.size)
itemEntries = sorted.subList(offsetInItems, end).map { Entry(it.key, it.intValue) }
// itemEntries = sorted.map { Entry(it.key, it.intValue) }
(player as ServerPlayerEntity).networkHandler.sendPacket(S2CTerminalUpdateDisplayedItems(terminal, itemEntries, searchQuery, sortMode, scrollPosition, totalEntries))
} }
fun sendUpdatedItemsToClient(player: ServerPlayerEntity, query: String, sortMode: SortMode) { fun totalRows(): Int {
return ceil(totalEntries / 9f).toInt()
}
fun maxScrollOffsetInRows(): Int {
return totalRows() - rowsDisplayed
}
fun currentScrollOffsetInRows(): Int {
return max(0, (scrollPosition * maxScrollOffsetInRows()).roundToInt())
}
fun currentScrollOffsetInItems(): Int {
return currentScrollOffsetInRows() * 9
}
fun sendUpdatedItemsToClient(player: ServerPlayerEntity, query: String, sortMode: SortMode, scrollPosition: Float) {
this.searchQuery = query this.searchQuery = query
this.sortMode = sortMode this.sortMode = sortMode
this.scrollPosition = scrollPosition
netItemsChanged() netItemsChanged()
} }
fun receivedUpdatedItemsFromServer(entries: List<Entry>, query: String, sortMode: SortMode) { fun receivedUpdatedItemsFromServer(entries: List<Entry>, query: String, sortMode: SortMode, scrollPosition: Float, totalEntries: Int) {
assert(playerInv.player.world.isClient) assert(playerInv.player.world.isClient)
this.searchQuery = query this.searchQuery = query
this.sortMode = sortMode this.sortMode = sortMode
this.scrollPosition = scrollPosition
this.totalEntries = totalEntries
itemEntries = entries itemEntries = entries
} }

View File

@ -19,6 +19,10 @@ class PhyModelProvider(resourceManager: ResourceManager) : ModelResourceProvider
val REDSTONE_CONTROLLER = Identifier(PhysicalConnectivity.MODID, "block/redstone_controller") val REDSTONE_CONTROLLER = Identifier(PhysicalConnectivity.MODID, "block/redstone_controller")
val REDSTONE_EMITTER = Identifier(PhysicalConnectivity.MODID, "block/redstone_emitter") val REDSTONE_EMITTER = Identifier(PhysicalConnectivity.MODID, "block/redstone_emitter")
val REDSTONE_EMITTER_SIDE = Identifier(PhysicalConnectivity.MODID, "block/redstone_emitter_side") val REDSTONE_EMITTER_SIDE = Identifier(PhysicalConnectivity.MODID, "block/redstone_emitter_side")
val EXTRACTOR = Identifier(PhysicalConnectivity.MODID, "block/extractor")
val EXTRACTOR_SIDE = Identifier(PhysicalConnectivity.MODID, "block/extractor_side")
val INSERTER = Identifier(PhysicalConnectivity.MODID, "block/inserter")
val INSERTER_SIDE = Identifier(PhysicalConnectivity.MODID, "block/inserter_side")
} }
override fun loadModelResource(resourceId: Identifier, context: ModelProviderContext): UnbakedModel? { override fun loadModelResource(resourceId: Identifier, context: ModelProviderContext): UnbakedModel? {
@ -26,6 +30,8 @@ class PhyModelProvider(resourceManager: ResourceManager) : ModelResourceProvider
INTERFACE -> SimpleFaceDeviceModel(INTERFACE_SIDE) INTERFACE -> SimpleFaceDeviceModel(INTERFACE_SIDE)
REDSTONE_CONTROLLER -> RedstoneControllerModel REDSTONE_CONTROLLER -> RedstoneControllerModel
REDSTONE_EMITTER -> SimpleFaceDeviceModel(REDSTONE_EMITTER_SIDE) REDSTONE_EMITTER -> SimpleFaceDeviceModel(REDSTONE_EMITTER_SIDE)
EXTRACTOR -> SimpleFaceDeviceModel(EXTRACTOR_SIDE)
INSERTER -> SimpleFaceDeviceModel(INSERTER_SIDE)
else -> null else -> null
} }
} }

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

@ -1,5 +1,6 @@
package net.shadowfacts.phycon.item package net.shadowfacts.phycon.item
import net.minecraft.block.BlockState
import net.minecraft.block.Blocks import net.minecraft.block.Blocks
import net.minecraft.entity.ItemEntity import net.minecraft.entity.ItemEntity
import net.minecraft.item.Item import net.minecraft.item.Item
@ -9,9 +10,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
@ -22,36 +26,85 @@ class ScrewdriverItem: Item(Settings()) {
} }
override fun useOnBlock(context: ItemUsageContext): ActionResult { override fun useOnBlock(context: ItemUsageContext): ActionResult {
if (context.player?.isSneaking != true) return ActionResult.PASS
val state = context.world.getBlockState(context.blockPos) val state = context.world.getBlockState(context.blockPos)
val block = state.block val block = state.block
if (block is DeviceBlock<*>) {
if (!context.world.isClient) {
val be = block.getBlockEntity(context.world, context.blockPos)!!
val stack = ItemStack(block) val newState =
val beTag = stack.getOrCreateSubTag("BlockEntityTag") when (block) {
be.toTag(beTag) is DeviceBlock<*> -> screwdriverDeviceBlock(context, state, block)
// remove x, y, z entries for stacking purposes PhyBlocks.CABLE -> screwdriverCableBlock(context)
beTag.remove("x") PhyBlocks.SWITCH -> screwdriverSwitchBlock(context)
beTag.remove("y") else -> null
beTag.remove("z")
if (block === PhyBlocks.TERMINAL) {
// remove the terminal's internal buffer since it drops its items
beTag.remove("InternalBuffer")
}
val entity = ItemEntity(context.world, context.blockPos.x.toDouble(), context.blockPos.y.toDouble(), context.blockPos.z.toDouble(), stack)
context.world.spawnEntity(entity)
context.world.setBlockState(context.blockPos, Blocks.AIR.defaultState, 3, 512)
} }
if (newState != null) {
context.world.setBlockState(context.blockPos, newState)
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)
return ActionResult.SUCCESS return ActionResult.SUCCESS
} else { } else {
return ActionResult.PASS return ActionResult.PASS
} }
} }
private fun screwdriverDeviceBlock(context: ItemUsageContext, state: BlockState, block: DeviceBlock<*>): BlockState? {
if (!context.world.isClient) {
val be = block.getBlockEntity(context.world, context.blockPos)!!
val stack = ItemStack(block)
val beTag = stack.getOrCreateSubTag("BlockEntityTag")
be.toTag(beTag)
// remove x, y, z entries for stacking purposes
beTag.remove("x")
beTag.remove("y")
beTag.remove("z")
if (block === PhyBlocks.TERMINAL) {
// remove the terminal's internal buffer since it drops its items
beTag.remove("InternalBuffer")
}
val entity = ItemEntity(context.world, context.blockPos.x.toDouble(), context.blockPos.y.toDouble(), context.blockPos.z.toDouble(), stack)
context.world.spawnEntity(entity)
}
return if (block is FaceDeviceBlock<*>) {
screwdriverFaceDeviceBlock(context, state, block)
} else {
Blocks.AIR.defaultState
}
}
private fun screwdriverFaceDeviceBlock(context: ItemUsageContext, state: BlockState, block: FaceDeviceBlock<*>): BlockState? {
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)) {
return PhyBlocks.CABLE.getInitialState(context.world, context.blockPos)
} else {
if (!context.world.isClient) {
val cable = ItemEntity(context.world, context.blockPos.x.toDouble(), context.blockPos.y.toDouble(), context.blockPos.z.toDouble(), ItemStack(PhyBlocks.CABLE))
context.world.spawnEntity(cable)
}
return Blocks.AIR.defaultState
}
}
private fun screwdriverCableBlock(context: ItemUsageContext): BlockState? {
if (!context.world.isClient) {
val entity = ItemEntity(context.world, context.blockPos.x.toDouble(), context.blockPos.y.toDouble(), context.blockPos.z.toDouble(), ItemStack(PhyBlocks.CABLE))
context.world.spawnEntity(entity)
}
return Blocks.AIR.defaultState
}
private fun screwdriverSwitchBlock(context: ItemUsageContext): BlockState? {
if (!context.world.isClient) {
val entity = ItemEntity(context.world, context.blockPos.x.toDouble(), context.blockPos.y.toDouble(), context.blockPos.z.toDouble(), ItemStack(PhyBlocks.SWITCH))
context.world.spawnEntity(entity)
}
return Blocks.AIR.defaultState
}
} }

View File

@ -21,7 +21,7 @@ object C2STerminalUpdateDisplayedItems: ServerReceiver {
override val CHANNEL = Identifier(PhysicalConnectivity.MODID, "terminal_update_displayed") override val CHANNEL = Identifier(PhysicalConnectivity.MODID, "terminal_update_displayed")
operator fun invoke(terminal: TerminalBlockEntity, query: String, sortMode: SortMode): Packet<*> { operator fun invoke(terminal: TerminalBlockEntity, query: String, sortMode: SortMode, scrollPosition: Float): Packet<*> {
val buf = PacketByteBufs.create() val buf = PacketByteBufs.create()
buf.writeIdentifier(terminal.world!!.registryKey.value) buf.writeIdentifier(terminal.world!!.registryKey.value)
@ -29,6 +29,7 @@ object C2STerminalUpdateDisplayedItems: ServerReceiver {
buf.writeString(query) buf.writeString(query)
buf.writeVarInt(sortMode.ordinal) buf.writeVarInt(sortMode.ordinal)
buf.writeFloat(scrollPosition)
return ClientPlayNetworking.createC2SPacket(CHANNEL, buf) return ClientPlayNetworking.createC2SPacket(CHANNEL, buf)
} }
@ -38,13 +39,14 @@ object C2STerminalUpdateDisplayedItems: ServerReceiver {
val pos = buf.readBlockPos() val pos = buf.readBlockPos()
val query = buf.readString() val query = buf.readString()
val sortMode = SortMode.values()[buf.readVarInt()] val sortMode = SortMode.values()[buf.readVarInt()]
val scrollPosition = buf.readFloat()
server.execute { server.execute {
if (player.world.registryKey.value != dimID) return@execute if (player.world.registryKey.value != dimID) return@execute
val screenHandler = player.currentScreenHandler val screenHandler = player.currentScreenHandler
if (screenHandler !is TerminalScreenHandler) return@execute if (screenHandler !is TerminalScreenHandler) return@execute
if (screenHandler.terminal.pos != pos) return@execute if (screenHandler.terminal.pos != pos) return@execute
screenHandler.sendUpdatedItemsToClient(player, query, sortMode) screenHandler.sendUpdatedItemsToClient(player, query, sortMode, scrollPosition)
} }
} }
} }

View File

@ -17,7 +17,7 @@ import net.shadowfacts.phycon.util.SortMode
object S2CTerminalUpdateDisplayedItems: ClientReceiver { object S2CTerminalUpdateDisplayedItems: ClientReceiver {
override val CHANNEL = C2STerminalUpdateDisplayedItems.CHANNEL override val CHANNEL = C2STerminalUpdateDisplayedItems.CHANNEL
operator fun invoke(terminal: TerminalBlockEntity, entries: List<TerminalScreenHandler.Entry>, query: String, sortMode: SortMode): Packet<*> { operator fun invoke(terminal: TerminalBlockEntity, entries: List<TerminalScreenHandler.Entry>, query: String, sortMode: SortMode, scrollPosition: Float, totalEntries: Int): Packet<*> {
val buf = PacketByteBufs.create() val buf = PacketByteBufs.create()
buf.writeIdentifier(terminal.world!!.registryKey.value) buf.writeIdentifier(terminal.world!!.registryKey.value)
@ -31,6 +31,8 @@ object S2CTerminalUpdateDisplayedItems: ClientReceiver {
buf.writeString(query) buf.writeString(query)
buf.writeVarInt(sortMode.ordinal) buf.writeVarInt(sortMode.ordinal)
buf.writeFloat(scrollPosition)
buf.writeInt(totalEntries)
return ServerPlayNetworking.createS2CPacket(CHANNEL, buf) return ServerPlayNetworking.createS2CPacket(CHANNEL, buf)
} }
@ -45,13 +47,15 @@ object S2CTerminalUpdateDisplayedItems: ClientReceiver {
} }
val query = buf.readString() val query = buf.readString()
val sortMode = SortMode.values()[buf.readVarInt()] val sortMode = SortMode.values()[buf.readVarInt()]
val scrollPosition = buf.readFloat()
val totalEntries = buf.readInt()
client.execute { client.execute {
if (client.player!!.world.registryKey.value != dimID) return@execute if (client.player!!.world.registryKey.value != dimID) return@execute
val screenHandler = client.player!!.currentScreenHandler val screenHandler = client.player!!.currentScreenHandler
if (screenHandler !is TerminalScreenHandler) return@execute if (screenHandler !is TerminalScreenHandler) return@execute
if (screenHandler.terminal.pos != pos) return@execute if (screenHandler.terminal.pos != pos) return@execute
screenHandler.receivedUpdatedItemsFromServer(entries, query, sortMode) screenHandler.receivedUpdatedItemsFromServer(entries, query, sortMode, scrollPosition, totalEntries)
} }
} }
} }

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

@ -1,29 +1,7 @@
{ {
"variants": { "multipart": [
"facing=down": { {
"model": "phycon:block/extractor" "apply": {"model": "phycon:block/extractor"}
},
"facing=up": {
"model": "phycon:block/extractor",
"x": 180
},
"facing=north": {
"model": "phycon:block/extractor",
"x": 270
},
"facing=south": {
"model": "phycon:block/extractor",
"x": 90
},
"facing=west": {
"model": "phycon:block/extractor",
"x": 90,
"y": 90
},
"facing=east": {
"model": "phycon:block/extractor",
"x": 90,
"y": 270
} }
} ]
} }

View File

@ -1,29 +1,7 @@
{ {
"variants": { "multipart": [
"facing=down": { {
"model": "phycon:block/inserter" "apply": {"model": "phycon:block/inserter"}
},
"facing=up": {
"model": "phycon:block/inserter",
"x": 180
},
"facing=north": {
"model": "phycon:block/inserter",
"x": 270
},
"facing=south": {
"model": "phycon:block/inserter",
"x": 90
},
"facing=west": {
"model": "phycon:block/inserter",
"x": 90,
"y": 90
},
"facing=east": {
"model": "phycon:block/inserter",
"x": 90,
"y": 270
} }
} ]
} }

View File

@ -1,8 +1,6 @@
{ {
"parent": "block/block", "parent": "block/block",
"textures": { "textures": {
"cable_side": "phycon:block/cable_straight",
"cable_end": "phycon:block/cable_cap_end"
}, },
"elements": [ "elements": [
{ {
@ -38,17 +36,6 @@
"west": {"texture": "phycon:block/extractor_side"}, "west": {"texture": "phycon:block/extractor_side"},
"east": {"texture": "phycon:block/extractor_side"} "east": {"texture": "phycon:block/extractor_side"}
} }
},
{
"from": [6, 6, 6],
"to": [10, 16, 10],
"faces": {
"up": {"texture": "#cable_end", "cullface": "up"},
"north": {"texture": "#cable_side"},
"south": {"texture": "#cable_side"},
"west": {"texture": "#cable_side"},
"east": {"texture": "#cable_side"}
}
} }
] ]
} }

View File

@ -1,8 +1,6 @@
{ {
"parent": "block/block", "parent": "block/block",
"textures": { "textures": {
"cable_side": "phycon:block/cable_straight",
"cable_end": "phycon:block/cable_cap_end"
}, },
"elements": [ "elements": [
{ {
@ -38,17 +36,6 @@
"west": {"texture": "phycon:block/extractor_side"}, "west": {"texture": "phycon:block/extractor_side"},
"east": {"texture": "phycon:block/extractor_side"} "east": {"texture": "phycon:block/extractor_side"}
} }
},
{
"from": [6, 6, 6],
"to": [10, 16, 10],
"faces": {
"up": {"texture": "#cable_end", "cullface": "up"},
"north": {"texture": "#cable_side"},
"south": {"texture": "#cable_side"},
"west": {"texture": "#cable_side"},
"east": {"texture": "#cable_side"}
}
} }
] ]
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 11 KiB

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"
}
]
} }
] ]
} }