type hints galore!
This commit is contained in:
parent
7b1f270587
commit
46f3fc7480
17 changed files with 700 additions and 667 deletions
1
build/public/assets/index.643c957c.js
Normal file
1
build/public/assets/index.643c957c.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
|
||||||
<title>🧩 jigsaw.hyottoko.club</title>
|
<title>🧩 jigsaw.hyottoko.club</title>
|
||||||
<script type="module" crossorigin src="/assets/index.8f906b9e.js"></script>
|
<script type="module" crossorigin src="/assets/index.643c957c.js"></script>
|
||||||
<link rel="modulepreload" href="/assets/vendor.b622ee49.js">
|
<link rel="modulepreload" href="/assets/vendor.b622ee49.js">
|
||||||
<link rel="stylesheet" href="/assets/index.f7304069.css">
|
<link rel="stylesheet" href="/assets/index.f7304069.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -7,22 +7,22 @@ const log = logger('fix_tiles.js')
|
||||||
function fix_tiles(gameId) {
|
function fix_tiles(gameId) {
|
||||||
GameStorage.loadGame(gameId)
|
GameStorage.loadGame(gameId)
|
||||||
let changed = false
|
let changed = false
|
||||||
const tiles = GameCommon.getTilesSortedByZIndex(gameId)
|
const tiles = GameCommon.getPiecesSortedByZIndex(gameId)
|
||||||
for (let tile of tiles) {
|
for (let tile of tiles) {
|
||||||
if (tile.owner === -1) {
|
if (tile.owner === -1) {
|
||||||
const p = GameCommon.getFinalTilePos(gameId, tile.idx)
|
const p = GameCommon.getFinalPiecePos(gameId, tile.idx)
|
||||||
if (p.x === tile.pos.x && p.y === tile.pos.y) {
|
if (p.x === tile.pos.x && p.y === tile.pos.y) {
|
||||||
// log.log('all good', tile.pos)
|
// log.log('all good', tile.pos)
|
||||||
} else {
|
} else {
|
||||||
log.log('bad tile pos', tile.pos, 'should be: ', p)
|
log.log('bad tile pos', tile.pos, 'should be: ', p)
|
||||||
tile.pos = p
|
tile.pos = p
|
||||||
GameCommon.setTile(gameId, tile.idx, tile)
|
GameCommon.setPiece(gameId, tile.idx, tile)
|
||||||
changed = true
|
changed = true
|
||||||
}
|
}
|
||||||
} else if (tile.owner !== 0) {
|
} else if (tile.owner !== 0) {
|
||||||
tile.owner = 0
|
tile.owner = 0
|
||||||
log.log('unowning tile', tile.idx)
|
log.log('unowning tile', tile.idx)
|
||||||
GameCommon.setTile(gameId, tile.idx, tile)
|
GameCommon.setPiece(gameId, tile.idx, tile)
|
||||||
changed = true
|
changed = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,50 @@
|
||||||
import Geometry, { Point, Rect } from './Geometry'
|
import Geometry, { Point, Rect } from './Geometry'
|
||||||
import Protocol from './Protocol'
|
import Protocol from './Protocol'
|
||||||
import { Rng } from './Rng'
|
import { Rng, RngSerialized } from './Rng'
|
||||||
import Time from './Time'
|
import Time from './Time'
|
||||||
|
import { FixedLengthArray } from './Types'
|
||||||
import Util from './Util'
|
import Util from './Util'
|
||||||
|
|
||||||
export type Timestamp = number
|
export type Timestamp = number
|
||||||
export type EncodedPlayer = Array<any>
|
|
||||||
export type EncodedPiece = Array<any>
|
export type EncodedPlayer = FixedLengthArray<[
|
||||||
|
string,
|
||||||
|
number,
|
||||||
|
number,
|
||||||
|
0|1,
|
||||||
|
string|null,
|
||||||
|
string|null,
|
||||||
|
string|null,
|
||||||
|
number,
|
||||||
|
Timestamp,
|
||||||
|
]>
|
||||||
|
|
||||||
|
export type EncodedPiece = FixedLengthArray<[
|
||||||
|
number,
|
||||||
|
number,
|
||||||
|
number,
|
||||||
|
number,
|
||||||
|
string|number,
|
||||||
|
number,
|
||||||
|
]>
|
||||||
|
|
||||||
export type EncodedPieceShape = number
|
export type EncodedPieceShape = number
|
||||||
|
|
||||||
|
export type EncodedGame = FixedLengthArray<[
|
||||||
|
string,
|
||||||
|
string,
|
||||||
|
RngSerialized,
|
||||||
|
Puzzle,
|
||||||
|
Array<EncodedPlayer>,
|
||||||
|
Record<string, EvtInfo>,
|
||||||
|
ScoreMode,
|
||||||
|
]>
|
||||||
|
|
||||||
|
export interface ReplayData {
|
||||||
|
log: any[],
|
||||||
|
game: EncodedGame|null
|
||||||
|
}
|
||||||
|
|
||||||
export interface Tag {
|
export interface Tag {
|
||||||
id: number
|
id: number
|
||||||
slug: string
|
slug: string
|
||||||
|
|
@ -20,7 +56,7 @@ interface GameRng {
|
||||||
type?: string
|
type?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Game {
|
export interface Game {
|
||||||
id: string
|
id: string
|
||||||
players: Array<EncodedPlayer>
|
players: Array<EncodedPlayer>
|
||||||
puzzle: Puzzle
|
puzzle: Puzzle
|
||||||
|
|
@ -112,7 +148,7 @@ export interface Player {
|
||||||
color: string|null
|
color: string|null
|
||||||
bgcolor: string|null
|
bgcolor: string|null
|
||||||
points: number
|
points: number
|
||||||
ts: number
|
ts: Timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EvtInfo {
|
interface EvtInfo {
|
||||||
|
|
@ -134,7 +170,7 @@ function exists(gameId: string) {
|
||||||
return (!!GAMES[gameId]) || false
|
return (!!GAMES[gameId]) || false
|
||||||
}
|
}
|
||||||
|
|
||||||
function __createPlayerObject(id: string, ts: number): Player {
|
function __createPlayerObject(id: string, ts: Timestamp): Player {
|
||||||
return {
|
return {
|
||||||
id: id,
|
id: id,
|
||||||
x: 0,
|
x: 0,
|
||||||
|
|
@ -191,8 +227,8 @@ function setPlayer(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTile(gameId: string, tileIdx: number, tile: Piece): void {
|
function setPiece(gameId: string, pieceIdx: number, piece: Piece): void {
|
||||||
GAMES[gameId].puzzle.tiles[tileIdx] = Util.encodeTile(tile)
|
GAMES[gameId].puzzle.tiles[pieceIdx] = Util.encodePiece(piece)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setPuzzleData(gameId: string, data: PuzzleData): void {
|
function setPuzzleData(gameId: string, data: PuzzleData): void {
|
||||||
|
|
@ -214,7 +250,7 @@ function getIdlePlayers(gameId: string, ts: number): Array<Player> {
|
||||||
return getAllPlayers(gameId).filter((p: Player) => p.ts < minTs && p.points > 0)
|
return getAllPlayers(gameId).filter((p: Player) => p.ts < minTs && p.points > 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
function addPlayer(gameId: string, playerId: string, ts: number): void {
|
function addPlayer(gameId: string, playerId: string, ts: Timestamp): void {
|
||||||
if (!playerExists(gameId, playerId)) {
|
if (!playerExists(gameId, playerId)) {
|
||||||
setPlayer(gameId, playerId, __createPlayerObject(playerId, ts))
|
setPlayer(gameId, playerId, __createPlayerObject(playerId, ts))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -261,7 +297,7 @@ function get(gameId: string) {
|
||||||
return GAMES[gameId]
|
return GAMES[gameId]
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTileCount(gameId: string): number {
|
function getPieceCount(gameId: string): number {
|
||||||
return GAMES[gameId].puzzle.tiles.length
|
return GAMES[gameId].puzzle.tiles.length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -278,22 +314,22 @@ function getScoreMode(gameId: string): ScoreMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isFinished(gameId: string): boolean {
|
function isFinished(gameId: string): boolean {
|
||||||
return getFinishedTileCount(gameId) === getTileCount(gameId)
|
return getFinishedPiecesCount(gameId) === getPieceCount(gameId)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFinishedTileCount(gameId: string): number {
|
function getFinishedPiecesCount(gameId: string): number {
|
||||||
let count = 0
|
let count = 0
|
||||||
for (let t of GAMES[gameId].puzzle.tiles) {
|
for (let t of GAMES[gameId].puzzle.tiles) {
|
||||||
if (Util.decodeTile(t).owner === -1) {
|
if (Util.decodePiece(t).owner === -1) {
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTilesSortedByZIndex(gameId: string): Piece[] {
|
function getPiecesSortedByZIndex(gameId: string): Piece[] {
|
||||||
const tiles = GAMES[gameId].puzzle.tiles.map(Util.decodeTile)
|
const pieces = GAMES[gameId].puzzle.tiles.map(Util.decodePiece)
|
||||||
return tiles.sort((t1, t2) => t1.z - t2.z)
|
return pieces.sort((t1, t2) => t1.z - t2.z)
|
||||||
}
|
}
|
||||||
|
|
||||||
function changePlayer(
|
function changePlayer(
|
||||||
|
|
@ -320,25 +356,25 @@ function changeData(gameId: string, change: any): void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeTile(gameId: string, tileIdx: number, change: any): void {
|
function changeTile(gameId: string, pieceIdx: number, change: any): void {
|
||||||
for (let k of Object.keys(change)) {
|
for (let k of Object.keys(change)) {
|
||||||
const tile = Util.decodeTile(GAMES[gameId].puzzle.tiles[tileIdx])
|
const piece = Util.decodePiece(GAMES[gameId].puzzle.tiles[pieceIdx])
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
tile[k] = change[k]
|
piece[k] = change[k]
|
||||||
GAMES[gameId].puzzle.tiles[tileIdx] = Util.encodeTile(tile)
|
GAMES[gameId].puzzle.tiles[pieceIdx] = Util.encodePiece(piece)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTile = (gameId: string, tileIdx: number): Piece => {
|
const getPiece = (gameId: string, pieceIdx: number): Piece => {
|
||||||
return Util.decodeTile(GAMES[gameId].puzzle.tiles[tileIdx])
|
return Util.decodePiece(GAMES[gameId].puzzle.tiles[pieceIdx])
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTileGroup = (gameId: string, tileIdx: number): number => {
|
const getPieceGroup = (gameId: string, tileIdx: number): number => {
|
||||||
const tile = getTile(gameId, tileIdx)
|
const tile = getPiece(gameId, tileIdx)
|
||||||
return tile.group
|
return tile.group
|
||||||
}
|
}
|
||||||
|
|
||||||
const getFinalTilePos = (gameId: string, tileIdx: number): Point => {
|
const getFinalPiecePos = (gameId: string, tileIdx: number): Point => {
|
||||||
const info = GAMES[gameId].puzzle.info
|
const info = GAMES[gameId].puzzle.info
|
||||||
const boardPos = {
|
const boardPos = {
|
||||||
x: (info.table.width - info.width) / 2,
|
x: (info.table.width - info.width) / 2,
|
||||||
|
|
@ -348,8 +384,8 @@ const getFinalTilePos = (gameId: string, tileIdx: number): Point => {
|
||||||
return Geometry.pointAdd(boardPos, srcPos)
|
return Geometry.pointAdd(boardPos, srcPos)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTilePos = (gameId: string, tileIdx: number): Point => {
|
const getPiecePos = (gameId: string, tileIdx: number): Point => {
|
||||||
const tile = getTile(gameId, tileIdx)
|
const tile = getPiece(gameId, tileIdx)
|
||||||
return tile.pos
|
return tile.pos
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -368,9 +404,9 @@ const getBounds = (gameId: string): Rect => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTileBounds = (gameId: string, tileIdx: number): Rect => {
|
const getPieceBounds = (gameId: string, tileIdx: number): Rect => {
|
||||||
const s = getTileSize(gameId)
|
const s = getPieceSize(gameId)
|
||||||
const tile = getTile(gameId, tileIdx)
|
const tile = getPiece(gameId, tileIdx)
|
||||||
return {
|
return {
|
||||||
x: tile.pos.x,
|
x: tile.pos.x,
|
||||||
y: tile.pos.y,
|
y: tile.pos.y,
|
||||||
|
|
@ -380,13 +416,13 @@ const getTileBounds = (gameId: string, tileIdx: number): Rect => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTileZIndex = (gameId: string, tileIdx: number): number => {
|
const getTileZIndex = (gameId: string, tileIdx: number): number => {
|
||||||
const tile = getTile(gameId, tileIdx)
|
const tile = getPiece(gameId, tileIdx)
|
||||||
return tile.z
|
return tile.z
|
||||||
}
|
}
|
||||||
|
|
||||||
const getFirstOwnedTileIdx = (gameId: string, playerId: string): number => {
|
const getFirstOwnedPieceIdx = (gameId: string, playerId: string): number => {
|
||||||
for (let t of GAMES[gameId].puzzle.tiles) {
|
for (let t of GAMES[gameId].puzzle.tiles) {
|
||||||
const tile = Util.decodeTile(t)
|
const tile = Util.decodePiece(t)
|
||||||
if (tile.owner === playerId) {
|
if (tile.owner === playerId) {
|
||||||
return tile.idx
|
return tile.idx
|
||||||
}
|
}
|
||||||
|
|
@ -394,20 +430,20 @@ const getFirstOwnedTileIdx = (gameId: string, playerId: string): number => {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
const getFirstOwnedTile = (gameId: string, playerId: string): EncodedPiece|null => {
|
const getFirstOwnedPiece = (gameId: string, playerId: string): EncodedPiece|null => {
|
||||||
const idx = getFirstOwnedTileIdx(gameId, playerId)
|
const idx = getFirstOwnedPieceIdx(gameId, playerId)
|
||||||
return idx < 0 ? null : GAMES[gameId].puzzle.tiles[idx]
|
return idx < 0 ? null : GAMES[gameId].puzzle.tiles[idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTileDrawOffset = (gameId: string): number => {
|
const getPieceDrawOffset = (gameId: string): number => {
|
||||||
return GAMES[gameId].puzzle.info.tileDrawOffset
|
return GAMES[gameId].puzzle.info.tileDrawOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTileDrawSize = (gameId: string): number => {
|
const getPieceDrawSize = (gameId: string): number => {
|
||||||
return GAMES[gameId].puzzle.info.tileDrawSize
|
return GAMES[gameId].puzzle.info.tileDrawSize
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTileSize = (gameId: string): number => {
|
const getPieceSize = (gameId: string): number => {
|
||||||
return GAMES[gameId].puzzle.info.tileSize
|
return GAMES[gameId].puzzle.info.tileSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -472,7 +508,7 @@ const setTilesZIndex = (gameId: string, tileIdxs: Array<number>, zIndex: number)
|
||||||
}
|
}
|
||||||
|
|
||||||
const moveTileDiff = (gameId: string, tileIdx: number, diff: Point): void => {
|
const moveTileDiff = (gameId: string, tileIdx: number, diff: Point): void => {
|
||||||
const oldPos = getTilePos(gameId, tileIdx)
|
const oldPos = getPiecePos(gameId, tileIdx)
|
||||||
const pos = Geometry.pointAdd(oldPos, diff)
|
const pos = Geometry.pointAdd(oldPos, diff)
|
||||||
changeTile(gameId, tileIdx, { pos })
|
changeTile(gameId, tileIdx, { pos })
|
||||||
}
|
}
|
||||||
|
|
@ -482,21 +518,21 @@ const moveTilesDiff = (
|
||||||
tileIdxs: Array<number>,
|
tileIdxs: Array<number>,
|
||||||
diff: Point
|
diff: Point
|
||||||
): void => {
|
): void => {
|
||||||
const tileDrawSize = getTileDrawSize(gameId)
|
const drawSize = getPieceDrawSize(gameId)
|
||||||
const bounds = getBounds(gameId)
|
const bounds = getBounds(gameId)
|
||||||
const cappedDiff = diff
|
const cappedDiff = diff
|
||||||
|
|
||||||
for (let tileIdx of tileIdxs) {
|
for (let tileIdx of tileIdxs) {
|
||||||
const t = getTile(gameId, tileIdx)
|
const t = getPiece(gameId, tileIdx)
|
||||||
if (t.pos.x + diff.x < bounds.x) {
|
if (t.pos.x + diff.x < bounds.x) {
|
||||||
cappedDiff.x = Math.max(bounds.x - t.pos.x, cappedDiff.x)
|
cappedDiff.x = Math.max(bounds.x - t.pos.x, cappedDiff.x)
|
||||||
} else if (t.pos.x + tileDrawSize + diff.x > bounds.x + bounds.w) {
|
} else if (t.pos.x + drawSize + diff.x > bounds.x + bounds.w) {
|
||||||
cappedDiff.x = Math.min(bounds.x + bounds.w - t.pos.x + tileDrawSize, cappedDiff.x)
|
cappedDiff.x = Math.min(bounds.x + bounds.w - t.pos.x + drawSize, cappedDiff.x)
|
||||||
}
|
}
|
||||||
if (t.pos.y + diff.y < bounds.y) {
|
if (t.pos.y + diff.y < bounds.y) {
|
||||||
cappedDiff.y = Math.max(bounds.y - t.pos.y, cappedDiff.y)
|
cappedDiff.y = Math.max(bounds.y - t.pos.y, cappedDiff.y)
|
||||||
} else if (t.pos.y + tileDrawSize + diff.y > bounds.y + bounds.h) {
|
} else if (t.pos.y + drawSize + diff.y > bounds.y + bounds.h) {
|
||||||
cappedDiff.y = Math.min(bounds.y + bounds.h - t.pos.y + tileDrawSize, cappedDiff.y)
|
cappedDiff.y = Math.min(bounds.y + bounds.h - t.pos.y + drawSize, cappedDiff.y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -522,52 +558,52 @@ const setTilesOwner = (
|
||||||
}
|
}
|
||||||
|
|
||||||
// get all grouped tiles for a tile
|
// get all grouped tiles for a tile
|
||||||
function getGroupedTileIdxs(gameId: string, tileIdx: number): number[] {
|
function getGroupedPieceIdxs(gameId: string, pieceIdx: number): number[] {
|
||||||
const tiles = GAMES[gameId].puzzle.tiles
|
const pieces = GAMES[gameId].puzzle.tiles
|
||||||
const tile = Util.decodeTile(tiles[tileIdx])
|
const piece = Util.decodePiece(pieces[pieceIdx])
|
||||||
|
|
||||||
const grouped = []
|
const grouped = []
|
||||||
if (tile.group) {
|
if (piece.group) {
|
||||||
for (let other of tiles) {
|
for (let other of pieces) {
|
||||||
const otherTile = Util.decodeTile(other)
|
const otherPiece = Util.decodePiece(other)
|
||||||
if (otherTile.group === tile.group) {
|
if (otherPiece.group === piece.group) {
|
||||||
grouped.push(otherTile.idx)
|
grouped.push(otherPiece.idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
grouped.push(tile.idx)
|
grouped.push(piece.idx)
|
||||||
}
|
}
|
||||||
return grouped
|
return grouped
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the index of the puzzle tile with the highest z index
|
// Returns the index of the puzzle tile with the highest z index
|
||||||
// that is not finished yet and that matches the position
|
// that is not finished yet and that matches the position
|
||||||
const freeTileIdxByPos = (gameId: string, pos: Point): number => {
|
const freePieceIdxByPos = (gameId: string, pos: Point): number => {
|
||||||
let info = GAMES[gameId].puzzle.info
|
let info = GAMES[gameId].puzzle.info
|
||||||
let tiles = GAMES[gameId].puzzle.tiles
|
let pieces = GAMES[gameId].puzzle.tiles
|
||||||
|
|
||||||
let maxZ = -1
|
let maxZ = -1
|
||||||
let tileIdx = -1
|
let pieceIdx = -1
|
||||||
for (let idx = 0; idx < tiles.length; idx++) {
|
for (let idx = 0; idx < pieces.length; idx++) {
|
||||||
const tile = Util.decodeTile(tiles[idx])
|
const piece = Util.decodePiece(pieces[idx])
|
||||||
if (tile.owner !== 0) {
|
if (piece.owner !== 0) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const collisionRect: Rect = {
|
const collisionRect: Rect = {
|
||||||
x: tile.pos.x,
|
x: piece.pos.x,
|
||||||
y: tile.pos.y,
|
y: piece.pos.y,
|
||||||
w: info.tileSize,
|
w: info.tileSize,
|
||||||
h: info.tileSize,
|
h: info.tileSize,
|
||||||
}
|
}
|
||||||
if (Geometry.pointInBounds(pos, collisionRect)) {
|
if (Geometry.pointInBounds(pos, collisionRect)) {
|
||||||
if (maxZ === -1 || tile.z > maxZ) {
|
if (maxZ === -1 || piece.z > maxZ) {
|
||||||
maxZ = tile.z
|
maxZ = piece.z
|
||||||
tileIdx = idx
|
pieceIdx = idx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tileIdx
|
return pieceIdx
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPlayerBgColor = (gameId: string, playerId: string): string|null => {
|
const getPlayerBgColor = (gameId: string, playerId: string): string|null => {
|
||||||
|
|
@ -596,8 +632,8 @@ const areGrouped = (
|
||||||
tileIdx1: number,
|
tileIdx1: number,
|
||||||
tileIdx2: number
|
tileIdx2: number
|
||||||
): boolean => {
|
): boolean => {
|
||||||
const g1 = getTileGroup(gameId, tileIdx1)
|
const g1 = getPieceGroup(gameId, tileIdx1)
|
||||||
const g2 = getTileGroup(gameId, tileIdx2)
|
const g2 = getPieceGroup(gameId, tileIdx2)
|
||||||
return !!(g1 && g1 === g2)
|
return !!(g1 && g1 === g2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -643,7 +679,7 @@ function handleInput(
|
||||||
const _tileChange = (tileIdx: number): void => {
|
const _tileChange = (tileIdx: number): void => {
|
||||||
changes.push([
|
changes.push([
|
||||||
Protocol.CHANGE_TILE,
|
Protocol.CHANGE_TILE,
|
||||||
Util.encodeTile(getTile(gameId, tileIdx)),
|
Util.encodePiece(getPiece(gameId, tileIdx)),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -671,8 +707,8 @@ function handleInput(
|
||||||
tileIdx2: number
|
tileIdx2: number
|
||||||
): void => {
|
): void => {
|
||||||
const tiles = GAMES[gameId].puzzle.tiles
|
const tiles = GAMES[gameId].puzzle.tiles
|
||||||
const group1 = getTileGroup(gameId, tileIdx1)
|
const group1 = getPieceGroup(gameId, tileIdx1)
|
||||||
const group2 = getTileGroup(gameId, tileIdx2)
|
const group2 = getPieceGroup(gameId, tileIdx2)
|
||||||
|
|
||||||
let group
|
let group
|
||||||
const searchGroups = []
|
const searchGroups = []
|
||||||
|
|
@ -701,10 +737,10 @@ function handleInput(
|
||||||
// TODO: strange
|
// TODO: strange
|
||||||
if (searchGroups.length > 0) {
|
if (searchGroups.length > 0) {
|
||||||
for (const t of tiles) {
|
for (const t of tiles) {
|
||||||
const tile = Util.decodeTile(t)
|
const piece = Util.decodePiece(t)
|
||||||
if (searchGroups.includes(tile.group)) {
|
if (searchGroups.includes(piece.group)) {
|
||||||
changeTile(gameId, tile.idx, { group })
|
changeTile(gameId, piece.idx, { group })
|
||||||
_tileChange(tile.idx)
|
_tileChange(piece.idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -732,12 +768,12 @@ function handleInput(
|
||||||
_playerChange()
|
_playerChange()
|
||||||
evtInfo._last_mouse_down = pos
|
evtInfo._last_mouse_down = pos
|
||||||
|
|
||||||
const tileIdxAtPos = freeTileIdxByPos(gameId, pos)
|
const tileIdxAtPos = freePieceIdxByPos(gameId, pos)
|
||||||
if (tileIdxAtPos >= 0) {
|
if (tileIdxAtPos >= 0) {
|
||||||
let maxZ = getMaxZIndex(gameId) + 1
|
let maxZ = getMaxZIndex(gameId) + 1
|
||||||
changeData(gameId, { maxZ })
|
changeData(gameId, { maxZ })
|
||||||
_dataChange()
|
_dataChange()
|
||||||
const tileIdxs = getGroupedTileIdxs(gameId, tileIdxAtPos)
|
const tileIdxs = getGroupedPieceIdxs(gameId, tileIdxAtPos)
|
||||||
setTilesZIndex(gameId, tileIdxs, getMaxZIndex(gameId))
|
setTilesZIndex(gameId, tileIdxs, getMaxZIndex(gameId))
|
||||||
setTilesOwner(gameId, tileIdxs, playerId)
|
setTilesOwner(gameId, tileIdxs, playerId)
|
||||||
_tileChanges(tileIdxs)
|
_tileChanges(tileIdxs)
|
||||||
|
|
@ -754,7 +790,7 @@ function handleInput(
|
||||||
changePlayer(gameId, playerId, {x, y, ts})
|
changePlayer(gameId, playerId, {x, y, ts})
|
||||||
_playerChange()
|
_playerChange()
|
||||||
} else {
|
} else {
|
||||||
let tileIdx = getFirstOwnedTileIdx(gameId, playerId)
|
let tileIdx = getFirstOwnedPieceIdx(gameId, playerId)
|
||||||
if (tileIdx >= 0) {
|
if (tileIdx >= 0) {
|
||||||
// player is moving a tile (and hand)
|
// player is moving a tile (and hand)
|
||||||
changePlayer(gameId, playerId, {x, y, ts})
|
changePlayer(gameId, playerId, {x, y, ts})
|
||||||
|
|
@ -762,11 +798,11 @@ function handleInput(
|
||||||
|
|
||||||
// check if pos is on the tile, otherwise dont move
|
// check if pos is on the tile, otherwise dont move
|
||||||
// (mouse could be out of table, but tile stays on it)
|
// (mouse could be out of table, but tile stays on it)
|
||||||
const tileIdxs = getGroupedTileIdxs(gameId, tileIdx)
|
const tileIdxs = getGroupedPieceIdxs(gameId, tileIdx)
|
||||||
let anyOk = Geometry.pointInBounds(pos, getBounds(gameId))
|
let anyOk = Geometry.pointInBounds(pos, getBounds(gameId))
|
||||||
&& Geometry.pointInBounds(evtInfo._last_mouse_down, getBounds(gameId))
|
&& Geometry.pointInBounds(evtInfo._last_mouse_down, getBounds(gameId))
|
||||||
for (let idx of tileIdxs) {
|
for (let idx of tileIdxs) {
|
||||||
const bounds = getTileBounds(gameId, idx)
|
const bounds = getPieceBounds(gameId, idx)
|
||||||
if (Geometry.pointInBounds(pos, bounds)) {
|
if (Geometry.pointInBounds(pos, bounds)) {
|
||||||
anyOk = true
|
anyOk = true
|
||||||
break
|
break
|
||||||
|
|
@ -799,16 +835,16 @@ function handleInput(
|
||||||
|
|
||||||
evtInfo._last_mouse_down = null
|
evtInfo._last_mouse_down = null
|
||||||
|
|
||||||
let tileIdx = getFirstOwnedTileIdx(gameId, playerId)
|
let tileIdx = getFirstOwnedPieceIdx(gameId, playerId)
|
||||||
if (tileIdx >= 0) {
|
if (tileIdx >= 0) {
|
||||||
// drop the tile(s)
|
// drop the tile(s)
|
||||||
let tileIdxs = getGroupedTileIdxs(gameId, tileIdx)
|
let tileIdxs = getGroupedPieceIdxs(gameId, tileIdx)
|
||||||
setTilesOwner(gameId, tileIdxs, 0)
|
setTilesOwner(gameId, tileIdxs, 0)
|
||||||
_tileChanges(tileIdxs)
|
_tileChanges(tileIdxs)
|
||||||
|
|
||||||
// Check if the tile was dropped near the final location
|
// Check if the tile was dropped near the final location
|
||||||
let tilePos = getTilePos(gameId, tileIdx)
|
let tilePos = getPiecePos(gameId, tileIdx)
|
||||||
let finalPos = getFinalTilePos(gameId, tileIdx)
|
let finalPos = getFinalPiecePos(gameId, tileIdx)
|
||||||
if (Geometry.pointDistance(finalPos, tilePos) < puzzle.info.snapDistance) {
|
if (Geometry.pointDistance(finalPos, tilePos) < puzzle.info.snapDistance) {
|
||||||
let diff = Geometry.pointSub(finalPos, tilePos)
|
let diff = Geometry.pointSub(finalPos, tilePos)
|
||||||
// Snap the tile to the final destination
|
// Snap the tile to the final destination
|
||||||
|
|
@ -829,7 +865,7 @@ function handleInput(
|
||||||
_playerChange()
|
_playerChange()
|
||||||
|
|
||||||
// check if the puzzle is finished
|
// check if the puzzle is finished
|
||||||
if (getFinishedTileCount(gameId) === getTileCount(gameId)) {
|
if (getFinishedPiecesCount(gameId) === getPieceCount(gameId)) {
|
||||||
changeData(gameId, { finished: ts })
|
changeData(gameId, { finished: ts })
|
||||||
_dataChange()
|
_dataChange()
|
||||||
}
|
}
|
||||||
|
|
@ -848,17 +884,17 @@ function handleInput(
|
||||||
if (areGrouped(gameId, tileIdx, otherTileIdx)) {
|
if (areGrouped(gameId, tileIdx, otherTileIdx)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const tilePos = getTilePos(gameId, tileIdx)
|
const tilePos = getPiecePos(gameId, tileIdx)
|
||||||
const dstPos = Geometry.pointAdd(
|
const dstPos = Geometry.pointAdd(
|
||||||
getTilePos(gameId, otherTileIdx),
|
getPiecePos(gameId, otherTileIdx),
|
||||||
{x: off[0] * info.tileSize, y: off[1] * info.tileSize}
|
{x: off[0] * info.tileSize, y: off[1] * info.tileSize}
|
||||||
)
|
)
|
||||||
if (Geometry.pointDistance(tilePos, dstPos) < info.snapDistance) {
|
if (Geometry.pointDistance(tilePos, dstPos) < info.snapDistance) {
|
||||||
let diff = Geometry.pointSub(dstPos, tilePos)
|
let diff = Geometry.pointSub(dstPos, tilePos)
|
||||||
let tileIdxs = getGroupedTileIdxs(gameId, tileIdx)
|
let tileIdxs = getGroupedPieceIdxs(gameId, tileIdx)
|
||||||
moveTilesDiff(gameId, tileIdxs, diff)
|
moveTilesDiff(gameId, tileIdxs, diff)
|
||||||
groupTiles(gameId, tileIdx, otherTileIdx)
|
groupTiles(gameId, tileIdx, otherTileIdx)
|
||||||
tileIdxs = getGroupedTileIdxs(gameId, tileIdx)
|
tileIdxs = getGroupedPieceIdxs(gameId, tileIdx)
|
||||||
const zIndex = getMaxZIndexByTileIdxs(gameId, tileIdxs)
|
const zIndex = getMaxZIndexByTileIdxs(gameId, tileIdxs)
|
||||||
setTilesZIndex(gameId, tileIdxs, zIndex)
|
setTilesZIndex(gameId, tileIdxs, zIndex)
|
||||||
_tileChanges(tileIdxs)
|
_tileChanges(tileIdxs)
|
||||||
|
|
@ -868,7 +904,7 @@ function handleInput(
|
||||||
}
|
}
|
||||||
|
|
||||||
let snapped = false
|
let snapped = false
|
||||||
for (let tileIdxTmp of getGroupedTileIdxs(gameId, tileIdx)) {
|
for (let tileIdxTmp of getGroupedPieceIdxs(gameId, tileIdx)) {
|
||||||
let othersIdxs = getSurroundingTilesByIdx(gameId, tileIdxTmp)
|
let othersIdxs = getSurroundingTilesByIdx(gameId, tileIdxTmp)
|
||||||
if (
|
if (
|
||||||
check(gameId, tileIdxTmp, othersIdxs[0], [0, 1]) // top
|
check(gameId, tileIdxTmp, othersIdxs[0], [0, 1]) // top
|
||||||
|
|
@ -916,15 +952,14 @@ function handleInput(
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
__createPlayerObject,
|
|
||||||
setGame,
|
setGame,
|
||||||
exists,
|
exists,
|
||||||
playerExists,
|
playerExists,
|
||||||
getActivePlayers,
|
getActivePlayers,
|
||||||
getIdlePlayers,
|
getIdlePlayers,
|
||||||
addPlayer,
|
addPlayer,
|
||||||
getFinishedTileCount,
|
getFinishedPiecesCount,
|
||||||
getTileCount,
|
getPieceCount,
|
||||||
getImageUrl,
|
getImageUrl,
|
||||||
setImageUrl,
|
setImageUrl,
|
||||||
get,
|
get,
|
||||||
|
|
@ -936,7 +971,7 @@ export default {
|
||||||
getPlayerIdByIndex,
|
getPlayerIdByIndex,
|
||||||
changePlayer,
|
changePlayer,
|
||||||
setPlayer,
|
setPlayer,
|
||||||
setTile,
|
setPiece,
|
||||||
setPuzzleData,
|
setPuzzleData,
|
||||||
getTableWidth,
|
getTableWidth,
|
||||||
getTableHeight,
|
getTableHeight,
|
||||||
|
|
@ -944,11 +979,11 @@ export default {
|
||||||
getRng,
|
getRng,
|
||||||
getPuzzleWidth,
|
getPuzzleWidth,
|
||||||
getPuzzleHeight,
|
getPuzzleHeight,
|
||||||
getTilesSortedByZIndex,
|
getPiecesSortedByZIndex,
|
||||||
getFirstOwnedTile,
|
getFirstOwnedPiece,
|
||||||
getTileDrawOffset,
|
getPieceDrawOffset,
|
||||||
getTileDrawSize,
|
getPieceDrawSize,
|
||||||
getFinalTilePos,
|
getFinalPiecePos,
|
||||||
getStartTs,
|
getStartTs,
|
||||||
getFinishTs,
|
getFinishTs,
|
||||||
handleInput,
|
handleInput,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
interface RngSerialized {
|
export interface RngSerialized {
|
||||||
rand_high: number,
|
rand_high: number,
|
||||||
rand_low: number,
|
rand_low: number,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
src/common/Types.ts
Normal file
6
src/common/Types.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
// @see https://stackoverflow.com/a/59906630/392905
|
||||||
|
type ArrayLengthMutationKeys = 'splice' | 'push' | 'pop' | 'shift' | 'unshift' | number
|
||||||
|
type ArrayItems<T extends Array<any>> = T extends Array<infer TItems> ? TItems : never
|
||||||
|
export type FixedLengthArray<T extends any[]> =
|
||||||
|
Pick<T, Exclude<keyof T, ArrayLengthMutationKeys>>
|
||||||
|
& { [Symbol.iterator]: () => IterableIterator< ArrayItems<T> > }
|
||||||
|
|
@ -1,4 +1,14 @@
|
||||||
import { EncodedPiece, EncodedPieceShape, EncodedPlayer, Piece, PieceShape, Player } from './GameCommon'
|
import {
|
||||||
|
EncodedGame,
|
||||||
|
EncodedPiece,
|
||||||
|
EncodedPieceShape,
|
||||||
|
EncodedPlayer,
|
||||||
|
Game,
|
||||||
|
Piece,
|
||||||
|
PieceShape,
|
||||||
|
Player,
|
||||||
|
ScoreMode
|
||||||
|
} from './GameCommon'
|
||||||
import { Point } from './Geometry'
|
import { Point } from './Geometry'
|
||||||
import { Rng } from './Rng'
|
import { Rng } from './Rng'
|
||||||
|
|
||||||
|
|
@ -58,11 +68,11 @@ function decodeShape(data: EncodedPieceShape): PieceShape {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function encodeTile(data: Piece): EncodedPiece {
|
function encodePiece(data: Piece): EncodedPiece {
|
||||||
return [data.idx, data.pos.x, data.pos.y, data.z, data.owner, data.group]
|
return [data.idx, data.pos.x, data.pos.y, data.z, data.owner, data.group]
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeTile(data: EncodedPiece): Piece {
|
function decodePiece(data: EncodedPiece): Piece {
|
||||||
return {
|
return {
|
||||||
idx: data[0],
|
idx: data[0],
|
||||||
pos: {
|
pos: {
|
||||||
|
|
@ -103,25 +113,19 @@ function decodePlayer(data: EncodedPlayer): Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function encodeGame(data: any): Array<any> {
|
function encodeGame(data: Game): EncodedGame {
|
||||||
if (Array.isArray(data)) {
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
return [
|
return [
|
||||||
data.id,
|
data.id,
|
||||||
data.rng.type,
|
data.rng.type || '',
|
||||||
Rng.serialize(data.rng.obj),
|
Rng.serialize(data.rng.obj),
|
||||||
data.puzzle,
|
data.puzzle,
|
||||||
data.players,
|
data.players,
|
||||||
data.evtInfos,
|
data.evtInfos,
|
||||||
data.scoreMode,
|
data.scoreMode || ScoreMode.FINAL,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeGame(data: any) {
|
function decodeGame(data: EncodedGame): Game {
|
||||||
if (!Array.isArray(data)) {
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
id: data[0],
|
id: data[0],
|
||||||
rng: {
|
rng: {
|
||||||
|
|
@ -174,8 +178,8 @@ export default {
|
||||||
encodeShape,
|
encodeShape,
|
||||||
decodeShape,
|
decodeShape,
|
||||||
|
|
||||||
encodeTile,
|
encodePiece,
|
||||||
decodeTile,
|
decodePiece,
|
||||||
|
|
||||||
encodePlayer,
|
encodePlayer,
|
||||||
decodePlayer,
|
decodePlayer,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
"use strict"
|
"use strict"
|
||||||
|
|
||||||
import { logger } from '../common/Util'
|
import { EncodedGame, ReplayData } from '../common/GameCommon'
|
||||||
|
import Util, { logger } from '../common/Util'
|
||||||
import Protocol from './../common/Protocol'
|
import Protocol from './../common/Protocol'
|
||||||
|
|
||||||
const log = logger('Communication.js')
|
const log = logger('Communication.js')
|
||||||
|
|
@ -51,7 +52,7 @@ function connect(
|
||||||
address: string,
|
address: string,
|
||||||
gameId: string,
|
gameId: string,
|
||||||
clientId: string
|
clientId: string
|
||||||
): Promise<any> {
|
): Promise<EncodedGame> {
|
||||||
clientSeq = 0
|
clientSeq = 0
|
||||||
events = {}
|
events = {}
|
||||||
setConnectionState(CONN_STATE_CONNECTING)
|
setConnectionState(CONN_STATE_CONNECTING)
|
||||||
|
|
@ -100,9 +101,10 @@ async function requestReplayData(
|
||||||
gameId: string,
|
gameId: string,
|
||||||
offset: number,
|
offset: number,
|
||||||
size: number
|
size: number
|
||||||
): Promise<{ log: Array<any>, game: any }> {
|
): Promise<ReplayData> {
|
||||||
const res = await fetch(`/api/replay-data?gameId=${gameId}&offset=${offset}&size=${size}`)
|
const args = { gameId, offset, size }
|
||||||
const json: { log: Array<any>, game: any } = await res.json()
|
const res = await fetch(`/api/replay-data${Util.asQueryArgs(args)}`)
|
||||||
|
const json: ReplayData = await res.json()
|
||||||
return json
|
return json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ async function createPuzzleTileBitmaps(
|
||||||
const ctx2 = c2.getContext('2d') as CanvasRenderingContext2D
|
const ctx2 = c2.getContext('2d') as CanvasRenderingContext2D
|
||||||
|
|
||||||
for (const t of tiles) {
|
for (const t of tiles) {
|
||||||
const tile = Util.decodeTile(t)
|
const tile = Util.decodePiece(t)
|
||||||
const srcRect = srcRectByIdx(info, tile.idx)
|
const srcRect = srcRectByIdx(info, tile.idx)
|
||||||
const path = pathForShape(Util.decodeShape(info.shapes[tile.idx]))
|
const path = pathForShape(Util.decodeShape(info.shapes[tile.idx]))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,12 @@ import Debug from './Debug'
|
||||||
import Communication from './Communication'
|
import Communication from './Communication'
|
||||||
import Util from './../common/Util'
|
import Util from './../common/Util'
|
||||||
import PuzzleGraphics from './PuzzleGraphics'
|
import PuzzleGraphics from './PuzzleGraphics'
|
||||||
import Game, { Player, Piece } from './../common/GameCommon'
|
import Game, { Game as GameType, Player, Piece, EncodedGame, ReplayData, Timestamp } from './../common/GameCommon'
|
||||||
import fireworksController from './Fireworks'
|
import fireworksController from './Fireworks'
|
||||||
import Protocol from '../common/Protocol'
|
import Protocol from '../common/Protocol'
|
||||||
import Time from '../common/Time'
|
import Time from '../common/Time'
|
||||||
import { Dim, Point } from '../common/Geometry'
|
import { Dim, Point } from '../common/Geometry'
|
||||||
|
import { FixedLengthArray } from '../common/Types'
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
|
|
@ -19,13 +20,6 @@ declare global {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @see https://stackoverflow.com/a/59906630/392905
|
|
||||||
type ArrayLengthMutationKeys = 'splice' | 'push' | 'pop' | 'shift' | 'unshift' | number
|
|
||||||
type ArrayItems<T extends Array<any>> = T extends Array<infer TItems> ? TItems : never
|
|
||||||
type FixedLengthArray<T extends any[]> =
|
|
||||||
Pick<T, Exclude<keyof T, ArrayLengthMutationKeys>>
|
|
||||||
& { [Symbol.iterator]: () => IterableIterator< ArrayItems<T> > }
|
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const images = import.meta.globEager('./*.png')
|
const images = import.meta.globEager('./*.png')
|
||||||
|
|
||||||
|
|
@ -50,15 +44,17 @@ interface Hud {
|
||||||
interface Replay {
|
interface Replay {
|
||||||
final: boolean
|
final: boolean
|
||||||
requesting: boolean
|
requesting: boolean
|
||||||
log: Array<any>
|
log: Array<any> // current log entries
|
||||||
logPointer: number,
|
logPointer: number // pointer to current item in the log array
|
||||||
logIdx: number
|
|
||||||
speeds: Array<number>
|
speeds: Array<number>
|
||||||
speedIdx: number
|
speedIdx: number
|
||||||
paused: boolean
|
paused: boolean
|
||||||
lastRealTs: number
|
lastRealTs: number
|
||||||
lastGameTs: number
|
lastGameTs: number
|
||||||
gameStartTs: number
|
gameStartTs: number
|
||||||
|
//
|
||||||
|
dataOffset: number
|
||||||
|
dataSize: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const shouldDrawPiece = (piece: Piece) => {
|
const shouldDrawPiece = (piece: Piece) => {
|
||||||
|
|
@ -267,51 +263,61 @@ export async function main(
|
||||||
requesting: true,
|
requesting: true,
|
||||||
log: [],
|
log: [],
|
||||||
logPointer: 0,
|
logPointer: 0,
|
||||||
logIdx: 0,
|
|
||||||
speeds: [0.5, 1, 2, 5, 10, 20, 50, 100, 250, 500],
|
speeds: [0.5, 1, 2, 5, 10, 20, 50, 100, 250, 500],
|
||||||
speedIdx: 1,
|
speedIdx: 1,
|
||||||
paused: false,
|
paused: false,
|
||||||
lastRealTs: 0,
|
lastRealTs: 0,
|
||||||
lastGameTs: 0,
|
lastGameTs: 0,
|
||||||
gameStartTs: 0,
|
gameStartTs: 0,
|
||||||
|
dataOffset: 0,
|
||||||
|
dataSize: 10000,
|
||||||
}
|
}
|
||||||
|
|
||||||
Communication.onConnectionStateChange((state) => {
|
Communication.onConnectionStateChange((state) => {
|
||||||
HUD.setConnectionState(state)
|
HUD.setConnectionState(state)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const queryNextReplayBatch = async (
|
||||||
|
gameId: string
|
||||||
|
): Promise<ReplayData> => {
|
||||||
|
REPLAY.requesting = true
|
||||||
|
const replay: ReplayData = await Communication.requestReplayData(
|
||||||
|
gameId,
|
||||||
|
REPLAY.dataOffset,
|
||||||
|
REPLAY.dataSize
|
||||||
|
)
|
||||||
|
REPLAY.dataOffset += REPLAY.dataSize
|
||||||
|
REPLAY.requesting = false
|
||||||
|
return replay
|
||||||
|
}
|
||||||
|
|
||||||
const getNextReplayBatch = async (
|
const getNextReplayBatch = async (
|
||||||
gameId: string,
|
gameId: string
|
||||||
offset: number,
|
|
||||||
size: number
|
|
||||||
) => {
|
) => {
|
||||||
const replay: {
|
const replay: ReplayData = await queryNextReplayBatch(gameId)
|
||||||
game: any,
|
|
||||||
log: Array<any>
|
|
||||||
} = await Communication.requestReplayData(gameId, offset, size)
|
|
||||||
// cut log that was already handled
|
// cut log that was already handled
|
||||||
REPLAY.log = REPLAY.log.slice(REPLAY.logPointer)
|
REPLAY.log = REPLAY.log.slice(REPLAY.logPointer)
|
||||||
REPLAY.logPointer = 0
|
REPLAY.logPointer = 0
|
||||||
|
|
||||||
REPLAY.log.push(...replay.log)
|
REPLAY.log.push(...replay.log)
|
||||||
if (replay.log.length < 10000) {
|
if (replay.log.length < REPLAY.dataSize) {
|
||||||
REPLAY.final = true
|
REPLAY.final = true
|
||||||
}
|
}
|
||||||
REPLAY.requesting = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let TIME: () => number = () => 0
|
let TIME: () => number = () => 0
|
||||||
const connect = async () => {
|
const connect = async () => {
|
||||||
if (MODE === MODE_PLAY) {
|
if (MODE === MODE_PLAY) {
|
||||||
const game = await Communication.connect(wsAddress, gameId, clientId)
|
const game: EncodedGame = await Communication.connect(wsAddress, gameId, clientId)
|
||||||
const gameObject = Util.decodeGame(game)
|
const gameObject: GameType = Util.decodeGame(game)
|
||||||
Game.setGame(gameObject.id, gameObject)
|
Game.setGame(gameObject.id, gameObject)
|
||||||
TIME = () => Time.timestamp()
|
TIME = () => Time.timestamp()
|
||||||
} else if (MODE === MODE_REPLAY) {
|
} else if (MODE === MODE_REPLAY) {
|
||||||
const replay: {
|
const replay: ReplayData = await queryNextReplayBatch(gameId)
|
||||||
game: any,
|
if (!replay.game) {
|
||||||
log: Array<any>
|
throw '[ 2021-05-29 no game received ]'
|
||||||
} = await Communication.requestReplayData(gameId, 0, 10000)
|
}
|
||||||
const gameObject = Util.decodeGame(replay.game)
|
const gameObject: GameType = Util.decodeGame(replay.game)
|
||||||
Game.setGame(gameObject.id, gameObject)
|
Game.setGame(gameObject.id, gameObject)
|
||||||
REPLAY.requesting = false
|
REPLAY.requesting = false
|
||||||
REPLAY.log = replay.log
|
REPLAY.log = replay.log
|
||||||
|
|
@ -329,8 +335,8 @@ export async function main(
|
||||||
|
|
||||||
await connect()
|
await connect()
|
||||||
|
|
||||||
const TILE_DRAW_OFFSET = Game.getTileDrawOffset(gameId)
|
const PIECE_DRAW_OFFSET = Game.getPieceDrawOffset(gameId)
|
||||||
const TILE_DRAW_SIZE = Game.getTileDrawSize(gameId)
|
const PIECE_DRAW_SIZE = Game.getPieceDrawSize(gameId)
|
||||||
const PUZZLE_WIDTH = Game.getPuzzleWidth(gameId)
|
const PUZZLE_WIDTH = Game.getPuzzleWidth(gameId)
|
||||||
const PUZZLE_HEIGHT = Game.getPuzzleHeight(gameId)
|
const PUZZLE_HEIGHT = Game.getPuzzleHeight(gameId)
|
||||||
const TABLE_WIDTH = Game.getTableWidth(gameId)
|
const TABLE_WIDTH = Game.getTableWidth(gameId)
|
||||||
|
|
@ -345,8 +351,8 @@ export async function main(
|
||||||
h: PUZZLE_HEIGHT,
|
h: PUZZLE_HEIGHT,
|
||||||
}
|
}
|
||||||
const PIECE_DIM = {
|
const PIECE_DIM = {
|
||||||
w: TILE_DRAW_SIZE,
|
w: PIECE_DRAW_SIZE,
|
||||||
h: TILE_DRAW_SIZE,
|
h: PIECE_DRAW_SIZE,
|
||||||
}
|
}
|
||||||
|
|
||||||
const bitmaps = await PuzzleGraphics.loadPuzzleBitmaps(Game.getPuzzle(gameId))
|
const bitmaps = await PuzzleGraphics.loadPuzzleBitmaps(Game.getPuzzle(gameId))
|
||||||
|
|
@ -380,8 +386,8 @@ export async function main(
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTimerElements()
|
updateTimerElements()
|
||||||
HUD.setPiecesDone(Game.getFinishedTileCount(gameId))
|
HUD.setPiecesDone(Game.getFinishedPiecesCount(gameId))
|
||||||
HUD.setPiecesTotal(Game.getTileCount(gameId))
|
HUD.setPiecesTotal(Game.getPieceCount(gameId))
|
||||||
const ts = TIME()
|
const ts = TIME()
|
||||||
HUD.setActivePlayers(Game.getActivePlayers(gameId, ts))
|
HUD.setActivePlayers(Game.getActivePlayers(gameId, ts))
|
||||||
HUD.setIdlePlayers(Game.getIdlePlayers(gameId, ts))
|
HUD.setIdlePlayers(Game.getIdlePlayers(gameId, ts))
|
||||||
|
|
@ -470,8 +476,8 @@ export async function main(
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Protocol.CHANGE_TILE: {
|
case Protocol.CHANGE_TILE: {
|
||||||
const t = Util.decodeTile(changeData)
|
const t = Util.decodePiece(changeData)
|
||||||
Game.setTile(gameId, t.idx, t)
|
Game.setPiece(gameId, t.idx, t)
|
||||||
RERENDER = true
|
RERENDER = true
|
||||||
} break;
|
} break;
|
||||||
case Protocol.CHANGE_DATA: {
|
case Protocol.CHANGE_DATA: {
|
||||||
|
|
@ -494,8 +500,7 @@ export async function main(
|
||||||
|
|
||||||
if (REPLAY.logPointer + 1 >= REPLAY.log.length) {
|
if (REPLAY.logPointer + 1 >= REPLAY.log.length) {
|
||||||
REPLAY.lastRealTs = realTs
|
REPLAY.lastRealTs = realTs
|
||||||
REPLAY.requesting = true
|
getNextReplayBatch(gameId)
|
||||||
getNextReplayBatch(gameId, REPLAY.logIdx, 10000)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -519,7 +524,7 @@ export async function main(
|
||||||
}
|
}
|
||||||
|
|
||||||
const logEntry = REPLAY.log[nextIdx]
|
const logEntry = REPLAY.log[nextIdx]
|
||||||
const nextTs = REPLAY.gameStartTs + logEntry[logEntry.length - 1]
|
const nextTs: Timestamp = REPLAY.gameStartTs + logEntry[logEntry.length - 1]
|
||||||
if (nextTs > maxGameTs) {
|
if (nextTs > maxGameTs) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -546,7 +551,6 @@ export async function main(
|
||||||
RERENDER = true
|
RERENDER = true
|
||||||
}
|
}
|
||||||
REPLAY.logPointer = nextIdx
|
REPLAY.logPointer = nextIdx
|
||||||
REPLAY.logIdx++
|
|
||||||
} while (true)
|
} while (true)
|
||||||
REPLAY.lastRealTs = realTs
|
REPLAY.lastRealTs = realTs
|
||||||
REPLAY.lastGameTs = maxGameTs
|
REPLAY.lastGameTs = maxGameTs
|
||||||
|
|
@ -572,7 +576,7 @@ export async function main(
|
||||||
RERENDER = true
|
RERENDER = true
|
||||||
viewport.move(diffX, diffY)
|
viewport.move(diffX, diffY)
|
||||||
} else if (type === Protocol.INPUT_EV_MOUSE_MOVE) {
|
} else if (type === Protocol.INPUT_EV_MOUSE_MOVE) {
|
||||||
if (_last_mouse_down && !Game.getFirstOwnedTile(gameId, clientId)) {
|
if (_last_mouse_down && !Game.getFirstOwnedPiece(gameId, clientId)) {
|
||||||
// move the cam
|
// move the cam
|
||||||
const pos = { x: evt[1], y: evt[2] }
|
const pos = { x: evt[1], y: evt[2] }
|
||||||
const mouse = viewport.worldToViewport(pos)
|
const mouse = viewport.worldToViewport(pos)
|
||||||
|
|
@ -692,7 +696,7 @@ export async function main(
|
||||||
|
|
||||||
// DRAW TILES
|
// DRAW TILES
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
const tiles = Game.getTilesSortedByZIndex(gameId)
|
const tiles = Game.getPiecesSortedByZIndex(gameId)
|
||||||
if (window.DEBUG) Debug.checkpoint('get tiles done')
|
if (window.DEBUG) Debug.checkpoint('get tiles done')
|
||||||
|
|
||||||
dim = viewport.worldDimToViewportRaw(PIECE_DIM)
|
dim = viewport.worldDimToViewportRaw(PIECE_DIM)
|
||||||
|
|
@ -702,8 +706,8 @@ export async function main(
|
||||||
}
|
}
|
||||||
bmp = bitmaps[tile.idx]
|
bmp = bitmaps[tile.idx]
|
||||||
pos = viewport.worldToViewportRaw({
|
pos = viewport.worldToViewportRaw({
|
||||||
x: TILE_DRAW_OFFSET + tile.pos.x,
|
x: PIECE_DRAW_OFFSET + tile.pos.x,
|
||||||
y: TILE_DRAW_OFFSET + tile.pos.y,
|
y: PIECE_DRAW_OFFSET + tile.pos.y,
|
||||||
})
|
})
|
||||||
ctx.drawImage(bmp,
|
ctx.drawImage(bmp,
|
||||||
0, 0, bmp.width, bmp.height,
|
0, 0, bmp.width, bmp.height,
|
||||||
|
|
@ -743,7 +747,7 @@ export async function main(
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
HUD.setActivePlayers(Game.getActivePlayers(gameId, ts))
|
HUD.setActivePlayers(Game.getActivePlayers(gameId, ts))
|
||||||
HUD.setIdlePlayers(Game.getIdlePlayers(gameId, ts))
|
HUD.setIdlePlayers(Game.getIdlePlayers(gameId, ts))
|
||||||
HUD.setPiecesDone(Game.getFinishedTileCount(gameId))
|
HUD.setPiecesDone(Game.getFinishedPiecesCount(gameId))
|
||||||
if (window.DEBUG) Debug.checkpoint('HUD done')
|
if (window.DEBUG) Debug.checkpoint('HUD done')
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
import GameCommon, { ScoreMode } from './../common/GameCommon'
|
import GameCommon, { Game, ScoreMode, Timestamp } from './../common/GameCommon'
|
||||||
import Util from './../common/Util'
|
import Util from './../common/Util'
|
||||||
import { Rng } from './../common/Rng'
|
import { Rng } from './../common/Rng'
|
||||||
import GameLog from './GameLog'
|
import GameLog from './GameLog'
|
||||||
import { createPuzzle } from './Puzzle'
|
import { createPuzzle, PuzzleCreationImageInfo } from './Puzzle'
|
||||||
import Protocol from './../common/Protocol'
|
import Protocol from './../common/Protocol'
|
||||||
import GameStorage from './GameStorage'
|
import GameStorage from './GameStorage'
|
||||||
|
|
||||||
async function createGameObject(
|
async function createGameObject(
|
||||||
gameId: string,
|
gameId: string,
|
||||||
targetTiles: number,
|
targetTiles: number,
|
||||||
image: { file: string, url: string },
|
image: PuzzleCreationImageInfo,
|
||||||
ts: number,
|
ts: number,
|
||||||
scoreMode: ScoreMode
|
scoreMode: ScoreMode
|
||||||
) {
|
): Promise<Game> {
|
||||||
const seed = Util.hash(gameId + ' ' + ts)
|
const seed = Util.hash(gameId + ' ' + ts)
|
||||||
const rng = new Rng(seed)
|
const rng = new Rng(seed)
|
||||||
return {
|
return {
|
||||||
|
|
@ -28,11 +28,17 @@ async function createGameObject(
|
||||||
async function createGame(
|
async function createGame(
|
||||||
gameId: string,
|
gameId: string,
|
||||||
targetTiles: number,
|
targetTiles: number,
|
||||||
image: { file: string, url: string },
|
image: PuzzleCreationImageInfo,
|
||||||
ts: number,
|
ts: number,
|
||||||
scoreMode: ScoreMode
|
scoreMode: ScoreMode
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const gameObject = await createGameObject(gameId, targetTiles, image, ts, scoreMode)
|
const gameObject = await createGameObject(
|
||||||
|
gameId,
|
||||||
|
targetTiles,
|
||||||
|
image,
|
||||||
|
ts,
|
||||||
|
scoreMode
|
||||||
|
)
|
||||||
|
|
||||||
GameLog.create(gameId)
|
GameLog.create(gameId)
|
||||||
GameLog.log(gameId, Protocol.LOG_HEADER, 1, targetTiles, image, ts, scoreMode)
|
GameLog.log(gameId, Protocol.LOG_HEADER, 1, targetTiles, image, ts, scoreMode)
|
||||||
|
|
@ -41,7 +47,7 @@ async function createGame(
|
||||||
GameStorage.setDirty(gameId)
|
GameStorage.setDirty(gameId)
|
||||||
}
|
}
|
||||||
|
|
||||||
function addPlayer(gameId: string, playerId: string, ts: number): void {
|
function addPlayer(gameId: string, playerId: string, ts: Timestamp): void {
|
||||||
const idx = GameCommon.getPlayerIndexById(gameId, playerId)
|
const idx = GameCommon.getPlayerIndexById(gameId, playerId)
|
||||||
const diff = ts - GameCommon.getStartTs(gameId)
|
const diff = ts - GameCommon.getStartTs(gameId)
|
||||||
if (idx === -1) {
|
if (idx === -1) {
|
||||||
|
|
@ -74,14 +80,4 @@ export default {
|
||||||
createGame,
|
createGame,
|
||||||
addPlayer,
|
addPlayer,
|
||||||
handleInput,
|
handleInput,
|
||||||
getAllGames: GameCommon.getAllGames,
|
|
||||||
getActivePlayers: GameCommon.getActivePlayers,
|
|
||||||
getFinishedTileCount: GameCommon.getFinishedTileCount,
|
|
||||||
getImageUrl: GameCommon.getImageUrl,
|
|
||||||
getTileCount: GameCommon.getTileCount,
|
|
||||||
exists: GameCommon.exists,
|
|
||||||
playerExists: GameCommon.playerExists,
|
|
||||||
get: GameCommon.get,
|
|
||||||
getStartTs: GameCommon.getStartTs,
|
|
||||||
getFinishTs: GameCommon.getFinishTs,
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,19 +8,19 @@ const log = logger('GameLog.js')
|
||||||
|
|
||||||
const filename = (gameId: string) => `${DATA_DIR}/log_${gameId}.log`
|
const filename = (gameId: string) => `${DATA_DIR}/log_${gameId}.log`
|
||||||
|
|
||||||
const create = (gameId: string) => {
|
const create = (gameId: string): void => {
|
||||||
const file = filename(gameId)
|
const file = filename(gameId)
|
||||||
if (!fs.existsSync(file)) {
|
if (!fs.existsSync(file)) {
|
||||||
fs.appendFileSync(file, '')
|
fs.appendFileSync(file, '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const exists = (gameId: string) => {
|
const exists = (gameId: string): boolean => {
|
||||||
const file = filename(gameId)
|
const file = filename(gameId)
|
||||||
return fs.existsSync(file)
|
return fs.existsSync(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
const _log = (gameId: string, ...args: Array<any>) => {
|
const _log = (gameId: string, ...args: Array<any>): void => {
|
||||||
const file = filename(gameId)
|
const file = filename(gameId)
|
||||||
if (!fs.existsSync(file)) {
|
if (!fs.existsSync(file)) {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ function loadGame(gameId: string): void {
|
||||||
}
|
}
|
||||||
if (typeof game.puzzle.data.finished === 'undefined') {
|
if (typeof game.puzzle.data.finished === 'undefined') {
|
||||||
const unfinished = game.puzzle.tiles
|
const unfinished = game.puzzle.tiles
|
||||||
.map(Util.decodeTile)
|
.map(Util.decodePiece)
|
||||||
.find((t: Piece) => t.owner !== -1)
|
.find((t: Piece) => t.owner !== -1)
|
||||||
game.puzzle.data.finished = unfinished ? 0 : Time.timestamp()
|
game.puzzle.data.finished = unfinished ? 0 : Time.timestamp()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,12 @@ import Util from './../common/Util'
|
||||||
import { Rng } from './../common/Rng'
|
import { Rng } from './../common/Rng'
|
||||||
import Images from './Images'
|
import Images from './Images'
|
||||||
import { EncodedPiece, EncodedPieceShape, PieceShape, Puzzle } from '../common/GameCommon'
|
import { EncodedPiece, EncodedPieceShape, PieceShape, Puzzle } from '../common/GameCommon'
|
||||||
import { Point } from '../common/Geometry'
|
import { Dim, Point } from '../common/Geometry'
|
||||||
|
|
||||||
|
export interface PuzzleCreationImageInfo {
|
||||||
|
file: string
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
|
||||||
interface PuzzleCreationInfo {
|
interface PuzzleCreationInfo {
|
||||||
width: number
|
width: number
|
||||||
|
|
@ -22,7 +27,7 @@ const TILE_SIZE = 64
|
||||||
async function createPuzzle(
|
async function createPuzzle(
|
||||||
rng: Rng,
|
rng: Rng,
|
||||||
targetTiles: number,
|
targetTiles: number,
|
||||||
image: { file: string, url: string },
|
image: PuzzleCreationImageInfo,
|
||||||
ts: number
|
ts: number
|
||||||
): Promise<Puzzle> {
|
): Promise<Puzzle> {
|
||||||
const imagePath = image.file
|
const imagePath = image.file
|
||||||
|
|
@ -33,11 +38,7 @@ async function createPuzzle(
|
||||||
if (!dim.w || !dim.h) {
|
if (!dim.w || !dim.h) {
|
||||||
throw `[ 2021-05-16 invalid dimension for path ${imagePath} ]`
|
throw `[ 2021-05-16 invalid dimension for path ${imagePath} ]`
|
||||||
}
|
}
|
||||||
const info: PuzzleCreationInfo = determinePuzzleInfo(
|
const info: PuzzleCreationInfo = determinePuzzleInfo(dim, targetTiles)
|
||||||
dim.w,
|
|
||||||
dim.h,
|
|
||||||
targetTiles
|
|
||||||
)
|
|
||||||
|
|
||||||
let tiles = new Array(info.tiles)
|
let tiles = new Array(info.tiles)
|
||||||
for (let i = 0; i < tiles.length; i++) {
|
for (let i = 0; i < tiles.length; i++) {
|
||||||
|
|
@ -98,7 +99,7 @@ async function createPuzzle(
|
||||||
positions = rng.shuffle(positions)
|
positions = rng.shuffle(positions)
|
||||||
|
|
||||||
const pieces: Array<EncodedPiece> = tiles.map(tile => {
|
const pieces: Array<EncodedPiece> = tiles.map(tile => {
|
||||||
return Util.encodeTile({
|
return Util.encodePiece({
|
||||||
idx: tile.idx, // index of tile in the array
|
idx: tile.idx, // index of tile in the array
|
||||||
group: 0, // if grouped with other tiles
|
group: 0, // if grouped with other tiles
|
||||||
z: 0, // z index of the tile
|
z: 0, // z index of the tile
|
||||||
|
|
@ -181,9 +182,12 @@ function determinePuzzleTileShapes(
|
||||||
return shapes.map(Util.encodeShape)
|
return shapes.map(Util.encodeShape)
|
||||||
}
|
}
|
||||||
|
|
||||||
const determineTilesXY = (w: number, h: number, targetTiles: number) => {
|
const determineTilesXY = (
|
||||||
const w_ = w < h ? (w * h) : (w * w)
|
dim: Dim,
|
||||||
const h_ = w < h ? (h * h) : (w * h)
|
targetTiles: number
|
||||||
|
): { tilesX: number, tilesY: number } => {
|
||||||
|
const w_ = dim.w < dim.h ? (dim.w * dim.h) : (dim.w * dim.w)
|
||||||
|
const h_ = dim.w < dim.h ? (dim.h * dim.h) : (dim.w * dim.h)
|
||||||
let size = 0
|
let size = 0
|
||||||
let tiles = 0
|
let tiles = 0
|
||||||
do {
|
do {
|
||||||
|
|
@ -198,11 +202,10 @@ const determineTilesXY = (w: number, h: number, targetTiles: number) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const determinePuzzleInfo = (
|
const determinePuzzleInfo = (
|
||||||
w: number,
|
dim: Dim,
|
||||||
h: number,
|
|
||||||
targetTiles: number
|
targetTiles: number
|
||||||
): PuzzleCreationInfo => {
|
): PuzzleCreationInfo => {
|
||||||
const {tilesX, tilesY} = determineTilesXY(w, h, targetTiles)
|
const {tilesX, tilesY} = determineTilesXY(dim, targetTiles)
|
||||||
const tiles = tilesX * tilesY
|
const tiles = tilesX * tilesY
|
||||||
const tileSize = TILE_SIZE
|
const tileSize = TILE_SIZE
|
||||||
const width = tilesX * tileSize
|
const width = tilesX * tileSize
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import {
|
||||||
PUBLIC_DIR,
|
PUBLIC_DIR,
|
||||||
UPLOAD_DIR,
|
UPLOAD_DIR,
|
||||||
} from './Dirs'
|
} from './Dirs'
|
||||||
import { GameSettings, ScoreMode } from '../common/GameCommon'
|
import GameCommon, { Game as GameType, GameSettings, ScoreMode } from '../common/GameCommon'
|
||||||
import GameStorage from './GameStorage'
|
import GameStorage from './GameStorage'
|
||||||
import Db from './Db'
|
import Db from './Db'
|
||||||
|
|
||||||
|
|
@ -81,7 +81,7 @@ app.get('/api/replay-data', async (req, res) => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const log = await GameLog.get(gameId, offset, size)
|
const log = await GameLog.get(gameId, offset, size)
|
||||||
let game = null
|
let game: GameType|null = null
|
||||||
if (offset === 0) {
|
if (offset === 0) {
|
||||||
// also need the game
|
// also need the game
|
||||||
game = await Game.createGameObject(
|
game = await Game.createGameObject(
|
||||||
|
|
@ -107,15 +107,15 @@ app.get('/api/newgame-data', (req, res) => {
|
||||||
app.get('/api/index-data', (req, res) => {
|
app.get('/api/index-data', (req, res) => {
|
||||||
const ts = Time.timestamp()
|
const ts = Time.timestamp()
|
||||||
const games = [
|
const games = [
|
||||||
...Game.getAllGames().map((game: any) => ({
|
...GameCommon.getAllGames().map((game: any) => ({
|
||||||
id: game.id,
|
id: game.id,
|
||||||
hasReplay: GameLog.exists(game.id),
|
hasReplay: GameLog.exists(game.id),
|
||||||
started: Game.getStartTs(game.id),
|
started: GameCommon.getStartTs(game.id),
|
||||||
finished: Game.getFinishTs(game.id),
|
finished: GameCommon.getFinishTs(game.id),
|
||||||
tilesFinished: Game.getFinishedTileCount(game.id),
|
tilesFinished: GameCommon.getFinishedPiecesCount(game.id),
|
||||||
tilesTotal: Game.getTileCount(game.id),
|
tilesTotal: GameCommon.getPieceCount(game.id),
|
||||||
players: Game.getActivePlayers(game.id, ts).length,
|
players: GameCommon.getActivePlayers(game.id, ts).length,
|
||||||
imageUrl: Game.getImageUrl(game.id),
|
imageUrl: GameCommon.getImageUrl(game.id),
|
||||||
})),
|
})),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -193,7 +193,7 @@ app.post('/newgame', bodyParser.json(), async (req, res) => {
|
||||||
const gameSettings = req.body as GameSettings
|
const gameSettings = req.body as GameSettings
|
||||||
log.log(gameSettings)
|
log.log(gameSettings)
|
||||||
const gameId = Util.uniqId()
|
const gameId = Util.uniqId()
|
||||||
if (!Game.exists(gameId)) {
|
if (!GameCommon.exists(gameId)) {
|
||||||
const ts = Time.timestamp()
|
const ts = Time.timestamp()
|
||||||
await Game.createGame(
|
await Game.createGame(
|
||||||
gameId,
|
gameId,
|
||||||
|
|
@ -238,13 +238,13 @@ wss.on('message', async ({socket, data} : { socket: WebSocket, data: any }) => {
|
||||||
const msgType = msg[0]
|
const msgType = msg[0]
|
||||||
switch (msgType) {
|
switch (msgType) {
|
||||||
case Protocol.EV_CLIENT_INIT: {
|
case Protocol.EV_CLIENT_INIT: {
|
||||||
if (!Game.exists(gameId)) {
|
if (!GameCommon.exists(gameId)) {
|
||||||
throw `[game ${gameId} does not exist... ]`
|
throw `[game ${gameId} does not exist... ]`
|
||||||
}
|
}
|
||||||
const ts = Time.timestamp()
|
const ts = Time.timestamp()
|
||||||
Game.addPlayer(gameId, clientId, ts)
|
Game.addPlayer(gameId, clientId, ts)
|
||||||
GameSockets.addSocket(gameId, socket)
|
GameSockets.addSocket(gameId, socket)
|
||||||
const game = Game.get(gameId)
|
const game: GameType = GameCommon.get(gameId)
|
||||||
notify(
|
notify(
|
||||||
[Protocol.EV_SERVER_INIT, Util.encodeGame(game)],
|
[Protocol.EV_SERVER_INIT, Util.encodeGame(game)],
|
||||||
[socket]
|
[socket]
|
||||||
|
|
@ -252,7 +252,7 @@ wss.on('message', async ({socket, data} : { socket: WebSocket, data: any }) => {
|
||||||
} break
|
} break
|
||||||
|
|
||||||
case Protocol.EV_CLIENT_EVENT: {
|
case Protocol.EV_CLIENT_EVENT: {
|
||||||
if (!Game.exists(gameId)) {
|
if (!GameCommon.exists(gameId)) {
|
||||||
throw `[game ${gameId} does not exist... ]`
|
throw `[game ${gameId} does not exist... ]`
|
||||||
}
|
}
|
||||||
const clientSeq = msg[1]
|
const clientSeq = msg[1]
|
||||||
|
|
@ -260,7 +260,7 @@ wss.on('message', async ({socket, data} : { socket: WebSocket, data: any }) => {
|
||||||
const ts = Time.timestamp()
|
const ts = Time.timestamp()
|
||||||
|
|
||||||
let sendGame = false
|
let sendGame = false
|
||||||
if (!Game.playerExists(gameId, clientId)) {
|
if (!GameCommon.playerExists(gameId, clientId)) {
|
||||||
Game.addPlayer(gameId, clientId, ts)
|
Game.addPlayer(gameId, clientId, ts)
|
||||||
sendGame = true
|
sendGame = true
|
||||||
}
|
}
|
||||||
|
|
@ -269,7 +269,7 @@ wss.on('message', async ({socket, data} : { socket: WebSocket, data: any }) => {
|
||||||
sendGame = true
|
sendGame = true
|
||||||
}
|
}
|
||||||
if (sendGame) {
|
if (sendGame) {
|
||||||
const game = Game.get(gameId)
|
const game: GameType = GameCommon.get(gameId)
|
||||||
notify(
|
notify(
|
||||||
[Protocol.EV_SERVER_INIT, Util.encodeGame(game)],
|
[Protocol.EV_SERVER_INIT, Util.encodeGame(game)],
|
||||||
[socket]
|
[socket]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue