@@ -10,6 +10,9 @@ import at.petrak.hexcasting.api.casting.math.HexPattern
1010import gay.`object`.hexdebug.HexDebug
1111import gay.`object`.hexdebug.adapter.proxy.DebugProxyServerLauncher
1212import gay.`object`.hexdebug.config.HexDebugServerConfig
13+ import gay.`object`.hexdebug.core.api.debugging.DebugEnvironment
14+ import gay.`object`.hexdebug.core.api.exceptions.IllegalDebugSessionException
15+ import gay.`object`.hexdebug.core.api.exceptions.IllegalDebugThreadException
1316import gay.`object`.hexdebug.debugger.*
1417import gay.`object`.hexdebug.items.DebuggerItem
1518import gay.`object`.hexdebug.items.EvaluatorItem
@@ -39,7 +42,6 @@ class DebugAdapter(val player: ServerPlayer) : IDebugProtocolServer {
3942 private var lastDebugger: HexDebugger ? = null // for resolving sources after exit
4043 private val debuggers = mutableMapOf<Int , HexDebugger >()
4144 private val threadIds = mutableMapOf<UUID , Int >()
42- private val restartArgs = mutableMapOf<Int , CastArgs >()
4345 private val state = SharedDebugState ()
4446
4547 val launcher: IHexDebugLauncher by lazy {
@@ -48,6 +50,8 @@ class DebugAdapter(val player: ServerPlayer) : IDebugProtocolServer {
4850
4951 private val remoteProxy: IDebugProtocolClient get() = launcher.remoteProxy
5052
53+ private val maxThreads get() = HexDebugServerConfig .config.maxDebugThreads(player)
54+
5155 fun isDebugging (threadId : Int ) = debugger(threadId) != null
5256
5357 fun debugger (sessionId : UUID ) =
@@ -84,28 +88,50 @@ class DebugAdapter(val player: ServerPlayer) : IDebugProtocolServer {
8488 ).sendToPlayer(player)
8589 }
8690
87- fun startDebugging (threadId : Int , args : CastArgs , notifyClient : Boolean = true): Boolean {
88- val threadLimit = if (args.env.isEnlightened) HexDebugServerConfig .config.maxDebugThreads else 1
89- if (threadId >= threadLimit) return false
91+ fun createDebugThread (debugEnv : DebugEnvironment , maybeThreadId : Int? ) {
92+ if (debugEnv.sessionId in threadIds) {
93+ throw IllegalDebugSessionException (" Debug session already in use" )
94+ }
9095
91- val debugger = HexDebugger (threadId, state, args)
92- lastDebugger = debugger
96+ val threadId = resolveThreadId(maybeThreadId)
97+ threadIds[debugEnv.sessionId] = threadId
98+
99+ val debugger = HexDebugger (state, debugEnv, threadId)
93100 debuggers[threadId] = debugger
94- threadIds[args.debugEnv.sessionId] = threadId
95- restartArgs[threadId] = args
96101
97102 remoteProxy.thread(ThreadEventArguments ().also {
98103 it.reason = ThreadEventArgumentsReason .STARTED
99104 it.threadId = threadId
100105 })
101106
102- if (notifyClient) {
103- MsgDebuggerStateS2C (threadId, DebuggerItem .DebugState .DEBUGGING ).sendToPlayer(player)
104- closeEvaluator(threadId)
107+ MsgDebuggerStateS2C (threadId, DebuggerItem .DebugState .DEBUGGING ).sendToPlayer(player)
108+ closeEvaluator(threadId)
109+ }
110+
111+ private fun resolveThreadId (threadId : Int? ): Int {
112+ if (threadId == null ) {
113+ return (0 until maxThreads).firstOrNull { ! isDebugging(it) }
114+ ? : throw IllegalDebugThreadException (" All debug threads are already in use" )
105115 }
106116
107- handleDebuggerStep(threadId, debugger.start())
108- return true
117+ if (threadId !in (0 until maxThreads)) {
118+ throw IllegalDebugThreadException (" Debug thread ID out of range: $threadId " )
119+ }
120+
121+ if (isDebugging(threadId)) {
122+ throw IllegalDebugThreadException (" Debug thread already in use: $threadId " )
123+ }
124+
125+ return threadId
126+ }
127+
128+ fun startExecuting (debugEnv : DebugEnvironment , env : CastingEnvironment , iotas : List <Iota >) {
129+ val debugger = debugger(debugEnv.sessionId)
130+ ? : throw IllegalDebugSessionException (" Debug session not found" )
131+ val result = debugger.startExecuting(env, iotas)
132+ ? : throw IllegalDebugSessionException (" Debug session is already executing something" )
133+ lastDebugger = debugger
134+ handleDebuggerStep(debugger.threadId, result)
109135 }
110136
111137 fun disconnectClient () {
@@ -139,7 +165,7 @@ class DebugAdapter(val player: ServerPlayer) : IDebugProtocolServer {
139165
140166 fun evaluate (threadId : Int , env : CastingEnvironment , list : SpellList ) =
141167 debugger(threadId)?.let {
142- val result = it.evaluate(env, list)
168+ val result = it.evaluate(env, list) ? : return null
143169 if (result.startedEvaluating) {
144170 setEvaluatorState(threadId, EvaluatorItem .EvalState .MODIFIED )
145171 }
@@ -158,7 +184,10 @@ class DebugAdapter(val player: ServerPlayer) : IDebugProtocolServer {
158184 it.reason = ThreadEventArgumentsReason .EXITED
159185 it.threadId = threadId
160186 })
161- restartArgs[threadId]?.let { startDebugging(threadId, it) }
187+ debuggers.remove(threadId)?.let {
188+ threadIds.remove(it.sessionId)
189+ it.debugEnv.restart(threadId)
190+ }
162191 }
163192
164193 private fun messageWrapper (consumer : MessageConsumer ) = MessageConsumer { message ->
@@ -366,16 +395,22 @@ class DebugAdapter(val player: ServerPlayer) : IDebugProtocolServer {
366395 }
367396
368397 override fun pause (args : PauseArguments ): CompletableFuture <Void > {
369- // TODO: wisps/circles?
398+ debugger(args.threadId)?.let {
399+ if (it.state == DebuggerState .RUNNING ) {
400+ it.debugEnv.pause()
401+ }
402+ }
370403 return futureOf()
371404 }
372405
373406 override fun restart (args : RestartArguments ? ): CompletableFuture <Void > {
407+ val envs = debuggers.map { (threadId, debugger) -> threadId to debugger.debugEnv }
408+
374409 debuggers.clear()
375410 threadIds.clear()
376411
377- for ((threadId, castArgs ) in restartArgs ) {
378- startDebugging (threadId, castArgs, false )
412+ for ((threadId, debugEnv ) in envs ) {
413+ debugEnv.restart (threadId)
379414 }
380415
381416 MsgDebuggerStateS2C (
@@ -446,7 +481,8 @@ class DebugAdapter(val player: ServerPlayer) : IDebugProtocolServer {
446481 .map { (threadId, debugger) ->
447482 Thread ().apply {
448483 id = threadId
449- name = " Thread $threadId (${debugger.envType} )"
484+ name = " Thread $threadId "
485+ debugger.envName?.let { name + = " ($it )" }
450486 }
451487 }
452488 .sortedBy { it.id }
0 commit comments