logo
Main

Forums

Downloads

Unreal-Netiquette

Donate for Oldunreal:
Donate

borderline

Links to our wiki:
Wiki

Walkthrough

Links

Tutorials

Unreal Reference

Usermaps

borderline

Contact us:
Submit News
Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Issue #39. Network-aware emitters don't properly implement the effect of Trigger function (Read 743 times)
Masterkent
Developer Team
Online



Posts: 1040
Location: Russia
Joined: Apr 5th, 2013
Gender: Male
Issue #39. Network-aware emitters don't properly implement the effect of Trigger function
Dec 16th, 2016 at 7:02pm
Print Post  
When a network-aware emitter is triggered, the effect of triggering may or may not be observed client-side depending on relative order between triggering and joining the game (an example can be found in this thread).

Network-aware emitters (NetSpriteEmitter, NetworkBeamEmitter, NetworkEmitter, NetworkMeshEmitter) use RepCounter to transfer information about server-side calls to Trigger to client:

Code
Select All
var byte RepCounter,ClientRepCounter;

replication
{
	reliable if ( Role==ROLE_Authority )
		RepCounter;
}

function PreBeginPlay();

simulated function PostNetBeginPlay()
{
	if( TriggerAction==ETR_ToggleDisabled && (RepCounter & 1)!=0 )
		EmTrigger();
	ClientRepCounter = RepCounter;
	bNetNotify = True;
}
simulated function PostNetReceive()
{
	if ( ClientRepCounter!=RepCounter )
	{
		ClientRepCounter = RepCounter;
		if ( RepCounter==0 )
			Reset();
		else EmTrigger();
	}
}
simulated function Reset()
{
	RepCounter = 0;
	bDisabled = BACKUP_Disabled;
}
function Trigger( Actor Other, Pawn EventInstigator )
{
	if ( Level.NetMode!=NM_DedicatedServer )
		EmTrigger();
	if ( ++RepCounter==255 )
		RepCounter = 1;
} 


Emitters have a lot of parameters, and, in order to preserve all values assigned by a map author, they have bNoDelete set to true by default. An actor having bNoDelete == true does not need to be replicated, and all its non-replicable properties can be obtained client-side directly from the map package. When all replicable properties have default values servers-side, this leads to an interesting situation: neither actor nor any of its properties need to be replicated, so no replication is needed for the actor at all. Since no replication is done for the actor, PostNetBeginPlay is not invoked (this function is supposed to be invoked after a replication is done).

For some unknown reason the implementator used PostNetReceive in order to set bNetNotify to true. Since the default value of bNetNotify is false, this effectively prevents engine calls to PostNetReceive that is supposed to react on changes of RepCounter and call EmTrigger when necessary, unless the player joined the game after the emitter actor has been modified in a way that requires initial replication of the actor leading to call to PostNetBeginPlay. Hence a call to EmTrigger can be omitted when it's actually supposed to be called.

In addition, the implementation of PostNetReceive itself has a problem with reliability. If the server changes RepCounter twice fast enough and packets containing value updates reach the client long enough, the client may drop intermediate changes and apply the most recent update, so f.e. the sequence of changes 0 -> 1 -> 2 for RepCounter can be viewed by client as 0 -> 2. For an emitter having TriggerAction == ETR_ToggleDisabled this may result in wrong toggle operation (double toggling is supposed to return the actor into the initial state, so the actual emitter state is determined by whether the number of applied toggle operations is odd or even). Hence PostNetReceive should distinguish even and odd number of toggle operations initiated by server-side calls to Trigger, without relying on receiving all intermediate changes of RepCounter.

Any way of fixing a reference network-aware emitter classes most likely implies potential breaking changes. That is, a user-defined class inherited from a reference network-aware class may work correctly before applying a fix and stop to work as intended after applying the fix.

For example, if we fix a network-aware class as follows

Code
Select All
event PostNetBeginPlay() {}

simulated event PostNetReceive()
{
	if (ClientRepCounter != RepCounter)
	{
		if (RepCounter == 0)
			Reset();
		else if (TriggerAction != ETR_ToggleDisabled || ((RepCounter - ClientRepCounter) & 1) != 0)
			EmTrigger();
		ClientRepCounter = RepCounter;
	}
}

