Browse Source

Merge pull request 'room notes, etc' (#139) from more_itemnotes into master

Reviewed-on: #139
fuckin_andy_making_me_do_this_now
jake 1 year ago
parent
commit
1f7dd1eafe
  1. 2388
      Cargo.lock
  2. 2
      Cargo.toml
  3. 10
      src/entity/gateway/entitygateway.rs
  4. 18
      src/entity/gateway/inmemory.rs
  5. 14
      src/entity/gateway/postgres/migrations/V0012__room.sql
  6. 17
      src/entity/gateway/postgres/migrations/V0013__room2.sql
  7. 88
      src/entity/gateway/postgres/models.rs
  8. 105
      src/entity/gateway/postgres/postgres.rs
  9. 24
      src/entity/item/mod.rs
  10. 1
      src/entity/mod.rs
  11. 83
      src/entity/room.rs
  12. 120
      src/ship/items/actions.rs
  13. 33
      src/ship/items/tasks.rs
  14. 14
      src/ship/packet/handler/direct_message.rs
  15. 14
      src/ship/packet/handler/lobby.rs
  16. 17
      src/ship/packet/handler/quest.rs
  17. 98
      src/ship/packet/handler/room.rs
  18. 75
      src/ship/quests.rs
  19. 142
      src/ship/room.rs
  20. 18
      src/ship/ship.rs

2388
Cargo.lock
File diff suppressed because it is too large
View File

2
Cargo.toml

@ -29,7 +29,7 @@ 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.5.10", features = ["runtime-async-std-native-tls", "postgres", "json", "chrono"] }
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"] }

10
src/entity/gateway/entitygateway.rs

@ -4,10 +4,10 @@ use futures::future::{Future, BoxFuture};
use crate::entity::account::*;
use crate::entity::character::*;
use crate::entity::item::*;
use crate::entity::room::*;
// TODO: better granularity?
//#[derive(Error, Debug)]
#[derive(Error, Debug)]
pub enum GatewayError {
#[error("unknown error")]
@ -147,6 +147,14 @@ pub trait EntityGateway: Send + Sync {
async fn set_character_playtime(&mut self, _char_id: &CharacterEntityId, _playtime: u32) -> Result<(), GatewayError> {
unimplemented!();
}
async fn create_room(&mut self, _room: NewRoomEntity) -> Result<RoomEntity, GatewayError> {
unimplemented!();
}
async fn add_room_note(&mut self, _room_id: RoomEntityId, _note: RoomNote) -> Result<(), GatewayError> {
unimplemented!();
}
}

18
src/entity/gateway/inmemory.rs

@ -6,6 +6,7 @@ use crate::entity::account::*;
use crate::entity::character::*;
use crate::entity::gateway::{EntityGateway, EntityGatewayTransaction, GatewayError};
use crate::entity::item::*;
use crate::entity::room::*;
use async_std::sync::{Arc, Mutex};
@ -766,4 +767,21 @@ impl EntityGateway for InMemoryGateway {
Err(GatewayError::Error)
}
}
// I do not care to replicate this in testing
async fn create_room(&mut self, room: NewRoomEntity) -> Result<RoomEntity, GatewayError> {
Ok(RoomEntity {
id: RoomEntityId(0),
name: room.name,
section_id: room.section_id,
episode: room.episode,
difficulty: room.difficulty,
mode: room.mode,
})
}
// I do not care to replicate this in testing
async fn add_room_note(&mut self, _room_id: RoomEntityId, _note: RoomNote) -> Result<(), GatewayError> {
Ok(())
}
}

14
src/entity/gateway/postgres/migrations/V0012__room.sql

@ -0,0 +1,14 @@
create table room (
id serial primary key not null,
name varchar(32) not null,
section_id char not null,
mode char not null,
episode char not null,
difficulty char not null
);
create table room_note (
room integer references room (id) not null,
note jsonb not null,
created_at timestamptz default current_timestamp not null
);

17
src/entity/gateway/postgres/migrations/V0013__room2.sql

@ -0,0 +1,17 @@
drop table room_note;
drop table room;
create table room (
id serial primary key not null,
name varchar(32) not null,
section_id "char" not null,
mode "char" not null,
episode "char" not null,
difficulty "char" not null
);
create table room_note (
room integer references room (id) not null,
note jsonb not null,
created_at timestamptz default current_timestamp not null
);

88
src/entity/gateway/postgres/models.rs

@ -7,7 +7,10 @@ use libpso::util::vec_to_array;
use crate::entity::account::*;
use crate::entity::character::*;
use crate::entity::item::*;
use crate::entity::room::*;
use crate::ship::map::MapArea;
use crate::ship::room::{Episode, Difficulty};
use crate::ship::monster::MonsterType;
#[derive(Debug, sqlx::FromRow)]
pub struct PgUserAccount {
@ -577,6 +580,16 @@ pub enum PgItemNoteDetail {
},
EnemyDrop {
character_id: u32,
room_id: u32,
monster_type: MonsterType,
map_area: MapArea,
x: f32,
y: f32,
z: f32,
},
BoxDrop {
character_id: u32,
room_id: u32,
map_area: MapArea,
x: f32,
y: f32,
@ -592,14 +605,19 @@ pub enum PgItemNoteDetail {
y: f32,
z: f32,
},
Consumed,
Consumed {
character_id: u32,
},
FedToMag {
character_id: u32,
mag: u32,
},
BoughtAtShop {
character_id: u32,
},
SoldToShop,
SoldToShop {
character_id: u32,
},
Trade {
trade_id: u32,
character_to: u32,
@ -624,8 +642,16 @@ impl From<ItemNote> for PgItemNoteDetail {
ItemNote::CharacterCreation{character_id} => PgItemNoteDetail::CharacterCreation {
character_id: character_id.0,
},
ItemNote::EnemyDrop{character_id, map_area, x, y, z} => PgItemNoteDetail::EnemyDrop {
ItemNote::EnemyDrop{character_id, room_id, monster_type, map_area, x, y, z} => PgItemNoteDetail::EnemyDrop {
character_id: character_id.0,
room_id: room_id.0,
monster_type,
map_area,
x,y,z,
},
ItemNote::BoxDrop{character_id, room_id, map_area, x, y, z} => PgItemNoteDetail::BoxDrop {
character_id: character_id.0,
room_id: room_id.0,
map_area,
x,y,z,
},
@ -637,14 +663,19 @@ impl From<ItemNote> for PgItemNoteDetail {
map_area,
x,y,z,
},
ItemNote::Consumed => PgItemNoteDetail::Consumed,
ItemNote::FedToMag{mag} => PgItemNoteDetail::FedToMag{
ItemNote::Consumed{character_id} => PgItemNoteDetail::Consumed {
character_id: character_id.0,
},
ItemNote::FedToMag{character_id, mag} => PgItemNoteDetail::FedToMag{
character_id: character_id.0,
mag: mag.0
},
ItemNote::BoughtAtShop{character_id} => PgItemNoteDetail::BoughtAtShop {
character_id: character_id.0,
},
ItemNote::SoldToShop => PgItemNoteDetail::SoldToShop,
ItemNote::SoldToShop{character_id} => PgItemNoteDetail::SoldToShop {
character_id: character_id.0,
},
ItemNote::Trade{trade_id, character_to, character_from} => PgItemNoteDetail::Trade {
trade_id: trade_id.0,
character_to: character_to.0,
@ -677,8 +708,16 @@ impl From<PgItemNoteDetail> for ItemNote {
PgItemNoteDetail::CharacterCreation{character_id} => ItemNote::CharacterCreation {
character_id: CharacterEntityId(character_id),
},
PgItemNoteDetail::EnemyDrop{character_id, map_area, x, y, z} => ItemNote::EnemyDrop {
PgItemNoteDetail::EnemyDrop{character_id, room_id, monster_type, map_area, x, y, z} => ItemNote::EnemyDrop {
character_id: CharacterEntityId(character_id),
room_id: RoomEntityId(room_id),
monster_type,
map_area,
x,y,z,
},
PgItemNoteDetail::BoxDrop{character_id, room_id, map_area, x, y, z} => ItemNote::BoxDrop {
character_id: CharacterEntityId(character_id),
room_id: RoomEntityId(room_id),
map_area,
x,y,z,
},
@ -690,14 +729,19 @@ impl From<PgItemNoteDetail> for ItemNote {
map_area,
x,y,z,
},
PgItemNoteDetail::Consumed => ItemNote::Consumed,
PgItemNoteDetail::FedToMag{mag} => ItemNote::FedToMag{
PgItemNoteDetail::Consumed{character_id} => ItemNote::Consumed {
character_id: CharacterEntityId(character_id),
},
PgItemNoteDetail::FedToMag{character_id, mag} => ItemNote::FedToMag{
character_id: CharacterEntityId(character_id),
mag: ItemEntityId(mag)
},
PgItemNoteDetail::BoughtAtShop{character_id} => ItemNote::BoughtAtShop {
character_id: CharacterEntityId(character_id),
},
PgItemNoteDetail::SoldToShop => ItemNote::SoldToShop,
PgItemNoteDetail::SoldToShop{character_id} => ItemNote::SoldToShop {
character_id: CharacterEntityId(character_id),
},
PgItemNoteDetail::Trade {trade_id, character_to, character_from} => ItemNote::Trade {
trade_id: TradeId(trade_id),
character_to: CharacterEntityId(character_to),
@ -880,3 +924,27 @@ impl From<PgTradeEntity> for TradeEntity {
}
}
}
#[derive(Debug, sqlx::FromRow, Serialize)]
pub struct PgRoomEntity {
id: i32,
name: String,
section_id: i8,
mode: i8,
episode: i8,
difficulty: i8,
}
impl From<PgRoomEntity> for RoomEntity {
fn from(other: PgRoomEntity) -> RoomEntity {
RoomEntity {
id: RoomEntityId(other.id as u32),
name: other.name,
section_id: SectionID::from(other.section_id as u8),
mode: RoomEntityMode::from(other.mode as u8),
episode: Episode::try_from(other.episode as u8).unwrap(),
difficulty: Difficulty::try_from(other.difficulty as u8).unwrap(),
}
}
}

105
src/entity/gateway/postgres/postgres.rs

@ -10,6 +10,7 @@ use crate::entity::account::*;
use crate::entity::character::*;
use crate::entity::gateway::{EntityGateway, EntityGatewayTransaction, GatewayError};
use crate::entity::item::*;
use crate::entity::room::*;
use super::models::*;
use sqlx::postgres::PgPoolOptions;
@ -178,7 +179,7 @@ async fn create_user(conn: &mut sqlx::PgConnection, user: NewUserAccountEntity)
async fn get_user_by_id(conn: &mut sqlx::PgConnection, id: UserAccountId) -> Result<UserAccountEntity, GatewayError>
{
let user = sqlx::query_as::<_, PgUserAccount>("select * from user_accounts where id = $1")
.bind(id.0)
.bind(id.0 as i32)
.fetch_one(conn).await?;
Ok(user.into())
}
@ -199,8 +200,8 @@ async fn save_user(conn: &mut sqlx::PgConnection, user: &UserAccountEntity) -> R
.bind(&user.password)
.bind(user.banned_until)
.bind(user.muted_until)
.bind(user.flags)
.bind(user.id.0)
.bind(user.flags as i32)
.bind(user.id.0 as i32)
.execute(conn).await?;
Ok(())
}
@ -209,7 +210,7 @@ async fn create_user_settings(conn: &mut sqlx::PgConnection, settings: NewUserSe
{
let new_settings = sqlx::query_as::<_, PgUserSettings>("insert into user_settings (user_account, blocked_users, key_config, joystick_config, option_flags, shortcuts, symbol_chats, team_name)
values ($1, $2, $3, $4, $5, $6, $7, $8) returning *;")
.bind(settings.user_id.0)
.bind(settings.user_id.0 as i32)
.bind(settings.settings.blocked_users.iter().copied().flat_map(|i| i.to_le_bytes().to_vec()).collect::<Vec<u8>>())
.bind(settings.settings.keyboard_config.to_vec())
.bind(settings.settings.gamepad_config.to_vec())
@ -224,7 +225,7 @@ async fn create_user_settings(conn: &mut sqlx::PgConnection, settings: NewUserSe
async fn get_user_settings_by_user(conn: &mut sqlx::PgConnection, user: &UserAccountEntity) -> Result<UserSettingsEntity, GatewayError>
{
let settings = sqlx::query_as::<_, PgUserSettings>("select * from user_settings where user_account = $1")
.bind(user.id.0)
.bind(user.id.0 as i32)
.fetch_one(conn).await?;
Ok(settings.into())
}
@ -235,11 +236,11 @@ async fn save_user_settings(conn: &mut sqlx::PgConnection, settings: &UserSettin
.bind(settings.settings.blocked_users.iter().copied().flat_map(|i| i.to_le_bytes().to_vec()).collect::<Vec<u8>>())
.bind(&settings.settings.keyboard_config.to_vec())
.bind(&settings.settings.gamepad_config.to_vec())
.bind(settings.settings.option_flags)
.bind(settings.settings.option_flags as i32)
.bind(&settings.settings.shortcuts.to_vec())
.bind(&settings.settings.symbol_chats.to_vec())
.bind(settings.settings.team_name.iter().copied().flat_map(|i| i.to_le_bytes().to_vec()).collect::<Vec<u8>>())
.bind(settings.id.0)
.bind(settings.id.0 as i32)
.execute(conn).await?;
Ok(())
}
@ -262,7 +263,7 @@ async fn create_character(conn: &mut sqlx::PgConnection, char: NewCharacterEntit
$26, $27, $28, $29, $30)
returning *;"#;
let character = sqlx::query_as::<_, PgCharacter>(q)
.bind(char.user_id.0)
.bind(char.user_id.0 as i32)
.bind(char.slot as i16)
.bind(char.name)
.bind(char.exp as i32)
@ -300,7 +301,7 @@ async fn create_character(conn: &mut sqlx::PgConnection, char: NewCharacterEntit
async fn get_characters_by_user(conn: &mut sqlx::PgConnection, user: &UserAccountEntity) -> Result<[Option<CharacterEntity>; 4], GatewayError>
{
let stream = sqlx::query_as::<_, PgCharacter>("select * from player_character where user_account = $1 and slot < 4 order by created_at;")
.bind(user.id.0)
.bind(user.id.0 as i32)
.fetch(conn);
Ok(stream.fold(core::array::from_fn(|_| None), |mut acc, char| async move {
@ -320,7 +321,7 @@ async fn save_character(conn: &mut sqlx::PgConnection, char: &CharacterEntity) -
evade=$24, luck=$25, hp=$26, tp=$27, tech_menu=$28, option_flags=$29, playtime=$30
where id=$31;"#;
sqlx::query(q)
.bind(char.user_id.0) // $1
.bind(char.user_id.0 as i32) // $1
.bind(char.slot as i16) // $2
.bind(&char.name) // $3
.bind(char.exp as i32) // $4
@ -370,7 +371,7 @@ async fn create_item(conn: &mut sqlx::PgConnection, item: NewItemEntity) -> Resu
async fn add_item_note(conn: &mut sqlx::PgConnection, item_id: &ItemEntityId, item_note: ItemNote) -> Result<(), GatewayError>
{
sqlx::query("insert into item_note(item, note) values ($1, $2)")
.bind(item_id.0)
.bind(item_id.0 as i32)
.bind(sqlx::types::Json(PgItemNoteDetail::from(item_note)))
.execute(conn).await?;
Ok(())
@ -379,7 +380,7 @@ async fn add_item_note(conn: &mut sqlx::PgConnection, item_id: &ItemEntityId, it
async fn feed_mag(conn: &mut sqlx::PgConnection, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) -> Result<(), GatewayError>
{
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
.bind(mag_item_id.0)
.bind(mag_item_id.0 as i32)
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::FeedMag{food: *tool_item_id})))
.execute(conn).await?;
Ok(())
@ -388,7 +389,7 @@ async fn feed_mag(conn: &mut sqlx::PgConnection, mag_item_id: &ItemEntityId, too
async fn change_mag_owner(conn: &mut sqlx::PgConnection, mag_item_id: &ItemEntityId, character: &CharacterEntity) -> Result<(), GatewayError>
{
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
.bind(mag_item_id.0)
.bind(mag_item_id.0 as i32)
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::OwnerChange(character.char_class, character.section_id))))
.execute(conn).await?;
Ok(())
@ -397,7 +398,7 @@ async fn change_mag_owner(conn: &mut sqlx::PgConnection, mag_item_id: &ItemEntit
async fn use_mag_cell(conn: &mut sqlx::PgConnection, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) -> Result<(), GatewayError>
{
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
.bind(mag_item_id.0)
.bind(mag_item_id.0 as i32)
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::MagCell(*mag_cell_id))))
.execute(conn).await?;
Ok(())
@ -406,7 +407,7 @@ async fn use_mag_cell(conn: &mut sqlx::PgConnection, mag_item_id: &ItemEntityId,
async fn add_weapon_modifier(conn: &mut sqlx::PgConnection, item_id: &ItemEntityId, modifier: &weapon::WeaponModifier) -> Result<(), GatewayError>
{
sqlx::query("insert into weapon_modifier (weapon, modifier) values ($1, $2);")
.bind(item_id.0)
.bind(item_id.0 as i32)
.bind(sqlx::types::Json(modifier))
.execute(conn).await?;
Ok(())
@ -416,7 +417,7 @@ async fn get_character_inventory(conn: &mut sqlx::PgConnection, char_id: &Charac
{
let conn = Arc::new(Mutex::new(conn.begin().await?)); // this is some degen shit
let inventory = sqlx::query_as::<_, PgInventoryEntity>("select * from inventory where pchar = $1")
.bind(char_id.0)
.bind(char_id.0 as i32)
.fetch_one(&mut **conn.lock().await).await?;
Ok(InventoryEntity::new(
@ -441,14 +442,14 @@ async fn get_character_bank(conn: &mut sqlx::PgConnection, char_id: &CharacterEn
let bank = match bank_identifier {
BankIdentifier::Character => {
sqlx::query_as::<_, PgInventoryEntity>("select * from bank where pchar = $1")
.bind(char_id.0)
.bind(char_id.0 as i32)
.fetch_one(&mut **conn.lock().await).await?
},
BankIdentifier::Shared(bank_name) => {
sqlx::query_as::<_, PgInventoryEntity>("select player_character.id as pchar, shared_bank.items as items from shared_bank
join player_character on shared_bank.user_account = player_character.user_account
where player_character.id = $1 and shared_bank.name = $2")
.bind(char_id.0)
.bind(char_id.0 as i32)
.bind(&bank_name.0)
.fetch_optional(&mut **conn.lock().await)
.await?
@ -491,7 +492,7 @@ async fn set_character_inventory(conn: &mut sqlx::PgConnection, char_id: &Charac
.collect::<Vec<_>>();
sqlx::query("insert into inventory (pchar, items) values ($1, $2) on conflict (pchar) do update set items = $2")
.bind(char_id.0)
.bind(char_id.0 as i32)
.bind(sqlx::types::Json(inventory))
.execute(conn)
.await?;
@ -516,7 +517,7 @@ async fn set_character_bank(conn: &mut sqlx::PgConnection, char_id: &CharacterEn
match bank_identifier {
BankIdentifier::Character => {
sqlx::query("insert into bank (pchar, items, name) values ($1, $2, '') on conflict (pchar, name) do update set items = $2")
.bind(char_id.0)
.bind(char_id.0 as i32)
.bind(sqlx::types::Json(bank))
.execute(conn)
.await?;
@ -526,7 +527,7 @@ async fn set_character_bank(conn: &mut sqlx::PgConnection, char_id: &CharacterEn
select player_character.user_account, $2, $3 from player_character
where player_character.id = $1
on conflict (user_account, name) do update set items = $2;")
.bind(char_id.0)
.bind(char_id.0 as i32)
.bind(sqlx::types::Json(bank))
.bind(&bank_name.0)
.execute(conn)
@ -539,7 +540,7 @@ async fn set_character_bank(conn: &mut sqlx::PgConnection, char_id: &CharacterEn
async fn get_character_equips(conn: &mut sqlx::PgConnection, char_id: &CharacterEntityId) -> Result<EquippedEntity, GatewayError>
{
let equips = sqlx::query_as::<_, PgEquipped>("select * from equipped where pchar = $1")
.bind(char_id.0)
.bind(char_id.0 as i32)
.fetch_one(conn)
.await?;
@ -550,7 +551,7 @@ async fn set_character_equips(conn: &mut sqlx::PgConnection, char_id: &Character
{
sqlx::query(r#"insert into equipped (pchar, weapon, armor, shield, unit0, unit1, unit2, unit3, mag) values ($1, $2, $3, $4, $5, $6, $7, $8, $9)
on conflict (pchar) do update set weapon=$2, armor=$3, shield=$4, unit0=$5, unit1=$6, unit2=$7, unit3=$8, mag=$9"#)
.bind(char_id.0)
.bind(char_id.0 as i32)
.bind(equips.weapon.map(|i| i.0 as i32))
.bind(equips.armor.map(|i| i.0 as i32))
.bind(equips.shield.map(|i| i.0 as i32))
@ -568,7 +569,7 @@ async fn set_character_equips(conn: &mut sqlx::PgConnection, char_id: &Character
async fn set_character_meseta(conn: &mut sqlx::PgConnection, char_id: &CharacterEntityId, meseta: Meseta) -> Result<(), GatewayError>
{
sqlx::query("insert into character_meseta values ($1, $2) on conflict (pchar) do update set meseta = $2")
.bind(char_id.0)
.bind(char_id.0 as i32)
.bind(meseta.0 as i32)
.execute(conn)
.await?;
@ -580,7 +581,7 @@ async fn get_character_meseta(conn: &mut sqlx::PgConnection, char_id: &Character
#[derive(sqlx::FromRow)]
struct PgMeseta(i32);
let meseta = sqlx::query_as::<_, PgMeseta>(r#"select meseta from character_meseta where pchar = $1"#)
.bind(char_id.0)
.bind(char_id.0 as i32)
.fetch_one(conn)
.await?;
Ok(Meseta(meseta.0 as u32))
@ -591,7 +592,7 @@ async fn set_bank_meseta(conn: &mut sqlx::PgConnection, char_id: &CharacterEntit
match bank_identifier {
BankIdentifier::Character => {
sqlx::query("insert into bank_meseta values ($1, '', $2) on conflict (pchar, bank) do update set meseta = $2")
.bind(char_id.0)
.bind(char_id.0 as i32)
.bind(meseta.0 as i32)
.execute(conn)
.await?;
@ -601,7 +602,7 @@ async fn set_bank_meseta(conn: &mut sqlx::PgConnection, char_id: &CharacterEntit
select player_character.user_account, $2, $3 from player_character
where player_character.id = $1
on conflict (user_account, name) do update set meseta = $3")
.bind(char_id.0)
.bind(char_id.0 as i32)
.bind(&bank_name.0)
.bind(meseta.0 as i32)
.execute(conn)
@ -620,7 +621,7 @@ async fn get_bank_meseta(conn: &mut sqlx::PgConnection, char_id: &CharacterEntit
let meseta = match bank_identifier {
BankIdentifier::Character => {
sqlx::query_as::<_, PgMeseta>(r#"select meseta from bank_meseta where pchar = $1"#)
.bind(char_id.0)
.bind(char_id.0 as i32)
.fetch_one(conn)
.await?
},
@ -628,7 +629,7 @@ async fn get_bank_meseta(conn: &mut sqlx::PgConnection, char_id: &CharacterEntit
sqlx::query_as::<_, PgMeseta>(r#"select shared_bank_meseta.meseta from shared_bank_meseta
join player_character on shared_bank_meseta.user_account = player_character.user_account
where player_character.id = $1 and shared_bank_meseta.name = $2"#)
.bind(char_id.0)
.bind(char_id.0 as i32)
.bind(&bank_name.0)
.fetch_optional(conn)
.await?
@ -641,8 +642,8 @@ async fn get_bank_meseta(conn: &mut sqlx::PgConnection, char_id: &CharacterEntit
async fn create_trade(conn: &mut sqlx::PgConnection, char_id1: &CharacterEntityId, char_id2: &CharacterEntityId) -> Result<TradeEntity, GatewayError>
{
let trade = sqlx::query_as::<_, PgTradeEntity>(r#"insert into trades (character1, character2) values ($1, $2) returning *;"#)
.bind(char_id1.0)
.bind(char_id2.0)
.bind(char_id1.0 as i32)
.bind(char_id2.0 as i32)
.fetch_one(conn)
.await?;
Ok(trade.into())
@ -651,8 +652,30 @@ async fn create_trade(conn: &mut sqlx::PgConnection, char_id1: &CharacterEntityI
async fn set_character_playtime(conn: &mut sqlx::PgConnection, char_id: &CharacterEntityId, playtime: u32) -> Result<(), GatewayError>
{
sqlx::query(r#"update player_character set playtime=$2 where id=$1;"#)
.bind(char_id.0)
.bind(playtime)
.bind(char_id.0 as i32)
.bind(playtime as i32)
.execute(conn)
.await?;
Ok(())
}
async fn create_room(conn: &mut sqlx::PgConnection, room: NewRoomEntity) -> Result<RoomEntity, GatewayError> {
sqlx::query_as::<_, PgRoomEntity>("insert into room (name, section_id, mode, episode, difficulty) values ($1, $2, $3, $4, $5) returning *")
.bind(room.name)
.bind(u8::from(room.section_id) as i8)
.bind(u8::from(room.mode) as i8)
.bind(u8::from(room.episode) as i8)
.bind(u8::from(room.difficulty) as i8)
.fetch_one(conn)
.await
.map(|room| room.into())
.map_err(|err| err.into())
}
async fn add_room_note(conn: &mut sqlx::PgConnection, room_id: RoomEntityId, note: RoomNote) -> Result<(), GatewayError> {
sqlx::query("insert into room_note (room, note) values ($1, $2)")
.bind(room_id.0 as i32)
.bind(sqlx::types::Json(note))
.execute(conn)
.await?;
Ok(())
@ -797,6 +820,14 @@ impl EntityGateway for PostgresGateway {
async fn set_character_playtime(&mut self, char_id: &CharacterEntityId, playtime: u32) -> Result<(), GatewayError> {
set_character_playtime(&mut *self.pool.acquire().await?, char_id, playtime).await
}
async fn create_room(&mut self, room: NewRoomEntity) -> Result<RoomEntity, GatewayError> {
create_room(&mut *self.pool.acquire().await?, room).await
}
async fn add_room_note(&mut self, room_id: RoomEntityId, note: RoomNote) -> Result<(), GatewayError> {
add_room_note(&mut *self.pool.acquire().await?, room_id, note).await
}
}
@ -923,5 +954,13 @@ impl<'c> EntityGateway for PostgresTransaction<'c> {
async fn set_character_playtime(&mut self, char_id: &CharacterEntityId, playtime: u32) -> Result<(), GatewayError> {
set_character_playtime(&mut *self.pgtransaction.lock().await, char_id, playtime).await
}
async fn create_room(&mut self, room: NewRoomEntity) -> Result<RoomEntity, GatewayError> {
create_room(&mut *self.pgtransaction.lock().await, room).await
}
async fn add_room_note(&mut self, room_id: RoomEntityId, note: RoomNote) -> Result<(), GatewayError> {
add_room_note(&mut *self.pgtransaction.lock().await, room_id, note).await
}
}

24
src/entity/item/mod.rs

@ -10,7 +10,9 @@ pub mod esweapon;
use serde::{Serialize, Deserialize};
use crate::entity::character::CharacterEntityId;
use crate::entity::room::RoomEntityId;
use crate::ship::map::MapArea;
use crate::ship::monster::MonsterType;
use crate::ship::drops::ItemDropType;
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash, PartialOrd, Ord, Serialize, Deserialize)]
@ -35,8 +37,16 @@ pub enum ItemNote {
},
EnemyDrop {
character_id: CharacterEntityId,
//monster_type: MonsterType,
//droprate: f32,
room_id: RoomEntityId,
monster_type: MonsterType,
map_area: MapArea,
x: f32,
y: f32,
z: f32,
},
BoxDrop {
character_id: CharacterEntityId,
room_id: RoomEntityId,
map_area: MapArea,
x: f32,
y: f32,
@ -52,15 +62,19 @@ pub enum ItemNote {
y: f32,
z: f32,
},
Consumed, // TODO: character_id
Consumed {
character_id: CharacterEntityId,
},
FedToMag {
//character_id: CharacterEntityId,
character_id: CharacterEntityId,
mag: ItemEntityId,
},
BoughtAtShop {
character_id: CharacterEntityId,
},
SoldToShop,
SoldToShop {
character_id: CharacterEntityId,
},
Trade {
trade_id: TradeId,
character_to: CharacterEntityId,

1
src/entity/mod.rs

@ -2,3 +2,4 @@ pub mod gateway;
pub mod account;
pub mod character;
pub mod item;
pub mod room;

83
src/entity/room.rs

@ -0,0 +1,83 @@
use serde::{Serialize, Deserialize};
use crate::entity::character::{CharacterEntityId, SectionID};
use crate::ship::room::{Episode, Difficulty};
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct RoomEntityId(pub u32);
#[derive(Debug, Copy, Clone)]
pub enum RoomEntityMode {
Multi,
Single,
Challenge,
Battle,
}
impl From<u8> for RoomEntityMode {
fn from(other: u8) -> RoomEntityMode {
match other {
0 => RoomEntityMode::Multi,
1 => RoomEntityMode::Single,
2 => RoomEntityMode::Challenge,
3 => RoomEntityMode::Battle,
_ => unreachable!()
}
}
}
impl From<RoomEntityMode> for u8 {
fn from(other: RoomEntityMode) -> u8 {
match other {
RoomEntityMode::Multi => 0,
RoomEntityMode::Single => 1,
RoomEntityMode::Challenge => 2,
RoomEntityMode::Battle => 3,
}
}
}
#[derive(Debug, Clone)]
pub struct RoomEntity {
pub id: RoomEntityId,
pub name: String,
pub section_id: SectionID,
pub mode: RoomEntityMode,
pub episode: Episode,
pub difficulty: Difficulty,
}
#[derive(Debug, Clone)]
pub struct NewRoomEntity {
pub name: String,
pub section_id: SectionID,
pub mode: RoomEntityMode,
pub episode: Episode,
pub difficulty: Difficulty,
}
#[derive(Debug, Copy, Clone, Serialize)]
pub enum RoomNote {
Create {
character_id: CharacterEntityId,
},
PlayerJoin {
character_id: CharacterEntityId,
},
PlayerLeave {
character_id: CharacterEntityId,
},
QuestStart {
// quest id
},
QuestComplete {
// quest id
},
}

120
src/ship/items/actions.rs

@ -9,22 +9,23 @@ use std::iter::IntoIterator;
use anyhow::Context;
use libpso::packet::{ship::Message, messages::GameMessage};
use crate::ship::map::MapArea;
use crate::ship::ship::SendShipPacket;
use crate::entity::character::{CharacterEntity, CharacterEntityId};
use crate::entity::gateway::{EntityGateway, EntityGatewayTransaction};
use crate::entity::item::{ItemDetail, NewItemEntity, TradeId, ItemModifier};
use crate::entity::item::tool::Tool;
use crate::entity::room::RoomEntityId;
use crate::ship::map::MapArea;
use crate::ship::ship::SendShipPacket;
use crate::ship::items::state::{ItemStateProxy, ItemStateError, AddItemResult, StackedItemDetail, IndividualItemDetail};
use crate::ship::items::bank::{BankItem, BankItemDetail};
use crate::ship::items::inventory::{InventoryItem, InventoryItemDetail};
use crate::ship::items::floor::{FloorItem, FloorItemDetail};
use crate::ship::items::apply_item::{apply_item, ApplyItemAction};
use crate::entity::item::{ItemDetail, NewItemEntity, TradeId};
use crate::entity::item::tool::Tool;
use crate::entity::item::ItemModifier;
use crate::ship::shops::ShopItem;
use crate::ship::drops::{ItemDrop, ItemDropType};
use crate::ship::packet::builder;
use crate::ship::location::AreaClient;
use crate::ship::monster::MonsterType;
pub enum TriggerCreateItem {
Yes,
@ -513,7 +514,9 @@ where
Box::pin(async move {
let mut transaction = inventory_item.with_entity_id(transaction, |mut transaction, entity_id| {
async move {
transaction.gateway().add_item_note(&entity_id, ItemNote::Consumed).await?;
transaction.gateway().add_item_note(&entity_id, ItemNote::Consumed {
character_id: character.id,
}).await?;
Ok(transaction)
}}).await?;
@ -548,7 +551,7 @@ where
let mut transaction = tool.with_entity_id(transaction, |mut transaction, entity_id| {
async move {
transaction.gateway().add_item_note(&entity_id, ItemNote::FedToMag {
//character_id: character.id,
character_id: character.id,
mag: mag_entity_id,
}).await?;
transaction.gateway().feed_mag(&mag_entity_id, &entity_id).await?;
@ -660,7 +663,9 @@ where
let mut transaction = inventory_item.with_entity_id(transaction, |mut transaction, entity_id| {
async move {
transaction.gateway().add_item_note(&entity_id, ItemNote::SoldToShop).await?;
transaction.gateway().add_item_note(&entity_id, ItemNote::SoldToShop {
character_id,
}).await?;
Ok(transaction)
}}).await?;
transaction.gateway().set_character_meseta(&character_id, inventory.meseta).await?;
@ -904,7 +909,6 @@ where
pub(super) fn convert_item_drop_to_floor_item<'a, EG, TR>(
character_id: CharacterEntityId,
item_drop: ItemDrop,
) -> impl Fn((ItemStateProxy, TR), ())
-> BoxFuture<'a, Result<((ItemStateProxy, TR), FloorItem), anyhow::Error>> + Clone
@ -946,13 +950,6 @@ where
let entity = transaction.gateway().create_item(NewItemEntity {
item: item_detail.clone(),
}).await?;
transaction.gateway().add_item_note(&entity.id, ItemNote::EnemyDrop {
character_id,
map_area: item_drop.map_area,
x: item_drop.x,
y: item_drop.y,
z: item_drop.z,
}).await?;
FloorItem {
item_id,
item: FloorItemDetail::Individual(IndividualItemDetail {
@ -969,13 +966,6 @@ where
let entity = transaction.gateway().create_item(NewItemEntity {
item: ItemDetail::Tool(tool),
}).await?;
transaction.gateway().add_item_note(&entity.id, ItemNote::EnemyDrop {
character_id,
map_area: item_drop.map_area,
x: item_drop.x,
y: item_drop.y,
z: item_drop.z,
}).await?;
FloorItem {
item_id,
item: FloorItemDetail::Stacked(StackedItemDetail{
@ -1005,6 +995,88 @@ where
}
}
pub(super) fn item_note_enemy_drop<'a, EG, TR>(
character_id: CharacterEntityId,
room_id: RoomEntityId,
monster_type: MonsterType,
) -> impl Fn((ItemStateProxy, TR), FloorItem)
-> BoxFuture<'a, Result<((ItemStateProxy, TR), FloorItem), anyhow::Error>> + Clone
where
EG: EntityGateway,
TR: EntityGatewayTransaction<ParentGateway = EG> + 'a,
{
move |(item_state, mut transaction), floor_item| {
Box::pin(async move {
match &floor_item.item {
FloorItemDetail::Individual(individual) => {
transaction.gateway().add_item_note(&individual.entity_id, ItemNote::EnemyDrop {
character_id,
room_id,
monster_type,
map_area: floor_item.map_area,
x: floor_item.x,
y: floor_item.y,
z: floor_item.z,
}).await?;
},
FloorItemDetail::Stacked(stacked) => {
transaction.gateway().add_item_note(&stacked.entity_ids[0], ItemNote::EnemyDrop {
character_id,
room_id,
monster_type,
map_area: floor_item.map_area,
x: floor_item.x,
y: floor_item.y,
z: floor_item.z,
}).await?;
},
_ => {},
}
Ok(((item_state, transaction), floor_item))
})
}
}
pub(super) fn item_note_box_drop<'a, EG, TR>(
character_id: CharacterEntityId,
room_id: RoomEntityId,
) -> impl Fn((ItemStateProxy, TR), FloorItem)
-> BoxFuture<'a, Result<((ItemStateProxy, TR), FloorItem), anyhow::Error>> + Clone
where
EG: EntityGateway,
TR: EntityGatewayTransaction<ParentGateway = EG> + 'a,
{
move |(item_state, mut transaction), floor_item| {
Box::pin(async move {
match &floor_item.item {
FloorItemDetail::Individual(individual) => {
transaction.gateway().add_item_note(&individual.entity_id, ItemNote::BoxDrop {
character_id,
room_id,
map_area: floor_item.map_area,
x: floor_item.x,
y: floor_item.y,
z: floor_item.z,
}).await?;
},
FloorItemDetail::Stacked(stacked) => {
transaction.gateway().add_item_note(&stacked.entity_ids[0], ItemNote::BoxDrop {
character_id,
room_id,
map_area: floor_item.map_area,
x: floor_item.x,
y: floor_item.y,
z: floor_item.z,
}).await?;
},
_ => {},
}
Ok(((item_state, transaction), floor_item))
})
}
}
pub(super) fn add_item_to_local_floor<'a, EG, TR>(
character_id: CharacterEntityId,
) -> impl Fn((ItemStateProxy, TR), FloorItem)
@ -1169,4 +1241,4 @@ where
Ok(((item_state, transaction), ()))
})
}
}
}

33
src/ship/items/tasks.rs

@ -6,15 +6,17 @@ use crate::ship::ship::SendShipPacket;
use crate::ship::map::MapArea;
use crate::entity::character::{CharacterEntity, CharacterEntityId};
use crate::entity::gateway::{EntityGateway, EntityGatewayTransaction};
use crate::entity::item::ItemModifier;
use crate::entity::room::RoomEntityId;
use crate::ship::items::state::{ItemState, ItemStateProxy, IndividualItemDetail};
use crate::ship::items::itemstateaction::{ItemStateAction, ItemAction};
use crate::ship::items::inventory::InventoryItem;
use crate::ship::items::floor::FloorItem;
use crate::entity::item::ItemModifier;
use crate::ship::shops::ShopItem;
use crate::ship::trade::TradeItem;
use crate::ship::location::AreaClient;
use crate::ship::drops::ItemDrop;
use crate::ship::monster::MonsterType;
use crate::ship::items::actions;
@ -465,6 +467,32 @@ pub fn enemy_drops_item<'a, EG> (
item_state: &'a mut ItemState,
entity_gateway: &'a mut EG,
character_id: CharacterEntityId,
room_id: RoomEntityId,
monster_type: MonsterType,
item_drop: ItemDrop)
-> BoxFuture<'a, Result<FloorItem, anyhow::Error>>
where
EG: EntityGateway + 'static,
{
entity_gateway.with_transaction(move |transaction| async move {
let item_state_proxy = ItemStateProxy::new(item_state.clone());
let ((item_state_proxy, transaction), floor_item) = ItemStateAction::default()
.act(actions::convert_item_drop_to_floor_item(item_drop))
.act(actions::item_note_enemy_drop(character_id, room_id, monster_type))
.act(actions::add_item_to_local_floor(character_id))
.commit((item_state_proxy, transaction))
.await?;
item_state_proxy.commit().await;
Ok((transaction, floor_item))
})
}
pub fn box_drops_item<'a, EG> (
item_state: &'a mut ItemState,
entity_gateway: &'a mut EG,
character_id: CharacterEntityId,
room_id: RoomEntityId,
item_drop: ItemDrop)
-> BoxFuture<'a, Result<FloorItem, anyhow::Error>>
where
@ -473,7 +501,8 @@ where
entity_gateway.with_transaction(move |transaction| async move {
let item_state_proxy = ItemStateProxy::new(item_state.clone());
let ((item_state_proxy, transaction), floor_item) = ItemStateAction::default()
.act(actions::convert_item_drop_to_floor_item(character_id, item_drop))
.act(actions::convert_item_drop_to_floor_item(item_drop))
.act(actions::item_note_box_drop(character_id, room_id))
.act(actions::add_item_to_local_floor(character_id))
.commit((item_state_proxy, transaction))
.await?;

14
src/ship/packet/handler/direct_message.rs

@ -18,7 +18,7 @@ use crate::ship::shops::{ShopItem, ToolShopItem, ArmorShopItem};
use crate::ship::items::state::{ItemState, ItemStateError};
use crate::ship::items::floor::{FloorType, FloorItemDetail};
use crate::ship::items::actions::TriggerCreateItem;
use crate::ship::items::tasks::{pick_up_item, withdraw_meseta, deposit_meseta, withdraw_item, deposit_item, buy_shop_item, enemy_drops_item, take_meseta, apply_modifier};
use crate::ship::items::tasks::{pick_up_item, withdraw_meseta, deposit_meseta, withdraw_item, deposit_item, buy_shop_item, enemy_drops_item, box_drops_item, take_meseta, apply_modifier};
const BANK_ACTION_DEPOSIT: u8 = 0;
const BANK_ACTION_WITHDRAW: u8 = 1;
@ -89,8 +89,8 @@ where
EG: EntityGateway + 'static,
{
let room_id = client_location.get_room(id).await?;
let monster = rooms.with(room_id, |room| Box::pin(async move {
room.maps.enemy_by_id(request_item.enemy_id as usize)
let (room_entity_id, monster) = rooms.with(room_id, |room| Box::pin(async move {
Ok::<_, anyhow::Error>((room.room_id, room.maps.enemy_by_id(request_item.enemy_id as usize)?))
})).await??;
if monster.dropped_item {
@ -121,7 +121,7 @@ where
client.character.id
})).await?;
let floor_item = enemy_drops_item(item_state, entity_gateway, character_id, item_drop).await?;
let floor_item = enemy_drops_item(item_state, entity_gateway, character_id, room_entity_id, monster.monster, item_drop).await?;
let item_drop_msg = builder::message::item_drop(request_item.client, request_item.target, &floor_item)?;
item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))));
@ -200,8 +200,8 @@ where
EG: EntityGateway + Clone + 'static
{
let room_id = client_location.get_room(id).await?;
let box_object = rooms.with(room_id, |room| Box::pin(async move {
room.maps.object_by_id(box_drop_request.object_id as usize)
let (room_entity_id, box_object) = rooms.with(room_id, |room| Box::pin(async move {
Ok::<_, anyhow::Error>((room.room_id, room.maps.object_by_id(box_drop_request.object_id as usize)?))
})).await??;
if box_object.dropped_item {
@ -232,7 +232,7 @@ where
let character_id = clients.with(area_client.client, |client| Box::pin(async move {
client.character.id
})).await?;
let floor_item = enemy_drops_item(item_state, entity_gateway, character_id, item_drop).await?;
let floor_item = box_drops_item(item_state, entity_gateway, character_id, room_entity_id, item_drop).await?;
//let floor_item = enemy_drops_item(item_state, &mut entity_gateway, client.character.id, item_drop).await?;
let item_drop_msg = builder::message::item_drop(box_drop_request.client, box_drop_request.target, &floor_item)?;
item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))))

14
src/ship/packet/handler/lobby.rs

@ -8,6 +8,7 @@ use crate::ship::location::{ClientLocation, LobbyId, RoomLobby, ClientLocationEr
use crate::ship::packet;
use crate::ship::items::state::ItemState;
use crate::entity::gateway::EntityGateway;
use crate::entity::room::RoomNote;
use crate::ship::map::MapArea;
use futures::future::join_all;
@ -89,14 +90,25 @@ where
}
},
RoomLobby::Room(old_room) => {
let room_entity_id = rooms.with(old_room, |room| Box::pin(async {
room.room_id
})).await?;
if client_location.get_client_neighbors(id).await?.is_empty() {
rooms.remove(old_room).await;
}
let character_id = clients.with(id, |client| Box::pin(async {
client.character.id
})).await?;
clients.with(id, |client| {
let mut item_state = item_state.clone();
let mut entity_gateway = entity_gateway.clone();
Box::pin(async move {
item_state.remove_character_from_room(&client.character).await;
})}).await?;
entity_gateway.add_room_note(room_entity_id, RoomNote::PlayerLeave {
character_id
}).await
})}).await??;
},
}
let leave_lobby = packet::builder::lobby::remove_from_lobby(id, client_location).await?;

17
src/ship/packet/handler/quest.rs

@ -46,8 +46,9 @@ pub async fn send_quest_category_list(id: ClientId,
let room_id = client_location.get_room(id).await?;
let rql = rql.clone();
rooms.with_mut(room_id, |room| Box::pin(async move {
let qcl = quest::quest_category_list(&room.quests[rql.flag.clamp(0, (room.quests.len() - 1) as u32) as usize]);
room.set_quest_group(rql.flag as usize);
//let qcl = quest::quest_category_list(&room.quests[rql.flag.clamp(0, (room.quests.len() - 1) as u32) as usize]);
room.quest_group = rql.flag.into();
let qcl = quest::quest_category_list(room.quests());
Ok(vec![(id, SendShipPacket::QuestCategoryList(qcl))])
})).await?
}
@ -59,10 +60,10 @@ pub async fn select_quest_category(id: ClientId,
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
let room_id = client_location.get_room(id).await?;
rooms.with(room_id, |room| Box::pin(async move {
let (_, category_quests) = room.quests[room.quest_group.value()].iter()
let (_, category_quests) = room.quests()
.iter()
.nth(menuselect.item as usize)
.ok_or_else(|| ShipError::InvalidQuestCategory(menuselect.item as u16))?;
let ql = quest::quest_list(menuselect.item, category_quests);
Ok(vec![(id, SendShipPacket::QuestOptionList(ql))])
})).await?
@ -76,7 +77,7 @@ pub async fn quest_detail(id: ClientId,
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
let room_id = client_location.get_room(id).await?;
rooms.with(room_id, |room| Box::pin(async move {
let (_, category_quests) = room.quests[room.quest_group.value()].iter()
let (_, category_quests) = room.quests().iter()
.nth(questdetailrequest.category as usize)
.ok_or_else(|| ShipError::InvalidQuestCategory(questdetailrequest.category))?;
@ -105,7 +106,7 @@ pub async fn player_chose_quest(id: ClientId,
rooms.with_mut(room_id, |room| {
let clients = clients.clone();
Box::pin(async move {
let quest = room.quests[room.quest_group.value()].iter()
let quest = room.quests().iter()
.nth(questmenuselect.category as usize)
.ok_or_else(|| ShipError::InvalidQuestCategory(questmenuselect.category))?
.1
@ -149,7 +150,7 @@ pub async fn quest_file_request(id: ClientId,
let quest_file_request = quest_file_request.clone();
rooms.with(room_id, |room| Box::pin(async move {
let (category_id, quest_id, datatype) = parse_filename(&quest_file_request.filename)?;
let (_, category_quests) = room.quests[room.quest_group.value()].iter()
let (_, category_quests) = room.quests().iter()
.nth(category_id as usize)
.ok_or_else(|| ShipError::InvalidQuestCategory(category_id))?;
@ -182,7 +183,7 @@ pub async fn quest_chunk_ack(id: ClientId,
let quest_chunk_ack = quest_chunk_ack.clone();
rooms.with(room_id, |room| Box::pin(async move {
let (category_id, quest_id, datatype) = parse_filename(&quest_chunk_ack.filename)?;
let (_, category_quests) = room.quests[room.quest_group.value()].iter()
let (_, category_quests) = room.quests().iter()
.nth(category_id as usize)
.ok_or_else(|| ShipError::InvalidQuestCategory(category_id))?;

98
src/ship/packet/handler/room.rs

@ -7,7 +7,9 @@ use libpso::packet::ship::*;
use libpso::packet::messages::*;
use crate::common::serverstate::ClientId;
use crate::common::leveltable::LEVEL_TABLE;
use crate::entity::gateway::EntityGateway;
use crate::entity::character::SectionID;
use crate::entity::room::{NewRoomEntity, RoomEntityMode, RoomNote};
use crate::ship::drops::DropTable;
use crate::ship::ship::{SendShipPacket, Clients, ShipEvent};
use crate::ship::room::{Rooms, Episode, Difficulty, RoomState, RoomMode};
@ -17,20 +19,25 @@ use crate::ship::packet::builder;
use crate::ship::items::state::ItemState;
#[allow(clippy::too_many_arguments)]
pub async fn create_room(id: ClientId,
create_room: CreateRoom,
client_location: &mut ClientLocation,
clients: &Clients,
item_state: &mut ItemState,
rooms: &Rooms,
map_builder: Arc<Box<dyn Fn(RoomMode, ShipEvent) -> Maps + Send + Sync>>,
drop_table_builder: Arc<Box<dyn Fn(Episode, Difficulty, SectionID) -> DropTable + Send + Sync>>,
event: ShipEvent)
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
pub async fn create_room<EG>(id: ClientId,
create_room: CreateRoom,
entity_gateway: &mut EG,
client_location: &mut ClientLocation,
clients: &Clients,
item_state: &mut ItemState,
rooms: &Rooms,
map_builder: Arc<Box<dyn Fn(RoomMode, ShipEvent) -> Maps + Send + Sync>>,
drop_table_builder: Arc<Box<dyn Fn(Episode, Difficulty, SectionID) -> DropTable + Send + Sync>>,
event: ShipEvent)
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error>
where
EG: EntityGateway + Clone + 'static