Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GUI block entity binding #441

Merged
merged 3 commits into from
Aug 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import net.minecraft.block.*
import net.minecraft.block.entity.BlockEntityType
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.inventory.Inventories
import net.minecraft.inventory.Inventory
import net.minecraft.inventory.SidedInventory
import net.minecraft.item.HoeItem
import net.minecraft.item.ItemStack
Expand Down Expand Up @@ -54,7 +55,7 @@ class HarvestBlockEntity(type: BlockEntityType<*>, pos: BlockPos, modelItem: Ite

override val allowedFacing = listOf(Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST)
private val inventory = DefaultedList.ofSize(4, ItemStack.EMPTY)
private val gui = GUI.Builder(ScreenHandlerType.GENERIC_9X3).setTitle(Text.translatable("block.HARVEST")).apply {
private val gui = GUI.Builder(ScreenHandlerType.GENERIC_9X3).setTitle(Text.translatable("block.HARVEST")).blockEntity(this).apply {
var i = 0
addSlot(4, 0, object : Slot(this@HarvestBlockEntity, i++, 0, 0) { // Tool
override fun canInsert(item: ItemStack) = isHoe(item)
Expand Down Expand Up @@ -167,9 +168,7 @@ class HarvestBlockEntity(type: BlockEntityType<*>, pos: BlockPos, modelItem: Ite
}

override fun canPlayerUse(player: PlayerEntity): Boolean {
return if (world!!.getBlockEntity(pos) !== this) {
false
} else player.squaredDistanceTo(pos.x.toDouble() + 0.5, pos.y.toDouble() + 0.5, pos.z.toDouble() + 0.5) <= 64.0
return Inventory.canPlayerUse(this, player)
}

override fun getAvailableSlots(side: Direction): IntArray {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import one.oktw.galaxy.item.Gui
class TestGuiBlockEntity(type: BlockEntityType<*>, pos: BlockPos, modelItem: ItemStack) : ModelCustomBlockEntity(type, pos, modelItem),
CustomBlockClickListener, Inventory {
private val inventory = DefaultedList.ofSize(3 * 9, ItemStack.EMPTY)
private val gui = GUI.Builder(ScreenHandlerType.GENERIC_9X6).setTitle(Text.of("Test GUI")).apply {
private val gui = GUI.Builder(ScreenHandlerType.GENERIC_9X6).setTitle(Text.of("Test GUI")).blockEntity(this).apply {
var i = 0
for (x in 0 until 9) addSlot(x, 0, Slot(this@TestGuiBlockEntity, i++, 0, 0))
for (y in 4 until 6) for (x in 0 until 9) addSlot(x, y, Slot(this@TestGuiBlockEntity, i++, 0, 0))
Expand All @@ -57,7 +57,7 @@ class TestGuiBlockEntity(type: BlockEntityType<*>, pos: BlockPos, modelItem: Ite
GUISBackStackManager.openGUI(player, gui2)
}
}
private val gui2 = GUI.Builder(ScreenHandlerType.GENERIC_9X4).setTitle(Text.of("Test GUI2")).apply {
private val gui2 = GUI.Builder(ScreenHandlerType.GENERIC_9X4).setTitle(Text.of("Test GUI2")).blockEntity(this).apply {
var i = 0
for (y in 0 until 3) for (x in 0 until 9) addSlot(x, y, Slot(this@TestGuiBlockEntity, i++, 0, 0))
}.build().apply {
Expand Down Expand Up @@ -113,8 +113,6 @@ class TestGuiBlockEntity(type: BlockEntityType<*>, pos: BlockPos, modelItem: Ite
}

override fun canPlayerUse(player: PlayerEntity): Boolean {
return if (world!!.getBlockEntity(pos) !== this) {
false
} else player.squaredDistanceTo(pos.x.toDouble() + 0.5, pos.y.toDouble() + 0.5, pos.z.toDouble() + 0.5) <= 64.0
return Inventory.canPlayerUse(this, player)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ class TrashcanBlockEntity(type: BlockEntityType<*>, pos: BlockPos, modelItem: It

override fun setStack(slot: Int, stack: ItemStack?) {}

override fun canPlayerUse(player: PlayerEntity): Boolean = false
override fun canPlayerUse(player: PlayerEntity): Boolean {
return Inventory.canPlayerUse(this, player)
}

override fun onClick(player: PlayerEntity, hand: Hand, hit: BlockHitResult): ActionResult {
if (player.isSpectator) {
Expand All @@ -60,20 +62,10 @@ class TrashcanBlockEntity(type: BlockEntityType<*>, pos: BlockPos, modelItem: It

val gui = GUI
.Builder(ScreenHandlerType.GENERIC_9X4)
.setTitle(Text.of("Trashcan"))
.blockEntity(this)
.apply {
setTitle(Text.of("Trashcan"))

var i = 0
// val inv = object : SimpleInventory(9 * 4) {
// override fun canPlayerUse(player: PlayerEntity): Boolean {
// val trashcanBlock = this@TrashcanBlockEntity
// if (trashcanBlock.world!!.getBlockEntity(trashcanBlock.pos) != trashcanBlock) {
// return false
// }
//
// return player.squaredDistanceTo(trashcanBlock.pos.x + 0.5, trashcanBlock.pos.y + 0.5, trashcanBlock.pos.z + 0.5) <= 64
// }
// }
val inv = SimpleInventory(9 * 4)

for (y in 0 until 4) for (x in 0 until 9) addSlot(x, y, Slot(inv, i++, 0, 0))
Expand Down
25 changes: 20 additions & 5 deletions src/main/kotlin/one/oktw/galaxy/gui/GUI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ package one.oktw.galaxy.gui
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.launch
import net.minecraft.block.entity.BlockEntity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.entity.player.PlayerInventory
import net.minecraft.inventory.Inventory
import net.minecraft.inventory.SimpleInventory
import net.minecraft.item.ItemStack
import net.minecraft.screen.NamedScreenHandlerFactory
Expand All @@ -41,7 +43,12 @@ import org.apache.logging.log4j.LogManager
import java.util.concurrent.ConcurrentHashMap

@Suppress("unused", "MemberVisibilityCanBePrivate")
class GUI private constructor(private val type: ScreenHandlerType<out ScreenHandler>, private val title: Text, private val slotBindings: HashMap<Int, Slot>) :
class GUI private constructor(
private val type: ScreenHandlerType<out ScreenHandler>,
private val title: Text,
private val slotBindings: HashMap<Int, Slot>,
private val blockEntity: BlockEntity? = null
) :
NamedScreenHandlerFactory {
private val inventory = when (type) {
GENERIC_9X1, GENERIC_3X3 -> SimpleInventory(9)
Expand All @@ -63,7 +70,8 @@ class GUI private constructor(private val type: ScreenHandlerType<out ScreenHand

override fun getDisplayName() = title

override fun createMenu(syncId: Int, playerInventory: PlayerInventory, player: PlayerEntity): ScreenHandler {
override fun createMenu(syncId: Int, playerInventory: PlayerInventory, player: PlayerEntity): ScreenHandler? {
if ((blockEntity as? Inventory)?.canPlayerUse(player) == false) return null
return GuiContainer(syncId, playerInventory)
}

Expand Down Expand Up @@ -118,6 +126,8 @@ class GUI private constructor(private val type: ScreenHandlerType<out ScreenHand
private val inventoryUtils = InventoryUtils(type)
private var title: Text = Text.empty()
private val slotBindings = HashMap<Int, Slot>()
private var blockEntity: BlockEntity? = null

fun setTitle(title: Text): Builder {
this.title = title
return this
Expand All @@ -133,8 +143,13 @@ class GUI private constructor(private val type: ScreenHandlerType<out ScreenHand

fun addSlot(x: Int, y: Int, slot: Slot) = this.addSlot(inventoryUtils.xyToIndex(x, y), slot)

fun blockEntity(entity: BlockEntity): Builder {
this.blockEntity = entity
return this
}

fun build(): GUI {
return GUI(type, title, slotBindings)
return GUI(type, title, slotBindings, blockEntity)
}
}

Expand Down Expand Up @@ -212,6 +227,7 @@ class GUI private constructor(private val type: ScreenHandlerType<out ScreenHand

return
}

PICKUP_ALL -> { // Rewrite PICKUP_ALL only take from allow use slot & player inventory.
if (slot < 0) return

Expand Down Expand Up @@ -252,8 +268,7 @@ class GUI private constructor(private val type: ScreenHandlerType<out ScreenHand
}

override fun canUse(player: PlayerEntity): Boolean {
// TODO close GUI
return true
return (blockEntity as? Inventory)?.canPlayerUse(player) ?: true
}

fun insertItemToBinding(item: ItemStack, fromLast: Boolean): Boolean {
Expand Down
7 changes: 6 additions & 1 deletion src/main/kotlin/one/oktw/galaxy/gui/GUISBackStackManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,12 @@ class GUISBackStackManager(private val player: ServerPlayerEntity) : CoroutineSc
stack.pollLast() // Remove closed

// Delay 1 tick to workaround open GUI on close callback
launch { stack.lastOrNull()?.let(player::openHandledScreen) } // Open previous
launch {
while (stack.isNotEmpty()) {
if (stack.last().let(player::openHandledScreen).isPresent) break // Try open previous
stack.pollLast() // Open fail, remove it
}
}
}
}
}