minecraft-web/backend/lib/minecraft.js

156 lines
3.7 KiB
JavaScript
Raw Permalink Normal View History

2025-12-16 08:40:32 +09:00
import { status } from "minecraft-server-util";
const MOD_API_URL = process.env.MOD_API_URL || "http://minecraft-server:8080";
// 캐시된 데이터
let cachedStatus = null;
let cachedPlayers = [];
/**
* 모드 API에서 상태 가져오기
*/
async function fetchModStatus() {
try {
const response = await fetch(`${MOD_API_URL}/status`);
if (response.ok) return await response.json();
return null;
} catch (error) {
console.error("[ModAPI] 상태 조회 실패:", error.message);
return null;
}
}
/**
* MOTD 가져오기 (마인크래프트 프로토콜 사용)
*/
async function fetchMotd() {
try {
const result = await status("minecraft-server", 25565, { timeout: 5000 });
return {
motd: result.motd?.html || null,
icon: result.favicon || null,
};
} catch (error) {
return { motd: null, icon: null };
}
}
/**
* 클라이언트용 상태 포맷 변환
*/
function formatStatusForClient(modStatus, motdData) {
if (!modStatus) {
return {
online: false,
motd: null,
players: { current: 0, max: 0, list: [] },
version: "Unknown",
icon: null,
uptime: "오프라인",
tps: 0,
mspt: 0,
memoryUsedMb: 0,
memoryMaxMb: 0,
2025-12-16 08:40:32 +09:00
};
}
const uptimeMinutes = modStatus.uptimeMinutes || 0;
const days = Math.floor(uptimeMinutes / 1440);
const hours = Math.floor((uptimeMinutes % 1440) / 60);
const minutes = uptimeMinutes % 60;
let uptime;
if (days > 0) uptime = `${days}${hours}시간`;
else if (hours > 0) uptime = `${hours}시간 ${minutes}`;
else uptime = `${minutes}`;
return {
online: modStatus.online,
motd: motdData?.motd || null,
icon: motdData?.icon || null,
players: {
current: modStatus.players?.current || 0,
max: modStatus.players?.max || 20,
list:
modStatus.players?.online?.map((p) => ({
name: p.name,
uuid: p.uuid,
id: p.uuid,
isOp: p.isOp,
})) || [],
},
version: modStatus.version || "Unknown",
modLoader: modStatus.modLoader || null,
uptime: modStatus.online ? uptime : "오프라인",
difficulty: modStatus.difficulty || "알 수 없음",
gameRules: modStatus.gameRules || {},
mods: modStatus.mods || [],
tps: modStatus.tps || 0,
mspt: modStatus.mspt || 0,
memoryUsedMb: modStatus.memoryUsedMb || 0,
memoryMaxMb: modStatus.memoryMaxMb || 0,
2025-12-16 08:40:32 +09:00
};
}
/**
* 전체 플레이어 목록 조회
*/
async function fetchAllPlayers() {
try {
const response = await fetch(`${MOD_API_URL}/players`);
if (response.ok) {
const data = await response.json();
return data.players || [];
}
return [];
} catch (error) {
console.error("[ModAPI] 플레이어 목록 조회 실패:", error.message);
return [];
}
}
/**
* 특정 플레이어 정보 조회
*/
async function fetchPlayerDetail(uuid) {
try {
const response = await fetch(`${MOD_API_URL}/player/${uuid}`);
if (response.ok) return await response.json();
return null;
} catch (error) {
console.error("[ModAPI] 플레이어 조회 실패:", error.message);
return null;
}
}
/**
* 주기적 데이터 갱신
*/
async function refreshData() {
const [modStatus, motdData, players] = await Promise.all([
fetchModStatus(),
fetchMotd(),
fetchAllPlayers(),
]);
cachedStatus = formatStatusForClient(modStatus, motdData);
cachedPlayers = players;
return { cachedStatus, cachedPlayers };
}
const getCachedStatus = () => cachedStatus;
const getCachedPlayers = () => cachedPlayers;
export {
MOD_API_URL,
fetchModStatus,
fetchMotd,
formatStatusForClient,
fetchAllPlayers,
fetchPlayerDetail,
refreshData,
getCachedStatus,
getCachedPlayers,
};