summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--byte_stream.gd72
-rw-r--r--client.gd9
-rw-r--r--client.tscn19
-rw-r--r--cursor.gd37
-rw-r--r--cursor.tscn6
-rw-r--r--extractor/action.gd222
-rw-r--r--extractor/grf.gd12
-rw-r--r--extractor/sprite.gd204
-rw-r--r--extractor/version.gd15
-rw-r--r--login.gd9
-rw-r--r--login.tscn13
-rw-r--r--network/network.gd2
-rw-r--r--project.godot1
14 files changed, 615 insertions, 9 deletions
diff --git a/.gitignore b/.gitignore
index 82eea3b..669284d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,6 @@
/data/*.grf
/data/extracted/
+/data/BGM/
+
+/extractor/test/
diff --git a/byte_stream.gd b/byte_stream.gd
new file mode 100644
index 0000000..df55a7d
--- /dev/null
+++ b/byte_stream.gd
@@ -0,0 +1,72 @@
+class_name ByteStream
+
+
+var bytes: PackedByteArray
+
+var position: int = 0
+
+
+@warning_ignore("shadowed_variable")
+static func from_bytes(bytes: PackedByteArray):
+ var byte_stream = ByteStream.new()
+
+ byte_stream.bytes = bytes
+
+ return byte_stream
+
+
+@warning_ignore("shadowed_variable")
+func seek(position: int):
+ if position > 0:
+ assert(position < bytes.size())
+
+ self.position = position
+
+
+func decode_u8():
+ var result = bytes.decode_u8(position)
+ seek(position + 1)
+
+ return result
+
+func decode_u16():
+ var result = bytes.decode_u16(position)
+ seek(position + 2)
+
+ return result
+
+func decode_u32():
+ var result = bytes.decode_u32(position)
+ seek(position + 4)
+
+ return result
+
+func decode_u64():
+ var result = bytes.decode_u64(position)
+ seek(position + 8)
+
+ return result
+
+func decode_s8():
+ var result = bytes.decode_s8(position)
+ seek(position + 1)
+
+ return result
+
+func decode_s16():
+ var result = bytes.decode_s16(position)
+ seek(position + 2)
+
+ return result
+
+func decode_s32():
+ var result = bytes.decode_s32(position)
+ seek(position + 4)
+
+ return result
+
+func decode_s64():
+ var result = bytes.decode_s64(position)
+ seek(position + 8)
+
+ return result
diff --git a/client.gd b/client.gd
new file mode 100644
index 0000000..a66cfaf
--- /dev/null
+++ b/client.gd
@@ -0,0 +1,9 @@
+extends Node
+
+
+func _ready() -> void:
+ #var grf = GRF.open("res://data/data.grf")
+ #grf.extract("user://data")
+
+ #Sprite.from_bytes(FileAccess.get_file_as_bytes("res://data/extracted/data/sprite/cursors.spr"))
+ ActionFormat.from_bytes(FileAccess.get_file_as_bytes("res://data/extracted/data/sprite/cursors.act"))
diff --git a/client.tscn b/client.tscn
new file mode 100644
index 0000000..fdc2b75
--- /dev/null
+++ b/client.tscn
@@ -0,0 +1,19 @@
+[gd_scene load_steps=11 format=3 uid="uid://cuylx656oarpy"]
+
+[ext_resource type="Script" path="res://client.gd" id="1_e4txq"]
+[ext_resource type="PackedScene" uid="uid://n0y3fpb8j820" path="res://cursor.tscn" id="2_m3abr"]
+[ext_resource type="Texture2D" uid="uid://dkc1awf1xpl2o" path="res://extractor/test/test-000.png" id="3_0vwpd"]
+[ext_resource type="Texture2D" uid="uid://bx25ptahbg1ve" path="res://extractor/test/test-001.png" id="4_qgfg3"]
+[ext_resource type="Texture2D" uid="uid://cj32t45v42v3a" path="res://extractor/test/test-002.png" id="5_h0rr4"]
+[ext_resource type="Texture2D" uid="uid://boeeuqg0sephn" path="res://extractor/test/test-003.png" id="6_k7dkb"]
+[ext_resource type="Texture2D" uid="uid://m5yp6e4y4dl2" path="res://extractor/test/test-004.png" id="7_lr2su"]
+[ext_resource type="Texture2D" uid="uid://p5h4en0yc8i5" path="res://extractor/test/test-005.png" id="8_vfr4i"]
+[ext_resource type="Texture2D" uid="uid://c5r5lpebvbcmp" path="res://extractor/test/test-007.png" id="9_im4or"]
+[ext_resource type="Texture2D" uid="uid://bw0ad3gkk1api" path="res://extractor/test/test-008.png" id="10_b8x2v"]
+
+[node name="Client" type="Node"]
+script = ExtResource("1_e4txq")
+
+[node name="Cursor" parent="." instance=ExtResource("2_m3abr")]
+arrow_images = Array[Texture2D]([ExtResource("3_0vwpd"), ExtResource("4_qgfg3"), ExtResource("5_h0rr4"), ExtResource("6_k7dkb"), ExtResource("7_lr2su"), ExtResource("8_vfr4i")])
+click_images = Array[Texture2D]([ExtResource("9_im4or"), ExtResource("10_b8x2v")])
diff --git a/cursor.gd b/cursor.gd
new file mode 100644
index 0000000..851441d
--- /dev/null
+++ b/cursor.gd
@@ -0,0 +1,37 @@
+extends Node
+
+
+@export var arrow_images: Array[Texture2D]
+@export_range(1.0, 10.0, 0.1) var arrow_speed := 7.0
+var arrow_idx := 0.0
+
+@export var click_images: Array[Texture2D]
+@export_range(1.0, 10.0, 0.1) var click_speed := 4.0
+var click_idx := 0.0
+
+class CurrentCursor:
+ var images: Array[Texture2D]
+ var speed: float
+ var idx: float
+
+
+func _process(delta: float) -> void:
+ if Input.get_current_cursor_shape() == Input.CURSOR_ARROW:
+ arrow_idx += (delta * arrow_speed)
+ if arrow_idx > arrow_images.size():
+ arrow_idx = 0
+
+ Input.set_custom_mouse_cursor(arrow_images[floor(arrow_idx)], Input.CURSOR_ARROW)
+ elif Input.get_current_cursor_shape() == Input.CURSOR_POINTING_HAND:
+ click_idx += (delta * click_speed)
+ if click_idx > click_images.size():
+ click_idx = 0
+
+ Input.set_custom_mouse_cursor(click_images[floor(click_idx)], Input.CURSOR_POINTING_HAND)
+ else:
+ Input.set_custom_mouse_cursor(null, Input.get_current_cursor_shape())
+
+
+func _input(event: InputEvent) -> void:
+ if event is InputEventMouseButton:
+ pass
diff --git a/cursor.tscn b/cursor.tscn
new file mode 100644
index 0000000..05f6703
--- /dev/null
+++ b/cursor.tscn
@@ -0,0 +1,6 @@
+[gd_scene load_steps=2 format=3 uid="uid://n0y3fpb8j820"]
+
+[ext_resource type="Script" path="res://cursor.gd" id="1_gyqds"]
+
+[node name="Cursor" type="Node"]
+script = ExtResource("1_gyqds")
diff --git a/extractor/action.gd b/extractor/action.gd
new file mode 100644
index 0000000..1865786
--- /dev/null
+++ b/extractor/action.gd
@@ -0,0 +1,222 @@
+class_name ActionFormat
+
+
+## Byte Length: 2 [br]
+## SP
+var signature: String = "AC"
+
+## Byte Type: u8 [br]
+## Byte Length: 2
+var version: Version
+
+## Byte Type: u16 [br]
+## Byte Length: 2
+var action_count: int
+
+## Byte Type: u8 [br]
+## Byte Length: 10
+var reserved: PackedByteArray
+
+## Length: [member action_count]
+var actions: Array[Action]
+
+## Byte Type: u16 [br]
+## Byte Length: 2
+var event_count: int
+
+## Length: [member event_count]
+var events: Array[Event]
+
+## Byte Type: f32 [br]
+## Byte Length: 4
+var frame_times: float
+
+
+func get_byte_length() -> int:
+ var length := 22
+
+ for action in actions:
+ length += action.get_byte_length()
+
+ length += Event.BYTE_LENGTH * event_count
+
+ return length
+
+
+static func from_bytes(bytes: PackedByteArray):
+ var action = ActionFormat.new()
+
+ @warning_ignore("shadowed_variable")
+ var version = Version.new()
+ version.minor = bytes.decode_u8(2)
+ version.major = bytes.decode_u8(3)
+ action.version = version
+
+ print(version)
+
+ action.action_count = bytes.decode_u16(4)
+ action.reserved = bytes.slice(6, 6 + 10)
+
+ # TODO
+ action.actions = [] as Array[Action]
+
+ action.event_count = 0
+
+ action.frame_times = 0.0
+
+ print(inst_to_dict(action))
+
+ return action
+
+
+class Action:
+ ## Byte Type: u32 [br]
+ ## Byte Length: 4
+ var motion_count: int
+
+ ## Length: [member motion_count]
+ var motions: Array[Motion]
+
+
+ func get_byte_length() -> int:
+ var length := 4
+ for motion in motions:
+ length += motion.get_byte_length()
+
+ return length
+
+
+class Motion:
+ ## Byte Type: u8 [br]
+ ## Byte Length: 32
+ var unused: PackedByteArray
+
+ ## Byte Type: u32 [br]
+ ## Byte Length: 4
+ var sprite_layer_count: int
+
+ ## Length: [member sprite_layer_count]
+ var sprite_layers: Array[SpriteLayer]
+
+ ## Byte Type: i32 [br]
+ ## Byte Length: 4
+ var event_id: int
+
+ ## Byte Type: u32 [br]
+ ## Byte Length: 4
+ var sprite_anchor_count: int
+
+ ## Length: [member sprite_anchor_count]
+ var sprite_anchors: Array[SpriteAnchor]
+
+
+ func get_byte_length() -> int:
+ return 44 + SpriteLayer.BYTE_LENGTH * sprite_layer_count + SpriteAnchor.BYTE_LENGTH * sprite_anchor_count
+
+
+class SpriteLayer:
+ const BYTE_LENGTH := 48
+
+ ## Byte Type: i32 [br]
+ ## Byte Length: 4
+ var position_u: int
+
+ ## Byte Type: i32 [br]
+ ## Byte Length: 4
+ var position_v: int
+
+ ## Byte Type: i32 [br]
+ ## Byte Length: 4
+ var sprite_index: int
+
+ ## Byte Type: u32 [br]
+ ## Byte Length: 4
+ var is_flipped_vertical: int
+
+ ## Byte Type: u8 [br]
+ ## Byte Length: 1
+ var color_r: int
+
+ ## Byte Type: u8 [br]
+ ## Byte Length: 1
+ var color_g: int
+
+ ## Byte Type: u8 [br]
+ ## Byte Length: 1
+ var color_b: int
+
+ ## Byte Type: u8 [br]
+ ## Byte Length: 1
+ var color_a: int
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var scale_u: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var scale_v: float
+
+ ## Byte Type: i32 [br]
+ ## Byte Length: 4
+ var rotation_degrees: int
+
+ ## Byte Type: u32 [br]
+ ## Byte Length: 4
+ var sprite_type: int
+
+ ## Byte Type: u32 [br]
+ ## Byte Length: 4
+ var sprite_width: int
+
+ ## Byte Type: u32 [br]
+ ## Byte Length: 4
+ var sprite_height: int
+
+
+ func get_position() -> Vector2:
+ return Vector2(position_u, position_v)
+
+
+ func get_color() -> Color:
+ return Color8(color_r, color_g, color_b, color_a)
+
+
+ func get_scale() -> Vector2:
+ return Vector2(scale_u, scale_v)
+
+
+ func get_size() -> Vector2:
+ return Vector2(sprite_width, sprite_height)
+
+
+class SpriteAnchor:
+ const BYTE_LENGTH := 16
+
+ ## Byte Type: u8 [br]
+ ## Byte Length: 4
+ var unused: PackedByteArray
+
+ ## Byte Type: i32 [br]
+ ## Byte Length: 4
+ var position_u: int
+
+ ## Byte Type: i32 [br]
+ ## Byte Length: 4
+ var position_v: int
+
+ ## Byte Type: u32 [br]
+ ## Byte Length: 4
+ var flag: int
+
+
+ func get_position() -> Vector2:
+ return Vector2(position_u, position_v)
+
+
+class Event:
+ const BYTE_LENGTH := 40
+
+ ## Byte Type: u8 [br]
+ ## Byte Length: 40
+ var name: String
diff --git a/extractor/grf.gd b/extractor/grf.gd
index 1e17264..3739c8c 100644
--- a/extractor/grf.gd
+++ b/extractor/grf.gd
@@ -9,7 +9,7 @@ class Header:
## Byte Length: 15
## Master of Magic
- var signature: String
+ var signature: String = "Master of Magic"
## Byte Length: 15
var encryption: PackedByteArray
@@ -138,6 +138,7 @@ class FileEntry:
return contents
+ @warning_ignore("shadowed_variable")
static func from_bytes_with_filename(bytes: PackedByteArray, file_name: String):
var file_entry = FileEntry.new()
@@ -188,12 +189,15 @@ static func open(path: String):
return grf
-func write():
+func extract(destination: String = "res://data"):
for file_entry in file_entries:
var file_path: String = file_entry.get_file_path()
- var base_directory = DirAccess.open("res://data")
+ var base_directory = DirAccess.open(destination)
base_directory.make_dir_recursive("extracted/" + file_path.get_base_dir())
- var file = FileAccess.open("res://data/extracted/%s" % [file_path], FileAccess.WRITE_READ)
+ var file = FileAccess.open("%s/extracted/%s" % [destination, file_path], FileAccess.WRITE_READ)
file.store_buffer(file_entry.get_contents(file_access))
+
+ # TODO: write pngs for sprites (and .tres files maybe if necessary)
+ # TODO: (also maybe write .tres files for action data files(whatever they are))
diff --git a/extractor/sprite.gd b/extractor/sprite.gd
new file mode 100644
index 0000000..410ce07
--- /dev/null
+++ b/extractor/sprite.gd
@@ -0,0 +1,204 @@
+class_name Sprite
+
+
+## Byte Length: 2 [br]
+## SP
+var signature: String = "SP"
+
+## Byte Type: u8 [br]
+## Byte Length: 2
+var version: Version
+
+## Byte Type: u16 [br]
+## Byte Length: 2
+var palette_image_count: int
+
+## Byte Type: u16 [br]
+## Byte Length: 2
+var rgba_image_count: int
+
+## Length: [member palette_image_count]
+var palette_image_data: Array[PaletteImageData]
+
+## Byte Type: u8 [br]
+## Byte Length: [member rgba_image_count]
+var rgba_image_data: Array[RGBAImageData]
+
+## Byte Type: u16 [br]
+## Byte Length: 256 * 4 (rgba u8) [br]
+## The color with palette index 0 can be considered the "background color". [br]
+## It must be cleared manually on load.
+var palette: Array[PaletteColor]
+
+
+static func from_bytes(bytes: PackedByteArray):
+ var sprite = Sprite.new()
+
+ @warning_ignore("shadowed_variable")
+ var version = Version.new()
+ version.minor = bytes.decode_u8(2)
+ version.major = bytes.decode_u8(3)
+ sprite.version = version
+
+ sprite.palette_image_count = bytes.decode_u16(4)
+ sprite.rgba_image_count = bytes.decode_u16(6)
+
+ sprite.palette_image_data = [] as Array[PaletteImageData]
+ var palette_image_offset = 8
+ var processed_palette_images = 0
+ while processed_palette_images < sprite.palette_image_count:
+ var data = PaletteImageData.new()
+ data.width = bytes.decode_u16(palette_image_offset)
+ data.height = bytes.decode_u16(palette_image_offset + 2)
+
+ data.data_size = bytes.decode_u16(palette_image_offset + 4)
+ data.encoded_data = bytes.slice(
+ palette_image_offset + 6,
+ palette_image_offset + 6 + data.data_size
+ )
+
+ data.decode()
+
+ sprite.palette_image_data.append(data)
+ processed_palette_images += 1
+ palette_image_offset += data.get_byte_length()
+
+ sprite.rgba_image_data = [] as Array[RGBAImageData]
+ var rgba_image_offset = palette_image_offset
+ var processed_rgba_images = 0
+ while processed_rgba_images < sprite.rgba_image_count:
+ var data = RGBAImageData.new()
+ data.width = bytes.decode_u16(rgba_image_offset)
+ data.height = bytes.decode_u16(rgba_image_offset + 2)
+
+ data.data = bytes.slice(
+ rgba_image_offset + 4,
+ rgba_image_offset + 4 + (data.width * data.height * 4)
+ )
+
+ sprite.rgba_image_data.append(data)
+ processed_rgba_images += 1
+ rgba_image_offset += data.get_byte_length()
+
+ sprite.palette = [] as Array[PaletteColor]
+ var palette_offset = rgba_image_offset
+ while palette_offset < bytes.size():
+ var color = PaletteColor.new()
+ color.r = bytes.decode_u8(palette_offset)
+ color.g = bytes.decode_u8(palette_offset + 1)
+ color.b = bytes.decode_u8(palette_offset + 2)
+ color.a = bytes.decode_u8(palette_offset + 3)
+ sprite.palette.append(color)
+ palette_offset += 4
+
+ #print(sprite.palette_image_data[0].get_rgba_data(sprite.palette))
+
+ for idx in sprite.palette_image_data.size():
+ var d: PaletteImageData = sprite.palette_image_data[idx]
+ var i = Image.create_from_data(
+ d.width,
+ d.height,
+ false,
+ Image.FORMAT_RGBA8,
+ d.get_rgba_data(sprite.palette)
+ )
+ i.save_png("res://extractor/test/test-" + str(idx).pad_zeros(3) + ".png")
+
+ return sprite
+
+
+class PaletteImageData:
+ ## Byte Type: u16
+ ## Byte Length: 2
+ var width: int
+
+ ## Byte Type: u16
+ ## Byte Length: 2
+ var height: int
+
+ ## Byte Type: u16
+ ## Byte Length: 2
+ var data_size: int
+
+ ## Byte Type: u8
+ ## Byte Length: [member data_size]
+ var encoded_data: PackedByteArray
+
+ var decoded_data: PackedByteArray
+
+
+ func get_byte_length() -> int:
+ return 6 + data_size
+
+
+ func decode():
+ decoded_data = PackedByteArray([])
+
+ var offset = 0
+ while offset < encoded_data.size():
+ var byte = encoded_data.decode_u8(offset)
+ if byte == 0:
+ var length = encoded_data.decode_u8(offset + 1)
+ var padding = PackedByteArray([])
+ padding.resize(length)
+ padding.fill(0)
+ decoded_data.append_array(padding)
+
+ offset += 2
+ else:
+ decoded_data.append(byte)
+ offset += 1
+
+
+ func get_rgba_data(palette: Array[PaletteColor]) -> PackedByteArray:
+ var rgba := PackedByteArray([])
+ var background_color := palette[0]
+
+ for idx in decoded_data:
+ var color := palette[idx]
+ if color == background_color:
+ rgba.append_array(PackedByteArray([0, 0, 0, 0]))
+ else:
+ rgba.append_array(color.to_bytes())
+
+ return rgba
+
+
+class PaletteColor:
+ const BYTE_LENGTH := 4
+
+ var r: int
+ var g: int
+ var b: int
+ var a: int
+
+
+ func to_bytes():
+ return PackedByteArray([r, g, b, 255])
+
+
+class RGBAImageData:
+ ## Byte Type: u16
+ ## Byte Length: 2
+ var width: int
+
+ ## Byte Type: u16
+ ## Byte Length: 2
+ var height: int
+
+ ## Byte Type: u8
+ ## Byte Length: width * height * RGBAPixel.byte_length
+ var data: Array[Pixel]
+
+
+ class Pixel:
+ const BYTE_LENGTH := 4
+
+ var r: int
+ var g: int
+ var b: int
+ var a: int
+
+
+ func get_byte_length() -> int:
+ return width * height * data.size()
diff --git a/extractor/version.gd b/extractor/version.gd
new file mode 100644
index 0000000..679a8f0
--- /dev/null
+++ b/extractor/version.gd
@@ -0,0 +1,15 @@
+class_name Version
+
+
+## Byte Type: u8
+## Byte Length: 1
+var major: int
+
+
+## Byte Type: u8
+## Byte Length: 1
+var minor: int
+
+
+func _to_string() -> String:
+ return "%s.%s" % [major, minor]
diff --git a/login.gd b/login.gd
index 8d8e945..c00e3cf 100644
--- a/login.gd
+++ b/login.gd
@@ -9,16 +9,19 @@ var current_character_information: CharacterInformation
func _ready() -> void:
switch_screen(%Login)
+ $AudioStreamPlayer2.play()
func switch_screen(screen: Node):
for node in get_children():
- node.visible = false
+ if node is Control:
+ node.visible = false
screen.visible = true
func _on_login_pressed() -> void:
+ $AudioStreamPlayer.play()
Network.login_server.login(%Username.text, %Password.text)
account_information = await Network.login_server.logged_in
@@ -29,6 +32,7 @@ func _on_login_pressed() -> void:
for info: CharacterServerInformation in character_server_information:
var select_character_server = Button.new()
+ select_character_server.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
select_character_server.text = info.server_name
select_character_server.pressed.connect(_on_character_server_login_pressed.bind(info))
%CharacterServerList.add_child(select_character_server)
@@ -37,6 +41,7 @@ func _on_login_pressed() -> void:
func _on_character_server_login_pressed(character_server_info: CharacterServerInformation) -> void:
+ $AudioStreamPlayer.play()
Network.character_server = CharacterServer.new(
character_server_info.get_server_ip(),
character_server_info.server_port
@@ -55,6 +60,7 @@ func _on_character_server_login_pressed(character_server_info: CharacterServerIn
for slot_idx in response.character_information.size():
var info: CharacterInformation = response.character_information[slot_idx]
var character = Button.new()
+ character.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
character.text = info.name
character.pressed.connect(func():
current_character_information = info
@@ -66,6 +72,7 @@ func _on_character_server_login_pressed(character_server_info: CharacterServerIn
func _on_character_selected_pressed(slot_idx: int):
+ $AudioStreamPlayer.play()
Network.character_server.select_character(slot_idx)
var packet = await Network.character_server.selected_character
diff --git a/login.tscn b/login.tscn
index 25b8a6d..165d3b0 100644
--- a/login.tscn
+++ b/login.tscn
@@ -1,6 +1,8 @@
-[gd_scene load_steps=2 format=3 uid="uid://dser74lcd3a4g"]
+[gd_scene load_steps=4 format=3 uid="uid://dser74lcd3a4g"]
[ext_resource type="Script" path="res://login.gd" id="1_1m5cv"]
+[ext_resource type="AudioStream" uid="uid://c2xge60t573wc" path="res://data/extracted/data/wav/¹öÆ°¼Ò¸®.wav" id="2_aeqi0"]
+[ext_resource type="AudioStream" uid="uid://br8ujl4uxv14a" path="res://data/BGM/01.mp3" id="3_2nukd"]
[node name="Login" type="Control"]
layout_mode = 3
@@ -13,7 +15,6 @@ script = ExtResource("1_1m5cv")
[node name="Login" type="CenterContainer" parent="."]
unique_name_in_owner = true
-visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
@@ -40,6 +41,7 @@ placeholder_text = "Password"
[node name="Login" type="Button" parent="Login/VBoxContainer"]
layout_mode = 2
+mouse_default_cursor_shape = 2
text = "Login"
[node name="CharacterServer" type="CenterContainer" parent="."]
@@ -58,6 +60,7 @@ layout_mode = 2
[node name="CharacterSelection" type="CenterContainer" parent="."]
unique_name_in_owner = true
+visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
@@ -70,4 +73,10 @@ unique_name_in_owner = true
layout_mode = 2
columns = 5
+[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
+stream = ExtResource("2_aeqi0")
+
+[node name="AudioStreamPlayer2" type="AudioStreamPlayer" parent="."]
+stream = ExtResource("3_2nukd")
+
[connection signal="pressed" from="Login/VBoxContainer/Login" to="." method="_on_login_pressed"]
diff --git a/network/network.gd b/network/network.gd
index 1db3c50..a0b3d1e 100644
--- a/network/network.gd
+++ b/network/network.gd
@@ -8,8 +8,6 @@ static var map_server: MapServer
func _ready() -> void:
login_server = LoginServer.new("127.0.0.1")
-
- var grf = GRF.open("res://data/data.grf")
func _process(_delta: float) -> void:
diff --git a/project.godot b/project.godot
index 6157940..74a299a 100644
--- a/project.godot
+++ b/project.godot
@@ -18,3 +18,4 @@ config/icon="res://icon.svg"
[autoload]
Network="*res://network/network.tscn"
+Client="*res://client.tscn"