break out entity and maps into separate crates
This commit is contained in:
parent
13ddbc8f5e
commit
d158ac1d7f
48
Cargo.toml
48
Cargo.toml
@ -4,8 +4,20 @@ version = "0.1.0"
|
|||||||
authors = ["Jake Probst <jake.probst@gmail.com>"]
|
authors = ["Jake Probst <jake.probst@gmail.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[workspace]
|
||||||
|
members = [
|
||||||
|
"entity",
|
||||||
|
"maps",
|
||||||
|
"common",
|
||||||
|
"networking",
|
||||||
|
]
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
libpso = { git = "http://git.sharnoth.com/jake/libpso" }
|
libpso = { git = "http://git.sharnoth.com/jake/libpso" }
|
||||||
|
entity = { path = "./entity" }
|
||||||
|
maps = { path = "./maps" }
|
||||||
|
common = { path = "./common" }
|
||||||
|
networking = { path = "./networking" }
|
||||||
async-std = { version = "1.9.0", features = ["unstable", "attributes"] }
|
async-std = { version = "1.9.0", features = ["unstable", "attributes"] }
|
||||||
futures = "0.3.5"
|
futures = "0.3.5"
|
||||||
rand = "0.7.3"
|
rand = "0.7.3"
|
||||||
@ -33,3 +45,37 @@ sqlx = { version = "0.6.2", features = ["runtime-async-std-native-tls", "postgre
|
|||||||
strum = "0.19.5"
|
strum = "0.19.5"
|
||||||
strum_macros = "0.19"
|
strum_macros = "0.19"
|
||||||
anyhow = { version = "1.0.68", features = ["backtrace"] }
|
anyhow = { version = "1.0.68", features = ["backtrace"] }
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libpso = { git = "http://git.sharnoth.com/jake/libpso" }
|
||||||
|
entity = { path = "./entity" }
|
||||||
|
maps = { path = "./maps" }
|
||||||
|
common = { path = "./common" }
|
||||||
|
networking = { path = "./networking" }
|
||||||
|
async-std = { version = "1.9.0", features = ["unstable", "attributes"] }
|
||||||
|
futures = "0.3.5"
|
||||||
|
rand = "0.7.3"
|
||||||
|
rand_chacha = "0.2.2"
|
||||||
|
crc = "^1.0.0"
|
||||||
|
bcrypt = "0.10"
|
||||||
|
chrono = { workspace = true }
|
||||||
|
serde = "*"
|
||||||
|
serde_json = "*"
|
||||||
|
ron = "*"
|
||||||
|
toml = "*"
|
||||||
|
log = "*"
|
||||||
|
fern = { version = "0.5", features = ["colored"] }
|
||||||
|
byteorder = "1"
|
||||||
|
enum-utils = "0.1.2"
|
||||||
|
derive_more = { version = "0.99.3", features = ["display"]}
|
||||||
|
thiserror = "1.0.37"
|
||||||
|
ages-prs = "0.1"
|
||||||
|
async-trait = "0.1.51"
|
||||||
|
async-recursion= "1.0.0"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
barrel = { version = "0.6.5", features = ["pg"] }
|
||||||
|
refinery = { version = "0.5.0", features = ["postgres"] }
|
||||||
|
#sqlx = { version = "0.6.2", features = ["runtime-async-std-native-tls", "postgres", "json", "chrono"] }
|
||||||
|
strum = "0.19.5"
|
||||||
|
strum_macros = "0.19"
|
||||||
|
anyhow = { workspace = true }
|
8
common/Cargo.toml
Normal file
8
common/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "common"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
derive_more = { workspace = true }
|
0
common/src/lib.rs
Normal file
0
common/src/lib.rs
Normal file
57
entity/Cargo.toml
Normal file
57
entity/Cargo.toml
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
[package]
|
||||||
|
name = "entity"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libpso = { workspace = true }
|
||||||
|
maps = { workspace = true }
|
||||||
|
chrono = { workspace = true }
|
||||||
|
anyhow = { workspace = true }
|
||||||
|
async-std = { workspace = true }
|
||||||
|
sqlx = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
|
serde = { workspace = true }
|
||||||
|
async-trait = { workspace = true }
|
||||||
|
enum-utils = { workspace = true }
|
||||||
|
derive_more = { workspace = true }
|
||||||
|
refinery = { workspace = true }
|
||||||
|
lazy_static = { workspace = true }
|
||||||
|
futures = { workspace = true }
|
||||||
|
strum = { workspace = true }
|
||||||
|
strum_macros = { workspace = true }
|
||||||
|
toml = { workspace = true }
|
||||||
|
|
||||||
|
|
||||||
|
#libpso = { git = "http://git.sharnoth.com/jake/libpso" }
|
||||||
|
#async-std = { version = "1.9.0", features = ["unstable", "attributes"] }
|
||||||
|
#futures = "0.3.5"
|
||||||
|
#rand = "0.7.3"
|
||||||
|
#rand_chacha = "0.2.2"
|
||||||
|
#crc = "^1.0.0"
|
||||||
|
#bcrypt = "0.10"
|
||||||
|
#chrono = "0.4.11"
|
||||||
|
#serde = "*"
|
||||||
|
#serde_json = "*"
|
||||||
|
#ron = "*"
|
||||||
|
#toml = "*"
|
||||||
|
#log = "*"
|
||||||
|
#fern = { version = "0.5", features = ["colored"] }
|
||||||
|
#byteorder = "1"
|
||||||
|
#enum-utils = "0.1.2"
|
||||||
|
#derive_more = { version = "0.99.3", features = ["display"]}
|
||||||
|
#thiserror = "1.0.37"
|
||||||
|
#ages-prs = "0.1"
|
||||||
|
#async-trait = "0.1.51"
|
||||||
|
#async-recursion= "1.0.0"
|
||||||
|
#lazy_static = "1.4.0"
|
||||||
|
#barrel = { version = "0.6.5", features = ["pg"] }
|
||||||
|
#refinery = { version = "0.5.0", features = ["postgres"] }
|
||||||
|
#sqlx = { version = "0.6.2", features = ["runtime-async-std-native-tls", "postgres", "json", "chrono"] }
|
||||||
|
#strum = "0.19.5"
|
||||||
|
#strum_macros = "0.19"
|
||||||
|
#anyhow = { version = "1.0.68", features = ["backtrace"] }
|
||||||
|
|
||||||
|
#[lib]
|
||||||
|
#name = "entity"
|
||||||
|
#path = "lib.rs"
|
@ -4,8 +4,8 @@ use serde::{Serialize, Deserialize};
|
|||||||
|
|
||||||
use libpso::packet::ship::{UpdateConfig, WriteInfoboard};
|
use libpso::packet::ship::{UpdateConfig, WriteInfoboard};
|
||||||
use libpso::character::settings::{DEFAULT_PALETTE_CONFIG, DEFAULT_TECH_MENU};
|
use libpso::character::settings::{DEFAULT_PALETTE_CONFIG, DEFAULT_TECH_MENU};
|
||||||
use crate::entity::item::tech::Technique;
|
use crate::item::tech::Technique;
|
||||||
use crate::entity::account::UserAccountId;
|
use crate::account::UserAccountId;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, enum_utils::FromStr, derive_more::Display, Serialize, Deserialize, Default)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, enum_utils::FromStr, derive_more::Display, Serialize, Deserialize, Default)]
|
||||||
pub enum CharacterClass {
|
pub enum CharacterClass {
|
@ -1,10 +1,10 @@
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use futures::future::{Future, BoxFuture};
|
use futures::future::{Future, BoxFuture};
|
||||||
|
|
||||||
use crate::entity::account::*;
|
use crate::account::*;
|
||||||
use crate::entity::character::*;
|
use crate::character::*;
|
||||||
use crate::entity::item::*;
|
use crate::item::*;
|
||||||
use crate::entity::room::*;
|
use crate::room::*;
|
||||||
|
|
||||||
|
|
||||||
// TODO: better granularity?
|
// TODO: better granularity?
|
@ -2,11 +2,11 @@ use std::collections::BTreeMap;
|
|||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use futures::future::{Future, BoxFuture};
|
use futures::future::{Future, BoxFuture};
|
||||||
|
|
||||||
use crate::entity::account::*;
|
use crate::account::*;
|
||||||
use crate::entity::character::*;
|
use crate::character::*;
|
||||||
use crate::entity::gateway::{EntityGateway, EntityGatewayTransaction, GatewayError};
|
use crate::gateway::{EntityGateway, EntityGatewayTransaction, GatewayError};
|
||||||
use crate::entity::item::*;
|
use crate::item::*;
|
||||||
use crate::entity::room::*;
|
use crate::room::*;
|
||||||
|
|
||||||
use async_std::sync::{Arc, Mutex};
|
use async_std::sync::{Arc, Mutex};
|
||||||
|
|
3
entity/src/gateway/postgres/migrations/mod.rs
Normal file
3
entity/src/gateway/postgres/migrations/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
use refinery::include_migration_mods;
|
||||||
|
|
||||||
|
include_migration_mods!("src/gateway/postgres/migrations");
|
@ -4,13 +4,13 @@ use std::convert::Into;
|
|||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use libpso::character::settings;
|
use libpso::character::settings;
|
||||||
use libpso::util::vec_to_array;
|
use libpso::util::vec_to_array;
|
||||||
use crate::entity::account::*;
|
use crate::account::*;
|
||||||
use crate::entity::character::*;
|
use crate::character::*;
|
||||||
use crate::entity::item::*;
|
use crate::item::*;
|
||||||
use crate::entity::room::*;
|
use crate::room::*;
|
||||||
use crate::ship::map::MapArea;
|
use maps::area::MapArea;
|
||||||
use crate::ship::room::{Episode, Difficulty};
|
use maps::room::{Episode, Difficulty};
|
||||||
use crate::ship::monster::MonsterType;
|
use maps::monster::MonsterType;
|
||||||
|
|
||||||
#[derive(Debug, sqlx::FromRow)]
|
#[derive(Debug, sqlx::FromRow)]
|
||||||
pub struct PgUserAccount {
|
pub struct PgUserAccount {
|
@ -1,16 +1,16 @@
|
|||||||
// this lint is currently bugged and suggests incorrect code https://github.com/rust-lang/rust-clippy/issues/9123
|
// this lint is currently bugged and suggests incorrect code https://github.com/rust-lang/rust-clippy/issues/9123
|
||||||
#![allow(clippy::explicit_auto_deref)]
|
#![allow(clippy::explicit_auto_deref)]
|
||||||
|
|
||||||
use std::convert::{From, TryFrom, Into};
|
use std::convert::{From, Into};
|
||||||
use futures::future::{Future, BoxFuture};
|
use futures::future::{Future, BoxFuture};
|
||||||
use futures::stream::{StreamExt, FuturesOrdered};
|
use futures::stream::{StreamExt, FuturesOrdered};
|
||||||
use async_std::sync::{Arc, Mutex};
|
use async_std::sync::{Arc, Mutex};
|
||||||
use libpso::character::guildcard;
|
use libpso::character::guildcard;
|
||||||
use crate::entity::account::*;
|
use crate::account::*;
|
||||||
use crate::entity::character::*;
|
use crate::character::*;
|
||||||
use crate::entity::gateway::{EntityGateway, EntityGatewayTransaction, GatewayError};
|
use crate::gateway::{EntityGateway, EntityGatewayTransaction, GatewayError};
|
||||||
use crate::entity::item::*;
|
use crate::item::*;
|
||||||
use crate::entity::room::*;
|
use crate::room::*;
|
||||||
use super::models::*;
|
use super::models::*;
|
||||||
|
|
||||||
use sqlx::postgres::PgPoolOptions;
|
use sqlx::postgres::PgPoolOptions;
|
||||||
@ -19,7 +19,7 @@ use sqlx::Connection;
|
|||||||
|
|
||||||
mod embedded {
|
mod embedded {
|
||||||
use refinery::embed_migrations;
|
use refinery::embed_migrations;
|
||||||
embed_migrations!("src/entity/gateway/postgres/migrations");
|
embed_migrations!("src/gateway/postgres/migrations");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use crate::entity::item::ItemEntityId;
|
use crate::item::ItemEntityId;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum ItemParseError {
|
pub enum ItemParseError {
|
@ -1,9 +1,9 @@
|
|||||||
use thiserror::Error;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use thiserror::Error;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use crate::entity::item::tool::ToolType;
|
use crate::item::tool::ToolType;
|
||||||
use crate::entity::character::{CharacterClass, SectionID};
|
use crate::character::{CharacterClass, SectionID};
|
||||||
use crate::entity::item::ItemEntityId;
|
use crate::item::ItemEntityId;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use std::cmp::Ordering::{Less, Greater, Equal};
|
use std::cmp::Ordering::{Less, Greater, Equal};
|
@ -9,11 +9,11 @@ pub mod mag;
|
|||||||
pub mod esweapon;
|
pub mod esweapon;
|
||||||
|
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use crate::entity::character::CharacterEntityId;
|
use crate::character::CharacterEntityId;
|
||||||
use crate::entity::room::RoomEntityId;
|
use crate::room::RoomEntityId;
|
||||||
use crate::ship::map::MapArea;
|
use maps::area::MapArea;
|
||||||
use crate::ship::monster::MonsterType;
|
use maps::monster::MonsterType;
|
||||||
use crate::ship::drops::ItemDropType;
|
//use crate::ship::drops::ItemDropType;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct ItemEntityId(pub u32);
|
pub struct ItemEntityId(pub u32);
|
||||||
@ -156,26 +156,6 @@ impl ItemDetail {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_item_from_bytes(data: [u8; 16]) -> Option<ItemDropType> {
|
|
||||||
let item_type = weapon::WeaponType::parse_type([data[0],data[1],data[2]]).map(ItemType::Weapon)
|
|
||||||
.or_else(|_| armor::ArmorType::parse_type([data[0],data[1],data[2]]).map(ItemType::Armor))
|
|
||||||
.or_else(|_| shield::ShieldType::parse_type([data[0],data[1],data[2]]).map(ItemType::Shield))
|
|
||||||
.or_else(|_| unit::UnitType::parse_type([data[0],data[1],data[2]]).map(ItemType::Unit))
|
|
||||||
.or_else(|_| mag::MagType::parse_type([data[0],data[1],data[2]]).map(ItemType::Mag))
|
|
||||||
.or_else(|_| tool::ToolType::parse_type([data[0],data[1],data[2]]).map(ItemType::Tool))
|
|
||||||
.or_else(|_| esweapon::ESWeaponType::parse_type([data[0],data[1],data[2]]).map(ItemType::ESWeapon)).ok()?;
|
|
||||||
|
|
||||||
match item_type {
|
|
||||||
ItemType::Weapon(_w) => Some(ItemDropType::Weapon(weapon::Weapon::from_bytes(data).ok()?)),
|
|
||||||
ItemType::Armor(_a) => Some(ItemDropType::Armor(armor::Armor::from_bytes(data).ok()?)),
|
|
||||||
ItemType::Shield(_s) => Some(ItemDropType::Shield(shield::Shield::from_bytes(data).ok()?)),
|
|
||||||
ItemType::Unit(_u) => Some(ItemDropType::Unit(unit::Unit::from_bytes(data).ok()?)),
|
|
||||||
ItemType::Mag(_m) => Some(ItemDropType::Mag(mag::Mag::from_bytes(data).ok()?)),
|
|
||||||
ItemType::Tool(_t) => Some(ItemDropType::Tool(tool::Tool::from_bytes(data).ok()?)),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_client_bytes(&self) -> [u8; 16] {
|
pub fn as_client_bytes(&self) -> [u8; 16] {
|
||||||
match self {
|
match self {
|
||||||
ItemDetail::Weapon(w) => w.as_bytes(),
|
ItemDetail::Weapon(w) => w.as_bytes(),
|
@ -1,4 +1,4 @@
|
|||||||
use crate::entity::item::ItemEntityId;
|
use crate::item::ItemEntityId;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
@ -1,8 +1,8 @@
|
|||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
|
||||||
use crate::entity::character::{CharacterEntityId, SectionID};
|
use crate::character::{CharacterEntityId, SectionID};
|
||||||
use crate::ship::room::{Episode, Difficulty};
|
use maps::room::{Episode, Difficulty};
|
||||||
|
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
31
entity/src/team.rs
Normal file
31
entity/src/team.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
use super::account::UserAccountId;
|
||||||
|
|
||||||
|
// [2022-10-23 00:11:18][elseware::common::mainloop::client][WARN] error RecvServerPacket::from_bytes: WrongPacketForServerType(490, [40, 0, 234, 1, 0, 0, 0, 0, 9, 0, 74, 0, 97, 0, 115, 0, 100, 0, 102, 0, 0, 0, 0, 0, 192, 52, 67, 3, 60, 159, 129, 0, 32, 64, 233, 10, 196, 156, 152, 0])
|
||||||
|
// [2022-10-23 00:20:14][elseware::common::mainloop::client][WARN] error RecvServerPacket::from_bytes: WrongPacketForServerType(490, [40, 0, 234, 1, 0, 0, 0, 0, 9, 0, 74, 0, 97, 0, 97, 0, 97, 0, 97, 0, 97, 0, 97, 0, 97, 0, 97, 0, 97, 0, 97, 0, 97, 0, 97, 0, 0, 0, 152, 0])
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
pub struct TeamEntityId(pub u32);
|
||||||
|
|
||||||
|
pub struct NewTeamEntity {
|
||||||
|
pub created_by: UserAccountId,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TeamEntity {
|
||||||
|
pub id: TeamEntityId,
|
||||||
|
pub owner: UserAccountId,
|
||||||
|
pub name: String,
|
||||||
|
|
||||||
|
pub team_flag: [u8; 2048],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
15
maps/Cargo.toml
Normal file
15
maps/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
[package]
|
||||||
|
name = "maps"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
common = { workspace = true }
|
||||||
|
byteorder = { workspace = true }
|
||||||
|
serde = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
|
rand = { workspace = true }
|
||||||
|
rand_chacha = { workspace = true }
|
||||||
|
toml = { workspace = true }
|
||||||
|
enum-utils = { workspace = true }
|
||||||
|
derive_more = { workspace = true }
|
@ -2,7 +2,7 @@
|
|||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use crate::ship::room::Episode;
|
use crate::room::Episode;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
@ -1,19 +1,24 @@
|
|||||||
// TOOD: `pub(super) for most of these?`
|
// TOOD: `pub(super) for most of these?`
|
||||||
use std::io::{Read};
|
use std::io::{Read};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use byteorder::{LittleEndian, ReadBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::ship::ship::ShipEvent;
|
|
||||||
use crate::ship::monster::MonsterType;
|
|
||||||
use crate::ship::room::Episode;
|
|
||||||
|
|
||||||
use crate::ship::map::*;
|
|
||||||
|
|
||||||
use rand::{Rng, SeedableRng};
|
use rand::{Rng, SeedableRng};
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use crate::ship::drops::{load_rare_monster_file};
|
|
||||||
|
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)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct RawMapEnemy {
|
pub struct RawMapEnemy {
|
||||||
@ -69,6 +74,17 @@ impl RawMapEnemy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn load_rare_monster_file<T: serde::de::DeserializeOwned>(episode: Episode) -> T {
|
||||||
|
// TODO: where does the rare monster toml file actually live
|
||||||
|
let mut path = PathBuf::from("data/battle_param/");
|
||||||
|
path.push(episode.to_string().to_lowercase() + "_rare_monster.toml");
|
||||||
|
|
||||||
|
let mut f = File::open(path).unwrap();
|
||||||
|
let mut s = String::new();
|
||||||
|
f.read_to_string(&mut s);
|
||||||
|
toml::from_str::<T>(s.as_str()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
#[error("")]
|
#[error("")]
|
||||||
pub enum MapEnemyError {
|
pub enum MapEnemyError {
|
||||||
@ -76,6 +92,7 @@ pub enum MapEnemyError {
|
|||||||
MapAreaError(#[from] MapAreaError),
|
MapAreaError(#[from] MapAreaError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// making this `pub type` doesn't allow `impl`s to be defined?
|
// making this `pub type` doesn't allow `impl`s to be defined?
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct RareMonsterAppearTable {
|
pub struct RareMonsterAppearTable {
|
||||||
@ -103,7 +120,7 @@ impl RareMonsterAppearTable {
|
|||||||
rand_chacha::ChaChaRng::from_entropy().gen::<f32>() < *self.appear_rate.get(monster).unwrap_or(&0.0f32)
|
rand_chacha::ChaChaRng::from_entropy().gen::<f32>() < *self.appear_rate.get(monster).unwrap_or(&0.0f32)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply(&self, enemy: MapEnemy, event: ShipEvent) -> MapEnemy {
|
pub fn apply(&self, enemy: MapEnemy, event: Option<RareEnemyEvent>) -> MapEnemy {
|
||||||
if enemy.can_be_rare() && self.roll_is_rare(&enemy.monster) {
|
if enemy.can_be_rare() && self.roll_is_rare(&enemy.monster) {
|
||||||
enemy.into_rare(event)
|
enemy.into_rare(event)
|
||||||
}
|
}
|
||||||
@ -345,12 +362,12 @@ impl MapEnemy {
|
|||||||
guaranteed rare monsters don't count towards the limit
|
guaranteed rare monsters don't count towards the limit
|
||||||
*/
|
*/
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn into_rare(self, event: ShipEvent) -> MapEnemy {
|
pub fn into_rare(self, event: Option<RareEnemyEvent>) -> MapEnemy {
|
||||||
match (self.monster, self.map_area.to_episode(), event) {
|
match (self.monster, self.map_area.to_episode(), event) {
|
||||||
(MonsterType::RagRappy, Episode::One, _) => {MapEnemy {monster: MonsterType::AlRappy, shiny:true, ..self}},
|
(MonsterType::RagRappy, Episode::One, _) => {MapEnemy {monster: MonsterType::AlRappy, shiny:true, ..self}},
|
||||||
(MonsterType::RagRappy, Episode::Two, ShipEvent::Easter) => {MapEnemy {monster: MonsterType::EasterRappy, shiny:true, ..self}},
|
(MonsterType::RagRappy, Episode::Two, Some(RareEnemyEvent::Easter)) => {MapEnemy {monster: MonsterType::EasterRappy, shiny:true, ..self}},
|
||||||
(MonsterType::RagRappy, Episode::Two, ShipEvent::Halloween) => {MapEnemy {monster: MonsterType::HalloRappy, shiny:true, ..self}},
|
(MonsterType::RagRappy, Episode::Two, Some(RareEnemyEvent::Halloween)) => {MapEnemy {monster: MonsterType::HalloRappy, shiny:true, ..self}},
|
||||||
(MonsterType::RagRappy, Episode::Two, ShipEvent::Christmas) => {MapEnemy {monster: MonsterType::StRappy, shiny:true, ..self}},
|
(MonsterType::RagRappy, Episode::Two, Some(RareEnemyEvent::Christmas)) => {MapEnemy {monster: MonsterType::StRappy, shiny:true, ..self}},
|
||||||
(MonsterType::RagRappy, Episode::Two, _) => {MapEnemy {monster: MonsterType::LoveRappy, shiny:true, ..self}},
|
(MonsterType::RagRappy, Episode::Two, _) => {MapEnemy {monster: MonsterType::LoveRappy, shiny:true, ..self}},
|
||||||
(MonsterType::Hildebear, _, _) => {MapEnemy {monster: MonsterType::Hildeblue, shiny:true, ..self}},
|
(MonsterType::Hildebear, _, _) => {MapEnemy {monster: MonsterType::Hildeblue, shiny:true, ..self}},
|
||||||
(MonsterType::PoisonLily, _, _) => {MapEnemy {monster: MonsterType::NarLily, shiny:true, ..self}},
|
(MonsterType::PoisonLily, _, _) => {MapEnemy {monster: MonsterType::NarLily, shiny:true, ..self}},
|
7
maps/src/lib.rs
Normal file
7
maps/src/lib.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
pub mod area;
|
||||||
|
pub mod enemy;
|
||||||
|
pub mod object;
|
||||||
|
pub mod variant;
|
||||||
|
pub mod maps;
|
||||||
|
pub mod monster;
|
||||||
|
pub mod room;
|
@ -6,14 +6,14 @@ use std::fs::File;
|
|||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::ship::ship::ShipEvent;
|
|
||||||
use crate::ship::monster::MonsterType;
|
|
||||||
use crate::ship::room::{Episode, RoomMode, PlayerMode};
|
|
||||||
|
|
||||||
// TODO: don't use *
|
|
||||||
use crate::ship::map::*;
|
|
||||||
|
|
||||||
|
|
||||||
|
//use crate::ship::ship::ShipEvent;
|
||||||
|
use crate::area::MapArea;
|
||||||
|
use crate::enemy::{MapEnemy, RawMapEnemy, RareEnemyEvent, RareMonsterAppearTable};
|
||||||
|
use crate::monster::MonsterType;
|
||||||
|
use crate::variant::{MapVariant, MapVariantMode};
|
||||||
|
use crate::object::{MapObject, RawMapObject};
|
||||||
|
use crate::room::{Episode, RoomMode, PlayerMode};
|
||||||
|
|
||||||
pub fn objects_from_stream(cursor: &mut impl Read, episode: &Episode, map_area: &MapArea) -> Vec<Option<MapObject>> {
|
pub fn objects_from_stream(cursor: &mut impl Read, episode: &Episode, map_area: &MapArea) -> Vec<Option<MapObject>> {
|
||||||
let mut object_data = Vec::new();
|
let mut object_data = Vec::new();
|
||||||
@ -325,7 +325,7 @@ impl Maps {
|
|||||||
enemies: Vec<Option<MapEnemy>>,
|
enemies: Vec<Option<MapEnemy>>,
|
||||||
objects: Vec<Option<MapObject>>,
|
objects: Vec<Option<MapObject>>,
|
||||||
rare_monster_table: &RareMonsterAppearTable,
|
rare_monster_table: &RareMonsterAppearTable,
|
||||||
event: ShipEvent)
|
event: Option<RareEnemyEvent>)
|
||||||
{
|
{
|
||||||
self.enemy_data = enemies
|
self.enemy_data = enemies
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -358,7 +358,7 @@ impl Maps {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_free_roam_maps(room_mode: RoomMode, event: ShipEvent) -> Maps {
|
pub fn generate_free_roam_maps(room_mode: RoomMode, event: Option<RareEnemyEvent>) -> Maps {
|
||||||
let rare_monster_table = RareMonsterAppearTable::new(room_mode.episode());
|
let rare_monster_table = RareMonsterAppearTable::new(room_mode.episode());
|
||||||
let map_variants = default_map_variants(room_mode.episode(), room_mode.player_mode());
|
let map_variants = default_map_variants(room_mode.episode(), room_mode.player_mode());
|
||||||
Maps {
|
Maps {
|
212
maps/src/monster.rs
Normal file
212
maps/src/monster.rs
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
#![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::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(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,13 +1,11 @@
|
|||||||
// TOOD: `pub(super) for most of these?`
|
// TOOD: `pub(super) for most of these?`
|
||||||
|
|
||||||
use std::io::{Read};
|
use std::io::Read;
|
||||||
|
|
||||||
use byteorder::{LittleEndian, ReadBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
|
|
||||||
use crate::ship::room::Episode;
|
use crate::room::Episode;
|
||||||
|
use crate::area::MapArea;
|
||||||
// TODO: don't use *
|
|
||||||
use crate::ship::map::*;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
150
maps/src/room.rs
Normal file
150
maps/src/room.rs
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
#[derive(Debug, Copy, Clone, derive_more::Display)]
|
||||||
|
pub enum Episode {
|
||||||
|
#[display(fmt="ep1")]
|
||||||
|
One,
|
||||||
|
#[display(fmt="ep2")]
|
||||||
|
Two,
|
||||||
|
#[display(fmt="ep4")]
|
||||||
|
Four,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u8> for Episode {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Episode, ()> {
|
||||||
|
match value {
|
||||||
|
1 => Ok(Episode::One),
|
||||||
|
2 => Ok(Episode::Two),
|
||||||
|
3 => Ok(Episode::Four),
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Episode> for u8 {
|
||||||
|
fn from(other: Episode) -> u8 {
|
||||||
|
match other {
|
||||||
|
Episode::One => 1,
|
||||||
|
Episode::Two => 2,
|
||||||
|
Episode::Four => 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Episode {
|
||||||
|
pub fn from_quest(value: u8) -> Option<Episode> {
|
||||||
|
match value {
|
||||||
|
0 => Some(Episode::One),
|
||||||
|
1 => Some(Episode::Two),
|
||||||
|
2 => Some(Episode::Four),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, derive_more::Display)]
|
||||||
|
pub enum Difficulty {
|
||||||
|
Normal,
|
||||||
|
Hard,
|
||||||
|
VeryHard,
|
||||||
|
Ultimate,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u8> for Difficulty {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Difficulty, ()> {
|
||||||
|
match value {
|
||||||
|
0 => Ok(Difficulty::Normal),
|
||||||
|
1 => Ok(Difficulty::Hard),
|
||||||
|
2 => Ok(Difficulty::VeryHard),
|
||||||
|
3 => Ok(Difficulty::Ultimate),
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Difficulty> for u8 {
|
||||||
|
fn from(other: Difficulty) -> u8 {
|
||||||
|
match other {
|
||||||
|
Difficulty::Normal => 0,
|
||||||
|
Difficulty::Hard => 1,
|
||||||
|
Difficulty::VeryHard => 2,
|
||||||
|
Difficulty::Ultimate => 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum PlayerMode {
|
||||||
|
Single,
|
||||||
|
Multi,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlayerMode {
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
match self {
|
||||||
|
PlayerMode::Single => 1,
|
||||||
|
PlayerMode::Multi => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, derive_more::Display)]
|
||||||
|
pub enum RoomMode {
|
||||||
|
#[display(fmt="single")]
|
||||||
|
Single {
|
||||||
|
episode: Episode,
|
||||||
|
difficulty: Difficulty,
|
||||||
|
},
|
||||||
|
#[display(fmt="multi")]
|
||||||
|
Multi {
|
||||||
|
episode: Episode,
|
||||||
|
difficulty: Difficulty,
|
||||||
|
},
|
||||||
|
#[display(fmt="challenge")]
|
||||||
|
Challenge {
|
||||||
|
episode: Episode,
|
||||||
|
},
|
||||||
|
#[display(fmt="battle")]
|
||||||
|
Battle {
|
||||||
|
episode: Episode,
|
||||||
|
difficulty: Difficulty,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl RoomMode {
|
||||||
|
pub fn difficulty(&self) -> Difficulty {
|
||||||
|
match self {
|
||||||
|
RoomMode::Single {difficulty, ..} => *difficulty,
|
||||||
|
RoomMode::Multi {difficulty, ..} => *difficulty,
|
||||||
|
RoomMode::Battle {difficulty, ..} => *difficulty,
|
||||||
|
RoomMode::Challenge {..} => Difficulty::Normal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn episode(&self) -> Episode {
|
||||||
|
match self {
|
||||||
|
RoomMode::Single {episode, ..} => *episode,
|
||||||
|
RoomMode::Multi {episode, ..} => *episode,
|
||||||
|
RoomMode::Battle {episode, ..} => *episode,
|
||||||
|
RoomMode::Challenge {episode, ..} => *episode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn battle(&self) -> bool {
|
||||||
|
matches!(self, RoomMode::Battle {..})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn challenge(&self) -> bool {
|
||||||
|
matches!(self, RoomMode::Challenge {..})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn player_mode(&self) -> PlayerMode {
|
||||||
|
match self {
|
||||||
|
RoomMode::Single {..} => PlayerMode::Single,
|
||||||
|
_ => PlayerMode::Multi,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,8 @@
|
|||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
// TODO: don't use *
|
// TODO: don't use *
|
||||||
use crate::ship::map::*;
|
//use crate::map::*;
|
||||||
|
use crate::area::MapArea;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum MapVariantMode {
|
pub enum MapVariantMode {
|
4
networking/Cargo.toml
Normal file
4
networking/Cargo.toml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[package]
|
||||||
|
name = "networking"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
0
networking/src/lib.rs
Normal file
0
networking/src/lib.rs
Normal file
@ -1,5 +1,5 @@
|
|||||||
use log::{info};
|
use log::{info};
|
||||||
use elseware::entity::gateway::postgres::PostgresGateway;
|
use entity::gateway::postgres::PostgresGateway;
|
||||||
use elseware::login::login::LoginServerState;
|
use elseware::login::login::LoginServerState;
|
||||||
use elseware::login::character::CharacterServerState;
|
use elseware::login::character::CharacterServerState;
|
||||||
use elseware::common::interserver::AuthToken;
|
use elseware::common::interserver::AuthToken;
|
||||||
|
@ -8,11 +8,11 @@ use elseware::patch::patch::{PatchServerState, generate_patch_tree, load_config,
|
|||||||
use elseware::ship::ship::{ShipServerStateBuilder, ShipEvent};
|
use elseware::ship::ship::{ShipServerStateBuilder, ShipEvent};
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use elseware::entity::gateway::{EntityGateway, InMemoryGateway, PostgresGateway};
|
use entity::gateway::{EntityGateway, InMemoryGateway, PostgresGateway};
|
||||||
use elseware::entity::account::{NewUserAccountEntity, NewUserSettingsEntity};
|
use entity::account::{NewUserAccountEntity, NewUserSettingsEntity};
|
||||||
use elseware::entity::character::NewCharacterEntity;
|
use entity::character::NewCharacterEntity;
|
||||||
use elseware::entity::item::{NewItemEntity, ItemDetail, InventoryItemEntity};
|
use entity::item::{NewItemEntity, ItemDetail, InventoryItemEntity};
|
||||||
use elseware::entity::item;
|
use entity::item;
|
||||||
|
|
||||||
fn setup_logger() {
|
fn setup_logger() {
|
||||||
let colors = fern::colors::ColoredLevelConfig::new()
|
let colors = fern::colors::ColoredLevelConfig::new()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use log::{info};
|
use log::{info};
|
||||||
use elseware::entity::gateway::postgres::PostgresGateway;
|
use entity::gateway::postgres::PostgresGateway;
|
||||||
use elseware::ship::ship::ShipServerStateBuilder;
|
use elseware::ship::ship::ShipServerStateBuilder;
|
||||||
use elseware::common::interserver::AuthToken;
|
use elseware::common::interserver::AuthToken;
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@ use std::net::Ipv4Addr;
|
|||||||
use async_std::channel;
|
use async_std::channel;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use crate::entity::account::UserAccountId;
|
use entity::account::UserAccountId;
|
||||||
use crate::entity::character::CharacterEntityId;
|
use entity::character::CharacterEntityId;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Copy, Clone, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct ServerId(pub usize);
|
pub struct ServerId(pub usize);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use crate::entity::character::CharacterClass;
|
use entity::character::CharacterClass;
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
pub static LEVEL_TABLE: LazyLock<CharacterLevelTable> = LazyLock::new(CharacterLevelTable::default);
|
pub static LEVEL_TABLE: LazyLock<CharacterLevelTable> = LazyLock::new(CharacterLevelTable::default);
|
||||||
|
@ -13,8 +13,7 @@ use crate::common::interserver::{ServerId, InterserverActor};
|
|||||||
use libpso::crypto::{PSOCipher, NullCipher, CipherError};
|
use libpso::crypto::{PSOCipher, NullCipher, CipherError};
|
||||||
use crate::common::serverstate::{ServerState, SendServerPacket, RecvServerPacket};
|
use crate::common::serverstate::{ServerState, SendServerPacket, RecvServerPacket};
|
||||||
use crate::login::character::CharacterServerState;
|
use crate::login::character::CharacterServerState;
|
||||||
//use crate::ship::ship::ShipServerState;
|
use entity::gateway::entitygateway::EntityGateway;
|
||||||
use crate::entity::gateway::entitygateway::EntityGateway;
|
|
||||||
|
|
||||||
use async_std::channel;
|
use async_std::channel;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
use refinery::include_migration_mods;
|
|
||||||
|
|
||||||
include_migration_mods!("src/entity/gateway/postgres/migrations");
|
|
@ -10,7 +10,7 @@
|
|||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
||||||
pub mod common;
|
pub mod common;
|
||||||
pub mod entity;
|
//pub mod entity;
|
||||||
pub mod patch;
|
pub mod patch;
|
||||||
pub mod login;
|
pub mod login;
|
||||||
pub mod ship;
|
pub mod ship;
|
||||||
|
@ -12,8 +12,8 @@ use libpso::packet::login::*;
|
|||||||
use libpso::packet::ship::{MenuDetail, SmallLeftDialog};
|
use libpso::packet::ship::{MenuDetail, SmallLeftDialog};
|
||||||
use libpso::{PacketParseError, PSOPacket};
|
use libpso::{PacketParseError, PSOPacket};
|
||||||
use libpso::crypto::bb::PSOBBCipher;
|
use libpso::crypto::bb::PSOBBCipher;
|
||||||
use crate::entity::item;
|
|
||||||
use libpso::character::character;
|
use libpso::character::character;
|
||||||
|
use entity::item;
|
||||||
|
|
||||||
use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
|
use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
|
||||||
use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
|
use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
|
||||||
@ -21,15 +21,15 @@ use crate::common::interserver::{ServerId, InterserverActor, LoginMessage, ShipM
|
|||||||
use crate::common::leveltable::LEVEL_TABLE;
|
use crate::common::leveltable::LEVEL_TABLE;
|
||||||
use libpso::{utf8_to_array, utf8_to_utf16_array};
|
use libpso::{utf8_to_array, utf8_to_utf16_array};
|
||||||
|
|
||||||
use crate::entity::gateway::{EntityGateway, GatewayError};
|
use entity::gateway::{EntityGateway, GatewayError};
|
||||||
use crate::entity::account::{UserAccountId, UserAccountEntity, NewUserSettingsEntity, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM};
|
use entity::account::{UserAccountId, UserAccountEntity, NewUserSettingsEntity, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM};
|
||||||
use crate::entity::item::{NewItemEntity, ItemDetail, ItemNote, InventoryItemEntity, InventoryEntity, BankEntity, BankIdentifier, EquippedEntity, Meseta};
|
use entity::item::{NewItemEntity, ItemDetail, ItemNote, InventoryItemEntity, InventoryEntity, BankEntity, BankIdentifier, EquippedEntity, Meseta};
|
||||||
use crate::entity::item::weapon::Weapon;
|
use entity::item::weapon::Weapon;
|
||||||
use crate::entity::item::armor::Armor;
|
use entity::item::armor::Armor;
|
||||||
use crate::entity::item::tech::Technique;
|
use entity::item::tech::Technique;
|
||||||
use crate::entity::item::tool::Tool;
|
use entity::item::tool::Tool;
|
||||||
use crate::entity::item::mag::Mag;
|
use entity::item::mag::Mag;
|
||||||
use crate::entity::character::{CharacterEntity, NewCharacterEntity, CharacterClass, TechLevel};
|
use entity::character::{CharacterEntity, NewCharacterEntity, CharacterClass, TechLevel};
|
||||||
|
|
||||||
use crate::login::login::{get_login_status};
|
use crate::login::login::{get_login_status};
|
||||||
use crate::common::interserver::AuthToken;
|
use crate::common::interserver::AuthToken;
|
||||||
@ -484,7 +484,7 @@ impl<EG: EntityGateway + Clone> CharacterServerState<EG> {
|
|||||||
async fn set_flag(&mut self, id: ClientId, setflag: &SetFlag) -> Result<std::option::IntoIter<SendCharacterPacket>, anyhow::Error> {
|
async fn set_flag(&mut self, id: ClientId, setflag: &SetFlag) -> Result<std::option::IntoIter<SendCharacterPacket>, anyhow::Error> {
|
||||||
let mut client = self.clients.write().await;
|
let mut client = self.clients.write().await;
|
||||||
let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?;
|
let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?;
|
||||||
let mut user = client.user.as_mut().unwrap();
|
let user = client.user.as_mut().unwrap();
|
||||||
user.flags = setflag.flags;
|
user.flags = setflag.flags;
|
||||||
self.entity_gateway.save_user(user).await.unwrap();
|
self.entity_gateway.save_user(user).await.unwrap();
|
||||||
Ok(None.into_iter())
|
Ok(None.into_iter())
|
||||||
@ -515,7 +515,7 @@ impl<EG: EntityGateway + Clone> CharacterServerState<EG> {
|
|||||||
async fn character_preview(&mut self, id: ClientId, preview: &CharacterPreview) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
async fn character_preview(&mut self, id: ClientId, preview: &CharacterPreview) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||||
let mut client = self.clients.write().await;
|
let mut client = self.clients.write().await;
|
||||||
let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?;
|
let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?;
|
||||||
let mut user = client.user.as_mut().unwrap();
|
let user = client.user.as_mut().unwrap();
|
||||||
if user.flags == USERFLAG_NEWCHAR {
|
if user.flags == USERFLAG_NEWCHAR {
|
||||||
new_character(&mut self.entity_gateway, user, preview).await?
|
new_character(&mut self.entity_gateway, user, preview).await?
|
||||||
}
|
}
|
||||||
@ -834,9 +834,21 @@ impl<'a> SelectScreenCharacterBuilder<'a> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::entity::account::*;
|
use entity::account::*;
|
||||||
use libpso::character::{settings, character};
|
use libpso::character::{settings, character};
|
||||||
use crate::entity::gateway::{InMemoryGateway, GatewayError};
|
use entity::gateway::{InMemoryGateway, EntityGatewayTransaction, GatewayError};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct CharTestDb;
|
||||||
|
|
||||||
|
impl EntityGateway for CharTestDb {
|
||||||
|
type Transaction<'t> = CharTestDb where Self: 't;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EntityGatewayTransaction for CharTestDb {
|
||||||
|
type ParentGateway = CharTestDb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
async fn test_option_send() {
|
async fn test_option_send() {
|
||||||
@ -846,7 +858,7 @@ mod test {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
impl EntityGateway for TestData {
|
||||||
type Transaction<'a> = () where Self: 'a;
|
type Transaction<'a> = CharTestDb where Self: 'a;
|
||||||
async fn get_user_settings_by_user(&mut self, user: &UserAccountEntity) -> Result<UserSettingsEntity, GatewayError> {
|
async fn get_user_settings_by_user(&mut self, user: &UserAccountEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||||
Ok(UserSettingsEntity {
|
Ok(UserSettingsEntity {
|
||||||
id: UserSettingsId(0),
|
id: UserSettingsId(0),
|
||||||
@ -889,7 +901,7 @@ mod test {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct TestData;
|
struct TestData;
|
||||||
impl EntityGateway for TestData {
|
impl EntityGateway for TestData {
|
||||||
type Transaction<'a> = () where Self: 'a;
|
type Transaction<'a> = CharTestDb where Self: 'a;
|
||||||
}
|
}
|
||||||
let mut server = CharacterServerState::new(TestData {}, AuthToken("".into()));
|
let mut server = CharacterServerState::new(TestData {}, AuthToken("".into()));
|
||||||
let send = server.handle(ClientId(1), RecvCharacterPacket::Checksum(Checksum {checksum: 1234,
|
let send = server.handle(ClientId(1), RecvCharacterPacket::Checksum(Checksum {checksum: 1234,
|
||||||
|
@ -14,8 +14,8 @@ use libpso::util::array_to_utf8;
|
|||||||
use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
|
use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
|
||||||
use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
|
use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
|
||||||
|
|
||||||
use crate::entity::gateway::EntityGateway;
|
use entity::gateway::EntityGateway;
|
||||||
use crate::entity::account::{UserAccountEntity};
|
use entity::account::{UserAccountEntity};
|
||||||
|
|
||||||
pub const LOGIN_PORT: u16 = 12000;
|
pub const LOGIN_PORT: u16 = 12000;
|
||||||
pub const COMMUNICATION_PORT: u16 = 12123;
|
pub const COMMUNICATION_PORT: u16 = 12123;
|
||||||
@ -178,8 +178,8 @@ impl<EG: EntityGateway + Clone> ServerState for LoginServerState<EG> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::entity::account::{UserAccountId};
|
use entity::account::{UserAccountId};
|
||||||
use crate::entity::gateway::{EntityGatewayTransaction, GatewayError};
|
use entity::gateway::{EntityGatewayTransaction, GatewayError};
|
||||||
|
|
||||||
const LOGIN_PACKET: RecvLoginPacket = RecvLoginPacket::Login(Login {
|
const LOGIN_PACKET: RecvLoginPacket = RecvLoginPacket::Login(Login {
|
||||||
tag: 65536,
|
tag: 65536,
|
||||||
@ -204,13 +204,16 @@ mod test {
|
|||||||
character_slot: 0,
|
character_slot: 0,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
impl EntityGateway for () {
|
#[derive(Clone)]
|
||||||
type Transaction<'t> = () where Self: 't;
|
struct LoginTestDb;
|
||||||
|
|
||||||
|
impl EntityGateway for LoginTestDb {
|
||||||
|
type Transaction<'t> = LoginTestDb where Self: 't;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EntityGatewayTransaction for () {
|
impl EntityGatewayTransaction for LoginTestDb {
|
||||||
type ParentGateway = ();
|
type ParentGateway = LoginTestDb;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
@ -221,7 +224,7 @@ mod test {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
impl EntityGateway for TestData {
|
||||||
type Transaction<'t> = () where Self: 't;
|
type Transaction<'t> = LoginTestDb where Self: 't;
|
||||||
async fn get_user_by_name(&mut self, name: String) -> Result<UserAccountEntity, GatewayError> {
|
async fn get_user_by_name(&mut self, name: String) -> Result<UserAccountEntity, GatewayError> {
|
||||||
assert!(name == "testuser");
|
assert!(name == "testuser");
|
||||||
Ok(UserAccountEntity {
|
Ok(UserAccountEntity {
|
||||||
@ -280,7 +283,7 @@ mod test {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
impl EntityGateway for TestData {
|
||||||
type Transaction<'t> = () where Self: 't;
|
type Transaction<'t> = LoginTestDb where Self: 't;
|
||||||
async fn get_user_by_name(&mut self, _name: String) -> Result<UserAccountEntity, GatewayError> {
|
async fn get_user_by_name(&mut self, _name: String) -> Result<UserAccountEntity, GatewayError> {
|
||||||
Err(GatewayError::Error)
|
Err(GatewayError::Error)
|
||||||
}
|
}
|
||||||
@ -315,7 +318,7 @@ mod test {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
impl EntityGateway for TestData {
|
||||||
type Transaction<'t> = () where Self: 't;
|
type Transaction<'t> = LoginTestDb where Self: 't;
|
||||||
async fn get_user_by_name(&mut self, name: String) -> Result<UserAccountEntity, GatewayError> {
|
async fn get_user_by_name(&mut self, name: String) -> Result<UserAccountEntity, GatewayError> {
|
||||||
assert!(name == "testuser");
|
assert!(name == "testuser");
|
||||||
Ok(UserAccountEntity {
|
Ok(UserAccountEntity {
|
||||||
@ -365,7 +368,7 @@ mod test {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
impl EntityGateway for TestData {
|
||||||
type Transaction<'t> = () where Self: 't;
|
type Transaction<'t> = LoginTestDb where Self: 't;
|
||||||
async fn get_user_by_name(&mut self, name: String) -> Result<UserAccountEntity, GatewayError> {
|
async fn get_user_by_name(&mut self, name: String) -> Result<UserAccountEntity, GatewayError> {
|
||||||
assert!(name == "testuser");
|
assert!(name == "testuser");
|
||||||
Ok(UserAccountEntity {
|
Ok(UserAccountEntity {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use libpso::character::character;
|
use libpso::character::character;
|
||||||
use crate::common::leveltable::CharacterStats;
|
use crate::common::leveltable::CharacterStats;
|
||||||
use crate::entity::character::CharacterEntity;
|
use entity::character::CharacterEntity;
|
||||||
//use crate::ship::items::{CharacterInventory, CharacterBank};
|
//use crate::ship::items::{CharacterInventory, CharacterBank};
|
||||||
use crate::ship::items::bank::BankState;
|
use crate::ship::items::bank::BankState;
|
||||||
use crate::ship::items::inventory::InventoryState;
|
use crate::ship::items::inventory::InventoryState;
|
||||||
use crate::entity::item::Meseta;
|
use entity::item::Meseta;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use libpso::packet::ship::PlayerChat;
|
use libpso::packet::ship::PlayerChat;
|
||||||
use crate::entity::gateway::EntityGateway;
|
use entity::gateway::EntityGateway;
|
||||||
use crate::common::serverstate::ClientId;
|
use crate::common::serverstate::ClientId;
|
||||||
use crate::ship::ship::{ShipServerState, SendShipPacket};
|
use crate::ship::ship::{ShipServerState, SendShipPacket};
|
||||||
use crate::ship::client::Clients;
|
use crate::ship::client::Clients;
|
||||||
use crate::ship::items::state::ItemState;
|
use crate::ship::items::state::ItemState;
|
||||||
use crate::entity::item::{BankName, BankIdentifier};
|
use entity::item::{BankName, BankIdentifier};
|
||||||
use crate::ship::packet::builder::message::bank_item_list;
|
use crate::ship::packet::builder::message::bank_item_list;
|
||||||
|
|
||||||
async fn default_bank<'a, EG>(id: ClientId,
|
async fn default_bank<'a, EG>(id: ClientId,
|
||||||
|
@ -7,13 +7,13 @@ use libpso::packet::ship::*;
|
|||||||
use libpso::packet::login::Session;
|
use libpso::packet::login::Session;
|
||||||
|
|
||||||
use crate::common::serverstate::ClientId;
|
use crate::common::serverstate::ClientId;
|
||||||
use crate::entity::account::{UserAccountEntity, UserSettingsEntity};
|
use entity::account::{UserAccountEntity, UserSettingsEntity};
|
||||||
use crate::entity::character::CharacterEntity;
|
use entity::character::CharacterEntity;
|
||||||
use crate::entity::item;
|
use entity::item;
|
||||||
|
|
||||||
use crate::ship::ship::ShipError;
|
use crate::ship::ship::ShipError;
|
||||||
use crate::ship::items;
|
use crate::ship::items;
|
||||||
use crate::ship::map::MapArea;
|
use maps::area::MapArea;
|
||||||
use crate::ship::shops::{WeaponShopItem, ToolShopItem, ArmorShopItem};
|
use crate::ship::shops::{WeaponShopItem, ToolShopItem, ArmorShopItem};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,18 +2,18 @@
|
|||||||
use rand::{Rng};
|
use rand::{Rng};
|
||||||
use rand::distributions::{WeightedIndex, Distribution};
|
use rand::distributions::{WeightedIndex, Distribution};
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use crate::entity::character::SectionID;
|
use entity::character::SectionID;
|
||||||
use crate::ship::room::{Difficulty, Episode};
|
use maps::room::{Difficulty, Episode};
|
||||||
use crate::ship::map::MapArea;
|
use maps::area::MapArea;
|
||||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||||
use crate::ship::map::{MapObject, MapObjectType, FixedBoxDropType};
|
use maps::object::{MapObject, MapObjectType, FixedBoxDropType};
|
||||||
use crate::ship::drops::rare_drop_table::{RareDropTable, RareDropItem};
|
use crate::ship::drops::rare_drop_table::{RareDropTable, RareDropItem};
|
||||||
use crate::ship::drops::generic_weapon::GenericWeaponTable;
|
use crate::ship::drops::generic_weapon::GenericWeaponTable;
|
||||||
use crate::ship::drops::generic_armor::GenericArmorTable;
|
use crate::ship::drops::generic_armor::GenericArmorTable;
|
||||||
use crate::ship::drops::generic_shield::GenericShieldTable;
|
use crate::ship::drops::generic_shield::GenericShieldTable;
|
||||||
use crate::ship::drops::generic_unit::GenericUnitTable;
|
use crate::ship::drops::generic_unit::GenericUnitTable;
|
||||||
use crate::ship::drops::tool_table::ToolTable;
|
use crate::ship::drops::tool_table::ToolTable;
|
||||||
use crate::entity::item::ItemDetail;
|
use entity::item::ItemDetail;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct BoxDropRate {
|
struct BoxDropRate {
|
||||||
@ -204,7 +204,7 @@ impl BoxDropTable {
|
|||||||
FixedBoxDropType::Specific(value) => {
|
FixedBoxDropType::Specific(value) => {
|
||||||
let mut buf: [u8; 16] = [0; 16];
|
let mut buf: [u8; 16] = [0; 16];
|
||||||
buf[0..4].copy_from_slice(&u32::to_be_bytes(value));
|
buf[0..4].copy_from_slice(&u32::to_be_bytes(value));
|
||||||
ItemDetail::parse_item_from_bytes(buf)
|
ItemDropType::parse_item_from_bytes(buf)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use rand::{Rng};
|
use rand::Rng;
|
||||||
use rand::distributions::{WeightedIndex, Distribution};
|
use rand::distributions::{WeightedIndex, Distribution};
|
||||||
|
|
||||||
use crate::entity::item::armor::{ArmorType, Armor};
|
use entity::character::SectionID;
|
||||||
use crate::ship::room::{Difficulty, Episode};
|
use entity::item::armor::{ArmorType, Armor};
|
||||||
use crate::ship::map::MapArea;
|
use maps::room::{Difficulty, Episode};
|
||||||
use crate::entity::character::SectionID;
|
use maps::area::MapArea;
|
||||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||||
use crate::ship::item_stats::{armor_stats, ArmorStats};
|
use crate::ship::item_stats::{armor_stats, ArmorStats};
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use rand::{Rng};
|
use rand::Rng;
|
||||||
use rand::distributions::{WeightedIndex, Distribution};
|
use rand::distributions::{WeightedIndex, Distribution};
|
||||||
|
|
||||||
use crate::entity::item::shield::{ShieldType, Shield};
|
use entity::item::shield::{ShieldType, Shield};
|
||||||
use crate::ship::room::{Difficulty, Episode};
|
use entity::character::SectionID;
|
||||||
use crate::ship::map::MapArea;
|
use maps::room::{Difficulty, Episode};
|
||||||
use crate::entity::character::SectionID;
|
use maps::area::MapArea;
|
||||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||||
use crate::ship::item_stats::{shield_stats, ShieldStats};
|
use crate::ship::item_stats::{shield_stats, ShieldStats};
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use rand::{Rng};
|
use rand::Rng;
|
||||||
use rand::seq::IteratorRandom;
|
use rand::seq::IteratorRandom;
|
||||||
|
|
||||||
use crate::entity::item::unit::{UnitType, Unit, UnitModifier};
|
use entity::character::SectionID;
|
||||||
use crate::ship::room::{Difficulty, Episode};
|
use entity::item::unit::{UnitType, Unit, UnitModifier};
|
||||||
use crate::ship::map::MapArea;
|
use maps::room::{Difficulty, Episode};
|
||||||
use crate::entity::character::SectionID;
|
use maps::area::MapArea;
|
||||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||||
use crate::ship::item_stats::{unit_stats, UnitStats};
|
use crate::ship::item_stats::{unit_stats, UnitStats};
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use std::collections::{HashMap, BTreeMap};
|
use std::collections::{HashMap, BTreeMap};
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use rand::{Rng};
|
use rand::Rng;
|
||||||
use rand::distributions::{WeightedIndex, Distribution};
|
use rand::distributions::{WeightedIndex, Distribution};
|
||||||
use rand::seq::SliceRandom;
|
use rand::seq::SliceRandom;
|
||||||
|
|
||||||
use crate::entity::item::weapon::{Weapon, WeaponType, Attribute, WeaponAttribute, WeaponSpecial};
|
use entity::character::SectionID;
|
||||||
use crate::ship::room::{Difficulty, Episode};
|
use entity::item::weapon::{Weapon, WeaponType, Attribute, WeaponAttribute, WeaponSpecial};
|
||||||
use crate::ship::map::MapArea;
|
use maps::room::{Difficulty, Episode};
|
||||||
use crate::entity::character::SectionID;
|
use maps::area::MapArea;
|
||||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,10 +22,10 @@ use std::io::Read;
|
|||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use rand::{Rng, SeedableRng};
|
use rand::{Rng, SeedableRng};
|
||||||
|
|
||||||
use crate::ship::monster::MonsterType;
|
use maps::monster::MonsterType;
|
||||||
use crate::ship::room::{Difficulty, Episode};
|
use maps::room::{Difficulty, Episode};
|
||||||
use crate::ship::map::MapArea;
|
use maps::area::MapArea;
|
||||||
use crate::entity::character::SectionID;
|
use entity::character::SectionID;
|
||||||
use crate::ship::drops::generic_weapon::GenericWeaponTable;
|
use crate::ship::drops::generic_weapon::GenericWeaponTable;
|
||||||
use crate::ship::drops::generic_armor::GenericArmorTable;
|
use crate::ship::drops::generic_armor::GenericArmorTable;
|
||||||
use crate::ship::drops::generic_shield::GenericShieldTable;
|
use crate::ship::drops::generic_shield::GenericShieldTable;
|
||||||
@ -33,8 +33,8 @@ use crate::ship::drops::generic_unit::GenericUnitTable;
|
|||||||
use crate::ship::drops::tool_table::ToolTable;
|
use crate::ship::drops::tool_table::ToolTable;
|
||||||
use crate::ship::drops::rare_drop_table::RareDropTable;
|
use crate::ship::drops::rare_drop_table::RareDropTable;
|
||||||
use crate::ship::drops::box_drop_table::BoxDropTable;
|
use crate::ship::drops::box_drop_table::BoxDropTable;
|
||||||
use crate::ship::map::MapObject;
|
use maps::object::MapObject;
|
||||||
use crate::entity::item::{weapon, armor, shield, unit, mag, tool, tech};
|
use entity::item::{ItemType, weapon, armor, shield, unit, mag, tool, tech, esweapon};
|
||||||
|
|
||||||
|
|
||||||
fn data_file_path(episode: Episode, difficulty: Difficulty, section_id: SectionID, filename: &str) -> PathBuf {
|
fn data_file_path(episode: Episode, difficulty: Difficulty, section_id: SectionID, filename: &str) -> PathBuf {
|
||||||
@ -55,18 +55,6 @@ pub fn load_data_file<T: serde::de::DeserializeOwned>(episode: Episode, difficul
|
|||||||
toml::from_str::<T>(s.as_str()).unwrap()
|
toml::from_str::<T>(s.as_str()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is just copypaste
|
|
||||||
pub fn load_rare_monster_file<T: serde::de::DeserializeOwned>(episode: Episode) -> T {
|
|
||||||
// TODO: where does the rare monster toml file actually live
|
|
||||||
let mut path = PathBuf::from("data/battle_param/");
|
|
||||||
path.push(episode.to_string().to_lowercase() + "_rare_monster.toml");
|
|
||||||
|
|
||||||
let mut f = File::open(path).unwrap();
|
|
||||||
let mut s = String::new();
|
|
||||||
f.read_to_string(&mut s);
|
|
||||||
toml::from_str::<T>(s.as_str()).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Copy, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Copy, Clone)]
|
||||||
pub enum MonsterDropType {
|
pub enum MonsterDropType {
|
||||||
#[serde(rename = "weapon")]
|
#[serde(rename = "weapon")]
|
||||||
@ -102,6 +90,28 @@ pub enum ItemDropType {
|
|||||||
Meseta(u32),
|
Meseta(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ItemDropType {
|
||||||
|
pub fn parse_item_from_bytes(data: [u8; 16]) -> Option<ItemDropType> {
|
||||||
|
let item_type = weapon::WeaponType::parse_type([data[0],data[1],data[2]]).map(ItemType::Weapon)
|
||||||
|
.or_else(|_| armor::ArmorType::parse_type([data[0],data[1],data[2]]).map(ItemType::Armor))
|
||||||
|
.or_else(|_| shield::ShieldType::parse_type([data[0],data[1],data[2]]).map(ItemType::Shield))
|
||||||
|
.or_else(|_| unit::UnitType::parse_type([data[0],data[1],data[2]]).map(ItemType::Unit))
|
||||||
|
.or_else(|_| mag::MagType::parse_type([data[0],data[1],data[2]]).map(ItemType::Mag))
|
||||||
|
.or_else(|_| tool::ToolType::parse_type([data[0],data[1],data[2]]).map(ItemType::Tool))
|
||||||
|
.or_else(|_| esweapon::ESWeaponType::parse_type([data[0],data[1],data[2]]).map(ItemType::ESWeapon)).ok()?;
|
||||||
|
|
||||||
|
match item_type {
|
||||||
|
ItemType::Weapon(_w) => Some(ItemDropType::Weapon(weapon::Weapon::from_bytes(data).ok()?)),
|
||||||
|
ItemType::Armor(_a) => Some(ItemDropType::Armor(armor::Armor::from_bytes(data).ok()?)),
|
||||||
|
ItemType::Shield(_s) => Some(ItemDropType::Shield(shield::Shield::from_bytes(data).ok()?)),
|
||||||
|
ItemType::Unit(_u) => Some(ItemDropType::Unit(unit::Unit::from_bytes(data).ok()?)),
|
||||||
|
ItemType::Mag(_m) => Some(ItemDropType::Mag(mag::Mag::from_bytes(data).ok()?)),
|
||||||
|
ItemType::Tool(_t) => Some(ItemDropType::Tool(tool::Tool::from_bytes(data).ok()?)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ItemDrop {
|
pub struct ItemDrop {
|
||||||
pub map_area: MapArea,
|
pub map_area: MapArea,
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use crate::entity::item::weapon::{Weapon, WeaponType};
|
use entity::item::weapon::{Weapon, WeaponType};
|
||||||
use crate::entity::item::armor::{Armor, ArmorType};
|
use entity::item::armor::{Armor, ArmorType};
|
||||||
use crate::entity::item::shield::{Shield, ShieldType};
|
use entity::item::shield::{Shield, ShieldType};
|
||||||
use crate::entity::item::unit::{Unit, UnitType};
|
use entity::item::unit::{Unit, UnitType};
|
||||||
use crate::entity::item::tool::{Tool, ToolType};
|
use entity::item::tool::{Tool, ToolType};
|
||||||
use crate::entity::item::mag::{Mag, MagType};
|
use entity::item::mag::{Mag, MagType};
|
||||||
use crate::entity::character::SectionID;
|
use entity::character::SectionID;
|
||||||
use crate::ship::monster::MonsterType;
|
use maps::monster::MonsterType;
|
||||||
use crate::ship::room::{Difficulty, Episode};
|
use maps::room::{Difficulty, Episode};
|
||||||
use crate::ship::map::MapArea;
|
use maps::area::MapArea;
|
||||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||||
use crate::ship::drops::generic_weapon::AttributeTable;
|
use crate::ship::drops::generic_weapon::AttributeTable;
|
||||||
use crate::ship::drops::generic_armor::GenericArmorTable;
|
use crate::ship::drops::generic_armor::GenericArmorTable;
|
||||||
|
@ -3,10 +3,10 @@ use serde::{Serialize, Deserialize};
|
|||||||
use rand::{Rng};
|
use rand::{Rng};
|
||||||
use rand::distributions::{WeightedIndex, Distribution};
|
use rand::distributions::{WeightedIndex, Distribution};
|
||||||
|
|
||||||
use crate::entity::item::tech::{Technique, TechniqueDisk};
|
use entity::item::tech::{Technique, TechniqueDisk};
|
||||||
use crate::ship::room::{Difficulty, Episode};
|
use maps::room::{Difficulty, Episode};
|
||||||
use crate::ship::map::MapArea;
|
use maps::area::MapArea;
|
||||||
use crate::entity::character::SectionID;
|
use entity::character::SectionID;
|
||||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use std::collections::{BTreeMap};
|
use std::collections::BTreeMap;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use rand::{Rng};
|
use rand::Rng;
|
||||||
use rand::distributions::{WeightedIndex, Distribution};
|
use rand::distributions::{WeightedIndex, Distribution};
|
||||||
|
|
||||||
use crate::entity::item::tool::{Tool, ToolType};
|
use entity::item::tool::{Tool, ToolType};
|
||||||
use crate::ship::room::{Difficulty, Episode};
|
use maps::room::{Difficulty, Episode};
|
||||||
use crate::ship::map::MapArea;
|
use maps::area::MapArea;
|
||||||
use crate::entity::character::SectionID;
|
use entity::character::SectionID;
|
||||||
use crate::ship::drops::{ItemDropType, load_data_file};
|
use crate::ship::drops::{ItemDropType, load_data_file};
|
||||||
use crate::ship::drops::tech_table::TechniqueTable;
|
use crate::ship::drops::tech_table::TechniqueTable;
|
||||||
|
|
||||||
|
@ -4,13 +4,13 @@ use serde::{Serialize, Deserialize};
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use crate::entity::item::weapon::WeaponType;
|
use entity::item::weapon::WeaponType;
|
||||||
use crate::entity::item::armor::ArmorType;
|
use entity::item::armor::ArmorType;
|
||||||
use crate::entity::item::shield::ShieldType;
|
use entity::item::shield::ShieldType;
|
||||||
use crate::entity::item::unit::UnitType;
|
use entity::item::unit::UnitType;
|
||||||
use crate::entity::item::mag::MagType;
|
use entity::item::mag::MagType;
|
||||||
use crate::entity::item::tool::ToolType;
|
use entity::item::tool::ToolType;
|
||||||
use crate::entity::item::tech::Technique;
|
use entity::item::tech::Technique;
|
||||||
|
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// TODO: replace various u32s and usizes denoting item amounts for ItemAmount(u32) for consistency
|
// TODO: replace various u32s and usizes denoting item amounts for ItemAmount(u32) for consistency
|
||||||
use crate::ship::items::ClientItemId;
|
use crate::ship::items::ClientItemId;
|
||||||
use crate::entity::item::{Meseta, ItemNote};
|
use entity::item::{Meseta, ItemNote};
|
||||||
use async_std::sync::Arc;
|
use async_std::sync::Arc;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use futures::future::BoxFuture;
|
use futures::future::BoxFuture;
|
||||||
@ -9,12 +9,12 @@ use std::iter::IntoIterator;
|
|||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
|
||||||
use libpso::packet::{ship::Message, messages::GameMessage};
|
use libpso::packet::{ship::Message, messages::GameMessage};
|
||||||
use crate::entity::character::{CharacterEntity, CharacterEntityId};
|
use entity::character::{CharacterEntity, CharacterEntityId};
|
||||||
use crate::entity::gateway::{EntityGateway, EntityGatewayTransaction};
|
use entity::gateway::{EntityGateway, EntityGatewayTransaction};
|
||||||
use crate::entity::item::{ItemDetail, NewItemEntity, TradeId, ItemModifier};
|
use entity::item::{ItemDetail, NewItemEntity, TradeId, ItemModifier};
|
||||||
use crate::entity::item::tool::Tool;
|
use entity::item::tool::Tool;
|
||||||
use crate::entity::room::RoomEntityId;
|
use entity::room::RoomEntityId;
|
||||||
use crate::ship::map::MapArea;
|
use maps::area::MapArea;
|
||||||
use crate::ship::ship::SendShipPacket;
|
use crate::ship::ship::SendShipPacket;
|
||||||
use crate::ship::items::state::{ItemStateProxy, ItemStateError, AddItemResult, StackedItemDetail, IndividualItemDetail};
|
use crate::ship::items::state::{ItemStateProxy, ItemStateError, AddItemResult, StackedItemDetail, IndividualItemDetail};
|
||||||
use crate::ship::items::bank::{BankItem, BankItemDetail};
|
use crate::ship::items::bank::{BankItem, BankItemDetail};
|
||||||
@ -25,7 +25,7 @@ use crate::ship::shops::ShopItem;
|
|||||||
use crate::ship::drops::{ItemDrop, ItemDropType};
|
use crate::ship::drops::{ItemDrop, ItemDropType};
|
||||||
use crate::ship::packet::builder;
|
use crate::ship::packet::builder;
|
||||||
use crate::ship::location::AreaClient;
|
use crate::ship::location::AreaClient;
|
||||||
use crate::ship::monster::MonsterType;
|
use maps::monster::MonsterType;
|
||||||
|
|
||||||
pub enum TriggerCreateItem {
|
pub enum TriggerCreateItem {
|
||||||
Yes,
|
Yes,
|
||||||
|
@ -4,13 +4,13 @@ use thiserror::Error;
|
|||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use rand::SeedableRng;
|
use rand::SeedableRng;
|
||||||
use rand::distributions::{WeightedIndex, Distribution};
|
use rand::distributions::{WeightedIndex, Distribution};
|
||||||
use crate::entity::gateway::{EntityGateway, GatewayError};
|
use entity::gateway::{EntityGateway, GatewayError};
|
||||||
use crate::entity::character::{CharacterEntity, TechLevel};
|
use entity::character::{CharacterEntity, TechLevel};
|
||||||
use crate::entity::item::mag::{MagCell, MagCellError};
|
use entity::item::mag::{MagCell, MagCellError};
|
||||||
use crate::entity::item::tool::{Tool, ToolType};
|
use entity::item::tool::{Tool, ToolType};
|
||||||
use crate::entity::item::tech::TechniqueDisk;
|
use entity::item::tech::TechniqueDisk;
|
||||||
use crate::entity::item::{ItemDetail, ItemEntityId};
|
use entity::item::{ItemDetail, ItemEntityId};
|
||||||
use crate::entity::item::weapon::WeaponModifier;
|
use entity::item::weapon::WeaponModifier;
|
||||||
use crate::ship::items::state::ItemStateProxy;
|
use crate::ship::items::state::ItemStateProxy;
|
||||||
use crate::ship::items::inventory::InventoryItemDetail;
|
use crate::ship::items::inventory::InventoryItemDetail;
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use libpso::character::character;
|
use libpso::character::character;
|
||||||
use crate::ship::items::ClientItemId;
|
use crate::ship::items::ClientItemId;
|
||||||
use crate::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 crate::entity::character::CharacterEntityId;
|
use entity::character::CharacterEntityId;
|
||||||
use crate::entity::item::BankIdentifier;
|
use entity::item::BankIdentifier;
|
||||||
use crate::ship::items::state::ItemStateError;
|
use crate::ship::items::state::ItemStateError;
|
||||||
use crate::ship::items::state::{IndividualItemDetail, StackedItemDetail, AddItemResult};
|
use crate::ship::items::state::{IndividualItemDetail, StackedItemDetail, AddItemResult};
|
||||||
use crate::ship::items::inventory::{InventoryItem, InventoryItemDetail};
|
use crate::ship::items::inventory::{InventoryItem, InventoryItemDetail};
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use crate::ship::items::ClientItemId;
|
use crate::ship::items::ClientItemId;
|
||||||
use crate::entity::item::{Meseta, ItemEntityId, ItemDetail};
|
use entity::item::{Meseta, ItemEntityId, ItemDetail};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
|
||||||
use crate::ship::map::MapArea;
|
use maps::area::MapArea;
|
||||||
use crate::entity::character::CharacterEntityId;
|
use entity::character::CharacterEntityId;
|
||||||
use crate::entity::item::mag::Mag;
|
use entity::item::mag::Mag;
|
||||||
|
|
||||||
use crate::ship::items::state::ItemStateError;
|
use crate::ship::items::state::ItemStateError;
|
||||||
use crate::ship::items::state::{IndividualItemDetail, StackedItemDetail};
|
use crate::ship::items::state::{IndividualItemDetail, StackedItemDetail};
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use libpso::character::character;
|
use libpso::character::character;
|
||||||
use crate::ship::items::ClientItemId;
|
use crate::ship::items::ClientItemId;
|
||||||
use crate::entity::item::{Meseta, ItemEntityId, ItemDetail, ItemEntity, InventoryEntity, InventoryItemEntity, EquippedEntity};
|
use entity::item::{Meseta, ItemEntityId, ItemDetail, ItemEntity, InventoryEntity, InventoryItemEntity, EquippedEntity};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use async_std::sync::{Arc, Mutex};
|
use async_std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crate::entity::character::CharacterEntityId;
|
use entity::character::CharacterEntityId;
|
||||||
use crate::entity::item::tool::ToolType;
|
use entity::item::tool::ToolType;
|
||||||
use crate::entity::item::mag::Mag;
|
use entity::item::mag::Mag;
|
||||||
use crate::entity::item::weapon::Weapon;
|
use entity::item::weapon::Weapon;
|
||||||
use crate::ship::shops::{ShopItem, ArmorShopItem, ToolShopItem, WeaponShopItem};
|
use crate::ship::shops::{ShopItem, ArmorShopItem, ToolShopItem, WeaponShopItem};
|
||||||
use crate::ship::items::state::ItemStateError;
|
use crate::ship::items::state::ItemStateError;
|
||||||
use crate::ship::items::state::{IndividualItemDetail, StackedItemDetail, AddItemResult};
|
use crate::ship::items::state::{IndividualItemDetail, StackedItemDetail, AddItemResult};
|
||||||
|
@ -4,12 +4,12 @@ use async_std::sync::{Arc, RwLock, Mutex};
|
|||||||
use futures::stream::{FuturesOrdered, StreamExt};
|
use futures::stream::{FuturesOrdered, StreamExt};
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
|
||||||
use crate::entity::gateway::{EntityGateway, GatewayError};
|
use entity::gateway::{EntityGateway, GatewayError};
|
||||||
use crate::entity::character::{CharacterEntity, CharacterEntityId};
|
use entity::character::{CharacterEntity, CharacterEntityId};
|
||||||
use crate::entity::item::{ItemEntityId, ItemDetail, ItemEntity, InventoryItemEntity, BankItemEntity, BankIdentifier};
|
use entity::item::{ItemEntityId, ItemDetail, ItemEntity, InventoryItemEntity, BankItemEntity, BankIdentifier};
|
||||||
use crate::entity::item::tool::Tool;
|
use entity::item::tool::Tool;
|
||||||
use crate::entity::item::weapon::Weapon;
|
use entity::item::weapon::Weapon;
|
||||||
use crate::entity::item::mag::Mag;
|
use entity::item::mag::Mag;
|
||||||
use crate::ship::drops::ItemDrop;
|
use crate::ship::drops::ItemDrop;
|
||||||
use crate::ship::items::ClientItemId;
|
use crate::ship::items::ClientItemId;
|
||||||
use crate::ship::items::inventory::{Inventory, InventoryItem, InventoryItemDetail, InventoryError, InventoryState};
|
use crate::ship::items::inventory::{Inventory, InventoryItem, InventoryItemDetail, InventoryError, InventoryState};
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use futures::future::BoxFuture;
|
use futures::future::BoxFuture;
|
||||||
use crate::ship::items::ClientItemId;
|
use crate::ship::items::ClientItemId;
|
||||||
use crate::entity::item::Meseta;
|
use entity::item::Meseta;
|
||||||
|
|
||||||
use crate::ship::ship::SendShipPacket;
|
use crate::ship::ship::SendShipPacket;
|
||||||
use crate::ship::map::MapArea;
|
use maps::area::MapArea;
|
||||||
use crate::entity::character::{CharacterEntity, CharacterEntityId};
|
use entity::character::{CharacterEntity, CharacterEntityId};
|
||||||
use crate::entity::gateway::{EntityGateway, EntityGatewayTransaction};
|
use entity::gateway::{EntityGateway, EntityGatewayTransaction};
|
||||||
use crate::entity::item::ItemModifier;
|
use entity::item::ItemModifier;
|
||||||
use crate::entity::room::RoomEntityId;
|
use entity::room::RoomEntityId;
|
||||||
use crate::ship::items::state::{ItemState, ItemStateProxy, IndividualItemDetail};
|
use crate::ship::items::state::{ItemState, ItemStateProxy, IndividualItemDetail};
|
||||||
use crate::ship::items::itemstateaction::{ItemStateAction, ItemAction};
|
use crate::ship::items::itemstateaction::{ItemStateAction, ItemAction};
|
||||||
use crate::ship::items::inventory::InventoryItem;
|
use crate::ship::items::inventory::InventoryItem;
|
||||||
@ -16,7 +16,7 @@ use crate::ship::shops::ShopItem;
|
|||||||
use crate::ship::trade::TradeItem;
|
use crate::ship::trade::TradeItem;
|
||||||
use crate::ship::location::AreaClient;
|
use crate::ship::location::AreaClient;
|
||||||
use crate::ship::drops::ItemDrop;
|
use crate::ship::drops::ItemDrop;
|
||||||
use crate::ship::monster::MonsterType;
|
use maps::monster::MonsterType;
|
||||||
|
|
||||||
use crate::ship::items::actions;
|
use crate::ship::items::actions;
|
||||||
|
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
pub mod area;
|
|
||||||
pub mod enemy;
|
|
||||||
pub mod object;
|
|
||||||
pub mod variant;
|
|
||||||
pub mod maps;
|
|
||||||
|
|
||||||
// TODO: don't just forward everything to the module scope
|
|
||||||
pub use area::*;
|
|
||||||
pub use enemy::*;
|
|
||||||
pub use object::*;
|
|
||||||
pub use variant::*;
|
|
||||||
pub use maps::*;
|
|
@ -6,8 +6,8 @@ pub mod client;
|
|||||||
pub mod room;
|
pub mod room;
|
||||||
pub mod items;
|
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;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use libpso::packet::messages::*;
|
use libpso::packet::messages::*;
|
||||||
use libpso::packet::ship::*;
|
use libpso::packet::ship::*;
|
||||||
use crate::entity::item;
|
use entity::item;
|
||||||
use crate::common::leveltable::CharacterStats;
|
use crate::common::leveltable::CharacterStats;
|
||||||
use crate::ship::ship::{ShipError};
|
use crate::ship::ship::{ShipError};
|
||||||
use crate::ship::items::ClientItemId;
|
use crate::ship::items::ClientItemId;
|
||||||
|
@ -3,7 +3,7 @@ use libpso::packet::ship::*;
|
|||||||
use crate::common::serverstate::ClientId;
|
use crate::common::serverstate::ClientId;
|
||||||
use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients};
|
use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients};
|
||||||
use crate::login::login::get_login_status;
|
use crate::login::login::get_login_status;
|
||||||
use crate::entity::gateway::EntityGateway;
|
use entity::gateway::EntityGateway;
|
||||||
use crate::ship::items::state::ItemState;
|
use crate::ship::items::state::ItemState;
|
||||||
use crate::common::interserver::ShipMessage;
|
use crate::common::interserver::ShipMessage;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use libpso::packet::ship::*;
|
|||||||
use crate::common::serverstate::ClientId;
|
use crate::common::serverstate::ClientId;
|
||||||
use crate::ship::ship::{SendShipPacket, Clients};
|
use crate::ship::ship::{SendShipPacket, Clients};
|
||||||
use crate::ship::location::{ClientLocation};
|
use crate::ship::location::{ClientLocation};
|
||||||
use crate::entity::gateway::EntityGateway;
|
use entity::gateway::EntityGateway;
|
||||||
|
|
||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ use crate::ship::location::ClientLocation;
|
|||||||
use crate::ship::drops::ItemDrop;
|
use crate::ship::drops::ItemDrop;
|
||||||
use crate::ship::room::Rooms;
|
use crate::ship::room::Rooms;
|
||||||
use crate::ship::items::ClientItemId;
|
use crate::ship::items::ClientItemId;
|
||||||
use crate::entity::gateway::EntityGateway;
|
use entity::gateway::EntityGateway;
|
||||||
use crate::entity::item;
|
use entity::item;
|
||||||
use libpso::utf8_to_utf16_array;
|
use libpso::utf8_to_utf16_array;
|
||||||
use crate::ship::packet::builder;
|
use crate::ship::packet::builder;
|
||||||
use crate::ship::shops::{ShopItem, ToolShopItem, ArmorShopItem};
|
use crate::ship::shops::{ShopItem, ToolShopItem, ArmorShopItem};
|
||||||
|
@ -7,9 +7,9 @@ use crate::ship::character::{FullCharacterBytesBuilder};
|
|||||||
use crate::ship::location::{ClientLocation, LobbyId, RoomLobby, ClientLocationError, RoomId};
|
use crate::ship::location::{ClientLocation, LobbyId, RoomLobby, ClientLocationError, RoomId};
|
||||||
use crate::ship::packet;
|
use crate::ship::packet;
|
||||||
use crate::ship::items::state::ItemState;
|
use crate::ship::items::state::ItemState;
|
||||||
use crate::entity::gateway::EntityGateway;
|
use entity::gateway::EntityGateway;
|
||||||
use crate::entity::room::RoomNote;
|
use entity::room::RoomNote;
|
||||||
use crate::ship::map::MapArea;
|
use maps::area::MapArea;
|
||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
|
|
||||||
// this function needs a better home
|
// this function needs a better home
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use libpso::packet::ship::*;
|
use libpso::packet::ship::*;
|
||||||
use libpso::packet::messages::*;
|
use libpso::packet::messages::*;
|
||||||
use crate::entity::gateway::EntityGateway;
|
use entity::gateway::EntityGateway;
|
||||||
use crate::entity::item::Meseta;
|
use entity::item::Meseta;
|
||||||
use crate::common::serverstate::ClientId;
|
use crate::common::serverstate::ClientId;
|
||||||
use crate::common::leveltable::LEVEL_TABLE;
|
use crate::common::leveltable::LEVEL_TABLE;
|
||||||
use crate::ship::ship::{SendShipPacket, ShipError, Clients, ItemDropLocation};
|
use crate::ship::ship::{SendShipPacket, ShipError, Clients, ItemDropLocation};
|
||||||
|
@ -4,7 +4,7 @@ use libpso::packet::ship::*;
|
|||||||
use crate::common::serverstate::ClientId;
|
use crate::common::serverstate::ClientId;
|
||||||
use crate::ship::ship::{SendShipPacket, ShipError, Clients, ShipEvent};
|
use crate::ship::ship::{SendShipPacket, ShipError, Clients, ShipEvent};
|
||||||
use crate::ship::room::Rooms;
|
use crate::ship::room::Rooms;
|
||||||
use crate::ship::map::enemy::RareMonsterAppearTable;
|
use maps::enemy::RareMonsterAppearTable;
|
||||||
use crate::ship::location::{ClientLocation};
|
use crate::ship::location::{ClientLocation};
|
||||||
use crate::ship::packet::builder::quest;
|
use crate::ship::packet::builder::quest;
|
||||||
use libpso::util::array_to_utf8;
|
use libpso::util::array_to_utf8;
|
||||||
@ -118,7 +118,7 @@ pub async fn player_chose_quest(id: ClientId,
|
|||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
let rare_monster_table = RareMonsterAppearTable::new(room.mode.episode());
|
let rare_monster_table = RareMonsterAppearTable::new(room.mode.episode());
|
||||||
room.maps.set_quest_data(quest.enemies.clone(), quest.objects.clone(), &rare_monster_table, event);
|
room.maps.set_quest_data(quest.enemies.clone(), quest.objects.clone(), &rare_monster_table, event.rare_enemy_event());
|
||||||
room.map_areas = quest.map_areas.clone();
|
room.map_areas = quest.map_areas.clone();
|
||||||
|
|
||||||
let bin = quest::quest_header(&questmenuselect, &quest.bin_blob, "bin");
|
let bin = quest::quest_header(&questmenuselect, &quest.bin_blob, "bin");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::convert::{TryFrom, Into};
|
use std::convert::Into;
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
|
|
||||||
use async_std::sync::Arc;
|
use async_std::sync::Arc;
|
||||||
@ -7,13 +7,15 @@ use libpso::packet::ship::*;
|
|||||||
use libpso::packet::messages::*;
|
use libpso::packet::messages::*;
|
||||||
use crate::common::serverstate::ClientId;
|
use crate::common::serverstate::ClientId;
|
||||||
use crate::common::leveltable::LEVEL_TABLE;
|
use crate::common::leveltable::LEVEL_TABLE;
|
||||||
use crate::entity::gateway::EntityGateway;
|
use entity::gateway::EntityGateway;
|
||||||
use crate::entity::character::SectionID;
|
use entity::character::SectionID;
|
||||||
use crate::entity::room::{NewRoomEntity, RoomEntityMode, RoomNote};
|
use entity::room::{NewRoomEntity, RoomEntityMode, RoomNote};
|
||||||
use crate::ship::drops::DropTable;
|
use crate::ship::drops::DropTable;
|
||||||
use crate::ship::ship::{SendShipPacket, Clients, ShipEvent};
|
use crate::ship::ship::{SendShipPacket, Clients, ShipEvent};
|
||||||
use crate::ship::room::{Rooms, Episode, Difficulty, RoomState, RoomMode};
|
use crate::ship::room::{Rooms, RoomState, RoomCreationError};
|
||||||
use crate::ship::map::Maps;
|
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::location::{ClientLocation, RoomId, RoomLobby, GetAreaError};
|
||||||
use crate::ship::packet::builder;
|
use crate::ship::packet::builder;
|
||||||
use crate::ship::items::state::ItemState;
|
use crate::ship::items::state::ItemState;
|
||||||
@ -26,7 +28,7 @@ pub async fn create_room<EG>(id: ClientId,
|
|||||||
clients: &Clients,
|
clients: &Clients,
|
||||||
item_state: &mut ItemState,
|
item_state: &mut ItemState,
|
||||||
rooms: &Rooms,
|
rooms: &Rooms,
|
||||||
map_builder: Arc<Box<dyn Fn(RoomMode, ShipEvent) -> Maps + Send + Sync>>,
|
map_builder: Arc<Box<dyn Fn(RoomMode, Option<RareEnemyEvent>) -> Maps + Send + Sync>>,
|
||||||
drop_table_builder: Arc<Box<dyn Fn(Episode, Difficulty, SectionID) -> DropTable + Send + Sync>>,
|
drop_table_builder: Arc<Box<dyn Fn(Episode, Difficulty, SectionID) -> DropTable + Send + Sync>>,
|
||||||
event: ShipEvent)
|
event: ShipEvent)
|
||||||
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error>
|
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error>
|
||||||
@ -36,7 +38,8 @@ where
|
|||||||
let level = clients.with(id, |client| Box::pin(async move {
|
let level = clients.with(id, |client| Box::pin(async move {
|
||||||
LEVEL_TABLE.get_level_from_exp(client.character.char_class, client.character.exp)
|
LEVEL_TABLE.get_level_from_exp(client.character.char_class, client.character.exp)
|
||||||
})).await?;
|
})).await?;
|
||||||
let difficulty = Difficulty::try_from(create_room.difficulty)?;
|
let difficulty = create_room.difficulty.try_into()
|
||||||
|
.map_err(|()| RoomCreationError::InvalidDifficulty(create_room.difficulty))?;
|
||||||
match difficulty {
|
match difficulty {
|
||||||
Difficulty::Ultimate if level < 80 => {
|
Difficulty::Ultimate if level < 80 => {
|
||||||
return Ok(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto create Ultimate rooms.".into())))])
|
return Ok(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto create Ultimate rooms.".into())))])
|
||||||
@ -64,8 +67,9 @@ where
|
|||||||
(0, 0, 1) => RoomEntityMode::Single,
|
(0, 0, 1) => RoomEntityMode::Single,
|
||||||
_ => RoomEntityMode::Multi,
|
_ => RoomEntityMode::Multi,
|
||||||
};
|
};
|
||||||
let episode = create_room.episode.try_into()?;
|
let episode = create_room.episode.try_into()
|
||||||
let difficulty = create_room.difficulty.try_into()?;
|
.map_err(|()| RoomCreationError::InvalidEpisode(create_room.episode))?;
|
||||||
|
//let difficulty = create_room.difficulty.try_into()?;
|
||||||
|
|
||||||
let room = clients.with(id, |client| {
|
let room = clients.with(id, |client| {
|
||||||
let mut item_state = item_state.clone();
|
let mut item_state = item_state.clone();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use libpso::packet::ship::*;
|
use libpso::packet::ship::*;
|
||||||
use crate::common::serverstate::ClientId;
|
use crate::common::serverstate::ClientId;
|
||||||
use crate::ship::ship::{SendShipPacket, Clients};
|
use crate::ship::ship::{SendShipPacket, Clients};
|
||||||
use crate::entity::gateway::EntityGateway;
|
use entity::gateway::EntityGateway;
|
||||||
|
|
||||||
pub async fn update_config<EG>(id: ClientId,
|
pub async fn update_config<EG>(id: ClientId,
|
||||||
update_config: UpdateConfig,
|
update_config: UpdateConfig,
|
||||||
|
@ -8,11 +8,11 @@ use crate::ship::items::ClientItemId;
|
|||||||
use crate::ship::items::state::{ItemState, ItemStateError};
|
use crate::ship::items::state::{ItemState, ItemStateError};
|
||||||
use crate::ship::items::inventory::InventoryItemDetail;
|
use crate::ship::items::inventory::InventoryItemDetail;
|
||||||
use crate::ship::trade::{TradeItem, TradeState, TradeStatus};
|
use crate::ship::trade::{TradeItem, TradeState, TradeStatus};
|
||||||
use crate::entity::gateway::EntityGateway;
|
use entity::gateway::EntityGateway;
|
||||||
use crate::ship::packet::builder;
|
use crate::ship::packet::builder;
|
||||||
use crate::ship::items::tasks::trade_items;
|
use crate::ship::items::tasks::trade_items;
|
||||||
use crate::ship::location::{AreaClient, RoomId};
|
use crate::ship::location::{AreaClient, RoomId};
|
||||||
use crate::entity::item::Meseta;
|
use entity::item::Meseta;
|
||||||
use crate::ship::trade::ClientTradeState;
|
use crate::ship::trade::ClientTradeState;
|
||||||
|
|
||||||
pub const MESETA_ITEM_ID: ClientItemId = ClientItemId(0xFFFFFF01);
|
pub const MESETA_ITEM_ID: ClientItemId = ClientItemId(0xFFFFFF01);
|
||||||
|
@ -10,9 +10,12 @@ use serde::{Serialize, Deserialize};
|
|||||||
use ages_prs::{LegacyPrsDecoder, LegacyPrsEncoder};
|
use ages_prs::{LegacyPrsDecoder, LegacyPrsEncoder};
|
||||||
use byteorder::{LittleEndian, ReadBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
use libpso::util::array_to_utf16;
|
use libpso::util::array_to_utf16;
|
||||||
use crate::ship::map::{MapArea, MapAreaError, MapObject, MapEnemy, enemy_data_from_stream, objects_from_stream};
|
use maps::area::{MapArea, MapAreaError};
|
||||||
use crate::ship::room::{Episode, RoomMode};
|
use maps::object::MapObject;
|
||||||
use crate::ship::map::area::{MapAreaLookup, MapAreaLookupBuilder};
|
use maps::enemy::MapEnemy;
|
||||||
|
use maps::maps::{objects_from_stream, enemy_data_from_stream};
|
||||||
|
use maps::room::{Episode, RoomMode};
|
||||||
|
use maps::area::{MapAreaLookup, MapAreaLookupBuilder};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
@ -101,7 +104,7 @@ fn quest_episode(bin: &[u8]) -> Option<Episode> {
|
|||||||
for bytes in bin.windows(3) {
|
for bytes in bin.windows(3) {
|
||||||
// set_episode
|
// set_episode
|
||||||
if bytes[0] == 0xF8 && bytes[1] == 0xBC {
|
if bytes[0] == 0xF8 && bytes[1] == 0xBC {
|
||||||
return Episode::from_quest(bytes[2]).ok()
|
return Episode::from_quest(bytes[2])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
168
src/ship/room.rs
168
src/ship/room.rs
@ -1,5 +1,5 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::{From, Into, TryFrom};
|
use std::convert::{From, Into};
|
||||||
use async_std::sync::{Arc, RwLock, RwLockReadGuard};
|
use async_std::sync::{Arc, RwLock, RwLockReadGuard};
|
||||||
use futures::future::BoxFuture;
|
use futures::future::BoxFuture;
|
||||||
use futures::stream::{FuturesOrdered, Stream};
|
use futures::stream::{FuturesOrdered, Stream};
|
||||||
@ -7,16 +7,19 @@ use futures::stream::{FuturesOrdered, Stream};
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use crate::ship::map::Maps;
|
use maps::maps::Maps;
|
||||||
use crate::ship::drops::DropTable;
|
use crate::ship::drops::DropTable;
|
||||||
use crate::entity::character::SectionID;
|
use entity::character::SectionID;
|
||||||
use crate::entity::room::{RoomEntityId, RoomEntityMode};
|
use entity::room::{RoomEntityId, RoomEntityMode};
|
||||||
use crate::ship::monster::{load_monster_stats_table, MonsterType, MonsterStats};
|
use maps::monster::{load_monster_stats_table, MonsterType, MonsterStats};
|
||||||
use crate::ship::map::area::MapAreaLookup;
|
use maps::area::MapAreaLookup;
|
||||||
|
use maps::enemy::RareEnemyEvent;
|
||||||
use crate::ship::quests;
|
use crate::ship::quests;
|
||||||
use crate::ship::ship::{ShipError, ShipEvent};
|
use crate::ship::ship::{ShipError, ShipEvent};
|
||||||
use crate::ship::location::{MAX_ROOMS, RoomId};
|
use crate::ship::location::{MAX_ROOMS, RoomId};
|
||||||
|
|
||||||
|
use maps::room::{Episode, Difficulty, RoomMode};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Rooms([Arc<RwLock<Option<RoomState>>>; MAX_ROOMS]);
|
pub struct Rooms([Arc<RwLock<Option<RoomState>>>; MAX_ROOMS]);
|
||||||
|
|
||||||
@ -123,156 +126,7 @@ pub enum RoomCreationError {
|
|||||||
CouldNotLoadQuests,
|
CouldNotLoadQuests,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, derive_more::Display)]
|
|
||||||
pub enum Episode {
|
|
||||||
#[display(fmt="ep1")]
|
|
||||||
One,
|
|
||||||
#[display(fmt="ep2")]
|
|
||||||
Two,
|
|
||||||
#[display(fmt="ep4")]
|
|
||||||
Four,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub enum PlayerMode{
|
|
||||||
Single,
|
|
||||||
Multi,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PlayerMode {
|
|
||||||
pub fn value(&self) -> u8 {
|
|
||||||
match self {
|
|
||||||
PlayerMode::Single => 1,
|
|
||||||
PlayerMode::Multi => 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<u8> for Episode {
|
|
||||||
type Error = RoomCreationError;
|
|
||||||
|
|
||||||
fn try_from(value: u8) -> Result<Episode, RoomCreationError> {
|
|
||||||
match value {
|
|
||||||
1 => Ok(Episode::One),
|
|
||||||
2 => Ok(Episode::Two),
|
|
||||||
3 => Ok(Episode::Four),
|
|
||||||
_ => Err(RoomCreationError::InvalidEpisode(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Episode> for u8 {
|
|
||||||
fn from(other: Episode) -> u8 {
|
|
||||||
match other {
|
|
||||||
Episode::One => 1,
|
|
||||||
Episode::Two => 2,
|
|
||||||
Episode::Four => 3,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Episode {
|
|
||||||
pub fn from_quest(value: u8) -> Result<Episode, RoomCreationError> {
|
|
||||||
match value {
|
|
||||||
0 => Ok(Episode::One),
|
|
||||||
1 => Ok(Episode::Two),
|
|
||||||
2 => Ok(Episode::Four),
|
|
||||||
_ => Err(RoomCreationError::InvalidEpisode(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, derive_more::Display)]
|
|
||||||
pub enum Difficulty {
|
|
||||||
Normal,
|
|
||||||
Hard,
|
|
||||||
VeryHard,
|
|
||||||
Ultimate,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<u8> for Difficulty {
|
|
||||||
type Error = RoomCreationError;
|
|
||||||
|
|
||||||
fn try_from(value: u8) -> Result<Difficulty, RoomCreationError> {
|
|
||||||
match value {
|
|
||||||
0 => Ok(Difficulty::Normal),
|
|
||||||
1 => Ok(Difficulty::Hard),
|
|
||||||
2 => Ok(Difficulty::VeryHard),
|
|
||||||
3 => Ok(Difficulty::Ultimate),
|
|
||||||
_ => Err(RoomCreationError::InvalidDifficulty(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Difficulty> for u8 {
|
|
||||||
fn from(other: Difficulty) -> u8 {
|
|
||||||
match other {
|
|
||||||
Difficulty::Normal => 0,
|
|
||||||
Difficulty::Hard => 1,
|
|
||||||
Difficulty::VeryHard => 2,
|
|
||||||
Difficulty::Ultimate => 3,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, derive_more::Display)]
|
|
||||||
pub enum RoomMode {
|
|
||||||
#[display(fmt="single")]
|
|
||||||
Single {
|
|
||||||
episode: Episode,
|
|
||||||
difficulty: Difficulty,
|
|
||||||
},
|
|
||||||
#[display(fmt="multi")]
|
|
||||||
Multi {
|
|
||||||
episode: Episode,
|
|
||||||
difficulty: Difficulty,
|
|
||||||
},
|
|
||||||
#[display(fmt="challenge")]
|
|
||||||
Challenge {
|
|
||||||
episode: Episode,
|
|
||||||
},
|
|
||||||
#[display(fmt="battle")]
|
|
||||||
Battle {
|
|
||||||
episode: Episode,
|
|
||||||
difficulty: Difficulty,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl RoomMode {
|
|
||||||
pub fn difficulty(&self) -> Difficulty {
|
|
||||||
match self {
|
|
||||||
RoomMode::Single {difficulty, ..} => *difficulty,
|
|
||||||
RoomMode::Multi {difficulty, ..} => *difficulty,
|
|
||||||
RoomMode::Battle {difficulty, ..} => *difficulty,
|
|
||||||
RoomMode::Challenge {..} => Difficulty::Normal,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn episode(&self) -> Episode {
|
|
||||||
match self {
|
|
||||||
RoomMode::Single {episode, ..} => *episode,
|
|
||||||
RoomMode::Multi {episode, ..} => *episode,
|
|
||||||
RoomMode::Battle {episode, ..} => *episode,
|
|
||||||
RoomMode::Challenge {episode, ..} => *episode,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn battle(&self) -> bool {
|
|
||||||
matches!(self, RoomMode::Battle {..})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn challenge(&self) -> bool {
|
|
||||||
matches!(self, RoomMode::Challenge {..})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn player_mode(&self) -> PlayerMode {
|
|
||||||
match self {
|
|
||||||
RoomMode::Single {..} => PlayerMode::Single,
|
|
||||||
_ => PlayerMode::Multi,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub enum QuestCategoryType {
|
pub enum QuestCategoryType {
|
||||||
Standard,
|
Standard,
|
||||||
Government,
|
Government,
|
||||||
@ -369,7 +223,7 @@ impl RoomState {
|
|||||||
name: String,
|
name: String,
|
||||||
password: [u16; 16],
|
password: [u16; 16],
|
||||||
event: ShipEvent,
|
event: ShipEvent,
|
||||||
map_builder: Arc<Box<dyn Fn(RoomMode, ShipEvent) -> Maps + Send + Sync>>,
|
map_builder: Arc<Box<dyn Fn(RoomMode, Option<RareEnemyEvent>) -> Maps + Send + Sync>>,
|
||||||
drop_table_builder: Arc<Box<dyn Fn(Episode, Difficulty, SectionID) -> DropTable + Send + Sync>>,
|
drop_table_builder: Arc<Box<dyn Fn(Episode, Difficulty, SectionID) -> DropTable + Send + Sync>>,
|
||||||
) -> Result<RoomState, anyhow::Error> {
|
) -> Result<RoomState, anyhow::Error> {
|
||||||
let mode = match mode {
|
let mode = match mode {
|
||||||
@ -397,7 +251,7 @@ impl RoomState {
|
|||||||
random_seed: rand::thread_rng().gen(),
|
random_seed: rand::thread_rng().gen(),
|
||||||
name,
|
name,
|
||||||
password,
|
password,
|
||||||
maps: map_builder(mode, event),
|
maps: map_builder(mode, event.rare_enemy_event()),
|
||||||
section_id,
|
section_id,
|
||||||
drop_table: Box::new(drop_table_builder(episode, difficulty, section_id)),
|
drop_table: Box::new(drop_table_builder(episode, difficulty, section_id)),
|
||||||
bursting: false,
|
bursting: false,
|
||||||
|
143
src/ship/ship.rs
143
src/ship/ship.rs
@ -18,14 +18,16 @@ use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
|
|||||||
use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
|
use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
|
||||||
use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage};
|
use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage};
|
||||||
use crate::login::character::SHIP_MENU_ID;
|
use crate::login::character::SHIP_MENU_ID;
|
||||||
use crate::entity::gateway::{EntityGateway, GatewayError};
|
use entity::gateway::{EntityGateway, GatewayError};
|
||||||
use crate::entity::character::SectionID;
|
use entity::character::SectionID;
|
||||||
use crate::entity::room::RoomNote;
|
use entity::room::RoomNote;
|
||||||
use crate::ship::location::{ClientLocation, RoomLobby, ClientLocationError, RoomId};
|
use crate::ship::location::{ClientLocation, RoomLobby, ClientLocationError, RoomId};
|
||||||
use crate::ship::drops::DropTable;
|
use crate::ship::drops::DropTable;
|
||||||
use crate::ship::items;
|
use crate::ship::items;
|
||||||
use crate::ship::room;
|
use crate::ship::room;
|
||||||
use crate::ship::map::{Maps, MapsError, MapAreaError, generate_free_roam_maps};
|
use maps::area::MapAreaError;
|
||||||
|
use maps::maps::{Maps, MapsError, generate_free_roam_maps};
|
||||||
|
use maps::enemy::RareEnemyEvent;
|
||||||
use crate::ship::packet::handler;
|
use crate::ship::packet::handler;
|
||||||
use crate::ship::shops::{WeaponShop, ToolShop, ArmorShop};
|
use crate::ship::shops::{WeaponShop, ToolShop, ArmorShop};
|
||||||
use crate::ship::trade::TradeState;
|
use crate::ship::trade::TradeState;
|
||||||
@ -38,57 +40,6 @@ pub const SHIP_PORT: u16 = 23423;
|
|||||||
pub const QUEST_CATEGORY_MENU_ID: u32 = 0xA2;
|
pub const QUEST_CATEGORY_MENU_ID: u32 = 0xA2;
|
||||||
pub const QUEST_SELECT_MENU_ID: u32 = 0xA3;
|
pub const QUEST_SELECT_MENU_ID: u32 = 0xA3;
|
||||||
|
|
||||||
#[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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum ShipError {
|
pub enum ShipError {
|
||||||
@ -139,7 +90,7 @@ pub enum ShipError {
|
|||||||
#[error("gateway error {0}")]
|
#[error("gateway error {0}")]
|
||||||
GatewayError(#[from] GatewayError),
|
GatewayError(#[from] GatewayError),
|
||||||
#[error("unknown monster {0}")]
|
#[error("unknown monster {0}")]
|
||||||
UnknownMonster(crate::ship::monster::MonsterType),
|
UnknownMonster(maps::monster::MonsterType),
|
||||||
#[error("invalid ship {0}")]
|
#[error("invalid ship {0}")]
|
||||||
InvalidShip(usize),
|
InvalidShip(usize),
|
||||||
#[error("invalid block {0}")]
|
#[error("invalid block {0}")]
|
||||||
@ -166,6 +117,70 @@ 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)]
|
#[derive(Debug)]
|
||||||
pub enum RecvShipPacket {
|
pub enum RecvShipPacket {
|
||||||
@ -345,14 +360,14 @@ impl SendServerPacket for SendShipPacket {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ItemShops {
|
pub struct ItemShops {
|
||||||
pub weapon_shop: HashMap<(room::Difficulty, SectionID), Arc<Mutex<WeaponShop<rand_chacha::ChaCha20Rng>>>>,
|
pub weapon_shop: HashMap<(maps::room::Difficulty, SectionID), Arc<Mutex<WeaponShop<rand_chacha::ChaCha20Rng>>>>,
|
||||||
pub tool_shop: Arc<Mutex<ToolShop<rand_chacha::ChaCha20Rng>>>,
|
pub tool_shop: Arc<Mutex<ToolShop<rand_chacha::ChaCha20Rng>>>,
|
||||||
pub armor_shop: Arc<Mutex<ArmorShop<rand_chacha::ChaCha20Rng>>>,
|
pub armor_shop: Arc<Mutex<ArmorShop<rand_chacha::ChaCha20Rng>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ItemShops {
|
impl Default for ItemShops {
|
||||||
fn default() -> ItemShops {
|
fn default() -> ItemShops {
|
||||||
let difficulty = [room::Difficulty::Normal, room::Difficulty::Hard, room::Difficulty::VeryHard, room::Difficulty::Ultimate];
|
let difficulty = [maps::room::Difficulty::Normal, maps::room::Difficulty::Hard, maps::room::Difficulty::VeryHard, maps::room::Difficulty::Ultimate];
|
||||||
let section_id = [SectionID::Viridia, SectionID::Greenill, SectionID::Skyly, SectionID::Bluefull, SectionID::Purplenum,
|
let section_id = [SectionID::Viridia, SectionID::Greenill, SectionID::Skyly, SectionID::Bluefull, SectionID::Purplenum,
|
||||||
SectionID::Pinkal, SectionID::Redria, SectionID::Oran, SectionID::Yellowboze, SectionID::Whitill];
|
SectionID::Pinkal, SectionID::Redria, SectionID::Oran, SectionID::Yellowboze, SectionID::Whitill];
|
||||||
|
|
||||||
@ -379,8 +394,8 @@ pub struct ShipServerStateBuilder<EG: EntityGateway + Clone + 'static> {
|
|||||||
port: Option<u16>,
|
port: Option<u16>,
|
||||||
auth_token: Option<AuthToken>,
|
auth_token: Option<AuthToken>,
|
||||||
event: Option<ShipEvent>,
|
event: Option<ShipEvent>,
|
||||||
map_builder: Option<Box<dyn Fn(room::RoomMode, ShipEvent) -> Maps + Send + Sync>>,
|
map_builder: Option<Box<dyn Fn(maps::room::RoomMode, Option<RareEnemyEvent>) -> Maps + Send + Sync>>,
|
||||||
drop_table_builder: Option<Box<dyn Fn(room::Episode, room::Difficulty, SectionID) -> DropTable + Send + Sync>>,
|
drop_table_builder: Option<Box<dyn Fn(maps::room::Episode, maps::room::Difficulty, SectionID) -> DropTable + Send + Sync>>,
|
||||||
num_blocks: usize,
|
num_blocks: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,13 +453,13 @@ impl<EG: EntityGateway + Clone + 'static> ShipServerStateBuilder<EG> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn map_builder(mut self, map_builder: Box<dyn Fn(room::RoomMode, ShipEvent) -> Maps + Send + Sync>) -> ShipServerStateBuilder<EG> {
|
pub fn map_builder(mut self, map_builder: Box<dyn Fn(maps::room::RoomMode, Option<RareEnemyEvent>) -> Maps + Send + Sync>) -> ShipServerStateBuilder<EG> {
|
||||||
self.map_builder = Some(map_builder);
|
self.map_builder = Some(map_builder);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn drop_table_builder(mut self, drop_table_builder: Box<dyn Fn(room::Episode, room::Difficulty, SectionID) -> DropTable + Send + Sync>) -> ShipServerStateBuilder<EG> {
|
pub fn drop_table_builder(mut self, drop_table_builder: Box<dyn Fn(maps::room::Episode, maps::room::Difficulty, SectionID) -> DropTable + Send + Sync>) -> ShipServerStateBuilder<EG> {
|
||||||
self.drop_table_builder = Some(drop_table_builder);
|
self.drop_table_builder = Some(drop_table_builder);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -516,8 +531,8 @@ pub struct ShipServerState<EG: EntityGateway + Clone + 'static> {
|
|||||||
ship_list: Arc<RwLock<Vec<Ship>>>,
|
ship_list: Arc<RwLock<Vec<Ship>>>,
|
||||||
shipgate_sender: Option<channel::Sender<ShipMessage>>,
|
shipgate_sender: Option<channel::Sender<ShipMessage>>,
|
||||||
trades: TradeState,
|
trades: TradeState,
|
||||||
map_builder: Arc<Box<dyn Fn(room::RoomMode, ShipEvent) -> Maps + Send + Sync>>,
|
map_builder: Arc<Box<dyn Fn(maps::room::RoomMode, Option<RareEnemyEvent>) -> Maps + Send + Sync>>,
|
||||||
drop_table_builder: Arc<Box<dyn Fn(room::Episode, room::Difficulty, SectionID) -> DropTable + Send + Sync>>,
|
drop_table_builder: Arc<Box<dyn Fn(maps::room::Episode, maps::room::Difficulty, SectionID) -> DropTable + Send + Sync>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EG: EntityGateway + Clone + 'static> ShipServerState<EG> {
|
impl<EG: EntityGateway + Clone + 'static> ShipServerState<EG> {
|
||||||
|
@ -5,10 +5,10 @@ use std::convert::TryInto;
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use rand::{Rng, SeedableRng};
|
use rand::{Rng, SeedableRng};
|
||||||
use rand::distributions::{WeightedIndex, Distribution};
|
use rand::distributions::{WeightedIndex, Distribution};
|
||||||
use crate::entity::item::ItemDetail;
|
use entity::item::ItemDetail;
|
||||||
use crate::entity::item::armor::{Armor, ArmorType};
|
use entity::item::armor::{Armor, ArmorType};
|
||||||
use crate::entity::item::shield::{Shield, ShieldType};
|
use entity::item::shield::{Shield, ShieldType};
|
||||||
use crate::entity::item::unit::{Unit, UnitType};
|
use entity::item::unit::{Unit, UnitType};
|
||||||
use crate::ship::shops::ShopItem;
|
use crate::ship::shops::ShopItem;
|
||||||
use crate::ship::item_stats::{ARMOR_STATS, SHIELD_STATS, UNIT_STATS};
|
use crate::ship::item_stats::{ARMOR_STATS, SHIELD_STATS, UNIT_STATS};
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ mod weapon;
|
|||||||
mod tool;
|
mod tool;
|
||||||
mod armor;
|
mod armor;
|
||||||
|
|
||||||
use crate::entity::item::ItemDetail;
|
use entity::item::ItemDetail;
|
||||||
|
|
||||||
pub trait ShopItem {
|
pub trait ShopItem {
|
||||||
fn price(&self) -> usize;
|
fn price(&self) -> usize;
|
||||||
|
@ -6,9 +6,9 @@ use std::convert::TryInto;
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use rand::{Rng, SeedableRng};
|
use rand::{Rng, SeedableRng};
|
||||||
use rand::distributions::{WeightedIndex, Distribution};
|
use rand::distributions::{WeightedIndex, Distribution};
|
||||||
use crate::entity::item::ItemDetail;
|
use entity::item::ItemDetail;
|
||||||
use crate::entity::item::tool::{Tool, ToolType};
|
use entity::item::tool::{Tool, ToolType};
|
||||||
use crate::entity::item::tech::{Technique, TechniqueDisk};
|
use entity::item::tech::{Technique, TechniqueDisk};
|
||||||
use crate::ship::shops::ShopItem;
|
use crate::ship::shops::ShopItem;
|
||||||
use crate::ship::item_stats::{TOOL_STATS, TECH_STATS};
|
use crate::ship::item_stats::{TOOL_STATS, TECH_STATS};
|
||||||
|
|
||||||
|
@ -8,10 +8,10 @@ use serde::Deserialize;
|
|||||||
use rand::{Rng, SeedableRng};
|
use rand::{Rng, SeedableRng};
|
||||||
use rand::distributions::{WeightedIndex, Distribution};
|
use rand::distributions::{WeightedIndex, Distribution};
|
||||||
use rand::seq::{SliceRandom, IteratorRandom};
|
use rand::seq::{SliceRandom, IteratorRandom};
|
||||||
use crate::entity::character::SectionID;
|
use entity::character::SectionID;
|
||||||
use crate::ship::room::Difficulty;
|
use maps::room::Difficulty;
|
||||||
use crate::entity::item::ItemDetail;
|
use entity::item::ItemDetail;
|
||||||
use crate::entity::item::weapon::{Weapon, WeaponType, WeaponSpecial, Attribute, WeaponAttribute};
|
use entity::item::weapon::{Weapon, WeaponType, WeaponSpecial, Attribute, WeaponAttribute};
|
||||||
use crate::ship::shops::ShopItem;
|
use crate::ship::shops::ShopItem;
|
||||||
use crate::ship::item_stats::WEAPON_STATS;
|
use crate::ship::item_stats::WEAPON_STATS;
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use elseware::common::serverstate::{ClientId, ServerState};
|
use elseware::common::serverstate::{ClientId, ServerState};
|
||||||
use elseware::entity::gateway::EntityGateway;
|
use entity::gateway::EntityGateway;
|
||||||
use elseware::entity::account::{UserAccountEntity, NewUserAccountEntity, NewUserSettingsEntity};
|
use entity::account::{UserAccountEntity, NewUserAccountEntity, NewUserSettingsEntity};
|
||||||
use elseware::entity::character::{CharacterEntity, NewCharacterEntity};
|
use entity::character::{CharacterEntity, NewCharacterEntity};
|
||||||
use elseware::entity::item::{Meseta, BankName, BankIdentifier};
|
use entity::item::{Meseta, BankName, BankIdentifier};
|
||||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket};
|
use elseware::ship::ship::{ShipServerState, RecvShipPacket};
|
||||||
use elseware::ship::room::Difficulty;
|
use maps::room::Difficulty;
|
||||||
|
|
||||||
use elseware::entity::item;
|
use entity::item;
|
||||||
|
|
||||||
use libpso::packet::ship::*;
|
use libpso::packet::ship::*;
|
||||||
use libpso::packet::login::{Login, Session};
|
use libpso::packet::login::{Login, Session};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use elseware::common::serverstate::{ClientId, ServerState};
|
use elseware::common::serverstate::{ClientId, ServerState};
|
||||||
use elseware::entity::gateway::{EntityGateway, InMemoryGateway};
|
use entity::gateway::{EntityGateway, InMemoryGateway};
|
||||||
use elseware::entity::item;
|
use entity::item;
|
||||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket};
|
use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket};
|
||||||
|
|
||||||
use libpso::packet::ship::*;
|
use libpso::packet::ship::*;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user