Replaced the 'Turn' protocol by the Update' protocol.
Bumped the UQM and netplay protocol versions. Some cleanups. git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3537 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
Changes towards version 0.7:
|
Changes towards version 0.7:
|
||||||
|
- Fixed the network SuperMelee team configuration protocol - SvdB
|
||||||
- Fixed fuel reserve bounds checks - SvdB
|
- Fixed fuel reserve bounds checks - SvdB
|
||||||
- Fixed a crash when filling fuel tanks over 10 (bug #1082) - Alex
|
- Fixed a crash when filling fuel tanks over 10 (bug #1082) - Alex
|
||||||
- Got rid of many warnings - SvdB
|
- Got rid of many warnings - SvdB
|
||||||
|
|||||||
+138
-33
@@ -5,7 +5,7 @@ of a network connection.
|
|||||||
This is used when both parties need to sending information to the
|
This is used when both parties need to sending information to the
|
||||||
other side, but what each party is doing does not interfere with
|
other side, but what each party is doing does not interfere with
|
||||||
what the other party is doing.
|
what the other party is doing.
|
||||||
- Only speak in your own turn ("Turn")
|
- Agree on changes ("Update")
|
||||||
This is used when the parties have changes to make to common data.
|
This is used when the parties have changes to make to common data.
|
||||||
- Mutual agreement on an action ("Confirm")
|
- Mutual agreement on an action ("Confirm")
|
||||||
This is used to end a state where both parties are modifying
|
This is used to end a state where both parties are modifying
|
||||||
@@ -49,43 +49,148 @@ local decision -> Send READY goto 3
|
|||||||
|
|
||||||
============================================================================
|
============================================================================
|
||||||
|
|
||||||
"Turn" negotiation.
|
"Update" negotiation.
|
||||||
|
|
||||||
For some actions (like changing a shared configuration option), it is
|
During configuration, both sides may change the same properties. So that the
|
||||||
important that both sides don't just send changes at once.
|
two sides don't have to take turns, the changes are made locally, and then
|
||||||
To handle this, only one party may send these packets at any moment.
|
the changes are synchronised.
|
||||||
If the party whose turn it isn't wants to speak, or if the party whose
|
|
||||||
turn it is doesn't have anything further to say, he can send an ENDTURN
|
|
||||||
packet. The other party should confirm this by sending another ENDTURN
|
|
||||||
packet back.
|
|
||||||
|
|
||||||
States:
|
To this end, each side has a state containing two copies of each property:
|
||||||
0. myTurn - I may speak
|
1. The value of the property as it is locally
|
||||||
myTurn && !endTurn
|
2. The last value which it sent to the other side (until it is no longer
|
||||||
1. endMyTurn - I've given up speaking, waiting for confirmation
|
relevant for the protocol)
|
||||||
myTurn && endTurn
|
|
||||||
2. yourTurn - You may speak
|
|
||||||
!myTurn && !endTurn
|
|
||||||
3. endYourTurn - I want to speak, waiting for confirmation
|
|
||||||
!myTurn && endTurn
|
|
||||||
|
|
||||||
Messages:
|
The basic idea of the Update protocol is:
|
||||||
- ENDTURN - "this party ready to change turns"
|
- both sides each send and receive one packet before being allowed to
|
||||||
|
send another one (we'll call this a "turn" here)
|
||||||
|
- when a packet has been sent and one has been received in a turn,
|
||||||
|
and the sent and received values are the same, then that value is the
|
||||||
|
agreed upon value. If the sent and received values differ, then a
|
||||||
|
tie breaker determines which one prevails.
|
||||||
|
- when the first local change of a turn is made, the change is sent to
|
||||||
|
the other side
|
||||||
|
- when a local change has been made while a packet has already been
|
||||||
|
sent this turn, the change will be made locally, but communicating the
|
||||||
|
change will be postponed
|
||||||
|
- when a turn ends while a change has been postponed, and this change isn't
|
||||||
|
negated by a remote change, then the change will be sent
|
||||||
|
- when a remote change arrives, and a packet has not been sent this turn,
|
||||||
|
the local state is updated with the change, and the same packet is sent
|
||||||
|
to the other side to confirm the change
|
||||||
|
|
||||||
|
The tie breaker is required to always let one side win, and the other
|
||||||
|
side lose, given the same property.
|
||||||
|
Any function satisfying this requirement is usable, but the currently
|
||||||
|
used one will return true for the side which 'owns' the property, and
|
||||||
|
false on the other side.
|
||||||
|
Another tie breaker could be one which always lets the same side win,
|
||||||
|
regardless of the property.
|
||||||
|
|
||||||
|
|
||||||
From state 0 (myTurn):
|
The protocol:
|
||||||
local decision -> Send ENDTURN, goto 1
|
|
||||||
received ENDTURN -> Send ENDTURN, goto 2
|
|
||||||
|
|
||||||
From state 1 (endMyTurn):
|
From state 1, {own=x0, sent=--}:
|
||||||
received ENDTURN -> Send ENDTURN, goto 2
|
1a Local change x1 -> send(x1); state=2:{own=x1,sent=x1}
|
||||||
|
1b Received UPDATE(x1) -> send(x1); state=1:{own=x1,sent=--}
|
||||||
|
|
||||||
From state 2 (yourTurn):
|
From state 2, {own=x0, sent=x0}:
|
||||||
local decision -> Send ENDTURN, goto 3
|
2a Local change x1 -> state=3:{own=x1,sent=x0}
|
||||||
received ENDTURN -> Send ENDTURN, goto 0
|
2b Received UPDATE(x0) -> state=1:{own=x0,sent=--}
|
||||||
|
2c+ Received UPDATE(x1) -> state=1:{own=x0,sent=--} if winTieBreak
|
||||||
|
2c- Received UPDATE(x1) -> state=1:{own=x1,sent=--} if !winTieBreak
|
||||||
|
|
||||||
From state 3 (endYourTurn):
|
From state 3, {own=x1, sent=x0}:
|
||||||
received ENDTURN -> Send ENDTURN, goto 0
|
3a Local change x0 -> state=2:{own=x0,sent=x0}
|
||||||
|
3b Local change !x0 -> state=3:{own=xN,sent=x0}
|
||||||
|
3c Received UPDATE(x0) -> send(x1); state=2:{own=x1,sent=x1}
|
||||||
|
3d+ Received UPDATE(!x0) -> send(x1); state=2:{own=x1,sent=x1} if winTieBreak
|
||||||
|
3d- Received UPDATE(!x0) -> state=1:{own=x?,sent=--} if !winTieBreak
|
||||||
|
|
||||||
|
|
||||||
|
Explanation:
|
||||||
|
We keep track of the local value ('own'), and whether or not we sent a packet
|
||||||
|
in this turn ('sent' != '--'), and if we did, the last packet which we sent
|
||||||
|
('sent'). When we proceed to the next turn, 'sent' is set to '--'.
|
||||||
|
|
||||||
|
State 1: We have not yet sent a packet this turn (which implies that we
|
||||||
|
haven't made a local change this turn).
|
||||||
|
1a. A local change is made. We update our local value, and send this to
|
||||||
|
the remote side.
|
||||||
|
1b. A remote change arrives. We don't have any local change ourselves,
|
||||||
|
so we accept the remote change, and sent it back to confirm.
|
||||||
|
With both a packet sent and one received, the turn ends, and 'sent'
|
||||||
|
is set back to '--'.
|
||||||
|
|
||||||
|
State 2: We have sent a packet this turn (after making a local change), and
|
||||||
|
have not changed our local value since (or we have changed it and changed
|
||||||
|
it back).
|
||||||
|
2a. A local change is made. We update our local value, but we have already
|
||||||
|
sent a packet this turn, so we can't report it until the next turn.
|
||||||
|
2b. A remote change arrives, and it is equal to both our local value and
|
||||||
|
the value which we sent to the other side this turn.
|
||||||
|
This remote notification may be a confirmation of our update, or a
|
||||||
|
coincidental identical remote change.
|
||||||
|
Either way, the packet acts as a confirmation, and we do not need
|
||||||
|
to change anything. With both a packet sent and received, the turn ends
|
||||||
|
and so 'sent' is set back to '--'.
|
||||||
|
2c. A remote change arrives, and it is not equal to our local value (which
|
||||||
|
is the same as the value which we sent).
|
||||||
|
The tie breaker decides which value prevails. The same value will
|
||||||
|
prevail on the remote side, so there is no need to send any confirmation
|
||||||
|
packets. The turn ends, and 'sent' is set back to '--'.
|
||||||
|
|
||||||
|
State 3: We have sent a packet this turn, and have made a local change since.
|
||||||
|
3a. A local change is made back to the value which we sent. No action
|
||||||
|
is required.
|
||||||
|
3b. A local change is made. We update our local value, but we have already
|
||||||
|
sent a packet this turn, so we can't report it until the next turn.
|
||||||
|
3c. A remote change arrives, and it is equal to the value which we sent
|
||||||
|
(which isn't equal to the current local value).
|
||||||
|
The sent/received value is the accepted value and the turn ends.
|
||||||
|
But we have changed our value since already, so as the next turn
|
||||||
|
starts, we immediately send an update.
|
||||||
|
3d. A remote change arrives, and it is not equal to the value which we sent
|
||||||
|
this turn.
|
||||||
|
+ We win the tie break, so the value which we sent prevails.
|
||||||
|
But we have changed our value since already, so as the next turn
|
||||||
|
starts, we immediately send an update.
|
||||||
|
- We lose the tie break, so the value which the remote value sent
|
||||||
|
prevails. We accept the value and the turn ends.
|
||||||
|
(An alternative would be to consider the local change(s) which
|
||||||
|
we made after our change was sent as made in the following turn,
|
||||||
|
in which case we would send our current local value in the next turn.
|
||||||
|
The advantage would be that 3d- would become equal to 3d+,
|
||||||
|
so these could be joined (with 3c too), which saves a few
|
||||||
|
if-statements in the code, but this requires another packet to be sent
|
||||||
|
and replied to in what currently is 3d-.)
|
||||||
|
|
||||||
|
|
||||||
|
Proof outline that this works:
|
||||||
|
- The states can never get out of sync:
|
||||||
|
After both a packet has been sent and received, both sides (temporarilly)
|
||||||
|
have accepted the same value
|
||||||
|
- There can be no indefinite loop without ongoing local changes.
|
||||||
|
Once there are no more local changes:
|
||||||
|
from state 3 we always go to state 2 or 1,
|
||||||
|
from state 2 we always go to state 1
|
||||||
|
from state 1 we can only go back to state 1, and only when a packet
|
||||||
|
has been received.
|
||||||
|
So eventually, both sides are in states 1. With both sides in state 1,
|
||||||
|
no packets have been sent in the current turn, so no more packets are
|
||||||
|
there to be received.
|
||||||
|
- Both sides can make changes, as long as the side which wins the tie breaks
|
||||||
|
stops making changes now and then:
|
||||||
|
Without making local changes, a side will go to state 1 eventually.
|
||||||
|
If a side makes a local change, and this is received by the other side
|
||||||
|
while it is in state 1, then that other side will accept the change.
|
||||||
|
|
||||||
|
|
||||||
|
The Confirm negatiation is used to finish the Update negotiation.
|
||||||
|
This works because local changes triggered by the reception of remote changes
|
||||||
|
are treated as local modifications for the purpose of the Confirm negotiation.
|
||||||
|
And this can be done because whenever the Confirm negotiation is in a state
|
||||||
|
where remote changes may be expected, local modifications are still allowed
|
||||||
|
(possily after sending a CANCEL packet).
|
||||||
|
|
||||||
|
|
||||||
============================================================================
|
============================================================================
|
||||||
@@ -130,7 +235,7 @@ States:
|
|||||||
|
|
||||||
|
|
||||||
Handshake messages:
|
Handshake messages:
|
||||||
- CONFIRM1 - "the current local configuration OK for me"
|
- CONFIRM1 - "the current local configuration is OK for me"
|
||||||
- CONFIRM2 - "acknowledging your CONFIRM1; my own configuration is unchanged
|
- CONFIRM2 - "acknowledging your CONFIRM1; my own configuration is unchanged
|
||||||
since I sent CONFIRM1 (after the last CANCEL)"
|
since I sent CONFIRM1 (after the last CANCEL)"
|
||||||
- CANCEL - "forget about my earlier CONFIRM1"
|
- CANCEL - "forget about my earlier CONFIRM1"
|
||||||
@@ -148,7 +253,7 @@ From state 1: (localOk)
|
|||||||
local cancel -> Send CANCEL, goto 4
|
local cancel -> Send CANCEL, goto 4
|
||||||
received CONFIRM1 -> Send CONFIRM2, goto 3
|
received CONFIRM1 -> Send CONFIRM2, goto 3
|
||||||
received CONFIRM2 -> Send CONFIRM2, goto 8
|
received CONFIRM2 -> Send CONFIRM2, goto 8
|
||||||
received MESSAGE(changes) -> Process(changes), Send CANCEL, goto 4
|
received MESSAGE(changes) -> Send CANCEL, Process(changes), goto 4
|
||||||
|
|
||||||
From state 2: (remoteOk)
|
From state 2: (remoteOk)
|
||||||
local confirmation -> Send CONFIRM2, goto 3
|
local confirmation -> Send CONFIRM2, goto 3
|
||||||
@@ -204,7 +309,7 @@ aren't expected.
|
|||||||
|
|
||||||
"Reset" negotiation.
|
"Reset" negotiation.
|
||||||
|
|
||||||
See src/sc2code/netplay/proto.c
|
See src/sc2code/netplay/proto/reset.c
|
||||||
|
|
||||||
|
|
||||||
============================================================================
|
============================================================================
|
||||||
|
|||||||
+141
-26
@@ -1,63 +1,178 @@
|
|||||||
NetState_unconnected is the initial state. When a connection attempt is made,
|
== Any connected state ==
|
||||||
the state is set to NetState_connecting.
|
Some packets may be sent and received in any state except
|
||||||
The state field of a NetConnection is NULL.
|
NetState_unconnected.
|
||||||
|
These are: PING, ACK, ABORT, RESET
|
||||||
|
These are not listed below at each individual state.
|
||||||
|
|
||||||
NetState_connecting indicates a connection is in progress.
|
Whenever a connection is aborted, the state is returned to
|
||||||
When the connection is established, an INIT packet is sent, the state
|
NetState_unconnected. This state transition is not listed below at each
|
||||||
is changed to NetState_init and InputFunc is set to DoNetworkInit.
|
individual state.
|
||||||
The state field of a NetConnection is a ConnectStateData structure.
|
|
||||||
|
|
||||||
|
|
||||||
|
== NetState_unconnected ==
|
||||||
|
NetState_unconnected is the initial state.
|
||||||
|
|
||||||
|
NetConnection.state: NULL
|
||||||
|
|
||||||
|
Packets ok to send: none
|
||||||
|
Packets ok to receive: none
|
||||||
|
|
||||||
|
Next state:
|
||||||
|
NetState_connecting -- connection attempt in progress
|
||||||
|
|
||||||
|
|
||||||
|
== NetState_connecting ==
|
||||||
|
NetState_connecting indicates that a connection is in progress.
|
||||||
|
|
||||||
|
When the connection is established, the state is changed to NetState_init
|
||||||
|
and InputFunc is set to DoNetworkInit.
|
||||||
|
|
||||||
|
NetConnection.state: instance of ConnectStateData
|
||||||
|
|
||||||
|
Packets ok to send: none
|
||||||
|
Packets ok to receive: none
|
||||||
|
|
||||||
|
Next state:
|
||||||
|
NetState_init -- connection established
|
||||||
|
|
||||||
|
|
||||||
|
== NetState_init ==
|
||||||
NetState_init is for initialising the connection before actual game
|
NetState_init is for initialising the connection before actual game
|
||||||
information is sent. When an INIT packet is received, the state is set
|
information is sent.
|
||||||
to NetState_inSetup and InputFunc is set to DoMelee.
|
|
||||||
The state field of a NetConnection is a BattleStateData structure.
|
|
||||||
|
|
||||||
|
As this state is entered, an INIT packet is sent. When an INIT packet
|
||||||
|
has also been received, the state is set to NetState_inSetup and
|
||||||
|
InputFunc is set to DoMelee.
|
||||||
|
|
||||||
|
NetConnection.state: instance of BattleStateData
|
||||||
|
|
||||||
|
Packets ok to send: INIT
|
||||||
|
Packets ok to receive: INIT
|
||||||
|
|
||||||
|
Next state:
|
||||||
|
NetState_inSetup -- received an INIT packet
|
||||||
|
|
||||||
|
|
||||||
|
== NetState_inSetup ==
|
||||||
NetState_inSetup is the state in which the fleet configuration is negotiated.
|
NetState_inSetup is the state in which the fleet configuration is negotiated.
|
||||||
Only the side who has myTurn set may send this ship information, by means
|
|
||||||
of FLEET and TEAMNAME packets.
|
This does not necessarilly mean that the fleet setup screen is visible;
|
||||||
The Turn negotiation is used to change myTurn.
|
this state is also held after a battle when the battle outcome is still
|
||||||
|
displayed.
|
||||||
|
|
||||||
|
Each side may send fleet configuration changes to the other side, by means of
|
||||||
|
FLEET and TEAMNAME packets. Agreement on configuration settings is provided
|
||||||
|
through the Update negotiation.
|
||||||
The Confirm negotiation is used to end this state and go to
|
The Confirm negotiation is used to end this state and go to
|
||||||
NetState_preBattle. At this time InputFunc is set to DoPreMelee.
|
NetState_preBattle. At this time InputFunc is set to DoPreMelee.
|
||||||
The state field of a NetConnection is a BattleStateData structure.
|
|
||||||
|
|
||||||
|
NetConnection.state: instance of BattleStateData
|
||||||
|
|
||||||
|
Packets ok to send: FLEET, TEAMNAME, HANDSHAKE0, HANDSHAKE1,
|
||||||
|
HANDSHAKECANCEL, HANDSHAKECANCELACK
|
||||||
|
Packets ok to receive: FLEET, TEAMNAME, HANDSHAKE0, HANDSHAKE1,
|
||||||
|
HANDSHAKECANCEL, HANDSHAKECANCELACK
|
||||||
|
|
||||||
|
Next state:
|
||||||
|
NetState_preBattle -- configuration has been confirmed
|
||||||
|
|
||||||
|
|
||||||
|
== NetState_preBattle ==
|
||||||
NetState_preBattle is used for non-interactive battle negotiations.
|
NetState_preBattle is used for non-interactive battle negotiations.
|
||||||
|
|
||||||
One side sends the random seed; the other receives it.
|
One side sends the random seed; the other receives it.
|
||||||
|
Both sides send their input delay value.
|
||||||
The Ready negotiation is used to end this state and go to
|
The Ready negotiation is used to end this state and go to
|
||||||
NetState_interBattle.
|
NetState_interBattle.
|
||||||
The state field of a NetConnection is a BattleStateData structure.
|
|
||||||
|
|
||||||
NetState_interBattle is used to allow either side to do some local
|
NetConnection.state: instance of BattleStateData
|
||||||
|
|
||||||
|
Packets ok to send: SEEDRANDOM, INPUTDELAY, READY
|
||||||
|
Packets ok to receive: SEEDRANDOM, INPUTDELAY, READY
|
||||||
|
|
||||||
|
Next state:
|
||||||
|
NetState_interBattle -- ready to continue
|
||||||
|
|
||||||
|
|
||||||
|
== NetState_interBattle ==
|
||||||
|
NetState_interBattle is used to allow each side to do some local
|
||||||
initialisations before moving on.
|
initialisations before moving on.
|
||||||
The Ready negotiation is used to end this state and go to
|
The Ready negotiation is used to end this state and go to
|
||||||
NetState_selectShip, or if there are no more ships to be selected,
|
NetState_selectShip, or if all sides have selected a ship, to
|
||||||
to NetState_inBattle.
|
NetState_inBattle, or if there are no more ships in a fleet,
|
||||||
The state field of a NetConnection is a BattleStateData structure.
|
to NetState_inSetup.
|
||||||
|
|
||||||
NetState_selectShip is where a side may select his ship. The other
|
If there are no more ships, the the Ready negotiation is used to
|
||||||
|
enter NetState_inSetup.
|
||||||
|
|
||||||
|
NetConnection.state: instance of BattleStateData
|
||||||
|
|
||||||
|
Packets ok to send: READY
|
||||||
|
Packets ok to receive: READY
|
||||||
|
|
||||||
|
Next state:
|
||||||
|
NetState_selectShip -- ready to select the next ship
|
||||||
|
NetState_inBattle -- ready to start the battle
|
||||||
|
NetState_inSetup -- no more ships; game over
|
||||||
|
|
||||||
|
|
||||||
|
== NetState_selectShip ==
|
||||||
|
NetState_selectShip is where a side may select their ship. The other
|
||||||
side is waiting for notice of this selection.
|
side is waiting for notice of this selection.
|
||||||
As soon as the selection has been sent or received, the state is changed
|
As soon as the selection has been sent or received, the state is changed
|
||||||
back to NetState_interBattle.
|
back to NetState_interBattle.
|
||||||
The state field of a NetConnection is a BattleStateData structure.
|
|
||||||
|
|
||||||
|
NetConnection.state: instance of BattleStateData
|
||||||
|
|
||||||
|
Packets ok to send: SELECTSHIP
|
||||||
|
Packets ok to receive: SELECTSHIP
|
||||||
|
|
||||||
|
Next state:
|
||||||
|
NetState_interBattle -- a selection has been made
|
||||||
|
|
||||||
|
|
||||||
|
== NetState_inBattle ==
|
||||||
NetState_inBattle is where the actual melee takes place.
|
NetState_inBattle is where the actual melee takes place.
|
||||||
Both sides send their input until the game is over, at which point
|
Both sides send their input until the game is over, at which point
|
||||||
the Ready negotiation is used to end this state and go to
|
the Ready negotiation is used to end this state and go to
|
||||||
the NetState_endingBattle state. Until the Ready negotiation has been
|
the NetState_endingBattle state. Until the Ready negotiation has been
|
||||||
completed, the simulation is continuing.
|
completed, the simulation is continuing.
|
||||||
The state field of a NetConnection is a BattleStateData structure.
|
|
||||||
|
|
||||||
|
NetConnection.state: instance of BattleStateData
|
||||||
|
|
||||||
|
Packets ok to send: BATTLEINPUT, READY
|
||||||
|
Packets ok to receive: BATTLEINPUT, READY
|
||||||
|
|
||||||
|
Next state:
|
||||||
|
NetState_endingBattle -- ready to end the battle
|
||||||
|
|
||||||
|
|
||||||
|
== NetState_endingBattle ==
|
||||||
NetState_endingBattle is where the local side waits for the remote
|
NetState_endingBattle is where the local side waits for the remote
|
||||||
battle frame count, after it has sent its own. When it arrives,
|
battle frame count, after it has sent its own. When it arrives,
|
||||||
the state changes to NetState_endingBattle2.
|
the state changes to NetState_endingBattle2.
|
||||||
The state field of a NetConnection is a BattleStateData structure.
|
|
||||||
|
|
||||||
|
NetConnection.state: instance of BattleStateData
|
||||||
|
|
||||||
|
Packets ok to send: BATTLEINPUT, FRAMECOUNT
|
||||||
|
Packets ok to receive: BATTLEINPUT, FRAMECOUNT
|
||||||
|
|
||||||
|
Next state:
|
||||||
|
NetState_endingBattle2 -- we know when to end the battle
|
||||||
|
|
||||||
|
|
||||||
|
== NetState_endingBattle2 ==
|
||||||
NetState_endingBattle2 is where the side with the lowest battle frame count
|
NetState_endingBattle2 is where the side with the lowest battle frame count
|
||||||
catches up with the other other side, while the other side waits.
|
catches up with the other other side, while the other side waits.
|
||||||
The Ready negotiation is used to signal that each side is ready,
|
The Ready negotiation is used to signal that each side is ready,
|
||||||
and the state changes back to NetState_interBattle.
|
and the state changes to NetState_interBattle.
|
||||||
The state field of a NetConnection is a BattleStateData structure.
|
|
||||||
|
|
||||||
|
NetConnection.state: instance of BattleStateData
|
||||||
|
|
||||||
When a connection is aborted, the state is returned to NetState_unconnected.
|
Packets ok to send: BATTLEINPUT, READY
|
||||||
|
Packets ok to receive: BATTLEINPUT, READY
|
||||||
|
|
||||||
|
Next state:
|
||||||
|
NetState_interBattle -- get ready for the next ship
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+14
-5
@@ -302,17 +302,29 @@ SetContext (OldContext);
|
|||||||
return (hBattleShip);
|
return (hBattleShip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QUEUE *
|
||||||
|
GetShipQueueForSide (COUNT sideNr)
|
||||||
|
{
|
||||||
|
if (sideNr == 0)
|
||||||
|
return &GLOBAL (built_ship_q);
|
||||||
|
else
|
||||||
|
return &GLOBAL (npc_built_ship_q);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next ship to use.
|
||||||
HSTARSHIP
|
HSTARSHIP
|
||||||
GetEncounterStarShip (STARSHIP *LastStarShipPtr, COUNT which_player)
|
GetEncounterStarShip (STARSHIP *LastStarShipPtr, COUNT which_player)
|
||||||
{
|
{
|
||||||
HSTARSHIP hBattleShip;
|
HSTARSHIP hBattleShip;
|
||||||
|
|
||||||
if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE)
|
if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE)
|
||||||
|
{
|
||||||
// Get the next ship from the battle group.
|
// Get the next ship from the battle group.
|
||||||
hBattleShip = GetHeadLink (&race_q[which_player]);
|
hBattleShip = GetHeadLink (&race_q[which_player]);
|
||||||
|
}
|
||||||
else if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE)
|
else if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE)
|
||||||
{
|
{
|
||||||
// Let the player chose his own ship. (May be a computer player).
|
// Let the player chose their own ship. (May be a computer player).
|
||||||
|
|
||||||
if (!(GLOBAL (CurrentActivity) & IN_BATTLE))
|
if (!(GLOBAL (CurrentActivity) & IN_BATTLE))
|
||||||
{
|
{
|
||||||
@@ -367,10 +379,7 @@ GetEncounterStarShip (STARSHIP *LastStarShipPtr, COUNT which_player)
|
|||||||
QUEUE *pQueue;
|
QUEUE *pQueue;
|
||||||
HSHIPFRAG hNextShip;
|
HSHIPFRAG hNextShip;
|
||||||
|
|
||||||
if (which_player == 0)
|
pQueue = GetShipQueueForSide (which_player);
|
||||||
pQueue = &GLOBAL (built_ship_q);
|
|
||||||
else
|
|
||||||
pQueue = &GLOBAL (npc_built_ship_q);
|
|
||||||
|
|
||||||
hBattleShip = GetHeadLink (&race_q[which_player]);
|
hBattleShip = GetHeadLink (&race_q[which_player]);
|
||||||
for (hStarShip = GetHeadLink (pQueue);
|
for (hStarShip = GetHeadLink (pQueue);
|
||||||
|
|||||||
@@ -493,6 +493,7 @@ spawn_ship (STARSHIP *StarShipPtr)
|
|||||||
return (hShip != 0);
|
return (hShip != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Select a new ship and spawn it.
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
GetNextStarShip (STARSHIP *LastStarShipPtr, COUNT which_side)
|
GetNextStarShip (STARSHIP *LastStarShipPtr, COUNT which_side)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ DrawFileString (const MeleeTeam *team, const POINT *origin,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns true if there are any entries in the view, in which case
|
// returns true if there are any entries in the view, in which case
|
||||||
// pMS->load.bot gets set to the index of the bottom entry in the view.
|
// pMS->load.bot gets set to the index just past the bottom entry in the view.
|
||||||
// returns false if not, in which case, the entire view remains unchanged.
|
// returns false if not, in which case, the entire view remains unchanged.
|
||||||
static bool
|
static bool
|
||||||
FillFileView (MELEE_STATE *pMS)
|
FillFileView (MELEE_STATE *pMS)
|
||||||
@@ -350,7 +350,7 @@ DoLoadTeam (MELEE_STATE *pMS)
|
|||||||
if (PulsedInputState.menu[KEY_MENU_SELECT])
|
if (PulsedInputState.menu[KEY_MENU_SELECT])
|
||||||
{
|
{
|
||||||
// Copy the selected fleet to the player.
|
// Copy the selected fleet to the player.
|
||||||
Melee_Change_team (pMS, pMS->side,
|
Melee_LocalChange_team (pMS, pMS->side,
|
||||||
pMS->load.view[pMS->load.cur - pMS->load.top]);
|
pMS->load.view[pMS->load.cur - pMS->load.top]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,11 +417,16 @@ DoLoadTeam (MELEE_STATE *pMS)
|
|||||||
|
|
||||||
if (newIndex != pMS->load.cur)
|
if (newIndex != pMS->load.cur)
|
||||||
{
|
{
|
||||||
|
// The cursor has been moved.
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
if (newTop == pMS->load.top)
|
if (newTop == pMS->load.top)
|
||||||
|
{
|
||||||
|
// The view itself hasn't changed.
|
||||||
SelectFileString (pMS, false);
|
SelectFileString (pMS, false);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// The view is changed.
|
||||||
pMS->load.top = newTop;
|
pMS->load.top = newTop;
|
||||||
DrawFileStrings (pMS);
|
DrawFileStrings (pMS);
|
||||||
}
|
}
|
||||||
|
|||||||
+328
-99
@@ -197,6 +197,7 @@ static BOOLEAN DoConfirmSettings (MELEE_STATE *pMS);
|
|||||||
#define DTSHS_BLOCKCUR 8
|
#define DTSHS_BLOCKCUR 8
|
||||||
static BOOLEAN DrawTeamString (MELEE_STATE *pMS, COUNT side,
|
static BOOLEAN DrawTeamString (MELEE_STATE *pMS, COUNT side,
|
||||||
COUNT HiLiteState, const char *str);
|
COUNT HiLiteState, const char *str);
|
||||||
|
static void DrawFleetValue (MELEE_STATE *pMS, COUNT side, COUNT HiLiteState);
|
||||||
|
|
||||||
static void Melee_UpdateView_fleetValue (MELEE_STATE *pMS, COUNT side);
|
static void Melee_UpdateView_fleetValue (MELEE_STATE *pMS, COUNT side);
|
||||||
static void Melee_UpdateView_ship (MELEE_STATE *pMS, COUNT side,
|
static void Melee_UpdateView_ship (MELEE_STATE *pMS, COUNT side,
|
||||||
@@ -363,6 +364,7 @@ DrawTeams (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DrawTeamString (pMeleeState, side, DTSHS_NORMAL, NULL);
|
DrawTeamString (pMeleeState, side, DTSHS_NORMAL, NULL);
|
||||||
|
DrawFleetValue (pMeleeState, side, DTSHS_NORMAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,6 +424,59 @@ RedrawMeleeFrame (void)
|
|||||||
RepairMeleeFrame (&r);
|
RepairMeleeFrame (&r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
GetTeamStringRect (COUNT side, RECT *r)
|
||||||
|
{
|
||||||
|
r->corner.x = MELEE_X_OFFS - 1;
|
||||||
|
r->corner.y = (side + 1) * (MELEE_Y_OFFS
|
||||||
|
+ ((MELEE_BOX_HEIGHT + MELEE_BOX_SPACE) * NUM_MELEE_ROWS + 2));
|
||||||
|
r->extent.width = NUM_MELEE_COLUMNS * (MELEE_BOX_WIDTH + MELEE_BOX_SPACE)
|
||||||
|
- 29;
|
||||||
|
r->extent.height = 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
GetFleetValueRect (COUNT side, RECT *r)
|
||||||
|
{
|
||||||
|
r->corner.x = MELEE_X_OFFS
|
||||||
|
+ NUM_MELEE_COLUMNS * (MELEE_BOX_WIDTH + MELEE_BOX_SPACE) - 30;
|
||||||
|
r->corner.y = (side + 1) * (MELEE_Y_OFFS
|
||||||
|
+ ((MELEE_BOX_HEIGHT + MELEE_BOX_SPACE) * NUM_MELEE_ROWS + 2));
|
||||||
|
r->extent.width = 29;
|
||||||
|
r->extent.height = 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
DrawFleetValue (MELEE_STATE *pMS, COUNT side, COUNT HiLiteState)
|
||||||
|
{
|
||||||
|
RECT r;
|
||||||
|
TEXT rtText;
|
||||||
|
UNICODE buf[30];
|
||||||
|
COUNT fleetValue;
|
||||||
|
|
||||||
|
GetFleetValueRect (side ,&r);
|
||||||
|
|
||||||
|
if (HiLiteState == DTSHS_REPAIR)
|
||||||
|
{
|
||||||
|
RepairMeleeFrame (&r);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetContextFont (MicroFont);
|
||||||
|
|
||||||
|
fleetValue = MeleeSetup_getFleetValue (pMS->meleeSetup, side);
|
||||||
|
sprintf (buf, "%u", fleetValue);
|
||||||
|
rtText.pStr = buf;
|
||||||
|
rtText.align = ALIGN_RIGHT;
|
||||||
|
rtText.CharCount = (COUNT)~0;
|
||||||
|
rtText.baseline.y = r.corner.y + r.extent.height - 3;
|
||||||
|
rtText.baseline.x = r.corner.x + r.extent.width;
|
||||||
|
|
||||||
|
SetContextForeGroundColor (!(HiLiteState & DTSHS_SELECTED)
|
||||||
|
? TEAM_NAME_TEXT_COLOR : TEAM_NAME_EDIT_TEXT_COLOR);
|
||||||
|
font_DrawText (&rtText);
|
||||||
|
}
|
||||||
|
|
||||||
// If teamName == NULL, the team name is taken from pMS->meleeSetup
|
// If teamName == NULL, the team name is taken from pMS->meleeSetup
|
||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
DrawTeamString (MELEE_STATE *pMS, COUNT side, COUNT HiLiteState,
|
DrawTeamString (MELEE_STATE *pMS, COUNT side, COUNT HiLiteState,
|
||||||
@@ -430,11 +485,7 @@ DrawTeamString (MELEE_STATE *pMS, COUNT side, COUNT HiLiteState,
|
|||||||
RECT r;
|
RECT r;
|
||||||
TEXT lfText;
|
TEXT lfText;
|
||||||
|
|
||||||
r.corner.x = MELEE_X_OFFS - 1;
|
GetTeamStringRect (side, &r);
|
||||||
r.corner.y = (side + 1) * (MELEE_Y_OFFS
|
|
||||||
+ ((MELEE_BOX_HEIGHT + MELEE_BOX_SPACE) * NUM_MELEE_ROWS + 2));
|
|
||||||
r.extent.width = NUM_MELEE_COLUMNS * (MELEE_BOX_WIDTH + MELEE_BOX_SPACE);
|
|
||||||
r.extent.height = 13;
|
|
||||||
if (HiLiteState == DTSHS_REPAIR)
|
if (HiLiteState == DTSHS_REPAIR)
|
||||||
{
|
{
|
||||||
RepairMeleeFrame (&r);
|
RepairMeleeFrame (&r);
|
||||||
@@ -446,7 +497,6 @@ DrawTeamString (MELEE_STATE *pMS, COUNT side, COUNT HiLiteState,
|
|||||||
lfText.pStr = (teamName != NULL) ? teamName :
|
lfText.pStr = (teamName != NULL) ? teamName :
|
||||||
MeleeSetup_getTeamName (pMS->meleeSetup, side);
|
MeleeSetup_getTeamName (pMS->meleeSetup, side);
|
||||||
lfText.baseline.y = r.corner.y + r.extent.height - 3;
|
lfText.baseline.y = r.corner.y + r.extent.height - 3;
|
||||||
|
|
||||||
lfText.baseline.x = r.corner.x + 1;
|
lfText.baseline.x = r.corner.x + 1;
|
||||||
lfText.align = ALIGN_LEFT;
|
lfText.align = ALIGN_LEFT;
|
||||||
lfText.CharCount = strlen (lfText.pStr);
|
lfText.CharCount = strlen (lfText.pStr);
|
||||||
@@ -454,20 +504,9 @@ DrawTeamString (MELEE_STATE *pMS, COUNT side, COUNT HiLiteState,
|
|||||||
BatchGraphics ();
|
BatchGraphics ();
|
||||||
if (!(HiLiteState & DTSHS_EDIT))
|
if (!(HiLiteState & DTSHS_EDIT))
|
||||||
{ // normal or selected state
|
{ // normal or selected state
|
||||||
TEXT rtText;
|
|
||||||
UNICODE buf[30];
|
|
||||||
|
|
||||||
sprintf (buf, "%u", MeleeSetup_getFleetValue (pMS->meleeSetup, side));
|
|
||||||
rtText.pStr = buf;
|
|
||||||
rtText.align = ALIGN_RIGHT;
|
|
||||||
rtText.CharCount = (COUNT)~0;
|
|
||||||
rtText.baseline.y = lfText.baseline.y;
|
|
||||||
rtText.baseline.x = lfText.baseline.x + r.extent.width - 1;
|
|
||||||
|
|
||||||
SetContextForeGroundColor (!(HiLiteState & DTSHS_SELECTED)
|
SetContextForeGroundColor (!(HiLiteState & DTSHS_SELECTED)
|
||||||
? TEAM_NAME_TEXT_COLOR : TEAM_NAME_EDIT_TEXT_COLOR);
|
? TEAM_NAME_TEXT_COLOR : TEAM_NAME_EDIT_TEXT_COLOR);
|
||||||
font_DrawText (&lfText);
|
font_DrawText (&lfText);
|
||||||
font_DrawText (&rtText);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // editing state
|
{ // editing state
|
||||||
@@ -476,9 +515,6 @@ DrawTeamString (MELEE_STATE *pMS, COUNT side, COUNT HiLiteState,
|
|||||||
BYTE char_deltas[MAX_TEAM_CHARS];
|
BYTE char_deltas[MAX_TEAM_CHARS];
|
||||||
BYTE *pchar_deltas;
|
BYTE *pchar_deltas;
|
||||||
|
|
||||||
// not drawing team bucks
|
|
||||||
r.extent.width -= 29;
|
|
||||||
|
|
||||||
TextRect (&lfText, &text_r, char_deltas);
|
TextRect (&lfText, &text_r, char_deltas);
|
||||||
if ((text_r.extent.width + 2) >= r.extent.width)
|
if ((text_r.extent.width + 2) >= r.extent.width)
|
||||||
{ // the text does not fit the input box size and so
|
{ // the text does not fit the input box size and so
|
||||||
@@ -712,6 +748,8 @@ Deselect (BYTE opt)
|
|||||||
// Not currently editing the team name.
|
// Not currently editing the team name.
|
||||||
DrawTeamString (pMeleeState, pMeleeState->side,
|
DrawTeamString (pMeleeState, pMeleeState->side,
|
||||||
DTSHS_NORMAL, NULL);
|
DTSHS_NORMAL, NULL);
|
||||||
|
DrawFleetValue (pMeleeState, pMeleeState->side,
|
||||||
|
DTSHS_NORMAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -773,6 +811,8 @@ Select (BYTE opt)
|
|||||||
// Not currently editing the team name.
|
// Not currently editing the team name.
|
||||||
DrawTeamString (pMeleeState, pMeleeState->side,
|
DrawTeamString (pMeleeState, pMeleeState->side,
|
||||||
DTSHS_SELECTED, NULL);
|
DTSHS_SELECTED, NULL);
|
||||||
|
DrawFleetValue (pMeleeState, pMeleeState->side,
|
||||||
|
DTSHS_SELECTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -942,7 +982,7 @@ static void
|
|||||||
DeleteCurrentShip (MELEE_STATE *pMS)
|
DeleteCurrentShip (MELEE_STATE *pMS)
|
||||||
{
|
{
|
||||||
FleetShipIndex slotI = GetShipIndex (pMS->row, pMS->col);
|
FleetShipIndex slotI = GetShipIndex (pMS->row, pMS->col);
|
||||||
Melee_Change_ship (pMS, pMS->side, slotI, MELEE_NONE);
|
Melee_LocalChange_ship (pMS, pMS->side, slotI, MELEE_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@@ -992,6 +1032,23 @@ OnTeamNameChange (TEXTENTRY_STATE *pTES)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOLEAN
|
||||||
|
TeamNameFrameCallback (TEXTENTRY_STATE *pTES)
|
||||||
|
{
|
||||||
|
#ifdef NETPLAY
|
||||||
|
// Process incoming packets, so that remote changes are displayed
|
||||||
|
// while we are editing the team name.
|
||||||
|
// The team name itself isn't modified visually due to remote changes
|
||||||
|
// while it is being edited.
|
||||||
|
netInput ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
(void) pTES;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
// Keep editing
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
BuildPickShipPopup (MELEE_STATE *pMS)
|
BuildPickShipPopup (MELEE_STATE *pMS)
|
||||||
{
|
{
|
||||||
@@ -1005,7 +1062,7 @@ BuildPickShipPopup (MELEE_STATE *pMS)
|
|||||||
// A ship has been selected.
|
// A ship has been selected.
|
||||||
// Add the currently selected ship to the fleet.
|
// Add the currently selected ship to the fleet.
|
||||||
FleetShipIndex index = GetShipIndex (pMS->row, pMS->col);
|
FleetShipIndex index = GetShipIndex (pMS->row, pMS->col);
|
||||||
Melee_Change_ship (pMS, pMS->side, index, pMS->currentShip);
|
Melee_LocalChange_ship (pMS, pMS->side, index, pMS->currentShip);
|
||||||
AdvanceCursor (pMS);
|
AdvanceCursor (pMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1122,12 +1179,13 @@ DoEdit (MELEE_STATE *pMS)
|
|||||||
tes.MaxSize = MAX_TEAM_CHARS + 1;
|
tes.MaxSize = MAX_TEAM_CHARS + 1;
|
||||||
tes.CbParam = pMS;
|
tes.CbParam = pMS;
|
||||||
tes.ChangeCallback = OnTeamNameChange;
|
tes.ChangeCallback = OnTeamNameChange;
|
||||||
tes.FrameCallback = 0;
|
tes.FrameCallback = TeamNameFrameCallback;
|
||||||
DoTextEntry (&tes);
|
DoTextEntry (&tes);
|
||||||
|
|
||||||
// done entering
|
// done entering
|
||||||
pMS->CurIndex = MELEE_STATE_INDEX_DONE;
|
pMS->CurIndex = MELEE_STATE_INDEX_DONE;
|
||||||
if (!Melee_Change_teamName (pMS, pMS->side, buf)) {
|
if (!tes.Success ||
|
||||||
|
!Melee_LocalChange_teamName (pMS, pMS->side, buf)) {
|
||||||
// The team name was not changed, so it was not redrawn.
|
// The team name was not changed, so it was not redrawn.
|
||||||
// However, because we now leave edit mode, we still
|
// However, because we now leave edit mode, we still
|
||||||
// need to redraw.
|
// need to redraw.
|
||||||
@@ -1253,6 +1311,7 @@ DoConfirmSettings (MELEE_STATE *pMS)
|
|||||||
|
|
||||||
if (PulsedInputState.menu[KEY_MENU_CANCEL])
|
if (PulsedInputState.menu[KEY_MENU_CANCEL])
|
||||||
{
|
{
|
||||||
|
// The connection is explicitely cancelled, locally.
|
||||||
pMS->InputFunc = DoMelee;
|
pMS->InputFunc = DoMelee;
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
cancelConfirmations ();
|
cancelConfirmations ();
|
||||||
@@ -1266,6 +1325,7 @@ DoConfirmSettings (MELEE_STATE *pMS)
|
|||||||
PulsedInputState.menu[KEY_MENU_UP] ||
|
PulsedInputState.menu[KEY_MENU_UP] ||
|
||||||
PulsedInputState.menu[KEY_MENU_DOWN])
|
PulsedInputState.menu[KEY_MENU_DOWN])
|
||||||
{
|
{
|
||||||
|
// The player moves the cursor; cancel the confirmation.
|
||||||
pMS->InputFunc = DoMelee;
|
pMS->InputFunc = DoMelee;
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
cancelConfirmations ();
|
cancelConfirmations ();
|
||||||
@@ -1278,7 +1338,9 @@ DoConfirmSettings (MELEE_STATE *pMS)
|
|||||||
#ifndef NETPLAY
|
#ifndef NETPLAY
|
||||||
pMS->InputFunc = DoMelee;
|
pMS->InputFunc = DoMelee;
|
||||||
SeedRandomNumbers ();
|
SeedRandomNumbers ();
|
||||||
|
pMS->meleeStarted = TRUE;
|
||||||
StartMelee (pMS);
|
StartMelee (pMS);
|
||||||
|
pMS->meleeStarted = FALSE;
|
||||||
if (GLOBAL (CurrentActivity) & CHECK_ABORT)
|
if (GLOBAL (CurrentActivity) & CHECK_ABORT)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -2041,9 +2103,11 @@ Melee (void)
|
|||||||
if (LoadMeleeConfig (&MenuState) == -1)
|
if (LoadMeleeConfig (&MenuState) == -1)
|
||||||
{
|
{
|
||||||
PlayerControl[0] = HUMAN_CONTROL | STANDARD_RATING;
|
PlayerControl[0] = HUMAN_CONTROL | STANDARD_RATING;
|
||||||
Melee_Change_team (&MenuState, 0, MenuState.load.preBuiltList[0]);
|
Melee_LocalChange_team (&MenuState, 0,
|
||||||
|
MenuState.load.preBuiltList[0]);
|
||||||
PlayerControl[1] = COMPUTER_CONTROL | STANDARD_RATING;
|
PlayerControl[1] = COMPUTER_CONTROL | STANDARD_RATING;
|
||||||
Melee_Change_team (&MenuState, 1, MenuState.load.preBuiltList[1]);
|
Melee_LocalChange_team (&MenuState, 1,
|
||||||
|
MenuState.load.preBuiltList[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuState.side = 0;
|
MenuState.side = 0;
|
||||||
@@ -2186,7 +2250,6 @@ resetFeedback (NetConnection *conn, NetplayResetReason reason,
|
|||||||
{
|
{
|
||||||
const char *msg;
|
const char *msg;
|
||||||
|
|
||||||
GLOBAL (CurrentActivity) |= CHECK_ABORT;
|
|
||||||
flushPacketQueues ();
|
flushPacketQueues ();
|
||||||
// If the local side queued a reset packet as a result of a
|
// If the local side queued a reset packet as a result of a
|
||||||
// remote reset, that packet will not have been sent yet.
|
// remote reset, that packet will not have been sent yet.
|
||||||
@@ -2202,6 +2265,10 @@ resetFeedback (NetConnection *conn, NetplayResetReason reason,
|
|||||||
msg = resetReasonString (reason);
|
msg = resetReasonString (reason);
|
||||||
if (msg != NULL)
|
if (msg != NULL)
|
||||||
connectionFeedback (conn, msg, false);
|
connectionFeedback (conn, msg, false);
|
||||||
|
|
||||||
|
// End supermelee. This must not be done before connectionFeedback(),
|
||||||
|
// otherwise the message will immediately disappear.
|
||||||
|
GLOBAL (CurrentActivity) |= CHECK_ABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -2241,15 +2308,24 @@ closeFeedback (NetConnection *conn)
|
|||||||
static void
|
static void
|
||||||
Melee_UpdateView_fleetValue (MELEE_STATE *pMS, COUNT side)
|
Melee_UpdateView_fleetValue (MELEE_STATE *pMS, COUNT side)
|
||||||
{
|
{
|
||||||
|
if (pMS->meleeStarted)
|
||||||
|
return;
|
||||||
|
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
DrawTeamString (pMS, side, DTSHS_REPAIR, NULL);
|
DrawFleetValue (pMS, side, DTSHS_REPAIR);
|
||||||
|
// BUG: The fleet value is always drawn as deselected.
|
||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
Melee_UpdateView_ship (MELEE_STATE *pMS, COUNT side, FleetShipIndex index)
|
Melee_UpdateView_ship (MELEE_STATE *pMS, COUNT side, FleetShipIndex index)
|
||||||
{
|
{
|
||||||
MeleeShip ship = MeleeSetup_getShip (pMS->meleeSetup, side, index);
|
MeleeShip ship;
|
||||||
|
|
||||||
|
if (pMS->meleeStarted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ship = MeleeSetup_getShip (pMS->meleeSetup, side, index);
|
||||||
|
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
if (ship == MELEE_NONE)
|
if (ship == MELEE_NONE)
|
||||||
@@ -2266,6 +2342,9 @@ Melee_UpdateView_ship (MELEE_STATE *pMS, COUNT side, FleetShipIndex index)
|
|||||||
static void
|
static void
|
||||||
Melee_UpdateView_teamName (MELEE_STATE *pMS, COUNT side)
|
Melee_UpdateView_teamName (MELEE_STATE *pMS, COUNT side)
|
||||||
{
|
{
|
||||||
|
if (pMS->meleeStarted)
|
||||||
|
return;
|
||||||
|
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
DrawTeamString (pMS, side, DTSHS_REPAIR, NULL);
|
DrawTeamString (pMS, side, DTSHS_REPAIR, NULL);
|
||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
@@ -2273,10 +2352,11 @@ Melee_UpdateView_teamName (MELEE_STATE *pMS, COUNT side)
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Melee_Change_xxx() functions are called when some value in the supermelee
|
// Melee_Change_xxx() functions are helper functions, called when some value
|
||||||
// fleet setup screen has changed, eithed locally, or remotely.
|
// in the supermelee fleet setup screen has changed, eithed because of a
|
||||||
|
// local change, or a remote change.
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
Melee_Change_ship (MELEE_STATE *pMS, COUNT side, FleetShipIndex index,
|
Melee_Change_ship (MELEE_STATE *pMS, COUNT side, FleetShipIndex index,
|
||||||
MeleeShip ship)
|
MeleeShip ship)
|
||||||
{
|
{
|
||||||
@@ -2300,16 +2380,11 @@ Melee_Change_ship (MELEE_STATE *pMS, COUNT side, FleetShipIndex index,
|
|||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NETPLAY
|
|
||||||
// Notify network connections of the change.
|
|
||||||
Netplay_NotifyAll_setShip (pMS, side, index);
|
|
||||||
#endif /* NETPLAY */
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pre: 'name' is '\0'-terminated
|
// Pre: 'name' is '\0'-terminated
|
||||||
bool
|
static bool
|
||||||
Melee_Change_teamName (MELEE_STATE *pMS, COUNT side, const char *name)
|
Melee_Change_teamName (MELEE_STATE *pMS, COUNT side, const char *name)
|
||||||
{
|
{
|
||||||
MeleeSetup *setup = pMS->meleeSetup;
|
MeleeSetup *setup = pMS->meleeSetup;
|
||||||
@@ -2329,37 +2404,93 @@ Melee_Change_teamName (MELEE_STATE *pMS, COUNT side, const char *name)
|
|||||||
Melee_UpdateView_teamName (pMS, side);
|
Melee_UpdateView_teamName (pMS, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Melee_LocalChange_xxx() functions are called when some value in the
|
||||||
|
// supermelee fleet setup screen has changed because of a local action.
|
||||||
|
// The behavior of these functions (and the comments therein) follow the
|
||||||
|
// description in doc/devel/netplay/protocol.
|
||||||
|
|
||||||
|
bool
|
||||||
|
Melee_LocalChange_ship (MELEE_STATE *pMS, COUNT side, FleetShipIndex index,
|
||||||
|
MeleeShip ship)
|
||||||
|
{
|
||||||
|
if (!Melee_Change_ship (pMS, side, index, ship))
|
||||||
|
return false;
|
||||||
|
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
Netplay_NotifyAll_setTeamName (pMS, side);
|
{
|
||||||
|
MeleeSetup *setup = pMS->meleeSetup;
|
||||||
|
|
||||||
|
MeleeShip sentShip = MeleeSetup_getSentShip (setup, side, index);
|
||||||
|
if (sentShip == MELEE_UNSET)
|
||||||
|
{
|
||||||
|
// State 1.
|
||||||
|
// Notify network connections of the change.
|
||||||
|
Netplay_NotifyAll_setShip (pMS, side, index);
|
||||||
|
MeleeSetup_setSentShip (setup, side, index, ship);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* NETPLAY */
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Pre: 'name' is '\0'-terminated
|
||||||
|
bool
|
||||||
|
Melee_LocalChange_teamName (MELEE_STATE *pMS, COUNT side, const char *name)
|
||||||
|
{
|
||||||
|
if (!Melee_Change_teamName (pMS, side, name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#ifdef NETPLAY
|
||||||
|
{
|
||||||
|
MeleeSetup *setup = pMS->meleeSetup;
|
||||||
|
|
||||||
|
const char *sentName = MeleeSetup_getSentTeamName (setup, side);
|
||||||
|
if (sentName == NULL)
|
||||||
|
{
|
||||||
|
// State 1.
|
||||||
|
// Notify network connections of the change.
|
||||||
|
Netplay_NotifyAll_setTeamName (pMS, side);
|
||||||
|
MeleeSetup_setSentTeamName (setup, side, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif /* NETPLAY */
|
#endif /* NETPLAY */
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Melee_Change_fleet (MELEE_STATE *pMS, size_t teamNr, const MeleeShip *fleet)
|
Melee_LocalChange_fleet (MELEE_STATE *pMS, size_t teamNr,
|
||||||
|
const MeleeShip *fleet)
|
||||||
{
|
{
|
||||||
MeleeSetup *setup = pMS->meleeSetup;
|
|
||||||
FleetShipIndex slotI;
|
FleetShipIndex slotI;
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++) {
|
for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++)
|
||||||
if (MeleeSetup_setShip (setup, teamNr, slotI, fleet[slotI]))
|
{
|
||||||
|
if (Melee_LocalChange_ship (pMS, teamNr, slotI, fleet[slotI]))
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Melee_Change_team (MELEE_STATE *pMS, size_t teamNr, const MeleeTeam *team)
|
Melee_LocalChange_team (MELEE_STATE *pMS, size_t teamNr,
|
||||||
|
const MeleeTeam *team)
|
||||||
{
|
{
|
||||||
MeleeSetup *setup = pMS->meleeSetup;
|
|
||||||
const MeleeShip *fleet = MeleeTeam_getFleet (team);
|
const MeleeShip *fleet = MeleeTeam_getFleet (team);
|
||||||
|
const char *name = MeleeTeam_getTeamName (team);
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
if (Melee_Change_fleet (pMS, teamNr, fleet))
|
if (Melee_LocalChange_fleet (pMS, teamNr, fleet))
|
||||||
changed = true;
|
changed = true;
|
||||||
if (MeleeSetup_setTeamName (setup, teamNr, MeleeTeam_getTeamName (team)))
|
if (Melee_LocalChange_teamName (pMS, teamNr, name))
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
@@ -2367,8 +2498,40 @@ Melee_Change_team (MELEE_STATE *pMS, size_t teamNr, const MeleeTeam *team)
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Send the entire team to the remote side. Used when the connection has
|
||||||
|
// just been established, or after the setup menu is reentered after battle.
|
||||||
|
void
|
||||||
|
Melee_bootstrapSyncTeam (MELEE_STATE *meleeState, size_t teamNr)
|
||||||
|
{
|
||||||
|
MeleeSetup *setup = meleeState->meleeSetup;
|
||||||
|
FleetShipIndex slotI;
|
||||||
|
const char *teamName;
|
||||||
|
|
||||||
|
// Send the current fleet.
|
||||||
|
Netplay_NotifyAll_setFleet(meleeState, teamNr);
|
||||||
|
|
||||||
|
// Update the last sent fleet.
|
||||||
|
for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++)
|
||||||
|
{
|
||||||
|
MeleeShip ship = MeleeSetup_getShip (setup, teamNr, slotI);
|
||||||
|
assert (MeleeSetup_getSentShip (setup, teamNr, slotI) == MELEE_UNSET);
|
||||||
|
MeleeSetup_setSentShip (setup, teamNr, slotI, ship);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the current team name.
|
||||||
|
Netplay_NotifyAll_setTeamName (meleeState, teamNr);
|
||||||
|
|
||||||
|
// Update the last sent team name.
|
||||||
|
teamName = MeleeSetup_getTeamName (setup, teamNr);
|
||||||
|
MeleeSetup_setSentTeamName (setup, teamNr, teamName);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Melee_RemoteChange_xxx() functions are called when some value in the
|
// Melee_RemoteChange_xxx() functions are called when some value in the
|
||||||
// supermelee fleet setup screen has changed remotely.
|
// supermelee fleet setup screen has changed remotely.
|
||||||
|
// The behavior of these functions (and the comments therein) follow the
|
||||||
|
// description in doc/devel/netplay/protocol.
|
||||||
|
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
void
|
void
|
||||||
@@ -2377,73 +2540,139 @@ Melee_RemoteChange_ship (MELEE_STATE *pMS, NetConnection *conn, COUNT side,
|
|||||||
{
|
{
|
||||||
MeleeSetup *setup = pMS->meleeSetup;
|
MeleeSetup *setup = pMS->meleeSetup;
|
||||||
|
|
||||||
MeleeShip currentShip = MeleeSetup_getShip (setup, side, index);
|
MeleeShip sentShip = MeleeSetup_getSentShip (setup, side, index);
|
||||||
|
MeleeShip currentShip;
|
||||||
|
|
||||||
if (ship == currentShip)
|
if (sentShip == MELEE_UNSET)
|
||||||
{
|
{
|
||||||
// The remote side has confirmed what we want the value to be.
|
// State 1
|
||||||
// If we had made the same local change before, then an update
|
|
||||||
// has already been sent. If not, then there is nothing to change.
|
// Change the ship locally.
|
||||||
// Either way, we do not need to send an update.
|
Melee_Change_ship (pMS, side, index, ship);
|
||||||
MeleeSetup_setConfirmedShip (setup, side, index, ship);
|
|
||||||
} else {
|
// Notify the remote side.
|
||||||
// The remote side wants to make a change.
|
Netplay_NotifyAll_setShip (pMS, side, index);
|
||||||
// We accept the change when we don't have any changes of our own,
|
|
||||||
// or when we do have changes, but we "lose" the tie break.
|
// A packet has now been received and sent. End of turn.
|
||||||
// If we "win" the tie break, we have already sent an update to the
|
return;
|
||||||
// remote side when our local change was made, so we do not need to
|
}
|
||||||
// send anything. The remote side still needs to confirm this local
|
|
||||||
// change, of which it will become aware shortly, when the already
|
// A packet has been sent and received. End of turn.
|
||||||
// sent update message arrives.
|
MeleeSetup_setSentShip (setup, side, index, MELEE_UNSET);
|
||||||
MeleeShip confirmedShip = MeleeSetup_getConfirmedShip (setup, side,
|
|
||||||
index);
|
if (ship != sentShip)
|
||||||
if (currentShip == confirmedShip ||
|
{
|
||||||
NetConnection_getDiscriminant(conn))
|
// Rule 2c or 3d. The value which we sent is different from the value
|
||||||
|
// which the opponent sent. We need a tie-breaker to determine which
|
||||||
|
// value prevails.
|
||||||
|
if (NetConnection_getPlayerNr (conn) != side)
|
||||||
{
|
{
|
||||||
MeleeSetup_setConfirmedShip (setup, side, index, ship);
|
// Rule 2c+ or 3d+
|
||||||
Melee_Change_ship (pMS, side, index, ship);
|
// We win the tie-breaker. The value which we sent prevails.
|
||||||
// This will also cause a notification of the local
|
|
||||||
// change to be sent to the remote side, which will act
|
|
||||||
// as a confirmation.
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Rule 2c- or 3d-.
|
||||||
|
// We lose the tie-breaker. We adopt the remote value.
|
||||||
|
Melee_Change_ship (pMS, side, index, ship);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Rule 2b or 3c. The value which we sent is the value which
|
||||||
|
// the opponent sent. This confirms the value.
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Rule 2b, 2c+, 3c, or 3d+. The value which we sent is confirmed.
|
||||||
|
|
||||||
|
currentShip = MeleeSetup_getShip (setup, side, index);
|
||||||
|
if (currentShip != sentShip)
|
||||||
|
{
|
||||||
|
// Rule 3c or 3d+. We had a local change which was yet
|
||||||
|
// unreported.
|
||||||
|
|
||||||
|
// Notify the remote side and keep track of what we sent.
|
||||||
|
Netplay_NotifyAll_setShip (pMS, side, index);
|
||||||
|
MeleeSetup_setSentShip (setup, side, index, ship);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Melee_RemoteChange_teamName (MELEE_STATE *pMS, NetConnection *conn, COUNT side,
|
Melee_RemoteChange_teamName (MELEE_STATE *pMS, NetConnection *conn,
|
||||||
const char *name)
|
COUNT side, const char *newName)
|
||||||
{
|
{
|
||||||
MeleeSetup *setup = pMS->meleeSetup;
|
MeleeSetup *setup = pMS->meleeSetup;
|
||||||
|
|
||||||
const char *currentName = MeleeSetup_getTeamName (setup, side);
|
const char *sentName = MeleeSetup_getSentTeamName (setup, side);
|
||||||
|
const char *currentName;
|
||||||
|
|
||||||
if (strcmp (name, currentName) == 0)
|
if (sentName == NULL)
|
||||||
{
|
{
|
||||||
// The remote side has confirmed what we want the value to be.
|
// State 1
|
||||||
// If we had made the same local change before, then an update
|
|
||||||
// has already been sent. If not, then there is nothing to change.
|
// Change the team name locally.
|
||||||
// Either way, we do not need to send an update.
|
Melee_Change_teamName (pMS, side, newName);
|
||||||
MeleeSetup_setConfirmedTeamName (setup, side, name);
|
|
||||||
} else {
|
// Notify the remote side.
|
||||||
// The remote side wants to make a change.
|
Netplay_NotifyAll_setTeamName (pMS, side);
|
||||||
// We accept the change when we don't have any changes of our own,
|
|
||||||
// or when we do have changes, but we "lose" the tie break.
|
// A packet has now been received and sent. End of turn.
|
||||||
// If we "win" the tie break, we have already sent an update to the
|
// The sent team name is still unset, so we don't have to reset it.
|
||||||
// remote side when our local change was made, so we do not need to
|
return;
|
||||||
// send anything. The remote side still needs to confirm this local
|
}
|
||||||
// change, of which it will become aware shortly, when the already
|
|
||||||
// sent update message arrives.
|
if (strcmp (newName, sentName) == 0)
|
||||||
const char *confirmedName =
|
{
|
||||||
MeleeSetup_getConfirmedTeamName (setup, side);
|
// Rule 2c or 3d. The value which we sent is different from the value
|
||||||
if (strcmp (currentName, confirmedName) == 0 ||
|
// which the opponent sent. We need a tie-breaker to determine which
|
||||||
NetConnection_getDiscriminant(conn))
|
// value prevails.
|
||||||
|
if (NetConnection_getPlayerNr (conn) != side)
|
||||||
{
|
{
|
||||||
MeleeSetup_setConfirmedTeamName (setup, side, name);
|
// Rule 2c+ or 3d+
|
||||||
Melee_Change_teamName (pMS, side, name);
|
// We win the tie-breaker. The value which we sent prevails.
|
||||||
// This will also cause a notification of the local
|
|
||||||
// change to be sent to the remote side, which will act
|
|
||||||
// as a confirmation.
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Rule 2c- or 3d-.
|
||||||
|
// We lose the tie-breaker. We adopt the remote value.
|
||||||
|
Melee_Change_teamName (pMS, side, newName);
|
||||||
|
MeleeSetup_setSentTeamName (setup, side, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Rule 2b or 3c. The value which we sent is the value which
|
||||||
|
// the opponent sent. This confirms the value.
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Rule 2b, 2c+, 3c, or 3d+. The value which we sent is confirmed.
|
||||||
|
|
||||||
|
currentName = MeleeSetup_getTeamName (setup, side);
|
||||||
|
if (strcmp (currentName, sentName) != 0)
|
||||||
|
{
|
||||||
|
// Rule 3c or 3d+. We had a local change which was yet
|
||||||
|
// unreported.
|
||||||
|
|
||||||
|
// A packet has been sent and received, which ends the turn.
|
||||||
|
// We don't bother clearing the sent team name, as we're going
|
||||||
|
// to send a new packet immediately.
|
||||||
|
|
||||||
|
// Notify the remote side and keep track of what we sent.
|
||||||
|
Netplay_NotifyAll_setTeamName (pMS, side);
|
||||||
|
|
||||||
|
// Update the last sent message.
|
||||||
|
MeleeSetup_setSentTeamName (setup, side, newName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// A packet has been sent and received. End of turn.
|
||||||
|
MeleeSetup_setSentTeamName (setup, side, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ struct melee_state
|
|||||||
BOOLEAN (*InputFunc) (struct melee_state *pInputState);
|
BOOLEAN (*InputFunc) (struct melee_state *pInputState);
|
||||||
|
|
||||||
BOOLEAN Initialized;
|
BOOLEAN Initialized;
|
||||||
|
BOOLEAN meleeStarted;
|
||||||
MELEE_OPTIONS MeleeOption;
|
MELEE_OPTIONS MeleeOption;
|
||||||
COUNT side;
|
COUNT side;
|
||||||
COUNT row;
|
COUNT row;
|
||||||
@@ -108,14 +109,17 @@ void resetFeedback (NetConnection *conn, NetplayResetReason reason,
|
|||||||
void errorFeedback (NetConnection *conn);
|
void errorFeedback (NetConnection *conn);
|
||||||
void closeFeedback (NetConnection *conn);
|
void closeFeedback (NetConnection *conn);
|
||||||
|
|
||||||
bool Melee_Change_ship (MELEE_STATE *pMS, COUNT side, FleetShipIndex index,
|
bool Melee_LocalChange_ship (MELEE_STATE *pMS, COUNT side,
|
||||||
MeleeShip ship);
|
FleetShipIndex index, MeleeShip ship);
|
||||||
bool Melee_Change_teamName (MELEE_STATE *pMS, COUNT side, const char *name);
|
bool Melee_LocalChange_teamName (MELEE_STATE *pMS, COUNT side,
|
||||||
bool Melee_Change_fleet (MELEE_STATE *pMS, size_t teamNr,
|
const char *name);
|
||||||
|
bool Melee_LocalChange_fleet (MELEE_STATE *pMS, size_t teamNr,
|
||||||
const MeleeShip *fleet);
|
const MeleeShip *fleet);
|
||||||
bool Melee_Change_team (MELEE_STATE *pMS, size_t teamNr,
|
bool Melee_LocalChange_team (MELEE_STATE *pMS, size_t teamNr,
|
||||||
const MeleeTeam *team);
|
const MeleeTeam *team);
|
||||||
|
|
||||||
|
void Melee_bootstrapSyncTeam (MELEE_STATE *pMS, size_t teamNr);
|
||||||
|
|
||||||
void Melee_RemoteChange_ship (MELEE_STATE *pMS, NetConnection *conn,
|
void Melee_RemoteChange_ship (MELEE_STATE *pMS, NetConnection *conn,
|
||||||
COUNT side, FleetShipIndex index, MeleeShip ship);
|
COUNT side, FleetShipIndex index, MeleeShip ship);
|
||||||
void Melee_RemoteChange_teamName (MELEE_STATE *pMS, NetConnection *conn,
|
void Melee_RemoteChange_teamName (MELEE_STATE *pMS, NetConnection *conn,
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ MeleeTeam_init (MeleeTeam *team)
|
|||||||
|
|
||||||
for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++)
|
for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++)
|
||||||
team->ships[slotI] = MELEE_NONE;
|
team->ships[slotI] = MELEE_NONE;
|
||||||
|
|
||||||
|
team->name[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -158,7 +160,7 @@ MeleeTeam_getTeamName (const MeleeTeam *team)
|
|||||||
|
|
||||||
// Returns true iff the state has actually changed.
|
// Returns true iff the state has actually changed.
|
||||||
void
|
void
|
||||||
MeleeTeam_setName (MeleeTeam *team, const UNICODE *name)
|
MeleeTeam_setName (MeleeTeam *team, const char *name)
|
||||||
{
|
{
|
||||||
strncpy (team->name, name, sizeof team->name - 1);
|
strncpy (team->name, name, sizeof team->name - 1);
|
||||||
team->name[sizeof team->name - 1] = '\0';
|
team->name[sizeof team->name - 1] = '\0';
|
||||||
@@ -196,6 +198,26 @@ MeleeTeam_isEqual (const MeleeTeam *team1, const MeleeTeam *team2)
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef NETPLAY
|
||||||
|
static void
|
||||||
|
MeleeSetup_initSentTeam (MeleeSetup *setup, size_t teamNr)
|
||||||
|
{
|
||||||
|
MeleeTeam *team = &setup->sentTeams[teamNr];
|
||||||
|
FleetShipIndex slotI;
|
||||||
|
|
||||||
|
for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++)
|
||||||
|
MeleeTeam_setShip (team, slotI, MELEE_UNSET);
|
||||||
|
|
||||||
|
setup->haveSentTeamName[teamNr] = false;
|
||||||
|
#ifdef DEBUG
|
||||||
|
// The actual team name should be irrelevant if haveSentTeamName is
|
||||||
|
// set to false. In a debug build, we set it to invalid, so that
|
||||||
|
// it is more likely that it will be noticed if it is ever used.
|
||||||
|
MeleeTeam_setName (team, "<INVALID>");
|
||||||
|
#endif /* DEBUG */
|
||||||
|
}
|
||||||
|
#endif /* NETPLAY */
|
||||||
|
|
||||||
MeleeSetup *
|
MeleeSetup *
|
||||||
MeleeSetup_new (void)
|
MeleeSetup_new (void)
|
||||||
{
|
{
|
||||||
@@ -209,7 +231,7 @@ MeleeSetup_new (void)
|
|||||||
MeleeTeam_init (&result->teams[teamI]);
|
MeleeTeam_init (&result->teams[teamI]);
|
||||||
result->fleetValue[teamI] = 0;
|
result->fleetValue[teamI] = 0;
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
MeleeTeam_init (&result->confirmedTeams[teamI]);
|
MeleeSetup_initSentTeam (result, teamI);
|
||||||
#endif /* NETPLAY */
|
#endif /* NETPLAY */
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -221,6 +243,17 @@ MeleeSetup_delete (MeleeSetup *setup)
|
|||||||
HFree (setup);
|
HFree (setup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NETPLAY
|
||||||
|
void
|
||||||
|
MeleeSetup_resetSentTeams (MeleeSetup *setup)
|
||||||
|
{
|
||||||
|
size_t teamI;
|
||||||
|
|
||||||
|
for (teamI = 0; teamI < NUM_SIDES; teamI++)
|
||||||
|
MeleeSetup_initSentTeam (setup, teamI);
|
||||||
|
}
|
||||||
|
#endif /* NETPLAY */
|
||||||
|
|
||||||
// Returns true iff the state has actually changed.
|
// Returns true iff the state has actually changed.
|
||||||
bool
|
bool
|
||||||
MeleeSetup_setShip (MeleeSetup *setup, size_t teamNr, FleetShipIndex slotNr,
|
MeleeSetup_setShip (MeleeSetup *setup, size_t teamNr, FleetShipIndex slotNr,
|
||||||
@@ -259,10 +292,10 @@ MeleeSetup_getFleet (const MeleeSetup *setup, size_t teamNr)
|
|||||||
// Returns true iff the state has actually changed.
|
// Returns true iff the state has actually changed.
|
||||||
bool
|
bool
|
||||||
MeleeSetup_setTeamName (MeleeSetup *setup, size_t teamNr,
|
MeleeSetup_setTeamName (MeleeSetup *setup, size_t teamNr,
|
||||||
const UNICODE *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
MeleeTeam *team = &setup->teams[teamNr];
|
MeleeTeam *team = &setup->teams[teamNr];
|
||||||
const UNICODE *oldName = MeleeTeam_getTeamName (team);
|
const char *oldName = MeleeTeam_getTeamName (team);
|
||||||
|
|
||||||
if (strcmp (oldName, name) == 0)
|
if (strcmp (oldName, name) == 0)
|
||||||
return false;
|
return false;
|
||||||
@@ -271,6 +304,8 @@ MeleeSetup_setTeamName (MeleeSetup *setup, size_t teamNr,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NB. This function returns a pointer to a static buffer, which is
|
||||||
|
// overwritten by calls to MeleeSetup_setTeamName().
|
||||||
const char *
|
const char *
|
||||||
MeleeSetup_getTeamName (const MeleeSetup *setup, size_t teamNr)
|
MeleeSetup_getTeamName (const MeleeSetup *setup, size_t teamNr)
|
||||||
{
|
{
|
||||||
@@ -301,24 +336,31 @@ MeleeSetup_serializeTeam (const MeleeSetup *setup, size_t teamNr,
|
|||||||
|
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
MeleeShip
|
MeleeShip
|
||||||
MeleeSetup_getConfirmedShip (const MeleeSetup *setup, size_t teamNr,
|
MeleeSetup_getSentShip (const MeleeSetup *setup, size_t teamNr,
|
||||||
FleetShipIndex slotNr)
|
FleetShipIndex slotNr)
|
||||||
{
|
{
|
||||||
return MeleeTeam_getShip (&setup->confirmedTeams[teamNr], slotNr);
|
return MeleeTeam_getShip (&setup->sentTeams[teamNr], slotNr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns NULL if there is no team name set. This is not the same
|
||||||
|
// as when an empty (zero-length) team name is set.
|
||||||
|
// NB. This function returns a pointer to a static buffer, which is
|
||||||
|
// overwritten by calls to MeleeSetup_setSentTeamName().
|
||||||
const char *
|
const char *
|
||||||
MeleeSetup_getConfirmedTeamName (const MeleeSetup *setup, size_t teamNr)
|
MeleeSetup_getSentTeamName (const MeleeSetup *setup, size_t teamNr)
|
||||||
{
|
{
|
||||||
return MeleeTeam_getTeamName (&setup->confirmedTeams[teamNr]);
|
if (!setup->haveSentTeamName[teamNr])
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return MeleeTeam_getTeamName (&setup->sentTeams[teamNr]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff the state has actually changed.
|
// Returns true iff the state has actually changed.
|
||||||
bool
|
bool
|
||||||
MeleeSetup_setConfirmedShip (MeleeSetup *setup, size_t teamNr,
|
MeleeSetup_setSentShip (MeleeSetup *setup, size_t teamNr,
|
||||||
FleetShipIndex slotNr, MeleeShip ship)
|
FleetShipIndex slotNr, MeleeShip ship)
|
||||||
{
|
{
|
||||||
MeleeTeam *team = &setup->confirmedTeams[teamNr];
|
MeleeTeam *team = &setup->sentTeams[teamNr];
|
||||||
MeleeShip oldShip = MeleeTeam_getShip (team, slotNr);
|
MeleeShip oldShip = MeleeTeam_getShip (team, slotNr);
|
||||||
|
|
||||||
if (ship == oldShip)
|
if (ship == oldShip)
|
||||||
@@ -329,28 +371,62 @@ MeleeSetup_setConfirmedShip (MeleeSetup *setup, size_t teamNr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff the state has actually changed.
|
// Returns true iff the state has actually changed.
|
||||||
|
// 'name' can be NULL to indicate that no team name set. This is not the same
|
||||||
|
// as when an empty (zero-length) team name is set.
|
||||||
bool
|
bool
|
||||||
MeleeSetup_setConfirmedTeamName (MeleeSetup *setup, size_t teamNr,
|
MeleeSetup_setSentTeamName (MeleeSetup *setup, size_t teamNr,
|
||||||
const UNICODE *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
MeleeTeam *team = &setup->confirmedTeams[teamNr];
|
bool haveSentName = setup->haveSentTeamName[teamNr];
|
||||||
const UNICODE *oldName = MeleeTeam_getTeamName (team);
|
|
||||||
|
|
||||||
if (strcmp (oldName, name) == 0)
|
if (name == NULL)
|
||||||
return false;
|
{
|
||||||
|
if (!haveSentName)
|
||||||
|
{
|
||||||
|
// Had not sent a team name, and still haven't.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
{
|
||||||
|
// The actual team name should be irrelevant if haveSentTeamName
|
||||||
|
// is set to false. In a debug build, we set it to invalid, so
|
||||||
|
// that it is more likely that it will be noticed if it is ever
|
||||||
|
// used.
|
||||||
|
MeleeTeam *team = &setup->sentTeams[teamNr];
|
||||||
|
MeleeTeam_setName (team, "<INVALID>");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MeleeTeam *team;
|
||||||
|
|
||||||
|
if (haveSentName)
|
||||||
|
{
|
||||||
|
// Have sent a team name. Check whether it has actually changed.
|
||||||
|
const char *oldName = MeleeTeam_getTeamName (team);
|
||||||
|
if (strcmp (oldName, name) == 0)
|
||||||
|
return false; // Team name has not changed.
|
||||||
|
}
|
||||||
|
|
||||||
|
team = &setup->sentTeams[teamNr];
|
||||||
|
MeleeTeam_setName (team, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
setup->haveSentTeamName[teamNr] = (name != NULL);
|
||||||
|
|
||||||
MeleeTeam_setName (team, name);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
bool
|
bool
|
||||||
MeleeSetup_isTeamConfirmed (MeleeSetup *setup, size_t teamNr)
|
MeleeSetup_isTeamSent (MeleeSetup *setup, size_t teamNr)
|
||||||
{
|
{
|
||||||
MeleeTeam *localTeam = &setup->teams[teamNr];
|
MeleeTeam *localTeam = &setup->teams[teamNr];
|
||||||
MeleeTeam *confirmedTeam = &setup->confirmedTeams[teamNr];
|
MeleeTeam *sentTeam = &setup->sentTeams[teamNr];
|
||||||
|
|
||||||
return MeleeTeam_isEqual (localTeam, confirmedTeam);
|
return MeleeTeam_isEqual (localTeam, sentTeam);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -36,47 +36,29 @@ typedef COUNT FleetShipIndex;
|
|||||||
struct MeleeTeam
|
struct MeleeTeam
|
||||||
{
|
{
|
||||||
MeleeShip ships[MELEE_FLEET_SIZE];
|
MeleeShip ships[MELEE_FLEET_SIZE];
|
||||||
UNICODE name[MAX_TEAM_CHARS + 1 + 24];
|
char name[MAX_TEAM_CHARS + 1 + 24];
|
||||||
/* The +1 is for the terminating \0; the +24 is in case some
|
/* The +1 is for the terminating \0; the +24 is in case some
|
||||||
* default name in starcon.txt is unknowingly mangled. */
|
* default name in starcon.txt is unknowingly mangled. */
|
||||||
|
// XXX: SvdB: Why would it be mangled? Why don't we just reject
|
||||||
|
// it if it is? Is this so that we have some space
|
||||||
|
// for multibyte UTF-8 chars?
|
||||||
};
|
};
|
||||||
#endif /* MELEETEAM_INTERNAL */
|
#endif /* MELEETEAM_INTERNAL */
|
||||||
|
|
||||||
#ifdef MELEESETUP_INTERNAL
|
#ifdef MELEESETUP_INTERNAL
|
||||||
// When Netplay is enabled, we keep two copies of the teams: the team as we
|
|
||||||
// consider it to be locally, and last confirmed team.
|
|
||||||
// There are no separate change and confirmation messages; a confirmation
|
|
||||||
// message is a message reporting a change to the value which was specified
|
|
||||||
// by the remote side.
|
|
||||||
// When a local change is made, the current team is updated, and a message
|
|
||||||
// is sent to the other side.
|
|
||||||
// When we receive a message of a remote update:
|
|
||||||
// - if the current value is the same as the received value, we change
|
|
||||||
// the confirmed value to the current/received value
|
|
||||||
// - if the current value is different from the received value, and
|
|
||||||
// the current value is the same as the confirmed value, we change both
|
|
||||||
// the current value and the confirmed value to the received value,
|
|
||||||
// and sent a message to the remote side of our modification.
|
|
||||||
// - if the current value is different from the received value, and
|
|
||||||
// the current value is not the same as the confirmed value, our
|
|
||||||
// action depends on who "owns" the value:
|
|
||||||
// - if the change is to the remote fleet, we change the current and
|
|
||||||
// confirmed value to the received value, and send a message to the
|
|
||||||
// remote side of our modification (as above)
|
|
||||||
// - if the change is to the local fleet, we take no action.
|
|
||||||
// (In this situation, a local change has been made, and a message of
|
|
||||||
// this has already been sent to the other side, and a confirmation
|
|
||||||
// from the other side will arrive eventually.)
|
|
||||||
// XXX: put this in docs/netplay/protocols.
|
|
||||||
// XXX: this not only works for teams, but also for other properties.
|
|
||||||
struct MeleeSetup
|
struct MeleeSetup
|
||||||
{
|
{
|
||||||
MeleeTeam teams[NUM_SIDES];
|
MeleeTeam teams[NUM_SIDES];
|
||||||
COUNT fleetValue[NUM_SIDES];
|
COUNT fleetValue[NUM_SIDES];
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
MeleeTeam confirmedTeams[NUM_SIDES];
|
MeleeTeam sentTeams[NUM_SIDES];
|
||||||
// The least team which both sides agreed upon.
|
// The last sent (parts of) teams.
|
||||||
|
// Used in the Update protocol. See doc/devel/netplay/protocol
|
||||||
// XXX: this may actually be deallocated when the battle starts.
|
// XXX: this may actually be deallocated when the battle starts.
|
||||||
|
bool haveSentTeamName[NUM_SIDES];
|
||||||
|
// Whether we have sent a team name this 'turn'.
|
||||||
|
// Used in the Update protocol. See doc/devel/netplay/protocol
|
||||||
|
// (also for the term 'turn').
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -88,6 +70,9 @@ void MeleeTeam_init (MeleeTeam *team);
|
|||||||
void MeleeTeam_uninit (MeleeTeam *team);
|
void MeleeTeam_uninit (MeleeTeam *team);
|
||||||
MeleeTeam *MeleeTeam_new (void);
|
MeleeTeam *MeleeTeam_new (void);
|
||||||
void MeleeTeam_delete (MeleeTeam *team);
|
void MeleeTeam_delete (MeleeTeam *team);
|
||||||
|
#ifdef NETPLAY
|
||||||
|
void MeleeSetup_resetSentTeams (MeleeSetup *setup);
|
||||||
|
#endif /* NETPLAY */
|
||||||
int MeleeTeam_serialize (const MeleeTeam *team, uio_Stream *stream);
|
int MeleeTeam_serialize (const MeleeTeam *team, uio_Stream *stream);
|
||||||
int MeleeTeam_deserialize (MeleeTeam *team, uio_Stream *stream);
|
int MeleeTeam_deserialize (MeleeTeam *team, uio_Stream *stream);
|
||||||
COUNT MeleeTeam_getValue (const MeleeTeam *team);
|
COUNT MeleeTeam_getValue (const MeleeTeam *team);
|
||||||
@@ -96,23 +81,23 @@ void MeleeTeam_setShip (MeleeTeam *team, FleetShipIndex slotNr,
|
|||||||
MeleeShip ship);
|
MeleeShip ship);
|
||||||
const MeleeShip *MeleeTeam_getFleet (const MeleeTeam *team);
|
const MeleeShip *MeleeTeam_getFleet (const MeleeTeam *team);
|
||||||
const char *MeleeTeam_getTeamName (const MeleeTeam *team);
|
const char *MeleeTeam_getTeamName (const MeleeTeam *team);
|
||||||
void MeleeTeam_setName (MeleeTeam *team, const UNICODE *name);
|
void MeleeTeam_setName (MeleeTeam *team, const char *name);
|
||||||
void MeleeTeam_copy (MeleeTeam *copy, const MeleeTeam *original);
|
void MeleeTeam_copy (MeleeTeam *copy, const MeleeTeam *original);
|
||||||
#if 0
|
#if 0
|
||||||
bool MeleeTeam_isEqual (const MeleeTeam *team1, const MeleeTeam *team2);
|
bool MeleeTeam_isEqual (const MeleeTeam *team1, const MeleeTeam *team2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NETPLAY
|
#ifdef NETPLAY
|
||||||
MeleeShip MeleeSetup_getConfirmedShip (const MeleeSetup *setup, size_t teamNr,
|
MeleeShip MeleeSetup_getSentShip (const MeleeSetup *setup, size_t teamNr,
|
||||||
FleetShipIndex slotNr);
|
FleetShipIndex slotNr);
|
||||||
const char *MeleeSetup_getConfirmedTeamName (const MeleeSetup *setup,
|
const char *MeleeSetup_getSentTeamName (const MeleeSetup *setup,
|
||||||
size_t teamNr);
|
size_t teamNr);
|
||||||
bool MeleeSetup_setConfirmedShip (MeleeSetup *setup, size_t teamNr,
|
bool MeleeSetup_setSentShip (MeleeSetup *setup, size_t teamNr,
|
||||||
FleetShipIndex slotNr, MeleeShip ship);
|
FleetShipIndex slotNr, MeleeShip ship);
|
||||||
bool MeleeSetup_setConfirmedTeamName (MeleeSetup *setup, size_t teamNr,
|
bool MeleeSetup_setSentTeamName (MeleeSetup *setup, size_t teamNr,
|
||||||
const UNICODE *name);
|
const char *name);
|
||||||
#if 0
|
#if 0
|
||||||
bool MeleeSetup_isTeamConfirmed (MeleeSetup *setup, size_t teamNr);
|
bool MeleeSetup_isTeamSent (MeleeSetup *setup, size_t teamNr);
|
||||||
#endif
|
#endif
|
||||||
#endif /* NETPLAY */
|
#endif /* NETPLAY */
|
||||||
|
|
||||||
@@ -127,7 +112,7 @@ bool MeleeSetup_setFleet (MeleeSetup *setup, size_t teamNr,
|
|||||||
const MeleeShip *fleet);
|
const MeleeShip *fleet);
|
||||||
const MeleeShip *MeleeSetup_getFleet (const MeleeSetup *setup, size_t teamNr);
|
const MeleeShip *MeleeSetup_getFleet (const MeleeSetup *setup, size_t teamNr);
|
||||||
bool MeleeSetup_setTeamName (MeleeSetup *setup, size_t teamNr,
|
bool MeleeSetup_setTeamName (MeleeSetup *setup, size_t teamNr,
|
||||||
const UNICODE *name);
|
const char *name);
|
||||||
const char *MeleeSetup_getTeamName (const MeleeSetup *setup,
|
const char *MeleeSetup_getTeamName (const MeleeSetup *setup,
|
||||||
size_t teamNr);
|
size_t teamNr);
|
||||||
COUNT MeleeSetup_getFleetValue (const MeleeSetup *setup, size_t teamNr);
|
COUNT MeleeSetup_getFleetValue (const MeleeSetup *setup, size_t teamNr);
|
||||||
@@ -142,7 +127,7 @@ void MeleeState_setShip (MELEE_STATE *pMS, size_t teamNr,
|
|||||||
void MeleeState_setFleet (MELEE_STATE *pMS, size_t teamNr,
|
void MeleeState_setFleet (MELEE_STATE *pMS, size_t teamNr,
|
||||||
const MeleeShip *fleet);
|
const MeleeShip *fleet);
|
||||||
void MeleeState_setTeamName (MELEE_STATE *pMS, size_t teamNr,
|
void MeleeState_setTeamName (MELEE_STATE *pMS, size_t teamNr,
|
||||||
const UNICODE *name);
|
const char *name);
|
||||||
void MeleeState_setTeam (MELEE_STATE *pMS, size_t teamNr,
|
void MeleeState_setTeam (MELEE_STATE *pMS, size_t teamNr,
|
||||||
const MeleeTeam *team);
|
const MeleeTeam *team);
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ typedef enum MeleeShip {
|
|||||||
MELEE_YEHAT,
|
MELEE_YEHAT,
|
||||||
MELEE_ZOQFOTPIK,
|
MELEE_ZOQFOTPIK,
|
||||||
|
|
||||||
|
MELEE_UNSET = ((BYTE) ~0) - 1,
|
||||||
|
// Used with the Update protocol, to register in the sentTeam
|
||||||
MELEE_NONE = (BYTE) ~0
|
MELEE_NONE = (BYTE) ~0
|
||||||
|
// Empty fleet position.
|
||||||
} MeleeShip;
|
} MeleeShip;
|
||||||
#define NUM_MELEE_SHIPS (MELEE_ZOQFOTPIK + 1)
|
#define NUM_MELEE_SHIPS (MELEE_ZOQFOTPIK + 1)
|
||||||
|
|
||||||
|
|||||||
@@ -181,8 +181,6 @@ NetConnection_connectedServerCallback(ListenState *listenState,
|
|||||||
// Ignore errors; it's not a big deal. In debug mode, a message
|
// Ignore errors; it's not a big deal. In debug mode, a message
|
||||||
// will already have been printed from the function itself.
|
// will already have been printed from the function itself.
|
||||||
|
|
||||||
conn->stateFlags.myTurn = true;
|
|
||||||
// The "server" may speak first.
|
|
||||||
conn->stateFlags.discriminant = true;
|
conn->stateFlags.discriminant = true;
|
||||||
|
|
||||||
NetConnection_connected(conn);
|
NetConnection_connected(conn);
|
||||||
@@ -210,8 +208,6 @@ NetConnection_connectedClientCallback(ConnectState *connectState,
|
|||||||
// Ignore errors; it's not a big deal. In debug mode, a message
|
// Ignore errors; it's not a big deal. In debug mode, a message
|
||||||
// will already have been printed from the function itself.
|
// will already have been printed from the function itself.
|
||||||
|
|
||||||
conn->stateFlags.myTurn = false;
|
|
||||||
// The "server" may speak first.
|
|
||||||
conn->stateFlags.discriminant = false;
|
conn->stateFlags.discriminant = false;
|
||||||
|
|
||||||
NetConnection_connected(conn);
|
NetConnection_connected(conn);
|
||||||
|
|||||||
@@ -129,9 +129,6 @@ NetConnection_open(int player, const NetplayPeerOptions *options,
|
|||||||
conn->stateData = NULL;
|
conn->stateData = NULL;
|
||||||
conn->stateFlags.connected = false;
|
conn->stateFlags.connected = false;
|
||||||
conn->stateFlags.disconnected = false;
|
conn->stateFlags.disconnected = false;
|
||||||
conn->stateFlags.myTurn = false;
|
|
||||||
conn->stateFlags.endingTurn = false;
|
|
||||||
conn->stateFlags.pendingTurnChange = false;
|
|
||||||
conn->stateFlags.discriminant = false;
|
conn->stateFlags.discriminant = false;
|
||||||
conn->stateFlags.handshake.localOk = false;
|
conn->stateFlags.handshake.localOk = false;
|
||||||
conn->stateFlags.handshake.remoteOk = false;
|
conn->stateFlags.handshake.remoteOk = false;
|
||||||
@@ -350,11 +347,6 @@ NetConnection_isConnected(const NetConnection *conn) {
|
|||||||
return conn->stateFlags.connected;
|
return conn->stateFlags.connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
NetConnection_isMyTurn(const NetConnection *conn) {
|
|
||||||
return conn->stateFlags.myTurn;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
NetConnection_getPlayerNr(const NetConnection *conn) {
|
NetConnection_getPlayerNr(const NetConnection *conn) {
|
||||||
return conn->player;
|
return conn->player;
|
||||||
|
|||||||
@@ -104,20 +104,11 @@ typedef struct {
|
|||||||
/* This NetConnection has been disconnected. This implies
|
/* This NetConnection has been disconnected. This implies
|
||||||
* !connected. It is only set if the NetConnection was once
|
* !connected. It is only set if the NetConnection was once
|
||||||
* connected, but is no longer. */
|
* connected, but is no longer. */
|
||||||
bool myTurn;
|
|
||||||
/* This party is the only one who may send specific packets
|
|
||||||
* at the moment. */
|
|
||||||
bool endingTurn;
|
|
||||||
/* Request to change the turn from/to the other party. */
|
|
||||||
bool pendingTurnChange;
|
|
||||||
/* It is our turn and the other party wants our turn,
|
|
||||||
* but we're not ready to give it up just yet; we will first
|
|
||||||
* send our pending packets. */
|
|
||||||
bool discriminant;
|
bool discriminant;
|
||||||
/* If it is true here, it is false on the remote side
|
/* If it is true here, it is false on the remote side
|
||||||
* of the same connection. It may be used to break ties.
|
* of the same connection. It may be used to break ties.
|
||||||
* Unlike myTurn, this one is guaranteed not to change
|
* It is guaranteed not to change during a connection. Undefined
|
||||||
* during a connection. Undefined while not connected. */
|
* while not connected. */
|
||||||
HandShakeFlags handshake;
|
HandShakeFlags handshake;
|
||||||
ReadyFlags ready;
|
ReadyFlags ready;
|
||||||
ResetFlags reset;
|
ResetFlags reset;
|
||||||
@@ -204,7 +195,6 @@ bool NetConnection_isConnected(const NetConnection *conn);
|
|||||||
|
|
||||||
void NetConnection_doErrorCallback(NetConnection *nd, int err);
|
void NetConnection_doErrorCallback(NetConnection *nd, int err);
|
||||||
|
|
||||||
bool NetConnection_isMyTurn(const NetConnection *conn);
|
|
||||||
void NetConnection_setStateData(NetConnection *conn,
|
void NetConnection_setStateData(NetConnection *conn,
|
||||||
NetConnectionStateData *stateData);
|
NetConnectionStateData *stateData);
|
||||||
NetConnectionStateData *NetConnection_getStateData(const NetConnection *conn);
|
NetConnectionStateData *NetConnection_getStateData(const NetConnection *conn);
|
||||||
|
|||||||
@@ -84,6 +84,9 @@ NetMelee_connectCallback(NetConnection *conn) {
|
|||||||
NetConnection_setStateData(conn, (void *) battleStateData);
|
NetConnection_setStateData(conn, (void *) battleStateData);
|
||||||
NetConnection_setExtra(conn, NULL);
|
NetConnection_setExtra(conn, NULL);
|
||||||
|
|
||||||
|
// We have sent no teams yet. Initialize the state accordingly.
|
||||||
|
MeleeSetup_resetSentTeams (meleeState->meleeSetup);
|
||||||
|
|
||||||
sendInit(conn);
|
sendInit(conn);
|
||||||
Netplay_localReady (conn, NetMelee_enterState_inSetup, NULL, false);
|
Netplay_localReady (conn, NetMelee_enterState_inSetup, NULL, false);
|
||||||
}
|
}
|
||||||
@@ -119,43 +122,13 @@ NetMelee_enterState_inSetup(NetConnection *conn, void *arg) {
|
|||||||
|
|
||||||
connectedFeedback(conn);
|
connectedFeedback(conn);
|
||||||
|
|
||||||
Netplay_NotifyAll_setFleet(meleeState, player);
|
// Send our team to the remote side.
|
||||||
Netplay_NotifyAll_setTeamName(meleeState, player);
|
// XXX This only works with 2 players atm.
|
||||||
|
assert (NUM_PLAYERS == 2);
|
||||||
|
Melee_bootstrapSyncTeam (meleeState, player);
|
||||||
|
|
||||||
flushPacketQueues();
|
flushPacketQueues();
|
||||||
|
|
||||||
(void) arg;
|
(void) arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback function for when both sides have confirmed that the battle
|
|
||||||
// has ended.
|
|
||||||
void
|
|
||||||
NetMelee_reenterState_inSetup(NetConnection *conn) {
|
|
||||||
BattleStateData *battleStateData;
|
|
||||||
struct melee_state *meleeState;
|
|
||||||
|
|
||||||
NetConnection_setState(conn, NetState_inSetup);
|
|
||||||
|
|
||||||
battleStateData = (BattleStateData *) NetConnection_getStateData(conn);
|
|
||||||
meleeState = battleStateData->meleeState;
|
|
||||||
|
|
||||||
// The player who entered the menu first should send his changes over
|
|
||||||
// to the other side when the other player enters setup too.
|
|
||||||
// As myTurn is set when a change is made, and will never be unset
|
|
||||||
// until the other side makes a change, it can be used to determine
|
|
||||||
// which side was first. In the case there were no changes made, myTurn
|
|
||||||
// may be the second player, but in this case it doesn't matter
|
|
||||||
// who sends what to whom.
|
|
||||||
if (NetConnection_isMyTurn(conn))
|
|
||||||
{
|
|
||||||
size_t side;
|
|
||||||
|
|
||||||
for (side = 0; side < NUM_SIDES; side++)
|
|
||||||
{
|
|
||||||
Netplay_NotifyAll_setFleet(meleeState, side);
|
|
||||||
Netplay_NotifyAll_setTeamName(meleeState, side);
|
|
||||||
}
|
|
||||||
flushPacketQueues();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -62,8 +62,7 @@ readyFlagsMeaningful(NetState state) {
|
|||||||
state == NetState_interBattle ||
|
state == NetState_interBattle ||
|
||||||
state == NetState_inBattle ||
|
state == NetState_inBattle ||
|
||||||
state == NetState_endingBattle ||
|
state == NetState_endingBattle ||
|
||||||
state == NetState_endingBattle2 ||
|
state == NetState_endingBattle2;
|
||||||
state == NetState_endMelee;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,15 +25,15 @@
|
|||||||
#define NETPLAY_FULL 2
|
#define NETPLAY_FULL 2
|
||||||
|
|
||||||
#define NETPLAY_PROTOCOL_VERSION_MAJOR 0
|
#define NETPLAY_PROTOCOL_VERSION_MAJOR 0
|
||||||
#define NETPLAY_PROTOCOL_VERSION_MINOR 3
|
#define NETPLAY_PROTOCOL_VERSION_MINOR 4
|
||||||
|
|
||||||
#define NETPLAY_MIN_UQM_VERSION_MAJOR 0
|
#define NETPLAY_MIN_UQM_VERSION_MAJOR 0
|
||||||
#define NETPLAY_MIN_UQM_VERSION_MINOR 5
|
#define NETPLAY_MIN_UQM_VERSION_MINOR 6
|
||||||
#define NETPLAY_MIN_UQM_VERSION_PATCH 4
|
#define NETPLAY_MIN_UQM_VERSION_PATCH 9
|
||||||
|
|
||||||
#define NETPLAY_DEBUG
|
#undef NETPLAY_DEBUG
|
||||||
/* Extra debugging for netplay */
|
/* Extra debugging for netplay */
|
||||||
#define NETPLAY_DEBUG_FILE
|
#undef NETPLAY_DEBUG_FILE
|
||||||
/* Dump extra debugging information to file.
|
/* Dump extra debugging information to file.
|
||||||
* Implies NETPLAY_DEBUG.*/
|
* Implies NETPLAY_DEBUG.*/
|
||||||
#define NETPLAY_STATISTICS
|
#define NETPLAY_STATISTICS
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "netplay.h"
|
#include "netplay.h"
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
|
|
||||||
|
#include "netsend.h"
|
||||||
#include "netconnection.h"
|
#include "netconnection.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "libs/log.h"
|
#include "libs/log.h"
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ NetStateData netStateData[] = {
|
|||||||
DEFINE_NETSTATEDATA(inBattle),
|
DEFINE_NETSTATEDATA(inBattle),
|
||||||
DEFINE_NETSTATEDATA(endingBattle),
|
DEFINE_NETSTATEDATA(endingBattle),
|
||||||
DEFINE_NETSTATEDATA(endingBattle2),
|
DEFINE_NETSTATEDATA(endingBattle2),
|
||||||
DEFINE_NETSTATEDATA(endMelee),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ typedef enum {
|
|||||||
NetState_inBattle, /* Battle has started */
|
NetState_inBattle, /* Battle has started */
|
||||||
NetState_endingBattle, /* Both sides are prepared to end */
|
NetState_endingBattle, /* Both sides are prepared to end */
|
||||||
NetState_endingBattle2, /* Waiting for the final synchronisation */
|
NetState_endingBattle2, /* Waiting for the final synchronisation */
|
||||||
NetState_endMelee, /* Melee ended; remote is not yet in setup */
|
|
||||||
} NetState;
|
} NetState;
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|||||||
@@ -29,33 +29,31 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
#define DEFINE_PACKETDATA(name, inTurn) \
|
#define DEFINE_PACKETDATA(name) \
|
||||||
{ \
|
{ \
|
||||||
/* .len = */ sizeof (Packet_##name), \
|
/* .len = */ sizeof (Packet_##name), \
|
||||||
/* .handler = */ (PacketHandler) PacketHandler_##name, \
|
/* .handler = */ (PacketHandler) PacketHandler_##name, \
|
||||||
/* .name = */ #name, \
|
/* .name = */ #name, \
|
||||||
/* .inTurn = */ (inTurn) \
|
|
||||||
}
|
}
|
||||||
PacketTypeData packetTypeData[PACKET_NUM] = {
|
PacketTypeData packetTypeData[PACKET_NUM] = {
|
||||||
DEFINE_PACKETDATA(Init, false),
|
DEFINE_PACKETDATA(Init),
|
||||||
DEFINE_PACKETDATA(Ping, false),
|
DEFINE_PACKETDATA(Ping),
|
||||||
DEFINE_PACKETDATA(Ack, false),
|
DEFINE_PACKETDATA(Ack),
|
||||||
DEFINE_PACKETDATA(EndTurn, false),
|
DEFINE_PACKETDATA(Ready),
|
||||||
DEFINE_PACKETDATA(Ready, false),
|
DEFINE_PACKETDATA(Fleet),
|
||||||
DEFINE_PACKETDATA(Fleet, true),
|
DEFINE_PACKETDATA(TeamName),
|
||||||
DEFINE_PACKETDATA(TeamName, true),
|
DEFINE_PACKETDATA(Handshake0),
|
||||||
DEFINE_PACKETDATA(Handshake0, false),
|
DEFINE_PACKETDATA(Handshake1),
|
||||||
DEFINE_PACKETDATA(Handshake1, false),
|
DEFINE_PACKETDATA(HandshakeCancel),
|
||||||
DEFINE_PACKETDATA(HandshakeCancel, false),
|
DEFINE_PACKETDATA(HandshakeCancelAck),
|
||||||
DEFINE_PACKETDATA(HandshakeCancelAck, false),
|
DEFINE_PACKETDATA(SeedRandom),
|
||||||
DEFINE_PACKETDATA(SeedRandom, false),
|
DEFINE_PACKETDATA(InputDelay),
|
||||||
DEFINE_PACKETDATA(InputDelay, false),
|
DEFINE_PACKETDATA(SelectShip),
|
||||||
DEFINE_PACKETDATA(SelectShip, false),
|
DEFINE_PACKETDATA(BattleInput),
|
||||||
DEFINE_PACKETDATA(BattleInput, false),
|
DEFINE_PACKETDATA(FrameCount),
|
||||||
DEFINE_PACKETDATA(FrameCount, false),
|
DEFINE_PACKETDATA(Checksum),
|
||||||
DEFINE_PACKETDATA(Checksum, false),
|
DEFINE_PACKETDATA(Abort),
|
||||||
DEFINE_PACKETDATA(Abort, false),
|
DEFINE_PACKETDATA(Reset),
|
||||||
DEFINE_PACKETDATA(Reset, false),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void *
|
static inline void *
|
||||||
@@ -113,14 +111,6 @@ Packet_Ack_create(uint32 id) {
|
|||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet_EndTurn *
|
|
||||||
Packet_EndTurn_create(void) {
|
|
||||||
Packet_EndTurn *packet =
|
|
||||||
(Packet_EndTurn *) Packet_create(PACKET_ENDTURN, 0);
|
|
||||||
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet_Ready *
|
Packet_Ready *
|
||||||
Packet_Ready_create(void) {
|
Packet_Ready_create(void) {
|
||||||
Packet_Ready *packet = (Packet_Ready *) Packet_create(PACKET_READY, 0);
|
Packet_Ready *packet = (Packet_Ready *) Packet_create(PACKET_READY, 0);
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ typedef enum PacketType {
|
|||||||
PACKET_INIT,
|
PACKET_INIT,
|
||||||
PACKET_PING,
|
PACKET_PING,
|
||||||
PACKET_ACK,
|
PACKET_ACK,
|
||||||
PACKET_ENDTURN,
|
|
||||||
PACKET_READY,
|
PACKET_READY,
|
||||||
PACKET_FLEET,
|
PACKET_FLEET,
|
||||||
PACKET_TEAMNAME,
|
PACKET_TEAMNAME,
|
||||||
@@ -79,7 +78,6 @@ typedef struct {
|
|||||||
size_t len; /* Minimal length of a packet of this type */
|
size_t len; /* Minimal length of a packet of this type */
|
||||||
PacketHandler handler;
|
PacketHandler handler;
|
||||||
const char *name;
|
const char *name;
|
||||||
bool inTurn; /* Can only be sent if it's this party's turn. */
|
|
||||||
} PacketTypeData;
|
} PacketTypeData;
|
||||||
|
|
||||||
extern PacketTypeData packetTypeData[];
|
extern PacketTypeData packetTypeData[];
|
||||||
@@ -142,12 +140,6 @@ typedef struct {
|
|||||||
uint32 id;
|
uint32 id;
|
||||||
} Packet_Ack;
|
} Packet_Ack;
|
||||||
|
|
||||||
// Used to ask or confirm a turn change.
|
|
||||||
typedef struct {
|
|
||||||
PacketHeader header;
|
|
||||||
// No contents.
|
|
||||||
} Packet_EndTurn;
|
|
||||||
|
|
||||||
// Used to signal that a party is ready to continue.
|
// Used to signal that a party is ready to continue.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PacketHeader header;
|
PacketHeader header;
|
||||||
@@ -262,7 +254,6 @@ void Packet_delete(Packet *packet);
|
|||||||
Packet_Init *Packet_Init_create(void);
|
Packet_Init *Packet_Init_create(void);
|
||||||
Packet_Ping *Packet_Ping_create(uint32 id);
|
Packet_Ping *Packet_Ping_create(uint32 id);
|
||||||
Packet_Ack *Packet_Ack_create(uint32 id);
|
Packet_Ack *Packet_Ack_create(uint32 id);
|
||||||
Packet_EndTurn *Packet_EndTurn_create(void);
|
|
||||||
Packet_Ready *Packet_Ready_create(void);
|
Packet_Ready *Packet_Ready_create(void);
|
||||||
Packet_Handshake0 *Packet_Handshake0_create(void);
|
Packet_Handshake0 *Packet_Handshake0_create(void);
|
||||||
Packet_Handshake1 *Packet_Handshake1_create(void);
|
Packet_Handshake1 *Packet_Handshake1_create(void);
|
||||||
|
|||||||
@@ -142,41 +142,6 @@ PacketHandler_Ack(NetConnection *conn, const Packet_Ack *packet) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
PacketHandler_EndTurn(NetConnection *conn, const Packet_EndTurn *packet) {
|
|
||||||
if (!testNetState(conn->state > NetState_init &&
|
|
||||||
!conn->stateFlags.pendingTurnChange, PACKET_ENDTURN))
|
|
||||||
return -1; // errno is set
|
|
||||||
|
|
||||||
if (conn->stateFlags.endingTurn) {
|
|
||||||
// This was the confirmation we were waiting for.
|
|
||||||
// NB. A remote request while we had sent a request serves as
|
|
||||||
// a confirmation.
|
|
||||||
conn->stateFlags.myTurn = !conn->stateFlags.myTurn;
|
|
||||||
conn->stateFlags.endingTurn = false;
|
|
||||||
} else {
|
|
||||||
// The other party wants to change whose turn it is.
|
|
||||||
// If it would become the other party's turn, we wait until
|
|
||||||
// the queue is flushed to actually carry out the turn change,
|
|
||||||
// and send the confirmation. I we wouldn't do that, and we still
|
|
||||||
// had some data to send in our own turn, we would end up asking
|
|
||||||
// for our turn back, and the turn would keep changing without
|
|
||||||
// any progress being made.
|
|
||||||
if (conn->stateFlags.myTurn) {
|
|
||||||
// Schedule the turn change until after the next queue flush.
|
|
||||||
conn->stateFlags.pendingTurnChange = true;
|
|
||||||
} else {
|
|
||||||
conn->stateFlags.myTurn = true;
|
|
||||||
sendEndTurn(conn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) packet;
|
|
||||||
// Its contents is not interesting.
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the side indication relative to a remote party to
|
// Convert the side indication relative to a remote party to
|
||||||
// a local player number.
|
// a local player number.
|
||||||
static inline int
|
static inline int
|
||||||
@@ -189,17 +154,6 @@ localSide(NetConnection *conn, NetplaySide side) {
|
|||||||
return 1 - conn->player;
|
return 1 - conn->player;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
checkYourTurn(NetConnection *conn, PacketType type) {
|
|
||||||
if (conn->stateFlags.myTurn) {
|
|
||||||
log_add(log_Warning, "Packet of type '%s' received in an "
|
|
||||||
"inappropriate turn.", packetTypeData[type].name);
|
|
||||||
errno = EBADMSG;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
PacketHandler_Ready(NetConnection *conn, const Packet_Ready *packet) {
|
PacketHandler_Ready(NetConnection *conn, const Packet_Ready *packet) {
|
||||||
if (conn->stateFlags.reset.localReset)
|
if (conn->stateFlags.reset.localReset)
|
||||||
@@ -239,11 +193,6 @@ PacketHandler_Fleet(NetConnection *conn, const Packet_Fleet *packet) {
|
|||||||
if (!testNetState(conn->state == NetState_inSetup, PACKET_FLEET))
|
if (!testNetState(conn->state == NetState_inSetup, PACKET_FLEET))
|
||||||
return -1; // errno is set
|
return -1; // errno is set
|
||||||
|
|
||||||
if (!checkYourTurn(conn, PACKET_FLEET)) {
|
|
||||||
// errno is set
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
player = localSide(conn, (NetplaySide) packet->side);
|
player = localSide(conn, (NetplaySide) packet->side);
|
||||||
|
|
||||||
len = packetLength((const Packet *) packet);
|
len = packetLength((const Packet *) packet);
|
||||||
@@ -304,14 +253,9 @@ PacketHandler_TeamName(NetConnection *conn, const Packet_TeamName *packet) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!testNetState(conn->state == NetState_inSetup, PACKET_TEAMNAME))
|
if (!testNetState(conn->state == NetState_inSetup, PACKET_FLEET))
|
||||||
return -1; // errno is set
|
return -1; // errno is set
|
||||||
|
|
||||||
if (!checkYourTurn(conn, PACKET_TEAMNAME)) {
|
|
||||||
// errno is set
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
battleStateData = (BattleStateData *) NetConnection_getStateData(conn);
|
battleStateData = (BattleStateData *) NetConnection_getStateData(conn);
|
||||||
|
|
||||||
if (conn->stateFlags.handshake.localOk) {
|
if (conn->stateFlags.handshake.localOk) {
|
||||||
@@ -503,8 +447,7 @@ PacketHandler_InputDelay(NetConnection *conn,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!testNetState(conn->state == NetState_preBattle,
|
if (!testNetState(conn->state == NetState_preBattle, PACKET_INPUTDELAY))
|
||||||
PACKET_INPUTDELAY))
|
|
||||||
return -1; // errno is set
|
return -1; // errno is set
|
||||||
|
|
||||||
battleStateData = (BattleStateData *) NetConnection_getStateData(conn);
|
battleStateData = (BattleStateData *) NetConnection_getStateData(conn);
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
DECLARE_PACKETHANDLER(Init);
|
DECLARE_PACKETHANDLER(Init);
|
||||||
DECLARE_PACKETHANDLER(Ping);
|
DECLARE_PACKETHANDLER(Ping);
|
||||||
DECLARE_PACKETHANDLER(Ack);
|
DECLARE_PACKETHANDLER(Ack);
|
||||||
DECLARE_PACKETHANDLER(EndTurn);
|
|
||||||
DECLARE_PACKETHANDLER(Ready);
|
DECLARE_PACKETHANDLER(Ready);
|
||||||
DECLARE_PACKETHANDLER(Fleet);
|
DECLARE_PACKETHANDLER(Fleet);
|
||||||
DECLARE_PACKETHANDLER(TeamName);
|
DECLARE_PACKETHANDLER(TeamName);
|
||||||
|
|||||||
@@ -47,9 +47,6 @@ PacketQueue_init(PacketQueue *queue) {
|
|||||||
queue->size = 0;
|
queue->size = 0;
|
||||||
queue->first = NULL;
|
queue->first = NULL;
|
||||||
queue->end = &queue->first;
|
queue->end = &queue->first;
|
||||||
|
|
||||||
queue->firstUrgent = NULL;
|
|
||||||
queue->endUrgent = &queue->first;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -64,31 +61,23 @@ PacketQueue_deleteLinks(PacketQueueLink *link) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
PacketQueue_uninit(PacketQueue *queue) {
|
PacketQueue_uninit(PacketQueue *queue) {
|
||||||
PacketQueue_deleteLinks(queue->firstUrgent);
|
|
||||||
PacketQueue_deleteLinks(queue->first);
|
PacketQueue_deleteLinks(queue->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
queuePacket(NetConnection *conn, Packet *packet, bool urgent) {
|
queuePacket(NetConnection *conn, Packet *packet) {
|
||||||
PacketQueue *queue;
|
PacketQueue *queue;
|
||||||
PacketQueueLink *link;
|
PacketQueueLink *link;
|
||||||
|
|
||||||
assert(NetConnection_isConnected(conn));
|
assert(NetConnection_isConnected(conn));
|
||||||
assert(!urgent || !packetTypeData[packetType(packet)].inTurn);
|
|
||||||
// Urgent packets should never stall the connection.
|
|
||||||
|
|
||||||
queue = &conn->queue;
|
queue = &conn->queue;
|
||||||
|
|
||||||
link = PacketQueueLink_alloc();
|
link = PacketQueueLink_alloc();
|
||||||
link->packet = packet;
|
link->packet = packet;
|
||||||
link->next = NULL;
|
link->next = NULL;
|
||||||
if (urgent) {
|
*queue->end = link;
|
||||||
*queue->endUrgent = link;
|
queue->end = &link->next;
|
||||||
queue->endUrgent = &link->next;
|
|
||||||
} else {
|
|
||||||
*queue->end = link;
|
|
||||||
queue->end = &link->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
queue->size++;
|
queue->size++;
|
||||||
// XXX: perhaps check that this queue isn't getting too large?
|
// XXX: perhaps check that this queue isn't getting too large?
|
||||||
@@ -124,29 +113,6 @@ flushPacketQueueLinks(NetConnection *conn, PacketQueueLink **first) {
|
|||||||
PacketQueue *queue = &conn->queue;
|
PacketQueue *queue = &conn->queue;
|
||||||
|
|
||||||
for (link = *first; link != NULL; link = next) {
|
for (link = *first; link != NULL; link = next) {
|
||||||
if (packetTypeData[packetType(link->packet)].inTurn &&
|
|
||||||
(!conn->stateFlags.myTurn || conn->stateFlags.endingTurn)) {
|
|
||||||
// This packet requires it to be 'our turn', and it isn't,
|
|
||||||
// or we've already told the other party we wanted to end our
|
|
||||||
// turn.
|
|
||||||
// This should never happen in the urgent queue.
|
|
||||||
assert(first != &queue->firstUrgent);
|
|
||||||
|
|
||||||
if (!conn->stateFlags.myTurn && !conn->stateFlags.endingTurn) {
|
|
||||||
conn->stateFlags.endingTurn = true;
|
|
||||||
if (sendEndTurnDirect(conn) == -1) {
|
|
||||||
// errno is set
|
|
||||||
*first = link;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*first = link;
|
|
||||||
errno = EAGAIN;
|
|
||||||
// We need to wait for the reply to the turn change.
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sendPacket(conn, link->packet) == -1) {
|
if (sendPacket(conn, link->packet) == -1) {
|
||||||
// Errno is set.
|
// Errno is set.
|
||||||
*first = link;
|
*first = link;
|
||||||
@@ -170,14 +136,6 @@ flushPacketQueue(NetConnection *conn) {
|
|||||||
|
|
||||||
assert(NetConnection_isConnected(conn));
|
assert(NetConnection_isConnected(conn));
|
||||||
|
|
||||||
flushResult = flushPacketQueueLinks(conn, &queue->firstUrgent);
|
|
||||||
if (queue->firstUrgent == NULL)
|
|
||||||
queue->endUrgent = &queue->firstUrgent;
|
|
||||||
if (flushResult == -1) {
|
|
||||||
// errno is set
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
flushResult = flushPacketQueueLinks(conn, &queue->first);
|
flushResult = flushPacketQueueLinks(conn, &queue->first);
|
||||||
if (queue->first == NULL)
|
if (queue->first == NULL)
|
||||||
queue->end = &queue->first;
|
queue->end = &queue->first;
|
||||||
@@ -186,23 +144,6 @@ flushPacketQueue(NetConnection *conn) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a turn change had been requested by the other side while it was
|
|
||||||
// our turn, we first sent everything we still had to send in our turn.
|
|
||||||
// Now that is done, it is the time to actually give up the turn.
|
|
||||||
if (conn->stateFlags.pendingTurnChange) {
|
|
||||||
assert(conn->stateFlags.myTurn);
|
|
||||||
conn->stateFlags.myTurn = false;
|
|
||||||
conn->stateFlags.pendingTurnChange = false;
|
|
||||||
|
|
||||||
// Send the confirmation to the other side:
|
|
||||||
if (sendEndTurnDirect(conn) == -1) {
|
|
||||||
// errno is set
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -37,30 +37,13 @@ struct PacketQueue {
|
|||||||
PacketQueueLink *first;
|
PacketQueueLink *first;
|
||||||
PacketQueueLink **end;
|
PacketQueueLink **end;
|
||||||
|
|
||||||
PacketQueueLink *firstUrgent;
|
|
||||||
PacketQueueLink **endUrgent;
|
|
||||||
|
|
||||||
// first points to the first entry in the queue
|
// first points to the first entry in the queue
|
||||||
// end points to the location where the next non-urgent message should
|
// end points to the location where the next message should be inserted.
|
||||||
// be inserted.
|
|
||||||
// 'firstUrgent' and 'endUrgent' are analogous to 'first' and 'end'.
|
|
||||||
|
|
||||||
// Urgent packets should only be used for packets that may not
|
|
||||||
// be delayed while we wait for some remote confirmation.
|
|
||||||
// As such, these messages themselves should not require a state change
|
|
||||||
// which needs to be remotely confirmed.
|
|
||||||
// For example, the endTurn message can be sent when we want to change
|
|
||||||
// which party is allowed to transmit specific packets. That message
|
|
||||||
// should not be delayed by messages which require that *we* are that
|
|
||||||
// party, as without the endTurn message, it will never become our turn.
|
|
||||||
// Also, ping and ack packets should give some indication of the round
|
|
||||||
// trip time, which they can only do if they aren't delayed by other
|
|
||||||
// packets.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void PacketQueue_init(PacketQueue *queue);
|
void PacketQueue_init(PacketQueue *queue);
|
||||||
void PacketQueue_uninit(PacketQueue *queue);
|
void PacketQueue_uninit(PacketQueue *queue);
|
||||||
void queuePacket(NetConnection *conn, Packet *packet, bool urgent);
|
void queuePacket(NetConnection *conn, Packet *packet);
|
||||||
int flushPacketQueue(NetConnection *conn);
|
int flushPacketQueue(NetConnection *conn);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ sendInit(NetConnection *conn) {
|
|||||||
Packet_Init *packet;
|
Packet_Init *packet;
|
||||||
|
|
||||||
packet = Packet_Init_create();
|
packet = Packet_Init_create();
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -37,7 +37,7 @@ sendPing(NetConnection *conn, uint32 id) {
|
|||||||
Packet_Ping *packet;
|
Packet_Ping *packet;
|
||||||
|
|
||||||
packet = Packet_Ping_create(id);
|
packet = Packet_Ping_create(id);
|
||||||
queuePacket(conn, (Packet *) packet, true);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -45,15 +45,7 @@ sendAck(NetConnection *conn, uint32 id) {
|
|||||||
Packet_Ack *packet;
|
Packet_Ack *packet;
|
||||||
|
|
||||||
packet = Packet_Ack_create(id);
|
packet = Packet_Ack_create(id);
|
||||||
queuePacket(conn, (Packet *) packet, true);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sendEndTurn(NetConnection *conn) {
|
|
||||||
Packet_EndTurn *packet;
|
|
||||||
|
|
||||||
packet = Packet_EndTurn_create();
|
|
||||||
queuePacket(conn, (Packet *) packet, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -61,17 +53,7 @@ sendReady(NetConnection *conn) {
|
|||||||
Packet_Ready *packet;
|
Packet_Ready *packet;
|
||||||
|
|
||||||
packet = Packet_Ready_create();
|
packet = Packet_Ready_create();
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
|
||||||
|
|
||||||
// Bypass the packet queue.
|
|
||||||
// Should only be called from the packet queue functions themselves.
|
|
||||||
int
|
|
||||||
sendEndTurnDirect(NetConnection *conn) {
|
|
||||||
Packet_EndTurn *packet;
|
|
||||||
|
|
||||||
packet = Packet_EndTurn_create();
|
|
||||||
return sendPacket(conn, (Packet *) packet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -79,7 +61,7 @@ sendHandshake0(NetConnection *conn) {
|
|||||||
Packet_Handshake0 *packet;
|
Packet_Handshake0 *packet;
|
||||||
|
|
||||||
packet = Packet_Handshake0_create();
|
packet = Packet_Handshake0_create();
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -87,7 +69,7 @@ sendHandshake1(NetConnection *conn) {
|
|||||||
Packet_Handshake1 *packet;
|
Packet_Handshake1 *packet;
|
||||||
|
|
||||||
packet = Packet_Handshake1_create();
|
packet = Packet_Handshake1_create();
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -95,7 +77,7 @@ sendHandshakeCancel(NetConnection *conn) {
|
|||||||
Packet_HandshakeCancel *packet;
|
Packet_HandshakeCancel *packet;
|
||||||
|
|
||||||
packet = Packet_HandshakeCancel_create();
|
packet = Packet_HandshakeCancel_create();
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -103,7 +85,7 @@ sendHandshakeCancelAck(NetConnection *conn) {
|
|||||||
Packet_HandshakeCancelAck *packet;
|
Packet_HandshakeCancelAck *packet;
|
||||||
|
|
||||||
packet = Packet_HandshakeCancelAck_create();
|
packet = Packet_HandshakeCancelAck_create();
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -112,7 +94,7 @@ sendTeamName(NetConnection *conn, NetplaySide side, const char *name,
|
|||||||
Packet_TeamName *packet;
|
Packet_TeamName *packet;
|
||||||
|
|
||||||
packet = Packet_TeamName_create(side, name, len);
|
packet = Packet_TeamName_create(side, name, len);
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -128,7 +110,7 @@ sendFleet(NetConnection *conn, NetplaySide side, const MeleeShip *ships,
|
|||||||
packet->ships[i].ship = (uint8) ships[i];
|
packet->ships[i].ship = (uint8) ships[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -141,7 +123,7 @@ sendFleetShip(NetConnection *conn, NetplaySide side,
|
|||||||
packet->ships[0].index = (uint8) shipIndex;
|
packet->ships[0].index = (uint8) shipIndex;
|
||||||
packet->ships[0].ship = (uint8) ship;
|
packet->ships[0].ship = (uint8) ship;
|
||||||
|
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -149,7 +131,7 @@ sendSeedRandom(NetConnection *conn, uint32 seed) {
|
|||||||
Packet_SeedRandom *packet;
|
Packet_SeedRandom *packet;
|
||||||
|
|
||||||
packet = Packet_SeedRandom_create(seed);
|
packet = Packet_SeedRandom_create(seed);
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -157,7 +139,7 @@ sendInputDelay(NetConnection *conn, uint32 delay) {
|
|||||||
Packet_InputDelay *packet;
|
Packet_InputDelay *packet;
|
||||||
|
|
||||||
packet = Packet_InputDelay_create(delay);
|
packet = Packet_InputDelay_create(delay);
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -165,7 +147,7 @@ sendSelectShip(NetConnection *conn, FleetShipIndex index) {
|
|||||||
Packet_SelectShip *packet;
|
Packet_SelectShip *packet;
|
||||||
|
|
||||||
packet = Packet_SelectShip_create((uint16) index);
|
packet = Packet_SelectShip_create((uint16) index);
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -173,7 +155,7 @@ sendBattleInput(NetConnection *conn, BATTLE_INPUT_STATE input) {
|
|||||||
Packet_BattleInput *packet;
|
Packet_BattleInput *packet;
|
||||||
|
|
||||||
packet = Packet_BattleInput_create((uint8) input);
|
packet = Packet_BattleInput_create((uint8) input);
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -181,7 +163,7 @@ sendFrameCount(NetConnection *conn, BattleFrameCounter frameCount) {
|
|||||||
Packet_FrameCount *packet;
|
Packet_FrameCount *packet;
|
||||||
|
|
||||||
packet = Packet_FrameCount_create((uint32) frameCount);
|
packet = Packet_FrameCount_create((uint32) frameCount);
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NETPLAY_CHECKSUM
|
#ifdef NETPLAY_CHECKSUM
|
||||||
@@ -191,7 +173,7 @@ sendChecksum(NetConnection *conn, BattleFrameCounter frameNr,
|
|||||||
Packet_Checksum *packet;
|
Packet_Checksum *packet;
|
||||||
|
|
||||||
packet = Packet_Checksum_create((uint32) frameNr, (uint32) checksum);
|
packet = Packet_Checksum_create((uint32) frameNr, (uint32) checksum);
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -200,7 +182,7 @@ sendAbort(NetConnection *conn, NetplayAbortReason reason) {
|
|||||||
Packet_Abort *packet;
|
Packet_Abort *packet;
|
||||||
|
|
||||||
packet = Packet_Abort_create((uint16) reason);
|
packet = Packet_Abort_create((uint16) reason);
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -208,7 +190,7 @@ sendReset(NetConnection *conn, NetplayResetReason reason) {
|
|||||||
Packet_Reset *packet;
|
Packet_Reset *packet;
|
||||||
|
|
||||||
packet = Packet_Reset_create((uint16) reason);
|
packet = Packet_Reset_create((uint16) reason);
|
||||||
queuePacket(conn, (Packet *) packet, false);
|
queuePacket(conn, (Packet *) packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,7 @@
|
|||||||
void sendInit(NetConnection *conn);
|
void sendInit(NetConnection *conn);
|
||||||
void sendPing(NetConnection *conn, uint32 id);
|
void sendPing(NetConnection *conn, uint32 id);
|
||||||
void sendAck(NetConnection *conn, uint32 id);
|
void sendAck(NetConnection *conn, uint32 id);
|
||||||
void sendEndTurn(NetConnection *conn);
|
|
||||||
void sendReady(NetConnection *conn);
|
void sendReady(NetConnection *conn);
|
||||||
int sendEndTurnDirect(NetConnection *conn);
|
|
||||||
void sendHandshake0(NetConnection *conn);
|
void sendHandshake0(NetConnection *conn);
|
||||||
void sendHandshake1(NetConnection *conn);
|
void sendHandshake1(NetConnection *conn);
|
||||||
void sendHandshakeCancel(NetConnection *conn);
|
void sendHandshakeCancel(NetConnection *conn);
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ Netplay_connectionReset(NetConnection *conn, NetplayResetReason reason,
|
|||||||
case NetState_inBattle:
|
case NetState_inBattle:
|
||||||
case NetState_endingBattle:
|
case NetState_endingBattle:
|
||||||
case NetState_endingBattle2:
|
case NetState_endingBattle2:
|
||||||
case NetState_endMelee:
|
|
||||||
resetFeedback(conn, reason, byRemote);
|
resetFeedback(conn, reason, byRemote);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -384,15 +384,6 @@ aborted:
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NETPLAY
|
|
||||||
static void
|
|
||||||
endMeleeCallback (NetConnection *conn, void *arg)
|
|
||||||
{
|
|
||||||
NetMelee_reenterState_inSetup (conn);
|
|
||||||
(void) arg;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static COUNT
|
static COUNT
|
||||||
GetRaceQueueValue (const QUEUE *queue) {
|
GetRaceQueueValue (const QUEUE *queue) {
|
||||||
COUNT result;
|
COUNT result;
|
||||||
@@ -662,9 +653,14 @@ MeleeGameOver (void)
|
|||||||
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
|
||||||
DrawPickMeleeFrame (playerI);
|
DrawPickMeleeFrame (playerI);
|
||||||
|
|
||||||
TimeOut = GetTimeCounter () + (ONE_SECOND * 4);
|
|
||||||
UnlockMutex (GraphicsLock);
|
UnlockMutex (GraphicsLock);
|
||||||
|
|
||||||
|
#ifdef NETPLAY
|
||||||
|
negotiateReadyConnections(true, NetState_inSetup);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TimeOut = GetTimeCounter () + (ONE_SECOND * 4);
|
||||||
|
|
||||||
PressState = PulsedInputState.menu[KEY_MENU_SELECT] ||
|
PressState = PulsedInputState.menu[KEY_MENU_SELECT] ||
|
||||||
PulsedInputState.menu[KEY_MENU_CANCEL];
|
PulsedInputState.menu[KEY_MENU_CANCEL];
|
||||||
do
|
do
|
||||||
@@ -683,11 +679,6 @@ MeleeGameOver (void)
|
|||||||
&& (!(PlayerControl[0] & PlayerControl[1] & PSYTRON_CONTROL)
|
&& (!(PlayerControl[0] & PlayerControl[1] & PSYTRON_CONTROL)
|
||||||
|| GetTimeCounter () < TimeOut)));
|
|| GetTimeCounter () < TimeOut)));
|
||||||
|
|
||||||
#ifdef NETPLAY
|
|
||||||
setStateConnections (NetState_endMelee);
|
|
||||||
localReadyConnections (endMeleeCallback, NULL, true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -898,6 +889,7 @@ GetInitialMeleeStarShips (HSTARSHIP *result)
|
|||||||
return GetMeleeStarShips (playerMask, result);
|
return GetMeleeStarShips (playerMask, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the next ship to use in SuperMelee.
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
GetNextMeleeStarShip (COUNT which_player, HSTARSHIP *result)
|
GetNextMeleeStarShip (COUNT which_player, HSTARSHIP *result)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ readyToEndCallback (NetConnection *conn, void *arg)
|
|||||||
* 3. After a player has both sent and received a frame count, the
|
* 3. After a player has both sent and received a frame count, the
|
||||||
* simulation continues for each party, until the maximum of both
|
* simulation continues for each party, until the maximum of both
|
||||||
* frame counts has been achieved.
|
* frame counts has been achieved.
|
||||||
* 4. The Ready protocol is used to let each side signal that the it has
|
* 4. The Ready protocol is used to let each side signal that it has
|
||||||
* reached the target frame count.
|
* reached the target frame count.
|
||||||
* 5. The battle ends.
|
* 5. The battle ends.
|
||||||
*/
|
*/
|
||||||
@@ -132,7 +132,7 @@ readyForBattleEndPlayer (NetConnection *conn)
|
|||||||
battleStateData = (BattleStateData *) NetConnection_getStateData(conn);
|
battleStateData = (BattleStateData *) NetConnection_getStateData(conn);
|
||||||
|
|
||||||
if (NetConnection_getState (conn) == NetState_interBattle ||
|
if (NetConnection_getState (conn) == NetState_interBattle ||
|
||||||
NetConnection_getState (conn) == NetState_endMelee)
|
NetConnection_getState (conn) == NetState_inSetup)
|
||||||
{
|
{
|
||||||
// This connection is already ready. The entire synchronisation
|
// This connection is already ready. The entire synchronisation
|
||||||
// protocol has already been done for this connection.
|
// protocol has already been done for this connection.
|
||||||
@@ -161,7 +161,7 @@ readyForBattleEndPlayer (NetConnection *conn)
|
|||||||
|
|
||||||
// Keep the simulation going as long as the target frame count
|
// Keep the simulation going as long as the target frame count
|
||||||
// hasn't been reached yet. Note that if the connection state is
|
// hasn't been reached yet. Note that if the connection state is
|
||||||
// NetState_endingBattle, that we haven't yet received the
|
// NetState_endingBattle, then we haven't yet received the
|
||||||
// remote frame count, so the target frame count may still rise.
|
// remote frame count, so the target frame count may still rise.
|
||||||
if (battleFrameCount < battleStateData->endFrameCount)
|
if (battleFrameCount < battleStateData->endFrameCount)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -21,8 +21,8 @@
|
|||||||
#define UQM_MAJOR_VERSION_S "0"
|
#define UQM_MAJOR_VERSION_S "0"
|
||||||
#define UQM_MINOR_VERSION 6
|
#define UQM_MINOR_VERSION 6
|
||||||
#define UQM_MINOR_VERSION_S "6"
|
#define UQM_MINOR_VERSION_S "6"
|
||||||
#define UQM_PATCH_VERSION 8
|
#define UQM_PATCH_VERSION 9
|
||||||
#define UQM_PATCH_VERSION_S "8"
|
#define UQM_PATCH_VERSION_S "9"
|
||||||
#define UQM_EXTRA_VERSION ""
|
#define UQM_EXTRA_VERSION ""
|
||||||
/* The final version is interpreted as:
|
/* The final version is interpreted as:
|
||||||
* printf ("%d.%d.%d%s", UQM_MAJOR_VERSION, UQM_MINOR_VERSION,
|
* printf ("%d.%d.%d%s", UQM_MAJOR_VERSION, UQM_MINOR_VERSION,
|
||||||
|
|||||||
Reference in New Issue
Block a user