cityrp.network
Clientside receiving, handshake, pull-on-visible resync and :ClientOwned() sends for the CityRP
networking library.
Storing values directly on the entity (sh_store.lua) retires the plugin this library replaces'
worst clientside bug for free: PLUGIN.NSVars[entIndex], keyed by raw index, was never cleared on
disconnect, so a recycled edict inherited whatever the previous occupant left behind. GMod hands a
newly-created entity a fresh Lua table regardless of which index it reuses, so ent.__netvars simply
does not exist yet for it -- there is nothing to clean up, and nothing here needs to try.
The gap that storage model leaves is timing. A value can arrive (via Update or Resync) referencing
an entity this client hasn't networked yet; those are buffered by raw index in pending until
OnEntityCreated produces the entity, and swept on a TTL in case it never does. And snapshots can
overtake net messages, so a value sent for a leaving player can arrive after the slot is empty or
already holds the next player. A player's index header carries their UserID for that: a value
for anyone but the slot's current or next occupant is dropped.
- Clientcityrp.network.AnnounceReady()Source ☍
-
Announces that this client's net channel is up and ready to receive the manifest.
- Servercityrp.network.ApplyAndSend(netvar, ent, value) → booleanSource ☍
-
Applies a value and, if
ApplyValue's delta guard says it changed, sends it.Parameters
Returns
- booleanWhether the value changed, and therefore whether an update was sent.
- Clientcityrp.network.ApplyIndexed(index, netvar, value, userid)Source ☍
-
Applies a decoded entity-scoped value, buffering it if the entity hasn't appeared yet. A player's value for an earlier occupant of the slot is dropped; one for a later occupant is buffered.
Parameters
- indexinteger
- netvarNetVar
- valueany
- useridinteger?The wire
UserIDof the player the value was sent for, or nil for a non-player entity.
- Clientcityrp.network.ApplyUnindexed(netvar, value)Source ☍
-
Applies a decoded no-index value: Global goes to the global table, LocalPlayer to
LocalPlayer().Parameters
- netvarNetVar
- valueany
- Sharedcityrp.network.ApplyValue(netvar, ent, value, predicted) → booleanSource ☍
-
Validates (if the var has an
:Enum()-setvalidatefunction), applies a value to storage, and fires the var's:SetHook()hook if the value changed. Shared by the server's ownSetNetVar/SetGlobal(sv_send.lua) -- so the server's own copy of a value updates immediately regardless of who receives the resulting net message, and so the delta guard that decides whether to bother networking at all lives in exactly one place -- and the client's receive path (cl_receive.lua), once an update has actually been decoded. for a client-side local apply the server has not confirmed, from either a:Predictable()or a:ClientOwned()var's client setter. SeeGenerateAccessorbelow.Parameters
- netvarNetVarThe var being applied.
- entEntity?The entity to store on. Ignored (may be nil) for Global scope.
- valueanyThe decoded value.
- predictedboolean?Passed through to the
:SetHook()hook as its 5th argument -- true only
Returns
- booleanWhether the value actually changed (false for a redundant re-set or a rejected invalid one).
- Clientcityrp.network.BufferPending(index, id, value, userid)Source ☍
-
Buffers a decoded value for an entity index that doesn't resolve to a valid entity yet. A value for a player replaces a buffer held for an earlier occupant of the slot, and is dropped if the buffer is already held for a later one.
Parameters
- indexinteger
- idinteger
- valueany
- useridinteger?The wire
UserIDof the player the value was sent for, or nil for a non-player entity.
- Servercityrp.network.ClearDebounce(owner)Source ☍
-
Drops every pending value and window for one owner. Called from
sv_send.lua's cleanup hooks.Parameters
- ownerEntityThe disconnecting player or removed entity.
- Clientcityrp.network.ClearPending(index)Source ☍
-
Drops everything buffered for
index.Parameters
- indexinteger
- Clientcityrp.network.ClientSet(name, value)Source ☍
-
Sets a
:ClientOwned()var on the local player: applies it locally, then asks the server to accept it. What the server receives is a claim, never a fact -- seedocs/networking.md.The generated
Set<Name>()calls this; use it directly for a var registered without:Accessor().Parameters
- namestringThe registered var name.
- valueanyThe new value.
nilclears it.
- Servercityrp.network.CollectSendableVars(ent, ply, names, revoke) → { netvar: NetVar, value: any }[]Source ☍
-
Collects this entity's currently-set entity-scoped vars (
IsEntityScope) thatplyis allowed to see. Global and LocalPlayer-scoped vars never go through resync -- Global is broadcast independently of any entity's visibility, and LocalPlayer is always pushed straight to its one owner. substitute, replacing it on their client. Defaults to true; only the join bootstrap passes false.Parameters
- entEntity
- plyPlayer
- namestable<string, boolean>?Only collect these var names. nil collects every set var.
- revokeboolean?Whether a
:Filter()ed varplyfails contributesGetRevokedValue's
Returns
- { netvar: NetVar, value: any }[]
- Servercityrp.network.CountInbound(ply) → booleanSource ☍
-
Counts one inbound message against
ply's budget and says whether to process it. Deliberately crude --:Debounce()is what actually makes client-owned vars safe, so this only ever fires for a client sending orders of magnitude more than a real one.Parameters
- plyPlayer
Returns
- booleanFalse if the message should be ignored.
- Servercityrp.network.DebounceSet(netvar, ent, value)Source ☍
-
Routes one server-side set through this var's debounce window. Called from
cityrp.network.Dispatch(sv_send.lua) for any var that declared:Debounce().Parameters
- Sharedcityrp.network.DecodeEntry() → NetVar?, any, booleanSource ☍
-
Reads one var entry written by
WriteVarEntry. On any decode failure the byte length of what follows is unknowable, so callers must stop reading rather than continue -- safe because a non-batchable entry is never batched with anything else.Returns
- 1NetVar?nil on failure.
- 2any
- 3booleanFalse if the rest of this message must be discarded.
- Servercityrp.network.DequeueEntity(ply, ent)Source ☍
-
Removes
entfromply's resync queue, clearingplyfrompendingPlayersif that empties it.Parameters
- Servercityrp.network.Dispatch(netvar, ent, value)Source ☍
-
The single seam every server-side set goes through, so
:Debounce()is one branch rather than a condition duplicated inSetNetVarandSetGlobal.Parameters
- Servercityrp.network.DrainOnePlayer(ply, take) → integerSource ☍
-
Drains up to
takeentities fromply's resync queue and sends whatever they're owed. A queue entry is a "re-evaluate me" marker, never a snapshot: no value and no recipient decision is captured when an entity is queued, only which vars to look at. Everything is read live here, so an entry queued several frames ago still sends the current value to whoever currently passes.Parameters
- plyPlayer
- takeinteger
Returns
- integerHow many queue entries were consumed (valid or not).
- Clientcityrp.network.DrainPending(ent)Source ☍
-
Applies any values buffered for
ent, now that it actually exists. A buffer held for a player other thanentis discarded.Parameters
- entEntity
- Servercityrp.network.DrainPendingDebounces()Source ☍
-
Applies any pending values whose windows have closed. On
Thinkrather than atimer.Simpleper pair, which would be a timer per player per var, each needing to re-validate its entity inside the callback (AGENTS.md footgun #2) for a routine mid-window disconnect. - Servercityrp.network.DrainResyncQueues()Source ☍
-
Drains every player's resync queue, round-robin, within the configured per-frame budgets. The cursor persists across frames (
drainCursorPly) so a player who was last in line this frame is first in line next frame -- with enough players queued to exceed the per-frame budget, this is what guarantees everyone is eventually served instead of the same players always winning the race. If the previous cursor's queue emptied out between frames, the round-robin simply restarts from the first candidate rather than trying to preserve a "position" a table with unstable iteration order can't actually promise -- a minor, self-correcting fairness wrinkle. - Servercityrp.network.EnqueueAllEntitiesForResync(ply, revoke)Source ☍
-
Queues every currently-known networked entity for resync to
ply. Used for the join bootstrap -- reusing the resync path means a large join gets the same per-frame rate limiting as any other resync, rather than a separate one-off bulk-send path to reason about and maintain. since a client holding a manifest from seconds ago has nothing stale to replace.Parameters
- plyPlayer
- revokeboolean?Passed through to
QueueEntity. Defaults to true;MarkReadypasses false,
- Sharedcityrp.network.FindVar(name) → NetVar?Source ☍
-
Looks up a registered var by name, logging (once per call, not once per name) if it isn't one. Shared by every public getter/setter so "unregistered name" fails the same way everywhere.
Parameters
- namestringThe var name to look up.
Returns
- NetVar?The registered var, or nil (and a logged error) if
nameisn't registered.
- Clientcityrp.network.FlushClientSets()Source ☍
-
Sends everything buffered while the manifest was outstanding. Called from the manifest receiver above, once
byId/idBitsare populated.The queue is swapped out before iterating: each apply runs the var's
:SetHook(), which may callClientSetagain, and adding a key mid-pairsis undefined in Lua. - Clientcityrp.network.FlushResyncRequests()Source ☍
-
Sends one batched resync request for every entity queued since the last flush.
- Sharedcityrp.network.GenerateAccessor(netvar)Source ☍
-
Defines
Get<Name>()(both realms) andSet<Name>()for a var registered with:Accessor(name), on the metatableACCESSOR_METATABLEmaps its scope to (Entity for Global/Entity scope, Player for Player/LocalPlayer, Vehicle/Weapon for those). A no-op for a var with no accessor name set. Idempotent -- safe to call more than once for the same var.Set<Name>()is server-only --SetNetVar/SetGloballive in the server-onlysv_send.lua-- unless the var opted into a client-side form::ClientOwned()applies locally and sends. Already vetted at seal byValidateClientOwned, so a var that failed has had the flag cleared and simply gets no setter here.:Predictable()applies locally only. Coherent for:SetLocalPlayer()alone, so a scope mismatch is a logged error rather than a silently-generated footgun.
Both pass
predicted = true-- the client is holding a value the server has not confirmed either way. Client-owned wins if a var chained both;ValidateClientOwnedhas already warned.Parameters
- netvarNetVarThe var to generate accessors for.
- Sharedcityrp.network.GenerateAccessors()Source ☍
-
Generates accessors for every currently-registered var. Called once from
Seal(), after which new registrations no longer occur -- seesh_registry.lua. - Sharedcityrp.network.GenerateEarlyAccessor(netvar)Source ☍
-
Installs
Get<Name>()(and the server'sSet<Name>()) at registration, so a caller running beforeSealfinds them. Re-run by:Accessor()and each scope setter because chain order is free; it removes what this var installed elsewhere. Client setters wait forGenerateAccessor.Parameters
- netvarNetVarThe var to install accessors for.
- Servercityrp.network.GetDebounceReport() → { owner: Entity?, netvar: NetVar, interval: number, pending: boolean, dispatches: integer }[]Source ☍
-
Every (owner, var) pair the debouncer is tracking, for
cityrp_network_dump. Includes settled pairs: without them the dump cannot tell a var that has never been set from one that has, which is exactly the question worth asking of a client-owned var that is not arriving.Returns
- Sharedcityrp.network.GetGlobal(name, default) → anySource ☍
-
Reads a Global-scoped networked value.
Parameters
- namestringThe registered var name.
- defaultanyReturned if the value has never been set, or on any error path.
Returns
- any
- Servercityrp.network.GetQueue(ply) → table<Entity, boolean|table<string, boolean>>Source ☍
-
Gets (creating if needed) a player's resync queue. A queue is a plain weak-keyed table of entities, not an ordered array. Photon's original resync queue is an array plus a drain cursor needing periodic "backlog reclamation" to stop the backing array growing forever; a weak-keyed table has no backing array to grow, and dropping an entity from it is an ordinary key removal. The trade-off is that iteration order (
pairs) is unspecified rather than FIFO, which is fine -- fairness across players already comes from the round-robin inDrainResyncQueues, not per-player ordering.Parameters
- plyPlayer
Returns
- table<Entity, boolean|table<string, boolean>>
- Servercityrp.network.GetRevokedValue(netvar) → anySource ☍
-
What to send a player who has stopped passing a
:Filter()ed var's check::SetDefault()'s value, or nil to clear it outright.Warning
A fixed substitute, not a per-player one -- every filtered-out player is told the same thing.
Parameters
- netvarNetVar
Returns
- any
- Sharedcityrp.network.GetSignedBits(value) → integerSource ☍
-
Number of bits required to write
valuewithnet.WriteInt, clamped to 1-32. Always reserves a sign-headroom bit -- without it, an exact power of two (e.g. 4, needing 3 unsigned bits) would not fit the signed range those same 3 bits provide (-4..3), silently truncating.Parameters
- valuenumberThe (integral) value that will be written.
Returns
- integerBits required, 1-32.
- Sharedcityrp.network.GetUnsignedBits(value) → integerSource ☍
-
Number of bits required to write
valuewithnet.WriteUInt, clamped to 1-32. UnlikeGetSignedBits, no sign-headroom bit is reserved -- callers must already knowvalueis non-negative.Parameters
- valuenumberThe (integral, non-negative) value that will be written.
Returns
- integerBits required, 1-32.
- Sharedcityrp.network.GetValueCodec(value) → NetCodecIdSource ☍
-
Determines which codec
Autoshould tag a value as. Mirrors the closed set bounded byAUTO_TAG_MAX-- every branch here must return an ID whose codec table entry actually exists and is self-contained (no extra argument required to read it back).Parameters
- valueanyThe value to classify.
Returns
- NetCodecIdThe codec ID to tag and write it with.
- Servercityrp.network.Invalidate(ply, ent, key)Source ☍
-
Re-evaluates
keyforply, delivering a value that has become visible and replacing one that has stopped being. Call it from whatever changed the eligibility; a filter is otherwise re-run only on a set or a PVS re-entry, neither of which is an authorization event.filter:GetPlayers(). Players mid-handshake are skipped. Global and LocalPlayer keys.Parameters
- Sharedcityrp.network.IsEntityScope(scope) → booleanSource ☍
-
Whether
scopestores on an entity and uses entity-index wire framing.Parameters
- scopeNetScopeWhere a
NetVar's value lives and who it is sent to by default.
Returns
- boolean
- scopeNetScopeWhere a
- Sharedcityrp.network.IsFloatValue(value) → booleanSource ☍
-
Whether a Lua number is non-integral. Written without GMod's
math.floor(value, 0)two-arg form this codebase's predecessor relied on -- the second argument is silently ignored either way.Parameters
- valuenumberThe number to check.
Returns
- booleanTrue if flooring
valuewould change it.
- Clientcityrp.network.IsLaterUserID(a, b) → booleanSource ☍
-
Whether wire
UserIDawas assigned afterb.UserIDonly climbs, but the wire carries it moduloUSERID_BITS, so this compares across the wrap.Parameters
- ainteger
- binteger
Returns
- boolean
- Sharedcityrp.network.IsNormalVector(vec) → booleanSource ☍
-
Whether a vector's components are all small enough to use the compact
Normalwire encoding. Checks magnitude, not raw value -- a component of -1000 must not qualify just for being < 1.Parameters
- vecVectorThe vector to check.
Returns
- booleanTrue if every component's magnitude is at most 1.
- Servercityrp.network.IsRecipientsEmpty(recipients) → booleanSource ☍
-
Whether a resolved recipient value (from
:Filter()/:SendOmit()) contains no one.Parameters
- recipientsCRecipientFilter|Player|Player[]|nilThe player metatable, with CityRP's own additions to Garry's Mod's
Player.
Returns
- boolean
- recipientsCRecipientFilter|Player|Player[]|nilThe player metatable, with CityRP's own additions to Garry's Mod's
- Servercityrp.network.MarkReady(ply)Source ☍
-
Completes a player's handshake: sends the manifest and initial bootstrap, marks them ready, and runs anything queued by
WaitForPlayer. Idempotent -- a client that re-announces before receiving anything back is a safe no-op.__netReadydoes not gate liveUpdate/Resyncsends (seeSendUpdate's own comment for why); it gates the server's willingness to accept a resync request from this player and to count them as a resync candidate, both of which would be meaningless before their manifest exists.Parameters
- plyPlayer
- Servercityrp.network.MergeQueueEntry(existing, incoming) → boolean|table<string, boolean>Source ☍
-
Merges an incoming queue entry into what is already queued, keeping whichever is broader on both of
NetResyncEntry's axes. Monotonic, so call order within a frame cannot narrow an entry.Parameters
- existing(boolean|table<string, boolean>)?What is already queued, or nil if nothing is.
- incomingboolean|table<string, boolean>The entry being added.
Returns
- boolean|table<string, boolean>The entry to store.
- Servercityrp.network.PassesRecipientCheck(netvar, ent, value, ply) → booleanSource ☍
-
Whether
plyshould receive this var's current value, for resync and bootstrap purposes. PVS/PAS are treated as bandwidth filters, not secrecy boundaries: they always pass here, because resync/bootstrap only ever consider a var for a player who is (or is about to be) in a position to receive it anyway. Only:Filter()can actually withhold a value from a specific player -- this is also why:Filter()'s callback doubles as the authorization check, rather than needing a second, separately-maintained predicate that could drift out of sync with the one used for live sends.Parameters
Returns
- boolean
- Servercityrp.network.QueueEntity(ply, ent, revoke)Source ☍
-
Adds
enttoply's resync queue for every var it has set, merging with anything already queued.GetRevokedValue's substitute. Defaults to true; only the join bootstrap passes false.Parameters
- Servercityrp.network.QueueEntityVars(ply, ent, names)Source ☍
-
Adds
enttoply's resync queue for only the named vars, merging with anything already queued.Warning
namesis stored by reference and must not be mutated afterwards -- one caller shares a single set across every pair it queues.Parameters
- Sharedcityrp.network.ReadAutoValue() → anySource ☍
-
Reads a value written by
WriteAutoValue.Returns
- anyThe decoded value, or nil if the tag was Nil.
- Clientcityrp.network.ReadIndexHeader() → boolean, integer?, integer?Source ☍
-
Reads an index header written by
WriteIndexHeaderin sv_send.lua: whether an entity index follows, the index itself if so, and the player's wireUserIDif it is a player's. Shared by the Update and Resync receivers below so this wire shape is decoded in exactly one place -- see the matchingWriteIndexHeaderfor why (AGENTS.md footgun #11: paired literals, or paired shapes, drift when edited independently).Returns
- 1boolean
- 2integer?
- 3integer?Only for a player's index.
- Sharedcityrp.network.ReadSignedComponent() → numberSource ☍
-
Reads one component written by
WriteSignedComponent.Returns
- numberThe decoded component.
- Servercityrp.network.RecipientsContain(recipients, ply) → booleanSource ☍
-
Whether
plyis a member of a resolved recipient value.Parameters
- recipientsCRecipientFilter|Player|Player[]|nilThe player metatable, with CityRP's own additions to Garry's Mod's
Player. - plyPlayer
Returns
- boolean
- recipientsCRecipientFilter|Player|Player[]|nilThe player metatable, with CityRP's own additions to Garry's Mod's
- Sharedcityrp.network.Register(name) → NetVarSource ☍
-
Registers a new network variable, or returns the existing one if
nameis already registered. Must be called before the registry seals (onInitialize) -- seeSealbelow.Parameters
- namestringThe variable's name. Must be unique.
Returns
- NetVarThe (possibly just-created)
NetVar, ready for chained configuration.
- Clientcityrp.network.RequestResync(ent)Source ☍
-
Queues
entfor resync, debounced to at most one request per frame regardless of how many entities become visible in that frame.Parameters
- entEntity
- Sharedcityrp.network.Seal()Source ☍
-
Seals the registry: assigns every var a stable numeric ID and locks out further registration. Only the server actually assigns IDs, by sorting registered names -- the client waits for the server's manifest to populate
byIdby name instead, so the two realms never need to agree on sort order or registration order. Safe to call more than once; later calls are no-ops. - Servercityrp.network.SendGlobalsAndLocal(ply, names, revoke)Source ☍
-
Sends every current Global value and
ply's own LocalPlayer-scoped values in one no-index group. The only path by which a Global value is re-delivered.Warning
LocalPlayer values skip the recipient check and cannot be revoked -- that scope is owner-only and its recipient mode is ignored everywhere.
GetRevokedValue's substitute. Defaults to true; only the join bootstrap passes false.Parameters
- plyPlayer
- namestable<string, boolean>?Only send these var names. nil sends everything.
- revokeboolean?Whether a Global var failing its
:Filter()check contributes
- Servercityrp.network.SendGroups(ply, groups)Source ☍
-
Sends a batch of
{ent, vars = {{netvar, value}, ...}}groups to one player as one or morecityrp.network.Resyncmessages, splitting on the byte threshold between groups. A non-batchable (custom-codec) var is never shared with any other entry -- it is always flushed into, and sent as, a message of its own -- so an undecodable custom value can only ever corrupt that one message, not a whole batch of unrelated vars riding alongside it.Parameters
- Servercityrp.network.SendManifest(ply)Source ☍
-
Sends the sealed registry as
id -> name/scope/codec/arg. Sent once per player, on their firstcityrp.network.Syncannounce -- seeMarkReadybelow. The ID width travels in the header so the two realms can never disagree about it, which is what keeps a load-order difference between them from corrupting every value the way it could in the plugin this library replaces. A Custom-coded var's realcodecArg(theoptpassed to its:Write()/:Read()) is whatever the registering plugin's own shared code chose -- not necessarily numeric, and not something the receiving client needs from the wire anyway, since decoding it already requires that client to have run the same local:Read(fn, opt)call. A placeholder0goes out instead of the real value so a non-numericoptcan never breaknet.WriteUInthere.Parameters
- plyPlayer
- Servercityrp.network.SendUpdate(netvar, ent, value)Source ☍
-
Sends a single var change. Resolves recipients before
net.Startso an empty:Filter()result skips networking entirely instead of leaving a started message with nowhere to send. Reaches every currently-connected player for Broadcast/PVS/PAS/Omit, including ones who haven't finished their handshake yet -- deliberately: filtering the recipient list down to "ready" players would mean reimplementing PVS/PAS membership in Lua just to exclude a few joining players from an engine call that already does that natively. Insteadcl_receive.luadiscards any Update/Resync payload before its own manifest has arrived, which costs that player nothing:MarkReadysends a full bootstrap right after the manifest, so a live update missed during the join race is already reflected in the state that bootstrap sends moments later.Parameters
- Servercityrp.network.SetGlobal(name, value)Source ☍
-
Sets a Global-scoped networked value and, if it changed, broadcasts it (subject to
:Filter()).Parameters
- namestringThe registered var name.
- valueanyThe new value.
nilclears it.
- Sharedcityrp.network.ValidateClientOwned(netvar)Source ☍
-
Checks a
:ClientOwned()var's constraints and clears the flag if it fails any, so the client setter is never generated rather than a var being writable in a shape nobody vetted.Runs at seal, not inside
:ClientOwned(): a chain sets its fields in whatever order it was written, so:ClientOwned():Bool():SetPlayer():Debounce(1)would see a default scope, a default codec and no debounce.:Predictable()defers its scope check for the same reason.Parameters
- netvarNetVarThe var to check. A no-op unless it called
:ClientOwned().
- netvarNetVarThe var to check. A no-op unless it called
- Servercityrp.network.WaitForPlayer(ply, fn)Source ☍
-
Runs
fn(ply)onceply's handshake has completed, or immediately if it already has.Parameters
- Servercityrp.network.WarnSuspectRegistrations()Source ☍
-
Warns once per var about a registration that configures cleanly but cannot do what it looks like it does. Called from
Seal, so each warning fires once per map load rather than once per send. - Sharedcityrp.network.WireUserID(ply) → integerSource ☍
-
A player's
UserIDas a player index header carries it: moduloUSERID_BITS, so both realms compare the same truncated value.Parameters
- plyPlayer
Returns
- integer
- Sharedcityrp.network.WriteAutoValue(value)Source ☍
-
Writes a value self-describingly: a codec tag, then the value via that codec. This is what backs both the
Autocodec and every key/value inside aTable.Parameters
- valueanyThe value to write.
nilwrites only the tag.
- valueanyThe value to write.
- Servercityrp.network.WriteIndexHeader(hasIndex, ent)Source ☍
-
Writes an index header: whether an entity index follows, and the index itself if so. Shared by every send path that needs this exact shape (
SendGroups's per-group header andSendUpdate's per-message header) so the wire format for "does this carry an index" is defined once -- see the matchingReadIndexHeaderincl_receive.lua(AGENTS.md footgun #11).A player entity's index is always within the engine's player-slot range, so
MAX_PLAYER_BITSis enough to encode it -- narrower than the generalENTITY_INDEX_BITS(MAX_EDICT_BITS) every non-player entity needs. Which width applies can't be inferred fromnetvar.scopealone -- a Player-scoped and an Entity-scoped var can share the same group/index header when they target the same physical player entity (SendGroupsgroups by entity, not scope) -- so the leadingisPlayerbool is checked against the entity itself, and travels on the wire since the reader doesn't haveentyet; it's what this index will construct.A player's header also carries their
UserID: snapshots can overtake net messages, so a value sent for a leaving player can land after a new player has taken the slot on the client.Parameters
- hasIndexboolean
- entEntity?Required (and used) only when
hasIndexis true.
- Sharedcityrp.network.WriteSignedComponent(component)Source ☍
-
Writes one signed vector/angle component, choosing between a raw float and a compact signed integer depending on which the value actually needs. Emits its own leading flag bit. Values outside the 32-bit signed integer range are forced onto the float path --
GetSignedBitsclamps to 32, which would otherwise silently truncate a huge whole-number component.Parameters
- componentnumberThe component to write.
- Sharedcityrp.network.WriteVarEntry(netvar, value)Source ☍
-
Writes one var entry:
[id][isNil][value?]. Used by the server's live Update and grouped Resync paths (sv_send.lua) and by the client'sClientSetsend (cl_receive.lua).Parameters
- netvarNetVar
- valueany
- ClientrecieveLPlyVarUpdate(length, ply)Source ☍
-
Internal function, for when a player's Local Player Var is updated.
Parameters
- lengthany
- plyany
- ClientrecieveNSVarBootstrap(length, svr)Source ☍
-
Internal function, for the batched spawn bootstrap of every player's NSVars. Reads (entity, key, type, value) entries until a continuation bit is false. Each entry has the exact same encoding as a single NSVar.Update, so this stays in lockstep with the server's batched send in sv_init.lua.
Parameters
- lengthnumberThe length of the net message.
- svrPlayer?An empty variable, to ensure this has been sent from the server.
- ClientrecieveNSVarClean(length, svr)Source ☍
-
Internal function, for when a player's NSVar is updated.
Parameters
- lengthany
- svrany
- ClientrecieveNSVarUpdate(length, svr)Source ☍
-
Parameters
- lengthany
- svrany
- Sharedcityrp.network.codecsSource ☍
-
Codec definitions, indexed by
NetCodecId. Each entry is{name, write, read, batchable}.write(value, arg)/read(arg)--argis the codec argument from theNetVar(bit width forInteger/UInteger, byte length forData), ignored by fixed-shape codecs.batchable = false(currently onlyCustom) marks a codec that can't safely share a batched message, since an undecodable value must not corrupt any entry after it -- seesv_send.lua.A
readmay return a second value,false, to declare the byte stream unsalvageable from there on -- onlyBoundedStringdoes, on a length prefix above its registered maximum.DecodeEntrychecks it with== false, since every other codec's second return isnil. - Sharedcityrp.network.ENTITY_LIKE_SCOPESSource ☍
-
Scopes whose value is stored on an entity and travels with an entity index on the wire, as opposed to Global (no entity at all) or LocalPlayer (never carries an index -- the recipient is implicit).
SetVehicle()/SetWeapon()behave exactly likeSetEntity()here; the only thing they change is:Accessor()'s target metatable. Consulted viaIsEntityScopebelow rather than repeating this set as an ad hocor-chain at every call site that cares -- adding a future metatable-specific scope (NPC, NextBot, ...) then only ever needs one line changed here.
- SharedNetCodecIdSource ☍
-
Numeric codec IDs. Freely renumberable -- unlike the manifest-assigned
NetVarIDs insh_registry.lua(which travel between realms and must never desync), these are never sent or persisted; both realms assign them identically from this shared file at every boot.Playeris inserted in the self-contained/fixed-argument block rather than appended soAUTO_TAG_MAXstays a simple contiguous bound. - SharedNetRecipientModeSource ☍
-
How a
NetVar's updates choose their recipients. - ServerNetResyncEntrySource ☍
-
What one entity's queued resync covers:
trueevery var, a name set only those,falseevery var with revokes suppressed.MergeQueueEntrycombines them. - SharedNetScopeSource ☍
-
Where a
NetVar's value lives and who it is sent to by default.
- Clientcityrp.networkSource ☍
- Clientcityrp.network.idBitsSource ☍
- Sharedcityrp.network.CODEC_ANGLESource ☍
- Sharedcityrp.network.CODEC_AUTOSource ☍
-
Meta codec: the value's shape is written to the wire as a per-value tag instead of being fixed by the manifest. Never chosen by
GetValueCodecas a nestedAuto/Tableentry's tag. - Sharedcityrp.network.CODEC_BITSource ☍
-
Raw single bit via
net.WriteBit/net.ReadBit, returning0/1rather than a real boolean. Declared-only, likeInteger/UInteger--Autoalready covers booleans viaCODEC_BOOL. - Sharedcityrp.network.CODEC_BOOLSource ☍
- Sharedcityrp.network.CODEC_BSTRINGSource ☍
-
Length-prefixed string, bounded to the
maxLenits:String(maxLen)registration declared. Declared-only:Autohas nomaxLento infer, which is also why this sits aboveAUTO_TAG_MAX. - Sharedcityrp.network.CODEC_BYTESource ☍
- Sharedcityrp.network.CODEC_COLORSource ☍
- Sharedcityrp.network.CODEC_CUSTOMSource ☍
-
User-supplied
:Write(fn, opt)/:Read(fn, opt). Cannot be described by the manifest, so vars using it are sent one per message rather than batched -- seesv_send.lua. - Sharedcityrp.network.CODEC_DATASource ☍
- Sharedcityrp.network.CODEC_DOUBLESource ☍
- Sharedcityrp.network.CODEC_ENTITYSource ☍
- Sharedcityrp.network.CODEC_FLOATSource ☍
- Sharedcityrp.network.CODEC_INTSource ☍
- Sharedcityrp.network.CODEC_INTEGERSource ☍
-
Explicit bit-width signed integer, 1-32 bits. Declared-only;
Autoalways prefers the fixed Nibble/Byte/Short/Int tiers instead, so a var must call:Integer(bits)to get this codec. - Sharedcityrp.network.CODEC_MAXSource ☍
- Sharedcityrp.network.CODEC_NIBBLESource ☍
- Sharedcityrp.network.CODEC_NILSource ☍
- Sharedcityrp.network.CODEC_NORMALSource ☍
- Sharedcityrp.network.CODEC_PLAYERSource ☍
-
Narrower counterpart to
CODEC_ENTITYfor a value known to be a player:net.WritePlayer/net.ReadPlayersize the index offMAX_PLAYER_BITS(the engine's own player-slot-count bound) instead of the widerMAX_EDICT_BITSevery other entity needs.GetValueCodecpicks this overCODEC_ENTITYautomatically whenever the value actually is a player. - Sharedcityrp.network.CODEC_SHORTSource ☍
- Sharedcityrp.network.CODEC_STRINGSource ☍
- Sharedcityrp.network.CODEC_TABLESource ☍
- Sharedcityrp.network.CODEC_UBYTESource ☍
- Sharedcityrp.network.CODEC_UINTSource ☍
- Sharedcityrp.network.CODEC_UINTEGERSource ☍
- Sharedcityrp.network.CODEC_UNIBBLESource ☍
- Sharedcityrp.network.CODEC_USHORTSource ☍
- Sharedcityrp.network.CODEC_VECTORSource ☍
- Sharedcityrp.network.byIdSource ☍
-
Registered vars by their sealed numeric ID. Empty until
Sealruns (server: immediately, from its own sort; client: incrementally, as manifest entries arrive -- seecl_receive.lua). - Sharedcityrp.network.ENTITY_INDEX_BITSSource ☍
-
Bits used to write/read an entity index on the wire for Entity/Player-scoped vars.
MAX_EDICT_BITSis the engine's own answer to "how many bits does any entity index need" (whatnet.WriteEntityitself is sized on), so this is guaranteed correct for whatever the server's actual edict limit is, rather than a separately-guessed "safely large" literal that could drift from the real limit. - Sharedcityrp.network.NETVARSource ☍
-
A registered network variable, mid-configuration or sealed. Every field below is set through the chained builder methods; construct with
cityrp.network.Register, never withsetmetatabledirectly. - Sharedcityrp.network.RECIPIENT_BROADCASTSource ☍
- Sharedcityrp.network.RECIPIENT_FILTERSource ☍
- Sharedcityrp.network.RECIPIENT_OMITSource ☍
- Sharedcityrp.network.RECIPIENT_PASSource ☍
- Sharedcityrp.network.RECIPIENT_PVSSource ☍
- Sharedcityrp.network.registrySource ☍
-
Registered vars by name. Populated by
cityrp.network.Register, consumed bySeal. - Sharedcityrp.network.RESYNC_GROUP_OVERHEAD_BITSSource ☍
-
Approximate extra bits a mapped-index
:Enum()(CODEC_CUSTOM) costs per resync versus a batchable one, assuming worst case: its ownWriteIndexHeaderplus the group/var/end framing boolsSendGroupsadds around a non-batchable entry -- seesv_send.lua. Deliberately a little above the literal ~20-bit tally, so a marginal bit saving isn't enough to justify losing batchability (see:Enum()). - Sharedcityrp.network.SCOPE_ENTITYSource ☍
- Sharedcityrp.network.SCOPE_GLOBALSource ☍
-
Stored in the library, not on any entity; has no owning entity at all.
- Sharedcityrp.network.SCOPE_LOCALPLAYERSource ☍
-
Stored on the owning player; sent only to that player, never broadcast.
- Sharedcityrp.network.SCOPE_PLAYERSource ☍
- Sharedcityrp.network.SCOPE_VEHICLESource ☍
-
Storage and wire format identical to
SCOPE_ENTITY-- only:Accessor()'s generated methods differ, attaching toFindMetaTable("Vehicle")instead ofFindMetaTable("Entity"). - Sharedcityrp.network.SCOPE_WEAPONSource ☍
- Sharedcityrp.network.sealedSource ☍
-
Whether the registry has sealed.
Registerafter this point is an error. - Sharedcityrp.network.sortedIdsSource ☍
-
Every assigned ID, in order. Populated once by
Seal(server only -- the client never assigns its own IDs) so repeat consumers likeSendManifestandcityrp_network_dumpdon't each rebuild and sort this frombyIdon every call to a value that cannot change after sealing. - Sharedcityrp.network.CODEC_ARG_BITSSource ☍
-
Bits used to write a manifest entry's codec argument (bit width, byte length, etc).
- Sharedcityrp.network.CODEC_BITSSource ☍
-
Bits used to write a
NetCodecIdvalue. - Sharedcityrp.network.globalsSource ☍
-
Global-scoped values, by name. Entity/Player/LocalPlayer-scoped values live on the entity itself instead -- see the
Entity.__netvarsfield below. - Sharedcityrp.network.MANIFEST_COUNT_BITSSource ☍
-
Bits used to write the manifest's entry count.
- Sharedcityrp.network.MANIFEST_IDBITS_FIELDSource ☍
-
Fixed-width wire format constants shared between
sv_send.luaandcl_receive.lua. Defined once here, rather than as literals repeated on both realms, so the two can never drift apart -- see AGENTS.md footgun #11 (client/server-paired literals must be edited together). Bits used to writecityrp.network.idBitsitself in the manifest header. - Sharedcityrp.network.RESYNC_COUNT_BITSSource ☍
-
Bits used to write how many entity indices a resync request contains.
- Servercityrp.network.resyncQueuesSource ☍
-
Per-player resync queues:
ply -> {[Entity] = NetResyncEntry}. Both axes are weak so a disconnect or an entity removal cleans itself up even if the explicitPlayerDisconnected/EntityRemovedhooks below somehow miss it (which, per AGENTS.md footgun #3, a third-partyhook.Addon the same event returning non-nil first genuinely could) -- seeGetQueue's note for why this is a plain weak-keyed set rather than an ordered array. - Sharedcityrp.network.SCOPE_BITSSource ☍
-
Bits used to write a
NetScopevalue. - Sharedcityrp.network.USERID_BITSSource ☍
-
Bits used to write the
UserIDa player's index header carries.UserIDonly climbs, so the wire carries it modulo this width, throughcityrp.network.WireUserID. - Servercityrp.network.waitQueueSource ☍
-
Callbacks waiting on a player's handshake to finish.
WaitForPlayerqueues here; cleared (and run) once that player's manifest and bootstrap have been sent. - Servercityrp_networkSource ☍
- SharedNETTYPE_ANGLESource ☍
- SharedNETTYPE_BITSource ☍
- SharedNETTYPE_BOOLSource ☍
- SharedNETTYPE_BYTESource ☍
-
Signed 8 bit.
- SharedNETTYPE_COLORSource ☍
- SharedNETTYPE_DATASource ☍
- SharedNETTYPE_ENTSource ☍
- SharedNETTYPE_FLOATSource ☍
-
32 bit floating point value.
- SharedNETTYPE_INTSource ☍
-
Signed 32 bit.
- SharedNETTYPE_LONGSource ☍
-
Signed 64 bit.
- SharedNETTYPE_MAXSource ☍
-
Increment this value if you add additional types.
- SharedNETTYPE_NIBBLESource ☍
-
Signed 4 bit.
- SharedNETTYPE_NILSource ☍
- SharedNETTYPE_NORMSource ☍
- SharedNETTYPE_SHORTSource ☍
-
Signed 16 bit.
- SharedNETTYPE_STRSource ☍
- SharedNETTYPE_TABSource ☍
- SharedNETTYPE_UBYTESource ☍
-
Unsigned 8 bit.
- SharedNETTYPE_UINTSource ☍
-
Unsigned 32 bit.
- SharedNETTYPE_ULONGSource ☍
-
Unsigned 64 bit.
- SharedNETTYPE_UNIBBLESource ☍
-
Unsigned 4 bit.
- SharedNETTYPE_USHORTSource ☍
-
Unsigned 16 bit.
- SharedNETTYPE_UXLONGSource ☍
-
Unsigned 128 bit.
- SharedNETTYPE_VECSource ☍
- SharedNETTYPE_XLONGSource ☍
-
Signed 128 bit.
codecIds
Scopes
wireConstants
A registered network variable, mid-configuration or sealed.
Every field below is set through the chained builder methods; construct with
cityrp.network.Register, never with setmetatable directly.
Functions
- SharedNetVar:Accessor(name) → NetVarSource ☍
-
Generates
Get<name>()(both realms) andSet<name>()(server only), attaching to the metatable that best matches this var's scope --FindMetaTable("Player")for:SetPlayer()/:SetLocalPlayer(),FindMetaTable("Vehicle")/FindMetaTable("Weapon")for those, andFindMetaTable("Entity")otherwise -- seesh_store.lua'sGenerateAccessorfor why that distinction exists.Parameters
- namestringSuffix for the generated method names.
Returns
- NetVarFor chaining.
- SharedNetVar:AutoHook() → NetVarSource ☍
-
Shorthand for
:SetHook()that derives the hook name from the var's own name, for the common case of not caring what it's called --"CityRP.Network." .. name .. ".Changed", matching this codebase's existingCityRP.<Module>.<Event>hook naming (CityRP.DayNight.PeriodChanged,CityRP.Networking.Register, etc).Returns
- NetVarFor chaining.
- SharedNetVar:Broadcast() → NetVarSource ☍
-
Sends updates to every player (the default for every scope except LocalPlayer, which is always owner-only regardless of this setting).
Returns
- NetVarFor chaining.
- SharedNetVar:ClientOwned() → NetVarSource ☍
-
Lets a client set this var on its own player:
Set<Name>()appears on the client, applying locally then sending, and the server applies it through the ordinarySetNetVarpath so recipient rules and the:Enum()validator still hold.cityrp.network.ClientSetis the same without an accessor.What arrives is a claim, never a fact -- never gate permissions, economy or anti-cheat on one. See
docs/networking.md.Constraints are checked at seal, not here: a builder chain sets its fields in any order, so none of them exist yet. See
ValidateClientOwned.Returns
- NetVarFor chaining.
- SharedNetVar:Data(maxLen) → NetVarSource ☍
-
Fixed-length byte string. Pads short values with
\0to exactlymaxLenand costs that much regardless; for text use:String(maxLen)above.Parameters
- maxLenintegerByte length. Both realms must agree on this value; it also travels in the manifest.
Returns
- NetVarFor chaining.
- SharedNetVar:Debounce(seconds, ceiling) → NetVarSource ☍
-
Coalesces sets to at most one change per
seconds: a set in a quiet period dispatches immediately, one inside the window overwrites a single pending slot. The apply is debounced too, so server-side reads lag by up toseconds.ceilingreserves the shape for adaptive backoff without enabling it -- omitted, it equalssecondsand the interval never moves. Required by:ClientOwned(). Seedocs/networking.md.Parameters
- secondsnumberMinimum seconds between dispatches. Must be positive.
- ceilingnumber?Upper bound for adaptive backoff. Defaults to
seconds, i.e. no escalation.
Returns
- NetVarFor chaining.
- SharedNetVar:Enum(list) → NetVarSource ☍
-
Declares this var as an enum over
list, a sequential (ipairs-ordered) array of its legal values. Picks between two wire strategies by comparing their actual bit cost:- Direct value (batchable):
listis entirely integers. The value itself goes on the wire, sized to its min/max via:Integer/:UInteger-- signed only ifminis negative. No offset fromminis applied even when every value shares a large common magnitude (e.g.{100,101}) -- an offset would itself need aCODEC_CUSTOMclosure, exactly the cost this path avoids. - Mapped index (not batchable): the value's index in
listgoes on the wire instead, via an auto-generated:Write()/:Read()pair sized to#list. Cheaper for a small set of large-magnitude or widely-spread values, at the cost ofCODEC_CUSTOM-- never sharing a resync message with sibling vars on the same entity.
For an all-integer
list, the mapped index is used only if it beats the direct-value encoding by more thanRESYNC_GROUP_OVERHEAD_BITS. Alistcontaining anything non-integer always uses the mapped index; there is no numeric value to size a direct encoding from.Either way,
Setting a value not present inlistis rejected -- logged, not stored/sent -- byApplyValue'svalidatecheck.nil(clearing the var) always bypasses this check.Parameters
- listany[]The enum's legal values, in wire-assignment order. Must be non-empty; a mapped-index list must also have no duplicates.
Returns
- NetVarFor chaining.
- Direct value (batchable):
- SharedNetVar:Filter(fn) → NetVarSource ☍
-
Sends updates only to whoever
fnreturns, and doubles as the authorization check used by resync and late-join sync -- seesv_send.lua. Keepfncheap and side-effect free: it can run once per update and again per resync candidate.Parameters
- fnfun(ent: Entity, value: any):CRecipientFilter|Player|Player[]|nilRecipients, or nil for none.
Returns
- NetVarFor chaining.
- SharedNetVar:Integer(bits) → NetVarSource ☍
-
net.WriteInt/net.WriteUIntonly accept 1-32 bits -- the plugin this library replaces declared 64- and 128-bit integer types that could never actually be written.:Long()below is the closest working replacement for those call sites, not a wider integer.Parameters
- bitsintegerBit width, 1-32.
Returns
- NetVarFor chaining.
- SharedNetVar:Long() → NetVarSource ☍
-
Widest integer GLua numbers can actually represent exactly (2^53). An alias of
:Double()-- there is no true 64-bit integer codec, because a Lua number cannot hold one losslessly regardless of how it is framed on the wire.Returns
- NetVarFor chaining.
- SharedNetVar:Predictable() → NetVarSource ☍
-
Allows client-side prediction:
:Accessor()'s generatedSet<Name>()becomes available on the CLIENT too, applying locally (storage +:SetHook()only -- never a network send, the client has no authority to send) instead of being server-only. A later confirmed value -- whether that same client's predicted action being confirmed, or an unrelated server-side change -- arrives through the normal decode path and overwrites the locally-applied one, correcting any drift.Only meaningful for
:SetLocalPlayer()-- a client predicting some other entity's state isn't coherent, so:Accessor()logs an error and skips generating the client setter on a scope mismatch rather than silently letting a broadcast/entity-scoped var be mutated client-side with nothing to correct it.Returns
- NetVarFor chaining.
- SharedNetVar:Read(readFn, opt) → NetVarSource ☍
-
Sets a custom deserializer to pair with
:Write().Parameters
- readFnfun(arg: any):anyCalled with
optto read the value back. - optanyPassed through as
arg; typically the same value given to:Write().
Returns
- NetVarFor chaining.
- readFnfun(arg: any):anyCalled with
- SharedNetVar:SendOmit(fn) → NetVarSource ☍
-
Sends updates to everyone except whoever
fnreturns (net.SendOmit).Parameters
Returns
- NetVarFor chaining.
- SharedNetVar:SendPAS() → NetVarSource ☍
-
Sends updates only to players who can potentially hear the entity's position (
net.SendPAS). Same bandwidth-not-secrecy caveat as:SendPVS().Returns
- NetVarFor chaining.
- SharedNetVar:SendPVS() → NetVarSource ☍
-
Sends updates only to players who can potentially see the entity's position (
net.SendPVS). Treated as a bandwidth filter, not a secrecy boundary: resync always includes a PVS var, because the client is asking precisely because the entity just entered its PVS. Use:Filter()for anything that must not reach a player at all.Returns
- NetVarFor chaining.
- SharedNetVar:SetDefault(value) → NetVarSource ☍
-
Sets the value
Entity:GetNetVar/cityrp.network.GetGlobalreturns before anything is set.Parameters
- valueanyThe default value.
Returns
- NetVarFor chaining.
- SharedNetVar:SetEntity() → NetVarSource ☍
-
Scopes this var to a single entity (the default scope).
Returns
- NetVarFor chaining.
- SharedNetVar:SetGlobal() → NetVarSource ☍
-
Scopes this var globally -- one value, no owning entity. Use
cityrp.network.SetGlobal/GetGlobalrather than an entity method.Returns
- NetVarFor chaining.
- SharedNetVar:SetHook(hookName) → NetVarSource ☍
-
Runs
hook.Run(hookName, ent, newValue, oldValue, predicted)on both realms whenever this var changes.predictedistrueonly for a client-side local apply from a:Predictable()var's clientSet<Name>(); every other trigger (a normal serverSet, or either realm decoding a confirmed value off the wire) passesnil.Parameters
- hookNamestringThe hook name to run.
Returns
- NetVarFor chaining.
- SharedNetVar:SetLocalPlayer() → NetVarSource ☍
-
Scopes this var to a single owning player's private state. Never broadcast: sent only to the owner via
net.Send(ply), regardless of any:Filter()/:SendPVS()call. Like:SetPlayer(),:Accessor()attaches toFindMetaTable("Player").Returns
- NetVarFor chaining.
- SharedNetVar:SetNoSync() → NetVarSource ☍
-
Excludes this var from join sync and resync -- it is only ever pushed on change. Use for fire-and-forget events rather than durable state; a client that was out of PVS during the push will never receive it.
Returns
- NetVarFor chaining.
- SharedNetVar:SetPlayer() → NetVarSource ☍
-
Scopes this var to a player. Storage/wire format are identical to
:SetEntity()-- a player is an entity -- but:Accessor()attaches toFindMetaTable("Player")rather than Entity's, so a same-named method Player's own metatable already defines natively can't shadow it.Returns
- NetVarFor chaining.
- SharedNetVar:SetVehicle() → NetVarSource ☍
-
Scopes this var to a vehicle. Storage/wire format identical to
:SetEntity(); only:Accessor()'s target metatable (FindMetaTable("Vehicle")) differs -- see:SetPlayer().Returns
- NetVarFor chaining.
- SharedNetVar:SetWeapon() → NetVarSource ☍
-
Scopes this var to a weapon. Same rationale as
:SetVehicle(), targetingFindMetaTable("Weapon")instead.Returns
- NetVarFor chaining.
- SharedNetVar:String(maxLen) → NetVarSource ☍
-
Text. With no argument,
net.WriteString/net.ReadString-- null-terminated, so the writer picks the length. WithmaxLen, a length prefix sized tomaxLenthen exactly that many bytes: no padding, and the read length comes from this registration rather than the wire, which is why it is the only string form:ClientOwned()accepts. Over-length is logged either way, never silently dropped (sh_codecs.lua).maxLencounts bytes, so truncation can split a character.Parameters
- maxLeninteger?Maximum byte length, 1 to
(2 ^ CODEC_ARG_BITS) - 1. Omit for the unbounded form.
Returns
- NetVarFor chaining.
- maxLeninteger?Maximum byte length, 1 to
- SharedNetVar:UInteger(bits) → NetVarSource ☍
-
Unsigned counterpart to
:Integer(bits). Same 1-32 bit range and the same fallback on misuse.Parameters
- bitsintegerBit width, 1-32.
Returns
- NetVarFor chaining.
- SharedNetVar:Write(writeFn, opt) → NetVarSource ☍
-
Sets a custom serializer, bypassing the built-in codec table. Because the manifest cannot describe an arbitrary function, vars using this are sent one per message rather than batched -- see
sv_send.lua.Parameters
- writeFnfun(value: any, arg: any)Called with the value (and
opt) to write it. - optanyPassed through to
writeFn/the matching:Read()call asarg.
Returns
- NetVarFor chaining.
- writeFnfun(value: any, arg: any)Called with the value (and
Fields
- SharedNetVar.__indexSource ☍
-
A registered network variable, mid-configuration or sealed. Every field below is set through the chained builder methods; construct with
cityrp.network.Register, never withsetmetatabledirectly. - SharedNetVar.accessorNameSource ☍
-
If set, generates
Get<Name>()/Set<Name>()(setter server-only unlesspredictable) on the metatable:Accessor()'s scope maps to -- seesh_store.lua'sGenerateAccessor. - SharedNetVar.AngleSource ☍
- SharedNetVar.AutoSource ☍
-
Explicitly requests the self-describing codec (the default when no codec method is called).
- SharedNetVar.BitSource ☍
- SharedNetVar.BoolSource ☍
- SharedNetVar.ByteSource ☍
- SharedNetVar.clientOwnedSource ☍
-
If true,
:Accessor()generates a client-sideSet<Name>()that applies locally and sends to the server -- see:ClientOwned(). Cleared at seal if the var failsValidateClientOwned. - SharedNetVar.codecSource ☍
-
The wire codec.
CODEC_AUTOunless a codec constructor was called. - SharedNetVar.codecArgSource ☍
-
Codec-specific argument (bit width for Integer/UInteger, byte length for Data).
- SharedNetVar.ColorSource ☍
- SharedNetVar.customReadSource ☍
-
Set by
:Read(); used whencodec == CODEC_CUSTOM. - SharedNetVar.customWriteSource ☍
-
Set by
:Write(); used whencodec == CODEC_CUSTOM. - SharedNetVar.debounceCeilingSource ☍
-
Upper bound for adaptive backoff. Equal to
debounceIntervalunless:Debounce()was given a second argument, in which case escalation is enabled. - SharedNetVar.debounceIntervalSource ☍
-
Minimum seconds between dispatches, and the floor an adaptive interval resets to -- see
:Debounce(). - SharedNetVar.defaultSource ☍
-
The value
Entity:GetNetVarreturns before anything has been set. - SharedNetVar.DoubleSource ☍
-
64-bit IEEE double via
net.WriteDouble. Also the target for:Long()-- see below. - SharedNetVar.EntitySource ☍
- SharedNetVar.enumListSource ☍
-
The list passed to
:Enum(), kept for introspection (cityrp_network_dump). - SharedNetVar.FloatSource ☍
- SharedNetVar.hasDefaultSource ☍
-
Whether
:SetDefault()was called. - SharedNetVar.hookNameSource ☍
-
Hook run on change, both realms:
hook.Run(hookName, ent, newValue, oldValue, predicted). - SharedNetVar.idSource ☍
-
Assigned at seal.
nilbefore the registry seals. - SharedNetVar.IntSource ☍
- SharedNetVar.nameSource ☍
-
The registered name. Unique; this is what travels in the manifest.
- SharedNetVar.NibbleSource ☍
- SharedNetVar.NilSource ☍
- SharedNetVar.NormalSource ☍
-
Compact vector codec for components known to stay within +/-1 (e.g. a direction). A component outside that range still encodes correctly, just without the compact path's benefit.
- SharedNetVar.noSyncSource ☍
-
If true, excluded from join sync and resync -- push-only.
- SharedNetVar.PlayerSource ☍
-
Narrower than
:Entity()for a value known to always be a player: sizes the index offMAX_PLAYER_BITSinstead of the widerMAX_EDICT_BITSevery other entity needs.:Auto()already picks this over:Entity()on its own whenever the value actually is a player, so this constructor is for declaring the narrower shape explicitly up front, not required for the saving. - SharedNetVar.predictableSource ☍
-
If true,
:Accessor()also generates a client-sideSet<Name>()that applies locally (storage + hook only, no network send) instead of being server-only -- see:Predictable(). - SharedNetVar.recipientFnSource ☍
-
Backing function for
:SendOmit()/:Filter(). - SharedNetVar.recipientModeSource ☍
-
How a
NetVar's updates choose their recipients. - SharedNetVar.scopeSource ☍
-
Where the value is stored and who receives it by default.
- SharedNetVar.ShortSource ☍
- SharedNetVar.TableSource ☍
- SharedNetVar.UByteSource ☍
- SharedNetVar.UIntSource ☍
- SharedNetVar.UNibbleSource ☍
- SharedNetVar.UShortSource ☍
- SharedNetVar.validateSource ☍
-
Optional value validator, set by
:Enum(). Checked by - SharedNetVar.VectorSource ☍