A question on PRI

Discussions about Coding and Scripting
Post Reply
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

A question on PRI

Post by JackGriffin »

OK, so I'm messing around a bit with the Val Av release made to UA. When I've created my own PlayerReplicationInfo I've always just made the class and then went on but I've never had to link more than one so I've never found the limitations imposed by doing this.

Here's what I'd like to do. I've cleaned up the Val Av code, removed the Ustripper stuff from it, and made it ready to be used in other mods. This Val Av carries it's own PRI (called ALPRI) and so I need to make it play friendly with mods that have an existing PRI. Let's use MH2 for example, since I know that one a bit.

Is it acceptable to simply alter the script so that ALPRI extends IPRI (MH2's PRI class) and load it into the spawned mutator list in PreBeginPlay? It seems like the logical solution to me but has anyone done this sort of thing and are there limitations on linking PRI classes? I will merge ALPRI into IPRI if I have to but I'd like to avoid this if possible.
So long, and thanks for all the fish
Bloeb
Experienced
Posts: 95
Joined: Tue Apr 06, 2010 11:07 am

Re: A question on PRI

Post by Bloeb »

I don't see why it's not acceptable. I can only think of 2 problems:
1. Name-clashes (easy to solve off course).
2. You create a dependency on a different mod. That might not be a real problem, but then you might as well just integrate/merge the code entirely.

Do you really have to replace the players PRI though? Is it not possible to keep the custom PRI's in a seperate array?
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: A question on PRI

Post by JackGriffin »

What I was trying to do was make a set of classes where someone can make a few edits and either integrate the mod into their existing custom game code or compile this generic Val Av to work with any existing PRI they already are using.

I compiled the code into the MissleMania mod I made (it has it's own PRI also) and it all looks good. I'll server test it this afternoon when I can get someone live to test it with me. It just occurred to me though that I didn't really need to do that whole thing since I could have just as easily compiled the Val Av with a dependency on the MissileMania and it would have worked just fine too.

As far as keeping the PRI's in an array I'm honestly just not sure if that's easily done. It's a bit above my pay grade in ability.
So long, and thanks for all the fish
Bloeb
Experienced
Posts: 95
Joined: Tue Apr 06, 2010 11:07 am

Re: A question on PRI

Post by Bloeb »

JackGriffin wrote: As far as keeping the PRI's in an array I'm honestly just not sure if that's easily done. It's a bit above my pay grade in ability.
Some mods (e.g. BT++, my own BTME-mod) use a seperate array to put all the Player Info. The mod checks for new players, finds a free slot and initiates them. I'm not sure if it will work with ValAv or MH2, but it's worth a try.

Code: Select all

class CustomMutator extends Mutator;

struct PlayerInfoStruct
{
	var PlayerPawn Player;

	var CustomPlayerReplicationInfo PRI;
};

var PlayerInfoStruct PlayersInfo[32];

simulated function tick(float DeltaTime)
{
	// check for new players and init them
}
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: A question on PRI

Post by JackGriffin »

OK I messed a bit with this and I got to try it as a separate mod. Total failure, the PRI's conflict with each other and the Val Av addition works (loads) but gets no info replicated to it. Online players are all green and skating. At least I'm hooking them all, it's just not sharing the information.

Dammit, as I was typing this I think I know what the problem might be. In my Deemer mod code I have the IPRI under alwayskeep. It might be causing the ALPRI to not share correctly. Ugh, nothing is ever easy is it?

I see what you mean about the array, and it's something I'd use except the Val Av code is actually really involved. It's going to be a lot of work to get that sort of setup. Honestly if this requires a large amount of test/tweak/rewrite I'm just going to scrap it. I was looking for a semi-easy fix for the problem but if this is major work then I'll give it to someone to do. It's not a deal breaker since skins and voices can be added to the server anyway.

Edit: Did a quick test removing my MissleMod but leaving the new Val Av. It works so there is conflict in the PRI chaining. Damn, I was afraid of that.
So long, and thanks for all the fish
Bloeb
Experienced
Posts: 95
Joined: Tue Apr 06, 2010 11:07 am

Re: A question on PRI

Post by Bloeb »

JackGriffin wrote:OK I messed a bit with this and I got to try it as a separate mod. Total failure, the PRI's conflict with each other and the Val Av addition works (loads) but gets no info replicated to it. Online players are all green and skating. At least I'm hooking them all, it's just not sharing the information.

Dammit, as I was typing this I think I know what the problem might be. In my Deemer mod code I have the IPRI under alwayskeep. It might be causing the ALPRI to not share correctly. Ugh, nothing is ever easy is it?
That's strange, hope you can find a way to fix it.
JackGriffin wrote: I see what you mean about the array, and it's something I'd use except the Val Av code is actually really involved. It's going to be a lot of work to get that sort of setup.
Well, I can hand you the necessary code for the checks and initialisation. That could atleast save you some time if you're interested in trying it with arrays.
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: A question on PRI

Post by JackGriffin »

UA is up/down at the moment...does anyone have any idea about chaining PRI together before I go tearing apart my other mod to find the conflict? I'll post to UA too as soon as I get a clear shot.
So long, and thanks for all the fish
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: A question on PRI

Post by Higor »

One PRI, one player.

Modifying a PRI has always been a key in replicating player data, but having only a single PRI per player creates a huge limitation.
As mentioned before, PRI's only difference with other bAlwaysRelevant actors is that it natively replicates a set of variables, subclassing PRI is not the way, specially since the new variables won't be affected by the enhanced native replication.

You need an external module.
You can either use syncronised lists (niceCtf, FV_AntiPistonCamp, NiceCTF, CTFPlus, AutoTeamBalancer, etc), or dupe the entire PRI system (smartCTF).
How to dupe replication system?
Create a master entity (simil of GameReplicationInfo), spawned at mutator PreBeginPlay(), (bAlwaysRelevant=true; RemoteRole=Role_DumbProxy).
Create a watcher class (simil of PlayerReplicationInfo), (bAlwaysRelevant=true; RemoteRole=Role_SimulatedProxy).
Create a SpawnNotify subclass that hooks into the ValAvatar players, use it to spawn a watcher and hook it into this playerpawn. (RemoteRole=Role_None)

Master entity will run the exact same checks for watchers as GameReplicationInfo does for PRI's, clean watcher list then store as well.
Watcher will run a timer every 2 seconds to see if player still exists (only server check Role<Role_Authority).

On client or Listen Server host:
On Watcher Timer() (Level.NetMode != NM_DedicatedServer), enforce skins if player owner exists (if player owner exists on client, it's because he's a relevant actor).

Tada, you duped the replication info system.
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: A question on PRI

Post by JackGriffin »

Tada, you lost me at around the third line ;)

I see what you mean (sorta) by following the example in SmartCTF_4B but this is much more involved than I really want to get with this mod. It's just going to be easier to import it into my existing stuff as it is and mix in it's PRI class into my own. I was just trying to find an easier way that preserved the ability of it to keep it's existing PRI and thus fix it's usage with mods that are already out there.

I appreciate the follow-up and instructions, they were quite informative and if I ever build a PRI system again it will be done this way.
So long, and thanks for all the fish
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: A question on PRI

Post by Higor »

SpawnNotify is an increadibly easy and powerful feature if that's what you mean.

I made various uses of these, can provide extremely powerful hacking abilities as well (I used it to tap into team messages and register them for later direct acknowledge).
Can be used as spawn alarm, or even better, as spawn item replacer...

That's it, I just gave you a 3rd option...
Plugin system + general function handler, something I extensively used on FerBotZ.

It consists on a plugin loader depending on the kind of PRI the game is spawning.
The plugin system is used through DynamicLoadObject to prevent dependencies.
Every plugin spawns it's own PRI, which is a subclass of the MOD PRI.
Then ValAvatar access the new PRI using GetPropertyText and SetPropertyText.
Custom functions will be static functions stored in the mutator.


If you're interested in doing this, ill give you further explanation with code examples.
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: A question on PRI

Post by JackGriffin »

Yeah I am very much interested. This is a bit above my skill level but I do enjoy the challenge of working something out. If you get time I'd appreciate an example to follow because I'm in the deep end of what I'm comfortable with understanding. There are a LOT of admins that would deeply appreciate this getting worked out and would love to use a Val Av type mod on server that doesn't conflict with what they already have running.
So long, and thanks for all the fish
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: A question on PRI

Post by Higor »

A few guidelines first:

Calling an function in an actor we don't have a code dependency (but we know how it works):

On call target:

Code: Select all

class Val(mod id and version)PRI extends (insert mod pri class here);
var string FunctionName;
var string Param1, Param2, Param3;
var string valIdentifier; //DEFAULT = VAL;    THIS IS IMPORTANT!!, create a VALIDENTIFIER variable and set it to VAL (case sensitive!), you'll see later

//Trigger is defined in actor class, it is a common method among actors
event Trigger( actor Other, pawn EventInstigator)
{
      if ( FunctionName != "" )
      {
            if ( FunctionName ~= "SampleFunction" )
                  SampleFunction( int(Param1), bool(Param2), Param3);
//            else if .. other functions to be added
            FunctionName = "";
            Param1 = "";
            Param2 = "";
            Param3 = "";
            return;
      }
}

function SampleFunction( int Par1, bool Par2, string Par3);

defaultproperties
{
      valIdentifier = VAL
}
On caller actor:

Code: Select all

//Pointer to basic PRI class, not advanced one
var PlayerReplicationInfo PRI;

function SampleCallOnPRI()
{
      if ( PRI == none )
            return;
      PRI.SetPropertyText( "FunctionName", "SampleFunction");
      PRI.SetPropertyText( "Param1", "346");
      PRI.SetPropertyText( "Param2", "True");
      PRI.SetPropertyText( "Param3", "test");
      PRI.Trigger( self, none);
}

You're going to need one package+PRIsubclass for EACH mod and version plus a base PRIextension for vanilla games.
So this code is to be duplicated on every PRI subclass, the one on the mutator or player doesn't need to be modified if PRI code is the same.
Make sure you pick variable names that are not used in any of the mod PRI's (i'd tag them like valSkin, valString, valBool, etc).

How do we perform the hook?
Theory below:
Spawn notify hooks into a certain actor class type, and this happens:
You attempt to spawn PRI on Pawn or on mod Login()
PRI = Spawn( class'MyModPRI');
After the PRI is spawned, but before PRI is set, SpawnNotify hooks it.
SpawnNotify can spawn a different actor and return this one instead, useful to hack things without breaking mods (if new item is subclass of desired item).

Code: Select all

class valPRINotify extends SpawnNotify;

var() string ReplaceThis[64];
var() string ReplaceWith[64];

event SpawnNotification( actor A)
{
      local int i;
      local string sTmp; //Faster operation
      local PlayerReplicationInfo newPRI;

      //This is a valhalla avatar extended PRI, do nothing, avoids infinite spawn recursion
      if ( A.GetPropertyText("valIdentifier") == "VAL" )
            return A;
      sTmp = String(A.Class);

      For ( i=0 ; (i<64)&&(ReplaceThis[i]!="") ; i++ )
      {
            if ( sTmp ~= ReplaceThis[i] )
            {
                  newPRI = Spawn( class<PlayerReplicationInfo>(DynamicLoadObject( ReplaceWith[i], class'class')), A.Owner, A.Tag, A.Location, A.Rotation);
                  if ( newPRI != none )
                  {
                        A.LifeSpan = 0.1; //Make sure this is deleted in no time
                        return newPRI;
                  }
                  return A;
            }
      }
      return A;
}

