Skip to content

Commit 5d68483

Browse files
committed
Manage queries in client instead of host
1 parent 83f87ad commit 5d68483

14 files changed

+192
-141
lines changed

src/controllers/script_controllers/host_bridge.nim

+68-87
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,23 @@ proc to_node(self: Worker, unit: Unit): PNode =
7979
else:
8080
ast.new_node(nkNilLit)
8181

82+
proc to_node[T: Unit](self: Worker, units: seq[T]): PNode =
83+
var node = ast.new_node(nkBracketExpr)
84+
for unit in units:
85+
if ?unit:
86+
node.add self.to_node(unit)
87+
else:
88+
node.add ast.new_node(nk_nil_lit)
89+
result = node
90+
8291
# Common bindings
8392

8493
proc press_action(self: Worker, name: string) =
8594
state.queued_action = name
8695

96+
proc register_template_node(self: Worker, pnode: PNode, name: string) =
97+
self.template_node_map[name] = pnode
98+
8799
proc register_active(self: Worker, pnode: PNode) =
88100
assert not self.active_unit.is_nil
89101
self.map_unit(self.active_unit, pnode)
@@ -154,35 +166,36 @@ proc reset_level(self: Worker) =
154166
state.config_value.value:
155167
level_dir = current_level
156168

157-
template query(
158-
T: type Unit, key: string, ctx: ScriptCtx, body: untyped
159-
): untyped =
160-
var result: T
161-
if key in ctx.query_results:
162-
result = T(ctx.query_results[key][^1])
163-
else:
164-
let results = body
165-
if ?results:
166-
result = results[^1]
167-
ctx.query_results[key] = cast[seq[Unit]](results)
168-
result
169-
170-
proc ensure_unit(self: Worker, unit: Unit) =
169+
proc ensure_unit_impl[T: Unit](self: Worker, unit: T) {.gcsafe.} =
171170
if unit notin self.node_map:
172-
var node = self.node_map[self.active_unit].copy_tree
171+
var node = self.template_node_map[$T].copy_tree
173172
self.map_unit(unit, node)
174173

175-
proc current_collider(self: Worker, unit: Unit, kind: string): Unit =
176-
Unit.query(kind & "-collider", unit.script_ctx):
177-
var colliders: seq[Unit]
178-
state.units.value.walk_tree proc(other: Unit) =
179-
if unit.collisions.value.any_it(it.id == other.id):
180-
if kind == "Unit" or kind == "Player" and other of Player or
181-
kind == "Bot" and other of Bot or kind == "Build" and other of Build or
182-
kind == "Sign" and other of Sign:
183-
colliders.add(other)
184-
self.ensure_unit(other)
185-
colliders
174+
method ensure_exists(self: Unit, worker: Worker) {.base, gcsafe.} =
175+
raise_assert "ensure_unit not implemented for " & $self.type
176+
177+
method ensure_exists(self: Player, worker: Worker) =
178+
worker.ensure_unit_impl(self)
179+
180+
method ensure_exists(self: Bot, worker: Worker) =
181+
worker.ensure_unit_impl(self)
182+
183+
method ensure_exists(self: Build, worker: Worker) =
184+
worker.ensure_unit_impl(self)
185+
186+
method ensure_exists(self: Sign, worker: Worker) =
187+
worker.ensure_unit_impl(self)
188+
189+
proc current_colliders*(self: Worker, unit: Unit, kind: string): seq[Unit] =
190+
var colliders: seq[Unit]
191+
state.units.value.walk_tree proc(other: Unit) =
192+
if unit.collisions.value.any_it(it.id == other.id):
193+
if kind == "Unit" or kind == "Player" and other of Player or
194+
kind == "Bot" and other of Bot or kind == "Build" and other of Build or
195+
kind == "Sign" and other of Sign:
196+
colliders.add(other)
197+
other.ensure_exists(self)
198+
colliders
186199

187200
proc world_name(): string =
188201
state.config.world
@@ -233,17 +246,6 @@ proc sleep_impl(self: Worker, ctx: ScriptCtx, seconds: float) =
233246
ctx.last_ran = MonoTime.default
234247
self.pause_script()
235248

236-
proc loop_finished(self: Worker, ctx: ScriptCtx) =
237-
if ?ctx.query_results:
238-
let key = ctx.query_results.first_key
239-
let res = ctx.query_results[key].pop
240-
if not ?ctx.query_results[key]:
241-
ctx.query_results.del key
242-
if not ?ctx.query_results:
243-
self.sleep_impl(ctx, 0.0)
244-
else:
245-
self.sleep_impl(ctx, 0.0)
246-
247249
proc hit(unit_a: Unit, unit_b: Unit): Vector3 =
248250
for collision in unit_a.collisions:
249251
if collision.id == unit_b.id:
@@ -253,38 +255,33 @@ proc find_all[T: Unit](worker: Worker, _: type T): seq[T] =
253255
var units: seq[T]
254256
state.units.value.walk_tree proc(unit: Unit) =
255257
if unit of T:
256-
worker.ensure_unit(unit)
258+
unit.ensure_exists(worker)
257259
units.add T(unit)
258260
units
259261

260-
proc all_players(ctx: ScriptCtx, worker: Worker): Player =
261-
Player.query("all-players", ctx):
262-
worker.find_all(Player)
262+
proc all_players(worker: Worker): seq[Player] =
263+
worker.find_all(Player)
263264

264-
proc all_bots(ctx: ScriptCtx, worker: Worker): Bot =
265-
Bot.query("all-bots", ctx):
266-
worker.find_all(Bot)
265+
proc all_bots(worker: Worker): seq[Bot] =
266+
worker.find_all(Bot)
267267

268-
proc all_builds(ctx: ScriptCtx, worker: Worker): Build =
269-
Build.query("all-builds", ctx):
270-
worker.find_all(Build)
268+
proc all_builds(worker: Worker): seq[Build] =
269+
worker.find_all(Build)
271270

272-
proc all_signs(ctx: ScriptCtx, worker: Worker): Sign =
273-
Sign.query("all-builds", ctx):
274-
worker.find_all(Sign)
271+
proc all_signs(worker: Worker): seq[Sign] =
272+
worker.find_all(Sign)
275273

276-
proc all_units(ctx: ScriptCtx, worker: Worker): Unit =
277-
Unit.query("all-builds", ctx):
278-
worker.find_all(Unit)
274+
proc all_units(worker: Worker): seq[Unit] =
275+
worker.find_all(Unit)
279276

280-
proc added*(_: type Player, ctx: ScriptCtx, worker: Worker): Player =
281-
Player.query("players-added", ctx):
282-
collect:
283-
for player in worker.find_all(Player):
284-
if player.frame_created == state.frame_count:
285-
player
277+
proc added_units(worker: Worker): seq[Unit] =
278+
collect:
279+
for unit in worker.find_all(Unit):
280+
if unit.frame_created == state.frame_count:
281+
unit
286282

287283
proc echo_console(msg: string) =
284+
echo(msg)
288285
logger("info", msg & "\n")
289286
state.push_flag ConsoleVisible
290287

@@ -461,24 +458,8 @@ proc reset(self: Unit, clear: bool) =
461458
proc play(self: Bot, animation_name: string) =
462459
self.animation = animation_name
463460

464-
proc all_units(T: type Unit, self: Worker): PNode =
465-
var node = ast.new_node(nkBracketExpr)
466-
state.units.value.walk_tree proc(unit: Unit) =
467-
if unit of T:
468-
# objects without scripts won't show up in the node map. Create
469-
# a new dummy object
470-
self.ensure_unit(unit)
471-
node.add self.to_node(unit)
472-
result = node
473-
474-
proc all_bots(self: Worker): PNode =
475-
Bot.all_units(self)
476-
477461
# Build bindings
478462

479-
proc all_builds(self: Worker): PNode =
480-
Build.all_units(self)
481-
482463
proc drawing(self: Build): bool =
483464
self.drawing
484465

@@ -635,7 +616,7 @@ proc `open=`(self: Sign, value: bool) =
635616
proc coding(self: Worker, unit: Unit): Unit =
636617
if unit == state.player:
637618
if ?state.open_unit:
638-
self.ensure_unit(state.open_unit)
619+
state.open_unit.ensure_exists(self)
639620
result = state.open_unit
640621

641622
proc `coding=`(self: Unit, value: Unit) =
@@ -650,25 +631,25 @@ proc bridge_to_vm*(worker: Worker) =
650631
result.bridged_from_vm "vm_bridge_utils", get_last_error
651632

652633
result.bridged_from_vm "base_bridge",
653-
register_active, echo_console, new_instance, exec_instance, hit, exit,
654-
global, `global=`, position, local_position, rotation, `rotation=`, id,
655-
glow, `glow=`, speed, `speed=`, scale, `scale=`, velocity, `velocity=`,
656-
active_unit, color, `color=`, sees, start_position, wake, frame_count,
657-
write_stack_trace, show, `show=`, frame_created, lock, `lock=`, reset,
658-
press_action, load_level, level_name, world_name, reset_level,
659-
current_collider, added, all_players, all_builds, all_bots, all_signs,
660-
all_units, loop_finished
634+
register_active, register_template_node, echo_console, new_instance,
635+
exec_instance, hit, exit, global, `global=`, position, local_position,
636+
rotation, `rotation=`, id, glow, `glow=`, speed, `speed=`, scale, `scale=`,
637+
velocity, `velocity=`, active_unit, color, `color=`, sees, start_position,
638+
wake, frame_count, write_stack_trace, show, `show=`, frame_created, lock,
639+
`lock=`, reset, press_action, load_level, level_name, world_name,
640+
reset_level, current_colliders, added_units, all_players, all_builds,
641+
all_bots, all_signs, all_units
661642

662643
result.bridged_from_vm "base_bridge_private",
663644
link_dependency, action_running, `action_running=`, yield_script,
664645
begin_turn, begin_move, sleep_impl, position_set, new_markdown_sign,
665646
update_markdown_sign
666647

667-
result.bridged_from_vm "bots", play, all_bots
648+
result.bridged_from_vm "bots", play
668649

669650
result.bridged_from_vm "builds",
670-
drawing, `drawing=`, initial_position, save, restore, all_builds,
671-
draw_position, draw_position_set
651+
drawing, `drawing=`, initial_position, save, restore, draw_position,
652+
draw_position_set
672653

673654
result.bridged_from_vm "signs",
674655
message, `message=`, more, `more=`, height, `height=`, width, `width=`,

src/controllers/script_controllers/host_bridge_utils.nim

+12-11
Original file line numberDiff line numberDiff line change
@@ -111,17 +111,18 @@ macro bridged_from_vm(
111111
new_call(bind_sym(getter), ident"a", new_lit(pos))
112112

113113
var call = new_call(proc_ref, args)
114-
if return_node.kind == nnk_sym:
115-
if return_node.str_val in unit_types:
116-
call = new_call(
117-
bind_sym"set_result",
118-
ident"a",
119-
new_call(bind_sym"to_node", ident"script_engine", call),
120-
)
121-
else:
122-
call = new_call(
123-
bind_sym"set_result", ident"a", new_call(bind_sym"to_result", call)
124-
)
114+
let return_type = return_node.repr
115+
if return_type in unit_types or
116+
return_type in unit_types.map_it(\"seq[{it}]"):
117+
call = new_call(
118+
bind_sym"set_result",
119+
ident"a",
120+
new_call(bind_sym"to_node", ident"script_engine", call),
121+
)
122+
elif return_node.kind == nnk_sym:
123+
call = new_call(
124+
bind_sym"set_result", ident"a", new_call(bind_sym"to_result", call)
125+
)
125126
elif return_node.kind == nnk_bracket_expr and return_node.len == 2 and
126127
return_node[0].str_val == "Future":
127128
call = new_call(bind_sym"await_future", call, ident"a")

src/controllers/script_controllers/scripting.nim

+18-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import std/[os, re]
1+
import std/[os, re, posix]
22

33
import pkg/godot except print
44
import pkg/compiler/ast except new_node
55
import pkg/compiler/[lineinfos, renderer, msgs, vmdef]
6+
from pkg/compiler/vm {.all.} import stack_trace_aux
67
import godotapi/[spatial, ray_cast, voxel_terrain]
78
import core, models/[states, bots, builds, units, signs, players]
89
import libs/[interpreters, eval]
@@ -61,9 +62,11 @@ proc init_interpreter*[T](self: Worker, _: T) {.gcsafe.} =
6162
) {.gcsafe.} =
6263
var info = info
6364
var msg = msg
65+
6466
let ctx = controller.active_unit.script_ctx
6567
let errors = controller.active_unit.errors
6668
if severity == Severity.Error and config.error_counter >= config.error_max:
69+
echo msg
6770
var file_name =
6871
if info.file_index.int >= 0:
6972
config.m.file_infos[info.file_index.int].full_path.string
@@ -72,7 +75,15 @@ proc init_interpreter*[T](self: Worker, _: T) {.gcsafe.} =
7275

