extends Node class_name CommunityEventSystem ## 社区活动和事件系统 ## 管理社区活动、事件和集体互动 # 事件类型枚举 enum EventType { SOCIAL_GATHERING, # 社交聚会 LEARNING_SESSION, # 学习会议 COMPETITION, # 竞赛活动 CELEBRATION, # 庆祝活动 WORKSHOP, # 工作坊 DISCUSSION, # 讨论会 GAME_ACTIVITY, # 游戏活动 COMMUNITY_PROJECT, # 社区项目 ANNOUNCEMENT, # 公告 MILESTONE # 里程碑事件 } # 事件状态枚举 enum EventStatus { PLANNED, # 计划中 ACTIVE, # 进行中 COMPLETED, # 已完成 CANCELLED # 已取消 } # 事件数据结构 class CommunityEvent: var event_id: String var title: String var description: String var event_type: EventType var status: EventStatus var organizer_id: String var participants: Array[String] = [] var max_participants: int = 0 # 0表示无限制 var start_time: float var end_time: float var location: String = "" # 游戏内位置 var rewards: Dictionary = {} var requirements: Dictionary = {} var created_at: float var updated_at: float var tags: Array[String] = [] var metadata: Dictionary = {} func _init(id: String, event_title: String, type: EventType, organizer: String): event_id = id title = event_title event_type = type organizer_id = organizer status = EventStatus.PLANNED created_at = Time.get_unix_time_from_system() updated_at = created_at start_time = created_at + 3600 # 默认1小时后开始 end_time = start_time + 3600 # 默认持续1小时 # 活动数据存储 var events: Dictionary = {} # event_id -> CommunityEvent var active_events: Array[String] = [] var user_events: Dictionary = {} # user_id -> Array[event_id] var event_history: Array[Dictionary] = [] # 系统配置 var max_events_per_user: int = 10 var max_active_events: int = 20 var auto_cleanup_days: int = 30 # 关系网络引用 var relationship_network: RelationshipNetwork # 数据持久化 var events_file_path: String = "user://community_events.json" # 信号 signal event_created(event_id: String, title: String, organizer_id: String) signal event_started(event_id: String, title: String) signal event_completed(event_id: String, title: String, participants: Array[String]) signal event_cancelled(event_id: String, title: String, reason: String) signal participant_joined(event_id: String, participant_id: String) signal participant_left(event_id: String, participant_id: String) signal event_reminder(event_id: String, title: String, minutes_until_start: int) signal milestone_achieved(milestone_type: String, data: Dictionary) func _ready(): """初始化社区事件系统""" load_events_data() # 启动定时器检查事件状态 var timer = Timer.new() timer.wait_time = 60.0 # 每分钟检查一次 timer.timeout.connect(_check_event_status) timer.autostart = true add_child(timer) print("CommunityEventSystem initialized") ## 设置关系网络引用 func set_relationship_network(rn: RelationshipNetwork) -> void: """ 设置关系网络引用 @param rn: 关系网络实例 """ relationship_network = rn ## 创建事件 func create_event(title: String, description: String, event_type: EventType, organizer_id: String, start_time: float = 0.0, duration: float = 3600.0) -> String: """ 创建新的社区事件 @param title: 事件标题 @param description: 事件描述 @param event_type: 事件类型 @param organizer_id: 组织者ID @param start_time: 开始时间(Unix时间戳,0表示使用默认时间) @param duration: 持续时间(秒) @return: 事件ID,失败返回空字符串 """ # 验证输入 if title.strip_edges().is_empty(): print("Event title cannot be empty") return "" if title.length() > 100: print("Event title too long") return "" # 检查用户事件数量限制 var user_event_count = user_events.get(organizer_id, []).size() if user_event_count >= max_events_per_user: print("User has reached maximum events limit") return "" # 检查活跃事件数量限制 if active_events.size() >= max_active_events: print("Maximum active events limit reached") return "" # 生成事件ID var event_id = generate_event_id() # 创建事件 var event = CommunityEvent.new(event_id, title.strip_edges(), event_type, organizer_id) event.description = description.strip_edges() if start_time > 0: event.start_time = start_time event.end_time = start_time + duration # 组织者自动参与 event.participants.append(organizer_id) # 存储事件 events[event_id] = event active_events.append(event_id) # 更新用户事件索引 _add_event_to_user_index(organizer_id, event_id) # 保存数据 save_events_data() # 发射信号 event_created.emit(event_id, title, organizer_id) print("Event created: ", title, " (", event_id, ") by ", organizer_id) return event_id ## 加入事件 func join_event(event_id: String, participant_id: String) -> bool: """ 加入事件 @param event_id: 事件ID @param participant_id: 参与者ID @return: 是否成功加入 """ if not events.has(event_id): print("Event not found: ", event_id) return false var event = events[event_id] # 检查事件状态 if event.status != EventStatus.PLANNED and event.status != EventStatus.ACTIVE: print("Cannot join event: event is not active") return false # 检查是否已经参与 if participant_id in event.participants: print("Already participating in event: ", event_id) return true # 检查参与者数量限制 if event.max_participants > 0 and event.participants.size() >= event.max_participants: print("Event is full") return false # 检查参与要求 if not _check_event_requirements(event, participant_id): print("Participant does not meet event requirements") return false # 加入事件 event.participants.append(participant_id) event.updated_at = Time.get_unix_time_from_system() # 更新用户事件索引 _add_event_to_user_index(participant_id, event_id) # 记录关系网络互动 if relationship_network: for other_participant in event.participants: if other_participant != participant_id: relationship_network.record_interaction(participant_id, other_participant, "community_event", {"event_id": event_id}) # 保存数据 save_events_data() # 发射信号 participant_joined.emit(event_id, participant_id) print("Participant ", participant_id, " joined event ", event_id) return true ## 离开事件 func leave_event(event_id: String, participant_id: String) -> bool: """ 离开事件 @param event_id: 事件ID @param participant_id: 参与者ID @return: 是否成功离开 """ if not events.has(event_id): print("Event not found: ", event_id) return false var event = events[event_id] # 检查是否参与 if not participant_id in event.participants: print("Not participating in event: ", event_id) return false # 组织者不能离开自己的事件 if participant_id == event.organizer_id: print("Organizer cannot leave their own event") return false # 离开事件 event.participants.erase(participant_id) event.updated_at = Time.get_unix_time_from_system() # 更新用户事件索引 _remove_event_from_user_index(participant_id, event_id) # 保存数据 save_events_data() # 发射信号 participant_left.emit(event_id, participant_id) print("Participant ", participant_id, " left event ", event_id) return true ## 开始事件 func start_event(event_id: String) -> bool: """ 开始事件 @param event_id: 事件ID @return: 是否成功开始 """ if not events.has(event_id): print("Event not found: ", event_id) return false var event = events[event_id] if event.status != EventStatus.PLANNED: print("Event cannot be started: not in planned status") return false # 更新状态 event.status = EventStatus.ACTIVE event.start_time = Time.get_unix_time_from_system() event.updated_at = event.start_time # 保存数据 save_events_data() # 发射信号 event_started.emit(event_id, event.title) print("Event started: ", event.title, " (", event_id, ")") return true ## 完成事件 func complete_event(event_id: String, results: Dictionary = {}) -> bool: """ 完成事件 @param event_id: 事件ID @param results: 事件结果数据 @return: 是否成功完成 """ if not events.has(event_id): print("Event not found: ", event_id) return false var event = events[event_id] if event.status != EventStatus.ACTIVE: print("Event cannot be completed: not active") return false # 更新状态 event.status = EventStatus.COMPLETED event.end_time = Time.get_unix_time_from_system() event.updated_at = event.end_time event.metadata["results"] = results # 从活跃事件列表移除 active_events.erase(event_id) # 添加到历史记录 _add_to_event_history(event) # 分发奖励 _distribute_event_rewards(event) # 记录关系网络互动 if relationship_network: _record_event_relationships(event) # 检查里程碑 _check_milestones(event) # 保存数据 save_events_data() # 发射信号 event_completed.emit(event_id, event.title, event.participants) print("Event completed: ", event.title, " (", event_id, ") with ", event.participants.size(), " participants") return true ## 取消事件 func cancel_event(event_id: String, reason: String = "") -> bool: """ 取消事件 @param event_id: 事件ID @param reason: 取消原因 @return: 是否成功取消 """ if not events.has(event_id): print("Event not found: ", event_id) return false var event = events[event_id] if event.status == EventStatus.COMPLETED or event.status == EventStatus.CANCELLED: print("Event cannot be cancelled: already completed or cancelled") return false # 更新状态 event.status = EventStatus.CANCELLED event.updated_at = Time.get_unix_time_from_system() event.metadata["cancel_reason"] = reason # 从活跃事件列表移除 active_events.erase(event_id) # 保存数据 save_events_data() # 发射信号 event_cancelled.emit(event_id, event.title, reason) print("Event cancelled: ", event.title, " (", event_id, ") - ", reason) return true ## 获取事件列表 func get_events_list(filter_type: EventType = EventType.SOCIAL_GATHERING, filter_status: EventStatus = EventStatus.PLANNED, include_all_types: bool = true, include_all_statuses: bool = true) -> Array[Dictionary]: """ 获取事件列表 @param filter_type: 过滤事件类型 @param filter_status: 过滤事件状态 @param include_all_types: 是否包含所有类型 @param include_all_statuses: 是否包含所有状态 @return: 事件信息数组 """ var events_list = [] for event_id in events: var event = events[event_id] # 应用过滤器 if not include_all_types and event.event_type != filter_type: continue if not include_all_statuses and event.status != filter_status: continue events_list.append(_get_event_info(event)) # 按开始时间排序 events_list.sort_custom(func(a, b): return a.start_time < b.start_time) return events_list ## 获取用户事件 func get_user_events(user_id: String) -> Array[Dictionary]: """ 获取用户参与的事件 @param user_id: 用户ID @return: 事件信息数组 """ var user_event_ids = user_events.get(user_id, []) var user_events_list = [] for event_id in user_event_ids: if events.has(event_id): user_events_list.append(_get_event_info(events[event_id])) # 按开始时间排序 user_events_list.sort_custom(func(a, b): return a.start_time < b.start_time) return user_events_list ## 搜索事件 func search_events(query: String, event_type: EventType = EventType.SOCIAL_GATHERING, include_all_types: bool = true) -> Array[Dictionary]: """ 搜索事件 @param query: 搜索关键词 @param event_type: 事件类型过滤 @param include_all_types: 是否包含所有类型 @return: 匹配的事件信息数组 """ var results = [] var search_query = query.to_lower() for event_id in events: var event = events[event_id] # 类型过滤 if not include_all_types and event.event_type != event_type: continue # 搜索标题和描述 if event.title.to_lower().contains(search_query) or event.description.to_lower().contains(search_query): results.append(_get_event_info(event)) # 搜索标签 else: for tag in event.tags: if tag.to_lower().contains(search_query): results.append(_get_event_info(event)) break return results ## 获取推荐事件 func get_recommended_events(user_id: String, limit: int = 5) -> Array[Dictionary]: """ 获取推荐事件 @param user_id: 用户ID @param limit: 限制返回数量 @return: 推荐事件信息数组 """ var recommendations = [] var user_interests = _get_user_interests(user_id) for event_id in events: var event = events[event_id] # 只推荐计划中的事件 if event.status != EventStatus.PLANNED: continue # 不推荐已参与的事件 if user_id in event.participants: continue var score = _calculate_recommendation_score(event, user_id, user_interests) recommendations.append({ "event": _get_event_info(event), "score": score }) # 按推荐分数排序 recommendations.sort_custom(func(a, b): return a.score > b.score) # 提取事件信息 var recommended_events = [] for i in range(min(limit, recommendations.size())): recommended_events.append(recommendations[i].event) return recommended_events ## 检查事件状态 func _check_event_status() -> void: """定期检查事件状态并处理自动转换""" var current_time = Time.get_unix_time_from_system() for event_id in active_events.duplicate(): # 使用副本避免修改时的问题 if not events.has(event_id): active_events.erase(event_id) continue var event = events[event_id] # 检查是否应该开始 if event.status == EventStatus.PLANNED and current_time >= event.start_time: start_event(event_id) # 检查是否应该结束 elif event.status == EventStatus.ACTIVE and current_time >= event.end_time: complete_event(event_id) # 发送提醒 elif event.status == EventStatus.PLANNED: var minutes_until_start = (event.start_time - current_time) / 60.0 if minutes_until_start <= 15 and minutes_until_start > 14: # 15分钟提醒 event_reminder.emit(event_id, event.title, 15) elif minutes_until_start <= 5 and minutes_until_start > 4: # 5分钟提醒 event_reminder.emit(event_id, event.title, 5) ## 检查事件要求 func _check_event_requirements(_event: CommunityEvent, _participant_id: String) -> bool: """ 检查参与者是否满足事件要求 @param _event: 事件对象 (暂未使用) @param _participant_id: 参与者ID (暂未使用) @return: 是否满足要求 """ # 这里可以添加各种要求检查,比如等级、成就、关系等 # 目前返回true,表示没有特殊要求 return true ## 分发事件奖励 func _distribute_event_rewards(event: CommunityEvent) -> void: """ 分发事件奖励 @param event: 事件对象 """ if event.rewards.is_empty(): return for participant_id in event.participants: # 这里可以实现具体的奖励分发逻辑 # 比如经验值、成就、物品等 print("Distributing rewards to ", participant_id, " for event ", event.title) ## 记录事件关系 func _record_event_relationships(event: CommunityEvent) -> void: """ 记录事件中的关系互动 @param event: 事件对象 """ if not relationship_network: return # 为所有参与者之间记录互动 for i in range(event.participants.size()): for j in range(i + 1, event.participants.size()): var participant1 = event.participants[i] var participant2 = event.participants[j] var interaction_data = { "event_id": event.event_id, "event_type": EventType.keys()[event.event_type], "event_title": event.title } relationship_network.record_interaction(participant1, participant2, "community_event", interaction_data) relationship_network.record_interaction(participant2, participant1, "community_event", interaction_data) ## 检查里程碑 func _check_milestones(event: CommunityEvent) -> void: """ 检查并触发里程碑事件 @param event: 完成的事件对象 """ # 检查各种里程碑条件 var total_events = event_history.size() # 事件数量里程碑 if total_events == 10: milestone_achieved.emit("events_10", {"count": total_events}) elif total_events == 50: milestone_achieved.emit("events_50", {"count": total_events}) elif total_events == 100: milestone_achieved.emit("events_100", {"count": total_events}) # 参与者数量里程碑 if event.participants.size() >= 20: milestone_achieved.emit("large_event", {"participants": event.participants.size(), "event_id": event.event_id}) ## 获取用户兴趣 func _get_user_interests(user_id: String) -> Dictionary: """ 获取用户兴趣(基于历史参与) @param user_id: 用户ID @return: 兴趣数据字典 """ var interests = {} var user_event_ids = user_events.get(user_id, []) for event_id in user_event_ids: if events.has(event_id): var event = events[event_id] var type_name = EventType.keys()[event.event_type] interests[type_name] = interests.get(type_name, 0) + 1 return interests ## 计算推荐分数 func _calculate_recommendation_score(event: CommunityEvent, user_id: String, user_interests: Dictionary) -> float: """ 计算事件推荐分数 @param event: 事件对象 @param user_id: 用户ID @param user_interests: 用户兴趣数据 @return: 推荐分数 """ var score = 0.0 # 基于用户兴趣 var type_name = EventType.keys()[event.event_type] score += user_interests.get(type_name, 0) * 10.0 # 基于关系网络 if relationship_network: var user_relationships = relationship_network.get_character_relationships(user_id) for relationship in user_relationships: if relationship.to_character in event.participants: score += relationship.strength * 0.5 # 基于事件规模(适中规模更受欢迎) var participant_count = event.participants.size() if participant_count >= 3 and participant_count <= 10: score += 5.0 # 基于时间(即将开始的事件更相关) var time_until_start = event.start_time - Time.get_unix_time_from_system() if time_until_start > 0 and time_until_start <= 86400: # 24小时内 score += 10.0 - (time_until_start / 8640.0) # 越近分数越高 return score ## 获取事件信息 func _get_event_info(event: CommunityEvent) -> Dictionary: """ 获取事件信息字典 @param event: 事件对象 @return: 事件信息字典 """ return { "id": event.event_id, "title": event.title, "description": event.description, "type": event.event_type, "type_name": EventType.keys()[event.event_type], "status": event.status, "status_name": EventStatus.keys()[event.status], "organizer_id": event.organizer_id, "participants": event.participants.duplicate(), "participant_count": event.participants.size(), "max_participants": event.max_participants, "start_time": event.start_time, "end_time": event.end_time, "location": event.location, "rewards": event.rewards.duplicate(), "requirements": event.requirements.duplicate(), "created_at": event.created_at, "updated_at": event.updated_at, "tags": event.tags.duplicate(), "metadata": event.metadata.duplicate() } ## 添加到事件历史 func _add_to_event_history(event: CommunityEvent) -> void: """ 添加事件到历史记录 @param event: 事件对象 """ var history_entry = { "event_id": event.event_id, "title": event.title, "type": event.event_type, "organizer_id": event.organizer_id, "participant_count": event.participants.size(), "start_time": event.start_time, "end_time": event.end_time, "completed_at": Time.get_unix_time_from_system() } event_history.append(history_entry) # 限制历史记录长度 if event_history.size() > 1000: event_history.pop_front() ## 添加事件到用户索引 func _add_event_to_user_index(user_id: String, event_id: String) -> void: """ 添加事件到用户索引 @param user_id: 用户ID @param event_id: 事件ID """ if not user_events.has(user_id): user_events[user_id] = [] var user_event_list = user_events[user_id] if not event_id in user_event_list: user_event_list.append(event_id) ## 从用户索引移除事件 func _remove_event_from_user_index(user_id: String, event_id: String) -> void: """ 从用户索引移除事件 @param user_id: 用户ID @param event_id: 事件ID """ if user_events.has(user_id): var user_event_list = user_events[user_id] user_event_list.erase(event_id) ## 生成事件ID func generate_event_id() -> String: """生成唯一的事件ID""" var timestamp = Time.get_unix_time_from_system() var random = randi() return "event_%d_%d" % [timestamp, random] ## 保存事件数据 func save_events_data() -> void: """保存事件数据到本地文件""" var data = { "events": {}, "active_events": active_events, "user_events": user_events, "event_history": event_history } # 序列化事件数据 for event_id in events: var event = events[event_id] data.events[event_id] = { "title": event.title, "description": event.description, "event_type": event.event_type, "status": event.status, "organizer_id": event.organizer_id, "participants": event.participants, "max_participants": event.max_participants, "start_time": event.start_time, "end_time": event.end_time, "location": event.location, "rewards": event.rewards, "requirements": event.requirements, "created_at": event.created_at, "updated_at": event.updated_at, "tags": event.tags, "metadata": event.metadata } var file = FileAccess.open(events_file_path, FileAccess.WRITE) if file: var json_string = JSON.stringify(data) file.store_string(json_string) file.close() print("Community events data saved") else: print("Failed to save community events data") ## 加载事件数据 func load_events_data() -> void: """从本地文件加载事件数据""" if not FileAccess.file_exists(events_file_path): print("No community events data file found, starting fresh") return var file = FileAccess.open(events_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: var data = json.data # 加载事件数据 if data.has("events"): for event_id in data.events: var event_data = data.events[event_id] var event = CommunityEvent.new( event_id, event_data.get("title", ""), event_data.get("event_type", EventType.SOCIAL_GATHERING), event_data.get("organizer_id", "") ) event.description = event_data.get("description", "") event.status = event_data.get("status", EventStatus.PLANNED) event.participants = event_data.get("participants", []) event.max_participants = event_data.get("max_participants", 0) event.start_time = event_data.get("start_time", Time.get_unix_time_from_system()) event.end_time = event_data.get("end_time", event.start_time + 3600) event.location = event_data.get("location", "") event.rewards = event_data.get("rewards", {}) event.requirements = event_data.get("requirements", {}) event.created_at = event_data.get("created_at", Time.get_unix_time_from_system()) event.updated_at = event_data.get("updated_at", event.created_at) event.tags = event_data.get("tags", []) event.metadata = event_data.get("metadata", {}) events[event_id] = event # 加载活跃事件列表 if data.has("active_events"): active_events = data.active_events # 加载用户事件索引 if data.has("user_events"): user_events = data.user_events # 加载事件历史 if data.has("event_history"): event_history = data.event_history print("Community events data loaded: ", events.size(), " events, ", active_events.size(), " active") else: print("Failed to parse community events data JSON") else: print("Failed to open community events data file") ## 获取统计信息 func get_statistics() -> Dictionary: """ 获取社区事件系统统计信息 @return: 统计信息字典 """ var type_counts = {} var status_counts = {} var total_participants = 0 for event_id in events: var event = events[event_id] var type_name = EventType.keys()[event.event_type] var status_name = EventStatus.keys()[event.status] type_counts[type_name] = type_counts.get(type_name, 0) + 1 status_counts[status_name] = status_counts.get(status_name, 0) + 1 total_participants += event.participants.size() return { "total_events": events.size(), "active_events": active_events.size(), "completed_events": event_history.size(), "total_participants": total_participants, "average_participants": float(total_participants) / max(events.size(), 1), "event_types": type_counts, "event_statuses": status_counts, "max_events_per_user": max_events_per_user, "max_active_events": max_active_events }