defaultproperties
{
      ActorClass = class'Engine.PlayerReplicationInfo'
      ReplaceThis(0) = Engine.PlayerReplicationInfo
      ReplaceWith(0) = valAvatar.BaseReplicationInfo
      ReplaceThis(1) = Mod07.Mod07PRI
      ReplaceWith(1) = valMod07.valMod07PRI
}
With this, your spawn notify will replace base or mod PRI's with their subclassed versions which do not generate code dependency.
You access these new PRI's properties by using SetPropertyText and GetPropertyText and call functions via Trigger(self,none).

MAKE SURE THE SPECIFIC PLUGIN PACKAGE TO BE USED WITH THE MOD IS AMONG THE 'SERVERPACKAGES', BECAUSE PRI IS REPLICATED TO CLIENT

One more thing, the SpawnNotify subclass must have RemoteRole = Role_None, it's not supposed to change PRI on client machines.
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: A question on PRI

Post by JackGriffin »

I'm working through this Higor, I have to take it a bit slowly so I understand each thing I'm doing. Is there an existing mod that I can follow that uses this method? I'm truthfully a little lost at the moment. I haven't gotten to the "A-ha!" point yet :(
So long, and thanks for all the fish
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: A question on PRI

Post by Higor »

So far that I know, there is no mod using this method.

Well, most known mods actually replace the BASE PRI with a modified one.
This method can replace the BASE one, or the MODIFIED one from other mods, so it's like an extension of it (with no code dependance).

Of course, this is actually a workaround of a bigger issue, because just like simple mods only allow ONE PRI change, this one allows up to TWO PRI variations via subclassing.
That is because the PRI is an actor and can't dynamically add variables into it.

The ideal design would have been a chained PRI method (nextPRI) on PlayerReplicationInfo, where the first PRI in chain remains the base PRI class and the ones belonging to mods added after this one.
So game detects variables just fine and mods find through PRI chain their modded PRI and functions.

The only way to multiple mods store/send data belonging to a player, is via a replicated (Owner=clientPlayer or bAlwaysRelevant) actor that is associated to this player, but this approach requires list management since PlayerPawn has absolutely no actor reference to the replicated actors.


I realised something, 4th solution:

Looking into VABeta2, maybe a bit outdated but saw something interesting I had forgotten.
You can use an external actor instead of subclassing PRI, and referencing it directly in your ALPlayer class.
So ALPRI instead of being a PlayerReplicationInfo subclass, use it as actor subclass (remember to bHidden, bAlwaysRelevant and RemoteRole=ROLE_SimulatedProxy)
And the ALPlayer will contain a reference to this new ALPRI and its functions without conflicting with the original PRI, the ALPRI reference can be replicated to clients because the referenced actor is also existing on clients all the time.
This is a unique solution to your mod because it replaces the PlayerPawn actor.

I would use this one.
Post Reply