Files
whale-town/scripts/DialogueHistoryManager.gd
2025-12-05 19:00:14 +08:00

258 lines
7.3 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extends Node
class_name DialogueHistoryManager
## 对话历史管理器
## 负责保存、加载和管理对话历史记录
# 历史记录存储
var dialogue_histories: Dictionary = {} # character_id -> Array[Dictionary]
var max_history_per_character: int = 100
var history_file_path: String = "user://dialogue_history.json"
# 信号
signal history_loaded()
signal history_saved()
func _ready():
"""初始化对话历史管理器"""
load_history()
print("DialogueHistoryManager initialized")
## 添加消息到历史记录
func add_message_to_history(character_id: String, sender: String, message: String, timestamp: float = 0.0) -> void:
"""
添加消息到指定角色的对话历史
@param character_id: 角色ID
@param sender: 发送者("player" 或角色ID
@param message: 消息内容
@param timestamp: 时间戳0表示使用当前时间
"""
if timestamp <= 0:
timestamp = Time.get_unix_time_from_system()
# 确保角色历史记录存在
if not dialogue_histories.has(character_id):
dialogue_histories[character_id] = []
var history = dialogue_histories[character_id]
# 创建消息记录
var message_record = {
"sender": sender,
"message": message,
"timestamp": timestamp,
"id": generate_message_id()
}
# 添加到历史记录
history.append(message_record)
# 限制历史记录长度
if history.size() > max_history_per_character:
history.pop_front()
# 自动保存(异步)
call_deferred("save_history")
## 获取角色的对话历史
func get_character_history(character_id: String, limit: int = 0) -> Array[Dictionary]:
"""
获取指定角色的对话历史
@param character_id: 角色ID
@param limit: 限制返回的消息数量0表示返回全部
@return: 消息历史数组
"""
if not dialogue_histories.has(character_id):
return []
var history = dialogue_histories[character_id]
if limit <= 0 or limit >= history.size():
return history.duplicate()
# 返回最近的消息
return history.slice(history.size() - limit, history.size())
## 获取最近的对话记录
func get_recent_conversations(limit: int = 10) -> Array[Dictionary]:
"""
获取最近的对话记录(按时间排序)
@param limit: 限制返回的对话数量
@return: 最近对话的摘要数组
"""
var recent_conversations = []
for character_id in dialogue_histories:
var history = dialogue_histories[character_id]
if history.size() > 0:
var last_message = history[-1] # 最后一条消息
recent_conversations.append({
"character_id": character_id,
"last_message": last_message.message,
"last_sender": last_message.sender,
"timestamp": last_message.timestamp,
"message_count": history.size()
})
# 按时间戳排序(最新的在前)
recent_conversations.sort_custom(func(a, b): return a.timestamp > b.timestamp)
# 限制数量
if limit > 0 and recent_conversations.size() > limit:
recent_conversations = recent_conversations.slice(0, limit)
return recent_conversations
## 搜索对话历史
func search_messages(query: String, character_id: String = "") -> Array[Dictionary]:
"""
在对话历史中搜索消息
@param query: 搜索关键词
@param character_id: 指定角色ID空字符串表示搜索所有角色
@return: 匹配的消息数组
"""
var results = []
var search_query = query.to_lower()
var characters_to_search = []
if character_id.is_empty():
characters_to_search = dialogue_histories.keys()
else:
characters_to_search = [character_id]
for char_id in characters_to_search:
if not dialogue_histories.has(char_id):
continue
var history = dialogue_histories[char_id]
for message_record in history:
if message_record.message.to_lower().contains(search_query):
var result = message_record.duplicate()
result["character_id"] = char_id
results.append(result)
# 按时间戳排序(最新的在前)
results.sort_custom(func(a, b): return a.timestamp > b.timestamp)
return results
## 清除角色的对话历史
func clear_character_history(character_id: String) -> void:
"""
清除指定角色的对话历史
@param character_id: 角色ID
"""
if dialogue_histories.has(character_id):
dialogue_histories.erase(character_id)
save_history()
## 清除所有对话历史
func clear_all_history() -> void:
"""清除所有对话历史"""
dialogue_histories.clear()
save_history()
## 保存历史记录到文件
func save_history() -> void:
"""保存对话历史到本地文件"""
var file = FileAccess.open(history_file_path, FileAccess.WRITE)
if file:
var json_string = JSON.stringify(dialogue_histories)
file.store_string(json_string)
file.close()
history_saved.emit()
print("Dialogue history saved")
else:
print("Failed to save dialogue history")
## 从文件加载历史记录
func load_history() -> void:
"""从本地文件加载对话历史"""
if not FileAccess.file_exists(history_file_path):
print("No dialogue history file found, starting fresh")
return
var file = FileAccess.open(history_file_path, FileAccess.READ)
if file:
var json_string = file.get_as_text()
file.close()
var json = JSON.new()
var parse_result = json.parse(json_string)
if parse_result == OK:
dialogue_histories = json.data
history_loaded.emit()
print("Dialogue history loaded: ", dialogue_histories.size(), " characters")
else:
print("Failed to parse dialogue history JSON")
else:
print("Failed to open dialogue history file")
## 生成消息ID
func generate_message_id() -> String:
"""生成唯一的消息ID"""
var timestamp = Time.get_unix_time_from_system()
var random = randi()
return "msg_%d_%d" % [timestamp, random]
## 获取统计信息
func get_statistics() -> Dictionary:
"""
获取对话历史统计信息
@return: 统计信息字典
"""
var total_messages = 0
var total_characters = dialogue_histories.size()
var oldest_message_time = 0.0
var newest_message_time = 0.0
for character_id in dialogue_histories:
var history = dialogue_histories[character_id]
total_messages += history.size()
if history.size() > 0:
var first_msg_time = history[0].timestamp
var last_msg_time = history[-1].timestamp
if oldest_message_time == 0.0 or first_msg_time < oldest_message_time:
oldest_message_time = first_msg_time
if newest_message_time == 0.0 or last_msg_time > newest_message_time:
newest_message_time = last_msg_time
return {
"total_messages": total_messages,
"total_characters": total_characters,
"oldest_message_time": oldest_message_time,
"newest_message_time": newest_message_time,
"file_path": history_file_path
}
## 导出历史记录
func export_history(export_path: String, character_id: String = "") -> bool:
"""
导出对话历史到指定文件
@param export_path: 导出文件路径
@param character_id: 指定角色ID空字符串表示导出所有
@return: 是否成功
"""
var export_data = {}
if character_id.is_empty():
export_data = dialogue_histories
elif dialogue_histories.has(character_id):
export_data[character_id] = dialogue_histories[character_id]
else:
print("Character not found: ", character_id)
return false
var file = FileAccess.open(export_path, FileAccess.WRITE)
if file:
var json_string = JSON.stringify(export_data)
file.store_string(json_string)
file.close()
print("History exported to: ", export_path)
return true
else:
print("Failed to export history to: ", export_path)
return false