update
This commit is contained in:
@@ -11,7 +11,8 @@ defmodule Odinsea.Database.Context do
|
||||
import Ecto.Query
|
||||
|
||||
alias Odinsea.Repo
|
||||
alias Odinsea.Database.Schema.{Account, Character}
|
||||
alias Odinsea.Database.Schema.{Account, Character, InventoryItem}
|
||||
alias Odinsea.Game.InventoryType
|
||||
alias Odinsea.Net.Cipher.LoginCrypto
|
||||
|
||||
# ==================================================================================================
|
||||
@@ -481,4 +482,113 @@ defmodule Odinsea.Database.Context do
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
# ==================================================================================================
|
||||
# Inventory Operations
|
||||
# ==================================================================================================
|
||||
|
||||
@doc """
|
||||
Loads all inventory items for a character.
|
||||
Returns a map of inventory types to lists of items.
|
||||
|
||||
Ported from ItemLoader.java
|
||||
"""
|
||||
def load_character_inventory(character_id) do
|
||||
items =
|
||||
InventoryItem
|
||||
|> where([i], i.characterid == ^character_id)
|
||||
|> Repo.all()
|
||||
|
||||
# Group by inventory type
|
||||
items
|
||||
|> Enum.map(&InventoryItem.to_game_item/1)
|
||||
|> Enum.group_by(fn item ->
|
||||
db_item = Enum.find(items, fn db -> db.inventoryitemid == item.id end)
|
||||
InventoryType.from_type(db_item.inventorytype)
|
||||
end)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets items for a specific inventory type.
|
||||
"""
|
||||
def get_inventory_items(character_id, inv_type) do
|
||||
type_value = InventoryType.type_value(inv_type)
|
||||
|
||||
InventoryItem
|
||||
|> where([i], i.characterid == ^character_id and i.inventorytype == ^type_value)
|
||||
|> Repo.all()
|
||||
|> Enum.map(&InventoryItem.to_game_item/1)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single inventory item by ID.
|
||||
"""
|
||||
def get_inventory_item(item_id) do
|
||||
case Repo.get(InventoryItem, item_id) do
|
||||
nil -> nil
|
||||
db_item -> InventoryItem.to_game_item(db_item)
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Creates a new inventory item.
|
||||
"""
|
||||
def create_inventory_item(character_id, inv_type, item) do
|
||||
attrs = InventoryItem.from_game_item(item, character_id, inv_type)
|
||||
|
||||
%InventoryItem{}
|
||||
|> InventoryItem.changeset(attrs)
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates an existing inventory item.
|
||||
"""
|
||||
def update_inventory_item(item_id, updates) do
|
||||
case Repo.get(InventoryItem, item_id) do
|
||||
nil -> {:error, :not_found}
|
||||
db_item ->
|
||||
db_item
|
||||
|> InventoryItem.changeset(updates)
|
||||
|> Repo.update()
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes an inventory item.
|
||||
"""
|
||||
def delete_inventory_item(item_id) do
|
||||
Repo.delete_all(from(i in InventoryItem, where: i.inventoryitemid == ^item_id))
|
||||
end
|
||||
|
||||
@doc """
|
||||
Saves all inventory items for a character.
|
||||
Used during character save.
|
||||
"""
|
||||
def save_character_inventory(character_id, inventories) do
|
||||
Enum.each(inventories, fn {inv_type, inventory} ->
|
||||
Enum.each(inventory.items, fn {_pos, item} ->
|
||||
attrs = InventoryItem.from_game_item(item, character_id, inv_type)
|
||||
|
||||
if item.id do
|
||||
# Update existing
|
||||
update_inventory_item(item.id, attrs)
|
||||
else
|
||||
# Insert new
|
||||
create_inventory_item(character_id, inv_type, item)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets the count of items for a character.
|
||||
"""
|
||||
def count_inventory_items(character_id) do
|
||||
InventoryItem
|
||||
|> where([i], i.characterid == ^character_id)
|
||||
|> Repo.aggregate(:count, :inventoryitemid)
|
||||
end
|
||||
end
|
||||
|
||||
238
lib/odinsea/database/schema/inventory_item.ex
Normal file
238
lib/odinsea/database/schema/inventory_item.ex
Normal file
@@ -0,0 +1,238 @@
|
||||
defmodule Odinsea.Database.Schema.InventoryItem do
|
||||
@moduledoc """
|
||||
Ecto schema for the inventoryitems table.
|
||||
Stores all items for all characters.
|
||||
"""
|
||||
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:inventoryitemid, :integer, autogenerate: false}
|
||||
schema "inventoryitems" do
|
||||
field :characterid, :integer
|
||||
field :itemid, :integer
|
||||
field :inventorytype, :integer
|
||||
field :position, :integer
|
||||
field :quantity, :integer
|
||||
field :owner, :string, default: ""
|
||||
field :petid, :integer, default: -1
|
||||
field :flag, :integer, default: 0
|
||||
field :expiration, :integer, default: -1
|
||||
field :gift_from, :string, source: :giftFrom, default: ""
|
||||
field :uniqueid, :integer, default: -1
|
||||
|
||||
# Equipment-specific fields (stored in the same table)
|
||||
field :upgradeslots, :integer, default: 0
|
||||
field :level, :integer, default: 0
|
||||
field :str, :integer, default: 0
|
||||
field :dex, :integer, default: 0
|
||||
field :int, :integer, default: 0
|
||||
field :luk, :integer, default: 0
|
||||
field :hp, :integer, default: 0
|
||||
field :mp, :integer, default: 0
|
||||
field :watk, :integer, default: 0
|
||||
field :matk, :integer, default: 0
|
||||
field :wdef, :integer, default: 0
|
||||
field :mdef, :integer, default: 0
|
||||
field :acc, :integer, default: 0
|
||||
field :avoid, :integer, default: 0
|
||||
field :hands, :integer, default: 0
|
||||
field :speed, :integer, default: 0
|
||||
field :jump, :integer, default: 0
|
||||
field :locked, :integer, default: 0
|
||||
field :vicioushammer, :integer, default: 0
|
||||
field :itemexp, :integer, default: 0
|
||||
field :durability, :integer, default: -1
|
||||
field :enhance, :integer, default: 0
|
||||
field :potential1, :integer, default: 0
|
||||
field :potential2, :integer, default: 0
|
||||
field :potential3, :integer, default: 0
|
||||
field :hp_r, :integer, source: :hpR, default: 0
|
||||
field :mp_r, :integer, source: :mpR, default: 0
|
||||
field :incskill, :integer, default: -1
|
||||
field :charmexp, :integer, default: -1
|
||||
field :pvpdamage, :integer, default: 0
|
||||
end
|
||||
|
||||
@doc """
|
||||
Changeset for creating a new inventory item.
|
||||
"""
|
||||
def changeset(item, attrs) do
|
||||
item
|
||||
|> cast(attrs, [
|
||||
:inventoryitemid,
|
||||
:characterid,
|
||||
:itemid,
|
||||
:inventorytype,
|
||||
:position,
|
||||
:quantity,
|
||||
:owner,
|
||||
:petid,
|
||||
:flag,
|
||||
:expiration,
|
||||
:gift_from,
|
||||
:uniqueid,
|
||||
:upgradeslots,
|
||||
:level,
|
||||
:str,
|
||||
:dex,
|
||||
:int,
|
||||
:luk,
|
||||
:hp,
|
||||
:mp,
|
||||
:watk,
|
||||
:matk,
|
||||
:wdef,
|
||||
:mdef,
|
||||
:acc,
|
||||
:avoid,
|
||||
:hands,
|
||||
:speed,
|
||||
:jump,
|
||||
:vicioushammer,
|
||||
:itemexp,
|
||||
:durability,
|
||||
:enhance,
|
||||
:potential1,
|
||||
:potential2,
|
||||
:potential3,
|
||||
:hp_r,
|
||||
:mp_r,
|
||||
:incskill,
|
||||
:charmexp,
|
||||
:pvpdamage
|
||||
])
|
||||
|> validate_required([:characterid, :itemid, :inventorytype, :position, :quantity])
|
||||
end
|
||||
|
||||
@doc """
|
||||
Converts a database item to a game Item or Equip struct.
|
||||
"""
|
||||
def to_game_item(%__MODULE__{} = db_item) do
|
||||
base_fields = %{
|
||||
id: db_item.inventoryitemid,
|
||||
item_id: db_item.itemid,
|
||||
position: db_item.position,
|
||||
quantity: db_item.quantity,
|
||||
flag: db_item.flag,
|
||||
unique_id: db_item.uniqueid,
|
||||
expiration: db_item.expiration,
|
||||
owner: db_item.owner || "",
|
||||
gift_from: db_item.gift_from || "",
|
||||
gm_log: "",
|
||||
inventory_id: db_item.inventoryitemid,
|
||||
pet: nil
|
||||
}
|
||||
|
||||
if is_equip?(db_item) do
|
||||
struct(Odinsea.Game.Equip, Map.merge(base_fields, equip_fields(db_item)))
|
||||
else
|
||||
struct(Odinsea.Game.Item, base_fields)
|
||||
end
|
||||
end
|
||||
|
||||
defp is_equip?(db_item) do
|
||||
# Equipment items have inventory type 1 (EQUIP) or -1 (EQUIPPED)
|
||||
# or have non-zero equip stats
|
||||
db_item.inventorytype in [1, -1] or
|
||||
db_item.upgradeslots > 0 or
|
||||
db_item.str > 0 or
|
||||
db_item.dex > 0 or
|
||||
db_item.int > 0 or
|
||||
db_item.luk > 0 or
|
||||
db_item.watk > 0 or
|
||||
db_item.wdef > 0
|
||||
end
|
||||
|
||||
defp equip_fields(db_item) do
|
||||
%{
|
||||
upgrade_slots: db_item.upgradeslots,
|
||||
level: db_item.level,
|
||||
vicious_hammer: db_item.vicioushammer,
|
||||
enhance: db_item.enhance,
|
||||
str: db_item.str,
|
||||
dex: db_item.dex,
|
||||
int: db_item.int,
|
||||
luk: db_item.luk,
|
||||
hp: db_item.hp,
|
||||
mp: db_item.mp,
|
||||
watk: db_item.watk,
|
||||
matk: db_item.matk,
|
||||
wdef: db_item.wdef,
|
||||
mdef: db_item.mdef,
|
||||
acc: db_item.acc,
|
||||
avoid: db_item.avoid,
|
||||
hands: db_item.hands,
|
||||
speed: db_item.speed,
|
||||
jump: db_item.jump,
|
||||
hp_r: db_item.hp_r,
|
||||
mp_r: db_item.mp_r,
|
||||
charm_exp: db_item.charmexp,
|
||||
pvp_damage: db_item.pvpdamage,
|
||||
item_exp: db_item.itemexp,
|
||||
durability: db_item.durability,
|
||||
inc_skill: db_item.incskill,
|
||||
potential1: db_item.potential1,
|
||||
potential2: db_item.potential2,
|
||||
potential3: db_item.potential3,
|
||||
ring: nil,
|
||||
android: nil
|
||||
}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Converts a game Item or Equip to database attributes.
|
||||
"""
|
||||
def from_game_item(%Odinsea.Game.Item{} = item, character_id, inv_type) do
|
||||
%{
|
||||
inventoryitemid: item.id,
|
||||
characterid: character_id,
|
||||
itemid: item.item_id,
|
||||
inventorytype: Odinsea.Game.InventoryType.type_value(inv_type),
|
||||
position: item.position,
|
||||
quantity: item.quantity,
|
||||
owner: item.owner,
|
||||
petid: if(item.pet, do: item.pet.unique_id, else: -1),
|
||||
flag: item.flag,
|
||||
expiration: item.expiration,
|
||||
gift_from: item.gift_from,
|
||||
uniqueid: item.unique_id
|
||||
}
|
||||
end
|
||||
|
||||
def from_game_item(%Odinsea.Game.Equip{} = equip, character_id, inv_type) do
|
||||
base = from_game_item(%Odinsea.Game.Item{} = equip, character_id, inv_type)
|
||||
|
||||
Map.merge(base, %{
|
||||
upgradeslots: equip.upgrade_slots,
|
||||
level: equip.level,
|
||||
str: equip.str,
|
||||
dex: equip.dex,
|
||||
int: equip.int,
|
||||
luk: equip.luk,
|
||||
hp: equip.hp,
|
||||
mp: equip.mp,
|
||||
watk: equip.watk,
|
||||
matk: equip.matk,
|
||||
wdef: equip.wdef,
|
||||
mdef: equip.mdef,
|
||||
acc: equip.acc,
|
||||
avoid: equip.avoid,
|
||||
hands: equip.hands,
|
||||
speed: equip.speed,
|
||||
jump: equip.jump,
|
||||
vicioushammer: equip.vicious_hammer,
|
||||
itemexp: equip.item_exp,
|
||||
durability: equip.durability,
|
||||
enhance: equip.enhance,
|
||||
potential1: equip.potential1,
|
||||
potential2: equip.potential2,
|
||||
potential3: equip.potential3,
|
||||
hp_r: equip.hp_r,
|
||||
mp_r: equip.mp_r,
|
||||
incskill: equip.inc_skill,
|
||||
charmexp: equip.charm_exp,
|
||||
pvpdamage: equip.pvp_damage
|
||||
})
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user