feat: GUI 클릭 소리 및 개선
- 모든 GUI에 bell 클릭 소리 추가 (playNotifySound로 해당 플레이어만 듣도록) - TeleportGui: 다른 플레이어 없으면 메시지만 표시, 빈 공간 클릭 무시 - EssentialsMenuGui: 아이템 이름 간소화 (스폰/좌표/제작대/텔레포트) - 설명 텍스트에서 '클릭하여' 제거, 좌표에 '저장된' 추가
This commit is contained in:
parent
791d6f2e9f
commit
4dba2a4803
5 changed files with 319 additions and 265 deletions
|
|
@ -4,6 +4,7 @@ import com.beemer.essentials.gui.TeleportGui
|
|||
import com.beemer.essentials.gui.TeleportGui.Companion.CONTAINER_SIZE
|
||||
import com.beemer.essentials.nickname.NicknameDataStore
|
||||
import com.beemer.essentials.util.CommandUtils
|
||||
import com.beemer.essentials.util.MessageUtils
|
||||
import com.beemer.essentials.util.TranslationUtils
|
||||
import com.mojang.authlib.GameProfile
|
||||
import net.minecraft.ChatFormatting
|
||||
|
|
@ -32,13 +33,22 @@ object TeleportCommand {
|
|||
CommandUtils.getPlayerOrSendFailure(context.source)
|
||||
?: return@executes 0
|
||||
|
||||
val container = SimpleContainer(9 * 3)
|
||||
|
||||
val targetPlayers =
|
||||
player.server.playerList.players.filter {
|
||||
it != player
|
||||
}
|
||||
|
||||
// 다른 플레이어가 없으면 메시지만 표시
|
||||
if (targetPlayers.isEmpty()) {
|
||||
MessageUtils.sendInfo(
|
||||
player,
|
||||
"현재 접속 중인 다른 플레이어가 없습니다."
|
||||
)
|
||||
return@executes 0
|
||||
}
|
||||
|
||||
val container = SimpleContainer(9 * 3)
|
||||
|
||||
targetPlayers.take(CONTAINER_SIZE).forEachIndexed {
|
||||
idx,
|
||||
target ->
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ 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.sounds.SoundEvents
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.Container
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
|
|
@ -77,6 +79,7 @@ class AntimobGui(
|
|||
) {
|
||||
if (player is ServerPlayer && slotId in 0 until CONTAINER_SIZE) {
|
||||
if (glassSlotToMob.containsKey(slotId)) {
|
||||
playClickSound(player)
|
||||
val mob = glassSlotToMob[slotId] ?: return
|
||||
AntimobConfig.toggle(mob)
|
||||
container.setItem(slotId, makeToggleGlass(mob))
|
||||
|
|
@ -94,6 +97,10 @@ class AntimobGui(
|
|||
index: Int
|
||||
): ItemStack = ItemStack.EMPTY
|
||||
|
||||
private fun playClickSound(player: ServerPlayer) {
|
||||
player.playNotifySound(SoundEvents.NOTE_BLOCK_BELL.value(), SoundSource.MASTER, 0.5f, 1.0f)
|
||||
}
|
||||
|
||||
private fun makeMobHead(mob: String): ItemStack {
|
||||
val headItem = ItemStack(Items.PLAYER_HEAD)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ import net.minecraft.network.chat.Component
|
|||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.Container
|
||||
import net.minecraft.world.SimpleContainer
|
||||
import net.minecraft.world.SimpleMenuProvider
|
||||
|
|
@ -88,6 +90,7 @@ class Menu(
|
|||
tag.getString("action") == "prev"
|
||||
) {
|
||||
if (currentPage > 0) {
|
||||
playClickSound(player)
|
||||
openPage(player, currentPage - 1)
|
||||
}
|
||||
return
|
||||
|
|
@ -100,6 +103,7 @@ class Menu(
|
|||
) {
|
||||
val totalPages = getTotalPages()
|
||||
if (currentPage < totalPages - 1) {
|
||||
playClickSound(player)
|
||||
openPage(player, currentPage + 1)
|
||||
}
|
||||
return
|
||||
|
|
@ -118,7 +122,6 @@ class Menu(
|
|||
val level = dimension?.let { player.server.getLevel(it) }
|
||||
|
||||
if (level != null) {
|
||||
// 이전 위치 저장
|
||||
val prevPos = player.blockPosition()
|
||||
PlayerConfig.recordLastLocation(
|
||||
player,
|
||||
|
|
@ -137,12 +140,17 @@ class Menu(
|
|||
)
|
||||
|
||||
player.teleportTo(level, x, y, z, player.yRot, player.xRot)
|
||||
playClickSound(player)
|
||||
MessageUtils.sendSuccess(player, "{$coordName}(으)로 이동했습니다.")
|
||||
}
|
||||
player.closeContainer()
|
||||
}
|
||||
}
|
||||
|
||||
private fun playClickSound(player: ServerPlayer) {
|
||||
player.playNotifySound(SoundEvents.NOTE_BLOCK_BELL.value(), SoundSource.MASTER, 0.5f, 1.0f)
|
||||
}
|
||||
|
||||
private fun getTotalPages(): Int {
|
||||
val totalItems = CoordinateConfig.getCoordinates().size
|
||||
return if (totalItems == 0) 1 else (totalItems + ITEMS_PER_PAGE - 1) / ITEMS_PER_PAGE
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import net.minecraft.core.component.DataComponents
|
|||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.Container
|
||||
import net.minecraft.world.SimpleContainer
|
||||
import net.minecraft.world.SimpleMenuProvider
|
||||
|
|
@ -29,240 +31,253 @@ class EssentialsMenuGui(
|
|||
val viewer: ServerPlayer
|
||||
) : AbstractContainerMenu(MenuType.GENERIC_9x3, syncId) {
|
||||
|
||||
companion object {
|
||||
const val CONTAINER_SIZE = 27
|
||||
companion object {
|
||||
const val CONTAINER_SIZE = 27
|
||||
|
||||
// 메뉴 아이템 슬롯 위치
|
||||
const val SLOT_SPAWN = 10 // 스폰
|
||||
const val SLOT_COORDINATES = 12 // 좌표
|
||||
const val SLOT_WORKBENCH = 14 // 제작대
|
||||
const val SLOT_TPA = 16 // TPA
|
||||
}
|
||||
|
||||
init {
|
||||
// 컨테이너 슬롯 추가
|
||||
for (i in 0 until CONTAINER_SIZE) {
|
||||
val x = 8 + (i % 9) * 18
|
||||
val y = 18 + (i / 9) * 18
|
||||
addSlot(
|
||||
object : Slot(container, i, x, y) {
|
||||
override fun mayPickup(player: Player): Boolean = false
|
||||
override fun mayPlace(stack: ItemStack): Boolean = false
|
||||
}
|
||||
)
|
||||
// 메뉴 아이템 슬롯 위치
|
||||
const val SLOT_SPAWN = 10 // 스폰
|
||||
const val SLOT_COORDINATES = 12 // 좌표
|
||||
const val SLOT_WORKBENCH = 14 // 제작대
|
||||
const val SLOT_TPA = 16 // TPA
|
||||
}
|
||||
|
||||
// 플레이어 인벤토리 슬롯
|
||||
for (row in 0 until 3) {
|
||||
for (col in 0 until 9) {
|
||||
val index = col + row * 9 + 9
|
||||
val x = 8 + col * 18
|
||||
val y = 86 + row * 18
|
||||
addSlot(Slot(playerInv, index, x, y))
|
||||
}
|
||||
}
|
||||
for (col in 0 until 9) {
|
||||
val x = 8 + col * 18
|
||||
val y = 144
|
||||
addSlot(Slot(playerInv, col, x, y))
|
||||
}
|
||||
}
|
||||
|
||||
override fun clicked(slotId: Int, button: Int, clickType: ClickType, player: Player) {
|
||||
if (slotId !in 0 until CONTAINER_SIZE || player !is ServerPlayer) {
|
||||
super.clicked(slotId, button, clickType, player)
|
||||
return
|
||||
}
|
||||
|
||||
val stack = slots[slotId].item
|
||||
val tag = stack.get(DataComponents.CUSTOM_DATA)?.copyTag() ?: return
|
||||
val action = tag.getString("action")
|
||||
|
||||
when (action) {
|
||||
"spawn" -> {
|
||||
player.closeContainer()
|
||||
// 스폰 명령어 실행
|
||||
player.server.commands.performPrefixedCommand(
|
||||
player.createCommandSourceStack(),
|
||||
"스폰"
|
||||
)
|
||||
}
|
||||
"coordinates" -> {
|
||||
player.closeContainer()
|
||||
// 좌표 GUI 열기
|
||||
player.server.commands.performPrefixedCommand(
|
||||
player.createCommandSourceStack(),
|
||||
"좌표"
|
||||
)
|
||||
}
|
||||
"workbench" -> {
|
||||
player.closeContainer()
|
||||
// 제작대 열기
|
||||
openWorkbench(player)
|
||||
}
|
||||
"tpa" -> {
|
||||
player.closeContainer()
|
||||
// TPA GUI 열기
|
||||
player.server.commands.performPrefixedCommand(
|
||||
player.createCommandSourceStack(),
|
||||
"tpa"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun openWorkbench(player: ServerPlayer) {
|
||||
val access =
|
||||
object : ContainerLevelAccess {
|
||||
override fun <T : Any> evaluate(
|
||||
function:
|
||||
java.util.function.BiFunction<
|
||||
net.minecraft.world.level.Level,
|
||||
net.minecraft.core.BlockPos,
|
||||
T>
|
||||
): java.util.Optional<T> {
|
||||
return java.util.Optional.ofNullable(
|
||||
function.apply(player.level(), player.blockPosition())
|
||||
init {
|
||||
// 컨테이너 슬롯 추가
|
||||
for (i in 0 until CONTAINER_SIZE) {
|
||||
val x = 8 + (i % 9) * 18
|
||||
val y = 18 + (i / 9) * 18
|
||||
addSlot(
|
||||
object : Slot(container, i, x, y) {
|
||||
override fun mayPickup(player: Player): Boolean = false
|
||||
override fun mayPlace(stack: ItemStack): Boolean = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
player.openMenu(
|
||||
SimpleMenuProvider(
|
||||
{ containerId, inventory, _ ->
|
||||
object : CraftingMenu(containerId, inventory, access) {
|
||||
override fun stillValid(player: Player): Boolean = true
|
||||
}
|
||||
},
|
||||
Component.translatable("container.crafting")
|
||||
)
|
||||
)
|
||||
}
|
||||
// 플레이어 인벤토리 슬롯
|
||||
for (row in 0 until 3) {
|
||||
for (col in 0 until 9) {
|
||||
val index = col + row * 9 + 9
|
||||
val x = 8 + col * 18
|
||||
val y = 86 + row * 18
|
||||
addSlot(Slot(playerInv, index, x, y))
|
||||
}
|
||||
}
|
||||
for (col in 0 until 9) {
|
||||
val x = 8 + col * 18
|
||||
val y = 144
|
||||
addSlot(Slot(playerInv, col, x, y))
|
||||
}
|
||||
}
|
||||
|
||||
override fun stillValid(player: Player): Boolean = true
|
||||
override fun quickMoveStack(player: Player, index: Int): ItemStack = ItemStack.EMPTY
|
||||
override fun clicked(slotId: Int, button: Int, clickType: ClickType, player: Player) {
|
||||
if (slotId !in 0 until CONTAINER_SIZE || player !is ServerPlayer) {
|
||||
super.clicked(slotId, button, clickType, player)
|
||||
return
|
||||
}
|
||||
|
||||
val stack = slots[slotId].item
|
||||
val tag = stack.get(DataComponents.CUSTOM_DATA)?.copyTag() ?: return
|
||||
val action = tag.getString("action")
|
||||
|
||||
when (action) {
|
||||
"spawn" -> {
|
||||
player.closeContainer()
|
||||
player.server.commands.performPrefixedCommand(
|
||||
player.createCommandSourceStack(),
|
||||
"스폰"
|
||||
)
|
||||
playClickSound(player)
|
||||
}
|
||||
"coordinates" -> {
|
||||
playClickSound(player)
|
||||
player.closeContainer()
|
||||
player.server.commands.performPrefixedCommand(
|
||||
player.createCommandSourceStack(),
|
||||
"좌표"
|
||||
)
|
||||
}
|
||||
"workbench" -> {
|
||||
player.closeContainer()
|
||||
openWorkbench(player)
|
||||
playClickSound(player)
|
||||
}
|
||||
"tpa" -> {
|
||||
playClickSound(player)
|
||||
player.closeContainer()
|
||||
player.server.commands.performPrefixedCommand(
|
||||
player.createCommandSourceStack(),
|
||||
"tpa"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun playClickSound(player: ServerPlayer) {
|
||||
player.playNotifySound(
|
||||
SoundEvents.NOTE_BLOCK_BELL.value(),
|
||||
SoundSource.MASTER,
|
||||
0.5f,
|
||||
1.0f
|
||||
)
|
||||
}
|
||||
|
||||
private fun openWorkbench(player: ServerPlayer) {
|
||||
val access =
|
||||
object : ContainerLevelAccess {
|
||||
override fun <T : Any> evaluate(
|
||||
function:
|
||||
java.util.function.BiFunction<
|
||||
net.minecraft.world.level.Level,
|
||||
net.minecraft.core.BlockPos,
|
||||
T>
|
||||
): java.util.Optional<T> {
|
||||
return java.util.Optional.ofNullable(
|
||||
function.apply(
|
||||
player.level(),
|
||||
player.blockPosition()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
player.openMenu(
|
||||
SimpleMenuProvider(
|
||||
{ containerId, inventory, _ ->
|
||||
object : CraftingMenu(containerId, inventory, access) {
|
||||
override fun stillValid(player: Player): Boolean =
|
||||
true
|
||||
}
|
||||
},
|
||||
Component.translatable("container.crafting")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun stillValid(player: Player): Boolean = true
|
||||
override fun quickMoveStack(player: Player, index: Int): ItemStack = ItemStack.EMPTY
|
||||
}
|
||||
|
||||
/** 메뉴 컨테이너 생성 */
|
||||
fun createEssentialsMenuContainer(): SimpleContainer {
|
||||
val container = SimpleContainer(27)
|
||||
val container = SimpleContainer(27)
|
||||
|
||||
// 배경을 회색 유리판으로 채우기
|
||||
val fillerItem = ItemStack(Items.GRAY_STAINED_GLASS_PANE)
|
||||
fillerItem.set(
|
||||
DataComponents.CUSTOM_NAME,
|
||||
Component.literal(" ").withStyle { it.withColor(ChatFormatting.DARK_GRAY) }
|
||||
)
|
||||
for (i in 0 until 27) {
|
||||
container.setItem(i, fillerItem.copy())
|
||||
}
|
||||
// 배경을 회색 유리판으로 채우기
|
||||
val fillerItem = ItemStack(Items.GRAY_STAINED_GLASS_PANE)
|
||||
fillerItem.set(
|
||||
DataComponents.CUSTOM_NAME,
|
||||
Component.literal(" ").withStyle { it.withColor(ChatFormatting.DARK_GRAY) }
|
||||
)
|
||||
for (i in 0 until 27) {
|
||||
container.setItem(i, fillerItem.copy())
|
||||
}
|
||||
|
||||
// 스폰 버튼
|
||||
val spawnItem = ItemStack(Items.GRASS_BLOCK)
|
||||
spawnItem.set(
|
||||
DataComponents.CUSTOM_NAME,
|
||||
Component.literal("스폰으로 이동").withStyle {
|
||||
it.withColor(ChatFormatting.GREEN).withBold(true)
|
||||
}
|
||||
)
|
||||
spawnItem.set(
|
||||
DataComponents.LORE,
|
||||
ItemLore(
|
||||
listOf(
|
||||
Component.literal("클릭하여 스폰으로 이동합니다.").withStyle {
|
||||
it.withColor(ChatFormatting.GRAY)
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
spawnItem.set(
|
||||
DataComponents.CUSTOM_DATA,
|
||||
CustomData.of(CompoundTag().apply { putString("action", "spawn") })
|
||||
)
|
||||
container.setItem(EssentialsMenuGui.SLOT_SPAWN, spawnItem)
|
||||
// 스폰 버튼
|
||||
val spawnItem = ItemStack(Items.GRASS_BLOCK)
|
||||
spawnItem.set(
|
||||
DataComponents.CUSTOM_NAME,
|
||||
Component.literal("스폰").withStyle {
|
||||
it.withColor(ChatFormatting.GREEN).withBold(true)
|
||||
}
|
||||
)
|
||||
spawnItem.set(
|
||||
DataComponents.LORE,
|
||||
ItemLore(
|
||||
listOf(
|
||||
Component.literal("스폰으로 이동합니다.").withStyle {
|
||||
it.withColor(ChatFormatting.GRAY)
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
spawnItem.set(
|
||||
DataComponents.CUSTOM_DATA,
|
||||
CustomData.of(CompoundTag().apply { putString("action", "spawn") })
|
||||
)
|
||||
container.setItem(EssentialsMenuGui.SLOT_SPAWN, spawnItem)
|
||||
|
||||
// 좌표 버튼
|
||||
val coordItem = ItemStack(Items.COMPASS)
|
||||
coordItem.set(
|
||||
DataComponents.CUSTOM_NAME,
|
||||
Component.literal("저장된 좌표").withStyle {
|
||||
it.withColor(ChatFormatting.YELLOW).withBold(true)
|
||||
}
|
||||
)
|
||||
coordItem.set(
|
||||
DataComponents.LORE,
|
||||
ItemLore(
|
||||
listOf(
|
||||
Component.literal("클릭하여 좌표 목록을 엽니다.").withStyle {
|
||||
it.withColor(ChatFormatting.GRAY)
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
coordItem.set(
|
||||
DataComponents.CUSTOM_DATA,
|
||||
CustomData.of(CompoundTag().apply { putString("action", "coordinates") })
|
||||
)
|
||||
container.setItem(EssentialsMenuGui.SLOT_COORDINATES, coordItem)
|
||||
// 좌표 버튼
|
||||
val coordItem = ItemStack(Items.COMPASS)
|
||||
coordItem.set(
|
||||
DataComponents.CUSTOM_NAME,
|
||||
Component.literal("좌표").withStyle {
|
||||
it.withColor(ChatFormatting.YELLOW).withBold(true)
|
||||
}
|
||||
)
|
||||
coordItem.set(
|
||||
DataComponents.LORE,
|
||||
ItemLore(
|
||||
listOf(
|
||||
Component.literal("저장된 좌표 목록을 엽니다.").withStyle {
|
||||
it.withColor(ChatFormatting.GRAY)
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
coordItem.set(
|
||||
DataComponents.CUSTOM_DATA,
|
||||
CustomData.of(CompoundTag().apply { putString("action", "coordinates") })
|
||||
)
|
||||
container.setItem(EssentialsMenuGui.SLOT_COORDINATES, coordItem)
|
||||
|
||||
// 제작대 버튼
|
||||
val workbenchItem = ItemStack(Items.CRAFTING_TABLE)
|
||||
workbenchItem.set(
|
||||
DataComponents.CUSTOM_NAME,
|
||||
Component.literal("제작대 열기").withStyle {
|
||||
it.withColor(ChatFormatting.GOLD).withBold(true)
|
||||
}
|
||||
)
|
||||
workbenchItem.set(
|
||||
DataComponents.LORE,
|
||||
ItemLore(
|
||||
listOf(
|
||||
Component.literal("클릭하여 제작대를 엽니다.").withStyle {
|
||||
it.withColor(ChatFormatting.GRAY)
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
workbenchItem.set(
|
||||
DataComponents.CUSTOM_DATA,
|
||||
CustomData.of(CompoundTag().apply { putString("action", "workbench") })
|
||||
)
|
||||
container.setItem(EssentialsMenuGui.SLOT_WORKBENCH, workbenchItem)
|
||||
// 제작대 버튼
|
||||
val workbenchItem = ItemStack(Items.CRAFTING_TABLE)
|
||||
workbenchItem.set(
|
||||
DataComponents.CUSTOM_NAME,
|
||||
Component.literal("제작대").withStyle {
|
||||
it.withColor(ChatFormatting.GOLD).withBold(true)
|
||||
}
|
||||
)
|
||||
workbenchItem.set(
|
||||
DataComponents.LORE,
|
||||
ItemLore(
|
||||
listOf(
|
||||
Component.literal("제작대를 엽니다.").withStyle {
|
||||
it.withColor(ChatFormatting.GRAY)
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
workbenchItem.set(
|
||||
DataComponents.CUSTOM_DATA,
|
||||
CustomData.of(CompoundTag().apply { putString("action", "workbench") })
|
||||
)
|
||||
container.setItem(EssentialsMenuGui.SLOT_WORKBENCH, workbenchItem)
|
||||
|
||||
// TPA 버튼
|
||||
val tpaItem = ItemStack(Items.ENDER_PEARL)
|
||||
tpaItem.set(
|
||||
DataComponents.CUSTOM_NAME,
|
||||
Component.literal("플레이어 텔레포트").withStyle {
|
||||
it.withColor(ChatFormatting.AQUA).withBold(true)
|
||||
}
|
||||
)
|
||||
tpaItem.set(
|
||||
DataComponents.LORE,
|
||||
ItemLore(
|
||||
listOf(
|
||||
Component.literal("클릭하여 다른 플레이어에게 이동합니다.").withStyle {
|
||||
it.withColor(ChatFormatting.GRAY)
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
tpaItem.set(
|
||||
DataComponents.CUSTOM_DATA,
|
||||
CustomData.of(CompoundTag().apply { putString("action", "tpa") })
|
||||
)
|
||||
container.setItem(EssentialsMenuGui.SLOT_TPA, tpaItem)
|
||||
// TPA 버튼
|
||||
val tpaItem = ItemStack(Items.ENDER_PEARL)
|
||||
tpaItem.set(
|
||||
DataComponents.CUSTOM_NAME,
|
||||
Component.literal("텔레포트").withStyle {
|
||||
it.withColor(ChatFormatting.AQUA).withBold(true)
|
||||
}
|
||||
)
|
||||
tpaItem.set(
|
||||
DataComponents.LORE,
|
||||
ItemLore(
|
||||
listOf(
|
||||
Component.literal("다른 플레이어에게 이동합니다.").withStyle {
|
||||
it.withColor(ChatFormatting.GRAY)
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
tpaItem.set(
|
||||
DataComponents.CUSTOM_DATA,
|
||||
CustomData.of(CompoundTag().apply { putString("action", "tpa") })
|
||||
)
|
||||
container.setItem(EssentialsMenuGui.SLOT_TPA, tpaItem)
|
||||
|
||||
return container
|
||||
return container
|
||||
}
|
||||
|
||||
/** 메뉴 GUI 열기 */
|
||||
fun openEssentialsMenu(player: ServerPlayer) {
|
||||
val container = createEssentialsMenuContainer()
|
||||
player.openMenu(
|
||||
SimpleMenuProvider(
|
||||
{ windowId, inv, _ -> EssentialsMenuGui(windowId, inv, container, player) },
|
||||
Component.literal("Essentials 메뉴").withStyle { it.withBold(true) }
|
||||
)
|
||||
)
|
||||
val container = createEssentialsMenuContainer()
|
||||
player.openMenu(
|
||||
SimpleMenuProvider(
|
||||
{ windowId, inv, _ -> EssentialsMenuGui(windowId, inv, container, player) },
|
||||
Component.literal("Essentials 메뉴").withStyle { it.withBold(true) }
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ package com.beemer.essentials.gui
|
|||
|
||||
import com.beemer.essentials.config.PlayerConfig
|
||||
import com.beemer.essentials.data.Location
|
||||
import com.beemer.essentials.data.Player
|
||||
import com.beemer.essentials.nickname.NicknameDataStore
|
||||
import com.beemer.essentials.util.MessageUtils
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.Container
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
|
|
@ -78,65 +79,78 @@ class TeleportGui(
|
|||
player: net.minecraft.world.entity.player.Player
|
||||
) {
|
||||
if (slotId in 0 until CONTAINER_SIZE && player is ServerPlayer) {
|
||||
// 해당 슬롯에 플레이어가 있는지 확인
|
||||
val currentTargetPlayer =
|
||||
targetPlayers.getOrNull(slotId)?.let {
|
||||
player.server.playerList.getPlayer(it)
|
||||
}
|
||||
|
||||
if (currentTargetPlayer != null && player.uuid != currentTargetPlayer.uuid
|
||||
) {
|
||||
val prevPos = player.blockPosition()
|
||||
val prevDimension = player.level().dimension().location().toString()
|
||||
val prevBiome =
|
||||
player.level()
|
||||
.getBiome(prevPos)
|
||||
.unwrapKey()
|
||||
.map { it.location().toString() }
|
||||
.orElse("minecraft:plains")
|
||||
val previousLocation =
|
||||
Location(
|
||||
dimension = prevDimension,
|
||||
biome = prevBiome,
|
||||
x = prevPos.x.toDouble(),
|
||||
y = prevPos.y.toDouble(),
|
||||
z = prevPos.z.toDouble()
|
||||
)
|
||||
PlayerConfig.recordLastLocation(player, previousLocation)
|
||||
|
||||
val targetLevel = currentTargetPlayer.serverLevel()
|
||||
|
||||
player.teleportTo(
|
||||
targetLevel,
|
||||
currentTargetPlayer.x,
|
||||
currentTargetPlayer.y,
|
||||
currentTargetPlayer.z,
|
||||
currentTargetPlayer.yRot,
|
||||
currentTargetPlayer.xRot
|
||||
)
|
||||
|
||||
// 닉네임이 있으면 닉네임 사용
|
||||
val targetName =
|
||||
NicknameDataStore.getNickname(currentTargetPlayer.uuid)
|
||||
?: currentTargetPlayer.gameProfile.name
|
||||
val playerName =
|
||||
NicknameDataStore.getNickname(player.uuid)
|
||||
?: player.gameProfile.name
|
||||
|
||||
MessageUtils.sendSuccess(player, "{$targetName}님에게 텔레포트 했습니다.")
|
||||
MessageUtils.sendInfo(
|
||||
currentTargetPlayer,
|
||||
"{$playerName}님이 당신에게 텔레포트 했습니다."
|
||||
)
|
||||
} else {
|
||||
MessageUtils.sendError(player, "해당 플레이어는 현재 오프라인입니다.")
|
||||
// 플레이어가 없으면 무시 (빈 공간 클릭)
|
||||
if (currentTargetPlayer == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val prevPos = player.blockPosition()
|
||||
val prevDimension = player.level().dimension().location().toString()
|
||||
val prevBiome =
|
||||
player.level()
|
||||
.getBiome(prevPos)
|
||||
.unwrapKey()
|
||||
.map { it.location().toString() }
|
||||
.orElse("minecraft:plains")
|
||||
val previousLocation =
|
||||
Location(
|
||||
dimension = prevDimension,
|
||||
biome = prevBiome,
|
||||
x = prevPos.x.toDouble(),
|
||||
y = prevPos.y.toDouble(),
|
||||
z = prevPos.z.toDouble()
|
||||
)
|
||||
PlayerConfig.recordLastLocation(player, previousLocation)
|
||||
|
||||
val targetLevel = currentTargetPlayer.serverLevel()
|
||||
|
||||
player.teleportTo(
|
||||
targetLevel,
|
||||
currentTargetPlayer.x,
|
||||
currentTargetPlayer.y,
|
||||
currentTargetPlayer.z,
|
||||
currentTargetPlayer.yRot,
|
||||
currentTargetPlayer.xRot
|
||||
)
|
||||
|
||||
// 소리 재생 (텔레포트 후)
|
||||
playClickSound(player)
|
||||
|
||||
// 닉네임이 있으면 닉네임 사용
|
||||
val targetName =
|
||||
NicknameDataStore.getNickname(currentTargetPlayer.uuid)
|
||||
?: currentTargetPlayer.gameProfile.name
|
||||
val playerName =
|
||||
NicknameDataStore.getNickname(player.uuid)
|
||||
?: player.gameProfile.name
|
||||
|
||||
MessageUtils.sendSuccess(player, "{$targetName}님에게 텔레포트 했습니다.")
|
||||
MessageUtils.sendInfo(
|
||||
currentTargetPlayer,
|
||||
"{$playerName}님이 당신에게 텔레포트 했습니다."
|
||||
)
|
||||
|
||||
player.closeContainer()
|
||||
return
|
||||
}
|
||||
super.clicked(slotId, button, clickType, player)
|
||||
}
|
||||
|
||||
private fun playClickSound(player: ServerPlayer) {
|
||||
player.playNotifySound(
|
||||
SoundEvents.NOTE_BLOCK_BELL.value(),
|
||||
SoundSource.MASTER,
|
||||
0.5f,
|
||||
1.0f
|
||||
)
|
||||
}
|
||||
|
||||
override fun stillValid(player: net.minecraft.world.entity.player.Player): Boolean = true
|
||||
|
||||
override fun quickMoveStack(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue