mirror of
https://github.com/sky-systems/sky_phone.git
synced 2026-08-29 01:01:31 +00:00
97db163cd0
* FIX - repair inventory metadata and ESX contracts Use the stable core_inventory metadata setter and validate the complete inventory adapter contract after provider bridges load. Preserve the real ESX configuration error instead of cascading into a missing RegisterUsableItem failure. * FIX - clarify phone opening without SIM * FIX - harden inventory and device contracts Validate SIM number configuration before item handling, preserve QB metadata mutation contracts, and propagate phone-open failures to callers. Extend regression coverage for inventory bridges and device bootstrap errors. * FIX - resolve reported phone interaction issues Stop game-input passthrough while NUI text fields are focused and add an independent hold-to-look option. Propagate SIM number formatting to the frontend, migrate configured currency symbols to utf8mb4, and clarify SkyRide, VaultX, and DarkChat behavior with focused contract coverage. * FIX - detect missing packaged phone UI Validate the generated NUI entrypoint, its referenced assets, and required static media when the resource starts. Print an actionable server-console warning for incomplete source archives, package phone sounds through the manifest, and cover the detection contract with Lua regressions.
151 lines
5.0 KiB
Lua
151 lines
5.0 KiB
Lua
if Bridge.Inventory.Name ~= "qb" and Bridge.Inventory.Name ~= "lj" then
|
|
return
|
|
end
|
|
|
|
local resource_name = Bridge.Inventory.Name == "lj" and "lj-inventory" or "qb-inventory"
|
|
local inventory = exports[resource_name]
|
|
local QBCore = Bridge.Inventory.Name == "lj" and exports["qb-core"]:GetCoreObject() or nil
|
|
|
|
local function get_lj_player(source)
|
|
return QBCore and QBCore.Functions.GetPlayer(tonumber(source)) or nil
|
|
end
|
|
|
|
local function normalize(item)
|
|
if not item then
|
|
return nil
|
|
end
|
|
|
|
local metadata = {}
|
|
for key, value in pairs(type(item.info) == "table" and item.info or {}) do
|
|
metadata[key] = value
|
|
end
|
|
return {
|
|
name = item.name,
|
|
slot = tonumber(item.slot),
|
|
count = tonumber(item.amount) or 0,
|
|
amount = tonumber(item.amount) or 0,
|
|
metadata = metadata,
|
|
}
|
|
end
|
|
|
|
local function metadata_matches(actual, expected)
|
|
if type(expected) ~= "table" then
|
|
return true
|
|
end
|
|
actual = type(actual) == "table" and actual or {}
|
|
for key, value in pairs(expected) do
|
|
if actual[key] ~= value then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function Bridge.Inventory.GetResourceName()
|
|
return resource_name
|
|
end
|
|
|
|
function Bridge.Inventory.GetSlot(source, slot_id)
|
|
if Bridge.Inventory.Name == "lj" then
|
|
local player = get_lj_player(source)
|
|
return normalize(player and player.PlayerData.items[tonumber(slot_id)] or nil)
|
|
end
|
|
return normalize(inventory:GetItemBySlot(source, tonumber(slot_id)))
|
|
end
|
|
|
|
function Bridge.Inventory.GetSlotsWithItem(source, item_name, metadata)
|
|
local matches = {}
|
|
local items
|
|
if Bridge.Inventory.Name == "lj" then
|
|
local player = get_lj_player(source)
|
|
items = player and player.PlayerData.items or {}
|
|
else
|
|
items = inventory:GetItemsByName(source, item_name) or {}
|
|
end
|
|
for _, item in pairs(items) do
|
|
local normalized = normalize(item)
|
|
if normalized.name == item_name and metadata_matches(normalized.metadata, metadata) then
|
|
matches[#matches + 1] = normalized
|
|
end
|
|
end
|
|
return matches
|
|
end
|
|
|
|
function Bridge.Inventory.SetSlotMetadata(source, slot_id, metadata)
|
|
local slot = Bridge.Inventory.GetSlot(source, slot_id)
|
|
if not slot then
|
|
return false
|
|
end
|
|
if Bridge.Inventory.Name == "lj" then
|
|
local player = get_lj_player(source)
|
|
if not player then
|
|
return false
|
|
end
|
|
local requested_metadata = type(metadata) == "table" and metadata or {}
|
|
player.PlayerData.items[slot.slot].info = requested_metadata
|
|
player.Functions.SetInventory(player.PlayerData.items, true)
|
|
local updated = player.PlayerData.items[slot.slot]
|
|
return updated ~= nil and Bridge.Inventory.MetadataMatches(updated.info, requested_metadata)
|
|
end
|
|
|
|
local amount = tonumber(slot.amount or slot.count) or 0
|
|
if amount <= 0 then
|
|
return false
|
|
end
|
|
|
|
local requested_metadata = type(metadata) == "table" and metadata or {}
|
|
if inventory:RemoveItem(source, slot.name, amount, slot.slot, "sky_phone:metadata-update") ~= true then
|
|
return false
|
|
end
|
|
|
|
if inventory:AddItem(source, slot.name, amount, slot.slot, requested_metadata, "sky_phone:metadata-update") ~= true then
|
|
return false
|
|
end
|
|
|
|
local updated = Bridge.Inventory.GetSlot(source, slot.slot)
|
|
return updated
|
|
and updated.name == slot.name
|
|
and updated.amount == amount
|
|
and Bridge.Inventory.MetadataMatches(updated.metadata, requested_metadata)
|
|
or false
|
|
end
|
|
|
|
function Bridge.Inventory.CanCarryItem(source, item_name, count)
|
|
if Bridge.Inventory.Name == "lj" then
|
|
return get_lj_player(source) ~= nil
|
|
end
|
|
return inventory:CanAddItem(source, item_name, count) == true
|
|
end
|
|
|
|
function Bridge.Inventory.AddItem(source, item_name, count, slot, metadata)
|
|
if not Bridge.Inventory.CanCarryItem(source, item_name, count, metadata) then
|
|
return false
|
|
end
|
|
if Bridge.Inventory.Name == "lj" then
|
|
local player = get_lj_player(source)
|
|
return player and player.Functions.AddItem(item_name, count, slot, metadata or {}) == true or false
|
|
end
|
|
return inventory:AddItem(source, item_name, count, slot, metadata or {}, "sky_phone") == true
|
|
end
|
|
|
|
function Bridge.Inventory.RemoveItem(source, item_name, count, slot, metadata)
|
|
if metadata and not slot then
|
|
local slots = Bridge.Inventory.GetSlotsWithItem(source, item_name, metadata)
|
|
slot = slots[1] and slots[1].slot or nil
|
|
if not slot then
|
|
return 0
|
|
end
|
|
end
|
|
if Bridge.Inventory.Name == "lj" then
|
|
local player = get_lj_player(source)
|
|
return player and player.Functions.RemoveItem(item_name, count, slot) == true and count or 0
|
|
end
|
|
return inventory:RemoveItem(source, item_name, count, slot, "sky_phone") == true and count or 0
|
|
end
|
|
|
|
function Bridge.Inventory.RegisterUsableItem(item_name, callback)
|
|
return Bridge.Framework.RegisterUsableItem(item_name, function(source, item)
|
|
callback(source, normalize(item))
|
|
end)
|
|
end
|