Skip to content

Commit

Permalink
feat: add game server panel (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanFlurry committed Jul 27, 2024
1 parent aa0da3e commit 130c547
Show file tree
Hide file tree
Showing 30 changed files with 559 additions and 319 deletions.
37 changes: 37 additions & 0 deletions addons/rivet/devtools/backend/panel.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
@tool extends Node

@onready var _start = %Start
@onready var _stop = %Stop
@onready var _restart = %Restart
@onready var _open_logs = %OpenLogs

@onready var _proc_manager: ProcessManager = %ProcessManager
@onready var _proc_logs: ProcessLogs = %ProcessLogs

func _ready():
_proc_manager.get_process_command = _get_process_command

func _get_process_command():
var cli = RivetPluginBridge.get_plugin().cli
return [cli.get_cli_path(), "sidekick", "backend-dev", "--no-color"]

func _on_process_manager_process_status_changed(status, _pid):
_start.visible = status == ProcessManager.ProcessStatus.STOPPED
_stop.visible = status == ProcessManager.ProcessStatus.RUNNING
_restart.visible = status == ProcessManager.ProcessStatus.RUNNING
_open_logs.visible = _proc_manager.logs_path != null

func _on_start_pressed():
_proc_manager.start_process()

func _on_stop_pressed():
_proc_manager.stop_process()

func _on_restart_pressed():
_proc_manager.start_process()

func _on_clear_logs_pressed():
_proc_logs.clear_logs()

func _on_open_logs_pressed():
_proc_manager.open_logs_in_file_manager()
65 changes: 65 additions & 0 deletions addons/rivet/devtools/backend/panel.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
[gd_scene load_steps=4 format=3 uid="uid://c4c4p87eotulc"]

[ext_resource type="Script" path="res://addons/rivet/devtools/backend/panel.gd" id="1_ydecy"]
[ext_resource type="Script" path="res://addons/rivet/devtools/elements/process_manager.gd" id="2_dolt5"]
[ext_resource type="PackedScene" uid="uid://v3rf8tpycjfv" path="res://addons/rivet/devtools/elements/process_logs.tscn" id="3_lqccm"]

[node name="Panel" type="HBoxContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_ydecy")

[node name="ProcessManager" type="Node" parent="." node_paths=PackedStringArray("logs")]
unique_name_in_owner = true
script = ExtResource("2_dolt5")
logs = NodePath("../ProcessLogs")

[node name="ProcessLogs" parent="." instance=ExtResource("3_lqccm")]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
init_message = "Press start to start backend server."

[node name="VBoxContainer" type="VBoxContainer" parent="."]
custom_minimum_size = Vector2(100, 2.08165e-12)
layout_mode = 2

[node name="Start" type="Button" parent="VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Start"

[node name="Stop" type="Button" parent="VBoxContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
text = "Stop"

[node name="Restart" type="Button" parent="VBoxContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
text = "Restart"

[node name="HSeparator" type="HSeparator" parent="VBoxContainer"]
layout_mode = 2

[node name="ClearLogs" type="Button" parent="VBoxContainer"]
layout_mode = 2
text = "Clear"

[node name="OpenLogs" type="Button" parent="VBoxContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
text = "Open in File Manager"

[connection signal="process_status_changed" from="ProcessManager" to="." method="_on_process_manager_process_status_changed"]
[connection signal="pressed" from="VBoxContainer/Start" to="." method="_on_start_pressed"]
[connection signal="pressed" from="VBoxContainer/Stop" to="." method="_on_stop_pressed"]
[connection signal="pressed" from="VBoxContainer/Restart" to="." method="_on_restart_pressed"]
[connection signal="pressed" from="VBoxContainer/ClearLogs" to="." method="_on_clear_logs_pressed"]
[connection signal="pressed" from="VBoxContainer/OpenLogs" to="." method="_on_open_logs_pressed"]
2 changes: 1 addition & 1 deletion addons/rivet/devtools/dock/deploy_tab.tscn
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[gd_scene load_steps=4 format=3 uid="uid://soum1c8oyrso"]

[ext_resource type="Script" path="res://addons/rivet/devtools/dock/deploy_tab.gd" id="1_7k6ip"]
[ext_resource type="PackedScene" uid="uid://bogw8dj8rr202" path="res://addons/rivet/devtools/dock/elements/env_menu_button.tscn" id="2_5hxk2"]
[ext_resource type="PackedScene" uid="uid://bogw8dj8rr202" path="res://addons/rivet/devtools/elements/env_menu_button.tscn" id="2_5hxk2"]

[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_dfadg"]

Expand Down
185 changes: 6 additions & 179 deletions addons/rivet/devtools/dock/dev_tab.gd
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,9 @@ const BACKEND_SINGLETON_NAME = "Backend"
@onready var deploy_button: Button = %DeployButton
@onready var env_selector = %AuthEnvSelector

# Game Server
var game_server_poll_timer: Timer
var game_server_pid: int = -1
@onready var game_server_start_button: Button = %GameServerStartButton
@onready var game_server_stop_button: Button = %GameServerStopButton
@onready var game_server_restart_button: Button = %GameServerRestartButton
@onready var game_server_status_label: Label = %GameServerStatusLabel
@onready var game_server_show_logs: CheckBox = %GameServerShowLogs

# Backend
@onready var backend_gerate_sdk_button: Button = %BackendGenerateSdk

# Backend Server
var backend_server_poll_timer: Timer
var backend_server_pid: int = -1
@onready var backend_server_start_button: Button = %BackendServerStartButton
@onready var backend_server_stop_button: Button = %BackendServerStopButton
@onready var backend_server_restart_button: Button = %BackendServerRestartButton
@onready var backend_server_status_label: Label = %BackendServerStatusLabel
@onready var backend_server_show_logs: CheckBox = %BackendServerShowLogs

func _ready() -> void:
if get_tree().edited_scene_root == self:
return # This is the scene opened in the editor!
Expand Down Expand Up @@ -58,26 +40,6 @@ func _ready() -> void:
env_selector.item_selected.connect(_on_env_selector_item_selected)
deploy_button.pressed.connect(_on_deploy_button_pressed)

# Game server
game_server_poll_timer = Timer.new()
game_server_poll_timer.wait_time = 0.5
game_server_poll_timer.paused = true
game_server_poll_timer.autostart = true
game_server_poll_timer.timeout.connect(_poll_game_server_status)
add_child(game_server_poll_timer)

_poll_game_server_status()

# Backend server
backend_server_poll_timer = Timer.new()
backend_server_poll_timer.wait_time = 0.5
backend_server_poll_timer.paused = true
backend_server_poll_timer.autostart = true
backend_server_poll_timer.timeout.connect(_poll_backend_server_status)
add_child(backend_server_poll_timer)

_poll_backend_server_status()

func _on_bootstrapped() -> void:
_update_selected_env()

Expand Down Expand Up @@ -139,79 +101,6 @@ func _on_deploy_button_pressed() -> void:
owner.deploy_tab.env_selector.current_value = env_selector.selected_remote_env
owner.deploy_tab.env_selector.selected = env_selector.selected

# MARK: Game Server
func _on_game_server_start_pressed():
start_game_server()

func _on_game_server_stop_pressed():
stop_game_server()

func _on_game_server_restart_pressed():
start_game_server()

func start_game_server():
if game_server_pid != -1:
RivetPluginBridge.log("Restarting server, old pid %s" % game_server_pid)
stop_game_server()

if game_server_show_logs.button_pressed:
# Running with logs does not have a PID we can kill
game_server_pid = -1

# Run via Rivet CLI to show the terminal. Get the PID from the process
# the Rivet CLI spawned.
var full_args = ["sidekick", "show-term", "--", OS.get_executable_path()]
full_args.append_array(_game_server_run_args())
var result = RivetPluginBridge.get_plugin().cli.run_and_wait_sync(full_args)
if result.exit_code != 0 or !("Ok" in result.output):
RivetPluginBridge.display_cli_error(self, result)
return
RivetPluginBridge.log("Started server with logs")
else:
# TODO: Use background thread for this & collect output to a file
# Run natively without terminal
game_server_pid = OS.create_process(OS.get_executable_path(), _game_server_run_args())
RivetPluginBridge.log("Started server without logs %s" % game_server_pid)

_poll_game_server_status()

func stop_game_server():
if game_server_pid != -1:
RivetPluginBridge.log("Stopped serer %s" % game_server_pid)
OS.kill(game_server_pid)
game_server_pid = -1
_poll_game_server_status()
else:
RivetPluginBridge.log("Server not running")

func _game_server_run_args() -> PackedStringArray:
var project_path = ProjectSettings.globalize_path("res://")
return ["--path", project_path, "--headless", "--", "--server"]

## Checks if the server process is still running.
func _poll_game_server_status():
# Check if server still running
if game_server_pid != -1 and !OS.is_process_running(game_server_pid):
RivetPluginBridge.log("Server process exited %s" % game_server_pid)
game_server_pid = -1

# Update stop button
if game_server_pid != -1:
game_server_poll_timer.paused = false
game_server_status_label.text = "Game server running (pid %s)" % game_server_pid
game_server_start_button.visible = false
game_server_stop_button.visible = true
game_server_restart_button.visible = true
game_server_status_label.visible = true
game_server_show_logs.visible = false
else:
game_server_poll_timer.paused = true
game_server_start_button.visible = true
game_server_stop_button.visible = false
game_server_restart_button.visible = false
game_server_status_label.visible = false
game_server_show_logs.visible = true

# MARK: Backend
func _on_backend_generate_sdk_pressed():
# TODO: Allow configuring this
Expand Down Expand Up @@ -286,73 +175,11 @@ func _full_cli_error_alert(title, cmd_result):
alert.popup_centered_ratio(0.4)
return

# MARK: Backend Server
func _on_backend_server_start_pressed():
start_backend_server()

func _on_backend_server_stop_pressed():
stop_backend_server()

func _on_backend_server_restart_pressed():
start_backend_server()

func start_backend_server():
if backend_server_pid != -1:
RivetPluginBridge.log("Restarting server, old pid %s" % backend_server_pid)
stop_backend_server()
func _on_manage_game_server_pressed():
# Focus the game server tab
RivetPluginBridge.get_plugin().focus_game_server.emit()

if backend_server_show_logs.button_pressed:
# Running with logs does not have a PID we can kill
backend_server_pid = -1

# Run via Rivet CLI to show the terminal. Get the PID from the process
# the Rivet CLI spawned.
var result = await RivetPluginBridge.get_plugin().cli.run_and_wait(["sidekick", "--show-terminal", "backend-dev"])
if result.exit_code != 0 or !("Ok" in result.output):
RivetPluginBridge.display_cli_error(self, result)
return
RivetPluginBridge.log("Started backend server with logs")
else:
# TODO: Use background thread for this in order to get output response
# Run natively without terminal
backend_server_pid = RivetPluginBridge.get_plugin().cli.run_with_pid(["sidekick", "backend-dev", "--capture-output", "--no-color"])
RivetPluginBridge.log("Started backend server without logs %s" % backend_server_pid)

_poll_backend_server_status()

func stop_backend_server():
if backend_server_pid != -1:
RivetPluginBridge.log("Stopped serer %s" % backend_server_pid)
OS.kill(backend_server_pid)
backend_server_pid = -1
_poll_backend_server_status()
else:
RivetPluginBridge.log("Server not running")

func _server_run_args() -> PackedStringArray:
var project_path = ProjectSettings.globalize_path("res://")
return ["--path", project_path, "--headless", "--", "--server"]

## Checks if the server process is still running.
func _poll_backend_server_status():
# Check if server still running
if backend_server_pid != -1 and !OS.is_process_running(backend_server_pid):
RivetPluginBridge.log("Server process exited %s" % backend_server_pid)
backend_server_pid = -1

# Update stop button
if backend_server_pid != -1:
backend_server_poll_timer.paused = false
backend_server_status_label.text = "Backend server running (pid %s)" % backend_server_pid
backend_server_start_button.visible = false
backend_server_stop_button.visible = true
backend_server_restart_button.visible = true
backend_server_status_label.visible = true
backend_server_show_logs.visible = false
else:
backend_server_poll_timer.paused = true
backend_server_start_button.visible = true
backend_server_stop_button.visible = false
backend_server_restart_button.visible = false
backend_server_status_label.visible = false
backend_server_show_logs.visible = true
func _on_manage_backend_pressed():
# Focus the backend tab
RivetPluginBridge.get_plugin().focus_backend.emit()
Loading

0 comments on commit 130c547

Please sign in to comment.