break out the rest of everything into its own crate
This commit is contained in:
parent
8135d673eb
commit
cd1476796e
24
Cargo.toml
24
Cargo.toml
@ -6,11 +6,19 @@ edition = "2021"
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
"client",
|
||||
"drops",
|
||||
"entity",
|
||||
"items",
|
||||
"location",
|
||||
"maps",
|
||||
"networking",
|
||||
"pktbuilder",
|
||||
"quests",
|
||||
"room",
|
||||
"shops",
|
||||
"stats",
|
||||
"trade",
|
||||
]
|
||||
|
||||
[workspace.dependencies]
|
||||
@ -19,6 +27,14 @@ maps = { path = "./maps" }
|
||||
networking = { path = "./networking" }
|
||||
shops = { path = "./shops" }
|
||||
stats = { path = "./stats" }
|
||||
items = { path = "./items" }
|
||||
pktbuilder = { path = "./pktbuilder" }
|
||||
quests = { path = "./quests" }
|
||||
location = { path = "./location" }
|
||||
client = { path = "./client" }
|
||||
drops = { path = "./drops" }
|
||||
trade = { path = "./trade" }
|
||||
room = { path = "./room" }
|
||||
|
||||
libpso = { git = "http://git.sharnoth.com/jake/libpso" }
|
||||
|
||||
@ -56,6 +72,14 @@ maps = { workspace = true }
|
||||
networking = { workspace = true }
|
||||
shops = { workspace = true }
|
||||
stats = { workspace = true }
|
||||
items = { workspace = true }
|
||||
pktbuilder = { workspace = true }
|
||||
quests = { workspace = true }
|
||||
location = { workspace = true }
|
||||
client = { workspace = true }
|
||||
drops = { workspace = true }
|
||||
trade = { workspace = true }
|
||||
room = { workspace = true }
|
||||
|
||||
libpso = { workspace = true }
|
||||
|
||||
|
20
client/Cargo.toml
Normal file
20
client/Cargo.toml
Normal file
@ -0,0 +1,20 @@
|
||||
[package]
|
||||
name = "client"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
|
||||
[dependencies]
|
||||
entity = { workspace = true }
|
||||
maps = { workspace = true }
|
||||
networking = { workspace = true }
|
||||
shops = { workspace = true }
|
||||
items = { workspace = true }
|
||||
|
||||
libpso = { workspace = true }
|
||||
|
||||
async-std = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
chrono = { workspace = true }
|
@ -6,17 +6,23 @@ use futures::future::BoxFuture;
|
||||
use libpso::packet::ship::*;
|
||||
use libpso::packet::login::Session;
|
||||
|
||||
use crate::common::serverstate::ClientId;
|
||||
use networking::serverstate::ClientId;
|
||||
use entity::account::{UserAccountEntity, UserSettingsEntity};
|
||||
use entity::character::CharacterEntity;
|
||||
use entity::item;
|
||||
|
||||
use crate::ship::ship::ShipError;
|
||||
use crate::ship::items;
|
||||
use items;
|
||||
use maps::area::MapArea;
|
||||
use shops::{WeaponShopItem, ToolShopItem, ArmorShopItem};
|
||||
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum ClientError {
|
||||
#[error("not found {0}")]
|
||||
NotFound(ClientId),
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Clients(Arc<RwLock<HashMap<ClientId, RwLock<ClientState>>>>);
|
||||
|
||||
@ -46,7 +52,7 @@ impl Clients {
|
||||
.await;
|
||||
let client = clients
|
||||
.get(&client_id)
|
||||
.ok_or_else(|| ShipError::ClientNotFound(client_id))?
|
||||
.ok_or_else(|| ClientError::NotFound(client_id))?
|
||||
.read()
|
||||
.await;
|
||||
|
||||
@ -69,7 +75,7 @@ impl Clients {
|
||||
for (cindex, client_id) in client_ids.iter().enumerate() {
|
||||
let c = clients
|
||||
.get(client_id)
|
||||
.ok_or_else(|| ShipError::ClientNotFound(*client_id))?
|
||||
.ok_or_else(|| ClientError::NotFound(*client_id))?
|
||||
.read()
|
||||
.await;
|
||||
client_states[cindex].write(c);
|
||||
@ -95,7 +101,7 @@ impl Clients {
|
||||
.await;
|
||||
let mut client = clients
|
||||
.get(&client_id)
|
||||
.ok_or_else(|| ShipError::ClientNotFound(client_id))?
|
||||
.ok_or_else(|| ClientError::NotFound(client_id))?
|
||||
.write()
|
||||
.await;
|
||||
|
3
client/src/lib.rs
Normal file
3
client/src/lib.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod client;
|
||||
|
||||
pub use client::*;
|
17
drops/Cargo.toml
Normal file
17
drops/Cargo.toml
Normal file
@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "drops"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
|
||||
[dependencies]
|
||||
entity = { workspace = true }
|
||||
maps = { workspace = true }
|
||||
stats = { workspace = true }
|
||||
|
||||
rand = { workspace = true }
|
||||
rand_chacha = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
enum-utils = { workspace = true }
|
||||
toml = { workspace = true }
|
||||
chrono = { workspace = true }
|
@ -5,14 +5,14 @@ use serde::{Serialize, Deserialize};
|
||||
use entity::character::SectionID;
|
||||
use maps::room::{Difficulty, Episode};
|
||||
use maps::area::MapArea;
|
||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||
use crate::{ItemDropType, load_data_file};
|
||||
use maps::object::{MapObject, MapObjectType, FixedBoxDropType};
|
||||
use crate::ship::drops::rare_drop_table::{RareDropTable, RareDropItem};
|
||||
use crate::ship::drops::generic_weapon::GenericWeaponTable;
|
||||
use crate::ship::drops::generic_armor::GenericArmorTable;
|
||||
use crate::ship::drops::generic_shield::GenericShieldTable;
|
||||
use crate::ship::drops::generic_unit::GenericUnitTable;
|
||||
use crate::ship::drops::tool_table::ToolTable;
|
||||
use crate::rare_drop_table::{RareDropTable, RareDropItem};
|
||||
use crate::generic_weapon::GenericWeaponTable;
|
||||
use crate::generic_armor::GenericArmorTable;
|
||||
use crate::generic_shield::GenericShieldTable;
|
||||
use crate::generic_unit::GenericUnitTable;
|
||||
use crate::tool_table::ToolTable;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct BoxDropRate {
|
@ -7,7 +7,7 @@ use entity::character::SectionID;
|
||||
use entity::item::armor::{ArmorType, Armor};
|
||||
use maps::room::{Difficulty, Episode};
|
||||
use maps::area::MapArea;
|
||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||
use crate::{ItemDropType, load_data_file};
|
||||
use stats::items::{armor_stats, ArmorStats};
|
||||
|
||||
|
@ -7,7 +7,7 @@ use entity::item::shield::{ShieldType, Shield};
|
||||
use entity::character::SectionID;
|
||||
use maps::room::{Difficulty, Episode};
|
||||
use maps::area::MapArea;
|
||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||
use crate::{ItemDropType, load_data_file};
|
||||
use stats::items::{shield_stats, ShieldStats};
|
||||
|
||||
|
@ -7,7 +7,7 @@ use entity::character::SectionID;
|
||||
use entity::item::unit::{UnitType, Unit, UnitModifier};
|
||||
use maps::room::{Difficulty, Episode};
|
||||
use maps::area::MapArea;
|
||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||
use crate::{ItemDropType, load_data_file};
|
||||
use stats::items::{unit_stats, UnitStats};
|
||||
|
||||
|
@ -8,7 +8,7 @@ use entity::character::SectionID;
|
||||
use entity::item::weapon::{Weapon, WeaponType, Attribute, WeaponAttribute, WeaponSpecial};
|
||||
use maps::room::{Difficulty, Episode};
|
||||
use maps::area::MapArea;
|
||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||
use crate::{ItemDropType, load_data_file};
|
||||
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
// to their drops
|
||||
|
||||
|
||||
mod drop_table;
|
||||
pub mod rare_drop_table;
|
||||
mod generic_weapon;
|
||||
mod generic_armor;
|
||||
@ -26,13 +25,13 @@ use maps::monster::MonsterType;
|
||||
use maps::room::{Difficulty, Episode};
|
||||
use maps::area::MapArea;
|
||||
use entity::character::SectionID;
|
||||
use crate::ship::drops::generic_weapon::GenericWeaponTable;
|
||||
use crate::ship::drops::generic_armor::GenericArmorTable;
|
||||
use crate::ship::drops::generic_shield::GenericShieldTable;
|
||||
use crate::ship::drops::generic_unit::GenericUnitTable;
|
||||
use crate::ship::drops::tool_table::ToolTable;
|
||||
use crate::ship::drops::rare_drop_table::RareDropTable;
|
||||
use crate::ship::drops::box_drop_table::BoxDropTable;
|
||||
use crate::generic_weapon::GenericWeaponTable;
|
||||
use crate::generic_armor::GenericArmorTable;
|
||||
use crate::generic_shield::GenericShieldTable;
|
||||
use crate::generic_unit::GenericUnitTable;
|
||||
use crate::tool_table::ToolTable;
|
||||
use crate::rare_drop_table::RareDropTable;
|
||||
use crate::box_drop_table::BoxDropTable;
|
||||
use maps::object::MapObject;
|
||||
use entity::item::{ItemType, weapon, armor, shield, unit, mag, tool, tech, esweapon};
|
||||
|
@ -11,10 +11,10 @@ use entity::character::SectionID;
|
||||
use maps::monster::MonsterType;
|
||||
use maps::room::{Difficulty, Episode};
|
||||
use maps::area::MapArea;
|
||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||
use crate::ship::drops::generic_weapon::AttributeTable;
|
||||
use crate::ship::drops::generic_armor::GenericArmorTable;
|
||||
use crate::ship::drops::generic_shield::GenericShieldTable;
|
||||
use crate::{ItemDropType, load_data_file};
|
||||
use crate::generic_weapon::AttributeTable;
|
||||
use crate::generic_armor::GenericArmorTable;
|
||||
use crate::generic_shield::GenericShieldTable;
|
||||
|
||||
type ItemParseFn = Box<dyn Fn(&String) -> Option<RareDropItem>>;
|
||||
|
@ -7,7 +7,7 @@ use entity::item::tech::{Technique, TechniqueDisk};
|
||||
use maps::room::{Difficulty, Episode};
|
||||
use maps::area::MapArea;
|
||||
use entity::character::SectionID;
|
||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||
use crate::{ItemDropType, load_data_file};
|
||||
|
||||
|
||||
|
@ -7,8 +7,8 @@ use entity::item::tool::{Tool, ToolType};
|
||||
use maps::room::{Difficulty, Episode};
|
||||
use maps::area::MapArea;
|
||||
use entity::character::SectionID;
|
||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||
use crate::ship::drops::tech_table::TechniqueTable;
|
||||
use crate::{ItemDropType, load_data_file};
|
||||
use crate::tech_table::TechniqueTable;
|
||||
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone, enum_utils::FromStr)]
|
25
items/Cargo.toml
Normal file
25
items/Cargo.toml
Normal file
@ -0,0 +1,25 @@
|
||||
[package]
|
||||
name = "items"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
entity = { workspace = true }
|
||||
maps = { workspace = true }
|
||||
shops = { workspace = true }
|
||||
location = { workspace = true }
|
||||
drops = { workspace = true }
|
||||
|
||||
libpso = { workspace = true }
|
||||
|
||||
enum-utils = { workspace = true }
|
||||
derive_more = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
rand_chacha = { workspace = true }
|
||||
async-recursion = { workspace = true }
|
||||
async-std = { workspace = true }
|
||||
async-trait = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
thiserror = { workspace = true }
|
@ -1,5 +1,5 @@
|
||||
// TODO: replace various u32s and usizes denoting item amounts for ItemAmount(u32) for consistency
|
||||
use crate::ship::items::ClientItemId;
|
||||
use crate::ClientItemId;
|
||||
use entity::item::{Meseta, ItemNote};
|
||||
use async_std::sync::Arc;
|
||||
use std::future::Future;
|
||||
@ -15,16 +15,15 @@ use entity::item::{ItemDetail, NewItemEntity, TradeId, ItemModifier};
|
||||
use entity::item::tool::Tool;
|
||||
use entity::room::RoomEntityId;
|
||||
use maps::area::MapArea;
|
||||
use crate::ship::ship::SendShipPacket;
|
||||
use crate::ship::items::state::{ItemStateProxy, ItemStateError, AddItemResult, StackedItemDetail, IndividualItemDetail};
|
||||
use crate::ship::items::bank::{BankItem, BankItemDetail};
|
||||
use crate::ship::items::inventory::{InventoryItem, InventoryItemDetail};
|
||||
use crate::ship::items::floor::{FloorItem, FloorItemDetail};
|
||||
use crate::ship::items::apply_item::{apply_item, ApplyItemAction};
|
||||
use crate::state::{ItemStateProxy, ItemStateError, AddItemResult, StackedItemDetail, IndividualItemDetail};
|
||||
use crate::bank::{BankItem, BankItemDetail};
|
||||
use crate::inventory::{InventoryItem, InventoryItemDetail};
|
||||
use crate::floor::{FloorItem, FloorItemDetail};
|
||||
use crate::apply_item::{apply_item, ApplyItemAction};
|
||||
use shops::ShopItem;
|
||||
use crate::ship::drops::{ItemDrop, ItemDropType};
|
||||
use crate::ship::packet::builder;
|
||||
use crate::ship::location::AreaClient;
|
||||
use drops::{ItemDrop, ItemDropType};
|
||||
//use crate::ship::packet::builder;
|
||||
use location::AreaClient;
|
||||
use maps::monster::MonsterType;
|
||||
|
||||
pub enum TriggerCreateItem {
|
||||
@ -32,6 +31,12 @@ pub enum TriggerCreateItem {
|
||||
No
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum CreateItem {
|
||||
Individual(AreaClient, ClientItemId, IndividualItemDetail),
|
||||
Stacked(AreaClient, ClientItemId, Tool, usize),
|
||||
}
|
||||
|
||||
pub(super) fn take_item_from_floor<'a, EG, TR>(
|
||||
character_id: CharacterEntityId,
|
||||
item_id: ClientItemId
|
||||
@ -1144,7 +1149,7 @@ pub(super) fn apply_item_action_packets<'a, EG, TR>(
|
||||
character_id: CharacterEntityId,
|
||||
area_client: AreaClient,
|
||||
) -> impl Fn((ItemStateProxy, TR), ApplyItemAction)
|
||||
-> BoxFuture<'a, Result<((ItemStateProxy, TR), Vec<SendShipPacket>), anyhow::Error>>
|
||||
-> BoxFuture<'a, Result<((ItemStateProxy, TR), Vec<CreateItem>), anyhow::Error>>
|
||||
where
|
||||
EG: EntityGateway,
|
||||
TR: EntityGatewayTransaction<ParentGateway = EG> + 'a,
|
||||
@ -1161,7 +1166,8 @@ where
|
||||
let (inventory_item_detail, create_item) = if item_detail.is_stackable() {
|
||||
let tool = item_detail.as_tool().ok_or_else(|| ItemStateError::NotATool(ClientItemId(0xFFFFFFFF)))?;
|
||||
|
||||
let create_item = builder::message::create_stacked_item(area_client, item_id, &tool, 1).map_err(|_err| ItemStateError::Dummy)?;
|
||||
//let create_item = builder::message::create_stacked_item(area_client, item_id, &tool, 1).map_err(|_err| ItemStateError::Dummy)?;
|
||||
let create_item = CreateItem::Stacked(area_client, item_id, tool.clone(), 1);
|
||||
let item_detail = StackedItemDetail {
|
||||
entity_ids: vec![new_item.id],
|
||||
tool
|
||||
@ -1173,7 +1179,8 @@ where
|
||||
entity_id: new_item.id,
|
||||
item: item_detail,
|
||||
};
|
||||
let create_item = builder::message::create_individual_item(area_client, item_id, &item_detail).map_err(|_err| ItemStateError::Dummy)?;
|
||||
//let create_item = builder::message::create_individual_item(area_client, item_id, &item_detail).map_err(|_err| ItemStateError::Dummy)?;
|
||||
let create_item = CreateItem::Individual(area_client, item_id, item_detail.clone());
|
||||
(InventoryItemDetail::Individual(item_detail), create_item)
|
||||
};
|
||||
|
||||
@ -1187,7 +1194,8 @@ where
|
||||
transaction.gateway().set_character_inventory(&character_id, &inventory.as_inventory_entity(&character_id)).await?;
|
||||
item_state.set_inventory(inventory).await;
|
||||
|
||||
vec![SendShipPacket::Message(Message::new(GameMessage::CreateItem(create_item)))]
|
||||
//vec![SendShipPacket::Message(Message::new(GameMessage::CreateItem(create_item)))]
|
||||
vec![create_item]
|
||||
}
|
||||
else {
|
||||
Vec::new()
|
@ -11,8 +11,8 @@ use entity::item::tool::{Tool, ToolType};
|
||||
use entity::item::tech::TechniqueDisk;
|
||||
use entity::item::{ItemDetail, ItemEntityId};
|
||||
use entity::item::weapon::WeaponModifier;
|
||||
use crate::ship::items::state::ItemStateProxy;
|
||||
use crate::ship::items::inventory::InventoryItemDetail;
|
||||
use crate::state::ItemStateProxy;
|
||||
use crate::inventory::InventoryItemDetail;
|
||||
|
||||
|
||||
#[derive(Error, Debug)]
|
@ -1,15 +1,15 @@
|
||||
use std::cmp::Ordering;
|
||||
use libpso::character::character;
|
||||
use crate::ship::items::ClientItemId;
|
||||
use crate::ClientItemId;
|
||||
use entity::item::{Meseta, ItemEntityId, ItemDetail, ItemEntity, BankEntity, BankItemEntity};
|
||||
use std::future::Future;
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
|
||||
use entity::character::CharacterEntityId;
|
||||
use entity::item::BankIdentifier;
|
||||
use crate::ship::items::state::ItemStateError;
|
||||
use crate::ship::items::state::{IndividualItemDetail, StackedItemDetail, AddItemResult};
|
||||
use crate::ship::items::inventory::{InventoryItem, InventoryItemDetail};
|
||||
use crate::state::ItemStateError;
|
||||
use crate::state::{IndividualItemDetail, StackedItemDetail, AddItemResult};
|
||||
use crate::inventory::{InventoryItem, InventoryItemDetail};
|
||||
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
@ -1,4 +1,4 @@
|
||||
use crate::ship::items::ClientItemId;
|
||||
use crate::ClientItemId;
|
||||
use entity::item::{Meseta, ItemEntityId, ItemDetail};
|
||||
use std::future::Future;
|
||||
|
||||
@ -6,9 +6,9 @@ use maps::area::MapArea;
|
||||
use entity::character::CharacterEntityId;
|
||||
use entity::item::mag::Mag;
|
||||
|
||||
use crate::ship::items::state::ItemStateError;
|
||||
use crate::ship::items::state::{IndividualItemDetail, StackedItemDetail};
|
||||
use crate::ship::items::inventory::{InventoryItem, InventoryItemDetail};
|
||||
use crate::state::ItemStateError;
|
||||
use crate::state::{IndividualItemDetail, StackedItemDetail};
|
||||
use crate::inventory::{InventoryItem, InventoryItemDetail};
|
||||
|
||||
pub enum FloorType {
|
||||
Local,
|
@ -1,6 +1,6 @@
|
||||
use std::cmp::Ordering;
|
||||
use libpso::character::character;
|
||||
use crate::ship::items::ClientItemId;
|
||||
use crate::ClientItemId;
|
||||
use entity::item::{Meseta, ItemEntityId, ItemDetail, ItemEntity, InventoryEntity, InventoryItemEntity, EquippedEntity};
|
||||
use std::future::Future;
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
@ -10,9 +10,9 @@ use entity::item::tool::ToolType;
|
||||
use entity::item::mag::Mag;
|
||||
use entity::item::weapon::Weapon;
|
||||
use shops::{ShopItem, ArmorShopItem, ToolShopItem, WeaponShopItem};
|
||||
use crate::ship::items::state::ItemStateError;
|
||||
use crate::ship::items::state::{IndividualItemDetail, StackedItemDetail, AddItemResult};
|
||||
use crate::ship::items::floor::{FloorItem, FloorItemDetail};
|
||||
use crate::state::ItemStateError;
|
||||
use crate::state::{IndividualItemDetail, StackedItemDetail, AddItemResult};
|
||||
use crate::floor::{FloorItem, FloorItemDetail};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum InventoryItemDetail {
|
@ -1,3 +1,5 @@
|
||||
#![feature(extract_if)]
|
||||
|
||||
pub mod state;
|
||||
pub mod actions;
|
||||
pub mod apply_item;
|
||||
@ -6,6 +8,7 @@ pub mod inventory;
|
||||
pub mod floor;
|
||||
pub mod bank;
|
||||
pub mod tasks;
|
||||
pub mod trade;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize, derive_more::Display)]
|
||||
pub struct ClientItemId(pub u32);
|
@ -1,4 +1,4 @@
|
||||
use crate::ship::items::ClientItemId;
|
||||
use crate::ClientItemId;
|
||||
use std::collections::HashMap;
|
||||
use std::cmp::Ordering;
|
||||
use std::cell::RefCell;
|
||||
@ -9,18 +9,18 @@ use crate::entity::item::{ItemDetail, ItemNote, BankName};
|
||||
use crate::entity::item::{Meseta, NewItemEntity, ItemEntity, InventoryItemEntity, BankItemEntity};
|
||||
use crate::entity::item::tool::{Tool, ToolType};
|
||||
use crate::entity::item::weapon;
|
||||
use crate::ship::map::MapArea;
|
||||
use maps::area::MapArea;
|
||||
use crate::ship::ship::ItemDropLocation;
|
||||
use crate::ship::trade::TradeItem;
|
||||
use crate::ship::drops::{ItemDrop, ItemDropType};
|
||||
use crate::ship::location::{AreaClient, RoomId};
|
||||
use crate::ship::shops::ShopItem;
|
||||
use drops::{ItemDrop, ItemDropType};
|
||||
use location::{AreaClient, RoomId};
|
||||
use shops::ShopItem;
|
||||
use crate::ship::packet::handler::trade::{TradeError, OTHER_MESETA_ITEM_ID};
|
||||
|
||||
use crate::ship::items::bank::*;
|
||||
use crate::ship::items::floor::*;
|
||||
use crate::ship::items::inventory::*;
|
||||
use crate::ship::items::transaction::{ItemTransaction, ItemAction, TransactionError, TransactionCommitError};
|
||||
use crate::bank::*;
|
||||
use crate::floor::*;
|
||||
use crate::inventory::*;
|
||||
use crate::transaction::{ItemTransaction, ItemAction, TransactionError, TransactionCommitError};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub enum FloorType {
|
@ -10,12 +10,12 @@ use entity::item::{ItemEntityId, ItemDetail, ItemEntity, InventoryItemEntity, Ba
|
||||
use entity::item::tool::Tool;
|
||||
use entity::item::weapon::Weapon;
|
||||
use entity::item::mag::Mag;
|
||||
use crate::ship::drops::ItemDrop;
|
||||
use crate::ship::items::ClientItemId;
|
||||
use crate::ship::items::inventory::{Inventory, InventoryItem, InventoryItemDetail, InventoryError, InventoryState};
|
||||
use crate::ship::items::floor::{FloorState, FloorItem, LocalFloor, SharedFloor, FloorType};
|
||||
use crate::ship::items::bank::{Bank, BankState, BankItem, BankItemDetail, BankError};
|
||||
use crate::ship::location::{AreaClient, RoomId};
|
||||
use drops::ItemDrop;
|
||||
use crate::ClientItemId;
|
||||
use crate::inventory::{Inventory, InventoryItem, InventoryItemDetail, InventoryError, InventoryState};
|
||||
use crate::floor::{FloorState, FloorItem, LocalFloor, SharedFloor, FloorType};
|
||||
use crate::bank::{Bank, BankState, BankItem, BankItemDetail, BankError};
|
||||
use location::{AreaClient, RoomId};
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum ItemStateError {
|
||||
@ -50,7 +50,7 @@ pub enum ItemStateError {
|
||||
#[error("stacked item")]
|
||||
StackedItemError(Vec<ItemEntity>),
|
||||
#[error("apply item {0}")]
|
||||
ApplyItemError(#[from] crate::ship::items::apply_item::ApplyItemError),
|
||||
ApplyItemError(#[from] crate::apply_item::ApplyItemError),
|
||||
#[error("item is not a mag {0}")]
|
||||
NotAMag(ClientItemId),
|
||||
#[error("item is not mag food {0}")]
|
@ -1,24 +1,23 @@
|
||||
use futures::future::BoxFuture;
|
||||
use crate::ship::items::ClientItemId;
|
||||
use crate::ClientItemId;
|
||||
use entity::item::Meseta;
|
||||
|
||||
use crate::ship::ship::SendShipPacket;
|
||||
use maps::area::MapArea;
|
||||
use entity::character::{CharacterEntity, CharacterEntityId};
|
||||
use entity::gateway::{EntityGateway, EntityGatewayTransaction};
|
||||
use entity::item::ItemModifier;
|
||||
use entity::room::RoomEntityId;
|
||||
use crate::ship::items::state::{ItemState, ItemStateProxy, IndividualItemDetail};
|
||||
use crate::ship::items::itemstateaction::{ItemStateAction, ItemAction};
|
||||
use crate::ship::items::inventory::InventoryItem;
|
||||
use crate::ship::items::floor::FloorItem;
|
||||
use crate::state::{ItemState, ItemStateProxy, IndividualItemDetail};
|
||||
use crate::itemstateaction::{ItemStateAction, ItemAction};
|
||||
use crate::inventory::InventoryItem;
|
||||
use crate::floor::FloorItem;
|
||||
use shops::ShopItem;
|
||||
use crate::ship::trade::TradeItem;
|
||||
use crate::ship::location::AreaClient;
|
||||
use crate::ship::drops::ItemDrop;
|
||||
use crate::trade::TradeItem;
|
||||
use location::AreaClient;
|
||||
use drops::ItemDrop;
|
||||
use maps::monster::MonsterType;
|
||||
|
||||
use crate::ship::items::actions;
|
||||
use crate::actions;
|
||||
|
||||
pub fn pick_up_item<'a, EG>(
|
||||
item_state: &'a mut ItemState,
|
||||
@ -278,7 +277,7 @@ pub fn use_item<'a, EG> (
|
||||
area_client: AreaClient,
|
||||
item_id: &'a ClientItemId,
|
||||
amount: u32,
|
||||
) -> BoxFuture<'a, Result<Vec<SendShipPacket>, anyhow::Error>>
|
||||
) -> BoxFuture<'a, Result<Vec<actions::CreateItem>, anyhow::Error>>
|
||||
where
|
||||
EG: EntityGateway + 'static,
|
||||
{
|
38
items/src/trade.rs
Normal file
38
items/src/trade.rs
Normal file
@ -0,0 +1,38 @@
|
||||
use crate::ClientItemId;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TradeItem {
|
||||
Individual(ClientItemId),
|
||||
Stacked(ClientItemId, usize),
|
||||
}
|
||||
|
||||
impl TradeItem {
|
||||
pub fn stacked(&self) -> Option<(ClientItemId, usize)> {
|
||||
match self {
|
||||
TradeItem::Stacked(item_id, amount) => Some((*item_id, *amount)),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stacked_mut(&mut self) -> Option<(ClientItemId, &mut usize)> {
|
||||
match self {
|
||||
TradeItem::Stacked(item_id, ref mut amount) => Some((*item_id, amount)),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn item_id(&self) -> ClientItemId {
|
||||
match self {
|
||||
TradeItem::Individual(item_id) => *item_id,
|
||||
TradeItem::Stacked(item_id, _) => *item_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn amount(&self) -> usize {
|
||||
match self {
|
||||
TradeItem::Individual(_) => 1,
|
||||
TradeItem::Stacked(_, amount) => *amount,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
12
location/Cargo.toml
Normal file
12
location/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "location"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
networking = { workspace = true }
|
||||
|
||||
async-std = { workspace = true }
|
||||
derive_more = { workspace = true }
|
||||
futures= { workspace = true }
|
||||
thiserror = { workspace = true }
|
3
location/src/lib.rs
Normal file
3
location/src/lib.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod location;
|
||||
|
||||
pub use location::*;
|
@ -2,7 +2,7 @@
|
||||
use std::collections::HashMap;
|
||||
use std::time::SystemTime;
|
||||
use thiserror::Error;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use networking::serverstate::ClientId;
|
||||
|
||||
use async_std::sync::{Arc, RwLock};
|
||||
use futures::{stream, StreamExt};
|
@ -9,17 +9,11 @@ use thiserror::Error;
|
||||
use rand::{Rng, SeedableRng};
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use crate::Holiday;
|
||||
use crate::area::{MapArea, MapAreaError};
|
||||
use crate::room::Episode;
|
||||
use crate::monster::MonsterType;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum RareEnemyEvent {
|
||||
Easter,
|
||||
Halloween,
|
||||
Christmas,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct RawMapEnemy {
|
||||
id: u32,
|
||||
@ -120,7 +114,7 @@ impl RareMonsterAppearTable {
|
||||
rand_chacha::ChaChaRng::from_entropy().gen::<f32>() < *self.appear_rate.get(monster).unwrap_or(&0.0f32)
|
||||
}
|
||||
|
||||
pub fn apply(&self, enemy: MapEnemy, event: Option<RareEnemyEvent>) -> MapEnemy {
|
||||
pub fn apply(&self, enemy: MapEnemy, event: Holiday) -> MapEnemy {
|
||||
if enemy.can_be_rare() && self.roll_is_rare(&enemy.monster) {
|
||||
enemy.into_rare(event)
|
||||
}
|
||||
@ -362,12 +356,12 @@ impl MapEnemy {
|
||||
guaranteed rare monsters don't count towards the limit
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn into_rare(self, event: Option<RareEnemyEvent>) -> MapEnemy {
|
||||
pub fn into_rare(self, event: Holiday) -> MapEnemy {
|
||||
match (self.monster, self.map_area.to_episode(), event) {
|
||||
(MonsterType::RagRappy, Episode::One, _) => {MapEnemy {monster: MonsterType::AlRappy, shiny:true, ..self}},
|
||||
(MonsterType::RagRappy, Episode::Two, Some(RareEnemyEvent::Easter)) => {MapEnemy {monster: MonsterType::EasterRappy, shiny:true, ..self}},
|
||||
(MonsterType::RagRappy, Episode::Two, Some(RareEnemyEvent::Halloween)) => {MapEnemy {monster: MonsterType::HalloRappy, shiny:true, ..self}},
|
||||
(MonsterType::RagRappy, Episode::Two, Some(RareEnemyEvent::Christmas)) => {MapEnemy {monster: MonsterType::StRappy, shiny:true, ..self}},
|
||||
(MonsterType::RagRappy, Episode::Two, Holiday::Easter) => {MapEnemy {monster: MonsterType::EasterRappy, shiny:true, ..self}},
|
||||
(MonsterType::RagRappy, Episode::Two, Holiday::Halloween) => {MapEnemy {monster: MonsterType::HalloRappy, shiny:true, ..self}},
|
||||
(MonsterType::RagRappy, Episode::Two, Holiday::Christmas) => {MapEnemy {monster: MonsterType::StRappy, shiny:true, ..self}},
|
||||
(MonsterType::RagRappy, Episode::Two, _) => {MapEnemy {monster: MonsterType::LoveRappy, shiny:true, ..self}},
|
||||
(MonsterType::Hildebear, _, _) => {MapEnemy {monster: MonsterType::Hildeblue, shiny:true, ..self}},
|
||||
(MonsterType::PoisonLily, _, _) => {MapEnemy {monster: MonsterType::NarLily, shiny:true, ..self}},
|
||||
|
@ -5,3 +5,55 @@ pub mod variant;
|
||||
pub mod maps;
|
||||
pub mod monster;
|
||||
pub mod room;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Holiday {
|
||||
None,
|
||||
Christmas,
|
||||
Valentines,
|
||||
Easter,
|
||||
Halloween,
|
||||
Sonic,
|
||||
NewYear,
|
||||
Summer,
|
||||
White,
|
||||
Wedding,
|
||||
Fall,
|
||||
Spring,
|
||||
Summer2,
|
||||
Spring2,
|
||||
}
|
||||
|
||||
|
||||
impl From<Holiday> for u32 {
|
||||
fn from(other: Holiday) -> u32 {
|
||||
u16::from(other) as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Holiday> for u16 {
|
||||
fn from(other: Holiday) -> u16 {
|
||||
u8::from(other) as u16
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Holiday> for u8 {
|
||||
fn from(other: Holiday) -> u8 {
|
||||
match other {
|
||||
Holiday::None => 0,
|
||||
Holiday::Christmas => 1,
|
||||
Holiday::Valentines => 3,
|
||||
Holiday::Easter => 4,
|
||||
Holiday::Halloween => 5,
|
||||
Holiday::Sonic => 6,
|
||||
Holiday::NewYear => 7,
|
||||
Holiday::Summer => 8,
|
||||
Holiday::White => 9,
|
||||
Holiday::Wedding => 10,
|
||||
Holiday::Fall => 11,
|
||||
Holiday::Spring => 12,
|
||||
Holiday::Summer2 => 13,
|
||||
Holiday::Spring2 => 14,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,8 @@ use thiserror::Error;
|
||||
|
||||
//use crate::ship::ship::ShipEvent;
|
||||
use crate::area::MapArea;
|
||||
use crate::enemy::{MapEnemy, RawMapEnemy, RareEnemyEvent, RareMonsterAppearTable};
|
||||
use crate::Holiday;
|
||||
use crate::enemy::{MapEnemy, RawMapEnemy, RareMonsterAppearTable};
|
||||
use crate::monster::MonsterType;
|
||||
use crate::variant::{MapVariant, MapVariantMode};
|
||||
use crate::object::{MapObject, RawMapObject};
|
||||
@ -325,7 +326,7 @@ impl Maps {
|
||||
enemies: Vec<Option<MapEnemy>>,
|
||||
objects: Vec<Option<MapObject>>,
|
||||
rare_monster_table: &RareMonsterAppearTable,
|
||||
event: Option<RareEnemyEvent>)
|
||||
event: Holiday)
|
||||
{
|
||||
self.enemy_data = enemies
|
||||
.into_iter()
|
||||
@ -358,7 +359,7 @@ impl Maps {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_free_roam_maps(room_mode: RoomMode, event: Option<RareEnemyEvent>) -> Maps {
|
||||
pub fn generate_free_roam_maps(room_mode: RoomMode, event: Holiday) -> Maps {
|
||||
let rare_monster_table = RareMonsterAppearTable::new(room_mode.episode());
|
||||
let map_variants = default_map_variants(room_mode.episode(), room_mode.player_mode());
|
||||
Maps {
|
||||
|
@ -2,3 +2,17 @@
|
||||
name = "networking"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
|
||||
[dependencies]
|
||||
entity = { workspace = true }
|
||||
|
||||
libpso = { workspace = true }
|
||||
|
||||
async-std = { workspace = true }
|
||||
async-trait = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
log = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
derive_more = { workspace = true }
|
@ -0,0 +1,18 @@
|
||||
pub mod cipherkeys;
|
||||
pub mod serverstate;
|
||||
pub mod mainloop;
|
||||
pub mod interserver;
|
||||
|
||||
// https://www.reddit.com/r/rust/comments/33xhhu/how_to_create_an_array_of_structs_that_havent/
|
||||
#[macro_export]
|
||||
macro_rules! init_array(
|
||||
($ty:ty, $len:expr, $val:expr) => (
|
||||
{
|
||||
let mut array: [$ty; $len] = unsafe { std::mem::uninitialized() };
|
||||
for i in array.iter_mut() {
|
||||
unsafe { ::std::ptr::write(i, $val); }
|
||||
}
|
||||
array
|
||||
}
|
||||
)
|
||||
);
|
@ -9,8 +9,8 @@ use log::{trace, info, warn, error};
|
||||
|
||||
use libpso::crypto::{PSOCipher, NullCipher, CipherError};
|
||||
use libpso::PacketParseError;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use crate::common::serverstate::{RecvServerPacket, SendServerPacket, ServerState, OnConnect};
|
||||
use crate::serverstate::ClientId;
|
||||
use crate::serverstate::{RecvServerPacket, SendServerPacket, ServerState, OnConnect};
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -255,7 +255,7 @@ where
|
||||
let (mut socket, addr) = listener.accept().await.unwrap();
|
||||
id += 1;
|
||||
|
||||
let client_id = crate::common::serverstate::ClientId(id);
|
||||
let client_id = crate::serverstate::ClientId(id);
|
||||
info!("new client {:?} {:?} {:?}", client_id, socket, addr);
|
||||
|
||||
let (client_tx, client_rx) = async_std::channel::unbounded();
|
@ -8,11 +8,10 @@ use std::collections::HashMap;
|
||||
use serde::Serialize;
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
use crate::common::interserver::{ServerId, InterserverActor};
|
||||
use crate::interserver::{ServerId, InterserverActor};
|
||||
|
||||
use libpso::crypto::{PSOCipher, NullCipher, CipherError};
|
||||
use crate::common::serverstate::{ServerState, SendServerPacket, RecvServerPacket};
|
||||
use crate::login::character::CharacterServerState;
|
||||
use crate::serverstate::{ServerState, SendServerPacket, RecvServerPacket};
|
||||
use entity::gateway::entitygateway::EntityGateway;
|
||||
|
||||
use async_std::channel;
|
||||
@ -148,7 +147,7 @@ where
|
||||
info!("[interserver listen] new server: {:?} {:?}", socket, addr);
|
||||
|
||||
id += 1;
|
||||
let server_id = crate::common::interserver::ServerId(id);
|
||||
let server_id = crate::interserver::ServerId(id);
|
||||
let (client_tx, client_rx) = async_std::channel::unbounded();
|
||||
state.set_sender(server_id, client_tx.clone()).await;
|
||||
|
||||
@ -195,7 +194,7 @@ where
|
||||
}
|
||||
};
|
||||
id += 1;
|
||||
let server_id = crate::common::interserver::ServerId(id);
|
||||
let server_id = crate::interserver::ServerId(id);
|
||||
info!("[interserver connect] found loginserv: {:?} {:?}", server_id, socket);
|
||||
|
||||
let (client_tx, client_rx) = async_std::channel::unbounded();
|
22
pktbuilder/Cargo.toml
Normal file
22
pktbuilder/Cargo.toml
Normal file
@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "pktbuilder"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
quests = { workspace = true }
|
||||
stats = { workspace = true }
|
||||
location = { workspace = true }
|
||||
client = { workspace = true }
|
||||
items = { workspace = true }
|
||||
networking = { workspace = true }
|
||||
maps = { workspace = true }
|
||||
room = { workspace = true }
|
||||
shops = { workspace = true }
|
||||
entity = { workspace = true }
|
||||
|
||||
libpso = { workspace = true }
|
||||
|
||||
anyhow = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
thiserror = { workspace = true }
|
@ -1,9 +1,8 @@
|
||||
use libpso::character::character;
|
||||
use stats::leveltable::CharacterStats;
|
||||
use entity::character::CharacterEntity;
|
||||
//use crate::ship::items::{CharacterInventory, CharacterBank};
|
||||
use crate::ship::items::bank::BankState;
|
||||
use crate::ship::items::inventory::InventoryState;
|
||||
use items::bank::BankState;
|
||||
use items::inventory::InventoryState;
|
||||
use entity::item::Meseta;
|
||||
|
||||
|
@ -3,14 +3,15 @@ pub mod message;
|
||||
pub mod room;
|
||||
pub mod quest;
|
||||
pub mod ship;
|
||||
pub mod character;
|
||||
|
||||
use libpso::character::character::Inventory;
|
||||
use libpso::packet::ship::{PlayerHeader, PlayerInfo};
|
||||
use stats::leveltable::LEVEL_TABLE;
|
||||
use crate::ship::character::CharacterBytesBuilder;
|
||||
use crate::ship::ship::ClientState;
|
||||
use crate::ship::location::AreaClient;
|
||||
use crate::ship::items::inventory::InventoryState;
|
||||
use crate::character::CharacterBytesBuilder;
|
||||
use client::ClientState;
|
||||
use location::AreaClient;
|
||||
use items::inventory::InventoryState;
|
||||
|
||||
pub fn player_header(tag: u32, client: &ClientState, area_client: &AreaClient) -> PlayerHeader {
|
||||
PlayerHeader {
|
@ -1,9 +1,10 @@
|
||||
use libpso::packet::ship::*;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use crate::ship::ship::{Clients, ShipEvent};
|
||||
use crate::ship::location::{ClientLocation, LobbyId, ClientLocationError};
|
||||
use crate::ship::packet::builder::{player_info};
|
||||
use crate::ship::items::state::ItemState;
|
||||
use networking::serverstate::ClientId;
|
||||
use maps::Holiday;
|
||||
use client::Clients;
|
||||
use location::{ClientLocation, LobbyId, ClientLocationError};
|
||||
use crate::player_info;
|
||||
use items::state::ItemState;
|
||||
|
||||
use futures::future::join_all;
|
||||
|
||||
@ -12,7 +13,7 @@ pub async fn join_lobby(id: ClientId,
|
||||
client_location: &ClientLocation,
|
||||
clients: &Clients,
|
||||
item_state: &ItemState,
|
||||
event: ShipEvent)
|
||||
event: Holiday)
|
||||
-> Result<JoinLobby, anyhow::Error> {
|
||||
let lobby_clients = client_location.get_clients_in_lobby(lobby).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
|
||||
@ -52,7 +53,7 @@ pub async fn add_to_lobby(id: ClientId,
|
||||
client_location: &ClientLocation,
|
||||
clients: &Clients,
|
||||
item_state: &ItemState,
|
||||
event: ShipEvent)
|
||||
event: Holiday)
|
||||
-> Result<AddToLobby, anyhow::Error> {
|
||||
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let leader = client_location.get_lobby_leader(lobby).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
@ -2,20 +2,20 @@ use libpso::packet::messages::*;
|
||||
use libpso::packet::ship::*;
|
||||
use entity::item;
|
||||
use stats::leveltable::CharacterStats;
|
||||
use crate::ship::ship::{ShipError};
|
||||
use crate::ship::items::ClientItemId;
|
||||
use crate::ship::items::inventory::InventoryItem;
|
||||
use crate::ship::items::state::IndividualItemDetail;
|
||||
use crate::ship::items::bank::BankState;
|
||||
use crate::ship::items::floor::FloorItem;
|
||||
use crate::ship::location::AreaClient;
|
||||
//use crate::ship::ship::{ShipError};
|
||||
use items::ClientItemId;
|
||||
use items::inventory::InventoryItem;
|
||||
use items::state::IndividualItemDetail;
|
||||
use items::bank::BankState;
|
||||
use items::floor::FloorItem;
|
||||
use location::AreaClient;
|
||||
use std::convert::TryInto;
|
||||
use shops::ShopItem;
|
||||
|
||||
|
||||
pub fn item_drop(client: u8, target: u8, item_drop: &FloorItem) -> Result<ItemDrop, ShipError> {
|
||||
pub fn item_drop(client: u8, target: u8, item_drop: &FloorItem) -> ItemDrop {
|
||||
let item_bytes = item_drop.as_client_bytes();
|
||||
Ok(ItemDrop {
|
||||
ItemDrop {
|
||||
client,
|
||||
target,
|
||||
map_area: item_drop.map_area.area_value(),
|
||||
@ -24,37 +24,37 @@ pub fn item_drop(client: u8, target: u8, item_drop: &FloorItem) -> Result<ItemDr
|
||||
x: item_drop.x,
|
||||
z: item_drop.z,
|
||||
y: item_drop.y,
|
||||
item_bytes: item_bytes[0..12].try_into()?,
|
||||
item_bytes: item_bytes[0..12].try_into().unwrap(),
|
||||
item_id: item_drop.item_id.0,
|
||||
item_bytes2: item_bytes[12..16].try_into()?,
|
||||
item_bytes2: item_bytes[12..16].try_into().unwrap(),
|
||||
unknown2: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this doesn't need to be a Result, just unwrap try_intos they are guaranteed to succeed
|
||||
pub fn create_individual_item(area_client: AreaClient, item_id: ClientItemId, item: &IndividualItemDetail) -> Result<CreateItem, ShipError> {
|
||||
pub fn create_individual_item(area_client: AreaClient, item_id: ClientItemId, item: &IndividualItemDetail) -> CreateItem {
|
||||
let bytes = item.as_client_bytes();
|
||||
Ok(CreateItem {
|
||||
CreateItem {
|
||||
client: area_client.local_client.id(),
|
||||
target: 0,
|
||||
item_data: bytes[0..12].try_into()?,
|
||||
item_data: bytes[0..12].try_into().unwrap(),
|
||||
item_id: item_id.0,
|
||||
item_data2: bytes[12..16].try_into()?,
|
||||
item_data2: bytes[12..16].try_into().unwrap(),
|
||||
unknown: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this doesn't need to be a Result, just unwrap try_intos they are guaranteed to succeed
|
||||
pub fn create_stacked_item(area_client: AreaClient, item_id: ClientItemId, tool: &item::tool::Tool, amount: usize) -> Result<CreateItem, ShipError> {
|
||||
pub fn create_stacked_item(area_client: AreaClient, item_id: ClientItemId, tool: &item::tool::Tool, amount: usize) -> CreateItem {
|
||||
let bytes = tool.as_stacked_bytes(amount);
|
||||
Ok(CreateItem {
|
||||
CreateItem {
|
||||
client: area_client.local_client.id(),
|
||||
target: 0,
|
||||
item_data: bytes[0..12].try_into()?,
|
||||
item_data: bytes[0..12].try_into().unwrap(),
|
||||
item_id: item_id.0,
|
||||
item_data2: bytes[12..16].try_into()?,
|
||||
item_data2: bytes[12..16].try_into().unwrap(),
|
||||
unknown: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_meseta(area_client: AreaClient, amount: usize) -> CreateItem {
|
||||
@ -69,32 +69,32 @@ pub fn create_meseta(area_client: AreaClient, amount: usize) -> CreateItem {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_withdrawn_inventory_item(area_client: AreaClient, item: &InventoryItem) -> Result<CreateItem, ShipError> {
|
||||
pub fn create_withdrawn_inventory_item(area_client: AreaClient, item: &InventoryItem) -> CreateItem {
|
||||
let bytes = item.item.as_client_bytes();
|
||||
Ok(CreateItem {
|
||||
CreateItem {
|
||||
client: area_client.local_client.id(),
|
||||
target: 0,
|
||||
item_data: bytes[0..12].try_into()?,
|
||||
item_data: bytes[0..12].try_into().unwrap(),
|
||||
item_id: item.item_id.0,
|
||||
item_data2: bytes[12..16].try_into()?,
|
||||
item_data2: bytes[12..16].try_into().unwrap(),
|
||||
unknown: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_withdrawn_inventory_item2(area_client: AreaClient, item: &InventoryItem) -> Result<CreateItem, ShipError> {
|
||||
pub fn create_withdrawn_inventory_item2(area_client: AreaClient, item: &InventoryItem) -> CreateItem {
|
||||
let bytes = item.item.as_client_bytes();
|
||||
Ok(CreateItem {
|
||||
CreateItem {
|
||||
client: area_client.local_client.id(),
|
||||
target: 0,
|
||||
item_data: bytes[0..12].try_into()?,
|
||||
item_data: bytes[0..12].try_into().unwrap(),
|
||||
item_id: item.item_id.0,
|
||||
item_data2: bytes[12..16].try_into()?,
|
||||
item_data2: bytes[12..16].try_into().unwrap(),
|
||||
unknown: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_item_from_floor(area_client: AreaClient, item: &FloorItem) -> Result<RemoveItemFromFloor, ShipError> {
|
||||
Ok(RemoveItemFromFloor {
|
||||
pub fn remove_item_from_floor(area_client: AreaClient, item: &FloorItem) -> RemoveItemFromFloor {
|
||||
RemoveItemFromFloor {
|
||||
client: area_client.local_client.id(),
|
||||
target: 0,
|
||||
client_id: area_client.local_client.id(),
|
||||
@ -102,12 +102,12 @@ pub fn remove_item_from_floor(area_client: AreaClient, item: &FloorItem) -> Resu
|
||||
map_area: item.map_area.area_value(),
|
||||
unknown2: 0,
|
||||
item_id: item.item_id.0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drop_split_stack(area_client: AreaClient, item: &FloorItem) -> Result<DropSplitStack, ShipError> {
|
||||
pub fn drop_split_stack(area_client: AreaClient, item: &FloorItem) -> DropSplitStack {
|
||||
let item_bytes = item.as_client_bytes();
|
||||
Ok(DropSplitStack {
|
||||
DropSplitStack {
|
||||
client: area_client.local_client.id(),
|
||||
target: 0,
|
||||
variety: 0,
|
||||
@ -115,16 +115,16 @@ pub fn drop_split_stack(area_client: AreaClient, item: &FloorItem) -> Result<Dro
|
||||
map_area: item.map_area.area_value(),
|
||||
x: item.x,
|
||||
z: item.z,
|
||||
item_bytes: item_bytes[0..12].try_into()?,
|
||||
item_bytes: item_bytes[0..12].try_into().unwrap(),
|
||||
item_id: item.item_id.0,
|
||||
item_bytes2: item_bytes[12..16].try_into()?,
|
||||
item_bytes2: item_bytes[12..16].try_into().unwrap(),
|
||||
unknown2: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drop_split_meseta_stack(area_client: AreaClient, item: &FloorItem) -> Result<DropSplitStack, ShipError> {
|
||||
pub fn drop_split_meseta_stack(area_client: AreaClient, item: &FloorItem) -> DropSplitStack {
|
||||
let item_bytes = item.as_client_bytes();
|
||||
Ok(DropSplitStack {
|
||||
DropSplitStack {
|
||||
client: area_client.local_client.id(),
|
||||
target: 0,
|
||||
variety: 0,
|
||||
@ -132,11 +132,11 @@ pub fn drop_split_meseta_stack(area_client: AreaClient, item: &FloorItem) -> Res
|
||||
map_area: item.map_area.area_value(),
|
||||
x: item.x,
|
||||
z: item.z,
|
||||
item_bytes: item_bytes[0..12].try_into()?,
|
||||
item_bytes: item_bytes[0..12].try_into().unwrap(),
|
||||
item_id: item.item_id.0,
|
||||
item_bytes2: item_bytes[12..16].try_into()?,
|
||||
item_bytes2: item_bytes[12..16].try_into().unwrap(),
|
||||
unknown2: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn character_gained_exp(area_client: AreaClient, exp: u32) -> GiveCharacterExp {
|
||||
@ -215,13 +215,13 @@ pub fn shop_list<I: ShopItem>(shop_type: u8, items: &[I]) -> ShopList {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tek_preview(id: ClientItemId, weapon: &item::weapon::Weapon) -> Result<TekPreview, ShipError> {
|
||||
pub fn tek_preview(id: ClientItemId, weapon: &item::weapon::Weapon) -> TekPreview {
|
||||
let bytes = weapon.as_bytes();
|
||||
Ok(TekPreview {
|
||||
TekPreview {
|
||||
client: 0x79,
|
||||
target: 0,
|
||||
item_bytes: bytes[0..12].try_into()?,
|
||||
item_bytes: bytes[0..12].try_into().unwrap(),
|
||||
item_id: id.0,
|
||||
item_bytes2: bytes[12..16].try_into()?,
|
||||
})
|
||||
item_bytes2: bytes[12..16].try_into().unwrap(),
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
use crate::ship::quests::{Quest, QuestList};
|
||||
use crate::ship::ship::{QUEST_CATEGORY_MENU_ID, QUEST_SELECT_MENU_ID};
|
||||
use quests::{Quest, QuestList};
|
||||
use libpso::packet::ship::*;
|
||||
use libpso::{utf8_to_array, utf8_to_utf16_array};
|
||||
|
||||
pub const QUEST_CATEGORY_MENU_ID: u32 = 0xA2;
|
||||
pub const QUEST_SELECT_MENU_ID: u32 = 0xA3;
|
||||
|
||||
pub fn quest_category_list(quests: &QuestList) -> QuestCategoryList {
|
||||
let categories = quests.iter()
|
@ -1,11 +1,12 @@
|
||||
use libpso::packet::ship::*;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use crate::ship::ship::{ShipError, ClientState, Clients, ShipEvent};
|
||||
use crate::ship::location::{ClientLocation, RoomId, AreaClient, ClientLocationError};
|
||||
use crate::ship::room::RoomState;
|
||||
use crate::ship::items::state::ItemState;
|
||||
use crate::ship::packet::builder::{player_header, player_info};
|
||||
use std::convert::TryInto;
|
||||
use libpso::packet::ship::*;
|
||||
use networking::serverstate::ClientId;
|
||||
use maps::Holiday;
|
||||
use client::{ClientState, Clients};
|
||||
use location::{ClientLocation, RoomId, AreaClient, ClientLocationError};
|
||||
use room::RoomState;
|
||||
use items::state::ItemState;
|
||||
use crate::{player_header, player_info};
|
||||
|
||||
use futures::stream::StreamExt;
|
||||
|
||||
@ -14,14 +15,14 @@ pub async fn join_room(id: ClientId,
|
||||
client_location: &ClientLocation,
|
||||
room_id: RoomId,
|
||||
room: &RoomState,
|
||||
event: ShipEvent)
|
||||
event: Holiday)
|
||||
-> Result<JoinRoom, anyhow::Error> {
|
||||
let all_clients = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
#[allow(clippy::manual_try_fold)] // I don't think its even possible to make this work here
|
||||
let players = futures::stream::iter(all_clients.iter())
|
||||
.enumerate()
|
||||
.fold::<Result<_, anyhow::Error>, _, _>(Ok([PlayerHeader::default(); 4]), |acc, (i, c)| async move {
|
||||
let header_area_client = client_location.get_local_client(id).await.map_err(|err| ShipError::ClientLocationError(err.into()))?;
|
||||
let header_area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError {err.into() })?;
|
||||
clients.with(c.client, |client| Box::pin(async move {
|
||||
acc.map(|mut a| {
|
||||
a[i] = player_header(0x10000, client, &header_area_client);
|
||||
@ -58,7 +59,7 @@ pub async fn add_to_room(_id: ClientId,
|
||||
area_client: &AreaClient,
|
||||
leader: &AreaClient,
|
||||
item_state: &ItemState,
|
||||
event: ShipEvent)
|
||||
event: Holiday)
|
||||
-> Result<AddToRoom, anyhow::Error> {
|
||||
let inventory = item_state.get_character_inventory(&client.character).await?;
|
||||
Ok(AddToRoom {
|
@ -1,8 +1,9 @@
|
||||
use libpso::packet::login::{ShipList, ShipListEntry};
|
||||
use libpso::utf8_to_utf16_array;
|
||||
|
||||
use crate::common::interserver::Ship;
|
||||
use crate::login::character::SHIP_MENU_ID;
|
||||
use networking::interserver::Ship;
|
||||
|
||||
pub const SHIP_MENU_ID: u32 = 1;
|
||||
|
||||
pub fn ship_list(ships: &[Ship]) -> ShipList {
|
||||
let ships = ships.iter()
|
107
pktbuilder/src/team.rs
Normal file
107
pktbuilder/src/team.rs
Normal file
@ -0,0 +1,107 @@
|
||||
use futures::stream::{FuturesOrdered, StreamExt};
|
||||
use libpso::packet::ship::*;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use crate::entity::gateway::EntityGateway;
|
||||
use crate::ship::client::{Clients, ClientState};
|
||||
use crate::ship::teams::Teams;
|
||||
use crate::ship::location::ClientLocation;
|
||||
use crate::ship::ship::ShipError;
|
||||
use crate::entity::team::TeamEntity;
|
||||
|
||||
|
||||
pub fn client_team_state_changed(client_id: ClientId, client: &ClientState, team: &TeamEntity) -> ClientTeamStateChanged {
|
||||
ClientTeamStateChanged {
|
||||
unknown: 0,
|
||||
guildcard: client.user.guildcard(),
|
||||
team_id: team.id.0,
|
||||
unknown2: [0;2],
|
||||
privilege: 0x40, // TODO: improve
|
||||
team_name: libpso::utf8_to_utf16_array!(team.name, 14),
|
||||
unknown3: 0x00986C84, // TODO: what if we omit this?
|
||||
}
|
||||
}
|
||||
|
||||
fn player_team_info(client_id: ClientId, client: &ClientState, team: &TeamEntity) -> PlayerTeamInfo {
|
||||
PlayerTeamInfo {
|
||||
guildcard: client.user.guildcard(),
|
||||
team_id: team.id.0,
|
||||
info: 0,
|
||||
info2: 0,
|
||||
privilege: 0x40, // TODO: improve
|
||||
team_name: libpso::utf8_to_utf16_array!(team.name, 14),
|
||||
unknown: 0x00986C84, // TODO: what if we omit this?
|
||||
guildcard_again: client.user.guildcard(),
|
||||
client_id: client_id.0 as u32,
|
||||
character_name: libpso::utf8_to_utf16_array!(client.character.name, 12),
|
||||
unknown2: 0,
|
||||
unknown3: 0,
|
||||
team_flag: team.team_flag,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn team_info_individual(client_id: ClientId, client: &ClientState, team: &TeamEntity) -> TeamInfo {
|
||||
TeamInfo {
|
||||
clients: vec![player_team_info(client_id, client, team)]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn player_team_info_list<EG>(id: ClientId,
|
||||
client_location: &ClientLocation,
|
||||
clients: &Clients,
|
||||
teams: &Teams<EG>,
|
||||
) -> Result<Vec<PlayerTeamInfo>, ShipError>
|
||||
where
|
||||
EG: EntityGateway + Clone + 'static,
|
||||
{
|
||||
Ok(futures::stream::iter(client_location.get_all_clients_by_client(id).await?.into_iter())
|
||||
.filter_map(|area_client| {
|
||||
let clients = clients.clone();
|
||||
async move {
|
||||
clients.with(area_client.client, |client| {
|
||||
let mut teams = teams.clone();
|
||||
Box::pin(async move {
|
||||
let team = teams.get_team(area_client.client).await.ok()??;
|
||||
Some(player_team_info(area_client.client, client, &team))
|
||||
})}).await.ok()?
|
||||
}})
|
||||
.collect::<Vec<_>>()
|
||||
.await)
|
||||
}
|
||||
|
||||
pub async fn team_info<EG>(id: ClientId,
|
||||
client_location: &ClientLocation,
|
||||
clients: &Clients,
|
||||
teams: &Teams<EG>,
|
||||
) -> Result<TeamInfo, ShipError>
|
||||
where
|
||||
EG: EntityGateway + Clone + 'static,
|
||||
{
|
||||
Ok(TeamInfo {
|
||||
clients: player_team_info_list(id, client_location, clients, teams).await?,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn lobby_team_list<EG>(id: ClientId,
|
||||
client_location: &ClientLocation,
|
||||
clients: &Clients,
|
||||
teams: &Teams<EG>,
|
||||
) -> Result<TeamLobbyList, ShipError>
|
||||
where
|
||||
EG: EntityGateway + Clone + 'static,
|
||||
{
|
||||
Ok(TeamLobbyList {
|
||||
clients: player_team_info_list(id, client_location, clients, teams).await?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn team_invitation_info(client_id: ClientId, client: &ClientState, team: &TeamEntity) -> TeamInvitationInfo {
|
||||
TeamInvitationInfo {
|
||||
guildcard: client.user.guildcard(),
|
||||
team_id: team.id.0,
|
||||
unknown: [0; 2],
|
||||
team_name: libpso::utf8_to_utf16_array!(team.name, 14),
|
||||
unknown2: 0x00986C84, // TODO: what if we omit this?
|
||||
team_flag: team.team_flag,
|
||||
}
|
||||
}
|
18
quests/Cargo.toml
Normal file
18
quests/Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "quests"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
maps = { workspace = true }
|
||||
|
||||
libpso = { workspace = true }
|
||||
|
||||
async-std = { workspace = true }
|
||||
ages-prs = { workspace = true }
|
||||
log = { workspace = true }
|
||||
byteorder = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
toml = { workspace = true }
|
||||
serde = { workspace = true }
|
4
quests/src/lib.rs
Normal file
4
quests/src/lib.rs
Normal file
@ -0,0 +1,4 @@
|
||||
pub mod quests;
|
||||
|
||||
|
||||
pub use quests::*;
|
17
room/Cargo.toml
Normal file
17
room/Cargo.toml
Normal file
@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "room"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
maps = { workspace = true }
|
||||
entity = { workspace = true }
|
||||
quests = { workspace = true }
|
||||
location = { workspace = true }
|
||||
drops = { workspace = true }
|
||||
|
||||
rand= { workspace = true }
|
||||
async-std = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
thiserror = { workspace = true }
|
3
room/src/lib.rs
Normal file
3
room/src/lib.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod room;
|
||||
|
||||
pub use room::*;
|
@ -8,21 +8,28 @@ use thiserror::Error;
|
||||
use rand::Rng;
|
||||
|
||||
use maps::maps::Maps;
|
||||
use crate::ship::drops::DropTable;
|
||||
use drops::DropTable;
|
||||
use entity::character::SectionID;
|
||||
use entity::room::{RoomEntityId, RoomEntityMode};
|
||||
use maps::monster::{load_monster_stats_table, MonsterType, MonsterStats};
|
||||
use maps::area::MapAreaLookup;
|
||||
use maps::enemy::RareEnemyEvent;
|
||||
use crate::ship::quests;
|
||||
use crate::ship::ship::{ShipError, ShipEvent};
|
||||
use crate::ship::location::{MAX_ROOMS, RoomId};
|
||||
use quests;
|
||||
use maps::Holiday;
|
||||
use location::{MAX_ROOMS, RoomId};
|
||||
|
||||
use maps::room::{Episode, Difficulty, RoomMode};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum RoomError {
|
||||
#[error("invalid room id {0}")]
|
||||
Invalid(u32),
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Rooms([Arc<RwLock<Option<RoomState>>>; MAX_ROOMS]);
|
||||
|
||||
|
||||
impl Default for Rooms {
|
||||
fn default() -> Rooms {
|
||||
Rooms(core::array::from_fn(|_| Arc::new(RwLock::new(None))))
|
||||
@ -33,7 +40,7 @@ impl Rooms {
|
||||
pub async fn add(&self, room_id: RoomId, room: RoomState) -> Result<(), anyhow::Error> {
|
||||
*self.0
|
||||
.get(room_id.0)
|
||||
.ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?
|
||||
.ok_or_else(|| RoomError::Invalid(room_id.0 as u32))?
|
||||
.write()
|
||||
.await = Some(room);
|
||||
Ok(())
|
||||
@ -66,14 +73,14 @@ impl Rooms {
|
||||
{
|
||||
let room = self.0
|
||||
.get(room_id.0)
|
||||
.ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?
|
||||
.ok_or_else(|| RoomError::Invalid(room_id.0 as u32))?
|
||||
.read()
|
||||
.await;
|
||||
if let Some(room) = room.as_ref() {
|
||||
Ok(func(room).await)
|
||||
}
|
||||
else {
|
||||
Err(ShipError::InvalidRoom(room_id.0 as u32).into())
|
||||
Err(RoomError::Invalid(room_id.0 as u32).into())
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +91,7 @@ impl Rooms {
|
||||
{
|
||||
let mut room = self.0
|
||||
.get(room_id.0)
|
||||
.ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?
|
||||
.ok_or_else(|| RoomError::Invalid(room_id.0 as u32))?
|
||||
.write()
|
||||
.await;
|
||||
|
||||
@ -92,7 +99,7 @@ impl Rooms {
|
||||
Ok(func(room).await)
|
||||
}
|
||||
else {
|
||||
Err(ShipError::InvalidRoom(room_id.0 as u32).into())
|
||||
Err(RoomError::Invalid(room_id.0 as u32).into())
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,8 +229,8 @@ impl RoomState {
|
||||
section_id: SectionID,
|
||||
name: String,
|
||||
password: [u16; 16],
|
||||
event: ShipEvent,
|
||||
map_builder: Arc<Box<dyn Fn(RoomMode, Option<RareEnemyEvent>) -> Maps + Send + Sync>>,
|
||||
event: Holiday,
|
||||
map_builder: Arc<Box<dyn Fn(RoomMode, Holiday) -> Maps + Send + Sync>>,
|
||||
drop_table_builder: Arc<Box<dyn Fn(Episode, Difficulty, SectionID) -> DropTable + Send + Sync>>,
|
||||
) -> Result<RoomState, anyhow::Error> {
|
||||
let mode = match mode {
|
||||
@ -251,7 +258,7 @@ impl RoomState {
|
||||
random_seed: rand::thread_rng().gen(),
|
||||
name,
|
||||
password,
|
||||
maps: map_builder(mode, event.rare_enemy_event()),
|
||||
maps: map_builder(mode, event),
|
||||
section_id,
|
||||
drop_table: Box::new(drop_table_builder(episode, difficulty, section_id)),
|
||||
bursting: false,
|
@ -2,7 +2,7 @@ use log::{info};
|
||||
use entity::gateway::postgres::PostgresGateway;
|
||||
use elseware::login::login::LoginServerState;
|
||||
use elseware::login::character::CharacterServerState;
|
||||
use elseware::common::interserver::AuthToken;
|
||||
use networking::interserver::AuthToken;
|
||||
|
||||
fn main() {
|
||||
let colors = fern::colors::ColoredLevelConfig::new()
|
||||
@ -38,17 +38,17 @@ fn main() {
|
||||
|
||||
let login_state = LoginServerState::new(entity_gateway.clone(), charserv_ip);
|
||||
let login_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(login_state, elseware::login::login::LOGIN_PORT).await;
|
||||
networking::mainloop::run_server(login_state, elseware::login::login::LOGIN_PORT).await;
|
||||
});
|
||||
|
||||
let char_state = CharacterServerState::new(entity_gateway, AuthToken(shipgate_token));
|
||||
let sub_char_state = char_state.clone();
|
||||
let character_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(sub_char_state, elseware::login::character::CHARACTER_PORT).await;
|
||||
networking::mainloop::run_server(sub_char_state, elseware::login::character::CHARACTER_PORT).await;
|
||||
});
|
||||
|
||||
let inter_character_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_interserver_listen(char_state, elseware::login::login::COMMUNICATION_PORT).await;
|
||||
networking::mainloop::run_interserver_listen(char_state, elseware::login::login::COMMUNICATION_PORT).await;
|
||||
});
|
||||
|
||||
info!("[auth/character] starting server");
|
||||
|
@ -1,13 +1,13 @@
|
||||
use std::net::Ipv4Addr;
|
||||
use log::{info};
|
||||
|
||||
use elseware::common::interserver::AuthToken;
|
||||
use networking::interserver::AuthToken;
|
||||
use elseware::login::login::LoginServerState;
|
||||
use elseware::login::character::CharacterServerState;
|
||||
use elseware::patch::patch::{PatchServerState, generate_patch_tree, load_config, load_motd};
|
||||
use elseware::ship::ship::{ShipServerStateBuilder, ShipEvent};
|
||||
use elseware::ship::ship::ShipServerStateBuilder;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use maps::Holiday;
|
||||
use entity::gateway::{EntityGateway, InMemoryGateway, PostgresGateway};
|
||||
use entity::account::{NewUserAccountEntity, NewUserSettingsEntity};
|
||||
use entity::character::NewCharacterEntity;
|
||||
@ -338,25 +338,25 @@ fn main() {
|
||||
let (patch_file_tree, patch_file_lookup) = generate_patch_tree(patch_config.path.as_str());
|
||||
let patch_state = PatchServerState::new(patch_file_tree, patch_file_lookup, patch_motd);
|
||||
let patch_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(patch_state, patch_config.port).await;
|
||||
networking::mainloop::run_server(patch_state, patch_config.port).await;
|
||||
});
|
||||
|
||||
info!("[auth] starting server");
|
||||
let login_state = LoginServerState::new(entity_gateway.clone(), "127.0.0.1".parse().unwrap());
|
||||
let login_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(login_state, elseware::login::login::LOGIN_PORT).await;
|
||||
networking::mainloop::run_server(login_state, elseware::login::login::LOGIN_PORT).await;
|
||||
});
|
||||
|
||||
info!("[character] starting server");
|
||||
let char_state = CharacterServerState::new(entity_gateway.clone(), AuthToken("".into()));
|
||||
let sub_char_state = char_state.clone();
|
||||
let character_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(sub_char_state, elseware::login::character::CHARACTER_PORT).await;
|
||||
networking::mainloop::run_server(sub_char_state, elseware::login::character::CHARACTER_PORT).await;
|
||||
});
|
||||
|
||||
let sub_char_state = char_state.clone();
|
||||
let inter_character_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_interserver_listen(sub_char_state, elseware::login::login::COMMUNICATION_PORT).await;
|
||||
networking::mainloop::run_interserver_listen(sub_char_state, elseware::login::login::COMMUNICATION_PORT).await;
|
||||
});
|
||||
|
||||
info!("[ship] starting servers");
|
||||
@ -364,32 +364,32 @@ fn main() {
|
||||
.name("US/Sona-Nyl".into())
|
||||
.ip(Ipv4Addr::new(127,0,0,1))
|
||||
.port(elseware::ship::ship::SHIP_PORT)
|
||||
.event(ShipEvent::Halloween)
|
||||
.event(Holiday::Halloween)
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
let sub_ship_state = ship_state.clone();
|
||||
let ship_loop1 = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT).await;
|
||||
networking::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT).await;
|
||||
});
|
||||
let sub_ship_state = ship_state.clone();
|
||||
let inter_ship_loop1 = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_interserver_connect(sub_ship_state, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT).await;
|
||||
networking::mainloop::run_interserver_connect(sub_ship_state, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT).await;
|
||||
});
|
||||
|
||||
let ship_state = ShipServerStateBuilder::default()
|
||||
.name("EU/Dylath-Leen".into())
|
||||
.ip(Ipv4Addr::new(127,0,0,1))
|
||||
.port(elseware::ship::ship::SHIP_PORT+2000)
|
||||
.event(ShipEvent::Christmas)
|
||||
.event(Holiday::Christmas)
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
let sub_ship_state = ship_state.clone();
|
||||
let ship_loop2 = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT+2000).await;
|
||||
networking::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT+2000).await;
|
||||
});
|
||||
let sub_ship_state = ship_state.clone();
|
||||
let inter_ship_loop2 = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_interserver_connect(sub_ship_state, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT).await;
|
||||
networking::mainloop::run_interserver_connect(sub_ship_state, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT).await;
|
||||
});
|
||||
|
||||
let ship_state = ShipServerStateBuilder::default()
|
||||
@ -400,11 +400,11 @@ fn main() {
|
||||
.build();
|
||||
let sub_ship_state = ship_state.clone();
|
||||
let ship_loop3 = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT+3000).await;
|
||||
networking::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT+3000).await;
|
||||
});
|
||||
let sub_ship_state = ship_state.clone();
|
||||
let inter_ship_loop3 = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_interserver_connect(sub_ship_state, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT).await;
|
||||
networking::mainloop::run_interserver_connect(sub_ship_state, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT).await;
|
||||
});
|
||||
|
||||
futures::future::join_all(vec![patch_loop, login_loop, character_loop, inter_character_loop,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use elseware::patch::patch::{PatchServerState, generate_patch_tree, load_config_env, load_motd};
|
||||
use log::{info};
|
||||
use log::info;
|
||||
|
||||
fn main() {
|
||||
info!("[patch] starting server");
|
||||
@ -9,7 +9,7 @@ fn main() {
|
||||
let patch_state = PatchServerState::new(patch_file_tree, patch_file_lookup, patch_motd);
|
||||
|
||||
let patch_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(patch_state, patch_config.port).await;
|
||||
networking::mainloop::run_server(patch_state, patch_config.port).await;
|
||||
});
|
||||
|
||||
async_std::task::block_on(patch_loop);
|
||||
|
@ -1,7 +1,7 @@
|
||||
use log::{info};
|
||||
use log::info;
|
||||
use entity::gateway::postgres::PostgresGateway;
|
||||
use elseware::ship::ship::ShipServerStateBuilder;
|
||||
use elseware::common::interserver::AuthToken;
|
||||
use networking::interserver::AuthToken;
|
||||
|
||||
fn main() {
|
||||
let colors = fern::colors::ColoredLevelConfig::new()
|
||||
@ -49,10 +49,10 @@ fn main() {
|
||||
|
||||
let sub_ship_state = ship_state.clone();
|
||||
let ship_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT).await;
|
||||
networking::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT).await;
|
||||
});
|
||||
let inter_ship_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_interserver_connect(ship_state, shipgate_ip, elseware::login::login::COMMUNICATION_PORT).await;
|
||||
networking::mainloop::run_interserver_connect(ship_state, shipgate_ip, elseware::login::login::COMMUNICATION_PORT).await;
|
||||
});
|
||||
|
||||
info!("[auth/character] starting server");
|
||||
|
@ -1,18 +0,0 @@
|
||||
pub mod cipherkeys;
|
||||
pub mod serverstate;
|
||||
pub mod mainloop;
|
||||
pub mod interserver;
|
||||
|
||||
// https://www.reddit.com/r/rust/comments/33xhhu/how_to_create_an_array_of_structs_that_havent/
|
||||
#[macro_export]
|
||||
macro_rules! init_array(
|
||||
($ty:ty, $len:expr, $val:expr) => (
|
||||
{
|
||||
let mut array: [$ty; $len] = unsafe { std::mem::uninitialized() };
|
||||
for i in array.iter_mut() {
|
||||
unsafe { ::std::ptr::write(i, $val); }
|
||||
}
|
||||
array
|
||||
}
|
||||
)
|
||||
);
|
@ -5,11 +5,10 @@
|
||||
#![feature(try_blocks)]
|
||||
#![feature(test)]
|
||||
#![feature(error_generic_member_access)]
|
||||
#![feature(lazy_cell)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
pub mod common;
|
||||
//pub mod common;
|
||||
//pub mod entity;
|
||||
pub mod patch;
|
||||
pub mod login;
|
||||
|
@ -15,9 +15,9 @@ use libpso::crypto::bb::PSOBBCipher;
|
||||
use libpso::character::character;
|
||||
use entity::item;
|
||||
|
||||
use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
|
||||
use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
|
||||
use crate::common::interserver::{ServerId, InterserverActor, LoginMessage, ShipMessage, Ship};
|
||||
use networking::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
|
||||
use networking::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
|
||||
use networking::interserver::{ServerId, InterserverActor, LoginMessage, ShipMessage, Ship};
|
||||
use stats::leveltable::LEVEL_TABLE;
|
||||
use libpso::{utf8_to_array, utf8_to_utf16_array};
|
||||
|
||||
@ -32,10 +32,11 @@ use entity::item::mag::Mag;
|
||||
use entity::character::{CharacterEntity, NewCharacterEntity, CharacterClass, TechLevel};
|
||||
|
||||
use crate::login::login::{get_login_status};
|
||||
use crate::common::interserver::AuthToken;
|
||||
use networking::interserver::AuthToken;
|
||||
|
||||
use pktbuilder::ship::SHIP_MENU_ID;
|
||||
|
||||
pub const CHARACTER_PORT: u16 = 12001;
|
||||
pub const SHIP_MENU_ID: u32 = 1;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum CharacterError {
|
||||
|
@ -11,8 +11,8 @@ use libpso::{PacketParseError, PSOPacket};
|
||||
use libpso::crypto::bb::PSOBBCipher;
|
||||
use libpso::util::array_to_utf8;
|
||||
|
||||
use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
|
||||
use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
|
||||
use networking::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
|
||||
use networking::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
|
||||
|
||||
use entity::gateway::EntityGateway;
|
||||
use entity::account::{UserAccountEntity};
|
||||
|
@ -11,8 +11,8 @@ use libpso::crypto::pc::PSOPCCipher;
|
||||
use ron::de::from_str;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::common::mainloop::{NetworkError};
|
||||
use crate::common::serverstate::{RecvServerPacket, SendServerPacket, ServerState, OnConnect, ClientId};
|
||||
use networking::mainloop::{NetworkError};
|
||||
use networking::serverstate::{RecvServerPacket, SendServerPacket, ServerState, OnConnect, ClientId};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PatchError {
|
||||
|
@ -1,11 +1,11 @@
|
||||
use libpso::packet::ship::PlayerChat;
|
||||
use entity::gateway::EntityGateway;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use networking::serverstate::ClientId;
|
||||
use crate::ship::ship::{ShipServerState, SendShipPacket};
|
||||
use crate::ship::client::Clients;
|
||||
use crate::ship::items::state::ItemState;
|
||||
use client::Clients;
|
||||
use items::state::ItemState;
|
||||
use entity::item::{BankName, BankIdentifier};
|
||||
use crate::ship::packet::builder::message::bank_item_list;
|
||||
use pktbuilder::message::bank_item_list;
|
||||
|
||||
async fn default_bank<'a, EG>(id: ClientId,
|
||||
entity_gateway: &mut EG,
|
||||
|
@ -1,16 +1,16 @@
|
||||
#[allow(clippy::module_inception)]
|
||||
pub mod ship;
|
||||
pub mod location;
|
||||
pub mod character;
|
||||
pub mod client;
|
||||
pub mod room;
|
||||
pub mod items;
|
||||
//pub mod location;
|
||||
//pub mod character;
|
||||
//pub mod client;
|
||||
//pub mod room;
|
||||
//pub mod items;
|
||||
//pub mod item_stats;
|
||||
//pub mod map;
|
||||
//pub mod monster;
|
||||
pub mod drops;
|
||||
//pub mod drops;
|
||||
pub mod packet;
|
||||
pub mod quests;
|
||||
//pub mod quests;
|
||||
//pub mod shops;
|
||||
pub mod trade;
|
||||
//pub mod trade;
|
||||
pub mod chatcommand;
|
||||
|
@ -1,212 +0,0 @@
|
||||
#![allow(dead_code)]
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use crate::ship::room::{Difficulty, Episode, RoomMode};
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MonsterParseError {
|
||||
UnknownMonster(String),
|
||||
}
|
||||
|
||||
pub struct MonsterStatError;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, enum_utils::FromStr, derive_more::Display)]
|
||||
pub enum MonsterType {
|
||||
Hildebear,
|
||||
Hildeblue,
|
||||
Mothmant,
|
||||
Monest,
|
||||
RagRappy,
|
||||
AlRappy,
|
||||
SavageWolf,
|
||||
BarbarousWolf,
|
||||
Booma,
|
||||
Gobooma,
|
||||
Gigobooma,
|
||||
GrassAssassin,
|
||||
PoisonLily,
|
||||
NarLily,
|
||||
NanoDragon,
|
||||
EvilShark,
|
||||
PalShark,
|
||||
GuilShark,
|
||||
PofuillySlime,
|
||||
PouillySlime,
|
||||
PanArms,
|
||||
Hidoom,
|
||||
Migium,
|
||||
Dubchic,
|
||||
Garanz,
|
||||
SinowBeat,
|
||||
SinowGold,
|
||||
Canadine,
|
||||
Canane,
|
||||
RingCanadine,
|
||||
Delsaber,
|
||||
ChaosSorcerer,
|
||||
BeeR,
|
||||
BeeL,
|
||||
DarkGunner,
|
||||
DeathGunner,
|
||||
ChaosBringer,
|
||||
DarkBelra,
|
||||
Claw,
|
||||
Bulk,
|
||||
Bulclaw,
|
||||
Dimenian,
|
||||
LaDimenian,
|
||||
SoDimenian,
|
||||
Dragon,
|
||||
DeRolLe,
|
||||
DeRolLeBody,
|
||||
DeRolLeMine,
|
||||
VolOptPartA,
|
||||
VolOptPillar,
|
||||
VolOptMonitor,
|
||||
VolOptAmp,
|
||||
VolOptCore,
|
||||
VolOptUnused,
|
||||
VolOpt,
|
||||
VolOptTrap,
|
||||
DarkFalz,
|
||||
DarkFalz1,
|
||||
DarkFalz2,
|
||||
DarkFalz3,
|
||||
Darvant,
|
||||
UltDarvant,
|
||||
Dubwitch,
|
||||
Gillchic,
|
||||
EventRappy,
|
||||
Merillia,
|
||||
Meriltas,
|
||||
Gee,
|
||||
GiGue,
|
||||
Mericarol,
|
||||
Merikle,
|
||||
Mericus,
|
||||
UlGibbon,
|
||||
ZolGibbon,
|
||||
Gibbles,
|
||||
SinowBerill,
|
||||
SinowSpigell,
|
||||
Dolmolm,
|
||||
Dolmdarl,
|
||||
Morfos,
|
||||
Recobox,
|
||||
Recon,
|
||||
SinowZoa,
|
||||
SinowZele,
|
||||
Deldepth,
|
||||
Delbiter,
|
||||
BarbaRay,
|
||||
PigRay,
|
||||
GolDragon,
|
||||
GalGryphon,
|
||||
OlgaFlow,
|
||||
OlgaFlow1,
|
||||
OlgaFlow2,
|
||||
Gael,
|
||||
Giel,
|
||||
StRappy,
|
||||
HalloRappy,
|
||||
EasterRappy,
|
||||
LoveRappy,
|
||||
IllGill,
|
||||
DelLily,
|
||||
Epsilon,
|
||||
Epsiguard,
|
||||
Boota,
|
||||
ZeBoota,
|
||||
BaBoota,
|
||||
SandRappyCrater,
|
||||
SandRappyDesert,
|
||||
ZuCrater,
|
||||
PazuzuCrater,
|
||||
Astark,
|
||||
SatelliteLizardCrater,
|
||||
YowieCrater,
|
||||
Dorphon,
|
||||
DorphonEclair,
|
||||
Goran,
|
||||
GoranDetonator,
|
||||
PyroGoran,
|
||||
DelRappyCrater,
|
||||
DelRappyDesert,
|
||||
MerissaA,
|
||||
MerissaAA,
|
||||
ZuDesert,
|
||||
PazuzuDesert,
|
||||
SatelliteLizardDesert,
|
||||
YowieDesert,
|
||||
Girtablulu,
|
||||
SaintMillion,
|
||||
Shambertin,
|
||||
Kondrieu,
|
||||
}
|
||||
|
||||
|
||||
#[derive(serde::Deserialize, Debug)]
|
||||
pub struct MonsterStats {
|
||||
pub atp: u16,
|
||||
pub mst: u16,
|
||||
pub evp: u16,
|
||||
pub hp: u16,
|
||||
pub dfp: u16,
|
||||
pub ata: u16,
|
||||
pub lck: u16,
|
||||
pub esp: u16,
|
||||
pub exp: u32,
|
||||
}
|
||||
|
||||
fn load_battle_param(filename: &str) -> HashMap<MonsterType, MonsterStats> {
|
||||
let mut path = PathBuf::from("data/battle_param/");
|
||||
path.push(filename);
|
||||
|
||||
let mut f = File::open(path).unwrap();
|
||||
let mut s = String::new();
|
||||
f.read_to_string(&mut s).unwrap();
|
||||
toml::from_str::<HashMap<String, MonsterStats>>(s.as_str()).unwrap()
|
||||
.into_iter()
|
||||
.map(|(monster_name, stats)| {
|
||||
(monster_name.parse().unwrap(), stats)
|
||||
}).collect()
|
||||
}
|
||||
|
||||
pub fn load_monster_stats_table(mode: &RoomMode) -> Result<HashMap<MonsterType, MonsterStats>, MonsterStatError> {
|
||||
match mode {
|
||||
RoomMode::Multi {episode: Episode::One, difficulty: Difficulty::Normal} => Ok(load_battle_param("ep1_multi_normal.toml")),
|
||||
RoomMode::Multi {episode: Episode::One, difficulty: Difficulty::Hard} => Ok(load_battle_param("ep1_multi_hard.toml")),
|
||||
RoomMode::Multi {episode: Episode::One, difficulty: Difficulty::VeryHard} => Ok(load_battle_param("ep1_multi_veryhard.toml")),
|
||||
RoomMode::Multi {episode: Episode::One, difficulty: Difficulty::Ultimate} => Ok(load_battle_param("ep1_multi_ultimate.toml")),
|
||||
|
||||
RoomMode::Multi {episode: Episode::Two, difficulty: Difficulty::Normal} => Ok(load_battle_param("ep2_multi_normal.toml")),
|
||||
RoomMode::Multi {episode: Episode::Two, difficulty: Difficulty::Hard} => Ok(load_battle_param("ep2_multi_hard.toml")),
|
||||
RoomMode::Multi {episode: Episode::Two, difficulty: Difficulty::VeryHard} => Ok(load_battle_param("ep2_multi_veryhard.toml")),
|
||||
RoomMode::Multi {episode: Episode::Two, difficulty: Difficulty::Ultimate} => Ok(load_battle_param("ep2_multi_ultimate.toml")),
|
||||
|
||||
RoomMode::Multi {episode: Episode::Four, difficulty: Difficulty::Normal} => Ok(load_battle_param("ep4_multi_normal.toml")),
|
||||
RoomMode::Multi {episode: Episode::Four, difficulty: Difficulty::Hard} => Ok(load_battle_param("ep4_multi_hard.toml")),
|
||||
RoomMode::Multi {episode: Episode::Four, difficulty: Difficulty::VeryHard} => Ok(load_battle_param("ep4_multi_veryhard.toml")),
|
||||
RoomMode::Multi {episode: Episode::Four, difficulty: Difficulty::Ultimate} => Ok(load_battle_param("ep4_multi_ultimate.toml")),
|
||||
|
||||
RoomMode::Single {episode: Episode::One, difficulty: Difficulty::Normal} => Ok(load_battle_param("ep1_solo_normal.toml")),
|
||||
RoomMode::Single {episode: Episode::One, difficulty: Difficulty::Hard} => Ok(load_battle_param("ep1_solo_hard.toml")),
|
||||
RoomMode::Single {episode: Episode::One, difficulty: Difficulty::VeryHard} => Ok(load_battle_param("ep1_solo_veryhard.toml")),
|
||||
RoomMode::Single {episode: Episode::One, difficulty: Difficulty::Ultimate} => Ok(load_battle_param("ep1_solo_ultimate.toml")),
|
||||
|
||||
RoomMode::Single {episode: Episode::Two, difficulty: Difficulty::Normal} => Ok(load_battle_param("ep2_solo_normal.toml")),
|
||||
RoomMode::Single {episode: Episode::Two, difficulty: Difficulty::Hard} => Ok(load_battle_param("ep2_solo_hard.toml")),
|
||||
RoomMode::Single {episode: Episode::Two, difficulty: Difficulty::VeryHard} => Ok(load_battle_param("ep2_solo_veryhard.toml")),
|
||||
RoomMode::Single {episode: Episode::Two, difficulty: Difficulty::Ultimate} => Ok(load_battle_param("ep2_solo_ultimate.toml")),
|
||||
|
||||
RoomMode::Single {episode: Episode::Four, difficulty: Difficulty::Normal} => Ok(load_battle_param("ep4_solo_normal.toml")),
|
||||
RoomMode::Single {episode: Episode::Four, difficulty: Difficulty::Hard} => Ok(load_battle_param("ep4_solo_hard.toml")),
|
||||
RoomMode::Single {episode: Episode::Four, difficulty: Difficulty::VeryHard} => Ok(load_battle_param("ep4_solo_veryhard.toml")),
|
||||
RoomMode::Single {episode: Episode::Four, difficulty: Difficulty::Ultimate} => Ok(load_battle_param("ep4_solo_ultimate.toml")),
|
||||
_ => Err(MonsterStatError),
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
use libpso::packet::login::{Login, LoginResponse, AccountStatus, Session};
|
||||
use libpso::packet::ship::*;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use networking::serverstate::ClientId;
|
||||
use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients};
|
||||
use crate::login::login::get_login_status;
|
||||
use entity::gateway::EntityGateway;
|
||||
use crate::ship::items::state::ItemState;
|
||||
use crate::common::interserver::ShipMessage;
|
||||
use items::state::ItemState;
|
||||
use networking::interserver::ShipMessage;
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn validate_login<EG>(id: ClientId,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use libpso::packet::ship::*;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use networking::serverstate::ClientId;
|
||||
use crate::ship::ship::{SendShipPacket, Clients};
|
||||
use crate::ship::location::{ClientLocation};
|
||||
use location::{ClientLocation};
|
||||
use entity::gateway::EntityGateway;
|
||||
|
||||
use futures::future::join_all;
|
||||
|
@ -4,21 +4,21 @@ use rand::seq::SliceRandom;
|
||||
use libpso::packet::ship::*;
|
||||
use libpso::packet::messages::*;
|
||||
use stats::leveltable::LEVEL_TABLE;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use networking::serverstate::ClientId;
|
||||
use crate::ship::ship::{SendShipPacket, ShipError, Clients, ItemShops};
|
||||
use crate::ship::location::ClientLocation;
|
||||
use crate::ship::drops::ItemDrop;
|
||||
use crate::ship::room::Rooms;
|
||||
use crate::ship::items::ClientItemId;
|
||||
use location::ClientLocation;
|
||||
use drops::ItemDrop;
|
||||
use room::Rooms;
|
||||
use items::ClientItemId;
|
||||
use entity::gateway::EntityGateway;
|
||||
use entity::item;
|
||||
use libpso::utf8_to_utf16_array;
|
||||
use crate::ship::packet::builder;
|
||||
use pktbuilder as builder;
|
||||
use shops::{ShopItem, ToolShopItem, ArmorShopItem};
|
||||
use crate::ship::items::state::{ItemState, ItemStateError};
|
||||
use crate::ship::items::floor::{FloorType, FloorItemDetail};
|
||||
use crate::ship::items::actions::TriggerCreateItem;
|
||||
use crate::ship::items::tasks::{pick_up_item, withdraw_meseta, deposit_meseta, withdraw_item, deposit_item, buy_shop_item, enemy_drops_item, box_drops_item, take_meseta, apply_modifier};
|
||||
use items::state::{ItemState, ItemStateError};
|
||||
use items::floor::{FloorType, FloorItemDetail};
|
||||
use items::actions::TriggerCreateItem;
|
||||
use items::tasks::{pick_up_item, withdraw_meseta, deposit_meseta, withdraw_item, deposit_item, buy_shop_item, enemy_drops_item, box_drops_item, take_meseta, apply_modifier};
|
||||
|
||||
const BANK_ACTION_DEPOSIT: u8 = 0;
|
||||
const BANK_ACTION_WITHDRAW: u8 = 1;
|
||||
@ -122,7 +122,7 @@ where
|
||||
})).await?;
|
||||
|
||||
let floor_item = enemy_drops_item(item_state, entity_gateway, character_id, room_entity_id, monster.monster, item_drop).await?;
|
||||
let item_drop_msg = builder::message::item_drop(request_item.client, request_item.target, &floor_item)?;
|
||||
let item_drop_msg = builder::message::item_drop(request_item.client, request_item.target, &floor_item);
|
||||
|
||||
item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))));
|
||||
}
|
||||
@ -149,10 +149,10 @@ where
|
||||
let mut item_state = item_state.clone();
|
||||
Box::pin(async move {
|
||||
let (item, floor_type) = item_state.get_floor_item(&client.character.id, &ClientItemId(pickup_item.item_id)).await?;
|
||||
let remove_item = builder::message::remove_item_from_floor(area_client, &item)?;
|
||||
let remove_item = builder::message::remove_item_from_floor(area_client, &item);
|
||||
let create_item = match &item.item {
|
||||
FloorItemDetail::Individual(individual_floor_item) => Some(builder::message::create_individual_item(area_client, item.item_id, individual_floor_item)?),
|
||||
FloorItemDetail::Stacked(stacked_floor_item) => Some(builder::message::create_stacked_item(area_client, item.item_id, &stacked_floor_item.tool, stacked_floor_item.count())?),
|
||||
FloorItemDetail::Individual(individual_floor_item) => Some(builder::message::create_individual_item(area_client, item.item_id, individual_floor_item)),
|
||||
FloorItemDetail::Stacked(stacked_floor_item) => Some(builder::message::create_stacked_item(area_client, item.item_id, &stacked_floor_item.tool, stacked_floor_item.count())),
|
||||
FloorItemDetail::Meseta(_) => None,
|
||||
};
|
||||
|
||||
@ -234,7 +234,7 @@ where
|
||||
})).await?;
|
||||
let floor_item = box_drops_item(item_state, entity_gateway, character_id, room_entity_id, item_drop).await?;
|
||||
//let floor_item = enemy_drops_item(item_state, &mut entity_gateway, client.character.id, item_drop).await?;
|
||||
let item_drop_msg = builder::message::item_drop(box_drop_request.client, box_drop_request.target, &floor_item)?;
|
||||
let item_drop_msg = builder::message::item_drop(box_drop_request.client, box_drop_request.target, &floor_item);
|
||||
item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))))
|
||||
}
|
||||
|
||||
@ -293,7 +293,7 @@ where
|
||||
}
|
||||
else {
|
||||
let item_added_to_inventory = withdraw_item(&mut item_state, &mut entity_gateway, &client.character, &ClientItemId(bank_interaction.item_id), bank_interaction.item_amount as u32).await?;
|
||||
let item_created = builder::message::create_withdrawn_inventory_item2(area_client, &item_added_to_inventory)?;
|
||||
let item_created = builder::message::create_withdrawn_inventory_item2(area_client, &item_added_to_inventory);
|
||||
vec![SendShipPacket::Message(Message::new(GameMessage::CreateItem(item_created)))]
|
||||
}
|
||||
},
|
||||
@ -440,7 +440,7 @@ where
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok::<_, anyhow::Error>(builder::message::create_withdrawn_inventory_item(area_client, &inventory_item)?)
|
||||
Ok::<_, anyhow::Error>(builder::message::create_withdrawn_inventory_item(area_client, &inventory_item))
|
||||
})}).await??;
|
||||
|
||||
let other_clients_in_area = client_location.get_client_neighbors(id).await?;
|
||||
@ -503,7 +503,7 @@ where
|
||||
});
|
||||
|
||||
take_meseta(&mut item_state, &mut entity_gateway, &client.character.id, item::Meseta(100)).await?;
|
||||
Ok::<_, anyhow::Error>(builder::message::tek_preview(ClientItemId(tek_request.item_id), &weapon)?)
|
||||
Ok::<_, anyhow::Error>(builder::message::tek_preview(ClientItemId(tek_request.item_id), &weapon))
|
||||
})}).await??;
|
||||
|
||||
|
||||
@ -539,7 +539,7 @@ where
|
||||
};
|
||||
let weapon = apply_modifier(&mut item_state, &mut entity_gateway, &client.character, item_id, item::ItemModifier::WeaponModifier(modifier)).await?;
|
||||
|
||||
let create_item_pkt = builder::message::create_individual_item(area_client, item_id, &weapon)?;
|
||||
let create_item_pkt = builder::message::create_individual_item(area_client, item_id, &weapon);
|
||||
|
||||
Ok(neighbors.into_iter()
|
||||
.map(move |c| {
|
||||
|
@ -1,12 +1,14 @@
|
||||
use libpso::packet::ship::*;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use networking::serverstate::ClientId;
|
||||
use stats::leveltable::LEVEL_TABLE;
|
||||
use crate::ship::ship::{SendShipPacket, ShipError, Clients, ShipEvent};
|
||||
use crate::ship::room::Rooms;
|
||||
use crate::ship::character::{FullCharacterBytesBuilder};
|
||||
use crate::ship::location::{ClientLocation, LobbyId, RoomLobby, ClientLocationError, RoomId};
|
||||
use crate::ship::packet;
|
||||
use crate::ship::items::state::ItemState;
|
||||
use crate::ship::ship::{SendShipPacket, ShipError};
|
||||
use maps::Holiday;
|
||||
use client::Clients;
|
||||
use room::Rooms;
|
||||
use pktbuilder::character::FullCharacterBytesBuilder;
|
||||
use location::{ClientLocation, LobbyId, RoomLobby, ClientLocationError, RoomId};
|
||||
//use pktbuilder;
|
||||
use items::state::ItemState;
|
||||
use entity::gateway::EntityGateway;
|
||||
use entity::room::RoomNote;
|
||||
use maps::area::MapArea;
|
||||
@ -57,11 +59,11 @@ pub async fn send_player_to_lobby(id: ClientId,
|
||||
client_location: &mut ClientLocation,
|
||||
clients: &Clients,
|
||||
item_state: &ItemState,
|
||||
event: ShipEvent)
|
||||
event: Holiday)
|
||||
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
||||
let lobby = client_location.add_client_to_next_available_lobby(id, LobbyId(0)).await.map_err(|_| ShipError::TooManyClients)?;
|
||||
let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_state, event).await?;
|
||||
let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_state, event).await?;
|
||||
let join_lobby = pktbuilder::lobby::join_lobby(id, lobby, client_location, clients, item_state, event).await?;
|
||||
let addto = pktbuilder::lobby::add_to_lobby(id, lobby, client_location, clients, item_state, event).await?;
|
||||
let neighbors = client_location.get_client_neighbors(id).await.unwrap();
|
||||
Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))]
|
||||
.into_iter()
|
||||
@ -77,7 +79,7 @@ pub async fn change_lobby<EG>(id: ClientId,
|
||||
item_state: &mut ItemState,
|
||||
rooms: &Rooms,
|
||||
entity_gateway: &mut EG,
|
||||
event: ShipEvent)
|
||||
event: Holiday)
|
||||
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error>
|
||||
where
|
||||
EG: EntityGateway + Clone + 'static,
|
||||
@ -111,7 +113,7 @@ where
|
||||
})}).await??;
|
||||
},
|
||||
}
|
||||
let leave_lobby = packet::builder::lobby::remove_from_lobby(id, client_location).await?;
|
||||
let leave_lobby = pktbuilder::lobby::remove_from_lobby(id, client_location).await?;
|
||||
let old_neighbors = client_location.get_client_neighbors(id).await.unwrap();
|
||||
let mut lobby = LobbyId(requested_lobby as usize);
|
||||
if client_location.add_client_to_lobby(id, lobby).await.is_err() {
|
||||
@ -131,8 +133,8 @@ where
|
||||
Box::pin(async move {
|
||||
item_state.load_character(&mut entity_gateway, &client.character).await
|
||||
})}).await??;
|
||||
let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_state, event).await?;
|
||||
let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_state, event).await?;
|
||||
let join_lobby = pktbuilder::lobby::join_lobby(id, lobby, client_location, clients, item_state, event).await?;
|
||||
let addto = pktbuilder::lobby::add_to_lobby(id, lobby, client_location, clients, item_state, event).await?;
|
||||
let neighbors = client_location.get_client_neighbors(id).await?;
|
||||
Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))]
|
||||
.into_iter()
|
||||
|
@ -2,15 +2,16 @@ use libpso::packet::ship::*;
|
||||
use libpso::packet::messages::*;
|
||||
use entity::gateway::EntityGateway;
|
||||
use entity::item::Meseta;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use networking::serverstate::ClientId;
|
||||
use stats::leveltable::LEVEL_TABLE;
|
||||
use crate::ship::ship::{SendShipPacket, ShipError, Clients, ItemDropLocation};
|
||||
use crate::ship::room::Rooms;
|
||||
use crate::ship::location::{ClientLocation, ClientLocationError};
|
||||
use crate::ship::items::ClientItemId;
|
||||
use crate::ship::packet::builder;
|
||||
use crate::ship::items::state::ItemState;
|
||||
use crate::ship::items::tasks::{drop_item, drop_partial_item, drop_meseta, equip_item, unequip_item, sort_inventory, use_item, feed_mag, sell_item, take_meseta, floor_item_limit_reached};
|
||||
use crate::ship::ship::{SendShipPacket, ShipError};
|
||||
use client::{Clients, ItemDropLocation};
|
||||
use ::room::Rooms;
|
||||
use location::{ClientLocation, ClientLocationError};
|
||||
use items::ClientItemId;
|
||||
use pktbuilder as builder;
|
||||
use items::state::ItemState;
|
||||
use items::tasks::{drop_item, drop_partial_item, drop_meseta, equip_item, unequip_item, sort_inventory, use_item, feed_mag, sell_item, take_meseta, floor_item_limit_reached};
|
||||
|
||||
pub async fn request_exp<EG>(id: ClientId,
|
||||
request_exp: RequestExp,
|
||||
@ -162,7 +163,7 @@ where
|
||||
drop_meseta(&mut item_state, &mut entity_gateway, &client.character, drop_location.map_area, (drop_location.x, drop_location.z), no_longer_has_item.amount).await
|
||||
})}).await??;
|
||||
|
||||
let dropped_meseta_pkt = builder::message::drop_split_meseta_stack(area_client, &dropped_meseta)?;
|
||||
let dropped_meseta_pkt = builder::message::drop_split_meseta_stack(area_client, &dropped_meseta);
|
||||
let no_longer_has_meseta_pkt = builder::message::player_no_longer_has_meseta(area_client, no_longer_has_item.amount);
|
||||
|
||||
let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
@ -198,7 +199,7 @@ where
|
||||
no_longer_has_item.amount)
|
||||
.await
|
||||
})}).await??;
|
||||
let dropped_item_pkt = builder::message::drop_split_stack(area_client, &dropped_item)?;
|
||||
let dropped_item_pkt = builder::message::drop_split_stack(area_client, &dropped_item);
|
||||
|
||||
let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
Ok(clients_in_area.into_iter()
|
||||
@ -348,6 +349,15 @@ where
|
||||
})}).await??
|
||||
.into_iter()
|
||||
.flat_map(move |pkt| {
|
||||
let pkt = match pkt {
|
||||
items::actions::CreateItem::Individual(area_client, item_id, item_detail) => {
|
||||
builder::message::create_individual_item(area_client, item_id, &item_detail)
|
||||
},
|
||||
items::actions::CreateItem::Stacked(area_client, item_id, tool, amount) => {
|
||||
builder::message::create_stacked_item(area_client, item_id, &tool, amount)
|
||||
}
|
||||
};
|
||||
let pkt = SendShipPacket::Message(Message::new(GameMessage::CreateItem(pkt)));
|
||||
let player_use_tool = player_use_tool.clone();
|
||||
neighbors.clone().map(move |client| {
|
||||
vec![(client.client, SendShipPacket::Message(Message::new(GameMessage::PlayerUseItem(player_use_tool.clone())))), (client.client, pkt.clone())]
|
||||
|
@ -1,12 +1,14 @@
|
||||
use std::io::{Cursor, Read, Seek, SeekFrom};
|
||||
use futures::stream::{FuturesOrdered, StreamExt};
|
||||
use libpso::packet::ship::*;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use crate::ship::ship::{SendShipPacket, ShipError, Clients, ShipEvent};
|
||||
use crate::ship::room::Rooms;
|
||||
use networking::serverstate::ClientId;
|
||||
use crate::ship::ship::{SendShipPacket, ShipError};
|
||||
use client::Clients;
|
||||
use maps::Holiday;
|
||||
use room::Rooms;
|
||||
use maps::enemy::RareMonsterAppearTable;
|
||||
use crate::ship::location::{ClientLocation};
|
||||
use crate::ship::packet::builder::quest;
|
||||
use location::{ClientLocation};
|
||||
use pktbuilder::quest;
|
||||
use libpso::util::array_to_utf8;
|
||||
|
||||
enum QuestFileType {
|
||||
@ -97,7 +99,7 @@ pub async fn player_chose_quest(id: ClientId,
|
||||
clients: &Clients,
|
||||
client_location: &ClientLocation,
|
||||
rooms: &Rooms,
|
||||
event: ShipEvent)
|
||||
event: Holiday)
|
||||
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
||||
let room_id = client_location.get_room(id).await?;
|
||||
|
||||
@ -118,7 +120,7 @@ pub async fn player_chose_quest(id: ClientId,
|
||||
.clone();
|
||||
|
||||
let rare_monster_table = RareMonsterAppearTable::new(room.mode.episode());
|
||||
room.maps.set_quest_data(quest.enemies.clone(), quest.objects.clone(), &rare_monster_table, event.rare_enemy_event());
|
||||
room.maps.set_quest_data(quest.enemies.clone(), quest.objects.clone(), &rare_monster_table, event);
|
||||
room.map_areas = quest.map_areas.clone();
|
||||
|
||||
let bin = quest::quest_header(&questmenuselect, &quest.bin_blob, "bin");
|
||||
|
@ -5,20 +5,21 @@ use async_std::sync::Arc;
|
||||
|
||||
use libpso::packet::ship::*;
|
||||
use libpso::packet::messages::*;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use networking::serverstate::ClientId;
|
||||
use stats::leveltable::LEVEL_TABLE;
|
||||
use entity::gateway::EntityGateway;
|
||||
use entity::character::SectionID;
|
||||
use entity::room::{NewRoomEntity, RoomEntityMode, RoomNote};
|
||||
use crate::ship::drops::DropTable;
|
||||
use crate::ship::ship::{SendShipPacket, Clients, ShipEvent};
|
||||
use crate::ship::room::{Rooms, RoomState, RoomCreationError};
|
||||
use drops::DropTable;
|
||||
use crate::ship::ship::SendShipPacket;
|
||||
use client::Clients;
|
||||
use room::{Rooms, RoomState, RoomCreationError};
|
||||
use maps::Holiday;
|
||||
use maps::room::{Episode, Difficulty, RoomMode};
|
||||
use maps::enemy::RareEnemyEvent;
|
||||
use maps::maps::Maps;
|
||||
use crate::ship::location::{ClientLocation, RoomId, RoomLobby, GetAreaError};
|
||||
use crate::ship::packet::builder;
|
||||
use crate::ship::items::state::ItemState;
|
||||
use location::{ClientLocation, RoomId, RoomLobby, GetAreaError};
|
||||
use pktbuilder as builder;
|
||||
use items::state::ItemState;
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn create_room<EG>(id: ClientId,
|
||||
@ -28,9 +29,9 @@ pub async fn create_room<EG>(id: ClientId,
|
||||
clients: &Clients,
|
||||
item_state: &mut ItemState,
|
||||
rooms: &Rooms,
|
||||
map_builder: Arc<Box<dyn Fn(RoomMode, Option<RareEnemyEvent>) -> Maps + Send + Sync>>,
|
||||
map_builder: Arc<Box<dyn Fn(RoomMode, Holiday) -> Maps + Send + Sync>>,
|
||||
drop_table_builder: Arc<Box<dyn Fn(Episode, Difficulty, SectionID) -> DropTable + Send + Sync>>,
|
||||
event: ShipEvent)
|
||||
event: Holiday)
|
||||
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error>
|
||||
where
|
||||
EG: EntityGateway + Clone + 'static,
|
||||
@ -136,7 +137,7 @@ pub async fn join_room<EG>(id: ClientId,
|
||||
clients: &Clients,
|
||||
item_state: &mut ItemState,
|
||||
rooms: &Rooms,
|
||||
event: ShipEvent)
|
||||
event: Holiday)
|
||||
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error>
|
||||
where
|
||||
EG: EntityGateway + Clone + 'static,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use libpso::packet::ship::*;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use networking::serverstate::ClientId;
|
||||
use crate::ship::ship::{SendShipPacket, Clients};
|
||||
use entity::gateway::EntityGateway;
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
use async_std::sync::{Arc, RwLock};
|
||||
use libpso::packet::ship::*;
|
||||
use libpso::packet::login::RedirectClient;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use crate::common::interserver::Ship;
|
||||
use networking::serverstate::ClientId;
|
||||
use networking::interserver::Ship;
|
||||
use crate::ship::ship::{SendShipPacket, ShipError};
|
||||
use crate::ship::packet::builder;
|
||||
use pktbuilder as builder;
|
||||
|
||||
pub async fn ship_list(id: ClientId, ship_list: &Arc<RwLock<Vec<Ship>>>) -> Vec<(ClientId, SendShipPacket)> {
|
||||
let ship_list = ship_list
|
||||
|
@ -1,19 +1,19 @@
|
||||
use std::convert::TryInto;
|
||||
use libpso::packet::ship::*;
|
||||
use libpso::packet::messages::*;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use networking::serverstate::ClientId;
|
||||
use crate::ship::ship::{SendShipPacket, ShipError, Clients};
|
||||
use crate::ship::location::{ClientLocation};
|
||||
use crate::ship::items::ClientItemId;
|
||||
use crate::ship::items::state::{ItemState, ItemStateError};
|
||||
use crate::ship::items::inventory::InventoryItemDetail;
|
||||
use crate::ship::trade::{TradeItem, TradeState, TradeStatus};
|
||||
use location::{ClientLocation};
|
||||
use items::ClientItemId;
|
||||
use items::state::{ItemState, ItemStateError};
|
||||
use items::inventory::InventoryItemDetail;
|
||||
use items::trade::TradeItem;
|
||||
use entity::gateway::EntityGateway;
|
||||
use crate::ship::packet::builder;
|
||||
use crate::ship::items::tasks::trade_items;
|
||||
use crate::ship::location::{AreaClient, RoomId};
|
||||
use pktbuilder as builder;
|
||||
use items::tasks::trade_items;
|
||||
use location::{AreaClient, RoomId};
|
||||
use entity::item::Meseta;
|
||||
use crate::ship::trade::ClientTradeState;
|
||||
use trade::{ClientTradeState, TradeState, TradeStatus};
|
||||
|
||||
pub const MESETA_ITEM_ID: ClientItemId = ClientItemId(0xFFFFFF01);
|
||||
pub const OTHER_MESETA_ITEM_ID: ClientItemId = ClientItemId(0xFFFFFFFF);
|
||||
@ -450,8 +450,8 @@ where
|
||||
enum TradeReady/*<'a>*/ {
|
||||
OnePlayer,
|
||||
BothPlayers(RoomId,
|
||||
(AreaClient, crate::ship::trade::ClientTradeState),
|
||||
(AreaClient, crate::ship::trade::ClientTradeState)),
|
||||
(AreaClient, ClientTradeState),
|
||||
(AreaClient, ClientTradeState)),
|
||||
//(AreaClient, &'a crate::ship::ship::ClientState, crate::ship::trade::ClientTradeState),
|
||||
//(AreaClient, &'a crate::ship::ship::ClientState, crate::ship::trade::ClientTradeState)),
|
||||
}
|
||||
@ -527,10 +527,10 @@ where
|
||||
.map(|(client, item)| {
|
||||
match item.item {
|
||||
InventoryItemDetail::Individual(individual_item) => {
|
||||
GameMessage::CreateItem(builder::message::create_individual_item(client, item.item_id, &individual_item).unwrap())
|
||||
GameMessage::CreateItem(builder::message::create_individual_item(client, item.item_id, &individual_item))
|
||||
},
|
||||
InventoryItemDetail::Stacked(stacked_item) => {
|
||||
GameMessage::CreateItem(builder::message::create_stacked_item(client, item.item_id, &stacked_item.tool, stacked_item.count()).unwrap())
|
||||
GameMessage::CreateItem(builder::message::create_stacked_item(client, item.item_id, &stacked_item.tool, stacked_item.count()))
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1,2 +1,2 @@
|
||||
pub mod builder;
|
||||
//pub mod builder;
|
||||
pub mod handler;
|
||||
|
105
src/ship/ship.rs
105
src/ship/ship.rs
@ -14,31 +14,29 @@ use libpso::{PacketParseError, PSOPacket};
|
||||
use libpso::crypto::bb::PSOBBCipher;
|
||||
use libpso::packet::ship::{BLOCK_MENU_ID, ROOM_MENU_ID};
|
||||
|
||||
use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
|
||||
use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
|
||||
use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage};
|
||||
use crate::login::character::SHIP_MENU_ID;
|
||||
use networking::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
|
||||
use networking::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
|
||||
use networking::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage};
|
||||
use pktbuilder::ship::SHIP_MENU_ID;
|
||||
use entity::gateway::{EntityGateway, GatewayError};
|
||||
use entity::character::SectionID;
|
||||
use entity::room::RoomNote;
|
||||
use crate::ship::location::{ClientLocation, RoomLobby, ClientLocationError, RoomId};
|
||||
use crate::ship::drops::DropTable;
|
||||
use crate::ship::items;
|
||||
use crate::ship::room;
|
||||
use location::{ClientLocation, RoomLobby, ClientLocationError, RoomId};
|
||||
use drops::DropTable;
|
||||
use items;
|
||||
use room;
|
||||
use maps::Holiday;
|
||||
use maps::area::MapAreaError;
|
||||
use maps::maps::{Maps, MapsError, generate_free_roam_maps};
|
||||
use maps::enemy::RareEnemyEvent;
|
||||
use crate::ship::packet::handler;
|
||||
use shops::{WeaponShop, ToolShop, ArmorShop};
|
||||
use crate::ship::trade::TradeState;
|
||||
use trade::TradeState;
|
||||
use crate::ship::chatcommand;
|
||||
use pktbuilder::quest::{QUEST_CATEGORY_MENU_ID, QUEST_SELECT_MENU_ID};
|
||||
|
||||
// TODO: remove once stuff settles down
|
||||
pub use crate::ship::client::*;
|
||||
pub use client::{Clients, ClientState};
|
||||
|
||||
pub const SHIP_PORT: u16 = 23423;
|
||||
pub const QUEST_CATEGORY_MENU_ID: u32 = 0xA2;
|
||||
pub const QUEST_SELECT_MENU_ID: u32 = 0xA3;
|
||||
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
@ -100,7 +98,7 @@ pub enum ShipError {
|
||||
#[error("trade error {0}")]
|
||||
TradeError(#[from] crate::ship::packet::handler::trade::TradeError),
|
||||
#[error("trade state error {0}")]
|
||||
TradeStateError(#[from] crate::ship::trade::TradeStateError),
|
||||
TradeStateError(#[from] trade::TradeStateError),
|
||||
#[error("message error {0}")]
|
||||
MessageError(#[from] crate::ship::packet::handler::direct_message::MessageError),
|
||||
#[error("room creation error {0}")]
|
||||
@ -117,69 +115,6 @@ impl<I: Into<ClientLocationError>> From<I> for ShipError {
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum ShipEvent {
|
||||
None,
|
||||
Christmas,
|
||||
Valentines,
|
||||
Easter,
|
||||
Halloween,
|
||||
Sonic,
|
||||
NewYear,
|
||||
Summer,
|
||||
White,
|
||||
Wedding,
|
||||
Fall,
|
||||
Spring,
|
||||
Summer2,
|
||||
Spring2,
|
||||
}
|
||||
|
||||
|
||||
impl From<ShipEvent> for u32 {
|
||||
fn from(other: ShipEvent) -> u32 {
|
||||
u16::from(other) as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ShipEvent> for u16 {
|
||||
fn from(other: ShipEvent) -> u16 {
|
||||
u8::from(other) as u16
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ShipEvent> for u8 {
|
||||
fn from(other: ShipEvent) -> u8 {
|
||||
match other {
|
||||
ShipEvent::None => 0,
|
||||
ShipEvent::Christmas => 1,
|
||||
ShipEvent::Valentines => 3,
|
||||
ShipEvent::Easter => 4,
|
||||
ShipEvent::Halloween => 5,
|
||||
ShipEvent::Sonic => 6,
|
||||
ShipEvent::NewYear => 7,
|
||||
ShipEvent::Summer => 8,
|
||||
ShipEvent::White => 9,
|
||||
ShipEvent::Wedding => 10,
|
||||
ShipEvent::Fall => 11,
|
||||
ShipEvent::Spring => 12,
|
||||
ShipEvent::Summer2 => 13,
|
||||
ShipEvent::Spring2 => 14,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ShipEvent {
|
||||
pub fn rare_enemy_event(&self) -> Option<RareEnemyEvent> {
|
||||
match self {
|
||||
ShipEvent::Easter => Some(RareEnemyEvent::Easter),
|
||||
ShipEvent::Halloween => Some(RareEnemyEvent::Halloween),
|
||||
ShipEvent::Christmas => Some(RareEnemyEvent::Christmas),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -393,8 +328,8 @@ pub struct ShipServerStateBuilder<EG: EntityGateway + Clone + 'static> {
|
||||
ip: Option<Ipv4Addr>,
|
||||
port: Option<u16>,
|
||||
auth_token: Option<AuthToken>,
|
||||
event: Option<ShipEvent>,
|
||||
map_builder: Option<Box<dyn Fn(maps::room::RoomMode, Option<RareEnemyEvent>) -> Maps + Send + Sync>>,
|
||||
event: Option<Holiday>,
|
||||
map_builder: Option<Box<dyn Fn(maps::room::RoomMode, Holiday) -> Maps + Send + Sync>>,
|
||||
drop_table_builder: Option<Box<dyn Fn(maps::room::Episode, maps::room::Difficulty, SectionID) -> DropTable + Send + Sync>>,
|
||||
num_blocks: usize,
|
||||
}
|
||||
@ -447,13 +382,13 @@ impl<EG: EntityGateway + Clone + 'static> ShipServerStateBuilder<EG> {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn event(mut self, event: ShipEvent) -> ShipServerStateBuilder<EG> {
|
||||
pub fn event(mut self, event: Holiday) -> ShipServerStateBuilder<EG> {
|
||||
self.event = Some(event);
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn map_builder(mut self, map_builder: Box<dyn Fn(maps::room::RoomMode, Option<RareEnemyEvent>) -> Maps + Send + Sync>) -> ShipServerStateBuilder<EG> {
|
||||
pub fn map_builder(mut self, map_builder: Box<dyn Fn(maps::room::RoomMode, Holiday) -> Maps + Send + Sync>) -> ShipServerStateBuilder<EG> {
|
||||
self.map_builder = Some(map_builder);
|
||||
self
|
||||
}
|
||||
@ -481,7 +416,7 @@ impl<EG: EntityGateway + Clone + 'static> ShipServerStateBuilder<EG> {
|
||||
port: self.port.unwrap_or(SHIP_PORT),
|
||||
shops: ItemShops::default(),
|
||||
blocks: Blocks(blocks),
|
||||
event: self.event.unwrap_or(ShipEvent::None),
|
||||
event: self.event.unwrap_or(Holiday::None),
|
||||
map_builder: Arc::new(self.map_builder.unwrap_or(Box::new(generate_free_roam_maps))),
|
||||
drop_table_builder: Arc::new(self.drop_table_builder.unwrap_or(Box::new(DropTable::new))),
|
||||
|
||||
@ -522,7 +457,7 @@ pub struct ShipServerState<EG: EntityGateway + Clone + 'static> {
|
||||
pub(crate) item_state: items::state::ItemState,
|
||||
shops: ItemShops,
|
||||
pub blocks: Blocks,
|
||||
event: ShipEvent,
|
||||
event: Holiday,
|
||||
|
||||
ip: Ipv4Addr,
|
||||
port: u16,
|
||||
@ -531,7 +466,7 @@ pub struct ShipServerState<EG: EntityGateway + Clone + 'static> {
|
||||
ship_list: Arc<RwLock<Vec<Ship>>>,
|
||||
shipgate_sender: Option<channel::Sender<ShipMessage>>,
|
||||
trades: TradeState,
|
||||
map_builder: Arc<Box<dyn Fn(maps::room::RoomMode, Option<RareEnemyEvent>) -> Maps + Send + Sync>>,
|
||||
map_builder: Arc<Box<dyn Fn(maps::room::RoomMode, Holiday) -> Maps + Send + Sync>>,
|
||||
drop_table_builder: Arc<Box<dyn Fn(maps::room::Episode, maps::room::Difficulty, SectionID) -> DropTable + Send + Sync>>,
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use networking::serverstate::{ClientId, ServerState};
|
||||
use entity::gateway::EntityGateway;
|
||||
use entity::account::{UserAccountEntity, NewUserAccountEntity, NewUserSettingsEntity};
|
||||
use entity::character::{CharacterEntity, NewCharacterEntity};
|
||||
use entity::item::{Meseta, BankName, BankIdentifier};
|
||||
use entity::item::{Meseta, BankIdentifier};
|
||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket};
|
||||
use maps::room::Difficulty;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::collections::BTreeSet;
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use networking::serverstate::{ClientId, ServerState};
|
||||
use entity::gateway::{EntityGateway, InMemoryGateway};
|
||||
use entity::item;
|
||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket};
|
||||
|
@ -1,4 +1,4 @@
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use networking::serverstate::{ClientId, ServerState};
|
||||
use entity::gateway::{EntityGateway, InMemoryGateway};
|
||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket};
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use networking::serverstate::{ClientId, ServerState};
|
||||
use entity::gateway::{EntityGateway, InMemoryGateway};
|
||||
use elseware::common::leveltable::CharacterLevelTable;
|
||||
use stats::leveltable::CharacterLevelTable;
|
||||
use elseware::ship::ship::{ShipServerState, SendShipPacket, RecvShipPacket};
|
||||
use elseware::ship::location::RoomId;
|
||||
use maps::variant::{MapVariant, MapVariantMode};
|
||||
use maps::maps::Maps;
|
||||
use maps::area::MapArea;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use networking::serverstate::{ClientId, ServerState};
|
||||
use entity::gateway::{EntityGateway, InMemoryGateway};
|
||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket};
|
||||
use entity::item;
|
||||
|
@ -1,13 +1,9 @@
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use entity::gateway::{EntityGateway, InMemoryGateway};
|
||||
use entity::character::SectionID;
|
||||
use elseware::common::leveltable::CharacterLevelTable;
|
||||
use networking::serverstate::{ClientId, ServerState};
|
||||
use entity::gateway::InMemoryGateway;
|
||||
use elseware::ship::ship::{ShipServerState, SendShipPacket, RecvShipPacket};
|
||||
use maps::room::{Episode, Difficulty};
|
||||
use maps::monster::MonsterType;
|
||||
use elseware::ship::location::RoomId;
|
||||
use elseware::ship::drops::{DropTable, MonsterDropStats, MonsterDropType};
|
||||
use elseware::ship::drops::rare_drop_table::{RareDropTable, RareDropRate, RareDropItem};
|
||||
use drops::{DropTable, MonsterDropStats, MonsterDropType};
|
||||
use drops::rare_drop_table::{RareDropTable, RareDropRate, RareDropItem};
|
||||
use maps::maps::Maps;
|
||||
use maps::area::MapArea;
|
||||
use maps::variant::{MapVariant, MapVariantMode};
|
||||
|
@ -1,9 +1,7 @@
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use networking::serverstate::{ClientId, ServerState};
|
||||
use entity::gateway::{EntityGateway, InMemoryGateway};
|
||||
use entity::item;
|
||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket};
|
||||
use entity::character::TechLevel;
|
||||
//use elseware::ship::items::{ClientItemId, ActiveItemEntityId, HeldItemType, FloorItemType};
|
||||
|
||||
use libpso::packet::ship::*;
|
||||
use libpso::packet::messages::*;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use networking::serverstate::{ClientId, ServerState};
|
||||
use entity::gateway::{EntityGateway, InMemoryGateway};
|
||||
use entity::item;
|
||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket};
|
||||
|
@ -1,9 +1,8 @@
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use networking::serverstate::{ClientId, ServerState};
|
||||
use entity::gateway::{EntityGateway, InMemoryGateway};
|
||||
use entity::item;
|
||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket};
|
||||
use entity::character::TechLevel;
|
||||
//use elseware::ship::items::{ClientItemId, ActiveItemEntityId, HeldItemType, FloorItemType};
|
||||
|
||||
use libpso::packet::ship::*;
|
||||
use libpso::packet::messages::*;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use networking::serverstate::{ClientId, ServerState};
|
||||
use entity::gateway::{EntityGateway, InMemoryGateway};
|
||||
use entity::item;
|
||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket};
|
||||
|
@ -1,8 +1,6 @@
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use networking::serverstate::{ClientId, ServerState};
|
||||
use entity::gateway::{EntityGateway, InMemoryGateway};
|
||||
use entity::item;
|
||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket};
|
||||
use elseware::ship::location::RoomId;
|
||||
|
||||
use libpso::packet::ship::*;
|
||||
//use libpso::packet::messages::*;
|
||||
|
@ -1,9 +1,9 @@
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use networking::serverstate::{ClientId, ServerState};
|
||||
use entity::gateway::{EntityGateway, InMemoryGateway};
|
||||
use entity::item;
|
||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket, ShipError};
|
||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket};
|
||||
use maps::room::Difficulty;
|
||||
use elseware::ship::items::state::ItemStateError;
|
||||
use items::state::ItemStateError;
|
||||
|
||||
use libpso::packet::ship::*;
|
||||
use libpso::packet::messages::*;
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::convert::TryInto;
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use networking::serverstate::{ClientId, ServerState};
|
||||
use entity::gateway::{EntityGateway, InMemoryGateway};
|
||||
use entity::item;
|
||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket, ShipError};
|
||||
|
14
trade/Cargo.toml
Normal file
14
trade/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "trade"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
|
||||
[dependencies]
|
||||
networking = { workspace = true }
|
||||
items = { workspace = true }
|
||||
|
||||
async-std = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
thiserror = { workspace = true }
|
4
trade/src/lib.rs
Normal file
4
trade/src/lib.rs
Normal file
@ -0,0 +1,4 @@
|
||||
pub mod trade;
|
||||
|
||||
|
||||
pub use trade::*;
|
@ -1,45 +1,9 @@
|
||||
use std::collections::HashMap;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use crate::ship::items;
|
||||
use networking::serverstate::ClientId;
|
||||
use items;
|
||||
use async_std::sync::{Arc, Mutex, MutexGuard};
|
||||
use futures::future::{Future, OptionFuture};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TradeItem {
|
||||
Individual(items::ClientItemId),
|
||||
Stacked(items::ClientItemId, usize),
|
||||
}
|
||||
|
||||
impl TradeItem {
|
||||
pub fn stacked(&self) -> Option<(items::ClientItemId, usize)> {
|
||||
match self {
|
||||
TradeItem::Stacked(item_id, amount) => Some((*item_id, *amount)),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stacked_mut(&mut self) -> Option<(items::ClientItemId, &mut usize)> {
|
||||
match self {
|
||||
TradeItem::Stacked(item_id, ref mut amount) => Some((*item_id, amount)),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn item_id(&self) -> items::ClientItemId {
|
||||
match self {
|
||||
TradeItem::Individual(item_id) => *item_id,
|
||||
TradeItem::Stacked(item_id, _) => *item_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn amount(&self) -> usize {
|
||||
match self {
|
||||
TradeItem::Individual(_) => 1,
|
||||
TradeItem::Stacked(_, amount) => *amount,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use items::trade::TradeItem;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum TradeStatus {
|
Loading…
x
Reference in New Issue
Block a user