Document Control¶
| Field | Value |
|---|---|
| Document ID | modders-events-callbacks |
| Version | 1.0.0 |
| Status | approved |
| Confidence | Medium |
| Category (track) | Modders |
| Build | both |
| Owner | PZ Knowledge-Base Pipeline |
| Created | 2026-10-07 |
| Updated | 2026-10-08 |
| Review due | 2027-01-07 |
| Game versions verified | 41.78.16 (Umbrella stubs), 42.21.0 (Umbrella stubs; 42.20.0 kept for comparison) |
Executive Summary¶
Project Zomboid exposes its game loop to Lua through a global Events
table. Each event is an object with an Add and a Remove function; you
register a Lua function and the engine calls it when the event fires [1] [2].
The Umbrella type stubs declare 244 events for 42.21.0 (234 at 42.20.0) and 240 events for
41.78.16 (the B41 figure includes 32 events the stubs flag as deprecated),
and every event has a Callback_<Name> type alias that records its parameter
list [1] [2] [3].
This document groups the full list by purpose, tabulates the events a mod author reaches for most, explains the load-order and cost traps (OnGameBoot versus OnGameStart versus OnNewGame, per-tick events), and diffs the two builds' stubs. The B41 to B42 diff is concrete: 39 events were added, 35 were dropped (32 of them were already deprecated on B41), and 65 callback signatures differ in text, some of them real parameter changes rather than type-notation clean-ups [1] [2] [3]. Between the 42.20.0 and 42.21.0 stub sets, ten events were added, none removed, and 16 callback signatures changed [1] [11].
Confidence is Medium. The facts come from pinned Umbrella stubs, which are primary code truth for what is declared, but the stubs are community-written type files, not a decompiled call graph, and nothing here was exercised in-game. The B42 verification build is the 42.21.0 stub set; the B41 stubs trail the legacy41 line (see Build Applicability).
Key Takeaways¶
- An event is registered with
Events.OnTick.Add(fn)and unregistered withEvents.OnTick.Remove(fn); the stubs declare exactly those two functions on every event. (cited) (both) [1] [2] - 42.21.0 declares 244 events, 41.78.16 declares 240 (208 current plus 32 flagged deprecated). 205 names are common to both. (cited) (both) [1] [2] [3]
- B42 adds 39 events and drops 35 B41 names; 32 of the dropped names carry a deprecation flag in the B41 stubs. (cited) (both) [1] [2] [3]
- The stub descriptions label an event
(Client),(Server)or(Multiplayer); 89 of the 244 B42 events carry no label at all, so the absence of a tag is not proof of where an event runs. (cited) (B42) [1] OnGameBootfires before a client has run the files inlua/server/, so a callback added from a server-folder file is never called for that event on a client. (cited) (both) [1] [2]OnTickfires every game tick andOnTickEvenPausedfires even while the game is paused, so work in them is paid continuously. (cited) (both) [1] [2]- A handful of callbacks changed shape between builds (for example
Events.OnMechanicActionDonelost four parameters). Do not copy a B41 handler to B42 without re-checking the signature. (cited) (both) [1] [2] - Mod-defined events via
LuaEventManager.AddEventandLuaEventManager.triggerEventare declared in the stubs, but how mods use them in practice is only community lore. (cited stub shape; usage quarantined) [4] [5]
Purpose¶
Answer the question a new mod author asks right after "hello world": which event do I hang my code on, what does the callback receive, where does it run, and what changes if I also support the other build. It is the Modders track's reference for the event system, going deeper than the overview in modders-foundation, which only points at the Umbrella stubs.
Scope¶
Covered: the Events.<Name>.Add and .Remove mechanism; callback signatures
as declared in the pinned Umbrella stubs; a purpose-based grouping of every
event in the stub index; the stub-level client, server and multiplayer
labels; ordering and cost pitfalls; the LuaEventManager API surface; and a
B41 to B42 diff of the event lists.
Not covered: what each Java class passed to a callback can do (see modders-lua-api-surface), client-to-server command networking in depth (see modders-mp-networking-porting), and per-event semantics that the stubs leave blank. About 18 of the 244 B42 event stubs have no description beyond the name, and this document says "undocumented in the stub" rather than guessing [1]. Unstable-branch behaviour is out of scope.
Definitions¶
- Event — a named hook in the Lua-visible
Eventstable; stubs declare it asEvents.<Name> = { Add = ..., Remove = ... }[1]. - Callback — the Lua function you register; its expected parameters are
recorded in the event's
Callback_<Name>alias [1]. - Tick — one iteration of the game's update loop;
OnTickreceives the number of ticks since the game started [1]. - Context label — the
(Client),(Server)or(Multiplayer)prefix in a stub description. It is documentation text written by the stub authors, not an enforced runtime restriction [1] [10]. - LuaEventManager — the Java class the stubs expose for creating and firing events [4].
- Deprecated event — one the B41 stubs mark with
@deprecated; all 32 live in a separate file [3].
Build Applicability¶
| Build | Applies | Verified against | Notes |
|---|---|---|---|
| B41 (legacy41) | Yes | Umbrella 41.78.16 stubs, commit fa2e7e19799740b57902f1cb4e989225c295c05e [2] [3] [9] | Newest B41 stub tag available; legacy41 itself has since moved on to 41.78.21 (2026-08-26) [7] |
| B42 (stable) | Yes | Umbrella 42.21.0 stubs, commit 13d01f9ee58fa48773553920db56d06f0005e7f8 [1] [9]; 42.21 patch notes [12] | Stable 42.21 was released 2026-09-28 [6] |
Re-baselined 2026-10-07 from 42.20.0 to 42.21. Re-checked: the 42.21.0
library/events.lua against the 42.20.0 one (event list, labels, callback
aliases, the Delta counts and tables) [1] [11], the LuaEventManager stub [4], and the
42.20.1 to 42.21 official notes for any event change [12] [6] [7]. Statements
not touched by those are carried forward from the 42.20.0 review with no
contradicting change found; nothing was re-tested in-game. The 42.21 announcement states the stable
release followed an unstable period and links to the full patch notes on the
Indie Stone forums [6]; those notes name no event change [12]. Legacy 41.78.21 was released
after 41.78.16, and its hotfix notes describe the removal of the loadstring and
loadstream Lua methods as a security fix [7]; build 42.21 re-enabled both
commands [6] [12], but the 42.21 notes state this for the 42.20.4 change, and no source
read here says whether legacy41 got the same reversal. Whether any of this
touches an event is not established here.
Reference¶
The mechanism: Events.Name.Add and Remove¶
Every event in the stubs is a table with two functions, Add(callback) and
Remove(callback), each taking a function typed as the event's
Callback_<Name> alias. For instance Callback_OnTick is declared as a
function taking one number, tick [1]. Events with no parameters are
declared with the alias function, such as the one for Events.OnGameStart
[1]. The B41 stubs use the same shape, but place events in
library/Events/Events.lua and, for deprecated ones,
library/Events/Events-deprecated.lua; B42 uses one file,
library/events.lua [1] [2] [3].
A minimal registration, in the shape the stubs describe:
local function onTick(tick)
-- tick is the number of ticks since the game started [1]
end
Events.OnTick.Add(onTick)
-- later, with the same function value:
Events.OnTick.Remove(onTick)
How the stubs label execution context¶
Stub descriptions may begin with one or two bracketed labels. Counting the
B42 stubs: 96 events are labelled (Client) only, 12 (Server) only, 36
(Multiplayer) (Client), 6 (Multiplayer) (Server), 5 (Multiplayer) alone,
and 89 carry no label [1]. The B41 counts are 92, 9, 35, 4, 3 and 65 over the
208 non-deprecated events [2]. The twelve server-only B42 events are
LevelPerk, OnClientCommand, OnFillContainer, OnForageRequestZone,
OnForageSpot, OnSGlobalObjectSystemInit,
OnUpdateModdedWeatherStage, OnWeaponHitThumpable,
OnWeatherPeriodComplete, OnWeatherPeriodStage, OnWeatherPeriodStart and
OnWeatherPeriodStop [1]; LevelPerk was labelled (Client) in the 42.20.0 stub
and carries (Server) at 42.21.0 [11] [1]. The labels are descriptive text; the stubs do not
say what an unlabelled event does when registered on the other side [1].
Events by purpose¶
The groups below are this document's own taxonomy applied to the stub index;
membership lists are representative, and the full list is in the stub files
[1]. Names are as declared, including the lower-case on prefix on a few
forage and search-mode events [1].
| Group | Representative members (B42 stubs) |
|---|---|
| Time and tick | OnTick, OnTickEvenPaused, OnRenderTick, OnFETick, OnSleepingTick, EveryOneMinute, EveryTenMinutes, EveryHours, EveryDays, OnClimateTick [1] |
| Lifecycle and loading | OnGameBoot, OnGameStart, OnNewGame, OnLoad, OnSave, OnPostSave, OnInitWorld, OnInitGlobalModData, OnGameTimeLoaded, OnPreMapLoad, OnPostMapLoad, OnLoadMapZones, OnLoadedTileDefinitions, OnMainMenuEnter, OnResetLua, OnModsModified [1] |
| Data and distribution setup | OnPreDistributionMerge, OnDistributionMerge, OnPostDistributionMerge, OnReceiveGlobalModData, OnSGlobalObjectSystemInit, OnCGlobalObjectSystemInit, plus the preAdd...Defs and onAddForageDefs family [1] |
| Player and character | OnCreatePlayer, OnPlayerUpdate, OnPlayerMove, OnPlayerDeath, OnCharacterDeath, OnEquipPrimary, OnEquipSecondary, OnClothingUpdated, AddXP, LevelPerk, OnPlayerGetDamage [1] |
| Combat and zombies | OnWeaponSwing, OnWeaponHitCharacter, OnHitZombie, OnZombieCreate, OnZombieUpdate, OnZombieDead, OnWeaponHitXp, OnPlayerAttackFinished [1] |
| World and map | LoadGridsquare, LoadChunk, OnObjectAdded, OnTileRemoved, OnObjectAboutToBeRemoved, OnContainerUpdate, OnNewFire, OnGridBurnt, OnSeeNewRoom, OnWaterAmountChange, OnDeadBodySpawn [1] |
| Weather and climate | OnClimateManagerInit, OnInitSeasons, OnWeatherPeriodStart, OnWeatherPeriodStage, OnWeatherPeriodStop, OnWeatherPeriodComplete, OnThunderEvent [1] |
| Vehicles | OnEnterVehicle, OnExitVehicle, OnSwitchVehicleSeat, OnUseVehicle, OnVehicleDamageTexture, OnSpawnVehicleStart, OnSpawnVehicleEnd, OnMechanicActionDone [1] |
| UI, input and menus | OnCreateUI, OnPreUIDraw, OnPostUIDraw, OnKeyStartPressed, OnKeyKeepPressed, OnKeyPressed, OnMouseDown, OnMouseWheel, OnFillWorldObjectContextMenu, OnFillInventoryObjectContextMenu, OnJoypadActivate, OnResolutionChange [1] |
| Multiplayer client | OnConnected, OnDisconnect, OnConnectFailed, OnServerCommand, OnReceiveGlobalModData, OnAddMessage, OnSafehousesChanged, OnSteamGameJoin, OnScoreboardUpdate [1] |
| Multiplayer server | OnClientCommand, OnServerStarted, OnServerStartSaving, OnServerFinishSaving, SendCustomModData, OnProcessAction, OnProcessTransaction [1] |
| Steam and workshop plumbing | OnSteamServerResponded, OnSteamRulesRefreshComplete, OnSteamWorkshopItemCreated, OnSteamWorkshopItemUpdated, OnServerWorkshopItems [1] |
| Deprecated on B41, absent on B42 | 32 events including OnRainStart, OnDawn, OnPreGameStart and OnMakeItem (listed in the Delta) [3] |
The events most mods use¶
Parameters are as declared in the B42 stubs unless a row says otherwise. A row tagged (B42) was not found in the B41 stubs [1] [2] [3].
| Event | Label in stub | Callback parameters | What the stub says it does |
|---|---|---|---|
Events.OnGameBoot |
none | none | Fires after the game finishes starting up; on clients, lua/server/ files have not run yet [1] |
Events.OnGameStart |
Client | none | Fires on finishing loading and entering the game [1] |
Events.OnLoad |
Client | none | Same description as OnGameStart [1] |
Events.OnNewGame |
Client | player, square |
A local player character was created for the first time [1] |
Events.OnCreatePlayer |
Client | playerIndex, player |
Fires every time a local player loads into the world [1] |
Events.OnInitGlobalModData |
none | newGame |
Earliest event after sandbox options load; newGame is true on a save's first start [1] |
Events.OnTick |
none | tick |
Every game tick [1] |
Events.OnTickEvenPaused |
none | tick |
Every game tick including while paused; tick is always zero while paused [1] |
Events.EveryOneMinute |
none | none | Every in-game minute [1] |
Events.EveryTenMinutes |
none | none | Every ten in-game minutes [1] |
Events.EveryHours |
none | none | Start of every in-game hour [1] |
Events.EveryDays |
none | none | 0:00 every in-game day [1] |
Events.OnPlayerUpdate |
Client | player |
Each local player's update, every tick [1] |
Events.OnZombieUpdate |
Client | zombie |
Whenever a zombie updates [1] |
Events.OnZombieDead |
none | zombie |
A zombie dies; loot is not yet filled and the corpse does not exist for a few seconds [1] |
Events.OnCharacterDeath |
none | character |
Any character dies, including zombies, players and animals [1] |
Events.OnPlayerDeath |
Client | player |
A local player dies [1] |
Events.OnWeaponHitCharacter |
Client | attacker, target, weapon, damage |
A character, zombie or player, is hit by a local player's attack (the 42.20.0 stub said non-zombie characters) [1] [11] |
Events.OnHitZombie |
none | zombie, attacker, bodyPart, weapon |
A character hits a zombie [1] |
Events.OnZombieCreate (B42) |
none | zombie |
A zombie is being spawned [1] |
Events.LoadGridsquare |
none | square |
After a new square loads [1] |
Events.OnObjectAdded |
none | object |
An object is added to the world; usually not called on a client [1] |
Events.OnFillWorldObjectContextMenu |
Client | playerIndex, context, worldObjects, test |
After a world context menu is filled [1] |
Events.OnFillInventoryObjectContextMenu |
Client | playerIndex, context, items |
After an inventory item context menu is filled [1] |
Events.OnKeyPressed |
Client | key |
Stub text says it fires when a key is released; OnKeyStartPressed is the press-down event [1] |
Events.OnPreDistributionMerge |
none | none | Distribution tables merge stage hook; its stub wording duplicates the post-merge text, so confirm order in-game [1] |
Events.OnPostDistributionMerge |
none | none | After the distribution tables have been merged [1] |
Events.OnEnterVehicle |
Client | character |
A character enters a vehicle [1] |
Events.OnClientCommand |
Server | module, command, player, args |
Server receives a command sent with sendClientCommand; args may be nil on B42 [1] |
Events.OnServerCommand |
Multiplayer, Client | module, command, args |
Client receives a command sent with sendServerCommand [1] |
Events.OnReceiveGlobalModData |
Multiplayer | key, data |
Receiving a global mod data table; data is false when none existed [1] |
Events.OnServerStarted |
Multiplayer, Server | none | The server started and can be connected to [1] |
Events.OnConnected |
Multiplayer, Client | none | Connected to a server from the main menu, before character creation [1] |
Setup-order facts the stubs document¶
The stubs give these ordering anchors and no more: OnGameBoot fires after
the game finishes starting up and, on a client, before lua/server/ files
have run [1]. OnInitGlobalModData is the earliest event after sandbox
options are loaded [1]. OnGameTimeLoaded fires after GameTime is
initialised and OnInitWorld after the world has initialised [1]. OnSave
fires after characters and sandbox options are saved but before global mod
data and the world are saved, and OnPostSave fires after saving and exiting
the game [1]. OnNewGame fires only on first creation of a local player
character, while OnCreatePlayer fires every time a local player loads in
[1]. The stubs do not publish a full ordering of these events relative to
each other [1].
LuaEventManager: custom events¶
The stubs (the LuaEventManager file is byte-identical between 42.20.0 and 42.21.0) expose LuaEventManager with LuaEventManager.AddEvent(name),
returning an Event, and LuaEventManager.triggerEvent(event, ...), which
takes the event name plus up to eight further parameters on both builds [4]
[5]. They also declare LuaEventManager.triggerEventGarbage (up to four
parameters on B42) and LuaEventManager.triggerEventUnique (one parameter)
[4] [5]. B42 additionally lists LuaEventManager.RunQueuedEvents,
LuaEventManager.getEvents, LuaEventManager.setEvents and an OnTickCallbacks
list that B41 does not list (B42) [4] [5]. The stubs say nothing about the
intended modder workflow for these calls, so see Claim 1 for the community
pattern [4].
B41 vs B42 Delta¶
Method: the KB's index extractor read the pinned Umbrella stubs for each build and the two event lists were compared as sets of names; callback alias text was compared per shared event [1] [2] [3] [9].
Counts¶
| Measure | B41 (41.78.16) | B42 (42.21.0) | B42 (42.20.0, for comparison) |
|---|---|---|---|
| Events declared | 240 [2] [3] | 244 [1] | 234 [11] |
| Of which current (non-deprecated) | 208 [2] | 244 [1] | 234 [11] |
Of which flagged @deprecated |
32 [3] | 0 [1] | 0 [11] |
| Names common to both builds | 205 [1] [2] [3] | 205 [1] [2] [3] | 203 [11] [2] [3] |
Added in B42 (39)¶
GrappleGrabCollisionCheck, GrapplerLetGo, LoadChunk, OnAlertMessage,
OnAnimalTracks, OnClickedAnimalForContext, OnContextKey,
OnDeadBodySpawn, OnDesignationZoneUpdatedNetwork,
OnFishingActionMPUpdate, OnGoogleAuthRequest, OnItemFound,
OnMouseWheel, OnNetworkUsersReceived, OnProcessAction,
OnProcessTransaction, OnQRReceived, OnRolesReceived,
OnServerCustomizationDataReceived, OnSleepingTick,
OnSourceWindowFileReload, OnSpawnVehicleEnd, OnSpawnVehicleStart,
OnSteamServerFailedToRespond2, OnWarUpdate, OnZombieCreate,
RefreshCheats, RenderOpaqueObjectsInWorld, SetDragItem, ViewBannedIPs
and ViewBannedSteamIDs (31 names present at 42.20.0), plus eight that first appear in the 42.21.0
stubs: AcceptedMedicalCheck, OnForagePool, OnForageRequestZone,
OnForageSpot, OnJoypadDebugRenderUIOptionSet,
OptionControllerButtonStyleChanged, OptionGamepadBindingPresetChanged and
RequestMedicalCheck [1] [2] [3] [11]. The 42.21.0 stub text describes the medical-check pair as
a target accepting a medical check request and a requester asking for one,
the three foraging events as a client receiving a foraging pool from the
server, the server receiving a request to send pools, and the server
receiving a client's report of a spotted icon, and the two option events as
changes to the controller button style and gamepad binding preset [1]. Several are plain thematic additions the
stubs describe: a grappler releasing its target, chunk loading, a spawning
zombie, a dead body spawning, a vehicle beginning and finishing its spawn,
and the context key being held for a duration [1]. Many others, such as
OnWarUpdate and OnItemFound, have no description in the stub [1].
Dropped from B42 (35)¶
32 are the B41 deprecated set: OnAIStateEnter, OnAIStateExecute,
OnAIStateExit, OnAddBuilding, OnBeingHitByZombie, OnChangeWeather,
OnCharacterCreateStats, OnCharacterMeet, OnDawn, OnDoTileBuilding,
OnDusk, OnIsoThumpableLoad, OnIsoThumpableSave, OnLoginState,
OnLoginStateSuccess, OnMakeItem, OnMapLoadCreateIsoObject,
OnNPCSurvivorUpdate, OnNewSurvivorGroup, OnPlayerSetSafehouse,
OnPostCharactersSquareDraw, OnPostFloorSquareDraw, OnPostTileDraw,
OnPostTilesSquareDraw, OnPostWallSquareDraw, OnPreGameStart,
OnRadioInteraction, OnRainStart, OnRainStop, OnRenderUpdate,
OnVehicleHorn and OnWorldMessage [3]. The remaining three were current on
B41 and are gone from the B42 stubs: OnGetDBSchema, OnGetTableResult
and OnServerStatisticReceived [2] [1]. Two more B41-current names,
OnFillInventoryContextMenuNoItems and OnPreFillInventoryContextMenuNoItems,
were missing from the 42.20.0 stubs (making that count 37 then) and are declared again in the
42.21.0 stubs, both labelled (Client) [11] [1]. The B41 stub text for
OnFillInventoryContextMenuNoItems warns the event is not properly
registered, so a mod must register it before adding its function [2]. Absence
from the B42 stubs shows the name is no longer declared; it does not prove the
engine stopped firing a same-named event [1].
Signature changes verified in the raw stubs¶
65 shared events have different alias text between builds (54 at 42.20.0) [1] [2] [3] [11]. Most are
notation (float and double became number; short became integer;
nullable ? became | nil; playerNum renamed playerIndex). The changes
that alter what a handler receives:
| Event | B41 callback | B42 callback |
|---|---|---|
Events.OnAmbientSound |
x, y, z as floats [2] |
name (string), x, y (B42) [1] |
Events.OnMechanicActionDone |
character, success, vehicleId, partType, itemId, installing [2] |
character, success only [1] |
Events.OnConnectionStateChanged |
state, message, optional place [2] |
state, message [1] |
Events.OnServerWorkshopItems |
type only [2] |
type, items, error, maxSize [1] |
Events.OnReceiveUserlog |
username, logs [2] |
adds suspiciousActivity table, typed as possibly nil at 42.21.0 (not nilable at 42.20.0) [1] [11] |
Events.OnPressRackButton |
player, weapon [2] |
adds a third shift parameter [1] |
Events.OnWeaponHitXp |
attacker, weapon, target, damage [2] |
adds a fifth hitcount parameter [1] |
Events.OnUseVehicle |
character (game character), vehicle, pressedNotTapped [2] |
player, vehicle; the pressedNotTapped boolean that 42.20.0 still declared is gone at 42.21.0 [1] [11] |
Events.OnDoTileBuilding3 |
cursor typed as the move cursor, optional square [2] |
cursor typed as the building object, square dropped [1] |
Events.OnDestroyIsoThumpable |
object [2] |
object plus a nil-typed player [1] |
Events.OnFETick |
no parameters [3] | one parameter unknown, described as always zero [1] |
Events.onItemFall |
no parameters [2] | item [1] |
Events.OnEquipPrimary |
item always an item [2] |
item may be nil [1] |
Events.OnConnectFailed |
message [2] |
message plus an optional detail string at 42.21.0 [1] [11] |
Events.OnScoreboardUpdate |
usernames, displayNames, steamIDs [2] |
adds a fourth pingValues list at 42.21.0 [1] [11] |
Events.AcceptedTrade |
accepted [2] |
target, requester, accepted at 42.21.0 [1] [2] |
Events.RequestTrade |
requester as a string [2] |
requester, target as players at 42.21.0 [1] [2] |
Events.ReceiveSafehouseInvite |
title, hostUsername [2] |
safehouse object, hostUsername, invitedUsername at 42.21.0 [1] [2] |
Stub changes between 42.20.0 and 42.21.0¶
Comparing the two B42 events.lua files [11] [1]: ten events were added and
none removed (the eight listed above plus OnFillInventoryContextMenuNoItems and
OnPreFillInventoryContextMenuNoItems). Besides the rows tagged above,
these callback or description changes appear: OnItemFound's third parameter is
renamed from amount to distanceTraveled; OnInitModdedWeatherStage
now documents its existing strength parameter; OnPlayerGetDamage
adds a "FIRE" damage type; OnSteamRulesRefreshComplete types rules as a
server-properties object; OnSpawnRegionsLoaded types regions as a list of
spawn regions; ReceiveFactionInvite now passes a faction object and an
invitedUsername; and the trading UI callbacks (TradingUIAddItem,
TradingUIRemoveItem, TradingUIUpdateState) gain a leading otherPlayer
parameter before player [1] [11]. The 42.21 patch notes list no event or callback change [12], so
these differences are known only from the stubs; whether the engine
changed in step with them (as opposed to the stubs being corrected) is not
established here. Handlers registered for the trading callbacks should be
re-checked, since a leading parameter shifts every later one [1] [11].
OnClientCommand, OnServerCommand and OnReceiveItemListNet also gained
nilable parameters in the B42 declarations [1] [2]. The OnFillWorldObjectContextMenu
and inventory context-menu events keep the same four and three parameters in
both builds, with the first parameter renamed [1] [2].
Practical Guidance¶
- Choose the narrowest event. Reach for
EveryTenMinutes,EveryHoursorEveryDayswhen the job is periodic, becauseOnTickandOnPlayerUpdatefire every tick [1]. - Keep a handle for removal.
Removetakes the callback, so register a named local function rather than an anonymous one if you ever need to unregister [1]. - Pick the right start-up event. Use
OnGameBootonly for things that must exist before gameplay and do not depend onlua/server/files; useOnGameStartorOnCreatePlayerfor per-session setup; reserveOnNewGamefor first-time character initialisation [1]. - Initialise saved data on
OnInitGlobalModData. It is the earliest hook after sandbox options are loaded, and itsnewGameflag distinguishes a fresh save [1]. - Branch on build when supporting both. For
OnMechanicActionDone,OnServerWorkshopItems,OnAmbientSoundand the others in the Delta table, write the handler to tolerate both parameter lists, or ship a version folder per build as described in modders-foundation [1] [2]. - Do not assume a label means safe on both sides. For an unlabelled event, test on a dedicated server and a client before shipping [1].
- Cross-reference. Command networking and API-surface depth are in modders-mp-networking-porting and modders-lua-api-surface; porting the rest of a mod is in modders-porting-b41-to-b42.
Common Pitfalls & Troubleshooting¶
- "My OnGameBoot handler never runs on the client." If the handler is
added from a file in
lua/server/, those files have not run yet whenOnGameBootfires on a client [1]. - "OnNewGame does not fire when I load my save." It fires only when a
local player character is created for the first time; use
OnCreatePlayerorOnGameStartfor every load [1]. - "The game stutters after I added my mod."
OnTick,OnTickEvenPaused,OnRenderTick,OnPlayerUpdateandOnZombieUpdaterun continuously, the last per zombie update [1]. Move non-urgent work to anEvery...event. - "A B41 handler gets nil or shifted arguments on B42." Compare against
the Delta table; for example
OnMechanicActionDonehas two parameters on B42 [1] [2]. - "OnZombieDead gave me an empty inventory." The stub says loot is not filled when it fires and the corpse does not exist for a few seconds [1].
- "OnKeyPressed fires on release." The stub text says exactly that;
use
OnKeyStartPressedorOnKeyKeepPressedfor press and hold [1]. - "A deprecated B41 event does nothing." The 32 deprecated names are not declared on B42 [1] [3].
- "My trading-UI handler gets the wrong player." At 42.21.0 the stubs declare
a leading
otherPlayerparameter on the three trading callbacks; older handlers written for the 42.20.0 shape read the wrong argument [1] [11]. - "I added an event handler on the server for a Client-labelled event." Nothing in the stubs says it will be called there [1].
Community Notes & Unverified Claims¶
Claim 1 — Mod authors create custom events with LuaEventManager.AddEvent and fire them with triggerEvent¶
- Claim: Modding guides and Discord answers describe a pattern in which a
mod registers its own event name once with
LuaEventManager.AddEvent, other mods then subscribe throughEvents.<YourName>.Add, and the owner mod fires it withtriggerEvent. - Why unverified: The stubs declare the functions [4] [5] but no primary
source found here shows the end-to-end pattern or confirms that a late
AddEventis visible toEvents. - Confidence: Low. It is plausible from the stub signatures but unproven against the game or a dev post.
Claim 2 — OnTick handlers are the main cause of mod-induced lag¶
- Claim: Performance threads in modding communities say per-tick handlers are the usual culprit for FPS drops in modded games.
- Why unverified: No primary benchmark was found; the stubs establish only how often these events fire [1]. See also modders-foundation Claim 2.
- Confidence: Low. Widely repeated but unmeasured.
Claim 3 — Unlabelled events run on both client and server¶
- Claim: Some community write-ups treat stub events with no
(Client)or(Server)label as available on both sides. - Why unverified: The stubs leave 90 B42 events unlabelled and do not state their behaviour on each side [1]; no dev statement was found.
- Confidence: Low. A reasonable default, not a guarantee.
Risks & Caveats¶
- Stale pin. Stubs are 42.21.0 and 41.78.16, while 41.78.21 legacy has shipped [7]. B41 events or signatures may have changed after 41.78.16, and later B42 hotfixes may change the list again.
- Stub changes without patch-note backing. The 42.20.0 to 42.21.0 callback differences come from the stubs only; the official notes name none of them [12].
- Stub text is not engine truth. Descriptions are written by
contributors; the generator named in the stub header is a community tool
[1] [10]. Wrong wording exists, as the
OnKeyPressedandOnPreDistributionMergeentries show [1]. - Blank entries. About 18 B42 stubs have no description sentence (KB script count), so their semantics are undocumented here [1].
- Counts are KB-derived. Totals come from the KB's extraction script run on the pinned stubs, not from a count published by the stub maintainers.
- Grouping is editorial. The purpose groups are this document's taxonomy.
Verification Steps¶
- Open the pinned
library/events.lua[1] and search forEvents.OnTick = {to see theAdd/Removeshape and the alias line above it. - Open the B41 files [2] [3] and confirm the deprecated set lives in
Events-deprecated.lua. - Diff the two name lists yourself; expect 39 added, 35 removed, 205 shared.
- In-game, register logging handlers on
OnGameBoot,OnGameStart,OnNewGameandOnCreatePlayer, then start a new and a loaded save and record the order. - Diff the B42
events.luaat58204fc[11] against13d01f9[1]; expect ten added events and no removals. Re-run against the next Umbrella release [9] when one exists.
Open Questions¶
- What do the roughly 18 undocumented B42 events actually pass and when do they fire? Resolve by reading decompiled callers or in-game logging.
- Did the engine change in step with the 42.21.0 stub differences (trading
callbacks,
OnUseVehicle,OnItemFound)? The patch notes list none [12]; resolve with in-game logging. - Did legacy41 re-enable
loadstring/loadstreamas 42.21 did for B42? No source read here says [7] [6] [12]. - Does a late
AddEventmakeEvents.<Name>available? See Claim 1. - Do unlabelled events fire on both client and server? See Claim 3.
References¶
Primary Sources — pinned Umbrella stubs, official announcements.
- [1] PZ-Umbrella — library/events.lua at Umbrella commit 13d01f9ee58fa48773553920db56d06f0005e7f8 (release 42.21.0). https://raw.githubusercontent.com/PZ-Umbrella/Umbrella/13d01f9ee58fa48773553920db56d06f0005e7f8/library/events.lua Accessed 2026-10-07.
- [2] PZ-Umbrella — library/Events/Events.lua at Umbrella commit fa2e7e19799740b57902f1cb4e989225c295c05e (release 41.78.16). https://raw.githubusercontent.com/PZ-Umbrella/Umbrella/fa2e7e19799740b57902f1cb4e989225c295c05e/library/Events/Events.lua Accessed 2026-10-07.
- [3] PZ-Umbrella — library/Events/Events-deprecated.lua at commit fa2e7e19799740b57902f1cb4e989225c295c05e. https://raw.githubusercontent.com/PZ-Umbrella/Umbrella/fa2e7e19799740b57902f1cb4e989225c295c05e/library/Events/Events-deprecated.lua Accessed 2026-10-07.
- [4] PZ-Umbrella — library/java/zombie/Lua/LuaEventManager.lua at commit 13d01f9ee58fa48773553920db56d06f0005e7f8 (identical to the 58204fc version). https://raw.githubusercontent.com/PZ-Umbrella/Umbrella/13d01f9ee58fa48773553920db56d06f0005e7f8/library/java/zombie/Lua/LuaEventManager.lua Accessed 2026-10-07.
- [5] PZ-Umbrella — library/Candle/zombie.Lua/LuaEventManager.lua at commit fa2e7e19799740b57902f1cb4e989225c295c05e. https://raw.githubusercontent.com/PZ-Umbrella/Umbrella/fa2e7e19799740b57902f1cb4e989225c295c05e/library/Candle/zombie.Lua/LuaEventManager.lua Accessed 2026-10-07.
- [6] The Indie Stone — Build 42.21 Stable Released (Steam Community announcement, 2026-09-28). https://steamcommunity.com/ogg/108600/announcements/detail/1844751498231307 — verified via the Steam news mirror [8]. Accessed 2026-10-07.
- [7] The Indie Stone — 42.20.4 STABLE & 42.19.2 UNSTABLE & 41.78.21 LEGACY Hotfixes Released (Steam Community announcement, 2026-08-26). https://steamcommunity.com/ogg/108600/announcements/detail/1842212951296601 — verified via the Steam news mirror [8]. Accessed 2026-10-07.
- [8] Valve — Steam News Web API (ISteamNews), app 108600. https://api.steampowered.com/ISteamNews/GetNewsForApp/v2/?appid=108600&count=40&maxlength=0 Accessed 2026-10-07.
-
[9] PZ-Umbrella — Umbrella releases (per-game-version tags). https://github.com/PZ-Umbrella/Umbrella/releases Accessed 2026-10-07.
-
[11] PZ-Umbrella — library/events.lua at the previous B42 pin, commit 58204fc47895ba249592519cedecc7cfbaaebd60 (42.20.0 stub set). https://raw.githubusercontent.com/PZ-Umbrella/Umbrella/58204fc47895ba249592519cedecc7cfbaaebd60/library/events.lua Accessed 2026-10-07.
- [12] The Indie Stone — 42.21 Patch Notes (TIS forum topic 101693, 2026-09-23). https://theindiestone.com/forums/topic/101693-4221-patch-notes/ Accessed 2026-10-07 (host bot-blocks checkers).
Fact-Only Sources (no prose reuse) — none used.
Secondary & Corroborating
- [10] demiurgeQuantified — PZEventDoc, the generator named in the stub header. https://github.com/demiurgeQuantified/PZEventDoc Accessed 2026-10-07.
Community & Creator — none.
Further Reading — see the Further Reading section.
Further Reading¶
- Unofficial B42 JavaDocs: https://albion.codeberg.page/PZ-JavaDocs/
- LuaDocs (game-side Lua, including events): https://demiurgequantified.github.io/ProjectZomboidLuaDocs/
Related Documents¶
- modders-foundation — toolchain and where the API truth lives.
- modders-lua-api-surface — what the objects passed to callbacks expose.
- modders-mp-networking-porting — client and server command flow.
- modders-porting-b41-to-b42 — wider porting checklist.
- modders-first-mod-tutorial-b42 — first mod using these events.
- modders-item-scripts-distributions — the distribution-merge events.
- modders-modinfo-modid-conventions — mod layout and IDs.
- modders-modoptions-pzapi — options API.
- players-crafting-chains — crafting content mods often hook.
- admins-workshop-mod-wiring — server-side mod deployment.
- meta-style-guide — how documents are written and gated.
Revision History¶
| Version | Date | Author | Change | Approved By |
|---|---|---|---|---|
| 0.1.0 | 2026-10-07 | KB Pipeline (virtual agent) | Initial draft. | — |
| 0.2.0 | 2026-10-07 | KB Pipeline (revision worker) | Re-baselined from 42.20.0 to 42.21: Umbrella pin moved to 13d01f9 (42.21.0); event counts, labels, added/dropped lists and signature tables recomputed (244 events; 10 added since 42.20.0); new 42.20.0 to 42.21.0 stub-change subsection; loadstring/loadstream re-enabled in 42.21 noted. Sources: Steam 42.21 stable and 42.20.4; TIS forum 42.21 patch notes; Umbrella 13d01f9 vs 58204fc. |
— |
| 1.0.0 | 2026-10-08 | Orchestrator (KB Pipeline) | Approved and frozen — release kb-release-2026.10.08 (42.21 re-baseline; validated against 42.21 and 41.78.21, Umbrella 42.21.0 @ 13d01f9). Content is the reviewed 0.2.0 text. | Project owner (user instruction 2026-10-08) |