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 std::cmp::Ordering;
|
||||
use libpso::character::character;
|
use libpso::character::character;
|
||||
use crate::ship::items::ClientItemId;
|
|
||||
|
use crate::ClientItemId;
|
||||
use entity::item::{Meseta, ItemEntityId, ItemDetail, ItemEntity, BankEntity, BankItemEntity};
|
use entity::item::{Meseta, ItemEntityId, ItemDetail, ItemEntity, BankEntity, BankItemEntity};
|
||||
use std::future::Future;
|
use std::future::Future;
|
||||
use async_std::sync::{Arc, Mutex};
|
use async_std::sync::{Arc, Mutex};
|
||||
|
|
||||
use entity::character::CharacterEntityId;
|
use entity::character::CharacterEntityId;
|
||||
use entity::item::BankIdentifier;
|
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)]
|
#[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 libpso::character::character;
|
||||
use stats::leveltable::CharacterStats;
|
use stats::leveltable::CharacterStats;
|
||||
use entity::character::CharacterEntity;
|
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;
|
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::packet::ship::*;
|
||||
use libpso::{utf8_to_array, utf8_to_utf16_array};
|
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 {
|
pub fn quest_category_list(quests: &QuestList) -> QuestCategoryList {
|
||||
let categories = quests.iter()
|
let categories = quests.iter()
|
@ -1,8 +1,9 @@ |
|||||
use libpso::packet::login::{ShipList, ShipListEntry};
|
use libpso::packet::login::{ShipList, ShipListEntry};
|
||||
use libpso::utf8_to_utf16_array;
|
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 {
|
pub fn ship_list(ships: &[Ship]) -> ShipList {
|
||||
let ships = ships.iter()
|
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)]
|
#[allow(clippy::module_inception)]
|
||||
pub mod ship;
|
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 item_stats;
|
||||
//pub mod map;
|
//pub mod map;
|
||||
//pub mod monster;
|
//pub mod monster;
|
||||
pub mod drops;
|
|
||||
|
//pub mod drops;
|
||||
pub mod packet;
|
pub mod packet;
|
||||
pub mod quests;
|
|
||||
|
//pub mod quests;
|
||||
//pub mod shops;
|
//pub mod shops;
|
||||
pub mod trade;
|
|
||||
|
//pub mod trade;
|
||||
pub mod chatcommand;
|
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;
|
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 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 async_std::sync::{Arc, Mutex, MutexGuard};
|
||||
use futures::future::{Future, OptionFuture};
|
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)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum TradeStatus {
|
pub enum TradeStatus {
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue