Browse Source

shared banks wow

pull/130/head
jake 2 years ago
parent
commit
fc5d318ac3
  1. 4
      Cargo.lock
  2. 66
      src/entity/gateway/postgres/postgres.rs
  3. 78
      src/ship/chatcommand.rs
  4. 2
      src/ship/client.rs
  5. 6
      src/ship/items/actions.rs
  6. 11
      src/ship/ship.rs

4
Cargo.lock

@ -1040,7 +1040,7 @@ checksum = "739e9d7726dc32173fed2d69d17eef3c54682169e4e20ff1d0a45dcd37063cef"
[[package]] [[package]]
name = "libpso" name = "libpso"
version = "0.1.0" version = "0.1.0"
source = "git+http://git.sharnoth.com/jake/libpso#e71b435ea3dde01a44abf0492bfab12236b1ec06"
source = "git+http://git.sharnoth.com/jake/libpso#05222bbf9fe402675447bc163b45e07a327cdb1a"
dependencies = [ dependencies = [
"chrono", "chrono",
"psopacket", "psopacket",
@ -1399,7 +1399,7 @@ dependencies = [
[[package]] [[package]]
name = "psopacket" name = "psopacket"
version = "1.0.0" version = "1.0.0"
source = "git+http://git.sharnoth.com/jake/libpso#e71b435ea3dde01a44abf0492bfab12236b1ec06"
source = "git+http://git.sharnoth.com/jake/libpso#05222bbf9fe402675447bc163b45e07a327cdb1a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

66
src/entity/gateway/postgres/postgres.rs

@ -418,8 +418,7 @@ async fn add_weapon_modifier(conn: &mut sqlx::PgConnection, item_id: &ItemEntity
async fn get_character_inventory(conn: &mut sqlx::PgConnection, char_id: &CharacterEntityId) -> Result<InventoryEntity, GatewayError> async fn get_character_inventory(conn: &mut sqlx::PgConnection, char_id: &CharacterEntityId) -> Result<InventoryEntity, GatewayError>
{ {
// this is some degen shit
let conn = Arc::new(Mutex::new(conn.begin().await?));
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") let inventory = sqlx::query_as::<_, PgInventoryEntity>("select * from inventory where pchar = $1")
.bind(char_id.0) .bind(char_id.0)
.fetch_one(&mut **conn.lock().await).await?; .fetch_one(&mut **conn.lock().await).await?;
@ -442,8 +441,7 @@ async fn get_character_inventory(conn: &mut sqlx::PgConnection, char_id: &Charac
async fn get_character_bank(conn: &mut sqlx::PgConnection, char_id: &CharacterEntityId, bank_identifier: &BankIdentifier) -> Result<BankEntity, GatewayError> async fn get_character_bank(conn: &mut sqlx::PgConnection, char_id: &CharacterEntityId, bank_identifier: &BankIdentifier) -> Result<BankEntity, GatewayError>
{ {
// this is some degen shit
let conn = Arc::new(Mutex::new(conn.begin().await?));
let conn = Arc::new(Mutex::new(conn.begin().await?)); // this is some degen shit
let bank = match bank_identifier { let bank = match bank_identifier {
BankIdentifier::Character => { BankIdentifier::Character => {
sqlx::query_as::<_, PgInventoryEntity>("select * from bank where pchar = $1") sqlx::query_as::<_, PgInventoryEntity>("select * from bank where pchar = $1")
@ -451,15 +449,17 @@ async fn get_character_bank(conn: &mut sqlx::PgConnection, char_id: &CharacterEn
.fetch_one(&mut **conn.lock().await).await? .fetch_one(&mut **conn.lock().await).await?
}, },
BankIdentifier::Shared(bank_name) => { BankIdentifier::Shared(bank_name) => {
todo!();
/*
sqlx::query_as::<_, PgInventoryEntity>("select shared_bank.* from shared_bank
left join player_character on shared_bank.user = player_character.user
where player_character.id = $1 and bank.name = $2")
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)
.bind(&bank_name.0) .bind(&bank_name.0)
.fetch_one(&mut **conn.lock().await).await?
*/
.fetch_optional(&mut **conn.lock().await)
.await?
.unwrap_or_else(|| PgInventoryEntity {
pchar: char_id.0 as i32,
items: sqlx::types::Json::default(),
})
} }
}; };
@ -519,21 +519,22 @@ async fn set_character_bank(conn: &mut sqlx::PgConnection, char_id: &CharacterEn
match bank_identifier { match bank_identifier {
BankIdentifier::Character => { BankIdentifier::Character => {
sqlx::query("insert into bank (pchar, items) values ($1, $2) on conflict (pchar, name) do update set items = $2")
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)
.bind(sqlx::types::Json(bank)) .bind(sqlx::types::Json(bank))
.execute(conn) .execute(conn)
.await?; .await?;
}, },
BankIdentifier::Shared(bank_name) => { BankIdentifier::Shared(bank_name) => {
// TODO!
/*
sqlx::query("insert into shared_bank (pchar, items) values ($1, $2) on conflict (pchar, name) do update set items = $2")
sqlx::query("insert into shared_bank (user_account, items, name)
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)
.bind(sqlx::types::Json(bank)) .bind(sqlx::types::Json(bank))
.bind(&bank_name.0)
.execute(conn) .execute(conn)
.await?; .await?;
*/
} }
} }
Ok(()) Ok(())
@ -569,7 +570,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> 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")
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)
.bind(meseta.0 as i32) .bind(meseta.0 as i32)
.execute(conn) .execute(conn)
@ -592,14 +593,22 @@ async fn set_bank_meseta(conn: &mut sqlx::PgConnection, char_id: &CharacterEntit
{ {
match bank_identifier { match bank_identifier {
BankIdentifier::Character => { BankIdentifier::Character => {
sqlx::query("insert into bank_meseta values ($1, '', $2) on conflict pchar do update set meseta = $2")
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)
.bind(meseta.0 as i32) .bind(meseta.0 as i32)
.execute(conn) .execute(conn)
.await?; .await?;
}, },
BankIdentifier::Shared(bank_name) => { BankIdentifier::Shared(bank_name) => {
todo!();
sqlx::query("insert into shared_bank_meseta (user_account, name, meseta)
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(&bank_name.0)
.bind(meseta.0 as i32)
.execute(conn)
.await?;
} }
} }
@ -611,18 +620,25 @@ async fn get_bank_meseta(conn: &mut sqlx::PgConnection, char_id: &CharacterEntit
#[derive(sqlx::FromRow)] #[derive(sqlx::FromRow)]
struct PgMeseta(i32); struct PgMeseta(i32);
match bank_identifier {
let meseta = match bank_identifier {
BankIdentifier::Character => { BankIdentifier::Character => {
let meseta = sqlx::query_as::<_, PgMeseta>(r#"select meseta from bank_meseta where pchar = $1"#)
sqlx::query_as::<_, PgMeseta>(r#"select meseta from bank_meseta where pchar = $1"#)
.bind(char_id.0) .bind(char_id.0)
.fetch_one(conn) .fetch_one(conn)
.await?;
Ok(Meseta(meseta.0 as u32))
.await?
}, },
BankIdentifier::Shared(bank_name) => { BankIdentifier::Shared(bank_name) => {
todo!();
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(&bank_name.0)
.fetch_optional(conn)
.await?
.unwrap_or_else(|| PgMeseta(0))
} }
}
};
Ok(Meseta(meseta.0 as u32))
} }
async fn create_trade(conn: &mut sqlx::PgConnection, char_id1: &CharacterEntityId, char_id2: &CharacterEntityId) -> Result<TradeEntity, GatewayError> async fn create_trade(conn: &mut sqlx::PgConnection, char_id1: &CharacterEntityId, char_id2: &CharacterEntityId) -> Result<TradeEntity, GatewayError>

78
src/ship/chatcommand.rs

@ -1,19 +1,89 @@
use libpso::packet::ship::PlayerChat; use libpso::packet::ship::PlayerChat;
use crate::entity::gateway::EntityGateway; use crate::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::items::state::ItemState;
use crate::entity::item::{BankName, BankIdentifier};
use crate::ship::packet::builder::message::bank_item_list;
async fn default_bank<'a, EG, T>(id: ClientId,
tokens: T,
entity_gateway: &mut EG,
clients: &Clients,
item_state: &mut ItemState)
-> Result<Vec<(ClientId, SendShipPacket)>, String>
where
EG: EntityGateway + Clone + 'static,
T: Iterator<Item = &'a str> + 'a,
{
let bank = clients
.with_mut(id, |client| {
let mut item_state = item_state.clone();
let mut entity_gateway = entity_gateway.clone();
Box::pin(async move {
item_state.load_character_bank(&mut entity_gateway, &client.character, BankIdentifier::Character).await?;
item_state.get_character_bank(&client.character).await
})
})
.await
.map_err(|err| format!("an error occured\n{:?}", err))?
.map_err(|err| format!("an error occured\n{:?}", err))?;
let bank_items_pkt = bank_item_list(&bank);
Ok(vec![(id, SendShipPacket::BankItemList(bank_items_pkt))])
}
async fn switch_bank<'a, EG, T>(id: ClientId,
mut tokens: T,
entity_gateway: &mut EG,
clients: &Clients,
item_state: &mut ItemState)
-> Result<Vec<(ClientId, SendShipPacket)>, String>
where
EG: EntityGateway + Clone + 'static,
T: Iterator<Item = &'a str> + 'a,
{
let bank_name = BankName(tokens.next().unwrap_or(&"").into());
let bank = clients
.with_mut(id, |client| {
let mut item_state = item_state.clone();
let mut entity_gateway = entity_gateway.clone();
Box::pin(async move {
item_state.load_character_bank(&mut entity_gateway, &client.character, BankIdentifier::Shared(bank_name)).await?;
item_state.get_character_bank(&client.character).await
})
})
.await
.map_err(|err| format!("an error occured\n{:?}", err))?
.map_err(|err| format!("an error occured\n{:?}", err))?;
let bank_items_pkt = bank_item_list(&bank);
Ok(vec![(id, SendShipPacket::BankItemList(bank_items_pkt))])
}
pub async fn handle_chat_command<EG>(id: ClientId, pub async fn handle_chat_command<EG>(id: ClientId,
message: PlayerChat, message: PlayerChat,
state: &mut ShipServerState<EG>) state: &mut ShipServerState<EG>)
-> Option<Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error>>
-> Option<Result<Vec<(ClientId, SendShipPacket)>, String>>
where where
EG: EntityGateway + Clone + 'static, EG: EntityGateway + Clone + 'static,
{ {
let mut tokens = message.message
.trim_start_matches("\tJ")
.trim_start_matches("\tE")
.trim_end_matches("\0")
.split_whitespace();
let cmd = tokens.next()?;
match cmd {
"/bank" => Some(default_bank(id, tokens, &mut state.entity_gateway, &state.clients, &mut state.item_state).await),
"/sbank" => Some(switch_bank(id, tokens, &mut state.entity_gateway, &state.clients, &mut state.item_state).await),
_ => None,
}
None
} }

2
src/ship/client.rs

@ -137,7 +137,6 @@ pub struct ClientState {
pub tek: Option<(items::ClientItemId, item::weapon::TekSpecialModifier, item::weapon::TekPercentModifier, i32)>, pub tek: Option<(items::ClientItemId, item::weapon::TekSpecialModifier, item::weapon::TekPercentModifier, i32)>,
pub character_playtime: chrono::Duration, pub character_playtime: chrono::Duration,
pub log_on_time: chrono::DateTime<chrono::Utc>, pub log_on_time: chrono::DateTime<chrono::Utc>,
pub current_bank: item::BankIdentifier,
} }
impl ClientState { impl ClientState {
@ -161,7 +160,6 @@ impl ClientState {
tek: None, tek: None,
character_playtime, character_playtime,
log_on_time: chrono::Utc::now(), log_on_time: chrono::Utc::now(),
current_bank: item::BankIdentifier::Character,
} }
} }

6
src/ship/items/actions.rs

@ -614,7 +614,8 @@ where
tool, tool,
}) })
}; };
inventory.add_item(inventory_item)?.1
inventory.add_item(inventory_item.clone())
.with_context(|| format!("inventory {inventory:?}\nitem {inventory_item:?}"))?.1
}, },
item_detail => { item_detail => {
let item_entity = transaction.gateway().create_item(NewItemEntity { let item_entity = transaction.gateway().create_item(NewItemEntity {
@ -631,7 +632,8 @@ where
item: item_detail, item: item_detail,
}) })
}; };
inventory.add_item(inventory_item)?.1
inventory.add_item(inventory_item.clone())
.with_context(|| format!("inventory {inventory:?}\nitem {inventory_item:?}"))?.1
}, },
}; };

11
src/ship/ship.rs

@ -291,6 +291,7 @@ pub enum SendShipPacket {
CancelTrade(CancelTrade), CancelTrade(CancelTrade),
TradeSuccessful(TradeSuccessful), TradeSuccessful(TradeSuccessful),
LobbyEvent(LobbyEvent), LobbyEvent(LobbyEvent),
LargeDialog(LargeDialog),
} }
impl SendServerPacket for SendShipPacket { impl SendServerPacket for SendShipPacket {
@ -334,6 +335,7 @@ impl SendServerPacket for SendShipPacket {
SendShipPacket::CancelTrade(pkt) => pkt.as_bytes(), SendShipPacket::CancelTrade(pkt) => pkt.as_bytes(),
SendShipPacket::TradeSuccessful(pkt) => pkt.as_bytes(), SendShipPacket::TradeSuccessful(pkt) => pkt.as_bytes(),
SendShipPacket::LobbyEvent(pkt) => pkt.as_bytes(), SendShipPacket::LobbyEvent(pkt) => pkt.as_bytes(),
SendShipPacket::LargeDialog(pkt) => pkt.as_bytes(),
} }
} }
} }
@ -496,10 +498,10 @@ impl Blocks {
#[derive(Clone)] #[derive(Clone)]
pub struct ShipServerState<EG: EntityGateway + Clone + 'static> { pub struct ShipServerState<EG: EntityGateway + Clone + 'static> {
entity_gateway: EG,
pub(crate) entity_gateway: EG,
pub clients: Clients, pub clients: Clients,
name: String, name: String,
item_state: items::state::ItemState,
pub(crate) item_state: items::state::ItemState,
shops: ItemShops, shops: ItemShops,
pub blocks: Blocks, pub blocks: Blocks,
event: ShipEvent, event: ShipEvent,
@ -736,7 +738,10 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
RecvShipPacket::PlayerChat(msg) => { RecvShipPacket::PlayerChat(msg) => {
match chatcommand::handle_chat_command(id, msg.clone(), &mut self).await { match chatcommand::handle_chat_command(id, msg.clone(), &mut self).await {
Some(ccmd) => { Some(ccmd) => {
ccmd?
match ccmd {
Ok(pkts) => pkts,
Err(msg) => vec![(id, SendShipPacket::LargeDialog(LargeDialog::new(msg)))]
}
}, },
None => { None => {
let block = self.blocks.get_from_client(id, &self.clients).await?; let block = self.blocks.get_from_client(id, &self.clients).await?;

Loading…
Cancel
Save