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::{
|
use kawari::world::ipc::{
|
||||||
ClientZoneIpcData, CommonSpawn, DisplayFlag, GameMasterCommandType, GameMasterRank, ObjectKind,
|
ClientZoneIpcData, CommonSpawn, DisplayFlag, GameMasterCommandType, GameMasterRank, ObjectKind,
|
||||||
OnlineStatus, PlayerSubKind, ServerZoneIpcData, ServerZoneIpcSegment, SocialListRequestType,
|
OnlineStatus, PlayerSubKind, ServerZoneIpcData, ServerZoneIpcSegment, SocialListRequestType,
|
||||||
StatusEffect,
|
|
||||||
};
|
};
|
||||||
use kawari::world::{
|
use kawari::world::{
|
||||||
ChatHandler, Inventory, Zone, ZoneConnection,
|
ChatHandler, Inventory, Zone, ZoneConnection,
|
||||||
|
@ -23,8 +22,8 @@ use kawari::world::{
|
||||||
SocialList,
|
SocialList,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use kawari::world::{LuaPlayer, PlayerData, WorldDatabase};
|
use kawari::world::{LuaPlayer, PlayerData, StatusEffects, WorldDatabase};
|
||||||
use mlua::{AnyUserData, Function, Lua};
|
use mlua::{Function, Lua};
|
||||||
use physis::common::{Language, Platform};
|
use physis::common::{Language, Platform};
|
||||||
use physis::gamedata::GameData;
|
use physis::gamedata::GameData;
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
|
@ -76,6 +75,7 @@ async fn main() {
|
||||||
zone: None,
|
zone: None,
|
||||||
position: Position::default(),
|
position: Position::default(),
|
||||||
inventory: Inventory::new(),
|
inventory: Inventory::new(),
|
||||||
|
status_effects: StatusEffects::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut lua_player = LuaPlayer::default();
|
let mut lua_player = LuaPlayer::default();
|
||||||
|
@ -99,7 +99,6 @@ async fn main() {
|
||||||
// collect actor data
|
// collect actor data
|
||||||
connection.player_data =
|
connection.player_data =
|
||||||
database.find_player_data(actor_id.parse::<u32>().unwrap());
|
database.find_player_data(actor_id.parse::<u32>().unwrap());
|
||||||
lua_player.player_data = connection.player_data;
|
|
||||||
|
|
||||||
// We have send THEM a keep alive
|
// 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;
|
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 tokio::net::TcpStream;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -26,9 +26,34 @@ pub struct PlayerData {
|
||||||
pub account_id: u32,
|
pub account_id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserData for PlayerData {
|
#[derive(Debug, Default, Clone)]
|
||||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
pub struct StatusEffects {
|
||||||
fields.add_field_method_get("content_id", |_, this| Ok(this.content_id));
|
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 position: Position,
|
||||||
pub inventory: Inventory,
|
pub inventory: Inventory,
|
||||||
|
pub status_effects: StatusEffects,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ZoneConnection {
|
impl ZoneConnection {
|
||||||
|
@ -270,11 +296,40 @@ impl ZoneConnection {
|
||||||
}
|
}
|
||||||
player.queued_segments.clear();
|
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)]
|
#[derive(Default)]
|
||||||
pub struct LuaPlayer {
|
pub struct LuaPlayer {
|
||||||
pub player_data: PlayerData,
|
pub player_data: PlayerData,
|
||||||
|
pub status_effects: StatusEffects,
|
||||||
queued_segments: Vec<PacketSegment<ServerZoneIpcSegment>>,
|
queued_segments: Vec<PacketSegment<ServerZoneIpcSegment>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,26 +357,7 @@ impl LuaPlayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn give_status_effect(&mut self, effect_id: u16, duration: f32) {
|
fn give_status_effect(&mut self, effect_id: u16, duration: f32) {
|
||||||
let ipc = ServerZoneIpcSegment {
|
self.status_effects.add(effect_id, duration);
|
||||||
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 },
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ mod chat_handler;
|
||||||
pub use chat_handler::ChatHandler;
|
pub use chat_handler::ChatHandler;
|
||||||
|
|
||||||
mod connection;
|
mod connection;
|
||||||
pub use connection::{LuaPlayer, PlayerData, ZoneConnection};
|
pub use connection::{LuaPlayer, PlayerData, StatusEffects, ZoneConnection};
|
||||||
|
|
||||||
mod database;
|
mod database;
|
||||||
pub use database::{CharacterData, WorldDatabase};
|
pub use database::{CharacterData, WorldDatabase};
|
||||||
|
|
Loading…
Add table
Reference in a new issue