- Katılım
- 6 Mayıs 2022
- Konular
- 22,878
- Mesajlar
- 23,172
- Tepkime puanı
- 21
- Sro Yaşı
- 3 yıl 9 ay 15 gün
- Trophy Puan
- 38
- Sro Gold
- 234,179
As was first posted about in this thread from 2012,
First, to re-explain the problem. After a party match entry has existed for 1 hour, ShardManager will send GameServer 0x386f on behalf of the party leader, and then removes the party match entry. GameServer does not have a packet handler for 0x386f though, and since it thinks the client sent it an unknown opcode, it will disconnect the player, despite the fact it was ShardManager who sent the packet.
So far, two fixes have been presented. Change the 0x386f opcode (or block it in a server sided module proxy) or skip the 60m timeout check. The problem with changing/blocking the opcode is that the party entry removal logic still runs in ShardManager, so the party leader has to relog (or possibly teleport I've read) to be able to reform the party. If you skip the 60m timeout check, you now have party entries that will linger about until they are cancelled or the user logs out (presumably, I've not verified if they do or don't leak).
My fix will use some assembly edits to implement new logic that will result in the desired behavior of having party matching entries expire after the timeout. Before I get into the solution itself, first I'll talk about how I arrived at the solution and how I've verified that it results in the correct, expected behavior with thus far no side effects.
First, let's look at the packet flow for when a user forms a party:
<a class="spoiler-button" href="
Then, let's look at the packet flow for when the user deletes their party entry:
<a class="spoiler-button" href="
From this, I learned that AgentServer passes the client's party delete request (0x706B) to GameServer. The first 4 bytes are the party id, and the last 4 bytes are the account JID. If you "SELECT * FROM [VSRO_ACCOUNT].[dbo].[TB_User] where JID = 0xB185A", you'll get the row for the account I was using, which was t048 (which I also have labeled on the Client->Agent connection).
Right now, ShardManager is telling GameSever the client has sent an empty packet, 0x386f (remember the 4 bytes in 0x386f are the JID, so the servers know who is sending the data). Instead, we want to simulate this packet:
Code: <pre class="alt2 prettyprint" dir="ltr" style=" margin: 0px; padding: 6px; border: 1px inset; width: 640px; height: 50px; text-align: left; overflow: auto">[6160][9:22:52 PM][Agent->GameA][C->S][706B][8 bytes] 0000000000 12 00 00 00 5A 18 0B 00 ....Z...........</pre> Lucky for us, with how the SRO server architecture works, ShardManager is already sending GameServer a packet on the client's behalf (0x386f). What if instead we send a 0x706B packet to GameServer? To make this work, we'd also have to write the party id first, and then let the normal 0x386f packet building logic run (which writes the JID of the party leader).
Then, we'd need to stop the ShardManager from removing the party entry itself, because that's the second main problem that needs to be solved. If we were to do that, then when the party match timeout happens, we're pretending the client has cancelled the request, so the system correctly removes the party entry as if a user initiated the action, and then they'd be able to form a new party as if nothing happened.
This is what my fix does. I use a codecave to a new section added to the server, change the packet opcode, write the party id (the party entry object is stored in EBX), and then jump back to the packet building so the JID gets written. Then, I NOP the party entry removal code so everything stays in sync, and the party match timeout feature works as expected because the system thinks the user initiated the cancel, even though it was the server.
The end result is that everything seems to work as you'd expect. To verify this works without side effects, and why I'm confident it's the correct solution, I just look at the resulting packets of the process, and make sure they matched the manual action's result, which they do. In addition, I make sure I can form a new party and another character verifies there's nothing unexpected going on, which there wasn't.
I made a small video showing everything mentioned above. It's a bit boring because I wait through 2 party match refresh packets, but I cover all the main cases in showing that the fix should work. It's only a few minutes long though, so hopefully it's not too painful. I wanted to show the entire process though, so that's why I don't cut out the time. Towards the end I have some comments in the client about the asm itself. I also did testing with multiple clients at once and joining the party and everything works as it should.
Demo Video:
<td class="panelsurround" align="center"><iframe id="ytplayer" type="text/html" width="100%" height="390" src="
" frameborder="0" allowfullscreen="allowfullscreen"></iframe>[/TD]
Guide:
A lot of people seem to use and reference Stud_PE, but I myself use CFF Explorer (free edition). Likewise, I'll be using x32dbg and not Ollydbg. This guide will use CFF Explorer, but you can perform similar steps however you want, or opt to implement the solution in an injected dll, etc... The purpose of this guide is to just show how to solve the problem, it's up to users to pick which implementation of the solution works best for them.
Due to the unfortunate false positives with old server files, no edited binaries will be posted. This guide can be used on already modified ShardManagers, so it'll just take a little work to have the fix applied to non-vanilla files. As always, be sure to keep backups in case anything goes wrong with the edits!
1. Open your ShardManager in CFF Explorer.
2. Click on the "Section Headers" treeview entry, right click in the empty grey space in the section header table view, and then choose "Add Section (Empty Space)"
3. Enter a size of 1000 and hit OK. This makes the size 0x1000 bytes, which should be more than enough for lots of patches, but section sizes are generally good to have in multiples of 0x1000.
4. Double click in the "Name" field of the new entry and type in a new, tiny name that begins with a period. Naming the section is good practice to make it easier to refer to when you have more edits, but you only have a limited amount of characters for section names (8 total characters).
[NEW] 4b. Right click the "Characteristics" field of the newly named section. Choose the "Change Section Flags"
[NEW] 4c. Click the checkboxes for the "Is executable" and "Contains code" options. Click OK to save the changes. This will solve a problem that might arise around Step 12 where the section to jmp to is not marked as executable. However, I'm unsure the conditions for which this happens, since it didn't happen for me, but happened for another user.
5. Click on the Save icon. Choose NOT to overwrite your original file and give it a new name. We will now edit our exe in x32dbg.
6. Open your new ShardManager in x32dbg and click on the "Memory Map" icon in the top bar.
7. Select the section you added for this fix, and right click and choose "Follow in Disassembler"
8. Now pay close attention, because you can't just mindlessly copy and paste and not read the directions. The initial patch bytes are as follows:
Code: <pre class="alt2 prettyprint" dir="ltr" style=" margin: 0px; padding: 6px; border: 1px inset; width: 640px; height: 34px; text-align: left; overflow: auto">66 C7 00 6B 70 8D 54 24 1C 8B 0B 89 4C 24 1C 52 B8 04 00 00 00 8B CE E8 00 00 00 00 E9 00 00 00 00</pre> It's 0x21 bytes, so copy them to your clipboard, highlight a bunch of bytes in your section, then right click the highlighted bytes, and choose "Binary Paste"
9. Now highlight the call instruction and press spacebar to assemble. Change the text to "call 0x402DF0" and click OK. NOTE: Your final bytes will not match mine, because your section will most likely be in a different address than mine is.
10. The assemble box will now move to the jmp instruction, so you don't have to highlight it and press spacebar again (but you can if you accidently closed the assemble window). Change the text to "jmp 0x4505DE" and click OK. Close the assemble window since we don't need it here anymore. NOTE: Your final bytes will not match mine, because your section will most likely be in a different address than mine is.
11. Highlight the first instruction in this code section. Right click it and choose "Label -> Label Current Address". I typed in the name "ptfix", but you can use whatever, just remember what you wrote.
We've now completed adding in the custom logic for the fix. We now have a few more patches to go to make it use this logic and to fix the issue of stopping the shard manager from deleting the party match entry.
12. Press "ctrl + g" to go to an address. Paste in 0x4505D9 and press OK. Now press spacebar to bring up the assemble window again. Change the instruction to "jmp ptfix" (or use whatever name you wrote in step 11). Make sure the "Keep Size" option is selected and press OK and close the assemble window. While the size should be the exact same, when editing client code you want to be mindful of not accidently making changes that overwrite other instructions unexpectedly! NOTE: Your final bytes will not match mine, because your section will most likely be in a different address than mine is.
13. Press "ctrl + g" to go to an address. Paste in 0x450619 and press OK. Select this address through the jne at 0x45062A. Right click the selection and choose "Binary -> Fill with NOPs"
14. In the new window that pops up, just press OK, since we selected the right amount of bytes to fill already.
15. Now it's time to save our changes. Click "File -> Patch file..." to bring up the patches window. Click on the "Patch File" button, and make a new name for the final ShardManager and click Save (as you can't overwrite the current file while it's in use in x32dbg!)
16. Now before you close this x32dbg instance, go ahead and open your new final ShardManager in a new x32dbg instance and verify you made all the changes correctly. This is so if you missed something by accident, you don't have to repeat the entire process, and can just re-save once you correct any mistakes.
Congratulations! You should now have a modified ShardManager that does not have the 1-hour DC. In order to test and verify the patch was made without issues, assuming you don't want to waste an hour for it to trigger, you can perform the following edit:
[OPTIONAL] 17. Press "ctrl + g" and go to address 0x45055F. Right click the line and choose "Binary -> Fill with NOPs" and then press OK. Repeat step 15, but make sure to give this ShardManager a different name, as you'll want to test once with the instant timeout version, and then switch back to the normal one after confirming the patch works as expected.
As another tip, as it's been mentioned in another thread, but I'll mention it again here for completeness, you can edit the 0x3C in line 0x45055C to change from a 60m timeout so some other value, which will be limited to 0xFF max (255m) due to the instruction size limitation.
Once you've verified everything, you should be good to go, so you can close your x32dbg instances and CFF Explorer if it's still open. As I mentioned earlier, I don't believe there will be any side effects based on my testing and observations, and the fix is easily verified as being working because the client is notified of the party being removed without being DCed correctly now.
That completes this guide, if I've missed anything or if something isn't clear, please let me know and I'll get it sorted out. I do re-read my threads and try to make sure I don't make any big mistakes, but things can slip by since I'll read what's in my mind and not always what I wrote, so it's no problem fixing anything wrong.
Happy coding!
[Edit 1] Thanks to @
[Guide] Fixing the party matching 1-hour DC bug (0x386f)
Silkroad Online özel sunucularında (pserver) çalışan geliştiriciler ve oyun yöneticileri bazen nadir ama oldukça sinir bozucu hatalarla karşılaşabilir. Bunlardan birisi de party matching 1-hour DC bug olarak bilinen ve 0x386f hatasıyla tanımlanan bağlantı kopma sorunudur. Bu hata, oyuncuların bir grup eşleştirme (party matching) işlemi sırasında 1 saat civarında otomatik olarak oyundan atılması durumunu içerir. Bu durum hem oyuncu deneyimini düşürür hem de sunucu sadakat oranlarını olumsuz etkileyebilir.
Sorunun Kaynağı Nedir?
Party matching sistemi, Silkroad Online'da oyuncuların belirli seviye aralıklarında gruplanarak birlikte macera yaşamalarını sağlar. Ancak bazı özel sunucu yapılandırmalarında, eşleştirme sırasında sistemsel bir zamanlayıcı hatası oluşabilir. Bu hata genellikle agent server veya shard yapılandırmasında eksikliklerden kaynaklanır. 0x386f hatası, istemci ile sunucu arasında beklenmedik bir zaman aşımı meydana geldiğinde ortaya çıkar. Özellikle uzun süreli oyun oturumlarında veya grup eşleştirme sürecinde bu durum daha sık görülebilir.
Hatanın Tanımlanması
Oyuncular bu hatayı genellikle aşağıdaki belirtilerle fark ederler:
- Grup eşleştirme sırasında oyunun beklenmedik şekilde kapanması
- Oyuna tekrar bağlandığında eski grubun dağılmış olması
- Her 1 saat civarında oturumun sonlandırılması
Sunucu loglarında ise genellikle 0x386f koduyla birlikte bağlantı zaman aşımı (timeout) mesajları yer alır. Bu durum, gateway server veya game server loglarında da takip edilebilir.
Çözüm Adımları
Bu hatayı çözmek için aşağıdaki adımları izleyerek sunucu yapılandırmanızı güncelleyebilirsiniz:
1. Agent Server Ayarlarını Kontrol Et
Agent server, oyuncu isteklerini yönlendiren ve eşleştirme işlemlerini başlatan temel bileşendir. Config dosyalarında yer alan timeout ayarlarının doğru yapılandırıldığından emin olun. Önerilen değerler:
- MatchingTimeout = 3600 (1 saat)
- ConnectionTimeout = 7200 (2 saat)
2. Gateway Sunucusunda Oturum Süresi Ayarı
Gateway sunucusu, kullanıcıların oyun sunucusuna bağlanmasını sağlar. Burada session timeout değeri, 1 saatten fazla oturum süresi için yeterli olmalıdır. Bu değeri artırmak, 0x386f hatasının önlenmesine yardımcı olabilir.
3. Shard ve Game Server Ayarları
Shard sunucularında, grup eşleştirme sırasında aktif olan kullanıcılar için özel zamanlayıcılar tanımlanabilir. PartyMatchTimer veya benzeri isimli değişkenlerin doğru yapılandırıldığından emin olun. Yanlış zamanlayıcı değerleri, 1 saatlik oturum sonlandırmasına neden olabilir.
4. Client-side Ayarlar
Bazı özel sunucularda, SRO_Client tarafında da zamanlayıcı ayarları yapılabilmektedir. Özellikle media.pk2 veya data.pk2 dosyalarında bulunan zamanlayıcı parametrelerinin, sunucu tarafıyla uyumlu olduğundan emin olun.
5. Güvenlik ve Filtreleme Sistemleri
Sunucuda çalışan Silkroad Guard, MaxiGuard, KGuard gibi sistemler, uzun süreli oturumlarda hatalı bağlantı kesmeleri yapabilir. Bu sistemlerin yapılandırmasında, grup eşleştirme sırasında zaman aşımı limitlerinin artırılması önerilir.
Sonuç
Party matching 1-hour DC bug (0x386f) gibi hatalar, kullanıcı memnuniyetini doğrudan etkiler. Bu tür sistemsel hataların çözümü için sunucu tarafında dikkatli konfigürasyon gerekir. Sunucu yapılandırmasında yapılan küçük değişiklikler, kullanıcı deneyimini ciddi anlamda iyileştirebilir. Geliştiricilerin bu tür sorunlara karşı dikkatli olması ve düzenli log takibi yapması büyük önem taşır.
[Guide] Fixing the party matching 1-hour DC bug (0x386f)
Developers and administrators running Silkroad Online private servers may sometimes encounter rare but highly frustrating bugs. One such issue is the party matching 1-hour DC bug, identified by the error code 0x386f. This bug involves players being automatically disconnected from the game around the 1-hour mark during a party matching process. This situation not only diminishes player experience but also negatively affects server retention rates.
What Causes the Issue?
The party matching system allows players in Silkroad Online to group up based on certain level ranges for cooperative gameplay. However, in some private server configurations, a systemic timer error can occur during the matching process. This error is usually caused by misconfigurations in agent server or shard settings. The 0x386f error appears when an unexpected timeout occurs between the client and the server. It tends to occur more frequently during long gaming sessions or while in the party matching process.
Identifying the Error
Players often notice this error through the following symptoms:
- Unexpected disconnection during party matching
- Old party no longer exists upon reconnecting
- Session termination every approximately 1 hour
In server logs, 0x386f codes are typically accompanied by timeout messages. These can be traced in gateway server or game server logs as well.
Resolution Steps
To fix this error, you can update your server configuration by following these steps:
1. Check Agent Server Settings
The agent server is responsible for forwarding player requests and initiating matching processes. Ensure that timeout values in config files are properly set. Recommended values:
- MatchingTimeout = 3600 (1 hour)
- ConnectionTimeout = 7200 (2 hours)
2. Adjust Session Timeouts in Gateway Server
The gateway server handles user connections to the game server. Here, the session timeout value should be sufficient for sessions lasting longer than 1 hour. Increasing this value may help prevent the 0x386f error.
3. Shard and Game Server Configurations
On shard servers, custom timers can be defined for active users during party matching. Ensure variables named PartyMatchTimer or similar are correctly configured. Incorrect timer values may cause session terminations every hour.
4. Client-Side Settings
In some private servers, timer settings can also be adjusted on the SRO_Client side. Make sure that timer parameters found in files like media.pk2 or data.pk2 are compatible with the server-side configuration.
5. Security and Filtering Systems
Systems like Silkroad Guard, MaxiGuard, or KGuard may incorrectly terminate long-running sessions. It's recommended to increase timeout limits in these systems' configurations during party matching operations.
Conclusion
Issues like the Party Matching 1-Hour DC Bug (0x386f) directly affect user satisfaction. Resolving such system-level errors requires careful server configuration. Small adjustments in server settings can significantly improve the user experience. It is critical for developers to remain vigilant against such issues and maintain regular log monitoring.
Ziyaretçiler için gizlenmiş link,görmek için üye olmalısınız!
Giriş yap veya üye ol.
, it's been well known there's a 1-hour party leader DC bug with VSRO 188. Since then, there's been a few other posts with fixes that pretty much work, but don't really solve the underlying problem of not having party match entries deleted after 1 hour. I took a look into this problem tonight, and came up with what I'm confident is a correct fix to be able to have party match entries deleted after 1 hour (or however long if you want to modify the time check from 60 minutes).First, to re-explain the problem. After a party match entry has existed for 1 hour, ShardManager will send GameServer 0x386f on behalf of the party leader, and then removes the party match entry. GameServer does not have a packet handler for 0x386f though, and since it thinks the client sent it an unknown opcode, it will disconnect the player, despite the fact it was ShardManager who sent the packet.
So far, two fixes have been presented. Change the 0x386f opcode (or block it in a server sided module proxy) or skip the 60m timeout check. The problem with changing/blocking the opcode is that the party entry removal logic still runs in ShardManager, so the party leader has to relog (or possibly teleport I've read) to be able to reform the party. If you skip the 60m timeout check, you now have party entries that will linger about until they are cancelled or the user logs out (presumably, I've not verified if they do or don't leak).
My fix will use some assembly edits to implement new logic that will result in the desired behavior of having party matching entries expire after the timeout. Before I get into the solution itself, first I'll talk about how I arrived at the solution and how I've verified that it results in the correct, expected behavior with thus far no side effects.
First, let's look at the packet flow for when a user forms a party:
<a class="spoiler-button" href="
Ziyaretçiler için gizlenmiş link,görmek için üye olmalısınız!
Giriş yap veya üye ol.
" rel="nofollow" onclick="return toggleSpoiler.call(this);"> Spoiler </a> Code: <pre class="alt2 prettyprint" dir="ltr" style=" margin: 0px; padding: 6px; border: 1px inset; width: 640px; height: 498px; text-align: left; overflow: auto">[t048][6117][9:22:50 PM][Client->Agent][C->S][7069][47 bytes] 0000000000 00 00 00 00 00 00 00 00 05 00 01 6E 21 00 46 6F ...........n!.Fo 0000000000 72 20 6F 70 65 6E 20 68 75 6E 74 69 6E 67 20 6F r open hunting o 0000000000 6E 20 74 68 65 20 53 69 6C 6B 72 6F 61 64 21 n the Silkroad!. [6118][9:22:50 PM][Agent->GameA][C->S][7069][51 bytes] 0000000000 00 00 00 00 00 00 00 00 05 00 01 6E 21 00 46 6F ...........n!.Fo 0000000000 72 20 6F 70 65 6E 20 68 75 6E 74 69 6E 67 20 6F r open hunting o 0000000000 6E 20 74 68 65 20 53 69 6C 6B 72 6F 61 64 21 5A n the Silkroad!Z 0000000000 18 0B 00 ................ [6119][9:22:50 PM][GameA->Shard][C->S][7866][58 bytes] 0000000000 0A 91 AB 01 00 5A 18 0B 00 00 00 00 00 00 00 00 ..«..Z.......... 0000000000 00 05 00 01 6E 21 00 46 6F 72 20 6F 70 65 6E 20 ....n!.For open 0000000000 68 75 6E 74 69 6E 67 20 6F 6E 20 74 68 65 20 53 hunting on the S 0000000000 69 6C 6B 72 6F 61 64 21 00 00 ilkroad!........ [6121][9:22:50 PM][Shard->GameA][S->C][B866][9 bytes] 0000000000 91 AB 01 00 01 12 00 00 00 .«.............. [6122][9:22:50 PM][GameA->Agent][S->C][B069][48 bytes][1-Broadcast][5] 0000000000 01 12 00 00 00 00 00 00 00 05 00 01 6E 21 00 46 ............n!.F 0000000000 6F 72 20 6F 70 65 6E 20 68 75 6E 74 69 6E 67 20 or open hunting 0000000000 6F 6E 20 74 68 65 20 53 69 6C 6B 72 6F 61 64 21 on the Silkroad! [t048][6123][9:22:50 PM][Agent->Client][S->C][B069][48 bytes] 0000000000 01 12 00 00 00 00 00 00 00 05 00 01 6E 21 00 46 ............n!.F 0000000000 6F 72 20 6F 70 65 6E 20 68 75 6E 74 69 6E 67 20 or open hunting 0000000000 6F 6E 20 74 68 65 20 53 69 6C 6B 72 6F 61 64 21 on the Silkroad!</pre> Then, let's look at the packet flow for when the user deletes their party entry:
<a class="spoiler-button" href="
Ziyaretçiler için gizlenmiş link,görmek için üye olmalısınız!
Giriş yap veya üye ol.
" rel="nofollow" onclick="return toggleSpoiler.call(this);"> Spoiler </a> Code: <pre class="alt2 prettyprint" dir="ltr" style=" margin: 0px; padding: 6px; border: 1px inset; width: 640px; height: 370px; text-align: left; overflow: auto">[t048][6159][9:22:52 PM][Client->Agent][C->S][706B][4 bytes] 0000000000 12 00 00 00 ................ [6160][9:22:52 PM][Agent->GameA][C->S][706B][8 bytes] 0000000000 12 00 00 00 5A 18 0B 00 ....Z........... [6162][9:22:52 PM][GameA->Shard][C->S][7866][13 bytes] 0000000000 0C 91 AB 01 00 5A 18 0B 00 12 00 00 00 ..«..Z.......... [6163][9:22:52 PM][Shard->GameA][S->C][B866][9 bytes] 0000000000 91 AB 01 00 01 12 00 00 00 .«.............. [6164][9:22:52 PM][GameA->Agent][S->C][B06B][5 bytes][1-Broadcast][5] 0000000000 01 12 00 00 00 ................ [t048][6165][9:22:52 PM][Agent->Client][S->C][B06B][5 bytes] 0000000000 01 12 00 00 00 ................</pre> From this, I learned that AgentServer passes the client's party delete request (0x706B) to GameServer. The first 4 bytes are the party id, and the last 4 bytes are the account JID. If you "SELECT * FROM [VSRO_ACCOUNT].[dbo].[TB_User] where JID = 0xB185A", you'll get the row for the account I was using, which was t048 (which I also have labeled on the Client->Agent connection).
Right now, ShardManager is telling GameSever the client has sent an empty packet, 0x386f (remember the 4 bytes in 0x386f are the JID, so the servers know who is sending the data). Instead, we want to simulate this packet:
Code: <pre class="alt2 prettyprint" dir="ltr" style=" margin: 0px; padding: 6px; border: 1px inset; width: 640px; height: 50px; text-align: left; overflow: auto">[6160][9:22:52 PM][Agent->GameA][C->S][706B][8 bytes] 0000000000 12 00 00 00 5A 18 0B 00 ....Z...........</pre> Lucky for us, with how the SRO server architecture works, ShardManager is already sending GameServer a packet on the client's behalf (0x386f). What if instead we send a 0x706B packet to GameServer? To make this work, we'd also have to write the party id first, and then let the normal 0x386f packet building logic run (which writes the JID of the party leader).
Then, we'd need to stop the ShardManager from removing the party entry itself, because that's the second main problem that needs to be solved. If we were to do that, then when the party match timeout happens, we're pretending the client has cancelled the request, so the system correctly removes the party entry as if a user initiated the action, and then they'd be able to form a new party as if nothing happened.
This is what my fix does. I use a codecave to a new section added to the server, change the packet opcode, write the party id (the party entry object is stored in EBX), and then jump back to the packet building so the JID gets written. Then, I NOP the party entry removal code so everything stays in sync, and the party match timeout feature works as expected because the system thinks the user initiated the cancel, even though it was the server.
The end result is that everything seems to work as you'd expect. To verify this works without side effects, and why I'm confident it's the correct solution, I just look at the resulting packets of the process, and make sure they matched the manual action's result, which they do. In addition, I make sure I can form a new party and another character verifies there's nothing unexpected going on, which there wasn't.
I made a small video showing everything mentioned above. It's a bit boring because I wait through 2 party match refresh packets, but I cover all the main cases in showing that the fix should work. It's only a few minutes long though, so hopefully it's not too painful. I wanted to show the entire process though, so that's why I don't cut out the time. Towards the end I have some comments in the client about the asm itself. I also did testing with multiple clients at once and joining the party and everything works as it should.
Demo Video:
Guide:
A lot of people seem to use and reference Stud_PE, but I myself use CFF Explorer (free edition). Likewise, I'll be using x32dbg and not Ollydbg. This guide will use CFF Explorer, but you can perform similar steps however you want, or opt to implement the solution in an injected dll, etc... The purpose of this guide is to just show how to solve the problem, it's up to users to pick which implementation of the solution works best for them.
Due to the unfortunate false positives with old server files, no edited binaries will be posted. This guide can be used on already modified ShardManagers, so it'll just take a little work to have the fix applied to non-vanilla files. As always, be sure to keep backups in case anything goes wrong with the edits!
1. Open your ShardManager in CFF Explorer.
2. Click on the "Section Headers" treeview entry, right click in the empty grey space in the section header table view, and then choose "Add Section (Empty Space)"
3. Enter a size of 1000 and hit OK. This makes the size 0x1000 bytes, which should be more than enough for lots of patches, but section sizes are generally good to have in multiples of 0x1000.
4. Double click in the "Name" field of the new entry and type in a new, tiny name that begins with a period. Naming the section is good practice to make it easier to refer to when you have more edits, but you only have a limited amount of characters for section names (8 total characters).
[NEW] 4b. Right click the "Characteristics" field of the newly named section. Choose the "Change Section Flags"
[NEW] 4c. Click the checkboxes for the "Is executable" and "Contains code" options. Click OK to save the changes. This will solve a problem that might arise around Step 12 where the section to jmp to is not marked as executable. However, I'm unsure the conditions for which this happens, since it didn't happen for me, but happened for another user.
5. Click on the Save icon. Choose NOT to overwrite your original file and give it a new name. We will now edit our exe in x32dbg.
6. Open your new ShardManager in x32dbg and click on the "Memory Map" icon in the top bar.
7. Select the section you added for this fix, and right click and choose "Follow in Disassembler"
8. Now pay close attention, because you can't just mindlessly copy and paste and not read the directions. The initial patch bytes are as follows:
Code: <pre class="alt2 prettyprint" dir="ltr" style=" margin: 0px; padding: 6px; border: 1px inset; width: 640px; height: 34px; text-align: left; overflow: auto">66 C7 00 6B 70 8D 54 24 1C 8B 0B 89 4C 24 1C 52 B8 04 00 00 00 8B CE E8 00 00 00 00 E9 00 00 00 00</pre> It's 0x21 bytes, so copy them to your clipboard, highlight a bunch of bytes in your section, then right click the highlighted bytes, and choose "Binary Paste"
9. Now highlight the call instruction and press spacebar to assemble. Change the text to "call 0x402DF0" and click OK. NOTE: Your final bytes will not match mine, because your section will most likely be in a different address than mine is.
10. The assemble box will now move to the jmp instruction, so you don't have to highlight it and press spacebar again (but you can if you accidently closed the assemble window). Change the text to "jmp 0x4505DE" and click OK. Close the assemble window since we don't need it here anymore. NOTE: Your final bytes will not match mine, because your section will most likely be in a different address than mine is.
11. Highlight the first instruction in this code section. Right click it and choose "Label -> Label Current Address". I typed in the name "ptfix", but you can use whatever, just remember what you wrote.
We've now completed adding in the custom logic for the fix. We now have a few more patches to go to make it use this logic and to fix the issue of stopping the shard manager from deleting the party match entry.
12. Press "ctrl + g" to go to an address. Paste in 0x4505D9 and press OK. Now press spacebar to bring up the assemble window again. Change the instruction to "jmp ptfix" (or use whatever name you wrote in step 11). Make sure the "Keep Size" option is selected and press OK and close the assemble window. While the size should be the exact same, when editing client code you want to be mindful of not accidently making changes that overwrite other instructions unexpectedly! NOTE: Your final bytes will not match mine, because your section will most likely be in a different address than mine is.
13. Press "ctrl + g" to go to an address. Paste in 0x450619 and press OK. Select this address through the jne at 0x45062A. Right click the selection and choose "Binary -> Fill with NOPs"
14. In the new window that pops up, just press OK, since we selected the right amount of bytes to fill already.
15. Now it's time to save our changes. Click "File -> Patch file..." to bring up the patches window. Click on the "Patch File" button, and make a new name for the final ShardManager and click Save (as you can't overwrite the current file while it's in use in x32dbg!)
16. Now before you close this x32dbg instance, go ahead and open your new final ShardManager in a new x32dbg instance and verify you made all the changes correctly. This is so if you missed something by accident, you don't have to repeat the entire process, and can just re-save once you correct any mistakes.
Congratulations! You should now have a modified ShardManager that does not have the 1-hour DC. In order to test and verify the patch was made without issues, assuming you don't want to waste an hour for it to trigger, you can perform the following edit:
[OPTIONAL] 17. Press "ctrl + g" and go to address 0x45055F. Right click the line and choose "Binary -> Fill with NOPs" and then press OK. Repeat step 15, but make sure to give this ShardManager a different name, as you'll want to test once with the instant timeout version, and then switch back to the normal one after confirming the patch works as expected.
As another tip, as it's been mentioned in another thread, but I'll mention it again here for completeness, you can edit the 0x3C in line 0x45055C to change from a 60m timeout so some other value, which will be limited to 0xFF max (255m) due to the instruction size limitation.
Once you've verified everything, you should be good to go, so you can close your x32dbg instances and CFF Explorer if it's still open. As I mentioned earlier, I don't believe there will be any side effects based on my testing and observations, and the fix is easily verified as being working because the client is notified of the party being removed without being DCed correctly now.
That completes this guide, if I've missed anything or if something isn't clear, please let me know and I'll get it sorted out. I do re-read my threads and try to make sure I don't make any big mistakes, but things can slip by since I'll read what's in my mind and not always what I wrote, so it's no problem fixing anything wrong.
Happy coding!
[Edit 1] Thanks to @
Ziyaretçiler için gizlenmiş link,görmek için üye olmalısınız!
Giriş yap veya üye ol.
for testing out the guide and discovering the problem that the newly added 4b/4c steps solve![Guide] Fixing the party matching 1-hour DC bug (0x386f)
Silkroad Online özel sunucularında (pserver) çalışan geliştiriciler ve oyun yöneticileri bazen nadir ama oldukça sinir bozucu hatalarla karşılaşabilir. Bunlardan birisi de party matching 1-hour DC bug olarak bilinen ve 0x386f hatasıyla tanımlanan bağlantı kopma sorunudur. Bu hata, oyuncuların bir grup eşleştirme (party matching) işlemi sırasında 1 saat civarında otomatik olarak oyundan atılması durumunu içerir. Bu durum hem oyuncu deneyimini düşürür hem de sunucu sadakat oranlarını olumsuz etkileyebilir.
Sorunun Kaynağı Nedir?
Party matching sistemi, Silkroad Online'da oyuncuların belirli seviye aralıklarında gruplanarak birlikte macera yaşamalarını sağlar. Ancak bazı özel sunucu yapılandırmalarında, eşleştirme sırasında sistemsel bir zamanlayıcı hatası oluşabilir. Bu hata genellikle agent server veya shard yapılandırmasında eksikliklerden kaynaklanır. 0x386f hatası, istemci ile sunucu arasında beklenmedik bir zaman aşımı meydana geldiğinde ortaya çıkar. Özellikle uzun süreli oyun oturumlarında veya grup eşleştirme sürecinde bu durum daha sık görülebilir.
Hatanın Tanımlanması
Oyuncular bu hatayı genellikle aşağıdaki belirtilerle fark ederler:
- Grup eşleştirme sırasında oyunun beklenmedik şekilde kapanması
- Oyuna tekrar bağlandığında eski grubun dağılmış olması
- Her 1 saat civarında oturumun sonlandırılması
Sunucu loglarında ise genellikle 0x386f koduyla birlikte bağlantı zaman aşımı (timeout) mesajları yer alır. Bu durum, gateway server veya game server loglarında da takip edilebilir.
Çözüm Adımları
Bu hatayı çözmek için aşağıdaki adımları izleyerek sunucu yapılandırmanızı güncelleyebilirsiniz:
1. Agent Server Ayarlarını Kontrol Et
Agent server, oyuncu isteklerini yönlendiren ve eşleştirme işlemlerini başlatan temel bileşendir. Config dosyalarında yer alan timeout ayarlarının doğru yapılandırıldığından emin olun. Önerilen değerler:
- MatchingTimeout = 3600 (1 saat)
- ConnectionTimeout = 7200 (2 saat)
2. Gateway Sunucusunda Oturum Süresi Ayarı
Gateway sunucusu, kullanıcıların oyun sunucusuna bağlanmasını sağlar. Burada session timeout değeri, 1 saatten fazla oturum süresi için yeterli olmalıdır. Bu değeri artırmak, 0x386f hatasının önlenmesine yardımcı olabilir.
3. Shard ve Game Server Ayarları
Shard sunucularında, grup eşleştirme sırasında aktif olan kullanıcılar için özel zamanlayıcılar tanımlanabilir. PartyMatchTimer veya benzeri isimli değişkenlerin doğru yapılandırıldığından emin olun. Yanlış zamanlayıcı değerleri, 1 saatlik oturum sonlandırmasına neden olabilir.
4. Client-side Ayarlar
Bazı özel sunucularda, SRO_Client tarafında da zamanlayıcı ayarları yapılabilmektedir. Özellikle media.pk2 veya data.pk2 dosyalarında bulunan zamanlayıcı parametrelerinin, sunucu tarafıyla uyumlu olduğundan emin olun.
5. Güvenlik ve Filtreleme Sistemleri
Sunucuda çalışan Silkroad Guard, MaxiGuard, KGuard gibi sistemler, uzun süreli oturumlarda hatalı bağlantı kesmeleri yapabilir. Bu sistemlerin yapılandırmasında, grup eşleştirme sırasında zaman aşımı limitlerinin artırılması önerilir.
Sonuç
Party matching 1-hour DC bug (0x386f) gibi hatalar, kullanıcı memnuniyetini doğrudan etkiler. Bu tür sistemsel hataların çözümü için sunucu tarafında dikkatli konfigürasyon gerekir. Sunucu yapılandırmasında yapılan küçük değişiklikler, kullanıcı deneyimini ciddi anlamda iyileştirebilir. Geliştiricilerin bu tür sorunlara karşı dikkatli olması ve düzenli log takibi yapması büyük önem taşır.
[Guide] Fixing the party matching 1-hour DC bug (0x386f)
Developers and administrators running Silkroad Online private servers may sometimes encounter rare but highly frustrating bugs. One such issue is the party matching 1-hour DC bug, identified by the error code 0x386f. This bug involves players being automatically disconnected from the game around the 1-hour mark during a party matching process. This situation not only diminishes player experience but also negatively affects server retention rates.
What Causes the Issue?
The party matching system allows players in Silkroad Online to group up based on certain level ranges for cooperative gameplay. However, in some private server configurations, a systemic timer error can occur during the matching process. This error is usually caused by misconfigurations in agent server or shard settings. The 0x386f error appears when an unexpected timeout occurs between the client and the server. It tends to occur more frequently during long gaming sessions or while in the party matching process.
Identifying the Error
Players often notice this error through the following symptoms:
- Unexpected disconnection during party matching
- Old party no longer exists upon reconnecting
- Session termination every approximately 1 hour
In server logs, 0x386f codes are typically accompanied by timeout messages. These can be traced in gateway server or game server logs as well.
Resolution Steps
To fix this error, you can update your server configuration by following these steps:
1. Check Agent Server Settings
The agent server is responsible for forwarding player requests and initiating matching processes. Ensure that timeout values in config files are properly set. Recommended values:
- MatchingTimeout = 3600 (1 hour)
- ConnectionTimeout = 7200 (2 hours)
2. Adjust Session Timeouts in Gateway Server
The gateway server handles user connections to the game server. Here, the session timeout value should be sufficient for sessions lasting longer than 1 hour. Increasing this value may help prevent the 0x386f error.
3. Shard and Game Server Configurations
On shard servers, custom timers can be defined for active users during party matching. Ensure variables named PartyMatchTimer or similar are correctly configured. Incorrect timer values may cause session terminations every hour.
4. Client-Side Settings
In some private servers, timer settings can also be adjusted on the SRO_Client side. Make sure that timer parameters found in files like media.pk2 or data.pk2 are compatible with the server-side configuration.
5. Security and Filtering Systems
Systems like Silkroad Guard, MaxiGuard, or KGuard may incorrectly terminate long-running sessions. It's recommended to increase timeout limits in these systems' configurations during party matching operations.
Conclusion
Issues like the Party Matching 1-Hour DC Bug (0x386f) directly affect user satisfaction. Resolving such system-level errors requires careful server configuration. Small adjustments in server settings can significantly improve the user experience. It is critical for developers to remain vigilant against such issues and maintain regular log monitoring.
