I posted about this problem a few weeks ago but I didn't have a firm grasp of exactly what was going on. This time around I've got a better understanding of the problem
What's happening is that replication isn't working. The client never receives an updated game state.
So I have a mutator, Foo. Foo has 2 classes, MyInteraction, and MySpectator.
The mutator doesn't do anything special:
The Interaction Class Tick:
The MySpectator class tick and replicated stuff:
Obviously there is a lot more. So here is the problem. When I load my small test map, consisting of a single room and some boxes, the server will load just fine but the client will launch the map and not receive any of the game state. It doesn't see ammo drops, weapons, or the main player. Oddly enough if I remove the calls to MySpectator from MyInteraction the world loads a little bit better. Problems seem to get worse the more replicated functions I add that are called from MyInteraction.Tick(). The other thing to note is that what I do get a failed client connection the Interaction class is never added because Tick in Foo is never called.
There are some checks in the MySpectator class to see if player bSpectator has been set and the PlayerReplicationInfo is not NONE, these both fail. Weirdly enough if I load a larger map the problems seem to go away. At first I thought it might be my map so I downloads a bunch off the net. The problems happens pretty randomly but generally the smaller maps have issues.
The other thing I tried was to put a wait condition in the Tick of MyInteraction. One thing I don't understand, the Tick() of MyInteraction is always running, even before it is added as an interaction in Foo. Is this supposed to be this way?
I'm at a loss as to whats wrong. It seems that the less I call MySpectator during map start up the more likely I will be to have a successful connection.
What's happening is that replication isn't working. The client never receives an updated game state.
So I have a mutator, Foo. Foo has 2 classes, MyInteraction, and MySpectator.
The mutator doesn't do anything special:
Code:
function ModifyLogin(out string Portal, out string Options) {
Level.Game.PlayerControllerClassName = "Foo.MySpectator";
Level.Game.PlayerControllerClass = class'MySpectator';
log("modifylogin");
super.ModifyLogin(Portal, Options);
}
simulated function Tick(float deltatime)
{
local PlayerController PC;
// if the player has an interaction already, exit function.
if (bHasInteraction) {
super.Tick(DeltaTime);
return;
}
PC = Level.GetLocalPlayerController();
if(PC == None) {
log(" Could not find local player controller");
Return;
}
// Run a check to see whether this mutator should create an interaction for the player
PC.Player.InteractionMaster.AddInteraction("Foo.MyInteraction", PC.Player); // Create the interaction
bHasInteraction = True; // Set the variable so this lot isn't called again
log("Interaction Added");
// hide all of the HUD display, but leave the code intact since we play nice that way
if(PC.myHUD.bCrosshairShow )
PC.ToggleScreenShotMode(); // (also hides the weapon)
}
The Interaction Class Tick:
Code:
simulate function Tick(float dt){
local Controller C;
local MySpectator S;
if (ViewportOwner.Actor == None)
return;
time+=DT;
if( Level.GetLocalPlayerController().PlayerReplicationInfo != none )
bSpectator = Level.GetLocalPlayerController().PlayerReplicationInfo.bIsSpectator;
if (ViewportOwner.Actor.Role == ROLE_Authority || !bSpectator)
{
if( Level.NetMode != NM_Standalone && (bSpectator || ViewportOwner.Actor.Role==ROLE_Authority)) {
for (C = ViewportOwner.Actor.Level.ControllerList; C != None; C = C.NextController)
{
S = MySpectator(C);
if (S != None && (S != ViewportOwner.Actor) )
{
S.UpdateCursor(X,Y);
}
else
{
S.UpdateCursor(-1,-1);
}
}
}
}
}
else {
S =MySpectator(ViewportOwner.Actor);
S.UpdateCursor(X,Y);
}
}
else {
S.UpdateCursor(-1,-1);
}
}
}
The MySpectator class tick and replicated stuff:
Code:
replication {
reliable if (Role == ROLE_Authority)
UpdateCursor;
}
simulated function UpdateCursor(float x, float y){
myX = x;
myY = y;
}
event PlayerCalcView(out actor ViewActor, out vector CameraLocation, out rotator CameraRotation )
{
//... Do some stuff.
PTarget = Pawn(ViewTarget);
if ( PTarget != None && !bBehindView ) { // This should always be true
log("Target found.");
} else {
log("MySpectator.PlayerCalcView: You shouldn't see me."$PTarget$" "$bBehindView);
}
}
Obviously there is a lot more. So here is the problem. When I load my small test map, consisting of a single room and some boxes, the server will load just fine but the client will launch the map and not receive any of the game state. It doesn't see ammo drops, weapons, or the main player. Oddly enough if I remove the calls to MySpectator from MyInteraction the world loads a little bit better. Problems seem to get worse the more replicated functions I add that are called from MyInteraction.Tick(). The other thing to note is that what I do get a failed client connection the Interaction class is never added because Tick in Foo is never called.
There are some checks in the MySpectator class to see if player bSpectator has been set and the PlayerReplicationInfo is not NONE, these both fail. Weirdly enough if I load a larger map the problems seem to go away. At first I thought it might be my map so I downloads a bunch off the net. The problems happens pretty randomly but generally the smaller maps have issues.
The other thing I tried was to put a wait condition in the Tick of MyInteraction. One thing I don't understand, the Tick() of MyInteraction is always running, even before it is added as an interaction in Foo. Is this supposed to be this way?
I'm at a loss as to whats wrong. It seems that the less I call MySpectator during map start up the more likely I will be to have a successful connection.
Last edited: