Sometimes unable to switch from vehicle driver to commander

Issue #330 resolved
Matt Hands created an issue

Hard to recreate, but occasionally vehicle driver has been unable to switch to commander's position, even though that slot was empty. But other net players can enter the commander's slot, so it's specific to the one player.

Has been observed in Puma, but probably a general problem. Unknown whether it affects other vehicle slots, but probably as relevant code & mechanics are very similar.

Believed, but not 100% certain, that vehicle driver in this situation could exit vehicle or switch to MG slot. If so then exit is not being blocked, so it's entry to the commander's slot that's being blocked.

Due to nature of bug, this is very likely a clientside problem, possibly a clientside check not meeting exit/entry conditions that would be expected and so blocking a call to the necessary server function.

Comments (10)

  1. Matt Hands reporter

    Added debug exec LogSwitch() to identify the cause of this problem, in commit f3a7351.

    If you ever find you are in a driver's slot and are blocked from entering the commander's position, or any other slot, when there is no apparent reason, then use this exec, copy down the log results & post them here. The bug only happens occasionally and is hard to recreate, so if we get this info it will probably point to the cause straight away.

    The function logs all relevant clientside variables, calls a server function, which then writes back to the client with the corresponding server values. Everything is logged on your client, including the server values, so it's very convenient and no need to access the server's log.

    By default it assumes you are blocked from the commander's position, but if you enter a WeaponPawn index after the console command, it will check variables relating to another position, e.g. "logswitch 1" will handle a hull MG position.

  2. Matt Hands reporter

    Longshot but worth a mention. Entry functionality can check against team number of weapon pawns, which gets set by a factory when it spawns a vehicle, by calling SetTeamNum() on the new vehicle. SpawnManager wasn't doing that, but it seems sensible to match what factory does, so have added same to SpawnManager.

  3. Colin Basnett

    Theel ran this when he got stuck. He got stuck in the driver slot of an M10 wolverine. It doesn't appear there are any discrepancies between the client and server.

    ScriptLog: CLIENT: DH_WolverineTank_Snow  PassengerWeapons.Length = 5  WeaponPawns.Length = 5  WeaponPawn[0] = DH_WolverineCannonPawn_Snow
    ScriptLog: CLIENT: Driver = DH_USTankerPawn  WP.Driver = None  Same team = True  WP.bTeamLocked = True  WP.Team = 1
    ScriptLog: CLIENT: CanExit() = False  StopExitToRiderPosition() = False  PassengerWeapons[0] is rider pawn = False  ViewTransition = False
    
    ScriptLog: SERVER: DH_WolverineTank_Snow  PassengerWeapons.Length = 5  WeaponPawns.Length = 5  WeaponPawn[0] = DH_WolverineCannonPawn_Snow
    ScriptLog: SERVER: Driver = DH_USTankerPawn  WP.Driver = None  Same team = True  WP.bTeamLocked = True  WP.Team = 1
    ScriptLog: SERVER: CanExit() = False  StopExitToRiderPosition() = False  PassengerWeapons[0] is rider pawn = False  ViewTransition = False
    
  4. Matt Hands reporter

    Hmmmm ....... CanExit() appears to be returning false on both. That function returns false

    if (DriverPositionIndex < UnbuttonedPositionIndex || (IsInState('ViewTransition') && DriverPositionIndex == UnbuttonedPositionIndex))
    

    We know it wasn't stuck in state ViewTrans as we logged that. So the only way the false condition can be met is if DriverPositionIndex < UnbuttonedPositionIndex. UPI doesn't change, so that suggests DPI isn't what it should be. Not at all what I expected ! DPI is variable that's only ever changed on the server and replicated to all clients.

    Will look through the code a little, but if nothing jumps out I'll add PositionIndex logging to the debug exec, so next time we'll get that extra info.

  5. Matt Hands reporter
    1. CanExit() was a red herring. A false value just means you can't exit the tank because you are buttoned up; doesn't mean you aren't allowed to switch to commander's slot. CanExit() and DriverPositionIndex are not to blame. I've removed CanExit() from the debug log as it is misleading.

    2. I have added logging of the RoleInfo's bCanBeTankCrew value on client and server. Is used in clientside checks for position swap eligibility, as well as checking on server, so values must match.

    3. Added new debug exec 'ToggleBypass'. This will toggle on/off a bypass of normal clientside checks in SwitchWeapon() function. If you get stuck in the driver's seat, after using LogSwicth(), try using ToggleBypass() and seeing what happens.

    4. I got this bug in the JP4 with my own PC running as a dedicated server, so it shows it can happen that way, although it seems extremely rare. In my case the log showed me straight away what was wrong, as my client didn't have the cannon pawn actor !

    ScriptLog: CLIENT: DH_JagdpanzerIVL70Destroyer_CamoTwo  PassengerWeapons.Length = 4  WeaponPawns.Length = 4  WeaponPawn[0] = None
    ScriptLog: CLIENT: Driver = DH_WSS_TankerPawn  WP.Driver = None  Same team = True  WP.bTeamLocked = True  WP.Team = 0
    ScriptLog: CLIENT: CanExit() = False  StopExitToRiderPosition() = False  PassengerWeapons[0] is rider pawn = False  ViewTransition = False
    ScriptLog: SERVER: DH_JagdpanzerIVL70Destroyer_CamoTwo  PassengerWeapons.Length = 4  WeaponPawns.Length = 4  WeaponPawn[0] = DH_JagdpanzerIVL70CannonPawn_CamoTwo
    ScriptLog: SERVER: Driver = DH_WSS_TankerPawn  WP.Driver = None  Same team = True  WP.bTeamLocked = True  WP.Team = 0
    ScriptLog: SERVER: CanExit() = False  StopExitToRiderPosition() = False  PassengerWeapons[0] is rider pawn = False  ViewTransition = False
    *(accompanied by lots of "Accessed None 'weaponPawn'" errors)*
    

    The cannon was visible, so I had the cannon actor, just no cannon pawn, which should of course have been replicated. I obviously would fail the clientside checks, but what would happen if they were removed and my client had called ServerChangeDriverPosition(2) on the server? The server would handle it fine, but it would tell my client to enter a cannon pawn that my client didn't have ! I don't think that would have ended well. Hence I have added the ToggleBypass() exec - let's find out what would have happened !

    I do wonder if this is a manifestation of that rare, but always present possibility that the engine's actor replication just gets screwed up sometimes and there's nothing you can do about it? You know when you very occasionally see a tank in spawn with no turret? Just means cannon actor didn't replicate. In my case I had the cannon - and saw it - but I got an 'invisible' bug where I couldn't move into the non-existent cannon pawn.

    ps - A perfectly rationalise explanation of the bug I just encountered, but I have no freakin' idea why it happened in Theel's Wolverine case reported above ! He obviously had the cannon pawn on his client, so ........... Computers, eh? I think we can say that there's nothing fundamentally wrong with the code. But I do want to find out what happens with the bypass option after someone gets stuck.

  6. Matt Hands reporter

    When driving to work this morning, I worked out what would happen - and why - if we skipped clientside checks and sent the call to ServerChangeDriverPosition(2) to the server, even if the cannon pawn actor doesn't exist on the client (for whatever network screw-up reason). The server would process the function without problem, as it has the necessary cannon pawn actor. On the server we now possess the cannon pawn, so the server would immediately realises the CP is relevant to us and replicates the actor to our client. The clientside CP entry process now takes place as normal, without problem.

    Why am I confident this would happen & work? Because it's exactly the same as happens with our new rider pawn system. Empty riders pawns will rarely be present on any client and the clientside checks in SwitchWeapon() allow for that, by allowing the call to the server switch function if the weapon pawn in the PassengerWeapons array is a rider pawn. Even though the weapon pawn does not exist on the client at that time, SwitchWeapon() allows the server call because it knows the rider pawn should exist on the server, so the client can expect the process to work. And we know the server manages to make the rider pawn relevant & replicate it in time for the client to perform the entry process.

    So ...... I'm going to modify SwitchWeapon [on Sat a.m. 20/6] to allow the server call if any hosen weapon pawn index exists in the PassengerWeapons array in def props, even if the weapon pawn does not exist on the client. In other words, treat switching to cannons and MGs exactly like rider pawns. I think this will actually simplify the function a little. And I am confident it will resolve the cannon pawn-related problem I've outlined. You know, this pain is worth it, as it helps out understanding of potential replication problems and how to spot and counter them !

  7. Log in to comment