7376
if file_exists(file_name) and ?ctx.file_name:
7477
if file_name.get_file_info != ctx.file_name.get_file_info:
75-
(file_name, info) = extract_file_info msg
78+
msg_writeln(
79+
config, "stack trace: (most recent call last)", {msg_no_unit_sep}
80+
)
81+
stack_trace_aux(ctx.ctx, ctx.tos, ctx.pc)
82+
let file_info = extract_file_info msg
83+
84+
if ?file_info:
85+
(file_name, info) = file_info
86+
# discard `raise` SIGINT
7687
# msg = msg.replace(re"unhandled exception:.*\) Error\: ", "")
7788
# else:
7889
# msg = msg.replace(re"(?ms);.*", "")
@@ -93,6 +104,11 @@ proc init_interpreter*[T](self: Worker, _: T) {.gcsafe.} =
93104
assert ?controller.active_unit.script_ctx
94105

95106
let ctx = controller.active_unit.script_ctx
107+
108+
ctx.ctx = c
109+
ctx.pc = pc
110+
ctx.tos = tos
111+
96112
let info = c.debug[pc]
97113
inc count
98114
if count == 255:
@@ -123,15 +139,11 @@ proc init_interpreter*[T](self: Worker, _: T) {.gcsafe.} =
123139
(ctx.previous_line, ctx.current_line) = (ctx.current_line, info)
124140

125141
if ctx.pause_requested:
126-
ctx.ctx = c
127-
ctx.pc = pc
128-
ctx.tos = tos
129142
ctx.pause_requested = false
130143
raise VMPause.new_exception("vm paused")
131144

132145
proc load_script*(self: Worker, unit: Unit, timeout = script_timeout) =
133146
let ctx = unit.script_ctx
134-
ctx.query_results.clear
135147
try:
136148
self.active_unit = unit
137149
unit.errors.clear

src/core.nim

+11-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ export types
33

44
import pkg/model_citizen/utils
55
import
6-
std/[sequtils, strutils, sugar, macros, asyncfutures, importutils, typetraits]
6+
std/[
7+
sequtils, strutils, sugar, macros, asyncfutures, importutils, typetraits,
8+
posix,
9+
]
710
export utils, sequtils, strutils, sugar, importutils
811

912
### Globals ###
@@ -196,6 +199,10 @@ when not defined(no_godot):
196199

197200
# misc
198201

202+
template breakpoint*() =
203+
{.line.}:
204+
discard `raise` SIGINT
205+
199206
proc resolve_level_name*(world, level: string, diff: int): string =
200207
var level = level
201208
let prefix = world & "-"
@@ -353,6 +360,9 @@ template `?`*[T](self: seq[T]): bool =
353360
template `?`*(self: Table): bool =
354361
self.len > 0
355362

363+
template `?`*(self: tuple): bool =
364+
self != self.type.default
365+
356366
proc first_key*[K, V](self: Table[K, V]): K =
357367
for key in self.keys:
358368
return key

src/libs/interpreters.nim

+3-4
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ export Interpreter, VmArgs, set_result
88
log_scope:
99
topics = "scripting"
1010

11-
const STDLIB_PATHS = [
12-
".", "core", "pure", "pure/collections", "pure/concurrency", "std", "fusion"
13-
]
11+
const STDLIB_PATHS =
12+
[".", "core", "pure", "pure/collections", "pure/concurrency", "std", "fusion"]
1413

1514
private_access ScriptCtx
1615

@@ -47,7 +46,7 @@ proc run*(self: ScriptCtx): bool =
4746
except VMPause:
4847
private_access ScriptCtx
4948
result = self.exit_code.is_none
50-
except CatchableError as e:
49+
except Exception as e:
5150
self.running = false
5251
self.exit_code = some(99)
5352
raise VMQuit.new_exception("Unhandled err", e)

src/types.nim

+1-1
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,6 @@ type
281281
pass_context*: PContext
282282
last_ran*: MonoTime
283283
file_index*: int
284-
query_results*: Table[string, seq[Unit]]
285284

286285
VMError* = object of CatchableError
287286
QuitKind* = enum
@@ -307,6 +306,7 @@ type
307306
active_unit*: Unit
308307
unit_map*: Table[PNode, Unit]
309308
node_map*: Table[Unit, PNode]
309+
template_node_map*: Table[string, PNode]
310310
failed*: seq[tuple[unit: Unit, e: ref VMQuit]]
311311
last_exception*: ref Exception
312312
player_cache*: Table[string, Player]

0 commit comments

Comments
 (0)