Initial commit: Transcience MVP

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
This commit is contained in:
2026-09-03 16:03:57 +02:00
commit c4beeae38f
385 changed files with 28725 additions and 0 deletions
+121
View File
@@ -0,0 +1,121 @@
[gd_scene load_steps=5 format=3 uid="uid://bqmo4dj64c7yl"]
[ext_resource type="Script" uid="uid://cax5phqs8acmu" path="res://addons/gut/gui/OutputText.gd" id="1"]
[ext_resource type="Texture2D" uid="uid://bvo0uao7deu0q" path="res://addons/gut/icon.png" id="2_b4xqv"]
[sub_resource type="DPITexture" id="DPITexture_lygvu"]
_source = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\"><path fill=\"#ff5d5d\" d=\"M2 1v8.586l1.293-1.293a1 1 0 0 1 1.414 0L7 10.587l2.293-2.293a1 1 0 0 1 1.414 0L13 10.586l1-1V6H9V1H2zm8 0v4h4zm-6 9.414-2 2V15h12v-2.586l-.293.293a1 1 0 0 1-1.414 0L10 10.414l-2.293 2.293a1 1 0 0 1-1.414 0L4 10.414z\"/></svg>
"
[sub_resource type="CodeHighlighter" id="CodeHighlighter_8ynmy"]
number_color = Color(1, 1, 1, 1)
symbol_color = Color(1, 1, 1, 1)
function_color = Color(1, 1, 1, 1)
member_variable_color = Color(1, 1, 1, 1)
keyword_colors = {
"ERROR": Color(1, 0, 0, 1),
"ExpectedError": Color(0.6784314, 0.84705883, 0.9019608, 1),
"Failed": Color(1, 0, 0, 1),
"Orphans": Color(1, 1, 0, 1),
"Passed": Color(0, 1, 0, 1),
"Pending": Color(1, 1, 0, 1),
"Risky": Color(1, 1, 0, 1),
"WARNING": Color(1, 1, 0, 1)
}
[node name="OutputText" type="VBoxContainer"]
offset_right = 862.0
offset_bottom = 523.0
size_flags_horizontal = 3
size_flags_vertical = 3
script = ExtResource("1")
[node name="Toolbar" type="HBoxContainer" parent="."]
layout_mode = 2
size_flags_horizontal = 3
[node name="ShowSearch" type="Button" parent="Toolbar"]
layout_mode = 2
tooltip_text = "Search"
toggle_mode = true
icon = ExtResource("2_b4xqv")
[node name="ShowSettings" type="Button" parent="Toolbar"]
layout_mode = 2
tooltip_text = "Settings"
toggle_mode = true
text = "..."
[node name="CenterContainer" type="CenterContainer" parent="Toolbar"]
layout_mode = 2
size_flags_horizontal = 3
[node name="LblPosition" type="Label" parent="Toolbar"]
layout_mode = 2
[node name="CopyButton" type="Button" parent="Toolbar"]
layout_mode = 2
text = " Copy "
[node name="ClearButton" type="Button" parent="Toolbar"]
layout_mode = 2
text = " Clear "
[node name="Settings" type="HBoxContainer" parent="."]
visible = false
layout_mode = 2
[node name="WordWrap" type="Button" parent="Settings"]
layout_mode = 2
tooltip_text = "Word Wrap"
toggle_mode = true
icon = SubResource("DPITexture_lygvu")
[node name="UseColors" type="Button" parent="Settings"]
layout_mode = 2
tooltip_text = "Colorized Text"
toggle_mode = true
button_pressed = true
icon = SubResource("DPITexture_lygvu")
[node name="Output" type="TextEdit" parent="."]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_font_sizes/font_size = 30
deselect_on_focus_loss_enabled = false
virtual_keyboard_enabled = false
middle_mouse_paste_enabled = false
scroll_smooth = true
syntax_highlighter = SubResource("CodeHighlighter_8ynmy")
highlight_all_occurrences = true
highlight_current_line = true
[node name="Search" type="HBoxContainer" parent="."]
visible = false
layout_mode = 2
[node name="SearchTerm" type="LineEdit" parent="Search"]
layout_mode = 2
size_flags_horizontal = 3
[node name="SearchNext" type="Button" parent="Search"]
layout_mode = 2
text = "Next"
[node name="SearchPrev" type="Button" parent="Search"]
layout_mode = 2
text = "Prev"
[connection signal="pressed" from="Toolbar/ShowSearch" to="." method="_on_ShowSearch_pressed"]
[connection signal="pressed" from="Toolbar/ShowSettings" to="." method="_on_settings_pressed"]
[connection signal="pressed" from="Toolbar/CopyButton" to="." method="_on_CopyButton_pressed"]
[connection signal="pressed" from="Toolbar/ClearButton" to="." method="_on_ClearButton_pressed"]
[connection signal="pressed" from="Settings/WordWrap" to="." method="_on_WordWrap_pressed"]
[connection signal="pressed" from="Settings/UseColors" to="." method="_on_UseColors_pressed"]
[connection signal="focus_entered" from="Search/SearchTerm" to="." method="_on_SearchTerm_focus_entered"]
[connection signal="gui_input" from="Search/SearchTerm" to="." method="_on_SearchTerm_gui_input"]
[connection signal="text_changed" from="Search/SearchTerm" to="." method="_on_SearchTerm_text_changed"]
[connection signal="text_submitted" from="Search/SearchTerm" to="." method="_on_SearchTerm_text_entered"]
[connection signal="pressed" from="Search/SearchNext" to="." method="_on_SearchNext_pressed"]
[connection signal="pressed" from="Search/SearchPrev" to="." method="_on_SearchPrev_pressed"]