Skip to content

Commit 83f87ad

Browse files
committed
Unpack collections inside command loops
1 parent 8ec4013 commit 83f87ad

14 files changed

+152
-89
lines changed

src/controllers/script_controllers/host_bridge.nim

+72-11
Original file line numberDiff line numberDiff line change
@@ -154,21 +154,35 @@ proc reset_level(self: Worker) =
154154
state.config_value.value:
155155
level_dir = current_level
156156

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+
157170
proc ensure_unit(self: Worker, unit: Unit) =
158171
if unit notin self.node_map:
159172
var node = self.node_map[self.active_unit].copy_tree
160173
self.map_unit(unit, node)
161174

162-
proc current_collider(self: Unit, kind: string): Unit =
163-
var collider: Unit
164-
state.units.value.walk_tree proc(unit: Unit) =
165-
if self.collisions.value.any_it(it.id == unit.id):
166-
if kind == "Unit" or kind == "Player" and unit of Player or
167-
kind == "Bot" and unit of Bot or kind == "Build" and unit of Build or
168-
kind == "Sign" and unit of Sign:
169-
collider = unit
170-
return
171-
result = collider
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
172186

173187
proc world_name(): string =
174188
state.config.world
@@ -219,11 +233,57 @@ proc sleep_impl(self: Worker, ctx: ScriptCtx, seconds: float) =
219233
ctx.last_ran = MonoTime.default
220234
self.pause_script()
221235

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+
222247
proc hit(unit_a: Unit, unit_b: Unit): Vector3 =
223248
for collision in unit_a.collisions:
224249
if collision.id == unit_b.id:
225250
return collision.normal.snapped(vec3(1, 1, 1))
226251

252+
proc find_all[T: Unit](worker: Worker, _: type T): seq[T] =
253+
var units: seq[T]
254+
state.units.value.walk_tree proc(unit: Unit) =
255+
if unit of T:
256+
worker.ensure_unit(unit)
257+
units.add T(unit)
258+
units
259+
260+
proc all_players(ctx: ScriptCtx, worker: Worker): Player =
261+
Player.query("all-players", ctx):
262+
worker.find_all(Player)
263+
264+
proc all_bots(ctx: ScriptCtx, worker: Worker): Bot =
265+
Bot.query("all-bots", ctx):
266+
worker.find_all(Bot)
267+
268+
proc all_builds(ctx: ScriptCtx, worker: Worker): Build =
269+
Build.query("all-builds", ctx):
270+
worker.find_all(Build)
271+
272+
proc all_signs(ctx: ScriptCtx, worker: Worker): Sign =
273+
Sign.query("all-builds", ctx):
274+
worker.find_all(Sign)
275+
276+
proc all_units(ctx: ScriptCtx, worker: Worker): Unit =
277+
Unit.query("all-builds", ctx):
278+
worker.find_all(Unit)
279+
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
286+
227287
proc echo_console(msg: string) =
228288
logger("info", msg & "\n")
229289
state.push_flag ConsoleVisible
@@ -596,7 +656,8 @@ proc bridge_to_vm*(worker: Worker) =
596656
active_unit, color, `color=`, sees, start_position, wake, frame_count,
597657
write_stack_trace, show, `show=`, frame_created, lock, `lock=`, reset,
598658
press_action, load_level, level_name, world_name, reset_level,
599-
current_collider
659+
current_collider, added, all_players, all_builds, all_bots, all_signs,
660+
all_units, loop_finished
600661

601662
result.bridged_from_vm "base_bridge_private",
602663
link_dependency, action_running, `action_running=`, yield_script,

src/controllers/script_controllers/host_bridge_utils.nim

+9-5
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ proc await_future[T](future: Future[T], a: VmArgs) =
6464
future.add_callback proc(future: Future[T]) =
6565
set_result(a, to_result(future.read))
6666

