summaryrefslogtreecommitdiff
path: root/server/api
diff options
context:
space:
mode:
authorewy <ewy0@protonmail.com>2026-09-14 19:48:36 +0200
committerewy <ewy0@protonmail.com>2026-09-14 19:48:36 +0200
commit899ef7448222f0d087c194b3379b702f8dd2ff8c (patch)
tree8c2b508bb4d01236c7f582e4eee91fd178d09670 /server/api
parentc69e6c0770359e2febafcf487eb21c4aa608c3e9 (diff)
add server and websocket comms
Diffstat (limited to 'server/api')
-rw-r--r--server/api/game.go79
1 files changed, 79 insertions, 0 deletions
diff --git a/server/api/game.go b/server/api/game.go
new file mode 100644
index 0000000..bccf12a
--- /dev/null
+++ b/server/api/game.go
@@ -0,0 +1,79 @@
+package api
+
+import (
+ "github.com/gorilla/websocket"
+ "net/http"
+ "sakura/engine"
+ "slices"
+ "uuid"
+)
+
+type Conn struct {
+ Socket *websocket.Conn
+}
+
+var upgrader = websocket.Upgrader{}
+
+var games = make(map[uuid.UUID]*engine.Game)
+var connections = make(map[uuid.UUID][]*Conn)
+
+func GameCreate(w http.ResponseWriter, r *http.Request) {
+ id := uuid.NewV7()
+ games[id] = engine.NewGame()
+ w.Write([]byte(id.String()))
+}
+
+func GameConnect(w http.ResponseWriter, r *http.Request) {
+ id := r.PathValue("id")
+ uid, err := uuid.Parse(id)
+ if err != nil {
+ http.Error(w, "unable to parse game uuid "+err.Error(), http.StatusBadRequest)
+ return
+ }
+ game := games[uid]
+ if game == nil {
+ http.Error(w, "game not found", http.StatusNotFound)
+ return
+ }
+ wsConn, err := upgrader.Upgrade(w, r, nil)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ if wsConn == nil {
+ http.Error(w, "unable to initialize websocket", http.StatusInternalServerError)
+ return
+ }
+ conn := &Conn{wsConn}
+ connections[uid] = append(connections[uid], conn)
+ wsConn.SetCloseHandler(func(code int, text string) error {
+ connections[uid] = slices.DeleteFunc(connections[uid], func(potential *Conn) bool {
+ return potential == conn
+ })
+ return nil
+ })
+ err = wsConn.WriteJSON(game)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ go PumpRead(uid, game, wsConn)
+}
+
+func Update(id uuid.UUID, g *engine.Game) {
+ for _, c := range connections[id] {
+ _ = c.Socket.WriteJSON(g)
+ }
+}
+
+func PumpRead(id uuid.UUID, g *engine.Game, conn *websocket.Conn) {
+ var interaction engine.InteractionID
+ for {
+ err := conn.ReadJSON(&interaction)
+ if err != nil {
+ break
+ }
+ g.Actions[interaction].Then(g)
+ Update(id, g)
+ }
+}