diff --git a/src/resources/icons/1280x720.webp b/src/resources/icons/1280x720.webp
new file mode 100644
index 0000000..6951b10
Binary files /dev/null and b/src/resources/icons/1280x720.webp differ
diff --git a/src/resources/icons/dummy16-9.webp.import b/src/resources/icons/1280x720.webp.import
similarity index 73%
rename from src/resources/icons/dummy16-9.webp.import
rename to src/resources/icons/1280x720.webp.import
index de2981e..f528598 100644
--- a/src/resources/icons/dummy16-9.webp.import
+++ b/src/resources/icons/1280x720.webp.import
@@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://blkl4og334med"
-path="res://.godot/imported/dummy16-9.webp-5a004b2714a0a12aeacb8a560e85c6af.ctex"
+uid="uid://itsm1b042lj4"
+path="res://.godot/imported/1280x720.webp-0f567b7e104b7306bf6aee1c3f094cf3.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://resources/icons/dummy16-9.webp"
-dest_files=["res://.godot/imported/dummy16-9.webp-5a004b2714a0a12aeacb8a560e85c6af.ctex"]
+source_file="res://resources/icons/1280x720.webp"
+dest_files=["res://.godot/imported/1280x720.webp-0f567b7e104b7306bf6aee1c3f094cf3.ctex"]
[params]
diff --git a/src/resources/icons/dummy16-9.webp b/src/resources/icons/dummy16-9.webp
deleted file mode 100644
index b50f87f..0000000
Binary files a/src/resources/icons/dummy16-9.webp and /dev/null differ
diff --git a/src/resources/icons/ui/block.svg b/src/resources/icons/ui/block.svg
new file mode 100644
index 0000000..d4cbede
--- /dev/null
+++ b/src/resources/icons/ui/block.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/resources/icons/ui/block.svg.import b/src/resources/icons/ui/block.svg.import
new file mode 100644
index 0000000..18b4b7f
--- /dev/null
+++ b/src/resources/icons/ui/block.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://b4mmsxpws0l2k"
+path="res://.godot/imported/block.svg-6cfa996c8806ab64f944c5134364e097.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://resources/icons/ui/block.svg"
+dest_files=["res://.godot/imported/block.svg-6cfa996c8806ab64f944c5134364e097.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=5.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/src/resources/icons/ui/check.svg b/src/resources/icons/ui/check.svg
new file mode 100644
index 0000000..a73f3ba
--- /dev/null
+++ b/src/resources/icons/ui/check.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/resources/icons/ui/check.svg.import b/src/resources/icons/ui/check.svg.import
new file mode 100644
index 0000000..782cab8
--- /dev/null
+++ b/src/resources/icons/ui/check.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dl0bn4f34xl51"
+path="res://.godot/imported/check.svg-5c326901df346860690e651c5c76add9.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://resources/icons/ui/check.svg"
+dest_files=["res://.godot/imported/check.svg-5c326901df346860690e651c5c76add9.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=5.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/src/resources/icons/ui/podiatry.svg b/src/resources/icons/ui/podiatry.svg
new file mode 100644
index 0000000..7fe6364
--- /dev/null
+++ b/src/resources/icons/ui/podiatry.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/resources/icons/ui/podiatry.svg.import b/src/resources/icons/ui/podiatry.svg.import
new file mode 100644
index 0000000..d3888fd
--- /dev/null
+++ b/src/resources/icons/ui/podiatry.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://daebexy1etluo"
+path="res://.godot/imported/podiatry.svg-07f24e83803c9675de4651b8b1e18f5d.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://resources/icons/ui/podiatry.svg"
+dest_files=["res://.godot/imported/podiatry.svg-07f24e83803c9675de4651b8b1e18f5d.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=5.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/src/resources/icons/ui/settings.svg b/src/resources/icons/ui/settings.svg
new file mode 100644
index 0000000..5dd859a
--- /dev/null
+++ b/src/resources/icons/ui/settings.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/resources/icons/ui/settings.svg.import b/src/resources/icons/ui/settings.svg.import
new file mode 100644
index 0000000..303ea47
--- /dev/null
+++ b/src/resources/icons/ui/settings.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://byxgefy5xsbuu"
+path="res://.godot/imported/settings.svg-441728aa7483309d4207a8a780e19829.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://resources/icons/ui/settings.svg"
+dest_files=["res://.godot/imported/settings.svg-441728aa7483309d4207a8a780e19829.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=5.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/src/resources/icons/ui/trash.svg b/src/resources/icons/ui/trash.svg
new file mode 100644
index 0000000..714432c
--- /dev/null
+++ b/src/resources/icons/ui/trash.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/resources/icons/ui/trash.svg.import b/src/resources/icons/ui/trash.svg.import
new file mode 100644
index 0000000..a292048
--- /dev/null
+++ b/src/resources/icons/ui/trash.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://5admxcll28y4"
+path="res://.godot/imported/trash.svg-b904a4d3b8b45a279de3fbe344053dc8.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://resources/icons/ui/trash.svg"
+dest_files=["res://.godot/imported/trash.svg-b904a4d3b8b45a279de3fbe344053dc8.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=5.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/src/resources/icons/ui/volume.svg b/src/resources/icons/ui/volume.svg
new file mode 100644
index 0000000..5ff96d4
--- /dev/null
+++ b/src/resources/icons/ui/volume.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/resources/icons/ui/volume.svg.import b/src/resources/icons/ui/volume.svg.import
new file mode 100644
index 0000000..09627f5
--- /dev/null
+++ b/src/resources/icons/ui/volume.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ma5txk116bd0"
+path="res://.godot/imported/volume.svg-bbcdade9bc2926f6c1390f115e0e5c98.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://resources/icons/ui/volume.svg"
+dest_files=["res://.godot/imported/volume.svg-bbcdade9bc2926f6c1390f115e0e5c98.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=5.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/src/resources/themes/default.tres b/src/resources/themes/default.tres
new file mode 100644
index 0000000..54206bb
--- /dev/null
+++ b/src/resources/themes/default.tres
@@ -0,0 +1,143 @@
+[gd_resource type="Theme" format=3 uid="uid://ckqsvvccivw0x"]
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_sn1o5"]
+bg_color = Color(0.07, 0, 0, 1)
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_kyium"]
+bg_color = Color(0, 0.2784314, 0.6, 1)
+corner_radius_top_left = 5
+corner_radius_top_right = 5
+corner_radius_bottom_right = 5
+corner_radius_bottom_left = 5
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_w1m0q"]
+bg_color = Color(4.7745703e-05, 0.4621603, 0.95651287, 1)
+corner_radius_top_left = 5
+corner_radius_top_right = 5
+corner_radius_bottom_right = 5
+corner_radius_bottom_left = 5
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dgxsq"]
+bg_color = Color(0.0627451, 0.0627451, 0.0627451, 1)
+corner_radius_top_left = 5
+corner_radius_top_right = 5
+corner_radius_bottom_right = 5
+corner_radius_bottom_left = 5
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_lmgqb"]
+bg_color = Color(0, 0.391321, 0.8202678, 1)
+corner_radius_top_left = 5
+corner_radius_top_right = 5
+corner_radius_bottom_right = 5
+corner_radius_bottom_left = 5
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_nfgd4"]
+bg_color = Color(0.38, 0, 0, 1)
+corner_radius_top_left = 5
+corner_radius_top_right = 5
+corner_radius_bottom_right = 5
+corner_radius_bottom_left = 5
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_hge1u"]
+bg_color = Color(0.68, 0.095199995, 0.095199995, 1)
+corner_radius_top_left = 5
+corner_radius_top_right = 5
+corner_radius_bottom_right = 5
+corner_radius_bottom_left = 5
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_hvbjw"]
+bg_color = Color(0.06, 0.06, 0.06, 0.39215687)
+corner_radius_top_left = 5
+corner_radius_top_right = 5
+corner_radius_bottom_right = 5
+corner_radius_bottom_left = 5
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_2d1ky"]
+content_margin_left = 4.0
+content_margin_top = 4.0
+content_margin_right = 4.0
+content_margin_bottom = 4.0
+bg_color = Color(0.1, 0.1, 0.1, 0.6)
+corner_radius_top_left = 3
+corner_radius_top_right = 3
+corner_radius_bottom_right = 3
+corner_radius_bottom_left = 3
+corner_detail = 5
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ipp3m"]
+bg_color = Color(0.078431375, 0.078431375, 0.078431375, 0.78431374)
+corner_radius_top_left = 10
+corner_radius_top_right = 10
+corner_radius_bottom_right = 10
+corner_radius_bottom_left = 10
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_kpyni"]
+bg_color = Color(0, 0.19833338, 0.34, 1)
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_x2xen"]
+bg_color = Color(0.038397167, 0.038397167, 0.03839716, 1)
+corner_radius_top_left = 5
+corner_radius_top_right = 5
+corner_radius_bottom_right = 5
+corner_radius_bottom_left = 5
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_gvfoe"]
+bg_color = Color(0.11062177, 0.15318072, 0.26589048, 1)
+border_width_left = 5
+border_width_top = 5
+border_width_right = 5
+border_width_bottom = 5
+border_color = Color(0.018563958, 0.2571708, 0.35101107, 1)
+border_blend = true
+corner_radius_top_left = 5
+corner_radius_top_right = 5
+corner_radius_bottom_right = 5
+corner_radius_bottom_left = 5
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_m5j5c"]
+bg_color = Color(0.0627451, 0.0627451, 0.0627451, 1)
+corner_radius_top_left = 5
+corner_radius_top_right = 5
+corner_radius_bottom_right = 5
+corner_radius_bottom_left = 5
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_iga00"]
+content_margin_left = 4.0
+content_margin_top = 4.0
+content_margin_right = 4.0
+content_margin_bottom = 4.0
+bg_color = Color(0.1, 0.1, 0.1, 0.6)
+border_color = Color(0, 0, 0, 0.6)
+corner_radius_top_left = 3
+corner_radius_top_right = 3
+corner_radius_bottom_right = 3
+corner_radius_bottom_left = 3
+corner_detail = 5
+
+[resource]
+Button/styles/disabled = SubResource("StyleBoxFlat_sn1o5")
+Button/styles/focus = SubResource("StyleBoxFlat_kyium")
+Button/styles/hover = SubResource("StyleBoxFlat_kyium")
+Button/styles/hover_pressed = SubResource("StyleBoxFlat_w1m0q")
+Button/styles/normal = SubResource("StyleBoxFlat_dgxsq")
+Button/styles/pressed = SubResource("StyleBoxFlat_lmgqb")
+Danger/base_type = &"Button"
+Danger/styles/focus = SubResource("StyleBoxFlat_nfgd4")
+Danger/styles/hover = SubResource("StyleBoxFlat_nfgd4")
+Danger/styles/hover_pressed = SubResource("StyleBoxFlat_nfgd4")
+Danger/styles/pressed = SubResource("StyleBoxFlat_hge1u")
+LightButton/base_type = &"Button"
+LightButton/styles/normal = SubResource("StyleBoxFlat_hvbjw")
+LineEdit/styles/normal = SubResource("StyleBoxFlat_2d1ky")
+Panel/styles/panel = SubResource("StyleBoxFlat_ipp3m")
+PopupMenu/constants/item_end_padding = 5
+PopupMenu/constants/item_start_padding = 5
+PopupMenu/constants/v_separation = 10
+PopupMenu/styles/hover = SubResource("StyleBoxFlat_kpyni")
+PopupMenu/styles/panel = SubResource("StyleBoxFlat_x2xen")
+ScrollContainer/constants/scrollbar_h_separation = 10
+SessionListing/base_type = &"Button"
+SessionListing/styles/hover = SubResource("StyleBoxFlat_gvfoe")
+SolidBackground/base_type = &"PanelContainer"
+SolidBackground/styles/panel = SubResource("StyleBoxFlat_m5j5c")
+TextEdit/styles/normal = SubResource("StyleBoxFlat_iga00")
diff --git a/src/scenes/managers/app/network.gd b/src/scenes/managers/app/network.gd
index 6b44e50..ac2429b 100644
--- a/src/scenes/managers/app/network.gd
+++ b/src/scenes/managers/app/network.gd
@@ -6,23 +6,10 @@
# License: MIT License
# Authors: Armored Dragon
# --- License
-
extends Node
const MAX_CLIENTS = 1000
const MINIMUM_INCREMENTAL_PORT = 20205
-
-var url_regex: RegEx = RegEx.create_from_string("^(https?)://([^/:]+)(?::(\\d+))?(.*)$")
-
-@onready var scene_m = get_node("../SceneManager")
-
-var _database = {
- "heartbeats": {},
- "sessions_id": {},
- "sessions": {},
- "sessions_api": {}
-}
-
const _instance_database_template = {
"id": "",
"name": "",
@@ -31,23 +18,32 @@ const _instance_database_template = {
"max_connected_users": 1,
"privacy": null,
"active": false,
-
"connected_players": [],
"start_time": 0,
-
"networking": {
"use_steam": false,
- "use_lan": false
- }
+ "use_lan": false,
+ },
}
+var url_regex: RegEx = RegEx.create_from_string("^(https?)://([^/:]+)(?::(\\d+))?(.*)$")
+var _database = {
+ "heartbeats": { },
+ "sessions_id": { },
+ "sessions": { },
+ "sessions_api": { },
+}
+
+@onready var scene_m = get_node("../SceneManager")
+
+
func start_server(port: int = 0, root_scene: Enum.BaseLevel = Enum.BaseLevel.GRID) -> Dictionary:
- var response_dict = {"ok": false, "error": null, "data": null}
- GlobalLogger.logs("Starting a new server.")
+ var response_dict = { "ok": false, "error": null, "data": null }
+ GlobalLogger.log("Starting a new server.")
# Get an available port. If port was defined, force that port or fail.
if port != 0:
- GlobalLogger.logs("Forcing port '%s'" % port)
+ GlobalLogger.log("Forcing port '%s'" % port)
var port_available = !_is_port_in_use(port)
if !port_available:
response_dict.error = "Port is not available."
@@ -81,7 +77,7 @@ func start_server(port: int = 0, root_scene: Enum.BaseLevel = Enum.BaseLevel.GRI
_database.sessions.set(_scene, _instance)
if _create_server_response != OK:
- GlobalLogger.logs("Failed to start server. Error: '%s'" % _create_server_response, Enum.LogLevel.INFO)
+ GlobalLogger.log("Failed to start server. Error: '%s'" % _create_server_response, Enum.LogLevel.INFO)
response_dict.error = str(_create_server_response)
_database.sessions_api.erase(_scene)
@@ -109,15 +105,16 @@ func start_server(port: int = 0, root_scene: Enum.BaseLevel = Enum.BaseLevel.GRI
return response_dict
+
func stop_server(id: String):
var database_has_sessions: bool = _database.sessions.has(id)
var database_has_sessions_api: bool = _database.sessions_api.has(id)
- GlobalLogger.logs("Stopping server '%s'." % id)
+ GlobalLogger.log("Stopping server '%s'." % id)
# TODO: Disable join requests to server
if !database_has_sessions && !database_has_sessions_api:
- GlobalLogger.logs("Session '%s' does not exist, cannot stop the server." % id, Enum.LogLevel.WARNING)
+ GlobalLogger.log("Session '%s' does not exist, cannot stop the server." % id, Enum.LogLevel.WARNING)
return
if database_has_sessions_api:
@@ -141,16 +138,20 @@ func stop_server(id: String):
_database.sessions.erase(id)
return
+
func update_server(id: String, server_info: Dictionary):
- GlobalLogger.logs("Updating server '%s'." % id)
- var _saved_session_servers = SettingsManager.get_session_servers()
+ GlobalLogger.log("Updating server '%s'." % id)
+
+ # var _saved_session_servers = SettingsManager.get_session_servers()
+ var _saved_session_servers = [{ "id": "123456", "url": "http://localhost:40500" }]
if server_info.privacy > Enum.PrivacyLevel.INVITE:
for _server in _saved_session_servers:
if _database.heartbeats.has(id):
- GlobalLogger.logs("Session '%s' is already advertised. Updating instead." % id)
+ GlobalLogger.log("Session '%s' is already advertised. Updating instead." % id)
await _update_session_server_listing(server_info, _server.url)
else:
+ GlobalLogger.log("Advertising Session '%s'." % id)
var advertise_response = await _advertise_session(server_info, _server.url)
if advertise_response.ok == true:
@@ -159,7 +160,7 @@ func update_server(id: String, server_info: Dictionary):
if server_info.privacy == Enum.PrivacyLevel.INVITE:
if _database.heartbeats.has(id):
- GlobalLogger.logs("Destroying session heartbeat for '%s'" % id)
+ GlobalLogger.log("Destroying session heartbeat for '%s'" % id)
_database.heartbeats.erase(id)
for _server in _saved_session_servers:
@@ -168,14 +169,15 @@ func update_server(id: String, server_info: Dictionary):
Events.emit_signal("instance_updated")
return
+
func join_server(ip: String, port: int):
- var response_dict = {"ok": false, "error": null, "data": null}
+ var response_dict = { "ok": false, "error": null, "data": null }
- GlobalLogger.logs("Joining server at '%s:%s'" % [ip, port], Enum.LogLevel.INFO)
+ GlobalLogger.log("Joining server at '%s:%s'" % [ip, port], Enum.LogLevel.INFO)
var _port_is_valid = port > 0 && port < 65535
if ip.is_empty() || !_port_is_valid:
- GlobalLogger.logs("Server information is invalid '%s:%s'." % [ip, port], Enum.LogLevel.INFO)
+ GlobalLogger.log("Server information is invalid '%s:%s'." % [ip, port], Enum.LogLevel.INFO)
response_dict.error = "Server information is invalid."
return response_dict
@@ -194,7 +196,7 @@ func join_server(ip: String, port: int):
var connect_error = _session_peer.create_client(ip, port)
if connect_error != OK:
- GlobalLogger.logs("Failed to join server. Error: '%s'" % connect_error, Enum.LogLevel.INFO)
+ GlobalLogger.log("Failed to join server. Error: '%s'" % connect_error, Enum.LogLevel.INFO)
response_dict.error = "Failed to join server. Error: '%s'" % connect_error
return response_dict
@@ -212,13 +214,14 @@ func join_server(ip: String, port: int):
Events.emit_signal("session_joined")
return
+
func leave_server(id: String):
- GlobalLogger.logs("Trying to leave server '%s'." % id)
+ GlobalLogger.log("Trying to leave server '%s'." % id)
var database_has_sessions: bool = _database.sessions.has(id)
var database_has_sessions_api: bool = _database.sessions_api.has(id)
if !database_has_sessions && !database_has_sessions_api:
- GlobalLogger.logs("Session '%s' does not exist, cannot disconnect." % id, Enum.LogLevel.WARNING)
+ GlobalLogger.log("Session '%s' does not exist, cannot disconnect." % id, Enum.LogLevel.WARNING)
return
if database_has_sessions_api:
@@ -226,7 +229,7 @@ func leave_server(id: String):
if mp_api.multiplayer_peer:
mp_api.multiplayer_peer.close()
- GlobalLogger.logs("Disconnected from session '%s'." % id, Enum.LogLevel.DEBUG)
+ GlobalLogger.log("Disconnected from session '%s'." % id, Enum.LogLevel.DEBUG)
scene_m.set_active_session(get_connected_sessions()[0].id)
@@ -236,12 +239,13 @@ func leave_server(id: String):
_database.sessions_api.erase(id)
_database.sessions.erase(id)
- GlobalLogger.logs("Successfully disconnected from session '%s' and cleaned up." % id, Enum.LogLevel.DEBUG)
+ GlobalLogger.log("Successfully disconnected from session '%s' and cleaned up." % id, Enum.LogLevel.DEBUG)
Events.emit_signal("session_left")
return
-func kick_player(server_id:String, peer_id: int, reason: String):
- GlobalLogger.logs("Kicking peer '%s' from '%s' for reason '%s'" % [peer_id, server_id, reason], Enum.LogLevel.DEBUG)
+
+func kick_player(server_id: String, peer_id: int, reason: String):
+ GlobalLogger.log("Kicking peer '%s' from '%s' for reason '%s'" % [peer_id, server_id, reason], Enum.LogLevel.DEBUG)
var database_has_sessions_api: bool = _database.sessions_api.has(server_id)
# TODO: Check if peer exists
if database_has_sessions_api:
@@ -250,17 +254,19 @@ func kick_player(server_id:String, peer_id: int, reason: String):
mp_api.disconnect_peer(peer_id)
return
+
func get_connected_sessions():
var result = []
for session_id in _database.sessions.keys():
- result.append(_database.sessions[session_id].merged({"id": session_id}))
+ result.append(_database.sessions[session_id].merged({ "id": session_id }))
return result
+
func set_active_session(id: String):
if _database.sessions.has(id):
- GlobalLogger.logs("Tried to mark an invalid session as active: '%s'" % id, Enum.LogLevel.WARNING)
+ GlobalLogger.log("Tried to mark an invalid session as active: '%s'" % id, Enum.LogLevel.WARNING)
return
for session_id in _database.sessions.keys():
@@ -274,14 +280,15 @@ func set_active_session(id: String):
scene_m.set_active_session(id)
return
+
func _update_session_server_listing(session_info: Dictionary, session_server: String) -> Dictionary:
- var response_dict = {"ok": false, "error": null, "data": null}
+ var response_dict = { "ok": false, "error": null, "data": null }
- GlobalLogger.logs("Updating session '%s' to the server '%s'" % [session_info.id, session_server])
+ GlobalLogger.log("Updating session '%s' to the server '%s'" % [session_info.id, session_server])
var url = UrlParser.deconstruct("%s/api/v1/updateSession" % session_server)
if url.ok != true:
- GlobalLogger.logs("Failed to deconstruct the URL '%s'. Error: '%s'" % [session_server, url.error])
+ GlobalLogger.log("Failed to deconstruct the URL '%s'. Error: '%s'" % [session_server, url.error])
response_dict.error = url.error
return response_dict
@@ -300,20 +307,21 @@ func _update_session_server_listing(session_info: Dictionary, session_server: St
url.path,
url.port,
["Accept: application/json", "Content-Type: application/json", "x-api-key: %s" % GlobalAccount.dev_session_server_api_key],
- JSON.stringify(_body)
+ JSON.stringify(_body),
)
return response_dict
+
func _remove_session_from_server(server_id: String, session_server: String) -> Dictionary:
- var response_dict = {"ok": false, "error": null, "data": {}}
+ var response_dict = { "ok": false, "error": null, "data": { } }
var _full_url = "%s/api/v1/deleteSession" % session_server
- GlobalLogger.logs("Removing session '%s' to the server '%s'" % [server_id, session_server])
+ GlobalLogger.log("Removing session '%s' to the server '%s'" % [server_id, session_server])
var url = UrlParser.deconstruct(_full_url)
if url.ok != true:
- GlobalLogger.logs("Failed to deconstruct the URL '%s'. Error: '%s'" % [_full_url, url.error])
+ GlobalLogger.log("Failed to deconstruct the URL '%s'. Error: '%s'" % [_full_url, url.error])
response_dict.error = url.error
return response_dict
@@ -329,7 +337,7 @@ func _remove_session_from_server(server_id: String, session_server: String) -> D
url.path,
url.port,
["Accept: application/json", "Content-Type: application/json", "x-api-key: %s" % GlobalAccount.dev_session_server_api_key],
- JSON.stringify(_body)
+ JSON.stringify(_body),
)
if _removal_response.ok:
@@ -340,8 +348,9 @@ func _remove_session_from_server(server_id: String, session_server: String) -> D
response_dict.error = _removal_response.error
return response_dict
+
func _find_available_port(target_port: int = MINIMUM_INCREMENTAL_PORT) -> int:
- GlobalLogger.logs("Trying to find an available port starting at '%s'." % target_port)
+ GlobalLogger.log("Trying to find an available port starting at '%s'." % target_port)
var _found_port = null
var _is_found = false
@@ -353,10 +362,11 @@ func _find_available_port(target_port: int = MINIMUM_INCREMENTAL_PORT) -> int:
break
target_port = target_port + 1
- GlobalLogger.logs("Port found: '%s'" % target_port)
+ GlobalLogger.log("Port found: '%s'" % target_port)
return _found_port
+
func _is_port_in_use(port: int) -> bool:
var udp_server = UDPServer.new()
var err_udp = udp_server.listen(port, "*")
@@ -372,8 +382,9 @@ func _is_port_in_use(port: int) -> bool:
tcp_server.stop()
return true
+
func _create_heartbeat_timer(session_id: String, session_server_url: String):
- GlobalLogger.logs("Creating a heartbeat timer for server '%s'" % session_id)
+ GlobalLogger.log("Creating a heartbeat timer for server '%s'" % session_id)
# FIXME: Hardcoded time for timer.
var timer = get_tree().create_timer(20)
@@ -382,10 +393,11 @@ func _create_heartbeat_timer(session_id: String, session_server_url: String):
timer.timeout.connect(_heartbeat_timer_timeout.bind(session_id, session_server_url))
return
+
func _heartbeat_timer_timeout(session_id: String, session_server_url: String):
- GlobalLogger.logs("Sending a heartbeat for server '%s'" % session_id)
+ GlobalLogger.log("Sending a heartbeat for server '%s'" % session_id)
if _database.heartbeats.has(session_id) == false:
- GlobalLogger.logs("Server '%s' does not exist anymore, not sending a heartbeat." % session_id)
+ GlobalLogger.log("Server '%s' does not exist anymore, not sending a heartbeat." % session_id)
return
_heartbeat_session(session_id, session_server_url)
@@ -393,16 +405,17 @@ func _heartbeat_timer_timeout(session_id: String, session_server_url: String):
_create_heartbeat_timer(session_id, session_server_url)
return
+
func _heartbeat_session(session_id: String, session_server_url: String) -> void:
var _full_url = "%s/api/v1/heartbeatSession" % session_server_url
var _url = UrlParser.deconstruct(_full_url)
if _url.ok != true:
- GlobalLogger.logs("Failed to deconstruct the URL '%s'. Error: '%s'" % [_full_url, _url.error])
+ GlobalLogger.log("Failed to deconstruct the URL '%s'. Error: '%s'" % [_full_url, _url.error])
return
_url = _url.data
- var body = {"session_id": _database.sessions_id.get(session_id)}
+ var body = { "session_id": _database.sessions_id.get(session_id) }
var response = await HTTP.req(
HTTPClient.Method.METHOD_POST,
@@ -410,21 +423,22 @@ func _heartbeat_session(session_id: String, session_server_url: String) -> void:
_url.path,
_url.port,
["Accept: application/json", "Content-Type: application/json", "x-api-key: %s" % GlobalAccount.dev_session_server_api_key],
- JSON.stringify(body)
+ JSON.stringify(body),
)
if response and response.get("ok"):
- GlobalLogger.logs("Heartbeat sent for session '%s'" % session_id)
+ GlobalLogger.log("Heartbeat sent for session '%s'" % session_id)
return
+
func _advertise_session(session_info: Dictionary, session_server: String) -> Dictionary:
- var response_dict = {"ok": false, "error": null, "data": null}
- GlobalLogger.logs("Advertising session '%s' to the server '%s'" % [session_info.id, session_server])
+ var response_dict = { "ok": false, "error": null, "data": null }
+ GlobalLogger.log("Advertising session '%s' to the server '%s'" % [session_info.id, session_server])
var _full_url = "%s/api/v1/postSession" % session_server
var url = UrlParser.deconstruct(_full_url)
if url.ok != true:
- GlobalLogger.logs("Failed to deconstruct the URL '%s'. Error: '%s'" % [_full_url, url.error])
+ GlobalLogger.log("Failed to deconstruct the URL '%s'. Error: '%s'" % [_full_url, url.error])
response_dict.error = url.error
return response_dict
@@ -443,7 +457,7 @@ func _advertise_session(session_info: Dictionary, session_server: String) -> Dic
url.path,
url.port,
["Accept: application/json", "Content-Type: application/json", "x-api-key: %s" % GlobalAccount.dev_session_server_api_key],
- JSON.stringify(_body)
+ JSON.stringify(_body),
)
# FIXME: What is this flow? This is bad?
@@ -452,6 +466,7 @@ func _advertise_session(session_info: Dictionary, session_server: String) -> Dic
return response_dict
advertise_response = JSON.parse_string(advertise_response.body)
+
if advertise_response.ok == false:
response_dict.error = advertise_response.error
return response_dict
diff --git a/src/scenes/managers/app/scene.gd b/src/scenes/managers/app/scene.gd
index 439391c..454f32f 100644
--- a/src/scenes/managers/app/scene.gd
+++ b/src/scenes/managers/app/scene.gd
@@ -6,18 +6,20 @@
# License: MIT License
# Authors: Armored Dragon
# --- License
-
extends Node
+var active_session: String = ""
+
# Game managers
@onready var network_m: Node = get_tree().current_scene.get_node("NetworkManager")
@onready var scene_container: Node3D = get_tree().current_scene.get_node("Scenes")
-var active_session: String = ""
+
func _ready():
network_m.start_server()
return
+
func create_master_scene():
var _scene_id = Random.random_string()
var _base_scene = preload("res://scenes/levels/base.tscn")
@@ -31,20 +33,23 @@ func create_master_scene():
return _scene_id
+
func get_master_scene(id: String) -> Node3D:
var _scene = scene_container.get_node(id)
return _scene
+
func destroy_master_scene(id: String):
var _scene = scene_container.get_node_or_null(id)
if _scene == null:
- GlobalLogger.logs("'%s' does not exist, could not delete." % id, Enum.LogLevel.WARNING)
+ GlobalLogger.log("'%s' does not exist, could not delete." % id, Enum.LogLevel.WARNING)
return
_scene.queue_free()
return
+
func set_master_root_from_program(id: String, scene_type: Enum.BaseLevel) -> void:
var _scene = get_master_scene(id)
@@ -71,13 +76,15 @@ func set_master_root_from_program(id: String, scene_type: Enum.BaseLevel) -> voi
Events.emit_signal("instance_root_changed")
return
+
func get_master_root(id: String) -> Node3D:
var _scene: Node3D = get_master_scene(id)
var _root = _scene.get_node_or_null("root")
return _root
+
func set_master_root_from_inventory(_id: String, _scene_type: Enum.BaseLevel) -> bool:
- GlobalLogger.logs("'%s' is not implemented." % get_stack()[0]["function"], Enum.LogLevel.WARNING)
+ GlobalLogger.log("'%s' is not implemented." % get_stack()[0]["function"], Enum.LogLevel.WARNING)
# get_master_scene
# Find scene from inventory.
# Validate scene integrity.
@@ -86,6 +93,7 @@ func set_master_root_from_inventory(_id: String, _scene_type: Enum.BaseLevel) ->
# Replace with new scene.
return false
+
func start_master_scene(id: String):
const MANAGERS = ["PlayerManager", "SignalBus"]
@@ -95,12 +103,13 @@ func start_master_scene(id: String):
var _scene_manager = _scene.get_node_or_null(node_name)
if _scene_manager:
_scene_manager.module_active = true
- GlobalLogger.logs("'%s' started in server '%s'" % [node_name, id])
+ GlobalLogger.log("'%s' started in server '%s'" % [node_name, id])
continue
- GlobalLogger.logs("Could not start invalid manager '%s' in server '%s'" % [node_name, id], Enum.LogLevel.ERROR)
+ GlobalLogger.log("Could not start invalid manager '%s' in server '%s'" % [node_name, id], Enum.LogLevel.ERROR)
return
+
func stop_master_scene(id: String):
const MANAGERS = ["PlayerManager", "SignalBus"]
@@ -110,29 +119,15 @@ func stop_master_scene(id: String):
var _scene_manager = _scene.get_node_or_null(node_name)
if _scene_manager:
_scene_manager.module_active = true
- GlobalLogger.logs("'%s' stopped in server '%s'" % [node_name, id])
+ GlobalLogger.log("'%s' stopped in server '%s'" % [node_name, id])
continue
- GlobalLogger.logs("Could not stop invalid manager '%s' in server '%s'" % [node_name, id], Enum.LogLevel.ERROR)
+ GlobalLogger.log("Could not stop invalid manager '%s' in server '%s'" % [node_name, id], Enum.LogLevel.ERROR)
return
-func _get_scene_by_type(scene_type: Enum.BaseLevel) -> PackedScene:
- var _scene_dir: String = ""
-
- match scene_type:
- Enum.BaseLevel.DEBUG:
- _scene_dir = "res://scenes/levels/debug.tscn"
- Enum.BaseLevel.EMPTY:
- _scene_dir = "res://scenes/levels/empty.tscn"
- Enum.BaseLevel.GRID:
- _scene_dir = "res://scenes/levels/grid.tscn"
- _:
- _scene_dir = "res://scenes/levels/debug.tscn"
-
- return load(_scene_dir)
func set_active_session(session_id: String):
- GlobalLogger.logs("Setting session '%s' active." % session_id)
+ GlobalLogger.log("Setting session '%s' active." % session_id)
for _scene in network_m.get_connected_sessions():
# Each session gets disabled
@@ -147,13 +142,30 @@ func set_active_session(session_id: String):
_set_player_authority_state(session_id, true)
return
+
+func _get_scene_by_type(scene_type: Enum.BaseLevel) -> PackedScene:
+ var _scene_dir: String = ""
+
+ match scene_type:
+ Enum.BaseLevel.DEBUG:
+ _scene_dir = "res://scenes/levels/debug.tscn"
+ Enum.BaseLevel.EMPTY:
+ _scene_dir = "res://scenes/levels/empty.tscn"
+ Enum.BaseLevel.GRID:
+ _scene_dir = "res://scenes/levels/grid.tscn"
+ _:
+ _scene_dir = "res://scenes/levels/debug.tscn"
+
+ return load(_scene_dir)
+
+
func _set_camera_active_state(session_id, state: bool = false) -> void:
# TODO: check if session exists.
var my_id: String = str(network_m._database.sessions_api[session_id].get_unique_id())
var master_scene: Node3D = get_master_scene(session_id)
# HACK: If my_id = 0, we get the desired result. This is not safe though.
if my_id == "0":
- GlobalLogger.logs("Could not set active state for session '%s', is session open?" % [session_id], Enum.LogLevel.WARNING)
+ GlobalLogger.log("Could not set active state for session '%s', is session open?" % [session_id], Enum.LogLevel.WARNING)
return
var player_manager: Node = master_scene.get_node("PlayerManager")
var player_database = player_manager.players
@@ -163,12 +175,13 @@ func _set_camera_active_state(session_id, state: bool = false) -> void:
camera.current = state
return
+
func _set_player_authority_state(session_id, is_active: bool = false) -> void:
var my_id: String = str(network_m._database.sessions_api[session_id].get_unique_id())
var master_scene: Node3D = get_master_scene(session_id)
# HACK: If my_id = 0, we get the desired result. This is not safe though.
if my_id == "0":
- GlobalLogger.logs("Could not set player authority for session '%s', is session open?" % [session_id], Enum.LogLevel.WARNING)
+ GlobalLogger.log("Could not set player authority for session '%s', is session open?" % [session_id], Enum.LogLevel.WARNING)
return
var player_manager: Node = master_scene.get_node("PlayerManager")
var player_database = player_manager.players
diff --git a/src/scenes/managers/scene/network.gd b/src/scenes/managers/scene/network.gd
index d3b2f5a..9145851 100644
--- a/src/scenes/managers/scene/network.gd
+++ b/src/scenes/managers/scene/network.gd
@@ -8,11 +8,13 @@ var _server_id: String = ""
@onready var scene_m = get_tree().current_scene.get_node("SceneManager")
@onready var network_m = get_tree().current_scene.get_node("NetworkManager")
+
func _process(_delta):
if multiplayer:
multiplayer.poll()
return
+
func setup_connection(api: SceneMultiplayer, id: String):
_specific_api = api
_server_id = id
@@ -24,62 +26,40 @@ func setup_connection(api: SceneMultiplayer, id: String):
_my_id = multiplayer.get_unique_id()
-func _on_connected_to_server():
- GlobalLogger.logs("[%s] I am connected to a server." % _my_id)
-
-func _on_server_disconnected():
- network_m.leave_server(_server_id)
- return
@rpc("authority", "unreliable")
func ban_player():
- GlobalLogger.logs("'%s' is not implemented." % get_stack()[0]["function"], Enum.LogLevel.WARNING)
+ GlobalLogger.log("'%s' is not implemented." % get_stack()[0]["function"], Enum.LogLevel.WARNING)
return
-func on_kicked():
- GlobalLogger.logs("'%s' is not implemented." % get_stack()[0]["function"], Enum.LogLevel.WARNING)
- return
-func on_banned():
- GlobalLogger.logs("'%s' is not implemented." % get_stack()[0]["function"], Enum.LogLevel.WARNING)
+func on_kicked():
+ GlobalLogger.log("'%s' is not implemented." % get_stack()[0]["function"], Enum.LogLevel.WARNING)
return
-func _on_peer_connected(peer_id: int):
- if is_multiplayer_authority() == false:
- return
- player_m.add_player(peer_id)
- player_m.add_player.rpc(peer_id)
-
- GlobalLogger.logs("[%s] Peer '%s' connected to our server." % [_my_id, peer_id])
- rpc_id(peer_id, "set_root", Enum.BaseLevel.GRID)
- rpc_id(peer_id, "add_players", player_m.players)
+func on_banned():
+ GlobalLogger.log("'%s' is not implemented." % get_stack()[0]["function"], Enum.LogLevel.WARNING)
return
-func _on_peer_disconnected(peer_id: int) -> void:
- if is_multiplayer_authority() == false:
- return
-
- player_m.remove_player(peer_id)
- player_m.remove_player.rpc(peer_id)
-
- GlobalLogger.logs("[%s] Peer '%s' disconnected to our server." % [_my_id, peer_id])
- return
@rpc("authority", "reliable")
func set_root(scene_type: Enum.BaseLevel):
- GlobalLogger.logs("[%s] Received root base scene." % [_my_id])
+ GlobalLogger.log("[%s] Received root base scene." % [_my_id])
scene_m.set_master_root_from_program(_server_id, scene_type)
+
@rpc("authority", "reliable")
func add_players(players: Dictionary):
- GlobalLogger.logs("[%s] Playerlist received." % [_my_id])
+ GlobalLogger.log("[%s] Playerlist received." % [_my_id])
for _player in players.keys():
player_m.add_player(int(_player))
+
@rpc("authority", "reliable")
func spawn_entity():
- GlobalLogger.logs("'%s' is not implemented." % get_stack()[0]["function"], Enum.LogLevel.WARNING)
+ GlobalLogger.log("'%s' is not implemented." % get_stack()[0]["function"], Enum.LogLevel.WARNING)
+
@rpc("any_peer", "unreliable")
func entity_position(entity_id: int, position):
@@ -90,3 +70,36 @@ func entity_position(entity_id: int, position):
if target_node:
target_node.position = NetworkCompression.d_16_pos(position)
target_node.rotation = NetworkCompression.d_16_vec3(position.slice(12))
+
+
+func _on_connected_to_server():
+ GlobalLogger.log("[%s] I am connected to a server." % _my_id)
+
+
+func _on_server_disconnected():
+ network_m.leave_server(_server_id)
+ return
+
+
+func _on_peer_connected(peer_id: int):
+ if is_multiplayer_authority() == false:
+ return
+
+ player_m.add_player(peer_id)
+ player_m.add_player.rpc(peer_id)
+
+ GlobalLogger.log("[%s] Peer '%s' connected to our server." % [_my_id, peer_id])
+ rpc_id(peer_id, "set_root", Enum.BaseLevel.GRID)
+ rpc_id(peer_id, "add_players", player_m.players)
+ return
+
+
+func _on_peer_disconnected(peer_id: int) -> void:
+ if is_multiplayer_authority() == false:
+ return
+
+ player_m.remove_player(peer_id)
+ player_m.remove_player.rpc(peer_id)
+
+ GlobalLogger.log("[%s] Peer '%s' disconnected to our server." % [_my_id, peer_id])
+ return
diff --git a/src/scenes/managers/scene/player.gd b/src/scenes/managers/scene/player.gd
index d91892a..9bf1fff 100644
--- a/src/scenes/managers/scene/player.gd
+++ b/src/scenes/managers/scene/player.gd
@@ -6,50 +6,51 @@
# License: MIT License
# Authors: Armored Dragon
# --- License
-
extends Node
-var module_active: bool = false
-
-var players = {}
-
const PLAYER_TEMPLATE = {
"peer_id": 0,
"has_spawned": false,
- "node": null
+ "node": null,
}
+var module_active: bool = false
+var players = { }
+
+
@rpc("authority", "reliable")
func add_player(peer_id: int) -> void:
var caller_id = multiplayer.get_remote_sender_id()
var database_template = PLAYER_TEMPLATE.duplicate()
- GlobalLogger.logs("[%s] Adding peer '%s' to the player list" % [caller_id, peer_id])
+ GlobalLogger.log("[%s] Adding peer '%s' to the player list" % [caller_id, peer_id])
database_template.set("peer_id", peer_id)
players.set(str(peer_id), database_template)
spawn_player(str(peer_id))
+
@rpc("authority", "reliable")
func remove_player(peer_id: int) -> void:
var caller_id = multiplayer.get_remote_sender_id()
- GlobalLogger.logs("[%s] Removing peer '%s' from the player list" % [caller_id, peer_id])
+ GlobalLogger.log("[%s] Removing peer '%s' from the player list" % [caller_id, peer_id])
players[str(peer_id)].get("node").queue_free()
players.erase(str(peer_id))
+
@rpc("authority", "unreliable")
func spawn_player(peer_id: String) -> void:
var caller_id = multiplayer.get_remote_sender_id()
if players[peer_id].get("has_spawned") == true:
- GlobalLogger.logs("[%s] Did not spawn peer '%s', already exists!" % [caller_id, peer_id], Enum.LogLevel.WARNING)
+ GlobalLogger.log("[%s] Did not spawn peer '%s', already exists!" % [caller_id, peer_id], Enum.LogLevel.WARNING)
return
- GlobalLogger.logs("[%s] Spawning peer '%s'" % [caller_id, peer_id])
+ GlobalLogger.log("[%s] Spawning peer '%s'" % [caller_id, peer_id])
if module_active == false:
- GlobalLogger.logs("[%s] Could not spawn peer '%s', module inactive." % [caller_id, peer_id])
+ GlobalLogger.log("[%s] Could not spawn peer '%s', module inactive." % [caller_id, peer_id])
return
var _player_scene: PackedScene = load("res://scenes/players/player.tscn")
@@ -57,13 +58,14 @@ func spawn_player(peer_id: String) -> void:
_new_player.name = str(peer_id)
_new_player.position = Vector3(0, 0, 0)
_new_player.set_multiplayer_authority(int(peer_id))
- get_node("../root").add_child( _new_player)
+ get_node("../root").add_child(_new_player)
var player_node = get_node("../root").get_node(str(peer_id))
- GlobalLogger.logs("[%s] Spawned peer '%s'." % [caller_id, peer_id])
+ GlobalLogger.log("[%s] Spawned peer '%s'." % [caller_id, peer_id])
players[peer_id].set("node", player_node)
players[peer_id].set("has_spawned", true)
return
+
func kill_player() -> void:
- GlobalLogger.logs("'%s' is not implemented." % get_stack()[0]["function"], Enum.LogLevel.WARNING)
+ GlobalLogger.log("'%s' is not implemented." % get_stack()[0]["function"], Enum.LogLevel.WARNING)
return
diff --git a/src/scenes/master.tscn b/src/scenes/master.tscn
index 01ce876..64e9c41 100644
--- a/src/scenes/master.tscn
+++ b/src/scenes/master.tscn
@@ -2,7 +2,7 @@
[ext_resource type="PackedScene" uid="uid://5v8rbnp716b0" path="res://scenes/managers/app/network.tscn" id="1_jooxx"]
[ext_resource type="PackedScene" uid="uid://cmknpdx5ba15o" path="res://scenes/managers/app/scene.tscn" id="2_h2qy3"]
-[ext_resource type="PackedScene" uid="uid://ckl5gw0xbduiv" path="res://userinterface/dash/hud.tscn" id="5_q3f5g"]
+[ext_resource type="PackedScene" uid="uid://c4y1sb6lmdr0q" path="res://userinterface/dashv2/dashboard.tscn" id="4_h2qy3"]
[node name="Master" type="Node3D" unique_id=420526444]
@@ -10,7 +10,7 @@
[node name="SceneManager" parent="." unique_id=5477810 instance=ExtResource("2_h2qy3")]
-[node name="Hud" parent="." unique_id=1053137144 instance=ExtResource("5_q3f5g")]
+[node name="Dashboard" parent="." unique_id=505457833 instance=ExtResource("4_h2qy3")]
visible = false
[node name="Scenes" type="Node3D" parent="." unique_id=308239834]
diff --git a/src/scripts/crypto/keys.gd b/src/scripts/crypto/keys.gd
index 507bb66..0be2455 100644
--- a/src/scripts/crypto/keys.gd
+++ b/src/scripts/crypto/keys.gd
@@ -2,9 +2,10 @@ extends Node
var keys = {
"public": "",
- "private": ""
+ "private": "",
}
+
# TODO: Move this to Files.gd script.
func read_keys_from_disk(username: String) -> PackedStringArray:
var pubKeyPath = "user://accounts/%s/keys/pubKey.pem" % username
@@ -16,18 +17,19 @@ func read_keys_from_disk(username: String) -> PackedStringArray:
var keys_exist = FileAccess.file_exists(pubKeyPath) && FileAccess.file_exists(privKeyPath)
if keys_exist:
- GlobalLogger.logs("Using saved account key.")
+ GlobalLogger.log("Using saved account key.")
pubKey = FileAccess.open(pubKeyPath, FileAccess.READ).get_as_text()
privKey = FileAccess.open(privKeyPath, FileAccess.READ).get_as_text()
return [pubKey, privKey]
- GlobalLogger.logs("No key available. Generating a new one!")
+ GlobalLogger.log("No key available. Generating a new one!")
_generate_keys()
_write_keys_to_disk(username)
return [keys.public, keys.private]
+
func _write_keys_to_disk(username):
# Make sure directory exists
var dir = DirAccess.open("user://")
@@ -44,6 +46,7 @@ func _write_keys_to_disk(username):
privKeyFile.store_string(keys.private)
return
+
func _generate_keys():
var crypto = Crypto.new()
diff --git a/src/scripts/crypto/rsa.gd b/src/scripts/crypto/rsa.gd
index 11b0fa3..e577779 100644
--- a/src/scripts/crypto/rsa.gd
+++ b/src/scripts/crypto/rsa.gd
@@ -6,14 +6,14 @@
# License: MIT License
# Authors: Armored Dragon
# --- License
-
extends Node
+
## Generates a RSA keypair at a specific bit length
## @returns Dictionary
func generate_keypair(level: int = 0) -> Dictionary:
# TODO: Error checks
- var return_dictionary = {"public": "", "private": ""}
+ var return_dictionary = { "public": "", "private": "" }
var _target_bits = 0
match level:
@@ -29,13 +29,14 @@ func generate_keypair(level: int = 0) -> Dictionary:
return_dictionary.public = generated_keys.save_to_string(true)
return return_dictionary
+
## Turns a pem into a CryptoKey
## @returns CryptoKey
func pem_to_cryptokey(pem: String = "") -> CryptoKey:
# TODO: Error checks
var public_key := CryptoKey.new()
if public_key.load_from_string(pem, true) != OK:
- GlobalLogger.logs("Failed to load public key", Enum.LogLevel.ERROR)
+ GlobalLogger.log("Failed to load public key", Enum.LogLevel.ERROR)
return null
return public_key
diff --git a/src/scripts/enum.gd b/src/scripts/enum.gd
index 347eb13..2ee5c8c 100644
--- a/src/scripts/enum.gd
+++ b/src/scripts/enum.gd
@@ -17,11 +17,11 @@ enum BaseLevel {
enum PrivacyLevel {
INVITE = 0,
- PUBLIC = 1,
- CONTACTS_PLUS = 2,
+ FRIENDS = 1,
+ FRIENDS_PLUS = 2,
CONTACTS = 3,
- FRIENDS_PLUS = 4,
- FRIENDS = 5
+ CONTACTS_PLUS = 4,
+ PUBLIC = 5,
}
const Settings = {
diff --git a/src/scripts/libs/account.gd b/src/scripts/libs/account.gd
index 0a2ba71..2b186e1 100644
--- a/src/scripts/libs/account.gd
+++ b/src/scripts/libs/account.gd
@@ -6,81 +6,65 @@
# License: MIT License
# Authors: Armored Dragon
# --- License
-
extends Node
+const ACCOUNT_DATABASE_DIRECTORY: String = "user://database/accounts.bin"
+
var time_lib = preload("res://scripts/libs/time.gd").new()
var random_lib = preload("res://scripts/utils/random.gd").new()
var rsa_lib = preload("res://scripts/crypto/rsa.gd").new()
-
-const ACCOUNT_DATABASE_DIRECTORY: String = "user://database/accounts.bin"
-
# TODO: Create proper encryption of the account database
# https://github.com/OpenMinerva/client/issues/59
var stop_connection_timer = false
-
-var active_account = {}
-var _database = []
+var active_account = { }
var dev_session_server_api_key = ""
+var _database: Array[Dictionary] = []
+
func _ready():
_load_account_database()
+
## Get a list of all accounts and return their information.
-func get_all() -> Array:
+func get_all() -> Array[Dictionary]:
return _database
+
## Adds an account to the account database.
func create(account: Dictionary, type: String) -> Dictionary:
# Make sure we are only recording data we are intending on.
- var account_formatted: Dictionary = {}
+ var account_formatted: Dictionary = { }
if type == "oauth":
account_formatted = _create_oauth(account)
if len(account_formatted.keys()) == 0:
- GlobalLogger.logs("Tried to create an account, but there was nothing to save.", Enum.LogLevel.ERROR)
- return {"ok": false, "error": "No account formatted.", "id": null}
+ GlobalLogger.log("Tried to create an account, but there was nothing to save.", Enum.LogLevel.ERROR)
+ return { "ok": false, "error": "No account formatted.", "id": null }
_database.append(account_formatted)
_save_account_database()
Events.emit_signal("dash_account_list_loaded")
- return {"ok": true, "id": account_formatted.id}
-
-func _create_oauth(account) -> Dictionary:
- var _account_keys = rsa_lib.generate_keypair()
-
- var _clean_account = {}
- _clean_account.id = random_lib.random_string(6, true)
- _clean_account.display_name = account.get("display_name", null)
- _clean_account.account_server = account.get("account_server", null)
- _clean_account.private_device_key = _account_keys.private
- _clean_account.public_device_key = _account_keys.public
+ return { "ok": true, "id": account_formatted.id }
- _clean_account.access_token = ""
- _clean_account.refresh_token = ""
- _clean_account.id_token = ""
- _clean_account.access_token_expiry = 0
-
- _clean_account.type = "oauth"
- return _clean_account
## Removes an account from the account database.
func remove(id: String) -> Dictionary:
- GlobalLogger.logs("Attempting to remove account '%s'" % id)
+ GlobalLogger.log("Attempting to remove account '%s'" % id)
var target_entry = _database.find_custom(func(entry): return entry.get("id") == id)
_database.remove_at(target_entry)
_save_account_database()
Events.emit_signal("dash_account_list_loaded")
- return {"ok": true}
+ return { "ok": true }
+
## Sets an account as the active account.
func use(id: String) -> void:
- GlobalLogger.logs("Setting active account to '%s'." % id, Enum.LogLevel.INFO)
+ GlobalLogger.log("Setting active account to '%s'." % id, Enum.LogLevel.INFO)
var _account = _get_account_by_id(id)
@@ -95,7 +79,7 @@ func use(id: String) -> void:
54000,
GlobalLogger,
HTTP,
- true
+ true,
)
if _account.type == "oauth":
@@ -108,11 +92,13 @@ func use(id: String) -> void:
Events.emit_signal("dash_active_account_changed", active_account)
return
+
## Signs out of the active account.
func clear() -> void:
- active_account = {}
+ active_account = { }
return
+
func update(id: String, data: Dictionary) -> void:
var target_entry = _database.find_custom(func(entry): return entry.get("id") == id)
var account = _get_account_by_id(id)
@@ -122,7 +108,7 @@ func update(id: String, data: Dictionary) -> void:
for key in _data_keys:
if key not in _database_keys:
- GlobalLogger.logs("Tried to update an invalid key in an account, '%s'." % key, Enum.LogLevel.WARNING)
+ GlobalLogger.log("Tried to update an invalid key in an account, '%s'." % key, Enum.LogLevel.WARNING)
continue
account[key] = data[key]
@@ -131,9 +117,10 @@ func update(id: String, data: Dictionary) -> void:
_save_account_database()
return
+
func authenticate_oauth(id: String, _remember_me: bool = false) -> void:
# TODO: Error checks
- GlobalLogger.logs("Attempting to connect account '%s' using oauth." % id)
+ GlobalLogger.log("Attempting to connect account '%s' using oauth." % id)
var account = _get_account_by_id(id)
# TODO: Check if account is still valid without trying to sign in.
@@ -147,7 +134,7 @@ func authenticate_oauth(id: String, _remember_me: bool = false) -> void:
54000,
GlobalLogger,
HTTP,
- true
+ true,
)
var oauth_tokens = await _oauth.authenticate()
@@ -156,9 +143,43 @@ func authenticate_oauth(id: String, _remember_me: bool = false) -> void:
return
+
+func get_account_authentication_status(id) -> Dictionary:
+ var status = {
+ "valid_passport": false,
+ "valid_private_jwt": false,
+ }
+
+ var _account = _get_account_by_id(id)
+
+ status.valid_passport = _account.get("public_account_server_passport", { "expires": 0 }).get("expires", 0) > int(Time.get_unix_time_from_system())
+ status.valid_private_jwt = _account.get("private_account_server_jwt", { "expires": 0 }).get("expires", 0) > int(Time.get_unix_time_from_system())
+
+ return status
+
+
+func _create_oauth(account) -> Dictionary:
+ var _account_keys = rsa_lib.generate_keypair()
+
+ var _clean_account = { }
+ _clean_account.id = random_lib.random_string(6, true)
+ _clean_account.display_name = account.get("display_name", null)
+ _clean_account.account_server = account.get("account_server", null)
+ _clean_account.private_device_key = _account_keys.private
+ _clean_account.public_device_key = _account_keys.public
+
+ _clean_account.access_token = ""
+ _clean_account.refresh_token = ""
+ _clean_account.id_token = ""
+ _clean_account.access_token_expiry = 0
+
+ _clean_account.type = "oauth"
+ return _clean_account
+
+
## Save the current account database we have in memory to the disk.
func _save_account_database() -> void:
- GlobalLogger.logs("Saving account database to disk.")
+ GlobalLogger.log("Saving account database to disk.")
DirAccess.open("user://").make_dir_recursive("user://database")
var file = FileAccess.open(ACCOUNT_DATABASE_DIRECTORY, FileAccess.WRITE)
@@ -167,18 +188,19 @@ func _save_account_database() -> void:
file.close()
return
+
## Read the account database from the config file on our disk.
-func _load_account_database() -> Array:
- GlobalLogger.logs("Loading the local account database.", Enum.LogLevel.INFO)
+func _load_account_database() -> Array[Dictionary]:
+ GlobalLogger.log("Loading the local account database.", Enum.LogLevel.INFO)
var account_file_exists = FileAccess.file_exists(ACCOUNT_DATABASE_DIRECTORY)
if account_file_exists == false:
- GlobalLogger.logs("Account database does not exist, creating one now.", Enum.LogLevel.INFO)
+ GlobalLogger.log("Account database does not exist, creating one now.", Enum.LogLevel.INFO)
_save_account_database()
var file = FileAccess.open(ACCOUNT_DATABASE_DIRECTORY, FileAccess.READ)
- var account_data
+ var account_data: Array[Dictionary]
if file:
account_data = file.get_var() # Deserializes variable back
@@ -187,13 +209,15 @@ func _load_account_database() -> Array:
_database = account_data
return account_data
+
func _get_account_by_id(id: String) -> Dictionary:
var index = _database.find_custom(func(entry): return entry.get("id") == id)
if index > -1:
return _database[index]
- return {}
+ return { }
+
func _update_account_by_key(id: String, key: String, value: Variant) -> void:
var index = _database.find_custom(func(entry): return entry.get("id") == id)
@@ -202,30 +226,18 @@ func _update_account_by_key(id: String, key: String, value: Variant) -> void:
_save_account_database()
return
-func get_account_authentication_status(id) -> Dictionary:
- var status = {
- "valid_passport": false,
- "valid_private_jwt": false
- }
-
- var _account = _get_account_by_id(id)
-
- status.valid_passport = _account.get("public_account_server_passport", {"expires": 0}).get("expires", 0) > int(Time.get_unix_time_from_system())
- status.valid_private_jwt = _account.get("private_account_server_jwt", {"expires": 0}).get("expires", 0) > int(Time.get_unix_time_from_system())
-
- return status
func _handle_response(response: Dictionary) -> Dictionary:
- var response_data = {"ok": false, "error": "", "body": {}}
+ var response_data = { "ok": false, "error": "", "body": { } }
if response.get("ok", false) == false:
response_data.error = "Request failed for unknown reason."
- GlobalLogger.logs(response_data.error, Enum.LogLevel.ERROR)
+ GlobalLogger.log(response_data.error, Enum.LogLevel.ERROR)
return response_data
if response.get("body", null) == null:
response_data.error = "No body provided from the request."
- GlobalLogger.logs(response_data.error, Enum.LogLevel.ERROR)
+ GlobalLogger.log(response_data.error, Enum.LogLevel.ERROR)
return response_data
response_data.ok = true
diff --git a/src/scripts/libs/bootstrap.gd b/src/scripts/libs/bootstrap.gd
index 0b88636..be92642 100644
--- a/src/scripts/libs/bootstrap.gd
+++ b/src/scripts/libs/bootstrap.gd
@@ -6,14 +6,14 @@
# License: MIT License
# Authors: Armored Dragon
# --- License
-
extends Node
@onready var network_m = get_tree().current_scene.get_node("NetworkManager")
+
func _notification(what: int) -> void:
if what == NOTIFICATION_WM_CLOSE_REQUEST:
- GlobalLogger.logs("Shutting down")
+ GlobalLogger.log("Shutting down")
# Shutdown / leave all servers.
for server in network_m.get_connected_sessions():
diff --git a/src/scripts/libs/jwt.gd b/src/scripts/libs/jwt.gd
index 495416b..b65cbd5 100644
--- a/src/scripts/libs/jwt.gd
+++ b/src/scripts/libs/jwt.gd
@@ -6,14 +6,13 @@
# License: MIT License
# Authors: Armored Dragon
# --- License
-
extends Node
+
# NOTE: To keep things consistent, please keep the signature always in base64. Only convert it where it will be used.
# NOTE: Currently the account server provides JWT that are Base64url encoded. We want to change this to Base64 in this application.
-
func decode(jwt_string: String = ""):
- var return_dict = {"ok": false, "data": {"head": "", "payload": "", "signature": ""}}
+ var return_dict = { "ok": false, "data": { "head": "", "payload": "", "signature": "" } }
var jwt_parts = _get_parts(jwt_string)
return_dict.data.head = JSON.parse_string(Marshalls.base64_to_utf8(base64url_to_base64(jwt_parts.head)))
@@ -23,31 +22,34 @@ func decode(jwt_string: String = ""):
return return_dict
+
func encode():
return
+
func validate(jwt_string: String, public_spki: String):
var crypto: Crypto = Crypto.new()
var jwt_parts: Dictionary = _get_parts(jwt_string)
var public_key: CryptoKey = pem_to_cryptokey(public_spki)
if jwt_parts.ok != true:
- GlobalLogger.logs("Failed to deconstruct jwt when verifying jwt.", Enum.LogLevel.WARNING)
- GlobalLogger.logs(str(jwt_string))
+ GlobalLogger.log("Failed to deconstruct jwt when verifying jwt.", Enum.LogLevel.WARNING)
+ GlobalLogger.log(str(jwt_string))
return false
var formatted_payload: Dictionary = _format_payload_for_verification(jwt_parts.head, jwt_parts.payload)
if formatted_payload.ok != true:
- GlobalLogger.logs("Failed to format the jwt payload when verifying jwt.", Enum.LogLevel.WARNING)
- GlobalLogger.logs(str(jwt_parts))
+ GlobalLogger.log("Failed to format the jwt payload when verifying jwt.", Enum.LogLevel.WARNING)
+ GlobalLogger.log(str(jwt_parts))
return false
return crypto.verify(
HashingContext.HASH_SHA256,
formatted_payload.payload_bytes,
Marshalls.base64_to_raw(jwt_parts.signature),
- public_key
+ public_key,
)
+
func base64url_to_base64(input_value: String):
var fixed: String = input_value
@@ -59,6 +61,7 @@ func base64url_to_base64(input_value: String):
return fixed
+
func base64_to_base64url(input_value: String):
var base64_str = input_value.replace("+", "-")
base64_str = base64_str.replace("/", "_")
@@ -68,14 +71,25 @@ func base64_to_base64url(input_value: String):
return base64_str
+
+func pem_to_cryptokey(pem: String = "") -> CryptoKey:
+ # TODO: Error checks
+ var public_key := CryptoKey.new()
+ if public_key.load_from_string(pem, true) != OK:
+ GlobalLogger.log("Failed to load public key", Enum.LogLevel.ERROR)
+ return null
+
+ return public_key
+
+
func _get_parts(input_value: String):
# TODO: Error checks
- var return_dict = {"ok": false, "error": "", "head": "", "payload": "", "signature": ""}
+ var return_dict = { "ok": false, "error": "", "head": "", "payload": "", "signature": "" }
var jwt_split = input_value.split(".")
if len(jwt_split) != 3:
- GlobalLogger.logs("JWT is not formatted correctly.", Enum.LogLevel.WARNING)
+ GlobalLogger.log("JWT is not formatted correctly.", Enum.LogLevel.WARNING)
return_dict.error = "JWT is not formatted correctly."
return return_dict
@@ -86,9 +100,10 @@ func _get_parts(input_value: String):
return return_dict
+
func _format_payload_for_verification(head: String, payload: String) -> Dictionary:
# TODO: Error checks
- var return_dict = {"ok": false, "payload_bytes": []}
+ var return_dict = { "ok": false, "payload_bytes": [] }
var formatted_payload = head + "." + payload
var payload_bytes = formatted_payload.to_utf8_buffer()
@@ -101,12 +116,3 @@ func _format_payload_for_verification(head: String, payload: String) -> Dictiona
return_dict.ok = true
return return_dict
-
-func pem_to_cryptokey(pem: String = "") -> CryptoKey:
- # TODO: Error checks
- var public_key := CryptoKey.new()
- if public_key.load_from_string(pem, true) != OK:
- GlobalLogger.logs("Failed to load public key", Enum.LogLevel.ERROR)
- return null
-
- return public_key
diff --git a/src/scripts/managers/settings.gd b/src/scripts/managers/settings.gd
index 842450c..37665ee 100644
--- a/src/scripts/managers/settings.gd
+++ b/src/scripts/managers/settings.gd
@@ -6,34 +6,54 @@
# License: MIT License
# Authors: Armored Dragon
# --- License
-
extends Node
-var _settings = {}
+const _templates = {
+ # The full settings file that is saved and stored.
+ "settings_file": {
+ "graphics": {
+ "display_mode": Enum.Settings.Graphics.DisplayMode.FULLSCREEN,
+ },
+ "config": {
+ "session_servers": [],
+ },
+ },
+
+ # Small templates that are duplicated and used to
+ "session_server": {
+ "name": "",
+ "url": "",
+ "date_added": int(0),
+ },
+}
+
+var _settings = { }
+
func _ready():
_load_settings()
+
# Settings versioning
# Settings file upgrade
-
# Get setting
func get_session_servers() -> Array:
var return_arr = []
- return_arr = _settings.get("config", {}).get("session_servers", [])
+ return_arr = _settings.get("config", { }).get("session_servers", [])
return return_arr
-func add_session_server(session_server: Dictionary) -> bool:
- var _name = session_server.get("name", "")
- var _url = session_server.get("url", "")
+
+func add_session_server(server_url: String) -> bool:
var _date_added = Time.get_unix_time_from_system()
- _settings.config.session_servers.append({"name": _name, "url": _url, "date_added": _date_added})
+ _settings.config.session_servers.append({ "url": server_url, "date_added": _date_added })
_save_settings()
+ Events.emit_signal("dash_settings_updated")
return true
+
func remove_session_server(url: String) -> bool:
var _index = -1
for i in range(_settings.config.session_servers.size()):
@@ -45,16 +65,19 @@ func remove_session_server(url: String) -> bool:
_settings.config.session_servers.remove_at(_index)
_save_settings()
+ Events.emit_signal("dash_settings_updated")
return false
+
func _save_settings():
var _file = FileAccess.open("user://settings/current.json", FileAccess.WRITE)
var _settings_string: String = JSON.stringify(_settings)
_file.store_string(_settings_string)
_file.close()
- GlobalLogger.logs("Saved settings file.", Enum.LogLevel.INFO)
+ GlobalLogger.log("Saved settings file.", Enum.LogLevel.INFO)
return
+
func _load_settings() -> void:
var _settings_exist: bool = FileAccess.file_exists("user://settings/current.json")
if _settings_exist:
@@ -62,32 +85,14 @@ func _load_settings() -> void:
var _content = _file.get_as_text()
var _parsed = JSON.parse_string(_content)
_settings = _parsed
- GlobalLogger.logs("Settings have been loaded.", Enum.LogLevel.INFO)
+ print(_content)
+ GlobalLogger.log("Settings have been loaded.", Enum.LogLevel.INFO)
return
# TODO: Check if backup settings exist.
- GlobalLogger.logs("Settings file does not exist, creating new settings file.", Enum.LogLevel.INFO)
+ GlobalLogger.log("Settings file does not exist, creating new settings file.", Enum.LogLevel.INFO)
FileManager.create_file("user://settings/", "current.json")
_settings = _templates.settings_file
_save_settings()
- GlobalLogger.logs("Blank settings have been loaded.", Enum.LogLevel.INFO)
+ GlobalLogger.log("Blank settings have been loaded.", Enum.LogLevel.INFO)
return
-
-const _templates = {
- # The full settings file that is saved and stored.
- "settings_file": {
- "graphics": {
- "display_mode": Enum.Settings.Graphics.DisplayMode.FULLSCREEN
- },
- "config": {
- "session_servers": []
- }
- },
-
- # Small templates that are duplicated and used to
- "session_server": {
- "name": "",
- "url": "",
- "date_added": int(0)
- }
-}
diff --git a/src/scripts/managers/settings.gd.uid b/src/scripts/managers/settings.gd.uid
index ab6ac06..f2c8d9e 100644
--- a/src/scripts/managers/settings.gd.uid
+++ b/src/scripts/managers/settings.gd.uid
@@ -1 +1 @@
-uid://bj4giyk05v042
+uid://cgvvntx8o26ds
diff --git a/src/scripts/network/account_servers.gd b/src/scripts/network/account_servers.gd
index 4227491..9656971 100644
--- a/src/scripts/network/account_servers.gd
+++ b/src/scripts/network/account_servers.gd
@@ -1,9 +1,9 @@
extends Node
-var _database = {}
+var _database = { }
-# TODO: Save public account server keys to disk
+# TODO: Save public account server keys to disk
func get_public_key(host: String, port: int) -> String:
if host in _database:
return _database[host]
@@ -15,9 +15,10 @@ func get_public_key(host: String, port: int) -> String:
return ""
+
func _request_server_pem(host: String, port: int = 443) -> Dictionary:
- GlobalLogger.logs("Requesting server '%s:%s'." % [host, port])
- var return_dict = {"ok": false, "data": ""}
+ GlobalLogger.log("Requesting server '%s:%s'." % [host, port])
+ var return_dict = { "ok": false, "data": "" }
var key = await HTTP.req(HTTPClient.METHOD_GET, host, "/public_key", port)
if key.ok == true:
return_dict.data = key.body
diff --git a/src/scripts/network/http.gd b/src/scripts/network/http.gd
index c804400..acf2332 100644
--- a/src/scripts/network/http.gd
+++ b/src/scripts/network/http.gd
@@ -1,3 +1,12 @@
+# --- License
+# File: /http.gd
+# Project: openminerva.oauth2
+# Created Date: 04 May 2026
+# Copyright (c) 2026 OpenMinerva
+# License: MIT License
+# Authors: Armored Dragon
+# --- License
+
extends Node
signal _completed(result: Dictionary)
diff --git a/src/scripts/network/network_compression.gd b/src/scripts/network/network_compression.gd
index 5fa51cf..8d1b618 100644
--- a/src/scripts/network/network_compression.gd
+++ b/src/scripts/network/network_compression.gd
@@ -1,7 +1,7 @@
extends Node
-# TODO: Positional data can further be reduced by using raw bytes instead of the given 16 bits. Maybe shoot for 10 bytes?
+# TODO: Positional data can further be reduced by using raw bytes instead of the given 16 bits. Maybe shoot for 10 bytes?
## Compresses a Vector3 to a PackedByteArray using 32 bit precision
## @returns PackedByteArray
func c_32_vec3(provided_data: Vector3) -> PackedByteArray:
@@ -13,12 +13,13 @@ func c_32_vec3(provided_data: Vector3) -> PackedByteArray:
return data
+
## Decompress a PackedByteArray to a Vector3 using 32 bit precision
## @returns Vector3
func d_32_vec3(provided_data: PackedByteArray) -> Vector3:
# Validate array size
if provided_data.size() < 12:
- GlobalLogger.logs("'%s' contained invalid PackedByteArray size. Can not decode value.", Enum.LogLevel.WARNING)
+ GlobalLogger.log("'%s' contained invalid PackedByteArray size. Can not decode value.", Enum.LogLevel.WARNING)
return Vector3()
var x = _int_to_float(provided_data.decode_s32(0))
@@ -27,6 +28,7 @@ func d_32_vec3(provided_data: PackedByteArray) -> Vector3:
return Vector3(x, y, z)
+
## Compresses a Vector3 to a PackedByteArray using 16 bit precision
## @returns PackedByteArray
func c_16_vec3(provided_data: Vector3) -> PackedByteArray:
@@ -38,12 +40,13 @@ func c_16_vec3(provided_data: Vector3) -> PackedByteArray:
return data
+
## Decompress a PackedByteArray to a Vector3 using 16 bit precision
## @returns Vector3
func d_16_vec3(provided_data: PackedByteArray) -> Vector3:
# Validate array size
if provided_data.size() < 6:
- GlobalLogger.logs("'%s' contained invalid PackedByteArray size. Can not decode value.", Enum.LogLevel.WARNING)
+ GlobalLogger.log("'%s' contained invalid PackedByteArray size. Can not decode value.", Enum.LogLevel.WARNING)
return Vector3()
var x = _int_to_float(provided_data.decode_s16(0))
@@ -52,6 +55,7 @@ func d_16_vec3(provided_data: PackedByteArray) -> Vector3:
return Vector3(x, y, z)
+
## Compresses a user position with octree position to a PackedByteArray using 32 bit precision
## @returns PackedByteArray
func c_32_pos(provided_data: Vector3) -> PackedByteArray:
@@ -88,6 +92,7 @@ func c_32_pos(provided_data: Vector3) -> PackedByteArray:
return p_c_pos
+
## Decompress a user position with octree position to a Vector3 using 32 bit precision
## @returns Vector3
func d_32_pos(provided_data: PackedByteArray) -> Vector3:
@@ -110,6 +115,7 @@ func d_32_pos(provided_data: PackedByteArray) -> Vector3:
return global_position
+
## Compresses a user position with octree position to a PackedByteArray using 16 bit precision
## @returns PackedByteArray
func c_16_pos(provided_data: Vector3) -> PackedByteArray:
@@ -134,6 +140,7 @@ func c_16_pos(provided_data: Vector3) -> PackedByteArray:
return p_c_pos
+
## Decompress a user position with octree position to a Vector3 using 16 bit precision
## @returns Vector3
func d_16_pos(provided_data: PackedByteArray) -> Vector3:
@@ -156,10 +163,12 @@ func d_16_pos(provided_data: PackedByteArray) -> Vector3:
return global_position
+
func _float_to_int(val: float) -> int:
const FLOAT_PRECISION: int = 1000
return int(val * FLOAT_PRECISION)
+
func _int_to_float(val: int) -> float:
const FLOAT_PRECISION: int = 1000
return float(val) / FLOAT_PRECISION
diff --git a/src/scripts/signal_bus.gd b/src/scripts/signal_bus.gd
index aa5b93b..3b836e4 100644
--- a/src/scripts/signal_bus.gd
+++ b/src/scripts/signal_bus.gd
@@ -8,7 +8,6 @@
# --- License
extends Node
-
# Dashboard
@warning_ignore("unused_signal")
signal dash_set_state(is_open: bool)
@@ -26,15 +25,16 @@ signal dash_message_received(message: Dictionary)
signal dash_notification(notification: Dictionary)
@warning_ignore("unused_signal")
signal dash_account_list_loaded(account_list: PackedStringArray)
-
+# Settings
+@warning_ignore("unused_signal")
+signal dash_settings_updated()
# Instance
@warning_ignore("unused_signal")
signal instance_updated(instance: Dictionary)
@warning_ignore("unused_signal")
signal instance_root_changed(instance: Dictionary)
-
# Multiplayer
@warning_ignore("unused_signal")
signal session_joined(instance: Dictionary)
@warning_ignore("unused_signal")
-signal session_left(instance: Dictionary)
\ No newline at end of file
+signal session_left(instance: Dictionary)
diff --git a/src/scripts/utils/files.gd b/src/scripts/utils/files.gd
index b1d64df..f31a934 100644
--- a/src/scripts/utils/files.gd
+++ b/src/scripts/utils/files.gd
@@ -1,8 +1,9 @@
extends Node
+
## Creates a log file following the internal format.
func create_log_file() -> String:
- GlobalLogger.logs("Creating a log file for this session.")
+ GlobalLogger.log("Creating a log file for this session.")
_maybe_make_directory("user://logs/")
# TODO: Sanataize param
# TODO: Error checks
@@ -11,20 +12,23 @@ func create_log_file() -> String:
var log_file_path = "user://logs/%s.%s" % [ProjectSettings.get_setting("application/config/name"), log_file_name]
var file = FileAccess.open(log_file_path, FileAccess.WRITE)
file.close()
- GlobalLogger.logs("Log file '%s' created." % log_file_path)
+ GlobalLogger.log("Log file '%s' created." % log_file_path)
return log_file_path
+
func create_file(dir: String, file_name: String) -> void:
_maybe_make_directory(dir)
# TODO: Sanitize name
var file = FileAccess.open("%s/%s" % [dir, file_name], FileAccess.WRITE)
- GlobalLogger.logs("File '%s' created at '%s'." % [file_name, dir])
+ GlobalLogger.log("File '%s' created at '%s'." % [file_name, dir])
file.close()
+
func _maybe_make_directory(dir: String):
var dir_access = DirAccess.open("user://")
dir_access.make_dir_recursive(dir)
+
func _parse_log_file_name(file_name: String) -> Dictionary:
var date = file_name.split(".")[1].split("-")
var year = date[0].split("_")[0]
@@ -36,6 +40,7 @@ func _parse_log_file_name(file_name: String) -> Dictionary:
var time_dictionary = Time.get_datetime_dict_from_datetime_string("%s-%s-%sT%s:%s:%s" % [year, month, day, hour, minute, second], true)
return time_dictionary
+
func _get_today_log_file_name() -> String:
var current_timestring = Time.get_datetime_string_from_system()
var file_name = current_timestring.replace("-", "_").replace("T", "-").replace(":", "_")
diff --git a/src/userinterface/dash/account_create.gd b/src/userinterface/dash/account_create.gd
deleted file mode 100644
index 81b7f4b..0000000
--- a/src/userinterface/dash/account_create.gd
+++ /dev/null
@@ -1,60 +0,0 @@
-# --- License
-# File: /client/src/userinterface/dash/account_create.gd
-# Project: OpenMinerva
-# Created Date: 28 March 2026
-# Copyright (c) 2026 OpenMinerva
-# License: MIT License
-# Authors: Armored Dragon
-# --- License
-
-extends Control
-
-var _page_names = []
-@onready var create = get_node("Create")
-@onready var select_oauth_btn = get_node("Create/SelectMethod/Container/OAuth")
-@onready var create_oauth_btn = get_node("Create/OAuth/Create/HBoxContainer/ConfirmCreateAccount")
-@onready var create_oauth_back_btn = get_node("Create/OAuth/Create/HBoxContainer/CreateAccountBack")
-
-func _ready():
- _get_pages()
- select_oauth_btn.pressed.connect(_display_login_route.bind("OAuth"))
-
- create_oauth_btn.pressed.connect(_create_oauth)
- create_oauth_back_btn.pressed.connect(_display_login_route.bind("SelectMethod"))
- return
-
-func _display_oauth():
- return
-
-func _display_login_route(page_name: String):
- if page_name not in _page_names:
- GlobalLogger.logs("Tried to display an invalid login route.", Enum.LogLevel.WARNING)
- return
-
- for page in create.get_children():
- if page.name == page_name:
- page.visible = true
- continue
-
- page.visible = false
- return
-
-func _get_pages() -> void:
- for page in create.get_children():
- _page_names.append(page.name)
- return
-
-func _create_oauth() -> void:
- var display_name = get_node("Create/OAuth/Create/VBoxContainer3/CADisplayName").text
- var account_server = get_node("Create/OAuth/Create/VBoxContainer3/CAAccountServer").text
-
- var account = {
- "display_name": display_name,
- "account_server": account_server
- }
-
- GlobalAccount.create(account, "oauth")
-
- Events.emit_signal("dash_switch_tab", "AccountDisplay")
-
- return
diff --git a/src/userinterface/dash/account_create.gd.uid b/src/userinterface/dash/account_create.gd.uid
deleted file mode 100644
index 1866a83..0000000
--- a/src/userinterface/dash/account_create.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://cchqs4c1p1prd
diff --git a/src/userinterface/dash/account_list.gd b/src/userinterface/dash/account_list.gd
deleted file mode 100644
index 14e47aa..0000000
--- a/src/userinterface/dash/account_list.gd
+++ /dev/null
@@ -1,69 +0,0 @@
-# --- License
-# File: /client/src/userinterface/dash/account_list.gd
-# Project: OpenMinerva
-# Created Date: 28 March 2026
-# Copyright (c) 2026 OpenMinerva
-# License: MIT License
-# Authors: Armored Dragon
-# --- License
-
-extends Control
-
-@onready var _account_template = get_node("Templates/Account")
-@onready var _account_list = get_node("List/ScrollContainer/AccountList")
-@onready var _create_account_button = get_node("List/HBoxContainer/NewAccount")
-
-func _ready():
- _display_account_lists()
- _create_account_button.pressed.connect(Events.emit_signal.bind("dash_switch_tab", "AccountCreate"))
-
- Events.dash_set_state.connect(_handle_dash_set_state)
- Events.dash_account_list_loaded.connect(_handle_account_list_loaded)
- return
-
-func _clear_account_listings() -> void:
- for child in _account_list.get_children():
- child.queue_free()
- return
-
-func _handle_dash_set_state(state: bool) -> void:
- if state == false:
- return
-
- _clear_account_listings()
- _display_account_lists()
- return
-
-func _handle_account_list_loaded() -> void:
- _clear_account_listings()
- _display_account_lists()
- return
-
-func _display_account_lists() -> void:
- var _list = GlobalAccount.get_all()
-
- if len(_list) == 0:
- GlobalLogger.logs("No accounts to display.")
- return
-
- for account in _list:
- var _account_listing = _account_template.duplicate()
-
- var _username_node = _account_listing.get_node("MarginContainer/HBoxContainer/VBoxContainer/Username")
- var _account_server_node = _account_listing.get_node("MarginContainer/HBoxContainer/VBoxContainer/AccountServer")
- var _login_button = _account_listing.get_node("MarginContainer/HBoxContainer/VBoxContainer/HBoxContainer/Login")
- var _configure_button = _account_listing.get_node("MarginContainer/HBoxContainer/VBoxContainer/HBoxContainer/Configure")
- var _remove_button = _account_listing.get_node("MarginContainer/HBoxContainer/VBoxContainer/HBoxContainer/Remove")
-
- # Display
- if account.type == "oauth":
- _username_node.text = account.display_name
- _account_server_node.text = account.account_server
-
- # Event listeners
- _login_button.pressed.connect(GlobalAccount.use.bind(account.id))
- _remove_button.pressed.connect(GlobalAccount.remove.bind(account.id))
-
- _account_list.add_child(_account_listing)
- GlobalLogger.logs("Added account '%s' to the login list." % account.id)
- return
diff --git a/src/userinterface/dash/account_list.gd.uid b/src/userinterface/dash/account_list.gd.uid
deleted file mode 100644
index e8d0fca..0000000
--- a/src/userinterface/dash/account_list.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://ftk8qksc10qg
diff --git a/src/userinterface/dash/apps.gd b/src/userinterface/dash/apps.gd
deleted file mode 100644
index 2f8863f..0000000
--- a/src/userinterface/dash/apps.gd
+++ /dev/null
@@ -1,10 +0,0 @@
-# --- License
-# File: /client/src/userinterface/dash/apps.gd
-# Project: OpenMinerva
-# Created Date: 27 March 2026
-# Copyright (c) 2026 OpenMinerva
-# License: MIT License
-# Authors: Armored Dragon
-# --- License
-
-extends Control
\ No newline at end of file
diff --git a/src/userinterface/dash/apps.gd.uid b/src/userinterface/dash/apps.gd.uid
deleted file mode 100644
index 9526fc4..0000000
--- a/src/userinterface/dash/apps.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://di7li0digjpa8
diff --git a/src/userinterface/dash/contacts.gd b/src/userinterface/dash/contacts.gd
deleted file mode 100644
index c54ac2a..0000000
--- a/src/userinterface/dash/contacts.gd
+++ /dev/null
@@ -1,10 +0,0 @@
-# --- License
-# File: /client/src/userinterface/dash/contacts.gd
-# Project: OpenMinerva
-# Created Date: 27 March 2026
-# Copyright (c) 2026 OpenMinerva
-# License: MIT License
-# Authors: Armored Dragon
-# --- License
-
-extends Control
diff --git a/src/userinterface/dash/contacts.gd.uid b/src/userinterface/dash/contacts.gd.uid
deleted file mode 100644
index 5468a3a..0000000
--- a/src/userinterface/dash/contacts.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://crlujtfv2bh1w
diff --git a/src/userinterface/dash/debug.gd b/src/userinterface/dash/debug.gd
deleted file mode 100644
index 3c4ba87..0000000
--- a/src/userinterface/dash/debug.gd
+++ /dev/null
@@ -1,10 +0,0 @@
-# --- License
-# File: /client/src/userinterface/dash/debug.gd
-# Project: OpenMinerva
-# Created Date: 27 March 2026
-# Copyright (c) 2026 OpenMinerva
-# License: MIT License
-# Authors: Armored Dragon
-# --- License
-
-extends Control
\ No newline at end of file
diff --git a/src/userinterface/dash/debug.gd.uid b/src/userinterface/dash/debug.gd.uid
deleted file mode 100644
index 669c34b..0000000
--- a/src/userinterface/dash/debug.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://bwcvodv6u21jm
diff --git a/src/userinterface/dash/exit.gd b/src/userinterface/dash/exit.gd
deleted file mode 100644
index 75b8331..0000000
--- a/src/userinterface/dash/exit.gd
+++ /dev/null
@@ -1,29 +0,0 @@
-# --- License
-# File: /client/src/userinterface/dash/exit.gd
-# Project: OpenMinerva
-# Created Date: 27 March 2026
-# Copyright (c) 2026 OpenMinerva
-# License: MIT License
-# Authors: Armored Dragon
-# --- License
-
-extends Control
-@onready var _cancel_button = get_node("VBoxContainer/HBoxContainer/Cancel")
-@onready var _exit_button = get_node("VBoxContainer/HBoxContainer/Exit")
-
-func _ready():
- _cancel_button.pressed.connect(_handle_cancel_pressed)
- _exit_button.pressed.connect(_handle_exit_pressed)
- return
-
-func _handle_cancel_pressed():
- Events.emit_signal("dash_switch_tab", "Home")
- return
-
-func _handle_exit_pressed():
- # TODO: Save?
- # TODO: Sync?
- # TODO: Validate database?
- # TODO: Prune cache?
- get_tree().root.propagate_notification(NOTIFICATION_WM_CLOSE_REQUEST)
- return
diff --git a/src/userinterface/dash/exit.gd.uid b/src/userinterface/dash/exit.gd.uid
deleted file mode 100644
index 6bf2d79..0000000
--- a/src/userinterface/dash/exit.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://e1djdo6st2a7
diff --git a/src/userinterface/dash/home.gd b/src/userinterface/dash/home.gd
deleted file mode 100644
index 9166e48..0000000
--- a/src/userinterface/dash/home.gd
+++ /dev/null
@@ -1,69 +0,0 @@
-# --- License
-# File: /client/src/userinterface/dash/home.gd
-# Project: OpenMinerva
-# Created Date: 27 March 2026
-# Copyright (c) 2026 OpenMinerva
-# License: MIT License
-# Authors: Armored Dragon
-# --- License
-
-extends Control
-
-@onready var network_m = get_tree().current_scene.get_node("NetworkManager")
-@onready var scene_m = get_tree().current_scene.get_node("SceneManager")
-
-@onready var account_card_container = get_node("HBoxContainer/VBoxContainer/AccountDisplay")
-@onready var storage_card_container = get_node("HBoxContainer/VBoxContainer/StorageDisplay")
-@onready var active_sessions_container = get_node("HBoxContainer/VBoxContainer/ActiveSessions")
-@onready var session_card_container = get_node("HBoxContainer/VBoxContainer3/SessionDisplay")
-
-@onready var active_session_template = get_node("Templates/ActiveSessionButton")
-
-func _ready():
- account_card_container.get_node("Button").pressed.connect(Events.emit_signal.bind("dash_switch_tab", "AccountDisplay"))
-
- Events.connect("dash_active_account_changed", _handle_active_account_changed)
- Events.connect("dash_storage_changed", _handle_storage_changed)
- Events.connect("dash_session_changed", _handle_session_changed)
-
- Events.connect("session_joined", _display_active_sessions)
- Events.connect("session_left", _display_active_sessions)
-
- _display_active_sessions()
-
- return
-
-func _handle_active_account_changed(account: Dictionary) -> void:
- account_card_container.get_node("MarginContainer/HBoxContainer/VBoxContainer/Username").text = account.get("username") if account.get("username") else account.get("display_name")
- account_card_container.get_node("MarginContainer/HBoxContainer/VBoxContainer/AccountServer").text = account.account_server
- return
-
-func _handle_storage_changed(storage_data: Dictionary) -> void:
- storage_card_container.get_node("MarginContainer/VBoxContainer/ProgressBar").value = storage_data.used_percent
- storage_card_container.get_node("MarginContainer/VBoxContainer/Label2").text = "%s GiB used of %s GiB" % [storage_data.used_gigs, storage_data.total_gigs]
- return
-
-func _handle_session_changed(session_data: Dictionary) -> void:
- session_card_container.get_node("MarginContainer/HBoxContainer/VBoxContainer/SessionName").text = session_data.session_name
- return
-
-func _display_active_sessions() -> void:
- for node in active_sessions_container.get_node("MarginContainer/VBoxContainer").get_children():
- if node is not Label:
- node.queue_free()
-
- var _sessions = network_m.get_connected_sessions()
-
- for session in _sessions:
- var _entry = active_session_template.duplicate()
- var _entry_label = _entry.get_node("HBoxContainer/Join")
- var _entry_close = _entry.get_node("HBoxContainer/Close")
-
- _entry_label.text = session.id
- _entry_label.pressed.connect(scene_m.set_active_session.bind(session.id))
- _entry_close.pressed.connect(network_m.leave_server.bind(session.id))
-
- active_sessions_container.get_node("MarginContainer/VBoxContainer").add_child(_entry)
-
- # TODO: When button is pressed, focus that session
- return
diff --git a/src/userinterface/dash/home.gd.uid b/src/userinterface/dash/home.gd.uid
deleted file mode 100644
index b2c4911..0000000
--- a/src/userinterface/dash/home.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://bwcgqn33pn62o
diff --git a/src/userinterface/dash/hud.tscn b/src/userinterface/dash/hud.tscn
deleted file mode 100644
index 415a470..0000000
--- a/src/userinterface/dash/hud.tscn
+++ /dev/null
@@ -1,2729 +0,0 @@
-[gd_scene format=3 uid="uid://ckl5gw0xbduiv"]
-
-[ext_resource type="Texture2D" uid="uid://7mgxvhy58nhp" path="res://resources/icons/home.svg" id="1_3b2ci"]
-[ext_resource type="Theme" uid="uid://bg2nbganyysst" path="res://openminerva_default.tres" id="1_cx7w0"]
-[ext_resource type="Script" uid="uid://cbl7rmnjxarba" path="res://userinterface/dash/master.gd" id="1_ugu7k"]
-[ext_resource type="Texture2D" uid="uid://coqi7w7inqyv1" path="res://resources/icons/account.svg" id="2_bucoy"]
-[ext_resource type="Texture2D" uid="uid://crrjk7c2g4q55" path="res://resources/icons/art.svg" id="3_6vaiq"]
-[ext_resource type="Script" uid="uid://bwcgqn33pn62o" path="res://userinterface/dash/home.gd" id="3_bnkjl"]
-[ext_resource type="Texture2D" uid="uid://c7ofnclcof0ud" path="res://resources/icons/world.svg" id="3_v4ccx"]
-[ext_resource type="StyleBox" uid="uid://cxx1q037xaswi" path="res://openminerva_darkpanel.tres" id="4_6rlgq"]
-[ext_resource type="Texture2D" uid="uid://dfckge3u00boi" path="res://resources/icons/contacts.svg" id="4_cyduv"]
-[ext_resource type="Texture2D" uid="uid://cnhy47i7saehq" path="res://resources/icons/environment.svg" id="4_tkvwg"]
-[ext_resource type="Texture2D" uid="uid://rdp5i1i18jus" path="res://resources/icons/search.svg" id="4_wfski"]
-[ext_resource type="Texture2D" uid="uid://fkfiymss8p57" path="res://resources/icons/science.svg" id="5_hu6eh"]
-[ext_resource type="Texture2D" uid="uid://br6hpysqvuhek" path="res://resources/icons/inventory.svg" id="5_r82dk"]
-[ext_resource type="Script" uid="uid://ftk8qksc10qg" path="res://userinterface/dash/account_list.gd" id="5_upsw6"]
-[ext_resource type="Script" uid="uid://cchqs4c1p1prd" path="res://userinterface/dash/account_create.gd" id="6_3rk53"]
-[ext_resource type="Texture2D" uid="uid://dp5u16rwxd0bp" path="res://resources/icons/apps.svg" id="6_6ybpt"]
-[ext_resource type="Texture2D" uid="uid://b0qo67fgifqe8" path="res://resources/icons/circus.svg" id="6_hu6eh"]
-[ext_resource type="Texture2D" uid="uid://basvqob80u3l6" path="res://resources/icons/settings.svg" id="7_tixj4"]
-[ext_resource type="Script" uid="uid://ccd2fw88a52mp" path="res://userinterface/dash/sessions.gd" id="8_4ahgm"]
-[ext_resource type="Texture2D" uid="uid://b8fed1h3aqw1s" path="res://resources/icons/debug.svg" id="8_fgqsp"]
-[ext_resource type="Texture2D" uid="uid://8fwxg1ipf0fp" path="res://resources/icons/exit.svg" id="9_amc1p"]
-[ext_resource type="Texture2D" uid="uid://ckoajckje5mq2" path="res://resources/icons/edit.svg" id="9_xdslj"]
-[ext_resource type="Texture2D" uid="uid://ddchrocw45muh" path="res://resources/icons/flowchart.svg" id="12_hq11n"]
-[ext_resource type="Script" uid="uid://dpo2x4ddv3ftt" path="res://userinterface/dash/instance.gd" id="14_3ff87"]
-[ext_resource type="Script" uid="uid://crlujtfv2bh1w" path="res://userinterface/dash/contacts.gd" id="15_gll50"]
-[ext_resource type="Script" uid="uid://e1djdo6st2a7" path="res://userinterface/dash/exit.gd" id="17_3rk53"]
-[ext_resource type="Script" uid="uid://cq26hbvdqb4sf" path="res://userinterface/dash/settings.gd" id="17_shwvw"]
-
-[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_kgckq"]
-draw_center = false
-
-[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_6vaiq"]
-bg_color = Color(0, 0, 0, 1)
-expand_margin_left = 2.0
-expand_margin_top = 2.0
-expand_margin_right = 2.0
-expand_margin_bottom = 2.0
-
-[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_wfski"]
-bg_color = Color(0, 0.73333335, 1, 1)
-
-[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_bucoy"]
-bg_color = Color(1, 0, 0, 1)
-corner_radius_top_left = 100
-corner_radius_top_right = 100
-corner_radius_bottom_right = 100
-corner_radius_bottom_left = 100
-
-[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dr1q3"]
-bg_color = Color(0, 0.73333335, 1, 1)
-corner_radius_top_left = 100
-corner_radius_top_right = 100
-corner_radius_bottom_right = 100
-corner_radius_bottom_left = 100
-
-[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_shwvw"]
-
-[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_3ff87"]
-
-[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_xdslj"]
-bg_color = Color(2.466701e-07, 0.13600668, 0.20061767, 1)
-
-[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_6rlgq"]
-bg_color = Color(0.099985994, 0.09998601, 0.099985965, 1)
-
-[sub_resource type="Theme" id="Theme_q6jcb"]
-
-[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_hq11n"]
-bg_color = Color(0.60038817, 0.60038817, 0.60038817, 0)
-draw_center = false
-
-[sub_resource type="CompressedTexture2D" id="CompressedTexture2D_hq11n"]
-
-[node name="Hud" type="Control" unique_id=1053137144]
-layout_mode = 3
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-script = ExtResource("1_ugu7k")
-
-[node name="MarginContainer" type="MarginContainer" parent="." unique_id=1988156212]
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer" unique_id=1376103708]
-layout_mode = 2
-theme_override_constants/separation = 10
-
-[node name="Master" type="Panel" parent="MarginContainer/VBoxContainer" unique_id=911098732]
-layout_mode = 2
-size_flags_vertical = 3
-theme = ExtResource("1_cx7w0")
-
-[node name="Home" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master" unique_id=675278383]
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-script = ExtResource("3_bnkjl")
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Home" unique_id=581087957]
-layout_mode = 2
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer" unique_id=2138031361]
-layout_mode = 2
-size_flags_horizontal = 3
-theme_override_constants/separation = 20
-
-[node name="AccountDisplay" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer" unique_id=383858349]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/AccountDisplay" unique_id=2024761038]
-layout_mode = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/AccountDisplay/MarginContainer" unique_id=133275778]
-layout_mode = 2
-theme_override_constants/separation = 20
-
-[node name="Container" type="CenterContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/AccountDisplay/MarginContainer/HBoxContainer" unique_id=539177141]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/AccountDisplay/MarginContainer/HBoxContainer/Container" unique_id=1941945009]
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/AccountDisplay/MarginContainer/HBoxContainer/Container/AspectRatioContainer" unique_id=1382039916]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-stretch_mode = 5
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/AccountDisplay/MarginContainer/HBoxContainer" unique_id=1966375622]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="Username" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/AccountDisplay/MarginContainer/HBoxContainer/VBoxContainer" unique_id=321531249]
-layout_mode = 2
-size_flags_vertical = 3
-theme_override_font_sizes/normal_font_size = 20
-bbcode_enabled = true
-text = "[color=gray]No Account[/color]"
-fit_content = true
-
-[node name="AccountServer" type="Label" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/AccountDisplay/MarginContainer/HBoxContainer/VBoxContainer" unique_id=881790720]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.7977378, 0.7977378, 0.7977378, 1)
-theme_override_font_sizes/font_size = 14
-
-[node name="Button" type="Button" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/AccountDisplay" unique_id=58113697]
-layout_mode = 2
-theme_override_styles/normal = SubResource("StyleBoxFlat_kgckq")
-
-[node name="StorageDisplay" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer" unique_id=1169784328]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/StorageDisplay" unique_id=1944750319]
-layout_mode = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/StorageDisplay/MarginContainer" unique_id=1039592827]
-layout_mode = 2
-theme_override_constants/separation = 10
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/StorageDisplay/MarginContainer/VBoxContainer" unique_id=21628856]
-layout_mode = 2
-text = "Used Storage"
-horizontal_alignment = 1
-
-[node name="ProgressBar" type="ProgressBar" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/StorageDisplay/MarginContainer/VBoxContainer" unique_id=1535856991]
-layout_mode = 2
-theme_override_styles/background = SubResource("StyleBoxFlat_6vaiq")
-theme_override_styles/fill = SubResource("StyleBoxFlat_wfski")
-value = 25.0
-
-[node name="Label2" type="Label" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/StorageDisplay/MarginContainer/VBoxContainer" unique_id=749951536]
-layout_mode = 2
-text = "2.5 GiB / 5 GiB"
-horizontal_alignment = 1
-
-[node name="ActiveSessions" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer" unique_id=1874646451]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/ActiveSessions" unique_id=591364507]
-layout_mode = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/ActiveSessions/MarginContainer" unique_id=1770756004]
-layout_mode = 2
-theme_override_constants/separation = 10
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer/ActiveSessions/MarginContainer/VBoxContainer" unique_id=66943091]
-layout_mode = 2
-text = "Active Sessions"
-horizontal_alignment = 1
-
-[node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer" unique_id=1873874176]
-custom_minimum_size = Vector2(1000, 0)
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="VBoxContainer3" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer" unique_id=1863434109]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="SessionDisplay" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer3" unique_id=368133605]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer3/SessionDisplay" unique_id=993828895]
-layout_mode = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer3/SessionDisplay/MarginContainer" unique_id=1881644944]
-layout_mode = 2
-theme_override_constants/separation = 20
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer3/SessionDisplay/MarginContainer/HBoxContainer" unique_id=2054814657]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="SessionName" type="Label" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer3/SessionDisplay/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1586628075]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Session Name"
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer3/SessionDisplay/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1575315261]
-layout_mode = 2
-theme_override_constants/separation = 25
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer3/SessionDisplay/MarginContainer/HBoxContainer/VBoxContainer/HBoxContainer" unique_id=408001748]
-layout_mode = 2
-
-[node name="Panel" type="Panel" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer3/SessionDisplay/MarginContainer/HBoxContainer/VBoxContainer/HBoxContainer/HBoxContainer" unique_id=770415475]
-custom_minimum_size = Vector2(20, 20)
-layout_mode = 2
-theme_override_styles/panel = SubResource("StyleBoxFlat_bucoy")
-
-[node name="AccountServer2" type="Label" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer3/SessionDisplay/MarginContainer/HBoxContainer/VBoxContainer/HBoxContainer/HBoxContainer" unique_id=415378036]
-layout_mode = 2
-theme_override_font_sizes/font_size = 12
-text = "Spectator"
-
-[node name="HBoxContainer2" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer3/SessionDisplay/MarginContainer/HBoxContainer/VBoxContainer/HBoxContainer" unique_id=1848382474]
-layout_mode = 2
-
-[node name="Panel" type="Panel" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer3/SessionDisplay/MarginContainer/HBoxContainer/VBoxContainer/HBoxContainer/HBoxContainer2" unique_id=1133926083]
-custom_minimum_size = Vector2(20, 20)
-layout_mode = 2
-theme_override_styles/panel = SubResource("StyleBoxFlat_dr1q3")
-
-[node name="AccountServer2" type="Label" parent="MarginContainer/VBoxContainer/Master/Home/HBoxContainer/VBoxContainer3/SessionDisplay/MarginContainer/HBoxContainer/VBoxContainer/HBoxContainer/HBoxContainer2" unique_id=36948057]
-layout_mode = 2
-theme_override_font_sizes/font_size = 12
-text = "157 ms"
-
-[node name="Templates" type="Control" parent="MarginContainer/VBoxContainer/Master/Home" unique_id=725523853]
-visible = false
-layout_mode = 2
-
-[node name="ActiveSessionButton" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Home/Templates" unique_id=1090596649]
-layout_mode = 0
-offset_left = 20.0
-offset_top = 274.0
-offset_right = 436.0
-offset_bottom = 297.0
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Home/Templates/ActiveSessionButton" unique_id=1736548450]
-layout_mode = 2
-
-[node name="Join" type="Button" parent="MarginContainer/VBoxContainer/Master/Home/Templates/ActiveSessionButton/HBoxContainer" unique_id=375184485]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="Close" type="Button" parent="MarginContainer/VBoxContainer/Master/Home/Templates/ActiveSessionButton/HBoxContainer" unique_id=797785460]
-custom_minimum_size = Vector2(50, 0)
-layout_mode = 2
-text = "X"
-
-[node name="AccountDisplay" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master" unique_id=1554068867]
-visible = false
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-script = ExtResource("5_upsw6")
-
-[node name="List" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountDisplay" unique_id=1462685937]
-custom_minimum_size = Vector2(500, 0)
-layout_mode = 2
-size_flags_horizontal = 4
-
-[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/List" unique_id=1122975855]
-layout_mode = 2
-size_flags_vertical = 3
-
-[node name="AccountList" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/List/ScrollContainer" unique_id=156940286]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/List" unique_id=1849303399]
-layout_mode = 2
-
-[node name="NewAccount" type="Button" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/List/HBoxContainer" unique_id=1573695902]
-custom_minimum_size = Vector2(0, 40)
-layout_mode = 2
-size_flags_horizontal = 3
-text = "New Account"
-
-[node name="Templates" type="Control" parent="MarginContainer/VBoxContainer/Master/AccountDisplay" unique_id=1889394597]
-visible = false
-layout_mode = 2
-
-[node name="Account" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/Templates" unique_id=1270586344]
-layout_mode = 0
-offset_left = 690.0
-offset_right = 1190.0
-offset_bottom = 106.0
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/Templates/Account" unique_id=1691936720]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/Templates/Account/MarginContainer" unique_id=877904178]
-layout_mode = 2
-theme_override_constants/separation = 10
-
-[node name="AspectRatioContainer2" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/Templates/Account/MarginContainer/HBoxContainer" unique_id=905758712]
-custom_minimum_size = Vector2(75, 50)
-layout_mode = 2
-
-[node name="ProfilePicture" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/Templates/Account/MarginContainer/HBoxContainer/AspectRatioContainer2" unique_id=1092421664]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/Templates/Account/MarginContainer/HBoxContainer" unique_id=1076341750]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="Username" type="Label" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/Templates/Account/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1381439920]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Account username"
-
-[node name="AccountServer" type="Label" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/Templates/Account/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1458428898]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.54, 0.54, 0.54, 1)
-theme_override_font_sizes/font_size = 14
-text = "https://accounts.openminerva.org"
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/Templates/Account/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1566413473]
-layout_mode = 2
-
-[node name="Login" type="Button" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/Templates/Account/MarginContainer/HBoxContainer/VBoxContainer/HBoxContainer" unique_id=249423624]
-custom_minimum_size = Vector2(0, 40)
-layout_mode = 2
-size_flags_horizontal = 3
-text = "Login"
-
-[node name="Configure" type="Button" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/Templates/Account/MarginContainer/HBoxContainer/VBoxContainer/HBoxContainer" unique_id=1395695382]
-layout_mode = 2
-size_flags_horizontal = 3
-text = "Configure"
-
-[node name="Remove" type="Button" parent="MarginContainer/VBoxContainer/Master/AccountDisplay/Templates/Account/MarginContainer/HBoxContainer/VBoxContainer/HBoxContainer" unique_id=1778567672]
-layout_mode = 2
-size_flags_horizontal = 3
-text = "Remove"
-
-[node name="AccountCreate" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master" unique_id=476222424]
-visible = false
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-script = ExtResource("6_3rk53")
-
-[node name="Create" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/AccountCreate" unique_id=1338768232]
-layout_mode = 2
-size_flags_horizontal = 4
-size_flags_vertical = 4
-theme_override_styles/panel = ExtResource("4_6rlgq")
-
-[node name="UsernamePassword" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create" unique_id=83231436]
-visible = false
-layout_mode = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="Create" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword" unique_id=1027080501]
-custom_minimum_size = Vector2(500, 0)
-layout_mode = 2
-size_flags_horizontal = 4
-size_flags_vertical = 4
-theme_override_constants/separation = 10
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword/Create" unique_id=44400410]
-layout_mode = 2
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword/Create/VBoxContainer" unique_id=1919638633]
-layout_mode = 2
-text = "Username"
-
-[node name="CAUsername" type="LineEdit" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword/Create/VBoxContainer" unique_id=925907901]
-layout_mode = 2
-text = "u"
-placeholder_text = "Username"
-
-[node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword/Create" unique_id=1696617473]
-layout_mode = 2
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword/Create/VBoxContainer2" unique_id=1480122353]
-layout_mode = 2
-text = "Password"
-
-[node name="CAPassword" type="LineEdit" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword/Create/VBoxContainer2" unique_id=8617011]
-layout_mode = 2
-text = "i"
-placeholder_text = "Password"
-secret = true
-
-[node name="VBoxContainer3" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword/Create" unique_id=2026306086]
-layout_mode = 2
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword/Create/VBoxContainer3" unique_id=252202476]
-layout_mode = 2
-text = "Account Server"
-
-[node name="CAAccountServer" type="LineEdit" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword/Create/VBoxContainer3" unique_id=783276815]
-layout_mode = 2
-text = "http://localhost"
-placeholder_text = "https://accounts.openminerva.org"
-
-[node name="CARememberMe" type="CheckButton" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword/Create" unique_id=1627203869]
-layout_mode = 2
-button_pressed = true
-text = "Remember Me"
-flat = true
-
-[node name="CALocalAccount" type="CheckButton" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword/Create" unique_id=869022482]
-layout_mode = 2
-text = "Local Account"
-flat = true
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword/Create" unique_id=700361537]
-layout_mode = 2
-
-[node name="CreateAccountBack" type="Button" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword/Create/HBoxContainer" unique_id=2040294501]
-layout_mode = 2
-size_flags_horizontal = 3
-text = "Back"
-
-[node name="ConfirmCreateAccount" type="Button" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/UsernamePassword/Create/HBoxContainer" unique_id=1706811869]
-layout_mode = 2
-size_flags_horizontal = 3
-text = "Create"
-
-[node name="OAuth" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create" unique_id=1033385490]
-visible = false
-layout_mode = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="Create" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/OAuth" unique_id=1431764238]
-custom_minimum_size = Vector2(500, 0)
-layout_mode = 2
-size_flags_horizontal = 4
-size_flags_vertical = 4
-theme_override_constants/separation = 10
-
-[node name="VBoxContainer3" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/OAuth/Create" unique_id=1971820391]
-layout_mode = 2
-
-[node name="DisplayName" type="Label" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/OAuth/Create/VBoxContainer3" unique_id=1545576882]
-layout_mode = 2
-text = "Display Name"
-
-[node name="CADisplayName" type="LineEdit" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/OAuth/Create/VBoxContainer3" unique_id=1868732970]
-layout_mode = 2
-text = "Anonymous"
-placeholder_text = "Display Name"
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/OAuth/Create/VBoxContainer3" unique_id=1010954308]
-layout_mode = 2
-text = "Account Server"
-
-[node name="CAAccountServer" type="LineEdit" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/OAuth/Create/VBoxContainer3" unique_id=404007920]
-layout_mode = 2
-text = "http://localhost:40400"
-placeholder_text = "https://accounts.openminerva.org"
-
-[node name="CARememberMe" type="CheckButton" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/OAuth/Create" unique_id=1759228467]
-layout_mode = 2
-button_pressed = true
-text = "Remember Me"
-flat = true
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/OAuth/Create" unique_id=162707587]
-layout_mode = 2
-
-[node name="CreateAccountBack" type="Button" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/OAuth/Create/HBoxContainer" unique_id=729130015]
-layout_mode = 2
-size_flags_horizontal = 3
-text = "Back"
-
-[node name="ConfirmCreateAccount" type="Button" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/OAuth/Create/HBoxContainer" unique_id=840318543]
-layout_mode = 2
-size_flags_horizontal = 3
-text = "Sign In"
-
-[node name="SelectMethod" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create" unique_id=1416964800]
-layout_mode = 2
-theme_override_constants/margin_left = 20
-theme_override_constants/margin_top = 20
-theme_override_constants/margin_right = 20
-theme_override_constants/margin_bottom = 20
-
-[node name="Container" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/SelectMethod" unique_id=1882060538]
-custom_minimum_size = Vector2(500, 0)
-layout_mode = 2
-size_flags_horizontal = 4
-size_flags_vertical = 4
-theme_override_constants/separation = 10
-
-[node name="OAuth" type="Button" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/SelectMethod/Container" unique_id=2044513720]
-custom_minimum_size = Vector2(0, 40)
-layout_mode = 2
-text = "OAuth2"
-
-[node name="UsernamePassword" type="Button" parent="MarginContainer/VBoxContainer/Master/AccountCreate/Create/SelectMethod/Container" unique_id=1669994196]
-custom_minimum_size = Vector2(0, 40)
-layout_mode = 2
-disabled = true
-text = "Username + Password"
-
-[node name="Sessions" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master" unique_id=2135749463]
-visible = false
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-script = ExtResource("8_4ahgm")
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Sessions" unique_id=1830116526]
-layout_mode = 2
-theme_override_constants/separation = 20
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer" unique_id=687228975]
-custom_minimum_size = Vector2(400, 0)
-layout_mode = 2
-theme_override_constants/separation = 5
-
-[node name="Art" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer" unique_id=8787651]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Art" unique_id=1704752065]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Art/MarginContainer" unique_id=723755098]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Art/MarginContainer/HBoxContainer" unique_id=1631358950]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Art/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=421186792]
-layout_mode = 2
-texture = ExtResource("3_6vaiq")
-expand_mode = 1
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Art/MarginContainer/HBoxContainer" unique_id=1515682350]
-layout_mode = 2
-text = "Art"
-
-[node name="Environment" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer" unique_id=1460467440]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Environment" unique_id=1960994802]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Environment/MarginContainer" unique_id=1078127539]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Environment/MarginContainer/HBoxContainer" unique_id=43665461]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Environment/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1826253390]
-layout_mode = 2
-texture = ExtResource("4_tkvwg")
-expand_mode = 1
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Environment/MarginContainer/HBoxContainer" unique_id=1155183315]
-layout_mode = 2
-text = "Environment"
-
-[node name="Science" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer" unique_id=508195085]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Science" unique_id=1375241018]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Science/MarginContainer" unique_id=1476810827]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Science/MarginContainer/HBoxContainer" unique_id=588549540]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Science/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1091425181]
-layout_mode = 2
-texture = ExtResource("5_hu6eh")
-expand_mode = 1
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Science/MarginContainer/HBoxContainer" unique_id=1662831340]
-layout_mode = 2
-text = "Science"
-
-[node name="Games" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer" unique_id=369382614]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Games" unique_id=1896102711]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Games/MarginContainer" unique_id=1907169258]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Games/MarginContainer/HBoxContainer" unique_id=2118476409]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Games/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1606136766]
-layout_mode = 2
-texture = ExtResource("6_hu6eh")
-expand_mode = 1
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer/Games/MarginContainer/HBoxContainer" unique_id=1728001482]
-layout_mode = 2
-text = "Games"
-
-[node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer" unique_id=275712777]
-custom_minimum_size = Vector2(1000, 0)
-layout_mode = 2
-size_flags_horizontal = 3
-theme_override_constants/separation = 15
-
-[node name="Search" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer2" unique_id=917704848]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer2/Search" unique_id=726470197]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer2/Search/MarginContainer" unique_id=65014822]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer2/Search/MarginContainer/HBoxContainer" unique_id=903609424]
-custom_minimum_size = Vector2(30, 0)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer2/Search/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1429839469]
-layout_mode = 2
-texture = ExtResource("4_wfski")
-expand_mode = 4
-
-[node name="LineEdit" type="LineEdit" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer2/Search/MarginContainer/HBoxContainer" unique_id=670617857]
-layout_mode = 2
-size_flags_horizontal = 3
-placeholder_text = "Search..."
-emoji_menu_enabled = false
-clear_button_enabled = true
-middle_mouse_paste_enabled = false
-flat = true
-caret_blink = true
-icon_expand_mode = 1
-
-[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer2" unique_id=242318771]
-layout_mode = 2
-size_flags_vertical = 3
-
-[node name="GridContainer" type="GridContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/HBoxContainer/VBoxContainer2/ScrollContainer" unique_id=164218999]
-layout_mode = 2
-size_flags_horizontal = 3
-theme_override_constants/h_separation = 15
-theme_override_constants/v_separation = 15
-columns = 4
-
-[node name="Templates" type="Control" parent="MarginContainer/VBoxContainer/Master/Sessions" unique_id=2135764135]
-visible = false
-layout_mode = 2
-
-[node name="WorldListing" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/Templates" unique_id=1301965468]
-custom_minimum_size = Vector2(350, 270)
-layout_mode = 0
-offset_left = 420.0
-offset_top = 56.0
-offset_right = 770.0
-offset_bottom = 326.0
-
-[node name="PanelContainer" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/Templates/WorldListing" unique_id=265222407]
-layout_mode = 2
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/Templates/WorldListing/PanelContainer" unique_id=2080859872]
-layout_mode = 2
-mouse_behavior_recursive = 2
-
-[node name="MarginContainer2" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/Templates/WorldListing/PanelContainer/VBoxContainer" unique_id=490931647]
-custom_minimum_size = Vector2(0, 200)
-layout_mode = 2
-size_flags_vertical = 3
-theme_override_constants/margin_left = 2
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 2
-theme_override_constants/margin_bottom = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/Templates/WorldListing/PanelContainer/VBoxContainer/MarginContainer2" unique_id=1546006054]
-layout_mode = 2
-size_flags_vertical = 3
-ratio = 1.7778
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Sessions/Templates/WorldListing/PanelContainer/VBoxContainer/MarginContainer2/AspectRatioContainer" unique_id=1678639094]
-layout_mode = 2
-expand_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Sessions/Templates/WorldListing/PanelContainer/VBoxContainer" unique_id=1720674229]
-layout_mode = 2
-size_flags_vertical = 3
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 15
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Sessions/Templates/WorldListing/PanelContainer/VBoxContainer/MarginContainer" unique_id=2066703758]
-custom_minimum_size = Vector2(200, 20)
-layout_mode = 2
-size_flags_vertical = 1
-mouse_filter = 1
-theme_override_font_sizes/font_size = 18
-autowrap_mode = 3
-text_overrun_behavior = 3
-max_lines_visible = 2
-
-[node name="Button" type="Button" parent="MarginContainer/VBoxContainer/Master/Sessions/Templates/WorldListing" unique_id=1779962200]
-layout_mode = 2
-mouse_default_cursor_shape = 2
-theme_override_styles/normal = SubResource("StyleBoxFlat_kgckq")
-
-[node name="Instance" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master" unique_id=919985343]
-visible = false
-layout_mode = 0
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-script = ExtResource("14_3ff87")
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Instance" unique_id=413032466]
-layout_mode = 2
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer" unique_id=1137764538]
-layout_mode = 2
-size_flags_vertical = 3
-
-[node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer" unique_id=90422462]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="PanelContainer" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer2" unique_id=1857065201]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer2/PanelContainer" unique_id=193436950]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="InstanceName" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer2/PanelContainer/MarginContainer" unique_id=1986372326]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer2/PanelContainer/MarginContainer/InstanceName" unique_id=1002302148]
-layout_mode = 2
-text = "Instance Name"
-
-[node name="InstanceNameField" type="LineEdit" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer2/PanelContainer/MarginContainer/InstanceName" unique_id=2029691082]
-layout_mode = 2
-text = "My Instance"
-placeholder_text = "Instance Name"
-
-[node name="PanelContainer2" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer2" unique_id=1338599011]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer2/PanelContainer2" unique_id=372944118]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="InstanceDescriptionContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer2/PanelContainer2/MarginContainer" unique_id=2036761912]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer2/PanelContainer2/MarginContainer/InstanceDescriptionContainer" unique_id=1778162350]
-layout_mode = 2
-text = "Instance Description"
-
-[node name="InstanceDescription" type="TextEdit" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer2/PanelContainer2/MarginContainer/InstanceDescriptionContainer" unique_id=1883764719]
-custom_minimum_size = Vector2(0, 100)
-layout_mode = 2
-text = "A basic instance description"
-placeholder_text = "Instance Description"
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer" unique_id=725794580]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="InstanceSettings" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer" unique_id=1058028038]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstanceSettings" unique_id=1068744384]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstanceSettings/MarginContainer" unique_id=91242726]
-layout_mode = 2
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstanceSettings/MarginContainer/HBoxContainer" unique_id=1980940677]
-layout_mode = 2
-size_flags_horizontal = 3
-text = "Max connected users"
-
-[node name="MaxConnectedUsers" type="SpinBox" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstanceSettings/MarginContainer/HBoxContainer" unique_id=218460777]
-layout_mode = 2
-min_value = 1.0
-max_value = 1000.0
-value = 1.0
-suffix = "Users"
-
-[node name="InstancePrivacy" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer" unique_id=418692061]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstancePrivacy" unique_id=520825558]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="InstancePrivacyContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstancePrivacy/MarginContainer" unique_id=44619055]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstancePrivacy/MarginContainer/InstancePrivacyContainer" unique_id=1242833055]
-layout_mode = 2
-text = "Instance Privacy"
-
-[node name="Public" type="Button" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstancePrivacy/MarginContainer/InstancePrivacyContainer" unique_id=700002280]
-custom_minimum_size = Vector2(0, 50)
-layout_mode = 2
-toggle_mode = true
-text = "Public"
-
-[node name="Contacts+" type="Button" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstancePrivacy/MarginContainer/InstancePrivacyContainer" unique_id=1719321337]
-visible = false
-custom_minimum_size = Vector2(0, 50)
-layout_mode = 2
-toggle_mode = true
-text = "Contacts+"
-
-[node name="Contacts" type="Button" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstancePrivacy/MarginContainer/InstancePrivacyContainer" unique_id=1878668850]
-custom_minimum_size = Vector2(0, 40)
-layout_mode = 2
-toggle_mode = true
-text = "Contacts"
-
-[node name="Friends+" type="Button" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstancePrivacy/MarginContainer/InstancePrivacyContainer" unique_id=1834008150]
-visible = false
-custom_minimum_size = Vector2(0, 50)
-layout_mode = 2
-toggle_mode = true
-text = "Friends+"
-
-[node name="Friends" type="Button" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstancePrivacy/MarginContainer/InstancePrivacyContainer" unique_id=4967885]
-custom_minimum_size = Vector2(0, 40)
-layout_mode = 2
-toggle_mode = true
-text = "Friends"
-
-[node name="InviteOnly" type="Button" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstancePrivacy/MarginContainer/InstancePrivacyContainer" unique_id=1625370876]
-custom_minimum_size = Vector2(0, 40)
-layout_mode = 2
-toggle_mode = true
-text = "Invite"
-
-[node name="InstanceAdvertisement" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer" unique_id=1453042159]
-visible = false
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstanceAdvertisement" unique_id=710014992]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="Instance Name" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstanceAdvertisement/MarginContainer" unique_id=339732048]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstanceAdvertisement/MarginContainer/Instance Name" unique_id=924196938]
-layout_mode = 2
-text = "Instance Advertisement"
-
-[node name="CheckButton" type="CheckButton" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstanceAdvertisement/MarginContainer/Instance Name" unique_id=476328324]
-layout_mode = 2
-theme = ExtResource("1_cx7w0")
-text = "Enable instance advertisement"
-
-[node name="ItemList" type="ItemList" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer/VBoxContainer/InstanceAdvertisement/MarginContainer/Instance Name" unique_id=645896803]
-custom_minimum_size = Vector2(0, 100)
-layout_mode = 2
-size_flags_vertical = 3
-theme_override_styles/cursor_unfocused = SubResource("StyleBoxEmpty_shwvw")
-theme_override_styles/cursor = SubResource("StyleBoxEmpty_3ff87")
-select_mode = 2
-item_count = 3
-item_0/text = "sessions.openminerva.org"
-item_1/text = "sessions.otherservice1.com"
-item_2/text = "sessions.otherservice2.com"
-
-[node name="HBoxContainer2" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer" unique_id=1107704271]
-custom_minimum_size = Vector2(0, 50)
-layout_mode = 2
-
-[node name="SaveChanges" type="Button" parent="MarginContainer/VBoxContainer/Master/Instance/VBoxContainer/HBoxContainer2" unique_id=175903443]
-layout_mode = 2
-size_flags_horizontal = 3
-text = "Save Changes"
-
-[node name="Contacts" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master" unique_id=1935681612]
-visible = false
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-script = ExtResource("15_gll50")
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts" unique_id=609852715]
-layout_mode = 2
-theme_override_constants/separation = 20
-
-[node name="PeopleList" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer" unique_id=495048038]
-custom_minimum_size = Vector2(400, 0)
-layout_mode = 2
-
-[node name="Search" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList" unique_id=1778670362]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/Search" unique_id=1330638996]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/Search/MarginContainer" unique_id=552152395]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/Search/MarginContainer/HBoxContainer" unique_id=1034644707]
-custom_minimum_size = Vector2(30, 0)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/Search/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1362549755]
-layout_mode = 2
-texture = ExtResource("4_wfski")
-expand_mode = 4
-
-[node name="LineEdit" type="LineEdit" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/Search/MarginContainer/HBoxContainer" unique_id=532774583]
-layout_mode = 2
-size_flags_horizontal = 3
-placeholder_text = "Search..."
-emoji_menu_enabled = false
-clear_button_enabled = true
-middle_mouse_paste_enabled = false
-flat = true
-caret_blink = true
-icon_expand_mode = 1
-
-[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList" unique_id=1230683167]
-layout_mode = 2
-size_flags_vertical = 3
-
-[node name="PeopleContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer" unique_id=1138665112]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="Contact" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=1376762730]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact" unique_id=1957164778]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact/MarginContainer" unique_id=530564555]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact/MarginContainer/HBoxContainer" unique_id=2037557771]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=213812101]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact/MarginContainer/HBoxContainer" unique_id=123418873]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1963379470]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1790589234]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact2" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=1917384234]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact2" unique_id=248931094]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact2/MarginContainer" unique_id=1105136801]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact2/MarginContainer/HBoxContainer" unique_id=1042937322]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact2/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=945263631]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact2/MarginContainer/HBoxContainer" unique_id=72060891]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact2/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1790458992]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact2/MarginContainer/HBoxContainer/VBoxContainer" unique_id=655308943]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact3" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=1002559792]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact3" unique_id=2110329168]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact3/MarginContainer" unique_id=587970321]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact3/MarginContainer/HBoxContainer" unique_id=1155569374]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact3/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=363334467]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact3/MarginContainer/HBoxContainer" unique_id=1291298320]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact3/MarginContainer/HBoxContainer/VBoxContainer" unique_id=58329549]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact3/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1652527413]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact4" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=1117539841]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact4" unique_id=882936545]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact4/MarginContainer" unique_id=1983831238]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact4/MarginContainer/HBoxContainer" unique_id=1797575450]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact4/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1904659656]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact4/MarginContainer/HBoxContainer" unique_id=1195268824]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact4/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1911785678]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact4/MarginContainer/HBoxContainer/VBoxContainer" unique_id=673745301]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact5" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=785320451]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact5" unique_id=488007093]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact5/MarginContainer" unique_id=1702189485]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact5/MarginContainer/HBoxContainer" unique_id=181066723]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact5/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=858326702]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact5/MarginContainer/HBoxContainer" unique_id=1622164735]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact5/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1525652223]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact5/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1764447998]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact6" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=1223741083]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact6" unique_id=1886365158]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact6/MarginContainer" unique_id=1000938433]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact6/MarginContainer/HBoxContainer" unique_id=1412410708]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact6/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1838408715]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact6/MarginContainer/HBoxContainer" unique_id=602696783]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact6/MarginContainer/HBoxContainer/VBoxContainer" unique_id=266752489]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact6/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1455339639]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact7" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=285355074]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact7" unique_id=496124961]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact7/MarginContainer" unique_id=2125957011]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact7/MarginContainer/HBoxContainer" unique_id=1679355086]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact7/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1263285591]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact7/MarginContainer/HBoxContainer" unique_id=1944026472]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact7/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1929228588]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact7/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1247873814]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact8" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=1645072851]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact8" unique_id=778625893]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact8/MarginContainer" unique_id=2038217778]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact8/MarginContainer/HBoxContainer" unique_id=1122556879]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact8/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1092189046]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact8/MarginContainer/HBoxContainer" unique_id=1922829072]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact8/MarginContainer/HBoxContainer/VBoxContainer" unique_id=584730902]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact8/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1752589710]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact9" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=2101167709]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact9" unique_id=618543179]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact9/MarginContainer" unique_id=1966106535]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact9/MarginContainer/HBoxContainer" unique_id=2145573781]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact9/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1400837203]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact9/MarginContainer/HBoxContainer" unique_id=300879442]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact9/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1887730979]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact9/MarginContainer/HBoxContainer/VBoxContainer" unique_id=591472536]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact10" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=1338233000]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact10" unique_id=1193164329]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact10/MarginContainer" unique_id=1302175277]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact10/MarginContainer/HBoxContainer" unique_id=547714522]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact10/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=207327638]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact10/MarginContainer/HBoxContainer" unique_id=292040170]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact10/MarginContainer/HBoxContainer/VBoxContainer" unique_id=800144392]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact10/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1643413008]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact11" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=1413470422]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact11" unique_id=2134138405]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact11/MarginContainer" unique_id=1392258180]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact11/MarginContainer/HBoxContainer" unique_id=643752280]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact11/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1015674972]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact11/MarginContainer/HBoxContainer" unique_id=157488074]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact11/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1826758548]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact11/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1006838147]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact12" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=758373763]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact12" unique_id=182319459]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact12/MarginContainer" unique_id=1225511965]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact12/MarginContainer/HBoxContainer" unique_id=833329707]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact12/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=288160845]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact12/MarginContainer/HBoxContainer" unique_id=956311638]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact12/MarginContainer/HBoxContainer/VBoxContainer" unique_id=291815739]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact12/MarginContainer/HBoxContainer/VBoxContainer" unique_id=142605013]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact13" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=110651033]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact13" unique_id=722964887]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact13/MarginContainer" unique_id=1681556310]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact13/MarginContainer/HBoxContainer" unique_id=1064996853]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact13/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=273745914]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact13/MarginContainer/HBoxContainer" unique_id=4372347]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact13/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1378094667]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact13/MarginContainer/HBoxContainer/VBoxContainer" unique_id=959498741]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact14" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=1765333158]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact14" unique_id=1834888416]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact14/MarginContainer" unique_id=1667692749]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact14/MarginContainer/HBoxContainer" unique_id=296732179]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact14/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=246164239]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact14/MarginContainer/HBoxContainer" unique_id=1729440618]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact14/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1697000745]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact14/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1424300167]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact15" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=608987246]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact15" unique_id=68254041]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact15/MarginContainer" unique_id=799897191]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact15/MarginContainer/HBoxContainer" unique_id=1562246438]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact15/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1995651580]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact15/MarginContainer/HBoxContainer" unique_id=1071607904]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact15/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1418212751]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact15/MarginContainer/HBoxContainer/VBoxContainer" unique_id=345858069]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Contact16" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer" unique_id=976707612]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact16" unique_id=1155713213]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact16/MarginContainer" unique_id=1444756375]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact16/MarginContainer/HBoxContainer" unique_id=1973316902]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact16/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=235764742]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact16/MarginContainer/HBoxContainer" unique_id=550050191]
-layout_mode = 2
-
-[node name="Name" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact16/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1145402858]
-layout_mode = 2
-theme_override_font_sizes/font_size = 20
-text = "Contact Username"
-
-[node name="OnlineStatus" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/PeopleList/ScrollContainer/PeopleContainer/Contact16/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1572016901]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.48570347, 0.48570353, 0.48570347, 1)
-theme_override_font_sizes/font_size = 14
-text = "Offline"
-
-[node name="Messages" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer" unique_id=847433634]
-layout_mode = 2
-size_flags_horizontal = 3
-theme_override_constants/separation = 10
-
-[node name="ColorRect" type="ColorRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages" unique_id=478337139]
-layout_mode = 2
-size_flags_vertical = 3
-color = Color(0, 0, 0, 0.1)
-
-[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect" unique_id=2057620318]
-process_mode = 3
-process_thread_group = 2
-process_thread_group_order = 0
-process_thread_messages = 0
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer" unique_id=385628332]
-layout_mode = 2
-size_flags_horizontal = 3
-size_flags_vertical = 3
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer" unique_id=87127683]
-layout_mode = 2
-size_flags_horizontal = 3
-size_flags_vertical = 3
-theme_override_constants/separation = 10
-
-[node name="OurMessage" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer" unique_id=2017134431]
-layout_mode = 2
-size_flags_horizontal = 8
-theme_override_styles/panel = SubResource("StyleBoxFlat_xdslj")
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/OurMessage" unique_id=227036190]
-layout_mode = 2
-size_flags_horizontal = 0
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/OurMessage/MarginContainer" unique_id=1039151222]
-custom_minimum_size = Vector2(800, 0)
-layout_mode = 2
-size_flags_horizontal = 0
-focus_mode = 2
-bbcode_enabled = true
-text = "This is a dummy text message made to simulate an actual message... Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vulputate enim at scelerisque accumsan. Ut aliquam sapien sem, venenatis ullamcorper felis pellentesque vitae. Nulla blandit dictum turpis, id viverra metus fermentum quis. Nulla dictum eros at lorem porta mattis. Nam rutrum et lacus vitae vehicula."
-fit_content = true
-scroll_active = false
-selection_enabled = true
-
-[node name="OurMessage2" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer" unique_id=890209952]
-layout_mode = 2
-size_flags_horizontal = 8
-theme_override_styles/panel = SubResource("StyleBoxFlat_xdslj")
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/OurMessage2" unique_id=1387435291]
-layout_mode = 2
-size_flags_horizontal = 0
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/OurMessage2/MarginContainer" unique_id=309283686]
-custom_minimum_size = Vector2(800, 0)
-layout_mode = 2
-size_flags_horizontal = 0
-focus_mode = 2
-bbcode_enabled = true
-text = "This is a dummy text message made to simulate an actual message... Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vulputate enim at scelerisque accumsan. Ut aliquam sapien sem, venenatis ullamcorper felis pellentesque vitae. Nulla blandit dictum turpis, id viverra metus fermentum quis. Nulla dictum eros at lorem porta mattis. Nam rutrum et lacus vitae vehicula."
-fit_content = true
-scroll_active = false
-selection_enabled = true
-
-[node name="ContactMessage3" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer" unique_id=1175570338]
-layout_mode = 2
-size_flags_horizontal = 0
-theme_override_styles/panel = SubResource("StyleBoxFlat_6rlgq")
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/ContactMessage3" unique_id=1197627479]
-layout_mode = 2
-size_flags_horizontal = 0
-theme = SubResource("Theme_q6jcb")
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/ContactMessage3/MarginContainer" unique_id=1326683365]
-custom_minimum_size = Vector2(800, 0)
-layout_mode = 2
-size_flags_horizontal = 0
-focus_mode = 2
-bbcode_enabled = true
-text = "This is a dummy text message made to simulate an actual message... Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vulputate enim at scelerisque accumsan. Ut aliquam sapien sem, venenatis ullamcorper felis pellentesque vitae. Nulla blandit dictum turpis, id viverra metus fermentum quis. Nulla dictum eros at lorem porta mattis. Nam rutrum et lacus vitae vehicula."
-fit_content = true
-scroll_active = false
-selection_enabled = true
-
-[node name="ContactMessage4" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer" unique_id=374331530]
-layout_mode = 2
-size_flags_horizontal = 0
-theme_override_styles/panel = SubResource("StyleBoxFlat_6rlgq")
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/ContactMessage4" unique_id=624597713]
-layout_mode = 2
-size_flags_horizontal = 0
-theme = SubResource("Theme_q6jcb")
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/ContactMessage4/MarginContainer" unique_id=1957773675]
-custom_minimum_size = Vector2(800, 0)
-layout_mode = 2
-size_flags_horizontal = 0
-focus_mode = 2
-bbcode_enabled = true
-text = "This is a dummy text message made to simulate an actual message... Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vulputate enim at scelerisque accumsan. Ut aliquam sapien sem, venenatis ullamcorper felis pellentesque vitae. Nulla blandit dictum turpis, id viverra metus fermentum quis. Nulla dictum eros at lorem porta mattis. Nam rutrum et lacus vitae vehicula."
-fit_content = true
-scroll_active = false
-selection_enabled = true
-
-[node name="OurMessage3" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer" unique_id=1739574120]
-layout_mode = 2
-size_flags_horizontal = 8
-theme_override_styles/panel = SubResource("StyleBoxFlat_xdslj")
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/OurMessage3" unique_id=1666305266]
-layout_mode = 2
-size_flags_horizontal = 0
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/OurMessage3/MarginContainer" unique_id=1972401865]
-custom_minimum_size = Vector2(800, 0)
-layout_mode = 2
-size_flags_horizontal = 0
-focus_mode = 2
-bbcode_enabled = true
-text = "This is a dummy text message made to simulate an actual message... Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vulputate enim at scelerisque accumsan. Ut aliquam sapien sem, venenatis ullamcorper felis pellentesque vitae. Nulla blandit dictum turpis, id viverra metus fermentum quis. Nulla dictum eros at lorem porta mattis. Nam rutrum et lacus vitae vehicula."
-fit_content = true
-scroll_active = false
-selection_enabled = true
-
-[node name="OurMessage4" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer" unique_id=851557100]
-layout_mode = 2
-size_flags_horizontal = 8
-theme_override_styles/panel = SubResource("StyleBoxFlat_xdslj")
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/OurMessage4" unique_id=16272845]
-layout_mode = 2
-size_flags_horizontal = 0
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/OurMessage4/MarginContainer" unique_id=1788643846]
-custom_minimum_size = Vector2(800, 0)
-layout_mode = 2
-size_flags_horizontal = 0
-focus_mode = 2
-bbcode_enabled = true
-text = "This is a dummy text message made to simulate an actual message... Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vulputate enim at scelerisque accumsan. Ut aliquam sapien sem, venenatis ullamcorper felis pellentesque vitae. Nulla blandit dictum turpis, id viverra metus fermentum quis. Nulla dictum eros at lorem porta mattis. Nam rutrum et lacus vitae vehicula."
-fit_content = true
-scroll_active = false
-selection_enabled = true
-
-[node name="ContactMessage5" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer" unique_id=1504758173]
-layout_mode = 2
-size_flags_horizontal = 0
-theme_override_styles/panel = SubResource("StyleBoxFlat_6rlgq")
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/ContactMessage5" unique_id=1387589042]
-layout_mode = 2
-size_flags_horizontal = 0
-theme = SubResource("Theme_q6jcb")
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/ContactMessage5/MarginContainer" unique_id=493655798]
-custom_minimum_size = Vector2(800, 0)
-layout_mode = 2
-size_flags_horizontal = 0
-focus_mode = 2
-bbcode_enabled = true
-text = "This is a dummy text message made to simulate an actual message... Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vulputate enim at scelerisque accumsan. Ut aliquam sapien sem, venenatis ullamcorper felis pellentesque vitae. Nulla blandit dictum turpis, id viverra metus fermentum quis. Nulla dictum eros at lorem porta mattis. Nam rutrum et lacus vitae vehicula."
-fit_content = true
-scroll_active = false
-selection_enabled = true
-
-[node name="OurMessage5" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer" unique_id=1120772320]
-layout_mode = 2
-size_flags_horizontal = 8
-theme_override_styles/panel = SubResource("StyleBoxFlat_xdslj")
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/OurMessage5" unique_id=1684659846]
-layout_mode = 2
-size_flags_horizontal = 0
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/OurMessage5/MarginContainer" unique_id=303214310]
-custom_minimum_size = Vector2(800, 0)
-layout_mode = 2
-size_flags_horizontal = 0
-focus_mode = 2
-bbcode_enabled = true
-text = "This is a dummy text message made to simulate an actual message... Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vulputate enim at scelerisque accumsan. Ut aliquam sapien sem, venenatis ullamcorper felis pellentesque vitae. Nulla blandit dictum turpis, id viverra metus fermentum quis. Nulla dictum eros at lorem porta mattis. Nam rutrum et lacus vitae vehicula."
-fit_content = true
-scroll_active = false
-selection_enabled = true
-
-[node name="OurMessage6" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer" unique_id=903773050]
-layout_mode = 2
-size_flags_horizontal = 8
-theme_override_styles/panel = SubResource("StyleBoxFlat_xdslj")
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/OurMessage6" unique_id=200480297]
-layout_mode = 2
-size_flags_horizontal = 0
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/ColorRect/ScrollContainer/MarginContainer/VBoxContainer/OurMessage6/MarginContainer" unique_id=1921158391]
-custom_minimum_size = Vector2(800, 0)
-layout_mode = 2
-size_flags_horizontal = 0
-focus_mode = 2
-bbcode_enabled = true
-text = "This is a dummy text message made to simulate an actual message... Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vulputate enim at scelerisque accumsan. Ut aliquam sapien sem, venenatis ullamcorper felis pellentesque vitae. Nulla blandit dictum turpis, id viverra metus fermentum quis. Nulla dictum eros at lorem porta mattis. Nam rutrum et lacus vitae vehicula."
-fit_content = true
-scroll_active = false
-selection_enabled = true
-
-[node name="Entry" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages" unique_id=657008232]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/Entry" unique_id=1730343636]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/Entry/MarginContainer" unique_id=2107826533]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/Entry/MarginContainer/HBoxContainer" unique_id=1490241753]
-custom_minimum_size = Vector2(30, 0)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/Entry/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1577549022]
-layout_mode = 2
-texture = ExtResource("9_xdslj")
-expand_mode = 4
-
-[node name="LineEdit" type="LineEdit" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Messages/Entry/MarginContainer/HBoxContainer" unique_id=1536400606]
-layout_mode = 2
-size_flags_horizontal = 3
-theme_override_styles/focus = SubResource("StyleBoxFlat_hq11n")
-placeholder_text = "Send a message..."
-emoji_menu_enabled = false
-clear_button_enabled = true
-middle_mouse_paste_enabled = false
-flat = true
-caret_blink = true
-icon_expand_mode = 1
-
-[node name="Bio" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer" unique_id=1343094501]
-custom_minimum_size = Vector2(400, 0)
-layout_mode = 2
-theme_override_constants/separation = 20
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio" unique_id=501129495]
-layout_mode = 2
-
-[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/HBoxContainer" unique_id=584912787]
-custom_minimum_size = Vector2(75, 75)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/HBoxContainer/AspectRatioContainer" unique_id=917984378]
-layout_mode = 2
-texture = ExtResource("2_bucoy")
-expand_mode = 1
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/HBoxContainer" unique_id=1940231142]
-layout_mode = 2
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/HBoxContainer/VBoxContainer" unique_id=1117926921]
-layout_mode = 2
-theme_override_font_sizes/font_size = 22
-text = "My contact"
-
-[node name="Label2" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/HBoxContainer/VBoxContainer" unique_id=1343091322]
-layout_mode = 2
-theme_override_colors/font_color = Color(0.6651851, 0.6651851, 0.6651851, 1)
-text = "https://accounts.openminerva.org"
-
-[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio" unique_id=526473658]
-layout_mode = 2
-size_flags_vertical = 3
-text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vulputate enim at scelerisque accumsan. Ut aliquam sapien sem, venenatis ullamcorper felis pellentesque vitae. Nulla blandit dictum turpis, id viverra metus fermentum quis. Nulla dictum eros at lorem porta mattis. Nam rutrum et lacus vitae vehicula. Quisque dictum diam nec felis aliquet auctor. Morbi placerat enim at finibus convallis. Curabitur non convallis mi, interdum ultricies augue.
-
-Ut eget varius libero, vitae porta ipsum. Integer sapien dui, ornare et semper et, sagittis sed libero. Nullam volutpat tempus nunc, id semper orci. Maecenas egestas tincidunt justo at ultricies. Vivamus ut nisi vestibulum, cursus dui non, ullamcorper sem. Cras sed ligula ante. Morbi eget pretium mi. Nullam iaculis sed ligula ut fermentum. Aenean cursus felis nibh, nec malesuada ante bibendum sed. Sed sed congue nunc. Duis purus odio, efficitur in eros sit amet, aliquam laoreet est. Interdum et malesuada fames ac ante ipsum primis in faucibus. Morbi fringilla mattis pharetra. Suspendisse ornare sagittis velit, sit amet rhoncus velit. "
-fit_content = true
-
-[node name="GridContainer" type="GridContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio" unique_id=485642944]
-layout_mode = 2
-theme_override_constants/h_separation = 10
-theme_override_constants/v_separation = 10
-columns = 2
-
-[node name="Button" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/GridContainer" unique_id=1404765838]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/GridContainer/Button" unique_id=1507499146]
-layout_mode = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/GridContainer/Button/MarginContainer" unique_id=89047822]
-layout_mode = 2
-text = "Add Contact"
-horizontal_alignment = 1
-
-[node name="Button2" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/GridContainer" unique_id=873002479]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/GridContainer/Button2" unique_id=1360585472]
-layout_mode = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/GridContainer/Button2/MarginContainer" unique_id=155640440]
-layout_mode = 2
-text = "Add Friend"
-horizontal_alignment = 1
-
-[node name="Button3" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/GridContainer" unique_id=343372836]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/GridContainer/Button3" unique_id=1968315918]
-layout_mode = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/GridContainer/Button3/MarginContainer" unique_id=1104766121]
-layout_mode = 2
-text = "Block User"
-horizontal_alignment = 1
-
-[node name="Button4" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/GridContainer" unique_id=2134122873]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/GridContainer/Button4" unique_id=193076607]
-layout_mode = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Contacts/HBoxContainer/Bio/GridContainer/Button4/MarginContainer" unique_id=1437723678]
-layout_mode = 2
-text = "Block Avatar"
-horizontal_alignment = 1
-
-[node name="Settings" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master" unique_id=362656680]
-visible = false
-layout_mode = 0
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-script = ExtResource("17_shwvw")
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Settings" unique_id=1829621060]
-layout_mode = 2
-
-[node name="Nav" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer" unique_id=954760906]
-custom_minimum_size = Vector2(300, 0)
-layout_mode = 2
-
-[node name="General" type="Button" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Nav" unique_id=985920354]
-custom_minimum_size = Vector2(0, 50)
-layout_mode = 2
-text = "General"
-
-[node name="Display" type="Button" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Nav" unique_id=1395666760]
-custom_minimum_size = Vector2(0, 50)
-layout_mode = 2
-text = "Display"
-
-[node name="Audio" type="Button" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Nav" unique_id=38839733]
-custom_minimum_size = Vector2(0, 50)
-layout_mode = 2
-text = "Audio"
-
-[node name="Controls" type="Button" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Nav" unique_id=875250441]
-custom_minimum_size = Vector2(0, 50)
-layout_mode = 2
-text = "Controls"
-
-[node name="Interface" type="Button" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Nav" unique_id=540067912]
-custom_minimum_size = Vector2(0, 50)
-layout_mode = 2
-text = "Interface"
-
-[node name="Network" type="Button" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Nav" unique_id=1675516200]
-custom_minimum_size = Vector2(0, 50)
-layout_mode = 2
-text = "Network"
-
-[node name="Config" type="Button" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Nav" unique_id=1660210073]
-custom_minimum_size = Vector2(0, 50)
-layout_mode = 2
-text = "Config"
-
-[node name="Security" type="Button" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Nav" unique_id=1489360741]
-custom_minimum_size = Vector2(0, 50)
-layout_mode = 2
-text = "Security"
-
-[node name="Misc" type="Button" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Nav" unique_id=1234025146]
-custom_minimum_size = Vector2(0, 50)
-layout_mode = 2
-text = "Misc"
-
-[node name="Advanced" type="Button" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Nav" unique_id=378374610]
-custom_minimum_size = Vector2(0, 50)
-layout_mode = 2
-text = "Advanced"
-
-[node name="Container" type="Control" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer" unique_id=444043284]
-layout_mode = 2
-size_flags_horizontal = 3
-
-[node name="General" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container" unique_id=351943332]
-visible = false
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-size_flags_horizontal = 3
-
-[node name="Config" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container" unique_id=661151710]
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-size_flags_horizontal = 3
-
-[node name="SessionServers" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config" unique_id=749605939]
-layout_mode = 2
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers" unique_id=1413203981]
-layout_mode = 2
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer" unique_id=1294718765]
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer/MarginContainer" unique_id=510822724]
-layout_mode = 2
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer/MarginContainer/HBoxContainer" unique_id=1248908459]
-layout_mode = 2
-size_flags_horizontal = 3
-theme_override_font_sizes/font_size = 20
-text = "Session Servers"
-
-[node name="Button" type="Button" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer/MarginContainer/HBoxContainer" unique_id=2141833094]
-custom_minimum_size = Vector2(200, 0)
-layout_mode = 2
-text = "Show List"
-
-[node name="PanelContainer" type="PanelContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer" unique_id=1524295507]
-visible = false
-layout_mode = 2
-
-[node name="MarginContainer2" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer" unique_id=1107486151]
-custom_minimum_size = Vector2(0, 200)
-layout_mode = 2
-theme_override_constants/margin_left = 5
-theme_override_constants/margin_top = 5
-theme_override_constants/margin_right = 5
-theme_override_constants/margin_bottom = 5
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer/MarginContainer2" unique_id=90574433]
-layout_mode = 2
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer/MarginContainer2/VBoxContainer" unique_id=1903245076]
-layout_mode = 2
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer/MarginContainer2/VBoxContainer/HBoxContainer" unique_id=1621920772]
-layout_mode = 2
-text = "Add Session Server"
-
-[node name="Name" type="LineEdit" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer/MarginContainer2/VBoxContainer/HBoxContainer" unique_id=351217801]
-layout_mode = 2
-size_flags_horizontal = 3
-placeholder_text = "Friendly Name"
-
-[node name="URL" type="LineEdit" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer/MarginContainer2/VBoxContainer/HBoxContainer" unique_id=512184669]
-layout_mode = 2
-size_flags_horizontal = 3
-placeholder_text = "URL"
-
-[node name="Button" type="Button" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer/MarginContainer2/VBoxContainer/HBoxContainer" unique_id=475127911]
-custom_minimum_size = Vector2(100, 0)
-layout_mode = 2
-text = "Add"
-
-[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer/MarginContainer2/VBoxContainer" unique_id=1281162897]
-layout_mode = 2
-size_flags_vertical = 3
-
-[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer/MarginContainer2/VBoxContainer/ScrollContainer" unique_id=1146094050]
-layout_mode = 2
-size_flags_horizontal = 3
-size_flags_vertical = 3
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer/MarginContainer2/VBoxContainer/ScrollContainer/MarginContainer" unique_id=1455078587]
-layout_mode = 2
-size_flags_horizontal = 3
-size_flags_vertical = 3
-
-[node name="Description" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer" unique_id=1192735413]
-custom_minimum_size = Vector2(300, 0)
-layout_mode = 2
-size_flags_horizontal = 4
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Settings/HBoxContainer/Description" unique_id=1672934352]
-layout_mode = 2
-size_flags_vertical = 1
-theme_override_font_sizes/font_size = 20
-text = "This is some top text, next we may be able to afford some bottom text. For now we will just be able to afford some medium text."
-autowrap_mode = 3
-
-[node name="Templates" type="Control" parent="MarginContainer/VBoxContainer/Master/Settings" unique_id=717770235]
-visible = false
-layout_mode = 2
-
-[node name="SessionServerListing" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Settings/Templates" unique_id=877735623]
-layout_mode = 0
-offset_left = 319.0
-offset_top = 57.0
-offset_right = 1553.0
-offset_bottom = 80.0
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Master/Settings/Templates/SessionServerListing" unique_id=22006714]
-layout_mode = 2
-size_flags_horizontal = 3
-theme_override_colors/font_color = Color(0.73333335, 0.73333335, 0.73333335, 1)
-text = "https://servers.openmierva.org"
-
-[node name="Remove" type="Button" parent="MarginContainer/VBoxContainer/Master/Settings/Templates/SessionServerListing" unique_id=725542881]
-custom_minimum_size = Vector2(100, 0)
-layout_mode = 2
-text = "X"
-
-[node name="Exit" type="MarginContainer" parent="MarginContainer/VBoxContainer/Master" unique_id=719734468]
-visible = false
-layout_mode = 0
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-theme_override_constants/margin_left = 10
-theme_override_constants/margin_top = 10
-theme_override_constants/margin_right = 10
-theme_override_constants/margin_bottom = 10
-script = ExtResource("17_3rk53")
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Master/Exit" unique_id=143476327]
-layout_mode = 2
-
-[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Master/Exit/VBoxContainer" unique_id=1484282659]
-layout_mode = 2
-size_flags_vertical = 3
-bbcode_enabled = true
-text = "[font_size=40]Thank you for using OpenMinerva![/font_size]
-
-[font_size=30]Come again soon![/font_size]"
-horizontal_alignment = 1
-vertical_alignment = 1
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Master/Exit/VBoxContainer" unique_id=611012192]
-custom_minimum_size = Vector2(0, 100)
-layout_mode = 2
-
-[node name="Cancel" type="Button" parent="MarginContainer/VBoxContainer/Master/Exit/VBoxContainer/HBoxContainer" unique_id=1332748794]
-layout_mode = 2
-size_flags_horizontal = 3
-theme_override_font_sizes/font_size = 26
-text = "Cancel"
-
-[node name="Exit" type="Button" parent="MarginContainer/VBoxContainer/Master/Exit/VBoxContainer/HBoxContainer" unique_id=1558278195]
-layout_mode = 2
-size_flags_horizontal = 3
-theme_override_font_sizes/font_size = 26
-text = "Exit"
-
-[node name="NavBar" type="Panel" parent="MarginContainer/VBoxContainer" unique_id=1428960291]
-custom_minimum_size = Vector2(0, 75)
-layout_mode = 2
-theme = ExtResource("1_cx7w0")
-
-[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/NavBar" unique_id=1728990786]
-layout_mode = 1
-anchors_preset = 8
-anchor_left = 0.5
-anchor_top = 0.5
-anchor_right = 0.5
-anchor_bottom = 0.5
-offset_left = -37.5
-offset_top = -37.5
-offset_right = 37.5
-offset_bottom = 37.5
-grow_horizontal = 2
-grow_vertical = 2
-theme_override_constants/separation = 10
-
-[node name="Home" type="Button" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer" unique_id=344464958]
-custom_minimum_size = Vector2(75, 75)
-layout_mode = 2
-theme = ExtResource("1_cx7w0")
-toggle_mode = true
-
-[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Home" unique_id=2077541755]
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Home/CenterContainer" unique_id=2146637607]
-layout_mode = 2
-theme_override_constants/separation = 2
-
-[node name="CenterContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Home/CenterContainer/VBoxContainer" unique_id=95810640]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Home/CenterContainer/VBoxContainer/CenterContainer" unique_id=1070773413]
-layout_mode = 2
-texture = ExtResource("1_3b2ci")
-expand_mode = 1
-
-[node name="CenterContainer2" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Home/CenterContainer/VBoxContainer" unique_id=1142003763]
-custom_minimum_size = Vector2(0, 15)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Home/CenterContainer/VBoxContainer/CenterContainer2" unique_id=862944763]
-layout_mode = 2
-texture = SubResource("CompressedTexture2D_hq11n")
-expand_mode = 5
-stretch_mode = 4
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Home/CenterContainer/VBoxContainer/CenterContainer2" unique_id=1897372055]
-layout_mode = 2
-theme_override_font_sizes/font_size = 12
-text = "Home"
-horizontal_alignment = 1
-vertical_alignment = 1
-
-[node name="Sessions" type="Button" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer" unique_id=1779312894]
-custom_minimum_size = Vector2(75, 75)
-layout_mode = 2
-theme = ExtResource("1_cx7w0")
-toggle_mode = true
-
-[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Sessions" unique_id=1414128034]
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Sessions/CenterContainer" unique_id=1222935685]
-layout_mode = 2
-theme_override_constants/separation = 2
-
-[node name="CenterContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Sessions/CenterContainer/VBoxContainer" unique_id=1794611439]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Sessions/CenterContainer/VBoxContainer/CenterContainer" unique_id=1479063914]
-layout_mode = 2
-texture = ExtResource("12_hq11n")
-expand_mode = 1
-
-[node name="CenterContainer2" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Sessions/CenterContainer/VBoxContainer" unique_id=739110456]
-custom_minimum_size = Vector2(0, 15)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Sessions/CenterContainer/VBoxContainer/CenterContainer2" unique_id=1283313696]
-layout_mode = 2
-texture = SubResource("CompressedTexture2D_hq11n")
-expand_mode = 5
-stretch_mode = 4
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Sessions/CenterContainer/VBoxContainer/CenterContainer2" unique_id=1726576248]
-layout_mode = 2
-theme_override_font_sizes/font_size = 12
-text = "Sessions"
-horizontal_alignment = 1
-vertical_alignment = 1
-
-[node name="Instance" type="Button" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer" unique_id=1199197758]
-custom_minimum_size = Vector2(75, 75)
-layout_mode = 2
-theme = ExtResource("1_cx7w0")
-toggle_mode = true
-
-[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Instance" unique_id=1968696261]
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Instance/CenterContainer" unique_id=524033554]
-layout_mode = 2
-theme_override_constants/separation = 2
-
-[node name="CenterContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Instance/CenterContainer/VBoxContainer" unique_id=1551725689]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Instance/CenterContainer/VBoxContainer/CenterContainer" unique_id=1325848905]
-layout_mode = 2
-texture = ExtResource("3_v4ccx")
-expand_mode = 1
-
-[node name="CenterContainer2" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Instance/CenterContainer/VBoxContainer" unique_id=1007113927]
-custom_minimum_size = Vector2(0, 15)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Instance/CenterContainer/VBoxContainer/CenterContainer2" unique_id=1992088652]
-layout_mode = 2
-texture = SubResource("CompressedTexture2D_hq11n")
-expand_mode = 5
-stretch_mode = 4
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Instance/CenterContainer/VBoxContainer/CenterContainer2" unique_id=1993490483]
-layout_mode = 2
-theme_override_font_sizes/font_size = 12
-text = "Instance"
-horizontal_alignment = 1
-vertical_alignment = 1
-
-[node name="Contacts" type="Button" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer" unique_id=2052926333]
-custom_minimum_size = Vector2(75, 75)
-layout_mode = 2
-theme = ExtResource("1_cx7w0")
-toggle_mode = true
-
-[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Contacts" unique_id=247880075]
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Contacts/CenterContainer" unique_id=1493676986]
-layout_mode = 2
-theme_override_constants/separation = 2
-
-[node name="CenterContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Contacts/CenterContainer/VBoxContainer" unique_id=993865409]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Contacts/CenterContainer/VBoxContainer/CenterContainer" unique_id=939575854]
-layout_mode = 2
-texture = ExtResource("4_cyduv")
-expand_mode = 1
-
-[node name="CenterContainer2" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Contacts/CenterContainer/VBoxContainer" unique_id=327218435]
-custom_minimum_size = Vector2(0, 15)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Contacts/CenterContainer/VBoxContainer/CenterContainer2" unique_id=1753921793]
-layout_mode = 2
-texture = SubResource("CompressedTexture2D_hq11n")
-expand_mode = 5
-stretch_mode = 4
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Contacts/CenterContainer/VBoxContainer/CenterContainer2" unique_id=1239993332]
-layout_mode = 2
-theme_override_font_sizes/font_size = 12
-text = "Contacts"
-horizontal_alignment = 1
-vertical_alignment = 1
-
-[node name="Inventory" type="Button" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer" unique_id=1154242515]
-custom_minimum_size = Vector2(75, 75)
-layout_mode = 2
-theme = ExtResource("1_cx7w0")
-toggle_mode = true
-
-[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Inventory" unique_id=477611878]
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Inventory/CenterContainer" unique_id=1029784273]
-layout_mode = 2
-theme_override_constants/separation = 2
-
-[node name="CenterContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Inventory/CenterContainer/VBoxContainer" unique_id=1434684623]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Inventory/CenterContainer/VBoxContainer/CenterContainer" unique_id=355063981]
-layout_mode = 2
-texture = ExtResource("5_r82dk")
-expand_mode = 1
-
-[node name="CenterContainer2" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Inventory/CenterContainer/VBoxContainer" unique_id=150216954]
-custom_minimum_size = Vector2(0, 15)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Inventory/CenterContainer/VBoxContainer/CenterContainer2" unique_id=2129474918]
-layout_mode = 2
-texture = SubResource("CompressedTexture2D_hq11n")
-expand_mode = 5
-stretch_mode = 4
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Inventory/CenterContainer/VBoxContainer/CenterContainer2" unique_id=436784442]
-layout_mode = 2
-theme_override_font_sizes/font_size = 12
-text = "Inventory"
-horizontal_alignment = 1
-vertical_alignment = 1
-
-[node name="Apps" type="Button" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer" unique_id=2035455386]
-custom_minimum_size = Vector2(75, 75)
-layout_mode = 2
-theme = ExtResource("1_cx7w0")
-toggle_mode = true
-
-[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Apps" unique_id=1234174942]
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Apps/CenterContainer" unique_id=2137480982]
-layout_mode = 2
-theme_override_constants/separation = 2
-
-[node name="CenterContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Apps/CenterContainer/VBoxContainer" unique_id=1172100987]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Apps/CenterContainer/VBoxContainer/CenterContainer" unique_id=1104376878]
-layout_mode = 2
-texture = ExtResource("6_6ybpt")
-expand_mode = 1
-
-[node name="CenterContainer2" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Apps/CenterContainer/VBoxContainer" unique_id=1849886021]
-custom_minimum_size = Vector2(0, 15)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Apps/CenterContainer/VBoxContainer/CenterContainer2" unique_id=573515185]
-layout_mode = 2
-texture = SubResource("CompressedTexture2D_hq11n")
-expand_mode = 5
-stretch_mode = 4
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Apps/CenterContainer/VBoxContainer/CenterContainer2" unique_id=1090534310]
-layout_mode = 2
-theme_override_font_sizes/font_size = 12
-text = "Apps"
-horizontal_alignment = 1
-vertical_alignment = 1
-
-[node name="Settings" type="Button" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer" unique_id=326520049]
-custom_minimum_size = Vector2(75, 75)
-layout_mode = 2
-theme = ExtResource("1_cx7w0")
-toggle_mode = true
-
-[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Settings" unique_id=803794329]
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Settings/CenterContainer" unique_id=639771866]
-layout_mode = 2
-theme_override_constants/separation = 2
-
-[node name="CenterContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Settings/CenterContainer/VBoxContainer" unique_id=42256113]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Settings/CenterContainer/VBoxContainer/CenterContainer" unique_id=121107602]
-layout_mode = 2
-texture = ExtResource("7_tixj4")
-expand_mode = 1
-
-[node name="CenterContainer2" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Settings/CenterContainer/VBoxContainer" unique_id=301796775]
-custom_minimum_size = Vector2(0, 15)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Settings/CenterContainer/VBoxContainer/CenterContainer2" unique_id=1389137151]
-layout_mode = 2
-texture = SubResource("CompressedTexture2D_hq11n")
-expand_mode = 5
-stretch_mode = 4
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Settings/CenterContainer/VBoxContainer/CenterContainer2" unique_id=463454723]
-layout_mode = 2
-theme_override_font_sizes/font_size = 12
-text = "Settings"
-horizontal_alignment = 1
-vertical_alignment = 1
-
-[node name="Debug" type="Button" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer" unique_id=239205402]
-custom_minimum_size = Vector2(75, 75)
-layout_mode = 2
-theme = ExtResource("1_cx7w0")
-toggle_mode = true
-
-[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Debug" unique_id=2128143430]
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Debug/CenterContainer" unique_id=189425462]
-layout_mode = 2
-theme_override_constants/separation = 2
-
-[node name="CenterContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Debug/CenterContainer/VBoxContainer" unique_id=1205603038]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Debug/CenterContainer/VBoxContainer/CenterContainer" unique_id=1576187531]
-layout_mode = 2
-texture = ExtResource("8_fgqsp")
-expand_mode = 1
-
-[node name="CenterContainer2" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Debug/CenterContainer/VBoxContainer" unique_id=1369920063]
-custom_minimum_size = Vector2(0, 15)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Debug/CenterContainer/VBoxContainer/CenterContainer2" unique_id=229165988]
-layout_mode = 2
-texture = SubResource("CompressedTexture2D_hq11n")
-expand_mode = 5
-stretch_mode = 4
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Debug/CenterContainer/VBoxContainer/CenterContainer2" unique_id=305966204]
-layout_mode = 2
-theme_override_font_sizes/font_size = 12
-text = "Debug"
-horizontal_alignment = 1
-vertical_alignment = 1
-
-[node name="Exit" type="Button" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer" unique_id=1604895221]
-custom_minimum_size = Vector2(75, 75)
-layout_mode = 2
-theme = ExtResource("1_cx7w0")
-toggle_mode = true
-
-[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Exit" unique_id=1519067308]
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-
-[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Exit/CenterContainer" unique_id=36849769]
-layout_mode = 2
-theme_override_constants/separation = 2
-
-[node name="CenterContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Exit/CenterContainer/VBoxContainer" unique_id=1840012224]
-custom_minimum_size = Vector2(50, 50)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Exit/CenterContainer/VBoxContainer/CenterContainer" unique_id=806908628]
-layout_mode = 2
-texture = ExtResource("9_amc1p")
-expand_mode = 1
-
-[node name="CenterContainer2" type="CenterContainer" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Exit/CenterContainer/VBoxContainer" unique_id=817841049]
-custom_minimum_size = Vector2(0, 15)
-layout_mode = 2
-
-[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Exit/CenterContainer/VBoxContainer/CenterContainer2" unique_id=71500259]
-layout_mode = 2
-texture = SubResource("CompressedTexture2D_hq11n")
-expand_mode = 5
-stretch_mode = 4
-
-[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/NavBar/HBoxContainer/Exit/CenterContainer/VBoxContainer/CenterContainer2" unique_id=1611628376]
-layout_mode = 2
-theme_override_font_sizes/font_size = 12
-text = "Exit"
-horizontal_alignment = 1
-vertical_alignment = 1
diff --git a/src/userinterface/dash/instance.gd b/src/userinterface/dash/instance.gd
deleted file mode 100644
index 8b593dc..0000000
--- a/src/userinterface/dash/instance.gd
+++ /dev/null
@@ -1,106 +0,0 @@
-# --- License
-# File: /client/src/userinterface/dash/instance.gd
-# Project: OpenMinerva
-# Created Date: 27 March 2026
-# Copyright (c) 2026 OpenMinerva
-# License: MIT License
-# Authors: Armored Dragon
-# --- License
-
-extends Control
-
-@onready var network_m = get_tree().current_scene.get_node("NetworkManager")
-
-@onready var instance_settings_root = get_node("VBoxContainer/HBoxContainer")
-@onready var instance_name = instance_settings_root.get_node("VBoxContainer2/PanelContainer/MarginContainer/InstanceName/InstanceNameField")
-@onready var instance_description = instance_settings_root.get_node("VBoxContainer2/PanelContainer2/MarginContainer/InstanceDescriptionContainer/InstanceDescription")
-@onready var instance_max_users = instance_settings_root.get_node("VBoxContainer/InstanceSettings/MarginContainer/HBoxContainer/MaxConnectedUsers")
-
-@onready var instance_privacy_container = instance_settings_root.get_node("VBoxContainer/InstancePrivacy/MarginContainer/InstancePrivacyContainer")
-@onready var instance_privacy_public_btn = instance_privacy_container.get_node("Public")
-@onready var instance_privacy_contacts_btn = instance_privacy_container.get_node("Contacts")
-@onready var instance_privacy_friends_btn = instance_privacy_container.get_node("Friends")
-@onready var instance_privacy_invite_btn = instance_privacy_container.get_node("InviteOnly")
-
-@onready var save_changes_btn = get_node("VBoxContainer/HBoxContainer2/SaveChanges")
-
-var session_privacy: Enum.PrivacyLevel
-
-func _ready():
- instance_privacy_public_btn.pressed.connect(_update_instance_privacy_visual.bind(Enum.PrivacyLevel.PUBLIC))
- instance_privacy_contacts_btn.pressed.connect(_update_instance_privacy_visual.bind(Enum.PrivacyLevel.CONTACTS))
- instance_privacy_friends_btn.pressed.connect(_update_instance_privacy_visual.bind(Enum.PrivacyLevel.FRIENDS))
- instance_privacy_invite_btn.pressed.connect(_update_instance_privacy_visual.bind(Enum.PrivacyLevel.INVITE))
-
- save_changes_btn.pressed.connect(_handle_save_session_info)
-
- Events.connect("instance_updated", update_instance)
-
- _update_instance_privacy_visual(Enum.PrivacyLevel.INVITE)
- return
-
-
-func _update_instance_privacy_visual(level):
- if !is_multiplayer_authority():
- return
-
- GlobalLogger.logs("Updating instance privacy.")
-
- session_privacy = level
-
- for node in instance_privacy_container.get_children():
- if node is Button:
- _privacy_button_disable(node)
- match level:
- Enum.PrivacyLevel.INVITE:
- _privacy_button_enable(instance_privacy_invite_btn)
- Enum.PrivacyLevel.PUBLIC:
- _privacy_button_enable(instance_privacy_public_btn)
- Enum.PrivacyLevel.CONTACTS:
- _privacy_button_enable(instance_privacy_contacts_btn)
- Enum.PrivacyLevel.FRIENDS:
- _privacy_button_enable(instance_privacy_friends_btn)
-
- return
-
-func _privacy_button_disable(node) -> void:
- node.button_pressed = false
- node.custom_minimum_size = Vector2(0, 40)
- return
-
-func _privacy_button_enable(node) -> void:
- node.button_pressed = true
- node.custom_minimum_size = Vector2(0, 50)
- return
-
-func update_instance(_instance: Dictionary) -> void:
- GlobalLogger.logs("'%s' is not implemented." % get_stack()[0]["function"], Enum.LogLevel.WARNING)
- # TODO Session Permissions: Admins can change instance settings.
- # Publish changes to the session server.
- # Update running server
- return
-
-func _handle_save_session_info() -> void:
- # TODO: Have this page know what instance it currently occupies.
- var _sessions = network_m.get_connected_sessions()
-
- # Get current session info settings from the dashboard.
- # TODO: Get the current session we are connected to.
- # Update the database to the new settings.
- var _current_session_settings = _get_server_settings()
-
- _sessions[0].set("name", _current_session_settings.name)
- _sessions[0].set("description", _current_session_settings.description)
- _sessions[0].set("max_connected_users", _current_session_settings.max_connected_users)
- _sessions[0].set("privacy", _current_session_settings.privacy)
-
- network_m.update_server(_sessions[0].id, _sessions[0])
- return
-
-func _get_server_settings() -> Dictionary:
- return {
- "name": instance_name.text,
- "description": instance_description.text,
- "max_connected_users": int(instance_max_users.value),
- "privacy": session_privacy,
- }
diff --git a/src/userinterface/dash/instance.gd.uid b/src/userinterface/dash/instance.gd.uid
deleted file mode 100644
index 1f83515..0000000
--- a/src/userinterface/dash/instance.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://dpo2x4ddv3ftt
diff --git a/src/userinterface/dash/inventory.gd b/src/userinterface/dash/inventory.gd
deleted file mode 100644
index 25fef36..0000000
--- a/src/userinterface/dash/inventory.gd
+++ /dev/null
@@ -1,10 +0,0 @@
-# --- License
-# File: /client/src/userinterface/dash/inventory.gd
-# Project: OpenMinerva
-# Created Date: 27 March 2026
-# Copyright (c) 2026 OpenMinerva
-# License: MIT License
-# Authors: Armored Dragon
-# --- License
-
-extends Control
\ No newline at end of file
diff --git a/src/userinterface/dash/inventory.gd.uid b/src/userinterface/dash/inventory.gd.uid
deleted file mode 100644
index 68f6055..0000000
--- a/src/userinterface/dash/inventory.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://c25o2e0f3y6yx
diff --git a/src/userinterface/dash/master.gd b/src/userinterface/dash/master.gd
deleted file mode 100644
index c904a18..0000000
--- a/src/userinterface/dash/master.gd
+++ /dev/null
@@ -1,59 +0,0 @@
-# --- License
-# File: /client/src/userinterface/dash/master.gd
-# Project: OpenMinerva
-# Created Date: 27 March 2026
-# Copyright (c) 2026 OpenMinerva
-# License: MIT License
-# Authors: Armored Dragon
-# --- License
-
-extends Control
-
-var dashboard_tabs = []
-var dashboard_tab_names = []
-
-@onready var dash_tab_master_container = get_node("MarginContainer/VBoxContainer/Master")
-@onready var dash_nav_master_container = get_node("MarginContainer/VBoxContainer/NavBar/HBoxContainer")
-
-func _ready():
- _build_page_list()
-
- Events.connect("dash_set_state", _handle_set_dash_state)
- Events.connect("dash_switch_tab", _handle_switch_tab)
-
- Events.emit_signal("dash_switch_tab", "Home")
-
-func _build_page_list():
- for child in get_node("MarginContainer/VBoxContainer/Master").get_children():
- child.add_to_group("_dashboard_pages")
- dashboard_tab_names.append(child.name)
-
- for button in get_node("MarginContainer/VBoxContainer/NavBar/HBoxContainer").get_children():
- if button.name not in dashboard_tab_names:
- button.disabled = true
- continue
- button.pressed.connect(Events.emit_signal.bind("dash_switch_tab", button.name))
-
-func _handle_set_dash_state(is_open: bool) -> void:
- GlobalLogger.logs("Changing dashboard state: '%s'" % is_open)
- visible = is_open
-
-func _handle_switch_tab(target_name: String) -> void:
- GlobalLogger.logs("Switching dashboard to page '%s'" % target_name)
-
- for dash_tab in dash_tab_master_container.get_children():
- dash_tab.visible = false
-
- for dash_nav_button in dash_nav_master_container.get_children():
- dash_nav_button.button_pressed = false
-
- if target_name not in dashboard_tab_names:
- GlobalLogger.logs("Tried to switch to an invalid dashboard page: '%s'" % target_name, Enum.LogLevel.WARNING)
- return
-
- dash_tab_master_container.get_node(target_name).visible = true
-
- if dash_nav_master_container.get_node(target_name):
- dash_nav_master_container.get_node(target_name).button_pressed = true
-
- return
diff --git a/src/userinterface/dash/master.gd.uid b/src/userinterface/dash/master.gd.uid
deleted file mode 100644
index 73601b6..0000000
--- a/src/userinterface/dash/master.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://cbl7rmnjxarba
diff --git a/src/userinterface/dash/sessions.gd b/src/userinterface/dash/sessions.gd
deleted file mode 100644
index d2dca93..0000000
--- a/src/userinterface/dash/sessions.gd
+++ /dev/null
@@ -1,70 +0,0 @@
-# --- License
-# File: /client/src/userinterface/dash/sessions.gd
-# Project: OpenMinerva
-# Created Date: 27 March 2026
-# Copyright (c) 2026 OpenMinerva
-# License: MIT License
-# Authors: Armored Dragon
-# --- License
-
-extends Control
-
-@onready var _template_world_listing = get_node("Templates/WorldListing")
-@onready var _world_listing_grid = get_node("HBoxContainer/VBoxContainer2/ScrollContainer/GridContainer")
-@onready var network_m = get_tree().current_scene.get_node("NetworkManager")
-
-# TODO: Keep track of what is different from the current live settings
-# When something changes, show icon or indicator of a change.
-
-func _ready():
- Events.dash_switch_tab.connect(_handle_page_opened)
- return
-
-func _handle_page_opened(page_name: String) -> void:
- if page_name != "Sessions":
- return
-
- # TODO: Make a more robust active_account detection mechanism.
- if GlobalAccount.active_account == {}:
- return
-
- # TODO: Check if we need to authenticate, if so
- for _session_server in SettingsManager.get_session_servers():
- await SessionQuery.authenticate(_session_server.url)
-
- # Get a list of all sessions from our saved sessions_list
- var session_list = await SessionQuery.get_sessions()
-
- # Remove all entries in the list
- _remove_all_listings()
-
- # In our flat array, add all sessions to the view
- for session in session_list:
- insert_world_into_session_listing(session)
- return
-
-func insert_world_into_session_listing(world_data: Dictionary) -> void:
- var _world = _template_world_listing.duplicate()
-
- var world_title = _world.get_node("PanelContainer/VBoxContainer/MarginContainer/Label")
- var world_thumbnail = _world.get_node("PanelContainer/VBoxContainer/MarginContainer2/AspectRatioContainer/TextureRect")
-
- world_title.text = world_data.get("sessionName", "Unknown session name.")
- world_thumbnail.set_texture(load(world_data.get("sessionThumbnail", "res://resources/icons/dummy16-9.webp")))
-
- _world_listing_grid.add_child(_world)
-
- # Buttons
- var _button = _world.get_node("Button")
-
- _button.pressed.connect(network_m.join_server.bind(world_data.url, world_data.port))
-
- GlobalLogger.logs("Added a session to the session list.")
- return
-
-func _remove_all_listings() -> void:
- GlobalLogger.logs("Removed all listings from the session list.", Enum.LogLevel.INFO)
-
- for session_listing in _world_listing_grid.get_children():
- session_listing.queue_free()
- return
diff --git a/src/userinterface/dash/sessions.gd.uid b/src/userinterface/dash/sessions.gd.uid
deleted file mode 100644
index 5cf606c..0000000
--- a/src/userinterface/dash/sessions.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://ccd2fw88a52mp
diff --git a/src/userinterface/dash/settings.gd b/src/userinterface/dash/settings.gd
deleted file mode 100644
index 79d6583..0000000
--- a/src/userinterface/dash/settings.gd
+++ /dev/null
@@ -1,74 +0,0 @@
-# --- License
-# File: /client/src/userinterface/dash/settings.gd
-# Project: OpenMinerva
-# Created Date: 27 March 2026
-# Copyright (c) 2026 OpenMinerva
-# License: MIT License
-# Authors: Armored Dragon
-# --- License
-
-extends Control
-
-@onready var _templates_session_server_listing = get_node("Templates/SessionServerListing")
-@onready var _session_server_container = get_node("HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer/MarginContainer2/VBoxContainer/ScrollContainer/MarginContainer/VBoxContainer")
-
-@onready var _show_session_server_info_btn = get_node("HBoxContainer/Container/Config/SessionServers/VBoxContainer/MarginContainer/HBoxContainer/Button")
-@onready var _session_server_info = get_node("HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer")
-@onready var _add_session_server_btn = get_node("HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer/MarginContainer2/VBoxContainer/HBoxContainer/Button")
-@onready var _add_session_server_name = get_node("HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer/MarginContainer2/VBoxContainer/HBoxContainer/Name")
-@onready var _add_session_server_url = get_node("HBoxContainer/Container/Config/SessionServers/VBoxContainer/PanelContainer/MarginContainer2/VBoxContainer/HBoxContainer/URL")
-
-func _ready():
- _load_session_servers()
-
- _show_session_server_info_btn.pressed.connect(_show_session_server_info_dialog)
- _add_session_server_btn.pressed.connect(_add_session_server)
-
- Events.dash_switch_tab.connect(_handle_page_opened)
- return
-
-func _handle_page_opened(page_name) -> void:
- if page_name != "Settings":
- return
-
- _load_session_servers()
- return
-
-func _load_session_servers() -> void:
- GlobalLogger.logs("Loading session servers.")
- var _servers = SettingsManager.get_session_servers()
-
- for _existing_listing in _session_server_container.get_children():
- _existing_listing.queue_free()
-
- for server in _servers:
- var _template = _templates_session_server_listing.duplicate()
- _template.get_node("Label").text = server.url
- _template.get_node("Remove").pressed.connect(_remove_session_server.bind(server.url))
- _session_server_container.add_child(_template)
- return
-
-func _remove_session_server(url: String) -> void:
- SettingsManager.remove_session_server(url)
- _load_session_servers()
-
-func _add_session_server() -> void:
- var _name = _add_session_server_name.text
- var _url = _add_session_server_url.text
-
- if _name == "":
- return
-
- if _url == "":
- return
-
- SettingsManager.add_session_server({"name": _name, "url": _url})
-
- _add_session_server_name.text = ""
- _add_session_server_url.text = ""
- _load_session_servers()
- return
-
-func _show_session_server_info_dialog() -> void:
- _session_server_info.visible = !_session_server_info.visible
- return
diff --git a/src/userinterface/dash/settings.gd.uid b/src/userinterface/dash/settings.gd.uid
deleted file mode 100644
index 238acd9..0000000
--- a/src/userinterface/dash/settings.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://cq26hbvdqb4sf
diff --git a/src/userinterface/dashv2/dashboard.tscn b/src/userinterface/dashv2/dashboard.tscn
new file mode 100644
index 0000000..99c805f
--- /dev/null
+++ b/src/userinterface/dashv2/dashboard.tscn
@@ -0,0 +1,774 @@
+[gd_scene format=3 uid="uid://c4y1sb6lmdr0q"]
+
+[ext_resource type="Script" uid="uid://ci5jkh01ixats" path="res://userinterface/dashv2/scripts/master.gd" id="1_7d87s"]
+[ext_resource type="Shader" uid="uid://bwr4b0mhgi4w6" path="res://userinterface/dashv2/shaders/blur.gdshader" id="1_co0dt"]
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="2_0nfpo"]
+[ext_resource type="Script" uid="uid://bd7a7r2u4cbtf" path="res://userinterface/dashv2/scripts/header.gd" id="2_7obga"]
+[ext_resource type="Script" uid="uid://bkqsi1aebefhj" path="res://userinterface/dashv2/scripts/navigation.gd" id="3_8u0v7"]
+[ext_resource type="PackedScene" uid="uid://dog17wkc4h48c" path="res://userinterface/dashv2/partials/left_nav_container.tscn" id="3_av8ee"]
+[ext_resource type="PackedScene" uid="uid://ccoyv1v4otf1b" path="res://userinterface/dashv2/partials/nav_button.tscn" id="3_ocjmf"]
+[ext_resource type="Script" uid="uid://ba1v2y41s8drb" path="res://userinterface/dashv2/scripts/pages/settings.gd" id="4_ap0b5"]
+[ext_resource type="PackedScene" uid="uid://clvk6h18vwcd3" path="res://userinterface/dashv2/partials/account_button.tscn" id="4_aw6p6"]
+[ext_resource type="PackedScene" uid="uid://71vuc3qrtgi7" path="res://userinterface/dashv2/partials/category_button.tscn" id="4_ql400"]
+[ext_resource type="Script" uid="uid://behsvrk7cf3e3" path="res://userinterface/dashv2/scripts/pages/home.gd" id="6_bh4hj"]
+[ext_resource type="PackedScene" uid="uid://dh0u5xtwooa0v" path="res://userinterface/dashv2/partials/home_server_listing.tscn" id="7_kk1ia"]
+[ext_resource type="Script" uid="uid://g1gvftyku5mb" path="res://userinterface/dashv2/scripts/pages/sessions.gd" id="7_kk4yy"]
+[ext_resource type="Script" uid="uid://cs3l7uq2q5uvo" path="res://userinterface/dashv2/scripts/pages/instance.gd" id="7_o4evp"]
+[ext_resource type="PackedScene" uid="uid://cyom30b1p54df" path="res://userinterface/dashv2/partials/search.tscn" id="9_gtfiv"]
+[ext_resource type="PackedScene" uid="uid://b1q1rp1y4dt2f" path="res://userinterface/dashv2/partials/account_userlist_listing.tscn" id="9_o4evp"]
+[ext_resource type="Script" uid="uid://dhdqv7d4orjgy" path="res://userinterface/dashv2/scripts/pages/account_selection.gd" id="9_qutrk"]
+[ext_resource type="PackedScene" uid="uid://crp73pbni8ils" path="res://userinterface/dashv2/partials/input_boxstring.tscn" id="11_hia1r"]
+[ext_resource type="Script" uid="uid://b2snjauxtpn22" path="res://userinterface/dashv2/scripts/pages/account_creation.gd" id="11_jgxeq"]
+[ext_resource type="PackedScene" uid="uid://dg8ypxmuk8rv" path="res://userinterface/dashv2/partials/input_string.tscn" id="11_qutrk"]
+[ext_resource type="PackedScene" uid="uid://bqf6iew4kyf0b" path="res://userinterface/dashv2/partials/input_dropdown.tscn" id="12_86ms5"]
+[ext_resource type="Texture2D" uid="uid://c7ofnclcof0ud" path="res://resources/icons/world.svg" id="14_njqt8"]
+[ext_resource type="PackedScene" uid="uid://bgr4s3s31rfsi" path="res://userinterface/dashv2/partials/input_stringlist.tscn" id="18_njqt8"]
+[ext_resource type="PackedScene" uid="uid://c314yewjhuk8s" path="res://userinterface/dashv2/partials/input_stringconfirm.tscn" id="19_s6s1v"]
+[ext_resource type="PackedScene" uid="uid://gopciccm8xx5" path="res://userinterface/dashv2/partials/removable_string_listing.tscn" id="20_v67rh"]
+[ext_resource type="Script" uid="uid://2vk6cxto4xw" path="res://userinterface/dashv2/scripts/pages/assets.gd" id="21_d3sj0"]
+[ext_resource type="Texture2D" uid="uid://8fwxg1ipf0fp" path="res://resources/icons/exit.svg" id="24_nakrv"]
+[ext_resource type="Script" uid="uid://cah3jpmu1x72b" path="res://userinterface/dashv2/scripts/pages/exit.gd" id="24_wvg7d"]
+
+[sub_resource type="ShaderMaterial" id="ShaderMaterial_0nfpo"]
+shader = ExtResource("1_co0dt")
+shader_parameter/blur_size = Vector2(3, 3)
+
+[node name="Dashboard" type="Control" unique_id=505457833]
+layout_mode = 3
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+script = ExtResource("1_7d87s")
+
+[node name="MarginContainer" type="MarginContainer" parent="." unique_id=235504345]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 10
+theme_override_constants/margin_top = 10
+theme_override_constants/margin_right = 10
+theme_override_constants/margin_bottom = 10
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer" unique_id=124409058]
+layout_mode = 2
+
+[node name="TopBar" type="Control" parent="MarginContainer/VBoxContainer" unique_id=1724217308]
+custom_minimum_size = Vector2(0, 70)
+layout_mode = 2
+script = ExtResource("2_7obga")
+
+[node name="BlurPanel" type="Panel" parent="MarginContainer/VBoxContainer/TopBar" unique_id=1417964669]
+material = SubResource("ShaderMaterial_0nfpo")
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme = ExtResource("2_0nfpo")
+
+[node name="BackgroundColor" type="Panel" parent="MarginContainer/VBoxContainer/TopBar" unique_id=2037087133]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme = ExtResource("2_0nfpo")
+
+[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/TopBar" unique_id=1173993118]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/TopBar/MarginContainer" unique_id=1648745915]
+layout_mode = 2
+theme_override_constants/separation = 10
+
+[node name="AccountButton" parent="MarginContainer/VBoxContainer/TopBar/MarginContainer/HBoxContainer" unique_id=649942124 instance=ExtResource("4_aw6p6")]
+layout_mode = 2
+selected_theme_type = "LightButton"
+
+[node name="Spacer" type="Control" parent="MarginContainer/VBoxContainer/TopBar/MarginContainer/HBoxContainer" unique_id=1621069338]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="Spacer2" type="Control" parent="MarginContainer/VBoxContainer/TopBar/MarginContainer/HBoxContainer" unique_id=47996349]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="Spacer3" type="Control" parent="MarginContainer/VBoxContainer/TopBar/MarginContainer/HBoxContainer" unique_id=187996788]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="Content" type="Control" parent="MarginContainer/VBoxContainer" unique_id=1517512624]
+layout_mode = 2
+size_flags_vertical = 3
+
+[node name="BlurPanel" type="Panel" parent="MarginContainer/VBoxContainer/Content" unique_id=64111206]
+material = SubResource("ShaderMaterial_0nfpo")
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme = ExtResource("2_0nfpo")
+
+[node name="BackgroundColor" type="Panel" parent="MarginContainer/VBoxContainer/Content" unique_id=730467318]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme = ExtResource("2_0nfpo")
+
+[node name="Container" type="MarginContainer" parent="MarginContainer/VBoxContainer/Content" unique_id=226262957]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 10
+theme_override_constants/margin_top = 10
+theme_override_constants/margin_right = 10
+theme_override_constants/margin_bottom = 10
+
+[node name="Home" type="Control" parent="MarginContainer/VBoxContainer/Content/Container" unique_id=154112638]
+visible = false
+layout_mode = 2
+script = ExtResource("6_bh4hj")
+
+[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Home" unique_id=1195053231]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="PanelContainer" type="PanelContainer" parent="MarginContainer/VBoxContainer/Content/Container/Home/HBoxContainer" unique_id=650457035]
+layout_mode = 2
+size_flags_horizontal = 3
+theme = ExtResource("2_0nfpo")
+
+[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/Content/Container/Home/HBoxContainer/PanelContainer" unique_id=409134466]
+layout_mode = 2
+theme_override_constants/margin_left = 10
+theme_override_constants/margin_top = 10
+theme_override_constants/margin_right = 10
+theme_override_constants/margin_bottom = 10
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Home/HBoxContainer/PanelContainer/MarginContainer" unique_id=758556458]
+layout_mode = 2
+
+[node name="Listing" parent="MarginContainer/VBoxContainer/Content/Container/Home/HBoxContainer/PanelContainer/MarginContainer/VBoxContainer" unique_id=902887409 instance=ExtResource("7_kk1ia")]
+layout_mode = 2
+theme = ExtResource("2_0nfpo")
+theme_type_variation = &"SolidBackground"
+
+[node name="Spacing" type="Control" parent="MarginContainer/VBoxContainer/Content/Container/Home/HBoxContainer" unique_id=643242587]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="Spacing2" type="Control" parent="MarginContainer/VBoxContainer/Content/Container/Home/HBoxContainer" unique_id=2026218850]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="Spacing3" type="Control" parent="MarginContainer/VBoxContainer/Content/Container/Home/HBoxContainer" unique_id=2092666911]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="Instance" parent="MarginContainer/VBoxContainer/Content/Container" unique_id=17586745 instance=ExtResource("3_av8ee")]
+visible = false
+layout_mode = 2
+script = ExtResource("7_o4evp")
+
+[node name="Users" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Left" parent_id_path=PackedInt32Array(17586745, 1799305671) index="0" unique_id=612707214 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Permissions" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Left" parent_id_path=PackedInt32Array(17586745, 1799305671) index="1" unique_id=915845213 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="World" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Left" parent_id_path=PackedInt32Array(17586745, 1799305671) index="2" unique_id=1224429742 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Hosting" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Left" parent_id_path=PackedInt32Array(17586745, 1799305671) index="3" unique_id=536388283 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Users" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right" parent_id_path=PackedInt32Array(17586745, 892180341) index="0" unique_id=1908722423]
+visible = false
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="AccountButtonListing" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right/Users" unique_id=430751695 instance=ExtResource("9_o4evp")]
+layout_mode = 2
+
+[node name="Permissions" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right" parent_id_path=PackedInt32Array(17586745, 892180341) index="1" unique_id=522357128]
+visible = false
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="World" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right" parent_id_path=PackedInt32Array(17586745, 892180341) index="2" unique_id=1519071951]
+visible = false
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="InputString" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right/World" unique_id=1236567120 instance=ExtResource("11_qutrk")]
+layout_mode = 2
+display_text = "Name"
+
+[node name="InputBoxString" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right/World" unique_id=368136274 instance=ExtResource("11_hia1r")]
+layout_mode = 2
+display_text = "Description"
+
+[node name="Hosting" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right" parent_id_path=PackedInt32Array(17586745, 892180341) index="3" unique_id=1206037028]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right/Hosting" unique_id=264747709]
+layout_mode = 2
+size_flags_vertical = 3
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right/Hosting/ScrollContainer" unique_id=233870972]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right/Hosting/ScrollContainer/VBoxContainer" unique_id=1973332395]
+layout_mode = 2
+size_flags_vertical = 3
+
+[node name="Privacy" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right/Hosting/ScrollContainer/VBoxContainer/VBoxContainer" unique_id=1881042579 instance=ExtResource("12_86ms5")]
+layout_mode = 2
+display_text = "Privacy"
+options = Array[String](["Invite", "Friends", "Friends+", "Contacts+", "Contacts", "Public"])
+
+[node name="Save" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right/Hosting/ScrollContainer/VBoxContainer" unique_id=995560766 instance=ExtResource("3_ocjmf")]
+layout_mode = 2
+display_text = "Save"
+selected_icon = "Instance"
+
+[node name="Button" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right/Hosting/ScrollContainer/VBoxContainer/Save" index="0" unique_id=1422381468]
+toggle_mode = false
+
+[node name="TextureRect" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right/Hosting/ScrollContainer/VBoxContainer/Save/Button/MarginContainer/VBoxContainer" parent_id_path=PackedInt32Array(995560766, 86696220) index="0" unique_id=1429445374]
+texture = ExtResource("14_njqt8")
+
+[node name="Label" parent="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right/Hosting/ScrollContainer/VBoxContainer/Save/Button/MarginContainer/VBoxContainer" parent_id_path=PackedInt32Array(995560766, 86696220) index="1" unique_id=1807295119]
+text = "Save"
+
+[node name="Sessions" parent="MarginContainer/VBoxContainer/Content/Container" unique_id=1512510126 instance=ExtResource("3_av8ee")]
+visible = false
+layout_mode = 2
+script = ExtResource("7_kk4yy")
+
+[node name="Art" parent="MarginContainer/VBoxContainer/Content/Container/Sessions/HBox/Left" parent_id_path=PackedInt32Array(1512510126, 1799305671) index="0" unique_id=790930258 instance=ExtResource("4_ql400")]
+layout_mode = 2
+selected_icon = "Art"
+
+[node name="Environment" parent="MarginContainer/VBoxContainer/Content/Container/Sessions/HBox/Left" parent_id_path=PackedInt32Array(1512510126, 1799305671) index="1" unique_id=1381397115 instance=ExtResource("4_ql400")]
+layout_mode = 2
+selected_icon = "Environment"
+
+[node name="Science" parent="MarginContainer/VBoxContainer/Content/Container/Sessions/HBox/Left" parent_id_path=PackedInt32Array(1512510126, 1799305671) index="2" unique_id=937204749 instance=ExtResource("4_ql400")]
+layout_mode = 2
+selected_icon = "Science"
+
+[node name="Games" parent="MarginContainer/VBoxContainer/Content/Container/Sessions/HBox/Left" parent_id_path=PackedInt32Array(1512510126, 1799305671) index="3" unique_id=618470106 instance=ExtResource("4_ql400")]
+layout_mode = 2
+selected_icon = "Games"
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Sessions/HBox/Right" parent_id_path=PackedInt32Array(1512510126, 892180341) index="0" unique_id=1522418383]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="InputString" parent="MarginContainer/VBoxContainer/Content/Container/Sessions/HBox/Right/VBoxContainer" unique_id=125373846 instance=ExtResource("9_gtfiv")]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer/Content/Container/Sessions/HBox/Right/VBoxContainer" unique_id=1395158644]
+layout_mode = 2
+size_flags_vertical = 3
+theme = ExtResource("2_0nfpo")
+
+[node name="GridContainer" type="GridContainer" parent="MarginContainer/VBoxContainer/Content/Container/Sessions/HBox/Right/VBoxContainer/ScrollContainer" unique_id=2033791184]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+theme_override_constants/h_separation = 10
+theme_override_constants/v_separation = 10
+columns = 5
+
+[node name="Settings" parent="MarginContainer/VBoxContainer/Content/Container" unique_id=739538319 instance=ExtResource("3_av8ee")]
+visible = false
+layout_mode = 2
+script = ExtResource("4_ap0b5")
+
+[node name="General" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Left" parent_id_path=PackedInt32Array(739538319, 1799305671) index="0" unique_id=1084146267 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Display" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Left" parent_id_path=PackedInt32Array(739538319, 1799305671) index="1" unique_id=884696286 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Audio" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Left" parent_id_path=PackedInt32Array(739538319, 1799305671) index="2" unique_id=83468254 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Controls" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Left" parent_id_path=PackedInt32Array(739538319, 1799305671) index="3" unique_id=1439698396 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Interface" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Left" parent_id_path=PackedInt32Array(739538319, 1799305671) index="4" unique_id=1049312458 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Network" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Left" parent_id_path=PackedInt32Array(739538319, 1799305671) index="5" unique_id=1617618443 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Config" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Left" parent_id_path=PackedInt32Array(739538319, 1799305671) index="6" unique_id=599049097 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Security" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Left" parent_id_path=PackedInt32Array(739538319, 1799305671) index="7" unique_id=1818668003 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Misc" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Left" parent_id_path=PackedInt32Array(739538319, 1799305671) index="8" unique_id=1457644847 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Advanced" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Left" parent_id_path=PackedInt32Array(739538319, 1799305671) index="9" unique_id=498611097 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="General" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right" parent_id_path=PackedInt32Array(739538319, 892180341) index="0" unique_id=1586946041]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="Display" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right" parent_id_path=PackedInt32Array(739538319, 892180341) index="1" unique_id=2012861645]
+visible = false
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="Audio" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right" parent_id_path=PackedInt32Array(739538319, 892180341) index="2" unique_id=1568674734]
+visible = false
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="Controls" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right" parent_id_path=PackedInt32Array(739538319, 892180341) index="3" unique_id=837764346]
+visible = false
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="Interface" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right" parent_id_path=PackedInt32Array(739538319, 892180341) index="4" unique_id=795526067]
+visible = false
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="Network" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right" parent_id_path=PackedInt32Array(739538319, 892180341) index="5" unique_id=247371837]
+visible = false
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="Config" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right" parent_id_path=PackedInt32Array(739538319, 892180341) index="6" unique_id=1318053714]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="InputDropdown" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right/Config" unique_id=1674546469 instance=ExtResource("18_njqt8")]
+layout_mode = 2
+display_text = "Session Servers"
+
+[node name="MarginContainer" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right/Config/InputDropdown/VBoxContainer" parent_id_path=PackedInt32Array(1674546469, 1064225030) index="0" unique_id=169083657]
+theme_override_constants/margin_top = 0
+
+[node name="Label" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right/Config/InputDropdown/VBoxContainer/MarginContainer/HBoxContainer" parent_id_path=PackedInt32Array(1674546469, 358122007) index="0" unique_id=144539274]
+text = "Session Servers"
+
+[node name="InputString" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right/Config/InputDropdown/VBoxContainer/MarginContainer2/PanelContainer/VBoxContainer" parent_id_path=PackedInt32Array(1674546469, 1765425757) index="0" unique_id=1750441705 instance=ExtResource("19_s6s1v")]
+layout_mode = 2
+display_text = "Add a Session Server"
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right/Config/InputDropdown/VBoxContainer/MarginContainer2/PanelContainer/VBoxContainer" parent_id_path=PackedInt32Array(1674546469, 1765425757) index="1" unique_id=923149220]
+layout_mode = 2
+
+[node name="InputString" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right/Config/InputDropdown/VBoxContainer/MarginContainer2/PanelContainer/VBoxContainer/VBoxContainer" unique_id=2057714596 instance=ExtResource("20_v67rh")]
+layout_mode = 2
+
+[node name="Security" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right" parent_id_path=PackedInt32Array(739538319, 892180341) index="7" unique_id=1254009990]
+visible = false
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="Misc" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right" parent_id_path=PackedInt32Array(739538319, 892180341) index="8" unique_id=547943782]
+visible = false
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="Advanced" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right" parent_id_path=PackedInt32Array(739538319, 892180341) index="9" unique_id=1440915562]
+visible = false
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="Assets" parent="MarginContainer/VBoxContainer/Content/Container" unique_id=1982137112 instance=ExtResource("3_av8ee")]
+visible = false
+layout_mode = 2
+script = ExtResource("21_d3sj0")
+
+[node name="Filesystem" parent="MarginContainer/VBoxContainer/Content/Container/Assets/HBox/Left" parent_id_path=PackedInt32Array(1982137112, 1799305671) index="0" unique_id=1857841582 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Local2" parent="MarginContainer/VBoxContainer/Content/Container/Assets/HBox/Left" parent_id_path=PackedInt32Array(1982137112, 1799305671) index="1" unique_id=1530762010 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Cloud" parent="MarginContainer/VBoxContainer/Content/Container/Assets/HBox/Left" parent_id_path=PackedInt32Array(1982137112, 1799305671) index="2" unique_id=1842483100 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Local" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Assets/HBox/Right" parent_id_path=PackedInt32Array(1982137112, 892180341) index="0" unique_id=99513489]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="Cloud" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Assets/HBox/Right" parent_id_path=PackedInt32Array(1982137112, 892180341) index="1" unique_id=1583883317]
+visible = false
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="Debug" parent="MarginContainer/VBoxContainer/Content/Container" unique_id=506436187 instance=ExtResource("3_av8ee")]
+visible = false
+layout_mode = 2
+
+[node name="General" parent="MarginContainer/VBoxContainer/Content/Container/Debug/HBox/Left" parent_id_path=PackedInt32Array(506436187, 1799305671) index="0" unique_id=725321320 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Display" parent="MarginContainer/VBoxContainer/Content/Container/Debug/HBox/Left" parent_id_path=PackedInt32Array(506436187, 1799305671) index="1" unique_id=1791779287 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Audio" parent="MarginContainer/VBoxContainer/Content/Container/Debug/HBox/Left" parent_id_path=PackedInt32Array(506436187, 1799305671) index="2" unique_id=1517275417 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Controls" parent="MarginContainer/VBoxContainer/Content/Container/Debug/HBox/Left" parent_id_path=PackedInt32Array(506436187, 1799305671) index="3" unique_id=127589259 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Interface" parent="MarginContainer/VBoxContainer/Content/Container/Debug/HBox/Left" parent_id_path=PackedInt32Array(506436187, 1799305671) index="4" unique_id=1269426169 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Network" parent="MarginContainer/VBoxContainer/Content/Container/Debug/HBox/Left" parent_id_path=PackedInt32Array(506436187, 1799305671) index="5" unique_id=571186988 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Config" parent="MarginContainer/VBoxContainer/Content/Container/Debug/HBox/Left" parent_id_path=PackedInt32Array(506436187, 1799305671) index="6" unique_id=1737883581 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Security" parent="MarginContainer/VBoxContainer/Content/Container/Debug/HBox/Left" parent_id_path=PackedInt32Array(506436187, 1799305671) index="7" unique_id=1319373843 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Misc" parent="MarginContainer/VBoxContainer/Content/Container/Debug/HBox/Left" parent_id_path=PackedInt32Array(506436187, 1799305671) index="8" unique_id=821001346 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="Advanced" parent="MarginContainer/VBoxContainer/Content/Container/Debug/HBox/Left" parent_id_path=PackedInt32Array(506436187, 1799305671) index="9" unique_id=59859102 instance=ExtResource("4_ql400")]
+layout_mode = 2
+
+[node name="General" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Debug/HBox/Right" parent_id_path=PackedInt32Array(506436187, 892180341) index="0" unique_id=588937059]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="Exit" type="Control" parent="MarginContainer/VBoxContainer/Content/Container" unique_id=2026000436]
+layout_mode = 2
+script = ExtResource("24_wvg7d")
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Exit" unique_id=242586756]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="Control2" type="Control" parent="MarginContainer/VBoxContainer/Content/Container/Exit/VBoxContainer" unique_id=1920615328]
+layout_mode = 2
+size_flags_vertical = 3
+
+[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/Content/Container/Exit/VBoxContainer" unique_id=2046503768]
+layout_mode = 2
+size_flags_vertical = 6
+theme_override_font_sizes/font_size = 60
+text = "Thank you for using OpenMinerva!"
+horizontal_alignment = 1
+
+[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/Exit/VBoxContainer" unique_id=1333815646]
+custom_minimum_size = Vector2(0, 50)
+layout_mode = 2
+
+[node name="Control2" type="Control" parent="MarginContainer/VBoxContainer/Content/Container/Exit/VBoxContainer/HBoxContainer" unique_id=1575232925]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="Cancel" type="Button" parent="MarginContainer/VBoxContainer/Content/Container/Exit/VBoxContainer/HBoxContainer" unique_id=1827195067]
+layout_mode = 2
+size_flags_horizontal = 3
+mouse_default_cursor_shape = 2
+theme = ExtResource("2_0nfpo")
+theme_type_variation = &"Danger"
+text = "Cancel"
+
+[node name="Exit" type="Button" parent="MarginContainer/VBoxContainer/Content/Container/Exit/VBoxContainer/HBoxContainer" unique_id=498096560]
+layout_mode = 2
+size_flags_horizontal = 3
+mouse_default_cursor_shape = 2
+theme = ExtResource("2_0nfpo")
+theme_type_variation = &"Danger"
+
+[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/VBoxContainer/Content/Container/Exit/VBoxContainer/HBoxContainer/Exit" unique_id=782073328]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer/Content/Container/Exit/VBoxContainer/HBoxContainer/Exit/AspectRatioContainer" unique_id=1077428590]
+layout_mode = 2
+texture = ExtResource("24_nakrv")
+expand_mode = 2
+
+[node name="Control3" type="Control" parent="MarginContainer/VBoxContainer/Content/Container/Exit/VBoxContainer/HBoxContainer" unique_id=2059609441]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+
+[node name="Control" type="Control" parent="MarginContainer/VBoxContainer/Content/Container/Exit/VBoxContainer" unique_id=772658709]
+layout_mode = 2
+size_flags_vertical = 3
+
+[node name="Control3" type="Control" parent="MarginContainer/VBoxContainer/Content/Container/Exit/VBoxContainer" unique_id=215825983]
+layout_mode = 2
+size_flags_vertical = 3
+
+[node name="_AccountSelection" type="Control" parent="MarginContainer/VBoxContainer/Content/Container" unique_id=942492755]
+visible = false
+layout_mode = 2
+script = ExtResource("9_qutrk")
+
+[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/_AccountSelection" unique_id=1122171112]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="Spacer" type="Control" parent="MarginContainer/VBoxContainer/Content/Container/_AccountSelection/HBoxContainer" unique_id=1558467922]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/_AccountSelection/HBoxContainer" unique_id=886733571]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer/Content/Container/_AccountSelection/HBoxContainer/VBoxContainer" unique_id=1823464631]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+theme_override_constants/scrollbar_h_separation = 10
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/_AccountSelection/HBoxContainer/VBoxContainer/ScrollContainer" unique_id=295905298]
+custom_minimum_size = Vector2(500, 0)
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="NavButton" parent="MarginContainer/VBoxContainer/Content/Container/_AccountSelection/HBoxContainer/VBoxContainer" unique_id=1677704621 instance=ExtResource("3_ocjmf")]
+layout_mode = 2
+display_text = "Create Account"
+
+[node name="Button" parent="MarginContainer/VBoxContainer/Content/Container/_AccountSelection/HBoxContainer/VBoxContainer/NavButton" index="0" unique_id=1422381468]
+toggle_mode = false
+
+[node name="Label" parent="MarginContainer/VBoxContainer/Content/Container/_AccountSelection/HBoxContainer/VBoxContainer/NavButton/Button/MarginContainer/VBoxContainer" parent_id_path=PackedInt32Array(1677704621, 86696220) index="1" unique_id=1807295119]
+size_flags_horizontal = 3
+text = "Create Account"
+
+[node name="Spacer2" type="Control" parent="MarginContainer/VBoxContainer/Content/Container/_AccountSelection/HBoxContainer" unique_id=962768924]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="_AccountCreation" type="Control" parent="MarginContainer/VBoxContainer/Content/Container" unique_id=580645222]
+visible = false
+layout_mode = 2
+script = ExtResource("11_jgxeq")
+
+[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/_AccountCreation" unique_id=165524708]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="Spacer" type="Control" parent="MarginContainer/VBoxContainer/Content/Container/_AccountCreation/HBoxContainer" unique_id=309184611]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/_AccountCreation/HBoxContainer" unique_id=1428128737]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer/Content/Container/_AccountCreation/HBoxContainer/VBoxContainer" unique_id=2089091704]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+theme_override_constants/scrollbar_h_separation = 10
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/Content/Container/_AccountCreation/HBoxContainer/VBoxContainer/ScrollContainer" unique_id=1579107512]
+custom_minimum_size = Vector2(500, 0)
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 4
+
+[node name="Username" parent="MarginContainer/VBoxContainer/Content/Container/_AccountCreation/HBoxContainer/VBoxContainer/ScrollContainer/VBoxContainer" unique_id=829702118 instance=ExtResource("11_qutrk")]
+layout_mode = 2
+display_text = "Display Name"
+
+[node name="AccountServer" parent="MarginContainer/VBoxContainer/Content/Container/_AccountCreation/HBoxContainer/VBoxContainer/ScrollContainer/VBoxContainer" unique_id=1844371600 instance=ExtResource("11_qutrk")]
+layout_mode = 2
+display_text = "Account Server"
+
+[node name="Accept" parent="MarginContainer/VBoxContainer/Content/Container/_AccountCreation/HBoxContainer/VBoxContainer" unique_id=223705548 instance=ExtResource("3_ocjmf")]
+layout_mode = 2
+display_text = "Add"
+
+[node name="Button" parent="MarginContainer/VBoxContainer/Content/Container/_AccountCreation/HBoxContainer/VBoxContainer/Accept" index="0" unique_id=1422381468]
+toggle_mode = false
+
+[node name="Label" parent="MarginContainer/VBoxContainer/Content/Container/_AccountCreation/HBoxContainer/VBoxContainer/Accept/Button/MarginContainer/VBoxContainer" parent_id_path=PackedInt32Array(223705548, 86696220) index="1" unique_id=1807295119]
+size_flags_horizontal = 3
+text = "Add"
+
+[node name="Spacer2" type="Control" parent="MarginContainer/VBoxContainer/Content/Container/_AccountCreation/HBoxContainer" unique_id=275254948]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="NavBar" type="Control" parent="MarginContainer/VBoxContainer" unique_id=401495078]
+custom_minimum_size = Vector2(0, 60)
+layout_mode = 2
+script = ExtResource("3_8u0v7")
+
+[node name="BlurPanel" type="Panel" parent="MarginContainer/VBoxContainer/NavBar" unique_id=1715463703]
+material = SubResource("ShaderMaterial_0nfpo")
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme = ExtResource("2_0nfpo")
+
+[node name="BackgroundColor" type="Panel" parent="MarginContainer/VBoxContainer/NavBar" unique_id=1259999416]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme = ExtResource("2_0nfpo")
+
+[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/NavBar" unique_id=1303027290]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/NavBar/MarginContainer" unique_id=1576091722]
+layout_mode = 2
+alignment = 1
+metadata/_edit_use_anchors_ = true
+
+[node name="Home" parent="MarginContainer/VBoxContainer/NavBar/MarginContainer/HBoxContainer" unique_id=1398937292 instance=ExtResource("3_ocjmf")]
+layout_mode = 2
+display_text = "Home"
+selected_icon = "Home"
+
+[node name="Instance" parent="MarginContainer/VBoxContainer/NavBar/MarginContainer/HBoxContainer" unique_id=2065864495 instance=ExtResource("3_ocjmf")]
+layout_mode = 2
+display_text = "Instance"
+selected_icon = "Instance"
+
+[node name="Sessions" parent="MarginContainer/VBoxContainer/NavBar/MarginContainer/HBoxContainer" unique_id=115442342 instance=ExtResource("3_ocjmf")]
+layout_mode = 2
+display_text = "Sessions"
+selected_icon = "Sessions"
+
+[node name="Contacts" parent="MarginContainer/VBoxContainer/NavBar/MarginContainer/HBoxContainer" unique_id=1218469163 instance=ExtResource("3_ocjmf")]
+layout_mode = 2
+display_text = "Contacts"
+selected_icon = "Contacts"
+
+[node name="Assets" parent="MarginContainer/VBoxContainer/NavBar/MarginContainer/HBoxContainer" unique_id=1841335532 instance=ExtResource("3_ocjmf")]
+layout_mode = 2
+display_text = "Assets"
+selected_icon = "Assets"
+
+[node name="Apps" parent="MarginContainer/VBoxContainer/NavBar/MarginContainer/HBoxContainer" unique_id=121060802 instance=ExtResource("3_ocjmf")]
+layout_mode = 2
+display_text = "Apps"
+selected_icon = "Apps"
+
+[node name="Settings" parent="MarginContainer/VBoxContainer/NavBar/MarginContainer/HBoxContainer" unique_id=849079664 instance=ExtResource("3_ocjmf")]
+layout_mode = 2
+display_text = "Settings"
+selected_icon = "Settings"
+
+[node name="Debug" parent="MarginContainer/VBoxContainer/NavBar/MarginContainer/HBoxContainer" unique_id=194442451 instance=ExtResource("3_ocjmf")]
+layout_mode = 2
+display_text = "Debug"
+selected_icon = "Debug"
+
+[node name="Exit" parent="MarginContainer/VBoxContainer/NavBar/MarginContainer/HBoxContainer" unique_id=1580421633 instance=ExtResource("3_ocjmf")]
+layout_mode = 2
+display_text = "Exit"
+selected_icon = "Exit"
+selected_theme_type = "Danger"
+
+[editable path="MarginContainer/VBoxContainer/Content/Container/Home/HBoxContainer/PanelContainer/MarginContainer/VBoxContainer/Listing"]
+[editable path="MarginContainer/VBoxContainer/Content/Container/Instance"]
+[editable path="MarginContainer/VBoxContainer/Content/Container/Instance/HBox/Right/Hosting/ScrollContainer/VBoxContainer/Save"]
+[editable path="MarginContainer/VBoxContainer/Content/Container/Sessions"]
+[editable path="MarginContainer/VBoxContainer/Content/Container/Settings"]
+[editable path="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right/Config/InputDropdown"]
+[editable path="MarginContainer/VBoxContainer/Content/Container/Settings/HBox/Right/Config/InputDropdown/VBoxContainer/MarginContainer2/PanelContainer/VBoxContainer/InputString"]
+[editable path="MarginContainer/VBoxContainer/Content/Container/Assets"]
+[editable path="MarginContainer/VBoxContainer/Content/Container/Debug"]
+[editable path="MarginContainer/VBoxContainer/Content/Container/_AccountSelection/HBoxContainer/VBoxContainer/NavButton"]
+[editable path="MarginContainer/VBoxContainer/Content/Container/_AccountCreation/HBoxContainer/VBoxContainer/Accept"]
diff --git a/src/userinterface/dashv2/partials/account_button.tscn b/src/userinterface/dashv2/partials/account_button.tscn
new file mode 100644
index 0000000..13b9ec0
--- /dev/null
+++ b/src/userinterface/dashv2/partials/account_button.tscn
@@ -0,0 +1,81 @@
+[gd_scene format=3 uid="uid://clvk6h18vwcd3"]
+
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="1_dmbuk"]
+[ext_resource type="Texture2D" uid="uid://coqi7w7inqyv1" path="res://resources/icons/account.svg" id="2_clecd"]
+
+[sub_resource type="GDScript" id="GDScript_q3lw4"]
+resource_name = "export"
+script/source = "extends Control
+
+@export var display_text: String = \"Default Text\"
+
+@onready var label_node = $Button/MarginContainer/VBoxContainer/Label
+@onready var icon_node = $Button/MarginContainer/VBoxContainer/TextureRect
+@onready var button_node = $Button
+@export_enum(\"Danger\", \"LightButton\") var selected_theme_type: String
+
+func _ready():
+ button_node.theme_type_variation = selected_theme_type if selected_theme_type != null else null
+"
+
+[node name="AccountButton" type="Control" unique_id=649942124]
+custom_minimum_size = Vector2(200, 50)
+layout_mode = 3
+anchor_top = 0.47685185
+anchor_right = 1.0
+anchor_bottom = 0.5231481
+offset_top = 25.0
+offset_bottom = -24.999939
+grow_horizontal = 2
+grow_vertical = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+theme = ExtResource("1_dmbuk")
+script = SubResource("GDScript_q3lw4")
+
+[node name="Button" type="Button" parent="." unique_id=1422381468]
+custom_minimum_size = Vector2(140, 0)
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+mouse_default_cursor_shape = 2
+theme = ExtResource("1_dmbuk")
+theme_type_variation = &"Danger"
+
+[node name="MarginContainer" type="MarginContainer" parent="Button" unique_id=665374152]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="HBox" type="HBoxContainer" parent="Button/MarginContainer" unique_id=86696220]
+layout_mode = 2
+theme_override_constants/separation = 10
+
+[node name="TextureRect" type="TextureRect" parent="Button/MarginContainer/HBox" unique_id=1429445374]
+layout_mode = 2
+texture = ExtResource("2_clecd")
+expand_mode = 2
+
+[node name="VBox" type="VBoxContainer" parent="Button/MarginContainer/HBox" unique_id=1074901883]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="Name" type="Label" parent="Button/MarginContainer/HBox/VBox" unique_id=1807295119]
+layout_mode = 2
+text = "ERROR"
+
+[node name="Location" type="Label" parent="Button/MarginContainer/HBox/VBox" unique_id=675948225]
+layout_mode = 2
+theme_override_colors/font_color = Color(0.70380783, 0.70380783, 0.70380783, 1)
+theme_override_font_sizes/font_size = 10
+text = "ERROR"
diff --git a/src/userinterface/dashv2/partials/account_button_listing.tscn b/src/userinterface/dashv2/partials/account_button_listing.tscn
new file mode 100644
index 0000000..022a7e4
--- /dev/null
+++ b/src/userinterface/dashv2/partials/account_button_listing.tscn
@@ -0,0 +1,135 @@
+[gd_scene format=3 uid="uid://cbietn7vfj6ud"]
+
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="1_h0f2g"]
+[ext_resource type="Texture2D" uid="uid://coqi7w7inqyv1" path="res://resources/icons/account.svg" id="2_rbo2h"]
+[ext_resource type="Texture2D" uid="uid://byxgefy5xsbuu" path="res://resources/icons/ui/settings.svg" id="3_els6r"]
+[ext_resource type="Texture2D" uid="uid://5admxcll28y4" path="res://resources/icons/ui/trash.svg" id="4_g1hvg"]
+
+[sub_resource type="GDScript" id="GDScript_q3lw4"]
+resource_name = "export"
+script/source = "extends Control
+"
+
+[node name="AccountButtonListing" type="Control" unique_id=649942124]
+custom_minimum_size = Vector2(200, 75)
+layout_mode = 3
+anchor_top = 0.47685185
+anchor_right = 1.0
+anchor_bottom = 0.5231481
+offset_top = 25.0
+offset_bottom = -24.999939
+grow_horizontal = 2
+grow_vertical = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+theme = ExtResource("1_h0f2g")
+script = SubResource("GDScript_q3lw4")
+
+[node name="HBoxContainer" type="HBoxContainer" parent="." unique_id=250429512]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="Button" type="Button" parent="HBoxContainer" unique_id=1422381468]
+custom_minimum_size = Vector2(140, 0)
+layout_mode = 2
+size_flags_horizontal = 3
+mouse_default_cursor_shape = 2
+theme = ExtResource("1_h0f2g")
+
+[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/Button" unique_id=665374152]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="HBox" type="HBoxContainer" parent="HBoxContainer/Button/MarginContainer" unique_id=86696220]
+layout_mode = 2
+theme_override_constants/separation = 10
+
+[node name="TextureRect" type="TextureRect" parent="HBoxContainer/Button/MarginContainer/HBox" unique_id=1429445374]
+layout_mode = 2
+texture = ExtResource("2_rbo2h")
+expand_mode = 2
+
+[node name="VBox" type="VBoxContainer" parent="HBoxContainer/Button/MarginContainer/HBox" unique_id=1074901883]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="Name" type="Label" parent="HBoxContainer/Button/MarginContainer/HBox/VBox" unique_id=1807295119]
+layout_mode = 2
+theme_override_font_sizes/font_size = 20
+text = "ERROR"
+
+[node name="Location" type="Label" parent="HBoxContainer/Button/MarginContainer/HBox/VBox" unique_id=675948225]
+layout_mode = 2
+theme_override_colors/font_color = Color(0.70380783, 0.70380783, 0.70380783, 1)
+text = "ERROR"
+
+[node name="Configure" type="AspectRatioContainer" parent="HBoxContainer" unique_id=559312234]
+custom_minimum_size = Vector2(75, 0)
+layout_mode = 2
+
+[node name="Button" type="Button" parent="HBoxContainer/Configure" unique_id=1933552852]
+layout_mode = 2
+mouse_default_cursor_shape = 2
+theme = ExtResource("1_h0f2g")
+
+[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/Configure/Button" unique_id=564567149]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="AspectRatioContainer" type="AspectRatioContainer" parent="HBoxContainer/Configure/Button/MarginContainer" unique_id=1526419418]
+layout_mode = 2
+
+[node name="TextureRect" type="TextureRect" parent="HBoxContainer/Configure/Button/MarginContainer/AspectRatioContainer" unique_id=522146680]
+layout_mode = 2
+texture = ExtResource("3_els6r")
+expand_mode = 2
+
+[node name="Delete" type="AspectRatioContainer" parent="HBoxContainer" unique_id=931685674]
+custom_minimum_size = Vector2(75, 0)
+layout_mode = 2
+
+[node name="Button" type="Button" parent="HBoxContainer/Delete" unique_id=1649839441]
+layout_mode = 2
+mouse_default_cursor_shape = 2
+theme = ExtResource("1_h0f2g")
+theme_type_variation = &"Danger"
+
+[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/Delete/Button" unique_id=335685794]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="AspectRatioContainer" type="AspectRatioContainer" parent="HBoxContainer/Delete/Button/MarginContainer" unique_id=910803916]
+layout_mode = 2
+
+[node name="TextureRect" type="TextureRect" parent="HBoxContainer/Delete/Button/MarginContainer/AspectRatioContainer" unique_id=1008457231]
+layout_mode = 2
+texture = ExtResource("4_g1hvg")
+expand_mode = 2
diff --git a/src/userinterface/dashv2/partials/account_userlist_listing.tscn b/src/userinterface/dashv2/partials/account_userlist_listing.tscn
new file mode 100644
index 0000000..e6537c5
--- /dev/null
+++ b/src/userinterface/dashv2/partials/account_userlist_listing.tscn
@@ -0,0 +1,157 @@
+[gd_scene format=3 uid="uid://b1q1rp1y4dt2f"]
+
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="1_oxocb"]
+[ext_resource type="Texture2D" uid="uid://coqi7w7inqyv1" path="res://resources/icons/account.svg" id="2_a7mjn"]
+[ext_resource type="Texture2D" uid="uid://daebexy1etluo" path="res://resources/icons/ui/podiatry.svg" id="3_oxocb"]
+[ext_resource type="Texture2D" uid="uid://b4mmsxpws0l2k" path="res://resources/icons/ui/block.svg" id="4_a7mjn"]
+
+[sub_resource type="GDScript" id="GDScript_q3lw4"]
+resource_name = "export"
+script/source = "extends Control
+"
+
+[node name="AccountButtonListing" type="Control" unique_id=649942124]
+custom_minimum_size = Vector2(200, 75)
+layout_mode = 3
+anchor_top = 0.4652778
+anchor_right = 1.0
+anchor_bottom = 0.5347222
+offset_top = 37.5
+offset_bottom = -37.5
+grow_horizontal = 2
+grow_vertical = 2
+size_flags_horizontal = 3
+theme = ExtResource("1_oxocb")
+script = SubResource("GDScript_q3lw4")
+
+[node name="HBoxContainer" type="HBoxContainer" parent="." unique_id=250429512]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="Button" type="Button" parent="HBoxContainer" unique_id=1422381468]
+custom_minimum_size = Vector2(140, 0)
+layout_mode = 2
+size_flags_horizontal = 3
+mouse_default_cursor_shape = 2
+theme = ExtResource("1_oxocb")
+
+[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/Button" unique_id=665374152]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="HBox" type="HBoxContainer" parent="HBoxContainer/Button/MarginContainer" unique_id=86696220]
+layout_mode = 2
+theme_override_constants/separation = 10
+
+[node name="TextureRect" type="TextureRect" parent="HBoxContainer/Button/MarginContainer/HBox" unique_id=1429445374]
+layout_mode = 2
+texture = ExtResource("2_a7mjn")
+expand_mode = 2
+
+[node name="VBox" type="VBoxContainer" parent="HBoxContainer/Button/MarginContainer/HBox" unique_id=1074901883]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="Name" type="Label" parent="HBoxContainer/Button/MarginContainer/HBox/VBox" unique_id=1807295119]
+layout_mode = 2
+theme_override_font_sizes/font_size = 20
+text = "ERROR"
+
+[node name="Location" type="Label" parent="HBoxContainer/Button/MarginContainer/HBox/VBox" unique_id=675948225]
+layout_mode = 2
+theme_override_colors/font_color = Color(0.70380783, 0.70380783, 0.70380783, 1)
+text = "ERROR"
+
+[node name="Volume" type="PanelContainer" parent="HBoxContainer" unique_id=493364002]
+custom_minimum_size = Vector2(200, 0)
+layout_mode = 2
+theme = ExtResource("1_oxocb")
+theme_type_variation = &"SolidBackground"
+
+[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/Volume" unique_id=1630519044]
+layout_mode = 2
+theme_override_constants/margin_left = 10
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 10
+theme_override_constants/margin_bottom = 5
+
+[node name="HSlider" type="HSlider" parent="HBoxContainer/Volume/MarginContainer" unique_id=1470760869]
+layout_mode = 2
+size_flags_vertical = 4
+mouse_default_cursor_shape = 2
+max_value = 150.0
+step = 5.0
+value = 100.0
+rounded = true
+ticks_on_borders = true
+
+[node name="Kick" type="AspectRatioContainer" parent="HBoxContainer" unique_id=559312234]
+custom_minimum_size = Vector2(75, 0)
+layout_mode = 2
+
+[node name="Button" type="Button" parent="HBoxContainer/Kick" unique_id=1933552852]
+layout_mode = 2
+mouse_default_cursor_shape = 2
+theme = ExtResource("1_oxocb")
+
+[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/Kick/Button" unique_id=564567149]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="AspectRatioContainer" type="AspectRatioContainer" parent="HBoxContainer/Kick/Button/MarginContainer" unique_id=1526419418]
+layout_mode = 2
+
+[node name="TextureRect" type="TextureRect" parent="HBoxContainer/Kick/Button/MarginContainer/AspectRatioContainer" unique_id=522146680]
+layout_mode = 2
+texture = ExtResource("3_oxocb")
+expand_mode = 2
+
+[node name="Ban" type="AspectRatioContainer" parent="HBoxContainer" unique_id=931685674]
+custom_minimum_size = Vector2(75, 0)
+layout_mode = 2
+
+[node name="Button" type="Button" parent="HBoxContainer/Ban" unique_id=1649839441]
+layout_mode = 2
+mouse_default_cursor_shape = 2
+theme = ExtResource("1_oxocb")
+theme_type_variation = &"Danger"
+
+[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/Ban/Button" unique_id=335685794]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="AspectRatioContainer" type="AspectRatioContainer" parent="HBoxContainer/Ban/Button/MarginContainer" unique_id=910803916]
+layout_mode = 2
+
+[node name="TextureRect" type="TextureRect" parent="HBoxContainer/Ban/Button/MarginContainer/AspectRatioContainer" unique_id=1008457231]
+layout_mode = 2
+texture = ExtResource("4_a7mjn")
+expand_mode = 2
diff --git a/src/userinterface/dashv2/partials/category_button.tscn b/src/userinterface/dashv2/partials/category_button.tscn
new file mode 100644
index 0000000..3f88b25
--- /dev/null
+++ b/src/userinterface/dashv2/partials/category_button.tscn
@@ -0,0 +1,83 @@
+[gd_scene format=3 uid="uid://71vuc3qrtgi7"]
+
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="1_dnctg"]
+
+[sub_resource type="GDScript" id="GDScript_q3lw4"]
+resource_name = "export"
+script/source = "@tool
+extends Control
+
+@onready var label_node = $Button/MarginContainer/VBoxContainer/Label
+@onready var icon_node = $Button/MarginContainer/VBoxContainer/TextureRect
+@onready var button_node = $Button
+@export_enum(\"Art\", \"Environment\", \"Science\", \"Games\") var selected_icon: String
+@export_enum(\"Danger\") var selected_theme_type: String
+
+var icon_paths = {
+ \"Art\": \"res://resources/icons/art.svg\",
+ \"Environment\": \"res://resources/icons/environment.svg\",
+ \"Science\": \"res://resources/icons/science.svg\",
+ \"Games\": \"res://resources/icons/circus.svg\",
+}
+
+func _ready():
+ var display_text: String = name
+ label_node.text = display_text
+ if icon_paths.has(selected_icon):
+ icon_node.texture = load(icon_paths[selected_icon])
+ button_node.theme_type_variation = selected_theme_type if selected_theme_type != null else null
+"
+
+[node name="CategoryButton" type="Control" unique_id=649942124]
+custom_minimum_size = Vector2(200, 50)
+layout_mode = 3
+anchor_top = 0.47685185
+anchor_right = 1.0
+anchor_bottom = 0.5231481
+offset_top = 25.0
+offset_bottom = -24.999939
+grow_horizontal = 2
+grow_vertical = 2
+size_flags_horizontal = 3
+size_flags_vertical = 4
+theme = ExtResource("1_dnctg")
+script = SubResource("GDScript_q3lw4")
+metadata/_edit_use_anchors_ = true
+
+[node name="Button" type="Button" parent="." unique_id=1422381468]
+custom_minimum_size = Vector2(140, 0)
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+mouse_default_cursor_shape = 2
+theme = ExtResource("1_dnctg")
+theme_type_variation = &"Danger"
+toggle_mode = true
+
+[node name="MarginContainer" type="MarginContainer" parent="Button" unique_id=665374152]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="VBoxContainer" type="HBoxContainer" parent="Button/MarginContainer" unique_id=86696220]
+layout_mode = 2
+theme_override_constants/separation = 10
+
+[node name="TextureRect" type="TextureRect" parent="Button/MarginContainer/VBoxContainer" unique_id=1429445374]
+layout_mode = 2
+expand_mode = 2
+
+[node name="Label" type="Label" parent="Button/MarginContainer/VBoxContainer" unique_id=1807295119]
+layout_mode = 2
+text = "ERROR"
+horizontal_alignment = 1
diff --git a/src/userinterface/dashv2/partials/home_server_listing.tscn b/src/userinterface/dashv2/partials/home_server_listing.tscn
new file mode 100644
index 0000000..e306b71
--- /dev/null
+++ b/src/userinterface/dashv2/partials/home_server_listing.tscn
@@ -0,0 +1,63 @@
+[gd_scene format=3 uid="uid://dh0u5xtwooa0v"]
+
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="1_cfy26"]
+[ext_resource type="Texture2D" uid="uid://8fwxg1ipf0fp" path="res://resources/icons/exit.svg" id="2_pwepf"]
+
+[node name="Listing" type="Button" unique_id=639969328]
+custom_minimum_size = Vector2(0, 75)
+offset_right = 249.0
+offset_bottom = 75.0
+
+[node name="MarginContainer" type="MarginContainer" parent="." unique_id=968923659]
+layout_mode = 1
+anchors_preset = 14
+anchor_top = 0.5
+anchor_right = 1.0
+anchor_bottom = 0.5
+offset_top = -32.5
+offset_bottom = 32.5
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer" unique_id=181669531]
+layout_mode = 2
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/HBoxContainer" unique_id=959619057]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="Label" type="Label" parent="MarginContainer/HBoxContainer/VBoxContainer" unique_id=252860746]
+layout_mode = 2
+theme_override_font_sizes/font_size = 20
+text = "Awesome server"
+
+[node name="Label2" type="Label" parent="MarginContainer/HBoxContainer/VBoxContainer" unique_id=603422230]
+layout_mode = 2
+text = "X / 20"
+
+[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/HBoxContainer" unique_id=35108429]
+custom_minimum_size = Vector2(75, 0)
+layout_mode = 2
+
+[node name="Button" type="Button" parent="MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=922118119]
+layout_mode = 2
+mouse_default_cursor_shape = 2
+theme = ExtResource("1_cfy26")
+theme_type_variation = &"Danger"
+
+[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/HBoxContainer/AspectRatioContainer/Button" unique_id=380622538]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="TextureRect" type="TextureRect" parent="MarginContainer/HBoxContainer/AspectRatioContainer/Button/AspectRatioContainer" unique_id=1848141350]
+layout_mode = 2
+texture = ExtResource("2_pwepf")
+expand_mode = 2
diff --git a/src/userinterface/dashv2/partials/input_boxstring.tscn b/src/userinterface/dashv2/partials/input_boxstring.tscn
new file mode 100644
index 0000000..2b657cb
--- /dev/null
+++ b/src/userinterface/dashv2/partials/input_boxstring.tscn
@@ -0,0 +1,68 @@
+[gd_scene format=3 uid="uid://crp73pbni8ils"]
+
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="1_f3kam"]
+
+[sub_resource type="GDScript" id="GDScript_wtshq"]
+script/source = "extends Control
+
+@export var display_text: String = \"Default Text\"
+
+@onready var label_node = $PanelContainer/MarginContainer/HBoxContainer/Label
+@onready var lineedit_node = $PanelContainer/MarginContainer/HBoxContainer/MarginContainer/LineEdit
+#@export_enum(\"Danger\") var selected_theme_type: String
+
+func _ready():
+ label_node.text = display_text
+ lineedit_node.placeholder_text = display_text
+"
+
+[node name="InputBoxString" type="Control" unique_id=1236567120]
+custom_minimum_size = Vector2(0, 100)
+layout_mode = 3
+anchor_top = 0.4814815
+anchor_right = 1.0
+anchor_bottom = 0.5185185
+grow_horizontal = 2
+script = SubResource("GDScript_wtshq")
+metadata/_edit_use_anchors_ = true
+
+[node name="PanelContainer" type="PanelContainer" parent="." unique_id=382665771]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme = ExtResource("1_f3kam")
+theme_type_variation = &"SolidBackground"
+
+[node name="MarginContainer" type="MarginContainer" parent="PanelContainer" unique_id=169083657]
+layout_mode = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_right = 5
+
+[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/MarginContainer" unique_id=358122007]
+custom_minimum_size = Vector2(0, 40)
+layout_mode = 2
+metadata/_edit_use_anchors_ = true
+
+[node name="Label" type="Label" parent="PanelContainer/MarginContainer/HBoxContainer" unique_id=144539274]
+custom_minimum_size = Vector2(200, 0)
+layout_mode = 2
+text = "ERROR"
+
+[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/MarginContainer/HBoxContainer" unique_id=514760511]
+layout_mode = 2
+size_flags_horizontal = 3
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 0
+theme_override_constants/margin_bottom = 5
+
+[node name="LineEdit" type="TextEdit" parent="PanelContainer/MarginContainer/HBoxContainer/MarginContainer" unique_id=369988496]
+layout_mode = 2
+size_flags_horizontal = 3
+theme = ExtResource("1_f3kam")
+text = "This is great"
+placeholder_text = "ERROR"
+wrap_mode = 1
diff --git a/src/userinterface/dashv2/partials/input_dropdown.tscn b/src/userinterface/dashv2/partials/input_dropdown.tscn
new file mode 100644
index 0000000..2cf16b6
--- /dev/null
+++ b/src/userinterface/dashv2/partials/input_dropdown.tscn
@@ -0,0 +1,76 @@
+[gd_scene format=3 uid="uid://bqf6iew4kyf0b"]
+
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="1_67hgs"]
+
+[sub_resource type="GDScript" id="GDScript_wtshq"]
+script/source = "@tool
+extends Control
+
+@export var display_text: String = \"Default Text\"
+@export var options: Array[String] = []
+@export var default_selection: int = 0
+
+@onready var label_node = $PanelContainer/MarginContainer/HBoxContainer/Label
+@onready var optionsbutton_node = $PanelContainer/MarginContainer/HBoxContainer/MarginContainer/OptionButton
+#@export_enum(\"Danger\") var selected_theme_type: String
+
+func _ready():
+ label_node.text = display_text
+ for _item in options:
+ optionsbutton_node.add_item(_item)
+ optionsbutton_node.select(default_selection)
+"
+
+[node name="InputDropdown" type="Control" unique_id=1236567120]
+custom_minimum_size = Vector2(0, 40)
+layout_mode = 3
+anchor_top = 0.4814815
+anchor_right = 1.0
+anchor_bottom = 0.5185185
+offset_top = 20.0
+offset_bottom = -20.0
+grow_horizontal = 2
+grow_vertical = 2
+script = SubResource("GDScript_wtshq")
+metadata/_edit_use_anchors_ = true
+
+[node name="PanelContainer" type="PanelContainer" parent="." unique_id=382665771]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme = ExtResource("1_67hgs")
+theme_type_variation = &"SolidBackground"
+
+[node name="MarginContainer" type="MarginContainer" parent="PanelContainer" unique_id=169083657]
+layout_mode = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_right = 5
+
+[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/MarginContainer" unique_id=358122007]
+custom_minimum_size = Vector2(0, 40)
+layout_mode = 2
+metadata/_edit_use_anchors_ = true
+
+[node name="Label" type="Label" parent="PanelContainer/MarginContainer/HBoxContainer" unique_id=144539274]
+custom_minimum_size = Vector2(200, 0)
+layout_mode = 2
+size_flags_horizontal = 3
+text = "ERROR"
+
+[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/MarginContainer/HBoxContainer" unique_id=514760511]
+layout_mode = 2
+size_flags_horizontal = 3
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 0
+theme_override_constants/margin_bottom = 5
+
+[node name="OptionButton" type="OptionButton" parent="PanelContainer/MarginContainer/HBoxContainer/MarginContainer" unique_id=1020799305]
+custom_minimum_size = Vector2(300, 0)
+layout_mode = 2
+size_flags_horizontal = 10
+theme = ExtResource("1_67hgs")
+alignment = 1
diff --git a/src/userinterface/dashv2/partials/input_string.tscn b/src/userinterface/dashv2/partials/input_string.tscn
new file mode 100644
index 0000000..e0951ac
--- /dev/null
+++ b/src/userinterface/dashv2/partials/input_string.tscn
@@ -0,0 +1,70 @@
+[gd_scene format=3 uid="uid://dg8ypxmuk8rv"]
+
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="1_w26cx"]
+
+[sub_resource type="GDScript" id="GDScript_wtshq"]
+script/source = "extends Control
+
+@export var display_text: String = \"Default Text\"
+
+@onready var label_node = $PanelContainer/MarginContainer/HBoxContainer/Label
+@onready var lineedit_node = $PanelContainer/MarginContainer/HBoxContainer/MarginContainer/LineEdit
+#@export_enum(\"Danger\") var selected_theme_type: String
+
+func _ready():
+ label_node.text = display_text
+ lineedit_node.placeholder_text = display_text
+"
+
+[node name="InputString" type="Control" unique_id=1236567120]
+custom_minimum_size = Vector2(0, 40)
+layout_mode = 3
+anchor_top = 0.4814815
+anchor_right = 1.0
+anchor_bottom = 0.5185185
+offset_top = 20.0
+offset_bottom = -20.0
+grow_horizontal = 2
+grow_vertical = 2
+script = SubResource("GDScript_wtshq")
+metadata/_edit_use_anchors_ = true
+
+[node name="PanelContainer" type="PanelContainer" parent="." unique_id=382665771]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme = ExtResource("1_w26cx")
+theme_type_variation = &"SolidBackground"
+
+[node name="MarginContainer" type="MarginContainer" parent="PanelContainer" unique_id=169083657]
+layout_mode = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_right = 5
+
+[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/MarginContainer" unique_id=358122007]
+custom_minimum_size = Vector2(0, 40)
+layout_mode = 2
+metadata/_edit_use_anchors_ = true
+
+[node name="Label" type="Label" parent="PanelContainer/MarginContainer/HBoxContainer" unique_id=144539274]
+custom_minimum_size = Vector2(200, 0)
+layout_mode = 2
+text = "ERROR"
+
+[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/MarginContainer/HBoxContainer" unique_id=514760511]
+layout_mode = 2
+size_flags_horizontal = 3
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 0
+theme_override_constants/margin_bottom = 5
+
+[node name="LineEdit" type="LineEdit" parent="PanelContainer/MarginContainer/HBoxContainer/MarginContainer" unique_id=828836954]
+layout_mode = 2
+size_flags_horizontal = 3
+theme = ExtResource("1_w26cx")
+placeholder_text = "ERROR"
+clear_button_enabled = true
diff --git a/src/userinterface/dashv2/partials/input_stringconfirm.tscn b/src/userinterface/dashv2/partials/input_stringconfirm.tscn
new file mode 100644
index 0000000..533849d
--- /dev/null
+++ b/src/userinterface/dashv2/partials/input_stringconfirm.tscn
@@ -0,0 +1,100 @@
+[gd_scene format=3 uid="uid://c314yewjhuk8s"]
+
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="1_c0drg"]
+[ext_resource type="Texture2D" uid="uid://dl0bn4f34xl51" path="res://resources/icons/ui/check.svg" id="2_suobs"]
+
+[sub_resource type="GDScript" id="GDScript_wtshq"]
+script/source = "extends Control
+
+@export var display_text: String = \"Default Text\"
+
+@onready var label_node = $PanelContainer/MarginContainer/HBoxContainer/Label
+@onready var lineedit_node = $PanelContainer/MarginContainer/HBoxContainer/MarginContainer/LineEdit
+#@export_enum(\"Danger\") var selected_theme_type: String
+
+func _ready():
+ label_node.text = display_text
+ lineedit_node.placeholder_text = display_text
+"
+
+[node name="InputString" type="Control" unique_id=1236567120]
+custom_minimum_size = Vector2(0, 40)
+layout_mode = 3
+anchor_top = 0.4814815
+anchor_right = 1.0
+anchor_bottom = 0.5185185
+offset_top = 20.0
+offset_bottom = -20.0
+grow_horizontal = 2
+grow_vertical = 2
+script = SubResource("GDScript_wtshq")
+metadata/_edit_use_anchors_ = true
+
+[node name="PanelContainer" type="PanelContainer" parent="." unique_id=382665771]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme = ExtResource("1_c0drg")
+theme_type_variation = &"SolidBackground"
+
+[node name="MarginContainer" type="MarginContainer" parent="PanelContainer" unique_id=169083657]
+layout_mode = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_right = 5
+
+[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/MarginContainer" unique_id=358122007]
+custom_minimum_size = Vector2(0, 40)
+layout_mode = 2
+metadata/_edit_use_anchors_ = true
+
+[node name="Label" type="Label" parent="PanelContainer/MarginContainer/HBoxContainer" unique_id=144539274]
+custom_minimum_size = Vector2(200, 0)
+layout_mode = 2
+text = "ERROR"
+
+[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/MarginContainer/HBoxContainer" unique_id=514760511]
+layout_mode = 2
+size_flags_horizontal = 3
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 0
+theme_override_constants/margin_bottom = 5
+
+[node name="LineEdit" type="LineEdit" parent="PanelContainer/MarginContainer/HBoxContainer/MarginContainer" unique_id=828836954]
+layout_mode = 2
+size_flags_horizontal = 3
+theme = ExtResource("1_c0drg")
+placeholder_text = "ERROR"
+clear_button_enabled = true
+
+[node name="AspectRatioContainer" type="AspectRatioContainer" parent="PanelContainer/MarginContainer/HBoxContainer" unique_id=197497637]
+custom_minimum_size = Vector2(40, 0)
+layout_mode = 2
+
+[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1583604096]
+layout_mode = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="Button" type="Button" parent="PanelContainer/MarginContainer/HBoxContainer/AspectRatioContainer/MarginContainer" unique_id=1775270283]
+layout_mode = 2
+mouse_default_cursor_shape = 2
+theme = ExtResource("1_c0drg")
+
+[node name="AspectRatioContainer" type="AspectRatioContainer" parent="PanelContainer/MarginContainer/HBoxContainer/AspectRatioContainer/MarginContainer/Button" unique_id=1966080045]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="TextureRect" type="TextureRect" parent="PanelContainer/MarginContainer/HBoxContainer/AspectRatioContainer/MarginContainer/Button/AspectRatioContainer" unique_id=24814137]
+layout_mode = 2
+texture = ExtResource("2_suobs")
+expand_mode = 2
diff --git a/src/userinterface/dashv2/partials/input_stringlist.tscn b/src/userinterface/dashv2/partials/input_stringlist.tscn
new file mode 100644
index 0000000..909388c
--- /dev/null
+++ b/src/userinterface/dashv2/partials/input_stringlist.tscn
@@ -0,0 +1,89 @@
+[gd_scene format=3 uid="uid://bgr4s3s31rfsi"]
+
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="1_1egk5"]
+
+[sub_resource type="GDScript" id="GDScript_wtshq"]
+script/source = "@tool
+extends Control
+
+@export var display_text: String = \"Default Text\"
+
+@onready var open_button = $VBoxContainer/MarginContainer/HBoxContainer/MarginContainer/Open
+@onready var margin_container = $VBoxContainer/MarginContainer2
+@onready var listing_container = $VBoxContainer/MarginContainer2/PanelContainer/VBoxContainer
+@onready var label_container = $VBoxContainer/MarginContainer/HBoxContainer/Label
+
+func _ready():
+ open_button.pressed.connect(_change_state)
+ label_container.text = display_text
+
+func _change_state() -> void:
+ var _state = open_button.button_pressed
+
+ if _state == true:
+ listing_container.visible = true
+ return
+
+ listing_container.visible = false
+ return
+"
+
+[node name="InputDropdown" type="PanelContainer" unique_id=822939208]
+custom_minimum_size = Vector2(0, 40)
+anchors_preset = -1
+anchor_top = 0.4814815
+anchor_right = 1.0
+anchor_bottom = 0.5185185
+grow_vertical = 0
+size_flags_horizontal = 3
+script = SubResource("GDScript_wtshq")
+metadata/_edit_use_anchors_ = true
+
+[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=1064225030]
+layout_mode = 2
+theme_override_constants/separation = 0
+
+[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer" unique_id=169083657]
+layout_mode = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_right = 5
+
+[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/MarginContainer" unique_id=358122007]
+custom_minimum_size = Vector2(0, 40)
+layout_mode = 2
+metadata/_edit_use_anchors_ = true
+
+[node name="Label" type="Label" parent="VBoxContainer/MarginContainer/HBoxContainer" unique_id=144539274]
+custom_minimum_size = Vector2(200, 0)
+layout_mode = 2
+size_flags_horizontal = 3
+text = "Default Text"
+
+[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/MarginContainer/HBoxContainer" unique_id=514760511]
+layout_mode = 2
+size_flags_horizontal = 3
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 0
+theme_override_constants/margin_bottom = 5
+
+[node name="Open" type="Button" parent="VBoxContainer/MarginContainer/HBoxContainer/MarginContainer" unique_id=1808464487]
+custom_minimum_size = Vector2(300, 0)
+layout_mode = 2
+size_flags_horizontal = 10
+theme = ExtResource("1_1egk5")
+toggle_mode = true
+text = "Open"
+
+[node name="MarginContainer2" type="MarginContainer" parent="VBoxContainer" unique_id=2073445125]
+layout_mode = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 0
+
+[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer/MarginContainer2" unique_id=734963898]
+layout_mode = 2
+
+[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/MarginContainer2/PanelContainer" unique_id=1765425757]
+visible = false
+layout_mode = 2
diff --git a/src/userinterface/dashv2/partials/left_nav_container.tscn b/src/userinterface/dashv2/partials/left_nav_container.tscn
new file mode 100644
index 0000000..fbafbeb
--- /dev/null
+++ b/src/userinterface/dashv2/partials/left_nav_container.tscn
@@ -0,0 +1,29 @@
+[gd_scene format=3 uid="uid://dog17wkc4h48c"]
+
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="1_wevnc"]
+
+[node name="LeftNavContainer" type="Control" unique_id=17586745]
+layout_mode = 3
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="HBox" type="HBoxContainer" parent="." unique_id=839834062]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/separation = 10
+
+[node name="Left" type="VBoxContainer" parent="HBox" unique_id=1799305671]
+custom_minimum_size = Vector2(300, 0)
+layout_mode = 2
+
+[node name="Right" type="ScrollContainer" parent="HBox" unique_id=892180341]
+layout_mode = 2
+size_flags_horizontal = 3
+theme = ExtResource("1_wevnc")
diff --git a/src/userinterface/dashv2/partials/nav_button.tscn b/src/userinterface/dashv2/partials/nav_button.tscn
new file mode 100644
index 0000000..7239166
--- /dev/null
+++ b/src/userinterface/dashv2/partials/nav_button.tscn
@@ -0,0 +1,87 @@
+[gd_scene format=3 uid="uid://ccoyv1v4otf1b"]
+
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="1_s6xcj"]
+
+[sub_resource type="GDScript" id="GDScript_q3lw4"]
+resource_name = "export"
+script/source = "@tool
+extends Control
+
+@export var display_text: String = \"Default Text\"
+
+@onready var label_node = $Button/MarginContainer/VBoxContainer/Label
+@onready var icon_node = $Button/MarginContainer/VBoxContainer/TextureRect
+@onready var button_node = $Button
+@export_enum(\"Home\", \"Sessions\", \"Instance\", \"Contacts\", \"Assets\", \"Apps\", \"Settings\", \"Debug\", \"Exit\") var selected_icon: String
+@export_enum(\"Danger\") var selected_theme_type: String
+
+var icon_paths = {
+ \"Home\": \"res://resources/icons/home.svg\",
+ \"Sessions\": \"res://resources/icons/flowchart.svg\",
+ \"Instance\": \"res://resources/icons/world.svg\",
+ \"Contacts\": \"res://resources/icons/contacts.svg\",
+ \"Assets\": \"res://resources/icons/inventory.svg\",
+ \"Apps\": \"res://resources/icons/apps.svg\",
+ \"Settings\": \"res://resources/icons/settings.svg\",
+ \"Debug\": \"res://resources/icons/debug.svg\",
+ \"Exit\": \"res://resources/icons/exit.svg\",
+}
+
+func _ready():
+ label_node.text = display_text
+ if icon_paths.has(selected_icon):
+ icon_node.texture = load(icon_paths[selected_icon])
+ button_node.theme_type_variation = selected_theme_type if selected_theme_type != null else null
+"
+
+[node name="NavButton" type="Control" unique_id=649942124]
+custom_minimum_size = Vector2(200, 50)
+layout_mode = 3
+anchor_left = 0.44791666
+anchor_top = 0.4675926
+anchor_right = 0.5520833
+anchor_bottom = 0.5231481
+offset_bottom = 6.1035156e-05
+grow_horizontal = 2
+grow_vertical = 2
+size_flags_horizontal = 3
+size_flags_vertical = 4
+theme = ExtResource("1_s6xcj")
+script = SubResource("GDScript_q3lw4")
+
+[node name="Button" type="Button" parent="." unique_id=1422381468]
+custom_minimum_size = Vector2(140, 0)
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+mouse_default_cursor_shape = 2
+theme = ExtResource("1_s6xcj")
+toggle_mode = true
+
+[node name="MarginContainer" type="MarginContainer" parent="Button" unique_id=665374152]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="VBoxContainer" type="HBoxContainer" parent="Button/MarginContainer" unique_id=86696220]
+layout_mode = 2
+theme_override_constants/separation = 10
+
+[node name="TextureRect" type="TextureRect" parent="Button/MarginContainer/VBoxContainer" unique_id=1429445374]
+layout_mode = 2
+expand_mode = 2
+
+[node name="Label" type="Label" parent="Button/MarginContainer/VBoxContainer" unique_id=1807295119]
+layout_mode = 2
+text = "Default Text"
+horizontal_alignment = 1
diff --git a/src/userinterface/dashv2/partials/removable_string_listing.tscn b/src/userinterface/dashv2/partials/removable_string_listing.tscn
new file mode 100644
index 0000000..1a66d22
--- /dev/null
+++ b/src/userinterface/dashv2/partials/removable_string_listing.tscn
@@ -0,0 +1,64 @@
+[gd_scene format=3 uid="uid://gopciccm8xx5"]
+
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="1_5ae8h"]
+[ext_resource type="Texture2D" uid="uid://5admxcll28y4" path="res://resources/icons/ui/trash.svg" id="2_5ae8h"]
+
+[sub_resource type="GDScript" id="GDScript_wtshq"]
+script/source = "extends Control
+
+
+#@onready var label_node = $PanelContainer/MarginContainer/HBoxContainer/Label
+#@export_enum(\"Danger\") var selected_theme_type: String
+
+func _ready():
+ return
+"
+
+[node name="RemovableStringListing" type="PanelContainer" unique_id=2057714596]
+custom_minimum_size = Vector2(0, 40)
+anchors_preset = -1
+anchor_top = 0.4814815
+anchor_right = 1.0
+anchor_bottom = 0.5185185
+grow_horizontal = 2
+grow_vertical = 2
+script = SubResource("GDScript_wtshq")
+metadata/_edit_use_anchors_ = true
+
+[node name="MarginContainer" type="MarginContainer" parent="." unique_id=169083657]
+layout_mode = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer" unique_id=2062898268]
+layout_mode = 2
+
+[node name="Label" type="Label" parent="MarginContainer/HBoxContainer" unique_id=769532347]
+layout_mode = 2
+size_flags_horizontal = 3
+text = "This is normal text"
+
+[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/HBoxContainer" unique_id=802951287]
+custom_minimum_size = Vector2(50, 0)
+layout_mode = 2
+
+[node name="Button" type="Button" parent="MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=1639558368]
+layout_mode = 2
+mouse_default_cursor_shape = 2
+theme = ExtResource("1_5ae8h")
+theme_type_variation = &"Danger"
+
+[node name="AspectRatioContainer" type="AspectRatioContainer" parent="MarginContainer/HBoxContainer/AspectRatioContainer/Button" unique_id=1435786467]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="TextureRect" type="TextureRect" parent="MarginContainer/HBoxContainer/AspectRatioContainer/Button/AspectRatioContainer" unique_id=1147780876]
+layout_mode = 2
+texture = ExtResource("2_5ae8h")
+expand_mode = 2
diff --git a/src/userinterface/dashv2/partials/search.tscn b/src/userinterface/dashv2/partials/search.tscn
new file mode 100644
index 0000000..cce1a13
--- /dev/null
+++ b/src/userinterface/dashv2/partials/search.tscn
@@ -0,0 +1,79 @@
+[gd_scene format=3 uid="uid://cyom30b1p54df"]
+
+[ext_resource type="Texture2D" uid="uid://rdp5i1i18jus" path="res://resources/icons/search.svg" id="1_ndgnd"]
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="2_p0vin"]
+
+[sub_resource type="GDScript" id="GDScript_wtshq"]
+script/source = "extends Control
+
+@export var display_text: String = \"Default Text\"
+
+@onready var label_node = $PanelContainer/MarginContainer/HBoxContainer/Label
+@onready var lineedit_node = $PanelContainer/MarginContainer/HBoxContainer/MarginContainer/LineEdit
+#@export_enum(\"Danger\") var selected_theme_type: String
+
+func _ready():
+ label_node.text = display_text
+ lineedit_node.placeholder_text = display_text
+"
+
+[node name="InputString" type="Control" unique_id=1236567120]
+custom_minimum_size = Vector2(0, 40)
+layout_mode = 3
+anchor_top = 0.4814815
+anchor_right = 1.0
+anchor_bottom = 0.5185185
+offset_top = 20.0
+offset_bottom = -20.0
+grow_horizontal = 2
+grow_vertical = 2
+script = SubResource("GDScript_wtshq")
+metadata/_edit_use_anchors_ = true
+
+[node name="PanelContainer" type="PanelContainer" parent="." unique_id=382665771]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="MarginContainer" type="MarginContainer" parent="PanelContainer" unique_id=169083657]
+layout_mode = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_right = 5
+
+[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/MarginContainer" unique_id=358122007]
+custom_minimum_size = Vector2(0, 40)
+layout_mode = 2
+metadata/_edit_use_anchors_ = true
+
+[node name="AspectRatioContainer" type="AspectRatioContainer" parent="PanelContainer/MarginContainer/HBoxContainer" unique_id=1923611684]
+custom_minimum_size = Vector2(30, 0)
+layout_mode = 2
+size_flags_horizontal = 4
+
+[node name="TextureRect" type="TextureRect" parent="PanelContainer/MarginContainer/HBoxContainer/AspectRatioContainer" unique_id=200410735]
+layout_mode = 2
+texture = ExtResource("1_ndgnd")
+expand_mode = 4
+
+[node name="Label" type="Label" parent="PanelContainer/MarginContainer/HBoxContainer" unique_id=144539274]
+visible = false
+layout_mode = 2
+text = "Search"
+
+[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/MarginContainer/HBoxContainer" unique_id=514760511]
+layout_mode = 2
+size_flags_horizontal = 3
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 0
+theme_override_constants/margin_bottom = 5
+
+[node name="LineEdit" type="LineEdit" parent="PanelContainer/MarginContainer/HBoxContainer/MarginContainer" unique_id=828836954]
+layout_mode = 2
+size_flags_horizontal = 3
+theme = ExtResource("2_p0vin")
+placeholder_text = "Search..."
+clear_button_enabled = true
diff --git a/src/userinterface/dashv2/partials/session_listing.tscn b/src/userinterface/dashv2/partials/session_listing.tscn
new file mode 100644
index 0000000..dc75442
--- /dev/null
+++ b/src/userinterface/dashv2/partials/session_listing.tscn
@@ -0,0 +1,65 @@
+[gd_scene format=3 uid="uid://2nh7b6daby5k"]
+
+[ext_resource type="Theme" uid="uid://ckqsvvccivw0x" path="res://resources/themes/default.tres" id="1_q20mg"]
+[ext_resource type="Texture2D" uid="uid://itsm1b042lj4" path="res://resources/icons/1280x720.webp" id="2_q20mg"]
+
+[node name="SessionListing" type="Control" unique_id=1752184822]
+custom_minimum_size = Vector2(300, 235)
+layout_mode = 3
+anchor_left = 0.421875
+anchor_top = 0.3912037
+anchor_right = 0.578125
+anchor_bottom = 0.6087963
+grow_horizontal = 2
+grow_vertical = 2
+size_flags_horizontal = 3
+metadata/_edit_use_anchors_ = true
+
+[node name="Button" type="Button" parent="." unique_id=730960087]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+mouse_default_cursor_shape = 2
+theme = ExtResource("1_q20mg")
+theme_type_variation = &"SessionListing"
+
+[node name="MarginContainer" type="MarginContainer" parent="Button" unique_id=920713370]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/margin_left = 5
+theme_override_constants/margin_top = 5
+theme_override_constants/margin_right = 5
+theme_override_constants/margin_bottom = 5
+
+[node name="VBoxContainer" type="VBoxContainer" parent="Button/MarginContainer" unique_id=811068562]
+layout_mode = 2
+alignment = 1
+
+[node name="AspectRatioContainer" type="AspectRatioContainer" parent="Button/MarginContainer/VBoxContainer" unique_id=1510549408]
+custom_minimum_size = Vector2(0, 164)
+layout_mode = 2
+size_flags_vertical = 3
+ratio = 1.7778
+
+[node name="TextureRect" type="TextureRect" parent="Button/MarginContainer/VBoxContainer/AspectRatioContainer" unique_id=188735628]
+layout_mode = 2
+texture = ExtResource("2_q20mg")
+expand_mode = 2
+
+[node name="Label" type="Label" parent="Button/MarginContainer/VBoxContainer" unique_id=1636360228]
+custom_minimum_size = Vector2(50, 0)
+layout_mode = 2
+size_flags_vertical = 3
+text = "This is a test
+New line and more stuff to make"
+autowrap_mode = 2
+clip_text = true
+text_overrun_behavior = 3
+max_lines_visible = 2
diff --git a/src/userinterface/dashv2/scripts/header.gd b/src/userinterface/dashv2/scripts/header.gd
new file mode 100644
index 0000000..c269aec
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/header.gd
@@ -0,0 +1,34 @@
+# --- License
+# File: /client/src/userinterface/dashv2/scripts/header.gd
+# Project: OpenMinerva
+# Created Date: 07 May 2026
+# Copyright (c) 2026 OpenMinerva
+# License: MIT License
+# Authors: Armored Dragon
+# --- License
+extends Control
+
+@onready var navigation_nodes: Array[Node] = get_node("MarginContainer/HBoxContainer").get_children()
+@onready var header_account_button: Control = get_node("MarginContainer/HBoxContainer/AccountButton")
+@onready var header_account_button_texture = header_account_button.get_node("Button/MarginContainer/HBox/TextureRect")
+@onready var header_account_button_name = header_account_button.get_node("Button/MarginContainer/HBox/VBox/Name")
+@onready var header_account_button_location = header_account_button.get_node("Button/MarginContainer/HBox/VBox/Location")
+
+
+func _ready():
+ Events.connect("dash_active_account_changed", _handle_active_account_changed)
+
+ _setup_header_bar()
+ return
+
+
+func _setup_header_bar():
+ header_account_button.get_node("Button").pressed.connect(Events.emit_signal.bind("dash_switch_tab", "_AccountSelection"))
+ return
+
+
+func _handle_active_account_changed(_account: Dictionary) -> void:
+ GlobalLogger.log("Active account changed: '%s'" % _account.display_name)
+ # TODO: header_account_button_texture
+ header_account_button_name.text = _account.display_name
+ header_account_button_location.text = _account.account_server
diff --git a/src/userinterface/dashv2/scripts/header.gd.uid b/src/userinterface/dashv2/scripts/header.gd.uid
new file mode 100644
index 0000000..92ae523
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/header.gd.uid
@@ -0,0 +1 @@
+uid://bd7a7r2u4cbtf
diff --git a/src/userinterface/dashv2/scripts/master.gd b/src/userinterface/dashv2/scripts/master.gd
new file mode 100644
index 0000000..102ea36
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/master.gd
@@ -0,0 +1,37 @@
+# --- License
+# File: /client/src/userinterface/dashv2/scripts/master.gd
+# Project: OpenMinerva
+# Created Date: 07 May 2026
+# Copyright (c) 2026 OpenMinerva
+# License: MIT License
+# Authors: Armored Dragon
+# --- License
+extends Control
+
+@onready var pages: Array[Node] = get_node("MarginContainer/VBoxContainer/Content/Container").get_children()
+
+
+func _ready():
+ Events.connect("dash_switch_tab", _handle_switch_tab)
+ Events.connect("dash_set_state", _handle_dash_state)
+
+ Events.emit_signal("dash_switch_tab", "Home")
+ return
+
+
+func _handle_switch_tab(tab_name):
+ GlobalLogger.log("Changing dashboard tab to: '%s'" % tab_name)
+ for _index in len(pages):
+ var _target_node = pages[_index]
+
+ if _target_node.name != tab_name:
+ _target_node.visible = false
+ continue
+
+ _target_node.visible = true
+ return
+
+
+func _handle_dash_state(is_open: bool) -> void:
+ GlobalLogger.log("Changing dashboard state: '%s'" % is_open)
+ visible = is_open
diff --git a/src/userinterface/dashv2/scripts/master.gd.uid b/src/userinterface/dashv2/scripts/master.gd.uid
new file mode 100644
index 0000000..33a9531
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/master.gd.uid
@@ -0,0 +1 @@
+uid://ci5jkh01ixats
diff --git a/src/userinterface/dashv2/scripts/navigation.gd b/src/userinterface/dashv2/scripts/navigation.gd
new file mode 100644
index 0000000..ad4a22d
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/navigation.gd
@@ -0,0 +1,40 @@
+# --- License
+# File: /client/src/userinterface/dashv2/scripts/navigation.gd
+# Project: OpenMinerva
+# Created Date: 07 May 2026
+# Copyright (c) 2026 OpenMinerva
+# License: MIT License
+# Authors: Armored Dragon
+# --- License
+
+extends Control
+
+@onready var navigation_nodes: Array[Node] = get_node("MarginContainer/HBoxContainer").get_children()
+
+func _ready():
+ Events.connect("dash_switch_tab", _handle_switch_tab)
+
+ _setup_dashboard_navigation_bar()
+ return
+
+func _setup_dashboard_navigation_bar():
+ for _index in len(navigation_nodes):
+ var _target_node = navigation_nodes[_index]
+ var _target_node_button = _target_node.get_node("Button")
+
+ _target_node_button.pressed.connect(Events.emit_signal.bind("dash_switch_tab", _target_node.name))
+
+ return
+
+func _handle_switch_tab(tab_name):
+ for _index in len(navigation_nodes):
+ var _target_node = navigation_nodes[_index]
+ var _target_node_button = _target_node.get_node("Button")
+
+ if _target_node.name != tab_name:
+ _target_node_button.button_pressed = false
+ continue
+
+ _target_node_button.button_pressed = true
+
+ return
diff --git a/src/userinterface/dashv2/scripts/navigation.gd.uid b/src/userinterface/dashv2/scripts/navigation.gd.uid
new file mode 100644
index 0000000..c6d3582
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/navigation.gd.uid
@@ -0,0 +1 @@
+uid://bkqsi1aebefhj
diff --git a/src/userinterface/dashv2/scripts/pages/account_creation.gd b/src/userinterface/dashv2/scripts/pages/account_creation.gd
new file mode 100644
index 0000000..a99e749
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/account_creation.gd
@@ -0,0 +1,39 @@
+# --- License
+# File: /client/src/userinterface/dashv2/scripts/pages/account_creation.gd
+# Project: OpenMinerva
+# Created Date: 07 May 2026
+# Copyright (c) 2026 OpenMinerva
+# License: MIT License
+# Authors: Armored Dragon
+# --- License
+
+extends Control
+
+@onready var _username_node: Control = get_node("HBoxContainer/VBoxContainer/ScrollContainer/VBoxContainer/Username")
+@onready var _username_lineedit_node: Control = _username_node.get_node("PanelContainer/MarginContainer/HBoxContainer/MarginContainer/LineEdit")
+@onready var _account_server_node: Control = get_node("HBoxContainer/VBoxContainer/ScrollContainer/VBoxContainer/AccountServer")
+@onready var _account_server_lineedit_node: Control = _account_server_node.get_node("PanelContainer/MarginContainer/HBoxContainer/MarginContainer/LineEdit")
+
+@onready var _accept_button: Button = get_node("HBoxContainer/VBoxContainer/Accept/Button")
+
+func _ready():
+ _accept_button.pressed.connect(_create_account)
+ return
+
+func _create_account() -> void:
+ var _username: String = _username_lineedit_node.text
+ var _account_server: String = _account_server_lineedit_node.text
+ var _account_data: Dictionary = {}
+ var _create_account_response: Dictionary = {}
+
+ _account_data.set("display_name", _username)
+ _account_data.set("account_server", _account_server)
+
+ _create_account_response = GlobalAccount.create(_account_data, "oauth")
+
+ # Reset page
+ _username_lineedit_node.text = ""
+ _account_server_lineedit_node.text = ""
+
+ Events.emit_signal("dash_switch_tab", "_AccountSelection")
+ return
\ No newline at end of file
diff --git a/src/userinterface/dashv2/scripts/pages/account_creation.gd.uid b/src/userinterface/dashv2/scripts/pages/account_creation.gd.uid
new file mode 100644
index 0000000..896a881
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/account_creation.gd.uid
@@ -0,0 +1 @@
+uid://b2snjauxtpn22
diff --git a/src/userinterface/dashv2/scripts/pages/account_selection.gd b/src/userinterface/dashv2/scripts/pages/account_selection.gd
new file mode 100644
index 0000000..100dabe
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/account_selection.gd
@@ -0,0 +1,63 @@
+# --- License
+# File: /client/src/userinterface/dashv2/scripts/pages/account_selection.gd
+# Project: OpenMinerva
+# Created Date: 07 May 2026
+# Copyright (c) 2026 OpenMinerva
+# License: MIT License
+# Authors: Armored Dragon
+# --- License
+extends Control
+
+@onready var template_account_listing: PackedScene = preload("res://userinterface/dashv2/partials/account_button_listing.tscn")
+@onready var account_list_container: Control = $"HBoxContainer/VBoxContainer/ScrollContainer/VBoxContainer"
+@onready var create_account_button: Control = $"HBoxContainer/VBoxContainer/NavButton/Button"
+
+
+func _ready():
+ Events.dash_account_list_loaded.connect(_populate_account_list)
+
+ _populate_account_list()
+ create_account_button.pressed.connect(Events.emit_signal.bind("dash_switch_tab", "_AccountCreation"))
+ return
+
+
+func _populate_account_list() -> void:
+ const TEMPLATE_ACCOUNT_NAME_PATH = "HBoxContainer/Button/MarginContainer/HBox/VBox/Name"
+ const TEMPLATE_ACCOUNT_DIRECTORY_PATH = "HBoxContainer/Button/MarginContainer/HBox/VBox/Location"
+ const TEMPLATE_ACCOUNT_PICTURE_PATH = "HBoxContainer/Button/MarginContainer/HBox/TextureRect"
+ const TEMPLATE_ACCOUNT_BUTTON_PATH = "HBoxContainer/Button"
+ const TEMPLATE_ACCOUNT_CONFIGURE_BUTTON_PATH = "HBoxContainer/Configure/Button"
+ const TEMPLATE_ACCOUNT_DELETE_BUTTON_PATH = "HBoxContainer/Delete/Button"
+
+ GlobalLogger.log("Populating account list in '%s'." % name)
+ var _accounts: Array[Dictionary] = GlobalAccount.get_all()
+
+ # Remove existing listings
+ for child: Control in account_list_container.get_children():
+ child.queue_free()
+
+ for _account: Dictionary in _accounts:
+ var _template = template_account_listing.instantiate()
+ var _name_node = _template.get_node(TEMPLATE_ACCOUNT_NAME_PATH)
+ var _location_node = _template.get_node(TEMPLATE_ACCOUNT_DIRECTORY_PATH)
+ var _picture_node = _template.get_node(TEMPLATE_ACCOUNT_PICTURE_PATH)
+ var _button_node = _template.get_node(TEMPLATE_ACCOUNT_BUTTON_PATH)
+ var _configure_node = _template.get_node(TEMPLATE_ACCOUNT_CONFIGURE_BUTTON_PATH)
+ var _delete_node = _template.get_node(TEMPLATE_ACCOUNT_DELETE_BUTTON_PATH)
+
+ # Set display visuals
+ _name_node.text = _account.display_name
+ _location_node.text = _account.account_server
+ # TODO: _picture_node.texture = null
+
+ # Add event listeners
+ _button_node.pressed.connect(GlobalAccount.use.bind(_account.id))
+ # TODO: _configure_node
+ _delete_node.pressed.connect(GlobalAccount.remove.bind(_account.id))
+
+ # Append
+ account_list_container.add_child(_template)
+
+ GlobalLogger.log("Added account '%s' to the list." % _account.id)
+ continue
+ return
diff --git a/src/userinterface/dashv2/scripts/pages/account_selection.gd.uid b/src/userinterface/dashv2/scripts/pages/account_selection.gd.uid
new file mode 100644
index 0000000..3c56b6d
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/account_selection.gd.uid
@@ -0,0 +1 @@
+uid://dhdqv7d4orjgy
diff --git a/src/userinterface/dashv2/scripts/pages/assets.gd b/src/userinterface/dashv2/scripts/pages/assets.gd
new file mode 100644
index 0000000..5273db7
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/assets.gd
@@ -0,0 +1,21 @@
+# --- License
+# File: /client/src/userinterface/dashv2/scripts/pages/assets.gd
+# Project: OpenMinerva
+# Created Date: 11 May 2026
+# Copyright (c) 2026 OpenMinerva
+# License: MIT License
+# Authors: Armored Dragon
+# --- License
+extends "res://userinterface/dashv2/scripts/pages/left_nav_container.gd"
+
+
+func _ready():
+ super._ready()
+
+ Events.dash_switch_tab.connect(_handle_switch_tab)
+
+ return
+
+
+func _handle_switch_tab(tab_name) -> void:
+ return
diff --git a/src/userinterface/dashv2/scripts/pages/assets.gd.uid b/src/userinterface/dashv2/scripts/pages/assets.gd.uid
new file mode 100644
index 0000000..046e01d
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/assets.gd.uid
@@ -0,0 +1 @@
+uid://2vk6cxto4xw
diff --git a/src/userinterface/dashv2/scripts/pages/exit.gd b/src/userinterface/dashv2/scripts/pages/exit.gd
new file mode 100644
index 0000000..e27e174
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/exit.gd
@@ -0,0 +1,28 @@
+# --- License
+# File: /client/src/userinterface/dashv2/scripts/pages/exit.gd
+# Project: OpenMinerva
+# Created Date: 11 May 2026
+# Copyright (c) 2026 OpenMinerva
+# License: MIT License
+# Authors: Armored Dragon
+# --- License
+extends Node
+
+@onready var cancel_button: Button = get_node("VBoxContainer/HBoxContainer/Cancel")
+@onready var exit_button: Button = get_node("VBoxContainer/HBoxContainer/Exit")
+
+
+func _ready() -> void:
+ cancel_button.pressed.connect(_cancel_exit)
+ exit_button.pressed.connect(_exit)
+ return
+
+
+func _cancel_exit() -> void:
+ Events.emit_signal("dash_switch_tab", "Home")
+ return
+
+
+func _exit() -> void:
+ get_tree().root.propagate_notification(NOTIFICATION_WM_CLOSE_REQUEST)
+ return
diff --git a/src/userinterface/dashv2/scripts/pages/exit.gd.uid b/src/userinterface/dashv2/scripts/pages/exit.gd.uid
new file mode 100644
index 0000000..2d56c8c
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/exit.gd.uid
@@ -0,0 +1 @@
+uid://cah3jpmu1x72b
diff --git a/src/userinterface/dashv2/scripts/pages/home.gd b/src/userinterface/dashv2/scripts/pages/home.gd
new file mode 100644
index 0000000..5aa2350
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/home.gd
@@ -0,0 +1,42 @@
+# --- License
+# File: /client/src/userinterface/dashv2/scripts/pages/home.gd
+# Project: OpenMinerva
+# Created Date: 11 May 2026
+# Copyright (c) 2026 OpenMinerva
+# License: MIT License
+# Authors: Armored Dragon
+# --- License
+extends Control
+
+@onready var active_sessions_container = get_node("HBoxContainer/PanelContainer/MarginContainer/VBoxContainer")
+@onready var template_account_session_listing = preload("res://userinterface/dashv2/partials/home_server_listing.tscn")
+@onready var network_m = get_tree().current_scene.get_node("NetworkManager")
+@onready var scene_m = get_tree().current_scene.get_node("SceneManager")
+
+
+func _ready() -> void:
+ Events.connect("session_joined", _show_joined_sessions)
+ Events.connect("session_left", _show_joined_sessions)
+ _show_joined_sessions()
+
+ return
+
+
+func _show_joined_sessions() -> void:
+ var _sessions = network_m.get_connected_sessions()
+
+ # Remove existing server listings
+ for node in active_sessions_container.get_children():
+ node.queue_free()
+
+ # Add listings to the container
+ for session in _sessions:
+ var _entry = template_account_session_listing.instantiate()
+ var _entry_label = _entry.get_node("MarginContainer/HBoxContainer/VBoxContainer/Label")
+ var _entry_close = _entry.get_node("MarginContainer/HBoxContainer/AspectRatioContainer/Button")
+
+ _entry_label.text = session.id
+ _entry.pressed.connect(scene_m.set_active_session.bind(session.id))
+ _entry_close.pressed.connect(network_m.leave_server.bind(session.id))
+ active_sessions_container.add_child(_entry)
+ return
diff --git a/src/userinterface/dashv2/scripts/pages/home.gd.uid b/src/userinterface/dashv2/scripts/pages/home.gd.uid
new file mode 100644
index 0000000..faa232e
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/home.gd.uid
@@ -0,0 +1 @@
+uid://behsvrk7cf3e3
diff --git a/src/userinterface/dashv2/scripts/pages/instance.gd b/src/userinterface/dashv2/scripts/pages/instance.gd
new file mode 100644
index 0000000..29487a5
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/instance.gd
@@ -0,0 +1,42 @@
+# --- License
+# File: /client/src/userinterface/dashv2/scripts/pages/instance.gd
+# Project: OpenMinerva
+# Created Date: 08 May 2026
+# Copyright (c) 2026 OpenMinerva
+# License: MIT License
+# Authors: Armored Dragon
+# --- License
+
+extends "res://userinterface/dashv2/scripts/pages/left_nav_container.gd"
+@onready var scene_m = get_tree().current_scene.get_node("SceneManager")
+@onready var network_m = get_tree().current_scene.get_node("NetworkManager")
+
+@onready var privacy_settings: Control = get_node("HBox/Right/Hosting/ScrollContainer/VBoxContainer/VBoxContainer/Privacy/PanelContainer/MarginContainer/HBoxContainer/MarginContainer/OptionButton")
+@onready var save_hosting_button = get_node("HBox/Right/Hosting/ScrollContainer/VBoxContainer/Save/Button")
+
+var session_settings: Dictionary = {
+ "privacy": 0
+}
+
+func _ready():
+ super._ready()
+ save_hosting_button.pressed.connect(_save_hosting_settings)
+ return
+
+func _save_hosting_settings() -> void:
+ var _privacy_enum: Enum.PrivacyLevel = Enum.PrivacyLevel.INVITE
+
+ session_settings.set("privacy", privacy_settings.selected)
+
+ _post_update()
+ return
+
+func _post_update() -> void:
+ var _sessions = network_m.get_connected_sessions()
+ # var _current_session = scene_m.active_session
+
+ _sessions[0].set("privacy", session_settings.privacy)
+
+ network_m.update_server(_sessions[0].id, _sessions[0])
+
+ return
diff --git a/src/userinterface/dashv2/scripts/pages/instance.gd.uid b/src/userinterface/dashv2/scripts/pages/instance.gd.uid
new file mode 100644
index 0000000..41af3fc
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/instance.gd.uid
@@ -0,0 +1 @@
+uid://cs3l7uq2q5uvo
diff --git a/src/userinterface/dashv2/scripts/pages/left_nav_container.gd b/src/userinterface/dashv2/scripts/pages/left_nav_container.gd
new file mode 100644
index 0000000..3724adb
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/left_nav_container.gd
@@ -0,0 +1,55 @@
+# --- License
+# File: /client/src/userinterface/dashv2/scripts/pages/left_nav_container.gd
+# Project: OpenMinerva
+# Created Date: 07 May 2026
+# Copyright (c) 2026 OpenMinerva
+# License: MIT License
+# Authors: Armored Dragon
+# --- License
+extends Control
+
+@onready var navigation_nodes: Array[Node] = get_node("HBox/Left").get_children()
+@onready var pages: Array[Node] = get_node("HBox/Right").get_children()
+
+
+func _ready():
+ var _first_navigation_node_name: String = navigation_nodes[0].name
+
+ _setup_navigation()
+ _handle_switch_tab(_first_navigation_node_name)
+ return
+
+
+func _setup_navigation():
+ GlobalLogger.log("Setting up navigation for '%s'" % name)
+ for index in len(navigation_nodes):
+ var _target_node = navigation_nodes[index]
+ var _target_node_button = _target_node.get_node("Button")
+
+ _target_node_button.pressed.connect(_handle_switch_tab.bind(_target_node.name))
+
+ return
+
+
+func _handle_switch_tab(tab_name):
+ GlobalLogger.log("Changing to page '%s' in '%s'" % [tab_name, name])
+
+ for _index in len(navigation_nodes):
+ var _target_node = navigation_nodes[_index]
+ var _target_node_button = _target_node.get_node("Button")
+
+ if _target_node.name != tab_name:
+ _target_node_button.button_pressed = false
+ continue
+
+ _target_node_button.button_pressed = true
+
+ for _index in len(pages):
+ var _target_node = pages[_index]
+
+ if _target_node.name != tab_name:
+ _target_node.visible = false
+ continue
+
+ _target_node.visible = true
+ return
diff --git a/src/userinterface/dashv2/scripts/pages/left_nav_container.gd.uid b/src/userinterface/dashv2/scripts/pages/left_nav_container.gd.uid
new file mode 100644
index 0000000..3d6dc3a
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/left_nav_container.gd.uid
@@ -0,0 +1 @@
+uid://t575b8ljyeap
diff --git a/src/userinterface/dashv2/scripts/pages/sessions.gd b/src/userinterface/dashv2/scripts/pages/sessions.gd
new file mode 100644
index 0000000..165fca0
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/sessions.gd
@@ -0,0 +1,104 @@
+# --- License
+# File: /client/src/userinterface/dashv2/scripts/pages/sessions.gd
+# Project: OpenMinerva
+# Created Date: 08 May 2026
+# Copyright (c) 2026 OpenMinerva
+# License: MIT License
+# Authors: Armored Dragon
+# --- License
+extends Control
+
+@onready var template_world_listing: PackedScene = preload("res://userinterface/dashv2/partials/session_listing.tscn")
+@onready var world_listing_grid: GridContainer = get_node("HBox/Right/VBoxContainer/ScrollContainer/GridContainer")
+@onready var tag_nodes: Array[Node] = get_node("HBox/Left").get_children()
+@onready var network_m = get_tree().current_scene.get_node("NetworkManager")
+
+
+func _ready():
+ Events.connect("dash_switch_tab", _handle_switch_tab)
+
+ _setup_navigation()
+ return
+
+
+func _handle_switch_tab(tab_name) -> void:
+ if tab_name != "Sessions":
+ return
+
+ GlobalLogger.log("Triggered in Sessions!")
+ # TODO: Make a more robust active_account detection mechanism.
+ if GlobalAccount.active_account == { }:
+ return
+
+ # TODO: Check if we need to authenticate, if so
+ for _session_server in SettingsManager.get_session_servers():
+ await SessionQuery.authenticate(_session_server.url)
+
+ # Get a list of all sessions from our saved sessions_list
+ var session_list = await SessionQuery.get_sessions()
+
+ # Remove all entries in the list
+ _remove_all_listings()
+
+ # In our flat array, add all sessions to the view
+ for session in session_list:
+ _insert_world_into_session_listing(session)
+ return
+
+
+func _remove_all_listings() -> void:
+ for _session_listing in world_listing_grid.get_children():
+ _session_listing.queue_free()
+
+ GlobalLogger.log("Removed all listings from the session list.")
+ return
+
+
+func _insert_world_into_session_listing(session: Dictionary) -> void:
+ var _world = template_world_listing.instantiate()
+ var _world_title = _world.get_node("Button/MarginContainer/VBoxContainer/Label")
+ var _world_thumbnail = _world.get_node("Button/MarginContainer/VBoxContainer/AspectRatioContainer/TextureRect")
+ var _button = _world.get_node("Button")
+
+ _world_title.text = session.get("sessionName", "Unknown session name.")
+ _world_thumbnail.set_texture(load(session.get("sessionThumbnail", "res://resources/icons/1280x720.webp")))
+
+ _button.pressed.connect(network_m.join_server.bind(session.url, session.port))
+
+ world_listing_grid.add_child(_world)
+ return
+
+
+func _setup_navigation():
+ GlobalLogger.log("Setting up navigation for '%s'" % name)
+ for index in len(tag_nodes):
+ var _target_node = tag_nodes[index]
+ var _target_node_button = _target_node.get_node("Button")
+
+ _target_node_button.pressed.connect(_handle_filter_selection.bind(_target_node.name))
+
+ return
+
+
+func _handle_filter_selection(tab_name):
+ for _index in len(tag_nodes):
+ var _target_node = tag_nodes[_index]
+ var _target_node_button = _target_node.get_node("Button")
+
+ if _target_node.name != tab_name:
+ _target_node_button.button_pressed = false
+ continue
+
+ # NOTE: By the time we have the filter button clicked, it is registered as not pressed.
+ # At this point, if our target node is registered as disabled, it is actually enabled.
+ # The desired result is to disable the selected filter button.
+ if _target_node_button.button_pressed == false:
+ GlobalLogger.log("Disable filtering results '%s' in '%s'" % [tab_name, name])
+ _target_node_button.button_pressed = false
+ continue
+
+ GlobalLogger.log("Filtering results to '%s' in '%s'" % [tab_name, name])
+ _target_node_button.button_pressed = true
+ continue
+
+ return
diff --git a/src/userinterface/dashv2/scripts/pages/sessions.gd.uid b/src/userinterface/dashv2/scripts/pages/sessions.gd.uid
new file mode 100644
index 0000000..e8f82c5
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/sessions.gd.uid
@@ -0,0 +1 @@
+uid://g1gvftyku5mb
diff --git a/src/userinterface/dashv2/scripts/pages/settings.gd b/src/userinterface/dashv2/scripts/pages/settings.gd
new file mode 100644
index 0000000..8681c27
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/settings.gd
@@ -0,0 +1,59 @@
+# --- License
+# File: /client/src/userinterface/dashv2/scripts/pages/settings.gd
+# Project: OpenMinerva
+# Created Date: 07 May 2026
+# Copyright (c) 2026 OpenMinerva
+# License: MIT License
+# Authors: Armored Dragon
+# --- License
+extends "res://userinterface/dashv2/scripts/pages/left_nav_container.gd"
+
+@onready var _session_server_list_container = get_node("HBox/Right/Config/InputDropdown/VBoxContainer/MarginContainer2/PanelContainer/VBoxContainer/VBoxContainer")
+@onready var _templates_session_server_listing = preload("res://userinterface/dashv2/partials/removable_string_listing.tscn")
+@onready var _add_session_server_button = get_node("HBox/Right/Config/InputDropdown/VBoxContainer/MarginContainer2/PanelContainer/VBoxContainer/InputString/PanelContainer/MarginContainer/HBoxContainer/AspectRatioContainer/MarginContainer/Button")
+
+
+func _ready():
+ super._ready()
+
+ Events.dash_switch_tab.connect(_handle_page_opened)
+ Events.dash_settings_updated.connect(_load_session_servers)
+ _add_session_server_button.pressed.connect(_add_session_server)
+
+ return
+
+
+func _handle_page_opened(page_name) -> void:
+ if page_name != "Settings":
+ return
+ _load_session_servers()
+ return
+
+
+func _load_session_servers() -> void:
+ GlobalLogger.log("Loading session servers.")
+ const _LABEL_PATH = "MarginContainer/HBoxContainer/Label"
+ const _REMOVE_BUTTON_PATH = "MarginContainer/HBoxContainer/AspectRatioContainer/Button"
+
+ var _servers = SettingsManager.get_session_servers()
+ for _existing_listing in _session_server_list_container.get_children():
+ _existing_listing.queue_free()
+
+ for server in _servers:
+ var _template = _templates_session_server_listing.instantiate()
+ _template.get_node(_LABEL_PATH).text = server.url
+ _template.get_node(_REMOVE_BUTTON_PATH).pressed.connect(_remove_session_server.bind(server.url))
+ _session_server_list_container.add_child(_template)
+ return
+
+
+func _add_session_server() -> void:
+ var _session_server_input_field = get_node("HBox/Right/Config/InputDropdown/VBoxContainer/MarginContainer2/PanelContainer/VBoxContainer/InputString/PanelContainer/MarginContainer/HBoxContainer/MarginContainer/LineEdit")
+ SettingsManager.add_session_server(_session_server_input_field.text)
+ _session_server_input_field.text = ""
+ return
+
+
+func _remove_session_server(server_url: String) -> void:
+ SettingsManager.remove_session_server(server_url)
+ return
diff --git a/src/userinterface/dashv2/scripts/pages/settings.gd.uid b/src/userinterface/dashv2/scripts/pages/settings.gd.uid
new file mode 100644
index 0000000..f6eb91c
--- /dev/null
+++ b/src/userinterface/dashv2/scripts/pages/settings.gd.uid
@@ -0,0 +1 @@
+uid://ba1v2y41s8drb
diff --git a/src/userinterface/dashv2/shaders/blur.gdshader b/src/userinterface/dashv2/shaders/blur.gdshader
new file mode 100644
index 0000000..42f3964
--- /dev/null
+++ b/src/userinterface/dashv2/shaders/blur.gdshader
@@ -0,0 +1,29 @@
+shader_type canvas_item;
+
+uniform sampler2D t0 : hint_screen_texture;
+uniform vec2 blur_size = vec2(.5, .5);
+
+void fragment() {
+ vec2 size = vec2(textureSize(t0, 0));
+
+ float uv_x = float(SCREEN_UV.x) * size.x;
+ float uv_y = float(SCREEN_UV.y) * size.y;
+
+ vec4 sum = vec4(0.0);
+ for (int n = 0; n < 9; ++n) {
+ uv_y = float(SCREEN_UV.y) * size.y + (blur_size.y * (float(n) - 4.5));
+ vec4 h_sum = vec4(0.0);
+ h_sum += texelFetch(t0, ivec2(int(uv_x) - int(4.0 * blur_size.x), int(uv_y)), 0);
+ h_sum += texelFetch(t0, ivec2(int(uv_x) - int(3.0 * blur_size.x), int(uv_y)), 0);
+ h_sum += texelFetch(t0, ivec2(int(uv_x) - int(2.0 * blur_size.x), int(uv_y)), 0);
+ h_sum += texelFetch(t0, ivec2(int(uv_x) - int(blur_size.x), int(uv_y)), 0);
+ h_sum += texelFetch(t0, ivec2(int(uv_x), int(uv_y)), 0);
+ h_sum += texelFetch(t0, ivec2(int(uv_x) + int(blur_size.x), int(uv_y)), 0);
+ h_sum += texelFetch(t0, ivec2(int(uv_x) + int(2.0 * blur_size.x), int(uv_y)), 0);
+ h_sum += texelFetch(t0, ivec2(int(uv_x) + int(3.0 * blur_size.x), int(uv_y)), 0);
+ h_sum += texelFetch(t0, ivec2(int(uv_x) + int(4.0 * blur_size.x), int(uv_y)), 0);
+ sum += h_sum / 9.0;
+ }
+
+ COLOR = sum / 9.0;
+}
diff --git a/src/userinterface/dashv2/shaders/blur.gdshader.uid b/src/userinterface/dashv2/shaders/blur.gdshader.uid
new file mode 100644
index 0000000..3e24681
--- /dev/null
+++ b/src/userinterface/dashv2/shaders/blur.gdshader.uid
@@ -0,0 +1 @@
+uid://bwr4b0mhgi4w6
diff --git a/src/userinterface/session_query.gd b/src/userinterface/session_query.gd
index 9b3cdd1..a4fc352 100644
--- a/src/userinterface/session_query.gd
+++ b/src/userinterface/session_query.gd
@@ -6,25 +6,25 @@
# License: MIT License
# Authors: Armored Dragon
# --- License
-
extends Node
+
func authenticate(url: String) -> Dictionary:
- var _return_dict: Dictionary = {"ok": false, "error": ""}
+ var _return_dict: Dictionary = { "ok": false, "error": "" }
# TODO: Do we need a new authentication key?
if GlobalAccount.dev_session_server_api_key == "":
var url_deconstructed = UrlParser.deconstruct(url)
if url_deconstructed.ok == false:
var ERROR_MESSAGE = "Failed to deconstruct the url '%s'" % url
- GlobalLogger.logs(ERROR_MESSAGE, Enum.LogLevel.WARNING)
+ GlobalLogger.log(ERROR_MESSAGE, Enum.LogLevel.WARNING)
_return_dict.error = ERROR_MESSAGE
return _return_dict
url_deconstructed = url_deconstructed.data
var body: Dictionary = {
"id_token": GlobalAccount.active_account.id_token,
- "challenge": "challenge value"
+ "challenge": "challenge value",
}
var authentication_response = await HTTP.req(HTTPClient.Method.METHOD_POST, url_deconstructed.host, "/api/v1/getAuthenticationKey", url_deconstructed.port, ["Accept: application/json", "Content-Type: application/json"], JSON.stringify(body))
@@ -40,6 +40,7 @@ func authenticate(url: String) -> Dictionary:
return _return_dict
+
func get_sessions() -> Array:
var _return_arr = []
var _session_servers = SettingsManager.get_session_servers()
@@ -50,7 +51,7 @@ func get_sessions() -> Array:
var url_deconstructed = UrlParser.deconstruct(server.url)
if url_deconstructed.ok == false:
- GlobalLogger.logs("Failed to parse the session server URL.", Enum.LogLevel.INFO)
+ GlobalLogger.log("Failed to parse the session server URL.", Enum.LogLevel.INFO)
continue
url_deconstructed = url_deconstructed.data
@@ -68,8 +69,9 @@ func get_sessions() -> Array:
return _return_arr
+
func _session_request_received(_host: String, response: Dictionary) -> Dictionary:
- var _return_arr = {"ok": false, "error": "", "data": null}
+ var _return_arr = { "ok": false, "error": "", "data": null }
# TODO: If response.ok
# TODO: Validate is valid JSON
@@ -81,8 +83,9 @@ func _session_request_received(_host: String, response: Dictionary) -> Dictionar
return _return_arr
+
func _authentication_request_received(_host: String, response: Dictionary) -> Dictionary:
- var _return_arr = {"ok": false, "error": "", "data": null}
+ var _return_arr = { "ok": false, "error": "", "data": null }
# TODO: If response.ok
# TODO: Validate is valid JSON