치지직 채팅창 인식 추가 및 주사위 횟수 증가 추가.

This commit is contained in:
kimyu
2026-09-16 02:21:39 +09:00
parent 171a4e19f6
commit 7c402dfd8f
22 changed files with 2133 additions and 90 deletions

View File

@@ -2,6 +2,7 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import Dice from './dice';
import ChatFeedPanel, { type ChatFeedItem } from './chat-feed';
import { Chessman } from './chessman';
import ChessmanPiece from './chessman-piece';
import { applyLandEvent, type PlaneCell } from './cell-event';
@@ -20,7 +21,19 @@ function cellLabel(cell: PlaneCell | undefined, index: number) {
return index === 0 ? '시작' : cell.type;
}
export default function DicePlane() {
export default function DicePlane({
requireDiceQueue = false,
diceQueue = 0,
onConsumeDice,
chatFeed = [],
showChatFeed = false,
}: {
requireDiceQueue?: boolean;
diceQueue?: number;
onConsumeDice?: (count?: number) => Promise<{ ok: boolean; error?: string }>;
chatFeed?: ChatFeedItem[];
showChatFeed?: boolean;
}) {
const initial = getOrCreateBoardConfig();
const [planeSize, setPlaneSize] = useState({
width: initial.width,
@@ -35,6 +48,11 @@ export default function DicePlane() {
const [chessmanSrc, setChessmanSrc] = useState('/chessman/default.png');
const [hopKey, setHopKey] = useState(0);
const [moving, setMoving] = useState(false);
const [chatOpen, setChatOpen] = useState(true);
useEffect(() => {
if (showChatFeed) setChatOpen(true);
}, [showChatFeed]);
const [landedLabel, setLandedLabel] = useState<string | null>(null);
const [landedKey, setLandedKey] = useState(0);
const [statusText, setStatusText] = useState('시계방향');
@@ -225,13 +243,72 @@ export default function DicePlane() {
minWidth: 0,
minHeight: 0,
zIndex: 6,
position: 'relative',
}}
>
<Dice onRolled={onDiceRolled} disabled={moving} />
<Dice
onRolled={onDiceRolled}
disabled={moving}
requireDiceQueue={requireDiceQueue}
diceQueue={diceQueue}
onConsumeDice={onConsumeDice}
/>
</div>
{showChatFeed && (
<div
style={{
// 주사위 영역(왼쪽)과 겹치지 않는 안쪽 오른쪽 위 칸만 사용
gridColumn: `${Math.max(2 + diceSpan, planeSize.width - 2)} / ${planeSize.width}`,
gridRow: `2 / ${Math.min(4, planeSize.height)}`,
zIndex: 7,
minWidth: 0,
minHeight: 0,
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch',
gap: 4,
padding: 4,
boxSizing: 'border-box',
overflow: 'hidden',
}}
>
<label
style={{
alignSelf: 'flex-end',
display: 'inline-flex',
alignItems: 'center',
gap: 5,
margin: 0,
padding: '3px 7px',
borderRadius: 7,
background: 'rgba(0,0,0,0.55)',
color: '#fff',
fontSize: 11,
fontWeight: 600,
cursor: 'pointer',
userSelect: 'none',
flexShrink: 0,
}}
>
<input
type="checkbox"
checked={chatOpen}
onChange={(e) => setChatOpen(e.target.checked)}
/>
채팅
</label>
{chatOpen && (
<div style={{ minHeight: 0, flex: 1, overflow: 'hidden' }}>
<ChatFeedPanel items={chatFeed} visible compact />
</div>
)}
</div>
)}
</div>
<div className="pointer-events-none absolute top-3 right-3 z-20 rounded bg-black/65 px-3 py-1 text-sm text-white">
<div className="pointer-events-none absolute bottom-3 left-3 z-20 rounded bg-black/65 px-3 py-1 text-sm text-white">
{statusText}
{islandTurnsLeft > 0 ? ` · 무인도 ${islandTurnsLeft}턴` : ''}
</div>