151 lines
3.7 KiB
GDScript
151 lines
3.7 KiB
GDScript
extends Node
|
|
|
|
|
|
var _server := UDPServer.new()
|
|
var _userInfo: Dictionary
|
|
var _pendingPackets: Array
|
|
var _metadataTimer: Timer
|
|
var _lastPeers: Array
|
|
|
|
# This array is of dictionary elements that contain:
|
|
# "online": Will be true except when used to update the array.
|
|
# "type": Either "pending" or "known", which is confusing.
|
|
# "ip": IP address of this peer.
|
|
# "user": User name on this IP.
|
|
# "refresh": Do we need to redraw this entry?
|
|
var peerArray: Array
|
|
|
|
|
|
func _metadataTimerTimeout():
|
|
if _server.is_listening():
|
|
var method = {}
|
|
# Request updated metadata from everyone on the network.
|
|
method["method"] = "query"
|
|
for peer in peerArray:
|
|
_sendTo(peer["ip"], method)
|
|
|
|
|
|
func _process(_delta):
|
|
if _server.is_listening():
|
|
# Handle incoming data.
|
|
_server.poll()
|
|
if _server.is_connection_available():
|
|
var client: PacketPeerUDP = _server.take_connection()
|
|
var packet = client.get_packet()
|
|
var clientIP = client.get_packet_ip()
|
|
var raw = packet.get_string_from_utf8()
|
|
var jsonIn = JSON.new()
|
|
var error = jsonIn.parse(raw)
|
|
# DEBUG
|
|
print("Raw: ", raw)
|
|
if error == OK:
|
|
# DEBUG
|
|
print("JSON In: ", jsonIn.data)
|
|
# Remote node wants our information.
|
|
if jsonIn.data["method"] == "query":
|
|
var payload = {}
|
|
payload["method"] = "queryResponse"
|
|
payload["user"] = _userInfo["user"]
|
|
client.put_packet(JSON.stringify(payload).to_utf8_buffer())
|
|
# Remote node replied to our query.
|
|
if jsonIn.data["method"] == "queryResponse":
|
|
for i in range(0, peerArray.size() - 1):
|
|
if peerArray[i]["ip"] == clientIP:
|
|
peerArray[i]["user"] = jsonIn.data["user"]
|
|
peerArray[i]["refresh"] = true
|
|
break
|
|
client.close()
|
|
|
|
# Handle outgoing data.
|
|
for outbound in _pendingPackets:
|
|
# DEBUG
|
|
print("Sending: ", outbound)
|
|
var destination := PacketPeerUDP.new()
|
|
destination.connect_to_host(outbound["ip"], _server.get_local_port())
|
|
var error = destination.put_packet(JSON.stringify(outbound["message"]).to_utf8_buffer())
|
|
if error:
|
|
print("Sending packet error: ", error)
|
|
destination.close()
|
|
_pendingPackets.clear()
|
|
|
|
|
|
func _ready():
|
|
clear()
|
|
_metadataTimer = Timer.new()
|
|
_metadataTimer.timeout.connect(_metadataTimerTimeout)
|
|
Engine.get_main_loop().current_scene.add_child(_metadataTimer)
|
|
_metadataTimer.start(5)
|
|
|
|
|
|
func _sendTo(ipAddress, message):
|
|
var pending = {}
|
|
pending["ip"] = ipAddress
|
|
pending["message"] = message
|
|
_pendingPackets.append(pending)
|
|
|
|
|
|
func _sort_by_ip(a, b):
|
|
#***TODO*** Sort numerically against last three digits.
|
|
if a["ip"] < b["ip"]:
|
|
return true
|
|
return false
|
|
|
|
|
|
func clear():
|
|
peerArray.clear()
|
|
|
|
|
|
func start_server(address, port, userInfo):
|
|
_userInfo = userInfo
|
|
if !_server.is_listening():
|
|
_server.listen(port, address)
|
|
_pendingPackets.clear()
|
|
|
|
|
|
func stop_server():
|
|
if _server.is_listening():
|
|
_server.stop()
|
|
|
|
|
|
func update(peers: Array):
|
|
var found
|
|
var newArray: Array = []
|
|
|
|
print("Real peers: ", peers.size())
|
|
|
|
peers.sort_custom(_sort_by_ip)
|
|
|
|
# Did the peer list change?
|
|
if Util.deep_equal(peers, _lastPeers):
|
|
# Does an existing peer need redrawn?
|
|
found = false
|
|
for peer in peerArray:
|
|
if peer["refresh"] == true:
|
|
peer["refresh"] = false
|
|
found = true
|
|
return found
|
|
|
|
# Add everyone connected.
|
|
for peer in peers:
|
|
# Do we have this peer's information?
|
|
found = false
|
|
for oldPeer in peerArray:
|
|
if oldPeer["ip"] == peer["ip"]:
|
|
print("Updating ", peer)
|
|
found = true
|
|
peer = oldPeer
|
|
if !found:
|
|
# We didn't have them. Add needed records.
|
|
peer["user"] = ""
|
|
peer["online"] = true
|
|
peer["refresh"] = false
|
|
# Add them to the new list.
|
|
newArray.append(peer)
|
|
|
|
# Use new array.
|
|
peerArray = newArray.duplicate(true)
|
|
|
|
# Remember this pass.
|
|
_lastPeers = peers.duplicate(true)
|
|
|
|
return true
|