Files
przygody-pana-cegly/addons/limbo_console/command_history.gd
Gabriel Kaszewski d786ef4c22 Complete C# rewrite with working game in Editor (#6)
* Refactor collectable components to C# and update resource scripts for consistency

* Update resource paths and refactor properties for consistency

* Refactor UI components to inherit from Control and update node paths for consistency

* Update node paths and group assignments for consistency across scenes

* Refactor GameManager and PlayerDeathComponent for improved state management and logging; update scene connections for player death handling

* Add PhantomCamera components and UI elements for improved scene management; refactor existing components for better integration

* Refactor skill components and update resource paths for consistency; enhance skill management in scenes

* Add new UID files and update scene configurations for dialogue components; refactor skill management and input handling

* Add next level command and refactor player retrieval in GameManager; update scene files for consistency

* Add skill upgrade system and refactor skill components for enhanced functionality; update resource paths and configurations

* Enhance ChargeProgressBar and Marketplace functionality; add owner exit handling and update skill button states

* Refactor ChargeProgressBar and SkillManager; update skill handling and improve component interactions

* Refactor player and level configurations; streamline FlipPlayerComponent and reposition Spaceship Enter
2025-08-27 01:12:26 +02:00

166 lines
3.6 KiB
GDScript
Vendored

extends RefCounted
## Manages command history.
const HISTORY_FILE := "user://limbo_console_history.log"
var _entries: PackedStringArray
var _hist_idx = -1
var _iterators: Array[WrappingIterator]
var _is_dirty: bool = false
func push_entry(p_entry: String) -> void:
_push_entry(p_entry)
_reset_iterators()
func _push_entry(p_entry: String) -> void:
var idx: int = _entries.find(p_entry)
if idx != -1:
# Duplicate commands not allowed in history.
_entries.remove_at(idx)
_entries.append(p_entry)
_is_dirty = true
func get_entry(p_index: int) -> String:
return _entries[clampi(p_index, 0, _entries.size())]
func create_iterator() -> WrappingIterator:
var it := WrappingIterator.new(_entries)
_iterators.append(it)
return it
func release_iterator(p_iter: WrappingIterator) -> void:
_iterators.erase(p_iter)
func size() -> int:
return _entries.size()
func trim(p_max_size: int) -> void:
if _entries.size() > p_max_size:
_entries.slice(p_max_size - _entries.size())
_reset_iterators()
func clear() -> void:
_entries.clear()
func load(p_path: String = HISTORY_FILE) -> void:
var file := FileAccess.open(p_path, FileAccess.READ)
if not file:
return
while not file.eof_reached():
var line: String = file.get_line().strip_edges()
if not line.is_empty():
_push_entry(line)
file.close()
_reset_iterators()
_is_dirty = false
func save(p_path: String = HISTORY_FILE) -> void:
if not _is_dirty:
return
var file := FileAccess.open(p_path, FileAccess.WRITE)
if not file:
push_error("LimboConsole: Failed to save console history to file: ", p_path)
return
for line in _entries:
file.store_line(line)
file.close()
_is_dirty = false
## Searches history and returns an array starting with most relevant entries.
func fuzzy_match(p_query: String) -> PackedStringArray:
if len(p_query) == 0:
var copy := _entries.duplicate()
copy.reverse()
return copy
var results: Array = []
for entry: String in _entries:
var score: int = _compute_match_score(p_query.to_lower(), entry.to_lower())
if score > 0:
results.append({"entry": entry, "score": score})
results.sort_custom(func(a, b): return a.score > b.score)
return results.map(func(rec): return rec.entry)
func _reset_iterators() -> void:
for it in _iterators:
it._reassign(_entries)
## Scoring function for fuzzy matching.
static func _compute_match_score(query: String, target: String) -> int:
var score: int = 0
var query_index: int = 0
# Exact match. give unbeatable score
if query == target:
score = 99999
return score
for i in range(target.length()):
if query_index < query.length() and target[i] == query[query_index]:
score += 10 # Base score for a match
if i == 0 or target[i - 1] == " ": # Bonus for word start
score += 5
query_index += 1
if query_index == query.length():
break
# Ensure full query matches
return score if query_index == query.length() else 0
## Iterator that wraps around and resets on history change.
class WrappingIterator:
extends RefCounted
var _idx: int = -1
var _entries: PackedStringArray
func _init(p_entries: PackedStringArray) -> void:
_entries = p_entries
func prev() -> String:
_idx = wrapi(_idx - 1, -1, _entries.size())
if _idx == -1:
return String()
return _entries[_idx]
func next() -> String:
_idx = wrapi(_idx + 1, -1, _entries.size())
if _idx == -1:
return String()
return _entries[_idx]
func current() -> String:
if _idx < 0 or _idx >= _entries.size():
return String()
return _entries[_idx]
func reset() -> void:
_idx = -1
func _reassign(p_entries: PackedStringArray) -> void:
_idx = -1
_entries = p_entries