UE1 - UT Can a mute replace a player's PlayerReplicationInfo?

  • Two Factor Authentication is now available on BeyondUnreal Forums. To configure it, visit your Profile and look for the "Two Step Verification" option on the left side. We can send codes via email (may be slower) or you can set up any TOTP Authenticator app on your phone (Authy, Google Authenticator, etc) to deliver codes. It is highly recommended that you configure this to keep your account safe.

Helen

Member
Jan 23, 2010
48
0
6
I am trying to replace the player's PlayerReplicationInfo class with my own.

I am not making a new game type, nor a new player pawn. I just have a mutator running against good old DeathMatchPlus.

The problem I experience is that during the game, each player appears immobile to every other player in the game. But in fact every player can still move around and do everything, so essentially their visual movement is not getting sent to the other players.

I DO know that my instance of the PlayerReplicationInfo is created, attached to the player, and it is doing the other tasks I assigned it. But something isn't right!

I guess I should first ask, has anyone got it to work to replace a player's existing player replication info class with a sub-classed one? If so, what am I missing?

First I simplified my class to make sure it wasn't my custom code that was faulty. So I have this:

Code:
class myPlayerReplicationInfo expands PlayerReplicationInfo;

defaultproperties
{
    bAlwaysRelevant=true
}

One way I attempted to sub it in was this way - I have a spawn notification that fires on the spawn of a PlayerReplicationInfo:

Code:
class myPRISpawnNotify expands SpawnNotify;

event Actor SpawnNotification(Actor A)
{
    if (A.IsA('myPlayerReplicationInfo'))
        return A;

    A.Destroy();
    return Spawn(class'myPlayerReplicationInfo');
}

defaultproperties
{
    ActorClass=class'PlayerReplicatonInfo'
}

Another way was catching when a player was spawned, and replacing the PlayerReplicationInfo at that point:

Code:
class myPlayerPawnSpawnNotify expands SpawnNotify;

event Actor SpawnNotification(Actor A)
{
    local PlayerPawn p;
    local PlayerReplicationInfo PRI;
    local myPlayerReplicationInfo mpri;

    if (!A.IsA('PlayerPawn'))
	return A;

    p = PlayerPawn(A);
    p.PlayerReplicationInfoClass = class'myPlayerReplicationInfo';

	Log("SpawnNotification() - A PlayerPawn.PlayerReplicationInfoClass has been set to a myPlayerReplicationInfo class type");

    if((p.PlayerReplicationInfo != None) && (!p.PlayerReplicationInfo.IsA('myPlayerReplicationInfo')))
    {
        Log("The regular PRI has already been assigned, so we are going to replace it");

        PRI = p.PlayerReplicationInfo;
        
        // Create our instance of the class
        mpri = Spawn(Class'myPlayerReplicationInfo', p);

        // Get any values from the current PRI
        mpri.PlayerName = PRI.PlayerName;
        mpri.OldName = PRI.OldName;
        mpri.PlayerID = PRI.PlayerID;
        mpri.TeamName = PRI.TeamName;
        mpri.Team = PRI.Team;
        mpri.TeamID = PRI.TeamID;
        mpri.Score = PRI.Score;
        mpri.Deaths = PRI.Deaths;
        mpri.VoiceType = PRI.VoiceType;
        mpri.HasFlag = PRI.HasFlag;
        mpri.Ping = PRI.Ping;
        mpri.PacketLoss = PRI.PacketLoss;
        mpri.bIsFemale = PRI.bIsFemale;
        mpri.bIsABot = PRI.bIsABot;
        mpri.bFeigningDeath = PRI.bFeigningDeath;
        mpri.bIsSpectator = PRI.bIsSpectator;
        mpri.bWaitingPlayer = PRI.bWaitingPlayer;
        mpri.bAdmin = PRI.bAdmin;
        mpri.TalkTexture = PRI.TalkTexture;
        mpri.PlayerZone = PRI.PlayerZone;
        mpri.PlayerLocation = PRI.PlayerLocation;
        mpri.StartTime = PRI.StartTime;
        mpri.TimeAcc = PRI.TimeAcc;

        // Destroy the original
        p.PlayerReplicationInfo.Destroy();

        // Give the player our instance
        p.PlayerReplicationInfo = mpri;
    }

    return A;
}

defaultproperties
{
    ActorClass=Class'Botpack.PlayerPawn'
}

Again, both of these work as far as getting called, and subbing in myPlayerReplicationInfo. But I get the problem of the player's movement not updated to each player.

Would someone know what I need to do?

Thanks.
 

meowcat

