You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lean4game/server/GameServer/WasmServer.lean

114 lines
4.0 KiB
Plaintext

1 year ago
import Lean.Server.Watchdog
1 year ago
import GameServer.EnvExtensions
1 year ago
import GameServer.Game
namespace WasmServer.Watchdog
open Lean
open Server
open Watchdog
open IO
open Lsp
open JsonRpc
open System.Uri
def ServerState := GameServerState
1 year ago
@[export game_make_state]
1 year ago
unsafe def makeState : IO (ServerState) := do
let e ← IO.getStderr
try
1 year ago
Lean.enableInitializersExecution
searchPathRef.set ["/lib", "/gamelib"]
1 year ago
e.putStrLn s!"Importing"
let state : GameServerState := {
env := ← importModules #[
1 year ago
{ module := `Init : Import },
{ module := `GameServer : Import }
] {} 0 --← createEnv gameDir module,
game := "TEST",
gameDir := "test",
inventory := #[]
difficulty := 0
}
1 year ago
e.putStrLn s!"Import complete"
let pExtDescrs ← persistentEnvExtensionsRef.get
pExtDescrs.forM fun extDescr => do
e.putStrLn ("extension '" ++ toString extDescr.name ++ "'")
let s := extDescr.toEnvExtension.getState state.env
let fmt := extDescr.statsFn s.state
unless fmt.isNil do IO.println (" " ++ toString (Format.nest 2 (extDescr.statsFn s.state)))
e.putStrLn (" number of imported entries: " ++ toString (s.importedEntries.foldl (fun sum es => sum + es.size) 0))
e.putStrLn s!"{(gameExt.getState state.env).size}"
let some game := (gameExt.getState state.env).find? `TestGame
| throwServerError "Game not found"
let gameJson : Json := toJson game
-- Add world sizes to Json object
-- let worldSize := game.worlds.nodes.toList.map (fun (n, w) => (n.toString, w.levels.size))
-- let gameJson := gameJson.mergeObj (Json.mkObj [("worldSize", Json.mkObj worldSize)])
e.putStrLn s!"{gameJson}"
return state
catch err =>
e.putStrLn s!"Import error: {err}"
throw err
1 year ago
def readMessage (s : String) : IO JsonRpc.Message := do
1 year ago
let j ← ofExcept (Json.parse s)
let m ← match fromJson? j with
| Except.ok (m : JsonRpc.Message) => pure m
| Except.error inner => throw $ userError s!"JSON '{j.compress}' did not have the format of a JSON-RPC message.\n{inner}"
return m
1 year ago
def readLspRequestAs (s : String) (expectedMethod : String) (α : Type) [FromJson α] : IO (Request α) := do
let m ← readMessage s
match m with
| Message.request id method params? =>
if method = expectedMethod then
let j := toJson params?
match fromJson? j with
| Except.ok v => pure $ JsonRpc.Request.mk id expectedMethod (v : α)
| Except.error inner => throw $ userError s!"Unexpected param '{j.compress}' for method '{expectedMethod}'\n{inner}"
else
throw $ userError s!"Expected method '{expectedMethod}', got method '{method}'"
| _ => throw $ userError s!"Expected JSON-RPC request, got: '{(toJson m).compress}'"
1 year ago
def initializeServer (id : RequestID) : IO Unit := do
1 year ago
let o ← IO.getStdout
o.writeLspResponse {
id := id
1 year ago
result := {
capabilities := mkLeanServerCapabilities
serverInfo? := some {
name := "Lean 4 Game Server"
version? := "0.1.1"
}
: InitializeResult
}
}
return ()
1 year ago
@[export game_send_message]
1 year ago
unsafe def sendMessage (s : String) (state : ServerState) : IO Unit := do
let o ← IO.getStdout
let e ← IO.getStderr
try
let m ← readMessage s
match m with
| Message.request id "initialize" params? =>
initializeServer id
| Message.request id "info" _ =>
1 year ago
let some game := (gameExt.getState state.env).find? `TestGame
| throwServerError "Game not found"
let gameJson : Json := toJson game
-- Add world sizes to Json object
1 year ago
-- let worldSize := game.worlds.nodes.toList.map (fun (n, w) => (n.toString, w.levels.size))
-- let gameJson := gameJson.mergeObj (Json.mkObj [("worldSize", Json.mkObj worldSize)])
e.putStrLn s!"{gameJson}"
o.writeLspResponse ⟨id, gameJson⟩
1 year ago
| _ => pure () --throw $ userError s!"Expected JSON-RPC request, got: '{(toJson m).compress}'"
catch err =>
e.putStrLn s!"Server error: {err}"
return ()