mirror of
https://github.com/redstrate/Kawari.git
synced 2025-04-22 15:27:44 +00:00
Improve how the status effect list is sent and created
There is now a dedicated StatusEffects struct that provides a nicer API to work with these. The list is also sent when needed and only when a status effect changes, as the client handles the ticking down of durations itself.
This commit is contained in:
parent
13b24e9cfe
commit
bbbe426617
3 changed files with 76 additions and 29 deletions
|
@ -14,7 +14,6 @@ use kawari::packet::{
|
|||
use kawari::world::ipc::{
|
||||
ClientZoneIpcData, CommonSpawn, DisplayFlag, GameMasterCommandType, GameMasterRank, ObjectKind,
|
||||
OnlineStatus, PlayerSubKind, ServerZoneIpcData, ServerZoneIpcSegment, SocialListRequestType,
|
||||
StatusEffect,
|
||||
};
|
||||
use kawari::world::{
|
||||
ChatHandler, Inventory, Zone, ZoneConnection,
|
||||
|
@ -23,8 +22,8 @@ use kawari::world::{
|
|||
SocialList,
|
||||
},
|
||||
};
|
||||
use kawari::world::{LuaPlayer, PlayerData, WorldDatabase};
|
||||
use mlua::{AnyUserData, Function, Lua};
|
||||
use kawari::world::{LuaPlayer, PlayerData, StatusEffects, WorldDatabase};
|
||||
use mlua::{Function, Lua};
|
||||
use physis::common::{Language, Platform};
|
||||
use physis::gamedata::GameData;
|
||||
use tokio::io::AsyncReadExt;
|
||||
|
@ -76,6 +75,7 @@ async fn main() {
|
|||
zone: None,
|
||||
position: Position::default(),
|
||||
inventory: Inventory::new(),
|
||||
status_effects: StatusEffects::default(),
|
||||
};
|
||||
|
||||
let mut lua_player = LuaPlayer::default();
|
||||
|
@ -99,7 +99,6 @@ async fn main() {
|
|||
// collect actor data
|
||||
connection.player_data =
|
||||
database.find_player_data(actor_id.parse::<u32>().unwrap());
|
||||
lua_player.player_data = connection.player_data;
|
||||
|
||||
// We have send THEM a keep alive
|
||||
{
|
||||
|
@ -942,7 +941,19 @@ async fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
// copy from lua player state, as they modify the status effects list
|
||||
// TODO: i dunno?
|
||||
connection.status_effects = lua_player.status_effects.clone();
|
||||
|
||||
// Process any queued packets from scripts and whatnot
|
||||
connection.process_lua_player(&mut lua_player).await;
|
||||
|
||||
// check if status effects need sending
|
||||
connection.process_effects_list().await;
|
||||
|
||||
// update lua player
|
||||
lua_player.player_data = connection.player_data;
|
||||
lua_player.status_effects = connection.status_effects.clone();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{UserData, UserDataFields, UserDataMethods};
|
||||
use mlua::{UserData, UserDataMethods};
|
||||
use tokio::net::TcpStream;
|
||||
|
||||
use crate::{
|
||||
|
@ -26,9 +26,34 @@ pub struct PlayerData {
|
|||
pub account_id: u32,
|
||||
}
|
||||
|
||||
impl UserData for PlayerData {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("content_id", |_, this| Ok(this.content_id));
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct StatusEffects {
|
||||
pub status_effects: Vec<StatusEffect>,
|
||||
/// If the list is dirty and must be propagated to the client
|
||||
pub dirty: bool,
|
||||
}
|
||||
|
||||
impl StatusEffects {
|
||||
pub fn add(&mut self, effect_id: u16, duration: f32) {
|
||||
let status_effect = self.find_or_create_status_effect(effect_id);
|
||||
status_effect.duration = duration;
|
||||
self.dirty = true
|
||||
}
|
||||
|
||||
fn find_or_create_status_effect(&mut self, effect_id: u16) -> &mut StatusEffect {
|
||||
if let Some(i) = self
|
||||
.status_effects
|
||||
.iter()
|
||||
.position(|effect| effect.effect_id == effect_id)
|
||||
{
|
||||
&mut self.status_effects[i]
|
||||
} else {
|
||||
self.status_effects.push(StatusEffect {
|
||||
effect_id,
|
||||
..Default::default()
|
||||
});
|
||||
self.status_effects.last_mut().unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,6 +69,7 @@ pub struct ZoneConnection {
|
|||
|
||||
pub position: Position,
|
||||
pub inventory: Inventory,
|
||||
pub status_effects: StatusEffects,
|
||||
}
|
||||
|
||||
impl ZoneConnection {
|
||||
|
@ -270,11 +296,40 @@ impl ZoneConnection {
|
|||
}
|
||||
player.queued_segments.clear();
|
||||
}
|
||||
|
||||
pub async fn process_effects_list(&mut self) {
|
||||
// Only update the client if absolutely nessecary (e.g. an effect is added, removed or changed duration)
|
||||
if self.status_effects.dirty {
|
||||
let mut list = [StatusEffect::default(); 30];
|
||||
list[..self.status_effects.status_effects.len()]
|
||||
.copy_from_slice(&self.status_effects.status_effects);
|
||||
|
||||
let ipc = ServerZoneIpcSegment {
|
||||
op_code: ServerZoneIpcType::StatusEffectList,
|
||||
timestamp: timestamp_secs(),
|
||||
data: ServerZoneIpcData::StatusEffectList(StatusEffectList {
|
||||
statues: list,
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
self.send_segment(PacketSegment {
|
||||
source_actor: self.player_data.actor_id,
|
||||
target_actor: self.player_data.actor_id,
|
||||
segment_type: SegmentType::Ipc { data: ipc },
|
||||
})
|
||||
.await;
|
||||
|
||||
self.status_effects.dirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct LuaPlayer {
|
||||
pub player_data: PlayerData,
|
||||
pub status_effects: StatusEffects,
|
||||
queued_segments: Vec<PacketSegment<ServerZoneIpcSegment>>,
|
||||
}
|
||||
|
||||
|
@ -302,26 +357,7 @@ impl LuaPlayer {
|
|||
}
|
||||
|
||||
fn give_status_effect(&mut self, effect_id: u16, duration: f32) {
|
||||
let ipc = ServerZoneIpcSegment {
|
||||
op_code: ServerZoneIpcType::StatusEffectList,
|
||||
timestamp: timestamp_secs(),
|
||||
data: ServerZoneIpcData::StatusEffectList(StatusEffectList {
|
||||
statues: [StatusEffect {
|
||||
effect_id,
|
||||
param: 0,
|
||||
duration,
|
||||
source_actor_id: self.player_data.actor_id,
|
||||
}; 30],
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
self.queue_segment(PacketSegment {
|
||||
source_actor: self.player_data.actor_id,
|
||||
target_actor: self.player_data.actor_id,
|
||||
segment_type: SegmentType::Ipc { data: ipc },
|
||||
});
|
||||
self.status_effects.add(effect_id, duration);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ mod chat_handler;
|
|||
pub use chat_handler::ChatHandler;
|
||||
|
||||
mod connection;
|
||||
pub use connection::{LuaPlayer, PlayerData, ZoneConnection};
|
||||
pub use connection::{LuaPlayer, PlayerData, StatusEffects, ZoneConnection};
|
||||
|
||||
mod database;
|
||||
pub use database::{CharacterData, WorldDatabase};
|
||||
|
|
Loading…
Add table
Reference in a new issue