board-game-server.lisp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. (in-package :server)
  2. (defvar *board-game-connections* (make-hash-table))
  3. (defvar *board-game-partial-messages* (make-hash-table))
  4. (defvar *board-game-connections-by-denizen-id* (make-hash-table))
  5. (defvar *board-game-states* (data:all-board-game-states))
  6. (defun handle-new-board-game-connection (con env)
  7. (let ((id (current-id env)))
  8. (setf (gethash con *board-game-connections*) id
  9. (gethash id *board-game-connections-by-denizen-id*) con)))
  10. (defun broadcast-board-game-message (message)
  11. (loop for con being the hash-key of *board-game-connections* do
  12. (websocket-driver:send con message)))
  13. (defun handle-board-game-message (con message)
  14. (cond ((not (equalp message "finished"))
  15. (setf message (concatenate 'string (gethash con *board-game-partial-messages*) message))
  16. (setf (gethash con *board-game-partial-messages*) message))
  17. (t
  18. (let* ((parsed-message (yason:parse (gethash con *board-game-partial-messages*)))
  19. (delete (gethash "delete" parsed-message))
  20. (refresh (gethash "refresh" parsed-message))
  21. (ping (gethash "ping" parsed-message))
  22. (chat (gethash "chat" parsed-message))
  23. (board (gethash "board" parsed-message)))
  24. (remhash con *board-game-partial-messages*)
  25. (unless ping
  26. (cond
  27. (delete
  28. (when (data:data-with-id delete)
  29. (let ((deleted-state (data:data-with-id delete)))
  30. (setf *board-game-states* (remove deleted-state *board-game-states*))
  31. (bknr.datastore:delete-object deleted-state))
  32. (broadcast-board-game-message
  33. (data:json
  34. (mapcar #'(lambda (state)
  35. (data:board-game-state-vector state))
  36. *board-game-states*)))))
  37. (refresh
  38. (let ((states-json (data:json
  39. (mapcar #'(lambda (state)
  40. (data:board-game-state-vector state))
  41. *board-game-states*))))
  42. (websocket-driver:send con states-json)))
  43. (chat
  44. (let ((message (make-hash-table)))
  45. (setf (gethash "chat" message)
  46. chat
  47. (gethash "sender" message)
  48. (gethash "label"
  49. (data:parsed-json
  50. (data:data-with-id
  51. (gethash con *board-game-connections*)))))
  52. (when board (setf (gethash "board" message) board))
  53. (broadcast-board-game-message (data:json message))))
  54. ((and board (not (data:data-with-id (gethash "stateId" board))))
  55. (let* ((game (data:data-with-id (gethash "gameId" board)))
  56. (game-state (data:make-board-game-state game board)))
  57. (push game-state *board-game-states*)
  58. (setf (gethash "stateId" board) (data:id game-state))
  59. (broadcast-board-game-message
  60. (data:json
  61. (mapcar #'(lambda (state)
  62. (data:board-game-state-vector state))
  63. *board-game-states*)))))
  64. (board
  65. (let ((game-state (data:data-with-id (gethash "stateId" board))))
  66. (vector-push-extend board
  67. (data:board-game-state-vector game-state))
  68. (data:with-transaction ()
  69. (setf (data:board-game-state-vector game-state)
  70. (data:board-game-state-vector game-state)))
  71. (broadcast-board-game-message (data:json board))))))))))
  72. (defun handle-board-game-close-connection (con)
  73. (let ((id (gethash con *board-game-connections*)))
  74. (remhash con *board-game-connections*)
  75. (remhash id *board-game-connections-by-denizen-id*)
  76. (remhash con *board-game-partial-messages*)))
  77. (defun board-game-server (env)
  78. (let ((ws (websocket-driver:make-server env)))
  79. (websocket-driver:on :open ws
  80. (lambda () (handle-new-board-game-connection ws env)))
  81. (websocket-driver:on :message ws
  82. (lambda (msg) (handle-board-game-message ws msg)))
  83. (websocket-driver:on :close ws
  84. (lambda (&key code reason)
  85. (declare (ignore code reason))
  86. (handle-board-game-close-connection ws)))
  87. (lambda (responder)
  88. (declare (ignore responder))
  89. (websocket-driver:start-connection ws))))