651c4ad94a
ci / verify (push) Successful in 1m57s
Top-down twin-stick bullet-hell, Godot 4.7, server-authoritative dedicated server with client-side prediction. Clients send input only; the server resolves every hit for both players and enemies (no PvP). - SimWorld: whole simulation as plain RefCounted objects (no nodes, no physics server), ~0.24ms/tick at peak load -- runs headless for free and drives 78 tests in under a second - BulletPool: struct-of-arrays bullet storage, replicated as spawn/despawn events rather than per-tick state - Emitter framework (Ring/AimedSpread/WallGap/ArcSweep) shared by trash enemies and bosses -- a new boss is data in src/content/content.gd, no simulation changes - The Warden of the Fold: stationary 4-phase boss built entirely on that format - Lobby hub with a portal into on-demand dungeon instances; one process hosts the hub plus every concurrent dungeon - Emergency escape: 3s server-owned channel, cancelled by damage - tools/check.sh, test.sh (GUT), smoke.sh (real server + bot clients over ENet), bench.gd; git hooks wired to the same scripts - docs/ARCHITECTURE.md, NETCODE.md, WORKFLOW.md, ROADMAP.md
37 lines
1.3 KiB
GDScript
37 lines
1.3 KiB
GDScript
extends SceneTree
|
|
## Writes .tres copies of everything in [Content] into res://resources/, so the
|
|
## numbers can be tuned in the editor inspector.
|
|
##
|
|
## godot --headless --path . --script tools/export_content.gd
|
|
##
|
|
## These files are an export, not the source of truth: [Content] is. Re-running
|
|
## this overwrites them. If you tune a value in the inspector and want to keep
|
|
## it, port it back into src/content/content.gd -- otherwise the next export
|
|
## silently reverts your change.
|
|
|
|
const OUT_ENEMIES := "res://resources/enemies"
|
|
const OUT_BOSSES := "res://resources/bosses"
|
|
|
|
|
|
func _init() -> void:
|
|
DirAccess.make_dir_recursive_absolute(OUT_ENEMIES)
|
|
DirAccess.make_dir_recursive_absolute(OUT_BOSSES)
|
|
var written := 0
|
|
for id in [Content.ENEMY_DRIFTER, Content.ENEMY_TURRET, Content.ENEMY_STALKER,
|
|
Content.ENEMY_DUMMY]:
|
|
written += _save(Content.enemy(id), "%s/%s.tres" % [OUT_ENEMIES, id])
|
|
for id in [Content.BOSS_WARDEN]:
|
|
written += _save(Content.boss(id), "%s/%s.tres" % [OUT_BOSSES, id])
|
|
print("exported %d resources" % written)
|
|
quit(0)
|
|
|
|
|
|
func _save(res: Resource, path: String) -> int:
|
|
# Sub-resources (the emitters) are inlined so one file is one whole enemy.
|
|
var err := ResourceSaver.save(res, path)
|
|
if err != OK:
|
|
printerr("failed to write %s (error %d)" % [path, err])
|
|
return 0
|
|
print(" ", path)
|
|
return 1
|