tAddition of new "A_DONEFIGHT" ability; conforming clients now send the server a C_DONE message to indicate that the user has read any relevant messages, closed dialogs, etc. and is ready to move on. - vaccinewars - be a doctor and try to vaccinate the world
git clone git://src.adamsgaard.dk/vaccinewars
Log
Files
Refs
README
LICENSE
---
commit 82bd31408cf47e0d219c71fddeb6ba780ae26fea
parent 4e2abfa579b8dff0f346479002e8fc06436594e7
Author: Ben Webb 
Date:   Sat, 13 Apr 2002 16:35:45 +0000

Addition of new "A_DONEFIGHT" ability; conforming clients now send the
server a C_DONE message to indicate that the user has read any relevant
messages, closed dialogs, etc. and is ready to move on.


Diffstat:
  M ChangeLog                           |       2 ++
  M doc/protocol.html                   |      28 +++++++++++++++++++++-------
  M src/AIPlayer.c                      |       1 +
  M src/curses_client/curses_client.c   |       3 +++
  M src/dopewars.h                      |       4 +++-
  M src/gui_client/gtk_client.c         |       3 +++
  M src/message.c                       |       1 +
  M src/serverside.c                    |      34 +++++++++++++++++++++++--------

8 files changed, 59 insertions(+), 17 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
t@@ -1,4 +1,6 @@
 cvs
+    - On fight termination the player is now allowed to close the "Fight"
+      dialog before any new dialogs pop up
     - Incorrect handling of WM_CLOSE under Win32 fixed
     - Unix server now fails "gracefully" if it cannot create the Unix domain
       socket for admin connections
diff --git a/doc/protocol.html b/doc/protocol.html
t@@ -396,7 +396,7 @@ C_REQUESTJET or C_FIGHTACT message

C_ABILITIES ('r')
Negotiates protocol extensions between client and server
-data = (playerid)(drugvalue)(newfight)(tstring) +data = (playerid)(drugvalue)(newfight)(tstring)(donefight)

playerid = '1' if we use player IDs rather than player names to identify players in network messages ('0' otherwise). It is t@@ -424,7 +424,20 @@ sent in the translated string (tstring) notation; only necessary if you are supporting non-English languages. Ability name in dopewars code: A_TSTRING

-e.g. "^^Ar1010" (N.B. the double ^ is a feature of the "old" protocol)
+

donefight = '1' if, when a fight finishes, +the client is expected to send a C_DONE message to instruct the server to +move on. (This is to allow the user to close the fight dialog before any +new dialogs pop up.) Ability name in dopewars code: A_DONEFIGHT

+ +

N.B. Only five abilities are listed here. Older servers or clients +may not only not support some of these abilities, they may not even know +of their existence (conversely, newer versions may add new abilities). Thus +all servers and clients, if passed an unexpectedly short abilities string, +should pad it out with zeroes. If passed a long string, it should be truncated. +This will cause these extra (or unspecified) abilities to be unsupported. +(The order of the abilities string should never change.)

+ +e.g. "^^Ar10100" (N.B. the double ^ is a feature of the "old" protocol) t@@ -541,11 +554,12 @@ no C_ABILITIES reply message will be sent, and the client should assume that after the C_ABILITIES message to be compliant with these abilities.