67+
const unit_types = ["Unit", "Bot", "Build", "Sign", "Player"]
68+
6769
macro bridged_from_vm(
6870
self: Worker, module_name: string, proc_refs: varargs[untyped]
6971
): untyped =
@@ -76,8 +78,7 @@ macro bridged_from_vm(
7678
let
7779
symbol = bind_sym($proc_ref)
7880
proc_impl = (if symbol.kind == nnkSym: symbol
79-
else: symbol[0]
80-
).get_impl
81+
else: symbol[0]).get_impl
8182
proc_name = proc_impl[0].str_val
8283
proc_impl_name = proc_name.replace("=", "_set") & "_impl"
8384
return_node = proc_impl[3][0]
@@ -87,28 +88,31 @@ macro bridged_from_vm(
8788
block:
8889
var pos = -1
8990
for ident_def in arg_nodes:
90-
let typ = ident_def[1].str_val
91+
let typ = ident_def[1].repr
9192
if typ == $Worker.type:
9293
ident"script_engine"
9394
elif typ == "VmArgs":
9495
ident"a"
9596
elif typ == "ScriptCtx":
9697
quote:
9798
script_engine.active_unit.script_ctx
98-
elif typ in ["Unit", "Bot", "Build", "Sign"]:
99+
elif typ in unit_types:
99100
let getter = "get_" & typ
100101
pos.inc
101102
new_call(
102103
bind_sym(getter), ident"script_engine", ident"a", new_lit(pos)
103104
)
105+
elif typ in unit_types.map_it(\"type {it}"):
106+
let type_name = typ.split(" ")[1]
107+
ident(type_name)
104108
else:
105109
let getter = "get_" & typ
106110
pos.inc
107111
new_call(bind_sym(getter), ident"a", new_lit(pos))
108112

109113
var call = new_call(proc_ref, args)
110114
if return_node.kind == nnk_sym:
111-
if return_node.str_val in ["Unit", "Bot", "Build", "Sign"]:
115+
if return_node.str_val in unit_types:
112116
call = new_call(
113117
bind_sym"set_result",
114118
ident"a",

src/controllers/script_controllers/scripting.nim

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ proc init_interpreter*[T](self: Worker, _: T) {.gcsafe.} =
131131

132132
proc load_script*(self: Worker, unit: Unit, timeout = script_timeout) =
133133
let ctx = unit.script_ctx
134+
ctx.query_results.clear
134135
try:
135136
self.active_unit = unit
136137
unit.errors.clear

src/core.nim

+10
Original file line numberDiff line numberDiff line change
@@ -346,3 +346,13 @@ const environments* = {
346346
template `?=`*[T](a: var T, b: T) =
347347
if not ?a:
348348
a = b
349+
350+
template `?`*[T](self: seq[T]): bool =
351+
self.len > 0
352+
353+
template `?`*(self: Table): bool =
354+
self.len > 0
355+
356+
proc first_key*[K, V](self: Table[K, V]): K =
357+
for key in self.keys:
358+
return key

src/models/players.nim

+8-3
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@ import godotapi/spatial
33
import core, models/units
44

55
proc init*(_: type Player): Player =
6-
result = Player(
6+
let self = Player(
77
id: \"player-{Zen.thread_ctx.id}",
88
rotation_value: ~0.0,
99
start_transform: Transform.init(origin = vec3(0, 1, 0)),
1010
input_direction_value: ~Vector3,
1111
cursor_position_value: ~((0, 0)),
1212
)
13-
result.init_unit(shared = false)
14-
result.global_flags += Global
13+
self.init_unit(shared = false)
14+
self.global_flags += Global
15+
16+
state.local_flags.changes:
17+
if ResettingVM.added:
18+
self.frame_created = state.frame_count
19+
result = self
1520

1621
method on_begin_turn*(
1722
self: Player, direction: Vector3, degrees: float, lean: bool, move_mode: int

src/types.nim

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

285286
VMError* = object of CatchableError
286287
QuitKind* = enum
@@ -303,12 +304,12 @@ type
303304
retry_failures*: bool
304305
interpreter*: Interpreter
305306
module_names*: HashSet[string]
306-
watch_active*: bool
307307
active_unit*: Unit
308308
unit_map*: Table[PNode, Unit]
309309
node_map*: Table[Unit, PNode]
310310
failed*: seq[tuple[unit: Unit, e: ref VMQuit]]
311311
last_exception*: ref Exception
312+
player_cache*: Table[string, Player]
312313

313314
NodeController* = ref object
314315

vmlib/enu/base_api.nim

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ proc `position=`*(self: Unit, position: Vector3) =
1717
proc `position=`*(self: Unit, unit: Unit) =
1818
self.position_set(unit.position)
1919

20+
proc go*(self: Unit, position: Unit | Vector3) =
21+
self.position = position
22+
2023
proc link_dependency*(dep: Unit) =
2124
if not dep.is_nil:
2225
link_dependency_impl(dep)

vmlib/enu/base_bridge.nim

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ bridged_to_host:
5050
proc level_name*(): string
5151
proc world_name*(): string
5252
proc current_collider*(self: Unit, name: string): Unit
53+
proc added*[T: Unit](kind: type T): T
5354

5455
# TODO: These should be in base_bridge_private, but are currently needed outside of base_api.
5556
proc echo_console*(msg: string)
@@ -59,3 +60,4 @@ bridged_to_host:
5960
proc wake*(self: Unit)
6061
proc create_new*(self: Unit)
6162
proc frame_count*(): int
63+
proc loop_finished*()

vmlib/enu/base_bridge_private.nim

+1-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ bridged_to_host:
77
proc action_running*(self: Unit): bool
88
proc `action_running=`*(self: Unit, value: bool)
99
proc yield_script*(self: Unit)
10-
proc begin_move*(
11-
self: Unit, direction: Vector3, steps: float, move_mode: int
12-
)
10+
proc begin_move*(self: Unit, direction: Vector3, steps: float, move_mode: int)
1311

1412
proc begin_turn*(
1513
self: Unit, axis: Vector3, steps: float, lean: bool, move_mode: int

vmlib/enu/bots.nim

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import std/[strutils, math]
22
import types, base_api, vm_bridge_utils
33

44
bridged_to_host:
5-
proc all_bots(): seq[Bot]
5+
proc all_bots(): Bot
66
proc play*(self: Bot, animation_name: string)
77

8-
proc all*(_: type Bot): seq[Bot] =
8+
proc all*(_: type Bot): Bot =
99
all_bots()
1010

1111
proc walk*(self: Bot) =

vmlib/enu/builds.nim

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ bridged_to_host:
55
proc drawing*(self: Build): bool
66
proc `drawing=`*(self: Build, drawing: bool)
77
proc initial_position(self: Build): Vector3
8-
proc all_builds(): seq[Build]
98
proc save*(self: Build, name = "default")
109
proc restore*(self: Build, name = "default")
1110
proc draw_position*(self: Build): Vector3
1211
proc `draw_position=`*(self: Build, value: Vector3)
12+
proc all_builds(): Build
13+
14+
proc all*(_: type Build): Build =
15+
all_builds()
1316

1417
proc `draw_position=`*(self: Build, unit: Unit) =
1518
self.draw_position = unit.position
1619

17-
proc all*(_: type Build): seq[Build] =
18-
all_builds()
19-
2020
proc go_home*(self: Build) =
2121
self.rotation = 0
2222
self.scale = 1

vmlib/enu/players.nim

+18-17
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import types, base_api, vm_bridge_utils
22

3-
let player* = PlayerType()
4-
register_active(player)
5-
63
bridged_to_host:
7-
proc tool*(self: PlayerType): Tools
8-
proc `tool=`*(self: PlayerType, value: Tools)
9-
proc playing*(self: PlayerType): bool
10-
proc `playing=`*(self: PlayerType, value: bool)
11-
proc flying*(self: PlayerType): bool
12-
proc `flying=`*(self: PlayerType, value: bool)
13-
proc running*(self: PlayerType): bool
14-
proc `running=`*(self: PlayerType, value: bool)
15-
proc god*(self: PlayerType): bool
16-
proc `god=`*(self: PlayerType, value: bool)
17-
proc coding*(self: PlayerType): Unit
18-
proc `coding=`*(self: PlayerType, value: Unit)
19-
proc open_sign*(self: PlayerType): Sign
20-
proc `open_sign=`*(self: PlayerType, value: Sign)
4+
proc tool*(self: Player): Tools
5+
proc `tool=`*(self: Player, value: Tools)
6+
proc playing*(self: Player): bool
7+
proc `playing=`*(self: Player, value: bool)
8+
proc flying*(self: Player): bool
9+
proc `flying=`*(self: Player, value: bool)
10+
proc running*(self: Player): bool
11+
proc `running=`*(self: Player, value: bool)
12+
proc god*(self: Player): bool
13+
proc `god=`*(self: Player, value: bool)
14+
proc coding*(self: Player): Unit
15+
proc `coding=`*(self: Player, value: Unit)
16+
proc open_sign*(self: Player): Sign
17+
proc `open_sign=`*(self: Player, value: Sign)
18+
proc all_players(): Player
19+
20+
proc all*(_: type Player): Player =
21+
all_players()

0 commit comments

Comments
 (0)