Skip to content

Commit

Permalink
Make hotkey data persistent
Browse files Browse the repository at this point in the history
  • Loading branch information
vE5li committed May 9, 2024
1 parent 4c1288a commit aabfdca
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 32 deletions.
3 changes: 1 addition & 2 deletions korangar/src/input/event.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use cgmath::Vector2;
use korangar_interface::event::ClickAction;
use korangar_interface::ElementEvent;
use ragnarok_packets::{AccountId, CharacterId, CharacterServerInformation, EntityId, TilePosition};
use ragnarok_packets::{AccountId, CharacterId, CharacterServerInformation, EntityId, HotbarSlot, TilePosition};

use super::HotbarSlot;
use crate::interface::application::{InterfaceSettings, InternalThemeKind};
use crate::interface::resource::Move;
use crate::loaders::ServiceId;
Expand Down
5 changes: 1 addition & 4 deletions korangar/src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use korangar_interface::elements::{ElementCell, Focus};
use korangar_interface::event::ClickAction;
use korangar_interface::state::{PlainTrackedState, TrackedState};
use korangar_interface::Interface;
use ragnarok_packets::ClientTick;
use ragnarok_packets::{ClientTick, HotbarSlot};
use winit::dpi::PhysicalPosition;
use winit::event::{ElementState, MouseButton, MouseScrollDelta, VirtualKeyCode};

Expand All @@ -28,9 +28,6 @@ use crate::interface::resource::PartialMove;
const MOUSE_SCOLL_MULTIPLIER: f32 = 30.0;
const KEY_COUNT: usize = variant_count::<VirtualKeyCode>();

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct HotbarSlot(pub usize);

pub struct InputSystem {
previous_mouse_position: ScreenPosition,
new_mouse_position: ScreenPosition,
Expand Down
7 changes: 5 additions & 2 deletions korangar/src/interface/elements/containers/hotbar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ use korangar_interface::event::{ChangeEvent, HoverInformation};
use korangar_interface::layout::PlacementResolver;
use korangar_interface::size_bound;
use korangar_interface::state::{PlainRemote, Remote};
use ragnarok_packets::HotbarSlot;

use crate::graphics::{InterfaceRenderer, Renderer};
use crate::input::{HotbarSlot, MouseInputMode};
use crate::input::MouseInputMode;
use crate::interface::application::InterfaceSettings;
use crate::interface::elements::SkillBox;
use crate::interface::layout::{ScreenClip, ScreenPosition, ScreenSize};
Expand All @@ -28,7 +29,9 @@ impl HotbarContainer {
.cloned()
.enumerate()
.map(|(slot, skill)| {
let skill_source = SkillSource::Hotbar { slot: HotbarSlot(slot) };
let skill_source = SkillSource::Hotbar {
slot: HotbarSlot(slot as u16),
};
let skill_box = SkillBox::new(
skill,
skill_source,
Expand Down
3 changes: 1 addition & 2 deletions korangar/src/interface/resource.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use ragnarok_packets::EquipPosition;
use ragnarok_packets::{EquipPosition, HotbarSlot};

use crate::input::HotbarSlot;
use crate::inventory::{Item, Skill};

#[derive(Clone, Copy, Debug, PartialEq)]
Expand Down
78 changes: 63 additions & 15 deletions korangar/src/inventory/hotbar.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,91 @@
use std::cell::Ref;

use korangar_interface::state::{PlainRemote, PlainTrackedState, TrackedState, TrackedStateExt};
use korangar_networking::NetworkingSystem;
use ragnarok_packets::handler::PacketCallback;
use ragnarok_packets::{HotbarSlot, HotbarTab, HotkeyData};

use super::Skill;
use crate::input::HotbarSlot;

#[derive(Default)]
pub struct Hotbar {
skills: PlainTrackedState<[Option<Skill>; 10]>,
}

impl Hotbar {
pub fn set_slot(&mut self, skill: Skill, slot: HotbarSlot) {
/// Set the slot without notifying the map server.
pub fn set_slot(&mut self, slot: HotbarSlot, skill: Skill) {
self.skills.mutate(|skills| {
skills[slot.0] = Some(skill);
skills[slot.0 as usize] = Some(skill);
});
}

pub fn swap_slot(&mut self, source_slot: HotbarSlot, destination_slot: HotbarSlot) {
/// Update the slot and notify the map server.
pub fn update_slot<Callback>(&mut self, networking_system: &mut NetworkingSystem<Callback>, slot: HotbarSlot, skill: Skill)
where
Callback: PacketCallback,
{
let _ = networking_system.set_hotkey_data(HotbarTab(0), slot, HotkeyData {
is_skill: true as u8,
skill_id: skill.skill_id.0 as u32,
quantity_or_skill_level: skill.skill_level,
});

self.skills.mutate(|skills| {
skills[slot.0 as usize] = Some(skill);
});
}

/// Swap two slots in the hotbar and notify the map server.
pub fn swap_slot<Callback>(
&mut self,
networking_system: &mut NetworkingSystem<Callback>,
source_slot: HotbarSlot,
destination_slot: HotbarSlot,
) where
Callback: PacketCallback,
{
if source_slot != destination_slot {
self.skills.mutate(|skills| {
let first = skills[source_slot.0].take();
let second = skills[destination_slot.0].take();
let first = skills[source_slot.0 as usize].take();
let second = skills[destination_slot.0 as usize].take();

skills[source_slot.0] = second;
skills[destination_slot.0] = first;
});
let first_data = first
.as_ref()
.map(|skill| HotkeyData {
is_skill: true as u8,
skill_id: skill.skill_id.0 as u32,
quantity_or_skill_level: skill.skill_level,
})
.unwrap_or(HotkeyData::UNBOUND);

let second_data = second
.as_ref()
.map(|skill| HotkeyData {
is_skill: true as u8,
skill_id: skill.skill_id.0 as u32,
quantity_or_skill_level: skill.skill_level,
})
.unwrap_or(HotkeyData::UNBOUND);

let _ = networking_system.set_hotkey_data(HotbarTab(0), destination_slot, first_data);
let _ = networking_system.set_hotkey_data(HotbarTab(0), source_slot, second_data);

skills[source_slot.0 as usize] = second;
skills[destination_slot.0 as usize] = first;
})
}
}

/*pub fn clear_slot(&mut self, slot: HotbarSlot) {
self.skills.with_mut(|skills, changed| {
skills[slot.0] = None;
changed();
/// Clear the slot without notifying the map server.
pub fn clear_slot(&mut self, slot: HotbarSlot) {
self.skills.mutate(|skills| {
skills[slot.0 as usize] = None;
});
}*/
}

pub fn get_skill_in_slot(&self, slot: HotbarSlot) -> Ref<Option<Skill>> {
Ref::map(self.skills.get(), |skills| &skills[slot.0])
Ref::map(self.skills.get(), |skills| &skills[slot.0 as usize])
}

pub fn get_skills(&self) -> PlainRemote<[Option<Skill>; 10]> {
Expand Down
4 changes: 4 additions & 0 deletions korangar/src/inventory/skills.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,8 @@ impl SkillTree {
pub fn get_skills(&self) -> PlainRemote<Vec<Skill>> {
self.skills.new_remote()
}

pub fn find_skill(&self, skill_id: SkillId) -> Option<Skill> {
self.skills.get().iter().find(|skill| skill.skill_id == skill_id).cloned()
}
}
31 changes: 27 additions & 4 deletions korangar/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ use korangar_debug::profiling::Profiler;
use korangar_interface::application::{Application, FocusState, FontSizeTrait, FontSizeTraitExt, PositionTraitExt};
use korangar_interface::state::{PlainTrackedState, Remote, RemoteClone, TrackedState, TrackedStateExt, TrackedStateTake, TrackedStateVec};
use korangar_interface::Interface;
use korangar_networking::{DisconnectReason, LoginServerLoginData, MessageColor, NetworkEvent, NetworkingSystem};
use ragnarok_packets::{CharacterId, CharacterServerInformation, Friend, SkillId, SkillType, TilePosition, UnitId, WorldPosition};
use korangar_networking::{DisconnectReason, HotkeyState, LoginServerLoginData, MessageColor, NetworkEvent, NetworkingSystem};
use ragnarok_packets::{
CharacterId, CharacterServerInformation, Friend, HotbarSlot, SkillId, SkillType, TilePosition, UnitId, WorldPosition,
};
use vulkano::device::{Device, DeviceCreateInfo, QueueCreateInfo};
#[cfg(feature = "debug")]
use vulkano::instance::debug::{
Expand Down Expand Up @@ -946,6 +948,27 @@ fn main() {
*friend_list = friends.into_iter().map(|friend| (friend, LinkedElement::new())).collect();
});
}
NetworkEvent::SetHotkeyData { tab, hotkeys } => {
// FIX: Since we only have one hotbar at the moment, we ignore
// everything but 0.
if tab.0 != 0 {
continue;
}

for (index, hotkey) in hotkeys.into_iter().take(10).enumerate() {
match hotkey {
HotkeyState::Bound(hotkey) => {
let Some(mut skill) = player_skill_tree.find_skill(SkillId(hotkey.skill_id as u16)) else {
panic!("Skill in hotbar is not learned by the player");
};

skill.skill_level = hotkey.quantity_or_skill_level;
hotbar.set_slot(HotbarSlot(index as u16), skill);
},
HotkeyState::Unbound => hotbar.clear_slot(HotbarSlot(index as u16)),
}
}
}
}
}

Expand Down Expand Up @@ -1116,10 +1139,10 @@ fn main() {
skill,
} => match (source, destination) {
(SkillSource::SkillTree, SkillSource::Hotbar { slot }) => {
hotbar.set_slot(skill, slot);
hotbar.update_slot(&mut networking_system, slot, skill);
}
(SkillSource::Hotbar { slot: source_slot }, SkillSource::Hotbar { slot: destination_slot }) => {
hotbar.swap_slot(source_slot, destination_slot);
hotbar.swap_slot(&mut networking_system, source_slot, destination_slot);
}
_ => {}
},
Expand Down
5 changes: 5 additions & 0 deletions korangar_networking/src/event.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use ragnarok_packets::*;

use crate::hotkey::HotkeyState;
use crate::{
CharacterServerLoginData, EntityData, InventoryItem, LoginServerLoginData, MessageColor, UnifiedCharacterSelectionFailedReason,
UnifiedLoginFailedReason,
Expand Down Expand Up @@ -119,6 +120,10 @@ pub enum NetworkEvent {
account_id: AccountId,
character_id: CharacterId,
},
SetHotkeyData {
tab: HotbarTab,
hotkeys: Vec<HotkeyState>,
},
}

/// New-type so we can implement some `From` traits. This will help when
Expand Down
7 changes: 7 additions & 0 deletions korangar_networking/src/hotkey.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use ragnarok_packets::HotkeyData;

#[derive(Debug)]
pub enum HotkeyState {
Bound(HotkeyData),
Unbound,
}
18 changes: 17 additions & 1 deletion korangar_networking/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod entity;
mod event;
mod hotkey;
mod inventory;
mod message;
mod server;
Expand All @@ -25,6 +26,7 @@ use tokio::task::JoinHandle;

pub use self::entity::EntityData;
pub use self::event::{DisconnectReason, NetworkEvent};
pub use self::hotkey::HotkeyState;
pub use self::inventory::InventoryItem;
pub use self::message::MessageColor;
pub use self::server::{
Expand Down Expand Up @@ -719,7 +721,17 @@ where
packet_handler.register_noop::<EquippableSwitchItemListPacket>()?;
packet_handler.register_noop::<MapTypePacket>()?;
packet_handler.register(|packet: UpdateSkillTreePacket| NetworkEvent::SkillTree(packet.skill_information))?;
packet_handler.register_noop::<UpdateHotkeysPacket>()?;
packet_handler.register(|packet: UpdateHotkeysPacket| NetworkEvent::SetHotkeyData {
tab: packet.tab,
hotkeys: packet
.hotkeys
.into_iter()
.map(|hotkey_data| match hotkey_data == HotkeyData::UNBOUND {
true => HotkeyState::Unbound,
false => HotkeyState::Bound(hotkey_data),
})
.collect(),
})?;
packet_handler.register_noop::<InitialStatusPacket>()?;
packet_handler.register_noop::<UpdatePartyInvitationStatePacket>()?;
packet_handler.register_noop::<UpdateShowEquipPacket>()?;
Expand Down Expand Up @@ -1011,6 +1023,10 @@ where
pub fn switch_character_slot(&mut self, origin_slot: usize, destination_slot: usize) -> Result<(), NotConnectedError> {
self.send_character_server_packet(&SwitchCharacterSlotPacket::new(origin_slot as u16, destination_slot as u16))
}

pub fn set_hotkey_data(&mut self, tab: HotbarTab, index: HotbarSlot, hotkey_data: HotkeyData) -> Result<(), NotConnectedError> {
self.send_map_server_packet(&SetHotkeyData2Packet::new(tab, index, hotkey_data))
}
}

#[cfg(test)]
Expand Down
37 changes: 35 additions & 2 deletions ragnarok_packets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,14 @@ pub struct SkillId(pub u16);
#[cfg_attr(feature = "interface", derive(korangar_interface::elements::PrototypeElement))]
pub struct SkillLevel(pub u16);

#[derive(Clone, Copy, Debug, ByteConvertable, FixedByteSize, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "interface", derive(korangar_interface::elements::PrototypeElement))]
pub struct HotbarTab(pub u16);

#[derive(Clone, Copy, Debug, ByteConvertable, FixedByteSize, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "interface", derive(korangar_interface::elements::PrototypeElement))]
pub struct HotbarSlot(pub u16);

#[derive(Clone, Copy, Debug, ByteConvertable, FixedByteSize)]
#[cfg_attr(feature = "interface", derive(korangar_interface::elements::PrototypeElement))]
pub struct ServerAddress(pub [u8; 4]);
Expand Down Expand Up @@ -1547,23 +1555,48 @@ pub struct UpdateSkillTreePacket {
pub skill_information: Vec<SkillInformation>,
}

#[derive(Debug, Clone, ByteConvertable, MapServer)]
#[derive(Debug, Clone, PartialEq, Eq, ByteConvertable, MapServer)]
#[cfg_attr(feature = "interface", derive(korangar_interface::elements::PrototypeElement))]
pub struct HotkeyData {
pub is_skill: u8,
pub skill_id: u32,
pub quantity_or_skill_level: SkillLevel,
}

impl HotkeyData {
pub const UNBOUND: Self = Self {
is_skill: 0,
skill_id: 0,
quantity_or_skill_level: SkillLevel(0),
};
}

#[derive(Debug, Clone, IncomingPacket, MapServer)]
#[cfg_attr(feature = "interface", derive(korangar_interface::elements::PrototypeElement))]
#[header(0x0B20)]
pub struct UpdateHotkeysPacket {
pub rotate: u8,
pub tab: u16,
pub tab: HotbarTab,
pub hotkeys: [HotkeyData; 38],
}

#[derive(Debug, Clone, OutgoingPacket, MapServer, new)]
#[cfg_attr(feature = "interface", derive(korangar_interface::elements::PrototypeElement))]
#[header(0x02BA)]
pub struct SetHotkeyData1Packet {
pub slot: HotbarSlot,
pub hotkey_data: HotkeyData,
}

#[derive(Debug, Clone, OutgoingPacket, MapServer, new)]
#[cfg_attr(feature = "interface", derive(korangar_interface::elements::PrototypeElement))]
#[header(0x0B21)]
pub struct SetHotkeyData2Packet {
pub tab: HotbarTab,
pub slot: HotbarSlot,
pub hotkey_data: HotkeyData,
}

#[derive(Debug, Clone, IncomingPacket, MapServer)]
#[cfg_attr(feature = "interface", derive(korangar_interface::elements::PrototypeElement))]
#[header(0x02C9)]
Expand Down

0 comments on commit aabfdca

Please sign in to comment.