We can view the player's current docking clearance status from the player.dockingClearanceStatus property, which has codes indicating current status with respect to the player's current docking target, but we don't seem to have direct access to the player's current docking target.
There are five world-script event handlers triggered at various stages of the docking protocol:
5. playerRequestedDockingClearance(string message) // this is invoked from two places in the game code:1. playerDockingClearanceCancelled() // This method was added in Oolite test release 1.85. The playerDockingClearanceCancelled handler is called when the player withdraws their request to dock at a station.
2. playerDockingClearanceExpired() // This method was added in Oolite test release 1.83. The playerDockingClearanceExpired handler is called when the player exceeds the two minute window without requesting an extension
3. playerDockingClearanceGranted() // This method was added in Oolite test release 1.85. The playerDockingClearanceGranted handler is called when the player is given permission to dock at a station. If the player is given immediate clearance to dock, this event will be called immediately after the playerRequestedDockingClearance event. If, however, the station is unable to give immediate clearance, then there will be some delay between the request to dock and permission being granted. This event will be called when the station actually gives docking clearance.
4. playerDockingRefused() // The playerDockingRefused handler is called when a station refuses to provide autopilot docking instructions.
a. When the player presses Shift-L (or equivalent remapped key) with a dockable as primary target
b. When the OOJS function player.ship.requestDockingClearance(station) is called from a script
Note that none of the above listed event handlers are informed which station triggered the event.
With both 5(a) and 5(b), the internal game function acceptDockingClearanceRequestFrom in StationEntity.m handles the request. Important for the multiple stations scenario, it checks if the player already has a docking target (an internal variable targetDockStation holds the dockable that the player most recently requested clearance from), and if it does, it then uses the internal game function setDockingClearanceStatus to update the player's status (accessible via player.dockingClearanceStatus) and sets that targetDockStation variable to the player ship's current target.
The 5(b) case, an OXP script triggering the docking request, is not used anywhere in the game Resources files, but at least one OXP uses it (BroadcastComms MFD). If the station provided in player.ship.requestDockingClearance(station) is not the player ship's primary target, it will log an error and set the targetDockStation to nil.
So, with either 5(a) or 5(b), it seems that we can use player.ship.target in the playerRequestedDockingClearance(string message) event handler to know which station generated the event.
But coming back to the multiple stations scenario, what happens with the clearance request to the previous station?
The internal game function update in StationEntity.m is the next point of interest. Every so often, each station independently runs this update function. It first looks at whether it is the player's current targetDockStation, and if it is, then it updates the player's docking clearance as appropriate (for example, changing it from granted to timing out, or from requested to granted, if the player has queued long enough). But if the player has some other station as targetDockStation then the update function does nothing.
So it seems that if you request docking with station A and then request docking with station B, the status with station A is overwritten and will not time out or progress in any way, and no further world script events are generated with respect to station A. If you then switch back to station A and request clearance again, it starts over from the beginning of the process.
This can leave OXPs that have been tracking these variables and events in a somewhat confused state unless they store the current player.ship.target each time the world script event handler playerRequestedDockingClearance(message) is called, and compare it any previously stored player.ship.target from that event to see if the target station was changed.
Another, unrelated, issue is that there is another OOJS function available to OXPs, player.ship.cancelDockingRequest(station), which seems to be the only way to trigger the playerDockingClearanceCancelled() world script event handler. Other methods of cancellation, such as pressing Shift-L again before the time out/renewal phase, do not seem to trigger that cancellation event handler.
I will leave the details of OOJS OXP-accessible Ship.dockingInstructions property and functions dockingInstructionsForShip, recallDockingInstructions and requestDockingInstructions as an exercise for the reader... (N.B., these are for NPCs and for the player ship under AI control when using docking computers; player.ship.dockingInstructions is null if the docking computers have not been activated, but remains with a value even after autopilot docking has been cancelled and clearance withdrawn, so it cannot be used to infer anything about the player ship's clearance status).
What am I proposing to change? Well, I don't know exactly, my analysis so far has only shown that it is complicated and confusing and has some inconsistencies. The game behavior around the docking clearance protocol seems okay, the pain point is mostly the ability for OXPs to figure out what is going on. I think that exposing the internal targetDockStation as an OOJS accessible property on the player ship would be helpful.
Perhaps we should also explicitly enforce that the station passed to player.ship.requestDockingClearance(station) must be the player.ship.target (this seems to be implicitly enforced once you get through several other functions but it could be checked earlier).
Also, player.ship.cancelDockingRequest(station) apparently returns without any effect if autopilot is engaged and the station is the same as targetDockStation. I imagine there is a story behind that.