defaultproperties
{
    ....
	bNetNotify=True
} 


Then a derived class that uses an alternative approach

Code
Select All
var bool bEmit;

event PostNetBeginPlay() {}

simulated event Tick(float DeltaTime)
{
	if (Level.NetMode == NM_Client && RepCounter != int(bEmit))
	{
		EmTrigger();
		bEmit = bool(RepCounter);
	}
}

function Trigger( Actor Other, Pawn EventInstigator )
{
	if (Level.NetMode != NM_DedicatedServer)
		EmTrigger();
	RepCounter = 1 - RepCounter;
} 


would become broken. It can argued though that inheriting from an admittedly broken class and using its variables RepCounter and ClientRepCounter (which normally should be declared private for the purposes of proper class encapsulation) is a programming mistake, and we don't need to support such unreasonable uses (it can be foreseen that an entirely broken class can eventually be fixed and the fix may imply radical changes). If a user wants to make a custom correctly and reliably working network-aware emitter class, he should inherit his class directly from XEmitter/XBeamEmitter/... rather than from broken NetworkEmitter/NetworkBeamEmitter/... whose destiny is unknown.

So, my current suggested resolution is:

in every network-aware class,

1) add the private specifier to variables RepCounter and ClientRepCounter. This should preserve binary but not source compatibility with old-fashion implementations that make use of those RepCounter and ClientRepCounter somehow.

2) change the definitions of PostNetBeginPlay and PostNetReceive to

Code
Select All
event PostNetBeginPlay() {} // preserved for binary compatibility with old derived classes

simulated event PostNetReceive()
{
	if (ClientRepCounter != RepCounter)
	{
		if (RepCounter == 0)
			Reset();
		else if (TriggerAction != ETR_ToggleDisabled || ((RepCounter - ClientRepCounter) & 1) != 0)
			EmTrigger();
		ClientRepCounter = RepCounter;
	}
} 


3) add

Code
Select All
bNetNotify=True 


to the defaultproperties section.

This probably should be targeted for 227j rather than for later release.
  
Back to top
 
IP Logged
 
Smirftsch
Forum Administrator
*****
Offline



Posts: 7686
Location: at home
Joined: Apr 30th, 1998
Gender: Male
Re: Issue #39. Network-aware emitters don't properly implement the effect of Trigger function
Reply #1 - Dec 17th, 2016 at 8:14am
Print Post  
perhaps it makes sense to assume that there are not many custom classes relying on it out there, if at all, and fix it properly in a way how mappers expect/expected it to work. I highly doubt there are any anyway and we have to much broken stuff already in there kept for compatibility reasons already.
However, I can try to point dots here, he may wants to have a look or explain what he had in mind when creating it.
  

Sometimes you have to lose a fight to win the war.
Back to top
WWWICQ  
IP Logged
 
Masterkent
Developer Team
Online



Posts: 1040
Location: Russia
Joined: Apr 5th, 2013
Gender: Male
Re: Issue #39. Network-aware emitters don't properly implement the effect of Trigger function
Reply #2 - Dec 17th, 2016 at 12:05pm
Print Post  
Smirftsch wrote on Dec 17th, 2016 at 8:14am:
I can try to point dots here, he may wants to have a look or explain what he had in mind when creating it.

Probably, he wanted to prevent postponed client-side triggering for non-ETR_ToggleDisabled emitters that might take place when a player joins the game after server-side triggering has been done. PostNetBeginPlay can be helpful in this regard, because it's able to distinguish the initial replication from later replications. The given approach, however, requires a guaranteed call to PostNetBeginPlay. We can achieve this by setting a specific default value of RepCounter so that RepCounter would always have to be updated to something non-default (thus forcing replication and a call to PostNetBeginPlay):

Code
Select All
// changing RepCounter from 255 to 0 (see the defaultproperties section)
function PreBeginPlay()
{
	RepCounter = 0;
}

// no changes here
simulated function PostNetBeginPlay()
{
	if( TriggerAction==ETR_ToggleDisabled && (RepCounter & 1)!=0 )
		EmTrigger();
	ClientRepCounter = RepCounter;
	bNetNotify = True;
}

