/ TaskMaster.gd
TaskMaster.gd
1 extends Node 2 @onready var pathfinding_service = get_node("/root/MainGame/Simulation/PathfindingService") 3 @onready var message_bus = get_node("/root/MainGame/NetworkLayer/RPC/MessageBus") 4 # The master queue of pending tasks 5 var pending_jobs: Array[Dictionary] = [] 6 var job_id: int = 0 7 8 func _ready(): 9 Lib.auto_wire_events(self) 10 if not multiplayer.is_server(): 11 set_process(false) 12 13 ## Adds a new job to the queue and sorts it by priority 14 func add_job(work_def: String, target_pos: Vector2i, target_object: Node2D = null): 15 job_id = job_id + 1 16 if (job_id > 2147483600): 17 job_id = 0 18 tLogger.error("Job ID hit max Int probably something cooked") 19 var dict = Defs.get(work_def) 20 var new_job = { 21 "work_name": work_def, 22 "work_type": dict.work_type, 23 "level_required": dict.level_required, 24 "target_pos": target_pos, 25 "status": "available", 26 "priority": 1, 27 "work_left": dict.work_max, 28 "output": dict.output, 29 "job_id": job_id 30 } 31 # check against duplicate jobs 32 if _is_job_already_queued(new_job): 33 return 34 35 pending_jobs.append(new_job) 36 _sort_queue() 37 tLogger.info("TaskMaster: Added job " + str(dict.work_type) + " at " + str(target_pos) + " and ID: " + str(job_id)) 38 39 40 func get_next_available_job(colonist: Node2D) -> Dictionary: 41 if pending_jobs.is_empty(): 42 tLogger.warn("no jobs available in taskmaster>get_next_available_job") 43 return {} 44 var min_distance = INF 45 var closest_job = -1 46 for i in range(pending_jobs.size()): 47 var job = pending_jobs[i] 48 var target_pos = job.get("target_pos") 49 if job.get("status") != "available": 50 continue 51 # Check if the colonist has the skill (expand this later) 52 if not _can_colonist_do_job(colonist, job): 53 continue 54 if not pathfinding_service.short_reachability_check(target_pos): 55 continue 56 var distance = pathfinding_service.get_distance(Lib.get_grid_position(colonist.global_position),target_pos) 57 if distance < min_distance: 58 closest_job = i 59 min_distance = distance 60 if closest_job != -1: 61 pending_jobs[closest_job].status = "claimed" 62 return pending_jobs[closest_job] 63 return {} 64 65 func finish_work(work: int): 66 for i in pending_jobs.size(): 67 if pending_jobs[i].job_id == work: 68 if pending_jobs[i].output != "": 69 message_bus.sync_item_dropped.rpc(pending_jobs[i].output, 5, pending_jobs[i].target_pos) 70 message_bus.sync_structure_changed.rpc("structure_dict_clear", pending_jobs[i].target_pos) 71 tLogger.info("Job " + str(pending_jobs[i].job_id) + " completed and removed.") 72 pending_jobs.pop_at(i) 73 return 74 75 #func _on_work_changed(job_id :int, amount: float): 76 # pass 77 78 func _sort_queue(): 79 #to do sort into different queues for different work types 80 pending_jobs.sort_custom(func(a, b): return a["priority"] < b["priority"]) 81 82 ## Helper: Prevents identical tasks from stacking 83 func _is_job_already_queued(new_job: Dictionary) -> bool: 84 for job in pending_jobs: 85 if job.get("work_type") == new_job["work_type"] and job.get("target_pos") == new_job["target_pos"]: 86 return true 87 return false 88 89 90 91 func _can_colonist_do_job(_colonist: Node2D, _job: Dictionary) -> bool: 92 # Future: if job["type"] == "mine" and colonist.mining_skill == 0: return false 93 return true # Currently, anyone can do anything