@littlepartytime/dev-kit 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +4 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/dev.d.ts +6 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +59 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/server/engine-loader.d.ts +11 -0
- package/dist/server/engine-loader.d.ts.map +1 -0
- package/dist/server/engine-loader.js +45 -0
- package/dist/server/engine-loader.js.map +1 -0
- package/dist/server/game-room.d.ts +25 -0
- package/dist/server/game-room.d.ts.map +1 -0
- package/dist/server/game-room.js +78 -0
- package/dist/server/game-room.js.map +1 -0
- package/dist/server/socket-server.d.ts +16 -0
- package/dist/server/socket-server.d.ts.map +1 -0
- package/dist/server/socket-server.js +167 -0
- package/dist/server/socket-server.js.map +1 -0
- package/dist/webapp/App.d.ts +3 -0
- package/dist/webapp/App.d.ts.map +1 -0
- package/dist/webapp/App.js +70 -0
- package/dist/webapp/App.js.map +1 -0
- package/dist/webapp/App.tsx +40 -0
- package/dist/webapp/index.html +16 -0
- package/dist/webapp/main.d.ts +2 -0
- package/dist/webapp/main.d.ts.map +1 -0
- package/dist/webapp/main.js +12 -0
- package/dist/webapp/main.js.map +1 -0
- package/dist/webapp/main.tsx +9 -0
- package/dist/webapp/pages/Debug.d.ts +3 -0
- package/dist/webapp/pages/Debug.d.ts.map +1 -0
- package/dist/webapp/pages/Debug.js +69 -0
- package/dist/webapp/pages/Debug.js.map +1 -0
- package/dist/webapp/pages/Debug.tsx +40 -0
- package/dist/webapp/pages/Play.d.ts +3 -0
- package/dist/webapp/pages/Play.d.ts.map +1 -0
- package/dist/webapp/pages/Play.js +129 -0
- package/dist/webapp/pages/Play.js.map +1 -0
- package/dist/webapp/pages/Play.tsx +137 -0
- package/dist/webapp/pages/Preview.d.ts +3 -0
- package/dist/webapp/pages/Preview.d.ts.map +1 -0
- package/dist/webapp/pages/Preview.js +118 -0
- package/dist/webapp/pages/Preview.js.map +1 -0
- package/dist/webapp/pages/Preview.tsx +112 -0
- package/package.json +13 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/webapp/main.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const react_1 = __importDefault(require("react"));
|
|
7
|
+
const client_1 = __importDefault(require("react-dom/client"));
|
|
8
|
+
const App_1 = __importDefault(require("./App"));
|
|
9
|
+
client_1.default.createRoot(document.getElementById('root')).render(<react_1.default.StrictMode>
|
|
10
|
+
<App_1.default />
|
|
11
|
+
</react_1.default.StrictMode>);
|
|
12
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/webapp/main.tsx"],"names":[],"mappings":";;;;;AAAA,kDAA0B;AAC1B,8DAAwC;AACxC,gDAAwB;AAExB,gBAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAE,CAAC,CAAC,MAAM,CAC1D,CAAC,eAAK,CAAC,UAAU,CACf;IAAA,CAAC,aAAG,CAAC,AAAD,EACN;EAAA,EAAE,eAAK,CAAC,UAAU,CAAC,CACpB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Debug.d.ts","sourceRoot":"","sources":["../../../src/webapp/pages/Debug.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,MAAM,CAAC,OAAO,UAAU,KAAK,sBAoC5B"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.default = Debug;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const socket_io_client_1 = require("socket.io-client");
|
|
39
|
+
function Debug() {
|
|
40
|
+
const [socket, setSocket] = (0, react_1.useState)(null);
|
|
41
|
+
const [room, setRoom] = (0, react_1.useState)({ players: [], phase: 'lobby' });
|
|
42
|
+
const [fullState, setFullState] = (0, react_1.useState)(null);
|
|
43
|
+
(0, react_1.useEffect)(() => {
|
|
44
|
+
const sock = (0, socket_io_client_1.io)('http://localhost:4001', { query: { nickname: '__debug__' } });
|
|
45
|
+
sock.on('room:update', setRoom);
|
|
46
|
+
sock.on('game:state', setFullState);
|
|
47
|
+
sock.on('debug:state', setFullState);
|
|
48
|
+
setSocket(sock);
|
|
49
|
+
return () => { sock.disconnect(); };
|
|
50
|
+
}, []);
|
|
51
|
+
return (<div className="grid grid-cols-2 gap-4 h-[calc(100vh-80px)]">
|
|
52
|
+
{/* Room State */}
|
|
53
|
+
<div className="bg-zinc-900 rounded-lg p-4 overflow-auto">
|
|
54
|
+
<h2 className="text-lg font-bold mb-4 text-amber-400">Room State</h2>
|
|
55
|
+
<pre className="text-xs font-mono whitespace-pre-wrap">
|
|
56
|
+
{JSON.stringify(room, null, 2)}
|
|
57
|
+
</pre>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
{/* Game State */}
|
|
61
|
+
<div className="bg-zinc-900 rounded-lg p-4 overflow-auto">
|
|
62
|
+
<h2 className="text-lg font-bold mb-4 text-amber-400">Full Game State</h2>
|
|
63
|
+
<pre className="text-xs font-mono whitespace-pre-wrap">
|
|
64
|
+
{fullState ? JSON.stringify(fullState, null, 2) : 'No game in progress'}
|
|
65
|
+
</pre>
|
|
66
|
+
</div>
|
|
67
|
+
</div>);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=Debug.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Debug.js","sourceRoot":"","sources":["../../../src/webapp/pages/Debug.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,wBAoCC;AAvCD,+CAAmD;AACnD,uDAA8C;AAE9C,SAAwB,KAAK;IAC3B,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,IAAA,gBAAQ,EAAgB,IAAI,CAAC,CAAC;IAC1D,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,IAAA,gBAAQ,EAAM,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IACvE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,IAAA,gBAAQ,EAAM,IAAI,CAAC,CAAC;IAEtD,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,MAAM,IAAI,GAAG,IAAA,qBAAE,EAAC,uBAAuB,EAAE,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;QAE/E,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAChC,IAAI,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QACpC,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;QAErC,SAAS,CAAC,IAAI,CAAC,CAAC;QAEhB,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,CACL,CAAC,GAAG,CAAC,SAAS,CAAC,6CAA6C,CAC1D;MAAA,CAAC,gBAAgB,CACjB;MAAA,CAAC,GAAG,CAAC,SAAS,CAAC,0CAA0C,CACvD;QAAA,CAAC,EAAE,CAAC,SAAS,CAAC,uCAAuC,CAAC,UAAU,EAAE,EAAE,CACpE;QAAA,CAAC,GAAG,CAAC,SAAS,CAAC,uCAAuC,CACpD;UAAA,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAChC;QAAA,EAAE,GAAG,CACP;MAAA,EAAE,GAAG,CAEL;;MAAA,CAAC,gBAAgB,CACjB;MAAA,CAAC,GAAG,CAAC,SAAS,CAAC,0CAA0C,CACvD;QAAA,CAAC,EAAE,CAAC,SAAS,CAAC,uCAAuC,CAAC,eAAe,EAAE,EAAE,CACzE;QAAA,CAAC,GAAG,CAAC,SAAS,CAAC,uCAAuC,CACpD;UAAA,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,CACzE;QAAA,EAAE,GAAG,CACP;MAAA,EAAE,GAAG,CACP;IAAA,EAAE,GAAG,CAAC,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { io, Socket } from 'socket.io-client';
|
|
3
|
+
|
|
4
|
+
export default function Debug() {
|
|
5
|
+
const [socket, setSocket] = useState<Socket | null>(null);
|
|
6
|
+
const [room, setRoom] = useState<any>({ players: [], phase: 'lobby' });
|
|
7
|
+
const [fullState, setFullState] = useState<any>(null);
|
|
8
|
+
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
const sock = io('http://localhost:4001', { query: { nickname: '__debug__' } });
|
|
11
|
+
|
|
12
|
+
sock.on('room:update', setRoom);
|
|
13
|
+
sock.on('game:state', setFullState);
|
|
14
|
+
sock.on('debug:state', setFullState);
|
|
15
|
+
|
|
16
|
+
setSocket(sock);
|
|
17
|
+
|
|
18
|
+
return () => { sock.disconnect(); };
|
|
19
|
+
}, []);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div className="grid grid-cols-2 gap-4 h-[calc(100vh-80px)]">
|
|
23
|
+
{/* Room State */}
|
|
24
|
+
<div className="bg-zinc-900 rounded-lg p-4 overflow-auto">
|
|
25
|
+
<h2 className="text-lg font-bold mb-4 text-amber-400">Room State</h2>
|
|
26
|
+
<pre className="text-xs font-mono whitespace-pre-wrap">
|
|
27
|
+
{JSON.stringify(room, null, 2)}
|
|
28
|
+
</pre>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
{/* Game State */}
|
|
32
|
+
<div className="bg-zinc-900 rounded-lg p-4 overflow-auto">
|
|
33
|
+
<h2 className="text-lg font-bold mb-4 text-amber-400">Full Game State</h2>
|
|
34
|
+
<pre className="text-xs font-mono whitespace-pre-wrap">
|
|
35
|
+
{fullState ? JSON.stringify(fullState, null, 2) : 'No game in progress'}
|
|
36
|
+
</pre>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Play.d.ts","sourceRoot":"","sources":["../../../src/webapp/pages/Play.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAGhE,MAAM,CAAC,OAAO,UAAU,IAAI,sBAqI3B"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.default = Play;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const socket_io_client_1 = require("socket.io-client");
|
|
39
|
+
function Play() {
|
|
40
|
+
const [socket, setSocket] = (0, react_1.useState)(null);
|
|
41
|
+
const [nickname, setNickname] = (0, react_1.useState)('');
|
|
42
|
+
const [joined, setJoined] = (0, react_1.useState)(false);
|
|
43
|
+
const [room, setRoom] = (0, react_1.useState)({ players: [], phase: 'lobby' });
|
|
44
|
+
const [gameState, setGameState] = (0, react_1.useState)(null);
|
|
45
|
+
const [myId, setMyId] = (0, react_1.useState)(null);
|
|
46
|
+
const [GameRenderer, setGameRenderer] = (0, react_1.useState)(null);
|
|
47
|
+
// Load renderer
|
|
48
|
+
(0, react_1.useEffect)(() => {
|
|
49
|
+
Promise.resolve().then(() => __importStar(require('/src/renderer.tsx'))).then((mod) => {
|
|
50
|
+
setGameRenderer(() => mod.default || mod.Renderer);
|
|
51
|
+
}).catch(console.error);
|
|
52
|
+
}, []);
|
|
53
|
+
const join = (0, react_1.useCallback)(() => {
|
|
54
|
+
if (!nickname.trim())
|
|
55
|
+
return;
|
|
56
|
+
const sock = (0, socket_io_client_1.io)('http://localhost:4001', { query: { nickname } });
|
|
57
|
+
sock.on('connect', () => {
|
|
58
|
+
setMyId(sock.id);
|
|
59
|
+
setJoined(true);
|
|
60
|
+
});
|
|
61
|
+
sock.on('room:update', setRoom);
|
|
62
|
+
sock.on('game:state', setGameState);
|
|
63
|
+
sock.on('game:result', (result) => {
|
|
64
|
+
console.log('Game result:', result);
|
|
65
|
+
});
|
|
66
|
+
setSocket(sock);
|
|
67
|
+
}, [nickname]);
|
|
68
|
+
const me = room.players.find((p) => socket && p.socketId === socket.id) || room.players.find((p) => p.nickname === nickname);
|
|
69
|
+
const isHost = me?.isHost;
|
|
70
|
+
const isReady = me?.ready;
|
|
71
|
+
const platform = socket ? {
|
|
72
|
+
getPlayers: () => room.players.map((p) => ({ id: p.id, nickname: p.nickname, avatarUrl: null, isHost: p.isHost })),
|
|
73
|
+
getLocalPlayer: () => me ? { id: me.id, nickname: me.nickname, avatarUrl: null, isHost: me.isHost } : { id: '', nickname: '', avatarUrl: null, isHost: false },
|
|
74
|
+
send: (action) => socket.emit('game:action', action),
|
|
75
|
+
on: (event, handler) => {
|
|
76
|
+
if (event === 'stateUpdate')
|
|
77
|
+
socket.on('game:state', handler);
|
|
78
|
+
},
|
|
79
|
+
off: (event, handler) => {
|
|
80
|
+
if (event === 'stateUpdate')
|
|
81
|
+
socket.off('game:state', handler);
|
|
82
|
+
},
|
|
83
|
+
reportResult: () => { },
|
|
84
|
+
} : null;
|
|
85
|
+
if (!joined) {
|
|
86
|
+
return (<div className="flex items-center justify-center h-[60vh]">
|
|
87
|
+
<div className="bg-zinc-900 rounded-lg p-6 w-80">
|
|
88
|
+
<h2 className="text-xl font-bold mb-4">Join Game</h2>
|
|
89
|
+
<input type="text" placeholder="Your nickname" value={nickname} onChange={(e) => setNickname(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && join()} className="w-full bg-zinc-800 border border-zinc-700 rounded px-3 py-2 mb-4"/>
|
|
90
|
+
<button onClick={join} className="w-full bg-amber-600 hover:bg-amber-500 text-white py-2 rounded font-semibold">
|
|
91
|
+
Join
|
|
92
|
+
</button>
|
|
93
|
+
</div>
|
|
94
|
+
</div>);
|
|
95
|
+
}
|
|
96
|
+
if (room.phase === 'lobby' || room.phase === 'ready') {
|
|
97
|
+
return (<div className="max-w-md mx-auto mt-8">
|
|
98
|
+
<div className="bg-zinc-900 rounded-lg p-6">
|
|
99
|
+
<h2 className="text-xl font-bold mb-4">Lobby</h2>
|
|
100
|
+
<div className="space-y-2 mb-6">
|
|
101
|
+
{room.players.map((p) => (<div key={p.id} className="flex items-center justify-between bg-zinc-800 rounded px-3 py-2">
|
|
102
|
+
<span>{p.nickname} {p.isHost && '(Host)'}</span>
|
|
103
|
+
<span className={p.ready ? 'text-green-400' : 'text-zinc-500'}>
|
|
104
|
+
{p.ready ? 'Ready' : 'Not Ready'}
|
|
105
|
+
</span>
|
|
106
|
+
</div>))}
|
|
107
|
+
</div>
|
|
108
|
+
<div className="flex gap-2">
|
|
109
|
+
<button onClick={() => socket?.emit('player:ready', !isReady)} className={`flex-1 py-2 rounded font-semibold ${isReady ? 'bg-zinc-700 text-zinc-300' : 'bg-green-600 text-white'}`}>
|
|
110
|
+
{isReady ? 'Cancel Ready' : 'Ready'}
|
|
111
|
+
</button>
|
|
112
|
+
{isHost && (<button onClick={() => socket?.emit('game:start')} disabled={!room.players.every((p) => p.ready) || room.players.length < 2} className="flex-1 bg-amber-600 hover:bg-amber-500 disabled:opacity-50 text-white py-2 rounded font-semibold">
|
|
113
|
+
Start Game
|
|
114
|
+
</button>)}
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</div>);
|
|
118
|
+
}
|
|
119
|
+
// Playing or ended
|
|
120
|
+
return (<div className="h-[calc(100vh-80px)]">
|
|
121
|
+
{GameRenderer && platform && gameState ? (<GameRenderer platform={platform} state={gameState}/>) : (<div className="p-4 text-zinc-500">Loading game...</div>)}
|
|
122
|
+
{room.phase === 'ended' && isHost && (<div className="fixed bottom-4 left-1/2 -translate-x-1/2">
|
|
123
|
+
<button onClick={() => socket?.emit('game:playAgain')} className="bg-amber-600 hover:bg-amber-500 text-white px-6 py-2 rounded-full font-semibold">
|
|
124
|
+
Play Again
|
|
125
|
+
</button>
|
|
126
|
+
</div>)}
|
|
127
|
+
</div>);
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=Play.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Play.js","sourceRoot":"","sources":["../../../src/webapp/pages/Play.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import { io, Socket } from 'socket.io-client';
|
|
3
|
+
|
|
4
|
+
export default function Play() {
|
|
5
|
+
const [socket, setSocket] = useState<Socket | null>(null);
|
|
6
|
+
const [nickname, setNickname] = useState('');
|
|
7
|
+
const [joined, setJoined] = useState(false);
|
|
8
|
+
const [room, setRoom] = useState<any>({ players: [], phase: 'lobby' });
|
|
9
|
+
const [gameState, setGameState] = useState<any>(null);
|
|
10
|
+
const [myId, setMyId] = useState<string | null>(null);
|
|
11
|
+
const [GameRenderer, setGameRenderer] = useState<React.ComponentType<any> | null>(null);
|
|
12
|
+
|
|
13
|
+
// Load renderer
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
import('/src/renderer.tsx').then((mod) => {
|
|
16
|
+
setGameRenderer(() => mod.default || mod.Renderer);
|
|
17
|
+
}).catch(console.error);
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
const join = useCallback(() => {
|
|
21
|
+
if (!nickname.trim()) return;
|
|
22
|
+
|
|
23
|
+
const sock = io('http://localhost:4001', { query: { nickname } });
|
|
24
|
+
|
|
25
|
+
sock.on('connect', () => {
|
|
26
|
+
setMyId(sock.id);
|
|
27
|
+
setJoined(true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
sock.on('room:update', setRoom);
|
|
31
|
+
sock.on('game:state', setGameState);
|
|
32
|
+
sock.on('game:result', (result) => {
|
|
33
|
+
console.log('Game result:', result);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
setSocket(sock);
|
|
37
|
+
}, [nickname]);
|
|
38
|
+
|
|
39
|
+
const me = room.players.find((p: any) => socket && p.socketId === socket.id) || room.players.find((p: any) => p.nickname === nickname);
|
|
40
|
+
const isHost = me?.isHost;
|
|
41
|
+
const isReady = me?.ready;
|
|
42
|
+
|
|
43
|
+
const platform = socket ? {
|
|
44
|
+
getPlayers: () => room.players.map((p: any) => ({ id: p.id, nickname: p.nickname, avatarUrl: null, isHost: p.isHost })),
|
|
45
|
+
getLocalPlayer: () => me ? { id: me.id, nickname: me.nickname, avatarUrl: null, isHost: me.isHost } : { id: '', nickname: '', avatarUrl: null, isHost: false },
|
|
46
|
+
send: (action: any) => socket.emit('game:action', action),
|
|
47
|
+
on: (event: string, handler: Function) => {
|
|
48
|
+
if (event === 'stateUpdate') socket.on('game:state', handler as any);
|
|
49
|
+
},
|
|
50
|
+
off: (event: string, handler: Function) => {
|
|
51
|
+
if (event === 'stateUpdate') socket.off('game:state', handler as any);
|
|
52
|
+
},
|
|
53
|
+
reportResult: () => {},
|
|
54
|
+
} : null;
|
|
55
|
+
|
|
56
|
+
if (!joined) {
|
|
57
|
+
return (
|
|
58
|
+
<div className="flex items-center justify-center h-[60vh]">
|
|
59
|
+
<div className="bg-zinc-900 rounded-lg p-6 w-80">
|
|
60
|
+
<h2 className="text-xl font-bold mb-4">Join Game</h2>
|
|
61
|
+
<input
|
|
62
|
+
type="text"
|
|
63
|
+
placeholder="Your nickname"
|
|
64
|
+
value={nickname}
|
|
65
|
+
onChange={(e) => setNickname(e.target.value)}
|
|
66
|
+
onKeyDown={(e) => e.key === 'Enter' && join()}
|
|
67
|
+
className="w-full bg-zinc-800 border border-zinc-700 rounded px-3 py-2 mb-4"
|
|
68
|
+
/>
|
|
69
|
+
<button
|
|
70
|
+
onClick={join}
|
|
71
|
+
className="w-full bg-amber-600 hover:bg-amber-500 text-white py-2 rounded font-semibold"
|
|
72
|
+
>
|
|
73
|
+
Join
|
|
74
|
+
</button>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (room.phase === 'lobby' || room.phase === 'ready') {
|
|
81
|
+
return (
|
|
82
|
+
<div className="max-w-md mx-auto mt-8">
|
|
83
|
+
<div className="bg-zinc-900 rounded-lg p-6">
|
|
84
|
+
<h2 className="text-xl font-bold mb-4">Lobby</h2>
|
|
85
|
+
<div className="space-y-2 mb-6">
|
|
86
|
+
{room.players.map((p: any) => (
|
|
87
|
+
<div key={p.id} className="flex items-center justify-between bg-zinc-800 rounded px-3 py-2">
|
|
88
|
+
<span>{p.nickname} {p.isHost && '(Host)'}</span>
|
|
89
|
+
<span className={p.ready ? 'text-green-400' : 'text-zinc-500'}>
|
|
90
|
+
{p.ready ? 'Ready' : 'Not Ready'}
|
|
91
|
+
</span>
|
|
92
|
+
</div>
|
|
93
|
+
))}
|
|
94
|
+
</div>
|
|
95
|
+
<div className="flex gap-2">
|
|
96
|
+
<button
|
|
97
|
+
onClick={() => socket?.emit('player:ready', !isReady)}
|
|
98
|
+
className={`flex-1 py-2 rounded font-semibold ${isReady ? 'bg-zinc-700 text-zinc-300' : 'bg-green-600 text-white'}`}
|
|
99
|
+
>
|
|
100
|
+
{isReady ? 'Cancel Ready' : 'Ready'}
|
|
101
|
+
</button>
|
|
102
|
+
{isHost && (
|
|
103
|
+
<button
|
|
104
|
+
onClick={() => socket?.emit('game:start')}
|
|
105
|
+
disabled={!room.players.every((p: any) => p.ready) || room.players.length < 2}
|
|
106
|
+
className="flex-1 bg-amber-600 hover:bg-amber-500 disabled:opacity-50 text-white py-2 rounded font-semibold"
|
|
107
|
+
>
|
|
108
|
+
Start Game
|
|
109
|
+
</button>
|
|
110
|
+
)}
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Playing or ended
|
|
118
|
+
return (
|
|
119
|
+
<div className="h-[calc(100vh-80px)]">
|
|
120
|
+
{GameRenderer && platform && gameState ? (
|
|
121
|
+
<GameRenderer platform={platform} state={gameState} />
|
|
122
|
+
) : (
|
|
123
|
+
<div className="p-4 text-zinc-500">Loading game...</div>
|
|
124
|
+
)}
|
|
125
|
+
{room.phase === 'ended' && isHost && (
|
|
126
|
+
<div className="fixed bottom-4 left-1/2 -translate-x-1/2">
|
|
127
|
+
<button
|
|
128
|
+
onClick={() => socket?.emit('game:playAgain')}
|
|
129
|
+
className="bg-amber-600 hover:bg-amber-500 text-white px-6 py-2 rounded-full font-semibold"
|
|
130
|
+
>
|
|
131
|
+
Play Again
|
|
132
|
+
</button>
|
|
133
|
+
</div>
|
|
134
|
+
)}
|
|
135
|
+
</div>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Preview.d.ts","sourceRoot":"","sources":["../../../src/webapp/pages/Preview.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,MAAM,CAAC,OAAO,UAAU,OAAO,sBA6G9B"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.default = Preview;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
function Preview() {
|
|
39
|
+
const [state, setState] = (0, react_1.useState)({ phase: 'playing', players: [], data: {} });
|
|
40
|
+
const [stateJson, setStateJson] = (0, react_1.useState)('');
|
|
41
|
+
const [playerIndex, setPlayerIndex] = (0, react_1.useState)(0);
|
|
42
|
+
const [actions, setActions] = (0, react_1.useState)([]);
|
|
43
|
+
const [GameRenderer, setGameRenderer] = (0, react_1.useState)(null);
|
|
44
|
+
// Load renderer dynamically
|
|
45
|
+
(0, react_1.useEffect)(() => {
|
|
46
|
+
Promise.resolve().then(() => __importStar(require('/src/renderer.tsx'))).then((mod) => {
|
|
47
|
+
setGameRenderer(() => mod.default || mod.Renderer);
|
|
48
|
+
}).catch((err) => {
|
|
49
|
+
console.error('Failed to load renderer:', err);
|
|
50
|
+
});
|
|
51
|
+
}, []);
|
|
52
|
+
// Mock players
|
|
53
|
+
const mockPlayers = [
|
|
54
|
+
{ id: 'player-1', nickname: 'Alice', avatarUrl: null, isHost: true },
|
|
55
|
+
{ id: 'player-2', nickname: 'Bob', avatarUrl: null, isHost: false },
|
|
56
|
+
{ id: 'player-3', nickname: 'Carol', avatarUrl: null, isHost: false },
|
|
57
|
+
];
|
|
58
|
+
// Mock platform
|
|
59
|
+
const platform = {
|
|
60
|
+
getPlayers: () => mockPlayers,
|
|
61
|
+
getLocalPlayer: () => mockPlayers[playerIndex],
|
|
62
|
+
send: (action) => {
|
|
63
|
+
setActions((prev) => [...prev, { time: new Date().toISOString(), player: mockPlayers[playerIndex].nickname, action }]);
|
|
64
|
+
},
|
|
65
|
+
on: () => { },
|
|
66
|
+
off: () => { },
|
|
67
|
+
reportResult: () => { },
|
|
68
|
+
};
|
|
69
|
+
const updateState = (0, react_1.useCallback)(() => {
|
|
70
|
+
try {
|
|
71
|
+
const parsed = JSON.parse(stateJson);
|
|
72
|
+
setState(parsed);
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
// ignore
|
|
76
|
+
}
|
|
77
|
+
}, [stateJson]);
|
|
78
|
+
(0, react_1.useEffect)(() => {
|
|
79
|
+
setStateJson(JSON.stringify(state, null, 2));
|
|
80
|
+
}, []);
|
|
81
|
+
return (<div className="flex gap-4 h-[calc(100vh-80px)]">
|
|
82
|
+
{/* Renderer */}
|
|
83
|
+
<div className="flex-1 bg-zinc-900 rounded-lg overflow-auto">
|
|
84
|
+
{GameRenderer ? (<GameRenderer platform={platform} state={state}/>) : (<div className="p-4 text-zinc-500">Loading renderer...</div>)}
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
{/* Control Panel */}
|
|
88
|
+
<div className="w-80 flex flex-col gap-4">
|
|
89
|
+
{/* Player Switcher */}
|
|
90
|
+
<div className="bg-zinc-900 rounded-lg p-3">
|
|
91
|
+
<h3 className="text-sm font-bold text-zinc-400 mb-2">Current Player</h3>
|
|
92
|
+
<select value={playerIndex} onChange={(e) => setPlayerIndex(Number(e.target.value))} className="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1">
|
|
93
|
+
{mockPlayers.map((p, i) => (<option key={p.id} value={i}>{p.nickname}</option>))}
|
|
94
|
+
</select>
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
{/* State Editor */}
|
|
98
|
+
<div className="bg-zinc-900 rounded-lg p-3 flex-1 flex flex-col">
|
|
99
|
+
<h3 className="text-sm font-bold text-zinc-400 mb-2">Game State</h3>
|
|
100
|
+
<textarea value={stateJson} onChange={(e) => setStateJson(e.target.value)} className="flex-1 bg-zinc-800 border border-zinc-700 rounded p-2 font-mono text-xs resize-none"/>
|
|
101
|
+
<button onClick={updateState} className="mt-2 bg-amber-600 hover:bg-amber-500 text-white px-3 py-1 rounded text-sm">
|
|
102
|
+
Apply State
|
|
103
|
+
</button>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
{/* Action Log */}
|
|
107
|
+
<div className="bg-zinc-900 rounded-lg p-3 h-48 overflow-auto">
|
|
108
|
+
<h3 className="text-sm font-bold text-zinc-400 mb-2">Action Log</h3>
|
|
109
|
+
{actions.length === 0 ? (<p className="text-zinc-500 text-xs">No actions yet</p>) : (<div className="space-y-1">
|
|
110
|
+
{actions.map((a, i) => (<div key={i} className="text-xs font-mono bg-zinc-800 rounded p-1">
|
|
111
|
+
<span className="text-amber-400">{a.player}</span>: {JSON.stringify(a.action)}
|
|
112
|
+
</div>))}
|
|
113
|
+
</div>)}
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
</div>);
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=Preview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Preview.js","sourceRoot":"","sources":["../../../src/webapp/pages/Preview.tsx"],"names":[],"mappings":"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"}
|