// edited version that correctly handles odd/even differences between RepCounter and ClientRepCounter
simulated event PostNetReceive()
{
	if (ClientRepCounter != RepCounter)
	{
		if (RepCounter == 0)
			Reset();
		else if (TriggerAction != ETR_ToggleDisabled || ((RepCounter - ClientRepCounter) & 1) != 0)
			EmTrigger();
		ClientRepCounter = RepCounter;
	}
}

// no changes here
simulated function Reset()
{
	RepCounter = 0;
	bDisabled = BACKUP_Disabled;
}

// no changes here
function Trigger( Actor Other, Pawn EventInstigator )
{
	if ( Level.NetMode!=NM_DedicatedServer )
		EmTrigger();
	if ( ++RepCounter==255 )
		RepCounter = 1;
}

defaultproperties
{
	.... // insert the existing default properties here
	RepCounter=255 // this value is never used in a completely initialized actor
} 


Possible values of RepCounter would be:
0 - initial state / marker of the reset operation
1...254 - markers of a trigger operation
255 - default value (is used only during actor initialization)

Or maybe it makes sense to tweak the native caller of PostNetBeginPlay so that this function could be called when no any replication is done for the implied actor.
  
Back to top
 
IP Logged
 
Masterkent
Developer Team
Online



Posts: 1040
Location: Russia
Joined: Apr 5th, 2013
Gender: Male
Re: Issue #39. Network-aware emitters don't properly implement the effect of Trigger function
Reply #3 - Mar 4th, 2018 at 5:26pm
Print Post  
The last resolution seems to have the least potential of breaking anything. I think, we could give it a try in j_39/j_40.

Any suggestions regarding maps/mods which use emitters and should be tested?
  
Back to top
 
IP Logged
 
[]KAOS[]Casey
Developer Team
Betatester
Offline


nedm

Posts: 3115
Joined: Aug 7th, 2011
Gender: Male
Re: Issue #39. Network-aware emitters don't properly implement the effect of Trigger function
Reply #4 - Mar 4th, 2018 at 7:29pm
Print Post  
maybe Krull0r used some that trigger online in his maps?

I can't think of any maps other than dm-retrospective that probably only use static emitters that don't change.

there's probably a few weapon mods that use emitters, but I don't know any offhand.
  
Back to top
 
IP Logged
 
Masterkent
Developer Team
Online



Posts: 1040
Location: Russia
Joined: Apr 5th, 2013
Gender: Male
Re: Issue #39. Network-aware emitters don't properly implement the effect of Trigger function
Reply #5 - Mar 4th, 2018 at 8:04pm
Print Post  
[]KAOS[]Casey wrote on Mar 4th, 2018 at 7:29pm:
there's probably a few weapon mods that use emitters, but I don't know any offhand.

Checked HD weapons v0.6 from here: http://www.unrealsp.org/viewtopic.php?f=3&t=2629&p=60027#p60027 (is there a newer version?)

This mod uses some emitters, but none of them are standard network-aware emitters, hence it can't be affected anyway.

Also checked dots' Botpack.u - it doesn't use standard network-aware emitters too.
  
Back to top
 
IP Logged
 
Krull0r
Global Moderator
Betatester
Developer Team
*****
Online


227 Emitter Expert

Posts: 345
Location: Germany
Joined: Jul 1st, 2007
Gender: Male
Re: Issue #39. Network-aware emitters don't properly implement the effect of Trigger function
Reply #6 - Mar 4th, 2018 at 10:54pm
Print Post  
Casey is right. I use a lot of triggered network emitters in my levels.

I already created a new sub class for all kinds of network emitters with Masterkents Code and they work really good so far.
I really don’t know if any other mods or maps use triggerable emitters.

I guess that maybe the 227 version of the unreleased map pack “Firestorm“ will also use them.


I have to check what code I‘m using right now.


I also have to mention that all my weapons and projectiles use a lot of Emitter effects like smoke, fire, explosions etc and even the muzzle flash effects are vertex attached emitters.

As long as only the network emitter get touched there will be no conflicts with weapon and projectile effects.
  

Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint
Bookmarks: del.icio.us Digg Facebook Google Google+ Linked in reddit StumbleUpon Twitter Yahoo