2025-03-15 20:36:39 -04:00
|
|
|
use tokio::net::TcpStream;
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
common::timestamp_secs,
|
|
|
|
packet::{
|
2025-03-16 17:43:29 -04:00
|
|
|
CompressionType, ConnectionType, PacketSegment, PacketState, SegmentType, parse_packet,
|
2025-03-15 20:36:39 -04:00
|
|
|
send_packet,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2025-03-16 17:43:29 -04:00
|
|
|
use super::{
|
|
|
|
Zone,
|
|
|
|
ipc::{
|
|
|
|
ActorSetPos, ClientZoneIpcSegment, InitZone, Position, ServerZoneIpcData,
|
2025-03-18 23:48:00 -04:00
|
|
|
ServerZoneIpcSegment, ServerZoneIpcType, UpdateClassInfo, WeatherChange,
|
2025-03-16 17:43:29 -04:00
|
|
|
},
|
|
|
|
};
|
2025-03-15 20:36:39 -04:00
|
|
|
|
2025-03-21 19:56:16 -04:00
|
|
|
#[derive(Debug, Default)]
|
|
|
|
pub struct PlayerData {
|
|
|
|
pub actor_id: u32,
|
|
|
|
pub content_id: u64,
|
|
|
|
pub account_id: u32,
|
|
|
|
}
|
|
|
|
|
2025-03-17 17:02:53 -04:00
|
|
|
/// Represents a single connection between an instance of the client and the world server
|
2025-03-15 20:36:39 -04:00
|
|
|
pub struct ZoneConnection {
|
|
|
|
pub socket: TcpStream,
|
|
|
|
|
2025-03-16 17:43:29 -04:00
|
|
|
pub state: PacketState,
|
2025-03-21 19:56:16 -04:00
|
|
|
pub player_data: PlayerData,
|
2025-03-15 20:49:07 -04:00
|
|
|
|
|
|
|
pub zone: Zone,
|
2025-03-16 14:07:56 -04:00
|
|
|
pub spawn_index: u8,
|
2025-03-15 20:36:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ZoneConnection {
|
2025-03-16 17:43:29 -04:00
|
|
|
pub async fn parse_packet(
|
|
|
|
&mut self,
|
|
|
|
data: &[u8],
|
|
|
|
) -> (Vec<PacketSegment<ClientZoneIpcSegment>>, ConnectionType) {
|
2025-03-15 20:36:39 -04:00
|
|
|
parse_packet(data, &mut self.state).await
|
|
|
|
}
|
|
|
|
|
2025-03-16 17:43:29 -04:00
|
|
|
pub async fn send_segment(&mut self, segment: PacketSegment<ServerZoneIpcSegment>) {
|
2025-03-15 20:36:39 -04:00
|
|
|
send_packet(
|
|
|
|
&mut self.socket,
|
|
|
|
&mut self.state,
|
2025-03-18 19:49:52 -04:00
|
|
|
ConnectionType::Zone,
|
2025-03-15 20:36:39 -04:00
|
|
|
CompressionType::Oodle,
|
2025-03-18 19:49:52 -04:00
|
|
|
&[segment],
|
2025-03-15 20:36:39 -04:00
|
|
|
)
|
|
|
|
.await;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn set_player_position(&mut self, position: Position) {
|
|
|
|
// set pos
|
|
|
|
{
|
2025-03-16 17:43:29 -04:00
|
|
|
let ipc = ServerZoneIpcSegment {
|
|
|
|
op_code: ServerZoneIpcType::ActorSetPos,
|
2025-03-15 20:36:39 -04:00
|
|
|
timestamp: timestamp_secs(),
|
2025-03-16 17:43:29 -04:00
|
|
|
data: ServerZoneIpcData::ActorSetPos(ActorSetPos {
|
2025-03-15 20:36:39 -04:00
|
|
|
unk: 0x020fa3b8,
|
|
|
|
position,
|
|
|
|
..Default::default()
|
|
|
|
}),
|
2025-03-16 14:07:56 -04:00
|
|
|
..Default::default()
|
2025-03-15 20:36:39 -04:00
|
|
|
};
|
|
|
|
|
2025-03-18 19:49:52 -04:00
|
|
|
self.send_segment(PacketSegment {
|
2025-03-21 19:56:16 -04:00
|
|
|
source_actor: self.player_data.actor_id,
|
|
|
|
target_actor: self.player_data.actor_id,
|
2025-03-15 20:36:39 -04:00
|
|
|
segment_type: SegmentType::Ipc { data: ipc },
|
2025-03-18 19:49:52 -04:00
|
|
|
})
|
2025-03-15 20:36:39 -04:00
|
|
|
.await;
|
|
|
|
}
|
|
|
|
}
|
2025-03-15 20:49:07 -04:00
|
|
|
|
|
|
|
pub async fn change_zone(&mut self, new_zone_id: u16) {
|
|
|
|
self.zone = Zone::load(new_zone_id);
|
|
|
|
|
|
|
|
// Player Class Info
|
|
|
|
{
|
2025-03-16 17:43:29 -04:00
|
|
|
let ipc = ServerZoneIpcSegment {
|
|
|
|
op_code: ServerZoneIpcType::UpdateClassInfo,
|
2025-03-15 20:49:07 -04:00
|
|
|
timestamp: timestamp_secs(),
|
2025-03-16 17:43:29 -04:00
|
|
|
data: ServerZoneIpcData::UpdateClassInfo(UpdateClassInfo {
|
2025-03-15 20:49:07 -04:00
|
|
|
class_id: 35,
|
|
|
|
unknown: 1,
|
|
|
|
synced_level: 90,
|
|
|
|
class_level: 90,
|
|
|
|
..Default::default()
|
|
|
|
}),
|
2025-03-16 14:07:56 -04:00
|
|
|
..Default::default()
|
2025-03-15 20:49:07 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
self.send_segment(PacketSegment {
|
2025-03-21 19:56:16 -04:00
|
|
|
source_actor: self.player_data.actor_id,
|
|
|
|
target_actor: self.player_data.actor_id,
|
2025-03-15 20:49:07 -04:00
|
|
|
segment_type: SegmentType::Ipc { data: ipc },
|
|
|
|
})
|
|
|
|
.await;
|
|
|
|
}
|
|
|
|
|
|
|
|
// link shell information
|
|
|
|
{
|
2025-03-16 17:43:29 -04:00
|
|
|
let ipc = ServerZoneIpcSegment {
|
|
|
|
op_code: ServerZoneIpcType::LinkShellInformation,
|
2025-03-15 20:49:07 -04:00
|
|
|
timestamp: timestamp_secs(),
|
2025-03-16 17:43:29 -04:00
|
|
|
data: ServerZoneIpcData::LinkShellInformation { unk: [0; 456] },
|
2025-03-16 14:07:56 -04:00
|
|
|
..Default::default()
|
2025-03-15 20:49:07 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
self.send_segment(PacketSegment {
|
2025-03-21 19:56:16 -04:00
|
|
|
source_actor: self.player_data.actor_id,
|
|
|
|
target_actor: self.player_data.actor_id,
|
2025-03-15 20:49:07 -04:00
|
|
|
segment_type: SegmentType::Ipc { data: ipc },
|
|
|
|
})
|
|
|
|
.await;
|
|
|
|
}
|
|
|
|
|
2025-03-16 14:07:56 -04:00
|
|
|
// TODO: send unk16?
|
2025-03-15 20:49:07 -04:00
|
|
|
|
|
|
|
// Init Zone
|
|
|
|
{
|
2025-03-16 17:43:29 -04:00
|
|
|
let ipc = ServerZoneIpcSegment {
|
|
|
|
op_code: ServerZoneIpcType::InitZone,
|
2025-03-15 20:49:07 -04:00
|
|
|
timestamp: timestamp_secs(),
|
2025-03-16 17:43:29 -04:00
|
|
|
data: ServerZoneIpcData::InitZone(InitZone {
|
2025-03-16 14:07:56 -04:00
|
|
|
server_id: 0,
|
2025-03-15 20:49:07 -04:00
|
|
|
zone_id: self.zone.id,
|
|
|
|
weather_id: 1,
|
|
|
|
..Default::default()
|
|
|
|
}),
|
2025-03-16 14:07:56 -04:00
|
|
|
..Default::default()
|
2025-03-15 20:49:07 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
self.send_segment(PacketSegment {
|
2025-03-21 19:56:16 -04:00
|
|
|
source_actor: self.player_data.actor_id,
|
|
|
|
target_actor: self.player_data.actor_id,
|
2025-03-15 20:49:07 -04:00
|
|
|
segment_type: SegmentType::Ipc { data: ipc },
|
|
|
|
})
|
|
|
|
.await;
|
|
|
|
}
|
|
|
|
}
|
2025-03-16 14:07:56 -04:00
|
|
|
|
2025-03-18 23:48:00 -04:00
|
|
|
pub async fn change_weather(&mut self, new_weather_id: u16) {
|
|
|
|
let ipc = ServerZoneIpcSegment {
|
|
|
|
op_code: ServerZoneIpcType::WeatherChange,
|
|
|
|
timestamp: timestamp_secs(),
|
|
|
|
data: ServerZoneIpcData::WeatherChange(WeatherChange {
|
|
|
|
weather_id: new_weather_id,
|
|
|
|
transistion_time: 1.0,
|
|
|
|
}),
|
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
|
|
|
|
self.send_segment(PacketSegment {
|
2025-03-21 19:56:16 -04:00
|
|
|
source_actor: self.player_data.actor_id,
|
|
|
|
target_actor: self.player_data.actor_id,
|
2025-03-18 23:48:00 -04:00
|
|
|
segment_type: SegmentType::Ipc { data: ipc },
|
|
|
|
})
|
|
|
|
.await;
|
|
|
|
}
|
|
|
|
|
2025-03-16 14:07:56 -04:00
|
|
|
pub fn get_free_spawn_index(&mut self) -> u8 {
|
|
|
|
self.spawn_index += 1;
|
2025-03-16 14:09:12 -04:00
|
|
|
self.spawn_index
|
2025-03-16 14:07:56 -04:00
|
|
|
}
|
2025-03-15 20:36:39 -04:00
|
|
|
}
|