ISource2ModTransmit

Interface for deciding which entities each player receives.

Every tick the server works out, per player, the set of entities to send (CheckTransmit). This interface sits after that decision and takes entities back out of it:

  • an entity is hooked once, and from then on has a visibility per viewer -- hidden from some players, shown to others, with up to eight independent "channels" so two features (a !hide command, a spectator mode, a team-only marker) can each hide the same entity without stepping on each other's toes: the entity shows only when no channel hides it;
  • a player is hidden through their controller: hiding a controller from a viewer hides the pawn that controller is driving, the observer pawn and a dead player pawn, while the controller itself stays -- the scoreboard keeps working;
  • an entity can be tied to an owner entity, and then disappears wherever its owner is hidden (a player's weapons, a beam attached to them);
  • BlockAll takes an entity away from everybody, the one-line "server-side only" switch;
  • and for anything that does not fit the model, HookCheckTransmit() hands over each viewer's transmit set, wrapped, so a plugin never has to lay out CCheckTransmitInfo itself.

Hiding is done the way the client expects: the entity leaves the transmit set and is put on the "non-transmitted" list at the same time, so the client keeps a record of it while it is hidden and takes it back without the "missing client entity" crash when it comes back. Both of those bits are what ISource2ModTransmitInfo::BlockTransmit() does.

Everything here belongs on the main thread.

Interface id ISource2ModTransmit002 (SOURCE2MOD_TRANSMIT_INTERFACE) · Global g_pSource2ModTransmit · Header source2mod/ISource2ModTransmit.h

Types

Source2ModTransmitHookId

using Source2ModTransmitHookId = Source2ModHookId;

A CheckTransmit hook (HookCheckTransmit).

CheckTransmitHook

using CheckTransmitHook = Source2ModCallback<void(ISource2ModTransmitInfo* const* infos, int infoCount, const uint16_t* entityIndices, int entityCount)>;

Hook called once per CheckTransmit, after Source2Mod has applied the hooked entities' visibility.

Runs every tick for every viewer, so do the expensive part (who owns what, who is on which team) once at the top and only the bit work per viewer.

Methods

HookEntity

virtual bool HookEntity(PluginId owner, CEntityInstance* entity, bool defaultVisible = true) = 0;

Puts an entity under this interface's control.

Until an entity is hooked, the setters below refuse it and it is sent as the engine decides. The hook goes away with the entity, with the plugin, or with UnhookEntity().

Hook a player's controller, not their pawn: a controller's visibility is applied to whatever pawn it is driving. Pawns are refused.

ParameterTypeDefaultDescription
ownerPluginIdPlugin ID that owns the hook
entityCEntityInstance*Entity to hook
defaultVisiblebooltrueWhether viewers see it until told otherwise. false is for "personal" entities: hidden from everybody, then SetVisible(entity, ownerSlot, true).

Returns bool — false when the entity is a pawn, already hooked, or about to be deleted.

UnhookEntity

virtual void UnhookEntity(CEntityInstance* entity) = 0;

Forgets an entity: sent as the engine decides from now on.

ParameterType
entityCEntityInstance*

IsEntityHooked

virtual bool IsEntityHooked(CEntityInstance* entity) = 0;
ParameterType
entityCEntityInstance*

SetVisible

virtual bool SetVisible(CEntityInstance* entity, CPlayerSlot viewer, bool visible, int channel = 0) = 0;

Shows or hides a hooked entity for one viewer.

ParameterTypeDefaultDescription
entityCEntityInstance*Hooked entity
viewerCPlayerSlotThe player it is shown to / hidden from
visibleboolfalse hides it on @p channel; true withdraws that channel's objection, and for an entity hidden by default also marks the viewer as allowed
channelint0Channel 0..TRANSMIT_MAX_CHANNELS-1, or TRANSMIT_CHANNEL_ALL for every channel at once

Returns bool — false when the entity is not hooked.

SetVisibleToAll

virtual bool SetVisibleToAll(CEntityInstance* entity, bool visible, int channel = 0) = 0;

SetVisible() for every player slot at once.

ParameterTypeDefault
entityCEntityInstance*
visiblebool
channelint0

IsVisible

virtual bool IsVisible(CEntityInstance* entity, CPlayerSlot viewer) = 0;

Whether a viewer would receive the entity, the channels, the default and BlockAll all taken into account. An unhooked entity is visible. The owner is not consulted -- ask about it directly.

ParameterType
entityCEntityInstance*
viewerCPlayerSlot

IsHiddenOnChannel

virtual bool IsHiddenOnChannel(CEntityInstance* entity, CPlayerSlot viewer, int channel) = 0;

Whether one channel hides the entity from the viewer.

ParameterType
entityCEntityInstance*
viewerCPlayerSlot
channelint

SetBlockAll

virtual bool SetBlockAll(CEntityInstance* entity, bool block) = 0;

Hides a hooked entity from everybody, whatever the channels say.

ParameterType
entityCEntityInstance*
blockbool

GetBlockAll

virtual bool GetBlockAll(CEntityInstance* entity) = 0;
ParameterType
entityCEntityInstance*

SetOwner

virtual bool SetOwner(CEntityInstance* entity, CEntityInstance* owner) = 0;

Ties a hooked entity to an owner: wherever the owner is hidden, so is the entity. The owner has to be hooked for that to apply.

ParameterTypeDescription
entityCEntityInstance*
ownerCEntityInstance*Owner entity, nullptr to untie

GetOwner

virtual CEntityInstance* GetOwner(CEntityInstance* entity) = 0;
ParameterType
entityCEntityInstance*

ResetViewer

virtual void ResetViewer(CPlayerSlot viewer) = 0;

Puts every hooked entity back to its default for one viewer.

Done by Source2Mod when the player disconnects.

ParameterType
viewerCPlayerSlot

HookCheckTransmit

virtual Source2ModTransmitHookId HookCheckTransmit(CheckTransmitHook handler) = 0;

Hooks CheckTransmit itself.

Handlers run after Source2Mod's own pass, in the order they were added; a plugin may add as many as it likes.

Whose it is, the core reads off the handler (see Source2ModCallback); what a plugin still holds at unload the core drops for it.

ParameterTypeDescription
handlerCheckTransmitHookA function, an object and a method, or a lambda

Returns Source2ModTransmitHookId — The id UnhookCheckTransmit(id) takes

UnhookCheckTransmit

virtual bool UnhookCheckTransmit(const CheckTransmitHook& handler) = 0;
virtual bool UnhookCheckTransmit(Source2ModTransmitHookId id) = 0;

Drops the hook with this handler -- a function or an object and a method; a lambda goes by its id.

Drops the hook HookCheckTransmit() returned the id for.

Returns bool — true when one was found

ISource2ModTransmitInfo

One viewer's slice of a CheckTransmit call: who it is for, and which entities are on their way to them.

Handed to a CheckTransmitHook, one per viewer, valid for the duration of the callback only.

GetPlayerSlot

virtual CPlayerSlot GetPlayerSlot() const = 0;

The player this transmit set belongs to.

IsFullUpdate

virtual bool IsFullUpdate() const = 0;

True when the player is being sent everything from scratch (first snapshot, reconnect), false for an ordinary delta.

IsTransmitting

virtual bool IsTransmitting(int entityIndex) const = 0;

Whether the entity is currently in the set.

ParameterType
entityIndexint

BlockTransmit

virtual void BlockTransmit(int entityIndex) = 0;
virtual void BlockTransmit(CEntityInstance* entity) = 0;

Takes an entity out of the set, and lets the client keep track of it while it is gone, so it can come back later.

This is the right way to hide an entity. Clearing the transmit bit alone makes the client forget the entity, and retransmitting it afterwards crashes the client on "missing client entity".

ParameterType
entityIndexint
entityCEntityInstance*

AllowTransmit

virtual void AllowTransmit(int entityIndex) = 0;
virtual void AllowTransmit(CEntityInstance* entity) = 0;

Puts an entity (back) into the set.

ParameterType
entityIndexint
entityCEntityInstance*

GetTransmitEntity

virtual CBitVec<MAX_EDICTS>* GetTransmitEntity() = 0;

The four bit sets of CCheckTransmitInfo, for whatever the methods above do not cover. Entity index = bit index.

TransmitEntity -- entities sent this tick. TransmitNonPlayers -- entities the client keeps a record of without receiving them (what BlockTransmit() sets). TransmitOutOfPVS -- entities that left the PVS but still get a delta. TransmitAlways -- HLTV/replay only, may be nullptr.

GetTransmitNonPlayers

virtual CBitVec<MAX_EDICTS>* GetTransmitNonPlayers() = 0;

GetTransmitOutOfPVS

virtual CBitVec<MAX_EDICTS>* GetTransmitOutOfPVS() = 0;

GetTransmitAlways

virtual CBitVec<MAX_EDICTS>* GetTransmitAlways() = 0;

Macros

TRANSMIT_HOOK_ENTITY

#define TRANSMIT_HOOK_ENTITY(entity, ...) g_pSource2ModTransmit->HookEntity(g_PluginID, entity, ##__VA_ARGS__)

Shorthand accessors via g_pSource2ModTransmit.

Other macros

MacroExpands to
TRANSMIT_UNHOOK_ENTITY(entity)g_pSource2ModTransmit->UnhookEntity(entity)
TRANSMIT_SET_VISIBLE(entity, ...)g_pSource2ModTransmit->SetVisible(entity, __VA_ARGS__)
TRANSMIT_SET_BLOCK_ALL(entity, on)g_pSource2ModTransmit->SetBlockAll(entity, on)
HOOK_CHECK_TRANSMIT(handler)g_pSource2ModTransmit->HookCheckTransmit(handler)
UNHOOK_CHECK_TRANSMIT(handler)g_pSource2ModTransmit->UnhookCheckTransmit(handler)

On this page