1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 | ;; ported-from: src/games/host/neon-grid-host.ts @ v1.3.0
;; (itself: game1/client/src/game/game.ts hi/in routing, live-beats-idle
;; split-brain rule, match flow @ 4c5def7) — the sim lives in
;; neon-grid-sim.cljs; roster/timers/auto-start in the driver base.
;; divergences: same as seance-host (no roster-grace, no election backstop);
;; the tick interval is a chained timeout (clients timestamp on receipt, so
;; cadence drift is cosmetic).
(ns ardegazu.peer.games.host.neon-grid-host
(:require [ardegazu.peer.games.host.driver :as driver]
[ardegazu.peer.games.host.neon-grid-sim :as ng]
[shadow.cljs.modern :refer (defclass)]))
(declare start-round)
(defclass NeonGridHost
(extends driver/HostDriver)
(constructor [this room opts]
(super room (if ^boolean (js* "~{} == null" opts) (js-obj) opts))
;; playing/countdown/roundover — true from "st" until "ma" or "lo"
(unchecked-set this "_live" false)
(unchecked-set
this "sim"
(ng/NeonGridSim.
(js-obj "roster" (fn [] (driver/roster-entries this))
"addScore" (fn [id]
(let [p (.get ^js (unchecked-get this "roster") id)]
(when ^boolean (js* "!!(~{})" p)
(unchecked-set p "score" (inc (unchecked-get p "score")))))
js/undefined)
"resetScores" (fn []
(.forEach ^js (unchecked-get this "roster")
(fn [p _k] (unchecked-set p "score" 0)))
js/undefined))))))
(defn- start-round [self]
(let [roster (unchecked-get self "roster")
riders (.map ^js (driver/connected-seated self)
(fn [id] (js-obj "id" id
"color" (unchecked-get (.get ^js roster id) "badge"))))]
(if (zero? (.-length riders))
(do (unchecked-set self "_live" false)
(driver/on-lobby self))
(do (unchecked-set self "_live" true)
(driver/run-emit self (ng/start-round (unchecked-get self "sim") riders)))))
js/undefined)
(let [proto (.-prototype NeonGridHost)]
;; live round beats idle claim, ties to lowest id (both sides of the split).
(unchecked-set
proto "concedeRule"
(fn [from m]
(this-as self
(let [my-live (unchecked-get self "_live")
their-live (identical? 1 (unchecked-get m "live"))
i-win (if-not (identical? my-live their-live)
my-live
(< (unchecked-get (unchecked-get self "room") "myId") from))]
(not i-win)))))
(unchecked-set proto "startMatch"
(fn [_ids]
(this-as self
(ng/new-match (unchecked-get self "sim"))
(driver/broadcast-roster self)
(start-round self)
js/undefined)))
(unchecked-set
proto "onGameFrame"
(fn [from m]
(this-as self
(let [t (unchecked-get m "t")]
(cond
(identical? t "hi") (driver/on-hi self from m)
(identical? t "in") (ng/input (unchecked-get self "sim") from
(bit-or (unchecked-get m "d") 0))
:else nil))
js/undefined)))
(unchecked-set
proto "execStep"
(fn [step]
(this-as self
(if (identical? step "round")
(start-round self)
(do
(when (or (identical? step "match") (identical? step "lobby"))
(unchecked-set self "_live" false))
(driver/run-emit self (ng/step (unchecked-get self "sim") step))))
js/undefined)))
(unchecked-set proto "simPeerGone"
(fn [id] (this-as self (ng/peer-gone (unchecked-get self "sim") id))))
(unchecked-set proto "sendSnap"
(fn [to] (this-as self
(driver/run-emit self (ng/snapshot (unchecked-get self "sim") to))
js/undefined)))
(unchecked-set proto "roundLive" (fn [] (this-as self (unchecked-get self "_live"))))
(unchecked-set proto "simRunning"
(fn [] (this-as self (unchecked-get (unchecked-get self "sim") "_running"))))
(unchecked-set proto "abortSim"
(fn [] (this-as self
(unchecked-set self "_live" false)
(ng/abort (unchecked-get self "sim"))))))
|