Table of Contents

DSR GameData Communication

These handle all game-specific data.

The two primary functions of interest are

bool sendNetMessage(NS_FRPG::FrpgSessionManagerImp *sessionman,ConnectedPlayerData *playerdata, uint64_t type, byte *data, int size) @1405098A0

and

ulonglong getNetMessage(NS_FRPG::FrpgSessionManagerImp *session_man,ConnectedPlayerData *player, uint type, byte *store_data_here, uint max_message_size) @140509560

Packet Types

This list is a Work-In-Progress. Underlined types are fully understood. The functions which handle each type are labeled ``sendTypeXNetMessage`` and ``readparseTypeXNetMessage``

0. TestMessage.

1. PlayerFrameUpdate

3. WorldChrSyncLocation

4. WorldChrSyncHealth

5. PlayerNumber

6. PlayerData

7. RequestPlayerNumber

8. RequestWorldChrSyncInitInfo

9. TeamChrType

10. PlayerEquipment

11. WeaponChange

12. MsgMapList

13. CompleteEvent

14. EventInit

15. WorldInit

16. Grab

17. GoodsSfxUpdate

18. PvPDamage

19. PvEDamage

20. WorldChrSyncRemoteToHostEnemyAI

21. WorldChrSyncHostToRemoteEnemyAI

23. One of the packets sent early on when summoning. Precedes type 51.

32. Unknown

33. EnemyAction

34. NPCSpEffectSync

Synchronises NPC SpEffects between players. It is used to tell all other players what SpEffect an NPC has. Packet size is 8, it contains:

35. ApplyEffectToPlayer

38. Unknown

39. EnemyInit

40. ObjDestroy

41. ObjUnknown

42. ItemSync

43. ActionObjSync

44. ActionObjFlagUnknown

45. ActionObjFlag

46. Unknown

47. EmvdSync

48. NPCSummon

49. NPCLeave

50. WorldChrSyncFlags

51. NetNeatoDb

52. ApplyEnemyEffect * WorldChrSync for enemy/NPC effects

53. WorldChrSyncEffect

54. Unknown

55. SkipCutscene

56. HumanityUpdate

Only received by remote players, the host does not listen for this packet. The size is 2 bytes, and will affect whoever receives the packet.

57. NetVagrantSync

58. SpEffectInitAlloc

59. SpEffectInitApply

60. BOSStartMatch

61. BOSRegisterPlayer

62. BOSBattleInformation

63. Unknown

64. BOSUpdateScore

66. Unknown

67. Unknown

68. BOSTimestamp

69. Unknown

70. KarmicJustice

74. ResponseSteamId

75. RequestSteamId

76. PCSpEffectSync

Synchronises SpEffects between players. It is used to tell all other players what SpEffect you have on yourself. Packet size is 8, it contains:

Invisible Backstab bug in DSR

DSR has a glitch where your first action after a backstab cancel is invisible. The explanation and fix for this is as follows.

The thread which sends the attack a player is currently doing (the ezstate info field in type 1 packets) is separate from the thread which sets what attack the player is doing. So, in rare situations the attacker could go into the backstab animation, then have it canceled, and only the packet which says “attacker in no animation” is sent, when instead both the “attacker in backstab animation” and then “attacker in no animation” packets should be sent.

But why, from the defender's view, do they see the attacker in the backstab animation? Well, it's because there is a 2nd packet type sent! When the attacker triggers the backstab, the game IMMEDIATELY sends a packet saying “i'm backstabbing this player now” (the throw id in type 16 packets). The defender receives it, and sets both the defender and attacker animations on their client side to reflect this. This occurs even if the defender doesn't also receive the “attacker in backstab animation” packet, because that should be redundant in this case, right? ;)

Ok, but why doesn’t the visual go away when the defender does later receive the “attacker in no animation” packet? The “attacker in backstab animation” packet must be setting up some special flags. In the case of a normal backstab cancel, where the “attacker in no animation” packet is just sent sooner than expected, it does cancel the visual. So “attacker in backstab animation” packet must be allowing the visual to be cancelable somehow.

Why, if we remove the code in the “i'm backstabbing this player now” throw type receiving packet function, which sets the attacker animation, does the attacker animation not get set later by the “attacker in backstab animation” packet when it’s received (in a good backstab case)? Because backstab doesn’t use ezstate. The ezstate state id for backstabs doesn’t set any animation id like other states do (via ChangeGeneralAnimCategorized, etc).

The way to fix this is to always send the “attacker in backstab animation” ezstate packet right after the “i'm backstabbing this player now” throw packet. Need to ensure the ezstate packet is actually sending type 225 (backstab). With dropping packets, this bug can still happen. If the forced sent backstab ezstate animation packet gets dropped repeatedly and doesn't arrive before the 0 ezstate animation packet. To be safe we should not have to even send the backstab ezstate packet, and just have that performed when the backstab throw packet is received.

Spell desyncing in DS1

In some circumstances, spell visuals can be desynced from the spells themselves in PvP, causing invisible bullets. This only occurs during any homing bullets. The explanation and fix for this is as follows.

This problem is due to the fact that, while spell casting is synced across clients by the type 1 packet, homing bullets don't actually fire off when the spell itself is cast. So while the bullet appearance is synced, when they fire is computed client side based on distance and other factors. And if the two clients don't have the exact same calculation for when the homing bullet is triggered, one side may see the visual for bullet firing when the other doesn't. The side that sees the visual sends a type 18 packet to be sent when the bullet on one client hits the other, and thus damage is taken by invisible bullet.

The code at 0x14042816a, in the HomingBullet_HandleAI function, is hit when a homing bullet is actually fired. Not when the spell itself is cast, but when the bullet actually shots out with a hitbox. We inject code there that gets the attacker and defender player's entity handles, along with the bullet number which is used to identify which of the bullets being rendered is actually fired off. This data is packed into a custom type 1 packet struct along with a magic header to indicate it's special.

The injected code then calls the sendType1NetMessage function, and the custom packet is then passed as an argument to it.

We also inject into the function which receives the type 1 packet, so we can check to see if the received packet is our special spell struct. If so, extract the handles and data, and store it off in an array.

Finally, inject into a bit earlier in the HomingBullet_HandleAI function. This function is called on every active bullet, every frame. We inject at the part which checks if the passed in bullet should be fired, and check if the bullet id and bullet owner are present in our list of received bullet packets. If it is, we set the bullet's target to the one provided by the packet, and it's fired off. We also don't allow any bullet we haven't gotten a packet for to be fired. This effectively syncs the bullet with the netcode.