mirror of
https://github.com/redstrate/Kawari.git
synced 2025-05-04 03:57:45 +00:00
Commit and restore inventory from the World databse
This commit is contained in:
parent
fed21b3617
commit
b1653f0808
4 changed files with 60 additions and 29 deletions
|
@ -19,11 +19,11 @@ use kawari::world::ipc::{
|
|||
ServerZoneIpcData, ServerZoneIpcSegment, SocialListRequestType,
|
||||
};
|
||||
use kawari::world::{
|
||||
Actor, ClientHandle, ClientId, EffectsBuilder, FromServer, LuaPlayer, PlayerData, ServerHandle,
|
||||
StatusEffects, ToServer, WorldDatabase,
|
||||
Actor, ClientHandle, ClientId, EffectsBuilder, FromServer, Inventory, LuaPlayer, PlayerData,
|
||||
ServerHandle, StatusEffects, ToServer, WorldDatabase,
|
||||
};
|
||||
use kawari::world::{
|
||||
ChatHandler, Inventory, Zone, ZoneConnection,
|
||||
ChatHandler, Zone, ZoneConnection,
|
||||
ipc::{
|
||||
ActorControlCategory, ActorControlSelf, PlayerEntry, PlayerSetup, PlayerSpawn, PlayerStats,
|
||||
SocialList,
|
||||
|
@ -276,12 +276,6 @@ async fn client_loop(
|
|||
let chara_details =
|
||||
database.find_chara_make(connection.player_data.content_id);
|
||||
|
||||
// fill inventory
|
||||
connection.inventory.equip_racial_items(
|
||||
chara_details.chara_make.customize.race,
|
||||
chara_details.chara_make.customize.gender,
|
||||
);
|
||||
|
||||
// Send inventory
|
||||
connection.send_inventory(false).await;
|
||||
|
||||
|
@ -389,7 +383,7 @@ async fn client_loop(
|
|||
let ipc;
|
||||
{
|
||||
let mut game_data = game_data.lock().unwrap();
|
||||
let equipped = &connection.inventory.equipped;
|
||||
let equipped = &connection.player_data.inventory.equipped;
|
||||
|
||||
ipc = ServerZoneIpcSegment {
|
||||
op_code: ServerZoneIpcType::PlayerSpawn,
|
||||
|
@ -656,8 +650,8 @@ async fn client_loop(
|
|||
})
|
||||
.await,
|
||||
GameMasterCommandType::GiveItem => {
|
||||
connection.inventory.extra_slot.id = *arg;
|
||||
connection.inventory.extra_slot.quantity = 1;
|
||||
connection.player_data.inventory.extra_slot.id = *arg;
|
||||
connection.player_data.inventory.extra_slot.quantity = 1;
|
||||
connection.send_inventory(false).await;
|
||||
}
|
||||
}
|
||||
|
@ -821,7 +815,7 @@ async fn client_loop(
|
|||
ClientZoneIpcData::InventoryModify(action) => {
|
||||
tracing::info!("Client is modifying inventory! {action:#?}");
|
||||
|
||||
connection.inventory.process_action(&action);
|
||||
connection.player_data.inventory.process_action(&action);
|
||||
connection.send_inventory(true).await;
|
||||
}
|
||||
}
|
||||
|
@ -857,11 +851,20 @@ async fn client_loop(
|
|||
game_data.get_citystate(chara_make.classjob_id as u16);
|
||||
}
|
||||
|
||||
let mut inventory = Inventory::new();
|
||||
|
||||
// fill inventory
|
||||
inventory.equip_racial_items(
|
||||
chara_make.customize.race,
|
||||
chara_make.customize.gender,
|
||||
);
|
||||
|
||||
let (content_id, actor_id) = database.create_player_data(
|
||||
name,
|
||||
chara_make_json,
|
||||
city_state,
|
||||
determine_initial_starting_zone(city_state),
|
||||
inventory
|
||||
);
|
||||
|
||||
tracing::info!("Created new player: {content_id} {actor_id}");
|
||||
|
@ -1117,7 +1120,6 @@ async fn main() {
|
|||
player_data: PlayerData::default(),
|
||||
spawn_index: 0,
|
||||
zone: None,
|
||||
inventory: Inventory::new(),
|
||||
status_effects: StatusEffects::default(),
|
||||
event: None,
|
||||
actors: Vec::new(),
|
||||
|
|
|
@ -47,6 +47,7 @@ pub struct PlayerData {
|
|||
/// In radians.
|
||||
pub rotation: f32,
|
||||
pub zone_id: u16,
|
||||
pub inventory: Inventory,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
|
@ -128,7 +129,6 @@ pub struct ZoneConnection {
|
|||
pub zone: Option<Zone>,
|
||||
pub spawn_index: u8,
|
||||
|
||||
pub inventory: Inventory,
|
||||
pub status_effects: StatusEffects,
|
||||
|
||||
pub event: Option<Event>,
|
||||
|
@ -450,7 +450,7 @@ impl ZoneConnection {
|
|||
pub async fn send_inventory(&mut self, send_appearance_update: bool) {
|
||||
// page 1
|
||||
{
|
||||
let extra_slot = self.inventory.extra_slot;
|
||||
let extra_slot = self.player_data.inventory.extra_slot;
|
||||
|
||||
let mut send_slot = async |slot_index: u16, item: &Item| {
|
||||
let ipc = ServerZoneIpcSegment {
|
||||
|
@ -480,7 +480,7 @@ impl ZoneConnection {
|
|||
|
||||
// equipped
|
||||
{
|
||||
let equipped = self.inventory.equipped;
|
||||
let equipped = self.player_data.inventory.equipped;
|
||||
|
||||
let mut send_slot = async |slot_index: u16, item: &Item| {
|
||||
let ipc = ServerZoneIpcSegment {
|
||||
|
@ -548,7 +548,7 @@ impl ZoneConnection {
|
|||
timestamp: timestamp_secs(),
|
||||
data: ServerZoneIpcData::ContainerInfo(ContainerInfo {
|
||||
container: ContainerType::Equipped,
|
||||
num_items: self.inventory.equipped.num_items(),
|
||||
num_items: self.player_data.inventory.equipped.num_items(),
|
||||
sequence: 1,
|
||||
..Default::default()
|
||||
}),
|
||||
|
@ -568,7 +568,7 @@ impl ZoneConnection {
|
|||
let ipc;
|
||||
{
|
||||
let mut game_data = self.gamedata.lock().unwrap();
|
||||
let equipped = &self.inventory.equipped;
|
||||
let equipped = &self.player_data.inventory.equipped;
|
||||
|
||||
ipc = ServerZoneIpcSegment {
|
||||
op_code: ServerZoneIpcType::Equip,
|
||||
|
|
|
@ -11,7 +11,7 @@ use crate::{
|
|||
},
|
||||
};
|
||||
|
||||
use super::PlayerData;
|
||||
use super::{Inventory, PlayerData};
|
||||
|
||||
pub struct WorldDatabase {
|
||||
connection: Mutex<Connection>,
|
||||
|
@ -43,7 +43,7 @@ impl WorldDatabase {
|
|||
|
||||
// Create characters data table
|
||||
{
|
||||
let query = "CREATE TABLE IF NOT EXISTS character_data (content_id INTEGER PRIMARY KEY, name STRING, chara_make STRING, city_state INTEGER, zone_id INTEGER, pos_x REAL, pos_y REAL, pos_z REAL, rotation REAL);";
|
||||
let query = "CREATE TABLE IF NOT EXISTS character_data (content_id INTEGER PRIMARY KEY, name STRING, chara_make STRING, city_state INTEGER, zone_id INTEGER, pos_x REAL, pos_y REAL, pos_z REAL, rotation REAL, inventory STRING);";
|
||||
connection.execute(query, ()).unwrap();
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,14 @@ impl WorldDatabase {
|
|||
};
|
||||
|
||||
// TODO: extract city-state
|
||||
self.create_player_data(&character.name, &chara_make.to_json(), 2, 132);
|
||||
// TODO: import inventory
|
||||
self.create_player_data(
|
||||
&character.name,
|
||||
&chara_make.to_json(),
|
||||
2,
|
||||
132,
|
||||
Inventory::new(),
|
||||
);
|
||||
|
||||
tracing::info!("{} added to the world!", character.name);
|
||||
}
|
||||
|
@ -127,9 +134,16 @@ impl WorldDatabase {
|
|||
.unwrap();
|
||||
|
||||
stmt = connection
|
||||
.prepare("SELECT pos_x, pos_y, pos_z, rotation, zone_id FROM character_data WHERE content_id = ?1")
|
||||
.prepare("SELECT pos_x, pos_y, pos_z, rotation, zone_id, inventory FROM character_data WHERE content_id = ?1")
|
||||
.unwrap();
|
||||
let (pos_x, pos_y, pos_z, rotation, zone_id) = stmt
|
||||
let (pos_x, pos_y, pos_z, rotation, zone_id, inventory_json): (
|
||||
f32,
|
||||
f32,
|
||||
f32,
|
||||
f32,
|
||||
u16,
|
||||
String,
|
||||
) = stmt
|
||||
.query_row((content_id,), |row| {
|
||||
Ok((
|
||||
row.get(0)?,
|
||||
|
@ -137,10 +151,13 @@ impl WorldDatabase {
|
|||
row.get(2)?,
|
||||
row.get(3)?,
|
||||
row.get(4)?,
|
||||
row.get(5)?,
|
||||
))
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let inventory = serde_json::from_str(&inventory_json).unwrap();
|
||||
|
||||
PlayerData {
|
||||
actor_id,
|
||||
content_id,
|
||||
|
@ -152,6 +169,7 @@ impl WorldDatabase {
|
|||
},
|
||||
rotation,
|
||||
zone_id,
|
||||
inventory,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +179,7 @@ impl WorldDatabase {
|
|||
let connection = self.connection.lock().unwrap();
|
||||
|
||||
let mut stmt = connection
|
||||
.prepare("UPDATE character_data SET zone_id=?1, pos_x=?2, pos_y=?3, pos_z=?4, rotation=?5 WHERE content_id = ?6")
|
||||
.prepare("UPDATE character_data SET zone_id=?1, pos_x=?2, pos_y=?3, pos_z=?4, rotation=?5, inventory=?6 WHERE content_id = ?7")
|
||||
.unwrap();
|
||||
stmt.execute((
|
||||
data.zone_id,
|
||||
|
@ -169,6 +187,7 @@ impl WorldDatabase {
|
|||
data.position.y,
|
||||
data.position.z,
|
||||
data.rotation,
|
||||
serde_json::to_string(&data.inventory).unwrap(),
|
||||
data.content_id,
|
||||
))
|
||||
.unwrap();
|
||||
|
@ -293,6 +312,7 @@ impl WorldDatabase {
|
|||
chara_make: &str,
|
||||
city_state: u8,
|
||||
zone_id: u16,
|
||||
inventory: Inventory,
|
||||
) -> (u64, u32) {
|
||||
let content_id = Self::generate_content_id();
|
||||
let actor_id = Self::generate_actor_id();
|
||||
|
@ -310,8 +330,15 @@ impl WorldDatabase {
|
|||
// insert char data
|
||||
connection
|
||||
.execute(
|
||||
"INSERT INTO character_data VALUES (?1, ?2, ?3, ?4, ?5, 0.0, 0.0, 0.0, 0.0);",
|
||||
(content_id, name, chara_make, city_state, zone_id),
|
||||
"INSERT INTO character_data VALUES (?1, ?2, ?3, ?4, ?5, 0.0, 0.0, 0.0, 0.0, ?6);",
|
||||
(
|
||||
content_id,
|
||||
name,
|
||||
chara_make,
|
||||
city_state,
|
||||
zone_id,
|
||||
serde_json::to_string(&inventory).unwrap(),
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -2,12 +2,13 @@ use physis::{
|
|||
common::{Language, Platform},
|
||||
gamedata::GameData,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::config::get_config;
|
||||
|
||||
use super::ipc::{ContainerType, InventoryModify};
|
||||
|
||||
#[derive(Default, Copy, Clone)]
|
||||
#[derive(Default, Copy, Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct Item {
|
||||
pub quantity: u32,
|
||||
pub id: u32,
|
||||
|
@ -19,7 +20,7 @@ impl Item {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Copy)]
|
||||
#[derive(Default, Clone, Copy, Deserialize, Serialize, Debug)]
|
||||
pub struct EquippedContainer {
|
||||
pub main_hand: Item,
|
||||
pub off_hand: Item,
|
||||
|
@ -73,6 +74,7 @@ impl EquippedContainer {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
|
||||
pub struct Inventory {
|
||||
pub equipped: EquippedContainer,
|
||||
pub extra_slot: Item, // WIP for inventory pages
|
||||
|
|
Loading…
Add table
Reference in a new issue