Add live multiplayer 500 over cg-net (cg-bid-net.el)
Host-authoritative networked 500: host sits South, joiners take W/N/E, open seats filled by AI. Per-seat rotated state hides other hands and the kitty; clients reuse the single-player renderer/commands via :around advice, so cg-bid.el/cg-bid-ui.el are untouched. Adds cg-bid-host/cg-bid-join, a start-now lobby with auto-start at four players, and cg-bid-shuffle-partners. cg-net.el gains cg-net-connect-functions. Verified: clean byte-compile, checkdoc, 34/34 ERT (incl. 3 new net tests) and a two-process TCP game.
This commit is contained in:
parent
6593b49b74
commit
2345f7e1a6
5 changed files with 502 additions and 10 deletions
26
cg-net.el
26
cg-net.el
|
|
@ -64,17 +64,24 @@
|
|||
"Abnormal hook run on a client after the game state is updated.
|
||||
Each function is called with the client's game object.")
|
||||
|
||||
(defvar cg-net-connect-functions nil
|
||||
"Abnormal hook run on the host when a client connects.
|
||||
Each function is called with (HOST SEAT): the `cg-net-host' struct and
|
||||
the seat number just assigned to the new connection.")
|
||||
|
||||
;;;; Game integration points
|
||||
|
||||
(cl-defgeneric cg-net-apply-move (game seat move)
|
||||
"Apply MOVE made by SEAT to GAME on the host.
|
||||
Return non-nil when the move was accepted (and state should broadcast).")
|
||||
|
||||
(cl-defgeneric cg-net-game-state (game)
|
||||
"Return a `read'able representation of GAME's shared state.")
|
||||
(cl-defgeneric cg-net-game-state (game &optional seat)
|
||||
"Return a `read'able representation of GAME's shared state for SEAT.
|
||||
SEAT is the recipient's seat number, letting a game hide other players'
|
||||
private information; nil requests the full host view.")
|
||||
|
||||
(cl-defmethod cg-net-game-state ((game cg-game))
|
||||
"Default: return GAME's env plist as the shared state."
|
||||
(cl-defmethod cg-net-game-state ((game cg-game) &optional _seat)
|
||||
"Default: return GAME's env plist (no per-seat filtering)."
|
||||
(oref game env))
|
||||
|
||||
(cl-defgeneric cg-net-set-game-state (game state)
|
||||
|
|
@ -150,7 +157,8 @@ HANDLER is called with (PROC MSG)."
|
|||
(cg-net--send connection (list :type 'welcome :seat seat))
|
||||
(cg-net--send connection
|
||||
(list :type 'state
|
||||
:state (cg-net-game-state (cg-net-host-game cg-net--host))))))
|
||||
:state (cg-net-game-state (cg-net-host-game cg-net--host) seat)))
|
||||
(run-hook-with-args 'cg-net-connect-functions cg-net--host seat)))
|
||||
|
||||
(defun cg-net--host-handle (proc msg)
|
||||
"Handle one message MSG from a client PROC on the host."
|
||||
|
|
@ -163,11 +171,13 @@ HANDLER is called with (PROC MSG)."
|
|||
(cg-net-host-broadcast))))))
|
||||
|
||||
(defun cg-net-host-broadcast ()
|
||||
"Send the current game state to every connected client."
|
||||
"Send each connected client the game state filtered for its seat."
|
||||
(when cg-net--host
|
||||
(let ((state (cg-net-game-state (cg-net-host-game cg-net--host))))
|
||||
(let ((game (cg-net-host-game cg-net--host)))
|
||||
(dolist (c (cg-net-host-clients cg-net--host))
|
||||
(cg-net--send c (list :type 'state :state state))))))
|
||||
(cg-net--send c (list :type 'state
|
||||
:state (cg-net-game-state
|
||||
game (process-get c 'cg-net-seat))))))))
|
||||
|
||||
;;;; Client
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue