jake
1 year ago
97 changed files with 828 additions and 719 deletions
-
24Cargo.toml
-
20client/Cargo.toml
-
18client/src/client.rs
-
3client/src/lib.rs
-
17drops/Cargo.toml
-
14drops/src/box_drop_table.rs
-
2drops/src/generic_armor.rs
-
2drops/src/generic_shield.rs
-
2drops/src/generic_unit.rs
-
2drops/src/generic_weapon.rs
-
15drops/src/lib.rs
-
8drops/src/rare_drop_table.rs
-
2drops/src/tech_table.rs
-
4drops/src/tool_table.rs
-
25items/Cargo.toml
-
36items/src/actions.rs
-
4items/src/apply_item.rs
-
8items/src/bank.rs
-
8items/src/floor.rs
-
8items/src/inventory.rs
-
0items/src/itemstateaction.rs
-
3items/src/lib.rs
-
18items/src/manager.rs
-
14items/src/state.rs
-
21items/src/tasks.rs
-
38items/src/trade.rs
-
12location/Cargo.toml
-
3location/src/lib.rs
-
2location/src/location.rs
-
18maps/src/enemy.rs
-
52maps/src/lib.rs
-
7maps/src/maps.rs
-
14networking/Cargo.toml
-
0networking/src/cipherkeys.rs
-
0networking/src/interserver.rs
-
18networking/src/lib.rs
-
6networking/src/mainloop/client.rs
-
9networking/src/mainloop/interserver.rs
-
0networking/src/mainloop/mod.rs
-
0networking/src/serverstate.rs
-
22pktbuilder/Cargo.toml
-
5pktbuilder/src/character.rs
-
9pktbuilder/src/lib.rs
-
15pktbuilder/src/lobby.rs
-
100pktbuilder/src/message.rs
-
5pktbuilder/src/quest.rs
-
21pktbuilder/src/room.rs
-
5pktbuilder/src/ship.rs
-
107pktbuilder/src/team.rs
-
0pktbuilder/src/trade.rs
-
18quests/Cargo.toml
-
4quests/src/lib.rs
-
0quests/src/quests.rs
-
17room/Cargo.toml
-
3room/src/lib.rs
-
33room/src/room.rs
-
8src/bin/login.rs
-
30src/bin/main.rs
-
4src/bin/patch.rs
-
8src/bin/ship.rs
-
18src/common/mod.rs
-
3src/lib.rs
-
11src/login/character.rs
-
4src/login/login.rs
-
4src/patch/patch.rs
-
8src/ship/chatcommand.rs
-
0src/ship/drops/drop_table.rs
-
16src/ship/mod.rs
-
212src/ship/monster.rs
-
6src/ship/packet/handler/auth.rs
-
4src/ship/packet/handler/communication.rs
-
38src/ship/packet/handler/direct_message.rs
-
30src/ship/packet/handler/lobby.rs
-
30src/ship/packet/handler/message.rs
-
16src/ship/packet/handler/quest.rs
-
23src/ship/packet/handler/room.rs
-
2src/ship/packet/handler/settings.rs
-
6src/ship/packet/handler/ship.rs
-
28src/ship/packet/handler/trade.rs
-
2src/ship/packet/mod.rs
-
105src/ship/ship.rs
-
4tests/common.rs
-
2tests/test_bank.rs
-
2tests/test_character.rs
-
5tests/test_exp_gain.rs
-
2tests/test_item_actions.rs
-
12tests/test_item_drop.rs
-
4tests/test_item_id.rs
-
2tests/test_item_pickup.rs
-
3tests/test_item_use.rs
-
2tests/test_mags.rs
-
4tests/test_rooms.rs
-
6tests/test_shops.rs
-
2tests/test_trade.rs
-
14trade/Cargo.toml
-
4trade/src/lib.rs
-
42trade/src/trade.rs
@ -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 } |
@ -0,0 +1,3 @@ |
|||
pub mod client;
|
|||
|
|||
pub use client::*;
|
@ -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 } |
@ -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,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)]
|
@ -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,
|
|||
}
|
|||
}
|
|||
}
|
|||
|
@ -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 } |
@ -0,0 +1,3 @@ |
|||
pub mod location;
|
|||
|
|||
pub use location::*;
|
@ -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
|
|||
}
|
|||
)
|
|||
);
|
@ -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;
|
|||
|
|||
|
@ -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,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()
|
@ -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,
|
|||
}
|
|||
}
|
@ -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 } |
@ -0,0 +1,4 @@ |
|||
pub mod quests;
|
|||
|
|||
|
|||
pub use quests::*;
|
@ -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 } |
@ -0,0 +1,3 @@ |
|||
pub mod room;
|
|||
|
|||
pub use room::*;
|
@ -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
|
|||
}
|
|||
)
|
|||
);
|
@ -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,2 +1,2 @@ |
|||
pub mod builder;
|
|||
//pub mod builder;
|
|||
pub mod handler;
|
@ -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 } |
@ -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 {
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue