2021-05-29 17:58:05 +02:00
|
|
|
import { Point } from "./Geometry"
|
|
|
|
|
import { Rng, RngSerialized } from "./Rng"
|
|
|
|
|
|
2021-05-29 15:36:03 +02:00
|
|
|
// @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> > }
|
2021-05-29 17:58:05 +02:00
|
|
|
|
|
|
|
|
export type Timestamp = number
|
|
|
|
|
|
|
|
|
|
export type Input = any
|
|
|
|
|
export type Change = Array<any>
|
|
|
|
|
|
|
|
|
|
export type GameEvent = Array<any>
|
|
|
|
|
|
2021-05-31 20:05:41 +02:00
|
|
|
export type ServerEvent = Array<any>
|
2021-05-29 17:58:05 +02:00
|
|
|
export type ClientEvent = 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 EncodedGame = FixedLengthArray<[
|
|
|
|
|
string,
|
|
|
|
|
string,
|
|
|
|
|
RngSerialized,
|
|
|
|
|
Puzzle,
|
|
|
|
|
Array<EncodedPlayer>,
|
|
|
|
|
Record<string, EvtInfo>,
|
|
|
|
|
ScoreMode,
|
2021-06-04 09:26:37 +02:00
|
|
|
ShapeMode,
|
|
|
|
|
SnapMode,
|
2021-05-29 17:58:05 +02:00
|
|
|
]>
|
|
|
|
|
|
|
|
|
|
export interface ReplayData {
|
|
|
|
|
log: any[],
|
|
|
|
|
game: EncodedGame|null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface Tag {
|
|
|
|
|
id: number
|
|
|
|
|
slug: string
|
|
|
|
|
title: string
|
2021-06-03 23:46:09 +02:00
|
|
|
total: number
|
2021-05-29 17:58:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface GameRng {
|
|
|
|
|
obj: Rng
|
|
|
|
|
type?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface Game {
|
|
|
|
|
id: string
|
|
|
|
|
players: Array<EncodedPlayer>
|
|
|
|
|
puzzle: Puzzle
|
|
|
|
|
evtInfos: Record<string, EvtInfo>
|
2021-07-08 00:00:17 +02:00
|
|
|
scoreMode: ScoreMode
|
|
|
|
|
shapeMode: ShapeMode
|
|
|
|
|
snapMode: SnapMode
|
2021-05-29 17:58:05 +02:00
|
|
|
rng: GameRng
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface Image {
|
|
|
|
|
id: number
|
|
|
|
|
filename: string
|
|
|
|
|
file: string
|
|
|
|
|
url: string
|
|
|
|
|
title: string
|
|
|
|
|
tags: Array<Tag>
|
|
|
|
|
created: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface GameSettings {
|
|
|
|
|
tiles: number
|
|
|
|
|
image: Image
|
|
|
|
|
scoreMode: ScoreMode
|
2021-06-03 09:07:57 +02:00
|
|
|
shapeMode: ShapeMode
|
2021-06-04 09:26:37 +02:00
|
|
|
snapMode: SnapMode
|
2021-05-29 17:58:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface Puzzle {
|
|
|
|
|
tiles: Array<EncodedPiece>
|
|
|
|
|
data: PuzzleData
|
|
|
|
|
info: PuzzleInfo
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface PuzzleData {
|
|
|
|
|
started: number
|
|
|
|
|
finished: number
|
|
|
|
|
maxGroup: number
|
|
|
|
|
maxZ: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface PuzzleDataChange {
|
|
|
|
|
started?: number
|
|
|
|
|
finished?: number
|
|
|
|
|
maxGroup?: number
|
|
|
|
|
maxZ?: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface PuzzleTable {
|
|
|
|
|
width: number
|
|
|
|
|
height: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum PieceEdge {
|
|
|
|
|
Flat = 0,
|
|
|
|
|
Out = 1,
|
|
|
|
|
In = -1,
|
|
|
|
|
}
|
|
|
|
|
export interface PieceShape {
|
|
|
|
|
top: PieceEdge
|
|
|
|
|
bottom: PieceEdge
|
|
|
|
|
left: PieceEdge
|
|
|
|
|
right: PieceEdge
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface Piece {
|
|
|
|
|
owner: string|number
|
|
|
|
|
idx: number
|
|
|
|
|
pos: Point
|
|
|
|
|
z: number
|
|
|
|
|
group: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface PieceChange {
|
|
|
|
|
owner?: string|number
|
|
|
|
|
idx?: number
|
|
|
|
|
pos?: Point
|
|
|
|
|
z?: number
|
|
|
|
|
group?: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface PuzzleInfo {
|
|
|
|
|
table: PuzzleTable
|
|
|
|
|
targetTiles: number,
|
|
|
|
|
imageUrl: string
|
|
|
|
|
|
|
|
|
|
width: number
|
|
|
|
|
height: number
|
|
|
|
|
tileSize: number
|
|
|
|
|
tileDrawSize: number
|
|
|
|
|
tileMarginWidth: number
|
|
|
|
|
tileDrawOffset: number
|
|
|
|
|
snapDistance: number
|
|
|
|
|
|
|
|
|
|
tiles: number
|
|
|
|
|
tilesX: number
|
|
|
|
|
tilesY: number
|
|
|
|
|
|
|
|
|
|
shapes: Array<EncodedPieceShape>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface Player {
|
|
|
|
|
id: string
|
|
|
|
|
x: number
|
|
|
|
|
y: number
|
|
|
|
|
d: 0|1
|
|
|
|
|
name: string|null
|
|
|
|
|
color: string|null
|
|
|
|
|
bgcolor: string|null
|
|
|
|
|
points: number
|
|
|
|
|
ts: Timestamp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface PlayerChange {
|
|
|
|
|
id?: string
|
|
|
|
|
x?: number
|
|
|
|
|
y?: number
|
|
|
|
|
d?: 0|1
|
|
|
|
|
name?: string|null
|
|
|
|
|
color?: string|null
|
|
|
|
|
bgcolor?: string|null
|
|
|
|
|
points?: number
|
|
|
|
|
ts?: Timestamp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface EvtInfo {
|
|
|
|
|
_last_mouse: Point|null
|
|
|
|
|
_last_mouse_down: Point|null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export enum ScoreMode {
|
|
|
|
|
FINAL = 0,
|
|
|
|
|
ANY = 1,
|
|
|
|
|
}
|
2021-06-03 09:07:57 +02:00
|
|
|
|
|
|
|
|
export enum ShapeMode {
|
|
|
|
|
NORMAL = 0,
|
|
|
|
|
ANY = 1,
|
|
|
|
|
FLAT = 2,
|
|
|
|
|
}
|
2021-06-04 09:26:37 +02:00
|
|
|
|
|
|
|
|
export enum SnapMode {
|
|
|
|
|
NORMAL = 0,
|
|
|
|
|
REAL = 1,
|
|
|
|
|
}
|
2021-07-08 00:00:17 +02:00
|
|
|
|
|
|
|
|
export const DefaultScoreMode = (v: any): ScoreMode => {
|
|
|
|
|
if (v === ScoreMode.FINAL || v === ScoreMode.ANY) {
|
|
|
|
|
return v
|
|
|
|
|
}
|
|
|
|
|
return ScoreMode.FINAL
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const DefaultShapeMode = (v: any): ShapeMode => {
|
|
|
|
|
if (v === ShapeMode.NORMAL || v === ShapeMode.ANY || v === ShapeMode.FLAT) {
|
|
|
|
|
return v
|
|
|
|
|
}
|
|
|
|
|
return ShapeMode.NORMAL
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const DefaultSnapMode = (v: any): SnapMode => {
|
|
|
|
|
if (v === SnapMode.NORMAL || v === SnapMode.REAL) {
|
|
|
|
|
return v
|
|
|
|
|
}
|
|
|
|
|
return SnapMode.NORMAL
|
|
|
|
|
}
|