location overhaul
This commit is contained in:
parent
6e1cc9a2c0
commit
161c0c94f8
132
src/ship/character.rs
Normal file
132
src/ship/character.rs
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
use crate::common::leveltable::CharacterStats;
|
||||||
|
use libpso::character::character;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct CharacterBuilder<'a> {
|
||||||
|
character: Option<&'a character::Character>,
|
||||||
|
stats: Option<&'a CharacterStats>,
|
||||||
|
level: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<'a> CharacterBuilder<'a> {
|
||||||
|
pub fn new() -> CharacterBuilder<'a> {
|
||||||
|
CharacterBuilder {
|
||||||
|
character: None,
|
||||||
|
stats: None,
|
||||||
|
level: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn character(self, character: &'a character::Character) -> CharacterBuilder<'a> {
|
||||||
|
CharacterBuilder {
|
||||||
|
character: Some(character),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stats(self, stats: &'a CharacterStats) -> CharacterBuilder<'a> {
|
||||||
|
CharacterBuilder {
|
||||||
|
stats: Some(stats),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn level(self, level: u32) -> CharacterBuilder<'a> {
|
||||||
|
CharacterBuilder {
|
||||||
|
level: Some(level),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> character::Character {
|
||||||
|
let character = self.character.unwrap();
|
||||||
|
let stats = self.stats.unwrap();
|
||||||
|
let level = self.level.unwrap();
|
||||||
|
character::Character {
|
||||||
|
hp: stats.hp,
|
||||||
|
atp: stats.atp,
|
||||||
|
mst: stats.mst,
|
||||||
|
evp: stats.evp,
|
||||||
|
dfp: stats.dfp,
|
||||||
|
ata: stats.ata,
|
||||||
|
lck: stats.lck,
|
||||||
|
level: level,
|
||||||
|
..*character
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct FullCharacterBuilder<'a> {
|
||||||
|
character: Option<&'a character::Character>,
|
||||||
|
inventory: Option<&'a [character::InventoryItem; 30]>,
|
||||||
|
inventory_len: Option<usize>,
|
||||||
|
key_config: Option<&'a [u8; 0x16C]>,
|
||||||
|
joystick_config: Option<&'a [u8; 0x38]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<'a> FullCharacterBuilder<'a> {
|
||||||
|
pub fn new() -> FullCharacterBuilder<'a> {
|
||||||
|
FullCharacterBuilder {
|
||||||
|
character: None,
|
||||||
|
inventory: None,
|
||||||
|
inventory_len: None,
|
||||||
|
key_config: None,
|
||||||
|
joystick_config: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn character(self, character: &'a character::Character) -> FullCharacterBuilder<'a> {
|
||||||
|
FullCharacterBuilder {
|
||||||
|
character: Some(character),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inventory(self, inventory: &'a [character::InventoryItem; 30], len: usize) -> FullCharacterBuilder<'a> {
|
||||||
|
FullCharacterBuilder {
|
||||||
|
inventory: Some(inventory),
|
||||||
|
inventory_len: Some(len),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn key_config(self, key_config: &'a [u8; 0x16C]) -> FullCharacterBuilder<'a> {
|
||||||
|
FullCharacterBuilder {
|
||||||
|
key_config: Some(key_config),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn joystick_config(self, joystick_config: &'a [u8; 0x38]) -> FullCharacterBuilder<'a> {
|
||||||
|
FullCharacterBuilder {
|
||||||
|
joystick_config: Some(joystick_config),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> character::FullCharacter {
|
||||||
|
let character = self.character.unwrap();
|
||||||
|
let inventory = self.inventory.unwrap();
|
||||||
|
let inventory_len = self.inventory_len.unwrap();
|
||||||
|
let key_config = self.key_config.unwrap();
|
||||||
|
let joystick_config = self.joystick_config.unwrap();
|
||||||
|
|
||||||
|
character::FullCharacter {
|
||||||
|
character: *character,
|
||||||
|
inventory: character::Inventory {
|
||||||
|
item_count: inventory_len as u8,
|
||||||
|
items: *inventory,
|
||||||
|
..character::Inventory::default()
|
||||||
|
},
|
||||||
|
key_team_config: character::KeyTeamConfig {
|
||||||
|
key_config: *key_config,
|
||||||
|
joystick_config: *joystick_config,
|
||||||
|
..character::KeyTeamConfig::default()
|
||||||
|
},
|
||||||
|
..character::FullCharacter::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,24 +1,31 @@
|
|||||||
|
use std::time::SystemTime;
|
||||||
use crate::common::serverstate::ClientId;
|
use crate::common::serverstate::ClientId;
|
||||||
// TODO: room passwords?
|
// TODO: room passwords?
|
||||||
// TODO: remove clients from areas (or upon insert, remove that id from anywhere else)
|
// TODO: remove clients from areas (or upon insert, remove that id from anywhere else)
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct ClientArea<const N: usize> {
|
pub struct AreaClient {
|
||||||
clients: [Option<ClientId>; N],
|
client_id: ClientId,
|
||||||
|
time_join: SystemTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize> ClientArea<{N}> {
|
|
||||||
pub fn new() -> ClientArea<{N}> {
|
#[derive(Copy, Clone)]
|
||||||
let mut clients: [std::mem::MaybeUninit<Option<ClientId>>; N] = unsafe {
|
pub struct InnerClientArea<const N: usize> {
|
||||||
|
clients: [Option<AreaClient>; N],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> InnerClientArea<{N}> {
|
||||||
|
pub fn new() -> InnerClientArea<{N}> {
|
||||||
|
let mut clients: [std::mem::MaybeUninit<Option<AreaClient>>; N] = unsafe {
|
||||||
std::mem::MaybeUninit::uninit().assume_init()
|
std::mem::MaybeUninit::uninit().assume_init()
|
||||||
};
|
};
|
||||||
for i in clients.iter_mut() {
|
for i in clients.iter_mut() {
|
||||||
i.write(None);
|
i.write(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientArea {
|
InnerClientArea {
|
||||||
clients: unsafe { (&clients as *const _ as *const [Option<ClientId>; N]).read()}
|
clients: unsafe { (&clients as *const _ as *const [Option<AreaClient>; N]).read()}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,38 +33,136 @@ impl<const N: usize> ClientArea<{N}> {
|
|||||||
fn add(&mut self, id: ClientId) -> Option<usize> {
|
fn add(&mut self, id: ClientId) -> Option<usize> {
|
||||||
for (i, client) in self.clients.iter_mut().enumerate() {
|
for (i, client) in self.clients.iter_mut().enumerate() {
|
||||||
if client.is_none() {
|
if client.is_none() {
|
||||||
*client = Some(id);
|
*client = Some(AreaClient{
|
||||||
|
client_id: id,
|
||||||
|
time_join: SystemTime::now(),
|
||||||
|
});
|
||||||
return Some(i);
|
return Some(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
fn remove(&mut self, id: ClientId) {
|
fn remove(&mut self, id: ClientId) {
|
||||||
for client in self.clients.iter_mut() {
|
for areaclient in self.clients.iter_mut() {
|
||||||
if *client == Some(id) {
|
if let Some(client) = *areaclient {
|
||||||
*client = None
|
if client.client_id == id {
|
||||||
|
*areaclient = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Lobby = ClientArea<12>;
|
fn contains(&self, id: ClientId) -> bool {
|
||||||
pub type Room = ClientArea<4>;
|
self.clients.iter()
|
||||||
|
.filter(|k| k.is_some())
|
||||||
|
.map(|k| k.unwrap() )
|
||||||
|
.fold(false, |acc, k| {
|
||||||
|
if acc {
|
||||||
|
acc
|
||||||
|
}
|
||||||
|
else if k.client_id == id {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type LobbyId = usize;
|
pub type LobbyId = usize;
|
||||||
pub type RoomId = usize;
|
pub type RoomId = usize;
|
||||||
|
|
||||||
|
pub type Lobby = InnerClientArea<12>;
|
||||||
|
pub type Room = InnerClientArea<4>;
|
||||||
|
|
||||||
pub struct ClientLocation {
|
pub struct ClientLocation {
|
||||||
lobbies: [Lobby; 15],
|
lobbies: [Lobby; 15],
|
||||||
rooms: [Option<Room>; 128],
|
rooms: [Option<Room>; 128],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait ClientArea<'a> {
|
||||||
|
fn clients(&'a self) -> std::slice::Iter<'_, Option<AreaClient>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<'a> ClientArea<'a> for Lobby {
|
||||||
|
fn clients(&'a self) -> std::slice::Iter<'_, Option<AreaClient>> {
|
||||||
|
self.clients.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ClientArea<'a> for Room {
|
||||||
|
fn clients(&'a self) -> std::slice::Iter<'_, Option<AreaClient>> {
|
||||||
|
self.clients.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ClientAtLocation {
|
||||||
|
pub client_id: ClientId,
|
||||||
|
pub index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Area<'a> {
|
||||||
|
area: &'a dyn ClientArea<'a>,
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Area<'a> {
|
||||||
|
fn new(area: &'a dyn ClientArea<'a>, index: usize) -> Area<'a> {
|
||||||
|
Area {
|
||||||
|
area: area,
|
||||||
|
index: index,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn clients(&'a self) -> Vec<ClientAtLocation> {
|
||||||
|
self.area.clients()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(_i, k)| k.is_some())
|
||||||
|
.map(|(i, k)| (i, k.unwrap()) )
|
||||||
|
.map(|(i, k)| ClientAtLocation {
|
||||||
|
client_id: k.client_id,
|
||||||
|
index: i
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
// TODO: Result in cases where no one is in the area?
|
||||||
|
pub fn leader(&self) -> ClientAtLocation {
|
||||||
|
self.area.clients()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(i, k)| k.is_some())
|
||||||
|
.map(|(i, k)| (i, k.unwrap()) )
|
||||||
|
.fold((ClientAtLocation {
|
||||||
|
client_id: ClientId(0),
|
||||||
|
index: 0
|
||||||
|
}, SystemTime::UNIX_EPOCH),
|
||||||
|
|(acc, time), (i, k)| {
|
||||||
|
if time > k.time_join {
|
||||||
|
(ClientAtLocation {
|
||||||
|
client_id: k.client_id,
|
||||||
|
index: i,
|
||||||
|
}, k.time_join)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
(acc, time)
|
||||||
|
}
|
||||||
|
}).0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn id(&self) -> usize {
|
||||||
|
self.index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum JoinRoomError {
|
pub enum JoinRoomError {
|
||||||
RoomDoesNotExist,
|
RoomDoesNotExist,
|
||||||
RoomFull,
|
RoomFull,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum JoinLobbyError {
|
pub enum JoinLobbyError {
|
||||||
LobbyDoesNotExist,
|
LobbyDoesNotExist,
|
||||||
LobbyFull,
|
LobbyFull,
|
||||||
@ -87,21 +192,21 @@ impl ClientLocation {
|
|||||||
.ok_or(JoinRoomError::RoomFull)
|
.ok_or(JoinRoomError::RoomFull)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_client_neighbors(&self, id: ClientId) -> Vec<ClientId> {
|
pub fn get_area_by_user(&self, id: ClientId) -> Area {
|
||||||
for lobby in self.lobbies.iter() {
|
for (i, lobby) in self.lobbies.iter().enumerate() {
|
||||||
if lobby.clients.contains(&Some(id)) {
|
if lobby.contains(id) {
|
||||||
return lobby.clients.iter().filter(|c| c.is_some()).map(|c| c.unwrap()).collect();
|
return Area::new(lobby, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for room in self.rooms.iter() {
|
for (i, room) in self.rooms.iter().enumerate() {
|
||||||
if let Some(room) = room {
|
if let Some(room) = room {
|
||||||
if room.clients.contains(&Some(id)) {
|
if room.contains(id){
|
||||||
return room.clients.iter().filter(|c| c.is_some()).map(|c| c.unwrap()).collect();
|
return Area::new(room, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!()
|
panic!("client is not in a room/lobby")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
pub mod ship;
|
pub mod ship;
|
||||||
pub mod location;
|
pub mod location;
|
||||||
|
pub mod character;
|
||||||
|
@ -20,6 +20,7 @@ use crate::entity::character::Character;
|
|||||||
use crate::entity::item::ItemLocation;
|
use crate::entity::item::ItemLocation;
|
||||||
use crate::login::login::get_login_status;
|
use crate::login::login::get_login_status;
|
||||||
use crate::ship::location::ClientLocation;
|
use crate::ship::location::ClientLocation;
|
||||||
|
use crate::ship::character::{CharacterBuilder, FullCharacterBuilder};
|
||||||
|
|
||||||
pub const SHIP_PORT: u16 = 23423;
|
pub const SHIP_PORT: u16 = 23423;
|
||||||
|
|
||||||
@ -143,17 +144,7 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
|||||||
let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
client.block = pkt.item as u32;
|
client.block = pkt.item as u32;
|
||||||
|
|
||||||
let mut fc = character::FullCharacter::default();
|
let (level, stats) = self.level_table.get_stats_from_exp(character::Class::from(client.character.character.ch_class), client.character.character.exp);
|
||||||
fc.character = client.character.character;
|
|
||||||
let stats = self.level_table.get_stats_from_exp(character::Class::from(fc.character.ch_class), fc.character.exp);
|
|
||||||
fc.character.hp = stats.1.hp;
|
|
||||||
fc.character.atp = stats.1.atp;
|
|
||||||
fc.character.mst = stats.1.mst;
|
|
||||||
fc.character.evp = stats.1.evp;
|
|
||||||
fc.character.dfp = stats.1.dfp;
|
|
||||||
fc.character.ata = stats.1.ata;
|
|
||||||
fc.character.lck = stats.1.lck;
|
|
||||||
fc.character.level = stats.0 - 1;
|
|
||||||
|
|
||||||
let items = self.entity_gateway.get_items_by_character(&client.character);
|
let items = self.entity_gateway.get_items_by_character(&client.character);
|
||||||
let (mut inventory, inv_len) = items
|
let (mut inventory, inv_len) = items
|
||||||
@ -173,11 +164,17 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
|||||||
inv[index].item_id = item.id;
|
inv[index].item_id = item.id;
|
||||||
(inv, len+1)
|
(inv, len+1)
|
||||||
});
|
});
|
||||||
fc.inventory.items = inventory;
|
let fc = FullCharacterBuilder::new()
|
||||||
fc.inventory.item_count = inv_len;
|
.character(&CharacterBuilder::new()
|
||||||
|
.character(&client.character.character)
|
||||||
fc.key_team_config.key_config = client.settings.settings.key_config;
|
.stats(&stats)
|
||||||
fc.key_team_config.joystick_config = client.settings.settings.joystick_config;
|
.level(level)
|
||||||
|
.build())
|
||||||
|
.inventory(&inventory, inv_len)
|
||||||
|
.key_config(&client.settings.settings.key_config)
|
||||||
|
.joystick_config(&client.settings.settings.joystick_config)
|
||||||
|
//.team_config(&joystick_config)
|
||||||
|
.build();
|
||||||
|
|
||||||
Ok(vec![
|
Ok(vec![
|
||||||
SendShipPacket::FullCharacter(FullCharacter {
|
SendShipPacket::FullCharacter(FullCharacter {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user