Skip to content

SA-MP maps

Neon can load common SA-MP Texture Studio / Pawn map exports without converting them to Lua first. The client parser understands object creation, virtual worlds, interiors, building removals, and per-material texture/color overrides.

The clip opens on the .pwn source, and almost every line is a SetDynamicObjectMaterial call. That is not unusual: in a real Texture Studio map, nearly no object keeps its original GTA texture. Mappers pick a handful of neutral shapes and retexture them, so a wall, a counter and a floor may all be the same model wearing three different materials.

A parser that only replayed CreateObject would place every piece of geometry in the right position and still render a map that looks nothing like the original. Material slots are what makes the import faithful rather than merely geometrically correct, which is why they are handled alongside object creation instead of being left to the resource.

Neon reads both the plain SA-MP form and the streamer plugin’s dynamic form:

RecognisedHandled as
CreateObject, CreateDynamicObject, CreateDynamicObjectExObject placement
SetObjectMaterial, SetDynamicObjectMaterialTexture and color slots
RemoveBuildingForPlayerBuilding removals
SetObjectMaterialText, SetDynamicObjectMaterialText, AddSimpleModelReported as unsupported in the diagnostics, never applied silently

For the complete ready-to-use path, use the bundled samp-map-loader resource. It owns the model mappings, map elements, removals, material state, and cleanup.

Declare the .pwn file in the resource that owns it, then call the loader:

local map, diagnostics = exports["samp-map-loader"]:loadSAMPMap(":my-maps/maps/interior.pwn")

Unload the returned handle when the map is no longer needed:

exports["samp-map-loader"]:unloadSAMPMap(map)

The loader waits until every required custom model is ready before creating the complete map. If loading fails, it can report parser/model diagnostics instead of leaving a half-created scene.

engineParseSAMPMap accepts the Pawn source text and returns inert data for the calls listed above, plus model, position, rotation, stream distance, draw distance, virtual world and interior metadata, and source line/column diagnostics.

Parsing does not create an MTA element or load a model. That separation keeps resource ownership and failure policy in Lua.

local parsed = engineParseSAMPMap(mapSource)
if not parsed.success then
outputDebugString(parsed.diagnostics[1].message, 1)
return
end

The reference loader resolves the official SA-MP 0.3.7 custom-object ranges to resource-owned Neon runtime models. The source map can keep its original SA-MP IDs; the loader maps them to the client slots actually allocated by Neon.

Material slots use setObjectMaterial and removeObjectMaterial. Neon applies the SA-MP slot index across every atomic in the DFF and keeps the override on the MTA object so it survives stream-out/recreation.

engineGetTXDIDFromName is available when a loader needs the current GTA slot for a named texture dictionary.

MTA keeps a fixed 1000-slot streamed-object budget for its normal and low-LOD object streamers. The default split remains 500 normal / 500 low-LOD.

SA-MP-style maps that do not use low-LOD objects can redistribute that existing budget:

engineSetObjectStreamingLimits(1000, 0)

engineGetObjectStreamingLimits returns the current normal quota, low-LOD quota, and hard combined maximum. The sum cannot exceed 1000; this feature does not enlarge GTA’s physical pools. Lowering a quota below current usage restreams that category so the new limit takes effect.

  • The parser is client-side and produces data only.
  • Model and map cleanup still belongs to the resource.
  • The public repository includes a focused fixture and loader; private map corpora used during validation are not distributed.
  • Custom map support does not bypass normal MTA element limits, collision rules, dimensions, or resource permissions.

Commit 28dfcff23 added native SA-MP map parsing, material-slot support, custom-object loading, and the reference loader. Commit c1d052e9d added the configurable object-streaming split.