PowerReceiver¶
The receiver half of a microwave power link (Assets.Scripts.Objects.Electrical.PowerReceiver). Its partner is PowerTransmitter; both subclass WirelessPower. The transmitter beams power onto a shared WirelessNetwork; the receiver pulls it off that network and re-emits it onto its own output cable network. The receiver carries no rating of its own: what it delivers is whatever potential the linked transmitter put on the wireless network.
Fields and pairing¶
Line refs at 0.2.6403.27689: class 408065, _powerProvided 408071, LinkedPowerTransmitter setter 408081-408097 (assigns InputNetwork = value.OutputNetwork only when value is non-null), OnDestroy 408108-408115, CheckConnections 408257-408261 (touches OutputNetwork only).
public Transform DishTarget;
private PowerTransmitter _linkedPowerTransmitter;
private float _powerProvided; // debt accumulator: += on UsePower, -= on ReceivePower
public WirelessNetwork WirelessInputNetwork => InputNetwork as WirelessNetwork;
public PowerTransmitter LinkedPowerTransmitter
{
get => _linkedPowerTransmitter;
set
{
if (value != null)
InputNetwork = value.OutputNetwork; // RX input network IS the TX output (wireless) network
if (GameManager.RunSimulation)
OnServer.Interact(base.InteractMode, (value != null) ? 1 : 0);
if (value == null)
base.VisualizerIntensity = 0f;
_linkedPowerTransmitter = value;
CheckError();
}
}
Topology consequences:
- Setting
LinkedPowerTransmitterwritesInputNetwork = value.OutputNetwork, so the receiver'sInputNetworkis the SAMEWirelessNetworkobject the transmitter outputs to.WirelessInputNetworkis that network typed asWirelessNetwork(the PowerTransmitter page documentsPT.OutputNetwork === PR.InputNetwork). - The receiver's
OutputNetworkis its own cable network, set inCheckConnectionsfrom the output connection's cable:
protected override void CheckConnections()
{
Cable cable = OutputConnection.GetCable();
OutputNetwork = (cable ? cable.CableNetwork : null);
}
OnDestroyclears the partner's back-reference (LinkedPowerTransmitter.LinkedReceiver = null), so destroying either dish breaks the pair cleanly.- Pairing is by cross-reference only (
PR._linkedPowerTransmitterandPT.LinkedReceiver); there is no central registry. Enumerating pairs requires walking both instance lists (see PowerGridPlus's bipartite wireless-edge gating, POWER.md §6.5).
Power-flow methods (verbatim)¶
Re-verified verbatim at 0.2.6403.27689: UsePower / ReceivePower ledger 408184-408204, GetUsedPower 408206-408229, GetGeneratedPower 408232-408243.
public override void UsePower(CableNetwork cableNetwork, float powerUsed)
{
if (Error != 1 && OnOff && cableNetwork == OutputNetwork)
_powerProvided += powerUsed;
}
public override void ReceivePower(CableNetwork cableNetwork, float powerAdded)
{
if (WirelessInputNetwork == null || cableNetwork == WirelessInputNetwork)
{
if (!OnOff || WirelessInputNetwork == null)
{
base.VisualizerIntensity = 0f;
return;
}
base.VisualizerIntensity = RocketMath.MapToScale(0f, PowerTransmitter.MaxPowerTransmission, 0f, 1f, powerAdded);
_powerProvided -= powerAdded;
}
}
public override float GetUsedPower([NotNull] CableNetwork cableNetwork)
{
if (InputNetwork == null)
base.VisualizerIntensity = 0f;
if (InputNetwork == null || cableNetwork != InputNetwork)
return 0f;
if (Error == 1)
{
base.VisualizerIntensity = 0f;
if (!OnOff) return 0f;
return UsedPower;
}
if (!OnOff) return 0f;
return Mathf.Min(PowerTransmitter.MaxPowerTransmission + UsedPower, _powerProvided);
}
public override float GetGeneratedPower(CableNetwork cableNetwork)
{
if (OutputNetwork == null || Error == 1 || cableNetwork != OutputNetwork)
return 0f;
if (!OnOff || WirelessInputNetwork == null)
return 0f;
return WirelessInputNetwork.PotentialLoad;
}
Reading them as a pair:
GetGeneratedPower(OutputNetwork)=WirelessInputNetwork.PotentialLoad. The receiver puts onto its cable network exactly the potential standing on the wireless network. That wireless potential is the linked transmitter'sGetGeneratedPower(wireless)(the deliverable cap), summed intoCableNetwork.PotentialLoadby the previous tick'sOnPowerTick(see CableNetwork / PowerTick). So the receiver is the grid-facing generator of the link, and its output equals the transmitter's deliverable. It carries no rating of its own.GetUsedPower(InputNetwork)=Mathf.Min(PowerTransmitter.MaxPowerTransmission + UsedPower, _powerProvided). The receiver's draw on the wireless network is its accumulated debt, capped atMaxPowerTransmission + UsedPower(= 5000 + the dish's own quiescent draw)._powerProvidedrises inUsePower(when the grid pulls power from the receiver's output cable) and falls inReceivePower(when the receiver is fed on the wireless side), so it tracks net outstanding throughput.MaxPowerTransmissionis the static 5000 W constant onPowerTransmitter; it appears here on the receiver as theGetUsedPowercap and the visualizer's full-brightness reference.
_powerProvided is runtime-only: not saved, not synced¶
The debt accumulator (declaration 408071) has no persistence path at 0.2.6403.27689. PowerReceiverSaveData : WirelessPowerSaveData (408062-408064) has an EMPTY body; the base record (426765-426778) carries only the four dish-rotation doubles, so nothing at the receiver level saves the ledger, and the whole-decompile census shows the field touched exclusively by UsePower (408188), ReceivePower (408202), and GetUsedPower (408229); no SerializeOnJoin / BuildUpdate / ProcessUpdate member reads it. It restarts at 0 on save load and on client join: a loaded or late-joining receiver reports zero wireless-side draw until its output cable network pulls power again. Cross-class census and consequences on Device, "Two per-device draw-state fields".
The deliverable path¶
End to end, vanilla:
PT input cable --(PT.GetUsedPower)--> PT --(PT.GetGeneratedPower(wireless))--> WirelessNetwork.PotentialLoad
--(PR.GetUsedPower(wireless))--> PR --(PR.GetGeneratedPower(cable) = WirelessInputNetwork.PotentialLoad)--> RX output cable
Delivered == drawn in vanilla: the transmitter's GetGeneratedPower already bakes in the distance derate (PowerLossOverDistance), and the receiver passes that derated potential straight to its cable network. Neither side multiplies or divides; the loss is entirely inside the transmitter's GetGeneratedPower number.
Unlink behavior: the stale-InputNetwork window NARROWED at 0.2.6403¶
At 0.2.6228 an unlinked receiver kept its last wireless InputNetwork reference indefinitely (nothing nulled it). At 0.2.6403.27689 the normal unlink path clears it:
ElectricalInputOutput.OnRemoveCableNetwork(oldNetwork)(394993-395006) now nullsInputNetworkwhenoldNetwork == InputNetwork(andOutputNetworksymmetrically), then re-runsCheckConnections/CheckPower.CableNetwork.RemoveDevice(Device)invokesdevice.OnRemoveCableNetwork(this)(line 271024).- The TX-side
LinkedReceiversetter removes the old RX from theWirelessNetwork(WirelessOutputNetwork.RemoveDevice(_linkedReceiver), PowerTransmitter line 408305).
So a setter-driven unlink or retarget (TryContactReceiver clearing / replacing LinkedReceiver, an OnOff toggle retarget, etc.) DOES clear rx.InputNetwork now: setter -> RemoveDevice -> OnRemoveCableNetwork -> InputNetwork = null. Paths that bypass CableNetwork.RemoveDevice still leave the reference stale; the known one is PowerTransmitter.OnDestroy (408387-408394), which only does LinkedReceiver.LinkedPowerTransmitter = null and never removes the RX from the wireless network before the TX (and with it the network's only ticking anchor) goes away. See Open Questions for the runtime-unverified hazard on that path.
PowerTransmitterPlus interaction¶
PowerReceiver's own methods are NOT patched by PowerTransmitterPlus; the distance model lives entirely on the transmitter side. PowerTransmitterPlus (a) drops the 5000 W delivery ceiling on PowerTransmitter.GetGeneratedPower (so the wireless PotentialLoad, and hence PR.GetGeneratedPower, can exceed 5000 W) and (b) inflates the TRANSMITTER's source-side draw to delivered * (1 + k * distance_km). The receiver still reports WirelessInputNetwork.PotentialLoad as its generation and its debt-capped draw as its use; it is a faithful pass-through. See PowerTransmitter and PowerGridPlus cross-mod compatibility for the transmitter-side model and the PowerGridPlus allocator's handling of the inflated source draw.
Verification history¶
- 2026-07-06: added the "
_powerProvidedis runtime-only" subsection (game version 0.2.6403.27689). Evidence:PowerReceiverSaveDataempty body (408062-408064),WirelessPowerSaveDatabody (426765-426778), whole-decompile_powerProvidedcensus (RX sites: declaration 408071, 408188 / 408202 / 408229 only; no serialization member). Additive; no prior claim on this page addressed save behavior of the ledger, no fresh validator. - 2026-07-02: re-verification pass against the 0.2.6403.27689 decompile after the game update from 0.2.6228.27061. Confirmed unchanged with new line refs:
GetGeneratedPower(OutputNetwork)=WirelessInputNetwork.PotentialLoadverbatim (408232-408243),GetUsedPower=Min(MaxPowerTransmission + UsedPower, _powerProvided)(408206-408229),UsePower/ReceivePowerledger (408184-408204),LinkedPowerTransmittersetter assigningInputNetwork = value.OutputNetworkonly when non-null (408081-408097),CheckConnectionstouchingOutputNetworkonly (408257-408261). CHANGED at 0.2.6403.27689 (supersession, new section "Unlink behavior"):ElectricalInputOutput.OnRemoveCableNetworknow nullsInputNetworkwhenoldNetwork == InputNetwork(394993-395006),CableNetwork.RemoveDeviceinvokes it (271024), and the TXLinkedReceiversetter removes the old RX from the WirelessNetwork (408305), so a setter-driven unlink or retarget clearsrx.InputNetwork; previously nothing cleared it and a formerly-linked RX kept advertising the dead wireless network'sPotentialLoad. Bypass paths (PowerTransmitter.OnDestroydoing onlyLinkedReceiver.LinkedPowerTransmitter = null, 408387-408394) still leave the reference stale; that residual hazard moved to Open Questions as runtime-unverified. - 2026-06-14: page created. Sourced from
.work/decomp/0.2.6228.27061/Assembly-CSharp.decompiled.cslines 386861-387058; verbatimUsePower/ReceivePower/GetUsedPower/GetGeneratedPower/LinkedPowerTransmittersetter /CheckConnectionsbodies. ConfirmsPowerReceiver.GetGeneratedPower(OutputNetwork)returnsWirelessInputNetwork.PotentialLoadandPowerReceiver.GetUsedPower(InputNetwork)returnsMathf.Min(PowerTransmitter.MaxPowerTransmission + UsedPower, _powerProvided). Established while correcting the PowerGridPlus x PowerTransmitterPlus loss-model interaction (POWER.md §6.3 / §8.4.2).
Open questions¶
PowerTransmitter.MaxPowerTransmission(5000) survives only as theGetUsedPowercap and the visualizer reference once PowerTransmitterPlus removes it as the delivery ceiling. Whether any other vanilla consumer still relies on the 5000 W receiver-draw cap is unverified; PowerGridPlus and PowerTransmitterPlus do not.- Bypass-path stale-InputNetwork hazard (runtime-unverified at 0.2.6403.27689): when a linked TX is destroyed,
PowerTransmitter.OnDestroy(408387-408394) only nullsLinkedPowerTransmitterand does not remove the RX from the WirelessNetwork, sorx.InputNetworkshould keep pointing at the dead wireless network; a still-ON formerly-linked RX would then keep advertising that network's lastPotentialLoadthroughGetGeneratedPoweruntil relink or destruction. Confirm with InspectorPlus (request: types=[PowerReceiver], fields=[_linkedPowerTransmitter, InputNetwork, OutputNetwork]) after destroying a linked transmitter.