Add Crafting Terminal
This commit is contained in:
parent
e4662b0f6f
commit
9d98481ba5
|
@ -26,9 +26,10 @@ object PhysicalConnectivity: ModInitializer {
|
||||||
PhyItems.init()
|
PhyItems.init()
|
||||||
PhyScreens.init()
|
PhyScreens.init()
|
||||||
|
|
||||||
|
registerGlobalReceiver(C2SConfigureDevice)
|
||||||
|
registerGlobalReceiver(C2STerminalCraftingButton)
|
||||||
registerGlobalReceiver(C2STerminalRequestItem)
|
registerGlobalReceiver(C2STerminalRequestItem)
|
||||||
registerGlobalReceiver(C2STerminalUpdateDisplayedItems)
|
registerGlobalReceiver(C2STerminalUpdateDisplayedItems)
|
||||||
registerGlobalReceiver(C2SConfigureDevice)
|
|
||||||
|
|
||||||
for (it in FabricLoader.getInstance().getEntrypoints("phycon", PhyConPlugin::class.java)) {
|
for (it in FabricLoader.getInstance().getEntrypoints("phycon", PhyConPlugin::class.java)) {
|
||||||
it.initializePhyCon(PhyConAPIImpl)
|
it.initializePhyCon(PhyConAPIImpl)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import net.fabricmc.fabric.api.renderer.v1.RendererAccess
|
||||||
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial
|
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial
|
||||||
import net.shadowfacts.phycon.block.inserter.InserterScreen
|
import net.shadowfacts.phycon.block.inserter.InserterScreen
|
||||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterScreen
|
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterScreen
|
||||||
|
import net.shadowfacts.phycon.block.terminal.CraftingTerminalScreen
|
||||||
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
|
||||||
import net.shadowfacts.phycon.client.PhyExtendedModelProvider
|
import net.shadowfacts.phycon.client.PhyExtendedModelProvider
|
||||||
|
@ -40,6 +41,7 @@ object PhysicalConnectivityClient: ClientModInitializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
ScreenRegistry.register(PhyScreens.TERMINAL, ::TerminalScreen)
|
ScreenRegistry.register(PhyScreens.TERMINAL, ::TerminalScreen)
|
||||||
|
ScreenRegistry.register(PhyScreens.CRAFTING_TERMINAL, ::CraftingTerminalScreen)
|
||||||
ScreenRegistry.register(PhyScreens.INSERTER, ::InserterScreen)
|
ScreenRegistry.register(PhyScreens.INSERTER, ::InserterScreen)
|
||||||
ScreenRegistry.register(PhyScreens.REDSTONE_EMITTER, ::RedstoneEmitterScreen)
|
ScreenRegistry.register(PhyScreens.REDSTONE_EMITTER, ::RedstoneEmitterScreen)
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>): DeviceBloc
|
||||||
protected val inventoryCache = mutableMapOf<IPAddress, GroupedItemInvView>()
|
protected val inventoryCache = mutableMapOf<IPAddress, GroupedItemInvView>()
|
||||||
val internalBuffer = TerminalBufferInventory(18)
|
val internalBuffer = TerminalBufferInventory(18)
|
||||||
|
|
||||||
private val pendingRequests = LinkedList<StackLocateRequest>()
|
protected val pendingRequests = LinkedList<StackLocateRequest>()
|
||||||
override val pendingInsertions = mutableListOf<PendingInsertion>()
|
override val pendingInsertions = mutableListOf<PendingInsertion>()
|
||||||
override val dispatchStackTimeout = INSERTION_TIMEOUT
|
override val dispatchStackTimeout = INSERTION_TIMEOUT
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>): DeviceBloc
|
||||||
sendPacket(LocateStackPacket(stack, ipAddress))
|
sendPacket(LocateStackPacket(stack, ipAddress))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stackLocateRequestCompleted(request: StackLocateRequest) {
|
protected open fun stackLocateRequestCompleted(request: StackLocateRequest) {
|
||||||
pendingRequests.remove(request)
|
pendingRequests.remove(request)
|
||||||
|
|
||||||
val sortedResults = request.results.toMutableList()
|
val sortedResults = request.results.toMutableList()
|
||||||
|
@ -252,19 +252,20 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>): DeviceBloc
|
||||||
var bufferSlot by Delegates.notNull<Int>()
|
var bufferSlot by Delegates.notNull<Int>()
|
||||||
}
|
}
|
||||||
|
|
||||||
data class StackLocateRequest(
|
open class StackLocateRequest(
|
||||||
val stack: ItemStack,
|
val stack: ItemStack,
|
||||||
val amount: Int,
|
val amount: Int,
|
||||||
val timestamp: Long,
|
val timestamp: Long,
|
||||||
var results: MutableSet<Pair<Int, NetworkStackProvider>> = mutableSetOf()
|
|
||||||
) {
|
) {
|
||||||
|
var results: MutableSet<Pair<Int, NetworkStackProvider>> = mutableSetOf()
|
||||||
|
|
||||||
val totalResultAmount: Int
|
val totalResultAmount: Int
|
||||||
get() = results.fold(0) { acc, (amount, _) -> acc + amount }
|
get() = results.fold(0) { acc, (amount, _) -> acc + amount }
|
||||||
|
|
||||||
fun isFinishable(currentTimestamp: Long): Boolean {
|
fun isFinishable(currentTimestamp: Long): Boolean {
|
||||||
// we can't check totalResultAmount >= amount because we need to hear back from all network stack providers to
|
// we can't check totalResultAmount >= amount because we need to hear back from all network stack providers to
|
||||||
// correctly sort by priority
|
// correctly sort by priority
|
||||||
return currentTimestamp - timestamp >= AbstractTerminalBlockEntity.LOCATE_REQUEST_TIMEOUT
|
return currentTimestamp - timestamp >= LOCATE_REQUEST_TIMEOUT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,8 @@ abstract class AbstractTerminalScreenHandler<T: AbstractTerminalBlockEntity>(
|
||||||
var itemsForDisplay = listOf<ItemStack>()
|
var itemsForDisplay = listOf<ItemStack>()
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
open val xOffset: Int = 0
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (!terminal.world!!.isClient) {
|
if (!terminal.world!!.isClient) {
|
||||||
assert(terminal.netItemObserver?.get() === null)
|
assert(terminal.netItemObserver?.get() === null)
|
||||||
|
@ -63,29 +65,31 @@ abstract class AbstractTerminalScreenHandler<T: AbstractTerminalBlockEntity>(
|
||||||
// intentionally don't call netItemsChanged immediately, we need to wait for the client to send us its settings
|
// intentionally don't call netItemsChanged immediately, we need to wait for the client to send us its settings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val xOffset = xOffset
|
||||||
|
|
||||||
// network
|
// network
|
||||||
for (y in 0 until 6) {
|
for (y in 0 until 6) {
|
||||||
for (x in 0 until 9) {
|
for (x in 0 until 9) {
|
||||||
addSlot(TerminalFakeSlot(fakeInv, y * 9 + x, 66 + x * 18, 18 + y * 18))
|
addSlot(TerminalFakeSlot(fakeInv, y * 9 + x, xOffset + 66 + x * 18, 18 + y * 18))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal buffer
|
// internal buffer
|
||||||
for (y in 0 until 6) {
|
for (y in 0 until 6) {
|
||||||
for (x in 0 until 3) {
|
for (x in 0 until 3) {
|
||||||
addSlot(Slot(terminal.internalBuffer, y * 3 + x, 8 + x * 18, 18 + y * 18))
|
addSlot(Slot(terminal.internalBuffer, y * 3 + x, xOffset + 8 + x * 18, 18 + y * 18))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// player inv
|
// player inv
|
||||||
for (y in 0 until 3) {
|
for (y in 0 until 3) {
|
||||||
for (x in 0 until 9) {
|
for (x in 0 until 9) {
|
||||||
addSlot(Slot(playerInv, x + y * 9 + 9, 66 + x * 18, 140 + y * 18))
|
addSlot(Slot(playerInv, x + y * 9 + 9, xOffset + 66 + x * 18, 140 + y * 18))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// hotbar
|
// hotbar
|
||||||
for (x in 0 until 9) {
|
for (x in 0 until 9) {
|
||||||
addSlot(Slot(playerInv, x, 66 + x * 18, 198))
|
addSlot(Slot(playerInv, x, xOffset + 66 + x * 18, 198))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ abstract class AbstractTerminalViewController<BE: AbstractTerminalBlockEntity, S
|
||||||
|
|
||||||
buffer = view.addLayoutGuide()
|
buffer = view.addLayoutGuide()
|
||||||
view.solver.dsl {
|
view.solver.dsl {
|
||||||
buffer.leftAnchor equalTo (pane.leftAnchor + 7)
|
buffer.leftAnchor equalTo (pane.leftAnchor + 7 + handler.xOffset)
|
||||||
buffer.topAnchor equalTo (pane.topAnchor + 17)
|
buffer.topAnchor equalTo (pane.topAnchor + 17)
|
||||||
buffer.widthAnchor equalTo (18 * 3)
|
buffer.widthAnchor equalTo (18 * 3)
|
||||||
buffer.heightAnchor equalTo (18 * 6)
|
buffer.heightAnchor equalTo (18 * 6)
|
||||||
|
@ -72,7 +72,7 @@ abstract class AbstractTerminalViewController<BE: AbstractTerminalBlockEntity, S
|
||||||
|
|
||||||
network = view.addLayoutGuide()
|
network = view.addLayoutGuide()
|
||||||
view.solver.dsl {
|
view.solver.dsl {
|
||||||
network.leftAnchor equalTo (pane.leftAnchor + 65)
|
network.leftAnchor equalTo (pane.leftAnchor + 65 + handler.xOffset)
|
||||||
network.topAnchor equalTo buffer.topAnchor
|
network.topAnchor equalTo buffer.topAnchor
|
||||||
network.widthAnchor equalTo (18 * 9)
|
network.widthAnchor equalTo (18 * 9)
|
||||||
network.heightAnchor equalTo (18 * 6)
|
network.heightAnchor equalTo (18 * 6)
|
||||||
|
@ -122,12 +122,12 @@ abstract class AbstractTerminalViewController<BE: AbstractTerminalBlockEntity, S
|
||||||
playerInvLabel.leftAnchor equalTo playerInv.leftAnchor
|
playerInvLabel.leftAnchor equalTo playerInv.leftAnchor
|
||||||
playerInvLabel.topAnchor equalTo (pane.topAnchor + 128)
|
playerInvLabel.topAnchor equalTo (pane.topAnchor + 128)
|
||||||
|
|
||||||
searchField.leftAnchor equalTo (pane.leftAnchor + 138)
|
searchField.leftAnchor equalTo (pane.leftAnchor + 138 + handler.xOffset)
|
||||||
searchField.topAnchor equalTo (pane.topAnchor + 5)
|
searchField.topAnchor equalTo (pane.topAnchor + 5)
|
||||||
searchField.widthAnchor equalTo 80
|
searchField.widthAnchor equalTo 80
|
||||||
searchField.heightAnchor equalTo 9
|
searchField.heightAnchor equalTo 9
|
||||||
|
|
||||||
scrollTrack.leftAnchor equalTo (pane.leftAnchor + 232)
|
scrollTrack.leftAnchor equalTo (pane.leftAnchor + 232 + handler.xOffset)
|
||||||
scrollTrack.topAnchor equalTo (network.topAnchor + 1)
|
scrollTrack.topAnchor equalTo (network.topAnchor + 1)
|
||||||
scrollTrack.bottomAnchor equalTo (network.bottomAnchor - 1)
|
scrollTrack.bottomAnchor equalTo (network.bottomAnchor - 1)
|
||||||
scrollTrack.widthAnchor equalTo 12
|
scrollTrack.widthAnchor equalTo 12
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package net.shadowfacts.phycon.block.terminal
|
||||||
|
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.minecraft.world.BlockView
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class CraftingTerminalBlock: AbstractTerminalBlock<CraftingTerminalBlockEntity>() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val ID = Identifier(PhysicalConnectivity.MODID, "crafting_terminal")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createBlockEntity(world: BlockView) = CraftingTerminalBlockEntity()
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
package net.shadowfacts.phycon.block.terminal
|
||||||
|
|
||||||
|
import alexiil.mc.lib.attributes.item.ItemStackCollections
|
||||||
|
import alexiil.mc.lib.attributes.item.ItemStackUtil
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2IntMap
|
||||||
|
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.entity.player.PlayerInventory
|
||||||
|
import net.minecraft.inventory.CraftingInventory
|
||||||
|
import net.minecraft.inventory.SimpleInventory
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
import net.minecraft.network.PacketByteBuf
|
||||||
|
import net.minecraft.screen.ScreenHandler
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
import net.minecraft.text.TranslatableText
|
||||||
|
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||||
|
import net.shadowfacts.phycon.packet.ItemStackPacket
|
||||||
|
import net.shadowfacts.phycon.packet.LocateStackPacket
|
||||||
|
import net.shadowfacts.phycon.packet.RequestInventoryPacket
|
||||||
|
import net.shadowfacts.phycon.util.fromTag
|
||||||
|
import net.shadowfacts.phycon.util.toTag
|
||||||
|
import java.util.LinkedList
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class CraftingTerminalBlockEntity: AbstractTerminalBlockEntity(PhyBlockEntities.CRAFTING_TERMINAL) {
|
||||||
|
|
||||||
|
val craftingInv = SimpleInventory(9)
|
||||||
|
|
||||||
|
private val completedCraftingStackRequests = LinkedList<CraftingStackLocateRequest>()
|
||||||
|
|
||||||
|
override fun onActivate(player: PlayerEntity) {
|
||||||
|
if (!world!!.isClient) {
|
||||||
|
updateAndSync()
|
||||||
|
|
||||||
|
inventoryCache.clear()
|
||||||
|
sendPacket(RequestInventoryPacket(ipAddress))
|
||||||
|
val factory = object: ExtendedScreenHandlerFactory {
|
||||||
|
override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler? {
|
||||||
|
return CraftingTerminalScreenHandler(syncId, playerInv, this@CraftingTerminalBlockEntity)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getDisplayName() = TranslatableText("block.phycon.crafting_terminal")
|
||||||
|
|
||||||
|
override fun writeScreenOpeningData(player: ServerPlayerEntity, buf: PacketByteBuf) {
|
||||||
|
buf.writeBlockPos(this@CraftingTerminalBlockEntity.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
player.openHandledScreen(factory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requestItemsForCrafting(maxAmount: Int) {
|
||||||
|
val amounts = ItemStackCollections.map<IntArray>()
|
||||||
|
|
||||||
|
for (i in 0 until craftingInv.size()) {
|
||||||
|
val craftingInvStack = craftingInv.getStack(i)
|
||||||
|
if (craftingInvStack.isEmpty) continue
|
||||||
|
if (craftingInvStack.count >= craftingInvStack.maxCount) continue
|
||||||
|
|
||||||
|
if (craftingInvStack !in amounts) amounts[craftingInvStack] = IntArray(9) { 0 }
|
||||||
|
amounts[craftingInvStack]!![i] = min(maxAmount, craftingInvStack.maxCount - craftingInvStack.count)
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((stack, amountPerSlot) in amounts) {
|
||||||
|
val total = amountPerSlot.sum()
|
||||||
|
val request = CraftingStackLocateRequest(stack, total, counter, amountPerSlot)
|
||||||
|
pendingRequests.add(request)
|
||||||
|
sendPacket(LocateStackPacket(stack, ipAddress))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun stackLocateRequestCompleted(request: StackLocateRequest) {
|
||||||
|
if (request is CraftingStackLocateRequest) {
|
||||||
|
completedCraftingStackRequests.add(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
super.stackLocateRequestCompleted(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doHandleItemStack(packet: ItemStackPacket): ItemStack {
|
||||||
|
val craftingReq = completedCraftingStackRequests.find { ItemStackUtil.areEqualIgnoreAmounts(it.stack, packet.stack) }
|
||||||
|
if (craftingReq != null) {
|
||||||
|
var remaining = packet.stack.copy()
|
||||||
|
|
||||||
|
for (i in 0 until craftingInv.size()) {
|
||||||
|
val currentStack = craftingInv.getStack(i)
|
||||||
|
if (currentStack.count >= currentStack.maxCount) continue
|
||||||
|
if (!ItemStackUtil.areEqualIgnoreAmounts(currentStack, remaining)) continue
|
||||||
|
|
||||||
|
val toInsert = minOf(remaining.count, currentStack.maxCount - currentStack.count, craftingReq.amountPerSlot[i])
|
||||||
|
currentStack.count += toInsert
|
||||||
|
remaining.count -= toInsert
|
||||||
|
craftingReq.amountPerSlot[i] -= toInsert
|
||||||
|
craftingReq.received += toInsert
|
||||||
|
|
||||||
|
if (remaining.isEmpty) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (craftingReq.amountPerSlot.sum() == 0 || craftingReq.received >= craftingReq.totalResultAmount) {
|
||||||
|
completedCraftingStackRequests.remove(craftingReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!remaining.isEmpty) {
|
||||||
|
remaining = internalBuffer.insert(remaining, TerminalBufferInventory.Mode.FROM_NETWORK)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateAndSync()
|
||||||
|
|
||||||
|
return remaining
|
||||||
|
} else {
|
||||||
|
return super.doHandleItemStack(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toCommonTag(tag: CompoundTag) {
|
||||||
|
super.toCommonTag(tag)
|
||||||
|
tag.put("CraftingInv", craftingInv.toTag())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromCommonTag(tag: CompoundTag) {
|
||||||
|
super.fromCommonTag(tag)
|
||||||
|
craftingInv.fromTag(tag.getList("CraftingInv", 10))
|
||||||
|
}
|
||||||
|
|
||||||
|
class CraftingStackLocateRequest(
|
||||||
|
stack: ItemStack,
|
||||||
|
amount: Int,
|
||||||
|
timestamp: Long,
|
||||||
|
val amountPerSlot: IntArray,
|
||||||
|
): StackLocateRequest(stack, amount, timestamp) {
|
||||||
|
var received: Int = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package net.shadowfacts.phycon.block.terminal
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem
|
||||||
|
import net.minecraft.client.util.math.MatrixStack
|
||||||
|
import net.minecraft.entity.player.PlayerInventory
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class CraftingTerminalScreen(
|
||||||
|
handler: CraftingTerminalScreenHandler,
|
||||||
|
playerInv: PlayerInventory,
|
||||||
|
title: Text,
|
||||||
|
): AbstractTerminalScreen<CraftingTerminalBlockEntity, CraftingTerminalScreenHandler>(
|
||||||
|
handler,
|
||||||
|
playerInv,
|
||||||
|
title,
|
||||||
|
259,
|
||||||
|
252,
|
||||||
|
) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val BACKGROUND_1 = Identifier(PhysicalConnectivity.MODID, "textures/gui/crafting_terminal_1.png")
|
||||||
|
private val BACKGROUND_2 = Identifier(PhysicalConnectivity.MODID, "textures/gui/crafting_terminal_2.png")
|
||||||
|
}
|
||||||
|
|
||||||
|
override val backgroundTexture = BACKGROUND_1
|
||||||
|
|
||||||
|
override fun createViewController(): AbstractTerminalViewController<*, *, *> {
|
||||||
|
return CraftingTerminalViewController(this, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun drawBackgroundTexture(matrixStack: MatrixStack) {
|
||||||
|
RenderSystem.color4f(1f, 1f, 1f, 1f)
|
||||||
|
client!!.textureManager.bindTexture(BACKGROUND_1)
|
||||||
|
val x = (width - backgroundWidth) / 2
|
||||||
|
val y = (height - backgroundHeight) / 2
|
||||||
|
drawTexture(matrixStack, x, y, 0, 0, 256, 252)
|
||||||
|
|
||||||
|
client!!.textureManager.bindTexture(BACKGROUND_2)
|
||||||
|
drawTexture(matrixStack, x + 256, y, 0, 0, 3, 252)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
package net.shadowfacts.phycon.block.terminal
|
||||||
|
|
||||||
|
import alexiil.mc.lib.attributes.item.ItemStackCollections
|
||||||
|
import net.minecraft.entity.player.PlayerInventory
|
||||||
|
import net.minecraft.inventory.CraftingInventory
|
||||||
|
import net.minecraft.inventory.CraftingResultInventory
|
||||||
|
import net.minecraft.inventory.Inventory
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.network.PacketByteBuf
|
||||||
|
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket
|
||||||
|
import net.minecraft.recipe.RecipeFinder
|
||||||
|
import net.minecraft.recipe.RecipeType
|
||||||
|
import net.minecraft.screen.slot.CraftingResultSlot
|
||||||
|
import net.minecraft.screen.slot.Slot
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity
|
||||||
|
import net.shadowfacts.phycon.init.PhyBlocks
|
||||||
|
import net.shadowfacts.phycon.init.PhyScreens
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class CraftingTerminalScreenHandler(
|
||||||
|
syncId: Int,
|
||||||
|
playerInv: PlayerInventory,
|
||||||
|
terminal: CraftingTerminalBlockEntity,
|
||||||
|
): AbstractTerminalScreenHandler<CraftingTerminalBlockEntity>(PhyScreens.CRAFTING_TERMINAL, syncId, playerInv, terminal) {
|
||||||
|
|
||||||
|
val craftingInv = CraftingInv(this)
|
||||||
|
val result = CraftingResultInventory()
|
||||||
|
val resultSlot: CraftingResultSlot
|
||||||
|
|
||||||
|
override val xOffset: Int
|
||||||
|
get() = 5
|
||||||
|
|
||||||
|
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf):
|
||||||
|
this(
|
||||||
|
syncId,
|
||||||
|
playerInv,
|
||||||
|
PhyBlocks.CRAFTING_TERMINAL.getBlockEntity(playerInv.player.world, buf.readBlockPos())!!
|
||||||
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
for (y in 0 until 3) {
|
||||||
|
for (x in 0 until 3) {
|
||||||
|
this.addSlot(Slot(craftingInv, x + y * 3, 13 + x * 18, 140 + y * 18))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resultSlot = CraftingResultSlot(playerInv.player, craftingInv, result, 0, 31, 224)
|
||||||
|
addSlot(resultSlot)
|
||||||
|
|
||||||
|
updateCraftingResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onContentChanged(inventory: Inventory?) {
|
||||||
|
updateCraftingResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateCraftingResult() {
|
||||||
|
val world = playerInv.player.world
|
||||||
|
if (!world.isClient) {
|
||||||
|
val player = playerInv.player as ServerPlayerEntity
|
||||||
|
val recipe = world.server!!.recipeManager.getFirstMatch(RecipeType.CRAFTING, craftingInv, world)
|
||||||
|
val resultStack =
|
||||||
|
if (recipe.isPresent && result.shouldCraftRecipe(world, player, recipe.get())) {
|
||||||
|
recipe.get().craft(craftingInv)
|
||||||
|
} else {
|
||||||
|
ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
result.setStack(0, resultStack)
|
||||||
|
player.networkHandler.sendPacket(ScreenHandlerSlotUpdateS2CPacket(syncId, resultSlot.id, resultStack))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearCraftingGrid() {
|
||||||
|
assert(!playerInv.player.world.isClient)
|
||||||
|
for (i in 0 until terminal.craftingInv.size()) {
|
||||||
|
val craftingInvStack = terminal.craftingInv.getStack(i)
|
||||||
|
if (craftingInvStack.isEmpty) continue
|
||||||
|
val remainder = terminal.internalBuffer.insert(craftingInvStack, TerminalBufferInventory.Mode.TO_NETWORK)
|
||||||
|
terminal.craftingInv.setStack(i, remainder)
|
||||||
|
}
|
||||||
|
updateCraftingResult()
|
||||||
|
sendContentUpdates()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requestMoreCraftingIngredients(maxAmount: Int) {
|
||||||
|
assert(!playerInv.player.world.isClient)
|
||||||
|
terminal.requestItemsForCrafting(maxAmount)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecipeType.CRAFTING wants a CraftingInventory, but we can't store a CraftingInventory on the BE without a screen handler, so...
|
||||||
|
class CraftingInv(val handler: CraftingTerminalScreenHandler): CraftingInventory(handler, 3, 3) {
|
||||||
|
private val backing = handler.terminal.craftingInv
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean {
|
||||||
|
return backing.isEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getStack(i: Int): ItemStack {
|
||||||
|
return backing.getStack(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeStack(i: Int): ItemStack {
|
||||||
|
return backing.removeStack(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeStack(i: Int, j: Int): ItemStack {
|
||||||
|
val res = backing.removeStack(i, j)
|
||||||
|
if (!res.isEmpty) {
|
||||||
|
handler.onContentChanged(this)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setStack(i: Int, itemStack: ItemStack?) {
|
||||||
|
backing.setStack(i, itemStack)
|
||||||
|
handler.onContentChanged(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clear() {
|
||||||
|
backing.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun provideRecipeInputs(finder: RecipeFinder) {
|
||||||
|
TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
package net.shadowfacts.phycon.block.terminal
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient
|
||||||
|
import net.minecraft.client.util.InputUtil
|
||||||
|
import net.minecraft.text.TranslatableText
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.shadowfacts.cacao.geometry.Size
|
||||||
|
import net.shadowfacts.cacao.util.Color
|
||||||
|
import net.shadowfacts.cacao.util.LayoutGuide
|
||||||
|
import net.shadowfacts.cacao.util.texture.Texture
|
||||||
|
import net.shadowfacts.cacao.view.Label
|
||||||
|
import net.shadowfacts.cacao.view.TextureView
|
||||||
|
import net.shadowfacts.cacao.view.button.Button
|
||||||
|
import net.shadowfacts.kiwidsl.dsl
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
import net.shadowfacts.phycon.networking.C2STerminalCraftingButton
|
||||||
|
import org.lwjgl.glfw.GLFW
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class CraftingTerminalViewController(
|
||||||
|
screen: CraftingTerminalScreen,
|
||||||
|
handler: CraftingTerminalScreenHandler,
|
||||||
|
): AbstractTerminalViewController<CraftingTerminalBlockEntity, CraftingTerminalScreen, CraftingTerminalScreenHandler>(
|
||||||
|
screen,
|
||||||
|
handler,
|
||||||
|
) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val SMALL_BUTTON = Texture(Identifier(PhysicalConnectivity.MODID, "textures/gui/icons.png"), 0, 48)
|
||||||
|
val SMALL_BUTTON_HOVERED = Texture(Identifier(PhysicalConnectivity.MODID, "textures/gui/icons.png"), 16, 48)
|
||||||
|
val CLEAR_ICON = Texture(Identifier(PhysicalConnectivity.MODID, "textures/gui/icons.png"), 32, 48)
|
||||||
|
val PLUS_ICON = Texture(Identifier(PhysicalConnectivity.MODID, "textures/gui/icons.png"), 48, 48)
|
||||||
|
}
|
||||||
|
|
||||||
|
lateinit var craftingInv: LayoutGuide
|
||||||
|
|
||||||
|
override fun viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
craftingInv = view.addLayoutGuide()
|
||||||
|
view.solver.dsl {
|
||||||
|
craftingInv.leftAnchor equalTo buffer.leftAnchor
|
||||||
|
craftingInv.topAnchor equalTo playerInv.topAnchor
|
||||||
|
craftingInv.widthAnchor equalTo buffer.widthAnchor
|
||||||
|
craftingInv.heightAnchor equalTo 54
|
||||||
|
}
|
||||||
|
|
||||||
|
val craftingLabel = view.addSubview(Label(TranslatableText("gui.phycon.terminal_crafting"))).apply {
|
||||||
|
textColor = Color.TEXT
|
||||||
|
}
|
||||||
|
view.solver.dsl {
|
||||||
|
craftingLabel.leftAnchor equalTo craftingInv.leftAnchor
|
||||||
|
craftingLabel.topAnchor equalTo playerInvLabel.topAnchor
|
||||||
|
}
|
||||||
|
|
||||||
|
val clearIcon = TextureView(CLEAR_ICON).apply {
|
||||||
|
intrinsicContentSize = Size(3.0,3.0)
|
||||||
|
}
|
||||||
|
val clearButton = view.addSubview(Button(clearIcon, padding = 2.0, handler = ::clearPressed)).apply {
|
||||||
|
background = TextureView(SMALL_BUTTON)
|
||||||
|
hoveredBackground = TextureView(SMALL_BUTTON_HOVERED)
|
||||||
|
tooltip = TranslatableText("gui.phycon.terminal.clear_crafting")
|
||||||
|
}
|
||||||
|
view.solver.dsl {
|
||||||
|
clearButton.topAnchor equalTo craftingInv.topAnchor
|
||||||
|
clearButton.leftAnchor equalTo (pane.leftAnchor + 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
val plusIcon = TextureView(PLUS_ICON).apply {
|
||||||
|
intrinsicContentSize = Size(3.0, 3.0)
|
||||||
|
}
|
||||||
|
val plusButton = view.addSubview(Button(plusIcon, padding = 2.0, handler = ::plusPressed)).apply {
|
||||||
|
background= TextureView(SMALL_BUTTON)
|
||||||
|
hoveredBackground = TextureView(SMALL_BUTTON_HOVERED)
|
||||||
|
tooltip = TranslatableText("gui.phycon.terminal.more_crafting")
|
||||||
|
}
|
||||||
|
view.solver.dsl {
|
||||||
|
plusButton.topAnchor equalTo (clearButton.bottomAnchor + 2)
|
||||||
|
plusButton.leftAnchor equalTo clearButton.leftAnchor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun clearPressed(button: Button) {
|
||||||
|
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2STerminalCraftingButton(terminal, C2STerminalCraftingButton.Action.CLEAR_GRID))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun plusPressed(button: Button) {
|
||||||
|
val client = MinecraftClient.getInstance()
|
||||||
|
val action =
|
||||||
|
if (InputUtil.isKeyPressed(client.window.handle, GLFW.GLFW_KEY_LEFT_SHIFT) || InputUtil.isKeyPressed(client.window.handle, GLFW.GLFW_KEY_RIGHT_SHIFT)) {
|
||||||
|
C2STerminalCraftingButton.Action.REQUEST_MAX_MORE
|
||||||
|
} else {
|
||||||
|
C2STerminalCraftingButton.Action.REQUEST_ONE_MORE
|
||||||
|
}
|
||||||
|
client.player!!.networkHandler.sendPacket(C2STerminalCraftingButton(terminal, action))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -19,6 +19,8 @@ import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlock
|
||||||
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlockEntity
|
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlockEntity
|
||||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterBlock
|
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterBlock
|
||||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterBlockEntity
|
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterBlockEntity
|
||||||
|
import net.shadowfacts.phycon.block.terminal.CraftingTerminalBlock
|
||||||
|
import net.shadowfacts.phycon.block.terminal.CraftingTerminalBlockEntity
|
||||||
import net.shadowfacts.phycon.block.terminal.TerminalBlock
|
import net.shadowfacts.phycon.block.terminal.TerminalBlock
|
||||||
import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity
|
import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity
|
||||||
|
|
||||||
|
@ -29,6 +31,7 @@ object PhyBlockEntities {
|
||||||
|
|
||||||
val INTERFACE = create(::InterfaceBlockEntity, PhyBlocks.INTERFACE)
|
val INTERFACE = create(::InterfaceBlockEntity, PhyBlocks.INTERFACE)
|
||||||
val TERMINAL = create(::TerminalBlockEntity, PhyBlocks.TERMINAL)
|
val TERMINAL = create(::TerminalBlockEntity, PhyBlocks.TERMINAL)
|
||||||
|
val CRAFTING_TERMINAL = create(::CraftingTerminalBlockEntity, PhyBlocks.CRAFTING_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 INSERTER = create(::InserterBlockEntity, PhyBlocks.INSERTER)
|
||||||
|
@ -43,6 +46,7 @@ object PhyBlockEntities {
|
||||||
fun init() {
|
fun init() {
|
||||||
register(InterfaceBlock.ID, INTERFACE)
|
register(InterfaceBlock.ID, INTERFACE)
|
||||||
register(TerminalBlock.ID, TERMINAL)
|
register(TerminalBlock.ID, TERMINAL)
|
||||||
|
register(CraftingTerminalBlock.ID, CRAFTING_TERMINAL)
|
||||||
register(SwitchBlock.ID, SWITCH)
|
register(SwitchBlock.ID, SWITCH)
|
||||||
register(ExtractorBlock.ID, EXTRACTOR)
|
register(ExtractorBlock.ID, EXTRACTOR)
|
||||||
register(InserterBlock.ID, INSERTER)
|
register(InserterBlock.ID, INSERTER)
|
||||||
|
|
|
@ -13,6 +13,7 @@ import net.shadowfacts.phycon.block.netinterface.InterfaceBlock
|
||||||
import net.shadowfacts.phycon.block.netswitch.SwitchBlock
|
import net.shadowfacts.phycon.block.netswitch.SwitchBlock
|
||||||
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlock
|
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.CraftingTerminalBlock
|
||||||
import net.shadowfacts.phycon.block.terminal.TerminalBlock
|
import net.shadowfacts.phycon.block.terminal.TerminalBlock
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,6 +25,7 @@ object PhyBlocks {
|
||||||
|
|
||||||
val INTERFACE = InterfaceBlock()
|
val INTERFACE = InterfaceBlock()
|
||||||
val TERMINAL = TerminalBlock()
|
val TERMINAL = TerminalBlock()
|
||||||
|
val CRAFTING_TERMINAL = CraftingTerminalBlock()
|
||||||
val SWITCH = SwitchBlock()
|
val SWITCH = SwitchBlock()
|
||||||
val EXTRACTOR = ExtractorBlock()
|
val EXTRACTOR = ExtractorBlock()
|
||||||
val INSERTER = InserterBlock()
|
val INSERTER = InserterBlock()
|
||||||
|
@ -38,6 +40,7 @@ object PhyBlocks {
|
||||||
|
|
||||||
register(InterfaceBlock.ID, INTERFACE)
|
register(InterfaceBlock.ID, INTERFACE)
|
||||||
register(TerminalBlock.ID, TERMINAL)
|
register(TerminalBlock.ID, TERMINAL)
|
||||||
|
register(CraftingTerminalBlock.ID, CRAFTING_TERMINAL)
|
||||||
register(SwitchBlock.ID, SWITCH)
|
register(SwitchBlock.ID, SWITCH)
|
||||||
register(ExtractorBlock.ID, EXTRACTOR)
|
register(ExtractorBlock.ID, EXTRACTOR)
|
||||||
register(InserterBlock.ID, INSERTER)
|
register(InserterBlock.ID, INSERTER)
|
||||||
|
|
|
@ -14,6 +14,7 @@ import net.shadowfacts.phycon.block.netinterface.InterfaceBlock
|
||||||
import net.shadowfacts.phycon.block.netswitch.SwitchBlock
|
import net.shadowfacts.phycon.block.netswitch.SwitchBlock
|
||||||
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlock
|
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.CraftingTerminalBlock
|
||||||
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
|
import net.shadowfacts.phycon.item.FaceDeviceBlockItem
|
||||||
|
@ -29,6 +30,7 @@ object PhyItems {
|
||||||
|
|
||||||
val INTERFACE = FaceDeviceBlockItem(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 CRAFTING_TERMINAL = DeviceBlockItem(PhyBlocks.CRAFTING_TERMINAL, Item.Settings())
|
||||||
val SWITCH = BlockItem(PhyBlocks.SWITCH, Item.Settings())
|
val SWITCH = BlockItem(PhyBlocks.SWITCH, Item.Settings())
|
||||||
val EXTRACTOR = FaceDeviceBlockItem(PhyBlocks.EXTRACTOR, Item.Settings())
|
val EXTRACTOR = FaceDeviceBlockItem(PhyBlocks.EXTRACTOR, Item.Settings())
|
||||||
val INSERTER = FaceDeviceBlockItem(PhyBlocks.INSERTER, Item.Settings())
|
val INSERTER = FaceDeviceBlockItem(PhyBlocks.INSERTER, Item.Settings())
|
||||||
|
@ -52,6 +54,7 @@ object PhyItems {
|
||||||
|
|
||||||
register(InterfaceBlock.ID, INTERFACE)
|
register(InterfaceBlock.ID, INTERFACE)
|
||||||
register(TerminalBlock.ID, TERMINAL)
|
register(TerminalBlock.ID, TERMINAL)
|
||||||
|
register(CraftingTerminalBlock.ID, CRAFTING_TERMINAL)
|
||||||
register(SwitchBlock.ID, SWITCH)
|
register(SwitchBlock.ID, SWITCH)
|
||||||
register(ExtractorBlock.ID, EXTRACTOR)
|
register(ExtractorBlock.ID, EXTRACTOR)
|
||||||
register(InserterBlock.ID, INSERTER)
|
register(InserterBlock.ID, INSERTER)
|
||||||
|
|
|
@ -4,6 +4,8 @@ import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry
|
||||||
import net.minecraft.screen.ScreenHandlerType
|
import net.minecraft.screen.ScreenHandlerType
|
||||||
import net.shadowfacts.phycon.block.inserter.InserterScreenHandler
|
import net.shadowfacts.phycon.block.inserter.InserterScreenHandler
|
||||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterScreenHandler
|
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterScreenHandler
|
||||||
|
import net.shadowfacts.phycon.block.terminal.CraftingTerminalBlock
|
||||||
|
import net.shadowfacts.phycon.block.terminal.CraftingTerminalScreenHandler
|
||||||
import net.shadowfacts.phycon.block.terminal.TerminalBlock
|
import net.shadowfacts.phycon.block.terminal.TerminalBlock
|
||||||
import net.shadowfacts.phycon.block.terminal.TerminalScreenHandler
|
import net.shadowfacts.phycon.block.terminal.TerminalScreenHandler
|
||||||
|
|
||||||
|
@ -11,6 +13,8 @@ object PhyScreens {
|
||||||
|
|
||||||
lateinit var TERMINAL: ScreenHandlerType<TerminalScreenHandler>
|
lateinit var TERMINAL: ScreenHandlerType<TerminalScreenHandler>
|
||||||
private set
|
private set
|
||||||
|
lateinit var CRAFTING_TERMINAL: ScreenHandlerType<CraftingTerminalScreenHandler>
|
||||||
|
private set
|
||||||
lateinit var INSERTER: ScreenHandlerType<InserterScreenHandler>
|
lateinit var INSERTER: ScreenHandlerType<InserterScreenHandler>
|
||||||
private set
|
private set
|
||||||
lateinit var REDSTONE_EMITTER: ScreenHandlerType<RedstoneEmitterScreenHandler>
|
lateinit var REDSTONE_EMITTER: ScreenHandlerType<RedstoneEmitterScreenHandler>
|
||||||
|
@ -18,6 +22,7 @@ object PhyScreens {
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
TERMINAL = ScreenHandlerRegistry.registerExtended(TerminalBlock.ID, ::TerminalScreenHandler)
|
TERMINAL = ScreenHandlerRegistry.registerExtended(TerminalBlock.ID, ::TerminalScreenHandler)
|
||||||
|
CRAFTING_TERMINAL = ScreenHandlerRegistry.registerExtended(CraftingTerminalBlock.ID, ::CraftingTerminalScreenHandler)
|
||||||
INSERTER = ScreenHandlerRegistry.registerExtended(InserterScreenHandler.ID, ::InserterScreenHandler)
|
INSERTER = ScreenHandlerRegistry.registerExtended(InserterScreenHandler.ID, ::InserterScreenHandler)
|
||||||
REDSTONE_EMITTER = ScreenHandlerRegistry.registerExtended(RedstoneEmitterScreenHandler.ID, ::RedstoneEmitterScreenHandler)
|
REDSTONE_EMITTER = ScreenHandlerRegistry.registerExtended(RedstoneEmitterScreenHandler.ID, ::RedstoneEmitterScreenHandler)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
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.terminal.CraftingTerminalBlockEntity
|
||||||
|
import net.shadowfacts.phycon.block.terminal.CraftingTerminalScreenHandler
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
object C2STerminalCraftingButton: ServerReceiver {
|
||||||
|
override val CHANNEL = Identifier(PhysicalConnectivity.MODID, "terminal_crafting_button")
|
||||||
|
|
||||||
|
enum class Action {
|
||||||
|
CLEAR_GRID,
|
||||||
|
REQUEST_ONE_MORE,
|
||||||
|
REQUEST_MAX_MORE,
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun invoke(terminal: CraftingTerminalBlockEntity, action: Action): Packet<*> {
|
||||||
|
val buf = PacketByteBufs.create()
|
||||||
|
|
||||||
|
buf.writeIdentifier(terminal.world!!.registryKey.value)
|
||||||
|
buf.writeBlockPos(terminal.pos)
|
||||||
|
buf.writeByte(action.ordinal)
|
||||||
|
|
||||||
|
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 action = Action.values()[buf.readByte().toInt()]
|
||||||
|
|
||||||
|
server.execute {
|
||||||
|
val key = RegistryKey.of(Registry.DIMENSION, dimID)
|
||||||
|
val screenHandler = player.currentScreenHandler as? CraftingTerminalScreenHandler ?: return@execute
|
||||||
|
if (screenHandler.terminal.pos != pos || screenHandler.terminal.world!!.registryKey != key) return@execute
|
||||||
|
|
||||||
|
when (action) {
|
||||||
|
Action.CLEAR_GRID -> screenHandler.clearCraftingGrid()
|
||||||
|
Action.REQUEST_ONE_MORE -> screenHandler.requestMoreCraftingIngredients(1)
|
||||||
|
Action.REQUEST_MAX_MORE -> screenHandler.requestMoreCraftingIngredients(64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
"block.phycon.switch": "Network Switch",
|
"block.phycon.switch": "Network Switch",
|
||||||
"block.phycon.network_interface": "Inventory Interface",
|
"block.phycon.network_interface": "Inventory Interface",
|
||||||
"block.phycon.terminal": "Terminal",
|
"block.phycon.terminal": "Terminal",
|
||||||
|
"block.phycon.crafting_terminal": "Crafting Terminal",
|
||||||
"block.phycon.cable_white": "White Cable",
|
"block.phycon.cable_white": "White Cable",
|
||||||
"block.phycon.cable_orange": "Orange Cable",
|
"block.phycon.cable_orange": "Orange Cable",
|
||||||
"block.phycon.cable_magenta": "Magenta Cable",
|
"block.phycon.cable_magenta": "Magenta Cable",
|
||||||
|
@ -35,6 +36,9 @@
|
||||||
|
|
||||||
"gui.phycon.terminal_buffer": "Buffer",
|
"gui.phycon.terminal_buffer": "Buffer",
|
||||||
"gui.phycon.terminal_network": "Network",
|
"gui.phycon.terminal_network": "Network",
|
||||||
|
"gui.phycon.terminal_crafting": "Crafting",
|
||||||
|
"gui.phycon.terminal.clear_crafting": "Clear crafting table",
|
||||||
|
"gui.phycon.terminal.more_crafting": "Request more ingredients",
|
||||||
"gui.phycon.console.details": "Device Details",
|
"gui.phycon.console.details": "Device Details",
|
||||||
"gui.phycon.console.details.ip": "IP Address: %s",
|
"gui.phycon.console.details.ip": "IP Address: %s",
|
||||||
"gui.phycon.console.details.mac": "MAC Address: %s",
|
"gui.phycon.console.details.mac": "MAC Address: %s",
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 3.5 KiB |
Loading…
Reference in New Issue