From 97d52be27ad0cc4f9ef6eeb1097e19c816d9e05e Mon Sep 17 00:00:00 2001
From: Darryl Pogue <darryl@dpogue.ca>
Date: Sun, 11 Aug 2024 11:22:06 -0700
Subject: [PATCH 1/2] Optional backwards compatibility with older clients

Co-Authored-By: dgelessus <dgelessus@users.noreply.github.com>
---
 AuthServ/AuthServer.cpp | 23 +++++++++++++++++++++++
 CMakeLists.txt          |  3 +++
 Dockerfile              |  5 +++--
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/AuthServ/AuthServer.cpp b/AuthServ/AuthServer.cpp
index f81ccce..8a063b8 100755
--- a/AuthServ/AuthServer.cpp
+++ b/AuthServ/AuthServer.cpp
@@ -93,10 +93,33 @@ void auth_init(AuthServer_Private& client)
     /* BCast Shard Capabilities */
     START_REPLY(e_AuthToCli_ServerCaps);
     uint32_t bufSzPos = client.m_buffer.tell();
+#ifdef DS_OU_COMPATIBLE
+    // OpenUru parses this as the start of a FileDownloadChunk message,
+    // which will be ignored,
+    // because no file download transaction is active.
+    client.m_buffer.write<uint32_t>(37);
+
+    // H'uru sees: 0x25 bytes of data, bit vector is 1 dword long, value is [caps]
+    // OpenUru sees: message type 0x25 (FileDownloadChunk), transaction ID 0x10000, error code 0x[caps]0000, file size 0x0000[caps] (continued below)
+    caps.write(&client.m_buffer);
+
+    // Ensure the caps haven't changed size and broken this compat hack
+    uint32_t newBufPos = client.m_buffer.tell();
+    DS_ASSERT(newBufPos - bufSzPos == 3 * sizeof(uint32_t));
+
+    // ServerCaps message extra data, which is ignored by H'uru,
+    // because the bit vector doesn't have this many dwords.
+    // OpenUru parses this as the rest of FileDownloadChunk message:
+    client.m_buffer.write<uint16_t>(0); // file size 0x0000[caps] (continued)
+    client.m_buffer.write<uint32_t>(0); // chunk offset 0
+    client.m_buffer.write<uint32_t>(19); // chunk size 19
+    client.m_buffer.writeBytes("[ServerCaps compat]", 19); // 19 bytes of chunk data
+#else
     client.m_buffer.write<uint32_t>(0);
     caps.write(&client.m_buffer);
     client.m_buffer.seek(bufSzPos, 0);
     client.m_buffer.write<uint32_t>(client.m_buffer.size() - bufSzPos - sizeof(uint32_t));
+#endif
     SEND_REPLY();
 }
 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5455b3a..7a9aa2b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -33,6 +33,8 @@ set(DS_HOOD_INST_NAME       "Neighborhood"
 set(DS_HOOD_POP_THRESHOLD   "20"
     CACHE STRING "Default Neighborhood Max Population")
 
+option(DS_OU_COMPATIBLE "Enable backwards compatibility with older game clients" OFF)
+
 add_compile_options(-Wall -Wextra -Wno-unused-parameter)
 
 list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_SOURCE_DIR}/cmake")
@@ -133,6 +135,7 @@ add_library(dirtsand STATIC ${dirtsand_SOURCES} ${SDL_SOURCES} ${PlasMOUL_SOURCE
 
 target_compile_definitions(dirtsand PRIVATE
     $<$<CONFIG:Debug>:DEBUG>
+    $<$<BOOL:${DS_OU_COMPATIBLE}>:DS_OU_COMPATIBLE>
     PRODUCT_BRANCH_ID=${PRODUCT_BRANCH_ID}
     PRODUCT_BUILD_ID=${PRODUCT_BUILD_ID}
     PRODUCT_BUILD_TYPE=${PRODUCT_BUILD_TYPE}
diff --git a/Dockerfile b/Dockerfile
index e362f29..26f866f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -52,6 +52,7 @@ ARG PRODUCT_UUID=ea489821-6c35-4bd0-9dae-bb17c585e680
 ARG DS_HOOD_USER_NAME=DS
 ARG DS_HOOD_INST_NAME=Neighborhood
 ARG DS_HOOD_POP_THRESHOLD=20
+ARG DS_OU_COMPATIBLE=ON
 
 RUN \
     mkdir -p /opt/dirtsand/db && cp dirtsand/db/*.sql /opt/dirtsand/db && \
@@ -59,8 +60,8 @@ RUN \
         -DPRODUCT_BRANCH_ID=${PRODUCT_BRANCH_ID} -DPRODUCT_BUILD_ID=${PRODUCT_BUILD_ID} \
         -DPRODUCT_BUILD_TYPE=${PRODUCT_BUILD_TYPE} -DPRODUCT_UUID=${PRODUCT_UUID} \
         -DDS_HOOD_USER_NAME=${DS_HOOD_USER_NAME} -DDS_HOOD_INST_NAME=${DS_HOOD_INST_NAME} \
-        -DDS_HOOD_POP_THRESHOLD=${DS_HOOD_POP_THRESHOLD} -DENABLE_TESTS=OFF \
-        -B dirtsand/build -S dirtsand && \
+        -DDS_HOOD_POP_THRESHOLD=${DS_HOOD_POP_THRESHOLD} -DDS_OU_COMPATIBLE=${DS_OU_COMPATIBLE} \
+        -DENABLE_TESTS=OFF -B dirtsand/build -S dirtsand && \
     cmake --build dirtsand/build --parallel && cmake --build dirtsand/build --target install && \
     mkdir -p /opt/dirtsand/etc && \
     \

From b31892d30d3881d2ad4160abc0efe67b060434ca Mon Sep 17 00:00:00 2001
From: Darryl Pogue <darryl@dpogue.ca>
Date: Sun, 11 Aug 2024 11:50:59 -0700
Subject: [PATCH 2/2] Include Server.Auth.Host in docker server.ini

The older client seems to want this for reasons that I don't fully care
to investigate at the moment. It should be grabbing it from the
GateKeeper, shouldn't it?
---
 bin/docker-entrypoint.sh | 1 +
 1 file changed, 1 insertion(+)

diff --git a/bin/docker-entrypoint.sh b/bin/docker-entrypoint.sh
index 3449ed8..6925842 100644
--- a/bin/docker-entrypoint.sh
+++ b/bin/docker-entrypoint.sh
@@ -145,6 +145,7 @@ Server.Status "${SHARD_STATUS_URL:-http://${DS_HOST:-127.0.0.1}:8080/welcome}"
 
 # Shard front-end server address.
 Server.Gate.Host "${DS_HOST:-127.0.0.1}"
+Server.Auth.Host "${DS_HOST:-127.0.0.1}"
 Server.Port ${SHARD_PORT:-14617}
 
 # Shard name - NOTE: this is currently not visible anywhere.