Announcement

Collapse
No announcement yet.

Replication from the Mutator Class? How?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    #46
    Can you get your hands on his log files?

    Comment


      #47
      Originally posted by KewlAzMe View Post
      But I have a log set in my ReplicatedEvent function that never gets called. This is where I call SetJumpNum() on the client so I assume this is the missing piece to getting it to work. Im looking at other classes that use this ReplicatedEvent and it seems to be correct, complete with the repnotify variables... so Im still trying to figure it out.
      Are you testing this with an actual client?

      Comment


        #48
        Originally posted by immortius View Post
        Are you testing this with an actual client?
        Yes. Chief is running UT3 and connecting to my server. He is seeing the DL of the mutator and I can see him on my server and the logs firing. All but the ReplicatedEvent.

        Mutator Class:
        Code:
        Class MultiJumpMut extends UTMutator Config(MultiJump);
        
        var() config int iMaxNumJumps;
        
        function ModifyPlayer(Pawn Other)
        {
        	local MultiJumpInv MJI;
        
        	Super.ModifyPlayer(Other);
        
        	MJI = Spawn(class'MultiJump.MultiJumpInv');
        	if (MJI != None) {
        		MJI.iMaxNumJumps = iMaxNumJumps;
        		MJI.GiveTo(Other);
        	}
        }
        
        defaultproperties
        {
           iMaxNumJumps=4
        }
        Invetory Class:
        Code:
        Class MultiJumpInv Extends UTInventory;
        
        var() repnotify int iMaxNumJumps;
        
        replication
        {
        	if (Role == ROLE_Authority)
        		iMaxNumJumps;
        }
        
        function GivenTo( Pawn thisPawn, optional bool bDoNotActivate )
        {
        	Super.GivenTo(thisPawn, bDoNotActivate );
        	SetJumpNum();
        }
        
        simulated function ReplicatedEvent(name VarName)
        {
        	`log("hit RepEvent");
                if (VarName == 'iMaxNumJumps')
        	{
        		SetJumpNum();
        	}
        	Super.ReplicatedEvent(VarName);
        }
        
        simulated function SetJumpNum() {
        	UTPawn(Owner).MaxMultiJump = iMaxNumJumps;
                UTPawn(Owner).MultiJumpRemaining = iMaxNumJumps;
        }
        
        
        defaultproperties {
        }
        It looks perfect to me! even the other examples I see in other pickups and other mutators seems to be nearly exact. But my log in the ReplicatedEvent function never hits.

        Comment


          #49
          Are you checking the client-side logs? :P

          The only other possibility I can think of at the moment is that the variable is replicating with the actor (I haven't done tests regarding the with UT3), in which case you'll want to call SetJumpNum() with the ClientGivenTo() function as well as the ReplicatedEvent() function.

          Comment


            #50
            Try changing the line where you spawn the inventory to this:
            Code:
            MJI = Spawn(class'MultiJump.MultiJumpInv', Other);
            or maybe:
            Code:
            MJI = Other.Spawn(class'MultiJump.MultiJumpInv');
            That will set the owner of the item to Other when it is spawned, ensuring that it is network-relevant right away. I'm not sure if that will make a difference.

            Don't forget that you can run server + client on the same machine for quicker testing.

            Comment


              #51
              There was nothing I could find in my client log files. I rewrote the Inv class to look more like other examples using AdjustPawn and stuff (yes i know AdjustPawn is just the generic name of a custom function)

              Let me clear up some process flow questions. From what I can tell, the process is something like this:

              1. A player joins the server, the server reads the Mutator class ModifyPlayer function first which does the spawning of the custom Inventory class to the clients.
              2. The server reads the Inventory class now to see what it needs to do while spawning it.
              3. First it sees that it has to replicate the iMaxNumJumps variable to clients, which it got from the mutator class' default props or config value.
              4. Next it sees there is a GivenTo override that it needs to run. This calls the AdjustPawn which does the custom code execution stuff and then the "Super" runs the normal version of the function
              That concludes the server's involvment

              5. Now when the server runs GivenTo, the Client sees that it is being given "something" and reads that inventory file to see what it is supposed to do with it. So it reads the Inventory class and only see the "simulated" functions on its to-do list. And sees that there is also a variable that is out there for him with a value already.

              Is this about how it works?

              Still not hitting the ReplicatedEvent. I did see it hit the ClientGivenTo once in the server log.. which may be odd.. but it didn't pass the If (Role < Role_Authority) to get to the main part of the function. I do see the serverside GivenTo getting hit tho.

              Code:
              Class MultiJumpInv Extends UTInventory;
              
              var() repnotify int iMaxNumJumps;
              
              replication
              {
              	if (Role == ROLE_Authority)
              		iMaxNumJumps;
              }
              
              function GivenTo(Pawn NewOwner, bool bDoNotActivate)
              {
              	Super.GivenTo(NewOwner, bDoNotActivate);
              	`log("GivenTo was run");
              	AdjustPawn(UTPawn(NewOwner), false);
              }
              
              reliable client function ClientGivenTo(Pawn NewOwner, bool bDoNotActivate)
              {
              	Super.ClientGivenTo(NewOwner, bDoNotActivate);
              	`log("ClientGivenTo has been hit");
              	if (Role < ROLE_Authority)
              	{
              		`log("ClientGivenTo adjustpawn hit! Winnar!");
              		AdjustPawn(UTPawn(NewOwner), false);
              	}
              }
              
              
              simulated function ReplicatedEvent(name VarName)
              {
              	`log("ReplicatedEvent has at least started");
              	if (VarName == 'iMaxNumJumps')
              	{
              		`log("ReplicatedEvent has iMaxNumJumps ="$iMaxNumJumps);
              		AdjustPawn(UTPawn(Owner), false);
              	}
              	Super.ReplicatedEvent(VarName);
              }
              
              simulated function AdjustPawn(UTPawn P, bool bRemoveBonus)
              {
              	if (P != None)
              	{
              	        `log("AdjustPawn was called with iMaxNumJumps="$iMaxNumJumps);
              	        P.MaxMultiJump = iMaxNumJumps;
                              P.MultiJumpRemaining = iMaxNumJumps;
              	        `log("AdjustPawn P.Maxmultijump="$P.MaxMultiJump);
              	}
              }
              
              defaultproperties {
              }
              It still never hits the 3 points in orange above. Which might make sense since those are Client only functions (i think). But the client logs in the My Docs\My Games\UT3\UTGame\Logs tell me nothing.

              I also tried adding the Other.Spawn(xxx....) to the mutator class to no avail.

              Seems like a lot of work for something so seemingly simple. Had they just replicated the variable like they used to, it could have been 4 lines of code like it was in UT2004's Quadjump mutator.

              Comment


                #52
                Originally posted by KewlAzMe View Post
                Had they just replicated the variable like they used to, it could have been 4 lines of code like it was in UT2004's Quadjump mutator.
                Perhaps, but it would be stupid of them to replicate a value that doesn't change in their code. I have a suspicion that whoever in epic created the QuadJump mutator changed the variable to replicate, so they basically cheated.

                Anyway, the workflow is something like:

                1. Mutator is spawned, which automatically sets it's default properties and reads config variables from the ini file.

                2. At some point a player joins the game. At some point he'll click to begin play, at which point a pawn is spawned for him and then all mutators get their ModifyPlayer function called on the server.

                3. Your mutator creates the inventory item, set's the new MaxJumpNum value on the item and gives it to the pawn, at which point GivenTo() in the inventory item is called. Still on the server.

                4. GivenTo() sets the max jump values on the pawn on the server, and then the Super calls ClientGivenTo().

                5. If the player is a player on a listen server or on in a standalone game, the ClientGivenTo() function will be called there and then, but won't set MaxJumpNum again because of the role check.

                6. Otherwise, at some point in the future the inventory item will be replicated to the client, the iMaxJumpNum variable will be replicated, and the ClientGivenTo() function called. Not necessarily in that order, although I'm sure the latter 2 would be saved for when the former occurs.

                7. When the inventory item is received it will be created on the client's machine and receive a PostBeginPlay() event.

                8. When the iMaxJumpNum variable is received it is set and a ReplicatedEvent should be called.

                9. When ClientGivenTo() is received it executes on the client.

                None of the stuff that happens on the client will appear on the server.log for the obvious reasons.

                Rather than relying on log files, you can run you client with the -log commandline argument and watch the messages as they appear.

                Comment


                  #53
                  I'm not sure what to tell you. At the very least, ClientGivenTo should be executed on the client since the replication for that is Epic's code, and the way you're handling ReplicatedEvent is virtually identical to the way I did it for the Gibalicious mutator which seemed to work when I tested it.

                  Is anything happening on the client at all? As a last resort you could try setting the inventory item's bAlwaysRelevant to true.

                  Comment


                    #54
                    OK I will try the -log switch and I think I used to have bAlwaysRelevant but thought it wasn't needed.. Ill try that again. I don't know if "nothing" is happening on the client, as my only real test is jump jump jump jump!

                    Comment


                      #55
                      You can host the server locally, as a lan, and connect to 127.0.0.1 to test locally and avoid having to wait for someone to test along side you. Your server will have to be dedicated, and your client will be you when you rejoin.

                      [Tab] > open 127.0.0.1 or [F10] > open 127.0.0.1

                      Comment


                        #56
                        Yes i know how to run a server & client, but I cannot run a client from my PC over VNC from work :P

                        Comment


                          #57
                          oic, kk, =)

                          Comment


                            #58
                            I gave it a quick try. The replication is all fine and firing off correctly (iMaxNumJumps is replicating before ClientGivenTo, incidently). However, this is happening before the player's pawn is replicated as far as I can tell, so the owner is none. Best way to deal with this is set a repeating timer that will continue until the pawn is replicated.

                            Code:
                            reliable client function ClientGivenTo(Pawn NewOwner, bool bDoNotActivate)
                            {
                            	Super.ClientGivenTo(NewOwner, bDoNotActivate);
                            	`log("ClientGivenTo has been hit");
                            	if (Role < ROLE_Authority)
                            	{
                            		if (!TryAdjustPawn) {
                                                    SetTimer(0.2,true,'TryAdjustPawn');
                                            }
                            	}
                            }
                            
                            
                            simulated function ReplicatedEvent(name VarName)
                            {
                            	`log("ReplicatedEvent has at least started");
                            	if (VarName == 'iMaxNumJumps')
                            	{
                            		`log("ReplicatedEvent has iMaxNumJumps ="$iMaxNumJumps);
                            		if (!TryAdjustPawn) {
                                                    SetTimer(0.2,true,'TryAdjustPawn');
                                            }
                            	}
                            	Super.ReplicatedEvent(VarName);
                            }
                            
                            simulated function bool TryAdjustPawn() {
                                    if (UTPawn(owner) != none) {
                                            AdjustPawn(UtPawn(owner), false);
                                            ClearTimer('TryAdjustPawn');
                                            return true;
                                    }
                                    return false;
                            }

                            Comment


                              #59
                              That sounds like a hell of a kludge. I appologize for my absence lately, but i have two days left to spend with my lady and ill be rejoining you guys on your quest for the best way to network a mutator.

                              Until then i hope you guys find a better way than this. Its only a step further than putting a test in my tick function to just return out when i have already sent the pawn my values.

                              Comment


                                #60
                                Perhaps this:
                                Code:
                                var repnotify int iMaxNumJumps;
                                var repnotify UTPawn Pwnzor;
                                
                                replication
                                {
                                	if (Role == ROLE_Authority)
                                		iMaxNumJumps, Pwnzor;
                                }
                                
                                simulated function ReplicatedEvent(name VarName)
                                {
                                	if((VarName == 'iMaxNumJumps' && Pwnzor != none) || (VarName == 'Pwnzor' && iMaxNumJumps != -1))
                                	{
                                		AdjustPawn(Pwnzor, false);
                                	}
                                	
                                	Super.ReplicatedEvent(VarName);
                                }
                                
                                defaultproperties
                                {
                                	iMaxNumJumps=-1
                                }
                                This ensures that AdjustPawn is called only after both variables have been replicated (set them both in the mutator at the same time), no matter the order.

                                Comment

                                Working...
                                X