Compare commits
No commits in common. "f4f4c7ff03b45fcbe6edc4e22a54952985f887ef" and "2cc9d592b265593d4e1b92f389f8261cb1a89ddb" have entirely different histories.
f4f4c7ff03
...
2cc9d592b2
|
@ -1,17 +1,9 @@
|
||||||
package net.shadowfacts.phycon
|
package net.shadowfacts.phycon
|
||||||
|
|
||||||
import net.fabricmc.api.ModInitializer
|
import net.fabricmc.api.ModInitializer
|
||||||
import net.fabricmc.fabric.api.container.ContainerFactory
|
|
||||||
import net.fabricmc.fabric.api.container.ContainerProviderRegistry
|
|
||||||
import net.minecraft.container.Container
|
|
||||||
import net.minecraft.entity.player.PlayerEntity
|
|
||||||
import net.minecraft.util.Identifier
|
|
||||||
import net.minecraft.util.PacketByteBuf
|
|
||||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||||
import net.shadowfacts.phycon.init.PhyBlocks
|
import net.shadowfacts.phycon.init.PhyBlocks
|
||||||
import net.shadowfacts.phycon.init.PhyItems
|
import net.shadowfacts.phycon.init.PhyItems
|
||||||
import net.shadowfacts.phycon.network.block.terminal.TerminalBlock
|
|
||||||
import net.shadowfacts.phycon.network.block.terminal.TerminalContainer
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -24,13 +16,5 @@ object PhysicalConnectivity: ModInitializer {
|
||||||
PhyBlocks.init()
|
PhyBlocks.init()
|
||||||
PhyBlockEntities.init()
|
PhyBlockEntities.init()
|
||||||
PhyItems.init()
|
PhyItems.init()
|
||||||
ContainerProviderRegistry.INSTANCE.registerFactory(TerminalContainer.ID, ContainerFactory(::createTerminalContainer))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createTerminalContainer(syncId: Int, identifier: Identifier, player: PlayerEntity, buf: PacketByteBuf): Container {
|
|
||||||
val pos = buf.readBlockPos()
|
|
||||||
val terminalEntity = PhyBlocks.TERMINAL.getBlockEntity(player.world, pos)!!
|
|
||||||
return TerminalContainer(syncId, player.inventory, terminalEntity)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,22 +0,0 @@
|
||||||
package net.shadowfacts.phycon
|
|
||||||
|
|
||||||
import net.fabricmc.api.ClientModInitializer
|
|
||||||
import net.fabricmc.fabric.api.client.screen.ContainerScreenFactory
|
|
||||||
import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry
|
|
||||||
import net.minecraft.client.MinecraftClient
|
|
||||||
import net.minecraft.util.Identifier
|
|
||||||
import net.shadowfacts.phycon.network.block.terminal.TerminalContainer
|
|
||||||
import net.shadowfacts.phycon.network.block.terminal.TerminalScreen
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
object PhysicalConnectivityClient: ClientModInitializer {
|
|
||||||
override fun onInitializeClient() {
|
|
||||||
ScreenProviderRegistry.INSTANCE.registerFactory(TerminalContainer.ID, ContainerScreenFactory(::createTerminalScreen))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createTerminalScreen(container: TerminalContainer): TerminalScreen {
|
|
||||||
return TerminalScreen(container, MinecraftClient.getInstance().player.inventory)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,11 +3,13 @@ package net.shadowfacts.phycon.network.block.netinterface
|
||||||
import alexiil.mc.lib.attributes.SearchOptions
|
import alexiil.mc.lib.attributes.SearchOptions
|
||||||
import alexiil.mc.lib.attributes.item.GroupedItemInv
|
import alexiil.mc.lib.attributes.item.GroupedItemInv
|
||||||
import alexiil.mc.lib.attributes.item.ItemAttributes
|
import alexiil.mc.lib.attributes.item.ItemAttributes
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
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.network.DeviceBlockEntity
|
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||||
import net.shadowfacts.phycon.network.packet.*
|
import net.shadowfacts.phycon.network.packet.ReadAllPacket
|
||||||
|
import net.shadowfacts.phycon.network.packet.RequestReadAllPacket
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -26,39 +28,24 @@ class InterfaceBlockEntity: DeviceBlockEntity(PhyBlockEntities.INTERFACE) {
|
||||||
inventory = ItemAttributes.GROUPED_INV.getFirstOrNull(world, offsetPos, option)
|
inventory = ItemAttributes.GROUPED_INV.getFirstOrNull(world, offsetPos, option)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getInventory(): GroupedItemInv? {
|
override fun handlePacket(packet: Packet) {
|
||||||
|
when (packet) {
|
||||||
|
is RequestReadAllPacket -> handleReadAll(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleReadAll(packet: RequestReadAllPacket) {
|
||||||
|
enqueueToSingle(ReadAllPacket(readAll(), macAddress, packet.source))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun readAll(): Map<ItemStack, Int> {
|
||||||
// if we don't have an inventory, try to get one
|
// if we don't have an inventory, try to get one
|
||||||
// this happens when readAll is called before a neighbor state changes, such as immediately after world load
|
// this happens when readAll is called before a neighbor state changes, such as immediately after world load
|
||||||
if (inventory == null) updateInventory()
|
if (inventory == null) updateInventory()
|
||||||
return inventory
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handlePacket(packet: Packet) {
|
return inventory?.let {
|
||||||
when (packet) {
|
it.storedStacks.associateWith(it::getAmount)
|
||||||
is RequestInventoryPacket -> handleRequestInventory(packet)
|
} ?: mapOf()
|
||||||
is LocateStackPacket -> handleLocateStack(packet)
|
|
||||||
is ExtractStackPacket -> handleExtractStack(packet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleRequestInventory(packet: RequestInventoryPacket) {
|
|
||||||
getInventory()?.also { inv ->
|
|
||||||
enqueueToSingle(ReadInventoryPacket(inv, macAddress, packet.source))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleLocateStack(packet: LocateStackPacket) {
|
|
||||||
getInventory()?.also { inv ->
|
|
||||||
val amount = inv.getAmount(packet.stack)
|
|
||||||
enqueueToSingle(StackLocationPacket(packet.stack, amount, this, macAddress, packet.source))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleExtractStack(packet: ExtractStackPacket) {
|
|
||||||
getInventory()?.also { inv ->
|
|
||||||
val extracted = inv.extract(packet.stack, packet.amount)
|
|
||||||
enqueueToSingle(ItemStackPacket(extracted, macAddress, packet.source))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,8 @@ class TerminalBlock: BlockWithEntity<TerminalBlockEntity>(Settings.of(Material.M
|
||||||
|
|
||||||
override fun createBlockEntity(world: BlockView) = TerminalBlockEntity()
|
override fun createBlockEntity(world: BlockView) = TerminalBlockEntity()
|
||||||
|
|
||||||
override fun activate(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hitResult: BlockHitResult): Boolean {
|
override fun activate(blockState_1: BlockState?, world_1: World?, blockPos_1: BlockPos?, playerEntity_1: PlayerEntity?, hand_1: Hand?, blockHitResult_1: BlockHitResult?): Boolean {
|
||||||
getBlockEntity(world, pos)!!.onActivate(player)
|
getBlockEntity(world_1!!, blockPos_1!!)!!.onActivate()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,227 +1,57 @@
|
||||||
package net.shadowfacts.phycon.network.block.terminal
|
package net.shadowfacts.phycon.network.block.terminal
|
||||||
|
|
||||||
import alexiil.mc.lib.attributes.item.GroupedItemInv
|
|
||||||
import alexiil.mc.lib.attributes.item.ItemStackCollections
|
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.block.entity.BlockEntityClientSerializable
|
|
||||||
import net.fabricmc.fabric.api.container.ContainerProviderRegistry
|
|
||||||
import net.minecraft.entity.ItemEntity
|
|
||||||
import net.minecraft.entity.player.PlayerEntity
|
|
||||||
import net.minecraft.inventory.BasicInventory
|
|
||||||
import net.minecraft.inventory.Inventory
|
|
||||||
import net.minecraft.inventory.InventoryListener
|
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.CompoundTag
|
|
||||||
import net.minecraft.nbt.ListTag
|
|
||||||
import net.shadowfacts.phycon.api.packet.Packet
|
import net.shadowfacts.phycon.api.packet.Packet
|
||||||
import net.shadowfacts.phycon.api.util.MACAddress
|
import net.shadowfacts.phycon.api.util.MACAddress
|
||||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||||
import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlockEntity
|
import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlockEntity
|
||||||
import net.shadowfacts.phycon.network.packet.*
|
import net.shadowfacts.phycon.network.packet.DeviceRemovedPacket
|
||||||
import net.shadowfacts.phycon.util.fromTag
|
import net.shadowfacts.phycon.network.packet.ReadAllPacket
|
||||||
import net.shadowfacts.phycon.util.toTag
|
import net.shadowfacts.phycon.network.packet.RequestReadAllPacket
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL), InventoryListener, BlockEntityClientSerializable {
|
class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL) {
|
||||||
|
|
||||||
companion object {
|
private val inventoryCache = mutableMapOf<MACAddress, Map<ItemStack, Int>>()
|
||||||
val LOCATE_REQUEST_TIMEOUT = 40 // ticks
|
|
||||||
}
|
|
||||||
|
|
||||||
private val inventoryCache = mutableMapOf<MACAddress, GroupedItemInv>()
|
|
||||||
val internalBuffer = BasicInventory(18)
|
|
||||||
|
|
||||||
private val pendingRequests = LinkedList<StackLocateRequest>()
|
|
||||||
|
|
||||||
private var observers = 0
|
|
||||||
val cachedNetItems = ItemStackCollections.intMap()
|
|
||||||
var cachedSortedNetItems = listOf<ItemStack>()
|
|
||||||
var counter = 0
|
|
||||||
|
|
||||||
init {
|
|
||||||
internalBuffer.addListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handlePacket(packet: Packet) {
|
override fun handlePacket(packet: Packet) {
|
||||||
when (packet) {
|
when (packet) {
|
||||||
is ReadInventoryPacket -> handleReadInventory(packet)
|
is ReadAllPacket -> handleReadAll(packet)
|
||||||
is DeviceRemovedPacket -> handleDeviceRemoved(packet)
|
is DeviceRemovedPacket -> handleDeviceRemoved(packet)
|
||||||
is StackLocationPacket -> handleStackLocation(packet)
|
|
||||||
is ItemStackPacket -> handleItemStack(packet)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleReadInventory(packet: ReadInventoryPacket) {
|
private fun handleReadAll(packet: ReadAllPacket) {
|
||||||
inventoryCache[packet.source] = packet.inventory
|
inventoryCache[packet.source] = packet.items
|
||||||
updateNetItems()
|
|
||||||
sync()
|
println("new items: ${computeNetItems()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleDeviceRemoved(packet: DeviceRemovedPacket) {
|
private fun handleDeviceRemoved(packet: DeviceRemovedPacket) {
|
||||||
inventoryCache.remove(packet.source)
|
inventoryCache.remove(packet.source)
|
||||||
updateNetItems()
|
|
||||||
sync()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleStackLocation(packet: StackLocationPacket) {
|
fun computeNetItems(): Map<ItemStack, Int> {
|
||||||
val request = pendingRequests.firstOrNull {
|
val net = ItemStackCollections.intMap()
|
||||||
ItemStackUtil.areEqualIgnoreAmounts(it.stack, packet.stack)
|
for (map in inventoryCache.values) {
|
||||||
}
|
for ((stack, amount) in map) {
|
||||||
if (request != null) {
|
net.mergeInt(stack, amount) { a, b -> a + b }
|
||||||
request.results.add(packet.amount to packet.sourceInterface)
|
|
||||||
if (request.totalResultAmount >= request.amount || counter - request.timestamp >= LOCATE_REQUEST_TIMEOUT || request.results.size >= inventoryCache.size) {
|
|
||||||
pendingRequests.remove(request)
|
|
||||||
stackLocateRequestCompleted(request)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return net
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleItemStack(packet: ItemStackPacket) {
|
fun onActivate() {
|
||||||
// todo: handle merging stacks into the buffer better?
|
|
||||||
for (i in 0 until internalBuffer.invSize) {
|
|
||||||
if (internalBuffer.getInvStack(i).isEmpty) {
|
|
||||||
internalBuffer.setInvStack(i, packet.stack)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// todo: calculate entity spawn point by finding non-obstructed location
|
|
||||||
val entity = ItemEntity(world!!, pos.x.toDouble(), pos.y + 1.0, pos.z.toDouble(), packet.stack)
|
|
||||||
world!!.spawnEntity(entity)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateNetItems() {
|
|
||||||
cachedNetItems.clear()
|
|
||||||
for (inventory in inventoryCache.values) {
|
|
||||||
for (stack in inventory.storedStacks) {
|
|
||||||
val amount = inventory.getAmount(stack)
|
|
||||||
cachedNetItems.mergeInt(stack, amount) { a, b -> a + b }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// todo: is the map necessary or is just the sorted list enough?
|
|
||||||
cachedSortedNetItems = cachedNetItems.object2IntEntrySet().sortedByDescending { it.intValue }.map {
|
|
||||||
val stack = it.key.copy()
|
|
||||||
stack.count = it.intValue
|
|
||||||
stack
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addObserver() {
|
|
||||||
observers++
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeObserver() {
|
|
||||||
observers--
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun tick() {
|
|
||||||
super.tick()
|
|
||||||
|
|
||||||
if (observers > 0 && (++counter % 20) == 0) {
|
|
||||||
if (world!!.isClient) {
|
|
||||||
println(cachedNetItems)
|
|
||||||
} else {
|
|
||||||
updateNetItems()
|
|
||||||
sync()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onActivate(player: PlayerEntity) {
|
|
||||||
if (!world!!.isClient) {
|
if (!world!!.isClient) {
|
||||||
updateNetItems()
|
|
||||||
sync()
|
|
||||||
|
|
||||||
inventoryCache.clear()
|
inventoryCache.clear()
|
||||||
enqueueToSingle(RequestInventoryPacket(macAddress))
|
enqueueToSingle(RequestReadAllPacket(macAddress))
|
||||||
ContainerProviderRegistry.INSTANCE.openContainer(TerminalContainer.ID, player) { buf ->
|
|
||||||
buf.writeBlockPos(pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addObserver()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun requestItem(stack: ItemStack, amount: Int = stack.count) {
|
|
||||||
pendingRequests.add(StackLocateRequest(stack, amount, counter))
|
|
||||||
enqueueToSingle(LocateStackPacket(stack, macAddress))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun stackLocateRequestCompleted(request: StackLocateRequest) {
|
|
||||||
// todo: also sort results by interface priority
|
|
||||||
val sortedResults = request.results.sortedByDescending { it.first }.toMutableList()
|
|
||||||
var amountRequested = 0
|
|
||||||
while (amountRequested < request.amount && sortedResults.isNotEmpty()) {
|
|
||||||
val (sourceAmount, sourceInterface) = sortedResults.removeAt(0)
|
|
||||||
val amountToRequest = min(sourceAmount, request.amount - amountRequested)
|
|
||||||
amountRequested += amountToRequest
|
|
||||||
enqueueToSingle(ExtractStackPacket(request.stack, amountToRequest, macAddress, sourceInterface.macAddress))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onInvChange(inv: Inventory) {
|
|
||||||
if (inv == internalBuffer && !world!!.isClient) {
|
|
||||||
markDirty()
|
|
||||||
sync()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toTag(tag: CompoundTag): CompoundTag {
|
|
||||||
tag.put("InternalBuffer", internalBuffer.toTag())
|
|
||||||
return super.toTag(tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fromTag(tag: CompoundTag) {
|
|
||||||
super.fromTag(tag)
|
|
||||||
internalBuffer.fromTag(tag.getList("InternalBuffer", 10))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toClientTag(tag: CompoundTag): CompoundTag {
|
|
||||||
tag.put("InternalBuffer", internalBuffer.toTag())
|
|
||||||
val list = ListTag()
|
|
||||||
tag.put("CachedNetItems", list)
|
|
||||||
for ((stack, amount) in cachedNetItems) {
|
|
||||||
val entryTag = stack.toTag(CompoundTag())
|
|
||||||
entryTag.putInt("NetAmount", amount)
|
|
||||||
list.add(entryTag)
|
|
||||||
}
|
|
||||||
return tag
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fromClientTag(tag: CompoundTag) {
|
|
||||||
tag.getList("InternalBuffer", 10)?.also { list ->
|
|
||||||
if (list.isNotEmpty()) {
|
|
||||||
internalBuffer.fromTag(list)
|
|
||||||
} else {
|
|
||||||
// todo: should this clear or just do nothing?
|
|
||||||
internalBuffer.clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val list = tag.getList("CachedNetItems", 10)
|
|
||||||
cachedNetItems.clear()
|
|
||||||
for (entryTag in list) {
|
|
||||||
val stack = ItemStack.fromTag(entryTag as CompoundTag)
|
|
||||||
val netAmount = entryTag.getInt("NetAmount")
|
|
||||||
cachedNetItems[stack] = netAmount
|
|
||||||
}
|
|
||||||
cachedSortedNetItems = cachedNetItems.object2IntEntrySet().sortedByDescending { it.intValue }.map {
|
|
||||||
val stack = it.key.copy()
|
|
||||||
stack.count = it.intValue
|
|
||||||
stack
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class StackLocateRequest(
|
|
||||||
val stack: ItemStack,
|
|
||||||
val amount: Int,
|
|
||||||
val timestamp: Int,
|
|
||||||
var results: MutableSet<Pair<Int, InterfaceBlockEntity>> = mutableSetOf()
|
|
||||||
) {
|
|
||||||
val totalResultAmount: Int
|
|
||||||
get() = results.fold(0) { acc, (amount, _) -> acc + amount }
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
package net.shadowfacts.phycon.network.block.terminal
|
|
||||||
|
|
||||||
import net.minecraft.container.Container
|
|
||||||
import net.minecraft.container.Slot
|
|
||||||
import net.minecraft.container.SlotActionType
|
|
||||||
import net.minecraft.entity.player.PlayerEntity
|
|
||||||
import net.minecraft.entity.player.PlayerInventory
|
|
||||||
import net.minecraft.item.ItemStack
|
|
||||||
import net.minecraft.util.Identifier
|
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
|
||||||
import kotlin.math.max
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
class TerminalContainer(syncId: Int, playerInv: PlayerInventory, val terminal: TerminalBlockEntity): Container(null, syncId) {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val ID = Identifier(PhysicalConnectivity.MODID, "terminal")
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
// network
|
|
||||||
for (y in 0 until 6) {
|
|
||||||
for (x in 0 until 9) {
|
|
||||||
addSlot(TerminalFakeSlot(terminal, y * 9 + x, 66 + x * 18, 18 + y * 18))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// internal buffer
|
|
||||||
for (y in 0 until 6) {
|
|
||||||
for (x in 0 until 3) {
|
|
||||||
addSlot(Slot(terminal.internalBuffer, y * 3 + x, 8 + x * 18, 18 + y * 18))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// player inv
|
|
||||||
for (y in 0 until 3) {
|
|
||||||
for (x in 0 until 9) {
|
|
||||||
addSlot(Slot(playerInv, x + y * 9 + 9, 66 + x * 18, 140 + y * 18))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// hotbar
|
|
||||||
for (x in 0 until 9) {
|
|
||||||
addSlot(Slot(playerInv, x, 66 + x * 18, 198))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canUse(player: PlayerEntity): Boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun close(player: PlayerEntity) {
|
|
||||||
super.close(player)
|
|
||||||
|
|
||||||
terminal.removeObserver()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSlotClick(slotId: Int, clickData: Int, actionType: SlotActionType, player: PlayerEntity): ItemStack {
|
|
||||||
if (actionType == SlotActionType.QUICK_MOVE) {
|
|
||||||
if (slotId < 54) {
|
|
||||||
// the slot clicked was one of the network stacks
|
|
||||||
val slot = slotList[slotId]
|
|
||||||
val stack = slotList[slotId].stack
|
|
||||||
if (!stack.isEmpty && !player.world.isClient) {
|
|
||||||
terminal.requestItem(stack, max(stack.count, stack.maxCount))
|
|
||||||
}
|
|
||||||
return ItemStack.EMPTY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.onSlotClick(slotId, clickData, actionType, player)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
package net.shadowfacts.phycon.network.block.terminal
|
|
||||||
|
|
||||||
import net.minecraft.container.Slot
|
|
||||||
import net.minecraft.entity.player.PlayerEntity
|
|
||||||
import net.minecraft.inventory.Inventory
|
|
||||||
import net.minecraft.item.ItemStack
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
class TerminalFakeSlot(val terminal: TerminalBlockEntity, slot: Int, x: Int, y: Int): Slot(FakeInventory(terminal, slot), slot, x, y) {
|
|
||||||
|
|
||||||
override fun canInsert(stack: ItemStack): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setStack(stack: ItemStack) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canTakeItems(player: PlayerEntity): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class FakeInventory(val terminal: TerminalBlockEntity, val slot: Int): Inventory {
|
|
||||||
override fun getInvStack(_slot: Int): ItemStack {
|
|
||||||
if (slot >= terminal.cachedSortedNetItems.size) return ItemStack.EMPTY
|
|
||||||
return terminal.cachedSortedNetItems[slot]
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun markDirty() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clear() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setInvStack(p0: Int, p1: ItemStack?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun removeInvStack(p0: Int): ItemStack {
|
|
||||||
return ItemStack.EMPTY
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canPlayerUseInv(p0: PlayerEntity?): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getInvSize(): Int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun takeInvStack(p0: Int, p1: Int): ItemStack {
|
|
||||||
return ItemStack.EMPTY
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isInvEmpty(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
package net.shadowfacts.phycon.network.block.terminal
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.GlStateManager
|
|
||||||
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen
|
|
||||||
import net.minecraft.entity.player.PlayerInventory
|
|
||||||
import net.minecraft.text.LiteralText
|
|
||||||
import net.minecraft.util.Identifier
|
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
// todo: translate title
|
|
||||||
class TerminalScreen(container: TerminalContainer, playerInv: PlayerInventory): AbstractContainerScreen<TerminalContainer>(container, playerInv, LiteralText("Terminal")) {
|
|
||||||
companion object {
|
|
||||||
val BACKGROUND = Identifier(PhysicalConnectivity.MODID, "textures/gui/terminal.png")
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
containerWidth = 252
|
|
||||||
containerHeight = 222
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun drawForeground(mouseX: Int, mouseY: Int) {
|
|
||||||
font.draw(title.asFormattedString(), 65f, 6f, 0x404040)
|
|
||||||
font.draw(playerInventory.displayName.asFormattedString(), 65f, containerHeight - 94f, 0x404040)
|
|
||||||
// todo: translate this
|
|
||||||
font.draw("Buffer", 7f, 6f, 0x404040)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun drawBackground(delta: Float, mouseX: Int, mouseY: Int) {
|
|
||||||
GlStateManager.color4f(1f, 1f, 1f, 1f)
|
|
||||||
minecraft!!.textureManager.bindTexture(BACKGROUND)
|
|
||||||
val x = (width - containerWidth) / 2
|
|
||||||
val y = (height - containerHeight) / 2
|
|
||||||
blit(x, y, 0, 0, containerWidth, containerHeight)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
package net.shadowfacts.phycon.network.packet
|
|
||||||
|
|
||||||
import net.minecraft.item.ItemStack
|
|
||||||
import net.shadowfacts.phycon.api.util.MACAddress
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
class ExtractStackPacket(val stack: ItemStack, val amount: Int, source: MACAddress, destination: MACAddress): BasePacket(source, destination) {
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
package net.shadowfacts.phycon.network.packet
|
|
||||||
|
|
||||||
import net.minecraft.item.ItemStack
|
|
||||||
import net.shadowfacts.phycon.api.util.MACAddress
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
class ItemStackPacket(val stack: ItemStack, source: MACAddress, destination: MACAddress): BasePacket(source, destination) {
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
package net.shadowfacts.phycon.network.packet
|
|
||||||
|
|
||||||
import net.minecraft.item.ItemStack
|
|
||||||
import net.shadowfacts.phycon.api.util.MACAddress
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
class LocateStackPacket(val stack: ItemStack, source: MACAddress, destination: MACAddress = MACAddress.BROADCAST): BasePacket(source, destination) {
|
|
||||||
}
|
|
|
@ -1,13 +1,13 @@
|
||||||
package net.shadowfacts.phycon.network.packet
|
package net.shadowfacts.phycon.network.packet
|
||||||
|
|
||||||
import alexiil.mc.lib.attributes.item.GroupedItemInv
|
import net.minecraft.item.ItemStack
|
||||||
import net.shadowfacts.phycon.api.util.MACAddress
|
import net.shadowfacts.phycon.api.util.MACAddress
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class ReadInventoryPacket(
|
class ReadAllPacket(
|
||||||
val inventory: GroupedItemInv,
|
val items: Map<ItemStack, Int>,
|
||||||
source: MACAddress,
|
source: MACAddress,
|
||||||
destination: MACAddress
|
destination: MACAddress
|
||||||
): BasePacket(source, destination)
|
): BasePacket(source, destination)
|
|
@ -1,8 +0,0 @@
|
||||||
package net.shadowfacts.phycon.network.packet
|
|
||||||
|
|
||||||
import net.shadowfacts.phycon.api.util.MACAddress
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
class RequestInventoryPacket(source: MACAddress, destination: MACAddress = MACAddress.BROADCAST): BasePacket(source, destination)
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package net.shadowfacts.phycon.network.packet
|
||||||
|
|
||||||
|
import net.shadowfacts.phycon.api.util.MACAddress
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class RequestReadAllPacket(source: MACAddress, destination: MACAddress = MACAddress.BROADCAST): BasePacket(source, destination)
|
|
@ -1,18 +0,0 @@
|
||||||
package net.shadowfacts.phycon.network.packet
|
|
||||||
|
|
||||||
import net.minecraft.item.ItemStack
|
|
||||||
import net.shadowfacts.phycon.api.util.MACAddress
|
|
||||||
import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlockEntity
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
// todo: better name with LocateStackPacket
|
|
||||||
class StackLocationPacket(
|
|
||||||
val stack: ItemStack,
|
|
||||||
val amount: Int,
|
|
||||||
val sourceInterface: InterfaceBlockEntity,
|
|
||||||
source: MACAddress,
|
|
||||||
destination: MACAddress
|
|
||||||
): BasePacket(source, destination) {
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
package net.shadowfacts.phycon.util
|
|
||||||
|
|
||||||
import net.minecraft.inventory.BasicInventory
|
|
||||||
import net.minecraft.item.ItemStack
|
|
||||||
import net.minecraft.nbt.CompoundTag
|
|
||||||
import net.minecraft.nbt.ListTag
|
|
||||||
import java.lang.RuntimeException
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
fun BasicInventory.toTag(): ListTag {
|
|
||||||
val list = ListTag()
|
|
||||||
for (slot in 0 until invSize) {
|
|
||||||
val stack = getInvStack(slot)
|
|
||||||
if (!stack.isEmpty) {
|
|
||||||
val stackTag = stack.toTag(CompoundTag())
|
|
||||||
stackTag.putInt("Slot", slot)
|
|
||||||
list.add(stackTag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
fun BasicInventory.fromTag(list: ListTag) {
|
|
||||||
if (list.listType != 10) throw RuntimeException("Can't decode BasicInventory from list tag that does not contain compound tags")
|
|
||||||
this.clear()
|
|
||||||
for (tag in list) {
|
|
||||||
val compound = tag as CompoundTag
|
|
||||||
val stack = ItemStack.fromTag(compound)
|
|
||||||
val slot = compound.getInt("Slot")
|
|
||||||
setInvStack(slot, stack)
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 9.9 KiB |
|
@ -19,12 +19,6 @@
|
||||||
"adapter": "kotlin",
|
"adapter": "kotlin",
|
||||||
"value": "net.shadowfacts.phycon.PhysicalConnectivity"
|
"value": "net.shadowfacts.phycon.PhysicalConnectivity"
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"client": [
|
|
||||||
{
|
|
||||||
"adapter": "kotlin",
|
|
||||||
"value": "net.shadowfacts.phycon.PhysicalConnectivityClient"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
||||||
|
|
Loading…
Reference in New Issue