← Home SEEBIE90 DOCS
The RIM-116 & Phalanx mod is published under the Arma Public License (APL)Example code is free to useSuggestions: Discord to the author

RIM-116 & Phalanx

Replication pitfalls

Most of what went wrong on the test server was not logic but replication: a value that differed between machines, a message that went nowhere, a reference that was not there yet.

In plain wordsThings that work on your own machine and fail silently for everyone else: clocks, who may send a message, and when a prefab's parts exist.

Replicate the duration, not the deadline

A lockout that replicated an absolute server timestamp showed 184 seconds on a client instead of 15, because GetWorldTime() is machine-local and the server's clock was minutes ahead of the client's. There is no shared global clock to fall back on: Replication.Time() does not exist in this engine build – verified in Core/generated/Replication/Replication.c. Replicate how long, and let each machine add it to its own clock.

Example code – free to use
[RplProp(onRplName: "OnLockChanged")]
protected int m_iLockDuration;		// replicated: how LONG, never until when

protected int m_iLockEndsLocal;		// not replicated: computed per machine

protected void OnLockChanged()
{
	m_iLockEndsLocal = 0;
	if (m_iLockDuration > 0)
		m_iLockEndsLocal = NowInSeconds() + m_iLockDuration;

	Redraw();
}

A client may only send an Rpc through an entity it owns

Calling an Rpc on a component of a foreign entity fails silently. A repair action in the Game Master did nothing at all for weeks for this reason. The way through is a modded SCR_PlayerController, which every client owns: send the RplComponent.Id() of the target and resolve it on the server.

Example code – free to use
modded class SCR_PlayerController
{
	void MyAD_AskRepair(IEntity target)
	{
		RplComponent rpl = RplComponent.Cast(target.FindComponent(RplComponent));
		if (rpl)
			Rpc(MyAD_RpcAsk_Repair, rpl.Id());
	}

	[RplRpc(RplChannel.Reliable, RplRcver.Server)]
	protected void MyAD_RpcAsk_Repair(RplId id)
	{
		IEntity target = IEntity.Cast(Replication.FindItem(id));
		if (target)
			MyAD_RepairNow(target);		// runs on the server, where it counts
	}
}

The reaction to a replicated field does not run on the authority

onRplName fires on the machines that receive a value, not on the one that wrote it. On a dedicated server that is fine; on a listen server the host never sees its own change. Call the same update method from both the setter and the callback.

Example code – free to use
void SetState(int state)
{
	m_iState = state;
	Replication.BumpMe();
	OnStateChanged();			// the authority does not get the callback - call it yourself
}

protected void OnStateChanged()		// also the onRplName callback on every proxy
{
	Refresh();
}

A prefab's children have no parent yet at init time

References to moving parts that are children in the prefab cannot be resolved in OnPostInit: GetParent() is still null. Resolve them lazily on first use instead.

Example code – free to use
protected IEntity Part()
{
	if (!m_Part)
		m_Part = GetOwner().FindChild("Part");	// not in OnPostInit - the hierarchy is not set up yet

	return m_Part;
}

Random numbers: one digit at a time

A random code drawn from one big range (Math.RandomInt(10^(n-1), 10^n)) can overflow the engine's integer: with eight digits the screen showed a negative code. A single digit never needs more than the range 0 to 9, so nothing can overflow, and the leading digit keeps the length.

Example code – free to use
string code = Math.RandomInt(1, 10).ToString();		// leading digit: never zero
for (int i = 1; i < digits; i++)
	code = code + Math.RandomInt(0, 10).ToString();

Let the server keep the answer

Whatever has to stay secret – a target value, the solution to something the player has to work out – is computed and compared only on the authority. Replicate what the player needs to see, never the answer. A client that knows the solution does not need to go looking.

Example code on this page is free to use in your own projects (credit appreciated). The RIM-116 & Phalanx mod is published under the Arma Public License (APL). Suggestions: Discord. Arma Reforger / Enfusion are trademarks of Bohemia Interactive.
Impressum · Privacy Policy