Files
claude c4beeae38f 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
2026-09-03 16:03:57 +02:00

130 lines
4.3 KiB
GDScript

class_name GutConstants
const TYPE_STRINGS = {
TYPE_NIL : 'TYPE_NIL',
TYPE_BOOL : 'TYPE_BOOL',
TYPE_INT : 'TYPE_INT',
TYPE_FLOAT : 'TYPE_FLOAT',
TYPE_STRING : 'TYPE_STRING',
TYPE_VECTOR2 : 'TYPE_VECTOR2',
TYPE_VECTOR2I : 'TYPE_VECTOR2I',
TYPE_RECT2 : 'TYPE_RECT2',
TYPE_RECT2I : 'TYPE_RECT2I',
TYPE_VECTOR3 : 'TYPE_VECTOR3',
TYPE_VECTOR3I : 'TYPE_VECTOR3I',
TYPE_TRANSFORM2D : 'TYPE_TRANSFORM2D',
TYPE_VECTOR4 : 'TYPE_VECTOR4',
TYPE_VECTOR4I : 'TYPE_VECTOR4I',
TYPE_PLANE : 'TYPE_PLANE',
TYPE_QUATERNION : 'TYPE_QUATERNION',
TYPE_AABB : 'TYPE_AABB',
TYPE_BASIS : 'TYPE_BASIS',
TYPE_TRANSFORM3D : 'TYPE_TRANSFORM3D',
TYPE_PROJECTION : 'TYPE_PROJECTION',
TYPE_COLOR : 'TYPE_COLOR',
TYPE_STRING_NAME : 'TYPE_STRING_NAME',
TYPE_NODE_PATH : 'TYPE_NODE_PATH',
TYPE_RID : 'TYPE_RID',
TYPE_OBJECT : 'TYPE_OBJECT',
TYPE_CALLABLE : 'TYPE_CALLABLE',
TYPE_SIGNAL : 'TYPE_SIGNAL',
TYPE_DICTIONARY : 'TYPE_DICTIONARY',
TYPE_ARRAY : 'TYPE_ARRAY',
TYPE_PACKED_BYTE_ARRAY : 'TYPE_PACKED_BYTE_ARRAY',
TYPE_PACKED_INT32_ARRAY : 'TYPE_PACKED_INT32_ARRAY',
TYPE_PACKED_INT64_ARRAY : 'TYPE_PACKED_INT64_ARRAY',
TYPE_PACKED_FLOAT32_ARRAY : 'TYPE_PACKED_FLOAT32_ARRAY',
TYPE_PACKED_FLOAT64_ARRAY : 'TYPE_PACKED_FLOAT64_ARRAY',
TYPE_PACKED_STRING_ARRAY : 'TYPE_PACKED_STRING_ARRAY',
TYPE_PACKED_VECTOR2_ARRAY : 'TYPE_PACKED_VECTOR2_ARRAY',
TYPE_PACKED_VECTOR3_ARRAY : 'TYPE_PACKED_VECTOR3_ARRAY',
TYPE_PACKED_COLOR_ARRAY : 'TYPE_PACKED_COLOR_ARRAY',
TYPE_PACKED_VECTOR4_ARRAY : 'TYPE_PACKED_VECTOR4_ARRAY',
TYPE_MAX : 'TYPE_MAX',
}
# Values should not be referenced outside of this script.
# Use get_default_return_value. The functions look weird, but they are here
# so that each call to a doubled method returns a unique instance of things for
# anything that would be passed by reference.
static var _default_returns = {
TYPE_NIL : null,
TYPE_BOOL : false,
TYPE_INT : 0,
TYPE_FLOAT : 0.0,
TYPE_STRING : '',
TYPE_VECTOR2 : Vector2.ZERO,
TYPE_VECTOR2I : Vector2i.ZERO,
TYPE_RECT2 : func(): return Rect2(0, 0, 0, 0),
TYPE_RECT2I : func(): return Rect2i(0, 0, 0, 0),
TYPE_VECTOR3 : Vector3.ZERO,
TYPE_VECTOR3I : Vector3i.ZERO,
TYPE_TRANSFORM2D : Transform2D.IDENTITY,
TYPE_VECTOR4 : Vector4.ZERO,
TYPE_VECTOR4I : Vector4i.ZERO,
TYPE_PLANE : Plane.PLANE_XY,
TYPE_QUATERNION : Quaternion.IDENTITY,
TYPE_AABB : func(): return AABB(),
TYPE_BASIS : Basis.IDENTITY,
TYPE_TRANSFORM3D : Transform3D.IDENTITY,
TYPE_PROJECTION : Projection.IDENTITY,
TYPE_COLOR : Color.WHITE,
TYPE_STRING_NAME : &'',
TYPE_NODE_PATH : func(): return NodePath(),
TYPE_RID : func(): return RID(),
TYPE_OBJECT : null,
TYPE_CALLABLE : func(): return Callable(),
TYPE_SIGNAL : null,
TYPE_DICTIONARY : func(): return {},
TYPE_ARRAY : func(): return [],
TYPE_PACKED_BYTE_ARRAY : func(): return PackedByteArray(),
TYPE_PACKED_INT32_ARRAY : func(): return PackedInt32Array(),
TYPE_PACKED_INT64_ARRAY : func(): return PackedInt64Array(),
TYPE_PACKED_FLOAT32_ARRAY : func(): return PackedFloat32Array(),
TYPE_PACKED_FLOAT64_ARRAY : func(): return PackedFloat64Array(),
TYPE_PACKED_STRING_ARRAY : func(): return PackedStringArray(),
TYPE_PACKED_VECTOR2_ARRAY : func(): return PackedVector2Array(),
TYPE_PACKED_VECTOR3_ARRAY : func(): return PackedVector3Array(),
TYPE_PACKED_COLOR_ARRAY : func(): return PackedColorArray(),
TYPE_PACKED_VECTOR4_ARRAY : func(): return PackedVector4Array(),
# TYPE_MAX : 'TYPE_MAX',
}
# Seeded with any type constant where the constant name can't be converted to
# a string using pascal case and/or the values need manual conversion. The
# rest are added in _static_init.
static var TYPE_KEYWORDS = {
TYPE_NIL : 'null',
TYPE_BOOL : 'bool',
TYPE_INT : 'int',
TYPE_FLOAT : 'float',
}
static var NOT_SET := &"___NOT__SET___"
static func _static_init() -> void:
for key in TYPE_STRINGS:
if(!TYPE_KEYWORDS.has(key)):
var n : String = TYPE_STRINGS[key].to_lower()
n = n.lstrip("type_")
TYPE_KEYWORDS[key] = n.to_pascal_case()
static func is_not_set(val):
return typeof(val) == TYPE_STRING_NAME and val == NOT_SET
static func get_default_return_value(type=null):
if(type == null or typeof(type) != TYPE_INT):
return null
var to_return = null
if(is_not_set(type)):
to_return = null
elif(_default_returns.has(type)):
to_return = _default_returns[type]
if(to_return is Callable):
to_return = to_return.call()
return to_return