|
|
|
@ -10,15 +10,38 @@ open Lsp
|
|
|
|
open JsonRpc
|
|
|
|
open JsonRpc
|
|
|
|
open System.Uri
|
|
|
|
open System.Uri
|
|
|
|
|
|
|
|
|
|
|
|
def counter := IO.mkRef 0
|
|
|
|
def ServerState := GameServerState
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@[export game_make_state]
|
|
|
|
|
|
|
|
def makeState : IO (Ref ServerState) := do
|
|
|
|
|
|
|
|
let e ← IO.getStderr
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
|
|
searchPathRef.set ["/lib", "/gamelib"]
|
|
|
|
|
|
|
|
let state : GameServerState := {
|
|
|
|
|
|
|
|
env := ← importModules #[
|
|
|
|
|
|
|
|
{ module := `Init : Import }
|
|
|
|
|
|
|
|
-- { module := `GameServer : Import }
|
|
|
|
|
|
|
|
] {} 0 --← createEnv gameDir module,
|
|
|
|
|
|
|
|
game := "TEST",
|
|
|
|
|
|
|
|
gameDir := "test",
|
|
|
|
|
|
|
|
inventory := #[]
|
|
|
|
|
|
|
|
difficulty := 0
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return ← IO.mkRef state
|
|
|
|
|
|
|
|
catch err =>
|
|
|
|
|
|
|
|
e.putStrLn s!"Import error: {err}"
|
|
|
|
|
|
|
|
throw err
|
|
|
|
|
|
|
|
|
|
|
|
def readLspRequestAs (s : String) (expectedMethod : String) (α : Type) [FromJson α] : IO (Request α) := do
|
|
|
|
def readMessage (s : String) : IO JsonRpc.Message := do
|
|
|
|
let j ← ofExcept (Json.parse s)
|
|
|
|
let j ← ofExcept (Json.parse s)
|
|
|
|
let m ← match fromJson? j with
|
|
|
|
let m ← match fromJson? j with
|
|
|
|
| Except.ok (m : JsonRpc.Message) => pure m
|
|
|
|
| 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}"
|
|
|
|
| Except.error inner => throw $ userError s!"JSON '{j.compress}' did not have the format of a JSON-RPC message.\n{inner}"
|
|
|
|
let initRequest ← match m with
|
|
|
|
return m
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def readLspRequestAs (s : String) (expectedMethod : String) (α : Type) [FromJson α] : IO (Request α) := do
|
|
|
|
|
|
|
|
let m ← readMessage s
|
|
|
|
|
|
|
|
match m with
|
|
|
|
| Message.request id method params? =>
|
|
|
|
| Message.request id method params? =>
|
|
|
|
if method = expectedMethod then
|
|
|
|
if method = expectedMethod then
|
|
|
|
let j := toJson params?
|
|
|
|
let j := toJson params?
|
|
|
|
@ -29,39 +52,10 @@ def readLspRequestAs (s : String) (expectedMethod : String) (α : Type) [FromJso
|
|
|
|
throw $ userError s!"Expected method '{expectedMethod}', got method '{method}'"
|
|
|
|
throw $ userError s!"Expected method '{expectedMethod}', got method '{method}'"
|
|
|
|
| _ => throw $ userError s!"Expected JSON-RPC request, got: '{(toJson m).compress}'"
|
|
|
|
| _ => throw $ userError s!"Expected JSON-RPC request, got: '{(toJson m).compress}'"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def initializeServer (id : RequestID) : IO Unit := do
|
|
|
|
@[export game_send_message]
|
|
|
|
|
|
|
|
def sendMessage (s : String) : IO Unit := do
|
|
|
|
|
|
|
|
-- IO.println s!"received {s}"
|
|
|
|
|
|
|
|
-- if args.length < 2 then
|
|
|
|
|
|
|
|
-- throwServerError s!"Expected 1-3 command line arguments in addition to `--server`:
|
|
|
|
|
|
|
|
-- game directory, the name of the main module (optional), and the name of the game (optional)."
|
|
|
|
|
|
|
|
-- let gameDir := args[1]!
|
|
|
|
|
|
|
|
-- let module := if args.length < 3 then defaultGameModule else args[2]!
|
|
|
|
|
|
|
|
-- let gameName := if args.length < 4 then defaultGameName else args[3]!
|
|
|
|
|
|
|
|
-- let workerPath := "./gameserver"
|
|
|
|
|
|
|
|
-- -- TODO: Do the following commands slow us down?
|
|
|
|
|
|
|
|
-- let srcSearchPath ← initSrcSearchPath (← getBuildDir)
|
|
|
|
|
|
|
|
-- let references ← IO.mkRef (← loadReferences)
|
|
|
|
|
|
|
|
-- let fileWorkersRef ← IO.mkRef (RBMap.empty : FileWorkerMap)
|
|
|
|
|
|
|
|
-- -- let i ← maybeTee "wdIn.txt" false i
|
|
|
|
|
|
|
|
-- -- let o ← maybeTee "wdOut.txt" true o
|
|
|
|
|
|
|
|
-- -- let e ← maybeTee "wdErr.txt" true e
|
|
|
|
|
|
|
|
-- let state : GameServerState := {
|
|
|
|
|
|
|
|
-- env := ← importModules #[] {} 0 --← createEnv gameDir module,
|
|
|
|
|
|
|
|
-- game := "TEST",
|
|
|
|
|
|
|
|
-- gameDir := "test",
|
|
|
|
|
|
|
|
-- inventory := #[]
|
|
|
|
|
|
|
|
-- difficulty := 0
|
|
|
|
|
|
|
|
-- }
|
|
|
|
|
|
|
|
let initRequest ← readLspRequestAs s "initialize" InitializeParams
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- We misuse the `rootUri` field to the gameName
|
|
|
|
|
|
|
|
let rootUri? := "TEST"
|
|
|
|
|
|
|
|
let initRequest := {initRequest with param := {initRequest.param with rootUri?}}
|
|
|
|
|
|
|
|
let o ← IO.getStdout
|
|
|
|
let o ← IO.getStdout
|
|
|
|
o.writeLspResponse {
|
|
|
|
o.writeLspResponse {
|
|
|
|
id := initRequest.id
|
|
|
|
id := id
|
|
|
|
result := {
|
|
|
|
result := {
|
|
|
|
capabilities := mkLeanServerCapabilities
|
|
|
|
capabilities := mkLeanServerCapabilities
|
|
|
|
serverInfo? := some {
|
|
|
|
serverInfo? := some {
|
|
|
|
@ -71,17 +65,27 @@ def sendMessage (s : String) : IO Unit := do
|
|
|
|
: InitializeResult
|
|
|
|
: InitializeResult
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
-- let context : ServerContext := {
|
|
|
|
return ()
|
|
|
|
-- hIn := i
|
|
|
|
|
|
|
|
-- hOut := o
|
|
|
|
@[export game_send_message]
|
|
|
|
-- hLog := e
|
|
|
|
def sendMessage (s : String) (state : Ref ServerState) : IO Unit := do
|
|
|
|
-- args := args
|
|
|
|
let o ← IO.getStdout
|
|
|
|
-- fileWorkersRef := fileWorkersRef
|
|
|
|
let e ← IO.getStderr
|
|
|
|
-- initParams := initRequest.param
|
|
|
|
try
|
|
|
|
-- workerPath
|
|
|
|
let m ← readMessage s
|
|
|
|
-- srcSearchPath
|
|
|
|
match m with
|
|
|
|
-- references
|
|
|
|
| Message.request id "initialize" params? =>
|
|
|
|
-- }
|
|
|
|
initializeServer id
|
|
|
|
-- discard $ ReaderT.run (StateT.run initAndRunWatchdogAux state) context
|
|
|
|
| Message.request id "info" _ =>
|
|
|
|
|
|
|
|
let some game := (gameExt.getState (← state.get).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)])
|
|
|
|
|
|
|
|
o.writeLspResponse ⟨id, gameJson⟩
|
|
|
|
|
|
|
|
| _ => throw $ userError s!"Expected JSON-RPC request, got: '{(toJson m).compress}'"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
catch err =>
|
|
|
|
|
|
|
|
e.putStrLn s!"Server error: {err}"
|
|
|
|
return ()
|
|
|
|
return ()
|
|
|
|
|