take a chance
Jun 7, 2001
803
3
18
We would need to see the code in your custom player replication info (whatever is collecting, storing and replicating the player's position). In general client computers only know about the existence/physical locations/movement of pawns that are relevant to them (eg: can be seen, or were rendered in the last 3 seconds or so). If they are no longer relevant, the server stops replicating info to the client, then the client destroys its local copy of the other client's pawn until the server replicates the info again.

So in order to replicate player movement I assume you must be collecting the player positions in the server's copy of the PRIs and then replicating that out. (this is the work around necessary for all of the radar type mutators/HUD modifiers).
 
Last edited:

Helen

Member
Jan 23, 2010
48
0
6
So in order to replicate player movement I assume you must be collecting the player positions in the server's copy of the PRIs and then replicating that out. (this is the work around necessary for all of the radar type mutators/HUD modifiers).

Are you saying I have to collect the player positions and replicate them? That isn't taken care of by the base class? In the example myPlayerReplicationInfo above, that wasn't shortened for this post, that was a literal version I tried, to make sure it wasn't my custom code that was messing anything up. So, for the above myPlayerReplicationInfo, do I have to implement some player position replication?
 

meowcat

take a chance
Jun 7, 2001
803
3
18
Yes if you want the other client to know where the other players are at all times. The base player replication info class only replicates general location information (which zone each player is in etc.) it does not include the specific vector location (which is what you would have to replicate).

The PlayerReplicationInfo already has bAlwaysRelevant set (in its parent class ReplicationInfo).

It pretty easy to do using timer though. Just overwrite the timer function in your subclass, and then have it grab the owning players location and store it in a variable that is replicated. Now, you may want to do some checks in the timer so you don't perform the other tasks quite as often. Also, you may have to consider updating the net frequency to something more like 5 or 10 if you absolutely must have smoother movement (it is defaulted to 2 which means the server send out updates twice per second). Now that the variable is replicated, you can use it for whatever purposes you need on each client.

I was able to successfully use this method in UT2k4 to create the HUD radars from Call of Duty Modern Warfare and Rainbow Six.
 
Last edited:

Wormbo

Administrator
Staff member
Jun 4, 2001
5,913
36
48
Germany
www.koehler-homepage.de
You don't need a SpawnNotify for that. Just use the Mutator.CheckReplacement() function to find spawned Pawns and change their PlayerReplicationInfoClass to your new PRI type. You don't need to initialize the PRI at all because it hasn't been spawned yet.
 

Helen

Member
Jan 23, 2010
48
0
6
I don't need to know the players location (at any time). I do have other variables, and they are successfully replicating, but the problem is, it seems that some of the base functionality is not doing its job.

Ok, ignoring my real class for the moment, I made this example mutator to purely test replacing the PlayerReplicationInfo:

Code:
// medUtilActor.uc
class medUtilActor extends Actor;

function PostBeginPlay()
{
    super.PostBeginPlay();

    Level.Game.BaseMutator.AddMutator(Spawn(class'medUtil'));
}

defaultproperties
{
    bHidden=True
}

// medUtil.uc
class medUtil expands mutator config(medUtil);

var medPlayerPawnSpawnNotify mPlayerPawnSpawnNotify;
var medPRISpawnNotify mPRISpawnNotify;

function PreBeginPlay()
{
    if (mPRISpawnNotify == None)
        mPRISpawnNotify = Spawn(Class'medPRISpawnNotify');

    if (mPlayerPawnSpawnNotify == None)
        mPlayerPawnSpawnNotify = Spawn(Class'medPlayerPawnSpawnNotify');
}

defaultproperties
{
    bAlwaysRelevant=True
}


// medPlayerReplicationInfo.uc
class medPlayerReplicationInfo expands PlayerReplicationInfo;


// medPlayerPawnSpawnNotify
class medPlayerPawnSpawnNotify expands SpawnNotify;

event Actor SpawnNotification(Actor A)
{
    if (!A.IsA('PlayerPawn'))
		return A;

    PlayerPawn(A).PlayerReplicationInfoClass = class'medPlayerReplicationInfo';

	return A;
}

defaultproperties
{
    ActorClass=Class'Botpack.PlayerPawn'
}


//  medPRISpawnNotify.uc

class medPRISpawnNotify expands SpawnNotify;

event Actor SpawnNotification(Actor A)
{
    if (A.IsA('medPlayerReplicationInfo'))
        return A;

    A.Destroy();
    return Spawn(class'medPlayerReplicationInfo');
}

defaultproperties
{
    ActorClass=class'PlayerReplicatonInfo'
}

Ok if you took the above and put them into their respective uc files, it is a complete and compiling mutator. If you look at the medPlayerReplicationInfo class, as you can see it is doing nothing but subclassing PlayerReplicationInfo.

Now if I add the actor to the server, and then join the server to play, now the other players (real players, not bots) are invisible to me (and each other).

There must be something else I need to do, at the point that I replace the player's PRI with my subclassed version, to ensure the base class can still function properly.

I hope I got across what is happening :(
 

Helen

Member
Jan 23, 2010
48
0
6
You don't need a SpawnNotify for that. Just use the Mutator.CheckReplacement() function to find spawned Pawns and change their PlayerReplicationInfoClass to your new PRI type. You don't need to initialize the PRI at all because it hasn't been spawned yet.

Whoops I didn't see your comment. I did in fact try that at one point, but it was in conjunction with my full mutator. I will try this way again right now with the little example mutator I made up.
 

Helen

Member
Jan 23, 2010
48
0
6
You don't need a SpawnNotify for that. Just use the Mutator.CheckReplacement() function to find spawned Pawns and change their PlayerReplicationInfoClass to your new PRI type. You don't need to initialize the PRI at all because it hasn't been spawned yet.

Yes, this did the trick. I'm not sure why it didn't work before. Probably because some of my other code was misfiring at the time.

Thanks so much for putting me back on the right track :) :) :) :) :)