minecraft-mod/Essentials/src/main/kotlin/com/beemer/essentials/gui/AntimobGui.kt

127 lines
5.2 KiB
Kotlin
Raw Normal View History

package com.beemer.essentials.gui
import com.beemer.essentials.config.AntimobConfig
import com.mojang.authlib.GameProfile
import net.minecraft.ChatFormatting
import net.minecraft.core.component.DataComponents
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.Container
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.inventory.ClickType
import net.minecraft.world.inventory.MenuType
import net.minecraft.world.inventory.Slot
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.item.component.ResolvableProfile
import java.util.*
class AntimobGui(syncId: Int, playerInv: Inventory, val container: Container, private val viewer: ServerPlayer) : AbstractContainerMenu(MenuType.GENERIC_9x2, syncId) {
companion object {
const val CONTAINER_COLUMNS = 9
const val CONTAINER_ROWS = 2
const val CONTAINER_SIZE = CONTAINER_COLUMNS * CONTAINER_ROWS
const val SLOT_SIZE = 18
const val LEFT_PADDING = 8
const val TOP_PADDING = 18
const val PLAYER_INV_TOP = 58
const val HOTBAR_Y = 116
}
private val headSlotToMob = mapOf(0 to "크리퍼", 1 to "가스트", 2 to "엔더맨")
private val glassSlotToMob = mapOf(9 to "크리퍼", 10 to "가스트", 11 to "엔더맨")
init {
for (i in 0 until CONTAINER_SIZE) {
val x = LEFT_PADDING + (i % CONTAINER_COLUMNS) * SLOT_SIZE
val y = TOP_PADDING + (i / CONTAINER_COLUMNS) * SLOT_SIZE
addSlot(object : Slot(container, i, x, y) {
override fun mayPickup(player: net.minecraft.world.entity.player.Player): Boolean = false
override fun mayPlace(stack: ItemStack): Boolean = false
})
}
for (row in 0 until 3) {
for (col in 0 until 9) {
val index = col + row * 9 + 9
val x = LEFT_PADDING + col * SLOT_SIZE
val y = PLAYER_INV_TOP + row * SLOT_SIZE
addSlot(Slot(playerInv, index, x, y))
}
}
for (col in 0 until 9) {
val x = LEFT_PADDING + col * SLOT_SIZE
val y = HOTBAR_Y
addSlot(Slot(playerInv, col, x, y))
}
refreshContainerContents()
}
override fun clicked(slotId: Int, button: Int, clickType: ClickType, player: net.minecraft.world.entity.player.Player) {
if (player is ServerPlayer && slotId in 0 until CONTAINER_SIZE) {
if (glassSlotToMob.containsKey(slotId)) {
val mob = glassSlotToMob[slotId] ?: return
AntimobConfig.toggle(mob)
container.setItem(slotId, makeToggleGlass(mob))
return
}
}
super.clicked(slotId, button, clickType, player)
}
override fun stillValid(player: net.minecraft.world.entity.player.Player): Boolean = true
override fun quickMoveStack(player: net.minecraft.world.entity.player.Player, index: Int): ItemStack = ItemStack.EMPTY
private fun makeMobHead(mob: String, player: ServerPlayer): ItemStack {
val headItem = ItemStack(Items.PLAYER_HEAD)
val uuid = when (mob) {
"크리퍼" -> UUID.fromString("057b1c47-1321-4863-a6fe-8887f9ec265f")
"가스트" -> UUID.fromString("063085a6-797f-4785-be1a-21cd7580f752")
"엔더맨" -> UUID.fromString("40ffb372-12f6-4678-b3f2-2176bf56dd4b")
else -> UUID.fromString("c06f8906-4c8a-4911-9c29-ea1dbd1aab82")
}
val filledProfile: GameProfile = try {
player.server.sessionService.fetchProfile(uuid, true)?.profile ?: player.gameProfile
} catch (_: Exception) {
player.gameProfile
}
val resolvableProfile = try {
ResolvableProfile(filledProfile)
} catch (_: NoSuchMethodError) {
val ctor = ResolvableProfile::class.java.getDeclaredConstructor(GameProfile::class.java)
ctor.isAccessible = true
ctor.newInstance(filledProfile)
}
headItem.set(DataComponents.CUSTOM_NAME, Component.literal(mob).withStyle { it.withColor(ChatFormatting.YELLOW) })
headItem.set(DataComponents.PROFILE, resolvableProfile)
return headItem
}
private fun makeToggleGlass(mob: String): ItemStack {
val enabled = AntimobConfig.get(mob)
val glass = if (enabled) ItemStack(Items.GREEN_STAINED_GLASS_PANE) else ItemStack(Items.RED_STAINED_GLASS_PANE)
val statusText = if (enabled) "활성화" else "비활성화"
glass.set(DataComponents.CUSTOM_NAME, Component.literal(statusText).withStyle { it.withColor(if (enabled) ChatFormatting.GREEN else ChatFormatting.RED) })
return glass
}
private fun refreshContainerContents() {
headSlotToMob.forEach { (slot, mob) ->
container.setItem(slot, makeMobHead(mob, viewer))
}
glassSlotToMob.forEach { (slot, mob) ->
container.setItem(slot, makeToggleGlass(mob))
}
}
}