From 73fbde7747ff5c5b120984fdb896adb3f5c2f696 Mon Sep 17 00:00:00 2001
From: Seth Fenske <fenskesd@gmail.com>
Date: Sat, 26 Apr 2025 16:06:26 -0500
Subject: [PATCH 1/2] Temp commit

---
 Host/Lobby/host.gd                 | 12 ----
 Host/Lobby/host.tscn               |  9 +++
 Host/Networking/SignalingServer.gd | 93 ++++++++++++++++--------------
 Host/Networking/rtc.gd             | 19 ++++++
 Host/TradingDay/trading_day.tscn   |  8 ++-
 addons/ez_rtc/RTCSingleton.gd      | 64 ++++++++++++++++++++
 addons/ez_rtc/RTCSingleton.gd.uid  |  1 +
 addons/ez_rtc/ez_rtc.gd            | 22 +++++++
 addons/ez_rtc/ez_rtc.gd.uid        |  1 +
 addons/ez_rtc/plugin.cfg           |  7 +++
 addons/ez_rtc/rtc_listener.gd      | 28 +++++++++
 addons/ez_rtc/rtc_listener.gd.uid  |  1 +
 project.godot                      |  9 +++
 13 files changed, 219 insertions(+), 55 deletions(-)
 create mode 100644 addons/ez_rtc/RTCSingleton.gd
 create mode 100644 addons/ez_rtc/RTCSingleton.gd.uid
 create mode 100644 addons/ez_rtc/ez_rtc.gd
 create mode 100644 addons/ez_rtc/ez_rtc.gd.uid
 create mode 100644 addons/ez_rtc/plugin.cfg
 create mode 100644 addons/ez_rtc/rtc_listener.gd
 create mode 100644 addons/ez_rtc/rtc_listener.gd.uid

diff --git a/Host/Lobby/host.gd b/Host/Lobby/host.gd
index 7203123..70298cb 100644
--- a/Host/Lobby/host.gd
+++ b/Host/Lobby/host.gd
@@ -1,5 +1,4 @@
 extends Control
-signal LobbyCodeChosen(code: String)
 
 @export var waitingScene: PackedScene
 
@@ -7,17 +6,6 @@ signal LobbyCodeChosen(code: String)
 
 func _ready():
 	get_tree().set_auto_accept_quit(false)
-	$SignalingServer.LobbyInUse.connect(_lobby_in_use)
-	$SignalingServer.LobbyConnected.connect(_lobby_connected)
-	$SignalingServer.PlayerJoined.connect(add_player)
-	$SignalingServer.PlayerLeft.connect(remove_player)
-	$SignalingServer.LobbyClosed.connect(_close_lobby)
-	$SignalingServer.OfferRecieved.connect($RTCPeer.session_description_received)
-	$SignalingServer.AnswerRecieved.connect($RTCPeer.session_description_received)
-	$SignalingServer.IceCandidateReceived.connect($RTCPeer.add_remote_ice_candidate)
-	
-	$RTCPeer.SendData.connect($SignalingServer.send_packet)
-		
 	IO.NewInputSource.connect(_handle_new_input_device)
 	IO.InputAssignedToPlayer.connect(_addPlayerByInputDevice)
 
diff --git a/Host/Lobby/host.tscn b/Host/Lobby/host.tscn
index 32af749..65620fb 100644
--- a/Host/Lobby/host.tscn
+++ b/Host/Lobby/host.tscn
@@ -104,3 +104,12 @@ layout_mode = 1
 [connection signal="pressed" from="VSplitContainer/CreateClose" to="." method="_on_create_close_pressed"]
 [connection signal="pressed" from="ControlBar/Play" to="." method="_on_play_pressed"]
 [connection signal="pressed" from="ControlBar/Quit" to="." method="_on_quit_pressed"]
+[connection signal="AnswerRecieved" from="SignalingServer" to="RTCPeer" method="session_description_received"]
+[connection signal="IceCandidateReceived" from="SignalingServer" to="RTCPeer" method="add_remote_ice_candidate"]
+[connection signal="LobbyClosed" from="SignalingServer" to="." method="_close_lobby"]
+[connection signal="LobbyConnected" from="SignalingServer" to="." method="_lobby_connected"]
+[connection signal="LobbyInUse" from="SignalingServer" to="." method="_lobby_in_use"]
+[connection signal="OfferRecieved" from="SignalingServer" to="RTCPeer" method="session_description_received"]
+[connection signal="PlayerJoined" from="SignalingServer" to="." method="add_player"]
+[connection signal="PlayerLeft" from="SignalingServer" to="." method="remove_player"]
+[connection signal="SendData" from="RTCPeer" to="SignalingServer" method="send_packet"]
diff --git a/Host/Networking/SignalingServer.gd b/Host/Networking/SignalingServer.gd
index c642170..f89cb0c 100644
--- a/Host/Networking/SignalingServer.gd
+++ b/Host/Networking/SignalingServer.gd
@@ -1,44 +1,24 @@
 extends Node
 
-@export var ADDRESS: = "fenske.page"
-@export var PORT: = 8916
-
-var peer = WebSocketMultiplayerPeer.new()
-var id: = 1
-
 # Called when the node enters the scene tree for the first time.
 func _ready():
-	connect_to_signaling_server()
+	RTCSingleton.SendSignalingData.connect(self.send_packet)
+	self.OfferRecieved.connect(RTCSingleton.SessionDescriptionReceived)
+	self.AnswerRecieved.connect(RTCSingleton.SessionDescriptionReceived)
+	self.IceCandidateReceived.connect(RTCSingleton.OnIceCandidateReceived)
+	Connect()
 
-signal OfferRecieved(type, sdp, remote_id)
-signal AnswerRecieved(type, sdp, remote_id)
-signal IceCandidateReceived(midName, indexName, sdpName, remoteId)
+#region Server Connection
+@export var ADDRESS: = "fenske.page"
+@export var PORT: = 8916
+var peer = WebSocketMultiplayerPeer.new()
 
-func _on_data_recieved(data: Dictionary):
-	if data.message == Globals.Message.id:
-		id = data.id
-		return
-	if data.message == Globals.Message.lobbyCreated:
-		_on_lobby_created(data)
-		return
-	if data.message == Globals.Message.lobbyUnavailable:
-		_on_lobby_unavailable()
-		return
-	if data.message == Globals.Message.playerJoined:
-		_on_player_joined(data)
-		return
-	if data.message == Globals.Message.playerLeft:
-		_on_player_left(data)
-		return
-	if data.message == Globals.Message.answer:
-		AnswerRecieved.emit("answer", data.sdp, data.id)
-		return
-	if data.message == Globals.Message.offer:
-		OfferRecieved.emit("offer", data.sdp, data.id)
-		return
-	if data.message == Globals.Message.candidate:
-		IceCandidateReceived.emit(data.mid, data.index, data.sdp, data.id)
-		return
+func Connect():
+	var err = peer.create_client("wss://%s:%s" % [ADDRESS, PORT])
+	if err != OK:
+		print("Encountered error code: %s" % err)
+	print("Connecting to wss://%s:%s" % [ADDRESS, PORT])
+#endregion
 
 #region Lobby
 signal LobbyInUse
@@ -79,7 +59,7 @@ func _on_player_left(data: Dictionary):
 
 #endregion
 
-#region Basic I/O
+#region Recieve Data
 func _process(_delta):
 	if !has_packets(): return
 	_on_data_recieved(get_packet_data())
@@ -92,15 +72,44 @@ func get_packet_data() -> Variant:
 	var packet = peer.get_packet()
 	if packet == null: return null
 	return JSON.parse_string(packet.get_string_from_utf8())
+#endregion
 
-func connect_to_signaling_server():
-	var err = peer.create_client("wss://%s:%s" % [ADDRESS, PORT])
-	if err != OK:
-		print("Encountered error code: %s" % err)
-	print("Connecting to wss://%s:%s" % [ADDRESS, PORT])
-
+#region Output
 func send_packet(data: Dictionary):
 	if !data.has("id"):
 		data["id"]=id
 	peer.put_packet(JSON.stringify(data).to_utf8_buffer())
 #endregion
+
+#region Logic
+signal OfferRecieved(type, sdp, remote_id)
+signal AnswerRecieved(type, sdp, remote_id)
+signal IceCandidateReceived(midName, indexName, sdpName, remoteId)
+var id: = 1
+
+func _on_data_recieved(data: Dictionary):
+	if data.message == Globals.Message.id:
+		id = data.id
+		return
+	if data.message == Globals.Message.lobbyCreated:
+		_on_lobby_created(data)
+		return
+	if data.message == Globals.Message.lobbyUnavailable:
+		_on_lobby_unavailable()
+		return
+	if data.message == Globals.Message.playerJoined:
+		_on_player_joined(data)
+		return
+	if data.message == Globals.Message.playerLeft:
+		_on_player_left(data)
+		return
+	if data.message == Globals.Message.answer:
+		AnswerRecieved.emit("answer", data.sdp, data.id)
+		return
+	if data.message == Globals.Message.offer:
+		OfferRecieved.emit("offer", data.sdp, data.id)
+		return
+	if data.message == Globals.Message.candidate:
+		IceCandidateReceived.emit(data.mid, data.index, data.sdp, data.id)
+		return
+#endregion
diff --git a/Host/Networking/rtc.gd b/Host/Networking/rtc.gd
index d96b223..26c5969 100644
--- a/Host/Networking/rtc.gd
+++ b/Host/Networking/rtc.gd
@@ -1,5 +1,21 @@
+@tool
 extends Node
 
+var OfflineTestFlag = "--offline"
+
+func _ready():
+	isTestingMode = OS.get_cmdline_args().find(OfflineTestFlag) > 0
+
+@onready var isTestingMode: = false
+func IsTestingMode():
+	return Engine.is_editor_hint() || isTestingMode
+
+func _enter_tree():
+	print("Enter Tree")
+
+func _exit_tree():
+	print("Exit Tree")
+
 var rtcPeer : = WebRTCMultiplayerPeer.new()
 
 signal DataReceived(playerId: String, data: Variant)
@@ -56,3 +72,6 @@ func SendData(data: Variant, peerId: int) -> void:
 	var channel: WebRTCDataChannel = channels[peerId]
 	channel.put_packet(data_buffer)
 #endregion
+
+func PutData(channel: WebRTCDataChannel, data: PackedByteArray):
+	channel.put_packet(data)
diff --git a/Host/TradingDay/trading_day.tscn b/Host/TradingDay/trading_day.tscn
index b697ae6..c8b42af 100644
--- a/Host/TradingDay/trading_day.tscn
+++ b/Host/TradingDay/trading_day.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=12 format=3 uid="uid://cje1yvapa41qv"]
+[gd_scene load_steps=13 format=3 uid="uid://cje1yvapa41qv"]
 
 [ext_resource type="Script" uid="uid://2wwwphpgxxp5" path="res://Host/TradingDay/background.gd" id="1_1xwot"]
 [ext_resource type="Script" uid="uid://e4fum3qxhatm" path="res://Host/TradingDay/Chart.gd" id="2_42rv4"]
@@ -11,6 +11,7 @@
 [ext_resource type="Script" uid="uid://cpeh82ihp5xpt" path="res://Host/TradingDay/Players.gd" id="7_1ys6b"]
 [ext_resource type="Script" uid="uid://c5j5s7p1gmkb1" path="res://Host/TradingDay/Price.gd" id="7_l1arb"]
 [ext_resource type="Script" uid="uid://mam3fov0mmuf" path="res://Host/TradingDay/card_controller.gd" id="10_vboce"]
+[ext_resource type="Script" uid="uid://dn42mjo1mdk54" path="res://addons/ez_rtc/rtc_listener.gd" id="12_l1arb"]
 
 [node name="TradingDay" type="Node2D"]
 script = ExtResource("1_1xwot")
@@ -71,6 +72,11 @@ GridNode = NodePath("../../Grid")
 [node name="CardController" type="Node" parent="."]
 script = ExtResource("10_vboce")
 
+[node name="RTCListener" type="Node" parent="."]
+process_mode = 4
+script = ExtResource("12_l1arb")
+metadata/_custom_type_script = "uid://dn42mjo1mdk54"
+
 [connection signal="ready" from="." to="." method="_on_ready"]
 [connection signal="DayFinished" from="Stocks" to="." method="DayFinished"]
 [connection signal="HourFinished" from="Stocks" to="Players" method="OnStockFinalized"]
diff --git a/addons/ez_rtc/RTCSingleton.gd b/addons/ez_rtc/RTCSingleton.gd
new file mode 100644
index 0000000..0babfa5
--- /dev/null
+++ b/addons/ez_rtc/RTCSingleton.gd
@@ -0,0 +1,64 @@
+extends Node
+
+signal SendSignalingData(data: Dictionary)
+var channels : Dictionary = {}
+var lobbyValue : = ""
+
+func AddDataChannel(connection: WebRTCDataChannel, playerId: int) -> void:
+	channels[playerId] = connection
+
+const STUN_SERVER_URL: = "stun:stun.l.google.com:19302"
+var rtcPeer : = WebRTCMultiplayerPeer.new()
+
+var serverCreated: = false
+func CreateRTCServer(lobby: String):
+	lobbyValue = lobby
+	# Skip if already instantiated
+	if serverCreated:
+		return
+	var err = RTC.rtcPeer.create_server()
+	serverCreated = true
+
+func CreateConnectionForPlayer(sourceId):
+	var peer = WebRTCPeerConnection.new()
+	peer.initialize({ "iceServers" : [{ "urls": [STUN_SERVER_URL] }] })
+	peer.session_description_created.connect(OnSessionCreated.bind(sourceId))
+	peer.ice_candidate_created.connect(OnIceCandidateCreated.bind(sourceId))
+	var connection = peer.create_data_channel("chat", {"negotiated": true, "id": 0})
+	AddDataChannel(connection, sourceId)
+	
+	RTC.rtcPeer.add_peer(peer, sourceId)
+	multiplayer.multiplayer_peer = RTC.rtcPeer
+
+#region Session
+func OnSessionCreated(type, sdp, remoteId):
+	self.rtcPeer.get_peer(remoteId).connection.set_local_description(type, sdp)
+	SendSignalingData.emit({
+		"message": Globals.Message.offer,
+		"lobbyValue": lobbyValue,
+		"type": type,
+		"sdp": sdp,
+		"remoteId": remoteId
+	})
+
+func SessionDescriptionReceived(type, sdp, remote_id: int):
+	self.rtcPeer.get_peer(remote_id).connection.set_remote_description(type, sdp)
+#endregion
+
+#region Ice Candidates
+# Relays the signal from WebRTCPeerConnection
+func OnIceCandidateCreated(midName, indexName, sdpName, remoteId):
+	SendSignalingData.emit({
+		"message" :  Globals.Message.candidate,
+		"lobbyValue": lobbyValue,
+		"mid": midName,
+		"index": indexName,
+		"sdp": sdpName,
+		"remoteId": remoteId
+	})
+
+# Adds the new ice candidate
+func OnIceCandidateReceived(midName, indexName, sdpName, remoteId):
+	var peer = self.rtcPeer.get_peer(remoteId)
+	peer.connection.add_ice_candidate(midName, indexName, sdpName)
+#endregion
diff --git a/addons/ez_rtc/RTCSingleton.gd.uid b/addons/ez_rtc/RTCSingleton.gd.uid
new file mode 100644
index 0000000..431a991
--- /dev/null
+++ b/addons/ez_rtc/RTCSingleton.gd.uid
@@ -0,0 +1 @@
+uid://bsvdkeq85k38o
diff --git a/addons/ez_rtc/ez_rtc.gd b/addons/ez_rtc/ez_rtc.gd
new file mode 100644
index 0000000..ee8dbce
--- /dev/null
+++ b/addons/ez_rtc/ez_rtc.gd
@@ -0,0 +1,22 @@
+@tool
+extends EditorPlugin
+
+#region RTC Listener Custom Type
+func _enter_tree():
+	# Register the RTC Listener
+	add_custom_type("RTCListener", "Node", preload("res://addons/ez_rtc/rtc_listener.gd"), preload("res://Assets/icon.svg"))
+
+func _exit_tree():
+	remove_custom_type("RTCListener")
+#region RTC Listener Custom Type
+
+#region RTC Global
+const GlobalName = "RTCSingleton"
+
+func _enable_plugin():
+	# The autoload can be a scene or script file.
+	add_autoload_singleton(GlobalName, "res://addons/ez_rtc/RTCSingleton.gd")
+
+func _disable_plugin():
+	remove_autoload_singleton(GlobalName)
+#endregion
diff --git a/addons/ez_rtc/ez_rtc.gd.uid b/addons/ez_rtc/ez_rtc.gd.uid
new file mode 100644
index 0000000..c102d17
--- /dev/null
+++ b/addons/ez_rtc/ez_rtc.gd.uid
@@ -0,0 +1 @@
+uid://qh3y8ihmsu0s
diff --git a/addons/ez_rtc/plugin.cfg b/addons/ez_rtc/plugin.cfg
new file mode 100644
index 0000000..fb7856e
--- /dev/null
+++ b/addons/ez_rtc/plugin.cfg
@@ -0,0 +1,7 @@
+[plugin]
+
+name="EZ RTC"
+description="A wrapper for the default Godot WebRTC exension which provides an easy way to establish RTC communication with a signaling server."
+author="Seth Fenske"
+version="1.0.0"
+script="ez_rtc.gd"
diff --git a/addons/ez_rtc/rtc_listener.gd b/addons/ez_rtc/rtc_listener.gd
new file mode 100644
index 0000000..0239162
--- /dev/null
+++ b/addons/ez_rtc/rtc_listener.gd
@@ -0,0 +1,28 @@
+@tool
+extends Node
+
+func _ready():
+	if RTC!= null && !RTC.IsTestingMode():
+		PutData.connect(RTC.SendData)
+		RTC.DataReceived.connect(self.RecieveData)
+
+func _enter_tree():
+	# Don't process RTC events until we are connected.
+	self.process_mode = ProcessMode.PROCESS_MODE_DISABLED
+
+#region Send Data
+signal PutData(channel: WebRTCDataChannel, data: PackedByteArray)
+
+func SendData(data: Variant) -> void:
+	var data_buffer: PackedByteArray = JSON.stringify(data).to_utf8_buffer()
+	PutData.emit(self.channel, data_buffer)
+#endregion
+
+#region Read Data
+@export var Sources: Array[String]
+signal DataReceived(sourceId: String, data: Variant)
+
+func RecieveData(sourceId: String, data: Variant):
+	if (Sources.find(sourceId) > 0):
+		DataReceived.emit(sourceId, data)
+#endregion
diff --git a/addons/ez_rtc/rtc_listener.gd.uid b/addons/ez_rtc/rtc_listener.gd.uid
new file mode 100644
index 0000000..c532d12
--- /dev/null
+++ b/addons/ez_rtc/rtc_listener.gd.uid
@@ -0,0 +1 @@
+uid://dn42mjo1mdk54
diff --git a/project.godot b/project.godot
index e6e3a5a..5bb68c6 100644
--- a/project.godot
+++ b/project.godot
@@ -22,6 +22,7 @@ Globals="*res://Host/Networking/Globals.gd"
 IO="*res://Input/io.gd"
 Settings="*res://Host/GameSate/Settings.gd"
 GameState="*res://Host/GameSate/GameState.gd"
+RTCSingleton="*res://addons/ez_rtc/RTCSingleton.gd"
 
 [display]
 
@@ -29,6 +30,14 @@ window/stretch/mode="viewport"
 window/stretch/aspect="ignore"
 window/emulate_touch_from_mouse=true
 
+[editor]
+
+run/main_run_args="--offline"
+
+[editor_plugins]
+
+enabled=PackedStringArray("res://addons/ez_rtc/plugin.cfg")
+
 [file_customization]
 
 folder_colors={
-- 
GitLab


From 1acb94fedf6cb6c9be228d899b61e70e1f9903b0 Mon Sep 17 00:00:00 2001
From: Seth Fenske <fenskesd@gmail.com>
Date: Sat, 3 May 2025 16:47:12 -0500
Subject: [PATCH 2/2] Back to working demo

---
 Host/GameSate/GameState.gd              |  4 +-
 Host/Lobby/host.gd                      | 13 ++---
 Host/Lobby/host.tscn                    | 14 +++---
 Host/Networking/RTCPeer.gd              | 59 -----------------------
 Host/Networking/RTCPeer.gd.uid          |  1 -
 Host/Networking/SignalingServer.gd      |  2 +-
 Host/SceneManager/scene_manager.gd      |  2 -
 Host/TradingDay/Players.gd              |  2 +-
 Host/TradingDay/Review/DayInReview.tscn |  8 +++-
 Host/TradingDay/Review/day_in_review.gd |  4 +-
 Host/TradingDay/Review/graph_point.gd   |  8 ++--
 Host/TradingDay/background.gd           | 21 ++++-----
 Host/TradingDay/grid.tscn               |  8 +---
 Host/TradingDay/player_data_listener.gd | 10 ++--
 Host/TradingDay/trading_day.tscn        | 15 ++++--
 Input/io.gd                             |  4 +-
 addons/ez_rtc/RTCSingleton.gd           | 62 ++++++++++++++++++++----
 addons/ez_rtc/rtc_listener.gd           | 63 +++++++++++++++++++++----
 project.godot                           |  6 +--
 19 files changed, 169 insertions(+), 137 deletions(-)
 delete mode 100644 Host/Networking/RTCPeer.gd
 delete mode 100644 Host/Networking/RTCPeer.gd.uid

diff --git a/Host/GameSate/GameState.gd b/Host/GameSate/GameState.gd
index 1e5587b..3cd8f1b 100644
--- a/Host/GameSate/GameState.gd
+++ b/Host/GameSate/GameState.gd
@@ -47,7 +47,9 @@ func SetHour(day: int, hour: int, data: TradingHourData):
 	return
 
 func GetHour(day: int, hour: int) -> TradingHourData:
-	var dayData = Days.get(day)
+	var dayData = null
+	if day >= 0:
+		dayData = Days.get(day)
 	if dayData == null:
 		return null
 	return GetHourFromData(dayData, hour)
diff --git a/Host/Lobby/host.gd b/Host/Lobby/host.gd
index 70298cb..9682f16 100644
--- a/Host/Lobby/host.gd
+++ b/Host/Lobby/host.gd
@@ -8,11 +8,12 @@ func _ready():
 	get_tree().set_auto_accept_quit(false)
 	IO.NewInputSource.connect(_handle_new_input_device)
 	IO.InputAssignedToPlayer.connect(_addPlayerByInputDevice)
+	connect_rtc()
 
-func connect_rtc(rtc: RTC):
-	self.SendData.connect(rtc.SendData)
-	$SignalingServer.PlayerJoined.connect(rtc.AddName)
-	rtc.DataReceived.connect(_listen_to_rtc_data)
+func connect_rtc():
+	self.SendData.connect($RTCListener.SendData)
+	$SignalingServer.PlayerJoined.connect($RTCListener.AddPlayerName)
+	$RTCListener.DataReceived.connect(_listen_to_rtc_data)
 
 #region Shutdown
 func _notification(what):
@@ -43,7 +44,7 @@ func _lobby_connected(lobbyCode: String):
 	$VSplitContainer/CreateClose.text = "Close Lobby"
 	host = false
 	lobby_code = lobbyCode
-	$RTCPeer.create_rtc_server(lobbyCode)
+	$RTCListener.CreateLobby(lobbyCode)
 
 func _close_lobby():
 	for player in $Players.get_children():
@@ -97,7 +98,7 @@ func _addPlayerByInputDevice(playerId: String, input: IO.InputSource):
 	$Players.add_child(playerLabel)
 
 func add_player(playerNumber:int, player_name):
-	$RTCPeer.create_connection_for_player(playerNumber)
+	$RTCListener.CreateConnectionForPlayer(playerNumber)
 
 func _listen_to_rtc_data(id: String, data: Variant):
 	print("%s, %s" % [id, data])
diff --git a/Host/Lobby/host.tscn b/Host/Lobby/host.tscn
index 65620fb..c9ad7ac 100644
--- a/Host/Lobby/host.tscn
+++ b/Host/Lobby/host.tscn
@@ -3,8 +3,8 @@
 [ext_resource type="Script" uid="uid://cgey0jytirsj2" path="res://Host/Lobby/host.gd" id="1_janmn"]
 [ext_resource type="Script" uid="uid://cx616v3q25qt8" path="res://Host/Networking/SignalingServer.gd" id="2_cdhtb"]
 [ext_resource type="PackedScene" uid="uid://cho5kftxmyvd7" path="res://Client/ClientWaiting.tscn" id="2_jjtug"]
-[ext_resource type="Script" uid="uid://dd36r0cpk568y" path="res://Host/Networking/RTCPeer.gd" id="3_vjxk6"]
 [ext_resource type="PackedScene" uid="uid://stub6ra523l5" path="res://Host/Lobby/NewInputDevice.tscn" id="5_bhg8j"]
+[ext_resource type="Script" uid="uid://dn42mjo1mdk54" path="res://addons/ez_rtc/rtc_listener.gd" id="6_lqk0a"]
 [ext_resource type="PackedScene" uid="uid://5oprdqg6eaev" path="res://Host/Menu/SettingsButton.tscn" id="8_jssyn"]
 
 [node name="Lobby" type="Control"]
@@ -94,22 +94,20 @@ scale = Vector2(0.25, 0.25)
 [node name="SignalingServer" type="Node" parent="."]
 script = ExtResource("2_cdhtb")
 
-[node name="RTCPeer" type="Node" parent="."]
-script = ExtResource("3_vjxk6")
-
 [node name="Settings" parent="." instance=ExtResource("8_jssyn")]
 layout_mode = 1
 
+[node name="RTCListener" type="Node" parent="."]
+process_mode = 4
+script = ExtResource("6_lqk0a")
+metadata/_custom_type_script = "uid://dn42mjo1mdk54"
+
 [connection signal="text_submitted" from="VSplitContainer/LobbyInfoBar/LobyCodeEditor" to="." method="_on_loby_code_editor_text_submitted"]
 [connection signal="pressed" from="VSplitContainer/CreateClose" to="." method="_on_create_close_pressed"]
 [connection signal="pressed" from="ControlBar/Play" to="." method="_on_play_pressed"]
 [connection signal="pressed" from="ControlBar/Quit" to="." method="_on_quit_pressed"]
-[connection signal="AnswerRecieved" from="SignalingServer" to="RTCPeer" method="session_description_received"]
-[connection signal="IceCandidateReceived" from="SignalingServer" to="RTCPeer" method="add_remote_ice_candidate"]
 [connection signal="LobbyClosed" from="SignalingServer" to="." method="_close_lobby"]
 [connection signal="LobbyConnected" from="SignalingServer" to="." method="_lobby_connected"]
 [connection signal="LobbyInUse" from="SignalingServer" to="." method="_lobby_in_use"]
-[connection signal="OfferRecieved" from="SignalingServer" to="RTCPeer" method="session_description_received"]
 [connection signal="PlayerJoined" from="SignalingServer" to="." method="add_player"]
 [connection signal="PlayerLeft" from="SignalingServer" to="." method="remove_player"]
-[connection signal="SendData" from="RTCPeer" to="SignalingServer" method="send_packet"]
diff --git a/Host/Networking/RTCPeer.gd b/Host/Networking/RTCPeer.gd
deleted file mode 100644
index 0e2dfea..0000000
--- a/Host/Networking/RTCPeer.gd
+++ /dev/null
@@ -1,59 +0,0 @@
-extends Node
-signal SendData(data: Dictionary)
-
-@export var url: = "stun:stun.l.google.com:19302"
-
-var lobbyValue : = ""
-
-@onready var serverCreated = false
-func create_rtc_server(lobby: String):
-	lobbyValue = lobby
-	# Skip if already instantiated
-	if serverCreated:
-		return
-	var err = RTC.rtcPeer.create_server()
-	serverCreated = true
-
-func create_connection_for_player(playerId):
-	var peer = WebRTCPeerConnection.new()
-	peer.initialize({
-		"iceServers" : [{ "urls": [url] }]
-	})
-	peer.session_description_created.connect(_on_session_created.bind(playerId))
-	peer.ice_candidate_created.connect(ice_candidate_created.bind(playerId))
-	var connection = peer.create_data_channel("chat", {"negotiated": true, "id": 0})
-	RTC.AddDataChannel(connection, playerId)
-	
-	RTC.rtcPeer.add_peer(peer, playerId)
-	multiplayer.multiplayer_peer = RTC.rtcPeer
-
-#region Session
-func _on_session_created(type, sdp, remoteId):
-	RTC.rtcPeer.get_peer(remoteId).connection.set_local_description(type, sdp)
-	SendData.emit({
-		"message": Globals.Message.offer,
-		"lobbyValue": lobbyValue,
-		"type": type,
-		"sdp": sdp,
-		"remoteId": remoteId
-	})
-
-func session_description_received(type, sdp, remote_id: int):
-	RTC.rtcPeer.get_peer(remote_id).connection.set_remote_description(type, sdp)
-#endregion
-
-#region Ice Candidates
-func ice_candidate_created(midName, indexName, sdpName, remoteId):
-	SendData.emit({
-		"message" :  Globals.Message.candidate,
-		"lobbyValue": lobbyValue,
-		"mid": midName,
-		"index": indexName,
-		"sdp": sdpName,
-		"remoteId": remoteId
-	})
-
-func add_remote_ice_candidate(midName, indexName, sdpName, remoteId):
-	var peer = RTC.rtcPeer.get_peer(remoteId)
-	peer.connection.add_ice_candidate(midName, indexName, sdpName)
-#endregion
diff --git a/Host/Networking/RTCPeer.gd.uid b/Host/Networking/RTCPeer.gd.uid
deleted file mode 100644
index 883a600..0000000
--- a/Host/Networking/RTCPeer.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://dd36r0cpk568y
diff --git a/Host/Networking/SignalingServer.gd b/Host/Networking/SignalingServer.gd
index f89cb0c..678c6e1 100644
--- a/Host/Networking/SignalingServer.gd
+++ b/Host/Networking/SignalingServer.gd
@@ -49,7 +49,7 @@ func close_lobby(lobbyValue: String):
 
 #region Players
 
-signal PlayerJoined(id:int, name: String)
+signal PlayerJoined(id:String, name: String)
 func _on_player_joined(data: Dictionary):
 	PlayerJoined.emit(data.id, data.name)
 
diff --git a/Host/SceneManager/scene_manager.gd b/Host/SceneManager/scene_manager.gd
index 9688859..b6ad48b 100644
--- a/Host/SceneManager/scene_manager.gd
+++ b/Host/SceneManager/scene_manager.gd
@@ -19,8 +19,6 @@ func Transition(currentScene: Node, nextScene: Globals.Scene):
 	var nextNode = next.instantiate()
 	if nextNode.has_signal("ChangeScene"):
 		nextNode.ChangeScene.connect(self.Transition)
-	if nextNode.has_method("connect_rtc"):
-		nextNode.connect_rtc(RTC)
 	add_child(nextNode)
 
 @export var Lobby: PackedScene
diff --git a/Host/TradingDay/Players.gd b/Host/TradingDay/Players.gd
index 63ba24a..a00fcce 100644
--- a/Host/TradingDay/Players.gd
+++ b/Host/TradingDay/Players.gd
@@ -4,7 +4,7 @@ var playerCount: = 0
 var playerKeys: Array
 func SetPlayerIds(keys: Array):
 	playerCount = keys.size()
-	playerKeys = keys
+	playerKeys = keys.duplicate()
 
 #region Stock Events
 @onready var price: = 0
diff --git a/Host/TradingDay/Review/DayInReview.tscn b/Host/TradingDay/Review/DayInReview.tscn
index 2755423..2098266 100644
--- a/Host/TradingDay/Review/DayInReview.tscn
+++ b/Host/TradingDay/Review/DayInReview.tscn
@@ -1,10 +1,11 @@
-[gd_scene load_steps=6 format=3 uid="uid://djleiwvsjar00"]
+[gd_scene load_steps=7 format=3 uid="uid://djleiwvsjar00"]
 
 [ext_resource type="Script" uid="uid://c2t0lwc31q58q" path="res://Host/TradingDay/Review/day_in_review.gd" id="1_vrwym"]
 [ext_resource type="PackedScene" uid="uid://bpjkcgbdtro3t" path="res://Host/TradingDay/Review/graph_point.tscn" id="2_8ika2"]
 [ext_resource type="Script" uid="uid://bafcw1hgepl0i" path="res://Host/TradingDay/Review/trading_day_data_provider.gd" id="2_c0n8j"]
 [ext_resource type="PackedScene" uid="uid://5pdwl8tk8dkk" path="res://Host/TradingDay/grid.tscn" id="4_8ika2"]
 [ext_resource type="Resource" uid="uid://dhy62t0y1olif" path="res://Host/TradingDay/Review/ResourceDefinitions/TradingDay1.tres" id="4_cnvyh"]
+[ext_resource type="Script" uid="uid://dn42mjo1mdk54" path="res://addons/ez_rtc/rtc_listener.gd" id="6_nuag1"]
 
 [node name="DayInReview" type="Node2D"]
 script = ExtResource("1_vrwym")
@@ -51,5 +52,10 @@ position = Vector2(840, 0)
 [node name="SpawnPoint8" type="Node2D" parent="Grid"]
 position = Vector2(960, 0)
 
+[node name="RTCListener" type="Node" parent="."]
+process_mode = 4
+script = ExtResource("6_nuag1")
+metadata/_custom_type_script = "uid://dn42mjo1mdk54"
+
 [connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"]
 [connection signal="timeout" from="TransitionTimer" to="." method="_on_transition_timer_timeout"]
diff --git a/Host/TradingDay/Review/day_in_review.gd b/Host/TradingDay/Review/day_in_review.gd
index 99827b6..32e2239 100644
--- a/Host/TradingDay/Review/day_in_review.gd
+++ b/Host/TradingDay/Review/day_in_review.gd
@@ -10,9 +10,7 @@ func _ready():
 			_graph_next_hour()
 	_begin_animation()
 	Max = $TradingDayDataProvider.GetMaxValue(day)
-
-func connect_rtc(rtc: RTC):
-	playerCount = rtc.GetPlayerCount()
+	playerCount = $RTCListener.GetPlayerCount()
 
 #region Node Configuration
 func _get_configuration_warnings():
diff --git a/Host/TradingDay/Review/graph_point.gd b/Host/TradingDay/Review/graph_point.gd
index 5e4a33e..d63dae1 100644
--- a/Host/TradingDay/Review/graph_point.gd
+++ b/Host/TradingDay/Review/graph_point.gd
@@ -23,12 +23,12 @@ func _notification(what: int) -> void:
 func SetNewMaxHeight(newHeight: int):
 	Maximum = newHeight
 
-var height
+var _height
 @export var Height: int:
 	get():
-		return height
+		return _height
 	set(value):
-		height = value
+		_height = value
 		recalculate_position()
 
 var maximum: = 100
@@ -71,7 +71,7 @@ signal AnimationFinished(node: Node)
 func StartAnimation():
 	$AnimationPlayer.play("RiseUp")
 
-func _on_animation_player_animation_finished(anim_name):
+func _on_animation_player_animation_finished(_anim_name):
 	AnimationFinished.emit(self)
 
 #endregion
diff --git a/Host/TradingDay/background.gd b/Host/TradingDay/background.gd
index 44d17b0..59c03d0 100644
--- a/Host/TradingDay/background.gd
+++ b/Host/TradingDay/background.gd
@@ -7,7 +7,7 @@ func _ready():
 	$Grid.generate_graph()
 	if Engine.is_editor_hint():
 		return
-	connect_rtc(RTC)
+	connect_rtc()
 	send_input_scenes(GameState.CurrentDay)
 
 func _on_ready():
@@ -70,29 +70,28 @@ func _on_grid_stock_value_changed(value):
 
 #region Networking
 
-signal SendVariable(name: String, value: Variant)
-signal SendData(dict: Variant, peerId: String)
+signal SendData(dict: Variant, peerId: int)
 signal SendDataToAllPlayers(dict: Variant)
 
 var playerIds: Array
-func connect_rtc(rtc: RTC):
-	SendVariable.connect(rtc.SendVariable.bind(-1)) # -1 Sends to all players
-	SendData.connect(rtc.SendData)
-	SendDataToAllPlayers.connect(rtc.SendDataToAllPlayers)
-	playerIds = rtc.Get_Player_Ids().duplicate()
-	$Players.SetPlayerIds(rtc.rtcPeer.get_peers().keys())
+func connect_rtc():
+	SendData.connect($RTCListener.SendData)
+	SendDataToAllPlayers.connect($RTCListener.SendDataToAllPlayers)
+	self.playerIds = $RTCListener.Get_Player_Ids().duplicate()
+	$Players.SetPlayerIds(self.playerIds)
 
 ## Sends stock purchase scene to all players except for
 ## the [param controller_player] player. They become the stock controller.
 func send_input_scenes(controller_player: int):
+	print("Player %s" % controller_player)
 	var dict = {
 			"type": "game_event",
 			"game_event": "load_scene",
 			"scene": var_to_bytes_with_objects(inputScene)
 	}
 	
-	var player1 = playerIds.get(controller_player)
-	playerIds.remove_at(controller_player)
+	var player1 = self.playerIds.get(controller_player)
+	self.playerIds.remove_at(controller_player)
 	for playerId in playerIds:
 		SendData.emit(dict, playerId)
 	SendData.emit({
diff --git a/Host/TradingDay/grid.tscn b/Host/TradingDay/grid.tscn
index 33ba067..94a51fb 100644
--- a/Host/TradingDay/grid.tscn
+++ b/Host/TradingDay/grid.tscn
@@ -1,15 +1,11 @@
-[gd_scene load_steps=3 format=3 uid="uid://5pdwl8tk8dkk"]
+[gd_scene load_steps=2 format=3 uid="uid://5pdwl8tk8dkk"]
 
 [ext_resource type="Script" uid="uid://e4fum3qxhatm" path="res://Host/TradingDay/Chart.gd" id="1_nnkdj"]
-[ext_resource type="FontFile" uid="uid://bu02jdmdcoi8j" path="res://Assets/DS-DIGIT.TTF" id="2_lf1ob"]
 
-[node name="Grid" type="Node2D" node_paths=PackedStringArray("StocksNode")]
+[node name="Grid" type="Node2D"]
 script = ExtResource("1_nnkdj")
 LineColor = Color(0.745098, 0.745098, 0.745098, 1)
 LineThickness = 1
 Columns = 9
 Rows = 10
-CustomFont = ExtResource("2_lf1ob")
-StockValue = 345
 StockLocation = Vector2(0, 91)
-StocksNode = NodePath("")
diff --git a/Host/TradingDay/player_data_listener.gd b/Host/TradingDay/player_data_listener.gd
index 7b7d907..1a2be38 100644
--- a/Host/TradingDay/player_data_listener.gd
+++ b/Host/TradingDay/player_data_listener.gd
@@ -5,17 +5,17 @@ extends Node
 @export var PlayerContainer: Node
 @export var GridNode: Node
 
-func connect_rtc(rtc: RTC):
-	rtc.DataReceived.connect(_on_data_received)
-	self.SendData.connect(rtc.SendData)
+func _ready():
+	$RTCListener.DataReceived.connect(_on_data_received)
+	self.SendData.connect($RTCListener.SendData)
 	var index = 0
-	for playerId in rtc.rtcPeer.get_peers().keys():
+	for playerId in $RTCListener.Get_Player_Ids():
 		var player: Node2D = PlayerContainer.get_child(index)
 		var data: = GameState.GetPlayerData(GameState.CurrentDay - 1, 7, str(index))
 		player.visible = true
 		player.Cash = 500
 		player.Id = playerId
-		player.PlayerName = rtc.names[playerId]
+		player.PlayerName = $RTCListener.GetPlayerName(str(playerId))
 		players[playerId] = player
 		index = index + 1
 		if data != null:
diff --git a/Host/TradingDay/trading_day.tscn b/Host/TradingDay/trading_day.tscn
index c8b42af..9e58ca2 100644
--- a/Host/TradingDay/trading_day.tscn
+++ b/Host/TradingDay/trading_day.tscn
@@ -2,10 +2,10 @@
 
 [ext_resource type="Script" uid="uid://2wwwphpgxxp5" path="res://Host/TradingDay/background.gd" id="1_1xwot"]
 [ext_resource type="Script" uid="uid://e4fum3qxhatm" path="res://Host/TradingDay/Chart.gd" id="2_42rv4"]
-[ext_resource type="PackedScene" uid="uid://d37m47k7c63s8" path="res://Client/StockPurchase.tscn" id="2_o8tlr"]
+[ext_resource type="PackedScene" uid="uid://d37m47k7c63s8" path="res://Client/StockPurchase.tscn" id="2_l1arb"]
 [ext_resource type="PackedScene" uid="uid://8v120xs2a14u" path="res://Host/TradingDay/stocks.tscn" id="3_42rv4"]
 [ext_resource type="FontFile" uid="uid://bu02jdmdcoi8j" path="res://Assets/DS-DIGIT.TTF" id="3_eefjg"]
-[ext_resource type="PackedScene" uid="uid://2gam1pehc15e" path="res://Client/StockController.tscn" id="3_u36li"]
+[ext_resource type="PackedScene" uid="uid://2gam1pehc15e" path="res://Client/StockController.tscn" id="3_vw4lc"]
 [ext_resource type="PackedScene" uid="uid://dxseh3d20m3yf" path="res://Host/TradingDay/PlayerDisplay/player_money_display.tscn" id="4_0fjvf"]
 [ext_resource type="Script" uid="uid://bv4ovpaoojdx3" path="res://Host/TradingDay/player_data_listener.gd" id="5_42rv4"]
 [ext_resource type="Script" uid="uid://cpeh82ihp5xpt" path="res://Host/TradingDay/Players.gd" id="7_1ys6b"]
@@ -15,9 +15,9 @@
 
 [node name="TradingDay" type="Node2D"]
 script = ExtResource("1_1xwot")
-Background = Color(0.0823529, 0.34902, 0.576471, 0.823529)
-InputScene = ExtResource("2_o8tlr")
-PriceFixingInput = ExtResource("3_u36li")
+Background = Color(6.97896e-07, 0.278181, 0.376653, 1)
+InputScene = ExtResource("2_l1arb")
+PriceFixingInput = ExtResource("3_vw4lc")
 NextScene = 2
 
 [node name="Grid" type="Node2D" parent="." node_paths=PackedStringArray("StocksNode")]
@@ -69,6 +69,11 @@ script = ExtResource("5_42rv4")
 PlayerContainer = NodePath("..")
 GridNode = NodePath("../../Grid")
 
+[node name="RTCListener" type="Node" parent="Players/PlayerDataListener"]
+process_mode = 4
+script = ExtResource("12_l1arb")
+metadata/_custom_type_script = "uid://dn42mjo1mdk54"
+
 [node name="CardController" type="Node" parent="."]
 script = ExtResource("10_vboce")
 
diff --git a/Input/io.gd b/Input/io.gd
index 26e7b89..83aa1bc 100644
--- a/Input/io.gd
+++ b/Input/io.gd
@@ -3,7 +3,7 @@ extends Node
 var PlayerInputs = {}
 
 func _ready():
-	RTC.DataReceived.connect(_rtcInput)
+	RTCSingleton.DataReceived.connect(_rtcInput)
 
 #region Detect New Input Devices
 signal NewInputSource(InputSource)
@@ -23,7 +23,7 @@ func _input(event: InputEvent):
 
 func _rtcInput(peerId: String, _data: Variant):
 	if isNewRTCDevice(peerId):
-		var newRtcDevice = RTCInput.Create(RTC.channels[int(peerId)], RTC.names[int(peerId)])
+		var newRtcDevice = RTCInput.Create(RTCSingleton.channels[peerId], RTCSingleton.GetPlayerName(peerId))
 		NewInputSource.emit(newRtcDevice)
 
 #endregion
diff --git a/addons/ez_rtc/RTCSingleton.gd b/addons/ez_rtc/RTCSingleton.gd
index 0babfa5..93ed463 100644
--- a/addons/ez_rtc/RTCSingleton.gd
+++ b/addons/ez_rtc/RTCSingleton.gd
@@ -1,11 +1,23 @@
+@tool
 extends Node
 
 signal SendSignalingData(data: Dictionary)
 var channels : Dictionary = {}
 var lobbyValue : = ""
+const OfflineTestFlag = "--offline"
 
-func AddDataChannel(connection: WebRTCDataChannel, playerId: int) -> void:
-	channels[playerId] = connection
+func _ready():
+	isTestingMode = OS.get_cmdline_args().find(OfflineTestFlag) > 0
+
+@onready var isTestingMode: = false
+func IsTestingMode():
+	return Engine.is_editor_hint() || isTestingMode
+
+func AddDataChannel(connection: WebRTCDataChannel, playerId: String) -> void:
+	self.channels[playerId] = connection
+
+func GetDataChannel(playerId: int) -> WebRTCDataChannel:
+	return self.channels[str(playerId)]
 
 const STUN_SERVER_URL: = "stun:stun.l.google.com:19302"
 var rtcPeer : = WebRTCMultiplayerPeer.new()
@@ -16,19 +28,19 @@ func CreateRTCServer(lobby: String):
 	# Skip if already instantiated
 	if serverCreated:
 		return
-	var err = RTC.rtcPeer.create_server()
+	var err = self.rtcPeer.create_server()
 	serverCreated = true
 
-func CreateConnectionForPlayer(sourceId):
+func CreateConnectionForPlayer(sourceId: int):
 	var peer = WebRTCPeerConnection.new()
 	peer.initialize({ "iceServers" : [{ "urls": [STUN_SERVER_URL] }] })
 	peer.session_description_created.connect(OnSessionCreated.bind(sourceId))
 	peer.ice_candidate_created.connect(OnIceCandidateCreated.bind(sourceId))
 	var connection = peer.create_data_channel("chat", {"negotiated": true, "id": 0})
-	AddDataChannel(connection, sourceId)
+	AddDataChannel(connection, str(sourceId))
 	
-	RTC.rtcPeer.add_peer(peer, sourceId)
-	multiplayer.multiplayer_peer = RTC.rtcPeer
+	self.rtcPeer.add_peer(peer, sourceId)
+	multiplayer.multiplayer_peer = self.rtcPeer
 
 #region Session
 func OnSessionCreated(type, sdp, remoteId):
@@ -42,7 +54,9 @@ func OnSessionCreated(type, sdp, remoteId):
 	})
 
 func SessionDescriptionReceived(type, sdp, remote_id: int):
-	self.rtcPeer.get_peer(remote_id).connection.set_remote_description(type, sdp)
+	var peer = self.rtcPeer.get_peer(remote_id)
+	print(self.rtcPeer.get_peers())
+	peer.connection.set_remote_description(type, sdp)
 #endregion
 
 #region Ice Candidates
@@ -62,3 +76,35 @@ func OnIceCandidateReceived(midName, indexName, sdpName, remoteId):
 	var peer = self.rtcPeer.get_peer(remoteId)
 	peer.connection.add_ice_candidate(midName, indexName, sdpName)
 #endregion
+
+signal DataReceived(playerId: String, data: Variant)
+func _process(_delta: float) -> void:
+	for peerId: int in rtcPeer.get_peers().keys():
+		var connection: WebRTCPeerConnection = rtcPeer.get_peer(peerId).connection
+		var channel: WebRTCDataChannel = self.channels[str(peerId)]
+		connection.poll()
+		if channel.get_ready_state() == WebRTCDataChannel.STATE_OPEN:
+			if channel.get_available_packet_count() > 0:
+				var jsonString: = channel.get_packet().get_string_from_utf8()
+				var data: Variant = JSON.parse_string(jsonString)
+				DataReceived.emit(str(peerId), data)
+
+func SendData(channel: WebRTCDataChannel, data: Variant) -> void:
+	var data_buffer: PackedByteArray = JSON.stringify(data).to_utf8_buffer()
+	channel.put_packet(data_buffer)
+
+# TODO: This should probably not be handled here. The end goal should be that
+# each RTC nodes only handles traffic to that specific player.
+func SendDataToAllPlayers(data: Variant) -> void:
+	var data_buffer: PackedByteArray = JSON.stringify(data).to_utf8_buffer()
+	for peerId: int in rtcPeer.get_peers().keys():
+		var channel: WebRTCDataChannel = channels[str(peerId)]
+		channel.put_packet(data_buffer)
+
+func GetPlayerName(playerId: String) -> String:
+	return self.names[playerId]
+
+var names : Dictionary = {}
+func AddName(playerNumber:String, player_name: String) -> void:
+	names[playerNumber] = player_name
+	DataReceived.emit(str(playerNumber), player_name)
diff --git a/addons/ez_rtc/rtc_listener.gd b/addons/ez_rtc/rtc_listener.gd
index 0239162..89d242e 100644
--- a/addons/ez_rtc/rtc_listener.gd
+++ b/addons/ez_rtc/rtc_listener.gd
@@ -2,20 +2,55 @@
 extends Node
 
 func _ready():
-	if RTC!= null && !RTC.IsTestingMode():
-		PutData.connect(RTC.SendData)
-		RTC.DataReceived.connect(self.RecieveData)
+	if RTCSingleton!= null && !RTCSingleton.IsTestingMode():
+		PutData.connect(RTCSingleton.SendData)
+		RTCSingleton.DataReceived.connect(self.RecieveData)
 
 func _enter_tree():
 	# Don't process RTC events until we are connected.
 	self.process_mode = ProcessMode.PROCESS_MODE_DISABLED
 
+func CreateLobby(lobbyCode: String):
+	RTCSingleton.CreateRTCServer(lobbyCode)
+
+func CreateConnectionForPlayer(playerId: int):
+	RTCSingleton.CreateConnectionForPlayer(playerId)
+
+func AddPlayerName(playerId: int, name: String):
+	RTCSingleton.AddName(str(playerId), name)
+
 #region Send Data
 signal PutData(channel: WebRTCDataChannel, data: PackedByteArray)
 
-func SendData(data: Variant) -> void:
-	var data_buffer: PackedByteArray = JSON.stringify(data).to_utf8_buffer()
-	PutData.emit(self.channel, data_buffer)
+# TODO: This is never set. In the future, we need to set this when
+# the rest of our data is set.
+var channel: WebRTCDataChannel
+
+func SendData(data: Variant, playerId: int) -> void:
+	var channel: = self.GetChannel(playerId)
+	PutData.emit(channel, data)
+
+func GetChannel(playerId: int) -> WebRTCDataChannel:
+	if self.channel != null:
+		return self.channel
+	return RTCSingleton.GetDataChannel(playerId)
+
+# TODO: This should probably not be handled here. The end goal should be that
+# each RTC nodes only handles traffic to that specific player.
+func SendDataToAllPlayers(data: Variant):
+	RTCSingleton.SendDataToAllPlayers(data)
+
+func SendVariable(key: String, value: Variant, peerId: int = -1):
+	var dict = {
+		"type": "game_event",
+		"game_event": "data",
+		"variable": key,
+		"value": value
+	}
+	#TODO: Don't rely on nodes to send data to all players.
+	#if peerId == -1:
+		#SendDataToAllPlayers(dict)
+	SendData(dict, peerId)
 #endregion
 
 #region Read Data
@@ -23,6 +58,18 @@ func SendData(data: Variant) -> void:
 signal DataReceived(sourceId: String, data: Variant)
 
 func RecieveData(sourceId: String, data: Variant):
-	if (Sources.find(sourceId) > 0):
-		DataReceived.emit(sourceId, data)
+	if (!Sources.is_empty() && Sources.find(sourceId) > 0):
+		return
+	DataReceived.emit(sourceId, data)
+#endregion
+
+#region Player Info
+func Get_Player_Ids() -> Array:
+	return RTCSingleton.rtcPeer.get_peers().keys()
+
+func GetPlayerCount() -> int:
+	return self.Get_Player_Ids().size()
+
+func GetPlayerName(playerId: String) -> String:
+	return RTCSingleton.GetPlayerName(playerId)
 #endregion
diff --git a/project.godot b/project.godot
index 5bb68c6..19b5f08 100644
--- a/project.godot
+++ b/project.godot
@@ -17,7 +17,7 @@ config/icon="res://Assets/icon.svg"
 
 [autoload]
 
-RTC="*res://Host/Networking/rtc.gd"
+RTC="res://Host/Networking/rtc.gd"
 Globals="*res://Host/Networking/Globals.gd"
 IO="*res://Input/io.gd"
 Settings="*res://Host/GameSate/Settings.gd"
@@ -30,10 +30,6 @@ window/stretch/mode="viewport"
 window/stretch/aspect="ignore"
 window/emulate_touch_from_mouse=true
 
-[editor]
-
-run/main_run_args="--offline"
-
 [editor_plugins]
 
 enabled=PackedStringArray("res://addons/ez_rtc/plugin.cfg")
-- 
GitLab