From 7b3f386449aeab124d84d2aff4c273e646e68763 Mon Sep 17 00:00:00 2001 From: Daniel Weipert Date: Sun, 22 Dec 2024 18:38:11 +0100 Subject: next commit --- extractor/rsw_format.gd | 519 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 519 insertions(+) create mode 100644 extractor/rsw_format.gd (limited to 'extractor/rsw_format.gd') 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 -- cgit v1.2.3