# ServerManager.gd extends Node var server_path: String = "" var log_dir: String = "" var log_string: String = "" var running := false var server_process_id: int = -50 var request_timer: Timer var server_pinger: Timer var ping_http: HTTPRequest var server_url = "http://localhost:27531" func write_log(message: String): # First check if path is valid # print("Attempting to write to: ", log_dir) var file = FileAccess.open(log_dir, FileAccess.WRITE_READ) var error = FileAccess.get_open_error() if error != OK: # print("Failed to open log file. Error code: ", error) return if file == null: # print("File handle is null") return var timestamp = Time.get_datetime_string_from_system() var log_message = "[" + timestamp + "] " + message + "\n" log_string += log_message print("Writing message: ", log_message) file.store_string(log_string) var write_error = FileAccess.get_open_error() if write_error != OK: print("Failed to write to log file. Error code: ", write_error) file.close() func _ready(): server_path = extract_server_files() + "/ChessEngines/fairy-chess-server" setup_logging() check_server_files(server_path) start_server() get_tree().set_auto_accept_quit(false) setup_server_pinger() func setup_server_pinger(): server_pinger = Timer.new() add_child(server_pinger) server_pinger.wait_time = 60.0 server_pinger.one_shot = false server_pinger.timeout.connect(self._on_ping_timer_timeout) ping_http = HTTPRequest.new() add_child(ping_http) ping_http.request_completed.connect(self._on_ping_completed) server_pinger.start() func _on_ping_timer_timeout(): write_log("Pinging server health endpoint...") var error = ping_http.request(server_url + "/health") if error != OK: write_log("Error sending ping request: " + str(error)) func _on_ping_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray): if result == HTTPRequest.RESULT_SUCCESS: write_log("Server ping successful") else: write_log("Server ping failed - may need to restart server") func write_log_dir_contents(path: String): var dir = DirAccess.open(path) if dir: write_log("Directory contents of: " + path) dir.list_dir_begin() var file_name = dir.get_next() while file_name != "": write_log(" - " + file_name) file_name = dir.get_next() else: write_log("ERROR: Could not open directory: " + path) func check_server_files(path: String): write_log("Checking server files...") write_log(path) var index_path = path.path_join("index.js") if FileAccess.file_exists(index_path): write_log("index.js exists") var file = FileAccess.open(index_path, FileAccess.READ) if file: write_log("index.js contents:") # write_log(file.get_as_text()) else: write_log("ERROR: Could not read index.js") else: write_log("ERROR: index.js does not exist at path: " + index_path) func get_globalDir() -> String: if OS.get_name() == "Linux": return OS.get_environment("HOME").path_join(".local/share/ChessBuilder") elif OS.get_name() == "Windows": return OS.get_environment("APPDATA").path_join("Roaming/ChessBuilder") else: # macOS return OS.get_environment("HOME").path_join("Library/ChessBuilder") func setup_logging(): var l_dir = get_globalDir() + "/logs" # Create directory if it doesn't exist DirAccess.make_dir_recursive_absolute(l_dir) log_dir = l_dir.path_join("godot-chess.log") write_log("ServerManager initialized") func _exit_tree(): stop_server() get_tree().quit() func _notification(what): if what == NOTIFICATION_WM_CLOSE_REQUEST: stop_server() get_tree().quit() func start_server() -> bool: if running: return true write_log("Starting chess server... " + server_path) var http_request = HTTPRequest.new() add_child(http_request) http_request.request_completed.connect(self._on_init_request_completed) request_timer = Timer.new() add_child(request_timer) request_timer.wait_time = 2.0 # 2 seconds request_timer.one_shot = true request_timer.timeout.connect(self._on_request_timeout) request_timer.start() http_request.request(server_url + "/health") return true func _on_request_timeout(): write_log("Request timed out, starting server manually") # Clean up timer request_timer.queue_free() request_timer = null # Call your secondary processing function here write_log("HTTP Request failed, starting server process") write_log(server_path + "/index.js") server_process_id = OS.create_process("node", [server_path + "/index.js"]) write_log("SERVER PATH " + server_path) if server_process_id <= 0: printerr("Failed to start server") write_log("ERROR: Failed to start server, process ID: " + str(server_process_id)) return false running = true write_log("Chess server started with PID: " + str(server_process_id)) return func _on_init_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray): write_log("*****************_on_init_request_completed************") if request_timer: request_timer.stop() request_timer.queue_free() request_timer = null var json = JSON.new() json.parse(body.get_string_from_utf8()) var response = json.get_data() write_log("Init request completed") write_log("Result: " + str(response)) if response == null: write_log("HTTP Request failed, starting server process") write_log(server_path + "/index.js") server_process_id = OS.create_process("node", [server_path + "/index.js"]) write_log("SERVER PATH " + server_path) if server_process_id <= 0: printerr("Failed to start server") write_log("ERROR: Failed to start server, process ID: " + str(server_process_id)) return false running = true write_log("Chess server started with PID: " + str(server_process_id)) return running = true if response and response.status != "ok": print("Server error : ", response_code, json.parse(body.get_string_from_utf8()),) return static func copy_directory_recursively(p_from: String, p_to: String) -> void: # Create target directory if it doesn't exist if not DirAccess.dir_exists_absolute(p_to): DirAccess.make_dir_recursive_absolute(p_to) # Open source directory var dir = DirAccess.open(p_from) if dir: # Begin listing directory contents dir.list_dir_begin() var file_name = dir.get_next() # Iterate through directory contents while file_name != "": # write_log(file_name + " isDIr? " + str(dir.current_is_dir())) if dir.current_is_dir(): # Recursively copy subdirectories copy_directory_recursively(p_from.path_join(file_name), p_to.path_join(file_name)) else: # Copy files dir.copy(p_from.path_join(file_name), p_to.path_join(file_name)) file_name = dir.get_next() func extract_server_files() -> String: write_log("Extracting server files from PCK...") var dir = get_globalDir() + "/Assets"; copy_directory_recursively("res://Assets/", dir) return dir func stop_server(): if not running: return write_log("Stopping chess server...") # Send a stop request to the server var headers = ["Content-Type: application/json"] var http = HTTPClient.new() var data = JSON.stringify({"command": "shutdown"}) http.request(HTTPClient.METHOD_POST, "/shutdown", headers, data) running = false write_log("Chess server stopped") func is_server_running() -> bool: return running