Fix build errors: Phaser SSR, TypeScript types, and ArenaScene logic
- Use next/dynamic with ssr:false for Phaser game page - Change tsconfig target to ES2022 for BigInt support - Replace Phaser default imports with namespace imports - Fix ArenaScene button logic using phase state machine - Remove invalid add:false from Phaser graphics config - Fix MatchState commitDeadline type Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
52565bf1a3
commit
dbe6a90e93
14 changed files with 14672 additions and 52 deletions
8113
apps/contracts/package-lock.json
generated
Normal file
8113
apps/contracts/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
14
apps/contracts/tsconfig.json
Normal file
14
apps/contracts/tsconfig.json
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": ["./test/**/*", "./ignition/**/*"],
|
||||
"files": ["./hardhat.config.ts"]
|
||||
}
|
||||
6
apps/web/next-env.d.ts
vendored
Normal file
6
apps/web/next-env.d.ts
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference path="./.next/types/routes.d.ts" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||
22
apps/web/src/app/play/PlayClient.tsx
Normal file
22
apps/web/src/app/play/PlayClient.tsx
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { initGame } from '@/phaser/Game';
|
||||
|
||||
export default function PlayClient() {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!containerRef.current) return;
|
||||
const game = initGame('phaser-container');
|
||||
return () => {
|
||||
game.destroy(true);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="w-full h-screen flex items-center justify-center bg-slate-950">
|
||||
<div id="phaser-container" ref={containerRef} className="w-full h-full"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,22 +1,9 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { initGame } from '@/phaser/Game';
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
const PlayClient = dynamic(() => import('./PlayClient'), { ssr: false });
|
||||
|
||||
export default function PlayPage() {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!containerRef.current) return;
|
||||
const game = initGame('phaser-container');
|
||||
return () => {
|
||||
game.destroy(true);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="w-full h-screen flex items-center justify-center bg-slate-950">
|
||||
<div id="phaser-container" ref={containerRef} className="w-full h-full"></div>
|
||||
</div>
|
||||
);
|
||||
return <PlayClient />;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import Phaser from 'phaser';
|
||||
import { BootScene } from './scenes/BootScene.js';
|
||||
import { LobbyScene } from './scenes/LobbyScene.js';
|
||||
import { ArenaScene } from './scenes/ArenaScene.js';
|
||||
import { ResultScene } from './scenes/ResultScene.js';
|
||||
import * as Phaser from 'phaser';
|
||||
import { BootScene } from './scenes/BootScene';
|
||||
import { LobbyScene } from './scenes/LobbyScene';
|
||||
import { ArenaScene } from './scenes/ArenaScene';
|
||||
import { ResultScene } from './scenes/ResultScene';
|
||||
|
||||
export function initGame(parent: string) {
|
||||
return new Phaser.Game({
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import Phaser from 'phaser';
|
||||
import * as Phaser from 'phaser';
|
||||
|
||||
export class UIButton extends Phaser.GameObjects.Container {
|
||||
private bg: Phaser.GameObjects.Rectangle;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import Phaser from 'phaser';
|
||||
import { UIButton } from '../objects/UIButton.js';
|
||||
import { socket } from '@/lib/socket.js';
|
||||
import * as Phaser from 'phaser';
|
||||
import { UIButton } from '../objects/UIButton';
|
||||
import { socket } from '@/lib/socket';
|
||||
import { keccak256, solidityPacked } from 'ethers';
|
||||
import { Choice, MatchStatus } from '@rps-royale/shared';
|
||||
|
||||
|
|
@ -25,7 +25,8 @@ export class ArenaScene extends Phaser.Scene {
|
|||
private infoText!: Phaser.GameObjects.Text;
|
||||
private choiceButtons: UIButton[] = [];
|
||||
private actionButton!: UIButton;
|
||||
private particles!: Phaser.GameObjects.Particles;
|
||||
private particles!: any;
|
||||
private phase: 'commit' | 'reveal' = 'commit';
|
||||
|
||||
constructor() {
|
||||
super({ key: 'ArenaScene' });
|
||||
|
|
@ -83,7 +84,8 @@ export class ArenaScene extends Phaser.Scene {
|
|||
|
||||
// Action button (commit / reveal)
|
||||
this.actionButton = new UIButton(this, width / 2, height / 2 + 160, 'Valider le Commit', () => {
|
||||
this.sendCommit();
|
||||
if (this.phase === 'commit') this.sendCommit();
|
||||
else if (this.phase === 'reveal') this.sendReveal();
|
||||
});
|
||||
this.actionButton.setDisabled(true);
|
||||
|
||||
|
|
@ -206,18 +208,12 @@ export class ArenaScene extends Phaser.Scene {
|
|||
}
|
||||
|
||||
startRevealPhase() {
|
||||
this.phase = 'reveal';
|
||||
this.cameras.main.zoomTo(1, 500, 'Sine.easeOut');
|
||||
this.statusText.setText('RÉVÈLE TON CHOIX').setColor('#22d3ee');
|
||||
this.infoText.setText('Dévoile ton signe pour déterminer le gagnant');
|
||||
this.actionButton.setLabel('Révéler');
|
||||
this.actionButton.setDisabled(false);
|
||||
|
||||
// Change action button to reveal
|
||||
this.actionButton['bg']?.off('pointerdown');
|
||||
this.actionButton['bg']?.on('pointerdown', () => {
|
||||
if (this.actionButton['disabled']) return;
|
||||
this.sendReveal();
|
||||
});
|
||||
}
|
||||
|
||||
sendReveal() {
|
||||
|
|
@ -233,7 +229,7 @@ export class ArenaScene extends Phaser.Scene {
|
|||
}
|
||||
|
||||
createParticles() {
|
||||
const graphics = this.make.graphics({ x: 0, y: 0, add: false });
|
||||
const graphics = this.make.graphics({ x: 0, y: 0 });
|
||||
graphics.fillStyle(0xffffff, 1);
|
||||
graphics.fillCircle(4, 4, 4);
|
||||
graphics.generateTexture('spark', 8, 8);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import Phaser from 'phaser';
|
||||
import { UIButton } from '../objects/UIButton.js';
|
||||
import * as Phaser from 'phaser';
|
||||
import { UIButton } from '../objects/UIButton';
|
||||
|
||||
export class BootScene extends Phaser.Scene {
|
||||
constructor() {
|
||||
|
|
@ -46,7 +46,7 @@ export class BootScene extends Phaser.Scene {
|
|||
});
|
||||
|
||||
// Create a simple flare texture procedurally
|
||||
const graphics = this.make.graphics({ x: 0, y: 0, add: false });
|
||||
const graphics = this.make.graphics({ x: 0, y: 0, });
|
||||
graphics.fillStyle(0xffffff, 1);
|
||||
graphics.fillCircle(8, 8, 8);
|
||||
graphics.generateTexture('flare', 16, 16);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import Phaser from 'phaser';
|
||||
import { UIButton } from '../objects/UIButton.js';
|
||||
import { socket } from '@/lib/socket.js';
|
||||
import * as Phaser from 'phaser';
|
||||
import { UIButton } from '../objects/UIButton';
|
||||
import { socket } from '@/lib/socket';
|
||||
|
||||
export class LobbyScene extends Phaser.Scene {
|
||||
private tablesText: Phaser.GameObjects.Text[] = [];
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import Phaser from 'phaser';
|
||||
import { UIButton } from '../objects/UIButton.js';
|
||||
import * as Phaser from 'phaser';
|
||||
import { UIButton } from '../objects/UIButton';
|
||||
|
||||
interface ResultData {
|
||||
matchId: string;
|
||||
|
|
@ -71,7 +71,7 @@ export class ResultScene extends Phaser.Scene {
|
|||
}
|
||||
|
||||
// Impact particles
|
||||
const graphics = this.make.graphics({ x: 0, y: 0, add: false });
|
||||
const graphics = this.make.graphics({ x: 0, y: 0, });
|
||||
graphics.fillStyle(0xffffff, 1);
|
||||
graphics.fillCircle(4, 4, 4);
|
||||
graphics.generateTexture('resultSpark', 8, 8);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"target": "ES2022",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
|
|
@ -13,11 +17,24 @@
|
|||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"plugins": [{ "name": "next" }],
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules"]
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
"next-env.d.ts",
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export interface MatchState {
|
|||
winner?: string;
|
||||
txHash?: string;
|
||||
createdAt: number;
|
||||
commitDeadline?: number;
|
||||
commitDeadline: number;
|
||||
revealDeadline?: number;
|
||||
}
|
||||
|
||||
|
|
|
|||
6465
pnpm-lock.yaml
generated
Normal file
6465
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue