summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client.gd26
-rw-r--r--extractor/gnd_format.gd119
-rw-r--r--extractor/rsm_format.gd64
-rw-r--r--extractor/rsw_format.gd93
-rw-r--r--network/network.gd4
-rw-r--r--ui/login.gd5
6 files changed, 280 insertions, 31 deletions
diff --git a/client.gd b/client.gd
index d553d3e..31264a6 100644
--- a/client.gd
+++ b/client.gd
@@ -32,16 +32,22 @@ func _ready() -> void:
#FileAccess.get_file_as_bytes("res://client_data/data/int_land02.gnd")
#)
#)
- #RSWFormat.from_bytes(
- #ByteStream.from_bytes(
- #FileAccess.get_file_as_bytes("res://client_data/data/int_land02.rsw")
- ##FileAccess.get_file_as_bytes("res://client_data/data/pay_dun00.rsw")
- #)
- #)
- RSMFormat.from_bytes(
+ var rsw = RSWFormat.from_bytes(
ByteStream.from_bytes(
- #FileAccess.get_file_as_bytes("res://client_data/data/model/prontera/chair_01.rsm")
- FileAccess.get_file_as_bytes("res://client_data/data/model/izlude/iz_academy.rsm")
- # TODO: find newer version rsm to test
+ #FileAccess.get_file_as_bytes("res://client_data/data/int_land02.rsw")
+ FileAccess.get_file_as_bytes("res://client_data/data/pay_dun00.rsw")
)
)
+ #RSMFormat.from_bytes(
+ #ByteStream.from_bytes(
+ ##FileAccess.get_file_as_bytes("res://client_data/data/model/prontera/chair_01.rsm")
+ #FileAccess.get_file_as_bytes("res://client_data/data/model/izlude/iz_academy.rsm")
+ ## TODO: not parseable
+ ##FileAccess.get_file_as_bytes("res://client_data/data/model/graywolf/bridge_e_01.rsm2")
+ #)
+ #)
+
+ #var scene_root := rsw.convert("pay_dun00", "res://client_data")
+ #var scene := PackedScene.new()
+ #scene.pack(scene_root)
+ #ResourceSaver.save(scene, "res://extractor/test/pay_dun00.tscn")
diff --git a/extractor/gnd_format.gd b/extractor/gnd_format.gd
index ea8d965..65635cf 100644
--- a/extractor/gnd_format.gd
+++ b/extractor/gnd_format.gd
@@ -1,6 +1,9 @@
class_name GNDFormat
+const MAP_TILE_SIZE := 10.0
+
+
## Byte Length: 4 [br]
## GRAT
var signature: String = "GRGN"
@@ -120,6 +123,67 @@ static func from_bytes(bytes: ByteStream) -> GNDFormat:
return gnd_format
+func get_cubes() -> Array:
+ var cubes := []
+ for cube in ground_mesh_cubes:
+ cubes.append({
+ "cube": cube,
+ Vector3(0, 1, 0): {
+ "surface": surfaces[cube.upwards_facing_surface_index],
+ "mesh": surfaces[cube.upwards_facing_surface_index].get_mesh({
+ Vector2(0, 0): Vector3(0, cube.top_left_height, 0),
+ Vector2(1, 0): Vector3(MAP_TILE_SIZE, cube.top_right_height, 0),
+ Vector2(1, 1): Vector3(MAP_TILE_SIZE, cube.bottom_right_height, MAP_TILE_SIZE),
+ Vector2(0, 1): Vector3(0, cube.bottom_left_height, MAP_TILE_SIZE),
+ }),
+ },
+ })
+
+ return cubes
+
+
+func convert(data_path: String) -> GridMap:
+ var grid_map := GridMap.new()
+ grid_map.cell_size = Vector3(GNDFormat.MAP_TILE_SIZE, GNDFormat.MAP_TILE_SIZE, GNDFormat.MAP_TILE_SIZE)
+ grid_map.cell_center_x = false
+ grid_map.cell_center_y = false
+ grid_map.cell_center_z = false
+
+ grid_map.position = Vector3(
+ (width * MAP_TILE_SIZE) / 2.0,
+ 0,
+ -(height * MAP_TILE_SIZE) / 2.0,
+ )
+
+ var library := MeshLibrary.new()
+ grid_map.mesh_library = library
+
+ var cubes := get_cubes()
+
+ for x in width:
+ for y in height:
+ var cube = cubes[x + y * width]
+ for surface_type in [Vector3(0, 1, 0)]:
+ var mesh: ArrayMesh = cube[surface_type].mesh
+ var material := StandardMaterial3D.new()
+ material.albedo_texture = load(
+ "%s/data/texture/%s" % [
+ data_path,
+ texture_paths[cube[surface_type].surface.texture_index]
+ ]
+ )
+
+ mesh.surface_set_material(0, material)
+
+ var id := library.get_last_unused_item_id()
+ library.create_item(id)
+ library.set_item_mesh(id, mesh)
+
+ grid_map.set_cell_item(Vector3(-x, 0, y), id)
+
+ return grid_map
+
+
class LightMapSlice:
## Byte Type: i32 [br]
## Byte Length: 4
@@ -229,6 +293,61 @@ class Surface:
)
+ func get_mesh(vertices: Dictionary[Vector2, Vector3]) -> ArrayMesh:
+ var surface_tool := SurfaceTool.new()
+ surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES)
+
+ var uvs = get_uvs()
+ var color = get_vertex_color()
+
+ var tiles_per_surface := 2 * 2
+
+ surface_tool.add_triangle_fan(
+ PackedVector3Array([
+ vertices[Vector2(0, 0)],
+ vertices[Vector2(1, 0)],
+ vertices[Vector2(1, 1)],
+ ]),
+ PackedVector2Array([
+ uvs[Vector2(0, 0)] * tiles_per_surface,
+ uvs[Vector2(1, 0)] * tiles_per_surface,
+ uvs[Vector2(1, 1)] * tiles_per_surface,
+ ]),
+ PackedColorArray([
+ color, color, color,
+ ])
+ )
+ surface_tool.add_triangle_fan(
+ PackedVector3Array([
+ vertices[Vector2(0, 0)],
+ vertices[Vector2(1, 1)],
+ vertices[Vector2(0, 1)],
+ ]),
+ PackedVector2Array([
+ uvs[Vector2(0, 0)] * tiles_per_surface,
+ uvs[Vector2(1, 1)] * tiles_per_surface,
+ uvs[Vector2(0, 1)] * tiles_per_surface,
+ ]),
+ PackedColorArray([
+ color, color, color,
+ ])
+ )
+
+ return surface_tool.commit()
+
+
+ func get_uv_id() -> String:
+ # TODO: add more data?
+ return (
+ "%d %d %d %d %d %d %d %d" % [
+ u_top_left, v_top_left,
+ u_top_right, v_top_right,
+ u_bottom_right, v_bottom_right,
+ u_bottom_left, v_bottom_left
+ ]
+ ).md5_text()
+
+
static func from_bytes(bytes: ByteStream) -> Surface:
var surface = Surface.new()
diff --git a/extractor/rsm_format.gd b/extractor/rsm_format.gd
index cf83af9..2eccbd2 100644
--- a/extractor/rsm_format.gd
+++ b/extractor/rsm_format.gd
@@ -39,10 +39,12 @@ var texture_count: int
## Length: [member texture_count]
## Byte Length: 40
+## Versions: [<2.3]
var texture_names: Array[String]
## Byte Type: u8
## Byte Length: 40
+## Versions: [<2.2]
var root_node_name: String
## Byte Type: u32 [br]
@@ -90,23 +92,24 @@ static func from_bytes(bytes: ByteStream) -> RSMFormat:
rsm_format.texture_names = [] as Array[String]
for _n in rsm_format.texture_count:
- rsm_format.texture_names.append(bytes.get_string_from_utf8(40))
+ rsm_format.texture_names.append(bytes.get_string_from_ascii(40))
- rsm_format.root_node_name = bytes.get_string_from_utf8(40)
+ if version.lower_than(2, 2):
+ rsm_format.root_node_name = bytes.get_string_from_ascii(40)
if version.higher_than(2, 1): # >= 2.2
rsm_format.root_node_count = bytes.decode_u32()
rsm_format.root_node_names = [] as Array[String]
for _n in rsm_format.root_node_count:
- rsm_format.root_node_names.append(bytes.get_string_from_utf8(40))
+ rsm_format.root_node_names.append(bytes.get_string_from_ascii(40))
rsm_format.node_count = bytes.decode_u32()
rsm_format.nodes = [] as Array[ModelNode]
for _n in rsm_format.node_count:
rsm_format.nodes.append(ModelNode.from_bytes(bytes, version))
- print(inst_to_dict(rsm_format))
+ #print(inst_to_dict(rsm_format))
#print(inst_to_dict(rsm_format.nodes[0].texture_coordinates[0]))
#rsm_format.nodes[0].texture_coordinates.clear()
#print(inst_to_dict(rsm_format.nodes[0].faces[0]))
@@ -115,12 +118,16 @@ static func from_bytes(bytes: ByteStream) -> RSMFormat:
return rsm_format
-func convert() -> Node3D:
- var node := Node3D.new()
- node.name = root_node_name
+func convert(data_path: String) -> Node3D:
+ var root_node := Node3D.new()
+ root_node.name = root_node_name
#node.set_script(load("res://extractor/model.gd"))
- return node
+ for model_node in nodes:
+ var node: Node = model_node.convert(texture_names, data_path)
+ root_node.add_child(node)
+
+ return root_node
class ModelNode:
@@ -245,7 +252,7 @@ class ModelNode:
var node = ModelNode.new()
node.node_name = bytes.get_string_from_utf8(40)
- node.parent_node_name = bytes.get_string_from_utf8(40)
+ node.parent_node_name = bytes.get_string_from_ascii(40)
if version.lower_than(2, 3): # < 2.3
node.texture_count = bytes.decode_u32()
@@ -259,7 +266,7 @@ class ModelNode:
node.texture_names = [] as Array[String]
for _n in node.texture_name_count:
- node.texture_names.append(bytes.get_string_from_utf8(40))
+ node.texture_names.append(bytes.get_string_from_ascii(40))
node.offset_matrix = [] as Array[Vector3]
for _in in 3:
@@ -345,6 +352,43 @@ class ModelNode:
node.textures_keyframes.append(TexturesKeyframe.from_bytes(bytes))
return node
+
+
+ func convert(textures: Array[String], data_path: String):
+ var node := MeshInstance3D.new()
+ node.name = node_name
+
+ node.translate(translation_2)
+
+ if rotation_axis != Vector3.ZERO:
+ node.rotate(rotation_axis, rotation_angle)
+
+ node.scale = scale
+
+ var surface_tool := SurfaceTool.new()
+ surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES)
+
+ var mesh := ArrayMesh.new()
+ for idx in faces.size():
+ var face := faces[idx]
+
+ surface_tool.add_triangle_fan(
+ PackedVector3Array(face.vertex_position_indices.map(func(idx):
+ return vertex_positions[idx])
+ ),
+ PackedVector2Array(face.texture_coordinate_indices.map(func(idx):
+ return texture_coordinates[idx].coordinates)
+ )
+ )
+ surface_tool.commit(mesh)
+
+ var material := StandardMaterial3D.new()
+ material.albedo_texture = load("%s/data/texture/%s" % [data_path, textures[face.texture_index]])
+ mesh.surface_set_material(idx, material)
+
+ node.mesh = mesh
+
+ return node
class TextureCoordinate:
diff --git a/extractor/rsw_format.gd b/extractor/rsw_format.gd
index 831a1cb..e38dad9 100644
--- a/extractor/rsw_format.gd
+++ b/extractor/rsw_format.gd
@@ -117,7 +117,43 @@ func convert(name: String, data_path: String) -> Node3D:
node.set_script(load("res://extractor/map.gd"))
for resource in map_resources:
- if resource is RSWFormat.SpatialAudioSource:
+ if resource is Animated3DModel:
+ var model_file_path := "%s/data/model/%s" % [data_path, resource.model_file]
+ if not FileAccess.file_exists(model_file_path):
+ continue
+
+ var rsm := RSMFormat.from_bytes(ByteStream.from_bytes(FileAccess.get_file_as_bytes(model_file_path)))
+
+ var model_root := Node3D.new()
+ model_root.name = resource.name
+ model_root.position = resource.get_position() * Vector3(-1, 1, 1)
+ model_root.rotate_x(resource.get_rotation().x)
+ model_root.rotate_y(resource.get_rotation().y)
+ model_root.rotate_z(resource.get_rotation().z)
+ model_root.scale = resource.get_scale()
+
+ node.add_child(model_root)
+ model_root.owner = node
+
+ var model := rsm.convert(data_path)
+ model_root.add_child(model)
+ model.owner = node
+ for child in model.get_children():
+ child.owner = node
+
+ elif resource is DynamicLightSource:
+ continue
+ var light := OmniLight3D.new()
+ light.name = resource.name
+ light.position = resource.get_position()
+ light.light_color = resource.get_diffuse_color()
+ light.omni_range = resource.light_range
+
+ node.add_child(light)
+ light.owner = node
+
+ elif resource is SpatialAudioSource:
+ continue
var audio_file_path := "%s/data/wav/%s" % [data_path, resource.audio_file]
if not FileAccess.file_exists(audio_file_path):
continue
@@ -128,13 +164,58 @@ func convert(name: String, data_path: String) -> Node3D:
audio.position = resource.get_position()
audio.volume_linear = resource.volume_gain
audio.max_distance = resource.audio_range
+
node.add_child(audio, true)
audio.owner = node
-
- var surface_tool := SurfaceTool.new()
- for surface: GNDFormat.Surface in gnd.surfaces:
- pass
- #surface_tool.add_vertex()
+
+ elif resource is ParticleEffectEmitter:
+ continue
+ var particles := CPUParticles3D.new()
+ particles.name = resource.name
+ particles.position = resource.get_position()
+
+ node.add_child(particles, true)
+ particles.owner = node
+
+ #var ground := MeshInstance3D.new()
+ #var mesh := ArrayMesh.new()
+ #var surface_tool := SurfaceTool.new()
+ #surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES)
+ #for surface_idx in gnd.surfaces.size():
+ #if surface_idx < 1:
+ #continue
+ #
+ #var surface: GNDFormat.Surface = gnd.surfaces[surface_idx]
+ #
+ #surface_tool.add_triangle_fan(
+ #PackedVector3Array([Vector3(-0.5, -0.5, 0), Vector3(0.5, -0.5, 0), Vector3(-0.5, -0.5, -0.5)]),
+ #PackedVector2Array([surface.get_uvs()[Vector2(0, 0)], surface.get_uvs()[Vector2(1, 0)], surface.get_uvs()[Vector2(0, 1)]]),
+ #PackedColorArray([surface.get_vertex_color(),surface.get_vertex_color(),surface.get_vertex_color()])
+ #)
+ #surface_tool.add_triangle_fan(
+ #PackedVector3Array([Vector3(0.5, -0.5, 0), Vector3(0.5, -0.5, -0.5), Vector3(-0.5, -0.5, -0.5)]),
+ #PackedVector2Array([surface.get_uvs()[Vector2(1, 0)], surface.get_uvs()[Vector2(1, 1)], surface.get_uvs()[Vector2(0, 1)]]),
+ #PackedColorArray([surface.get_vertex_color(),surface.get_vertex_color(),surface.get_vertex_color()])
+ #)
+ #surface_tool.commit(mesh)
+ #var material := StandardMaterial3D.new()
+ #material.albedo_texture = load("%s/data/texture/%s" % [data_path, gnd.texture_paths[surface.texture_index]])
+ #mesh.surface_set_material(0, material)
+ #print(surface.get_uvs())
+ #break
+
+
+ #grid_map.owner = node
+
+ #ground.mesh = mesh
+ #
+ #node.add_child(ground)
+ #ground.owner = node
+
+ var grid_map := gnd.convert(data_path)
+ grid_map.name = gnd_file_path.get_basename()
+ node.add_child(grid_map)
+ grid_map.owner = node
return node
diff --git a/network/network.gd b/network/network.gd
index a0b3d1e..63de38a 100644
--- a/network/network.gd
+++ b/network/network.gd
@@ -6,10 +6,6 @@ static var character_server: CharacterServer
static var map_server: MapServer
-func _ready() -> void:
- login_server = LoginServer.new("127.0.0.1")
-
-
func _process(_delta: float) -> void:
if login_server:
login_server.listen()
diff --git a/ui/login.gd b/ui/login.gd
index fb3c80b..d58d6e8 100644
--- a/ui/login.gd
+++ b/ui/login.gd
@@ -27,6 +27,8 @@ func switch_screen(screen: Node):
func _on_login_pressed() -> void:
$ButtonClickSound.play()
+
+ Network.login_server = LoginServer.new("127.0.0.1")
Network.login_server.login(username.text, password.text)
account_information = await Network.login_server.logged_in
@@ -135,7 +137,8 @@ func _on_character_selected_pressed(slot_idx: int):
var _logged_in = await Network.map_server.logged_in
get_tree().change_scene_to_file(
- "res://client_data/data/%s.tscn" % current_character_information.get_map_name()
+ #"res://client_data/data/%s.tscn" % current_character_information.get_map_name()
+ "res://extractor/test/pay_dun00.tscn"
)