v4.1.0
A big feature release. Most of what scripts used to pull in ox_lib for is now part of msk_core, written from scratch in the MSK style, and every existing module was read again on the way. That turned up a number of security issues and bugs, which are fixed here too.
Old call forms keep working. They log a deprecation warning once per resource, so the console does not fill up. See Deprecated for the new forms.
Added
New UI
MSK.Input.Dialogwith eleven field types and validation in the NUI, on the client and on the server.MSK.Alert, including atimeoutthat returns'timeout'.MSK.Radial, configured throughConfig.Radial.MSK.SkillcheckandMSK.Progress.Circle.- A settings menu for players: language, notification position and sound, plus
MSK.Clipboard.
New client modules
MSK.Zones(sphere, box, poly) with an in-game/zoneCreatorthat copies the finished code to the clipboard.MSK.KeybindwithallowInPauseMenu,MSK.Controls,MSK.Dui,MSK.Marker,MSK.Anim.MSK.VehicleProperties. The field names match the format other garages already store, so existing rows stay readable.
New server modules
MSK.Loggerfor Loki, Datadog and Fivemanage.MSK.Eventsto trigger a list of players or everyone in range.MSK.Filesand txAdmin messages as MSK notifications.
MSK.SpawnVehicle
MSK.SpawnVehicle(model, coords, options) spawns a vehicle on the server with CreateVehicleServerSetter. Options: heading, type, plate, props, bucket, warp, playerId.
Without type a client is asked once per model and the answer is remembered. Trailers cannot be told apart by their model and need type = 'trailer'.
New shared modules
MSK.Class, MSK.Array, MSK.Selector, MSK.Timer, MSK.Grid, MSK.Print, MSK.Locale (including Locale.GetFrom(resource, key, ...)), MSK.Require, MSK.Hook and MSK.Cache(key, fn, ttl).
More
- Math:
Clamp,Lerp,InverseLerp,Remap,HexToRgb,RgbToHex,ToScalars,ToVector,NormalToRotation,ToHex,ToRgba. - Table:
Freeze,IsFrozen,Merge,Matches,Keys,Values,Wipe. String:RandomPattern. Vector:GetRelativeCoords. - Request:
AudioBank,WeaponAsset,CameraRaycast,RaycastFromCoords, andStartCameraRaycast/ReadRaycastfor code that must not wait inside a frame. - Entities:
GetNearbyPeds,GetNearbyObjects,GetNearbyVehicles,GetNearbyPlayers,GetClosestPed,GetClosestObject.GetClosestEntity,GetClosestVehicleandGetClosestPlayertake an optionalmaxDistance. Nothing found still returns-1, -1. - Cron expressions:
MSK.Cron.Schedule,Unschedule,GetNextRun,IsValid. MSK.TriggerAwaitwith its own timeout:(event, timeout, ...)on the client,(event, playerId, timeout, ...)on the server. The default timeout of every callback is the convarmsk:callbackTimeout(5000 ms).MSK.OnPlayer(key, cb)reacts to changes in the player mirror:cb(value, oldValue)on the client,cb(playerId, value, oldValue)on the server.- Points: a
nearbycallback that runs every frame while the player is inside, andMSK.Points.GetNearbyPoints(). - Scaleform:
MSK.Scaleform.New(name, options)with render targets,IsRendering()and a clear error afterDispose(). - Commands: parameter type
longString, which takes the rest of the line.
Changed
Table forms for the UI
MSK.Notification, MSK.Progress.Start, MSK.TextUI.Show and MSK.Numpad.Open take a table.
- Notifications got an
idto replace an open one, icons with animation, a position per call and an optional title. - TextUI updates while it is open, has an icon and four positions.
- Progress supports props and a bar position, and the server waits for the result.
- Context got
iconAnimationand metadata as text or bars. - Menu got a menu callback,
Show(id, startIndex),SetOptionsandHide(false).
A player's notification position beats the script's. The setting starts on automatic, and only then does position from the script apply.
Behaviour changes
| Function | Before | Now |
|---|---|---|
MSK.Request.* loaders | 5 s timeout | timeout parameter, default 30 s |
MSK.Request.Raycast | error after a second on a miss | line-of-sight probe, returns entity or false |
MSK.Cron.Create | returned nothing | returns the job id, nil on invalid arguments |
MSK.Math.Round(2.5) | 2 | 3, halves round away from zero |
MSK.Math.Round(1234, -2) | not supported | 1200 |
MSK.String.Split(s, ', ') | split on every single character | splits on the whole separator |
Server MSK.GetPedVehicleSeat | -1 when in no seat | false |
bulletProofTyres | means "tyres can burst", as the game reports it | |
MSK.IsSpawnPointClear | default radius 5.0 | |
MSK.Call in a consumer | raised an error | returns nil |
A cron job for a time of day without a valid atH (0 to 23), with an atM outside 0 to 59 or an atD outside 1 to 7 is rejected with a message. Before, it was stored and stopped the scheduler on the next tick, or silently never ran.
Without atM a job runs at the full hour. It used to be accepted and then never run at all. Without atD it runs every day.
The cron page used to say atD = 1 is Monday. msk_core has always compared against os.date('*t').wday, where 1 is Sunday and 7 is Saturday. The code did not change, the documentation was wrong. Check jobs that use atD, they may run one day off from what you intended.
Config.showCoords, Config.copyCoords and the ban commands include the god group.
Deprecated
These still work and log a warning once per resource:
| Old form | New form |
|---|---|
MSK.Notification(title, message, type, duration) | MSK.Notification({ ... }) |
MSK.Progress(duration, text, color) | MSK.Progress.Start({ ... }) |
MSK.TextUI.Show(key, text, color) | MSK.TextUI.Show({ ... }) |
MSK.Numpad(pin, showPin, cb) | MSK.Numpad.Open({ ... }) |
MSK.Input / MSK.OpenInput | MSK.Input.Dialog |
MSK.ScaleformAnnounce | MSK.Scaleform.New |
Security
The numpad code no longer reaches the NUI
It was sent to the browser in plain text and the check ran on the client, so it could be skipped. The server form checks the code itself and supports maxAttempts.
A client-side numpad is fine for game mechanics that protect nothing of value. Anything a player could profit from belongs on the server form.
Callbacks accept an answer only from the player they asked
Before, any client could answer a request that was meant for somebody else. Handlers run protected, and a failing handler reaches the caller right away instead of after the timeout. Callbacks belong to the resource that registered them, cannot be overwritten by another resource and are removed when it stops.
The player mirror validates what clients send
Only known keys with the right type are accepted. coords, heading and state are never taken from the client, a vehicle is only accepted within 15 m, custom keys are limited, and the data is cleared when the player leaves.
More
- Ace: the ace callback only answers for groups and the caller's own principals.
- Ban: a ban is no longer matched by player name, an active ban wins over an expired one, and bans from the console are stored as
Console. - Commands: an alias used to lose
restricted, so a restricted command was open under its second name. - Logger: API keys come from convars only. Use
set, neversetr, which would send the key to every client.
Fixed
- Server-side
MSK.InputandMSK.Numpadgave up with nil after 5 seconds. - Context and Numpad NUI callbacks never answered, so every input left an open request behind.
- An error in a menu callback froze the menu, and a menu opened from
onSelectclosed again right away. - Progress:
playEnter = falseturned intotrue, andforceOverrideleft the old wait running, so a late end stopped the next progress bar. - TextUI stayed on screen after the resource that opened it stopped.
- Cron: a job that deleted itself killed the scheduler, old jobs compared only part of their timestamp, jobs could run twice, and jobs of a stopped resource kept running. Ticks now start on the full minute.
- Points: an error in a callback broke all points,
onExitdid not run on remove, and points of a stopped resource stayed. Anim.Playwithwaitwaited forever on a looping animation without a duration.- Vehicle properties from the server: up to ten tries to become owner, and the state bag is cleared once the client applied them.
- Searching a vehicle by plate crashed on vehicles that no longer existed and ignored differently padded plates.
MSK.VehicleStore.Insertwithout a model now stops with a log line on QBCore and Qbox.MSK.Offlinereads online players through the framework and handlesNULLJSON columns.MSK.Societyno longer caches "no provider" forever.GetClosestEntityon the server: player entities, excluding yourself and searches without a distance were wrong.- The disconnect logger marker is sent to players within 250 m instead of 20 m, because it stays for 60 s and players walk into it.
- The version check survives an invalid JSON answer from GitHub.
MSK.Files.Listworks on Linux.- A logger entry that cannot be encoded no longer throws away the whole batch.
- The module loader keeps the stack trace of an error.
- The zone creator no longer waits in the middle of a frame, which lost key presses and let E act in the world.
Changed files
Replace the whole resource. config.lua has four new blocks, see Configuration.
fxmanifest.lua
Readme.md
config.lua
import.lua
aliases.lua
init/shared.lua
init/client.lua
init/server.lua
modules/Alert/ (new)
modules/Anim/ (new)
modules/Array/ (new)
modules/Cache/ (new)
modules/Class/ (new)
modules/Clipboard/ (new)
modules/Controls/ (new)
modules/Dui/ (new)
modules/Events/ (new)
modules/Files/ (new)
modules/Grid/ (new)
modules/Hook/ (new)
modules/Keybind/ (new)
modules/Locale/ (new)
modules/Logger/ (new)
modules/Marker/ (new)
modules/Print/ (new)
modules/Radial/ (new)
modules/Require/ (new)
modules/Selector/ (new)
modules/Settings/ (new)
modules/Skillcheck/ (new)
modules/Timer/ (new)
modules/TxAdmin/ (new)
modules/VehicleProperties/ (new)
modules/ZoneCreator/ (new)
modules/Zones/ (new)
modules/Input/shared.lua (new)
modules/Ace/server.lua
modules/Ban/server.lua
modules/Call/shared.lua
modules/Callback/shared.lua
modules/Callback/client.lua
modules/Callback/server.lua
modules/Check/server.lua
modules/Command/client.lua
modules/Command/server.lua
modules/Context/client.lua
modules/Cron/server.lua
modules/DisconnectLogger/server.lua
modules/Entities/client.lua
modules/Entities/server.lua
modules/Input/client.lua
modules/Input/server.lua
modules/Math/shared.lua
modules/Menu/client.lua
modules/Menu/server.lua
modules/Notify/client.lua
modules/Notify/server.lua
modules/Numpad/client.lua
modules/Numpad/server.lua
modules/Offline/server.lua
modules/Player/client.lua
modules/Player/server.lua
modules/Points/client.lua
modules/Progress/client.lua
modules/Progress/server.lua
modules/Request/client.lua
modules/Scaleform/client.lua
modules/Scaleform/server.lua
modules/Society/server.lua
modules/String/shared.lua
modules/Table/shared.lua
modules/TextUI/client.lua
modules/TextUI/server.lua
modules/Vector/shared.lua
modules/Vehicle/client.lua
modules/Vehicle/server.lua
modules/VehicleStore/server.lua
modules/World/client.lua
modules/World/server.lua
web/dist/ (rebuilt NUI)