├── src ├── fonts │ └── Ubuntu-M.ttf ├── components │ ├── dead.rs │ ├── damage_digits.rs │ ├── night_time_effect.rs │ ├── player_character.rs │ ├── zone.rs │ ├── bank.rs │ ├── passive_recovery_time.rs │ ├── model_height.rs │ ├── item_drop_model.rs │ ├── dummy_bone_offset.rs │ ├── sound_category.rs │ ├── client_entity_name.rs │ ├── position.rs │ ├── vehicle.rs │ ├── vehicle_sound.rs │ ├── npc_model.rs │ ├── facing_direction.rs │ ├── warp_object.rs │ ├── visible_status_effects.rs │ ├── clan_membership.rs │ ├── effect.rs │ ├── event_object.rs │ ├── personal_store.rs │ ├── vehicle_model.rs │ ├── client_entity.rs │ ├── projectile.rs │ ├── character_model_blink_timer.rs │ ├── character_model.rs │ ├── party_info.rs │ ├── pending_damage_list.rs │ ├── clan.rs │ ├── name_tag_entity.rs │ ├── pending_skill_effect_list.rs │ ├── zone_object.rs │ └── collision.rs ├── events │ ├── clan_dialog_event.rs │ ├── party_event.rs │ ├── game_connection_event.rs │ ├── move_destination_effect_event.rs │ ├── client_entity_event.rs │ ├── system_func_event.rs │ ├── login_event.rs │ ├── character_select_event.rs │ ├── use_item_event.rs │ ├── quest_trigger_event.rs │ ├── bank_event.rs │ ├── conversation_dialog_event.rs │ ├── chatbox_event.rs │ ├── message_box_event.rs │ ├── number_input_dialog_event.rs │ ├── npc_store_event.rs │ ├── zone_event.rs │ ├── spawn_projectile_event.rs │ ├── network_event.rs │ ├── world_connection_event.rs │ ├── personal_store_event.rs │ ├── player_command_event.rs │ ├── spawn_effect_event.rs │ ├── hit_event.rs │ └── mod.rs ├── resources │ ├── account.rs │ ├── specular_texture.rs │ ├── login_state.rs │ ├── debug_inspector.rs │ ├── selected_target.rs │ ├── render_configuration.rs │ ├── character_list.rs │ ├── virtual_filesystem.rs │ ├── world_rates.rs │ ├── app_state.rs │ ├── current_zone.rs │ ├── character_select_state.rs │ ├── server_list.rs │ ├── server_configuration.rs │ ├── name_tag_cache.rs │ ├── sound_settings.rs │ ├── world_time.rs │ ├── zone_time.rs │ ├── debug_render.rs │ ├── name_tag_settings.rs │ ├── login_connection.rs │ ├── world_connection.rs │ ├── game_connection.rs │ ├── client_entity_list.rs │ ├── network_thread.rs │ ├── sound_cache.rs │ ├── game_data.rs │ ├── mod.rs │ └── damage_digits_spawner.rs ├── scripting │ ├── quest_function_context.rs │ ├── lua4 │ │ └── mod.rs │ ├── script_function_resources.rs │ ├── mod.rs │ └── script_function_context.rs ├── protocol │ ├── irose │ │ └── mod.rs │ └── mod.rs ├── bundles │ └── mod.rs ├── systems │ ├── world_time_system.rs │ ├── debug_render_collider_system.rs │ ├── zone_viewer_system.rs │ ├── name_tag_update_healthbar_system.rs │ ├── update_position_system.rs │ ├── clan_system.rs │ ├── quest_trigger_system.rs │ ├── cooldown_system.rs │ ├── facing_direction_system.rs │ ├── game_system.rs │ ├── debug_render_skeleton_system.rs │ ├── passive_recovery_system.rs │ ├── directional_light_system.rs │ ├── name_tag_update_color_system.rs │ ├── damage_digit_render_system.rs │ ├── personal_store_model_system.rs │ ├── effect_system.rs │ ├── pending_damage_system.rs │ ├── systemfunc_event_system.rs │ ├── move_destination_effect_system.rs │ ├── debug_render_directional_light_system.rs │ ├── npc_idle_sound_system.rs │ ├── character_model_blink_system.rs │ ├── personal_store_model_add_collider_system.rs │ └── visible_status_effects_system.rs ├── ui │ ├── widgets │ │ ├── radio_box.rs │ │ ├── caption.rs │ │ ├── tab.rs │ │ ├── draw.rs │ │ ├── scrollbox.rs │ │ ├── pane.rs │ │ ├── image.rs │ │ ├── skill.rs │ │ ├── zlistbox.rs │ │ ├── checkbox.rs │ │ ├── editbox.rs │ │ ├── table.rs │ │ └── gauge.rs │ ├── ui_sound_event_system.rs │ ├── ui_debug_diagnostics_system.rs │ ├── dialog_loader.rs │ ├── ui_debug_camera_info_system.rs │ ├── ui_drag_and_drop_system.rs │ ├── ui_respawn_system.rs │ ├── ui_window_sound_system.rs │ ├── ui_debug_entity_inspector_system.rs │ └── ui_character_select_name_tag_system.rs ├── render │ ├── damage_digit_render_data.rs │ ├── shaders │ │ ├── trail_effect.wgsl │ │ ├── sky_material.wgsl │ │ ├── world_ui.wgsl │ │ ├── zone_lighting.wgsl │ │ ├── water_material.wgsl │ │ └── damage_digit.wgsl │ ├── particle_material.rs │ ├── damage_digit_material.rs │ ├── particle_render_data.rs │ └── mod.rs ├── audio │ ├── audio_source.rs │ ├── wav.rs │ └── ogg.rs ├── vfs_asset_io.rs ├── animation │ ├── mod.rs │ └── transform_animation.rs └── exe_resource_loader.rs ├── .gitignore ├── .github └── workflows │ └── build.yml └── README.md /src/fonts/Ubuntu-M.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exjam/rose-offline-client/HEAD/src/fonts/Ubuntu-M.ttf -------------------------------------------------------------------------------- /src/components/dead.rs: -------------------------------------------------------------------------------- 1 | use bevy::{prelude::Component, reflect::Reflect}; 2 | 3 | #[derive(Component, Reflect)] 4 | pub struct Dead; 5 | -------------------------------------------------------------------------------- /src/events/clan_dialog_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Event; 2 | 3 | #[derive(Event)] 4 | pub enum ClanDialogEvent { 5 | Open, 6 | } 7 | -------------------------------------------------------------------------------- /src/components/damage_digits.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Component; 2 | 3 | #[derive(Component)] 4 | pub struct DamageDigits { 5 | pub damage: u32, 6 | } 7 | -------------------------------------------------------------------------------- /src/components/night_time_effect.rs: -------------------------------------------------------------------------------- 1 | use bevy::{prelude::Component, reflect::Reflect}; 2 | 3 | #[derive(Component, Reflect)] 4 | pub struct NightTimeEffect; 5 | -------------------------------------------------------------------------------- /src/components/player_character.rs: -------------------------------------------------------------------------------- 1 | use bevy::{prelude::Component, reflect::Reflect}; 2 | 3 | #[derive(Component, Reflect)] 4 | pub struct PlayerCharacter; 5 | -------------------------------------------------------------------------------- /src/components/zone.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Component; 2 | 3 | use rose_data::ZoneId; 4 | 5 | #[derive(Component)] 6 | pub struct Zone { 7 | pub id: ZoneId, 8 | } 9 | -------------------------------------------------------------------------------- /src/resources/account.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Resource; 2 | 3 | #[derive(Resource)] 4 | pub struct Account { 5 | pub username: String, 6 | pub password: String, 7 | } 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # These are backup files generated by rustfmt 6 | **/*.rs.bk 7 | 8 | .vscode 9 | -------------------------------------------------------------------------------- /src/events/party_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Entity, Event}; 2 | 3 | #[derive(Event)] 4 | pub enum PartyEvent { 5 | InvitedCreate(Entity), 6 | InvitedJoin(Entity), 7 | } 8 | -------------------------------------------------------------------------------- /src/components/bank.rs: -------------------------------------------------------------------------------- 1 | use bevy::ecs::prelude::Component; 2 | 3 | use rose_data::Item; 4 | 5 | #[derive(Component)] 6 | pub struct Bank { 7 | pub slots: Vec>, 8 | } 9 | -------------------------------------------------------------------------------- /src/resources/specular_texture.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Handle, Image, Resource}; 2 | 3 | #[derive(Resource)] 4 | pub struct SpecularTexture { 5 | pub image: Handle, 6 | } 7 | -------------------------------------------------------------------------------- /src/events/game_connection_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Event; 2 | 3 | use rose_data::ZoneId; 4 | 5 | #[derive(Event)] 6 | pub enum GameConnectionEvent { 7 | Connected(ZoneId), 8 | } 9 | -------------------------------------------------------------------------------- /src/events/move_destination_effect_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Event, Vec3}; 2 | 3 | #[derive(Event)] 4 | pub enum MoveDestinationEffectEvent { 5 | Show { position: Vec3 }, 6 | Hide, 7 | } 8 | -------------------------------------------------------------------------------- /src/scripting/quest_function_context.rs: -------------------------------------------------------------------------------- 1 | #[derive(Default)] 2 | pub struct QuestFunctionContext { 3 | pub selected_quest_index: Option, 4 | pub next_quest_trigger: Option, 5 | } 6 | -------------------------------------------------------------------------------- /src/protocol/irose/mod.rs: -------------------------------------------------------------------------------- 1 | mod game_client; 2 | mod login_client; 3 | mod world_client; 4 | 5 | pub use game_client::GameClient; 6 | pub use login_client::LoginClient; 7 | pub use world_client::WorldClient; 8 | -------------------------------------------------------------------------------- /src/events/client_entity_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Entity, Event}; 2 | 3 | #[derive(Event, Copy, Clone, Debug)] 4 | pub enum ClientEntityEvent { 5 | Die(Entity), 6 | LevelUp(Entity, Option), 7 | } 8 | -------------------------------------------------------------------------------- /src/resources/login_state.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Resource; 2 | 3 | #[derive(Resource)] 4 | pub enum LoginState { 5 | Input, 6 | WaitServerList, 7 | ServerSelect, 8 | JoiningServer, 9 | } 10 | -------------------------------------------------------------------------------- /src/resources/debug_inspector.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Entity, Resource}; 2 | 3 | #[derive(Resource, Default)] 4 | pub struct DebugInspector { 5 | pub enable_picking: bool, 6 | pub entity: Option, 7 | } 8 | -------------------------------------------------------------------------------- /src/events/system_func_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Event; 2 | 3 | use crate::scripting::lua4::Lua4Value; 4 | 5 | #[derive(Event, Clone)] 6 | pub enum SystemFuncEvent { 7 | CallFunction(String, Vec), 8 | } 9 | -------------------------------------------------------------------------------- /src/resources/selected_target.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Entity, Resource}; 2 | 3 | #[derive(Default, Resource)] 4 | pub struct SelectedTarget { 5 | pub selected: Option, 6 | pub hover: Option, 7 | } 8 | -------------------------------------------------------------------------------- /src/events/login_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Event; 2 | 3 | #[derive(Event)] 4 | pub enum LoginEvent { 5 | Login { username: String, password: String }, 6 | SelectServer { server_id: usize, channel_id: usize }, 7 | } 8 | -------------------------------------------------------------------------------- /src/events/character_select_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Event; 2 | 3 | #[derive(Event)] 4 | pub enum CharacterSelectEvent { 5 | SelectCharacter(usize), 6 | PlaySelected, 7 | DeleteSelected, 8 | Disconnect, 9 | } 10 | -------------------------------------------------------------------------------- /src/events/use_item_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Entity, Event}; 2 | 3 | use rose_data::ItemReference; 4 | 5 | #[derive(Event)] 6 | pub struct UseItemEvent { 7 | pub entity: Entity, 8 | pub item: ItemReference, 9 | } 10 | -------------------------------------------------------------------------------- /src/resources/render_configuration.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Resource; 2 | 3 | #[derive(Resource)] 4 | pub struct RenderConfiguration { 5 | pub passthrough_terrain_textures: bool, 6 | pub trail_effect_duration_multiplier: f32, 7 | } 8 | -------------------------------------------------------------------------------- /src/components/passive_recovery_time.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use bevy::{prelude::Component, reflect::Reflect}; 4 | 5 | #[derive(Component, Default, Reflect)] 6 | pub struct PassiveRecoveryTime { 7 | pub time: Duration, 8 | } 9 | -------------------------------------------------------------------------------- /src/resources/character_list.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Resource; 2 | 3 | use rose_game_common::messages::server::CharacterListItem; 4 | 5 | #[derive(Resource)] 6 | pub struct CharacterList { 7 | pub characters: Vec, 8 | } 9 | -------------------------------------------------------------------------------- /src/bundles/mod.rs: -------------------------------------------------------------------------------- 1 | mod ability_values; 2 | 3 | pub use ability_values::{ 4 | ability_values_add_value, ability_values_add_value_exclusive, ability_values_get_value, 5 | ability_values_set_value, ability_values_set_value_exclusive, 6 | }; 7 | -------------------------------------------------------------------------------- /src/events/quest_trigger_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Event; 2 | 3 | use rose_data::QuestTriggerHash; 4 | 5 | #[derive(Event)] 6 | pub enum QuestTriggerEvent { 7 | ApplyRewards(QuestTriggerHash), 8 | DoTrigger(QuestTriggerHash), 9 | } 10 | -------------------------------------------------------------------------------- /src/resources/virtual_filesystem.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Resource; 2 | use std::sync::Arc; 3 | 4 | use rose_file_readers::VirtualFilesystem; 5 | 6 | #[derive(Resource)] 7 | pub struct VfsResource { 8 | pub vfs: Arc, 9 | } 10 | -------------------------------------------------------------------------------- /src/events/bank_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Event; 2 | 3 | use rose_game_common::messages::ClientEntityId; 4 | 5 | #[derive(Event)] 6 | pub enum BankEvent { 7 | OpenBankFromClientEntity { client_entity_id: ClientEntityId }, 8 | Show, 9 | } 10 | -------------------------------------------------------------------------------- /src/resources/world_rates.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Resource; 2 | 3 | #[derive(Resource)] 4 | pub struct WorldRates { 5 | pub craft_rate: i32, 6 | pub world_price_rate: i32, 7 | pub item_price_rate: i32, 8 | pub town_price_rate: i32, 9 | } 10 | -------------------------------------------------------------------------------- /src/scripting/lua4/mod.rs: -------------------------------------------------------------------------------- 1 | mod function; 2 | mod instruction; 3 | mod value; 4 | mod vm; 5 | 6 | pub use function::Lua4Function; 7 | pub use instruction::Lua4Instruction; 8 | pub use value::Lua4Value; 9 | pub use vm::{Lua4VM, Lua4VMError, Lua4VMRustClosures}; 10 | -------------------------------------------------------------------------------- /src/events/conversation_dialog_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Entity, Event}; 2 | 3 | use rose_file_readers::VfsPathBuf; 4 | 5 | #[derive(Event)] 6 | pub enum ConversationDialogEvent { 7 | OpenNpcDialog(Entity, VfsPathBuf), 8 | OpenEventDialog(VfsPathBuf), 9 | } 10 | -------------------------------------------------------------------------------- /src/resources/app_state.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::States; 2 | 3 | #[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash, States)] 4 | pub enum AppState { 5 | #[default] 6 | GameLogin, 7 | GameCharacterSelect, 8 | Game, 9 | ModelViewer, 10 | ZoneViewer, 11 | } 12 | -------------------------------------------------------------------------------- /src/resources/current_zone.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Handle, Resource}; 2 | 3 | use rose_data::ZoneId; 4 | 5 | use crate::zone_loader::ZoneLoaderAsset; 6 | 7 | #[derive(Resource)] 8 | pub struct CurrentZone { 9 | pub id: ZoneId, 10 | pub handle: Handle, 11 | } 12 | -------------------------------------------------------------------------------- /src/components/model_height.rs: -------------------------------------------------------------------------------- 1 | use bevy::{prelude::Component, reflect::Reflect}; 2 | 3 | #[derive(Component, Reflect)] 4 | pub struct ModelHeight { 5 | pub height: f32, 6 | } 7 | 8 | impl ModelHeight { 9 | pub fn new(height: f32) -> Self { 10 | Self { height } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/events/chatbox_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Event; 2 | 3 | #[derive(Event)] 4 | pub enum ChatboxEvent { 5 | Say(String, String), 6 | Shout(String, String), 7 | Whisper(String, String), 8 | Announce(Option, String), 9 | System(String), 10 | Quest(String), 11 | } 12 | -------------------------------------------------------------------------------- /src/components/item_drop_model.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Component, Entity}; 2 | use rose_game_common::components::DroppedItem; 3 | 4 | #[derive(Component)] 5 | pub struct ItemDropModel { 6 | pub dropped_item: Option, 7 | pub root_bone: Entity, 8 | pub model_parts: Vec, 9 | } 10 | -------------------------------------------------------------------------------- /src/components/dummy_bone_offset.rs: -------------------------------------------------------------------------------- 1 | use bevy::{prelude::Component, reflect::Reflect}; 2 | 3 | #[derive(Component, Reflect)] 4 | pub struct DummyBoneOffset { 5 | pub index: usize, 6 | } 7 | 8 | impl DummyBoneOffset { 9 | pub fn new(index: usize) -> Self { 10 | Self { index } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/resources/character_select_state.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Resource; 2 | 3 | #[derive(Resource)] 4 | pub enum CharacterSelectState { 5 | Entering, 6 | CharacterSelect(Option), 7 | CharacterCreate, 8 | CharacterCreating, 9 | ConnectingGameServer, 10 | Leaving, 11 | Loading, 12 | } 13 | -------------------------------------------------------------------------------- /src/components/sound_category.rs: -------------------------------------------------------------------------------- 1 | use bevy::{prelude::Component, reflect::Reflect}; 2 | use enum_map::Enum; 3 | 4 | #[derive(Component, Enum, Copy, Clone, Debug, Reflect)] 5 | pub enum SoundCategory { 6 | BackgroundMusic, 7 | PlayerFootstep, 8 | OtherFootstep, 9 | PlayerCombat, 10 | OtherCombat, 11 | NpcSounds, 12 | Ui, 13 | } 14 | -------------------------------------------------------------------------------- /src/events/message_box_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Commands, Event}; 2 | 3 | #[derive(Event)] 4 | pub enum MessageBoxEvent { 5 | Show { 6 | message: String, 7 | modal: bool, 8 | ok: Option>, 9 | cancel: Option>, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /src/components/client_entity_name.rs: -------------------------------------------------------------------------------- 1 | use bevy::{ 2 | prelude::{Component, Deref, DerefMut}, 3 | reflect::Reflect, 4 | }; 5 | 6 | #[derive(Component, Deref, DerefMut, Reflect)] 7 | pub struct ClientEntityName { 8 | pub name: String, 9 | } 10 | 11 | impl ClientEntityName { 12 | pub fn new(name: String) -> Self { 13 | Self { name } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/components/position.rs: -------------------------------------------------------------------------------- 1 | use bevy::{ 2 | prelude::{Component, Deref, DerefMut, Vec3}, 3 | reflect::Reflect, 4 | }; 5 | 6 | #[derive(Component, Clone, Debug, Deref, DerefMut, Reflect)] 7 | pub struct Position { 8 | pub position: Vec3, 9 | } 10 | 11 | impl Position { 12 | pub fn new(position: Vec3) -> Self { 13 | Self { position } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/events/number_input_dialog_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Commands, Event}; 2 | 3 | #[derive(Event)] 4 | pub enum NumberInputDialogEvent { 5 | Show { 6 | max_value: Option, 7 | modal: bool, 8 | ok: Option>, 9 | cancel: Option>, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /src/components/vehicle.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Component, Entity, Handle}; 2 | use enum_map::EnumMap; 3 | 4 | use rose_data::VehicleMotionAction; 5 | 6 | use crate::animation::ZmoAsset; 7 | 8 | #[derive(Component)] 9 | pub struct Vehicle { 10 | pub driver_model_entity: Entity, 11 | pub vehicle_model_entity: Entity, 12 | pub action_motions: EnumMap>, 13 | } 14 | -------------------------------------------------------------------------------- /src/components/vehicle_sound.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Component, Entity}; 2 | use enum_map::EnumMap; 3 | use rose_data::VehiclePartIndex; 4 | 5 | #[derive(Clone, Copy, PartialEq, Eq)] 6 | pub enum VehicleSoundState { 7 | Idle, 8 | Move, 9 | } 10 | 11 | #[derive(Component)] 12 | pub struct VehicleSound { 13 | pub state: VehicleSoundState, 14 | pub sound_entity: EnumMap, 15 | } 16 | -------------------------------------------------------------------------------- /src/events/npc_store_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Event; 2 | 3 | use rose_game_common::messages::ClientEntityId; 4 | 5 | #[derive(Event)] 6 | pub enum NpcStoreEvent { 7 | OpenClientEntityStore(ClientEntityId), 8 | RemoveFromBuyList(usize), 9 | RemoveFromSellList(usize), 10 | AddToBuyList { 11 | store_tab_index: usize, 12 | store_tab_slot: usize, 13 | quantity: usize, 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /src/resources/server_list.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Resource; 2 | 3 | pub struct ServerListGameServer { 4 | pub id: usize, 5 | pub name: String, 6 | } 7 | 8 | pub struct ServerListWorldServer { 9 | pub id: usize, 10 | pub name: String, 11 | pub game_servers: Vec, 12 | } 13 | 14 | #[derive(Resource)] 15 | pub struct ServerList { 16 | pub world_servers: Vec, 17 | } 18 | -------------------------------------------------------------------------------- /src/components/npc_model.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Component, Entity, Handle, Vec3}; 2 | use enum_map::EnumMap; 3 | 4 | use rose_data::{NpcId, NpcMotionAction}; 5 | 6 | use crate::animation::ZmoAsset; 7 | 8 | #[derive(Component)] 9 | pub struct NpcModel { 10 | pub npc_id: NpcId, 11 | pub model_parts: Vec, 12 | pub action_motions: EnumMap>, 13 | pub root_bone_position: Vec3, 14 | } 15 | -------------------------------------------------------------------------------- /src/components/facing_direction.rs: -------------------------------------------------------------------------------- 1 | use bevy::{ 2 | prelude::{Component, Vec3}, 3 | reflect::Reflect, 4 | }; 5 | 6 | #[derive(Component, Default, Reflect)] 7 | pub struct FacingDirection { 8 | pub desired: f32, 9 | pub actual: f32, 10 | } 11 | 12 | impl FacingDirection { 13 | pub fn set_desired_vector(&mut self, direction: Vec3) { 14 | self.desired = direction.y.atan2(direction.x) + std::f32::consts::PI; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/components/warp_object.rs: -------------------------------------------------------------------------------- 1 | use bevy::{prelude::Component, reflect::Reflect}; 2 | 3 | use rose_data::WarpGateId; 4 | 5 | #[derive(Component, Reflect)] 6 | pub struct WarpObject { 7 | pub warp_id: WarpGateId, 8 | pub last_collision: f64, 9 | } 10 | 11 | impl WarpObject { 12 | pub fn new(warp_id: WarpGateId) -> Self { 13 | Self { 14 | warp_id, 15 | last_collision: 0.0, 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/resources/server_configuration.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Resource; 2 | 3 | #[derive(Resource)] 4 | pub struct ServerConfiguration { 5 | pub ip: String, 6 | pub port: String, 7 | pub preset_username: Option, 8 | pub preset_password: Option, 9 | pub preset_server_id: Option, 10 | pub preset_channel_id: Option, 11 | pub preset_character_name: Option, 12 | pub auto_login: bool, 13 | } 14 | -------------------------------------------------------------------------------- /src/components/visible_status_effects.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Component, Entity}; 2 | 3 | use enum_map::EnumMap; 4 | use rose_data::{StatusEffectId, StatusEffectType}; 5 | 6 | #[derive(Component)] 7 | pub struct VisibleStatusEffect { 8 | pub status_effect_type: StatusEffectType, 9 | } 10 | 11 | #[derive(Component, Default)] 12 | pub struct VisibleStatusEffects { 13 | pub effects: EnumMap>, 14 | } 15 | -------------------------------------------------------------------------------- /src/components/clan_membership.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Component; 2 | 3 | use rose_data::ClanMemberPosition; 4 | use rose_game_common::components::{ClanLevel, ClanMark, ClanPoints, ClanUniqueId}; 5 | 6 | #[derive(Component)] 7 | pub struct ClanMembership { 8 | pub clan_unique_id: ClanUniqueId, 9 | pub mark: ClanMark, 10 | pub level: ClanLevel, 11 | pub name: String, 12 | pub position: ClanMemberPosition, 13 | pub contribution: ClanPoints, 14 | } 15 | -------------------------------------------------------------------------------- /src/components/effect.rs: -------------------------------------------------------------------------------- 1 | use bevy::{prelude::Component, reflect::Reflect}; 2 | 3 | #[derive(Component, Reflect)] 4 | pub struct Effect { 5 | pub manual_despawn: bool, 6 | } 7 | 8 | impl Effect { 9 | pub fn new(manual_despawn: bool) -> Self { 10 | Self { manual_despawn } 11 | } 12 | } 13 | 14 | #[derive(Component, Default, Reflect)] 15 | pub struct EffectMesh {} 16 | 17 | #[derive(Component, Default, Reflect)] 18 | pub struct EffectParticle {} 19 | -------------------------------------------------------------------------------- /src/events/zone_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Event; 2 | 3 | use rose_data::ZoneId; 4 | 5 | #[derive(Event)] 6 | pub struct LoadZoneEvent { 7 | pub id: ZoneId, 8 | pub despawn_other_zones: bool, 9 | } 10 | 11 | impl LoadZoneEvent { 12 | pub fn new(id: ZoneId) -> Self { 13 | Self { 14 | id, 15 | despawn_other_zones: true, 16 | } 17 | } 18 | } 19 | 20 | #[derive(Event)] 21 | pub enum ZoneEvent { 22 | Loaded(ZoneId), 23 | } 24 | -------------------------------------------------------------------------------- /src/resources/name_tag_cache.rs: -------------------------------------------------------------------------------- 1 | use arrayvec::ArrayVec; 2 | use bevy::{ 3 | prelude::{Handle, Image, Resource, Vec2}, 4 | utils::HashMap, 5 | }; 6 | 7 | use crate::render::WorldUiRect; 8 | 9 | pub struct NameTagData { 10 | pub image: Handle, 11 | pub size: Vec2, 12 | pub rects: ArrayVec, // NPC names are 2 rows 13 | } 14 | 15 | #[derive(Default, Resource)] 16 | pub struct NameTagCache { 17 | pub cache: HashMap, 18 | } 19 | -------------------------------------------------------------------------------- /src/scripting/script_function_resources.rs: -------------------------------------------------------------------------------- 1 | use bevy::{ecs::system::SystemParam, prelude::Res}; 2 | 3 | use crate::resources::{GameConnection, GameData, WorldTime}; 4 | 5 | #[derive(SystemParam)] 6 | pub struct ScriptFunctionResources<'w, 's> { 7 | pub game_connection: Option>, 8 | pub game_data: Res<'w, GameData>, 9 | pub world_time: Res<'w, WorldTime>, 10 | 11 | #[system_param(ignore)] 12 | pub phantom: std::marker::PhantomData<&'s ()>, 13 | } 14 | -------------------------------------------------------------------------------- /src/components/event_object.rs: -------------------------------------------------------------------------------- 1 | use bevy::{prelude::Component, reflect::Reflect}; 2 | 3 | #[derive(Component, Reflect)] 4 | pub struct EventObject { 5 | pub quest_trigger_name: String, 6 | pub script_function_name: String, 7 | pub last_collision: f64, 8 | } 9 | 10 | impl EventObject { 11 | pub fn new(quest_trigger_name: String, script_function_name: String) -> Self { 12 | Self { 13 | quest_trigger_name, 14 | script_function_name, 15 | last_collision: 0.0, 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/components/personal_store.rs: -------------------------------------------------------------------------------- 1 | use bevy::{ 2 | prelude::{Component, Entity}, 3 | reflect::Reflect, 4 | }; 5 | 6 | #[derive(Clone, Component, Reflect)] 7 | pub struct PersonalStore { 8 | pub title: String, 9 | pub skin: usize, 10 | } 11 | 12 | impl PersonalStore { 13 | pub fn new(title: String, skin: usize) -> Self { 14 | Self { title, skin } 15 | } 16 | } 17 | 18 | #[derive(Clone, Component, Reflect)] 19 | pub struct PersonalStoreModel { 20 | pub skin: usize, 21 | pub model: Entity, 22 | pub model_parts: Vec, 23 | } 24 | -------------------------------------------------------------------------------- /src/events/spawn_projectile_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Entity, Event}; 2 | 3 | use rose_data::{EffectBulletMoveType, EffectId, SkillId}; 4 | 5 | use crate::components::ProjectileTarget; 6 | 7 | #[derive(Event)] 8 | pub struct SpawnProjectileEvent { 9 | pub effect_id: EffectId, 10 | 11 | pub source: Entity, 12 | pub source_dummy_bone_id: Option, 13 | pub source_skill_id: Option, 14 | pub target: ProjectileTarget, 15 | 16 | pub move_type: EffectBulletMoveType, 17 | pub move_speed: f32, 18 | 19 | pub apply_damage: bool, 20 | } 21 | -------------------------------------------------------------------------------- /src/events/network_event.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Event; 2 | 3 | #[derive(Event)] 4 | #[allow(clippy::enum_variant_names)] 5 | pub enum NetworkEvent { 6 | ConnectLogin { 7 | ip: String, 8 | port: u16, 9 | }, 10 | ConnectWorld { 11 | ip: String, 12 | port: u16, 13 | packet_codec_seed: u32, 14 | login_token: u32, 15 | password: String, 16 | }, 17 | ConnectGame { 18 | ip: String, 19 | port: u16, 20 | packet_codec_seed: u32, 21 | login_token: u32, 22 | password: String, 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /src/components/vehicle_model.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Component, Entity, Handle}; 2 | use enum_map::EnumMap; 3 | 4 | use rose_data::{VehicleMotionAction, VehiclePartIndex}; 5 | 6 | use crate::animation::ZmoAsset; 7 | 8 | #[derive(Component)] 9 | pub struct VehicleModel { 10 | pub driver_model_entity: Entity, 11 | pub driver_dummy_entity: Entity, 12 | pub model_parts: EnumMap)>, 13 | pub vehicle_action_motions: EnumMap>, 14 | pub character_action_motions: EnumMap>, 15 | } 16 | -------------------------------------------------------------------------------- /src/resources/sound_settings.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Resource; 2 | use enum_map::EnumMap; 3 | 4 | use crate::{audio::SoundGain, components::SoundCategory}; 5 | 6 | #[derive(Resource)] 7 | pub struct SoundSettings { 8 | pub enabled: bool, 9 | pub global_gain: f32, 10 | pub gains: EnumMap, 11 | } 12 | 13 | impl SoundSettings { 14 | pub fn gain(&self, category: SoundCategory) -> SoundGain { 15 | if self.enabled { 16 | SoundGain::Ratio(self.global_gain * self.gains[category]) 17 | } else { 18 | SoundGain::Ratio(0.0) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/components/client_entity.rs: -------------------------------------------------------------------------------- 1 | use bevy::{prelude::Component, reflect::Reflect}; 2 | 3 | pub use rose_game_common::messages::ClientEntityId; 4 | 5 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Reflect)] 6 | pub enum ClientEntityType { 7 | Character, 8 | Monster, 9 | Npc, 10 | ItemDrop, 11 | } 12 | 13 | #[derive(Copy, Clone, Component, Reflect)] 14 | pub struct ClientEntity { 15 | pub id: ClientEntityId, 16 | pub entity_type: ClientEntityType, 17 | } 18 | 19 | impl ClientEntity { 20 | pub fn new(id: ClientEntityId, entity_type: ClientEntityType) -> Self { 21 | Self { id, entity_type } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/systems/world_time_system.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use bevy::{ 4 | ecs::prelude::{Res, ResMut}, 5 | prelude::Time, 6 | }; 7 | 8 | use rose_data::{WorldTicks, WORLD_TICK_DURATION}; 9 | 10 | use crate::resources::WorldTime; 11 | 12 | pub fn world_time_system(time: Res