Skip to content

Commit dfa44de

Browse files
committed
[U|F] More Customizations & Compatibility Fixes
[U] Now client side can use WorldLink.toml to customize RelayUrl with custom port. Just incase if server side is using other relay port instead of 20101. If user not defining RelayUrl or comment it out, it will use the LobbyUrl link with the default port 20101. (Modification has been made to WorldLink.toml, check it out! I wrote some comment in there) [F] Fixed the issue where new clients could not join a room opened by an old client. This was caused by accidentally using different UserIDs types.
1 parent bf63e88 commit dfa44de

File tree

8 files changed

+85
-17
lines changed

8 files changed

+85
-17
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ WorldLink maimai DX Online C2C Multiplayer Mod
1515
2. Download [WorldLink.dll](https://github.com/MewoLab/worldlinkd/releases/latest/download/WorldLink.dll), put it in Mods
1616
3. Download [WorldLink.toml](https://github.com/MewoLab/worldlinkd/blob/main/mod/WorldLink.toml)
1717
4. Edit `WorldLink.toml` to select a lobby server
18+
- **LobbyUrl**: Required. Choose from `{asia, euro, usw, use, cn}.link.aquadx.net`
19+
- **RelayUrl**: Optional. Custom relay server URL (e.g., `"myrelay.example.com:20101"`). If not specified, uses relay info from lobby server
1820
5. Start the game
1921

2022
### On KanadeDX

mod/Compat.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
2-
31
using MelonLoader;
42
using WorldLink;
53

64
static class AquaMai
75
{
86
public static string ReadString(string key)
97
{
10-
return key == "Mods.WorldLink.LobbyUrl" ? Core.Config.LobbyUrl : null;
8+
return key switch
9+
{
10+
"Mods.WorldLink.LobbyUrl" => Core.Config.LobbyUrl,
11+
"Mods.WorldLink.RelayUrl" => Core.Config.RelayUrl,
12+
_ => null
13+
};
1114
}
1215
}
1316

mod/Core.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace WorldLink;
99
public class Config
1010
{
1111
public string LobbyUrl { get; set; }
12+
public string RelayUrl { get; set; }
1213
public bool Debug { get; set; }
1314
}
1415

mod/WorldLink.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
# WorldLink configuration file
32
#
43
# The Lobby URL can be one of {asia, euro, usw, use, cn}.link.aquadx.net
@@ -12,6 +11,12 @@
1211
# NOTE: If you're playing with your friend, make sure you both use the same Lobby URL.
1312
LobbyUrl="https://euro.link.aquadx.net"
1413

14+
# Optional: Custom relay server URL
15+
# If not specified or blank, the mod will use the relay server info from the lobby server
16+
# Format: "hostname:port" or "hostname" (defaults to port 20101)
17+
# Examples:
18+
# RelayUrl="relay.example.com:20101"
19+
1520
# Show debug messages
1621
Debug=false
1722

mod/WorldLink/FutariClient.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
public class FutariClient
1818
{
1919
public static string LOBBY_BASE => AquaMai.ReadString("Mods.WorldLink.LobbyUrl");
20+
public static string RELAY_BASE => AquaMai.ReadString("Mods.WorldLink.RelayUrl");
2021
// public const string LOBBY_BASE = "https://aquadx.net/aqua/mai2-futari";
2122
public static FutariClient Instance { get; private set; }
2223

@@ -165,6 +166,23 @@ private void HandleIncomingMessage(FutariMsg futariMsg)
165166

166167
switch (futariMsg.FutariCmd)
167168
{
169+
// Server registration response with version
170+
case FutariCmd.CTL_START:
171+
if (!string.IsNullOrEmpty(futariMsg.data))
172+
{
173+
Log.Info($"Server registration response: {futariMsg.data}");
174+
// Parse version if present (format: "version=X")
175+
if (futariMsg.data.StartsWith("version="))
176+
{
177+
var versionStr = futariMsg.data.Substring("version=".Length);
178+
if (int.TryParse(versionStr, out var version))
179+
{
180+
Log.Info($"Server protocol version: {version}");
181+
}
182+
}
183+
}
184+
break;
185+
168186
// Heartbeat
169187
case FutariCmd.CTL_HEARTBEAT:
170188
var delay = _heartbeat.ElapsedMilliseconds;

mod/WorldLink/FutariPatch.cs

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,31 @@ public static void OnBeforePatch()
6464

6565
// Send HTTP request to get the futari client address
6666
client = new FutariClient("A1234567890", "", 20101);
67-
$"{FutariClient.LOBBY_BASE}/info".GetAsync((sender, e) =>
67+
68+
// Check if RelayUrl is configured
69+
if (!string.IsNullOrEmpty(FutariClient.RELAY_BASE))
6870
{
69-
if (e.Error != null)
71+
// Use configured RelayUrl directly
72+
try
7073
{
71-
Log.Error($"Failed to get WorldLink server address: {e.Error}");
72-
return;
74+
var relayUri = new Uri(FutariClient.RELAY_BASE);
75+
client.host = relayUri.Host;
76+
client.port = relayUri.Port != -1 ? relayUri.Port : 20101; // Default to 20101 if no port specified
77+
Log.Info($"Using configured relay server: {client.host}:{client.port}");
7378
}
74-
// Response Format: {"relayHost": "google.com", "relayPort": 20101}
75-
var info = JsonUtility.FromJson<ServerInfo>(e.Result);
76-
client.host = info.relayHost;
77-
client.port = info.relayPort;
78-
Log.Info($"WorldLink server address: {info.relayHost}:{info.relayPort}");
79-
});
79+
catch (Exception ex)
80+
{
81+
Log.Error($"Invalid RelayUrl format: {FutariClient.RELAY_BASE}. Error: {ex.Message}");
82+
Log.Info("Falling back to lobby server relay info");
83+
// Fall back to lobby server method
84+
GetRelayInfoFromLobby();
85+
}
86+
}
87+
else
88+
{
89+
// Fall back to getting relay info from lobby server
90+
GetRelayInfoFromLobby();
91+
}
8092
}
8193

8294
// Entrypoint
@@ -855,4 +867,22 @@ public static bool RecvClientState(Packet packet)
855867
#endif
856868

857869
#endregion
870+
871+
// Helper method to get relay info from lobby server
872+
private static void GetRelayInfoFromLobby()
873+
{
874+
$"{FutariClient.LOBBY_BASE}/info".GetAsync((sender, e) =>
875+
{
876+
if (e.Error != null)
877+
{
878+
Log.Error($"Failed to get WorldLink server address: {e.Error}");
879+
return;
880+
}
881+
// Response Format: {"relayHost": "google.com", "relayPort": 20101}
882+
var info = JsonUtility.FromJson<ServerInfo>(e.Result);
883+
client.host = info.relayHost;
884+
client.port = info.relayPort;
885+
Log.Info($"WorldLink server address: {info.relayHost}:{info.relayPort}");
886+
});
887+
}
858888
}

src/main/kotlin/Application.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ fun main(args: Array<String>) {
1616
val relayPort = parsePort(args, "--relay-port", "RELAY_PORT", 20101)
1717

1818
println("=== WorldLink Server Configuration ===")
19-
println("Lobby Port (HTTP API): $lobbyPort")
20-
println("Relay Port (Game Communication): $relayPort")
19+
println("Lobby Port: $lobbyPort")
20+
println("Relay Port: $relayPort")
2121
println("=====================================")
2222

2323
embeddedServer(Netty, port = lobbyPort, module = Application::module).start()

src/main/kotlin/FutariLobby.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,16 @@ fun Application.configureRouting() = routing {
5858
recruits[d.ip] = d
5959

6060
if (!exists) log(d, "StartRecruit")
61-
d.RecruitInfo.MechaInfo.UserIDs = d.RecruitInfo.MechaInfo.UserIDs.map { it.str.hashToUInt().toLong() }
61+
62+
// Backward compatibility: only hash UserIDs if they are strings (old clients)
63+
// New clients already send hashed long values
64+
d.RecruitInfo.MechaInfo.UserIDs = d.RecruitInfo.MechaInfo.UserIDs.map { userId ->
65+
when (userId) {
66+
is String -> userId.hashToUInt().toLong()
67+
is Long -> userId
68+
else -> userId.toString().hashToUInt().toLong()
69+
}
70+
}
6271
}
6372

6473
post("/recruit/finish") {

0 commit comments

Comments
 (0)