Browse Source

appease the clip

pull/80/head
jake 2 years ago
parent
commit
a6e50555de
  1. 10
      src/entity/character.rs
  2. 4
      src/entity/gateway/inmemory.rs
  3. 1
      src/entity/gateway/postgres/models.rs
  4. 2
      src/entity/item/mod.rs
  5. 2
      src/login/character.rs
  6. 34
      src/ship/character.rs
  7. 2
      src/ship/items/bank.rs
  8. 8
      src/ship/items/floor.rs
  9. 2
      src/ship/items/inventory.rs
  10. 67
      src/ship/items/manager.rs
  11. 9
      src/ship/items/transaction.rs
  12. 9
      src/ship/map/area.rs
  13. 46
      src/ship/map/enemy.rs
  14. 60
      src/ship/map/object.rs
  15. 89
      src/ship/packet/handler/trade.rs
  16. 4
      src/ship/ship.rs
  17. 10
      src/ship/shops/weapon.rs
  18. 51
      src/ship/trade.rs

10
src/entity/character.rs

@ -160,19 +160,11 @@ pub struct CharacterAppearance {
#[derive(Clone, Debug)]
pub struct TechLevel(pub u8);
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Default)]
pub struct CharacterTechniques {
pub techs: HashMap<Technique, TechLevel>
}
impl Default for CharacterTechniques {
fn default() -> CharacterTechniques {
CharacterTechniques {
techs: HashMap::new(),
}
}
}
impl CharacterTechniques {
pub fn set_tech(&mut self, tech: Technique, level: TechLevel) {
self.techs.insert(tech, TechLevel(level.0 - 1));

4
src/entity/gateway/inmemory.rs

@ -231,7 +231,7 @@ impl EntityGateway for InMemoryGateway {
Ok(new_item)
}
async fn add_item_note(&mut self, item_id: &ItemEntityId, item_note: ItemNote) -> Result<(), GatewayError> {
async fn add_item_note(&mut self, _item_id: &ItemEntityId, _item_note: ItemNote) -> Result<(), GatewayError> {
Ok(())
}
@ -324,7 +324,7 @@ impl EntityGateway for InMemoryGateway {
async fn get_character_meseta(&mut self, char_id: &CharacterEntityId) -> Result<Meseta, GatewayError> {
let mut character_meseta = self.character_meseta.lock().unwrap();
if let Some(meseta) = character_meseta.get_mut(&char_id) {
if let Some(meseta) = character_meseta.get_mut(char_id) {
Ok(*meseta)
}
else {

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

@ -1,3 +1,4 @@
#![allow(dead_code)]
use std::collections::HashMap;
use std::convert::Into;
use serde::{Serialize, Deserialize};

2
src/entity/item/mod.rs

@ -224,7 +224,7 @@ impl InventoryItemEntity {
}
}
pub fn individual<'a>(&'a self) -> Option<&'a ItemEntity> {
pub fn individual(&self) -> Option<&ItemEntity> {
match self {
InventoryItemEntity::Individual(i) => Some(i),
_ => None,

2
src/login/character.rs

@ -260,7 +260,7 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
let (monomates, monofluids) = futures::future::join_all((0..4usize).map(|_| {
let mut eg = entity_gateway.clone();
let character_id = character.id;
return async move {
async move {
let monomate = eg.create_item(
NewItemEntity {
item: ItemDetail::Tool (

34
src/ship/character.rs

@ -4,6 +4,8 @@ use crate::entity::character::CharacterEntity;
use crate::ship::items::{CharacterInventory, CharacterBank};
use crate::entity::item::Meseta;
#[derive(Default)]
pub struct CharacterBytesBuilder<'a> {
character: Option<&'a CharacterEntity>,
stats: Option<&'a CharacterStats>,
@ -11,18 +13,6 @@ pub struct CharacterBytesBuilder<'a> {
meseta: Option<Meseta>,
}
impl<'a> Default for CharacterBytesBuilder<'a> {
fn default() -> CharacterBytesBuilder<'a> {
CharacterBytesBuilder {
character: None,
stats: None,
level: None,
meseta: None,
}
}
}
impl<'a> CharacterBytesBuilder<'a> {
pub fn character(self, character: &'a CharacterEntity) -> CharacterBytesBuilder<'a> {
CharacterBytesBuilder {
@ -89,6 +79,7 @@ impl<'a> CharacterBytesBuilder<'a> {
}
#[derive(Default)]
pub struct FullCharacterBytesBuilder<'a> {
character: Option<&'a CharacterEntity>,
stats: Option<&'a CharacterStats>,
@ -103,25 +94,6 @@ pub struct FullCharacterBytesBuilder<'a> {
option_flags: Option<u32>,
}
impl<'a> Default for FullCharacterBytesBuilder<'a> {
fn default() -> FullCharacterBytesBuilder<'a> {
FullCharacterBytesBuilder {
character: None,
stats: None,
level: None,
meseta: None,
inventory: None,
bank: None,
key_config: None,
joystick_config: None,
symbol_chat: None,
tech_menu: None,
option_flags: None,
}
}
}
impl<'a> FullCharacterBytesBuilder<'a> {
pub fn character(self, character: &'a CharacterEntity) -> FullCharacterBytesBuilder<'a> {
FullCharacterBytesBuilder {

2
src/ship/items/bank.rs

@ -293,7 +293,7 @@ impl CharacterBank {
self.items.last()
}
pub fn as_bank_entity(&self, character_id: &CharacterEntityId, bank_name: &BankName) -> BankEntity {
pub fn as_bank_entity(&self, _character_id: &CharacterEntityId, _bank_name: &BankName) -> BankEntity {
BankEntity {
items: self.items.iter()
.map(|item| {

8
src/ship/items/floor.rs

@ -159,15 +159,9 @@ impl<'a> FloorItemHandle<'a> {
}
// TODO: floors should keep track of their own item_ids
#[derive(Debug)]
#[derive(Debug, Default)]
pub struct RoomFloorItems(Vec<FloorItem>);
impl Default for RoomFloorItems {
fn default() -> RoomFloorItems {
RoomFloorItems(Vec::new())
}
}
impl RoomFloorItems {
pub fn add_item(&mut self, item: FloorItem) {
self.0.push(item);

2
src/ship/items/inventory.rs

@ -897,7 +897,7 @@ impl CharacterInventory {
}
}
pub fn as_inventory_entity(&self, character_id: &CharacterEntityId) -> InventoryEntity {
pub fn as_inventory_entity(&self, _character_id: &CharacterEntityId) -> InventoryEntity {
InventoryEntity {
items: self.items.iter()
.map(|item| {

67
src/ship/items/manager.rs

@ -1,4 +1,3 @@
use log::warn;
use crate::ship::items::ClientItemId;
use std::collections::HashMap;
use std::cell::RefCell;
@ -6,7 +5,7 @@ use thiserror::Error;
use crate::entity::gateway::{EntityGateway, GatewayError};
use crate::entity::character::{CharacterEntity, CharacterEntityId, TechLevel};
use crate::entity::item::{ItemDetail, ItemNote, BankName};
use crate::entity::item::{Meseta, NewItemEntity, ItemEntity, ItemEntityId, InventoryItemEntity, BankItemEntity};
use crate::entity::item::{Meseta, NewItemEntity, ItemEntity, InventoryItemEntity, BankItemEntity};
use crate::entity::item::tool::{Tool, ToolType};
use crate::entity::item::weapon;
use crate::ship::map::MapArea;
@ -239,38 +238,36 @@ impl ItemManager {
}
pub fn get_character_bank(&self, character: &CharacterEntity) -> Result<&CharacterBank, anyhow::Error> {
Ok(self.character_bank
self.character_bank
.get(&character.id)
.ok_or(ItemManagerError::NoCharacter(character.id))?)
//.get(&BankName("".to_string()))
//.ok_or(ItemManagerError::InvalidBankName(BankName("".to_string())))?)
.ok_or_else(|| ItemManagerError::NoCharacter(character.id).into())
}
pub fn get_character_meseta(&self, character_id: &CharacterEntityId) -> Result<&Meseta, ItemManagerError> {
Ok(self.character_meseta.get(&character_id)
.ok_or(ItemManagerError::NoCharacter(*character_id))?)
self.character_meseta.get(character_id)
.ok_or(ItemManagerError::NoCharacter(*character_id))
}
pub fn get_character_meseta_mut<'a>(&'a mut self, character_id: &CharacterEntityId) -> Result<&'a mut Meseta, ItemManagerError> {
Ok(self.character_meseta.get_mut(&character_id)
.ok_or(ItemManagerError::NoCharacter(*character_id))?)
self.character_meseta.get_mut(character_id)
.ok_or(ItemManagerError::NoCharacter(*character_id))
}
pub fn get_bank_meseta(&self, character_id: &CharacterEntityId) -> Result<&Meseta, ItemManagerError> {
Ok(self.bank_meseta.get(&character_id)
.ok_or(ItemManagerError::NoCharacter(*character_id))?)
self.bank_meseta.get(character_id)
.ok_or(ItemManagerError::NoCharacter(*character_id))
}
pub fn get_bank_meseta_mut<'a>(&'a mut self, character_id: &CharacterEntityId) -> Result<&'a mut Meseta, ItemManagerError> {
Ok(self.bank_meseta.get_mut(&character_id)
.ok_or(ItemManagerError::NoCharacter(*character_id))?)
self.bank_meseta.get_mut(character_id)
.ok_or(ItemManagerError::NoCharacter(*character_id))
}
pub fn get_character_and_bank_meseta_mut<'a>(&'a mut self, character_id: &CharacterEntityId) -> Result<(&'a mut Meseta, &'a mut Meseta), ItemManagerError> {
Ok((
self.character_meseta.get_mut(&character_id)
self.character_meseta.get_mut(character_id)
.ok_or(ItemManagerError::NoCharacter(*character_id))?,
self.bank_meseta.get_mut(&character_id)
self.bank_meseta.get_mut(character_id)
.ok_or(ItemManagerError::NoCharacter(*character_id))?
))
}
@ -299,7 +296,7 @@ impl ItemManager {
pub async fn character_picks_up_item<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &mut CharacterEntity, item_id: ClientItemId)
-> Result<TriggerCreateItem, anyhow::Error> {
let it = ItemTransaction::new(&self, (character, item_id))
let it = ItemTransaction::new(self, (character, item_id))
.act(|it, (character, item_id)| -> Result<_, ItemManagerError> {
let local_floor = it.manager.character_floor.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
let inventory = it.manager.character_inventory.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
@ -310,7 +307,7 @@ impl ItemManager {
Some(floor_item) => {
it.action(Box::new(RemoveFromLocalFloor {
character_id: character.id,
item_id: item_id.clone()
item_id: *item_id
}));
floor_item
},
@ -319,12 +316,12 @@ impl ItemManager {
Some(floor_item) => {
it.action(Box::new(RemoveFromSharedFloor {
room_id: *room_id,
item_id: item_id.clone()
item_id: *item_id
}));
floor_item
},
None => {
return Err(ItemManagerError::NoSuchItemId(item_id.clone())).into()
return Err(ItemManagerError::NoSuchItemId(*item_id))
}
}
}
@ -339,7 +336,7 @@ impl ItemManager {
}))
}
else {
return Err(ItemManagerError::CouldNotAddToInventory(*item_id).into());
return Err(ItemManagerError::CouldNotAddToInventory(*item_id));
}
TriggerCreateItem::Yes
},
@ -360,14 +357,14 @@ impl ItemManager {
TriggerCreateItem::No
},
SpaceForStack::No(_) => {
return Err(ItemManagerError::CouldNotAddToInventory(*item_id).into());
return Err(ItemManagerError::CouldNotAddToInventory(*item_id));
},
}
},
FloorItem::Meseta(meseta_floor_item) => {
let character_meseta = it.manager.character_meseta.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
if character_meseta.0 >= 999999 {
return Err(ItemManagerError::CouldNotAddToInventory(*item_id).into());
return Err(ItemManagerError::CouldNotAddToInventory(*item_id));
}
it.action(Box::new(AddMesetaFloorItemToInventory {
character_id: character.id,
@ -615,7 +612,7 @@ impl ItemManager {
.ok_or(ItemManagerError::NoCharacter(character.id))?;
let item_to_deposit = inventory.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?;
let bank_item = bank.deposit_item(item_to_deposit, amount).ok_or(ItemManagerError::Idunnoman)?;
let _bank_item = bank.deposit_item(item_to_deposit, amount).ok_or(ItemManagerError::Idunnoman)?;
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
entity_gateway.set_character_bank(&character.id, &bank.as_bank_entity(&character.id, &BankName("".into())), BankName("".into())).await?;
@ -972,7 +969,7 @@ impl ItemManager {
p1: (&AreaClient, &CharacterEntity, &Vec<TradeItem>, usize),
p2: (&AreaClient, &CharacterEntity, &Vec<TradeItem>, usize))
-> Result<Vec<ItemToTrade>, anyhow::Error> {
let it = ItemTransaction::new(&self, (p1, p2, room_id))
let it = ItemTransaction::new(self, (p1, p2, room_id))
.act(|it, (p1, p2, room_id)| -> Result<_, anyhow::Error> {
let p1_inventory = it.manager.get_character_inventory(p1.1)?;
let p2_inventory = it.manager.get_character_inventory(p2.1)?;
@ -1049,27 +1046,27 @@ impl ItemManager {
})
.collect::<Result<Vec<_>, _>>()?;
let trade_items = [(p1, p2, p1_inventory, p2_inventory), (p2, p1, p2_inventory, p1_inventory)]
.map(|(src_client, dest_client, src_inventory, dest_inventory)| {
let trade_items = [(p1, p2, p1_inventory), (p2, p1, p2_inventory)]
.map(|(src_client, dest_client, src_inventory)| {
src_client.2.iter()
.map(|item| -> Option<(Option<ItemToTrade>, Box<dyn ItemAction<EG>>)> {
match item {
TradeItem::Individual(item_id) => {
let item = src_inventory.get_item_by_id(*item_id)?.individual()?;
let new_item_id = it.manager.room_item_id_counter.borrow_mut().get_mut(&room_id)?();
let new_item_id = it.manager.room_item_id_counter.borrow_mut().get_mut(room_id)?();
Some((
Some(ItemToTrade {
add_to: *dest_client.0,
remove_from: *src_client.0,
current_item_id: *item_id,
new_item_id: new_item_id,
new_item_id,
item_detail: ItemToTradeDetail::Individual(item.item.clone())
}),
Box::new(TradeIndividualItem {
src_character_id: src_client.1.id,
dest_character_id: dest_client.1.id,
current_item_id: *item_id,
new_item_id: new_item_id,
new_item_id,
}),
))
},
@ -1079,13 +1076,13 @@ impl ItemManager {
None
}
else {
let new_item_id = it.manager.room_item_id_counter.borrow_mut().get_mut(&room_id)?();
let new_item_id = it.manager.room_item_id_counter.borrow_mut().get_mut(room_id)?();
Some((
Some(ItemToTrade {
add_to: *dest_client.0,
remove_from: *src_client.0,
current_item_id: *item_id,
new_item_id: new_item_id,
new_item_id,
item_detail: ItemToTradeDetail::Stacked(item.tool, *amount)
}),
Box::new(TradeStackedItem {
@ -1093,7 +1090,7 @@ impl ItemManager {
dest_character_id: dest_client.1.id,
//item_ids: item.entity_ids.iter().cloned().take(*amount).collect(),
current_item_id: *item_id,
new_item_id: new_item_id,
new_item_id,
amount: *amount,
}),
))
@ -1125,8 +1122,8 @@ impl ItemManager {
if let [Some(p1_trades), Some(p2_trades)] = trade_items {
let (p1_item_trades, p1_item_actions): (Vec<Option<ItemToTrade>>, Vec<Box<dyn ItemAction<EG>>>) = p1_trades.into_iter().unzip();
let (p2_item_trades, p2_item_actions): (Vec<Option<ItemToTrade>>, Vec<Box<dyn ItemAction<EG>>>) = p2_trades.into_iter().unzip();
let (p1_item_trades, p1_item_actions): (Vec<_>, Vec<_>) = p1_trades.into_iter().unzip();
let (p2_item_trades, p2_item_actions): (Vec<_>, Vec<_>) = p2_trades.into_iter().unzip();
let item_trades = p1_item_trades.into_iter().flatten().chain(p2_item_trades.into_iter().flatten());
let item_actions = p1_item_actions.into_iter().chain(p2_item_actions.into_iter());

9
src/ship/items/transaction.rs

@ -1,17 +1,8 @@
use crate::entity::gateway::EntityGateway;
use thiserror::Error;
use std::borrow::Cow;
use crate::ship::items::manager::{ItemManager, ItemManagerError};
use std::collections::HashMap;
use crate::entity::character::{CharacterEntity, CharacterEntityId, TechLevel};
use crate::ship::items::bank::*;
use crate::ship::items::floor::*;
use crate::ship::items::inventory::*;
use crate::ship::items::ClientItemId;
use crate::entity::gateway::GatewayError;
use crate::ship::location::{AreaClient, RoomId};
#[derive(Error, Debug)]
pub enum TransactionCommitError {
#[error("transaction commit gateway error {0}")]

9
src/ship/map/area.rs

@ -287,18 +287,11 @@ impl MapAreaLookup {
}
#[derive(Default)]
pub struct MapAreaLookupBuilder {
map_areas: HashMap<u16, MapArea>,
}
impl Default for MapAreaLookupBuilder {
fn default() -> MapAreaLookupBuilder {
MapAreaLookupBuilder {
map_areas: HashMap::new()
}
}
}
impl MapAreaLookupBuilder {
pub fn add(mut self, value: u16, map_area: MapArea) -> MapAreaLookupBuilder {
self.map_areas.insert(value, map_area);

46
src/ship/map/enemy.rs

@ -14,17 +14,17 @@ pub struct RawMapEnemy {
id: u32,
_unknown1: u16,
pub children: u16,
map_area: u16,
_map_area: u16,
_unknown4: u16,
section: u16,
wave_idd: u16,
wave_id: u32,
x: f32,
y: f32,
z: f32,
xrot: u32,
yrot: u32,
zrot: u32,
_section: u16,
_wave_idd: u16,
_wave_id: u32,
_x: f32,
_y: f32,
_z: f32,
_xrot: u32,
_yrot: u32,
_zrot: u32,
_field1: u32,
field2: u32,
_field3: u32,
@ -40,17 +40,17 @@ impl RawMapEnemy {
id: cursor.read_u32::<LittleEndian>()?,
_unknown1: cursor.read_u16::<LittleEndian>()?,
children: cursor.read_u16::<LittleEndian>()?,
map_area: cursor.read_u16::<LittleEndian>()?,
_map_area: cursor.read_u16::<LittleEndian>()?,
_unknown4: cursor.read_u16::<LittleEndian>()?,
section: cursor.read_u16::<LittleEndian>()?,
wave_idd: cursor.read_u16::<LittleEndian>()?,
wave_id: cursor.read_u32::<LittleEndian>()?,
x: cursor.read_f32::<LittleEndian>()?,
y: cursor.read_f32::<LittleEndian>()?,
z: cursor.read_f32::<LittleEndian>()?,
xrot: cursor.read_u32::<LittleEndian>()?,
yrot: cursor.read_u32::<LittleEndian>()?,
zrot: cursor.read_u32::<LittleEndian>()?,
_section: cursor.read_u16::<LittleEndian>()?,
_wave_idd: cursor.read_u16::<LittleEndian>()?,
_wave_id: cursor.read_u32::<LittleEndian>()?,
_x: cursor.read_f32::<LittleEndian>()?,
_y: cursor.read_f32::<LittleEndian>()?,
_z: cursor.read_f32::<LittleEndian>()?,
_xrot: cursor.read_u32::<LittleEndian>()?,
_yrot: cursor.read_u32::<LittleEndian>()?,
_zrot: cursor.read_u32::<LittleEndian>()?,
_field1: cursor.read_u32::<LittleEndian>()?,
field2: cursor.read_u32::<LittleEndian>()?,
_field3: cursor.read_u32::<LittleEndian>()?,
@ -75,7 +75,7 @@ pub enum MapEnemyError {
pub struct MapEnemy {
pub monster: MonsterType,
pub map_area: MapArea,
hp: u32,
_hp: u32,
// TODO: other stats from battleparam
pub player_hit: [bool; 4],
pub dropped_item: bool,
@ -254,7 +254,7 @@ impl MapEnemy {
Ok(MapEnemy {
monster,
map_area: *map_area,
hp: 0,
_hp: 0,
dropped_item: false,
gave_exp: false,
player_hit: [false; 4],
@ -265,7 +265,7 @@ impl MapEnemy {
MapEnemy {
monster,
map_area,
hp: 0,
_hp: 0,
dropped_item: false,
gave_exp: false,
player_hit: [false; 4],

60
src/ship/map/object.rs

@ -13,50 +13,50 @@ use crate::ship::map::*;
#[derive(Debug, Copy, Clone)]
pub struct RawMapObject {
otype: u16,
unknown1: u16,
unknown2: u32,
id: u16,
group: u16,
section: u16,
unknown3: u16,
x: f32,
y: f32,
z: f32,
xrot: u32,
yrot: u32,
zrot: u32,
_unknown1: u16,
_unknown2: u32,
_id: u16,
_group: u16,
_section: u16,
_unknown3: u16,
_x: f32,
_y: f32,
_z: f32,
_xrot: u32,
_yrot: u32,
_zrot: u32,
field1: f32,
field2: f32,
field3: f32,
field4: u32,
field5: u32,
field6: u32,
field7: u32,
_field5: u32,
_field6: u32,
_field7: u32,
}
impl RawMapObject {
pub fn from_byte_stream<R: Read>(cursor: &mut R) -> Result<RawMapObject, std::io::Error> {
Ok(RawMapObject {
otype: cursor.read_u16::<LittleEndian>()?,
unknown1: cursor.read_u16::<LittleEndian>()?,
unknown2: cursor.read_u32::<LittleEndian>()?,
id: cursor.read_u16::<LittleEndian>()?,
group: cursor.read_u16::<LittleEndian>()?,
section: cursor.read_u16::<LittleEndian>()?,
unknown3: cursor.read_u16::<LittleEndian>()?,
x: cursor.read_f32::<LittleEndian>()?,
y: cursor.read_f32::<LittleEndian>()?,
z: cursor.read_f32::<LittleEndian>()?,
xrot: cursor.read_u32::<LittleEndian>()?,
yrot: cursor.read_u32::<LittleEndian>()?,
zrot: cursor.read_u32::<LittleEndian>()?,
_unknown1: cursor.read_u16::<LittleEndian>()?,
_unknown2: cursor.read_u32::<LittleEndian>()?,
_id: cursor.read_u16::<LittleEndian>()?,
_group: cursor.read_u16::<LittleEndian>()?,
_section: cursor.read_u16::<LittleEndian>()?,
_unknown3: cursor.read_u16::<LittleEndian>()?,
_x: cursor.read_f32::<LittleEndian>()?,
_y: cursor.read_f32::<LittleEndian>()?,
_z: cursor.read_f32::<LittleEndian>()?,
_xrot: cursor.read_u32::<LittleEndian>()?,
_yrot: cursor.read_u32::<LittleEndian>()?,
_zrot: cursor.read_u32::<LittleEndian>()?,
field1: cursor.read_f32::<LittleEndian>()?,
field2: cursor.read_f32::<LittleEndian>()?,
field3: cursor.read_f32::<LittleEndian>()?,
field4: cursor.read_u32::<LittleEndian>()?,
field5: cursor.read_u32::<LittleEndian>()?,
field6: cursor.read_u32::<LittleEndian>()?,
field7: cursor.read_u32::<LittleEndian>()?,
_field5: cursor.read_u32::<LittleEndian>()?,
_field6: cursor.read_u32::<LittleEndian>()?,
_field7: cursor.read_u32::<LittleEndian>()?,
})
}
}

89
src/ship/packet/handler/trade.rs

@ -1,22 +1,14 @@
use std::convert::TryInto;
use log::warn;
use rand::Rng;
use rand::seq::SliceRandom;
use libpso::packet::ship::*;
use libpso::packet::messages::*;
use crate::common::leveltable::CharacterLevelTable;
use crate::common::serverstate::ClientId;
use crate::ship::ship::{SendShipPacket, ShipError, Clients, Rooms, ItemShops};
use crate::ship::location::{ClientLocation, ClientLocationError, LocalClientId};
use crate::ship::drops::ItemDrop;
use crate::ship::items::{ItemManager, ItemManagerError, ClientItemId, TriggerCreateItem, FloorItem, FloorType, ItemToTradeDetail};
use crate::ship::ship::{SendShipPacket, ShipError, Clients};
use crate::ship::location::{ClientLocation, ClientLocationError};
use crate::ship::items::{ItemManager, ItemManagerError, ClientItemId, ItemToTradeDetail};
use crate::ship::items::inventory::InventoryItem;
use crate::ship::trade::{TradeItem, TradeState, TradeStatus};
use crate::entity::gateway::EntityGateway;
use crate::entity::item;
use libpso::utf8_to_utf16_array;
use crate::ship::packet::builder;
use crate::ship::shops::{ShopItem, ToolShopItem, ArmorShopItem};
pub const MESETA_ITEM_ID: ClientItemId = ClientItemId(0xFFFFFF01);
pub const OTHER_MESETA_ITEM_ID: ClientItemId = ClientItemId(0xFFFFFFFF);
@ -54,21 +46,18 @@ pub enum TradeError {
// TODO: remove target
pub async fn trade_request<EG>(id: ClientId,
pub async fn trade_request(id: ClientId,
trade_request: &TradeRequest,
target: u32,
entity_gateway: &mut EG,
client_location: &ClientLocation,
clients: &mut Clients,
item_manager: &mut ItemManager,
trades: &mut TradeState)
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
where
EG: EntityGateway
{
let trade_request = trade_request.clone(); // TODO: make this function take ownership of packet
match trade_request.trade {
TradeRequestCommand::Initialize(ref act, meseta) => {
TradeRequestCommand::Initialize(ref act, _meseta) => {
match act {
TradeRequestInitializeCommand::Initialize => {
if trades.in_trade(&id) {
@ -76,10 +65,9 @@ where
}
let trade_partner = client_location.get_client_neighbors(id)?
.into_iter()
.filter(|ac| {
.find(|ac| {
ac.local_client.id() == target as u8 //trade_request.client
})
.next()
.ok_or(TradeError::CouldNotFindTradePartner)?;
if trades.in_trade(&trade_partner.client) {
return Err(TradeError::OtherAlreadyInTrade.into())
@ -125,7 +113,7 @@ where
Ok(trades
.with(&id, |this, other| -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
if this.status == TradeStatus::Trading && other.status == TradeStatus::Trading {
let client = clients.get(&this.client()).ok_or(ShipError::ClientNotFound(this.client()))?;
let client = clients.get(&this.client()).ok_or_else(|| ShipError::ClientNotFound(this.client()))?;
let inventory = item_manager.get_character_inventory(&client.character)?;
if ClientItemId(item_id) == MESETA_ITEM_ID {
this.meseta += amount as usize;
@ -157,7 +145,7 @@ where
Err(TradeError::MismatchedStatus.into())
}
})?
.unwrap_or_else(|err| {
.unwrap_or_else(|_err| {
trades.remove_trade(&id);
Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
.filter(move |client| client.local_client.id() == target as u8)
@ -184,9 +172,8 @@ where
this.items.retain(|item| {
item.item_id() != ClientItemId(item_id)
})
//this.items.push(TradeItem::Individual(ClientItemId(item_id)));
},
InventoryItem::Stacked(stacked_item) => {
InventoryItem::Stacked(_stacked_item) => {
let trade_item_index = this.items.iter()
.position(|item| {
item.item_id() == ClientItemId(item_id)
@ -302,16 +289,13 @@ fn status_is_not<const N: usize>(status: &TradeStatus, statuses: &[TradeStatus;
!status_is(status, statuses)
}
pub async fn inner_items_to_trade<EG>(id: ClientId,
items_to_trade: &ItemsToTrade,
entity_gateway: &mut EG,
client_location: &ClientLocation,
clients: &mut Clients,
item_manager: &mut ItemManager,
trades: &mut TradeState)
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
where
EG: EntityGateway
pub async fn inner_items_to_trade(id: ClientId,
items_to_trade: &ItemsToTrade,
client_location: &ClientLocation,
clients: &mut Clients,
item_manager: &mut ItemManager,
trades: &mut TradeState)
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
{
Ok(trades
.with(&id, |this, other| -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
@ -319,8 +303,8 @@ where
return Err(TradeError::MismatchedStatus.into())
}
let client = clients.get(&this.client()).ok_or(ShipError::ClientNotFound(this.client()))?;
let other_client = clients.get(&other.client()).ok_or(ShipError::ClientNotFound(other.client()))?;
let client = clients.get(&this.client()).ok_or_else(|| ShipError::ClientNotFound(this.client()))?;
let other_client = clients.get(&other.client()).ok_or_else(|| ShipError::ClientNotFound(other.client()))?;
let inventory = item_manager.get_character_inventory(&client.character)?;
if items_to_trade.count as usize != (this.items.len() + (if this.meseta != 0 { 1 } else { 0 })) {
@ -355,14 +339,14 @@ where
let real_trade_item = this.items
.iter()
.find(|i| i.item_id() == ClientItemId(item.item_id))
.ok_or_else(|| TradeError::SketchyTrade)?;
.ok_or(TradeError::SketchyTrade)?;
let trade_item_bytes: [u8; 16] = item.item_data.iter()
.chain(item.item_data2.iter())
.cloned().collect::<Vec<u8>>()
.try_into()
.unwrap();
match real_item {
InventoryItem::Individual(individual_inventory_item) => {
InventoryItem::Individual(_individual_inventory_item) => {
if real_item.as_client_bytes() == trade_item_bytes {
Ok(())
}
@ -374,7 +358,7 @@ where
if real_item.as_client_bytes()[0..4] == trade_item_bytes[0..4] {
let amount = trade_item_bytes[5] as usize;
if amount <= stacked_inventory_item.entity_ids.len() {
if real_trade_item.stacked().ok_or_else(|| TradeError::SketchyTrade)?.1 == amount {
if real_trade_item.stacked().ok_or(TradeError::SketchyTrade)?.1 == amount {
Ok(())
}
else {
@ -407,7 +391,7 @@ where
})?
.unwrap_or_else(|err| {
log::warn!("trade error: {:?}", err);
let (this, other) = trades.remove_trade(&id);
let (_this, other) = trades.remove_trade(&id);
Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
.filter(move |client| other.as_ref().map(|other| client.client == other.client() ).unwrap_or_else(|| false))
.map(move |client| {
@ -417,23 +401,20 @@ where
}))
}
pub async fn items_to_trade<EG>(id: ClientId,
items_to_trade_pkt: &ItemsToTrade,
entity_gateway: &mut EG,
client_location: &ClientLocation,
clients: &mut Clients,
item_manager: &mut ItemManager,
trades: &mut TradeState)
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
where
EG: EntityGateway
pub async fn items_to_trade(id: ClientId,
items_to_trade_pkt: &ItemsToTrade,
client_location: &ClientLocation,
clients: &mut Clients,
item_manager: &mut ItemManager,
trades: &mut TradeState)
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
{
let t = inner_items_to_trade(id, items_to_trade_pkt, entity_gateway, client_location, clients, item_manager, trades).await;
let t = inner_items_to_trade(id, items_to_trade_pkt, client_location, clients, item_manager, trades).await;
match t {
Ok(p) => Ok(p),
Err(err) => {
log::warn!("atrade error: {:?}", err);
let (this, other) = trades.remove_trade(&id);
let (_this, other) = trades.remove_trade(&id);
Ok(Box::new(client_location.get_all_clients_by_client(id)?.into_iter()
.filter(move |client| other.as_ref().map(|other| client.client == other.client()).unwrap_or_else(|| false))
.map(move |client| {
@ -469,8 +450,8 @@ where
this.status = TradeStatus::TradeComplete;
if this.status == TradeStatus::TradeComplete && other.status == TradeStatus::TradeComplete {
let this_client = clients.get(&this.client()).ok_or(ShipError::ClientNotFound(this.client()))?;
let other_client = clients.get(&other.client()).ok_or(ShipError::ClientNotFound(other.client()))?;
let this_client = clients.get(&this.client()).ok_or_else(|| ShipError::ClientNotFound(this.client()))?;
let other_client = clients.get(&other.client()).ok_or_else(|| ShipError::ClientNotFound(other.client()))?;
let this_local_client = client_location.get_local_client(this.client())?;
let other_local_client = client_location.get_local_client(other.client())?;
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
@ -550,8 +531,8 @@ where
}
}
},
err @ _ => {
let (this, other) = trades.remove_trade(&id);
_ => {
let (_this, other) = trades.remove_trade(&id);
Ok(Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
.filter(move |client| other.as_ref().map(|other| client.client == other.client()).unwrap_or_else(|| false))
.map(move |client| {

4
src/ship/ship.rs

@ -556,7 +556,7 @@ impl<EG: EntityGateway> ShipServerState<EG> {
handler::direct_message::accept_tek_item(id, tek_accept, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await?
},
GameMessage::TradeRequest(trade_request) => {
handler::trade::trade_request(id, trade_request, target, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager, &mut self.trades).await?
handler::trade::trade_request(id, trade_request, target, &block.client_location, &mut self.clients, &mut self.item_manager, &mut self.trades).await?
},
_ => {
let cmsg = msg.clone();
@ -727,7 +727,7 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
},
RecvShipPacket::ItemsToTrade(items_to_trade) => {
let block = self.blocks.with_client(id, &self.clients)?;
handler::trade::items_to_trade(id, items_to_trade, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager, &mut self.trades).await?
handler::trade::items_to_trade(id, items_to_trade, &block.client_location, &mut self.clients, &mut self.item_manager, &mut self.trades).await?
},
RecvShipPacket::TradeConfirmed(_) => {
let block = self.blocks.with_client(id, &self.clients)?;

10
src/ship/shops/weapon.rs

@ -315,7 +315,7 @@ fn number_of_weapons_to_generate(character_level: usize) -> usize {
#[derive(Debug)]
pub struct WeaponShop<R: Rng + SeedableRng> {
difficulty: Difficulty,
_difficulty: Difficulty,
section_id: SectionID,
weapon: WeaponTable,
special: SpecialTable,
@ -329,7 +329,7 @@ pub struct WeaponShop<R: Rng + SeedableRng> {
impl<R: Rng + SeedableRng> WeaponShop<R> {
pub fn new(difficulty: Difficulty, section_id: SectionID) -> WeaponShop<R> {
WeaponShop {
difficulty,
_difficulty: difficulty,
section_id,
weapon: load_weapon_table(difficulty, section_id),
special: load_special_table(),
@ -358,8 +358,10 @@ impl<R: Rng + SeedableRng> WeaponShop<R> {
.last()
.unwrap();
let special_tier = WeightedIndex::new(tier.special.iter().map(|t| t.probability)).unwrap();
match special_tier.sample(&mut self.rng) {
let special_tier_choice = WeightedIndex::new(tier.special.iter().map(|t| t.probability)).unwrap();
let special_tier_index = special_tier_choice.sample(&mut self.rng);
let special_tier = tier.special.get(special_tier_index)?;
match special_tier.tier {
1 => TIER1_SPECIAL.choose(&mut self.rng).cloned(),
2 => TIER2_SPECIAL.choose(&mut self.rng).cloned(),
_ => None

51
src/ship/trade.rs

@ -1,6 +1,5 @@
use std::collections::HashMap;
use std::cell::RefCell;
use async_std::sync::{Arc, Mutex};
use crate::common::serverstate::ClientId;
use crate::ship::items;
@ -67,38 +66,6 @@ impl ClientTradeState {
}
}
/*
pub struct ClientTradeHandle<'a> {
handle: std::cell::Ref<'a, ClientTradeState>,
}
impl<'a> ClientTradeHandle<'a> {
fn new(handle: std::cell::Ref<'a, ClientTradeState>) -> ClientTradeHandle<'a> {
ClientTradeHandle {
handle: handle,
}
}
}
impl<'a> std::ops::Deref for ClientTradeHandle<'a> {
type Target = ClientTradeState;
fn deref(&self) -> &ClientTradeState {
&self.handle
}
}
impl<'a> std::ops::DerefMut for ClientTradeHandle<'a> {
fn deref_mut(&mut self) -> &mut ClientTradeState {
&mut self.handle
}
}
impl<'a> Clone for ClientTradeHandle<'a> {
}
*/
#[derive(thiserror::Error, Debug)]
#[error("")]
pub enum TradeStateError {
@ -141,7 +108,7 @@ impl TradeState {
F: Fn(&mut ClientTradeState, &mut ClientTradeState) -> T
{
let mut c1 = self.trades.get(client).ok_or_else(|| TradeStateError::ClientNotInTrade(*client))?.borrow_mut();
let mut c2 = self.trades.get(&c1.other_client).ok_or_else(|| TradeStateError::ClientNotInTrade(c1.other_client))?.borrow_mut();
let mut c2 = self.trades.get(&c1.other_client).ok_or(TradeStateError::ClientNotInTrade(c1.other_client))?.borrow_mut();
// sanity check
if c1.client != c2.other_client {
@ -150,22 +117,6 @@ impl TradeState {
Ok(func(&mut *c1, &mut *c2))
}
/*
pub fn with<T, F> (&self, client: &ClientId, func: F) -> Result<T, TradeStateError>
where
F: Fn(&mut ClientTradeHandle, &mut ClientTradeHandle) -> T
{
let c1 = ClientTradeHandle::new(self.trades.get(client).ok_or_else(|| TradeStateError::ClientNotInTrade(*client))?.borrow_mut());
let c2 = ClientTradeHandle::new(self.trades.get(&c1.other_client).ok_or_else(|| TradeStateError::ClientNotInTrade(c1.other_client))?.borrow_mut());
// sanity check
if c1.client != c2.other_client {
return Err(TradeStateError::MismatchedTrade(c1.client, c2.client));
}
Ok(func(&mut c1, &mut c2))
}
*/
// TODO: is it possible for this to not return Options?
pub fn remove_trade(&mut self, client: &ClientId) -> (Option<ClientTradeState>, Option<ClientTradeState>) {

Loading…
Cancel
Save