mirror of
https://github.com/redstrate/Kawari.git
synced 2025-06-30 11:47:45 +00:00
parent
ad4edf801d
commit
9a3652fb42
4 changed files with 83 additions and 31 deletions
|
@ -11,7 +11,7 @@ use kawari::ipc::zone::{
|
||||||
ActorControlCategory, ActorControlSelf, PlayerEntry, PlayerSpawn, PlayerStatus, SocialList,
|
ActorControlCategory, ActorControlSelf, PlayerEntry, PlayerSpawn, PlayerStatus, SocialList,
|
||||||
};
|
};
|
||||||
use kawari::ipc::zone::{
|
use kawari::ipc::zone::{
|
||||||
ClientTriggerCommand, ClientZoneIpcData, CommonSpawn, EventStart, GameMasterRank, OnlineStatus,
|
ClientTriggerCommand, ClientZoneIpcData, EventStart, GameMasterRank, OnlineStatus,
|
||||||
ServerZoneIpcData, ServerZoneIpcSegment, SocialListRequestType,
|
ServerZoneIpcData, ServerZoneIpcSegment, SocialListRequestType,
|
||||||
};
|
};
|
||||||
use kawari::opcodes::{ServerChatIpcType, ServerZoneIpcType};
|
use kawari::opcodes::{ServerChatIpcType, ServerZoneIpcType};
|
||||||
|
@ -79,7 +79,6 @@ pub fn spawn_client(connection: ZoneConnection) {
|
||||||
ip: *ip,
|
ip: *ip,
|
||||||
channel: send,
|
channel: send,
|
||||||
actor_id: 0,
|
actor_id: 0,
|
||||||
common: CommonSpawn::default(),
|
|
||||||
};
|
};
|
||||||
let _ = my_send.send(handle);
|
let _ = my_send.send(handle);
|
||||||
}
|
}
|
||||||
|
@ -170,7 +169,6 @@ async fn client_loop(
|
||||||
|
|
||||||
let mut client_handle = client_handle.clone();
|
let mut client_handle = client_handle.clone();
|
||||||
client_handle.actor_id = actor_id;
|
client_handle.actor_id = actor_id;
|
||||||
client_handle.common = connection.get_player_common_spawn(connection.exit_position, connection.exit_rotation);
|
|
||||||
|
|
||||||
// tell the server we exist, now that we confirmed we are a legitimate connection
|
// tell the server we exist, now that we confirmed we are a legitimate connection
|
||||||
connection.handle.send(ToServer::NewClient(client_handle)).await;
|
connection.handle.send(ToServer::NewClient(client_handle)).await;
|
||||||
|
@ -326,11 +324,11 @@ async fn client_loop(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
ClientZoneIpcData::FinishLoading { .. } => {
|
ClientZoneIpcData::FinishLoading { .. } => {
|
||||||
// tell the server we loaded into the zone, so it can start sending us acors
|
|
||||||
connection.handle.send(ToServer::ZoneLoaded(connection.id, connection.zone.as_ref().unwrap().id)).await;
|
|
||||||
|
|
||||||
let common = connection.get_player_common_spawn(connection.exit_position, connection.exit_rotation);
|
let common = connection.get_player_common_spawn(connection.exit_position, connection.exit_rotation);
|
||||||
|
|
||||||
|
// tell the server we loaded into the zone, so it can start sending us acors
|
||||||
|
connection.handle.send(ToServer::ZoneLoaded(connection.id, connection.zone.as_ref().unwrap().id, common.clone())).await;
|
||||||
|
|
||||||
let chara_details = database.find_chara_make(connection.player_data.content_id);
|
let chara_details = database.find_chara_make(connection.player_data.content_id);
|
||||||
|
|
||||||
connection.send_inventory(false).await;
|
connection.send_inventory(false).await;
|
||||||
|
@ -941,6 +939,7 @@ async fn client_loop(
|
||||||
FromServer::ActionComplete(request) => connection.execute_action(request, &mut lua_player).await,
|
FromServer::ActionComplete(request) => connection.execute_action(request, &mut lua_player).await,
|
||||||
FromServer::ActionCancelled() => connection.cancel_action().await,
|
FromServer::ActionCancelled() => connection.cancel_action().await,
|
||||||
FromServer::UpdateConfig(actor_id, config) => connection.update_config(actor_id, config).await,
|
FromServer::UpdateConfig(actor_id, config) => connection.update_config(actor_id, config).await,
|
||||||
|
FromServer::ActorEquip(actor_id, main_weapon_id, model_ids) => connection.update_equip(actor_id, main_weapon_id, model_ids).await,
|
||||||
},
|
},
|
||||||
None => break,
|
None => break,
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@ pub enum FromServer {
|
||||||
ActionCancelled(),
|
ActionCancelled(),
|
||||||
/// Update an actor's equip display flags.
|
/// Update an actor's equip display flags.
|
||||||
UpdateConfig(u32, Config),
|
UpdateConfig(u32, Config),
|
||||||
|
/// Update an actor's model IDs.
|
||||||
|
ActorEquip(u32, u64, [u32; 10]),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -50,7 +52,6 @@ pub struct ClientHandle {
|
||||||
pub ip: SocketAddr,
|
pub ip: SocketAddr,
|
||||||
pub channel: Sender<FromServer>,
|
pub channel: Sender<FromServer>,
|
||||||
pub actor_id: u32,
|
pub actor_id: u32,
|
||||||
pub common: CommonSpawn,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientHandle {
|
impl ClientHandle {
|
||||||
|
@ -86,7 +87,7 @@ pub enum ToServer {
|
||||||
ClientTrigger(ClientId, u32, ClientTrigger),
|
ClientTrigger(ClientId, u32, ClientTrigger),
|
||||||
/// The connection loaded into a zone.
|
/// The connection loaded into a zone.
|
||||||
// TODO: the connection should not be in charge and telling the global server what zone they just loaded in! but this will work for now
|
// TODO: the connection should not be in charge and telling the global server what zone they just loaded in! but this will work for now
|
||||||
ZoneLoaded(ClientId, u16),
|
ZoneLoaded(ClientId, u16, CommonSpawn),
|
||||||
/// The connection left a zone.
|
/// The connection left a zone.
|
||||||
LeftZone(ClientId, u32, u16),
|
LeftZone(ClientId, u32, u16),
|
||||||
/// The connection disconnected.
|
/// The connection disconnected.
|
||||||
|
@ -103,6 +104,8 @@ pub enum ToServer {
|
||||||
ActionRequest(ClientId, u32, ActionRequest),
|
ActionRequest(ClientId, u32, ActionRequest),
|
||||||
/// We want to update our own equip display flags.
|
/// We want to update our own equip display flags.
|
||||||
Config(ClientId, u32, Config),
|
Config(ClientId, u32, Config),
|
||||||
|
/// Tell the server what models IDs we have equipped.
|
||||||
|
Equip(ClientId, u32, u64, [u32; 10]),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
|
@ -585,35 +585,48 @@ impl ZoneConnection {
|
||||||
|
|
||||||
// send them an appearance update
|
// send them an appearance update
|
||||||
if send_appearance_update {
|
if send_appearance_update {
|
||||||
let ipc;
|
let main_weapon_id;
|
||||||
|
let model_ids;
|
||||||
{
|
{
|
||||||
let mut game_data = self.gamedata.lock().unwrap();
|
let mut game_data = self.gamedata.lock().unwrap();
|
||||||
let inventory = &self.player_data.inventory;
|
let inventory = &self.player_data.inventory;
|
||||||
|
|
||||||
ipc = ServerZoneIpcSegment {
|
main_weapon_id = inventory.get_main_weapon_id(&mut game_data);
|
||||||
op_code: ServerZoneIpcType::Equip,
|
model_ids = inventory.get_model_ids(&mut game_data);
|
||||||
timestamp: timestamp_secs(),
|
|
||||||
data: ServerZoneIpcData::Equip(Equip {
|
|
||||||
main_weapon_id: inventory.get_main_weapon_id(&mut game_data),
|
|
||||||
sub_weapon_id: 0,
|
|
||||||
crest_enable: 0,
|
|
||||||
pattern_invalid: 0,
|
|
||||||
model_ids: inventory.get_model_ids(&mut game_data),
|
|
||||||
}),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.send_segment(PacketSegment {
|
self.handle
|
||||||
source_actor: self.player_data.actor_id,
|
.send(ToServer::Equip(
|
||||||
target_actor: self.player_data.actor_id,
|
self.id,
|
||||||
segment_type: SegmentType::Ipc,
|
self.player_data.actor_id,
|
||||||
data: SegmentData::Ipc { data: ipc },
|
main_weapon_id,
|
||||||
})
|
model_ids,
|
||||||
.await;
|
))
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn update_equip(&mut self, actor_id: u32, main_weapon_id: u64, model_ids: [u32; 10]) {
|
||||||
|
let ipc = ServerZoneIpcSegment {
|
||||||
|
op_code: ServerZoneIpcType::Equip,
|
||||||
|
timestamp: timestamp_secs(),
|
||||||
|
data: ServerZoneIpcData::Equip(Equip {
|
||||||
|
main_weapon_id,
|
||||||
|
model_ids,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
self.send_segment(PacketSegment {
|
||||||
|
source_actor: actor_id,
|
||||||
|
target_actor: self.player_data.actor_id,
|
||||||
|
segment_type: SegmentType::Ipc,
|
||||||
|
data: SegmentData::Ipc { data: ipc },
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn send_message(&mut self, message: &str) {
|
pub async fn send_message(&mut self, message: &str) {
|
||||||
let ipc = ServerZoneIpcSegment {
|
let ipc = ServerZoneIpcSegment {
|
||||||
op_code: ServerZoneIpcType::ServerChatMessage,
|
op_code: ServerZoneIpcType::ServerChatMessage,
|
||||||
|
|
|
@ -62,6 +62,10 @@ impl Instance {
|
||||||
self.actors.get(&id)
|
self.actors.get(&id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_actor_mut(&mut self, id: ObjectId) -> Option<&mut NetworkedActor> {
|
||||||
|
self.actors.get_mut(&id)
|
||||||
|
}
|
||||||
|
|
||||||
fn insert_npc(&mut self, id: ObjectId, spawn: NpcSpawn) {
|
fn insert_npc(&mut self, id: ObjectId, spawn: NpcSpawn) {
|
||||||
self.actors.insert(id, NetworkedActor::Npc(spawn));
|
self.actors.insert(id, NetworkedActor::Npc(spawn));
|
||||||
}
|
}
|
||||||
|
@ -132,7 +136,7 @@ pub async fn server_main_loop(mut recv: Receiver<ToServer>) -> Result<(), std::i
|
||||||
data.clients
|
data.clients
|
||||||
.insert(handle.id, (handle, ClientState::default()));
|
.insert(handle.id, (handle, ClientState::default()));
|
||||||
}
|
}
|
||||||
ToServer::ZoneLoaded(from_id, zone_id) => {
|
ToServer::ZoneLoaded(from_id, zone_id, common_spawn) => {
|
||||||
let mut data = data.lock().unwrap();
|
let mut data = data.lock().unwrap();
|
||||||
|
|
||||||
// create a new instance if necessary
|
// create a new instance if necessary
|
||||||
|
@ -181,7 +185,7 @@ pub async fn server_main_loop(mut recv: Receiver<ToServer>) -> Result<(), std::i
|
||||||
instance.actors.insert(
|
instance.actors.insert(
|
||||||
ObjectId(client.actor_id),
|
ObjectId(client.actor_id),
|
||||||
NetworkedActor::Player(NpcSpawn {
|
NetworkedActor::Player(NpcSpawn {
|
||||||
common: client.common.clone(),
|
common: common_spawn.clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -208,7 +212,7 @@ pub async fn server_main_loop(mut recv: Receiver<ToServer>) -> Result<(), std::i
|
||||||
spawn_index: 0,
|
spawn_index: 0,
|
||||||
},
|
},
|
||||||
NpcSpawn {
|
NpcSpawn {
|
||||||
common: client.common.clone(),
|
common: common_spawn.clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -601,6 +605,39 @@ pub async fn server_main_loop(mut recv: Receiver<ToServer>) -> Result<(), std::i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ToServer::Equip(_from_id, from_actor_id, main_weapon_id, model_ids) => {
|
||||||
|
// update their stored state so it's correctly sent on new spawns
|
||||||
|
{
|
||||||
|
let mut data = data.lock().unwrap();
|
||||||
|
|
||||||
|
let Some(instance) = data.find_actor_instance_mut(from_actor_id) else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(actor) = instance.find_actor_mut(ObjectId(from_actor_id)) else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
let NetworkedActor::Player(player) = actor else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
player.common.main_weapon_model = main_weapon_id;
|
||||||
|
player.common.models = model_ids.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inform all clients about their new equipped model ids
|
||||||
|
let mut data = data.lock().unwrap();
|
||||||
|
for (id, (handle, _)) in &mut data.clients {
|
||||||
|
let id = *id;
|
||||||
|
|
||||||
|
let msg = FromServer::ActorEquip(from_actor_id, main_weapon_id, model_ids);
|
||||||
|
|
||||||
|
if handle.send(msg).is_err() {
|
||||||
|
to_remove.push(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
ToServer::Disconnected(from_id) => {
|
ToServer::Disconnected(from_id) => {
|
||||||
let mut data = data.lock().unwrap();
|
let mut data = data.lock().unwrap();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue