98 lines
2.9 KiB
React
98 lines
2.9 KiB
React
|
|
import React, { useState, useEffect, useRef } from 'react';
|
||
|
|
import { motion } from 'framer-motion';
|
||
|
|
import { io } from 'socket.io-client';
|
||
|
|
import { ServerOff, Map } from 'lucide-react';
|
||
|
|
|
||
|
|
const WorldMapPage = ({ isMobile = false }) => {
|
||
|
|
const [serverOnline, setServerOnline] = useState(null); // null = loading, true/false = 상태
|
||
|
|
const socketRef = useRef(null);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
// 소켓 연결하여 서버 상태 확인
|
||
|
|
const socket = io('/', {
|
||
|
|
path: '/socket.io',
|
||
|
|
transports: ['websocket', 'polling']
|
||
|
|
});
|
||
|
|
socketRef.current = socket;
|
||
|
|
|
||
|
|
socket.on('status', (data) => {
|
||
|
|
setServerOnline(data.online);
|
||
|
|
});
|
||
|
|
|
||
|
|
return () => {
|
||
|
|
socket.disconnect();
|
||
|
|
};
|
||
|
|
}, []);
|
||
|
|
|
||
|
|
// 로딩 중
|
||
|
|
if (serverOnline === null) {
|
||
|
|
return (
|
||
|
|
<div
|
||
|
|
className="w-full flex items-center justify-center bg-mc-dark"
|
||
|
|
style={{ height: isMobile ? 'calc(100dvh - 56px)' : '100dvh' }}
|
||
|
|
>
|
||
|
|
<div className="text-center">
|
||
|
|
<div className="w-12 h-12 border-4 border-mc-green/30 border-t-mc-green rounded-full animate-spin mx-auto mb-4" />
|
||
|
|
<p className="text-gray-400">서버 상태 확인 중...</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 서버 오프라인
|
||
|
|
if (!serverOnline) {
|
||
|
|
return (
|
||
|
|
<div
|
||
|
|
className="w-full flex items-center justify-center bg-mc-dark"
|
||
|
|
style={{ height: isMobile ? 'calc(100dvh - 56px)' : '100dvh' }}
|
||
|
|
>
|
||
|
|
<motion.div
|
||
|
|
initial={{ opacity: 0, y: 20 }}
|
||
|
|
animate={{ opacity: 1, y: 0 }}
|
||
|
|
className="text-center p-8"
|
||
|
|
>
|
||
|
|
<div className="w-20 h-20 mx-auto mb-6 rounded-2xl bg-gradient-to-br from-red-500/20 to-orange-500/20 border border-red-500/30 flex items-center justify-center">
|
||
|
|
<ServerOff className="w-10 h-10 text-red-400" />
|
||
|
|
</div>
|
||
|
|
<h2 className="text-2xl font-bold text-white mb-2">서버 오프라인</h2>
|
||
|
|
<p className="text-gray-400 mb-6">
|
||
|
|
마인크래프트 서버가 현재 오프라인 상태입니다.<br />
|
||
|
|
서버가 시작되면 월드맵을 확인할 수 있습니다.
|
||
|
|
</p>
|
||
|
|
<div className="inline-flex items-center gap-2 px-4 py-2 bg-white/5 rounded-lg text-gray-500 text-sm">
|
||
|
|
<Map size={16} />
|
||
|
|
월드맵 이용 불가
|
||
|
|
</div>
|
||
|
|
</motion.div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 서버 온라인 - BlueMap 표시
|
||
|
|
return (
|
||
|
|
<div
|
||
|
|
className="w-full"
|
||
|
|
style={{
|
||
|
|
height: isMobile ? 'calc(100dvh - 56px)' : '100dvh'
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
{/* BlueMap iframe - 전체 화면 */}
|
||
|
|
<motion.div
|
||
|
|
initial={{ opacity: 0 }}
|
||
|
|
animate={{ opacity: 1 }}
|
||
|
|
transition={{ duration: 0.3 }}
|
||
|
|
className="h-full w-full"
|
||
|
|
>
|
||
|
|
<iframe
|
||
|
|
src="/map/"
|
||
|
|
title="BlueMap 3D World Map"
|
||
|
|
className="w-full h-full border-none"
|
||
|
|
allowFullScreen
|
||
|
|
/>
|
||
|
|
</motion.div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default WorldMapPage;
|