Hi everyone!
I've been messing around with the 1.69 bins for a couple of weeks now, and I just want to share some of the changes that need to be done to server files to be able to use them. I haven't identified all of them, but these at least let you do the basics without crashing: character selection, boat creation, departure and battle completion. My focus here is updating the server messages to match what the client expects, I'm not interested in content changes right now.
I'm using a pristine version of EU 1.69 client, directly from installation. The only extra thing you need to do is override its heroes.db3 file as usual, use your preferred method for that (like winnsi.dll).
Ok, just to introduce the basics for anyone that needs it, everything happens in ServiceCore.dll. There's a bunch of message classes in the namespace ServiceCore.EndPointNetwork. These messages are serialized and sent to the client along with a 'CategoryID' that lets the client identify each message type. The client crashes when the packet size is shorter than expected, meaning that the message class is missing some fields. So what we do is add these missing fields.
You can use
Character Selection
To fix the crash that happens here you need to update ServiceCore.CharacterServiceOperations.CharacterSummary, it's used as part of CharacterListMessage. It needs a new Int32 right at the end:
You can initialize it in the constructor:
The name doesn't matter really but I call it that because the client seems to associate it with the string 'GameUI_Heroes_Pvp_TournamentTitle'. I don't know its purpose but 0 is a safe value.
Boat Creation
The issue lies in ServiceCore.EndPointNetwork.GameJoinMemberInfo, sent as part of LaunchShipGrantedMessage. Again a new field is required right at the end, but a long this time:
I haven't investigated its purpose yet, so a generic name for now. 0 is a safe value as well.
Boat Departure
Departure fails because of ServiceCore.EndPointNetwork.GameStartGrantedMessage. A new integer is required at the end:
I haven't investigated its purpose either. 0 is a safe value as well.
Battle Completion
I've found that the games crashes when completing a battle as well. We need to update ServiceCore.EndPointNetwork.QuestSummaryInfo. It's sent as part of FinishGameMessage. This time there's much more:
Their position is important! A new list after EtcAp and 3 new objects after RewardItem. Again, I haven't investigated their use but assigning empty values for them in the constructor works:
That's it! I'm still investigating the assembly but a lot can be inferred from there. I'll make sure to share whatever else I find in the future.
I've been messing around with the 1.69 bins for a couple of weeks now, and I just want to share some of the changes that need to be done to server files to be able to use them. I haven't identified all of them, but these at least let you do the basics without crashing: character selection, boat creation, departure and battle completion. My focus here is updating the server messages to match what the client expects, I'm not interested in content changes right now.
I'm using a pristine version of EU 1.69 client, directly from installation. The only extra thing you need to do is override its heroes.db3 file as usual, use your preferred method for that (like winnsi.dll).
Ok, just to introduce the basics for anyone that needs it, everything happens in ServiceCore.dll. There's a bunch of message classes in the namespace ServiceCore.EndPointNetwork. These messages are serialized and sent to the client along with a 'CategoryID' that lets the client identify each message type. The client crashes when the packet size is shorter than expected, meaning that the message class is missing some fields. So what we do is add these missing fields.
You can use
You must be registered to see links
as a starting point, or modify it directly (I recommend dnSpy for that purpose), your choice.Character Selection
To fix the crash that happens here you need to update ServiceCore.CharacterServiceOperations.CharacterSummary, it's used as part of CharacterListMessage. It needs a new Int32 right at the end:
Code:
...
public int ArenaSuccessiveWinCount { get; set; }
public int TournamentTitle { get; set; } // <- new field
You can initialize it in the constructor:
Code:
...
this.TournamentTitle = 0;
The name doesn't matter really but I call it that because the client seems to associate it with the string 'GameUI_Heroes_Pvp_TournamentTitle'. I don't know its purpose but 0 is a safe value.
Boat Creation
The issue lies in ServiceCore.EndPointNetwork.GameJoinMemberInfo, sent as part of LaunchShipGrantedMessage. Again a new field is required right at the end, but a long this time:
Code:
...
public bool IsAlive{ get; set; }
public long Reserved0 { get; set; } // <- new field
I haven't investigated its purpose yet, so a generic name for now. 0 is a safe value as well.
Code:
public GameJoinMemberInfo()
{
this.Reserved0 = 0;
}
Boat Departure
Departure fails because of ServiceCore.EndPointNetwork.GameStartGrantedMessage. A new integer is required at the end:
Code:
...
public bool IsUserDedicated{ get; set; }
public int Reserved0 { get; set; } // <- new field
I haven't investigated its purpose either. 0 is a safe value as well.
Code:
public GameStartGrantedMessage()
{
this.Reserved0 = 0;
}
Battle Completion
I've found that the games crashes when completing a battle as well. We need to update ServiceCore.EndPointNetwork.QuestSummaryInfo. It's sent as part of FinishGameMessage. This time there's much more:
Code:
...
public List<SummaryRewardInfo> EtcAp { get; set; }
public List<SummaryRewardInfo> Reserved0 { get; set; } // <- new field
...
public Dictionary<string, int> RewardItem { get; set; }
public SummaryRewardInfo Reserved1 { get; set; } // <- new field
public SummaryRewardInfo Reserved2 { get; set; } // <- new field
public SummaryRewardInfo Reserved3 { get; set; } // <- new field
Their position is important! A new list after EtcAp and 3 new objects after RewardItem. Again, I haven't investigated their use but assigning empty values for them in the constructor works:
Code:
this.Reserved0 = new List<SummaryRewardInfo>();
this.Reserved1 = null;
this.Reserved2 = null;
this.Reserved3 = null;
That's it! I'm still investigating the assembly but a lot can be inferred from there. I'll make sure to share whatever else I find in the future.
Last edited: