minecraft-mod/Essentials/src/main/kotlin/com/beemer/essentials/event/PlayerEvents.kt
Caadiq fd4540c9e7 feat: 커스텀 사운드 시스템 추가
- 클릭 사운드 (custom.click) - GUI 버튼 클릭 시
- 에러 사운드 (custom.error) - 오류 메시지 시 자동 재생
- 알림 사운드 (custom.notification) - 신규 플레이어 환영 시
- 텔레포트 사운드 (custom.teleport) - 스폰, 좌표이동, TPA, back
- 메뉴 사운드 (custom.menu) - 메뉴 GUI 열기 시

기타 변경:
- 닉네임 변경 시 동일 닉네임 예외처리 추가
- TPA 오류 메시지 빨간색으로 변경
2025-12-30 19:26:10 +09:00

156 lines
5.9 KiB
Kotlin

package com.beemer.essentials.event
import com.beemer.essentials.config.PlayerConfig
import com.beemer.essentials.config.SpawnConfig
import com.beemer.essentials.data.Location
import com.beemer.essentials.util.ChatUtils
import com.beemer.essentials.util.DimensionUtils
import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerPlayer
import net.neoforged.bus.api.SubscribeEvent
import net.neoforged.neoforge.event.entity.player.PlayerEvent
object PlayerEvents {
@SubscribeEvent
fun onPlayerRespawn(event: PlayerEvent.PlayerRespawnEvent) {
val player = event.entity as? ServerPlayer ?: return
val target = SpawnConfig.getCustomSpawn() ?: SpawnConfig.getDefaultSpawn() ?: return
val level = DimensionUtils.getLevelById(player.server, target.dimension) ?: return
player.teleportTo(level, target.x, target.y, target.z, player.yRot, player.xRot)
}
@SubscribeEvent
fun onPlayerLoggedIn(event: PlayerEvent.PlayerLoggedInEvent) {
val player = event.entity as? ServerPlayer ?: return
val existing = PlayerConfig.getPlayer(player)
val isFirstJoin = existing == null
ChatUtils.broadcastJoin(player, isFirstJoin)
PlayerConfig.recordLogin(player)
if (isFirstJoin) {
val spawn = SpawnConfig.getCustomSpawn() ?: SpawnConfig.getDefaultSpawn() ?: return
val level = DimensionUtils.getLevelById(player.server, spawn.dimension) ?: return
player.teleportTo(level, spawn.x, spawn.y, spawn.z, player.yRot, player.xRot)
// 신규 플레이어 도움말 (약간의 딜레이 후 표시)
player.server.execute {
sendWelcomeGuide(player)
// 알림 사운드 재생
playNotificationSound(player)
}
}
}
/** 알림 사운드 재생 */
private fun playNotificationSound(player: ServerPlayer) {
val notificationSound =
net.minecraft.sounds.SoundEvent.createVariableRangeEvent(
net.minecraft.resources.ResourceLocation.parse(
"minecraft:custom.notification"
)
)
player.playNotifySound(
notificationSound,
net.minecraft.sounds.SoundSource.MASTER,
0.5f,
1.0f
)
}
/** 신규 플레이어 도움말 */
private fun sendWelcomeGuide(player: ServerPlayer) {
val separator =
Component.literal("═══════════════════════════════").withStyle {
it.withColor(ChatFormatting.DARK_AQUA)
}
player.sendSystemMessage(Component.empty())
player.sendSystemMessage(separator)
player.sendSystemMessage(
Component.literal("🎉 서버에 오신 것을 환영합니다!").withStyle {
it.withColor(ChatFormatting.AQUA).withBold(true)
}
)
player.sendSystemMessage(Component.empty())
// 기본 명령어 안내
player.sendSystemMessage(
Component.literal("▸ 기본 명령어").withStyle {
it.withColor(ChatFormatting.YELLOW).withBold(true)
}
)
sendGuideItem(player, "/도움말", "명령어 목록 보기")
sendGuideItem(player, "/메뉴", "메뉴 GUI 열기")
sendGuideItem(player, "/스폰", "스폰으로 이동")
player.sendSystemMessage(Component.empty())
// 단축키 안내
player.sendSystemMessage(
Component.literal("▸ 단축키").withStyle {
it.withColor(ChatFormatting.YELLOW).withBold(true)
}
)
sendGuideItem(player, "Shift + F", "메뉴 GUI 열기")
player.sendSystemMessage(separator)
player.sendSystemMessage(Component.empty())
}
private fun sendGuideItem(player: ServerPlayer, key: String, desc: String) {
player.sendSystemMessage(
Component.literal(" ")
.append(
Component.literal(key).withStyle {
it.withColor(ChatFormatting.WHITE)
}
)
.append(
Component.literal(" - $desc").withStyle {
it.withColor(ChatFormatting.GRAY)
}
)
)
}
@SubscribeEvent
fun onPlayerLoggedOut(event: PlayerEvent.PlayerLoggedOutEvent) {
val player = event.entity as? ServerPlayer ?: return
ChatUtils.broadcastQuit(player)
PlayerConfig.recordLogout(player)
}
@SubscribeEvent
fun onPlayerClone(event: PlayerEvent.Clone) {
if (!event.isWasDeath) return
val oldPlayer = event.original as? ServerPlayer ?: return
val pos = oldPlayer.blockPosition()
val dimension = oldPlayer.level().dimension().location().toString()
val biome =
oldPlayer
.level()
.getBiome(pos)
.unwrapKey()
.map { it.location().toString() }
.orElse("minecraft:plains")
val lastLoc =
Location(
dimension = dimension,
biome = biome,
x = pos.x.toDouble(),
y = pos.y.toDouble(),
z = pos.z.toDouble()
)
PlayerConfig.recordLastLocation(oldPlayer, lastLoc)
}
}