e.g.
-- client sends "1110" (supports everything except +- client sends "11101" (supports everything except A_TSTRING)
-- server responds with "1011" (supports everything except -A_DRUGVALUE)
-- client should adopt the abilities "1010" ( +- server responds with "10110" (supports everything except +A_DRUGVALUE and +A_DONEFIGHT)
+- client should adopt the abilities "10100" ( A_PLAYERID and A_NEWFIGHT) t@@ -558,7 +572,7 @@ e.g.
-

Last update: 29-10-2001

+

Last update: 13-04-2002

diff --git a/src/AIPlayer.c b/src/AIPlayer.c
t@@ -81,6 +81,7 @@ static void AIStartGame(Player *AIPlay)
 {
   Client = Network = TRUE;
   InitAbilities(AIPlay);
+  SetAbility(AIPlay, A_DONEFIGHT, FALSE);
   SendAbilities(AIPlay);
 
   AISetName(AIPlay);
diff --git a/src/curses_client/curses_client.c b/src/curses_client/curses_client.c
t@@ -2321,6 +2321,9 @@ static void Curses_DoGame(Player *Play)
       switch (c) {
       case 'D':
         DisplayMode = DM_STREET;
+        if (!(Play->Flags & FIGHTING) && HaveAbility(Play, A_DONEFIGHT)) {
+          SendClientMessage(Play, C_NONE, C_DONE, NULL, NULL);
+        }
         break;
       case 'R':
         if (RunHere) {
diff --git a/src/dopewars.h b/src/dopewars.h
t@@ -64,6 +64,8 @@ typedef enum {
   A_NEWFIGHT,                   /* Use new unified fighting code */
   A_TSTRING,                    /* We understand the %Txx (tstring)
                                  * notation */
+  A_DONEFIGHT,                  /* A fight is only considered over once the
+                                 * client sends the server a C_DONE message */
   A_NUM                         /* N.B. Must be last */
 } AbilType;
 
t@@ -125,7 +127,7 @@ typedef enum {
   E_FINISH = 100,
 
   E_OUTOFSYNC = 120,
-  E_FIGHT, E_FIGHTASK, E_DOCTOR,
+  E_FIGHT, E_FIGHTASK, E_DOCTOR, E_WAITDONE,
   E_MAXOOS
 } EventCode;
 
diff --git a/src/gui_client/gtk_client.c b/src/gui_client/gtk_client.c
t@@ -791,6 +791,9 @@ static void FightCallback(GtkWidget *widget, gpointer data)
   switch (Answer) {
   case 'D':
     gtk_widget_hide(FightDialog);
+    if (!(Play->Flags & FIGHTING) && HaveAbility(Play, A_DONEFIGHT)) {
+      SendClientMessage(Play, C_NONE, C_DONE, NULL, NULL);
+    }
     break;
   case 'R':
     if (CanRunHere) {
diff --git a/src/message.c b/src/message.c
t@@ -244,6 +244,7 @@ void InitAbilities(Player *Play)
   Play->Abil.Local[A_NEWFIGHT] = TRUE;
   Play->Abil.Local[A_DRUGVALUE] = (DrugValue ? TRUE : FALSE);
   Play->Abil.Local[A_TSTRING] = TRUE;
+  Play->Abil.Local[A_DONEFIGHT] = TRUE;
 
   if (!Network)
     for (i = 0; i < A_NUM; i++) {
diff --git a/src/serverside.c b/src/serverside.c
t@@ -469,6 +469,10 @@ void HandleServerMessage(gchar *buf, Player *Play)
       } else {
         RunFromCombat(Play, i);
       }
+      if (Play->EventNum == E_WAITDONE) {
+        Play->EventNum = Play->ResyncNum;
+        SendEvent(Play);
+      }
     }
     if (NumTurns > 0 && Play->Turn >= NumTurns
         && Play->EventNum != E_FINISH) {
t@@ -534,7 +538,10 @@ void HandleServerMessage(gchar *buf, Player *Play)
     HandleAnswer(Play, To, Data);
     break;
   case C_DONE:
-    if (Play->EventNum != E_NONE && Play->EventNum < E_OUTOFSYNC) {
+    if (Play->EventNum == E_WAITDONE) {
+      Play->EventNum = Play->ResyncNum;
+      SendEvent(Play);
+    } else if (Play->EventNum != E_NONE && Play->EventNum < E_OUTOFSYNC) {
       Play->EventNum++;
       SendEvent(Play);
     }
t@@ -2529,6 +2536,19 @@ void DoReturnFire(Player *Play)
   }
 }
 
+/*
+ * Puts the given player into the "fight ended" state.
+ */
+static void WaitForFightDone(Player *Play)
+{
+  if (HaveAbility(Play, A_DONEFIGHT)) {
+    Play->EventNum = E_WAITDONE;
+  } else {
+    Play->EventNum = Play->ResyncNum;
+    SendEvent(Play);
+  }
+}
+
 /* 
  * Withdraws player "Play" from combat, and levies any penalties on
  * the player for this cowardly act, if applicable. If "ToLocation"
t@@ -2570,8 +2590,7 @@ void RunFromCombat(Player *Play, int ToLocation)
     Play->IsAt = ToLocation;
     WithdrawFromCombat(Play);
     Play->IsAt = BackupAt;
-    Play->EventNum = Play->ResyncNum;
-    SendEvent(Play);
+    WaitForFightDone(Play);
   } else {
     SendFightMessage(Play, NULL, 0, F_FAILFLEE, (price_t)0, TRUE, NULL);
     AllowNextShooter(Play);
t@@ -2878,8 +2897,7 @@ void WithdrawFromCombat(Player *Play)
         SendQuestion(NULL, C_ASKSEW, Defend, text);
         g_free(text);
       } else {
-        Defend->EventNum = Defend->ResyncNum;
-        SendEvent(Defend);
+        WaitForFightDone(Defend);
       }
     }
     g_ptr_array_free(Play->FightArray, TRUE);
t@@ -3239,8 +3257,7 @@ void HandleAnswer(Player *From, Player *To, char *answer)
         From->Health = 100;
         SendPlayerData(From);
       }
-      From->EventNum = From->ResyncNum;
-      SendEvent(From);
+      WaitForFightDone(From);
       break;
     default:
       break;
t@@ -3276,8 +3293,7 @@ void HandleAnswer(Player *From, Player *To, char *answer)
       SendEvent(From);
       break;
     case E_DOCTOR:
-      From->EventNum = From->ResyncNum;
-      SendEvent(From);
+      WaitForFightDone(From);
       break;
     case E_HIREBITCH:
     case E_GUNSHOP: