FIX - harden inventory contracts and resolve phone interaction issues (#20)

* 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.
This commit is contained in:
DerEchteAlec
2026-08-21 17:19:27 +02:00
committed by GitHub
parent 698420584d
commit 97db163cd0
34 changed files with 912 additions and 79 deletions
+31 -6
View File
@@ -6,7 +6,12 @@ local nui_callbacks = {}
local nui_focus = nil
local nui_keep_input = nil
Config = { Phone = { AllowMovement = true } }
Config = {
Phone = {
AllowMovement = true,
HoldToLook = { Enabled = true, Control = 19 },
},
}
Bridge = { Debug = function() end }
function CreateThread(callback)
@@ -61,6 +66,7 @@ local function resolve(overrides)
cursor_disabled = false,
external_game_input = nil,
is_open = false,
look_passthrough = false,
notification_focus = false,
payphone_focus = false,
sim_picker_open = false,
@@ -115,10 +121,10 @@ local typing_phone = resolve({
assert(
typing_phone.cursor
and typing_phone.focused
and typing_phone.keep_input
and typing_phone.game_input
and not typing_phone.keep_input
and not typing_phone.game_input
and typing_phone.block_game,
"a focused phone text input must block GTA controls without hiding the NUI cursor"
"a focused phone text input must stop game-input passthrough and retain the NUI cursor"
)
local external_movement_phone = resolve({
@@ -142,8 +148,8 @@ local external_movement_typing_phone = resolve({
assert(
external_movement_typing_phone.cursor
and external_movement_typing_phone.focused
and external_movement_typing_phone.keep_input
and external_movement_typing_phone.game_input
and not external_movement_typing_phone.keep_input
and not external_movement_typing_phone.game_input
and external_movement_typing_phone.block_game,
"a focused text input must override an external movement claim"
)
@@ -177,6 +183,21 @@ assert(
"LB noFocus must preserve movement and camera look without retaining the NUI cursor"
)
local movable_look_passthrough_phone = resolve({
allow_movement = true,
is_open = true,
look_passthrough = true,
})
assert(
not movable_look_passthrough_phone.cursor
and movable_look_passthrough_phone.focused
and movable_look_passthrough_phone.keep_input
and movable_look_passthrough_phone.game_input
and not movable_look_passthrough_phone.block_game
and not movable_look_passthrough_phone.block_look,
"HoldToLook must temporarily release the NUI cursor without disabling configured movement"
)
local stationary_cursor_disabled_phone = resolve({
cursor_disabled = true,
is_open = true,
@@ -289,6 +310,10 @@ assert(
SkyPhoneFocus.SetPhone(false)
SkyPhoneFocus.SetPhone(true)
assert(nui_focus.cursor, "closing the phone must clear the previous no-focus claim")
SkyPhoneFocus.SetTextInputFocused(true)
assert(not nui_keep_input, "runtime text focus must stop game-input passthrough")
SkyPhoneFocus.SetTextInputFocused(false)
assert(nui_keep_input, "leaving a text input must restore configured phone movement")
local external_success, external_error = SkyPhoneFocus.SetExternalGameInput("custom_app", true)
assert(external_success and external_error == nil and nui_keep_input, "external movement claim must apply")