Zum Hauptinhalt springen

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.

Nothing breaks

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

New client modules

New server modules

MSK.SpawnVehicle

MSK.SpawnVehicle(model, coords, options) spawns a vehicle on the server with CreateVehicleServerSetter. Options: heading, type, plate, props, bucket, warp, playerId.

info

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, and StartCameraRaycast / ReadRaycast for code that must not wait inside a frame.
  • Entities: GetNearbyPeds, GetNearbyObjects, GetNearbyVehicles, GetNearbyPlayers, GetClosestPed, GetClosestObject. GetClosestEntity, GetClosestVehicle and GetClosestPlayer take an optional maxDistance. Nothing found still returns -1, -1.
  • Cron expressions: MSK.Cron.Schedule, Unschedule, GetNextRun, IsValid.
  • MSK.TriggerAwait with its own timeout: (event, timeout, ...) on the client, (event, playerId, timeout, ...) on the server. The default timeout of every callback is the convar msk: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 nearby callback that runs every frame while the player is inside, and MSK.Points.GetNearbyPoints().
  • Scaleform: MSK.Scaleform.New(name, options) with render targets, IsRendering() and a clear error after Dispose().
  • 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 id to 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 iconAnimation and metadata as text or bars.
  • Menu got a menu callback, Show(id, startIndex), SetOptions and Hide(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

FunctionBeforeNow
MSK.Request.* loaders5 s timeouttimeout parameter, default 30 s
MSK.Request.Raycasterror after a second on a missline-of-sight probe, returns entity or false
MSK.Cron.Createreturned nothingreturns the job id, nil on invalid arguments
MSK.Math.Round(2.5)23, halves round away from zero
MSK.Math.Round(1234, -2)not supported1200
MSK.String.Split(s, ', ')split on every single charactersplits on the whole separator
Server MSK.GetPedVehicleSeat-1 when in no seatfalse
bulletProofTyresmeans "tyres can burst", as the game reports it
MSK.IsSpawnPointCleardefault radius 5.0
MSK.Call in a consumerraised an errorreturns 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.

Cron weekdays: 1 is Sunday

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 formNew 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.OpenInputMSK.Input.Dialog
MSK.ScaleformAnnounceMSK.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.

warnung

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, never setr, which would send the key to every client.

Fixed

  • Server-side MSK.Input and MSK.Numpad gave 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 onSelect closed again right away.
  • Progress: playEnter = false turned into true, and forceOverride left 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, onExit did not run on remove, and points of a stopped resource stayed.
  • Anim.Play with wait waited 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.Insert without a model now stops with a log line on QBCore and Qbox.
  • MSK.Offline reads online players through the framework and handles NULL JSON columns.
  • MSK.Society no longer caches "no provider" forever.
  • GetClosestEntity on 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.List works 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)