teletilt #3

Merged
gavin merged 20 commits from teletilt into trunk 2025-07-03 14:40:35 -04:00
4 changed files with 29 additions and 21 deletions
Showing only changes of commit f61ca0d0a1 - Show all commits

View File

@@ -45,6 +45,10 @@ export function AppProvider({ children }: { children: ReactNode }) {
if (tilt[cardIndex]) { if (tilt[cardIndex]) {
emitTilt(cardIndex, tilt[cardIndex]); emitTilt(cardIndex, tilt[cardIndex]);
} else {
// cardIndex does not matter
// all tilts for this user will be cleared
emitTilt(0, { rotateX: 0, rotateY: 0 });
} }
}, [tilt]); }, [tilt]);

View File

@@ -23,15 +23,13 @@ export default function TiltCard({
if (!card) return; if (!card) return;
if (tilt) { if (tilt) {
const tilt = gameData.tilts[cardIndex]; const tilts = gameData.tilts[cardIndex];
if (!tilt) { if (!tilts.length) {
card.style.transform = `rotateX(0deg) rotateY(0deg)`; card.style.transform = `rotateX(0deg) rotateY(0deg)`;
return; return;
} }
const tilted = tilt.filter(({ rotateX, rotateY }) => rotateX || rotateY); const { totalX, totalY } = tilts.reduce(
const { totalX, totalY } = tilted.reduce(
({ totalX, totalY }, { rotateX, rotateY }) => ({ ({ totalX, totalY }, { rotateX, rotateY }) => ({
totalX: totalX + rotateX, totalX: totalX + rotateX,
totalY: totalY + rotateY, totalY: totalY + rotateY,
@@ -39,8 +37,8 @@ export default function TiltCard({
{ totalX: 0, totalY: 0 }, { totalX: 0, totalY: 0 },
); );
const rotateX = totalX / tilted.length; const rotateX = totalX / tilts.length;
const rotateY = totalY / tilted.length; const rotateY = totalY / tilts.length;
if (rotateX || rotateY) { if (rotateX || rotateY) {
card.style.transform = `rotateX(${rotateX}deg) rotateY(${rotateY}deg)`; card.style.transform = `rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;

View File

@@ -107,11 +107,15 @@ export default class GameStore {
return this.gameUpdate(game); return this.gameUpdate(game);
} }
leaveGame(game: GameState, playerID: string): GameState { leaveGame(playerID: string): GameUpdate {
const game = this.getGameByPlayerID(playerID);
this.players.delete(playerID);
game.players.delete(playerID); game.players.delete(playerID);
this._clearTilts(game, playerID);
game.lastUpdated = Date.now(); game.lastUpdated = Date.now();
return game; return this.gameUpdate(game);
} }
flipCard(gameID: string, cardIndex: number): GameUpdate { flipCard(gameID: string, cardIndex: number): GameUpdate {
@@ -159,15 +163,21 @@ export default class GameStore {
if (!cardTilts) throw new Error(`Card tilts ${cardIndex} not found`); if (!cardTilts) throw new Error(`Card tilts ${cardIndex} not found`);
game.tilts[cardIndex] = [ this._clearTilts(game, playerID);
...cardTilts.filter((tilt) => tilt.playerID !== playerID),
{ playerID, rotateX, rotateY }, if (rotateX && rotateY) {
]; game.tilts[cardIndex] = [...game.tilts[cardIndex], { playerID, rotateX, rotateY }];
game.lastUpdated = Date.now(); game.lastUpdated = Date.now();
}
return this.gameUpdate(game); return this.gameUpdate(game);
} }
_clearTilts(game: GameState, playerID: string) {
game.tilts = game.tilts.map((card) => card.filter((tilt) => tilt.playerID !== playerID));
game.lastUpdated = Date.now();
}
updateSettings(gameID: string, settings: Settings) { updateSettings(gameID: string, settings: Settings) {
const game = this.getGame(gameID); const game = this.getGame(gameID);
@@ -198,16 +208,13 @@ export default class GameStore {
return { dmID, spectatorID, cards, settings, tilts }; return { dmID, spectatorID, cards, settings, tilts };
} }
playerExit(playerID: string): GameState | null { playerExit(playerID: string): GameUpdate | null {
if (this.startUps.has(playerID)) { if (this.startUps.has(playerID)) {
this.startUps.delete(playerID); this.startUps.delete(playerID);
return null; return null;
} else { } else {
const game = this.getGameByPlayerID(playerID); return this.leaveGame(playerID);
this.players.delete(playerID);
return this.leaveGame(game, playerID);
} }
} }

View File

@@ -21,7 +21,6 @@ const timedReleases = {};
app.prepare().then(() => { app.prepare().then(() => {
const httpServer = createServer(handler); const httpServer = createServer(handler);
const io = new SocketIOServer(httpServer); const io = new SocketIOServer(httpServer);
const broadcast = (event: string, gameUpdate: GameUpdate) => { const broadcast = (event: string, gameUpdate: GameUpdate) => {
@@ -32,9 +31,9 @@ app.prepare().then(() => {
const timedRelease = (event: string, gameUpdate: GameUpdate, threshold: number) => { const timedRelease = (event: string, gameUpdate: GameUpdate, threshold: number) => {
const now = Date.now(); const now = Date.now();
const lastEvent = timedReleases[event]; const lastEvent = timedReleases[event];
clearTimeout(lastEvent?.to);
if (lastEvent?.embargo >= now) { if (lastEvent?.embargo >= now) {
clearTimeout(lastEvent.to);
const embargo = lastEvent.embargo - now; const embargo = lastEvent.embargo - now;
const to = setTimeout(() => { const to = setTimeout(() => {