From e4ef8a3c36668a694bd741fa04b6e0f53b0e3537 Mon Sep 17 00:00:00 2001 From: Nobody Date: Tue, 29 Mar 2022 23:35:33 +0500 Subject: [PATCH] Implement (almost) proper shopping: now you can buy stuff (but not pay for it yet) --- src/server/game_server.rs | 8 +++++--- src/subsystems/misc/shop.rs | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/server/game_server.rs b/src/server/game_server.rs index 568eb2f..2fe0a4b 100644 --- a/src/server/game_server.rs +++ b/src/server/game_server.rs @@ -12,7 +12,7 @@ use crate::JsonManager; use crate::LuaManager; use crate::server::LoginManager; use std::sync::Arc; -use crate::subsystems::{NpcSubsystem, ShopSubsystem}; +use crate::subsystems::{InventorySubsystem, NpcSubsystem, ShopSubsystem}; use crate::subsystems::misc::{PauseSubsystem, SceneSubsystem, SocialSubsystem}; pub struct GameServer { @@ -27,14 +27,16 @@ pub struct GameServer { impl GameServer { pub fn new(packets_to_process_rx: mpsc::Receiver, packets_to_send_tx: mpsc::Sender) -> GameServer { - let db = Arc::new(DatabaseManager::new("sqlite://./database.db3")); let jm = Arc::new(JsonManager::new("./data/json")); + let db = Arc::new(DatabaseManager::new("sqlite://./database.db3", jm.clone())); let lm = LoginManager::new(db.clone(), jm.clone(), packets_to_send_tx.clone()); let lum = Arc::new(LuaManager::new("./data/lua")); + let inv = Arc::new(InventorySubsystem::new(jm.clone(), db.clone(), packets_to_send_tx.clone())); + let em = EntitySubsystem::new(lum.clone(), jm.clone(), db.clone(), packets_to_send_tx.clone()); let nt = NpcSubsystem::new(packets_to_send_tx.clone()); - let ss = ShopSubsystem::new(jm.clone(), db.clone(), packets_to_send_tx.clone()); + let ss = ShopSubsystem::new(jm.clone(), db.clone(), inv.clone(), packets_to_send_tx.clone()); let scs = SceneSubsystem::new(packets_to_send_tx.clone()); let ps = PauseSubsystem::new(packets_to_send_tx.clone()); let socs = SocialSubsystem::new(db.clone(), packets_to_send_tx.clone()); diff --git a/src/subsystems/misc/shop.rs b/src/subsystems/misc/shop.rs index 11611ed..a79e8c7 100644 --- a/src/subsystems/misc/shop.rs +++ b/src/subsystems/misc/shop.rs @@ -15,6 +15,7 @@ use packet_processor_macro::*; use packet_processor::*; use serde_json::de::Read; use crate::{DatabaseManager, JsonManager, LuaManager}; +use crate::subsystems::InventorySubsystem; use crate::utils::{IdManager, TimeManager}; #[packet_processor( @@ -25,15 +26,17 @@ pub struct ShopSubsystem { packets_to_send_tx: Sender, json_manager: Arc, db_manager: Arc, + inventory: Arc, } impl ShopSubsystem { - pub fn new(jm: Arc, db: Arc, packets_to_send_tx: Sender) -> Self { + pub fn new(jm: Arc, db: Arc, inv: Arc, packets_to_send_tx: Sender) -> Self { let mut ss = Self { packets_to_send_tx: packets_to_send_tx, packet_callbacks: HashMap::new(), json_manager: jm.clone(), db_manager: db.clone(), + inventory: inv.clone(), }; ss.register(); @@ -113,7 +116,39 @@ impl ShopSubsystem { } fn process_buy_goods(&self, user_id: u32, metadata: &proto::PacketHead, req: &proto::BuyGoodsReq, rsp: &mut proto::BuyGoodsRsp) { + // Buying goods can produce the following packets: + // 1) Response packet + // 2) AddHintNotify (to show nice graphical image to user) + // 3) StoreItemChangeNotify for this particular item + // 4) StoreItemChangeNotify/StoreItemDelNotify depending on the currency used + // TODO: client performs checks on it's side to make sure player don't buy extra or have enough currency; + // but it's a good idea to check everything too + // Also, we don't have any 'state' yet, so we never gonna run "out of stock" + + // Retrieve goods in question + let mut good = req.goods.clone().unwrap(); + + good.bought_num = req.buy_count; + + // First, confirm buying goods + // TODO: in all the packets I've seen so far goods_list only contains one item identical to goods field. Is this always the case? + rsp.shop_type = req.shop_type; + rsp.buy_count = req.buy_count; + rsp.goods = Some(good.clone()); + rsp.goods_list = vec![good.clone()]; + + let goods_item = good.goods_item.as_ref().unwrap(); + + let total_count = goods_item.count * req.buy_count; + + // Ok, now add item to user's inventory and show nice graphical hint + self.inventory.add_item(user_id, metadata, goods_item.item_id, total_count, &proto::ActionReasonType::ActionReasonShop, true); + + // Tell the client to update / delete currency used + + // TODO! + //self.inventory.sub_item(user_id, metadata, good.goods_item.as_ref().unwrap().item_id, req.buy_count, &proto::ActionReasonType::ActionReasonShop); } fn get_shop_refresh_time(&self, shop_type: u32, item_id: u32) -> u32 {