FIX - harden phone lifecycle and server authority

This commit is contained in:
DerEchteAlec
2026-08-12 18:59:05 +02:00
parent 8cffaeaa3c
commit c3b7a0871a
30 changed files with 1630 additions and 174 deletions
+67
View File
@@ -0,0 +1,67 @@
dofile("sky_phone/source/client/focus.lua")
local function resolve(overrides)
local state = {
activity_suspended = false,
call_focus = false,
camera_active = false,
camera_nui_focused = true,
is_open = false,
notification_focus = false,
payphone_focus = false,
sim_picker_open = false,
}
for key, value in pairs(overrides or {}) do
state[key] = value
end
return SkyPhoneFocus.Resolve(state)
end
local idle = resolve()
assert(not idle.focused and not idle.keep_input, "idle NUI must release focus and game input override")
local minimized_call = resolve()
assert(not minimized_call.focused, "a replayed call without an attention claim must stay unfocused")
local incoming_call = resolve({ call_focus = true })
assert(incoming_call.focused and not incoming_call.keep_input, "incoming call attention must focus the NUI")
local camera_game_input = resolve({
camera_active = true,
camera_nui_focused = false,
is_open = true,
})
assert(
not camera_game_input.focused and camera_game_input.keep_input,
"unfocused camera must own game input over the open phone"
)
local camera_interrupted_by_call = resolve({
call_focus = true,
camera_active = true,
camera_nui_focused = false,
is_open = true,
})
assert(
camera_interrupted_by_call.focused and not camera_interrupted_by_call.keep_input,
"incoming call attention must override unfocused camera input"
)
local camera_after_connected_call = resolve({
call_focus = false,
camera_active = true,
camera_nui_focused = false,
is_open = true,
})
assert(
not camera_after_connected_call.focused and camera_after_connected_call.keep_input,
"connected call without an attention claim must restore unfocused camera input"
)
local payphone_closed_behind_phone = resolve({ is_open = true, payphone_focus = false })
assert(payphone_closed_behind_phone.focused, "releasing payphone focus must not clear mobile phone focus")
local suspended = resolve({ activity_suspended = true, call_focus = true, is_open = true })
assert(not suspended.focused and not suspended.keep_input, "suspended activities must mask every focus claim")
print("Client focus tests passed")
+39
View File
@@ -0,0 +1,39 @@
dofile("sky_phone/source/server/payphones.lua")
local allowed_models = {
prop_phonebox_01a = true,
prop_phonebox_04 = true,
}
local locations, rejected = SkyPhonePayphones.ValidateLocations({
{ model = "prop_phonebox_01a", coords = { x = 100.0, y = 200.0, z = 30.0 } },
{ model = "prop_phonebox_04", coords = { x = 105.0, y = 200.0, z = 30.0 } },
{ model = "not_allowed", coords = { x = 100.0, y = 200.0, z = 30.0 } },
{ model = "prop_phonebox_01a", coords = { x = "100", y = 200.0, z = 30.0 } },
{ model = "prop_phonebox_01a", coords = { x = 10001.0, y = 200.0, z = 30.0 } },
"malformed",
}, allowed_models)
assert(#locations == 2, "only strictly valid configured locations must be accepted")
assert(rejected == 4, "every malformed or disallowed configured location must be reported")
local first = SkyPhonePayphones.FindNearest(locations, { x = 101.0, y = 200.0, z = 30.0 }, 3.0)
assert(first and first.model == "prop_phonebox_01a", "nearest configured booth must be selected")
local second = SkyPhonePayphones.FindNearest(locations, { x = 104.0, y = 200.0, z = 30.0 }, 3.0)
assert(second and second.model == "prop_phonebox_04", "another configured booth must be selected by proximity")
assert(
not SkyPhonePayphones.FindNearest(locations, { x = 0.0, y = 0.0, z = 0.0 }, 3.0),
"a player away from every configured booth must be rejected"
)
assert(
not SkyPhonePayphones.FindNearest(locations, { x = "100", y = 200.0, z = 30.0 }, 3.0),
"malformed player coordinates must be rejected"
)
assert(
not SkyPhonePayphones.FindNearest(locations, { x = 100.0, y = 200.0, z = 30.0 }, 0.0),
"an invalid validation distance must be rejected"
)
print("Server payphone validation tests passed")