import GameServer.RpcHandlers open Lean structure GameServerState := (env : Lean.Environment) (game : Name) (gameDir : String) (inventory : Array String) (difficulty : Nat) abbrev GameServerM := StateT GameServerState Server.Watchdog.ServerM instance : MonadEnv GameServerM := { getEnv := do return (← get).env modifyEnv := fun f => do let s ← get set {s with env := f s.env} } namespace Game open Server open Watchdog open Lsp open JsonRpc open IO structure DidOpenLevelParams where uri : String gameDir : String levelModule : Name tactics : Array InventoryTile lemmas : Array InventoryTile definitions : Array InventoryTile inventory : Array String /-- Check for tactics/theorems that are not unlocked. 0: no check 1: give warnings 2: give errors -/ difficulty : Nat /-- The name of the theorem to be proven in this level. -/ statementName : Name deriving ToJson, FromJson structure SetInventoryParams where inventory : Array String difficulty : Nat deriving ToJson, FromJson def handleDidOpenLevel (params : Json) : GameServerM Unit := do let p ← parseParams _ params let m := p.textDocument -- Execute the regular handling of the `didOpen` event handleDidOpen p let fw ← findFileWorker! m.uri -- let s ← get let c ← read let some lvl ← GameServer.getLevelByFileName? c.initParams ((System.Uri.fileUriToPath? m.uri).getD m.uri |>.toString) | do c.hLog.putStr s!"Level not found: {m.uri} {c.initParams.rootUri?}" c.hLog.flush -- Send an extra notification to the file worker to inform it about the level data let s ← get fw.stdin.writeLspNotification { method := "$/game/didOpenLevel" param := { uri := m.uri gameDir := s.gameDir levelModule := lvl.module tactics := lvl.tactics.tiles lemmas := lvl.lemmas.tiles definitions := lvl.definitions.tiles inventory := s.inventory difficulty := s.difficulty statementName := lvl.statementName : DidOpenLevelParams } } partial def handleServerEvent (ev : ServerEvent) : GameServerM Bool := do match ev with | ServerEvent.clientMsg msg => match msg with | Message.notification "$/game/setInventory" params => let p := (← parseParams SetInventoryParams (toJson params)) let s ← get set {s with inventory := p.inventory, difficulty := p.difficulty} let st ← read let workers ← st.fileWorkersRef.get for (_, fw) in workers do fw.stdin.writeLspMessage msg return true | _ => return false | _ => return false end Game