feat: GUI 클릭 소리 및 개선

- 모든 GUI에 bell 클릭 소리 추가 (playNotifySound로 해당 플레이어만 듣도록)
- TeleportGui: 다른 플레이어 없으면 메시지만 표시, 빈 공간 클릭 무시
- EssentialsMenuGui: 아이템 이름 간소화 (스폰/좌표/제작대/텔레포트)
- 설명 텍스트에서 '클릭하여' 제거, 좌표에 '저장된' 추가
This commit is contained in:
Caadiq 2025-12-29 17:27:49 +09:00
parent 791d6f2e9f
commit 4dba2a4803
5 changed files with 319 additions and 265 deletions

View file

@ -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 ->

View file

@ -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)

View file

@ -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

View file

@ -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
@ -81,15 +83,15 @@ class EssentialsMenuGui(
when (action) {
"spawn" -> {
player.closeContainer()
// 스폰 명령어 실행
player.server.commands.performPrefixedCommand(
player.createCommandSourceStack(),
"스폰"
)
playClickSound(player)
}
"coordinates" -> {
playClickSound(player)
player.closeContainer()
// 좌표 GUI 열기
player.server.commands.performPrefixedCommand(
player.createCommandSourceStack(),
"좌표"
@ -97,12 +99,12 @@ class EssentialsMenuGui(
}
"workbench" -> {
player.closeContainer()
// 제작대 열기
openWorkbench(player)
playClickSound(player)
}
"tpa" -> {
playClickSound(player)
player.closeContainer()
// TPA GUI 열기
player.server.commands.performPrefixedCommand(
player.createCommandSourceStack(),
"tpa"
@ -111,6 +113,15 @@ class EssentialsMenuGui(
}
}
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 {
@ -122,7 +133,10 @@ class EssentialsMenuGui(
T>
): java.util.Optional<T> {
return java.util.Optional.ofNullable(
function.apply(player.level(), player.blockPosition())
function.apply(
player.level(),
player.blockPosition()
)
)
}
}
@ -131,7 +145,8 @@ class EssentialsMenuGui(
SimpleMenuProvider(
{ containerId, inventory, _ ->
object : CraftingMenu(containerId, inventory, access) {
override fun stillValid(player: Player): Boolean = true
override fun stillValid(player: Player): Boolean =
true
}
},
Component.translatable("container.crafting")
@ -161,7 +176,7 @@ fun createEssentialsMenuContainer(): SimpleContainer {
val spawnItem = ItemStack(Items.GRASS_BLOCK)
spawnItem.set(
DataComponents.CUSTOM_NAME,
Component.literal("스폰으로 이동").withStyle {
Component.literal("스폰").withStyle {
it.withColor(ChatFormatting.GREEN).withBold(true)
}
)
@ -169,7 +184,7 @@ fun createEssentialsMenuContainer(): SimpleContainer {
DataComponents.LORE,
ItemLore(
listOf(
Component.literal("클릭하여 스폰으로 이동합니다.").withStyle {
Component.literal("스폰으로 이동합니다.").withStyle {
it.withColor(ChatFormatting.GRAY)
}
)
@ -185,7 +200,7 @@ fun createEssentialsMenuContainer(): SimpleContainer {
val coordItem = ItemStack(Items.COMPASS)
coordItem.set(
DataComponents.CUSTOM_NAME,
Component.literal("저장된 좌표").withStyle {
Component.literal("좌표").withStyle {
it.withColor(ChatFormatting.YELLOW).withBold(true)
}
)
@ -193,7 +208,7 @@ fun createEssentialsMenuContainer(): SimpleContainer {
DataComponents.LORE,
ItemLore(
listOf(
Component.literal("클릭하여 좌표 목록을 엽니다.").withStyle {
Component.literal("저장된 좌표 목록을 엽니다.").withStyle {
it.withColor(ChatFormatting.GRAY)
}
)
@ -209,7 +224,7 @@ fun createEssentialsMenuContainer(): SimpleContainer {
val workbenchItem = ItemStack(Items.CRAFTING_TABLE)
workbenchItem.set(
DataComponents.CUSTOM_NAME,
Component.literal("제작대 열기").withStyle {
Component.literal("제작대").withStyle {
it.withColor(ChatFormatting.GOLD).withBold(true)
}
)
@ -217,7 +232,7 @@ fun createEssentialsMenuContainer(): SimpleContainer {
DataComponents.LORE,
ItemLore(
listOf(
Component.literal("클릭하여 제작대를 엽니다.").withStyle {
Component.literal("제작대를 엽니다.").withStyle {
it.withColor(ChatFormatting.GRAY)
}
)
@ -233,7 +248,7 @@ fun createEssentialsMenuContainer(): SimpleContainer {
val tpaItem = ItemStack(Items.ENDER_PEARL)
tpaItem.set(
DataComponents.CUSTOM_NAME,
Component.literal("플레이어 텔레포트").withStyle {
Component.literal("텔레포트").withStyle {
it.withColor(ChatFormatting.AQUA).withBold(true)
}
)
@ -241,7 +256,7 @@ fun createEssentialsMenuContainer(): SimpleContainer {
DataComponents.LORE,
ItemLore(
listOf(
Component.literal("클릭하여 다른 플레이어에게 이동합니다.").withStyle {
Component.literal("다른 플레이어에게 이동합니다.").withStyle {
it.withColor(ChatFormatting.GRAY)
}
)

View file

@ -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,13 +79,17 @@ 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
) {
// 플레이어가 없으면 무시 (빈 공간 클릭)
if (currentTargetPlayer == null) {
return
}
val prevPos = player.blockPosition()
val prevDimension = player.level().dimension().location().toString()
val prevBiome =
@ -114,6 +119,9 @@ class TeleportGui(
currentTargetPlayer.xRot
)
// 소리 재생 (텔레포트 후)
playClickSound(player)
// 닉네임이 있으면 닉네임 사용
val targetName =
NicknameDataStore.getNickname(currentTargetPlayer.uuid)
@ -127,9 +135,6 @@ class TeleportGui(
currentTargetPlayer,
"{$playerName}님이 당신에게 텔레포트 했습니다."
)
} else {
MessageUtils.sendError(player, "해당 플레이어는 현재 오프라인입니다.")
}
player.closeContainer()
return
@ -137,6 +142,15 @@ class TeleportGui(
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(