2025-12-29 15:13:37 +09:00
|
|
|
package com.beemer.essentials.util
|
|
|
|
|
|
|
|
|
|
import net.minecraft.network.chat.Component
|
|
|
|
|
import net.minecraft.network.chat.MutableComponent
|
|
|
|
|
import net.minecraft.network.chat.Style
|
|
|
|
|
import net.minecraft.network.chat.TextColor
|
|
|
|
|
import net.minecraft.server.level.ServerPlayer
|
|
|
|
|
|
|
|
|
|
/** 메시지 스타일 유틸리티 기본 텍스트: 밝은 청록색 (#A8D8D8) 강조 텍스트: 흰색 (#FFFFFF) */
|
|
|
|
|
object MessageUtils {
|
|
|
|
|
|
|
|
|
|
// 기본 색상 (더 밝게)
|
|
|
|
|
private const val BASE_COLOR = 0xA8D8D8 // 밝은 청록색 (기본 텍스트)
|
|
|
|
|
private const val ACCENT_COLOR = 0xFFFFFF // 흰색 (강조)
|
|
|
|
|
private const val ERROR_COLOR = 0xFF8888 // 밝은 빨간색 (오류)
|
|
|
|
|
private const val WARNING_COLOR = 0xFFE066 // 밝은 노란색 (경고)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 기본 스타일 메시지 생성
|
|
|
|
|
* @param text 텍스트 (강조 부분은 {중괄호}로 감싸기) 예: "스폰으로 이동했습니다." 또는 "{비머}님에게 텔레포트 요청을 보냈습니다."
|
|
|
|
|
*/
|
|
|
|
|
fun styled(text: String): MutableComponent {
|
|
|
|
|
return parseStyledText(text, BASE_COLOR, ACCENT_COLOR)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 성공 메시지 (아이콘 없이 기본 스타일) */
|
|
|
|
|
fun success(text: String): MutableComponent {
|
|
|
|
|
return styled(text)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 정보 메시지 (아이콘 없이 기본 스타일) */
|
|
|
|
|
fun info(text: String): MutableComponent {
|
|
|
|
|
return styled(text)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 오류 메시지 (빨간색 스타일) */
|
|
|
|
|
fun error(text: String): MutableComponent {
|
|
|
|
|
return parseStyledText(text, ERROR_COLOR, ACCENT_COLOR)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 경고 메시지 (노란색 스타일) */
|
|
|
|
|
fun warning(text: String): MutableComponent {
|
|
|
|
|
return parseStyledText(text, WARNING_COLOR, ACCENT_COLOR)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// === 플레이어에게 직접 전송 ===
|
|
|
|
|
|
|
|
|
|
fun sendSuccess(player: ServerPlayer, text: String) {
|
|
|
|
|
player.sendSystemMessage(success(text))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun sendInfo(player: ServerPlayer, text: String) {
|
|
|
|
|
player.sendSystemMessage(info(text))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun sendError(player: ServerPlayer, text: String) {
|
|
|
|
|
player.sendSystemMessage(error(text))
|
2025-12-30 19:26:10 +09:00
|
|
|
playErrorSound(player)
|
2025-12-29 15:13:37 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun sendWarning(player: ServerPlayer, text: String) {
|
|
|
|
|
player.sendSystemMessage(warning(text))
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-30 19:26:10 +09:00
|
|
|
/** 알림 메시지 (사운드 포함) - 서버 접속 시 등 */
|
|
|
|
|
fun sendNotification(player: ServerPlayer, text: String) {
|
|
|
|
|
player.sendSystemMessage(info(text))
|
|
|
|
|
playNotificationSound(player)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// === 사운드 재생 ===
|
|
|
|
|
|
|
|
|
|
private fun playErrorSound(player: ServerPlayer) {
|
|
|
|
|
val errorSound =
|
|
|
|
|
net.minecraft.sounds.SoundEvent.createVariableRangeEvent(
|
|
|
|
|
net.minecraft.resources.ResourceLocation.parse("minecraft:custom.error")
|
|
|
|
|
)
|
|
|
|
|
player.playNotifySound(errorSound, net.minecraft.sounds.SoundSource.MASTER, 0.2f, 1.0f)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-29 15:13:37 +09:00
|
|
|
/** 스타일 텍스트 파싱 {중괄호} 안의 텍스트는 강조 색상으로 표시 */
|
|
|
|
|
private fun parseStyledText(text: String, baseColor: Int, accentColor: Int): MutableComponent {
|
|
|
|
|
val result: MutableComponent = Component.empty()
|
|
|
|
|
var i = 0
|
|
|
|
|
val sb = StringBuilder()
|
|
|
|
|
|
|
|
|
|
while (i < text.length) {
|
|
|
|
|
when {
|
|
|
|
|
text[i] == '{' -> {
|
|
|
|
|
// 이전 텍스트 추가 (기본 색상)
|
|
|
|
|
if (sb.isNotEmpty()) {
|
|
|
|
|
result.append(
|
|
|
|
|
Component.literal(sb.toString())
|
|
|
|
|
.withStyle(
|
|
|
|
|
Style.EMPTY.withColor(TextColor.fromRgb(baseColor))
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
sb.clear()
|
|
|
|
|
}
|
|
|
|
|
// 강조 텍스트 찾기
|
|
|
|
|
val endIdx = text.indexOf('}', i)
|
|
|
|
|
if (endIdx != -1) {
|
|
|
|
|
val accentText = text.substring(i + 1, endIdx)
|
|
|
|
|
result.append(
|
|
|
|
|
Component.literal(accentText)
|
|
|
|
|
.withStyle(
|
|
|
|
|
Style.EMPTY.withColor(
|
|
|
|
|
TextColor.fromRgb(accentColor)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
i = endIdx + 1
|
|
|
|
|
} else {
|
|
|
|
|
sb.append(text[i])
|
|
|
|
|
i++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else -> {
|
|
|
|
|
sb.append(text[i])
|
|
|
|
|
i++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 남은 텍스트 추가
|
|
|
|
|
if (sb.isNotEmpty()) {
|
|
|
|
|
result.append(
|
|
|
|
|
Component.literal(sb.toString())
|
|
|
|
|
.withStyle(Style.EMPTY.withColor(TextColor.fromRgb(baseColor)))
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
}
|