From 81b069d6a8154ff53fa8d5b8b55523c95f136e3a Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Thu, 4 Jan 2024 03:47:18 +0200
Subject: [PATCH 29/29] Let server decide if the other party meets clause
 requirements

Client was blocking clauses when it didn't really know
if the other party meets the requirements.

See RM #123

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 client/clitreaty.c          |  3 ++-
 common/diptreaty.c          | 25 +++++++++++++++++--------
 common/diptreaty.h          |  3 ++-
 server/diplhand.c           | 11 ++++++-----
 server/savegame/savegame2.c |  2 +-
 server/savegame/savegame3.c |  2 +-
 6 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/client/clitreaty.c b/client/clitreaty.c
index f2ff3de77f..8ef31d27f1 100644
--- a/client/clitreaty.c
+++ b/client/clitreaty.c
@@ -119,7 +119,8 @@ void client_recv_create_clause(int counterpart, int giver,
 
   gui_prepare_clause_updt(ptreaty, they);
 
-  add_clause(ptreaty, player_by_number(giver), type, value);
+  add_clause(ptreaty, player_by_number(giver), type, value,
+             client_player());
 
   gui_recv_create_clause(ptreaty, they);
 }
diff --git a/common/diptreaty.c b/common/diptreaty.c
index 4df9c23206..6ad57fb6b0 100644
--- a/common/diptreaty.c
+++ b/common/diptreaty.c
@@ -143,7 +143,8 @@ bool remove_clause(struct Treaty *ptreaty, struct player *pfrom,
   Add clause to treaty.
 **************************************************************************/
 bool add_clause(struct Treaty *ptreaty, struct player *pfrom, 
-                enum clause_type type, int val)
+                enum clause_type type, int val,
+                struct player *client_player)
 {
   struct player *pto = (pfrom == ptreaty->plr0
                         ? ptreaty->plr1 : ptreaty->plr0);
@@ -175,7 +176,7 @@ bool add_clause(struct Treaty *ptreaty, struct player *pfrom,
   }
 
   if (type == CLAUSE_EMBASSY && player_has_real_embassy(pto, pfrom)) {
-    /* we already have embassy */
+    /* We already have embassy */
     log_error("Illegal embassy clause: %s already have embassy with %s.",
               nation_rule_name(nation_of_player(pto)),
               nation_rule_name(nation_of_player(pfrom)));
@@ -186,12 +187,20 @@ bool add_clause(struct Treaty *ptreaty, struct player *pfrom,
     return FALSE;
   }
 
-  if (!are_reqs_active(&(const struct req_context) { .player = pfrom },
-                       pto, &clause_infos[type].giver_reqs, RPT_POSSIBLE)
-      || !are_reqs_active(&(const struct req_context) { .player = pto },
-                          pfrom, &clause_infos[type].receiver_reqs,
-                          RPT_POSSIBLE)) {
-    return FALSE;
+  /* Leave it to the server to decide if the other party can meet
+   * the requirements. */
+  if (client_player == NULL || client_player == pfrom) {
+    if (!are_reqs_active(&(const struct req_context) { .player = pfrom },
+                         pto, &clause_infos[type].giver_reqs, RPT_POSSIBLE)) {
+      return FALSE;
+    }
+  }
+  if (client_player == NULL || client_player == pto) {
+    if (!are_reqs_active(&(const struct req_context) { .player = pto },
+                         pfrom, &clause_infos[type].receiver_reqs,
+                         RPT_POSSIBLE)) {
+      return FALSE;
+    }
   }
 
   clause_list_iterate(ptreaty->clauses, old_clause) {
diff --git a/common/diptreaty.h b/common/diptreaty.h
index bc150f0eae..161f28778e 100644
--- a/common/diptreaty.h
+++ b/common/diptreaty.h
@@ -91,7 +91,8 @@ bool could_intel_with_player(const struct player *pplayer,
 void init_treaty(struct Treaty *ptreaty, 
                  struct player *plr0, struct player *plr1);
 bool add_clause(struct Treaty *ptreaty, struct player *pfrom, 
-                enum clause_type type, int val);
+                enum clause_type type, int val,
+                struct player *client_player);
 bool remove_clause(struct Treaty *ptreaty, struct player *pfrom, 
                    enum clause_type type, int val);
 void clear_treaty(struct Treaty *ptreaty);
diff --git a/server/diplhand.c b/server/diplhand.c
index 77c5ec5d98..6dc356f7c2 100644
--- a/server/diplhand.c
+++ b/server/diplhand.c
@@ -768,11 +768,12 @@ void handle_diplomacy_create_clause_req(struct player *pplayer,
 
   ptreaty = find_treaty(pplayer, pother);
 
-  if (ptreaty && add_clause(ptreaty, pgiver, type, value)) {
-    /* 
-     * If we are trading cities, then it is possible that the
-     * dest is unaware of it's existence.  We have 2 choices,
-     * forbid it, or lighten that area.  If we assume that
+  if (ptreaty != NULL
+      && add_clause(ptreaty, pgiver, type, value, NULL)) {
+    /*
+     * If we are trading cities, then it is possible that
+     * the dest is unaware of it's existence. We have 2 choices,
+     * forbid it, or lighten that area. If we assume that
      * the giver knows what they are doing, then 2. is the
      * most powerful option - I'll choose that for now.
      *                           - Kris Bubendorfer
diff --git a/server/savegame/savegame2.c b/server/savegame/savegame2.c
index 2c77c2d783..000b13d473 100644
--- a/server/savegame/savegame2.c
+++ b/server/savegame/savegame2.c
@@ -5436,7 +5436,7 @@ static void sg_load_treaties(struct loaddata *loading)
                                                "treaty%d.clause%d.value",
                                                tidx, cidx);
 
-            add_clause(ptreaty, pgiver, type, value);
+            add_clause(ptreaty, pgiver, type, value, NULL);
           }
         }
       }
diff --git a/server/savegame/savegame3.c b/server/savegame/savegame3.c
index a7f5f6f336..1bb1b71b3b 100644
--- a/server/savegame/savegame3.c
+++ b/server/savegame/savegame3.c
@@ -7804,7 +7804,7 @@ static void sg_load_treaties(struct loaddata *loading)
                                                "treaty%d.clause%d.value",
                                                tidx, cidx);
 
-            add_clause(ptreaty, pgiver, type, value);
+            add_clause(ptreaty, pgiver, type, value, NULL);
           }
         }
       }
-- 
2.43.0

