# 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_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(): # Get the path to the server directory relative to the project # server_path = OS.get_executable_path().get_base_dir().path_join("Assets/ChessEngines/fairy-chess-server") # server_path = "res://Assets/ChessEngines/fairy-chess-server" # server_path = ProjectSettings.globalize_path("res://Assets/ChessEngines/fairy-chess-server") # if OS.has_feature("editor"): # server_path = ProjectSettings.globalize_path("res://Assets/ChessEngines/fairy-chess-server") # else: # # Running from an exported project. # # `path` will contain the absolute path to `hello.txt` next to the executable. # # This is *not* identical to using `ProjectSettings.globalize_path()` with a `res://` path, # # but is close enough in spirit. # server_path = OS.get_executable_path().get_base_dir().path_join("Assets/ChessEngines/fairy-chess-server") 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) 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) # Make sure we're in the correct directory var http_request = HTTPRequest.new() add_child(http_request) # http_request.connect("request_completed", self._on_init_request_completed) 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