aboutsummaryrefslogtreecommitdiff
path: root/client/server.gd
blob: b236fa2a88584c84a62e3cebb262613a2bb2557d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# Hurry Curry! - a game about cooking
# Copyright 2024 metamuffin
# Copyright 2024 nokoe
# Copyright 2024 tpart
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, version 3 of the License only.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
class_name GameServer
extends Node

var thread = null
var pid = null

var state = State.TESTING
enum State {
	TESTING,
	UNAVAILABLE,
	FAILED,
	STOPPED,
	STARTING,
	RUNNING,
}

var sem = Semaphore.new()
var thread_result = null;

func _ready():
	state = State.TESTING
	thread = Thread.new()
	thread.start(_test_server)

func test():
	pass

func start():
	if state != State.STOPPED and state != State.FAILED:
		push_error("server cant be started")
		return
	state = State.STARTING
	thread = Thread.new()
	thread.start(_server_exec)

func stop():
	if state != State.RUNNING:
		push_error("server cant be stopped")
		return
	OS.kill(pid)

func _test_server():
	var output = []
	thread_result = OS.execute(get_server_path(), ["-v"], output, true, false)
	sem.post()

func _server_exec():
	var args = []
	var data_path = get_server_data()
	if data_path != null:
		args.push_back("--data-dir")
		args.push_back(data_path)
	thread_result = OS.create_process(get_server_path(), args, false)
	if thread_result >= 0:
		var ok = false
		while not ok:
			var conn = StreamPeerTCP.new()
			if conn.connect_to_host("127.0.0.1", 27032) == OK:
				while conn.poll() == OK:
					if conn.get_status() == StreamPeerTCP.STATUS_ERROR: break
					elif conn.get_status() == StreamPeerTCP.STATUS_CONNECTED: ok = true; break
					OS.delay_msec(10)
			OS.delay_msec(500 if not ok else 50)
			if !OS.is_process_running(thread_result):
				thread_result = -1
				break
	sem.post()

func get_server_path() -> String:
	var path: String = Global.get_setting("other.server_binary")
	if path != "":
		return path
	else:
		return "hurrycurry-server"

func get_server_data():
	var path: String = Global.get_setting("other.server_data")
	if path != "": return path
	else: return null

func _process(_delta):
	match state:
		State.TESTING:
			if sem.try_wait():
				print("Server: Test result=", thread_result)
				if thread_result == 0: state = State.STOPPED
				else: state = State.UNAVAILABLE
				thread.wait_to_finish()
				thread = null
		State.STARTING:
			if sem.try_wait():
				if thread_result >= 0:
					state = State.RUNNING
					pid = thread_result
					print("Server: Started pid=", thread_result)
				else:
					state = State.FAILED
					print("Server: Failed")
				thread.wait_to_finish()
				thread = null
		State.RUNNING:
			if not OS.is_process_running(pid):
				print("Server: Stopped")
				state = State.STOPPED
				pid = null

func _exit_tree():
	if thread != null: thread.wait_to_finish()
	if pid != null: OS.kill(pid)