keep track of item slots without having 74894794793 inventory locations
This commit is contained in:
parent
bfa3a93bd6
commit
4caaee880a
@ -74,6 +74,11 @@ create table item_location (
|
||||
created_at timestamptz default current_timestamp not null
|
||||
);
|
||||
|
||||
create table inventory_slots (
|
||||
pchar integer references player_character not null,
|
||||
items integer[30] /* references item (id) */
|
||||
);
|
||||
|
||||
create table weapon_modifier (
|
||||
weapon integer references item (id) not null,
|
||||
modifier jsonb not null,
|
||||
|
@ -182,7 +182,7 @@ impl From<SectionID> for PgSectionId {
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
pub struct PgCharacter {
|
||||
id: i32,
|
||||
pub id: i32,
|
||||
user_account: i32,
|
||||
pub slot: i16,
|
||||
name: String,
|
||||
@ -569,6 +569,7 @@ pub struct PgItem {
|
||||
pub enum PgItemLocationDetail {
|
||||
Inventory {
|
||||
character_id: u32,
|
||||
#[serde(skip_serializing)]
|
||||
slot: usize,
|
||||
equipped: bool,
|
||||
},
|
||||
|
@ -204,6 +204,10 @@ impl EntityGateway for PostgresGateway {
|
||||
.bind(char.meseta as i32)
|
||||
.bind(char.bank_meseta as i32)
|
||||
.fetch_one(&self.pool).await.unwrap();
|
||||
|
||||
sqlx::query("insert into inventory_slots (pchar) values ($1)")
|
||||
.bind(character.id)
|
||||
.execute(&self.pool).await.unwrap();
|
||||
Some(character.into())
|
||||
}
|
||||
|
||||
@ -273,10 +277,35 @@ impl EntityGateway for PostgresGateway {
|
||||
let new_item = sqlx::query_as::<_, PgItem>("insert into item (item) values ($1) returning *;")
|
||||
.bind(sqlx::types::Json(PgItemDetail::from(item.item)))
|
||||
.fetch_one(&self.pool).await.unwrap();
|
||||
let location = sqlx::query_as::<_, PgItemLocation>("insert into item_location (item, location) values ($1, $2) returning *;")
|
||||
.bind(new_item.id)
|
||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item.location)))
|
||||
.fetch_one(&self.pool).await.unwrap();
|
||||
let location = if let ItemLocation::Inventory{character_id, slot, ..} = &item.location {
|
||||
sqlx::query("insert into item_location (item, location) values ($1, $2)")
|
||||
.bind(new_item.id)
|
||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item.location.clone())))
|
||||
.execute(&self.pool).await.unwrap();
|
||||
sqlx::query("update inventory_slots set items[$2] = $1 where pchar = $3")
|
||||
.bind(new_item.id)
|
||||
.bind(*slot as i32)
|
||||
.bind(character_id.0 as i32)
|
||||
.execute(&self.pool).await.unwrap();
|
||||
sqlx::query_as::<_, PgItemLocation>(r#"select
|
||||
item_location.item,
|
||||
jsonb_set(item_location.location, '{Inventory,slot}', (array_position(inventory_slots.items, item.id))::text::jsonb) as location,
|
||||
item_location.created_at
|
||||
from item_location
|
||||
join item on item.id = item_location.item
|
||||
join inventory_slots on inventory_slots.pchar = cast (item_location.location -> 'Inventory' ->> 'character_id' as integer)
|
||||
where item.id = $1
|
||||
order by item_location.created_at
|
||||
limit 1"#)
|
||||
.bind(new_item.id)
|
||||
.fetch_one(&self.pool).await.unwrap()
|
||||
}
|
||||
else {
|
||||
sqlx::query_as::<_, PgItemLocation>("insert into item_location (item, location) values ($1, $2) returning *")
|
||||
.bind(new_item.id)
|
||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item.location)))
|
||||
.fetch_one(&self.pool).await.unwrap()
|
||||
};
|
||||
Some(ItemEntity {
|
||||
id: ItemEntityId(new_item.id as u32),
|
||||
item: new_item.item.0.into(),
|
||||
@ -285,10 +314,30 @@ impl EntityGateway for PostgresGateway {
|
||||
}
|
||||
|
||||
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) {
|
||||
sqlx::query("insert into item_location (item, location) values ($1, $2);")
|
||||
.bind(item_id.0)
|
||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item_location)))
|
||||
.execute(&self.pool).await.unwrap();
|
||||
if let ItemLocation::Inventory{character_id, slot, ..} = &item_location {
|
||||
sqlx::query("update inventory_slots set items[array_position(items, $1)] = null where pchar = $2 and items[array_position(items, $1)] is not null")
|
||||
.bind(item_id.0 as i32)
|
||||
.bind(character_id.0 as i32)
|
||||
.execute(&self.pool).await.unwrap();
|
||||
sqlx::query("update inventory_slots set items[$2] = $1 where pchar = $3")
|
||||
.bind(item_id.0 as i32)
|
||||
.bind(*slot as i32)
|
||||
.bind(character_id.0 as i32)
|
||||
.execute(&self.pool).await.unwrap();
|
||||
sqlx::query(r#"insert into item_location (item, location)
|
||||
select $1, $2
|
||||
where (select jsonb_object_keys(location) from item_location where item=$1
|
||||
order by created_at desc limit 1) != 'Inventory'"#)
|
||||
.bind(item_id.0)
|
||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item_location)))
|
||||
.execute(&self.pool).await.unwrap();
|
||||
}
|
||||
else {
|
||||
sqlx::query("insert into item_location (item, location) values ($1, $2)")
|
||||
.bind(item_id.0)
|
||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item_location)))
|
||||
.execute(&self.pool).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) {
|
||||
@ -315,28 +364,57 @@ impl EntityGateway for PostgresGateway {
|
||||
|
||||
async fn get_items_by_character(&self, char: &CharacterEntity) -> Vec<ItemEntity> {
|
||||
let q = r#"select * from (
|
||||
select distinct on (item_location.item) item.id, item_location.location, item.item
|
||||
from item_location join item on item.id = item_location.item
|
||||
select distinct on (item_location.item)
|
||||
item.id,
|
||||
case
|
||||
when item_location.location -> 'Inventory' is not null then
|
||||
jsonb_set(item_location.location, '{Inventory,slot}', (array_position(inventory_slots.items, item.id))::text::jsonb),
|
||||
else
|
||||
item_location.location
|
||||
end location,
|
||||
item.item
|
||||
from item_location
|
||||
join item on item.id = item_location.item
|
||||
order by item_location.item, item_location.created_at desc
|
||||
) as i
|
||||
where cast (location -> 'Inventory' ->> 'character_id' as integer) = 2
|
||||
or cast (location -> 'Bank' ->> 'character_id' as integer) = 2"#;
|
||||
where cast (location -> 'Inventory' ->> 'character_id' as integer) = $1
|
||||
or cast (location -> 'Bank' ->> 'character_id' as integer) = $1"#;
|
||||
let q = r#"select * from (
|
||||
select distinct on (item_location.item)
|
||||
item.id,
|
||||
case
|
||||
when item_location.location -> 'Inventory' is not null then
|
||||
jsonb_set(item_location.location, '{Inventory,slot}', (array_position(inventory_slots.items, item.id))::text::jsonb)
|
||||
else
|
||||
item_location.location
|
||||
end,
|
||||
item.item
|
||||
from item_location
|
||||
join item on item.id = item_location.item
|
||||
join inventory_slots on inventory_slots.pchar = $1
|
||||
order by item_location.item, item_location.created_at desc
|
||||
) as i
|
||||
where cast (location -> 'Inventory' ->> 'character_id' as integer) = $1
|
||||
or cast (location -> 'Bank' ->> 'character_id' as integer) = $1
|
||||
"#;
|
||||
let items = sqlx::query_as::<_, PgItemWithLocation>(q)
|
||||
.bind(char.id.0)
|
||||
.fetch(&self.pool);
|
||||
join_all(items
|
||||
.filter_map(|item: Result<PgItemWithLocation, _>| {
|
||||
let item = item.ok()?;
|
||||
Some(ItemEntity {
|
||||
id: ItemEntityId(item.id as u32),
|
||||
item: item.item.0.into(),
|
||||
location: item.location.0.into()
|
||||
})
|
||||
})
|
||||
.map(|item: ItemEntity| {
|
||||
self.apply_item_modifications(item)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.await).await
|
||||
.filter_map(|item: Result<PgItemWithLocation, _>| {
|
||||
let item = item.ok()?;
|
||||
Some(ItemEntity {
|
||||
id: ItemEntityId(item.id as u32),
|
||||
item: item.item.0.into(),
|
||||
location: item.location.0.into()
|
||||
})
|
||||
})
|
||||
.map(|item: ItemEntity| {
|
||||
self.apply_item_modifications(item)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.await
|
||||
).await
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user