75 lines
2.1 KiB
GDScript
75 lines
2.1 KiB
GDScript
## SpellDeck — 运行时执行游标
|
||
## 权威来源:implementation_plan.md §2.2
|
||
extends RefCounted
|
||
class_name SpellDeck
|
||
|
||
var _nodes: Array = [] # Array[SpellNode]
|
||
var _cursor: int = 0
|
||
var _consumed: PackedByteArray = PackedByteArray() # 消费掩码(共鸣 consume_inputs,P6-N29);1=跳过
|
||
|
||
func setup(nodes: Array, consumed_indices: Array = []) -> void:
|
||
_nodes = nodes
|
||
_cursor = 0
|
||
_consumed = PackedByteArray()
|
||
_consumed.resize(_nodes.size()) # 全 0
|
||
for idx in consumed_indices:
|
||
if idx >= 0 and idx < _consumed.size():
|
||
_consumed[idx] = int(1)
|
||
|
||
func has_next() -> bool:
|
||
var c: int = _cursor
|
||
while c < _nodes.size() and c < _consumed.size() and _consumed[c] != 0:
|
||
c += 1
|
||
return c < _nodes.size()
|
||
|
||
func pop() -> SpellNode:
|
||
while _cursor < _nodes.size() and _cursor < _consumed.size() and _consumed[_cursor] != 0:
|
||
_cursor += 1 # 跳过被共鸣消费的槽位
|
||
if _cursor >= _nodes.size():
|
||
return null
|
||
var node: SpellNode = _nodes[_cursor]
|
||
_cursor += 1
|
||
return node
|
||
|
||
func peek() -> SpellNode:
|
||
if _cursor >= _nodes.size():
|
||
return null
|
||
return _nodes[_cursor]
|
||
|
||
func reset_cursor() -> void:
|
||
_cursor = 0
|
||
|
||
## 跳过直到遇到 SCOPE_CLOSE(深度计数器处理嵌套)
|
||
func skip_until_scope_end() -> void:
|
||
var depth := 1
|
||
while _cursor < _nodes.size():
|
||
var n: SpellNode = _nodes[_cursor]
|
||
_cursor += 1
|
||
if n.type == SpellNode.SpellType.SCOPE_CLOSE:
|
||
depth -= 1
|
||
if depth <= 0:
|
||
return
|
||
elif n.type == SpellNode.SpellType.TRIGGER or n.type == SpellNode.SpellType.LOGIC:
|
||
depth += 1
|
||
|
||
## 将游标到下一个 SCOPE_CLOSE 之间的节点列表取出(用于打包 SubPayload)
|
||
func consume_until_scope_end() -> Array:
|
||
var result: Array = []
|
||
var depth := 1
|
||
while _cursor < _nodes.size():
|
||
var n: SpellNode = _nodes[_cursor]
|
||
_cursor += 1
|
||
if n.type == SpellNode.SpellType.SCOPE_CLOSE:
|
||
depth -= 1
|
||
if depth <= 0:
|
||
break
|
||
result.append(n)
|
||
else:
|
||
if n.type == SpellNode.SpellType.TRIGGER or n.type == SpellNode.SpellType.LOGIC:
|
||
depth += 1
|
||
result.append(n)
|
||
return result
|
||
|
||
func get_remaining_count() -> int:
|
||
return _nodes.size() - _cursor
|