Add Inserter
This commit is contained in:
parent
9b4fc548e5
commit
e13154943e
|
@ -16,7 +16,7 @@ import java.util.*
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class CacaoHandledScreen<Handler: ScreenHandler>(
|
open class CacaoHandledScreen<Handler: ScreenHandler>(
|
||||||
handler: Handler,
|
handler: Handler,
|
||||||
playerInv: PlayerInventory,
|
playerInv: PlayerInventory,
|
||||||
title: Text,
|
title: Text,
|
||||||
|
@ -90,4 +90,4 @@ class CacaoHandledScreen<Handler: ScreenHandler>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ object PhysicalConnectivity: ModInitializer {
|
||||||
registerGlobalReceiver(C2STerminalUpdateDisplayedItems)
|
registerGlobalReceiver(C2STerminalUpdateDisplayedItems)
|
||||||
registerGlobalReceiver(C2SConfigureActivationMode)
|
registerGlobalReceiver(C2SConfigureActivationMode)
|
||||||
registerGlobalReceiver(C2SConfigureRedstoneController)
|
registerGlobalReceiver(C2SConfigureRedstoneController)
|
||||||
|
registerGlobalReceiver(C2SConfigureInserterAmount)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerGlobalReceiver(receiver: ServerReceiver) {
|
private fun registerGlobalReceiver(receiver: ServerReceiver) {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap
|
||||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking
|
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.block.inserter.InserterScreen
|
||||||
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.block.terminal.TerminalScreen
|
import net.shadowfacts.phycon.block.terminal.TerminalScreen
|
||||||
|
@ -17,9 +18,8 @@ import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems
|
||||||
object PhysicalConnectivityClient: ClientModInitializer {
|
object PhysicalConnectivityClient: ClientModInitializer {
|
||||||
|
|
||||||
override fun onInitializeClient() {
|
override fun onInitializeClient() {
|
||||||
BlockRenderLayerMap.INSTANCE.putBlock(PhyBlocks.CABLE, RenderLayer.getTranslucent())
|
|
||||||
|
|
||||||
ScreenRegistry.register(PhyScreens.TERMINAL_SCREEN_HANDLER, ::TerminalScreen)
|
ScreenRegistry.register(PhyScreens.TERMINAL_SCREEN_HANDLER, ::TerminalScreen)
|
||||||
|
ScreenRegistry.register(PhyScreens.INSERTER_SCREEN_HANDLER, ::InserterScreen)
|
||||||
|
|
||||||
registerGlobalReceiver(S2CTerminalUpdateDisplayedItems)
|
registerGlobalReceiver(S2CTerminalUpdateDisplayedItems)
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ class ExtractorBlock: DeviceBlock<ExtractorBlockEntity>(Settings.of(Material.MET
|
||||||
override fun createBlockEntity(world: BlockView) = ExtractorBlockEntity()
|
override fun createBlockEntity(world: BlockView) = ExtractorBlockEntity()
|
||||||
|
|
||||||
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.playerLookDirection.opposite
|
||||||
return defaultState.with(FACING, facing)
|
return defaultState.with(FACING, facing)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
package net.shadowfacts.phycon.block.inserter
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.block.Material
|
||||||
|
import net.minecraft.block.ShapeContext
|
||||||
|
import net.minecraft.entity.LivingEntity
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.entity.player.PlayerInventory
|
||||||
|
import net.minecraft.item.ItemPlacementContext
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.network.PacketByteBuf
|
||||||
|
import net.minecraft.screen.ScreenHandler
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity
|
||||||
|
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.Hand
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.minecraft.util.hit.BlockHitResult
|
||||||
|
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.PhysicalConnectivity
|
||||||
|
import net.shadowfacts.phycon.api.Interface
|
||||||
|
import net.shadowfacts.phycon.block.DeviceBlock
|
||||||
|
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class InserterBlock: DeviceBlock<InserterBlockEntity>(Settings.of(Material.METAL)) {
|
||||||
|
companion object {
|
||||||
|
val ID = Identifier(PhysicalConnectivity.MODID, "inserter")
|
||||||
|
val FACING = Properties.FACING
|
||||||
|
private val INSERTER_SHAPES = mutableMapOf<Direction, VoxelShape>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
val components = arrayOf(
|
||||||
|
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(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(
|
||||||
|
Triple(Direction.DOWN, null, false),
|
||||||
|
Triple(Direction.UP, null, true),
|
||||||
|
Triple(Direction.NORTH, 2, false),
|
||||||
|
Triple(Direction.SOUTH, 2, true),
|
||||||
|
Triple(Direction.WEST, 1, false),
|
||||||
|
Triple(Direction.EAST, 1, true),
|
||||||
|
)
|
||||||
|
for ((dir, rotate, flip) in directions) {
|
||||||
|
val shapes = components.map { it ->
|
||||||
|
val arr = it.copyOf()
|
||||||
|
if (rotate != null) {
|
||||||
|
for (i in 0 until 3) {
|
||||||
|
arr[i] = it[(i + rotate) % 3]
|
||||||
|
arr[3 + i] = it[3 + ((i + rotate) % 3)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flip) {
|
||||||
|
for (i in arr.indices) {
|
||||||
|
arr[i] = 16.0 - arr[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
createCuboidShape(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5])
|
||||||
|
}
|
||||||
|
INSERTER_SHAPES[dir] = shapes.reduce { a, b -> VoxelShapes.union(a, b) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getNetworkConnectedSides(state: BlockState, world: WorldAccess, pos: BlockPos): Collection<Direction> {
|
||||||
|
return EnumSet.of(state[FACING].opposite)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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) {
|
||||||
|
if (!world.isClient) {
|
||||||
|
getBlockEntity(world, pos)!!.updateInventory()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun neighborUpdate(state: BlockState, world: World, pos: BlockPos, neighborBlock: Block, neighborPos: BlockPos, bl: Boolean) {
|
||||||
|
if (!world.isClient) {
|
||||||
|
getBlockEntity(world, pos)!!.updateInventory()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUse(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hitResult: BlockHitResult): ActionResult {
|
||||||
|
if (!world.isClient) {
|
||||||
|
val be = getBlockEntity(world, pos)!!
|
||||||
|
|
||||||
|
be.sync()
|
||||||
|
|
||||||
|
val factory = object: ExtendedScreenHandlerFactory {
|
||||||
|
override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler {
|
||||||
|
return InserterScreenHandler(syncId, playerInv, be)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getDisplayName() = this@InserterBlock.name
|
||||||
|
|
||||||
|
override fun writeScreenOpeningData(player: ServerPlayerEntity, buf: PacketByteBuf) {
|
||||||
|
buf.writeBlockPos(be.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
player.openHandledScreen(factory)
|
||||||
|
}
|
||||||
|
return ActionResult.SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,168 @@
|
||||||
|
package net.shadowfacts.phycon.block.inserter
|
||||||
|
|
||||||
|
import alexiil.mc.lib.attributes.SearchOptions
|
||||||
|
import alexiil.mc.lib.attributes.Simulation
|
||||||
|
import alexiil.mc.lib.attributes.item.ItemAttributes
|
||||||
|
import alexiil.mc.lib.attributes.item.ItemInsertable
|
||||||
|
import alexiil.mc.lib.attributes.item.ItemStackUtil
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
import net.minecraft.util.math.Direction
|
||||||
|
import net.shadowfacts.phycon.api.packet.Packet
|
||||||
|
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||||
|
import net.shadowfacts.phycon.component.ActivationController
|
||||||
|
import net.shadowfacts.phycon.component.ItemStackPacketHandler
|
||||||
|
import net.shadowfacts.phycon.component.NetworkStackProvider
|
||||||
|
import net.shadowfacts.phycon.component.handleItemStack
|
||||||
|
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||||
|
import net.shadowfacts.phycon.packet.*
|
||||||
|
import net.shadowfacts.phycon.util.ActivationMode
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class InserterBlockEntity: DeviceBlockEntity(PhyBlockEntities.INSERTER),
|
||||||
|
ItemStackPacketHandler,
|
||||||
|
ActivationController.ActivatableDevice {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val SLEEP_TIME = 40L
|
||||||
|
val REQUEST_TIMEOUT = 40
|
||||||
|
}
|
||||||
|
|
||||||
|
private val facing: Direction
|
||||||
|
get() = cachedState[InserterBlock.FACING]
|
||||||
|
|
||||||
|
private var inventory: ItemInsertable? = null
|
||||||
|
private var currentRequest: PendingExtractRequest? = null
|
||||||
|
var stackToExtract = ItemStack.EMPTY
|
||||||
|
var amountToExtract = 1
|
||||||
|
override val controller = ActivationController(SLEEP_TIME, this)
|
||||||
|
|
||||||
|
fun updateInventory() {
|
||||||
|
val offsetPos = pos.offset(facing)
|
||||||
|
val option = SearchOptions.inDirection(facing)
|
||||||
|
inventory = ItemAttributes.INSERTABLE.getFirstOrNull(world, offsetPos, option)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getInventory(): ItemInsertable? {
|
||||||
|
if (inventory == null) updateInventory()
|
||||||
|
return inventory
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handle(packet: Packet) {
|
||||||
|
when (packet) {
|
||||||
|
is RemoteActivationPacket -> controller.handleRemoteActivation(packet)
|
||||||
|
is StackLocationPacket -> handleStackLocation(packet)
|
||||||
|
is ItemStackPacket -> handleItemStack(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doHandleItemStack(packet: ItemStackPacket): ItemStack {
|
||||||
|
val inventory = getInventory()
|
||||||
|
return if (inventory != null) {
|
||||||
|
inventory.attemptInsertion(packet.stack, Simulation.ACTION)
|
||||||
|
} else {
|
||||||
|
// no inventory, entire stack remains
|
||||||
|
packet.stack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleStackLocation(packet: StackLocationPacket) {
|
||||||
|
val request = currentRequest
|
||||||
|
if (request != null && ItemStackUtil.areEqualIgnoreAmounts(request.stack, packet.stack)) {
|
||||||
|
request.results.add(packet.amount to packet.stackProvider)
|
||||||
|
if (request.isFinishable(counter)) {
|
||||||
|
finishRequest()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tick() {
|
||||||
|
super.tick()
|
||||||
|
|
||||||
|
if (!world!!.isClient) {
|
||||||
|
controller.tick()
|
||||||
|
|
||||||
|
val request = currentRequest
|
||||||
|
if (request != null) {
|
||||||
|
if (request.isFinishable(counter)) {
|
||||||
|
finishRequest()
|
||||||
|
} else if (counter - request.timestamp >= REQUEST_TIMEOUT && request.totalAmount == 0) {
|
||||||
|
currentRequest = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun activate(): Boolean {
|
||||||
|
if (currentRequest != null || stackToExtract.isEmpty) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: configure me
|
||||||
|
currentRequest = PendingExtractRequest(stackToExtract, counter)
|
||||||
|
sendPacket(LocateStackPacket(stackToExtract, ipAddress))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun finishRequest() {
|
||||||
|
val request = currentRequest ?: return
|
||||||
|
|
||||||
|
// todo: dedup with TerminalBlockEntity.stackLocateRequestCompleted
|
||||||
|
val actualAmount = min(min(request.stack.maxCount, request.totalAmount), amountToExtract)
|
||||||
|
val sortedResults = request.results.sortedByDescending { it.first }.toMutableList()
|
||||||
|
var amountRequested = 0
|
||||||
|
while (amountRequested < actualAmount && sortedResults.isNotEmpty()) {
|
||||||
|
val (sourceAmount, source) = sortedResults.removeAt(0)
|
||||||
|
val amountToRequest = min(sourceAmount, actualAmount - amountRequested)
|
||||||
|
amountRequested += amountToRequest
|
||||||
|
sendPacket(ExtractStackPacket(request.stack, amountToRequest, ipAddress, source.ipAddress))
|
||||||
|
}
|
||||||
|
|
||||||
|
currentRequest = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toTag(tag: CompoundTag): CompoundTag {
|
||||||
|
tag.putString("ActivationMode", controller.activationMode.name)
|
||||||
|
tag.put("StackToExtract", stackToExtract.toTag(CompoundTag()))
|
||||||
|
tag.putInt("AmountToExtract", amountToExtract)
|
||||||
|
return super.toTag(tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromTag(state: BlockState, tag: CompoundTag) {
|
||||||
|
super.fromTag(state, tag)
|
||||||
|
controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode"))
|
||||||
|
stackToExtract = ItemStack.fromTag(tag.getCompound("StackToExtract"))
|
||||||
|
amountToExtract = tag.getInt("AmountToExtract")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toClientTag(tag: CompoundTag): CompoundTag {
|
||||||
|
tag.putString("ActivationMode", controller.activationMode.name)
|
||||||
|
tag.put("StackToExtract", stackToExtract.toTag(CompoundTag()))
|
||||||
|
tag.putInt("AmountToExtract", amountToExtract)
|
||||||
|
return super.toClientTag(tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromClientTag(tag: CompoundTag) {
|
||||||
|
super.fromClientTag(tag)
|
||||||
|
controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode"))
|
||||||
|
stackToExtract = ItemStack.fromTag(tag.getCompound("StackToExtract"))
|
||||||
|
amountToExtract = tag.getInt("AmountToExtract")
|
||||||
|
}
|
||||||
|
|
||||||
|
class PendingExtractRequest(
|
||||||
|
val stack: ItemStack,
|
||||||
|
val timestamp: Long,
|
||||||
|
var results: MutableSet<Pair<Int, NetworkStackProvider>> = mutableSetOf()
|
||||||
|
) {
|
||||||
|
val totalAmount: Int
|
||||||
|
get() = results.fold(0) { acc, (amount, _) -> acc + amount }
|
||||||
|
|
||||||
|
fun isFinishable(currentTimestamp: Long): Boolean {
|
||||||
|
return totalAmount >= stack.maxCount || (currentTimestamp - timestamp >= REQUEST_TIMEOUT && totalAmount > 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
package net.shadowfacts.phycon.block.inserter
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem
|
||||||
|
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||||
|
import net.minecraft.client.gui.widget.TextFieldWidget
|
||||||
|
import net.minecraft.client.util.math.MatrixStack
|
||||||
|
import net.minecraft.entity.player.PlayerInventory
|
||||||
|
import net.minecraft.screen.slot.Slot
|
||||||
|
import net.minecraft.screen.slot.SlotActionType
|
||||||
|
import net.minecraft.text.LiteralText
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
import net.minecraft.text.TranslatableText
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
import net.shadowfacts.phycon.networking.C2SConfigureInserterAmount
|
||||||
|
import java.lang.NumberFormatException
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class InserterScreen(
|
||||||
|
handler: InserterScreenHandler,
|
||||||
|
playerInv: PlayerInventory,
|
||||||
|
title: Text,
|
||||||
|
): HandledScreen<InserterScreenHandler>(
|
||||||
|
handler,
|
||||||
|
playerInv,
|
||||||
|
title
|
||||||
|
) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val BACKGROUND = Identifier(PhysicalConnectivity.MODID, "textures/gui/inserter.png")
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var amountField: TextFieldWidget
|
||||||
|
|
||||||
|
init {
|
||||||
|
backgroundWidth = 176
|
||||||
|
backgroundHeight = 133
|
||||||
|
playerInventoryTitleY = backgroundHeight - 94
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun init() {
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
amountField = TextFieldWidget(textRenderer, x + 57, y + 24, 80, 9, LiteralText("Amount"))
|
||||||
|
amountField.text = handler.inserter.amountToExtract.toString()
|
||||||
|
amountField.setHasBorder(false)
|
||||||
|
amountField.isVisible = true
|
||||||
|
amountField.setSelected(true)
|
||||||
|
amountField.setEditableColor(0xffffff)
|
||||||
|
amountField.setTextPredicate {
|
||||||
|
if (it.isEmpty()) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
val value = Integer.parseInt(it)
|
||||||
|
value in 1..64
|
||||||
|
} catch (e: NumberFormatException) {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addChild(amountField)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun amountUpdated() {
|
||||||
|
if (amountField.text.isNotEmpty()) {
|
||||||
|
handler.inserter.amountToExtract = Integer.parseInt(amountField.text)
|
||||||
|
client!!.player!!.networkHandler.sendPacket(C2SConfigureInserterAmount(handler.inserter))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tick() {
|
||||||
|
super.tick()
|
||||||
|
amountField.tick()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) {
|
||||||
|
RenderSystem.color4f(1f, 1f, 1f, 1f)
|
||||||
|
client!!.textureManager.bindTexture(BACKGROUND)
|
||||||
|
val x = (width - backgroundWidth) / 2
|
||||||
|
val y = (height - backgroundHeight) / 2
|
||||||
|
drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) {
|
||||||
|
super.render(matrixStack, mouseX, mouseY, delta)
|
||||||
|
|
||||||
|
amountField.render(matrixStack, mouseX, mouseY, delta)
|
||||||
|
|
||||||
|
drawMouseoverTooltip(matrixStack, mouseX, mouseY)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, slotActionType: SlotActionType?) {
|
||||||
|
super.onMouseClick(slot, invSlot, clickData, slotActionType)
|
||||||
|
|
||||||
|
amountField.setSelected(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun charTyped(c: Char, i: Int): Boolean {
|
||||||
|
val oldText = amountField.text
|
||||||
|
if (amountField.charTyped(c, i)) {
|
||||||
|
if (oldText != amountField.text) {
|
||||||
|
amountUpdated()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.charTyped(c, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun keyPressed(i: Int, j: Int, k: Int): Boolean {
|
||||||
|
val oldText = amountField.text
|
||||||
|
if (amountField.keyPressed(i, j, k)) {
|
||||||
|
if (oldText != amountField.text) {
|
||||||
|
amountUpdated()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.keyPressed(i, j, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
package net.shadowfacts.phycon.block.inserter
|
||||||
|
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.entity.player.PlayerInventory
|
||||||
|
import net.minecraft.inventory.Inventory
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.network.PacketByteBuf
|
||||||
|
import net.minecraft.screen.ScreenHandler
|
||||||
|
import net.minecraft.screen.slot.Slot
|
||||||
|
import net.minecraft.screen.slot.SlotActionType
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
import net.shadowfacts.phycon.init.PhyBlocks
|
||||||
|
import net.shadowfacts.phycon.init.PhyScreens
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class InserterScreenHandler(
|
||||||
|
syncId: Int,
|
||||||
|
playerInv: PlayerInventory,
|
||||||
|
val inserter: InserterBlockEntity,
|
||||||
|
): ScreenHandler(PhyScreens.INSERTER_SCREEN_HANDLER, syncId) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val ID = Identifier(PhysicalConnectivity.MODID, "inserter")
|
||||||
|
}
|
||||||
|
|
||||||
|
private val fakeInv = FakeInventory(inserter)
|
||||||
|
|
||||||
|
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf):
|
||||||
|
this(
|
||||||
|
syncId,
|
||||||
|
playerInv,
|
||||||
|
PhyBlocks.INSERTER.getBlockEntity(playerInv.player.world, buf.readBlockPos())!!
|
||||||
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
// fake slot
|
||||||
|
addSlot(FakeSlot(fakeInv, 31, 20))
|
||||||
|
|
||||||
|
// player inv
|
||||||
|
for (y in 0 until 3) {
|
||||||
|
for (x in 0 until 9) {
|
||||||
|
addSlot(Slot(playerInv, x + y * 9 + 9, 8 + x * 18, 51 + y * 18))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hotbar
|
||||||
|
for (x in 0 until 9) {
|
||||||
|
addSlot(Slot(playerInv, x, 8 + x * 18, 109))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stackToExtractChanged() {
|
||||||
|
inserter.amountToExtract = min(inserter.stackToExtract.maxCount, inserter.amountToExtract)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canUse(player: PlayerEntity): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSlotClick(slotId: Int, clickData: Int, actionType: SlotActionType, player: PlayerEntity): ItemStack {
|
||||||
|
// fake slot
|
||||||
|
if (slotId == 0) {
|
||||||
|
if (player.inventory.cursorStack.isEmpty) {
|
||||||
|
inserter.stackToExtract = ItemStack.EMPTY
|
||||||
|
} else {
|
||||||
|
val copy = player.inventory.cursorStack.copy()
|
||||||
|
copy.count = 1
|
||||||
|
inserter.stackToExtract = copy
|
||||||
|
}
|
||||||
|
stackToExtractChanged()
|
||||||
|
}
|
||||||
|
return super.onSlotClick(slotId, clickData, actionType, player)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun transferSlot(player: PlayerEntity, slotId: Int): ItemStack {
|
||||||
|
val slot = slots[slotId]
|
||||||
|
val copy = slot.stack.copy()
|
||||||
|
copy.count = 1
|
||||||
|
inserter.stackToExtract = copy
|
||||||
|
stackToExtractChanged()
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeSlot(inv: FakeInventory, x: Int, y: Int): Slot(inv, 0, x, y) {
|
||||||
|
override fun canInsert(stack: ItemStack) = false
|
||||||
|
|
||||||
|
override fun setStack(stack: ItemStack) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canTakeItems(player: PlayerEntity) = false
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeInventory(val inserter: InserterBlockEntity): Inventory {
|
||||||
|
override fun clear() {
|
||||||
|
inserter.stackToExtract = ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun size() = 1
|
||||||
|
|
||||||
|
override fun isEmpty() = inserter.stackToExtract.isEmpty
|
||||||
|
|
||||||
|
override fun getStack(i: Int): ItemStack {
|
||||||
|
return if (i == 0) inserter.stackToExtract else ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeStack(i: Int, j: Int) = ItemStack.EMPTY
|
||||||
|
|
||||||
|
override fun removeStack(i: Int) = ItemStack.EMPTY
|
||||||
|
|
||||||
|
override fun setStack(i: Int, itemStack: ItemStack?) {}
|
||||||
|
|
||||||
|
override fun markDirty() {}
|
||||||
|
|
||||||
|
override fun canPlayerUse(playerEntity: PlayerEntity?) = true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -183,7 +183,7 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
||||||
inventoryCache.clear()
|
inventoryCache.clear()
|
||||||
sendPacket(RequestInventoryPacket(ipAddress))
|
sendPacket(RequestInventoryPacket(ipAddress))
|
||||||
val factory = object: ExtendedScreenHandlerFactory {
|
val factory = object: ExtendedScreenHandlerFactory {
|
||||||
override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler? {
|
override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler {
|
||||||
return TerminalScreenHandler(syncId, playerInv, this@TerminalBlockEntity)
|
return TerminalScreenHandler(syncId, playerInv, this@TerminalBlockEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ import net.minecraft.util.Identifier
|
||||||
import net.minecraft.util.registry.Registry
|
import net.minecraft.util.registry.Registry
|
||||||
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
|
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
|
||||||
import net.shadowfacts.phycon.block.extractor.ExtractorBlockEntity
|
import net.shadowfacts.phycon.block.extractor.ExtractorBlockEntity
|
||||||
|
import net.shadowfacts.phycon.block.inserter.InserterBlock
|
||||||
|
import net.shadowfacts.phycon.block.inserter.InserterBlockEntity
|
||||||
import net.shadowfacts.phycon.block.miner.MinerBlock
|
import net.shadowfacts.phycon.block.miner.MinerBlock
|
||||||
import net.shadowfacts.phycon.block.miner.MinerBlockEntity
|
import net.shadowfacts.phycon.block.miner.MinerBlockEntity
|
||||||
import net.shadowfacts.phycon.block.netinterface.InterfaceBlock
|
import net.shadowfacts.phycon.block.netinterface.InterfaceBlock
|
||||||
|
@ -27,6 +29,7 @@ object PhyBlockEntities {
|
||||||
val TERMINAL = create(::TerminalBlockEntity, PhyBlocks.TERMINAL)
|
val TERMINAL = create(::TerminalBlockEntity, PhyBlocks.TERMINAL)
|
||||||
val SWITCH = create(::SwitchBlockEntity, PhyBlocks.SWITCH)
|
val SWITCH = create(::SwitchBlockEntity, PhyBlocks.SWITCH)
|
||||||
val EXTRACTOR = create(::ExtractorBlockEntity, PhyBlocks.EXTRACTOR)
|
val EXTRACTOR = create(::ExtractorBlockEntity, PhyBlocks.EXTRACTOR)
|
||||||
|
val INSERTER = create(::InserterBlockEntity, PhyBlocks.INSERTER)
|
||||||
val MINER = create(::MinerBlockEntity, PhyBlocks.MINER)
|
val MINER = create(::MinerBlockEntity, PhyBlocks.MINER)
|
||||||
val REDSTONE_CONTROLLER = create(::RedstoneControllerBlockEntity, PhyBlocks.REDSTONE_CONTROLLER)
|
val REDSTONE_CONTROLLER = create(::RedstoneControllerBlockEntity, PhyBlocks.REDSTONE_CONTROLLER)
|
||||||
|
|
||||||
|
@ -39,6 +42,7 @@ object PhyBlockEntities {
|
||||||
register(TerminalBlock.ID, TERMINAL)
|
register(TerminalBlock.ID, TERMINAL)
|
||||||
register(SwitchBlock.ID, SWITCH)
|
register(SwitchBlock.ID, SWITCH)
|
||||||
register(ExtractorBlock.ID, EXTRACTOR)
|
register(ExtractorBlock.ID, EXTRACTOR)
|
||||||
|
register(InserterBlock.ID, INSERTER)
|
||||||
register(MinerBlock.ID, MINER)
|
register(MinerBlock.ID, MINER)
|
||||||
register(RedstoneControllerBlock.ID, REDSTONE_CONTROLLER)
|
register(RedstoneControllerBlock.ID, REDSTONE_CONTROLLER)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import net.minecraft.util.Identifier
|
||||||
import net.minecraft.util.registry.Registry
|
import net.minecraft.util.registry.Registry
|
||||||
import net.shadowfacts.phycon.block.cable.CableBlock
|
import net.shadowfacts.phycon.block.cable.CableBlock
|
||||||
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
|
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
|
||||||
|
import net.shadowfacts.phycon.block.inserter.InserterBlock
|
||||||
import net.shadowfacts.phycon.block.miner.MinerBlock
|
import net.shadowfacts.phycon.block.miner.MinerBlock
|
||||||
import net.shadowfacts.phycon.block.netinterface.InterfaceBlock
|
import net.shadowfacts.phycon.block.netinterface.InterfaceBlock
|
||||||
import net.shadowfacts.phycon.block.netswitch.SwitchBlock
|
import net.shadowfacts.phycon.block.netswitch.SwitchBlock
|
||||||
|
@ -21,6 +22,7 @@ object PhyBlocks {
|
||||||
val SWITCH = SwitchBlock()
|
val SWITCH = SwitchBlock()
|
||||||
val CABLE = CableBlock()
|
val CABLE = CableBlock()
|
||||||
val EXTRACTOR = ExtractorBlock()
|
val EXTRACTOR = ExtractorBlock()
|
||||||
|
val INSERTER = InserterBlock()
|
||||||
val MINER = MinerBlock()
|
val MINER = MinerBlock()
|
||||||
val REDSTONE_CONTROLLER = RedstoneControllerBlock()
|
val REDSTONE_CONTROLLER = RedstoneControllerBlock()
|
||||||
|
|
||||||
|
@ -30,6 +32,7 @@ object PhyBlocks {
|
||||||
register(SwitchBlock.ID, SWITCH)
|
register(SwitchBlock.ID, SWITCH)
|
||||||
register(CableBlock.ID, CABLE)
|
register(CableBlock.ID, CABLE)
|
||||||
register(ExtractorBlock.ID, EXTRACTOR)
|
register(ExtractorBlock.ID, EXTRACTOR)
|
||||||
|
register(InserterBlock.ID, INSERTER)
|
||||||
register(MinerBlock.ID, MINER)
|
register(MinerBlock.ID, MINER)
|
||||||
register(RedstoneControllerBlock.ID, REDSTONE_CONTROLLER)
|
register(RedstoneControllerBlock.ID, REDSTONE_CONTROLLER)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import net.shadowfacts.phycon.item.ConsoleItem
|
||||||
import net.shadowfacts.phycon.item.ScrewdriverItem
|
import net.shadowfacts.phycon.item.ScrewdriverItem
|
||||||
import net.shadowfacts.phycon.block.cable.CableBlock
|
import net.shadowfacts.phycon.block.cable.CableBlock
|
||||||
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
|
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
|
||||||
|
import net.shadowfacts.phycon.block.inserter.InserterBlock
|
||||||
import net.shadowfacts.phycon.block.miner.MinerBlock
|
import net.shadowfacts.phycon.block.miner.MinerBlock
|
||||||
import net.shadowfacts.phycon.block.netinterface.InterfaceBlock
|
import net.shadowfacts.phycon.block.netinterface.InterfaceBlock
|
||||||
import net.shadowfacts.phycon.block.netswitch.SwitchBlock
|
import net.shadowfacts.phycon.block.netswitch.SwitchBlock
|
||||||
|
@ -24,6 +25,7 @@ object PhyItems {
|
||||||
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 = BlockItem(PhyBlocks.EXTRACTOR, Item.Settings())
|
val EXTRACTOR = BlockItem(PhyBlocks.EXTRACTOR, Item.Settings())
|
||||||
|
val INSERTER = BlockItem(PhyBlocks.INSERTER, Item.Settings())
|
||||||
val MINER = BlockItem(PhyBlocks.MINER, Item.Settings())
|
val MINER = BlockItem(PhyBlocks.MINER, Item.Settings())
|
||||||
val REDSTONE_CONTROLLER = BlockItem(PhyBlocks.REDSTONE_CONTROLLER, Item.Settings())
|
val REDSTONE_CONTROLLER = BlockItem(PhyBlocks.REDSTONE_CONTROLLER, Item.Settings())
|
||||||
|
|
||||||
|
@ -36,6 +38,7 @@ object PhyItems {
|
||||||
register(SwitchBlock.ID, SWITCH)
|
register(SwitchBlock.ID, SWITCH)
|
||||||
register(CableBlock.ID, CABLE)
|
register(CableBlock.ID, CABLE)
|
||||||
register(ExtractorBlock.ID, EXTRACTOR)
|
register(ExtractorBlock.ID, EXTRACTOR)
|
||||||
|
register(InserterBlock.ID, INSERTER)
|
||||||
register(MinerBlock.ID, MINER)
|
register(MinerBlock.ID, MINER)
|
||||||
register(RedstoneControllerBlock.ID, REDSTONE_CONTROLLER)
|
register(RedstoneControllerBlock.ID, REDSTONE_CONTROLLER)
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,19 @@ import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry
|
||||||
import net.minecraft.screen.ScreenHandlerType
|
import net.minecraft.screen.ScreenHandlerType
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
import net.shadowfacts.phycon.block.inserter.InserterScreenHandler
|
||||||
import net.shadowfacts.phycon.block.terminal.TerminalScreenHandler
|
import net.shadowfacts.phycon.block.terminal.TerminalScreenHandler
|
||||||
|
|
||||||
object PhyScreens {
|
object PhyScreens {
|
||||||
|
|
||||||
lateinit var TERMINAL_SCREEN_HANDLER: ScreenHandlerType<TerminalScreenHandler>
|
lateinit var TERMINAL_SCREEN_HANDLER: ScreenHandlerType<TerminalScreenHandler>
|
||||||
private set
|
private set
|
||||||
|
lateinit var INSERTER_SCREEN_HANDLER: ScreenHandlerType<InserterScreenHandler>
|
||||||
|
private set
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
TERMINAL_SCREEN_HANDLER = ScreenHandlerRegistry.registerExtended(Identifier(PhysicalConnectivity.MODID, "terminal"), ::TerminalScreenHandler)
|
TERMINAL_SCREEN_HANDLER = ScreenHandlerRegistry.registerExtended(TerminalScreenHandler.ID, ::TerminalScreenHandler)
|
||||||
|
INSERTER_SCREEN_HANDLER = ScreenHandlerRegistry.registerExtended(InserterScreenHandler.ID, ::InserterScreenHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package net.shadowfacts.phycon.networking
|
||||||
|
|
||||||
|
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.minecraft.util.registry.Registry
|
||||||
|
import net.minecraft.util.registry.RegistryKey
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
import net.shadowfacts.phycon.block.inserter.InserterBlockEntity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
object C2SConfigureInserterAmount: ServerReceiver {
|
||||||
|
override val CHANNEL = Identifier(PhysicalConnectivity.MODID, "configure_inserter_amount")
|
||||||
|
|
||||||
|
operator fun invoke(be: InserterBlockEntity): Packet<*> {
|
||||||
|
val buf = PacketByteBufs.create()
|
||||||
|
|
||||||
|
buf.writeIdentifier(be.world!!.registryKey.value)
|
||||||
|
buf.writeBlockPos(be.pos)
|
||||||
|
buf.writeVarInt(be.amountToExtract)
|
||||||
|
|
||||||
|
return createPacket(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun receive(server: MinecraftServer, player: ServerPlayerEntity, handler: ServerPlayNetworkHandler, buf: PacketByteBuf, responseSender: PacketSender) {
|
||||||
|
val dimID = buf.readIdentifier()
|
||||||
|
val pos = buf.readBlockPos()
|
||||||
|
val amount = buf.readVarInt()
|
||||||
|
|
||||||
|
server.execute {
|
||||||
|
val key = RegistryKey.of(Registry.DIMENSION, dimID)
|
||||||
|
val world = server.getWorld(key) ?: return@execute
|
||||||
|
val be = world.getBlockEntity(pos) as? InserterBlockEntity ?: return@execute
|
||||||
|
be.amountToExtract = amount
|
||||||
|
be.markDirty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"facing=down": {
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
"block.phycon.terminal": "Terminal",
|
"block.phycon.terminal": "Terminal",
|
||||||
"block.phycon.cable": "Cable",
|
"block.phycon.cable": "Cable",
|
||||||
"block.phycon.extractor": "Inventory Extractor",
|
"block.phycon.extractor": "Inventory Extractor",
|
||||||
|
"block.phycon.inserter": "Inventory Inserter",
|
||||||
"block.phycon.miner": "Block Miner",
|
"block.phycon.miner": "Block Miner",
|
||||||
"block.phycon.redstone_controller": "Redstone Controller",
|
"block.phycon.redstone_controller": "Redstone Controller",
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
{
|
{
|
||||||
"parent": "block/block",
|
"parent": "block/block",
|
||||||
|
"textures": {
|
||||||
|
"cable_side": "phycon:block/cable_straight",
|
||||||
|
"cable_end": "phycon:block/cable_cap_end"
|
||||||
|
},
|
||||||
"elements": [
|
"elements": [
|
||||||
{
|
{
|
||||||
"from": [0, 0, 0],
|
"from": [0, 0, 0],
|
||||||
"to": [16, 2, 16],
|
"to": [16, 2, 16],
|
||||||
"faces": {
|
"faces": {
|
||||||
"down": {"texture": "phycon:block/extractor_front"},
|
"down": {"texture": "phycon:block/extractor_front", "cullface": "down"},
|
||||||
"up": {"texture": "phycon:block/extractor_back"},
|
"up": {"texture": "phycon:block/extractor_back"},
|
||||||
"north": {"texture": "phycon:block/extractor_side"},
|
"north": {"texture": "phycon:block/extractor_side"},
|
||||||
"south": {"texture": "phycon:block/extractor_side"},
|
"south": {"texture": "phycon:block/extractor_side"},
|
||||||
|
@ -39,12 +43,12 @@
|
||||||
"from": [6, 6, 6],
|
"from": [6, 6, 6],
|
||||||
"to": [10, 16, 10],
|
"to": [10, 16, 10],
|
||||||
"faces": {
|
"faces": {
|
||||||
"up": {"texture": "phycon:block/cable_side"},
|
"up": {"texture": "#cable_end", "cullface": "up"},
|
||||||
"north": {"texture": "phycon:block/cable_side"},
|
"north": {"texture": "#cable_side"},
|
||||||
"south": {"texture": "phycon:block/cable_side"},
|
"south": {"texture": "#cable_side"},
|
||||||
"west": {"texture": "phycon:block/cable_side"},
|
"west": {"texture": "#cable_side"},
|
||||||
"east": {"texture": "phycon:block/cable_side"}
|
"east": {"texture": "#cable_side"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
"parent": "block/block",
|
||||||
|
"textures": {
|
||||||
|
"cable_side": "phycon:block/cable_straight",
|
||||||
|
"cable_end": "phycon:block/cable_cap_end"
|
||||||
|
},
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"from": [4, 0, 4],
|
||||||
|
"to": [12, 2, 12],
|
||||||
|
"faces": {
|
||||||
|
"down": {"texture": "phycon:block/extractor_front", "cullface": "down"},
|
||||||
|
"north": {"texture": "phycon:block/extractor_side"},
|
||||||
|
"south": {"texture": "phycon:block/extractor_side"},
|
||||||
|
"west": {"texture": "phycon:block/extractor_side"},
|
||||||
|
"east": {"texture": "phycon:block/extractor_side"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [2, 2, 2],
|
||||||
|
"to": [14, 4, 14],
|
||||||
|
"faces": {
|
||||||
|
"down": {"texture": "phycon:block/extractor_front"},
|
||||||
|
"north": {"texture": "phycon:block/extractor_side"},
|
||||||
|
"south": {"texture": "phycon:block/extractor_side"},
|
||||||
|
"west": {"texture": "phycon:block/extractor_side"},
|
||||||
|
"east": {"texture": "phycon:block/extractor_side"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [0, 4, 0],
|
||||||
|
"to": [16, 6, 16],
|
||||||
|
"faces": {
|
||||||
|
"down": {"texture": "phycon:block/extractor_front"},
|
||||||
|
"up": {"texture": "phycon:block/extractor_back"},
|
||||||
|
"north": {"texture": "phycon:block/extractor_side"},
|
||||||
|
"south": {"texture": "phycon:block/extractor_side"},
|
||||||
|
"west": {"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.
After Width: | Height: | Size: 6.1 KiB |
Loading…
Reference in New Issue