summaryrefslogtreecommitdiff
path: root/extractor/rsw_format.gd
diff options
context:
space:
mode:
authorDaniel Weipert <git@mail.dweipert.de>2024-12-22 18:38:11 +0100
committerDaniel Weipert <git@mail.dweipert.de>2024-12-22 18:38:11 +0100
commit7b3f386449aeab124d84d2aff4c273e646e68763 (patch)
tree9d24a7de247d190edcd8e315fc3e45ab8a4a8d34 /extractor/rsw_format.gd
parentf4e07d090cded56ebab54363f1b47f1ea45c8682 (diff)
next commitHEADmain
Diffstat (limited to 'extractor/rsw_format.gd')
-rw-r--r--extractor/rsw_format.gd519
1 files changed, 519 insertions, 0 deletions
diff --git a/extractor/rsw_format.gd b/extractor/rsw_format.gd
new file mode 100644
index 0000000..18874e2
--- /dev/null
+++ b/extractor/rsw_format.gd
@@ -0,0 +1,519 @@
+class_name RSWFormat
+
+
+## Byte Length: 4 [br]
+## GRAT
+var signature: String = "GRSW"
+
+## Byte Type: u8 [br]
+## Byte Length: 2
+var version: Version
+
+## Byte Type: u8, u32 [br]
+## Byte Length: 1, 4
+## Versions: [2.2, 2.5]
+var build_number: int
+
+## Byte Type: u8 [br]
+## Byte Length: 1
+## Versions: [2.5]
+var unknown_render_flag: int
+
+## Byte Type: u8 [br]
+## Byte Length: 40
+var ini_file: String
+
+## Byte Type: u8 [br]
+## Byte Length: 40
+var gnd_file: String
+
+## Byte Type: u8 [br]
+## Byte Length: 40
+var gat_file: String
+
+## Byte Type: u8 [br]
+## Byte Length: 40
+## Versions: [1.4]
+var source_file: String
+
+var water_configuration: WaterConfiguration
+var lighting_parameters: LightingParameters
+
+## Byte Type: u32 [br]
+## Byte Length: 4
+var map_resource_count: int
+
+## Length: [member map_resource_count]
+var map_resources: Array[MapResource]
+
+var quad_tree
+
+
+static func from_bytes(bytes: ByteStream) -> RSWFormat:
+ var rsw_format = RSWFormat.new()
+
+ bytes.advance(rsw_format.signature.length())
+
+ @warning_ignore("shadowed_variable")
+ var version = Version.new()
+ version.major = bytes.decode_u8()
+ version.minor = bytes.decode_u8()
+ rsw_format.version = version
+
+ if version.major < 2:
+ print(version)
+ return rsw_format
+
+ if version.major >= 2 and version.minor >= 5:
+ rsw_format.build_number = bytes.decode_u32()
+ rsw_format.unknown_render_flag = bytes.decode_u8()
+ elif version.major >= 2 and version.minor >= 2:
+ rsw_format.build_number = bytes.decode_u8()
+
+ rsw_format.ini_file = bytes.get_string_from_utf8(40)
+ rsw_format.gnd_file = bytes.get_string_from_utf8(40)
+ rsw_format.gat_file = bytes.get_string_from_utf8(40)
+ rsw_format.source_file = bytes.get_string_from_utf8(40)
+
+ if version.major >= 2 and version.minor <= 5:
+ rsw_format.water_configuration = WaterConfiguration.from_bytes(bytes)
+
+ rsw_format.lighting_parameters = LightingParameters.from_bytes(bytes)
+
+ bytes.advance(16) # map boundaries - bounding box # TODO
+
+ rsw_format.map_resource_count = bytes.decode_u32()
+ rsw_format.map_resources = [] as Array[MapResource]
+ for _n in rsw_format.map_resource_count:
+ var resource_type = bytes.decode_u32()
+ var resource: MapResource
+
+ if resource_type == MapResourceType.Animated3DModel:
+ resource = Animated3DModel.from_bytes(bytes)
+ elif resource_type == MapResourceType.DynamicLightSource:
+ resource = DynamicLightSource.from_bytes(bytes)
+ elif resource_type == MapResourceType.SpatialAudioSource:
+ resource = SpatialAudioSource.from_bytes(bytes)
+ elif resource_type == MapResourceType.ParticleEffectEmitter:
+ resource = ParticleEffectEmitter.from_bytes(bytes)
+
+ rsw_format.map_resources.append(resource)
+
+ # TODO: quadtree
+
+ #print(inst_to_dict(rsw_format))
+ return rsw_format
+
+
+class WaterConfiguration:
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var water_level: int
+
+ ## Byte Type: i32 [br]
+ ## Byte Length: 4
+ var water_type: int
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var wave_height: int
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var wave_speed: int
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var wave_pitch: int
+
+ ## Byte Type: i32 [br]
+ ## Byte Length: 4
+ var water_animation_speed: int
+
+
+ static func from_bytes(bytes: ByteStream) -> WaterConfiguration:
+ var config = WaterConfiguration.new()
+
+ config.water_level = bytes.decode_float()
+ config.water_type = bytes.decode_u32()
+ config.wave_height = bytes.decode_float()
+ config.wave_speed = bytes.decode_float()
+ config.wave_pitch = bytes.decode_float()
+ config.water_animation_speed = bytes.decode_u32()
+
+ return config
+
+
+class LightingParameters:
+ ## Byte Type: i32 [br]
+ ## Byte Length: 4
+ var longitude: int
+
+ ## Byte Type: i32 [br]
+ ## Byte Length: 4
+ var latitude: int
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var diffuse_color_r: int
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var diffuse_color_g: int
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var diffuse_color_b: int
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var ambient_color_r: int
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var ambient_color_g: int
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var ambient_color_b: int
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ ## Shadow Map Alpha
+ var intensity: int
+
+
+ func get_diffuse_color() -> Color:
+ return Color(diffuse_color_r, diffuse_color_g, diffuse_color_b)
+
+
+ func get_ambient_color() -> Color:
+ return Color(ambient_color_r, ambient_color_g, ambient_color_b)
+
+
+ static func from_bytes(bytes: ByteStream) -> LightingParameters:
+ var params = LightingParameters.new()
+
+ params.longitude = bytes.decode_s32()
+ params.latitude = bytes.decode_s32()
+ params.diffuse_color_r = bytes.decode_float()
+ params.diffuse_color_g = bytes.decode_float()
+ params.diffuse_color_b = bytes.decode_float()
+ params.ambient_color_r = bytes.decode_float()
+ params.ambient_color_g = bytes.decode_float()
+ params.ambient_color_b = bytes.decode_float()
+ params.intensity = bytes.decode_float()
+
+ return params
+
+
+class MapResource:
+ pass
+
+enum MapResourceType {
+ Animated3DModel = 1,
+ DynamicLightSource = 2,
+ SpatialAudioSource = 3,
+ ParticleEffectEmitter = 4,
+}
+
+enum ModelAnimationType {
+ None = 0,
+ Looping = 2,
+}
+
+enum ParticlePresetEffect {
+ None = -1,
+ Hit_1 = 1,
+ Hit_2 = 2,
+ Hit_3 = 3,
+ Torch = 47,
+ TunaParty = 1097,
+}
+
+
+class Animated3DModel extends MapResource:
+ ## Byte Type: u8 [br]
+ ## Byte Length: 40
+ var name: String
+
+ ## Byte Type: u32 [br]
+ ## Byte Length: 4
+ var animation_type: ModelAnimationType
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var animation_speed_percent: float
+
+ ## Byte Type: u32 [br]
+ ## Byte Length: 4
+ var collision_flags: int
+
+ ## Byte Type: u8 [br]
+ ## Byte Length: 80
+ var model_file: String
+
+ ## Byte Type: u8 [br]
+ ## Byte Length: 80
+ var root_node_name: String
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var position_x: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var position_y: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var position_z: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var rotation_x: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var rotation_y: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var rotation_z: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var scale_x: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var scale_y: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var scale_z: float
+
+
+ func get_position() -> Vector3:
+ return Vector3(position_x, position_y, position_z)
+
+
+ func get_rotation() -> Vector3:
+ return Vector3(rotation_x, rotation_y, rotation_z)
+
+
+ func get_scale() -> Vector3:
+ return Vector3(scale_x, scale_y, scale_z)
+
+
+ static func from_bytes(bytes: ByteStream) -> Animated3DModel:
+ var resource = Animated3DModel.new()
+
+ resource.name = bytes.get_string_from_ascii(40)
+ resource.animation_type = bytes.decode_u32()
+ resource.animation_speed_percent = bytes.decode_float()
+ resource.collision_flags = bytes.decode_u32()
+ resource.model_file = bytes.get_string_from_ascii(80)
+ resource.root_node_name = bytes.get_string_from_utf8(80)
+ resource.position_x = bytes.decode_float()
+ resource.position_y = bytes.decode_float()
+ resource.position_z = bytes.decode_float()
+ resource.rotation_x = bytes.decode_float()
+ resource.rotation_y = bytes.decode_float()
+ resource.rotation_z = bytes.decode_float()
+ resource.scale_x = bytes.decode_float()
+ resource.scale_y = bytes.decode_float()
+ resource.scale_z = bytes.decode_float()
+
+ #print(inst_to_dict(resource))
+ return resource
+
+
+class DynamicLightSource extends MapResource:
+ ## Byte Type: u8 [br]
+ ## Byte Length: 80
+ var name: String
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var position_x: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var position_y: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var position_z: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var diffuse_color_r: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var diffuse_color_g: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var diffuse_color_b: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var light_range: float
+
+
+ func get_position() -> Vector3:
+ return Vector3(position_x, position_y, position_z)
+
+
+ func get_diffuse_color() -> Color:
+ return Color(diffuse_color_r, diffuse_color_g, diffuse_color_b)
+
+
+ static func from_bytes(bytes: ByteStream) -> DynamicLightSource:
+ var resource = DynamicLightSource.new()
+
+ resource.name = bytes.get_string_from_ascii(80)
+ resource.position_x = bytes.decode_float()
+ resource.position_y = bytes.decode_float()
+ resource.position_z = bytes.decode_float()
+ resource.diffuse_color_r = bytes.decode_float()
+ resource.diffuse_color_g = bytes.decode_float()
+ resource.diffuse_color_b = bytes.decode_float()
+ resource.light_range = bytes.decode_float()
+
+ #print(inst_to_dict(resource))
+ return resource
+
+
+class SpatialAudioSource extends MapResource:
+ ## Byte Type: u8 [br]
+ ## Byte Length: 80
+ var name: String
+
+ ## Byte Type: u8 [br]
+ ## Byte Length: 80
+ var audio_file: String
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var position_x: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var position_y: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var position_z: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var volume_gain: float
+
+ ## Byte Type: u32 [br]
+ ## Byte Length: 4
+ var width: int
+
+ ## Byte Type: u32 [br]
+ ## Byte Length: 4
+ var height: int
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var audio_range: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var duration: float
+
+
+ func get_position() -> Vector3:
+ return Vector3(position_x, position_y, position_z)
+
+
+ func get_size() -> Vector2:
+ return Vector2(width, height)
+
+
+ static func from_bytes(bytes: ByteStream) -> SpatialAudioSource:
+ var resource = SpatialAudioSource.new()
+
+ resource.name = bytes.get_string_from_ascii(80)
+ resource.audio_file = bytes.get_string_from_ascii(80)
+ resource.position_x = bytes.decode_float()
+ resource.position_y = bytes.decode_float()
+ resource.position_z = bytes.decode_float()
+ resource.volume_gain = bytes.decode_float()
+ resource.width = bytes.decode_u32()
+ resource.height = bytes.decode_u32()
+ resource.audio_range = bytes.decode_float()
+ resource.duration = bytes.decode_float()
+
+ return resource
+
+
+class ParticleEffectEmitter extends MapResource:
+ ## Byte Type: u8 [br]
+ ## Byte Length: 80
+ var name: String
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var position_x: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var position_y: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var position_z: float
+
+ @warning_ignore("enum_variable_without_default")
+ ## Byte Type: u32 [br]
+ ## Byte Length: 4
+ var preset_effect: ParticlePresetEffect
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4 [br]
+ ## in frames; 60 means 1 second
+ var emission_delay: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var launch_parameter_a: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var launch_parameter_b: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var launch_parameter_c: float
+
+ ## Byte Type: f32 [br]
+ ## Byte Length: 4
+ var launch_parameter_d: float
+
+
+ func get_position() -> Vector3:
+ return Vector3(position_x, position_y, position_z)
+
+
+ static func from_bytes(bytes: ByteStream) -> ParticleEffectEmitter:
+ var resource = ParticleEffectEmitter.new()
+
+ resource.name = bytes.get_string_from_ascii(80)
+ resource.position_x = bytes.decode_float()
+ resource.position_y = bytes.decode_float()
+ resource.position_z = bytes.decode_float()
+ resource.preset_effect = bytes.decode_u32()
+ resource.emission_delay = bytes.decode_float()
+ resource.launch_parameter_a = bytes.decode_float()
+ resource.launch_parameter_b = bytes.decode_float()
+ resource.launch_parameter_c = bytes.decode_float()
+ resource.launch_parameter_d = bytes.decode_float()
+
+ return resource