multiplayer_and_some_card_art #2
3 changed files with 273 additions and 26 deletions
159
main.gd
159
main.gd
|
|
@ -1,6 +1,7 @@
|
|||
extends Node
|
||||
|
||||
const PORT = 25565
|
||||
const PORT_RANGE := 10
|
||||
const MAX_CONNECTIONS = 20
|
||||
|
||||
var counter = 0
|
||||
|
|
@ -8,31 +9,128 @@ var counter = 0
|
|||
@onready var before_connect_container = get_node("BeforeConnect") as Container
|
||||
@onready var host_text_edit = get_node("%HostTextEdit") as TextEdit
|
||||
@onready var connect_button = get_node("%ConnectButton") as Button
|
||||
@onready var host_button = get_node("%HostButton") as Button
|
||||
@onready var server_discovery = get_node("%ServerDiscovery") as ServerDiscovery
|
||||
|
||||
@onready var after_connect_container = get_node("%AfterConnect") as Container
|
||||
@onready var counter_label = get_node("%CounterLabel") as Label
|
||||
@onready var decrement_button = get_node("%DecrementButton") as Button
|
||||
@onready var increment_button = get_node("%IncrementButton") as Button
|
||||
@onready var disconnect_button = get_node("%DisconnectButton") as Button
|
||||
@onready var start_game_button = get_node("%StartGameButton") as Button
|
||||
|
||||
var active_port: int
|
||||
var server_buttons: Dictionary = Dictionary()
|
||||
|
||||
func _clean_room():
|
||||
# this is if someone left the room and we will just clean the game room again
|
||||
# should only called on host
|
||||
_set_counter(0)
|
||||
pass
|
||||
|
||||
func _on_start_game_clicked():
|
||||
if !multiplayer.multiplayer_peer:
|
||||
return
|
||||
if !multiplayer.get_unique_id() != 1:
|
||||
return
|
||||
if (multiplayer.get_peers().size() == 0):
|
||||
return
|
||||
# do start game here, should only run on host
|
||||
pass
|
||||
|
||||
func _ready() -> void:
|
||||
if OS.has_feature("dedicated_server"):
|
||||
print("Starting dedicated server")
|
||||
var peer = ENetMultiplayerPeer.new()
|
||||
var err = peer.create_server(PORT, MAX_CONNECTIONS)
|
||||
if err:
|
||||
print(err)
|
||||
multiplayer.multiplayer_peer = peer
|
||||
host_button.button_up.connect(_on_host_pressed)
|
||||
host_button.text = "Host (%s)" % server_discovery.id
|
||||
|
||||
start_game_button.button_up.connect(_on_start_game_clicked)
|
||||
|
||||
print("Attach client")
|
||||
multiplayer.peer_connected.connect(_on_player_connected)
|
||||
else:
|
||||
print("Game starting")
|
||||
#multiplayer.peer_disconnected.connect(_on_player_disconnected)
|
||||
multiplayer.peer_disconnected.connect(_on_player_disconnected)
|
||||
multiplayer.connected_to_server.connect(_on_connected_ok)
|
||||
#multiplayer.connection_failed.connect(_on_connected_fail)
|
||||
#multiplayer.server_disconnected.connect(_on_server_disconnected)
|
||||
multiplayer.server_disconnected.connect(_on_server_disconnected)
|
||||
|
||||
increment_button.button_up.connect(func(): _increment.rpc())
|
||||
decrement_button.button_up.connect(func(): _decrement.rpc())
|
||||
connect_button.button_up.connect(_on_connect_pressed)
|
||||
disconnect_button.button_up.connect(_on_disconnect_clicked)
|
||||
connect_button.get_parent().remove_child(connect_button)
|
||||
|
||||
server_discovery.server_added.connect(_on_server_added)
|
||||
server_discovery.server_removed.connect(_on_server_removed)
|
||||
|
||||
func _on_disconnect_clicked():
|
||||
if (multiplayer.is_server()):
|
||||
server_discovery.disable_server()
|
||||
multiplayer.peer_connected.disconnect(_on_player_connected)
|
||||
for peer_id in multiplayer.get_peers():
|
||||
multiplayer.disconnect_peer(peer_id)
|
||||
|
||||
multiplayer.multiplayer_peer = null
|
||||
|
||||
$BeforeConnect.visible = true
|
||||
$AfterConnect.visible = false
|
||||
|
||||
func _on_server_added(id, ip, port):
|
||||
print("%s | Server added %s %s" % [server_discovery.id, id, ip])
|
||||
|
||||
var button = connect_button.duplicate()
|
||||
before_connect_container.add_child(button)
|
||||
|
||||
var key = "%s|%s" % [id,ip]
|
||||
server_buttons[key] = button
|
||||
|
||||
button.text = "%s\nConnect\n%s:%d" % [id, ip, port]
|
||||
for conn in button.button_down.get_connections():
|
||||
button.button_down.disconnect(conn)
|
||||
|
||||
var _on_button_downed = func():
|
||||
_do_connect(ip, port)
|
||||
button.button_down.connect(_on_button_downed)
|
||||
|
||||
func _on_server_removed(id, ip):
|
||||
print("%s | Server removed %s %s" % [server_discovery.id, id, ip])
|
||||
|
||||
var key = "%s|%s" % [id,ip]
|
||||
var button = server_buttons[key]
|
||||
button.queue_free()
|
||||
server_buttons.erase(key)
|
||||
|
||||
func _do_connect(ip: String, port: int):
|
||||
var peer = ENetMultiplayerPeer.new()
|
||||
print("%s Connecting to %s:%d" % [server_discovery.id, ip, port])
|
||||
peer.create_client(ip, port)
|
||||
multiplayer.multiplayer_peer = peer
|
||||
|
||||
func _on_host_pressed():
|
||||
print("%s | Starting dedicated server" % server_discovery.id)
|
||||
var peer = ENetMultiplayerPeer.new()
|
||||
for offset in range(PORT_RANGE):
|
||||
if not is_port_available(PORT + offset):
|
||||
continue
|
||||
|
||||
active_port = PORT + offset
|
||||
var err = peer.create_server(active_port, MAX_CONNECTIONS)
|
||||
if err:
|
||||
print(err)
|
||||
break
|
||||
|
||||
multiplayer.multiplayer_peer = peer
|
||||
|
||||
_on_connected_ok()
|
||||
|
||||
server_discovery.enable_server(active_port)
|
||||
|
||||
func is_port_available(port: int) -> bool:
|
||||
var udp_peer = PacketPeerUDP.new()
|
||||
|
||||
var error = udp_peer.bind(port)
|
||||
|
||||
if error == OK:
|
||||
udp_peer.close()
|
||||
return true
|
||||
else:
|
||||
return false
|
||||
|
||||
@rpc("any_peer", "call_local")
|
||||
func _increment():
|
||||
|
|
@ -49,28 +147,45 @@ func _set_counter(value: int):
|
|||
counter = value
|
||||
counter_label.text = str(counter)
|
||||
|
||||
func _on_connect_pressed():
|
||||
var peer = ENetMultiplayerPeer.new()
|
||||
var parsed: PackedStringArray = host_text_edit.text.split(":")
|
||||
print("Connecting to ", parsed[0])
|
||||
peer.create_client(parsed[0] if not parsed[0].is_empty() else "localhost", int(parsed[1]) if parsed.size() > 1 else PORT)
|
||||
multiplayer.multiplayer_peer = peer
|
||||
|
||||
func _on_player_connected(id: int):
|
||||
if multiplayer.get_unique_id() == 1:
|
||||
_set_counter.rpc_id(id, counter)
|
||||
|
||||
func _on_player_disconnected():
|
||||
pass
|
||||
if (multiplayer.get_peers().size() > 0):
|
||||
start_game_button.text = "Start Game"
|
||||
server_discovery.disable_server()
|
||||
|
||||
func _on_player_disconnected(id):
|
||||
print("%s | _on_player_disconnected %s" % [server_discovery.id, id])
|
||||
|
||||
if multiplayer.get_unique_id() == id:
|
||||
$BeforeConnect.visible = true
|
||||
$AfterConnect.visible = false
|
||||
|
||||
if (id != 1 and multiplayer.get_unique_id() == 1):
|
||||
_clean_room()
|
||||
start_game_button.text = "Start Game (Not enough player)"
|
||||
server_discovery.enable_server(active_port)
|
||||
|
||||
func _on_connected_ok():
|
||||
$AfterConnect.visible = true
|
||||
$BeforeConnect.visible = false
|
||||
counter_label.text = str(counter)
|
||||
|
||||
if (multiplayer.is_server()):
|
||||
disconnect_button.text = "Disconnect (Host)"
|
||||
if start_game_button.get_parent() != after_connect_container:
|
||||
after_connect_container.add_child(start_game_button)
|
||||
else:
|
||||
disconnect_button.text = "Disconnect"
|
||||
if start_game_button.get_parent() == after_connect_container:
|
||||
after_connect_container.remove_child(start_game_button)
|
||||
|
||||
func _on_connected_fail():
|
||||
pass
|
||||
|
||||
func _on_server_disconnected():
|
||||
pass
|
||||
print("%s | _on_server_disconnected" % [server_discovery.id])
|
||||
$AfterConnect.visible = false
|
||||
$BeforeConnect.visible = true
|
||||
|
||||
|
|
|
|||
34
main.tscn
34
main.tscn
|
|
@ -1,6 +1,7 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://c7gn46af6whf8"]
|
||||
[gd_scene load_steps=3 format=3 uid="uid://c7gn46af6whf8"]
|
||||
|
||||
[ext_resource type="Script" path="res://main.gd" id="1_e0ud3"]
|
||||
[ext_resource type="Script" path="res://server_discovery.gd" id="2_hed18"]
|
||||
|
||||
[node name="Main" type="Control"]
|
||||
layout_mode = 3
|
||||
|
|
@ -33,12 +34,31 @@ layout_mode = 2
|
|||
size_flags_vertical = 3
|
||||
placeholder_text = "192.168.*.*"
|
||||
|
||||
[node name="RefreshButton" type="Button" parent="BeforeConnect"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 64)
|
||||
layout_mode = 2
|
||||
text = "Refresh"
|
||||
|
||||
[node name="HostButton" type="Button" parent="BeforeConnect"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 64)
|
||||
layout_mode = 2
|
||||
text = "Host"
|
||||
|
||||
[node name="ConnectButton" type="Button" parent="BeforeConnect"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 64)
|
||||
layout_mode = 2
|
||||
text = "Connect"
|
||||
|
||||
[node name="DiscoveryTimer" type="Timer" parent="BeforeConnect"]
|
||||
unique_name_in_owner = true
|
||||
|
||||
[node name="ServerDiscovery" type="Node" parent="BeforeConnect"]
|
||||
unique_name_in_owner = true
|
||||
script = ExtResource("2_hed18")
|
||||
|
||||
[node name="AfterConnect" type="VBoxContainer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
|
|
@ -64,6 +84,12 @@ text = "1"
|
|||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="DisconnectButton" type="Button" parent="AfterConnect"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Disconnect"
|
||||
|
||||
[node name="Actions" type="HBoxContainer" parent="AfterConnect"]
|
||||
layout_mode = 2
|
||||
|
||||
|
|
@ -78,3 +104,9 @@ unique_name_in_owner = true
|
|||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "+"
|
||||
|
||||
[node name="StartGameButton" type="Button" parent="AfterConnect"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Start Game"
|
||||
|
|
|
|||
100
server_discovery.gd
Normal file
100
server_discovery.gd
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
extends Node
|
||||
class_name ServerDiscovery
|
||||
|
||||
const PORT := 26566
|
||||
const PORT_RANGE := 10 # cannot listen to the same port on one device
|
||||
|
||||
signal server_added(id: String, ip: String, port: int)
|
||||
signal server_removed(id: String, ip: String)
|
||||
|
||||
var server: UDPServer = null
|
||||
var client: PacketPeerUDP = null
|
||||
var port_offset: int
|
||||
var id: String
|
||||
var servers: Array[String] = []
|
||||
var enabled := false
|
||||
|
||||
func enable_server(server_port: int):
|
||||
enabled = true
|
||||
var data = "%s|AVAILABLE|%d" %[id,server_port]
|
||||
_broadcast_packet(data.to_utf8_buffer())
|
||||
|
||||
func disable_server():
|
||||
enabled = false
|
||||
var data = "%s|NOT_AVAILABLE" %id
|
||||
_broadcast_packet(data.to_utf8_buffer())
|
||||
|
||||
func _ready():
|
||||
id = _generate_id()
|
||||
_init_server()
|
||||
_init_client()
|
||||
|
||||
func _process(_delta):
|
||||
server.poll()
|
||||
while(server.is_connection_available()):
|
||||
var peer = server.take_connection()
|
||||
while(peer.get_available_packet_count() > 0):
|
||||
var packet = peer.get_packet()
|
||||
var packet_str = packet.get_string_from_utf8()
|
||||
if (packet_str.begins_with(id)):
|
||||
continue
|
||||
|
||||
var ip = peer.get_packet_ip()
|
||||
var port = peer.get_packet_port()
|
||||
print(id, " | Received data from ", ip, ":", port, " => ", packet_str)
|
||||
|
||||
var data = packet_str.split("|")
|
||||
var conn_id = data[0]
|
||||
var conn_detail = data[1]
|
||||
var key = "%s:%s" %[ip, port]
|
||||
|
||||
if (conn_detail == "AVAILABLE" and key not in servers):
|
||||
var conn_actual_server_port = int(data[2])
|
||||
servers.append(key)
|
||||
server_added.emit(conn_id, ip, conn_actual_server_port)
|
||||
elif (conn_detail == "NOT_AVAILABLE" and key in servers):
|
||||
servers.erase(key)
|
||||
server_removed.emit(conn_id, ip)
|
||||
elif (conn_detail == "DISCOVERY" and enabled):
|
||||
var available_data = "%s|AVAILABLE" %id
|
||||
_broadcast_packet(available_data.to_utf8_buffer())
|
||||
|
||||
func _exit_tree():
|
||||
var data = "%s|NOT_AVAILABLE" %id
|
||||
_broadcast_packet(data.to_utf8_buffer())
|
||||
|
||||
func _init_server():
|
||||
server = UDPServer.new()
|
||||
|
||||
for offset in range(PORT_RANGE):
|
||||
var err = server.listen(PORT + offset)
|
||||
if !err:
|
||||
port_offset = offset
|
||||
break
|
||||
|
||||
print("Server ", id, " initialized on port ", PORT + port_offset)
|
||||
|
||||
func _init_client():
|
||||
client = PacketPeerUDP.new()
|
||||
client.set_broadcast_enabled(true)
|
||||
|
||||
var data = "%s|DISCOVERY" %id
|
||||
_broadcast_packet(data.to_utf8_buffer())
|
||||
|
||||
func _broadcast_packet(buffer: PackedByteArray):
|
||||
for offset in range(PORT_RANGE):
|
||||
client.connect_to_host("255.255.255.255", PORT + offset)
|
||||
client.put_packet(buffer)
|
||||
|
||||
func _generate_id() -> String:
|
||||
var id_len = 5
|
||||
var from = 'A'.unicode_at(0)
|
||||
var to = 'Z'.unicode_at(0)
|
||||
|
||||
var result:= ""
|
||||
|
||||
for i in range(id_len):
|
||||
var rand_char = char(randi_range(from, to))
|
||||
result += rand_char
|
||||
|
||||
return result
|
||||
Loading…
Add table
Add a link
Reference in a new issue