hamncheese/hamncheese/peers.gd

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