initial commit
This commit is contained in:
parent
3ef5eb2a56
commit
2317e2bafb
76 changed files with 19213 additions and 0 deletions
15
assets/Application/config.json
Normal file
15
assets/Application/config.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"InfoGroups": {
|
||||
"StandaloneWindows64": {
|
||||
"VersionInfoGroups": {
|
||||
"0.1.0": {
|
||||
"MinVersion": "0.1.0",
|
||||
"LatestVersion": "0.1.18",
|
||||
"GameResUrl": "http://127.0.0.1:21000/game_res/NAP_Publish/output_147608_1361f678bc/client/",
|
||||
"DesignDataUrl": "http://127.0.0.1:21000/",
|
||||
"ServerListUrl": "http://127.0.0.1:21000/design_data/NAP_Publish_AppStore_0.1.0/oversea/serverlist.bin"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
assets/Application/serverlist.json
Normal file
11
assets/Application/serverlist.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
[
|
||||
{
|
||||
"sid": 142,
|
||||
"serverName": "HollowPS",
|
||||
"ip": "127.0.0.1",
|
||||
"port": "21000",
|
||||
"noticeRegion": "nap_glb_cbus01",
|
||||
"protocol": "http",
|
||||
"$Type": "MoleMole.ServerListInfo"
|
||||
}
|
||||
]
|
BIN
assets/Application/versions.bundle
Normal file
BIN
assets/Application/versions.bundle
Normal file
Binary file not shown.
1
assets/BinOutput/EventGraphCollection.json
Normal file
1
assets/BinOutput/EventGraphCollection.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,15 @@
|
|||
ID CodeName Name AudioEventReplaceParam AudioBank HudIconPath HollowIconPath IconPath RectIconPath AvatarPath ScriptConfigPath UIScriptConfigPath PrefabPath UIPrefabPath MainPageShow NeedShow HitTypes ElementTypes Tags Gender Camp CampName GroupIconPath WeaponType StarInitial AvatarPieceID AvatarDecompose AvatarCompose HP HPGrowth Armor ArmorGrowth Shield ShieldGrowth Endurance Attack AttackGrowth Defence DefenceGrowth Crit CritDamage CritRes CritDmgRes PenRate PenDelta Luck Stun BreakStun SPBarPoint SpRecover RBL RBLCorrectionFactor RBLProbability BuffResistBurnPossibilityRatio BuffResistBurnPossibilityDelta BuffResistFrozenPossibilityRatio BuffResistFrozenPossibilityDelta BuffResistElectricPossibilityRatio BuffResistElectricPossibilityDelta Weapon RBP RBPFadeOutRate RBPFadeOutTime RBPCorrectionFactor RBPProbability
|
||||
1011 Avatar_Female_Size02_Anbi_En Avatar_Female_Size02_Anbi anbi BK_Anbi|BK_CHR_Common|BK_Anbi_VO UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral01.png UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral01.png UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconRoleCircle01.png UI/Sprite/A1DynamicLoad/IconRoleSelect/UnPacker/IconRoleSelect01.png UI/Sprite/RoleHollowSystemPage/TeamEditAvatar01 Data/ScriptConfig/Character/Avatar_Female_Size02_Anbi Data/ScriptConfig/Character/Avatar_Female_Size02_Anbi_UI Char/Avatar/Female/Female_Size02/Avatar_Female_Size02_Anbi/Avatar_Female_Size02_Anbi Char/Avatar/Female/Female_Size02/Avatar_Female_Size02_Anbi/Avatar_Female_Size02_Anbi_UI true true 101 203 Anbi,Cut,Electric,Female 2 1 CampGentleHouse UI/Sprite/A1DynamicLoad/IconRoleCamp/UnPacker/IconCampGentleHouse.png 1 1 5011 10 20 462 382500 0 0 0 0 0 100 82800 48 39000 500 5000 0 0 0 0 10 0 110 120 180 1 10000 0 0 0 0 0 0 0 10012 0 0 0 0 0
|
||||
1021 Avatar_Female_Size01_Tsubaki_En Avatar_Female_Size01_Tsubaki tsubaki BK_Tsubaki|BK_CHR_Common|BK_Tsubaki_VO UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral11.png UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral11.png UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconRoleCircle11.png UI/Sprite/A1DynamicLoad/IconRoleSelect/UnPacker/IconRoleSelect11.png UI/Sprite/RoleHollowSystemPage/TeamEditAvatar02 Data/ScriptConfig/Character/Avatar_Female_Size01_Tsubaki Data/ScriptConfig/Character/Avatar_Female_Size01_Tsubaki_UI Char/Avatar/Female/Female_Size01/Avatar_Female_Size01_Tsubaki/Avatar_Female_Size01_Tsubaki Char/Avatar/Female/Female_Size01/Avatar_Female_Size01_Tsubaki/Avatar_Female_Size01_Tsubaki_UI true true 101 200 Tsubaki,Cut,Female 2 1 CampGentleHouse UI/Sprite/A1DynamicLoad/IconRoleCamp/UnPacker/IconCampGentleHouse.png 2 1 5021 10 20 440 364300 0 0 0 0 0 95 78400 48 39000 500 5000 0 0 0 0 10 0 100 120 200 1 10000 0 0 0 0 0 0 0 10012 0 0 0 0 0
|
||||
1031 Avatar_Female_Size02_Nostradamus_En Avatar_Female_Size02_Nostradamus nicole BK_Nicole|BK_CHR_Common|BK_Nicole_VO UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral12.png UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral12.png UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconRoleCircle12.png UI/Sprite/A1DynamicLoad/IconRoleSelect/UnPacker/IconRoleSelect12.png UI/Sprite/RoleHollowSystemPage/TeamEditAvatar03 Data/ScriptConfig/Character/Avatar_Female_Size02_Nostradamus Data/ScriptConfig/Character/Avatar_Female_Size02_Nostradamus_UI Char/Avatar/Female/Female_Size02/Avatar_Female_Size02_Nostradamus/Avatar_Female_Size02_Nostradamus Char/Avatar/Female/Female_Size02/Avatar_Female_Size02_Nostradamus/Avatar_Female_Size02_Nostradamus_UI true true 102 200 Nostradamus,Punch,Female 2 1 CampGentleHouse UI/Sprite/A1DynamicLoad/IconRoleCamp/UnPacker/IconCampGentleHouse.png 1 1 5031 10 20 440 364300 0 0 0 0 0 116 95900 43 35100 500 5000 0 0 0 0 10 0 100 120 200 1 10000 0 0 0 0 0 0 0 10012 0 0 0 0 0
|
||||
1041 Avatar_Female_Size02_Longinus_En Avatar_Female_Size02_Longinus longinus BK_Longinus|BK_CHR_Common|BK_Longinus_VO UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral05.png UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral05.png UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconRoleCircle05.png UI/Sprite/A1DynamicLoad/IconRoleSelect/UnPacker/IconRoleSelect05.png UI/Sprite/RoleHollowSystemPage/TeamEditAvatar04 Data/ScriptConfig/Character/Avatar_Female_Size02_Longinus Data/ScriptConfig/Character/Avatar_Female_Size02_Longinus_UI Char/Avatar/Female/Female_Size02/Avatar_Female_Size02_Longinus/Avatar_Female_Size02_Longinus Char/Avatar/Female/Female_Size02/Avatar_Female_Size02_Longinus/Avatar_Female_Size02_Longinus_UI false true 101 201 Longinus,Cut,Fire,Female 2 5 CampObols UI/Sprite/A1DynamicLoad/IconRoleCamp/UnPacker/IconCampObols.png 1 1 5041 10 20 462 382500 0 0 0 0 0 100 82800 48 39000 500 5000 0 0 0 0 10 0 110 120 180 1 10000 0 0 0 0 0 0 0 10012 0 0 0 0 0
|
||||
1061 Avatar_Female_Size01_Corin_En Avatar_Female_Size01_Corin corin BK_Corin|BK_CHR_Common|BK_Corin_VO UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral09.png UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral09.png UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconRoleCircle09.png UI/Sprite/A1DynamicLoad/IconRoleSelect/UnPacker/IconRoleSelect09.png UI/Sprite/RoleHollowSystemPage/TeamEditAvatar04 Data/ScriptConfig/Character/Avatar_Female_Size01_Corin Data/ScriptConfig/Character/Avatar_Female_Size01_Corin_UI Char/Avatar/Female/Female_Size01/Avatar_Female_Size01_Corin/Avatar_Female_Size01_Corin Char/Avatar/Female/Female_Size01/Avatar_Female_Size01_Corin/Avatar_Female_Size01_Corin_UI false true 101 200 Corin,Cut,Female 2 2 CampVictoriaHousekeepingCo. UI/Sprite/A1DynamicLoad/IconRoleCamp/UnPacker/IconCampVictoriaHousekeepingCo..png 1 1 5061 10 20 484 400800 0 0 0 0 0 105 87200 48 39000 500 5000 0 0 0 0 10 0 120 120 160 1 10000 0 0 0 0 0 0 0 10012 0 0 0 0 0
|
||||
1081 Avatar_Male_Size03_Billy_En Avatar_Male_Size03_Billy billy BK_Billy|BK_CHR_Common|BK_Billy_VO UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral10.png UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral10.png UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconRoleCircle10.png UI/Sprite/A1DynamicLoad/IconRoleSelect/UnPacker/IconRoleSelect10.png UI/Sprite/RoleHollowSystemPage/TeamEditAvatar04 Data/ScriptConfig/Character/Avatar_Male_Size03_Billy Data/ScriptConfig/Character/Avatar_Male_Size03_Billy_UI Char/Avatar/Male/Male_Size03/Avatar_Male_Size03_Billy/Avatar_Male_Size03_Billy Char/Avatar/Male/Male_Size03/Avatar_Male_Size03_Billy/Avatar_Male_Size03_Billy_UI true true 103 200 Billy,Pierce,Male 1 1 CampGentleHouse UI/Sprite/A1DynamicLoad/IconRoleCamp/UnPacker/IconCampGentleHouse.png 1 1 5081 10 20 396 327900 0 0 0 0 0 105 87200 43 35100 500 5000 0 0 0 0 10 0 80 120 240 1 10000 0 0 0 0 0 0 0 10012 0 0 0 0 0
|
||||
1091 Avatar_Female_Size02_Unagi_En Avatar_Female_Size02_Unagi unagi BK_Unagi|BK_CHR_Common|BK_Unagi_VO UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral13.png UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral13.png UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconRoleCircle13.png UI/Sprite/A1DynamicLoad/IconRoleSelect/UnPacker/IconRoleSelect13.png UI/Sprite/RoleHollowSystemPage/TeamEditAvatar04 Data/ScriptConfig/Character/Avatar_Female_Size02_Unagi Data/ScriptConfig/Character/Avatar_Female_Size02_Unagi_UI Char/Avatar/Female/Female_Size02/Avatar_Female_Size02_Unagi/Avatar_Female_Size02_Unagi Char/Avatar/Female/Female_Size02/Avatar_Female_Size02_Unagi/Avatar_Female_Size02_Unagi_UI false true 101 202 Unagi,Cut,Ice,Female 2 6 CampH.S.O-S6 UI/Sprite/A1DynamicLoad/IconRoleCamp/UnPacker/IconCampH.S.O-S6.png 1 1 5091 10 20 462 382500 0 0 0 0 0 100 82800 48 39000 500 5000 0 0 0 0 10 0 110 120 180 1 10000 0 0 0 0 0 0 0 10012 0 0 0 0 0
|
||||
1101 Avatar_Female_Size01_OokumaMari_En Avatar_Female_Size01_OokumaMari koleda BK_Koleda|BK_CHR_Common|BK_Koleda_VO UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral14.png UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral14.png UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconRoleCircle14.png UI/Sprite/A1DynamicLoad/IconRoleSelect/UnPacker/IconRoleSelect14.png UI/Sprite/RoleHollowSystemPage/TeamEditAvatar04 Data/ScriptConfig/Character/Avatar_Female_Size01_OokumaMari Data/ScriptConfig/Character/Avatar_Female_Size01_OokumaMari_UI Char/Avatar/Female/Female_Size01/Avatar_Female_Size01_OokumaMari/Avatar_Female_Size01_OokumaMari Char/Avatar/Female/Female_Size01/Avatar_Female_Size01_OokumaMari/Avatar_Female_Size01_OokumaMari_UI false true 102 201 OokumaMari,Punch,Fire,Female 2 3 CampBelobogIndustries UI/Sprite/A1DynamicLoad/IconRoleCamp/UnPacker/IconCampBelobogIndustries.png 1 1 5101 10 20 431 356900 0 0 0 0 0 99 82200 45 36900 500 5000 0 0 0 0 10 0 100 120 200 1 10000 0 0 0 0 0 0 0 10012 0 0 0 0 0
|
||||
1111 Avatar_Male_Size03_Anton_En Avatar_Male_Size03_Anton anton BK_Anton|BK_CHR_Common|BK_Anton_VO UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral15.png UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral15.png UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconRoleCircle15.png UI/Sprite/A1DynamicLoad/IconRoleSelect/UnPacker/IconRoleSelect15.png UI/Sprite/RoleHollowSystemPage/TeamEditAvatar04 Data/ScriptConfig/Character/Avatar_Male_Size03_Anton Data/ScriptConfig/Character/Avatar_Male_Size03_Anton_UI Char/Avatar/Male/Male_Size03/Avatar_Male_Size03_Anton/Avatar_Male_Size03_Anton Char/Avatar/Male/Male_Size03/Avatar_Male_Size03_Anton/Avatar_Male_Size03_Anton_UI false true 103 203 Anton,Pierce,Electric,Male 1 3 CampBelobogIndustries UI/Sprite/A1DynamicLoad/IconRoleCamp/UnPacker/IconCampBelobogIndustries.png 1 1 5111 10 20 462 382500 0 0 0 0 0 100 82800 48 39000 500 5000 0 0 0 0 10 0 110 120 180 1 10000 0 0 0 0 0 0 0 10012 0 0 0 0 0
|
||||
1121 Avatar_Male_Size03_Ben_En Avatar_Male_Size03_Ben ben BK_Ben|BK_CHR_Common|BK_Ben_VO UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral16.png UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral16.png UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconRoleCircle16.png UI/Sprite/A1DynamicLoad/IconRoleSelect/UnPacker/IconRoleSelect16.png UI/Sprite/RoleHollowSystemPage/TeamEditAvatar04 Data/ScriptConfig/Character/Avatar_Male_Size03_Ben Data/ScriptConfig/Character/Avatar_Male_Size03_Ben_UI Char/Avatar/Male/Male_Size03/Avatar_Male_Size03_Ben/Avatar_Male_Size03_Ben Char/Avatar/Male/Male_Size03/Avatar_Male_Size03_Ben/Avatar_Male_Size03_Ben_UI false true 102 200 Ben,Punch,Male 1 3 CampBelobogIndustries UI/Sprite/A1DynamicLoad/IconRoleCamp/UnPacker/IconCampBelobogIndustries.png 1 1 5121 10 20 550 455900 0 0 0 0 0 90 74700 55 45100 500 5000 0 0 0 0 10 0 120 120 160 1 10000 0 0 0 0 0 0 0 10012 0 0 0 0 0
|
||||
1131 Avatar_Female_Size01_Aokaku_En Avatar_Female_Size01_Aokaku aokaku BK_Aokaku|BK_CHR_Common|BK_Aokaku_VO UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral17.png UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral17.png UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconRoleCircle17.png UI/Sprite/A1DynamicLoad/IconRoleSelect/UnPacker/IconRoleSelect17.png UI/Sprite/RoleHollowSystemPage/TeamEditAvatar04 Data/ScriptConfig/Character/Avatar_Female_Size01_Aokaku Data/ScriptConfig/Character/Avatar_Female_Size01_Aokaku_UI Char/Avatar/Female/Female_Size01/Avatar_Female_Size01_Aokaku/Avatar_Female_Size01_Aokaku Char/Avatar/Female/Female_Size01/Avatar_Female_Size01_Aokaku/Avatar_Female_Size01_Aokaku_UI false true 101,102 204 Aokaku,Cut,Punch,Wind,Female 2 6 CampH.S.O-S6 UI/Sprite/A1DynamicLoad/IconRoleCamp/UnPacker/IconCampH.S.O-S6.png 1 1 5131 10 20 484 400800 0 0 0 0 0 105 87200 48 39000 500 5000 0 0 0 0 10 0 120 120 160 1 10000 0 0 0 0 0 0 0 10012 0 0 0 0 0
|
||||
1141 Avatar_Male_Size03_Lycaon_En Avatar_Male_Size03_Lycaon lycaon BK_Lycaon|BK_CHR_Common|BK_Lycaon_VO UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral18.png UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral18.png UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconRoleCircle18.png UI/Sprite/A1DynamicLoad/IconRoleSelect/UnPacker/IconRoleSelect18.png UI/Sprite/RoleHollowSystemPage/TeamEditAvatar04 Data/ScriptConfig/Character/Avatar_Male_Size03_Lycaon Data/ScriptConfig/Character/Avatar_Male_Size03_Lycaon_UI Char/Avatar/Male/Male_Size03/Avatar_Male_Size03_Lycaon/Avatar_Male_Size03_Lycaon Char/Avatar/Male/Male_Size03/Avatar_Male_Size03_Lycaon/Avatar_Male_Size03_Lycaon_UI false true 102 202 Lycaon,Punch,Ice,Male 1 2 CampVictoriaHousekeepingCo. UI/Sprite/A1DynamicLoad/IconRoleCamp/UnPacker/IconCampVictoriaHousekeepingCo..png 1 1 5141 10 20 473 391700 0 0 0 0 0 95 78900 50 41000 500 5000 0 0 0 0 10 0 110 120 180 1 10000 0 0 0 0 0 0 0 10012 0 0 0 0 0
|
||||
2011 Avatar_Male_Size01_Wise_En Avatar_Male_Size01_Wise wise BK_Wise UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral01.png UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral01.png UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconRoleCircle01.png UI/Sprite/A1DynamicLoad/IconRoleSelect/UnPacker/IconRoleSelect01.png UI/Sprite/RoleHollowSystemPage/TeamEditAvatar01 Data/ScriptConfig/Character/Avatar_Male_Size01_Wise_MainCity Data/ScriptConfig/Character/Avatar_Male_Size01_Wise_MainCity Char/Avatar/Male/Male_Size01/Avatar_Male_Size01_Wise/Avatar_Male_Size01_Wise_MainCity Char/Avatar/Male/Male_Size01/Avatar_Male_Size01_Wise/Avatar_Male_Size01_Wise_UI false false 0 0 1 0 None UI/Sprite/A1DynamicLoad/IconRoleCamp/UnPacker/IconCampGentleHouse.png 1 1 6011 5 10 449 372100 0 0 0 0 0 90 74900 48 39000 500 5000 0 0 0 0 10 0 110 120 180 1 10000 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2021 Avatar_Female_Size02_Belle_En Avatar_Female_Size02_Belle belle BK_Belle UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral01.png UI/Sprite/A1DynamicLoad/IconRoleGeneral/UnPacker/IconRoleGeneral01.png UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconRoleCircle01.png UI/Sprite/A1DynamicLoad/IconRoleSelect/UnPacker/IconRoleSelect01.png UI/Sprite/RoleHollowSystemPage/TeamEditAvatar01 Data/ScriptConfig/Character/Avatar_Female_Size02_Belle_MainCity Data/ScriptConfig/Character/Avatar_Female_Size02_Belle_MainCity Char/Avatar/Female/Female_Size02/Avatar_Female_Size02_Belle/Avatar_Female_Size02_Belle_MainCity Char/Avatar/Female/Female_Size02/Avatar_Female_Size02_Belle/Avatar_Female_Size02_Belle_UI false false 0 0 2 0 None UI/Sprite/A1DynamicLoad/IconRoleCamp/UnPacker/IconCampGentleHouse.png 1 1 6011 5 10 438 363500 0 0 0 0 0 95 78700 45 37000 500 5000 0 0 0 0 10 0 110 120 180 1 10000 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
498
assets/TemplateCollections/MainCityObjectTemplateCollection.tsv
Normal file
498
assets/TemplateCollections/MainCityObjectTemplateCollection.tsv
Normal file
|
@ -0,0 +1,498 @@
|
|||
TagID NPCID CreatePosition CreateType DefaultInteractIDs InteractName InteractShape InteractScale FanInteractParam FocusInteractScale IgnoreCollider LookIK NPCLookIK SceneSoundID PlayerRotate NPCRotate SceneObjectName CameraStoryKey ActionState ColliderState ItemState ObjectIDs CreateInterval CreateDelay NPCIcon ActionSwitch
|
||||
1 100171011 Street_NPCPos_ToWorkshop 0 10000001 None 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
2 100171011 Street_NPCPos_ToGarage 0 10000002 None 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
3 100171011 Workshop_NPCPos_ToStreet 0 10000003 None 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
4 100171011 Workshop_NPCPos_ToGarage 0 10000004 None 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
5 100171011 Garage_NPCPos_ToStreet 0 10000005 None 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
6 100171011 Garage_NPCPos_ToWorkshop 0 10000006 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
7 100171011 Street_NPCPos_ToGarage2 0 10000016 None 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
8 100171011 Garage_NPCPos_ToStreet2 0 10000017 None 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
1001 100171011 Workshop_NPCPos_VHS 0 10000010 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
1002 100171011 Workshop_NPCPos_Hollow 0 10000009 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Middle 0 None None 0 0 None None
|
||||
1003 100171011 Street_NPCPos_Smithy 0 10000007 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
1004 100171011 Workshop_NPCPos_Gacha 0 A 1 0.75,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
1005 100171011 Workshop_NPCPos_WorkTable 0 10000014 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
1006 100171011 Street_NPCPos_Grocery 0 A 1 2,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
1007 100171011 Workshop_NPCPos_TimeMachine 0 10000020 A 2 0,1.5,2,150,10 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
2000 100172011 WorkShop_NPCPos_Noca_Quest10020001 1 20000002 A 1 2,0,0,0,0 None 3.0 true true true 0 false false None Middle 3 AvatarCollider:true None 0 0 None None
|
||||
2001 100172011 Garage_NPCPos_Nocha_Quest10020003 1 20000002 A 1 2,0,0,0,0 None 3.0 true true true 0 false false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2002 100172031 Garage_NPCPos_Billy_Quest10020003 1 20000002 A 1 2,0,0,0,0 None 3.0 true true true 0 false false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2003 100172041 Garage_NPCPos_Anbi_Quest10020003 1 20000002 A 1 2,0,0,0,0 None 3.0 true true true 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2004 100172151 Street_NPCPos_Temp_Quest10020005 1 20000002 A 1 2,0,0,0,0 None 3.0 true true true 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2005 100172031 Street_NPCPos_Billy_Quest10020006 1 19900013,20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2006 100172011 Garage_NPCPos_Nocha_Quest10020003 1 20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2007 100172031 Garage_NPCPos_Billy_Quest10020003 1 20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2008 100172041 Garage_NPCPos_Anbi_Quest10020003 1 19900022,20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2009 100172052 Street_NPCPos_Temp_Quest10020015 1 19900022,20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2010 100172011 Street_NPCPos_Nocha_Quest10020008 1 19900014,20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2011 100172041 Street_NPCPos_Anbi_Quest10020006 1 19900026,20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2012 100172054 Street_NPCPos_Bangboo_Quest10020018 1 19900026,20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Small 0 AvatarCollider:true None 0 0 None None
|
||||
2013 100172055 Street_NPCPos_Temp_Quest10020020 1 19900028,20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2014 100172056 Street_NPCPos_Temp_Quest10020021 1 19900029,20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2015 100172091 Workshop_NPCPos_SisterLing 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200203 AvatarCollider:true None 0 0 None None
|
||||
2016 100172058 Street_NPCPos_BangbooA_Quest10020006 0 10000015,20000001 A 2 0,1.8,2,120,10 None 3.0 true true false 0 true false None Small 300101 AvatarCollider:true None 0 0 None None
|
||||
2017 100172059 Street_NPCPos_BangbooB_Quest10020006 0 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Small 0 AvatarCollider:true None 0 0 None None
|
||||
2018 100172060 Street_NPCPos_BangbooC_Quest10020006 0 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Small 0 AvatarCollider:true None 0 0 None None
|
||||
2019 100172061 Street_NPCPos_RamenStore 0 10000013,20000001 A 2 0,2.4,2,150,10 None 3.0 true true true 0 true false None Middle 0 AvatarCollider:true noodle:true 0 0 None None
|
||||
2020 100172062 Street_NPCPos_TestS 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Small 0 AvatarCollider:true None 0 0 None None
|
||||
2021 100172063 Street_NPCPos_TestL 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2022 100172021 WorkShop_NPCPos_Tsubaki_Quest10020106 1 20000002 A 1 2,0,0,0,0 None 3.0 true true true 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2023 100172064 WorkShop_NPCPos_Salesman_Quest10020103 1 20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2024 100171011 Workshop_NPCPos_Telephone 1 20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2025 100172082 Workshop_NPCPos_HollowPause 0 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2026 100172092 Workshop_NPCPos_HollowPause 0 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2027 100172081 Workshop_NPCPos_SisterLing 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200101 AvatarCollider:true None 0 0 None None
|
||||
2028 100173001 Workshop_NPCPos_VHSBangboo 0 19900052 A 2 9,2,2,90,10 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2029 100172101 Street_NPCPos_TestBear 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Large 0 AvatarCollider:true None 0 0 None None
|
||||
2031 100180131 Street_NPCPos_Quest10020151 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2032 100180714 Street_NPCPos_Quest10020152 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2033 100180812 Workshop_NPCPos_Bangboo05_VHS 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2034 100180161 Street_NPCPos_Quest10020154 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400302 AvatarCollider:true phone:true 1006 0 0 None None
|
||||
2035 100180714 Street_NPCPos_Quest10020155 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400309 AvatarCollider:false None 0 0 None None
|
||||
2036 100180171 Street_NPCPos_Quest10020156 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2037 100180912 Workshop_NPCPos_Bangboo01_VHS 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2038 100180712 Street_NPCPos_Quest10020157 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400409 SitDownCollider:true|WallCollider:false|AvatarCollider:false bag:false 0 0 None None
|
||||
2039 100180713 Street_NPCPos_Quest10020158 1 100701 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400109 AvatarCollider:true None 0 0 None None
|
||||
2040 100172021 Street_NPCPos_Quest10020118 1 20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2041 100172091 Workshop_NPCPos_ARole4 1 A 1 3,0,0,0,0 None 3.0 true true true 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2042 100172081 Workshop_NPCPos_ARole4 1 A 1 3,0,0,0,0 None 3.0 true true true 0 true false None Middle 200101 AvatarCollider:true None 0 0 None None
|
||||
2043 100172091 Workshop_NPCPos_ARole5 1 A 1 3,0,0,0,0 None 3.0 true true true 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2044 100172081 Workshop_NPCPos_ARole5 1 A 1 3,0,0,0,0 None 3.0 true true true 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2045 100172021 WorkShop_NPCPos_Tsubaki_Quest10020115 1 20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2046 100172091 Workshop_NPCPos_ARole6 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200201 AvatarCollider:true None 0 0 None None
|
||||
2047 100172081 Workshop_NPCPos_ARole6 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200101 AvatarCollider:true None 0 0 None None
|
||||
2051 100172091 Workshop_NPCPos_ARole1 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2052 100172081 Workshop_NPCPos_ARole1 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2053 100172091 Workshop_NPCPos_ARole2 1 A 1 3,0,0,0,0 None 3.0 true true true 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2054 100172081 Workshop_NPCPos_ARole2 1 A 1 3,0,0,0,0 None 3.0 true true true 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2055 100172091 Workshop_NPCPos_ARole3 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 200203 AvatarCollider:true None 0 0 None None
|
||||
2056 100172081 Workshop_NPCPos_ARole3 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 200103 AvatarCollider:true None 0 0 None None
|
||||
2057 100172091 Workshop_NPCPos_ARole7 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200203 AvatarCollider:true None 0 0 None None
|
||||
2058 100172081 Workshop_NPCPos_ARole7 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200103 AvatarCollider:true None 0 0 None None
|
||||
2059 100172091 Workshop_NPCPos_ARole8F 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200202 SitDownCollider:true|WallCollider:false|AvatarCollider:false phone:true 1003 0 0 None None
|
||||
2060 100172081 Workshop_NPCPos_ARole8 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200102 SitDownCollider:true|WallCollider:false|AvatarCollider:false phone:true 1004 0 0 None None
|
||||
2061 100172091 Workshop_NPCPos_ARole9 1 A 1 3,0,0,0,0 None 3.0 true true true 0 true false None Middle 200201 AvatarCollider:true None 0 0 None None
|
||||
2062 100172081 Workshop_NPCPos_ARole9 1 A 1 3,0,0,0,0 None 3.0 true true true 0 true false None Middle 200101 AvatarCollider:true None 0 0 None None
|
||||
2063 100180719 Street_NPCPos_Gate 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400409 SitDownCollider:true|WallCollider:false|AvatarCollider:false None 0 0 None None
|
||||
2064 100180712 Street_NPCPos_Quest10020151 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400417 SitDownCollider:true|WallCollider:false|AvatarCollider:false mask:true|computer:true 0,1026 0 0 None None
|
||||
2065 100180812 Workshop_NpcPos_Quest10020151 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400415 AvatarCollider:true None 0 0 None None
|
||||
2066 100180912 Workshop_NpcPos_Quest10020181 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400512 AvatarCollider:true None 0 0 None None
|
||||
2067 100172091 Workshop_NPCPos_ARole11 1 20000002 A 1 3,0,0,0,0 None 3.0 true true true 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2068 100172081 Workshop_NPCPos_ARole11 1 20000002 A 1 3,0,0,0,0 None 3.0 true true true 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2069 100172021 WorkShop_NPCPos_Tsubaki_Quest10020119 1 20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2070 100172061 Street_NPCPos_RamenStore 1 20000002 A 2 0,2.4,2,150,10 None 3.0 true true true 0 true false None Middle 200303 AvatarCollider:true noodle:false 0 0 None None
|
||||
2071 100172031 Street_NPCPos_Billy_Quest10020005 1 19900047 A 1 2,0,0,0,0 None 3.0 true true false 0 false false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2072 100172041 Street_NPCPos_Anbi_Quest10020005 1 19900048 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2073 100172031 Garage_NPCPos_Billy_Quest10020012 1 20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 false false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2074 100172041 Garage_NPCPos_Anbi_Quest10020012 1 20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2075 100172011 Garage_NPCPos_Nocha_Quest10020012 1 20000002 A 1 2,0,0,0,0 None 3.0 true true true 0 false false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2077 100172091 Workshop_NPCPos_ARole10 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200203 AvatarCollider:true None 0 0 None None
|
||||
2078 100172081 Workshop_NPCPos_ARole10 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200104 AvatarCollider:true None 0 0 None None
|
||||
2081 100172091 Workshop_NPCPos_ARole12 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2082 100172081 Workshop_NPCPos_ARole12 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2083 100180812 Street_NPCPos_Joe 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400412 AvatarCollider:true None 0 0 None None
|
||||
2084 100172042 Street_NPCPos_No11_01 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2085 100180912 Street_NPCPos_Xiute 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400512 AvatarCollider:true None 0 0 None None
|
||||
2086 100180718 Street_NPCPos_Keli_01 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400103 AvatarCollider:true None 0 0 None None
|
||||
2087 100172042 Workshop_NPCPos_No11_03 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2088 100180714 Workshop_NPCPos_DrawingRoom 1 20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2089 100180715 Street_NPCPos_Bangboo_Quest10020188 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Small 200702 AvatarCollider:true None 0 0 None None
|
||||
2090 100172042 Street_NPCPos_No11_01End 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2091 100172042 Street_NPCPos_No11_02 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2092 100180718 Street_NPCPos_Keli_02 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400103 AvatarCollider:true None 0 0 None None
|
||||
2093 100180718 Street_NPCPos_Keli_02End 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400103 AvatarCollider:true None 0 0 None None
|
||||
2094 100180717 Street_NPCPos_Quest10020155_02 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 200701 AvatarCollider:false None 0 0 None 30:200703
|
||||
2095 100172042 Street_NPCPos_No11_03End 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2096 100180718 Street_NPCPos_Keli_03End 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400103 AvatarCollider:true None 0 0 None None
|
||||
2097 100172181 Street_NPCPos_Woof 0 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200501 AvatarCollider:true None 0 0 None None
|
||||
2098 100172161 WorkShop_NPCPos_Bangboo_Quest10020106 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Small 200703 AvatarCollider:true None 0 0 None 30:200703
|
||||
2099 100172181 Street_NPCPos_Woof2 0 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200501 AvatarCollider:true None 0 0 None 45:200502
|
||||
2100 100172181 Street_NPCPos_Woof3 0 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200503 AvatarCollider:true None 0 0 None None
|
||||
2101 100172091 Garage_NPCPos_Quest10020024 1 A 1 3,0,0,0,0 None 3.0 true true true 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2102 100172081 Garage_NPCPos_Quest10020024 1 A 1 3,0,0,0,0 None 3.0 true true true 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2103 100172191 Street_NPCPos_Susie 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2104 100172201 Street_NPCPos_TinMaster01 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 200602 AvatarCollider:true None 0 0 None None
|
||||
2105 100172201 Street_NPCPos_TinMaster02 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 200601 AvatarCollider:true None 0 0 None None
|
||||
2106 100180715 Street_NPCPos_Bangboo_Quest10020140 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Small 200701 AvatarCollider:true None 0 0 None 30:200703
|
||||
2107 100180715 Workshop_NpcPos_Bangboo_Quest10020195 1 20000002 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Small 200701 AvatarCollider:true None 0 0 None 30:200703
|
||||
2108 100180715 Street_NPCPos_Bangboo_Quest10020196 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Small 200701 AvatarCollider:true None 0 0 None 30:200703
|
||||
2109 100180112 Street_NPCPos_PAFUMEI 1 20000002 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400204 AvatarCollider:true None 0 0 None None
|
||||
2110 100180412 Street_NPCPos_MEIKE 1 20000002 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400303 AvatarCollider:true None 0 0 None None
|
||||
2111 100172101 Street_NPCPos_Ben 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Large 0 AvatarCollider:true None 0 0 None None
|
||||
2112 100172071 Street_NPCPos_Anton 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2113 100172211 Street_NPCPos_OokumaMari 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2114 100172231 Street_NPCPos_Enzo 0 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2115 100172041 Street_NPCPos_Anbi02 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2116 100172211 Street_NPCPos_OokumaMari02 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2117 100172031 Street_NPCPos_Billy02 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2118 100172021 Street_NPCPos_Tsubaki 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2119 100172071 Street_NPCPos_Anton02 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2120 100172011 Street_NPCPos_Nocha02 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2121 100172021 Street_NPCPos_Tsubaki02 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2122 100172211 Street_NPCPos_OokumaMari04 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2123 100172101 Street_NPCPos_Ben02 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Large 0 AvatarCollider:true None 0 0 None None
|
||||
2124 100172211 Street_NPCPos_OokumaMari03 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2125 100172101 Street_NPCPos_Ben03 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Large 0 AvatarCollider:true None 0 0 None None
|
||||
2126 100172031 Street_NPCPos_Billy03 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2127 100172011 Street_NPCPos_Nocha03 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2128 100172021 Street_NPCPos_Tsubaki03 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2129 100172041 Street_NPCPos_Anbi03 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2130 100172101 Street_NPCPos_Ben04 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Large 0 AvatarCollider:true None 0 0 None None
|
||||
2131 100172211 Street_NPCPos_OokumaMari05 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2132 100172071 Street_NPCPos_Anton03 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2133 100172011 Street_NPCPos_Nocha04 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2134 100172031 Street_NPCPos_Billy04 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2135 100172041 Street_NPCPos_Anbi04 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2136 100180715 Workshop_NpcPos_Bangboo_Quest10020141 1 20000002 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Small 200701 AvatarCollider:true None 0 0 None 30:200703
|
||||
2140 100173012 Street_NPCPos_Schroeder02 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Small 400418 SitDownCollider:true|WallCollider:false|AvatarCollider:false bag:false|phone01:true 0,1017 0 0 None None
|
||||
2141 100173012 Street_NPCPos_Schroeder03 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Small 400409 SitDownCollider:true|WallCollider:false|AvatarCollider:false bag:false|phone02:true 0,1017 0 0 None None
|
||||
2142 100172042 Garage_NPCPos_No11 1 20000002 A 1 2,0,0,0,0 None 3.0 true true true 0 true false None Middle 200405 AvatarCollider:true None 0 0 None None
|
||||
2143 100172042 Garage_NPCPos_No11_02 1 20000002 A 1 2,0,0,0,0 None 3.0 true true true 0 true false None Middle 200403 AvatarCollider:true None 0 0 None None
|
||||
2144 100172042 Garage_NPCPos_No11_03 1 20000002 A 1 2,0,0,0,0 None 3.0 true true true 0 true false None Middle 200405 AvatarCollider:true None 0 0 None None
|
||||
2145 100180712 Street_NPCPos_Shepherd02 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400417 SitDownCollider:true|WallCollider:false|AvatarCollider:false mask:true|computer:true 0,1025 0 0 None None
|
||||
2146 100172091 Workshop_NPCPos_ARole13 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200201 AvatarCollider:true None 0 0 None None
|
||||
2147 100172081 Workshop_NPCPos_ARole13 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200101 AvatarCollider:true None 0 0 None None
|
||||
2148 100172091 Workshop_NPCPos_ARole14 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200202 AvatarCollider:true None 0 0 None None
|
||||
2149 100172081 Workshop_NPCPos_ARole14 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200102 AvatarCollider:true None 0 0 None None
|
||||
2150 100172091 Workshop_NPCPos_ARole15 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200203 AvatarCollider:true None 0 0 None None
|
||||
2151 100172081 Workshop_NPCPos_ARole15 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200103 AvatarCollider:true None 0 0 None None
|
||||
2152 100172091 Workshop_NPCPos_ARole16 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200204 SitDownCollider:true|WallCollider:false|AvatarCollider:false computer:true 1027 0 0 None None
|
||||
2153 100172081 Workshop_NPCPos_ARole16F 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200104 AvatarCollider:true None 0 0 None None
|
||||
2154 100172091 Workshop_NPCPos_ARole17F 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Small 200205 AvatarCollider:true gameboy:true 1022 0 0 None None
|
||||
2155 100172081 Workshop_NPCPos_ARole17 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Small 200105 AvatarCollider:true gameboy:true 1022 0 0 None None
|
||||
2156 100172042 Garage_NPCPos_No11_04 1 20000002 A 1 3,0,0,0,0 None 3.0 true true true 0 true false None Middle 200403 AvatarCollider:true None 0 0 None None
|
||||
2157 100172091 Workshop_NPCPos_ARole18 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2158 100172081 Workshop_NPCPos_ARole18 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
2159 100172091 Garage_NPCPos_Quest10020120 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200203 AvatarCollider:true None 0 0 None None
|
||||
2160 100172081 Garage_NPCPos_Quest10020120 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 200103 AvatarCollider:true None 0 0 None None
|
||||
3005 100173005 Workshop_NPCPos_Bangboo01_VHS 1 100701 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Small 0 AvatarCollider:true None 0 0 None None
|
||||
3006 100173006 Workshop_NPCPos_Bangboo02_VHS 1 100702 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Small 0 AvatarCollider:true None 0 0 None None
|
||||
3007 100173007 Workshop_NPCPos_Bangboo03_VHS 1 100703 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Small 0 AvatarCollider:true None 0 0 None None
|
||||
3008 100173008 Workshop_NPCPos_Bangboo04_VHS 1 100707 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Small 0 AvatarCollider:true None 0 0 None None
|
||||
3009 100173009 Workshop_NPCPos_Bangboo05_VHS 1 100708 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Small 0 AvatarCollider:true None 0 0 None None
|
||||
3011 100180711 Workshop_NPCPos_guest01_VHS 1 10200001 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400413 AvatarCollider:true None 0 0 None None
|
||||
3012 100181411 Workshop_NPCPos_guest02_VHS 1 10200002 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400414 AvatarCollider:true None 0 0 None None
|
||||
3013 100180511 Workshop_NPCPos_guest03_VHS 1 10200003 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400117 AvatarCollider:true bag:false 0 0 None None
|
||||
3014 100180511 Workshop_NPCPos_guest04_VHS 1 10200004 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400109 AvatarCollider:true None 0 0 None None
|
||||
3015 100180111 Workshop_NPCPos_guest05_VHS 1 10200005 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400309 AvatarCollider:true None 0 0 None None
|
||||
3016 100180211 Workshop_NPCPos_guest06_VHS 1 10200006 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400310 AvatarCollider:true None 0 0 None None
|
||||
3017 100180311 Workshop_NPCPos_guest01_VHS 1 10200007 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400215 AvatarCollider:true None 0 0 None None
|
||||
3018 100180411 Workshop_NPCPos_guest03_VHS 1 10200008 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400311 AvatarCollider:true None 0 0 None None
|
||||
3019 100181111 Workshop_NPCPos_guest02_VHS 1 10200009 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400510 AvatarCollider:true None 0 0 None 30:200703
|
||||
3020 100181011 Workshop_NPCPos_guest04_VHS 1 10200010 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400511 AvatarCollider:true None 0 0 None 30:200703
|
||||
3021 100180713 Workshop_NpcPos_VHS31020001 1 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400113 AvatarCollider:true bag:false 0 0 UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconNPCCircle2090.png None
|
||||
3022 100180714 Workshop_NpcPos_VHS31020002 1 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400310 AvatarCollider:true None 0 0 UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconNPCCircle2035.png 30:200703
|
||||
3023 100180715 Workshop_NpcPos_VHS31010001 1 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Small 200701 AvatarCollider:true None 0 0 None None
|
||||
3024 100180716 Workshop_NpcPos_VHS31010002 1 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Small 200701 AvatarCollider:true None 0 0 None 30:200703
|
||||
3025 100180713 Workshop_NpcPos_VHS31020001End 1 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400111 AvatarCollider:true None 0 0 UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconNPCCircle2090.png None
|
||||
3026 100180717 Workshop_NpcPos_VHS31020002_02 1 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Small 200701 AvatarCollider:true None 0 0 None None
|
||||
3027 100180714 Workshop_NpcPos_VHS31020002End 1 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400310 AvatarCollider:true None 0 0 UI/Sprite/A1DynamicLoad/IconRoleCircle/UnPacker/IconNPCCircle2035.png None
|
||||
3028 100180717 Workshop_NpcPos_VHS31020002_02End 1 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Small 200701 AvatarCollider:true None 0 0 None None
|
||||
4001 100180711 Street_Passerby_A1 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400409 SitDownCollider:true|WallCollider:false|AvatarCollider:false bag:false 0 0 None None
|
||||
4002 100181111 Street_Passerby_A2 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400507 SitDownCollider:true|WallCollider:false|AvatarCollider:false gameboy:true 1022 0 0 None None
|
||||
4003 100180311 Street_Passerby_B1 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400204 AvatarCollider:true None 0 0 None None
|
||||
4004 100181111 Street_Passerby_B2 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400509 AvatarCollider:true None 0 0 None None
|
||||
4005 100181311 Street_Passerby_C1 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400502 AvatarCollider:true phone:true 1029 0 0 None None
|
||||
4006 100181011 Street_Passerby_C2 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400506 SitDownCollider:true|WallCollider:false|AvatarCollider:false bag:false|phone02:true 0,1003 0 0 None None
|
||||
4007 100181511 Street_Passerby_D1 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400118 AvatarCollider:true None 0 0 None None
|
||||
4008 100180811 Street_Passerby_D2 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400421 AvatarCollider:true phone:true 1016 0 0 None None
|
||||
4009 100180711 Street_Passerby_09 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400402 AvatarCollider:true phone:true|bag:false 1014,0 0 0 None None
|
||||
4010 100180811 Street_Passerby_10 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400419 AvatarCollider:true None 0 0 None None
|
||||
4011 100180911 Street_Passerby_11 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400509 AvatarCollider:true None 0 0 None None
|
||||
4012 100181111 Street_Passerby_12 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400503 AvatarCollider:true None 0 0 None None
|
||||
4013 100181311 Street_Passerby_13 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400510 AvatarCollider:true None 0 0 None None
|
||||
4014 100180111 Street_Passerby_14 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400203 AvatarCollider:true None 0 0 None None
|
||||
4015 100181311 Street_Passerby_15 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400510 AvatarCollider:true None 0 0 None None
|
||||
4016 100180311 Street_Passerby_16 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400503 AvatarCollider:true None 0 0 None None
|
||||
4017 100180111 Street_Passerby_17 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400215 AvatarCollider:true None 0 0 None None
|
||||
4018 100180411 Street_Passerby_18 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400312 AvatarCollider:true None 0 0 None None
|
||||
4019 100180711 Street_Passerby_19 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400412 AvatarCollider:true None 0 0 None None
|
||||
4020 100181511 Street_Passerby_20 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400118 AvatarCollider:true None 0 0 None None
|
||||
4021 100180911 Street_Passerby_21 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400503 AvatarCollider:true None 0 0 None None
|
||||
4022 100180111 Street_Passerby_22 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400210 AvatarCollider:true None 0 0 None None
|
||||
4023 100180511 Street_Passerby_23 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400116 AvatarCollider:true bag:false 0 0 None None
|
||||
4024 100181011 Street_Passerby_24 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400512 AvatarCollider:true bag:false 0 0 None None
|
||||
4025 100180811 Street_Passerby_25 1 C 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400412 AvatarCollider:true None 0 0 None None
|
||||
4026 100180111 Street_Passerby_26 1 D 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400215 AvatarCollider:true None 0 0 None None
|
||||
4027 100180211 Street_Passerby_27 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400308 AvatarCollider:true None 0 0 None None
|
||||
4028 100180311 Street_Passerby_28 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400202 AvatarCollider:true phone:true 1010 0 0 None None
|
||||
4029 100181111 Street_Passerby_29 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400503 AvatarCollider:true None 0 0 None None
|
||||
4030 100180411 Street_Passerby_30 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400312 AvatarCollider:false None 0 0 None None
|
||||
4031 100180111 Street_Passerby_31 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400214 AvatarCollider:true None 0 0 None None
|
||||
4032 100180411 Street_Passerby_32 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400303 AvatarCollider:true None 0 0 None None
|
||||
4033 100181411 Street_Passerby_33 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400419 AvatarCollider:true None 0 0 None None
|
||||
4034 100180611 Street_Passerby_34 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400116 AvatarCollider:true bag:false 0 0 None None
|
||||
4035 100181511 Street_Passerby_35 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400116 AvatarCollider:true bag:false 0 0 None None
|
||||
4036 100180711 Street_Passerby_36 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400402 AvatarCollider:true phone:true 1016 0 0 None None
|
||||
4037 100181111 Street_Passerby_37 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400503 AvatarCollider:true None 0 0 None None
|
||||
4038 100180611 Street_Passerby_38 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400118 AvatarCollider:true bag:false 0 0 None None
|
||||
4039 100181311 Street_Passerby_39 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400512 AvatarCollider:true None 0 0 None None
|
||||
4040 100180711 Street_Passerby_40 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400402 AvatarCollider:true phone:true 1021 0 0 None None
|
||||
4041 100180211 Street_Passerby_41 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400309 AvatarCollider:true None 0 0 None None
|
||||
4042 100181411 Street_Passerby_42 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400411 AvatarCollider:true mask:false 0 0 None None
|
||||
4043 100180311 Street_Passerby_43 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400214 AvatarCollider:true None 0 0 None None
|
||||
4044 100180611 Street_Passerby_44 1 B 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400102 AvatarCollider:true phone_idle:true 1012 0 0 None None
|
||||
4045 100180511 Street_Passerby_45 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400102 AvatarCollider:true phone_idle:true 1008 0 0 None None
|
||||
4046 100181511 Street_Passerby_46 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400114 AvatarCollider:true bag:false 0 0 None None
|
||||
4047 100180111 Street_Passerby_47 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400211 AvatarCollider:true None 0 0 None None
|
||||
4048 100181511 Street_Passerby_48 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400111 AvatarCollider:true None 0 0 None None
|
||||
4049 100180411 Street_Passerby_49 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400302 AvatarCollider:true phone:true 1011 0 0 None None
|
||||
4050 100181011 Street_Passerby_50 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400503 AvatarCollider:true None 0 0 None None
|
||||
4051 100180911 Street_Passerby_51 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400509 AvatarCollider:true None 0 0 None None
|
||||
4052 100180411 Street_Passerby_52 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400303 AvatarCollider:true None 0 0 None None
|
||||
4053 100180111 Street_Passerby_53 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400216 AvatarCollider:true mask:true 0 0 None None
|
||||
4054 100181111 Street_Passerby_54 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400513 AvatarCollider:true gameboy02:true|bag:false 1023 0 0 None None
|
||||
4055 100181411 Street_Passerby_55 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400402 AvatarCollider:true phone:true 1017 0 0 None None
|
||||
4056 100180511 Street_Passerby_56 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400110 AvatarCollider:true mask:false 0 0 None None
|
||||
4057 100180711 Street_Passerby_57 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400413 AvatarCollider:true None 0 0 None None
|
||||
4058 100180811 Street_Passerby_58 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400103 AvatarCollider:true None 0 0 None None
|
||||
4059 100180611 Street_Passerby_59 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400111 AvatarCollider:true None 0 0 None None
|
||||
4060 100181511 Street_Passerby_60 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400110 AvatarCollider:true None 0 0 None None
|
||||
4061 100180711 Street_Passerby_61 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400410 SitDownCollider:true|WallCollider:false|AvatarCollider:false computer:true|bag:false 1025,0 0 0 None None
|
||||
4062 100180511 Street_Passerby_62 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400108 SitDownCollider:true|WallCollider:false|AvatarCollider:false phone_cafe:true|bag:false 1011,0 0 0 None None
|
||||
4063 100180211 Street_Passerby_63 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400302 AvatarCollider:true phone:true 1006 0 0 None None
|
||||
4064 100180311 Street_Passerby_64 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400215 AvatarCollider:true None 0 0 None None
|
||||
4065 100181411 Street_Passerby_65 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400402 AvatarCollider:true phone:true 1017 0 0 None None
|
||||
4066 100180511 Street_Passerby_66 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400117 AvatarCollider:true bag:false 0 0 None None
|
||||
4067 100181311 Street_Passerby_67 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400509 AvatarCollider:true None 0 0 None None
|
||||
4068 100181311 Street_Passerby_68 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400503 AvatarCollider:true None 0 0 None None
|
||||
4069 100181011 Street_Passerby_69 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400512 AvatarCollider:true None 0 0 None None
|
||||
4070 100180511 Street_Passerby_70 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400102 AvatarCollider:true phone_idle:true 1011 0 0 None None
|
||||
4071 100180311 Street_Passerby_71 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400210 AvatarCollider:true None 0 0 None None
|
||||
4072 100180311 Street_Passerby_72 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400202 AvatarCollider:true phone:true 1007 0 0 None None
|
||||
4073 100180211 Street_Passerby_73 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400210 AvatarCollider:true None 0 0 None None
|
||||
4074 100181011 Street_Passerby_74 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400511 AvatarCollider:true None 0 0 None None
|
||||
4075 100180711 Street_Passerby_75 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400408 SitDownCollider:true|WallCollider:false|AvatarCollider:false bag:false 0 0 None None
|
||||
4076 100180811 Street_Passerby_76 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400414 AvatarCollider:true None 0 0 None None
|
||||
4077 100180611 Street_Passerby_77 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400102 AvatarCollider:true phone_idle:true 1013 0 0 None None
|
||||
4078 100180411 Street_Passerby_78 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400302 AvatarCollider:true phone:true 1007 0 0 None None
|
||||
4079 100181511 Street_Passerby_79 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400112 AvatarCollider:true bag:false 0 0 None None
|
||||
4080 100180611 Street_Passerby_80 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400112 AvatarCollider:true bag:false 0 0 None None
|
||||
4081 100180711 Street_Passerby_81 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400405 AvatarCollider:true None 0 0 None None
|
||||
4082 100180111 Street_Passerby_82 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400211 AvatarCollider:true None 0 0 None None
|
||||
4083 100180411 Street_Passerby_83 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400302 AvatarCollider:true phone:true 1003 0 0 None None
|
||||
4084 100180311 Street_Passerby_84 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400204 AvatarCollider:true mask:false 0 0 None None
|
||||
4085 100180411 Street_Passerby_85 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400308 AvatarCollider:true None 0 0 None None
|
||||
4086 100180111 Street_Passerby_86 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
4087 100180211 Street_Passerby_87 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
4088 100180311 Street_Passerby_88 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
4089 100180311 Street_Passerby_89 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400202 AvatarCollider:true phone:true 1004 0 0 None None
|
||||
4090 100180111 Street_Passerby_90 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400207 SitDownCollider:true|WallCollider:false|AvatarCollider:false phone:true 1010 0 0 None None
|
||||
4091 100180411 Street_Passerby_91 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400303 AvatarCollider:true None 0 0 None None
|
||||
4092 100180511 Street_Passerby_92 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400107 SitDownCollider:true|WallCollider:false|AvatarCollider:false phone_ramen:true|bag:false 1010,0 0 0 None None
|
||||
4093 100180411 Street_Passerby_93 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
4094 100180811 Street_Passerby_94 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400421 AvatarCollider:true phone:true 1015 0 0 None None
|
||||
4095 100181411 Street_Passerby_95 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400402 AvatarCollider:true phone:true 1021 0 0 None None
|
||||
4096 100180711 Street_Passerby_96 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400402 AvatarCollider:true phone:true 1019 0 0 None None
|
||||
4097 100181411 Street_Passerby_97 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400415 AvatarCollider:true bag:false 0 0 None None
|
||||
4098 100181411 Street_Passerby_98 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400413 AvatarCollider:true None 0 0 None None
|
||||
4099 100180811 Street_Passerby_99 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400408 SitDownCollider:true|WallCollider:false|AvatarCollider:false None 0 0 None None
|
||||
4100 100180811 Street_Passerby_100 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400411 AvatarCollider:true None 0 0 None None
|
||||
4101 100180811 Street_Passerby_101 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400404 AvatarCollider:true phone02:true 0 0 None None
|
||||
4102 100180711 Street_Passerby_102 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400408 SitDownCollider:true|WallCollider:false|AvatarCollider:false None 0 0 None None
|
||||
4103 100181111 Street_Passerby_103 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
4104 100181111 Street_Passerby_104 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400509 AvatarCollider:true None 0 0 None None
|
||||
4105 100181111 Street_Passerby_105 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400502 AvatarCollider:true phone:true 1028 0 0 None None
|
||||
4106 100181011 Street_Passerby_106 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
4107 100180911 Street_Passerby_107 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400507 SitDownCollider:true|WallCollider:false|AvatarCollider:false gameboy:true 1023 0 0 None None
|
||||
4108 100181111 Street_Passerby_108 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
4109 100181511 Street_Passerby_109 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400106 SitDownCollider:true|WallCollider:false|AvatarCollider:false phone_bench:true|bag:false 1004,0 0 0 None None
|
||||
4110 100181511 Street_Passerby_110 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
4111 100180611 Street_Passerby_111 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400117 AvatarCollider:true bag:false 0 0 None None
|
||||
4112 100181511 Street_Passerby_112 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400115 SitDownCollider:true|WallCollider:false|AvatarCollider:false phone_cafe02:true 1006 0 0 None None
|
||||
4113 100180611 Street_Passerby_113 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400111 AvatarCollider:true None 0 0 None None
|
||||
4114 100181511 Street_Passerby_114 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:true None 0 0 None None
|
||||
4115 100181311 Street_Passerby_115 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400507 SitDownCollider:true|WallCollider:false|AvatarCollider:false gameboy:true 1023 0 0 None None
|
||||
4116 100181311 Street_Passerby_116 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400507 SitDownCollider:true|WallCollider:false|AvatarCollider:false gameboy:true 1022 0 0 None None
|
||||
4117 100180611 Street_Passerby_117 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400108 SitDownCollider:true|WallCollider:false|AvatarCollider:false phone_cafe:true 1008 0 0 None None
|
||||
4118 100181011 Street_Passerby_118 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400507 SitDownCollider:true|WallCollider:false|AvatarCollider:false gameboy:true 1023 0 0 None None
|
||||
4119 100180211 Street_Passerby_119 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400302 AvatarCollider:true phone:true 1009 0 0 None None
|
||||
4120 100180811 Street_Passerby_120 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400410 SitDownCollider:true|WallCollider:false|AvatarCollider:false computer:true|bag:false 1026,0 0 0 None None
|
||||
4123 100180811 Street_Passerby_123 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400409 SitDownCollider:true|WallCollider:false|AvatarCollider:false bag:false 0 0 None None
|
||||
4124 100180611 Street_Passerby_124 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400107 SitDownCollider:true|WallCollider:false|AvatarCollider:false phone_ramen:true|bag:false 1013,0 0 0 None None
|
||||
4125 100180711 Street_Passerby_125 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400409 SitDownCollider:true|WallCollider:false|AvatarCollider:false bag:false 0 0 None None
|
||||
4126 100181511 Street_Passerby_126 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400107 SitDownCollider:true|WallCollider:false|AvatarCollider:false phone_ramen:true|bag:false 1011,0 0 0 None None
|
||||
4127 100180911 Street_Passerby_127 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400507 SitDownCollider:true|WallCollider:false|AvatarCollider:false gameboy:true 1023 0 0 None None
|
||||
4128 100181511 Street_Passerby_128 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400107 SitDownCollider:true|WallCollider:false|AvatarCollider:false phone_ramen:true|bag:false 1005,0 0 0 None None
|
||||
4129 100180811 Street_Passerby_129 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400409 SitDownCollider:true|WallCollider:false|AvatarCollider:false bag:false 0 0 None None
|
||||
4130 100180711 Street_Passerby_130 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400420 AvatarCollider:true bag:false 0 0 None None
|
||||
4131 100180711 Street_Passerby_131 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400409 SitDownCollider:true|WallCollider:false|AvatarCollider:false bag:false 0 0 None None
|
||||
4132 100180511 Street_Passerby_132 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400102 AvatarCollider:true phone_idle:true 1006 0 0 None None
|
||||
4133 100180611 Workshop_Passerby_133 1 10200004 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400118 AvatarCollider:true None 0 0 None None
|
||||
4134 100181511 Workshop_Passerby_134 1 10200004 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400117 AvatarCollider:true bag:false 0 0 None None
|
||||
4135 100180611 Workshop_Passerby_135 1 10200004 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400110 AvatarCollider:true None 0 0 None None
|
||||
4136 100180311 Workshop_Passerby_136 1 10200006 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400210 AvatarCollider:true None 5000 5000 None None
|
||||
4137 100180411 Workshop_Passerby_137 1 10200006 A 1 1,0,0,0,0 None 3.0 true true false 0 true false None Middle 400309 AvatarCollider:true None 5000 5000 None None
|
||||
4138 100180811 Workshop_Passerby_138 1 20000002 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400411 AvatarCollider:true None 0 0 None None
|
||||
4139 100173241 Street_Passerby_139 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400512 AvatarCollider:true None 0 0 None None
|
||||
4140 100173242 Street_Passerby_140 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400511 AvatarCollider:true None 0 0 None None
|
||||
4141 100173243 Street_Passerby_141 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400302 AvatarCollider:true phone:true 1006 0 0 None None
|
||||
4142 100173244 Street_Passerby_142 3 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400118 AvatarCollider:true None 0 0 None None
|
||||
4143 100173245 Street_Passerby_143 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400415 AvatarCollider:true None 0 0 None None
|
||||
4144 100173246 Street_Passerby_144 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400512 AvatarCollider:true None 0 0 None None
|
||||
4145 100173247 Street_Passerby_145 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400112 AvatarCollider:true bag:false 0 0 None None
|
||||
4146 100173248 Street_Passerby_146 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400116 AvatarCollider:true bag:false 0 0 None None
|
||||
4147 100173249 Street_Passerby_147 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400512 AvatarCollider:true None 0 0 None None
|
||||
4148 100173250 Street_Passerby_148 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400511 AvatarCollider:true None 0 0 None None
|
||||
4149 100173251 Street_Passerby_149 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400216 AvatarCollider:true None 0 0 None None
|
||||
4150 100173252 Street_Passerby_150 3 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 400111 AvatarCollider:true None 0 0 None None
|
||||
4151 100180811 Street_Passerby_151 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400416 SitDownCollider:true|WallCollider:false|AvatarCollider:false None 0 0 None None
|
||||
4152 100180711 Street_Passerby_152 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Small 400418 AvatarCollider:true None 0 0 None 30:200703
|
||||
4153 100181111 Street_Passerby_153 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400508 AvatarCollider:true None 0 0 None None
|
||||
4501 100173501 Street_Passerby_501 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400512 AvatarCollider:true None 0 0 None None
|
||||
4502 100173502 Street_Passerby_502 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400117 AvatarCollider:true bag:false 0 0 None None
|
||||
4503 100173503 Street_Passerby_503 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Small 200703 AvatarCollider:true None 0 0 None None
|
||||
4504 100173010 Street_Passerby_121 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400303 AvatarCollider:true None 0 0 None None
|
||||
4505 100173011 Street_Passerby_122 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400213 AvatarCollider:true None 0 0 None None
|
||||
4506 100173012 Street_NPCPos_Schroeder 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Small 400418 SitDownCollider:true|WallCollider:false|AvatarCollider:false bag:false 0 0 None None
|
||||
4507 100173504 Street_Passerby_507 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400412 AvatarCollider:true None 0 0 None None
|
||||
4508 100173505 Street_Passerby_508 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400415 AvatarCollider:true None 0 0 None None
|
||||
4509 100173506 Street_Passerby_509 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400511 AvatarCollider:true None 0 0 None None
|
||||
4510 100173507 Street_Passerby_510 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400108 SitDownCollider:true|WallCollider:false|AvatarCollider:false phone_cafe:true|bag:false 1007,0 0 0 None None
|
||||
4511 100173508 Street_Passerby_511 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400411 AvatarCollider:true None 0 0 None None
|
||||
4512 100173509 Street_Passerby_512 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400115 SitDownCollider:true|WallCollider:false|AvatarCollider:false phone_cafe02:true 1012,0 0 0 None None
|
||||
4513 100173510 Street_Passerby_513 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400509 AvatarCollider:true None 0 0 None None
|
||||
4514 100173511 Street_Passerby_514 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400213 AvatarCollider:true None 0 0 None None
|
||||
4515 100173512 Street_Passerby_515 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400313 AvatarCollider:true bag:false|phone02:true 0,1006 0 0 None None
|
||||
4516 100173513 Street_Passerby_516 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400202 AvatarCollider:true phone:true 1003 0 0 None None
|
||||
4517 100173514 Street_Passerby_517 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400210 AvatarCollider:true None 0 0 None None
|
||||
4518 100173515 Street_Passerby_518 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400509 AvatarCollider:true None 0 0 None None
|
||||
4519 100173516 Street_Passerby_519 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400102 AvatarCollider:true phone_idle:true 1013 0 0 None None
|
||||
4520 100173517 Street_Passerby_520 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400413 AvatarCollider:true None 0 0 None None
|
||||
4521 100173518 Street_Passerby_521 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400418 AvatarCollider:true bag:false|mask:false 0 0 None None
|
||||
4522 100173519 Street_Passerby_522 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400403 AvatarCollider:true bag:false 0 0 None None
|
||||
4523 100173520 Street_Passerby_523 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400401 AvatarCollider:true None 0 0 None None
|
||||
4524 100173521 Street_Passerby_524 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400106 SitDownCollider:true|WallCollider:false|AvatarCollider:false phone_bench:true|mask:false|bag:false 1013,0,0 0 0 None None
|
||||
4525 100173522 Street_Passerby_525 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400211 AvatarCollider:true None 0 0 None None
|
||||
4526 100173523 Street_Passerby_526 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400509 AvatarCollider:true None 0 0 None None
|
||||
4527 100173524 Street_Passerby_527 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400413 AvatarCollider:true None 0 0 None None
|
||||
4528 100173525 Street_Passerby_528 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400503 AvatarCollider:true None 0 0 None None
|
||||
4529 100173526 Street_Passerby_529 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400511 AvatarCollider:true None 0 0 None None
|
||||
4530 100173527 Street_Passerby_530 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400110 AvatarCollider:true None 0 0 None None
|
||||
4531 100173528 Street_Passerby_531 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400511 AvatarCollider:true None 0 0 None None
|
||||
4532 100173529 Street_Passerby_532 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400509 AvatarCollider:true None 0 0 None None
|
||||
4533 100173530 Street_Passerby_533 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400415 AvatarCollider:true None 0 0 None None
|
||||
4534 100173531 Street_Passerby_534 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400415 AvatarCollider:true None 0 0 None None
|
||||
4535 100173532 Street_Passerby_535 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400112 AvatarCollider:true bag:false 0 0 None None
|
||||
4536 100173249 Street_Passerby_536 3 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400503 AvatarCollider:true mask:false 0 0 None None
|
||||
5001 100180191 Garage_Object_Car_01 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 None None 0 0 None None
|
||||
5002 100180191 Street_NPCPos_Car_Quest10020005 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 None None 0 0 None None
|
||||
5003 100171011 Street_ObjectPos_Newsstand 0 70000001 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
5004 100171011 Street_ObjectPos_02 0 70000002 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Large 0 None None 0 0 None None
|
||||
5005 100171011 Street_ObjectPos_03 0 70000003 A 1 2,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
5006 100171011 Street_ObjectPos_04 0 70000004 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Middle 0 None None 0 0 None None
|
||||
5007 100171011 Street_ObjectPos_05 0 70000005 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Large 0 None None 0 0 None None
|
||||
5008 100171011 Street_ObjectPos_06 0 70000006 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Large 0 None None 0 0 None None
|
||||
5009 100171011 Street_ObjectPos_07 0 70000007 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Middle 0 None None 0 0 None None
|
||||
5010 100171011 Street_ObjectPos_08 0 70000008 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
5011 100171011 Street_ObjectPos_09 0 70000009 A 1 1.5,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
5012 100171011 Street_ObjectPos_10 0 70000010 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Large 0 None None 0 0 None None
|
||||
5013 100171011 Street_ObjectPos_11 0 70000011 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Large 0 None None 0 0 None None
|
||||
5014 100171011 Street_ObjectPos_12 0 70000012 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
5015 100171011 Street_ObjectPos_13 0 70000013 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Middle 0 None None 0 0 None None
|
||||
5016 100171011 Garage_ObjectPos_14 0 70000014 A 1 3,0,0,0,0 None 3.0 true true false 0 false false None Middle 0 None None 0 0 None None
|
||||
5017 100171011 Garage_ObjectPos_15 0 70000015 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Middle 0 None None 0 0 None None
|
||||
5018 100171011 Garage_ObjectPos_16 0 70000016 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Middle 0 None None 0 0 None None
|
||||
5019 100171011 Garage_ObjectPos_17 0 70000017 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Middle 0 None None 0 0 None None
|
||||
5020 100171011 Garage_ObjectPos_18 0 70000018 A 1 1,0,0,0,0 None 3.0 true true false 0 false false None Small 0 None None 0 0 None None
|
||||
6001 100185001 Way8 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400217 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 0 5000 None None
|
||||
6002 100185014 Way8 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400407 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 4000 27000 None None
|
||||
6003 100185004 Way8 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400314 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 3000 45000 None None
|
||||
6004 100185015 Way8 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400120 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 7600 70000 None None
|
||||
6005 100185008 Way8 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400407 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 2540 86000 None None
|
||||
6006 100185005 Way8 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400120 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 7600 100000 None None
|
||||
6007 100185002 Way8 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400304 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 10000 0 None None
|
||||
6008 100185007 Way14 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400423 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true phone_walk:true 1014 21100 0 None None
|
||||
6009 100185013 Way14 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400505 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true phone_walk:true 1008 0 36000 None None
|
||||
6010 100185006 Way14 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400105 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true phone_walk:true 1015 20400 72000 None None
|
||||
6011 100185011 Way13 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400504 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 11600 0 None None
|
||||
6012 100185003 Way13 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400205 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 6700 32000 None None
|
||||
6013 100185001 Way13 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400206 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true phone:true 1004 0 64000 None None
|
||||
6014 100185010 Way13 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400504 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 11600 96000 None None
|
||||
6015 100185003 Way13 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400304 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 0 0 None None
|
||||
6016 100185001 Way13 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400406 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 0 0 None None
|
||||
6017 100185005 Way6 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400119 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true bag:false 2960 0 None None
|
||||
6018 100185014 Way6 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400406 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 0 36000 None None
|
||||
6019 100185015 Way6 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400119 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true bag:false 2960 72000 None None
|
||||
6020 100185003 Way19 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400206 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true phone:true 1006 0 0 None None
|
||||
6021 100185009 Way19 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400504 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 13000 36000 None None
|
||||
6022 100185001 Way19 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400205 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 7500 72000 None None
|
||||
6023 100185008 Way12 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400406 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 0 10000 None None
|
||||
6024 100185006 Way12 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400119 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 3000 46000 None None
|
||||
6025 100185007 Way12 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400406 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 0 82000 None None
|
||||
6026 100185015 Way10 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400105 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true phone_walk:true 1017 2700 0 None None
|
||||
6027 100185007 Way10 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400423 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true phone_walk:true 1016 8700 36000 None None
|
||||
6028 100185004 Way10 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400305 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true phone:true 1010 0 72000 None None
|
||||
6029 100185006 Way17 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400119 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 2960 0 None None
|
||||
6030 100185008 Way17 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400406 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 0 48000 None None
|
||||
6031 100185005 Way6 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400120 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 12000 0 None None
|
||||
6032 100185002 Way6 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400304 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 8000 20000 None None
|
||||
6033 100185008 Way6 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400407 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 530 38000 None None
|
||||
6034 100185004 Way6 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400314 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 0 56000 None None
|
||||
6035 100185006 Way6 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400120 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 12000 84000 None None
|
||||
6036 100185007 Way6 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400407 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 530 96000 None None
|
||||
6037 100185005 Way12 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400120 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 5000 96000 None None
|
||||
6038 100185014 Way17 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400406 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 0 0 None None
|
||||
6039 100185007 Way17 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400406 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 0 36000 None None
|
||||
6040 100185015 Way17 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400119 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true bag:false 2960 72000 None None
|
||||
6041 100185001 Way12 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400206 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true phone:true 1010 0 5000 None None
|
||||
6042 100185003 Way12 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400205 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 7500 37000 None None
|
||||
6043 100185011 Way12 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400504 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 13000 69000 None None
|
||||
6044 100185010 Way12 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400504 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 13000 101000 None None
|
||||
6045 100185003 Way6 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400304 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 0 76000 None None
|
||||
6046 100185001 Way6 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400406 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 4000 95000 None None
|
||||
6047 100185009 Way11 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400504 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 5500 0 None None
|
||||
6048 100185003 Way11 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400205 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 0 36000 None None
|
||||
6049 100185011 Way11 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400504 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 5500 72000 None None
|
||||
6050 100185010 Way9 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400514 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true gameboy_walk:true 1023 0 0 None None
|
||||
6051 100185013 Way9 2 A 1 2,0,0,0,0 None 3.0 true true false 50001 true false None Middle 400505 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true phone_walk:true 1011 0 36000 None None
|
||||
6052 100185008 Way9 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400422 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 0 72000 None None
|
||||
6053 100185006 Way18 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400120 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 6300 0 None None
|
||||
6054 100185015 Way18 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400119 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true bag:false 18000 36000 None None
|
||||
6055 100185002 Way18 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 400314 SitDownCollider:false|AvatarCollider:false|WalkCollider:false|WallCollider:true None 0 72000 None None
|
||||
7001 100184011 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 0 None None
|
||||
7002 100184021 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 10000 None None
|
||||
7003 100184111 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 30000 None None
|
||||
7004 100184211 Way103 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 600000 60000 None None
|
||||
7005 100184011 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 10000 None None
|
||||
7006 100184021 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 0 None None
|
||||
7007 100184111 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 39000 None None
|
||||
7008 100184221 Way103 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 600000 60000 None None
|
||||
7009 100184121 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 55000 None None
|
||||
7010 100184121 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 30000 None None
|
||||
7011 100184111 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 49000 None None
|
||||
7012 100184111 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 49000 None None
|
||||
7013 100184121 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 39000 None None
|
||||
7014 100184121 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 55000 None None
|
||||
7015 100184111 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 30000 0 None None
|
||||
7016 100184111 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 30000 5000 None None
|
||||
7017 100184121 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 30000 5000 None None
|
||||
7018 100184121 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 30000 0 None None
|
||||
7101 100184011 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 0 None None
|
||||
7102 100184021 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 10000 None None
|
||||
7103 100184111 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 30000 None None
|
||||
7104 100184211 Way103 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 600000 60000 None None
|
||||
7105 100184011 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 10000 None None
|
||||
7106 100184021 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 0 None None
|
||||
7107 100184111 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 39000 None None
|
||||
7108 100184221 Way103 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 600000 60000 None None
|
||||
7109 100184121 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 55000 None None
|
||||
7110 100184121 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 30000 None None
|
||||
7111 100184111 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 49000 None None
|
||||
7112 100184111 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 49000 None None
|
||||
7113 100184121 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 39000 None None
|
||||
7114 100184121 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 60000 55000 None None
|
||||
7115 100184111 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 30000 0 None None
|
||||
7116 100184111 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 30000 5000 None None
|
||||
7117 100184121 Way101 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 30000 5000 None None
|
||||
7118 100184121 Way102 2 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 AvatarCollider:false|WalkCollider:false|WallCollider:true None 30000 0 None None
|
||||
9001 100171011 Street_NPCPos_Test 0 10000008 A 1 2,0,0,0,0 None 3.0 true true false 0 true false None Small 0 None None 0 0 None None
|
||||
9002 100170111 Street_NPCPos_Test 0 19900001 A 1 2,0,0,0,0 None 3.0 true true false 0 true true None Small 0 None None 0 0 None None
|
||||
9003 100170111 Street_NPCPos_Test 0 19900000 A 1 2,0,0,0,0 None 3.0 true true false 0 true true None Small 0 None None 0 0 None None
|
||||
9004 100170111 Street_NPCPos_Test 0 19900000 B 1 2,0,0,0,0 None 3.0 true true false 0 true true None Middle 0 None None 0 0 None None
|
||||
9005 100172011 Street_NPCPos_Test 0 19900002 A 1 2,0,0,0,0 None 3.0 true true false 0 true true None Middle 0 None None 0 0 None None
|
||||
9006 100172021 Street_NPCPos_Test 0 19900003 A 1 2,0,0,0,0 None 3.0 true true false 0 true true None Small 0 None None 0 0 None None
|
||||
9007 10086 Workshop_NPCPos_Test 0 100860 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 None None 0 0 None None
|
||||
9008 100172011 Workshop_NPCPos_Test 1 10000003 A 1 2,0,0,0,0 None 3.0 true true false 0 true true None Middle 0 None None 0 0 None None
|
||||
9009 100172053 Street_NPCPos_Quest 1 A 1 2,0,0,0,0 None 3.0 true true false 0 true true None Middle 0 None None 0 0 None None
|
||||
9010 100172091 Workshop_NPCPos_ARoleTest 1 A 1 3,0,0,0,0 None 3.0 true true false 0 true false None Middle 0 None None 0 0 None None
|
|
443
assets/TemplateCollections/NPCTransformTemplateCollection.tsv
Normal file
443
assets/TemplateCollections/NPCTransformTemplateCollection.tsv
Normal file
|
@ -0,0 +1,443 @@
|
|||
ID PositionX PositionY PositionZ RotationX RotationY RotationZ Section
|
||||
Street_Teleport_ToGrocery -16.73 0.3 -5.624 0.0 180.0 0.0 1
|
||||
Street_Teleport_ToRamenStore 5.41 0.32 -1.36 0.0 0.0 0.0 1
|
||||
Street_Teleport_ToAudioVideoStore 18.23 0.36 -9.16 0.0 180.0 0.0 1
|
||||
Street_PlayerPos_Default 29.125 0.0 -4.375 0.0 270.0 0.0 1
|
||||
Street_PlayerPos_FromWorkshop 17.541 0.34003 5.481 0.0 193.27106 0.0 1
|
||||
Street_PlayerPos_FromGarage 12.89 0.34 10.71725 0.0 179.08109 0.0 1
|
||||
Street_PlayerPos_FromGrocery -17.177 0.0 0.0 0.0 0.0 0.0 1
|
||||
Street_NPCPos_ToWorkshop 18.243 0.557 8.079 0.0 209.99998 0.0 1
|
||||
Street_NPCPos_Smithy 18.208 0.95 -12.138 0.0 180.0 0.0 1
|
||||
Street_NPCPos_ToGarage 12.83 0.39287 14.673 0.0 180.0 0.0 1
|
||||
Street_NPCPos_Test 0.75 0.31757 -4.5 0.0 90.0 0.0 1
|
||||
Street_NPCPos_Quest 7.875 0.5 -2.125 0.0 185.0 0.0 1
|
||||
Street_NPCPos_RamenStore 5.678 0.9 1.753 0.0 185.0 0.0 1
|
||||
Street_NPCPos_TestS 6.761 0.3 -2.028 0.0 185.0 0.0 1
|
||||
Street_NPCPos_TestL 9.04 0.5 -2.227 0.0 185.0 0.0 1
|
||||
Street_NPCPos_Billy_Quest10020005 37.245 0.35 -1.786 0.0 0.0 0.0 1
|
||||
Street_NPCPos_Anbi_Quest10020005 -22.37 0.36 -7.05 0.0 180.0 0.0 1
|
||||
Street_NPCPos_Car_Quest10020005 37.43 0.75 3.26 0.0 270.0 0.0 1
|
||||
Street_NPCPos_Temp_Quest10020005 20.275 0.35 -10.2 0.0 326.98425 0.0 1
|
||||
Street_NPCPos_Billy_Quest10020006 -28.05087 0.5 -4.7 0.0 52.99999 0.0 1
|
||||
Street_NPCPos_Anbi_Quest10020006 -26.5 0.5 -5.98 0.0 0.0 0.0 1
|
||||
Street_NPCPos_Nocha_Quest10020008 -1.042 0.393 -3.014 0.0 90.0 0.0 1
|
||||
Street_NPCPos_Temp_Quest10020015 19.36 0.393 1.37 0.0 29.52794 0.0 1
|
||||
Street_NPCPos_Bangboo_Quest10020018 11.3 0.393 -0.25 0.0 180.0 0.0 1
|
||||
Street_NPCPos_Temp_Quest10020020 -9.17 0.393 -10.86 0.0 0.0 0.0 1
|
||||
Street_NPCPos_Temp_Quest10020021 6.67203 0.393 -8.174 0.0 84.99999 0.0 1
|
||||
Street_NPCPos_BangbooA_Quest10020006 -16.869 0.729 -8.124 0.0 0.0 0.0 1
|
||||
Street_NPCPos_BangbooB_Quest10020006 -17.556 0.729 -8.124 0.0 0.0 0.0 1
|
||||
Street_NPCPos_BangbooC_Quest10020006 -16.186 0.729 -8.097 0.0 0.0 0.0 1
|
||||
Street_CameraPos_Grocery -16.866 0.98 -1.508 0.0 180.0 0.0 1
|
||||
Street_CameraPos_RamenStore 2.48 2.45 -2.52 10.60003 45.5 0.0 1
|
||||
Street_CameraPos_RamenStore_PC 2.67 2.4 -2.29 10.8 44.0 0.0 1
|
||||
Street_CameraPos_Workshop 18.71 0.91 -9.14 10.60001 180.0 0.0 1
|
||||
TriggerPos_1 35.5 0.31757 -4.5 0.0 270.0 0.0 1
|
||||
Street_NPCPos_Grocery -18.928 0.95 -9.358 0.0 324.60001 0.0 1
|
||||
Street_NPCPos_TestBear 10.929 0.5 -2.392 0.0 185.0 0.0 1
|
||||
Street_PlayerPos_FromGarage2 4.15 0.0 19.17 0.0 270.0 0.0 1
|
||||
Street_NPCPos_ToGarage2 8.618 0.39287 19.235 0.0 270.0 0.0 1
|
||||
Street_Passerby_A1 6.168 0.35 0.017 0.0 0.0 0.0 1
|
||||
Street_Passerby_A2 7.0 0.48 -0.027 0.0 0.0 0.0 1
|
||||
Street_Passerby_B1 14.832 0.35 1.667 0.0 169.99998 0.0 1
|
||||
Street_Passerby_B2 15.41 0.35 1.09 0.0 240.0 0.0 1
|
||||
Street_Passerby_C1 -27.068 0.35 5.609 0.0 230.92207 0.0 1
|
||||
Street_Passerby_C2 -26.701 0.35 6.222 0.0 298.08884 0.0 1
|
||||
Street_Passerby_D1 -12.857 0.35 -11.668 0.0 32.81414 0.0 1
|
||||
Street_Passerby_D2 -12.635 0.35 -10.965 0.0 189.98178 0.0 1
|
||||
Street_ObjectPos_08 -14.573 -0.013 -12.512 0.0 0.0 0.0 1
|
||||
Street_ObjectPos_10 -14.303 1.375 -11.119 0.0 0.0 0.0 1
|
||||
Street_ObjectPos_09 -13.948 0.092 -18.786 0.0 0.0 0.0 1
|
||||
Street_Passerby_09 -5.95 0.35 11.106 0.0 32.66373 0.0 1
|
||||
Street_Passerby_10 -5.734 0.35 12.094 0.0 176.94084 0.0 1
|
||||
Street_Passerby_11 2.162 0.4 -9.208 0.0 86.23466 0.0 1
|
||||
Street_Passerby_12 2.898 0.4 -9.705 0.0 344.81543 0.0 1
|
||||
Street_Passerby_13 16.917 0.35 -10.73 0.0 196.76297 0.0 1
|
||||
Street_Passerby_14 16.337 0.35 -10.233 0.0 150.0 0.0 1
|
||||
Street_Passerby_15 21.459 0.36 -8.39 0.0 231.98558 0.0 1
|
||||
Street_Passerby_16 20.742 0.35 -8.932 0.0 48.55833 0.0 1
|
||||
Street_Passerby_17 15.15 0.35 7.51 0.0 212.18704 0.0 1
|
||||
Street_Passerby_18 14.808 0.35 6.799 0.0 29.95915 0.0 1
|
||||
Street_Passerby_19 -9.383 0.35 -0.624 0.0 261.22681 0.0 1
|
||||
Street_Passerby_20 -10.141 0.35 -1.371 0.0 64.0559 0.0 1
|
||||
Street_Passerby_21 -17.508 0.35 -0.558 0.0 339.64786 0.0 1
|
||||
Street_Passerby_22 -17.19 0.35 0.057 0.0 286.36243 0.0 1
|
||||
Street_Passerby_23 -11.63 0.35 -18.32 0.0 291.77817 0.0 1
|
||||
Street_Passerby_24 -12.63 0.35 -18.43 0.0 27.8 0.0 1
|
||||
Street_Passerby_25 -11.539 0.35 -17.535 0.0 234.79996 0.0 1
|
||||
Street_Passerby_26 -13.04 0.35 -18.03 0.0 66.79999 0.0 1
|
||||
Street_Passerby_27 -26.85 0.569 12.797 0.0 20.89114 0.0 1
|
||||
Street_Passerby_28 -27.431 0.38 13.319 0.0 223.54056 0.0 1
|
||||
Street_Passerby_29 22.296 0.35 -8.766 0.0 151.64432 0.0 1
|
||||
Street_Passerby_30 22.839 0.528 -9.841 0.0 332.39041 0.0 1
|
||||
Street_Passerby_31 -34.693 0.373 12.751 0.0 324.8782 0.0 1
|
||||
Street_Passerby_32 -35.538 0.3793 13.14 0.0 116.70426 0.0 1
|
||||
Street_NPCPos_Quest10020151 -4.574 0.3346 1.6568 0.0 10.32042 0.0 1
|
||||
Street_NPCPos_Quest10020152 14.23 0.35 -9.95 0.0 0.0 0.0 1
|
||||
Street_NPCPos_Quest10020153 11.12 0.4 -8.17 0.0 0.0 0.0 1
|
||||
Street_NPCPos_Quest10020154 24.721 0.348 4.248 0.0 289.53577 0.0 1
|
||||
Street_NPCPos_Quest10020155 -1.79 0.395 -21.504 0.0 321.61935 0.0 1
|
||||
Street_NPCPos_Quest10020156 27.16 0.35 -1.49 0.0 190.0 0.0 1
|
||||
Street_NPCPos_Quest10020157 3.28 0.35 1.465 0.0 90.0 0.0 1
|
||||
Street_NPCPos_Quest10020158 1.35 0.4 -1.38 0.0 180.0 0.0 1
|
||||
Street_Passerby_33 -26.297 0.35 -8.271 0.0 123.11625 0.0 1
|
||||
Street_Passerby_34 -25.442 0.35 -8.919 0.0 318.86185 0.0 1
|
||||
Street_Passerby_35 10.662 0.37 1.331 0.0 233.42654 0.0 1
|
||||
Street_Passerby_36 10.038 0.36 1.146 0.0 193.91667 0.0 1
|
||||
Street_Passerby_37 1.222 0.35 17.124 0.0 73.19746 0.0 1
|
||||
Street_Passerby_38 2.177 0.35 17.239 0.0 295.93552 0.0 1
|
||||
Street_Passerby_39 -7.65 0.35 -11.34 0.0 317.07599 0.0 1
|
||||
Street_Passerby_40 -8.56 0.35 -10.89 0.0 62.40825 0.0 1
|
||||
Street_Passerby_41 -21.485 0.35 -7.556 0.0 231.75189 0.0 1
|
||||
Street_Passerby_42 -22.217 0.36 -7.046 0.0 135.27699 0.0 1
|
||||
Street_Passerby_43 -26.552 0.355 0.922 0.0 329.71353 0.0 1
|
||||
Street_Passerby_44 -26.563 0.36 1.809 0.0 203.36967 0.0 1
|
||||
Street_Passerby_45 -29.2 0.39 -5.888 0.0 61.42846 0.0 1
|
||||
Street_Passerby_46 -14.932 0.35 -29.664 0.0 79.99999 0.0 1
|
||||
Street_Passerby_47 11.51 0.35 -13.93 0.0 209.63834 0.0 1
|
||||
Street_Passerby_48 -22.751 0.36 -7.545 0.0 109.76276 0.0 1
|
||||
Street_Passerby_49 2.386 0.4 -9.954 0.0 19.77401 0.0 1
|
||||
Street_Passerby_50 3.13 0.4 -9.31 0.0 245.81375 0.0 1
|
||||
Street_Passerby_51 -2.53 0.35 -29.03 0.0 20.00001 0.0 1
|
||||
Street_ObjectPos_11 -6.0202 1.62 -36.027 0.0 0.0 0.0 1
|
||||
Street_Passerby_52 -1.89 0.35 -29.04 0.0 330.0 0.0 1
|
||||
Street_Passerby_53 -5.976 0.35 -1.683 0.0 295.77307 0.0 1
|
||||
Street_Passerby_54 -6.768 0.35 -1.331 0.0 119.76264 0.0 1
|
||||
Street_Passerby_55 2.566 0.35 -1.384 0.0 65.57031 0.0 1
|
||||
Street_Passerby_56 3.203 0.35 -1.407 0.0 340.54376 0.0 1
|
||||
Street_Passerby_57 -19.31 0.35 -7.24 0.0 50.0 0.0 1
|
||||
Street_Passerby_58 -18.45 0.35 -6.99 0.0 270.0 0.0 1
|
||||
Street_Passerby_59 -2.315 0.35 -25.478 0.0 240.0 0.0 1
|
||||
Street_Passerby_60 -2.538 0.35 -26.063 0.0 20.00001 0.0 1
|
||||
Street_Passerby_61 -4.613 0.3373 0.009 0.0 171.87192 0.0 1
|
||||
Street_Passerby_62 -4.637 0.357 1.647 0.0 184.25121 0.0 1
|
||||
Street_Passerby_63 16.305 0.35 -10.866 0.0 69.14664 0.0 1
|
||||
Street_Passerby_64 17.0 0.35 -10.3 0.0 212.32573 0.0 1
|
||||
Street_Passerby_65 9.307 0.38 -28.054 0.0 205.75116 0.0 1
|
||||
Street_Passerby_66 9.613 0.38 -29.102 0.0 332.5571 0.0 1
|
||||
Street_Passerby_67 -7.099 0.4991 11.649 0.0 63.06116 0.0 1
|
||||
Street_Passerby_68 -6.042 0.35 12.561 0.0 227.34982 0.0 1
|
||||
Street_Passerby_69 22.433 0.35 6.054 0.0 317.61322 0.0 1
|
||||
Street_Passerby_70 -19.002 0.35 -1.416 0.0 154.39163 0.0 1
|
||||
Street_Passerby_71 -25.812 0.71 15.861 0.0 317.13211 0.0 1
|
||||
Street_ObjectPos_06 -26.43 1.8 16.614 0.0 0.0 0.0 1
|
||||
Street_ObjectPos_07 -24.915 0.996 12.736 0.0 0.0 0.0 1
|
||||
Street_Passerby_72 32.834 0.35 -7.017 0.0 325.03073 0.0 1
|
||||
Street_Passerby_73 -7.586 0.4 -0.346 0.0 136.72357 0.0 1
|
||||
Street_Passerby_74 -26.168 0.5651 12.814 0.0 205.99687 0.0 1
|
||||
Street_ObjectPos_05 -26.783 1.263 10.008 0.0 110.0 0.0 1
|
||||
Street_Passerby_75 -26.378 0.35 6.141 0.0 288.5228 0.0 1
|
||||
Street_Passerby_76 -6.893 0.64 15.257 0.0 50.22827 0.0 1
|
||||
Street_Passerby_77 -11.306 0.35 -9.496 0.0 119.16231 0.0 1
|
||||
Street_Passerby_78 -32.834 0.35 -2.719 0.0 50.0 0.0 1
|
||||
Street_ObjectPos_02 -35.7 1.556 -6.62 0.0 0.0 0.0 1
|
||||
Street_Passerby_79 -35.854 0.38 4.449 0.0 330.0 0.0 1
|
||||
Street_Passerby_80 -0.168 0.388 21.145 0.0 247.54602 0.0 1
|
||||
Street_ObjectPos_13 1.141 0.836 15.84 0.0 0.0 0.0 1
|
||||
Street_Passerby_81 9.372 0.36 -8.746 0.0 319.89386 0.0 1
|
||||
Street_NPCPos_Quest10020118 0.46 0.4 16.07 0.0 132.127 0.0 1
|
||||
Street_NPCPos_Joe 14.487 0.344 7.658 0.0 117.47181 0.0 1
|
||||
Street_Passerby_82 1.345 0.35 -29.269 0.0 318.21954 0.0 1
|
||||
Street_Passerby_83 -29.28 0.36 -6.019 0.0 92.8725 0.0 1
|
||||
Street_Passerby_84 -20.485 0.35 -8.332 0.0 218.35194 0.0 1
|
||||
Street_Passerby_85 11.059 0.35 5.281 0.0 120.00001 0.0 1
|
||||
Street_Passerby_86 12.09 0.36 -5.24 0.0 320.0 0.0 1
|
||||
Street_Passerby_87 12.09 0.36 -5.24 0.0 320.0 0.0 1
|
||||
Street_Passerby_88 12.09 0.36 -5.24 0.0 320.0 0.0 1
|
||||
Street_Passerby_89 12.743 0.35 -10.13 0.0 52.06183 0.0 1
|
||||
Street_Passerby_90 -26.65 0.36 6.866 0.0 260.0 0.0 1
|
||||
Street_Passerby_91 -13.317 0.35 -1.324 0.0 154.53731 0.0 1
|
||||
Street_Passerby_92 7.02 0.33 0.0589 0.0 0.0 0.0 1
|
||||
Street_Passerby_93 12.09 0.36 -5.24 0.0 320.0 0.0 1
|
||||
Street_Passerby_94 24.156 0.36 -0.589 0.0 258.23029 0.0 1
|
||||
Street_Passerby_95 -8.074 0.35 -11.114 0.0 321.74228 0.0 1
|
||||
Street_Passerby_96 32.996 0.35 -7.036 0.0 298.86584 0.0 1
|
||||
Street_Passerby_97 -2.633 0.35 -25.815 0.0 294.18304 0.0 1
|
||||
Street_Passerby_98 -14.06 0.36 -7.276 0.0 289.05328 0.0 1
|
||||
Street_Passerby_99 -26.389 0.356 7.356 0.0 257.54462 0.0 1
|
||||
Street_Passerby_100 28.999 0.36 -7.249 0.0 36.28022 0.0 1
|
||||
Street_Passerby_101 4.87 0.36 -29.65 0.0 180.0 0.0 1
|
||||
Street_Passerby_102 -26.387 0.35 7.338 0.0 249.63678 0.0 1
|
||||
Street_Passerby_103 12.09 0.31 -5.24 0.0 320.0 0.0 1
|
||||
Street_Passerby_104 14.6 0.36 8.1 0.0 210.0 0.0 1
|
||||
Street_Passerby_105 2.127 0.4 -9.184 0.0 33.36407 0.0 1
|
||||
Street_Passerby_106 12.09 0.36 -5.24 0.0 320.0 0.0 1
|
||||
Street_Passerby_107 3.32 0.48 1.472 0.0 90.0 0.0 1
|
||||
Street_Passerby_108 12.09 0.36 -5.24 0.0 320.0 0.0 1
|
||||
Street_Passerby_109 -26.7 0.36 7.295 0.0 260.0 0.0 1
|
||||
Street_Passerby_110 12.09 0.36 -5.24 0.0 320.0 0.0 1
|
||||
Street_Passerby_111 -14.558 0.35 -8.069 0.0 288.58353 0.0 1
|
||||
Street_Passerby_112 -4.577 0.353 1.663 0.0 194.16655 0.0 1
|
||||
Street_Passerby_113 11.049 0.35 5.16 0.0 115.38074 0.0 1
|
||||
Street_Passerby_114 12.09 0.36 -5.24 0.0 320.0 0.0 1
|
||||
Street_NPCPos_Xiute 15.328 0.347 7.214 0.0 298.45078 0.0 1
|
||||
Street_NPCPos_No11_01 5.784 0.35 -35.839 0.0 240.0 0.0 1
|
||||
Street_NPCPos_Keli_01 5.12 0.36 -36.21 0.0 50.0 0.0 1
|
||||
Street_NPCPos_No11_01End 6.64 0.35 -35.06 0.0 10.0 0.0 1
|
||||
Street_Passerby_501 -26.61 0.69 16.044 0.0 28.75916 0.0 1
|
||||
Street_Passerby_502 -22.804 0.36 -7.391 0.0 60.44901 0.0 1
|
||||
Street_Passerby_503 -22.058 0.36 -7.339 0.0 324.42499 0.0 1
|
||||
Street_Passerby_115 3.28 0.4537 1.464 0.0 90.0 0.0 1
|
||||
Street_Passerby_116 8.16 0.48 2.362 0.0 270.0 0.0 1
|
||||
Street_Passerby_117 -4.593 0.351 0.1033 0.0 343.36163 0.0 1
|
||||
Street_Passerby_118 -4.43 0.49 1.48 0.0 180.0 0.0 1
|
||||
Street_Passerby_119 -25.591 0.35 -6.895 0.0 315.20914 0.0 1
|
||||
Street_Passerby_120 -4.667 0.337 1.677 0.0 345.07632 0.0 1
|
||||
Street_NPCPos_Bangboo_Quest10020188 2.652 0.344 -0.622 0.0 74.99999 0.0 1
|
||||
Street_NPCPos_Bangboo_Quest10020196 -3.648 0.353 -17.817 0.0 220.05724 0.0 1
|
||||
Street_NPCPos_Bangboo_Quest10020140 21.47 0.344 5.908 0.0 0.0 0.0 1
|
||||
Street_Passerby_121 -35.256 0.41 13.372 0.0 150.83507 0.0 1
|
||||
Street_Passerby_122 -34.693 0.373 12.751 0.0 324.8782 0.0 1
|
||||
Street_NPCPos_No11_02 -1.8 0.345 -29.986 0.0 310.0 0.0 1
|
||||
Street_NPCPos_Keli_02 -2.26 0.36 -29.6 0.0 150.0 0.0 1
|
||||
Street_NPCPos_Keli_02End 0.11 0.315 -29.62 0.0 79.99999 0.0 1
|
||||
Street_NPCPos_Quest10020155_02 -1.763 0.8425 -21.017 0.0 237.17775 0.0 1
|
||||
Street_NPCPos_No11_03End 14.81 0.349 0.54 0.0 120.00001 0.0 1
|
||||
Street_NPCPos_Keli_03End 15.38 0.359 -0.28 0.0 20.00001 0.0 1
|
||||
Street_NPCPos_Woof 11.26 1.15 -10.188 0.0 0.0 0.0 1
|
||||
Street_ObjectPos_Newsstand 11.08 1.15 -9.372 0.0 0.0 0.0 1
|
||||
Street_Passerby_123 4.504 0.329 -0.0001 0.0 0.0 0.0 1
|
||||
Street_Passerby_124 8.166 0.329 1.463 0.0 270.0 0.0 1
|
||||
Street_Passerby_125 5.36 0.35 -0.01 0.0 0.0 0.0 1
|
||||
Street_Passerby_126 3.358 0.333 1.456 0.0 90.0 0.0 1
|
||||
Street_Passerby_127 8.212 0.452 1.48 0.0 270.0 0.0 1
|
||||
Street_NPCPos_Schroeder 1.752 0.342 -1.479 0.0 55.99999 0.0 1
|
||||
Street_Passerby_128 5.38 0.334 0.064 0.0 0.0 0.0 1
|
||||
Street_Passerby_129 3.287 0.35 1.452 0.0 90.0 0.0 1
|
||||
Street_Passerby_130 -22.633 0.35 -7.275 0.0 53.62085 0.0 1
|
||||
Street_Passerby_131 8.232 0.35 2.374 0.0 270.0 0.0 1
|
||||
Street_Passerby_132 10.17 0.35 2.07 0.0 163.21513 0.0 1
|
||||
Street_Passerby_139 -26.414 0.71 15.934 0.0 336.39316 0.0 1
|
||||
Street_Passerby_140 -27.703 0.593 15.938 0.0 55.93431 0.0 1
|
||||
Street_Passerby_141 10.968 0.4 6.067 0.0 120.00001 0.0 1
|
||||
Street_Passerby_142 11.058 0.35 4.379 0.0 117.98868 0.0 1
|
||||
Street_Passerby_143 10.678 0.36 -13.711 0.0 216.67374 0.0 1
|
||||
Street_Passerby_144 -13.401 0.35 -12.446 0.0 333.78751 0.0 1
|
||||
Street_Passerby_145 40.108 0.353 -0.147 0.0 154.59579 0.0 1
|
||||
Street_ObjectPos_12 43.325 -0.015 -4.342 0.0 90.0 0.0 1
|
||||
Street_Passerby_146 40.73 0.3506 -0.68 0.0 314.69949 0.0 1
|
||||
Street_Passerby_147 2.594 0.35 -7.269 0.0 88.00859 0.0 1
|
||||
Street_Passerby_148 3.52 0.4 -7.453 0.0 303.92548 0.0 1
|
||||
Street_Passerby_149 4.667 0.4 -10.8 0.0 221.15468 0.0 1
|
||||
Street_ObjectPos_04 0.763 1.038 -9.181 0.0 0.0 0.0 1
|
||||
Street_Passerby_150 12.273 0.359 -8.928 0.0 238.31017 0.0 1
|
||||
Street_NPCPos_Woof2 11.26 1.15 -10.188 0.0 0.0 0.0 1
|
||||
Street_NPCPos_Woof3 11.26 1.15 -10.188 0.0 0.0 0.0 1
|
||||
Street_Passerby_507 -26.592 0.36 -9.141 0.0 331.79459 0.0 1
|
||||
Street_Passerby_508 -27.964 0.35 9.704 0.0 276.12378 0.0 1
|
||||
Street_Passerby_509 5.012 0.35 -7.226 0.0 36.47496 0.0 1
|
||||
Street_Passerby_510 -7.145 0.363 4.026 0.0 270.0 0.0 1
|
||||
Street_Passerby_511 4.493 0.36 -35.899 0.0 20.00001 0.0 1
|
||||
Street_Passerby_512 -4.592 0.355 0.073 0.0 343.46274 0.0 1
|
||||
Street_Passerby_513 2.122 0.4 -10.398 0.0 32.57107 0.0 1
|
||||
Street_Passerby_514 2.891 0.4 -10.705 0.0 0.0 0.0 1
|
||||
Street_Passerby_515 14.095 0.36 -14.156 0.0 22.06978 0.0 1
|
||||
Street_Passerby_516 15.321 0.35 7.58 0.0 123.66821 0.0 1
|
||||
Street_Passerby_517 -4.305 0.4 -7.595 0.0 125.55424 0.0 1
|
||||
Street_Passerby_518 -1.701 0.4 -23.751 0.0 310.0 0.0 1
|
||||
Street_Passerby_519 -19.162 0.36 -8.18 0.0 37.20817 0.0 1
|
||||
Street_ObjectPos_03 -21.194 0.171 -9.311 0.0 0.0 0.0 1
|
||||
Street_Passerby_520 -3.812 0.347 -17.462 0.0 247.24823 0.0 1
|
||||
Street_NPCPos_Susie -25.671 0.6214 14.104 0.0 268.89499 0.0 1
|
||||
Street_NPCPos_TinMaster01 -10.191 0.36 -1.46 0.0 345.65805 0.0 1
|
||||
Street_NPCPos_TinMaster02 -6.288 0.3505 -7.195 0.0 321.44672 0.0 1
|
||||
Street_NPCPos_Gate 7.03 0.35 0.017 0.0 0.0 0.0 1
|
||||
Street_NPCPos_Ben 2.233 0.36 2.478 0.0 133.82996 0.0 1
|
||||
Street_PlayerPos_FromRamen 6.074 0.0 -0.758 0.0 0.0 0.0 1
|
||||
Street_NPCPos_Anton -34.865 0.396 13.443 0.0 142.69867 0.0 1
|
||||
Street_NPCPos_OokumaMari 11.921 0.347 -8.374 0.0 219.14148 0.0 1
|
||||
Street_Passerby_151 -4.573 0.34 0.044 0.0 168.11601 1.0 1
|
||||
Street_Passerby_152 9.423 0.352 -32.084 0.0 339.92599 0.0 1
|
||||
Street_Passerby_153 -26.66462 0.3402 7.56905 359.60715 269.99854 0.65592 1
|
||||
Street_NPCPos_Anbi02 -22.5 0.36 0.573 0.0 163.69124 0.0 1
|
||||
Street_NPCPos_Enzo 27.243 0.35 -1.528 0.0 229.92622 0.0 1
|
||||
Street_NPCPos_OokumaMari02 3.281 0.3965 -10.212 0.0 31.35417 0.0 1
|
||||
Street_NPCPos_Billy02 -13.986 0.36 -7.091 0.0 113.60025 0.0 1
|
||||
Street_NPCPos_Tsubaki 10.39 0.35 -8.91 0.0 137.00946 0.0 1
|
||||
Street_NPCPos_Anton02 26.712 0.35 -6.986 0.0 305.87402 0.0 1
|
||||
Street_NPCPos_Nocha02 9.577 0.348 -7.368 0.0 151.92999 0.0 1
|
||||
Street_NPCPos_Tsubaki02 -18.173 0.35 -6.936 0.0 133.66385 0.0 1
|
||||
Street_NPCPos_OokumaMari04 -25.138 0.7161 16.08 0.0 326.39648 0.0 1
|
||||
Street_NPCPos_Ben02 20.665 0.35 -10.565 0.0 251.54306 0.0 1
|
||||
Street_NPCPos_OokumaMari03 -22.553 0.36 -0.064 0.0 159.34224 0.0 1
|
||||
Street_NPCPos_Ben03 -21.869 0.35 0.596 0.0 192.34038 0.0 1
|
||||
Street_NPCPos_Billy03 22.297 0.36 5.854 0.0 340.17264 0.0 1
|
||||
Street_NPCPos_Nocha03 6.929 0.395 -1.278 0.0 342.26456 0.0 1
|
||||
Street_NPCPos_Tsubaki03 7.076 0.35 -0.706 0.0 312.97723 0.0 1
|
||||
Street_NPCPos_Anbi03 10.312 0.35 2.109 0.0 240.46249 0.0 1
|
||||
Street_NPCPos_Ben04 -32.609 0.342 -8.256 0.0 67.92832 0.0 1
|
||||
Street_NPCPos_OokumaMari05 -1.27 0.3492 -29.178 0.0 305.29065 0.0 1
|
||||
Street_NPCPos_Anton03 -2.058 0.35 -28.686 0.0 125.14816 0.0 1
|
||||
Street_NPCPos_Nocha04 -22.595 0.395 -7.348 0.0 125.5207 0.0 1
|
||||
Street_NPCPos_Billy04 -3.506 0.36 -17.778 0.0 251.33165 0.0 1
|
||||
Street_NPCPos_Anbi04 -4.261 0.35 -17.505 0.0 264.7402 0.0 1
|
||||
Street_NPCPos_Schroeder02 -5.053 0.342 4.863 0.0 70.83122 0.0 1
|
||||
Street_NPCPos_Schroeder03 3.253 0.323 1.458 0.0 92.53754 0.0 1
|
||||
Street_Passerby_521 -32.515 2.3 30.558 0.0 75.47579 0.0 1
|
||||
Street_Passerby_522 -29.71 2.3 29.43 0.0 209.83707 0.0 1
|
||||
Street_Passerby_523 -30.529 2.3 28.95 0.0 55.32315 0.0 1
|
||||
Street_Passerby_524 -26.636 0.368 7.484 0.0 250.28363 0.0 1
|
||||
Street_Passerby_525 21.991 0.35 -1.218 0.0 245.47432 0.0 1
|
||||
Street_Passerby_526 -27.72 0.35 12.558 0.0 70.0 0.0 1
|
||||
Street_Passerby_527 -2.147 0.35 -23.641 0.0 290.0 0.0 1
|
||||
Street_Passerby_528 -3.553 0.395 -18.033 0.0 155.24419 0.0 1
|
||||
Street_Passerby_529 -2.866 0.395 -19.195 0.0 327.30453 0.0 1
|
||||
Street_Passerby_530 2.248 0.35 17.375 0.0 240.0 0.0 1
|
||||
Street_Passerby_531 -30.195 2.3 29.303 0.0 316.19141 0.0 1
|
||||
Street_Passerby_532 -15.625 0.35 -6.819 0.0 195.36263 0.0 1
|
||||
Street_Passerby_533 -2.562 0.35 -23.881 0.0 312.95004 0.0 1
|
||||
Street_Passerby_534 -12.646 0.35 -18.012 0.0 255.57466 0.0 1
|
||||
Street_Passerby_535 -13.387 0.35 -16.812 0.0 152.59938 0.0 1
|
||||
Street_NPCPos_Shepherd02 -4.574 0.3346 1.6568 0.0 10.32042 0.0 1
|
||||
Street_NPCPos_No11_04 10.123 0.356 1.745 0.0 142.0 0.0 1
|
||||
Street_NPCPos_PAFUMEI 15.973 0.35 7.416 0.0 334.46896 0.0 1
|
||||
Street_NPCPos_MEIKE 15.483 0.35 7.766 0.0 120.00001 0.0 1
|
||||
Street_Passerby_536 3.952 0.4 -11.297 0.0 48.38462 0.0 1
|
||||
Garage_PlayerPos_Default 19.05 0.42063 21.43 0.0 0.0 0.0 3
|
||||
Garage_PlayerPos_FromWorkshop 19.05 0.42063 22.744 0.0 0.0 0.0 3
|
||||
Garage_PlayerPos_FromStreet 12.79 0.42063 18.82 0.0 0.0 0.0 3
|
||||
Garage_PlayerPos_Quest10020003 20.701 0.42063 29.794 0.0 220.0 0.0 3
|
||||
Garage_NPCPos_ToWorkshop 19.13 0.25 19.663 0.0 0.0 0.0 3
|
||||
Garage_NPCPos_ToStreet 12.836 0.476 15.002 0.0 0.0 0.0 3
|
||||
Garage_NPCPos_Nocha_Quest10020003 17.614 0.35 30.44 0.0 136.39999 0.0 3
|
||||
Garage_NPCPos_Billy_Quest10020003 15.226 0.32 27.58 0.0 82.8 0.0 3
|
||||
Garage_NPCPos_Anbi_Quest10020003 15.319 0.32 28.817 0.0 94.7 0.0 3
|
||||
Garage_NPCPos_Nocha_Quest10020012 17.39999 0.34 27.69 0.0 158.30615 0.0 3
|
||||
Garage_NPCPos_Billy_Quest10020012 18.56 0.31 32.58 0.0 250.0 0.0 3
|
||||
Garage_NPCPos_Anbi_Quest10020012 18.58 0.31 31.46 0.0 320.0 0.0 3
|
||||
ItemPos_1 17.0 0.42063 24.5 0.0 0.0 0.0 3
|
||||
ItemPos_2 18.0 0.42063 24.5 0.0 0.0 0.0 3
|
||||
ItemPos_3 19.0 0.42063 24.5 0.0 0.0 0.0 3
|
||||
ItemPos_4 20.0 0.42063 24.5 0.0 0.0 0.0 3
|
||||
ItemPos_5 21.0 0.42063 24.5 0.0 0.0 0.0 3
|
||||
Garage_PlayerPos_FromStreet2 11.254 0.42063 19.31 0.0 90.0 0.0 3
|
||||
Garage_NPCPos_ToStreet2 8.785 0.42063 19.238 0.0 270.0 0.0 3
|
||||
Garage_PlayerPos_Quest10020010 19.81 0.42063 27.32 0.0 0.0 0.0 3
|
||||
Garage_Object_Car_01 16.19 0.29 31.46 0.0 135.89999 0.0 3
|
||||
Garage_ObjectPos_14 23.874 0.86 31.988 0.0 0.0 0.0 3
|
||||
Garage_ObjectPos_15 22.254 0.82 22.982 0.0 0.0 0.0 3
|
||||
Garage_ObjectPos_16 31.804 0.42063 28.509 0.0 0.0 0.0 3
|
||||
Garage_ObjectPos_17 29.128 0.25 22.05 0.0 0.0 0.0 3
|
||||
Garage_ObjectPos_18 29.941 0.0 32.857 0.0 0.0 0.0 3
|
||||
Garage_NPCPos_Quest10020024 18.54 0.34 27.46 0.0 210.79999 0.0 3
|
||||
Garage_PlayerPos_Quest10020120 17.75 0.42063 26.39 0.0 30.00001 0.0 3
|
||||
Garage_NPCPos_No11 13.818 0.301 26.28 0.0 70.26791 0.0 3
|
||||
Garage_NPCPos_No11_02 29.598 0.345 23.527 0.0 308.61368 0.0 3
|
||||
Garage_NPCPos_No11_03 15.599 0.345 20.68 0.0 335.6268 0.0 3
|
||||
Garage_NPCPos_No11_04 13.97 0.3 25.64 0.74837 128.50786 359.98956 3
|
||||
Garage_NPCPos_Quest10020120 21.467 0.3 30.233 0.0 206.48201 0.0 3
|
||||
Garage_PlayerPos_Chat01 20.545 0.42063 29.194 0.0 43.57 0.0 3
|
||||
Workshop_PlayerPos_Default 23.75 0.58003 12.5 0.0 202.0 0.0 2
|
||||
Workshop_PlayerPos_FromStreet 22.598 0.58003 7.611 0.0 30.00001 0.0 2
|
||||
Workshop_PlayerPos_FromGarage 22.112 0.58002 14.386 0.0 180.0 0.0 2
|
||||
Workshop_PlayerPos_Quest10020003 23.375 0.58002 11.406 0.0 0.0 0.0 2
|
||||
Workshop_PlayerPos_Quest10020013 29.982 0.58002 15.418 0.0 120.00001 0.0 2
|
||||
Workshop_PlayerPos_Quest10020011 29.867 0.58002 11.406 0.0 30.0 0.0 2
|
||||
Workshop_PlayerPos_Quest10020012 29.587 0.58002 11.979 0.0 92.99999 0.0 2
|
||||
Workshop_PlayerPos_Quest10020001 30.31 0.58002 11.18 0.0 40.0 0.0 2
|
||||
Workshop_PlayerPos_Quest10020028 30.38 0.58002 12.826 0.0 80.0 0.0 2
|
||||
Workshop_PlayerPos_Pos1 29.44 0.605 15.48 0.0 0.0 0.0 2
|
||||
Workshop_PlayerPos_Pos2 30.729 0.584 15.3 0.0 0.0 0.0 2
|
||||
Workshop_NPCPos_ToGarage 22.093 0.749 16.512 0.0 180.0 0.0 2
|
||||
Workshop_NPCPos_ToStreet 21.529 0.666 5.786 0.0 28.1 0.0 2
|
||||
Workshop_NPCPos_Hollow 33.19 0.86 11.482 0.0 270.0 0.0 2
|
||||
Workshop_NPCPos_VHS 28.02 0.87 16.887 0.0 0.0 0.0 2
|
||||
Workshop_NPCPos_Gacha 19.368 1.41 6.382 0.0 270.0 0.0 2
|
||||
Workshop_NPCPos_TimeMachine 30.08 0.4 14.386 0.0 0.0 0.0 2
|
||||
Workshop_NPCPos_Test 28.875 0.58384 9.625 0.0 312.68036 0.0 2
|
||||
Workshop_NPCPos_SisterLing 24.476 0.5998 10.557 0.0 313.60257 0.0 2
|
||||
Workshop_NPCPos_WorkTable 28.336 0.75 8.292 0.0 44.79997 0.0 2
|
||||
Workshop_NPCPos_Noca 22.0 0.58003 8.5 0.0 50.0 0.0 2
|
||||
WorkShop_NPCPos_Noca_Quest10020001 33.372 0.626 14.29 0.0 270.0 0.0 2
|
||||
WorkShop_NPCPos_Billy_Quest10020003 22.0 0.58003 9.5 0.0 125.0 0.0 2
|
||||
WorkShop_NPCPos_Anbi_Quest10020003 23.0 0.58003 9.0 0.0 295.0 0.0 2
|
||||
WorkShop_NPCPos_Noca_Quest10020009 24.14684 0.58003 12.46807 0.0 207.99998 0.0 2
|
||||
WorkShop_NPCPos_Billy_Quest10020009 24.211 0.58003 10.839 0.0 318.87799 0.0 2
|
||||
WorkShop_NPCPos_Anbi_Quest10020009 22.779 0.58384 11.511 0.0 103.268 0.0 2
|
||||
WorkShop_NPCPos_Salesman_Quest10020103 23.46 0.58003 12.533 0.0 206.96613 0.0 2
|
||||
WorkShop_NPCPos_Tsubaki_Quest10020106 31.594 0.597 15.71 0.0 237.34885 0.0 2
|
||||
Workshop_NpcPos_Quest10020151 19.5 0.58003 10.89 0.0 240.0 0.0 2
|
||||
Workshop_NpcPos_Quest10020181 19.674 0.58003 12.272 0.0 4.53792 0.0 2
|
||||
Workshop_NPCPos_BangbooA_VHS 25.03 0.58003 6.0 0.0 280.0 0.0 2
|
||||
Workshop_NPCPos_guest01_VHS 19.845 0.58003 8.695 0.0 312.21448 0.0 2
|
||||
Workshop_NPCPos_guest02_VHS 19.777 0.58003 10.577 0.0 169.99998 0.0 2
|
||||
Workshop_NPCPos_guest03_VHS 19.84 0.58003 15.49 0.0 270.0 0.0 2
|
||||
Workshop_NPCPos_guest04_VHS 19.152 0.58003 7.176 0.0 250.0 0.0 2
|
||||
Workshop_NPCPos_guest05_VHS 19.256 0.58003 11.563 0.0 300.0 0.0 2
|
||||
Workshop_NPCPos_guest06_VHS 19.27 0.58003 14.28 0.0 240.0 0.0 2
|
||||
Workshop_NPCPos_Bangboo01_VHS 21.29 0.58003 13.62 0.0 199.99998 0.0 2
|
||||
Workshop_NPCPos_Bangboo02_VHS 21.93 0.58003 11.36 0.0 150.0 0.0 2
|
||||
Workshop_NPCPos_Bangboo03_VHS 21.13 0.58003 9.31 0.0 99.99999 0.0 2
|
||||
Workshop_NPCPos_Bangboo04_VHS 20.5 0.58003 10.36 0.0 180.0 0.0 2
|
||||
Workshop_NPCPos_Bangboo05_VHS 22.1 0.58003 9.9 0.0 120.00001 0.0 2
|
||||
Workshop_CameraPos_Pos1 30.85 1.93 13.0 8.0 335.0 0.0 2
|
||||
Workshop_CameraPos_Pos2 29.39 1.93 13.2 8.0 30.0 0.0 2
|
||||
Workshop_NPCPos_Telephone 26.807 1.008 8.432 0.0 270.0 0.0 2
|
||||
Workshop_NPCPos_HollowPause 32.61 0.59 11.58 0.0 90.0 0.0 2
|
||||
Workshop_NPCPos_VHSBangboo 26.098 1.337 9.692 0.0 260.0 0.0 2
|
||||
Workshop_PlayerPos_HollowQuest 32.37027 0.58384 11.5826 0.0 86.69299 0.0 2
|
||||
WorkShop_CameraPos_VHSStore 22.53 1.855 10.8 0.0 115.38 0.0 2
|
||||
Workshop_PlayerPos_FromHollow 32.37027 0.58384 11.5826 0.0 86.69299 0.0 2
|
||||
Workshop_PlayerPos_FromVHS 28.0 0.58384 15.6 0.0 0.0 0.0 2
|
||||
Workshop_PlayerPos_VHSStore 22.758 0.58384 9.921 0.0 86.69299 0.0 2
|
||||
Workshop_NPCPos_ARole1 32.5 0.594 15.027 0.0 150.0 0.0 2
|
||||
Workshop_NPCPos_ARole2 31.15 0.594 12.748 0.0 270.0 0.0 2
|
||||
Workshop_NPCPos_ARole3 32.1 0.594 12.55 0.0 120.00001 0.0 2
|
||||
Workshop_NPCPos_ARole4 25.555 0.594 6.693 0.0 306.96448 0.0 2
|
||||
Workshop_NPCPos_ARole5 28.429 0.594 15.22 0.0 186.60002 0.0 2
|
||||
Workshop_NPCPos_ARole6 28.74 0.594 13.821 0.0 131.39603 0.0 2
|
||||
WorkShop_NPCPos_Tsubaki_Quest10020115 28.903 0.58003 16.034 0.0 154.11002 0.0 2
|
||||
Workshop_PlayerPos_Quest10020106 31.701 0.594 13.423 0.0 255.0 0.0 2
|
||||
Workshop_PlayerPos_Quest10020115 30.447 0.594 12.817 0.0 296.12622 0.0 2
|
||||
Workshop_Teleport_ToWorkshop 23.69 0.6 9.698 0.0 60.0 0.0 2
|
||||
Workshop_NPCPos_ARole7 27.35 0.59 16.0 0.0 45.0 0.0 2
|
||||
Workshop_NPCPos_ARole8 29.952 0.594 14.702 0.0 0.0 0.0 2
|
||||
Workshop_NPCPos_ARole8F 30.263 0.594 14.64 0.0 0.0 0.0 2
|
||||
Workshop_NPCPos_ARole9 31.6 0.594 10.85 0.0 307.60001 0.0 2
|
||||
Workshop_NPCPos_ARole10 33.19 0.594 15.438 0.0 260.0 0.0 2
|
||||
Workshop_NPCPos_ARoleTest 30.05 0.594 14.858 0.0 0.0 0.0 2
|
||||
Workshop_PlayerPos_Quest10020109 30.628 0.594 11.88 0.0 280.0 0.0 2
|
||||
Workshop_PlayerPos_Quest10020113 30.628 0.594 11.88 0.0 280.0 0.0 2
|
||||
Workshop_PlayerPos_Quest10020116 30.506 0.594 11.88 0.0 90.0 0.0 2
|
||||
Workshop_PlayerPos_Quest10020010 30.208 0.594 12.092 0.0 348.5 0.0 2
|
||||
Workshop_NPCPos_DrawingRoom 24.38 0.594 6.223 0.0 353.79999 0.0 2
|
||||
Workshop_PlayerPos_Quest10020119 30.892 0.594 10.112 0.0 125.60002 0.0 2
|
||||
Workshop_NPCPos_ARole11 31.605 0.594 9.471 0.0 300.0 0.0 2
|
||||
Workshop_NPCPos_ARole12 30.402 0.6 9.8 0.0 44.15999 0.0 2
|
||||
Workshop_NPCPos_ARole17 30.645 0.58 15.042 0.0 0.0 0.0 2
|
||||
Workshop_NPCPos_ARole16 28.292 0.593 8.216 3.08252 316.2569 0.0 2
|
||||
Workshop_NPCPos_ARole16F 25.559 0.578 7.945 0.0 204.72104 0.0 2
|
||||
Workshop_NPCPos_ARole15 33.043 0.6 13.442 0.0 0.0 0.0 2
|
||||
Workshop_NPCPos_ARole14 33.043 0.6 13.442 0.0 0.0 0.0 2
|
||||
Workshop_NPCPos_ARole13 33.043 0.6 13.442 0.0 0.0 0.0 2
|
||||
WorkShop_NPCPos_Tsubaki_Quest10020119 31.19 0.59 10.23 0.0 289.17999 0.0 2
|
||||
Workshop_PlayerPos_Quest10020151 20.396 0.58003 11.186 0.0 270.0 0.0 2
|
||||
Workshop_PlayerPos_Quest10020111 28.9 0.588 13.1 0.0 129.89999 0.0 2
|
||||
Workshop_NpcPos_VHS31020002 25.688 0.58003 7.624 0.0 251.93011 0.0 2
|
||||
Workshop_NpcPos_VHS31020001 23.12 0.58003 6.209 0.0 29.26875 0.0 2
|
||||
Workshop_NpcPos_VHS31010001 21.59 0.58003 15.2 0.0 240.0 0.0 2
|
||||
Workshop_NpcPos_Bangboo_Quest10020141 25.28177 0.588 6.47026 0.0 320.26306 0.0 2
|
||||
Workshop_NpcPos_Bangboo_Quest10020195 19.567 0.588 15.244 0.0 120.5 0.0 2
|
||||
Workshop_NpcPos_VHS31010002 21.9 0.58003 14.84 0.0 240.0 0.0 2
|
||||
Workshop_PlayerPos_VHS31020002 21.924 0.58003 12.388 0.0 315.51761 0.0 2
|
||||
Workshop_PlayerPos_VHS31020001 24.0 0.58003 9.36 0.0 150.0 0.0 2
|
||||
Workshop_PlayerPos_VHS31010001 21.59 0.58003 14.46 0.0 0.0 0.0 2
|
||||
Workshop_PlayerPos_VHS31010002 21.9 0.58003 14.46 0.0 0.0 0.0 2
|
||||
Workshop_NPCPos_No11_03 25.3 0.587 13.56 0.0 240.0 0.0 2
|
||||
Workshop_PlayerPos_Quest10020123 30.724 0.594 11.259 0.0 125.60002 0.0 2
|
||||
WorkShop_NPCPos_Bangboo_Quest10020106 32.19 0.595 15.605 0.0 337.73215 0.0 2
|
||||
Workshop_Passerby_133 19.237 0.58003 8.191 0.0 290.0 0.0 2
|
||||
Workshop_Passerby_134 19.838 0.58003 10.448 0.0 199.99998 0.0 2
|
||||
Workshop_Passerby_135 19.435 0.58003 15.141 0.0 270.0 0.0 2
|
||||
Workshop_Passerby_136 19.403 0.58003 7.347 0.0 260.0 0.0 2
|
||||
Workshop_Passerby_137 19.292 0.58003 11.969 0.0 270.0 0.0 2
|
||||
Workshop_Passerby_138 20.347 0.58003 15.573 0.0 340.0 0.0 2
|
||||
Workshop_PlayerPos_HollowPause 31.23 0.584 13.08 0.0 118.0 0.0 2
|
||||
Workshop_NPCPos_ARole17F 31.0 0.58 15.15 0.0 311.0 0.0 2
|
||||
Workshop_NpcPos_VHS31020001End 24.626 0.58003 8.681 0.0 311.76859 0.0 2
|
||||
Workshop_NpcPos_VHS31020002_02 25.503 0.58003 7.032 0.0 306.8797 0.0 2
|
||||
Workshop_NpcPos_VHS31020002End 21.218 0.58003 12.853 0.0 126.61777 0.0 2
|
||||
Workshop_NpcPos_VHS31020002_02End 21.66 0.58003 13.136 0.0 152.39877 0.0 2
|
||||
Workshop_NPCPos_ARole18 31.802 0.594 14.909 0.0 283.90863 0.0 2
|
||||
Workshop_PlayerPos_ARole18 28.258 0.594 15.121 0.0 81.46976 0.0 2
|
||||
Borderlands 0.0 0.0 0.0 0.0 0.0 0.0 0
|
|
|
@ -0,0 +1,36 @@
|
|||
ID LockType LockParam UnlockType UnlockParam MenuType IconRes Name
|
||||
1001 1 None 0 None 1 UI/Sprite/MainCityMenus/Packer/IconSundryBtn.png UIText_321
|
||||
1002 1 None 0 None 0 UI/Sprite/MainCityMenus/Packer/IconGashaponBtn.png UIText_322
|
||||
1003 1 None 0 None 0 UI/Sprite/MainCityMenus/Packer/IconShopBtn02.png UIText_323
|
||||
1004 1 None 0 None 0 UI/Sprite/MainCityMenus/Packer/IconMissionBtn.png UIText_324
|
||||
1005 1 None 0 None 1 UI/Sprite/MainCityMenus/Packer/IconYorozuyaManualBtn.png UIText_325
|
||||
1006 1 None 0 None 1 UI/Sprite/MainCityMenus/Packer/IconBagBtn.png UIText_326
|
||||
1007 1 None 0 None 0 UI/Sprite/MainCityMenus/Packer/IconBangBooBtn.png UIText_327
|
||||
1008 1 None 0 None 1 UI/Sprite/MainCityMenus/Packer/IconRoleBtn02.png UIText_328
|
||||
1009 1 None 0 None 1 UI/Sprite/MainCityMenus/Packer/IconTeleportBtn.png UIText_329
|
||||
1010 1 None 0 None 0 None None
|
||||
1011 1 MenuText_LockHint 1 MenuText_UnlockHint 0 None None
|
||||
1013 1 None 0 None 0 None None
|
||||
1014 1 None 0 None 1 UI/Sprite/MainCityMenus/Packer/IconSetUp.png UIText_330
|
||||
1015 2 None 0 None 2 UI/Sprite/A1DynamicLoad/IconMenusOption/Packer/IconMail.png UIText_331
|
||||
1016 2 None 0 None 2 UI/Sprite/A1DynamicLoad/IconMenusOption/Packer/IconNotice.png UIText_332
|
||||
1017 2 None 0 None 2 UI/Sprite/A1DynamicLoad/IconMenusOption/Packer/IconFeedback.png UIText_354
|
||||
1018 1 HollowPause_LockHint 0 None 0 None None
|
||||
1019 2 None 0 None 2 UI/Sprite/A1DynamicLoad/IconMenusOption/Packer/IconSignOut UIText_367
|
||||
10001 1 None 0 None 0 None None
|
||||
10002 1 None 0 None 0 None None
|
||||
10003 1 None 0 None 0 None None
|
||||
10004 1 None 0 None 0 None None
|
||||
10005 1 None 0 None 0 None None
|
||||
10006 1 InventoryText_LockHint 0 InventoryText_UnlockHint 0 None None
|
||||
10007 1 None 0 None 0 None None
|
||||
10008 1 None 0 None 0 None None
|
||||
10009 1 None 0 None 0 None None
|
||||
10010 1 SmithyText_LockHint 1 SmithyText_UnlockHint 0 None None
|
||||
10012 1 RamenText_LockHint 1 RamenText_UnlockHint 0 None None
|
||||
10013 1 WorkbenchText_LockHint 1 WorkbenchText_UnlockHint 0 None None
|
||||
10014 1 VHSStoreText_LockHint 1 VHSStoreText_UnlockHint 0 None None
|
||||
10015 1 GroceryText_LockHint 1 GroceryText_UnlockHint 0 None None
|
||||
10017 1 None 0 None 0 None None
|
||||
10018 1 None 0 None 0 None None
|
||||
10019 1 None 0 None 0 None None
|
|
BIN
cargo
BIN
cargo
Binary file not shown.
6
common/Cargo.toml
Normal file
6
common/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "common"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
|
||||
[dependencies]
|
1
common/src/lib.rs
Normal file
1
common/src/lib.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod util;
|
25
common/src/util.rs
Normal file
25
common/src/util.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
pub fn load_or_create_config(path: &str, defaults: &str) -> String {
|
||||
std::fs::read_to_string(path).map_or_else(
|
||||
|_| {
|
||||
std::fs::write(path, defaults).unwrap();
|
||||
defaults.to_string()
|
||||
},
|
||||
|data| data,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn cur_timestamp_ms() -> i64 {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_millis() as i64
|
||||
}
|
||||
|
||||
pub fn cur_timestamp_seconds() -> i64 {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs() as i64
|
||||
}
|
1
gameserver/.env
Normal file
1
gameserver/.env
Normal file
|
@ -0,0 +1 @@
|
|||
SKIP_TUTORIAL=1
|
36
gameserver/Cargo.toml
Normal file
36
gameserver/Cargo.toml
Normal file
|
@ -0,0 +1,36 @@
|
|||
[package]
|
||||
name = "gameserver"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
ansi_term.workspace = true
|
||||
anyhow.workspace = true
|
||||
dirs.workspace = true
|
||||
env_logger.workspace = true
|
||||
hex.workspace = true
|
||||
paste.workspace = true
|
||||
sysinfo.workspace = true
|
||||
itertools.workspace = true
|
||||
|
||||
csv.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
tokio.workspace = true
|
||||
tokio-util.workspace = true
|
||||
|
||||
tracing.workspace = true
|
||||
tracing-futures.workspace = true
|
||||
tracing-log.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
tracing-bunyan-formatter.workspace = true
|
||||
|
||||
common.workspace = true
|
||||
protocol.workspace = true
|
||||
qwer.workspace = true
|
||||
parking_lot.workspace = true
|
||||
|
||||
[[bin]]
|
||||
name = "nap-gameserver"
|
||||
path = "src/main.rs"
|
14
gameserver/gameserver.default.json
Normal file
14
gameserver/gameserver.default.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"gateway_endpoint": "0.0.0.0:10301",
|
||||
"skip_tutorial": false,
|
||||
"manual_chain_attacks": false,
|
||||
"characters_lvl": 5,
|
||||
"characters_ascension_rank": 1,
|
||||
"characters_star_rank": 3,
|
||||
"characters_unlocked_talents": 4,
|
||||
"characters_normal_atk_lvl": 1,
|
||||
"characters_special_lvl": 1,
|
||||
"characters_dodge_lvl": 1,
|
||||
"characters_ult_lvl": 1,
|
||||
"system_resources_logging": false
|
||||
}
|
32
gameserver/src/config.rs
Normal file
32
gameserver/src/config.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use std::sync::LazyLock;
|
||||
|
||||
use common::util::load_or_create_config;
|
||||
use serde::Deserialize;
|
||||
|
||||
|
||||
const DEFAULT_CONFIG: &str = include_str!("../gameserver.default.json");
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct GameServerConfig {
|
||||
pub gateway_endpoint: String,
|
||||
pub skip_tutorial: bool,
|
||||
pub manual_chain_attacks: bool,
|
||||
pub characters_lvl: u8,
|
||||
pub characters_ascension_rank: u8,
|
||||
pub characters_star_rank: u8,
|
||||
pub characters_unlocked_talents: u8,
|
||||
pub characters_normal_atk_lvl : u8,
|
||||
pub characters_special_lvl : u8,
|
||||
pub characters_dodge_lvl : u8,
|
||||
pub characters_ult_lvl : u8,
|
||||
pub system_resources_logging: bool,
|
||||
}
|
||||
|
||||
pub static CONFIGURATION: LazyLock<GameServerConfig> = LazyLock::new(|| {
|
||||
serde_json::from_str(&load_or_create_config("gameserver.json", DEFAULT_CONFIG))
|
||||
.expect("Failed to parse server configuration file")
|
||||
});
|
||||
|
||||
pub fn init_config() {
|
||||
let _configuration = &*CONFIGURATION;
|
||||
}
|
102
gameserver/src/data/event_graph.rs
Normal file
102
gameserver/src/data/event_graph.rs
Normal file
|
@ -0,0 +1,102 @@
|
|||
#![allow(unused)]
|
||||
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
|
||||
use protocol::{HollowEventType, NodeState, NodeVisible};
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct ConfigEventGraph {
|
||||
#[serde(rename = "ID")]
|
||||
pub id: i32,
|
||||
pub events: BTreeMap<ConfigEventType, ConfigEvent>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default)]
|
||||
#[serde(untagged)]
|
||||
pub enum ConfigValue {
|
||||
Constant(i32),
|
||||
Expression(String),
|
||||
#[default]
|
||||
Empty,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Ord, PartialOrd, Eq, PartialEq)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub enum ConfigEventType {
|
||||
OnStart,
|
||||
OnEnd,
|
||||
OnBro,
|
||||
OnSis,
|
||||
#[serde(other)]
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct ConfigEvent {
|
||||
#[serde(default)]
|
||||
pub actions: Vec<ConfigAction>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default)]
|
||||
pub enum HollowPositionOffsetType {
|
||||
#[default]
|
||||
Relative = 0,
|
||||
Absolute = 1,
|
||||
EventPos = 2,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default)]
|
||||
#[serde(tag = "$type")]
|
||||
pub enum ConfigAction {
|
||||
#[serde(rename = "Share.CConfigEmpty")]
|
||||
ConfigEmpty,
|
||||
#[serde(rename = "Share.CConfigSetMapState")]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
ConfigSetMapState {
|
||||
#[serde(default)]
|
||||
x: ConfigValue,
|
||||
#[serde(default)]
|
||||
y: ConfigValue,
|
||||
#[serde(default)]
|
||||
position: HollowPositionOffsetType,
|
||||
radius: Option<ConfigValue>,
|
||||
count: Option<ConfigValue>,
|
||||
#[serde(default)]
|
||||
r#type: HashSet<HollowEventType>,
|
||||
event_type_tag: Option<String>,
|
||||
#[serde(default)]
|
||||
from_visible_state: HashSet<NodeVisible>,
|
||||
#[serde(default)]
|
||||
to_visible_state: Vec<NodeVisible>,
|
||||
#[serde(default)]
|
||||
from_state: HashSet<NodeState>,
|
||||
#[serde(default)]
|
||||
to_state: Vec<NodeState>,
|
||||
#[serde(default)]
|
||||
exclude_player_pos: bool,
|
||||
#[serde(default)]
|
||||
index_list: Vec<ConfigValue>,
|
||||
#[serde(default)]
|
||||
use_perform: bool,
|
||||
},
|
||||
#[serde(rename = "Share.CConfigTriggerBattle")]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
ConfigTriggerBattle {
|
||||
#[serde(rename = "BattleID")]
|
||||
battle_id: ConfigValue,
|
||||
on_success: Option<String>,
|
||||
on_failure: Option<String>,
|
||||
#[serde(default)]
|
||||
end_hollow: bool,
|
||||
#[serde(default)]
|
||||
goto_next_hollow: bool,
|
||||
},
|
||||
#[serde(rename = "Share.CConfigFinishHollow")]
|
||||
ConfigFinishHollow,
|
||||
#[default]
|
||||
#[serde(other)]
|
||||
ConfigUnknown,
|
||||
}
|
79
gameserver/src/data/mod.rs
Normal file
79
gameserver/src/data/mod.rs
Normal file
|
@ -0,0 +1,79 @@
|
|||
mod event_graph;
|
||||
mod templates;
|
||||
mod tsv_util;
|
||||
|
||||
use std::{collections::HashMap, path::Path};
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
pub use event_graph::*;
|
||||
use paste::paste;
|
||||
pub use templates::*;
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
macro_rules! template_collections {
|
||||
($($template_type:ident;)*) => {
|
||||
$(paste! {
|
||||
static [<$template_type:snake:upper _COLLECTION>]: OnceCell<Vec<[<$template_type Template>]>> = OnceCell::const_new();
|
||||
})*
|
||||
|
||||
fn init_template_collections() -> Result<()> {
|
||||
$(paste! {
|
||||
let path = concat!("assets/TemplateCollections/", stringify!($template_type), "TemplateCollection.tsv");
|
||||
let data = std::fs::read_to_string(path)?;
|
||||
[<$template_type:snake:upper _COLLECTION>].set(tsv_util::from_str(&data)?).unwrap();
|
||||
})*
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
$(paste! {
|
||||
pub fn [<iter_ $template_type:snake _collection>]() -> ::std::slice::Iter<'static, [<$template_type Template>]> {
|
||||
[<$template_type:snake:upper _COLLECTION>].get().unwrap().iter()
|
||||
}
|
||||
})*
|
||||
};
|
||||
}
|
||||
|
||||
template_collections! {
|
||||
AvatarConfig;
|
||||
UnlockConfig;
|
||||
MainCityObject;
|
||||
NPCTransform;
|
||||
}
|
||||
|
||||
static EVENT_GRAPH_COLLECTION: OnceCell<HashMap<i32, ConfigEventGraph>> = OnceCell::const_new();
|
||||
|
||||
fn init_binoutput() -> Result<()> {
|
||||
let _ = EVENT_GRAPH_COLLECTION.set(serde_json::from_str(
|
||||
std::fs::read_to_string("assets/BinOutput/EventGraphCollection.json")?.as_str(),
|
||||
)?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn init_assets() -> Result<()> {
|
||||
if !Path::new("assets/").exists() {
|
||||
bail!(
|
||||
"Assets directory not found! Make sure you have it in the same directory with executable."
|
||||
)
|
||||
}
|
||||
|
||||
init_template_collections()?;
|
||||
init_binoutput()
|
||||
}
|
||||
|
||||
pub fn get_main_city_object(tag_id: i32, npc_id: i32) -> Option<&'static MainCityObjectTemplate> {
|
||||
iter_main_city_object_collection().find(|o| o.tag_id == tag_id && o.npc_id == npc_id)
|
||||
}
|
||||
|
||||
pub fn is_transform_in_section(transform_id: &str, section_id: i32) -> bool {
|
||||
iter_n_p_c_transform_collection()
|
||||
.find(|t| t.id == transform_id)
|
||||
.map_or(false, |t| t.section == section_id)
|
||||
}
|
||||
|
||||
pub fn get_event_graph(id: i32) -> Option<&'static ConfigEventGraph> {
|
||||
EVENT_GRAPH_COLLECTION.get().unwrap().get(&id)
|
||||
}
|
||||
|
162
gameserver/src/data/templates.rs
Normal file
162
gameserver/src/data/templates.rs
Normal file
|
@ -0,0 +1,162 @@
|
|||
#![allow(dead_code)]
|
||||
use super::tsv_util::from_sequence;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct MainCityObjectTemplate {
|
||||
#[serde(rename = "TagID")]
|
||||
pub tag_id: i32,
|
||||
#[serde(rename = "NPCID")]
|
||||
pub npc_id: i32,
|
||||
pub create_position: String,
|
||||
pub create_type: i32,
|
||||
#[serde(rename = "DefaultInteractIDs")]
|
||||
#[serde(deserialize_with = "from_sequence")]
|
||||
pub default_interact_ids: Vec<i32>,
|
||||
pub interact_name: Option<String>,
|
||||
pub interact_shape: i32,
|
||||
#[serde(deserialize_with = "from_sequence")]
|
||||
pub interact_scale: Vec<f64>,
|
||||
pub fan_interact_param: Option<String>,
|
||||
pub focus_interact_scale: f64,
|
||||
pub ignore_collider: bool,
|
||||
#[serde(rename = "LookIK")]
|
||||
pub look_ik: bool,
|
||||
#[serde(rename = "NPCLookIK")]
|
||||
pub npc_look_ik: bool,
|
||||
#[serde(rename = "SceneSoundID")]
|
||||
pub scene_sound_id: i32,
|
||||
pub player_rotate: bool,
|
||||
#[serde(rename = "NPCRotate")]
|
||||
pub npc_rotate: bool,
|
||||
pub scene_object_name: Option<String>,
|
||||
pub camera_story_key: Option<String>,
|
||||
pub action_state: i32,
|
||||
pub collider_state: Option<String>,
|
||||
pub item_state: Option<String>,
|
||||
#[serde(rename = "ObjectIDs")]
|
||||
#[serde(deserialize_with = "from_sequence")]
|
||||
pub object_ids: Vec<i32>,
|
||||
pub create_interval: i32,
|
||||
pub create_delay: i32,
|
||||
#[serde(rename = "NPCIcon")]
|
||||
pub npc_icon: Option<String>,
|
||||
pub action_switch: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct NPCTransformTemplate {
|
||||
#[serde(rename = "ID")]
|
||||
pub id: String,
|
||||
pub position_x: f64,
|
||||
pub position_y: f64,
|
||||
pub position_z: f64,
|
||||
pub rotation_x: f64,
|
||||
pub rotation_y: f64,
|
||||
pub rotation_z: f64,
|
||||
pub section: i32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct UnlockConfigTemplate {
|
||||
#[serde(rename = "ID")]
|
||||
pub id: i32,
|
||||
pub lock_type: i32,
|
||||
pub lock_param: Option<String>,
|
||||
pub unlock_type: i32,
|
||||
pub unlock_param: Option<String>,
|
||||
pub menu_type: i32,
|
||||
pub icon_res: Option<String>,
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct AvatarConfigTemplate {
|
||||
#[serde(rename = "ID")]
|
||||
pub id: i32,
|
||||
pub code_name: String,
|
||||
pub name: String,
|
||||
pub audio_event_replace_param: String,
|
||||
pub audio_bank: String,
|
||||
pub hud_icon_path: String,
|
||||
pub hollow_icon_path: String,
|
||||
pub icon_path: String,
|
||||
pub rect_icon_path: String,
|
||||
pub avatar_path: String,
|
||||
pub script_config_path: String,
|
||||
#[serde(rename = "UIScriptConfigPath")]
|
||||
pub uiscript_config_path: String,
|
||||
pub prefab_path: String,
|
||||
#[serde(rename = "UIPrefabPath")]
|
||||
pub uiprefab_path: String,
|
||||
pub main_page_show: bool,
|
||||
pub need_show: bool,
|
||||
#[serde(deserialize_with = "from_sequence")]
|
||||
pub hit_types: Vec<i32>,
|
||||
#[serde(deserialize_with = "from_sequence")]
|
||||
pub element_types: Vec<i32>,
|
||||
#[serde(deserialize_with = "from_sequence")]
|
||||
pub tags: Vec<String>,
|
||||
pub gender: i32,
|
||||
pub camp: i32,
|
||||
pub camp_name: Option<String>,
|
||||
pub group_icon_path: String,
|
||||
pub weapon_type: i32,
|
||||
pub star_initial: i32,
|
||||
#[serde(rename = "AvatarPieceID")]
|
||||
pub avatar_piece_id: i32,
|
||||
pub avatar_decompose: i32,
|
||||
pub avatar_compose: i32,
|
||||
#[serde(rename = "HP")]
|
||||
pub hp: i32,
|
||||
#[serde(rename = "HPGrowth")]
|
||||
pub hp_growth: i32,
|
||||
pub armor: i32,
|
||||
pub armor_growth: i32,
|
||||
pub shield: i32,
|
||||
pub shield_growth: i32,
|
||||
pub endurance: i32,
|
||||
pub attack: i32,
|
||||
pub attack_growth: i32,
|
||||
pub defence: i32,
|
||||
pub defence_growth: i32,
|
||||
pub crit: i32,
|
||||
pub crit_damage: i32,
|
||||
pub crit_res: i32,
|
||||
pub crit_dmg_res: i32,
|
||||
pub pen_rate: i32,
|
||||
pub pen_delta: i32,
|
||||
pub luck: i32,
|
||||
pub stun: i32,
|
||||
pub break_stun: i32,
|
||||
#[serde(rename = "SPBarPoint")]
|
||||
pub spbar_point: i32,
|
||||
pub sp_recover: i32,
|
||||
#[serde(rename = "RBL")]
|
||||
pub rbl: i32,
|
||||
#[serde(rename = "RBLCorrectionFactor")]
|
||||
pub rblcorrection_factor: i32,
|
||||
#[serde(rename = "RBLProbability")]
|
||||
pub rblprobability: i32,
|
||||
pub buff_resist_burn_possibility_ratio: i32,
|
||||
pub buff_resist_burn_possibility_delta: i32,
|
||||
pub buff_resist_frozen_possibility_ratio: i32,
|
||||
pub buff_resist_frozen_possibility_delta: i32,
|
||||
pub buff_resist_electric_possibility_ratio: i32,
|
||||
pub buff_resist_electric_possibility_delta: i32,
|
||||
pub weapon: i32,
|
||||
#[serde(rename = "RBP")]
|
||||
pub rbp: i32,
|
||||
#[serde(rename = "RBPFadeOutRate")]
|
||||
pub rbp_fade_out_rate: i32,
|
||||
#[serde(rename = "RBPFadeOutTime")]
|
||||
pub rbp_fade_out_time: i32,
|
||||
#[serde(rename = "RBPCorrectionFactor")]
|
||||
pub rbp_correction_factor: i32,
|
||||
#[serde(rename = "RBPProbability")]
|
||||
pub rbp_probability: i32,
|
||||
}
|
31
gameserver/src/data/tsv_util.rs
Normal file
31
gameserver/src/data/tsv_util.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
use csv::ReaderBuilder;
|
||||
use serde::{de::DeserializeOwned, Deserialize, Deserializer};
|
||||
|
||||
pub fn from_sequence<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
T: FromStr + Default,
|
||||
{
|
||||
let sequence = String::deserialize(deserializer)?;
|
||||
match sequence.len() {
|
||||
0 => Ok(vec![]),
|
||||
_ => Ok(sequence
|
||||
.split(",")
|
||||
.map(|s| s.parse::<T>().unwrap_or_default())
|
||||
.collect()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str<'de, T>(data: &str) -> Result<Vec<T>, csv::Error>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
let mut reader = ReaderBuilder::new()
|
||||
.delimiter(b'\t')
|
||||
.from_reader(data.as_bytes());
|
||||
|
||||
reader.deserialize::<T>().collect()
|
||||
}
|
85
gameserver/src/game/context.rs
Normal file
85
gameserver/src/game/context.rs
Normal file
|
@ -0,0 +1,85 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Result;
|
||||
use parking_lot::RwLock;
|
||||
use protocol::{PlayerInfo, PtcPlayerInfoChangedArg};
|
||||
|
||||
use crate::net::NetworkSession;
|
||||
|
||||
use super::manager::{
|
||||
DungeonManager, HollowGridManager, ItemManager, QuestManager, SceneUnitManager,
|
||||
UniqueIDManager, UnlockManager, YorozuyaQuestManager,
|
||||
};
|
||||
|
||||
pub struct GameContext {
|
||||
#[allow(unused)]
|
||||
pub uid_manager: Arc<UniqueIDManager>,
|
||||
pub item_manager: Arc<ItemManager>,
|
||||
pub dungeon_manager: Arc<DungeonManager>,
|
||||
pub quest_manager: Arc<QuestManager>,
|
||||
pub scene_unit_manager: Arc<SceneUnitManager>,
|
||||
pub hollow_grid_manager: Arc<HollowGridManager>,
|
||||
pub unlock_manager: Arc<UnlockManager>,
|
||||
pub yorozuya_quest_manager: Arc<YorozuyaQuestManager>,
|
||||
}
|
||||
|
||||
impl GameContext {
|
||||
pub fn new(player: Arc<RwLock<PlayerInfo>>) -> Self {
|
||||
let uid_manager = Arc::new(UniqueIDManager::new());
|
||||
|
||||
Self {
|
||||
uid_manager: uid_manager.clone(),
|
||||
item_manager: Arc::new(ItemManager::new(uid_manager.clone(), player.clone())),
|
||||
dungeon_manager: Arc::new(DungeonManager::new(uid_manager.clone(), player.clone())),
|
||||
quest_manager: Arc::new(QuestManager::new(uid_manager.clone(), player.clone())),
|
||||
scene_unit_manager: Arc::new(SceneUnitManager::new(uid_manager)),
|
||||
hollow_grid_manager: Arc::new(HollowGridManager::new(player.clone())),
|
||||
unlock_manager: Arc::new(UnlockManager::new(player.clone())),
|
||||
yorozuya_quest_manager: Arc::new(YorozuyaQuestManager::new(player)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PlayerOperationResult<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
result: T,
|
||||
player_info_changes: Option<PlayerInfo>,
|
||||
}
|
||||
|
||||
impl<T> PlayerOperationResult<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
pub fn take(self) -> T {
|
||||
self.result
|
||||
}
|
||||
|
||||
pub async fn send_changes(mut self, session: &NetworkSession) -> Result<T> {
|
||||
if self.player_info_changes.is_some() {
|
||||
let ptc_player_info_changed = PtcPlayerInfoChangedArg {
|
||||
player_uid: session.player_uid().raw(),
|
||||
player_info: self.player_info_changes.take().unwrap(),
|
||||
};
|
||||
|
||||
session.push_rpc_arg(101, ptc_player_info_changed).await?;
|
||||
}
|
||||
|
||||
Ok(self.take())
|
||||
}
|
||||
|
||||
pub const fn ret(result: T) -> Self {
|
||||
Self {
|
||||
result,
|
||||
player_info_changes: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn with_changes(result: T, player_info_changes: PlayerInfo) -> Self {
|
||||
Self {
|
||||
result,
|
||||
player_info_changes: Some(player_info_changes),
|
||||
}
|
||||
}
|
||||
}
|
853
gameserver/src/game/manager/dungeon.rs
Normal file
853
gameserver/src/game/manager/dungeon.rs
Normal file
|
@ -0,0 +1,853 @@
|
|||
use anyhow::{anyhow, bail, Result};
|
||||
use parking_lot::RwLock;
|
||||
use protocol::*;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::game::{manager::UniqueIDManager, util, PlayerOperationResult};
|
||||
use qwer::{
|
||||
pdkhashmap, phashmap, phashset, PropertyDoubleKeyHashMap, PropertyHashMap, PropertyHashSet,
|
||||
};
|
||||
|
||||
pub struct DungeonManager {
|
||||
uid_mgr: Arc<UniqueIDManager>,
|
||||
player: Arc<RwLock<PlayerInfo>>,
|
||||
scene_properties: RwLock<PropertyDoubleKeyHashMap<u64, u16, i32>>,
|
||||
}
|
||||
|
||||
impl DungeonManager {
|
||||
pub fn new(uid_mgr: Arc<UniqueIDManager>, player: Arc<RwLock<PlayerInfo>>) -> Self {
|
||||
Self {
|
||||
uid_mgr,
|
||||
player,
|
||||
scene_properties: RwLock::new(pdkhashmap![]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enter_main_city(&self) -> Result<PlayerOperationResult<PtcEnterSceneArg>> {
|
||||
let (player_uid, scene_position, scene_rotation) = {
|
||||
let player = self.player.read();
|
||||
let pos_in_main_city = player.pos_in_main_city.as_ref().unwrap();
|
||||
|
||||
(
|
||||
player.uid.unwrap(),
|
||||
*pos_in_main_city.position.as_ref().unwrap(),
|
||||
*pos_in_main_city.rotation.as_ref().unwrap(),
|
||||
)
|
||||
};
|
||||
|
||||
let mut player = self.player.write();
|
||||
let default_scene_uid = player
|
||||
.dungeon_collection
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.default_scene_uid
|
||||
.unwrap();
|
||||
|
||||
player.scene_uid.replace(default_scene_uid);
|
||||
let dungeon_collection = player.dungeon_collection.as_mut().unwrap();
|
||||
|
||||
let scene_info = dungeon_collection
|
||||
.scenes
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.get_mut(&default_scene_uid)
|
||||
.ok_or_else(|| anyhow!("Scene with uid {default_scene_uid} doesn't exist"))?;
|
||||
|
||||
let dungeon_uid = scene_info.get_dungeon_uid();
|
||||
let dungeon_info = dungeon_collection
|
||||
.dungeons
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.get_mut(&scene_info.get_dungeon_uid())
|
||||
.ok_or_else(|| anyhow!("Dungeon with uid {dungeon_uid} doesn't exist"))?;
|
||||
|
||||
scene_info.set_entered_times(scene_info.get_entered_times() + 1);
|
||||
dungeon_info.entered_times += 1;
|
||||
|
||||
let ptc_enter_scene = PtcEnterSceneArg {
|
||||
player_uid,
|
||||
scene_uid: default_scene_uid,
|
||||
section_id: scene_info.get_section_id(),
|
||||
open_ui: UIType::Default,
|
||||
condition_config_ids: Vec::new(),
|
||||
transform: Transform {
|
||||
position: scene_position,
|
||||
rotation: scene_rotation,
|
||||
},
|
||||
timestamp: util::cur_timestamp_ms(),
|
||||
camera_x: 0,
|
||||
camera_y: 6000,
|
||||
entered_times: scene_info.get_entered_times(),
|
||||
ext: match scene_info {
|
||||
SceneInfo::Hall { .. } => SceneTableExt::Hall {
|
||||
event_graphs_info: EventGraphsInfo {
|
||||
default_event_graph_id: 0,
|
||||
event_graphs_info: phashmap![],
|
||||
},
|
||||
},
|
||||
_ => bail!("Unexpected main city scene type"),
|
||||
},
|
||||
};
|
||||
|
||||
let add_dungeon = dungeon_info.clone();
|
||||
let add_scene = scene_info.clone();
|
||||
let cur_scene_uid = scene_info.get_uid();
|
||||
|
||||
Ok(PlayerOperationResult::with_changes(
|
||||
ptc_enter_scene,
|
||||
PlayerInfo {
|
||||
dungeon_collection: Some(DungeonCollection {
|
||||
dungeons: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(add_dungeon.uid, add_dungeon)],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
scenes: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(add_scene.get_uid(), add_scene)],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
scene_uid: Some(cur_scene_uid),
|
||||
..Default::default()
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn enter_scene_section(
|
||||
&self,
|
||||
scene_uid: u64,
|
||||
section_id: i32,
|
||||
) -> PlayerOperationResult<PtcEnterSectionArg> {
|
||||
let mut player = self.player.write();
|
||||
let scene_info = player
|
||||
.dungeon_collection
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.scenes
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.get_mut(&scene_uid)
|
||||
.unwrap();
|
||||
scene_info.set_section_id(section_id);
|
||||
|
||||
PlayerOperationResult::with_changes(
|
||||
PtcEnterSectionArg { section_id },
|
||||
PlayerInfo {
|
||||
dungeon_collection: Some(DungeonCollection {
|
||||
scenes: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(scene_uid, scene_info.clone())],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn enter_scene(&self, scene_uid: u64) -> Result<PlayerOperationResult<PtcEnterSceneArg>> {
|
||||
let (player_uid, prev_scene_uid) = {
|
||||
let player = self.player.read();
|
||||
|
||||
(
|
||||
*player.uid.as_ref().unwrap(),
|
||||
*player.scene_uid.as_ref().unwrap(),
|
||||
)
|
||||
};
|
||||
|
||||
let mut player = self.player.write();
|
||||
player.scene_uid.replace(scene_uid);
|
||||
player.prev_scene_uid.replace(prev_scene_uid);
|
||||
let dungeon_collection = player.dungeon_collection.as_mut().unwrap();
|
||||
|
||||
let scene_info = dungeon_collection
|
||||
.scenes
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.get_mut(&scene_uid)
|
||||
.ok_or_else(|| anyhow!("Scene with uid {scene_uid} doesn't exist"))?;
|
||||
|
||||
let dungeon_uid = scene_info.get_dungeon_uid();
|
||||
let dungeon_info = dungeon_collection
|
||||
.dungeons
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.get_mut(&scene_info.get_dungeon_uid())
|
||||
.ok_or_else(|| anyhow!("Dungeon with uid {dungeon_uid} doesn't exist"))?;
|
||||
|
||||
scene_info.set_entered_times(scene_info.get_entered_times() + 1);
|
||||
dungeon_info.entered_times += 1;
|
||||
|
||||
if let SceneInfo::Hollow { sections_info, .. } = scene_info {
|
||||
let section = sections_info.get_mut(&1).unwrap();
|
||||
section.entered_times += 1;
|
||||
}
|
||||
|
||||
let ptc_enter_scene = PtcEnterSceneArg {
|
||||
player_uid,
|
||||
scene_uid,
|
||||
section_id: scene_info.get_section_id(),
|
||||
open_ui: UIType::Default,
|
||||
condition_config_ids: Vec::new(),
|
||||
transform: Transform::default(),
|
||||
timestamp: util::cur_timestamp_ms(),
|
||||
camera_x: 0,
|
||||
camera_y: 6000,
|
||||
entered_times: scene_info.get_entered_times(),
|
||||
ext: match scene_info {
|
||||
SceneInfo::Hall { .. } => SceneTableExt::Hall {
|
||||
event_graphs_info: EventGraphsInfo {
|
||||
default_event_graph_id: 0,
|
||||
event_graphs_info: phashmap![],
|
||||
},
|
||||
},
|
||||
SceneInfo::Fresh { .. } => SceneTableExt::Fresh {
|
||||
event_graphs_info: EventGraphsInfo {
|
||||
default_event_graph_id: 0,
|
||||
event_graphs_info: phashmap![],
|
||||
},
|
||||
},
|
||||
SceneInfo::Hollow { .. } => SceneTableExt::Hollow {
|
||||
event_graphs_info: EventGraphsInfo {
|
||||
default_event_graph_id: 0,
|
||||
event_graphs_info: phashmap![],
|
||||
},
|
||||
grid_random_seed: 0,
|
||||
alter_section_id: 0,
|
||||
},
|
||||
SceneInfo::Fight { .. } => SceneTableExt::Fight {
|
||||
event_graphs_info: EventGraphsInfo {
|
||||
default_event_graph_id: 0,
|
||||
event_graphs_info: phashmap![],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Ok(PlayerOperationResult::with_changes(
|
||||
ptc_enter_scene,
|
||||
PlayerInfo {
|
||||
dungeon_collection: Some(DungeonCollection {
|
||||
dungeons: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(dungeon_info.uid, dungeon_info.clone())],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
scenes: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(scene_info.get_uid(), scene_info.clone())],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
scene_uid: Some(scene_uid),
|
||||
prev_scene_uid: Some(prev_scene_uid),
|
||||
..Default::default()
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn hollow_finished(&self) -> PlayerOperationResult<u64> {
|
||||
let cur_scene_uid = self.get_cur_scene_uid();
|
||||
|
||||
let mut player = self.player.write();
|
||||
|
||||
let hollow_scene = player
|
||||
.dungeon_collection
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.scenes
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.get_mut(&cur_scene_uid)
|
||||
.unwrap();
|
||||
|
||||
let dungeon_uid = hollow_scene.get_dungeon_uid();
|
||||
|
||||
if let SceneInfo::Hollow {
|
||||
hollow_system_ui_state,
|
||||
..
|
||||
} = hollow_scene
|
||||
{
|
||||
hollow_system_ui_state.insert(
|
||||
HollowSystemType::HollowResultPage,
|
||||
HollowSystemUIState::Normal,
|
||||
);
|
||||
hollow_system_ui_state.insert(HollowSystemType::Menu, HollowSystemUIState::Close);
|
||||
}
|
||||
|
||||
let add_scene = hollow_scene.clone();
|
||||
|
||||
let quest_data = player.quest_data.as_ref().unwrap();
|
||||
|
||||
//let quest_id = quest_data.quests.as_ref().unwrap().get_id;
|
||||
|
||||
//Finish inner hollow quest (DungeonInner)
|
||||
let mut dungeon_quest = quest_data
|
||||
.quests
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get(&dungeon_uid, &1001000102)
|
||||
.unwrap()
|
||||
.clone();
|
||||
dungeon_quest.set_progress(1);
|
||||
dungeon_quest.set_finished_count(1);
|
||||
dungeon_quest.set_state(QuestState::Finished);
|
||||
|
||||
PlayerOperationResult::with_changes(
|
||||
cur_scene_uid,
|
||||
PlayerInfo {
|
||||
dungeon_collection: Some(DungeonCollection {
|
||||
scenes: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(cur_scene_uid, add_scene)],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
quest_data: Some(QuestData {
|
||||
quests: Some(PropertyDoubleKeyHashMap::Modify {
|
||||
to_add: vec![(dungeon_uid, 1001000102, dungeon_quest)],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_default_scene_uid(&self) -> u64 {
|
||||
self.player
|
||||
.read()
|
||||
.dungeon_collection
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.default_scene_uid
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_default_scene_uid_for_dungeon(&self, dungeon_uid: u64) -> u64 {
|
||||
self.player
|
||||
.read()
|
||||
.dungeon_collection
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dungeons
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get(&dungeon_uid)
|
||||
.unwrap()
|
||||
.default_scene_uid
|
||||
}
|
||||
|
||||
pub fn get_cur_scene_uid(&self) -> u64 {
|
||||
self.player.read().scene_uid.unwrap()
|
||||
}
|
||||
|
||||
fn add_default_hollow_properties(&self, scene_uid: u64) {
|
||||
let mut props = self.scene_properties.write();
|
||||
|
||||
for (sub_key, value) in &[
|
||||
(1001, 0),
|
||||
(1002, 100),
|
||||
(1003, 0),
|
||||
(1004, 0),
|
||||
(1019, 10),
|
||||
(1020, 1),
|
||||
(1005, 0),
|
||||
(1006, 0),
|
||||
(1007, 0),
|
||||
(1008, 0),
|
||||
(1009, 0),
|
||||
(1010, 0),
|
||||
(1011, 0),
|
||||
(1012, 0),
|
||||
(1013, 1),
|
||||
(1014, 1),
|
||||
(1015, 0),
|
||||
(1016, 0),
|
||||
(1017, 4),
|
||||
(1018, 10000),
|
||||
(1021, 1),
|
||||
(1025, 1),
|
||||
(1035, 10000),
|
||||
(1041, 10000),
|
||||
(1042, 10000),
|
||||
(1043, 2),
|
||||
(1044, 1),
|
||||
] {
|
||||
props.insert(scene_uid, *sub_key, *value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn leave_battle(&self) -> Result<PlayerOperationResult<PtcEnterSceneArg>> {
|
||||
let back_scene_uid = self.get_back_scene_uid();
|
||||
|
||||
{
|
||||
let mut player = self.player.write();
|
||||
|
||||
let hollow_scene = player
|
||||
.dungeon_collection
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.scenes
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.get_mut(&back_scene_uid)
|
||||
.unwrap();
|
||||
|
||||
if let SceneInfo::Hollow {
|
||||
battle_scene_uid, ..
|
||||
} = hollow_scene
|
||||
{
|
||||
*battle_scene_uid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
self.enter_scene(back_scene_uid)
|
||||
}
|
||||
|
||||
fn get_back_scene_uid(&self) -> u64 {
|
||||
let player = self.player.read();
|
||||
let fight_scene_uid = player.scene_uid.as_ref().unwrap();
|
||||
let fight_scene = player
|
||||
.dungeon_collection
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.scenes
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get(fight_scene_uid)
|
||||
.unwrap();
|
||||
|
||||
fight_scene.get_back_scene_uid()
|
||||
}
|
||||
|
||||
pub fn enter_battle(&self, scene_uid: u64) -> PlayerOperationResult<PtcEnterSceneArg> {
|
||||
let hollow_scene_uid = *self.player.read().scene_uid.as_ref().unwrap();
|
||||
let hollow_scene = self.set_cur_hollow_battle(scene_uid, hollow_scene_uid);
|
||||
let ptc_enter_scene = self.enter_scene(scene_uid).unwrap().take().clone();
|
||||
|
||||
let player = self.player.read();
|
||||
let dungeon_collection = player.dungeon_collection.as_ref().unwrap();
|
||||
let fight_scene = dungeon_collection
|
||||
.scenes
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get(&scene_uid)
|
||||
.unwrap();
|
||||
|
||||
PlayerOperationResult::with_changes(
|
||||
ptc_enter_scene,
|
||||
PlayerInfo {
|
||||
dungeon_collection: Some(DungeonCollection {
|
||||
scenes: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![
|
||||
(hollow_scene_uid, hollow_scene),
|
||||
(scene_uid, fight_scene.clone()),
|
||||
],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
scene_uid: Some(scene_uid),
|
||||
prev_scene_uid: Some(hollow_scene_uid),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn set_cur_hollow_battle(&self, scene_uid: u64, hollow_scene_uid: u64) -> SceneInfo {
|
||||
let mut player = self.player.write();
|
||||
let hollow_scene = player
|
||||
.dungeon_collection
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.scenes
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.get_mut(&hollow_scene_uid)
|
||||
.unwrap();
|
||||
let SceneInfo::Hollow {
|
||||
on_battle_success,
|
||||
battle_scene_uid,
|
||||
..
|
||||
} = hollow_scene
|
||||
else {
|
||||
panic!("Unexpected scene type")
|
||||
};
|
||||
|
||||
*battle_scene_uid = scene_uid;
|
||||
*on_battle_success = String::from("OnEnd");
|
||||
|
||||
hollow_scene.clone()
|
||||
}
|
||||
|
||||
pub fn create_fight(&self, id: i32, hollow_scene_uid: u64) -> PlayerOperationResult<u64> {
|
||||
let mut player = self.player.write();
|
||||
let dungeon_collection = player.dungeon_collection.as_mut().unwrap();
|
||||
let scenes = dungeon_collection.scenes.as_mut().unwrap();
|
||||
let hollow_scene = scenes.get_mut(&hollow_scene_uid).unwrap();
|
||||
|
||||
let fight_scene_uid = self.uid_mgr.next();
|
||||
let fight_scene = SceneInfo::Fight {
|
||||
uid: fight_scene_uid,
|
||||
id,
|
||||
dungeon_uid: hollow_scene.get_dungeon_uid(),
|
||||
end_timestamp: 0,
|
||||
back_scene_uid: hollow_scene_uid,
|
||||
entered_times: 1,
|
||||
section_id: 1,
|
||||
open_ui: UIType::Default,
|
||||
to_be_destroyed: false,
|
||||
camera_x: 0xFFFFFFFF,
|
||||
camera_y: 0xFFFFFFFF,
|
||||
perform_show_progress: phashmap![],
|
||||
end_hollow: false,
|
||||
random_seed: 2281337,
|
||||
};
|
||||
|
||||
scenes.insert(fight_scene_uid, fight_scene.clone());
|
||||
PlayerOperationResult::with_changes(
|
||||
fight_scene_uid,
|
||||
PlayerInfo {
|
||||
dungeon_collection: Some(DungeonCollection {
|
||||
scenes: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(fight_scene_uid, fight_scene)],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn is_in_tutorial(&self) -> bool {
|
||||
let cur_scene_uid = self.get_cur_scene_uid();
|
||||
|
||||
let player = self.player.read();
|
||||
let cur_scene = player
|
||||
.dungeon_collection
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.scenes
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get(&cur_scene_uid)
|
||||
.unwrap();
|
||||
|
||||
matches!(cur_scene, SceneInfo::Fresh { .. })
|
||||
}
|
||||
|
||||
pub fn create_hollow(
|
||||
&self,
|
||||
id: i32,
|
||||
world_quest_id: i32,
|
||||
avatar_uids: &[u64],
|
||||
) -> PlayerOperationResult<(u64, u64)> {
|
||||
let back_scene_uid = self.get_default_scene_uid();
|
||||
|
||||
let mut dungeon = self.create_base_dungeon(id, back_scene_uid, world_quest_id);
|
||||
dungeon.hollow_event_version = 526;
|
||||
|
||||
let scene_uid = self.uid_mgr.next();
|
||||
dungeon.default_scene_uid = scene_uid;
|
||||
dungeon.scene_properties_uid = scene_uid;
|
||||
|
||||
self.add_default_hollow_properties(scene_uid);
|
||||
|
||||
for (index, avatar_uid) in avatar_uids.iter().enumerate() {
|
||||
dungeon.avatar_map.insert(
|
||||
index.try_into().unwrap(),
|
||||
AvatarUnitInfo {
|
||||
uid: *avatar_uid,
|
||||
properties_uid: self.uid_mgr.next(),
|
||||
is_banned: false,
|
||||
modified_property: pdkhashmap![],
|
||||
hp_add_hollow: 0,
|
||||
hp_lost_hollow: 0,
|
||||
layer_property_change: phashmap![],
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
let scene = SceneInfo::Hollow {
|
||||
uid: scene_uid,
|
||||
id,
|
||||
dungeon_uid: dungeon.uid,
|
||||
end_timestamp: 0,
|
||||
back_scene_uid,
|
||||
entered_times: 1,
|
||||
section_id: 1,
|
||||
open_ui: UIType::Default,
|
||||
to_be_destroyed: false,
|
||||
camera_x: 0xFFFFFFFF,
|
||||
camera_y: 0xFFFFFFFF,
|
||||
event_variables: phashmap![],
|
||||
buddy: BuddyUnitInfo {
|
||||
uid: 0,
|
||||
properties: 0,
|
||||
},
|
||||
stress_punish_ability_random_pool: vec![String::from(
|
||||
"Stress_Punish_RandomDebuff_Normal",
|
||||
)],
|
||||
finished: false,
|
||||
event_weight_factor: phashmap![],
|
||||
shop_modification: HollowShopModification {
|
||||
ability_modified_num: pdkhashmap![],
|
||||
action_modified_num: phashmap![],
|
||||
overwrite_price: phashmap![],
|
||||
},
|
||||
last_challenge_stat: phashmap![],
|
||||
cur_challenge: phashset![],
|
||||
hollow_system_switch: phashmap![],
|
||||
sections_info: phashmap![(
|
||||
1,
|
||||
PlayerHollowSectionInfo {
|
||||
prev_grid_index: 0,
|
||||
cur_grid_index: 8,
|
||||
entered_times: 0,
|
||||
global_event: 0,
|
||||
perform_event_graph: 3405096459205834,
|
||||
pos_before_move: 0,
|
||||
}
|
||||
)],
|
||||
executing_event: true,
|
||||
event_id: 1000,
|
||||
hollow_event_graph_uid: 8,
|
||||
on_battle_success: String::new(),
|
||||
on_battle_failure: String::new(),
|
||||
battle_finished: false,
|
||||
battle_success: false,
|
||||
battle_scene_uid: 0,
|
||||
scene_global_events: phashmap![],
|
||||
prepare_section: PrepareSection {
|
||||
section_id: 0,
|
||||
initial_pos: 0,
|
||||
show_other: false,
|
||||
battle_end_goto_next_hollow: false,
|
||||
},
|
||||
abilities_info: AbilitiesInfo {
|
||||
abilities: phashmap![],
|
||||
sequence_no: 0,
|
||||
},
|
||||
blackout: false,
|
||||
hollow_system_ui_state: phashmap![],
|
||||
};
|
||||
|
||||
{
|
||||
let mut player = self.player.write();
|
||||
player
|
||||
.scene_properties
|
||||
.replace(self.scene_properties.read().clone());
|
||||
|
||||
let dungeon_collection = player.dungeon_collection.as_mut().unwrap();
|
||||
|
||||
dungeon_collection
|
||||
.dungeons
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.insert(dungeon.uid, dungeon.clone());
|
||||
dungeon_collection
|
||||
.scenes
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.insert(scene_uid, scene.clone());
|
||||
}
|
||||
let mut player = self.player.write();
|
||||
let items = player.items.as_mut().unwrap();
|
||||
|
||||
let mut updated_items = Vec::new();
|
||||
for avatar_uid in avatar_uids {
|
||||
let item = items.get_mut(avatar_uid).unwrap();
|
||||
let ItemInfo::Avatar { robot_id, .. } = item else {
|
||||
continue;
|
||||
};
|
||||
*robot_id = 101000101;
|
||||
//*robot_id2 = 101000201;
|
||||
updated_items.push((*avatar_uid, item.clone()));
|
||||
|
||||
}
|
||||
|
||||
let mut prop_changes = Vec::new();
|
||||
for (key, sub_key, value) in &*self.scene_properties.write() {
|
||||
prop_changes.push((*key, *sub_key, *value));
|
||||
}
|
||||
|
||||
PlayerOperationResult::with_changes(
|
||||
(dungeon.uid, scene_uid),
|
||||
PlayerInfo {
|
||||
items: Some(PropertyHashMap::Modify {
|
||||
to_add: updated_items,
|
||||
to_remove: vec![],
|
||||
}),
|
||||
dungeon_collection: Some(DungeonCollection {
|
||||
dungeons: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(dungeon.uid, dungeon)],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
scenes: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(scene_uid, scene)],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
scene_properties: Some(PropertyDoubleKeyHashMap::Modify {
|
||||
to_add: prop_changes,
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn create_hall(&self, id: i32) -> PlayerOperationResult<u64> {
|
||||
let mut dungeon = self.create_base_dungeon(id, 0, 0);
|
||||
let dungeon_uid = dungeon.uid;
|
||||
|
||||
let scene_uid = self.uid_mgr.next();
|
||||
let hall_scene_info = SceneInfo::Hall {
|
||||
uid: scene_uid,
|
||||
id,
|
||||
dungeon_uid,
|
||||
end_timestamp: 0,
|
||||
back_scene_uid: 0,
|
||||
entered_times: 1,
|
||||
section_id: 1,
|
||||
open_ui: UIType::Default,
|
||||
to_be_destroyed: true,
|
||||
camera_x: 0xFFFFFFFF,
|
||||
camera_y: 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
dungeon.default_scene_uid = scene_uid;
|
||||
|
||||
let mut player = self.player.write();
|
||||
let dungeon_collection = player.dungeon_collection.as_mut().unwrap();
|
||||
|
||||
dungeon_collection
|
||||
.dungeons
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.insert(dungeon_uid, dungeon.clone());
|
||||
|
||||
dungeon_collection
|
||||
.scenes
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.insert(scene_uid, hall_scene_info.clone());
|
||||
|
||||
dungeon_collection.default_scene_uid.replace(scene_uid);
|
||||
PlayerOperationResult::with_changes(
|
||||
scene_uid,
|
||||
PlayerInfo {
|
||||
dungeon_collection: Some(DungeonCollection {
|
||||
dungeons: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(dungeon_uid, dungeon)],
|
||||
to_remove: vec![],
|
||||
}),
|
||||
scenes: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(scene_uid, hall_scene_info)],
|
||||
to_remove: vec![],
|
||||
}),
|
||||
default_scene_uid: Some(scene_uid),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn create_fresh(&self) -> PlayerOperationResult<u64> {
|
||||
let mut dungeon = self.create_base_dungeon(2, 0, 0);
|
||||
let dungeon_uid = dungeon.uid;
|
||||
|
||||
let scene_uid = self.uid_mgr.next();
|
||||
let fresh_scene_info = SceneInfo::Fresh {
|
||||
uid: scene_uid,
|
||||
id: 2,
|
||||
dungeon_uid,
|
||||
end_timestamp: 0,
|
||||
back_scene_uid: 0,
|
||||
entered_times: 1,
|
||||
section_id: 1,
|
||||
open_ui: UIType::Default,
|
||||
to_be_destroyed: true,
|
||||
camera_x: 0xFFFFFFFF,
|
||||
camera_y: 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
dungeon.default_scene_uid = scene_uid;
|
||||
|
||||
let mut player = self.player.write();
|
||||
let dungeon_collection = player.dungeon_collection.as_mut().unwrap();
|
||||
|
||||
dungeon_collection
|
||||
.dungeons
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.insert(dungeon_uid, dungeon.clone());
|
||||
|
||||
dungeon_collection
|
||||
.scenes
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.insert(scene_uid, fresh_scene_info.clone());
|
||||
|
||||
PlayerOperationResult::with_changes(
|
||||
scene_uid,
|
||||
PlayerInfo {
|
||||
dungeon_collection: Some(DungeonCollection {
|
||||
dungeons: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(dungeon_uid, dungeon)],
|
||||
to_remove: vec![],
|
||||
}),
|
||||
scenes: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(scene_uid, fresh_scene_info)],
|
||||
to_remove: vec![],
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn create_base_dungeon(
|
||||
&self,
|
||||
id: i32,
|
||||
back_scene_uid: u64,
|
||||
world_quest_id: i32,
|
||||
) -> DungeonInfo {
|
||||
let player = self.player.read();
|
||||
let uid = self.uid_mgr.next();
|
||||
|
||||
DungeonInfo {
|
||||
uid,
|
||||
id,
|
||||
default_scene_uid: 0,
|
||||
start_timestamp: util::cur_timestamp_ms(),
|
||||
to_be_destroyed: false,
|
||||
back_scene_uid,
|
||||
quest_collection_uid: uid,
|
||||
avatars: phashmap![],
|
||||
buddy: BuddyUnitInfo {
|
||||
uid: 0,
|
||||
properties: 0,
|
||||
},
|
||||
world_quest_id,
|
||||
scene_properties_uid: 0,
|
||||
drop_poll_chg_infos: phashmap![],
|
||||
is_in_dungeon: false,
|
||||
initiative_item: 0,
|
||||
initiative_item_used_times: 0,
|
||||
avatar_map: phashmap![],
|
||||
battle_report: Vec::new(),
|
||||
dungeon_group_uid: player.uid.unwrap(),
|
||||
entered_times: 0,
|
||||
is_preset_avatar: false,
|
||||
hollow_event_version: 0,
|
||||
}
|
||||
}
|
||||
}
|
8039
gameserver/src/game/manager/hollow_grid.rs
Normal file
8039
gameserver/src/game/manager/hollow_grid.rs
Normal file
File diff suppressed because it is too large
Load diff
170
gameserver/src/game/manager/item.rs
Normal file
170
gameserver/src/game/manager/item.rs
Normal file
|
@ -0,0 +1,170 @@
|
|||
use parking_lot::RwLock;
|
||||
use protocol::{ItemInfo, PlayerInfo};
|
||||
use qwer::{phashmap, PropertyHashMap};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::game::{util, PlayerOperationResult};
|
||||
use crate::config::CONFIGURATION;
|
||||
|
||||
use super::UniqueIDManager;
|
||||
|
||||
pub struct ItemManager {
|
||||
uid_mgr: Arc<UniqueIDManager>,
|
||||
player_info: Arc<RwLock<PlayerInfo>>,
|
||||
}
|
||||
|
||||
impl ItemManager {
|
||||
pub fn new(uid_mgr: Arc<UniqueIDManager>, player_info: Arc<RwLock<PlayerInfo>>) -> Self {
|
||||
Self {
|
||||
uid_mgr,
|
||||
player_info,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_resource(&self, currency_id: i32, amount: i32) -> PlayerOperationResult<i32> {
|
||||
let mut player_info = self.player_info.write();
|
||||
|
||||
for (uid, item) in player_info.items.as_mut().unwrap() {
|
||||
if let ItemInfo::Resource { id, count, .. } = item {
|
||||
if currency_id == *id {
|
||||
*count += amount;
|
||||
|
||||
return PlayerOperationResult::with_changes(
|
||||
*count,
|
||||
PlayerInfo {
|
||||
items: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(*uid, item.clone())],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let uid = self.uid_mgr.next();
|
||||
let item = ItemInfo::Resource {
|
||||
uid,
|
||||
id: currency_id,
|
||||
count: amount,
|
||||
package: 3,
|
||||
first_get_time: util::cur_timestamp_ms(),
|
||||
};
|
||||
|
||||
let items = player_info.items.as_mut().unwrap();
|
||||
items.insert(uid, item.clone());
|
||||
|
||||
PlayerOperationResult::with_changes(
|
||||
amount,
|
||||
PlayerInfo {
|
||||
items: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(uid, item)],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn unlock_avatar(&self, id: i32) -> PlayerOperationResult<u64> {
|
||||
let uid = self.uid_mgr.next();
|
||||
|
||||
let avatar = ItemInfo::Avatar {
|
||||
uid,
|
||||
id,
|
||||
count: 1,
|
||||
package: 3,
|
||||
first_get_time: util::cur_timestamp_ms(),
|
||||
star: CONFIGURATION.characters_star_rank,
|
||||
exp: 0,
|
||||
level: CONFIGURATION.characters_lvl,
|
||||
rank: CONFIGURATION.characters_ascension_rank,
|
||||
unlocked_talent_num: CONFIGURATION.characters_unlocked_talents,
|
||||
skills: phashmap![(2, CONFIGURATION.characters_dodge_lvl), (1, CONFIGURATION.characters_special_lvl), (0, CONFIGURATION.characters_normal_atk_lvl), (3, CONFIGURATION.characters_ult_lvl), (4, 1)],
|
||||
is_custom_by_dungeon: true,
|
||||
robot_id: 0,
|
||||
};
|
||||
|
||||
// Unlock & equip default weapon
|
||||
let weapon_uid = self.unlock_weapon(10012).take();
|
||||
self.equip_weapon(weapon_uid, uid);
|
||||
|
||||
let mut player_info = self.player_info.write();
|
||||
let items = player_info.items.as_mut().unwrap();
|
||||
items.insert(uid, avatar.clone());
|
||||
|
||||
PlayerOperationResult::with_changes(
|
||||
uid,
|
||||
PlayerInfo {
|
||||
items: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![
|
||||
(uid, avatar),
|
||||
(weapon_uid, items.get(&weapon_uid).unwrap().clone()),
|
||||
],
|
||||
to_remove: vec![],
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn unlock_weapon(&self, id: i32) -> PlayerOperationResult<u64> {
|
||||
let mut player_info = self.player_info.write();
|
||||
let items = player_info.items.as_mut().unwrap();
|
||||
|
||||
let uid = self.uid_mgr.next();
|
||||
|
||||
let weapon = ItemInfo::Weapon {
|
||||
uid,
|
||||
id,
|
||||
count: 1,
|
||||
package: 3,
|
||||
first_get_time: util::cur_timestamp_ms(),
|
||||
avatar_uid: 0,
|
||||
star: 0,
|
||||
exp: 0,
|
||||
level: 1,
|
||||
lock: 0,
|
||||
refine_level: 1,
|
||||
};
|
||||
|
||||
items.insert(uid, weapon.clone());
|
||||
PlayerOperationResult::with_changes(
|
||||
uid,
|
||||
PlayerInfo {
|
||||
items: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(uid, weapon)],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn equip_weapon(
|
||||
&self,
|
||||
weapon_uid: u64,
|
||||
equip_avatar_uid: u64,
|
||||
) -> PlayerOperationResult<bool> {
|
||||
let mut player_info = self.player_info.write();
|
||||
let items = player_info.items.as_mut().unwrap();
|
||||
|
||||
let Some(ItemInfo::Weapon { avatar_uid, .. }) = items.get_mut(&weapon_uid) else {
|
||||
return PlayerOperationResult::ret(false);
|
||||
};
|
||||
|
||||
*avatar_uid = equip_avatar_uid;
|
||||
|
||||
PlayerOperationResult::with_changes(
|
||||
true,
|
||||
PlayerInfo {
|
||||
items: Some(PropertyHashMap::Modify {
|
||||
to_add: vec![(weapon_uid, items.get(&weapon_uid).unwrap().clone())],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
18
gameserver/src/game/manager/mod.rs
Normal file
18
gameserver/src/game/manager/mod.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
mod dungeon;
|
||||
mod hollow_grid;
|
||||
mod item;
|
||||
pub mod net_stream;
|
||||
mod quest;
|
||||
mod scene_unit;
|
||||
mod unique_id;
|
||||
mod unlock;
|
||||
mod yorozuya_quest;
|
||||
|
||||
pub use dungeon::DungeonManager;
|
||||
pub use hollow_grid::HollowGridManager;
|
||||
pub use item::ItemManager;
|
||||
pub use quest::QuestManager;
|
||||
pub use scene_unit::SceneUnitManager;
|
||||
pub use unique_id::UniqueIDManager;
|
||||
pub use unlock::UnlockManager;
|
||||
pub use yorozuya_quest::YorozuyaQuestManager;
|
30
gameserver/src/game/manager/net_stream.rs
Normal file
30
gameserver/src/game/manager/net_stream.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use parking_lot::RwLock;
|
||||
use protocol::{AccountInfo, PlayerInfo, PropertyBlob};
|
||||
use qwer::OctData;
|
||||
use std::sync::Arc;
|
||||
|
||||
const CLIENT_PROP_FLAG: u16 = 1;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PropertyManager {
|
||||
pub account_info: Arc<RwLock<AccountInfo>>,
|
||||
pub player_info: Arc<RwLock<PlayerInfo>>,
|
||||
}
|
||||
|
||||
impl PropertyManager {
|
||||
pub fn serialize_account_info(&self) -> PropertyBlob {
|
||||
Self::serialize_property(&*self.account_info.read()).unwrap()
|
||||
}
|
||||
|
||||
pub fn serialize_player_info(&self) -> PropertyBlob {
|
||||
Self::serialize_property(&*self.player_info.read()).unwrap()
|
||||
}
|
||||
|
||||
pub fn serialize_property(prop: &impl OctData) -> Result<PropertyBlob, std::io::Error> {
|
||||
let mut stream = Vec::new();
|
||||
let mut cursor = std::io::Cursor::new(&mut stream);
|
||||
|
||||
prop.marshal_to(&mut cursor, CLIENT_PROP_FLAG)?;
|
||||
Ok(PropertyBlob { stream })
|
||||
}
|
||||
}
|
74
gameserver/src/game/manager/quest.rs
Normal file
74
gameserver/src/game/manager/quest.rs
Normal file
|
@ -0,0 +1,74 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::RwLock;
|
||||
use qwer::PropertyDoubleKeyHashMap;
|
||||
|
||||
use crate::game::PlayerOperationResult;
|
||||
|
||||
use super::UniqueIDManager;
|
||||
use protocol::*;
|
||||
|
||||
pub struct QuestManager {
|
||||
uid_mgr: Arc<UniqueIDManager>,
|
||||
player: Arc<RwLock<PlayerInfo>>,
|
||||
}
|
||||
|
||||
impl QuestManager {
|
||||
pub fn new(uid_mgr: Arc<UniqueIDManager>, player: Arc<RwLock<PlayerInfo>>) -> Self {
|
||||
Self { uid_mgr, player }
|
||||
}
|
||||
|
||||
pub fn add_world_quest(&self, quest: QuestInfo) -> PlayerOperationResult<u64> {
|
||||
let mut world_quest_collection_uid = self
|
||||
.player
|
||||
.read()
|
||||
.quest_data
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.world_quest_collection_uid
|
||||
.unwrap();
|
||||
|
||||
if world_quest_collection_uid == 0 {
|
||||
world_quest_collection_uid = self.uid_mgr.next();
|
||||
self.player
|
||||
.write()
|
||||
.quest_data
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.world_quest_collection_uid
|
||||
.replace(world_quest_collection_uid);
|
||||
}
|
||||
|
||||
self.add_quest_to_collection(world_quest_collection_uid, quest)
|
||||
}
|
||||
|
||||
pub fn add_quest_to_collection(
|
||||
&self,
|
||||
collection_uid: u64,
|
||||
mut quest: QuestInfo,
|
||||
) -> PlayerOperationResult<u64> {
|
||||
let mut player = self.player.write();
|
||||
let quest_data = player.quest_data.as_mut().unwrap();
|
||||
quest.set_collection_uid(collection_uid);
|
||||
|
||||
quest_data
|
||||
.quests
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.insert(collection_uid, quest.get_id(), quest.clone());
|
||||
|
||||
PlayerOperationResult::with_changes(
|
||||
collection_uid,
|
||||
PlayerInfo {
|
||||
quest_data: Some(QuestData {
|
||||
quests: Some(PropertyDoubleKeyHashMap::Modify {
|
||||
to_add: vec![(collection_uid, quest.get_id(), quest)],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
131
gameserver/src/game/manager/scene_unit.rs
Normal file
131
gameserver/src/game/manager/scene_unit.rs
Normal file
|
@ -0,0 +1,131 @@
|
|||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use parking_lot::RwLock;
|
||||
use protocol::*;
|
||||
use qwer::{phashmap, PropertyHashMap};
|
||||
|
||||
use crate::data;
|
||||
|
||||
use super::UniqueIDManager;
|
||||
|
||||
pub struct SceneUnitManager {
|
||||
uid_mgr: Arc<UniqueIDManager>,
|
||||
units: RwLock<HashMap<u64, SceneUnitProtocolInfo>>,
|
||||
}
|
||||
|
||||
impl SceneUnitManager {
|
||||
pub fn new(uid_mgr: Arc<UniqueIDManager>) -> Self {
|
||||
Self {
|
||||
uid_mgr,
|
||||
units: RwLock::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_npc(
|
||||
&self,
|
||||
id: i32,
|
||||
tag: i32,
|
||||
quest_id: i32,
|
||||
interacts_info: PropertyHashMap<i32, InteractInfo>,
|
||||
) -> u64 {
|
||||
let uid = self.uid_mgr.next();
|
||||
|
||||
self.units.write().insert(
|
||||
uid,
|
||||
SceneUnitProtocolInfo::NpcProtocolInfo {
|
||||
uid,
|
||||
tag,
|
||||
id,
|
||||
quest_id,
|
||||
interacts_info,
|
||||
},
|
||||
);
|
||||
|
||||
uid
|
||||
}
|
||||
|
||||
pub fn get(&self, uid: u64) -> Option<SceneUnitProtocolInfo> {
|
||||
self.units.read().get(&uid).map(|u| u.clone())
|
||||
}
|
||||
|
||||
pub fn sync(&self, scene_uid: u64, section_id: i32) -> PtcSyncSceneUnitArg {
|
||||
PtcSyncSceneUnitArg {
|
||||
scene_uid,
|
||||
section_id,
|
||||
is_partial: false,
|
||||
removed_scene_units: Vec::new(),
|
||||
scene_units: self
|
||||
.units
|
||||
.read()
|
||||
.iter()
|
||||
.map(|(_, unit)| unit.clone())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_scene_units(&self, section_id: i32) {
|
||||
for o in data::iter_main_city_object_collection().filter(|o| {
|
||||
o.create_type == 0
|
||||
&& data::is_transform_in_section(&o.create_position, section_id)
|
||||
&& o.default_interact_ids.len() != 0
|
||||
&& !o.create_position.ends_with("_Test")
|
||||
}) {
|
||||
self.create_npc(
|
||||
o.npc_id,
|
||||
o.tag_id,
|
||||
0,
|
||||
PropertyHashMap::Base(
|
||||
o.default_interact_ids
|
||||
.iter()
|
||||
.map(|id| {
|
||||
(
|
||||
*id,
|
||||
create_interact(
|
||||
*id,
|
||||
o.interact_shape as u16,
|
||||
InteractScale::from_slice(&o.interact_scale).unwrap(),
|
||||
&o.interact_name.clone().unwrap_or_default(),
|
||||
phashmap![],
|
||||
),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: partial_sync for newly added/removed units
|
||||
}
|
||||
|
||||
struct InteractScale(pub f64, pub f64, pub f64, pub f64, pub f64);
|
||||
impl InteractScale {
|
||||
pub fn from_slice(v: &[f64]) -> Result<Self> {
|
||||
if v.len() != 5 {
|
||||
bail!("InteractScale slice should contain 5 values");
|
||||
}
|
||||
|
||||
Ok(Self(v[0], v[1], v[2], v[3], v[4]))
|
||||
}
|
||||
}
|
||||
|
||||
fn create_interact(
|
||||
interact_id: i32,
|
||||
interact_shape: u16,
|
||||
scale: InteractScale,
|
||||
name: &str,
|
||||
participators: PropertyHashMap<i32, String>,
|
||||
) -> InteractInfo {
|
||||
InteractInfo {
|
||||
interact_id,
|
||||
interact_shape,
|
||||
scale_x: scale.0,
|
||||
scale_y: scale.1,
|
||||
scale_z: scale.2,
|
||||
scale_w: scale.3,
|
||||
scale_r: scale.4,
|
||||
name: name.to_string(),
|
||||
participators,
|
||||
}
|
||||
}
|
14
gameserver/src/game/manager/unique_id.rs
Normal file
14
gameserver/src/game/manager/unique_id.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
pub struct UniqueIDManager(AtomicU64);
|
||||
|
||||
impl UniqueIDManager {
|
||||
const BASE_UID: u64 = 1000000;
|
||||
pub const fn new() -> Self {
|
||||
Self(AtomicU64::new(Self::BASE_UID))
|
||||
}
|
||||
|
||||
pub fn next(&self) -> u64 {
|
||||
self.0.fetch_add(1, Ordering::SeqCst) + 1
|
||||
}
|
||||
}
|
42
gameserver/src/game/manager/unlock.rs
Normal file
42
gameserver/src/game/manager/unlock.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::RwLock;
|
||||
use protocol::*;
|
||||
use qwer::PropertyHashSet;
|
||||
|
||||
use crate::game::PlayerOperationResult;
|
||||
|
||||
pub struct UnlockManager {
|
||||
player: Arc<RwLock<PlayerInfo>>,
|
||||
}
|
||||
|
||||
impl UnlockManager {
|
||||
pub fn new(player: Arc<RwLock<PlayerInfo>>) -> Self {
|
||||
Self { player }
|
||||
}
|
||||
|
||||
pub fn unlock(&self, unlock_id: i32) -> PlayerOperationResult<PtcUnlockArg> {
|
||||
let mut player = self.player.write();
|
||||
let unlock_info = player.unlock_info.as_mut().unwrap();
|
||||
|
||||
unlock_info
|
||||
.unlocked_list
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.insert(unlock_id);
|
||||
|
||||
PlayerOperationResult::with_changes(
|
||||
PtcUnlockArg { unlock_id },
|
||||
PlayerInfo {
|
||||
unlock_info: Some(UnlockInfo {
|
||||
unlocked_list: Some(PropertyHashSet::Modify {
|
||||
to_add: vec![unlock_id],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
condition_progress: None,
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
68
gameserver/src/game/manager/yorozuya_quest.rs
Normal file
68
gameserver/src/game/manager/yorozuya_quest.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::RwLock;
|
||||
use qwer::{PropertyDoubleKeyHashMap, PropertyHashSet};
|
||||
|
||||
use crate::game::PlayerOperationResult;
|
||||
|
||||
use protocol::*;
|
||||
|
||||
pub struct YorozuyaQuestManager {
|
||||
player: Arc<RwLock<PlayerInfo>>,
|
||||
}
|
||||
|
||||
impl YorozuyaQuestManager {
|
||||
pub fn new(player: Arc<RwLock<PlayerInfo>>) -> Self {
|
||||
Self { player }
|
||||
}
|
||||
|
||||
pub fn add_hollow_quest(
|
||||
&self,
|
||||
yorozuya_collection_id: i32,
|
||||
hollow_quest_type: HollowQuestType,
|
||||
id: i32,
|
||||
) -> PlayerOperationResult<i32> {
|
||||
let mut player = self.player.write();
|
||||
let yorozuya = player.yorozuya_info.as_mut().unwrap();
|
||||
let hollow_quests = yorozuya.hollow_quests.as_mut().unwrap();
|
||||
|
||||
let updated_set = {
|
||||
if let Some(quests) = hollow_quests.get_mut(&yorozuya_collection_id, &hollow_quest_type)
|
||||
{
|
||||
quests.insert(id);
|
||||
let PropertyHashSet::Base(set) = quests else {
|
||||
return PlayerOperationResult::ret(yorozuya_collection_id);
|
||||
};
|
||||
set.clone()
|
||||
} else {
|
||||
let set = HashSet::from([id]);
|
||||
hollow_quests.insert(
|
||||
yorozuya_collection_id,
|
||||
hollow_quest_type,
|
||||
PropertyHashSet::Base(set.clone()),
|
||||
);
|
||||
|
||||
set
|
||||
}
|
||||
};
|
||||
|
||||
PlayerOperationResult::with_changes(
|
||||
yorozuya_collection_id,
|
||||
PlayerInfo {
|
||||
yorozuya_info: Some(YorozuyaInfo {
|
||||
hollow_quests: Some(PropertyDoubleKeyHashMap::Modify {
|
||||
to_add: vec![(
|
||||
yorozuya_collection_id,
|
||||
hollow_quest_type,
|
||||
PropertyHashSet::Base(updated_set),
|
||||
)],
|
||||
to_remove: Vec::new(),
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
5
gameserver/src/game/mod.rs
Normal file
5
gameserver/src/game/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
mod context;
|
||||
pub mod manager;
|
||||
pub mod util;
|
||||
|
||||
pub use context::{GameContext, PlayerOperationResult};
|
295
gameserver/src/game/util.rs
Normal file
295
gameserver/src/game/util.rs
Normal file
|
@ -0,0 +1,295 @@
|
|||
use protocol::*;
|
||||
use qwer::{
|
||||
pdkhashmap, phashmap, phashset, PropertyDoubleKeyHashMap, PropertyHashMap, PropertyHashSet,
|
||||
};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use crate::config::CONFIGURATION;
|
||||
|
||||
pub fn cur_timestamp_ms() -> u64 {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_millis() as u64
|
||||
}
|
||||
|
||||
pub fn create_default_account(id: u64) -> AccountInfo {
|
||||
AccountInfo {
|
||||
account_name: Some(format!("1_{id}")),
|
||||
players: Some(Vec::new()),
|
||||
gm_level: Some(10),
|
||||
account_type: Some(1),
|
||||
register_cps: Some(String::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_default_player(id: u64) -> PlayerInfo {
|
||||
PlayerInfo {
|
||||
uid: Some(id),
|
||||
account_name: Some(format!("1_{id}")),
|
||||
items: Some(qwer::phashmap![(
|
||||
3405096459205780,
|
||||
ItemInfo::Buddy {
|
||||
uid: 3405096459205780,
|
||||
id: 50012,
|
||||
count: 1,
|
||||
package: 3,
|
||||
first_get_time: 0,
|
||||
}
|
||||
)]),
|
||||
dungeon_collection: Some(DungeonCollection {
|
||||
dungeons: Some(qwer::phashmap![]),
|
||||
scenes: Some(qwer::phashmap![]),
|
||||
default_scene_uid: Some(0),
|
||||
transform: Some(Transform::default()),
|
||||
used_story_mode: Some(true),
|
||||
used_manual_qte_mode: Some(true),
|
||||
}),
|
||||
properties: Some(pdkhashmap![]),
|
||||
scene_properties: Some(pdkhashmap![]),
|
||||
quest_data: Some(QuestData {
|
||||
quests: Some(pdkhashmap![]),
|
||||
is_afk: Some(false),
|
||||
unlock_condition_progress: Some(pdkhashmap![]),
|
||||
world_quest_collection_uid: Some(0),
|
||||
world_quest_for_cur_dungeon: Some(0),
|
||||
world_quest_for_cur_dungeon_afk: Some(0),
|
||||
}),
|
||||
joined_chat_rooms: Some(Vec::new()),
|
||||
last_enter_world_timestamp: Some(0),
|
||||
scene_uid: Some(0),
|
||||
archive_info: Some(ArchiveInfo {
|
||||
videotapes_info: Some(phashmap![]),
|
||||
}),
|
||||
auto_recovery_info: Some(phashmap![(
|
||||
501,
|
||||
AutoRecoveryInfo {
|
||||
buy_times: 0,
|
||||
last_recovery_timestamp: 0,
|
||||
}
|
||||
)]),
|
||||
unlock_info: Some(UnlockInfo {
|
||||
condition_progress: Some(pdkhashmap![]),
|
||||
unlocked_list: Some(phashset![]),
|
||||
}),
|
||||
yorozuya_info: Some(YorozuyaInfo {
|
||||
yorozuya_level: Some(5),
|
||||
yorozuya_rank: Some(1),
|
||||
gm_enabled: Some(true),
|
||||
gm_quests: Some(phashmap![]),
|
||||
finished_hollow_quest_count: Some(0),
|
||||
finished_hollow_quest_count_of_type: Some(phashmap![]),
|
||||
hollow_quests: Some(pdkhashmap![]),
|
||||
urgent_quests_queue: Some(phashmap![]),
|
||||
unlock_hollow_id: Some(vec![102,101]),
|
||||
unlock_hollow_id_progress: Some(pdkhashmap![]),
|
||||
last_refresh_timestamp_common: Some(0),
|
||||
last_refresh_timestamp_urgent: Some(0),
|
||||
next_refresh_timestamp_urgent: Some(0),
|
||||
}),
|
||||
equip_gacha_info: Some(EquipGachaInfo {
|
||||
avatar_level_advance_times: Some(0),
|
||||
equip_star_up_times: Some(0),
|
||||
security_num_by_lv: Some(phashmap![]),
|
||||
smithy_level: Some(0),
|
||||
total_gacha_times: Some(0),
|
||||
}),
|
||||
beginner_procedure_info: Some(BeginnerProcedureInfo {
|
||||
procedure_info: Some(0),
|
||||
}),
|
||||
pos_in_main_city: Some(PlayerPosInMainCity {
|
||||
position: Some(Vector3f {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
}),
|
||||
rotation: Some(Vector3f {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
}),
|
||||
initial_pos_id: Some(0),
|
||||
}),
|
||||
fairy_info: Some(FairyInfo {
|
||||
condition_progress: Some(pdkhashmap![]),
|
||||
fairy_groups: Some(phashmap![]),
|
||||
}),
|
||||
popup_window_info: Some(PopupWindowInfo {
|
||||
condition_progress: Some(pdkhashmap![]),
|
||||
popup_window_list: Some(Vec::new()),
|
||||
}),
|
||||
tips_info: Some(TipsInfo {
|
||||
tips_list: Some(Vec::new()),
|
||||
tips_group: Some(Vec::new()),
|
||||
tips_condition_progress: Some(pdkhashmap![]),
|
||||
tips_group_condition_progress: Some(pdkhashmap![]),
|
||||
}),
|
||||
main_city_quest_data: Some(MainCityQuestData {
|
||||
in_progress_quests: Some(Vec::new()),
|
||||
exicing_finish_script_group: Some(vec![10020001]),
|
||||
}),
|
||||
embattles: Some(Embattles {
|
||||
last_embattles: Some(phashmap![]),
|
||||
}),
|
||||
day_change_info: Some(DayChangeInfo {
|
||||
last_daily_refresh_timing: Some(0),
|
||||
}),
|
||||
npcs_info: Some(PlayerNPCsInfo {
|
||||
npcs_info: Some(phashmap![]),
|
||||
destroy_npc_when_leave_section: Some(phashset![]),
|
||||
}),
|
||||
scripts_to_execute: Some(pdkhashmap![]),
|
||||
scripts_to_remove: Some(phashmap![]),
|
||||
last_leave_world_timestamp: Some(0),
|
||||
muip_data: Some(MUIPData {
|
||||
alread_cmd_uids: Some(phashset![]),
|
||||
ban_end_time: Some(String::new()),
|
||||
tag_value: Some(0),
|
||||
scene_pass_times: Some(phashmap![]),
|
||||
scene_enter_times: Some(phashmap![]),
|
||||
dungeon_pass_times: Some(phashmap![]),
|
||||
dungeon_enter_times: Some(phashmap![]),
|
||||
ban_begin_time: Some(String::new()),
|
||||
game_total_time: Some(0),
|
||||
language_type: Some(0),
|
||||
}),
|
||||
nick_name: Some(String::new()),
|
||||
ramen_data: Some(RamenData {
|
||||
unlock_ramen: Some(phashset![20301, 20401, 20501, 20601, 20201]),
|
||||
cur_ramen: Some(0),
|
||||
used_times: Some(0),
|
||||
unlock_initiative_item: Some(phashset![]),
|
||||
unlock_ramen_condition_progress: Some(pdkhashmap![]),
|
||||
unlock_item_condition_progress: Some(pdkhashmap![]),
|
||||
has_mystical_spice: Some(true),
|
||||
unlock_has_mystical_spice_condition_progress: Some(phashmap![]),
|
||||
cur_mystical_spice: Some(0),
|
||||
unlock_mystical_spice: Some(phashset![
|
||||
30101, 30601, 30201, 30501, 30301, 30801, 31201, 30401, 31401, 31001
|
||||
]),
|
||||
unlock_mystical_spice_condition_progress: Some(pdkhashmap![]),
|
||||
unlock_initiative_item_group: Some(phashset![]),
|
||||
hollow_item_history: Some(phashmap![]),
|
||||
initial_item_ability: Some(0),
|
||||
new_unlock_ramen: Some(Vec::new()),
|
||||
eat_ramen_times: Some(0),
|
||||
make_hollow_item_times: Some(0),
|
||||
new_unlock_initiative_item: Some(phashset![]),
|
||||
}),
|
||||
|
||||
shop: Some(ShopsInfo {
|
||||
shops: Some(phashmap![]),
|
||||
shop_buy_times: Some(0),
|
||||
vip_level: Some(0),
|
||||
}),
|
||||
vhs_store_data: Some(VHSStoreData {
|
||||
store_level: Some(0),
|
||||
unreceived_reward: Some(0),
|
||||
hollow_enter_times: Some(0),
|
||||
last_receive_time: Some(0),
|
||||
vhs_collection_slot: Some(Vec::new()),
|
||||
unlock_vhs_collection: Some(phashset![]),
|
||||
already_trending: Some(phashset![]),
|
||||
unlock_trending_condition_progress: Some(pdkhashmap![]),
|
||||
is_need_refresh: Some(true),
|
||||
scripts_id: Some(phashset![]),
|
||||
store_exp: Some(0),
|
||||
is_level_chg_tips: Some(true),
|
||||
vhs_hollow: Some(Vec::new()),
|
||||
is_receive_trending_reward: Some(false),
|
||||
is_need_first_trending: Some(false),
|
||||
last_basic_script: Some(0),
|
||||
is_complete_first_trending: Some(false),
|
||||
last_basic_npc: Some(0),
|
||||
can_random_trending: Some(phashset![]),
|
||||
vhs_trending_info: Some(Vec::new()),
|
||||
unlock_vhs_trending_info: Some(phashmap![]),
|
||||
vhs_flow: Some(0),
|
||||
received_reward: Some(0),
|
||||
last_reward: Some(0),
|
||||
last_exp: Some(0),
|
||||
last_flow: Some(0),
|
||||
last_vhs_trending_info: Some(Vec::new()),
|
||||
new_know_trend: Some(Vec::new()),
|
||||
quest_finish_script: Some(pdkhashmap![]),
|
||||
quest_finish_scripts_id: Some(phashset![]),
|
||||
total_received_reward: Some(phashmap![]),
|
||||
last_vhs_npc_info: Some(Vec::new()),
|
||||
vhs_npc_info: Some(Vec::new()),
|
||||
npc_info: Some(phashset![]),
|
||||
total_received_reward_times: Some(0),
|
||||
}),
|
||||
operation_mail_receive_info: Some(OperationMailReceiveInfo {
|
||||
receive_list: Some(phashset![]),
|
||||
condition_progress: Some(pdkhashmap![]),
|
||||
}),
|
||||
second_last_enter_world_timestamp: Some(0),
|
||||
login_times: Some(1),
|
||||
create_timestamp: Some(cur_timestamp_ms()),
|
||||
gender: Some(0),
|
||||
avatar_id: Some(0),
|
||||
prev_scene_uid: Some(2),
|
||||
register_cps: Some(String::new()),
|
||||
register_platform: Some(3),
|
||||
pay_info: Some(PayInfo {
|
||||
month_total_pay: Some(0),
|
||||
}),
|
||||
private_npcs: Some(phashmap![]),
|
||||
battle_event_info: Some(BattleEventInfo {
|
||||
unlock_battle: Some(phashset![]),
|
||||
unlock_battle_condition_progress: Some(pdkhashmap![]),
|
||||
alread_rand_battle: Some(pdkhashmap![]),
|
||||
alread_battle_stage: Some(Vec::new()),
|
||||
rand_battle_type: Some(phashmap![]),
|
||||
}),
|
||||
gm_data: Some(GMData {
|
||||
register_conditions: Some(phashset![]),
|
||||
condition_proress: Some(pdkhashmap![]),
|
||||
completed_conditions: Some(phashset![]),
|
||||
}),
|
||||
player_mail_ext_infos: Some(PlayerMailExtInfos {
|
||||
player_mail_ext_info: Some(phashmap![]),
|
||||
}),
|
||||
single_dungeon_group: Some(SingleDungeonGroup {
|
||||
dungeons: Some(phashmap![]),
|
||||
scenes: Some(pdkhashmap![]),
|
||||
npcs: Some(pdkhashmap![]),
|
||||
section: Some(pdkhashmap![]),
|
||||
}),
|
||||
newbie_info: Some(NewbieInfo {
|
||||
unlocked_id: Some(phashset![3]),
|
||||
condition_progress: Some(pdkhashmap![]),
|
||||
}),
|
||||
loading_page_tips_info: Some(LoadingPageTipsInfo {
|
||||
unlocked_id: Some(phashset![1, 2, 3]),
|
||||
condition_progress: Some(pdkhashmap![]),
|
||||
}),
|
||||
switch_of_story_mode: Some(true),
|
||||
switch_of_qte: Some(CONFIGURATION.manual_chain_attacks),
|
||||
collect_map: Some(CollectMap {
|
||||
card_map: Some(phashset![]),
|
||||
curse_map: Some(phashset![]),
|
||||
unlock_cards: Some(phashset![]),
|
||||
unlock_curses: Some(phashset![]),
|
||||
event_icon_map: Some(phashset![]),
|
||||
unlock_events: Some(phashset![]),
|
||||
new_card_map: Some(phashset![]),
|
||||
new_curse_map: Some(phashset![]),
|
||||
new_event_icon_map: Some(phashset![]),
|
||||
unlock_event_icon_condition_progress: Some(pdkhashmap![]),
|
||||
unlock_card_condition_progress: Some(pdkhashmap![]),
|
||||
unlock_curse_condition_progress: Some(pdkhashmap![]),
|
||||
unlock_event_condition_progress: Some(pdkhashmap![]),
|
||||
unlock_event_icons: Some(phashset![]),
|
||||
}),
|
||||
areas_info: Some(AreasInfo {
|
||||
area_owners_info: Some(pdkhashmap![]),
|
||||
sequence: Some(0),
|
||||
}),
|
||||
bgm_info: Some(BGMInfo { bgm_id: Some(1) }),
|
||||
main_city_objects_state: Some(phashmap![(1000,10002), (1001,10004), (1002,10006), (999,10007)]),
|
||||
hollow_info: Some(HollowInfo {
|
||||
banned_hollow_event: Some(phashset![]),
|
||||
}),
|
||||
}
|
||||
}
|
61
gameserver/src/logging.rs
Normal file
61
gameserver/src/logging.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use tracing::Instrument;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! log_error {
|
||||
($e:expr) => {
|
||||
if let Err(e) = $e {
|
||||
tracing::error!(error.message = %format!("{}", &e), "{:?}", e);
|
||||
}
|
||||
};
|
||||
($context:expr, $e:expr $(,)?) => {
|
||||
if let Err(e) = $e {
|
||||
let e = format!("{:?}", ::anyhow::anyhow!(e).context($context));
|
||||
tracing::error!(error.message = %format!("{}", &e), "{:?}", e);
|
||||
}
|
||||
};
|
||||
($ok_context:expr, $err_context:expr, $e:expr $(,)?) => {
|
||||
if let Err(e) = $e {
|
||||
let e = format!("{:?}", ::anyhow::anyhow!(e).context($err_context));
|
||||
tracing::error!(error.message = %format!("{}", &e), "{:?}", e);
|
||||
} else {
|
||||
tracing::info!($ok_context);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn init_logging() {
|
||||
#[cfg(target_os = "windows")]
|
||||
ansi_term::enable_ansi_support().unwrap();
|
||||
|
||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
}
|
||||
|
||||
pub async fn init_system_logging() {
|
||||
use std::time::Duration;
|
||||
use sysinfo::System;
|
||||
|
||||
tokio::spawn(
|
||||
async {
|
||||
let mut s = System::new_all();
|
||||
s.refresh_all();
|
||||
let num_cpus = s.cpus().len();
|
||||
loop {
|
||||
tokio::time::sleep(Duration::from_millis(20000)).await;
|
||||
s.refresh_all();
|
||||
let process = s.process(sysinfo::get_current_pid().unwrap()).unwrap();
|
||||
tracing::info!(
|
||||
cpu_usage = %format!("{:.2}%", process.cpu_usage() / num_cpus as f32)
|
||||
);
|
||||
let memory = process.memory();
|
||||
let formatted = match memory {
|
||||
m if m < 1024 => format!("{m} B"),
|
||||
m if m < 1024 * 1024 => format!("{:.2} KB", m as f32 / 1024.0),
|
||||
m if m < 1024 * 1024 * 1024 => format!("{:.2} MB", m as f32 / 1024.0 / 1024.0),
|
||||
m => format!("{:.2} GB", m as f32 / 1024.0 / 1024.0 / 1024.0),
|
||||
};
|
||||
tracing::info!(total_memory = %format!("{formatted}"));
|
||||
}
|
||||
}
|
||||
.instrument(tracing::info_span!("system-usage")),
|
||||
);
|
||||
}
|
40
gameserver/src/main.rs
Normal file
40
gameserver/src/main.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
use std::io::{stdin, Read};
|
||||
|
||||
use anyhow::Result;
|
||||
use tracing::Level;
|
||||
|
||||
mod config;
|
||||
mod data;
|
||||
mod game;
|
||||
mod logging;
|
||||
mod net;
|
||||
|
||||
use config::{init_config, CONFIGURATION};
|
||||
use data::init_assets;
|
||||
use logging::{init_logging, init_system_logging};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
init_logging();
|
||||
init_config();
|
||||
if let Err(err) = init_assets() {
|
||||
tracing::error!("Error occurred during assets initialization: {err}");
|
||||
on_critical_fault();
|
||||
}
|
||||
|
||||
let span = tracing::span!(Level::DEBUG, "main");
|
||||
let _enter = span.enter();
|
||||
|
||||
if CONFIGURATION.system_resources_logging {
|
||||
init_system_logging().await;
|
||||
}
|
||||
|
||||
net::gateway::listen(&CONFIGURATION.gateway_endpoint).await
|
||||
}
|
||||
|
||||
fn on_critical_fault() {
|
||||
eprintln!("Critical error occurred, press any key to exit...");
|
||||
|
||||
let _ = stdin().read(&mut [0u8]).unwrap();
|
||||
std::process::exit(1);
|
||||
}
|
32
gameserver/src/net/gateway.rs
Normal file
32
gameserver/src/net/gateway.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use anyhow::Result;
|
||||
use tokio::net::TcpListener;
|
||||
use tracing::Instrument;
|
||||
|
||||
use crate::log_error;
|
||||
|
||||
use super::NetworkSession;
|
||||
|
||||
pub async fn listen(bind_addr: &str) -> Result<()> {
|
||||
let listener = TcpListener::bind(bind_addr).await?;
|
||||
tracing::info!("Listening at {bind_addr}");
|
||||
|
||||
loop {
|
||||
let Ok((client_socket, client_addr)) = listener.accept().await else {
|
||||
continue;
|
||||
};
|
||||
|
||||
tracing::info!("New session from {client_addr}");
|
||||
|
||||
let mut session = NetworkSession::new(client_socket);
|
||||
tokio::spawn(
|
||||
async move {
|
||||
log_error!(
|
||||
"Session from {client_addr} disconnected",
|
||||
format!("An error occurred while processing session ({client_addr})"),
|
||||
Box::pin(session.run()).await
|
||||
);
|
||||
}
|
||||
.instrument(tracing::info_span!("session", addr = %client_addr)),
|
||||
);
|
||||
}
|
||||
}
|
13
gameserver/src/net/handlers/battle.rs
Normal file
13
gameserver/src/net/handlers/battle.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
use super::*;
|
||||
|
||||
pub async fn on_rpc_battle_report(
|
||||
_session: &NetworkSession,
|
||||
arg: &RpcBattleReportArg,
|
||||
) -> Result<RpcBattleReportRet> {
|
||||
let need_index = arg
|
||||
.battle_reports
|
||||
.last()
|
||||
.map_or(0, |report| report.index + 1);
|
||||
|
||||
Ok(RpcBattleReportRet::new(need_index))
|
||||
}
|
43
gameserver/src/net/handlers/beginner_procedure.rs
Normal file
43
gameserver/src/net/handlers/beginner_procedure.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
use common::util;
|
||||
|
||||
use super::*;
|
||||
|
||||
const START_PROC_ID: i32 = 1;
|
||||
|
||||
pub async fn on_rpc_advance_beginner_procedure(
|
||||
session: &NetworkSession,
|
||||
arg: &RpcAdvanceBeginnerProcedureArg,
|
||||
) -> Result<RpcAdvanceBeginnerProcedureRet> {
|
||||
let next_procedure_id = if arg.procedure_id == 0 {
|
||||
START_PROC_ID
|
||||
} else {
|
||||
arg.procedure_id + 1
|
||||
};
|
||||
|
||||
tracing::info!("{arg:?}");
|
||||
if arg.procedure_id == 6 {
|
||||
Box::pin(world::enter_main_city(session)).await?;
|
||||
}
|
||||
|
||||
Ok(RpcAdvanceBeginnerProcedureRet::new(next_procedure_id))
|
||||
}
|
||||
|
||||
pub async fn on_rpc_beginnerbattle_begin(
|
||||
_session: &NetworkSession,
|
||||
arg: &RpcBeginnerbattleBeginArg,
|
||||
) -> Result<RpcBeginnerbattleBeginRet> {
|
||||
Ok(RpcBeginnerbattleBeginRet::new(format!(
|
||||
"{}-{}",
|
||||
arg.battle_id,
|
||||
util::cur_timestamp_seconds()
|
||||
)))
|
||||
}
|
||||
|
||||
pub async fn on_rpc_beginnerbattle_end(
|
||||
_session: &NetworkSession,
|
||||
arg: &RpcBeginnerbattleEndArg,
|
||||
) -> Result<RpcBeginnerbattleEndRet> {
|
||||
tracing::info!("Battle statistics: {:?}", arg.battle_statistics);
|
||||
|
||||
Ok(RpcBeginnerbattleEndRet::new())
|
||||
}
|
506
gameserver/src/net/handlers/hollow.rs
Normal file
506
gameserver/src/net/handlers/hollow.rs
Normal file
|
@ -0,0 +1,506 @@
|
|||
use itertools::Itertools;
|
||||
use qwer::{phashmap, phashset, PropertyHashMap, PropertyHashSet};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::data;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub async fn on_rpc_hollow_move(
|
||||
session: &mut NetworkSession,
|
||||
arg: &RpcHollowMoveArg,
|
||||
) -> Result<RpcHollowMoveRet> {
|
||||
tracing::info!("Hollow movement {:?}", &arg);
|
||||
|
||||
let destination_pos = *arg.positions.last().unwrap();
|
||||
let scene_uid = session.ns_prop_mgr.player_info.read().scene_uid.unwrap();
|
||||
|
||||
let (ptc_hollow_grid, ptc_sync_hollow_event) = session
|
||||
.context
|
||||
.hollow_grid_manager
|
||||
.move_to(destination_pos, scene_uid);
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_HOLLOW_GRID_ID, ptc_hollow_grid)
|
||||
.await?;
|
||||
|
||||
if let Some(ptc_sync_hollow_event) = ptc_sync_hollow_event {
|
||||
session
|
||||
.push_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, ptc_sync_hollow_event)
|
||||
.await?;
|
||||
}
|
||||
|
||||
let pos = PtcPositionInHollowChangedArg {
|
||||
player_uid: session.player_uid().raw(),
|
||||
hollow_level: arg.hollow_level,
|
||||
position: destination_pos,
|
||||
};
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_POSITION_IN_HOLLOW_CHANGED_ID, pos)
|
||||
.await?;
|
||||
|
||||
let ptc_hollow_grid_around = session
|
||||
.context
|
||||
.hollow_grid_manager
|
||||
.check_around(destination_pos, scene_uid);
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_HOLLOW_GRID_ID, ptc_hollow_grid_around)
|
||||
.await?;
|
||||
|
||||
Ok(RpcHollowMoveRet::new(
|
||||
arg.hollow_level,
|
||||
*arg.positions.last().unwrap(),
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn on_rpc_run_hollow_event_graph(
|
||||
session: &mut NetworkSession,
|
||||
arg: &RpcRunHollowEventGraphArg,
|
||||
) -> Result<RpcRunHollowEventGraphRet> {
|
||||
tracing::info!("Run hollow event graph {:?}", arg);
|
||||
|
||||
let cur_hollow = session
|
||||
.context
|
||||
.hollow_grid_manager
|
||||
.get_cur_chessboard_id();
|
||||
|
||||
let start_position = session
|
||||
.context
|
||||
.hollow_grid_manager
|
||||
.get_cur_position_in_hollow();
|
||||
|
||||
let event_on_hollow_start: i32;
|
||||
|
||||
if cur_hollow == 2020701 { event_on_hollow_start = 1000108; }
|
||||
else { event_on_hollow_start = 1000; }
|
||||
|
||||
let scene_uid = session.ns_prop_mgr.player_info.read().scene_uid.unwrap();
|
||||
|
||||
if arg.event_graph_uid == 3405096459205834 {
|
||||
// Perform event at the beginning of a level
|
||||
let finish_perform = PtcSyncHollowEventInfoArg {
|
||||
event_graph_uid: 3405096459205834,
|
||||
hollow_event_template_id: event_on_hollow_start,
|
||||
event_graph_id: event_on_hollow_start,
|
||||
updated_event: EventInfo {
|
||||
id: 1000,
|
||||
cur_action_id: -1,
|
||||
action_move_path: vec![1001, 1002, -1],
|
||||
state: EventState::Finished,
|
||||
prev_state: EventState::Running,
|
||||
cur_action_info: ActionInfo::None {},
|
||||
cur_action_state: ActionState::Init,
|
||||
predicated_failed_actions: phashset![],
|
||||
stack_frames: Vec::new(),
|
||||
},
|
||||
specials: phashmap![],
|
||||
};
|
||||
session
|
||||
.push_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, finish_perform)
|
||||
.await?;
|
||||
|
||||
let (ptc_hollow_grid, ptc_sync_hollow_event) =
|
||||
session.context.hollow_grid_manager.move_to(start_position, scene_uid);
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_HOLLOW_GRID_ID, ptc_hollow_grid)
|
||||
.await?;
|
||||
if let Some(ptc_sync_hollow_event) = ptc_sync_hollow_event {
|
||||
session
|
||||
.push_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, ptc_sync_hollow_event)
|
||||
.await?;
|
||||
}
|
||||
|
||||
} else {
|
||||
let (sync_hollow_event, hollow_grid, trigger_battle_id, hollow_finished) = session
|
||||
.context
|
||||
.hollow_grid_manager
|
||||
.run_event_graph(arg.event_graph_uid, arg.event_id, arg.move_path.clone());
|
||||
|
||||
if !hollow_finished {
|
||||
session
|
||||
.push_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, sync_hollow_event)
|
||||
.await?;
|
||||
}
|
||||
session
|
||||
.push_rpc_arg(PTC_HOLLOW_GRID_ID, hollow_grid)
|
||||
.await?;
|
||||
|
||||
if hollow_finished {
|
||||
let _ = session
|
||||
.context
|
||||
.dungeon_manager
|
||||
.hollow_finished()
|
||||
.send_changes(session)
|
||||
.await?;
|
||||
|
||||
let ptc_dungeon_quest_finished = PtcDungeonQuestFinishedArg {
|
||||
player_uid: session.player_uid().raw(),
|
||||
quest_id: 1001000102,
|
||||
success: true,
|
||||
reward_items: phashmap![],
|
||||
statistics: phashmap![(QuestStatisticsType::ArrivedLevel, 1)],
|
||||
};
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_DUNGEON_QUEST_FINISHED_ID, ptc_dungeon_quest_finished)
|
||||
.await?;
|
||||
}
|
||||
|
||||
if let Some(trigger_battle_id) = trigger_battle_id {
|
||||
let hollow_uid = *session
|
||||
.ns_prop_mgr
|
||||
.player_info
|
||||
.read()
|
||||
.scene_uid
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
let battle_scene_uid = session
|
||||
.context
|
||||
.dungeon_manager
|
||||
.create_fight(trigger_battle_id, hollow_uid)
|
||||
.send_changes(session)
|
||||
.await?;
|
||||
|
||||
let ptc_position_in_hollow_changed = PtcPositionInHollowChangedArg {
|
||||
player_uid: session.player_uid().raw(),
|
||||
hollow_level: 1,
|
||||
position: session
|
||||
.context
|
||||
.hollow_grid_manager
|
||||
.get_cur_position_in_hollow(),
|
||||
};
|
||||
|
||||
session
|
||||
.push_rpc_arg(
|
||||
PTC_POSITION_IN_HOLLOW_CHANGED_ID,
|
||||
ptc_position_in_hollow_changed,
|
||||
)
|
||||
.await?;
|
||||
|
||||
session
|
||||
.push_rpc_arg(
|
||||
PTC_ENTER_SCENE_ID,
|
||||
session
|
||||
.context
|
||||
.dungeon_manager
|
||||
.enter_battle(battle_scene_uid)
|
||||
.send_changes(session)
|
||||
.await?,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(RpcRunHollowEventGraphRet::new())
|
||||
}
|
||||
|
||||
pub async fn on_rpc_start_hollow_quest(
|
||||
session: &NetworkSession,
|
||||
arg: &RpcStartHollowQuestArg,
|
||||
) -> Result<RpcStartHollowQuestRet> {
|
||||
tracing::info!("start hollow quest: {arg:?}");
|
||||
|
||||
|
||||
// Set avatar HP properties
|
||||
for (_idx, avatar_uid) in &arg.avatar_map {
|
||||
let update_properties = {
|
||||
let player_info = session.ns_prop_mgr.player_info.read();
|
||||
let items = player_info.items.as_ref().unwrap();
|
||||
let Some(ItemInfo::Avatar { id, .. }) = items
|
||||
.iter()
|
||||
.find(|(uid, _)| **uid == *avatar_uid)
|
||||
.map(|(_, item)| item)
|
||||
else {
|
||||
return Ok(RpcStartHollowQuestRet::error(
|
||||
ErrorCode::ObjectNotExist,
|
||||
Vec::new(),
|
||||
));
|
||||
};
|
||||
|
||||
let avatar_config = data::iter_avatar_config_collection()
|
||||
.find(|c| c.id == *id)
|
||||
.unwrap();
|
||||
|
||||
PtcPropertyChangedArg {
|
||||
scene_unit_uid: *avatar_uid,
|
||||
is_partial: true,
|
||||
changed_properties: phashmap![(1, avatar_config.hp), (111, avatar_config.hp)],
|
||||
}
|
||||
};
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_PROPERTY_CHANGED_ID, update_properties)
|
||||
.await?;
|
||||
}
|
||||
|
||||
let avatars = arg
|
||||
.avatar_map
|
||||
.iter()
|
||||
.sorted_by_key(|kv| kv.0)
|
||||
.map(|(_idx, uid)| *uid)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
//time of day
|
||||
let hour: u64;
|
||||
//check for current hollow quest
|
||||
let hollow_quest = arg.hollow_quest_id;
|
||||
//level
|
||||
let level: u8;
|
||||
//hollow id
|
||||
let hollow_id: i32;
|
||||
|
||||
//Quest List:
|
||||
|
||||
if hollow_quest == 10010106 { //The light of day (Rescue)
|
||||
hour = 18; //Set in-game time to 6 PM
|
||||
hollow_id = 10112;
|
||||
level = 2;
|
||||
|
||||
} else if hollow_quest == 10010102 { //Lost and found
|
||||
hour = 23; //Set in-game time to 11 PM
|
||||
hollow_id = 10102;
|
||||
level = 3;
|
||||
|
||||
} else if hollow_quest == 10010103 { //Engulfed by the Hollow (Time Trial)
|
||||
hour = 11; //Set in-game time to 11 AM
|
||||
hollow_id = 10103;
|
||||
level = 4;
|
||||
|
||||
} else if hollow_quest == 1990035 { //Descent (High-Risk 1)
|
||||
hour = 23; //Set in-game time to 11 PM
|
||||
hollow_id = 19935;
|
||||
level = 5;
|
||||
|
||||
} else { //Prologue ("Where Despair Breeds" is used because trial units don't work), loads by default
|
||||
hour = 8; //Set in-game time to 8 AM
|
||||
hollow_id = 10001;
|
||||
level = 1;
|
||||
}
|
||||
|
||||
//Set in-game time
|
||||
session
|
||||
.push_rpc_arg(
|
||||
PTC_SYNC_SCENE_TIME_ID,
|
||||
PtcSyncSceneTimeArg {
|
||||
timestamp: 3600 * hour * 1000,
|
||||
last_timestamp: 0,
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
let (dungeon_uid, scene_uid) = session
|
||||
.context
|
||||
.dungeon_manager
|
||||
.create_hollow(hollow_id, hollow_quest, &avatars)
|
||||
.send_changes(session)
|
||||
.await?;
|
||||
|
||||
session
|
||||
.context
|
||||
.quest_manager
|
||||
.add_quest_to_collection(
|
||||
dungeon_uid,
|
||||
QuestInfo::DungeonInner {
|
||||
id: 1001000102,
|
||||
finished_count: 0,
|
||||
collection_uid: 0,
|
||||
progress: 0,
|
||||
parent_quest_id: hollow_quest,
|
||||
state: QuestState::InProgress,
|
||||
finish_condition_progress: phashmap![],
|
||||
progress_time: 2111605,
|
||||
sort_id: 2000,
|
||||
},
|
||||
)
|
||||
.send_changes(session)
|
||||
.await?;
|
||||
|
||||
let ptc_enter_scene = session
|
||||
.context
|
||||
.dungeon_manager
|
||||
.enter_scene(scene_uid)?
|
||||
.send_changes(session)
|
||||
.await?
|
||||
.clone();
|
||||
|
||||
if level == 1 {
|
||||
session.context.hollow_grid_manager.init_prologue();
|
||||
} else if level == 2 {
|
||||
session.context.hollow_grid_manager.init_rescue();
|
||||
} else if level == 3 {
|
||||
session.context.hollow_grid_manager.init_lost();
|
||||
} else if level == 4 {
|
||||
session.context.hollow_grid_manager.init_time_trial();
|
||||
} else if level == 5 {
|
||||
session.context.hollow_grid_manager.init_descent();
|
||||
}
|
||||
|
||||
|
||||
session
|
||||
.push_rpc_arg(
|
||||
PTC_SYNC_HOLLOW_GRID_MAPS_ID,
|
||||
session
|
||||
.context
|
||||
.hollow_grid_manager
|
||||
.sync_hollow_maps(session.player_uid().raw(), scene_uid),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let ptc_position_in_hollow_changed = PtcPositionInHollowChangedArg {
|
||||
player_uid: session.player_uid().raw(),
|
||||
hollow_level: 1,
|
||||
position: session
|
||||
.context
|
||||
.hollow_grid_manager
|
||||
.get_cur_position_in_hollow(),
|
||||
};
|
||||
|
||||
session
|
||||
.push_rpc_arg(
|
||||
PTC_POSITION_IN_HOLLOW_CHANGED_ID,
|
||||
ptc_position_in_hollow_changed,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let event_on_hollow_start: i32;
|
||||
|
||||
if level == 1 { event_on_hollow_start = 1000108; }
|
||||
else { event_on_hollow_start = 1000; }
|
||||
|
||||
let ptc_sync_hollow_event_info = PtcSyncHollowEventInfoArg {
|
||||
event_graph_uid: 3405096459205834,
|
||||
hollow_event_template_id: event_on_hollow_start,
|
||||
event_graph_id: event_on_hollow_start,
|
||||
updated_event: EventInfo {
|
||||
id: 1000,
|
||||
cur_action_id: 1001,
|
||||
action_move_path: vec![1001],
|
||||
state: EventState::WaitingClient,
|
||||
prev_state: EventState::Running,
|
||||
cur_action_info: ActionInfo::None {},
|
||||
cur_action_state: ActionState::Init,
|
||||
predicated_failed_actions: phashset![],
|
||||
stack_frames: Vec::new(),
|
||||
},
|
||||
specials: phashmap![],
|
||||
};
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, ptc_sync_hollow_event_info)
|
||||
.await?;
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_ENTER_SCENE_ID, ptc_enter_scene)
|
||||
.await?;
|
||||
|
||||
|
||||
|
||||
Ok(RpcStartHollowQuestRet::new())
|
||||
|
||||
}
|
||||
|
||||
pub async fn on_rpc_end_battle(
|
||||
session: &NetworkSession,
|
||||
arg: &RpcEndBattleArg,
|
||||
) -> Result<RpcEndBattleRet> {
|
||||
tracing::info!("RpcEndBattle: {:?}", &arg);
|
||||
|
||||
let player_uid = session.player_uid().raw();
|
||||
let (sync_event, hollow_finished) = session.context.hollow_grid_manager.battle_finished();
|
||||
|
||||
if arg.success != true {
|
||||
let _ = session
|
||||
.context
|
||||
.dungeon_manager
|
||||
.hollow_finished()
|
||||
.send_changes(session)
|
||||
.await?;
|
||||
|
||||
let ptc_dungeon_quest_finished = PtcDungeonQuestFinishedArg {
|
||||
player_uid,
|
||||
quest_id: 1001000102,
|
||||
success: true,
|
||||
reward_items: phashmap![],
|
||||
statistics: phashmap![(QuestStatisticsType::ArrivedLevel, 1)],
|
||||
};
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_DUNGEON_QUEST_FINISHED_ID, ptc_dungeon_quest_finished)
|
||||
.await?;
|
||||
}
|
||||
|
||||
if !hollow_finished {
|
||||
session
|
||||
.push_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, sync_event)
|
||||
.await?;
|
||||
} else {
|
||||
let _ = session
|
||||
.context
|
||||
.dungeon_manager
|
||||
.hollow_finished()
|
||||
.send_changes(session)
|
||||
.await?;
|
||||
|
||||
let ptc_dungeon_quest_finished = PtcDungeonQuestFinishedArg {
|
||||
player_uid,
|
||||
quest_id: 1001000102,
|
||||
success: true,
|
||||
reward_items: phashmap![],
|
||||
statistics: phashmap![(QuestStatisticsType::ArrivedLevel, 1)],
|
||||
};
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_DUNGEON_QUEST_FINISHED_ID, ptc_dungeon_quest_finished)
|
||||
.await?;
|
||||
}
|
||||
|
||||
let ptc_enter_scene = session
|
||||
.context
|
||||
.dungeon_manager
|
||||
.leave_battle()
|
||||
.unwrap()
|
||||
.send_changes(session)
|
||||
.await?
|
||||
.clone();
|
||||
|
||||
session
|
||||
.push_rpc_arg(
|
||||
PTC_SYNC_HOLLOW_GRID_MAPS_ID,
|
||||
session.context.hollow_grid_manager.sync_hollow_maps(
|
||||
player_uid,
|
||||
session.context.dungeon_manager.get_cur_scene_uid(),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let ptc_position_in_hollow_changed = PtcPositionInHollowChangedArg {
|
||||
player_uid,
|
||||
hollow_level: 1,
|
||||
position: session
|
||||
.context
|
||||
.hollow_grid_manager
|
||||
.get_cur_position_in_hollow(),
|
||||
};
|
||||
|
||||
session
|
||||
.push_rpc_arg(
|
||||
PTC_POSITION_IN_HOLLOW_CHANGED_ID,
|
||||
ptc_position_in_hollow_changed,
|
||||
)
|
||||
.await?;
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_ENTER_SCENE_ID, ptc_enter_scene)
|
||||
.await?;
|
||||
|
||||
Ok(RpcEndBattleRet::new(
|
||||
session
|
||||
.context
|
||||
.hollow_grid_manager
|
||||
.get_cur_event_template_id(),
|
||||
HashMap::new(),
|
||||
))
|
||||
}
|
70
gameserver/src/net/handlers/login.rs
Normal file
70
gameserver/src/net/handlers/login.rs
Normal file
|
@ -0,0 +1,70 @@
|
|||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
game::util,
|
||||
net::session::{AccountUID, PlayerUID},
|
||||
};
|
||||
|
||||
const DEFAULT_ACCOUNT_ID: u64 = 1;
|
||||
|
||||
pub async fn on_rpc_login(session: &NetworkSession, arg: &RpcLoginArg) -> Result<RpcLoginRet> {
|
||||
tracing::info!("Received rpc login arg: {}", arg.account_name);
|
||||
|
||||
match session.logged_in(
|
||||
AccountUID(DEFAULT_ACCOUNT_ID),
|
||||
util::create_default_account(DEFAULT_ACCOUNT_ID),
|
||||
) {
|
||||
Ok(()) => Ok(RpcLoginRet::new(
|
||||
session.ns_prop_mgr.serialize_account_info(),
|
||||
)),
|
||||
Err(_) => Ok(RpcLoginRet::error(ErrorCode::RepeatedLogin, Vec::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn on_rpc_create_player(
|
||||
session: &NetworkSession,
|
||||
_arg: &RpcCreatePlayerArg,
|
||||
) -> Result<RpcCreatePlayerRet> {
|
||||
let account_uid = session.account_uid();
|
||||
let player_count = session
|
||||
.ns_prop_mgr
|
||||
.account_info
|
||||
.read()
|
||||
.players
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.len();
|
||||
|
||||
let player_uid = PlayerUID::new(account_uid, player_count + 1);
|
||||
session
|
||||
.ns_prop_mgr
|
||||
.account_info
|
||||
.write()
|
||||
.players
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.push(player_uid.raw());
|
||||
|
||||
Ok(RpcCreatePlayerRet::new(player_uid.raw()))
|
||||
}
|
||||
|
||||
pub async fn on_ptc_get_server_timestamp(
|
||||
_session: &NetworkSession,
|
||||
_arg: &PtcGetServerTimestampArg,
|
||||
) -> Result<PtcGetServerTimestampRet> {
|
||||
Ok(PtcGetServerTimestampRet::new(
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_millis() as u64,
|
||||
0,
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn on_rpc_keep_alive(
|
||||
_session: &NetworkSession,
|
||||
_arg: &RpcKeepAliveArg,
|
||||
) -> Result<RpcKeepAliveRet> {
|
||||
Ok(RpcKeepAliveRet::new())
|
||||
}
|
8
gameserver/src/net/handlers/mail.rs
Normal file
8
gameserver/src/net/handlers/mail.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
use super::*;
|
||||
|
||||
pub async fn on_rpc_get_player_mails(
|
||||
_session: &NetworkSession,
|
||||
_arg: &RpcGetPlayerMailsArg,
|
||||
) -> Result<RpcGetPlayerMailsRet> {
|
||||
Ok(RpcGetPlayerMailsRet::new(0))
|
||||
}
|
89
gameserver/src/net/handlers/mod.rs
Normal file
89
gameserver/src/net/handlers/mod.rs
Normal file
|
@ -0,0 +1,89 @@
|
|||
mod battle;
|
||||
mod beginner_procedure;
|
||||
mod hollow;
|
||||
mod login;
|
||||
mod mail;
|
||||
mod plot_play;
|
||||
mod progression;
|
||||
mod role;
|
||||
mod world;
|
||||
mod yorozuya;
|
||||
|
||||
pub use battle::*;
|
||||
pub use beginner_procedure::*;
|
||||
pub use hollow::*;
|
||||
pub use login::*;
|
||||
pub use mail::*;
|
||||
pub use plot_play::*;
|
||||
pub use progression::*;
|
||||
pub use role::*;
|
||||
pub use world::*;
|
||||
pub use yorozuya::*;
|
||||
|
||||
use super::NetworkSession;
|
||||
use anyhow::Result;
|
||||
use paste::paste;
|
||||
use protocol::*;
|
||||
|
||||
macro_rules! protocol_handlers {
|
||||
($($name:ident;)*) => {
|
||||
pub trait ProtocolHandler {
|
||||
async fn on_message(session: &mut NetworkSession, protocol_id: u16, payload: Vec<u8>) -> Result<()> {
|
||||
use ::qwer::OctData;
|
||||
use ::tracing::Instrument;
|
||||
paste! {
|
||||
match protocol_id {
|
||||
$(::protocol::[<$name:snake:upper _ID>] => {
|
||||
let arg = ::protocol::[<$name Arg>]::unmarshal_from(&mut &payload[..], 0)?;
|
||||
let ret = [<on_$name:snake>](session, &arg)
|
||||
.instrument(tracing::info_span!(stringify!([<on_$name:snake>]), protocol_id = protocol_id))
|
||||
.await?;
|
||||
|
||||
session.flush_rpc_queue().await?;
|
||||
session.send_rpc_ret(ret).await
|
||||
}
|
||||
)*
|
||||
_ => {
|
||||
tracing::warn!("Message with protocol id {protocol_id} wasn't handled!");
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn send_rpc_ret(&self, data: impl ::qwer::OctData) -> Result<()>;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protocol_handlers! {
|
||||
RpcLogin;
|
||||
RpcCreatePlayer;
|
||||
PtcGetServerTimestamp;
|
||||
PtcPlayerOperation;
|
||||
RpcAdvanceBeginnerProcedure;
|
||||
RpcBattleReport;
|
||||
RpcBeginnerbattleBegin;
|
||||
RpcBeginnerbattleEnd;
|
||||
RpcCheckYorozuyaInfoRefresh;
|
||||
RpcCloseLevelChgTips;
|
||||
RpcDelNewMap;
|
||||
RpcEndBattle;
|
||||
RpcEnterWorld;
|
||||
RpcReenterWorld;
|
||||
RpcFinishActPerformShow;
|
||||
RpcFinishEventGraphPerformShow;
|
||||
RpcGetPlayerMails;
|
||||
RpcHollowMove;
|
||||
RpcInteractWithUnit;
|
||||
RpcKeepAlive;
|
||||
RpcLeaveCurDungeon;
|
||||
RpcModNickName;
|
||||
RpcPerformEnd;
|
||||
RpcPerformJump;
|
||||
RpcPerformTrigger;
|
||||
RpcRunEventGraph;
|
||||
RpcRunHollowEventGraph;
|
||||
RpcSavePosInMainCity;
|
||||
RpcStartHollowQuest;
|
||||
}
|
32
gameserver/src/net/handlers/plot_play.rs
Normal file
32
gameserver/src/net/handlers/plot_play.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::*;
|
||||
|
||||
pub async fn on_rpc_perform_trigger(
|
||||
_session: &NetworkSession,
|
||||
arg: &RpcPerformTriggerArg,
|
||||
) -> Result<RpcPerformTriggerRet> {
|
||||
Ok(RpcPerformTriggerRet::new(format!(
|
||||
"{}-{}",
|
||||
arg.perform_id, arg.perform_type
|
||||
)))
|
||||
}
|
||||
|
||||
pub async fn on_rpc_perform_end(
|
||||
_session: &NetworkSession,
|
||||
_arg: &RpcPerformEndArg,
|
||||
) -> Result<RpcPerformEndRet> {
|
||||
Ok(RpcPerformEndRet::new())
|
||||
}
|
||||
|
||||
pub async fn on_rpc_finish_act_perform_show(
|
||||
_session: &NetworkSession,
|
||||
_arg: &RpcFinishActPerformShowArg,
|
||||
) -> Result<RpcFinishActPerformShowRet> {
|
||||
Ok(RpcFinishActPerformShowRet::new())
|
||||
}
|
||||
|
||||
pub async fn on_rpc_perform_jump(
|
||||
_session: &NetworkSession,
|
||||
_arg: &RpcPerformJumpArg,
|
||||
) -> Result<RpcPerformJumpRet> {
|
||||
Ok(RpcPerformJumpRet::new())
|
||||
}
|
15
gameserver/src/net/handlers/progression.rs
Normal file
15
gameserver/src/net/handlers/progression.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
use super::*;
|
||||
|
||||
pub async fn on_rpc_close_level_chg_tips(
|
||||
_session: &NetworkSession,
|
||||
_arg: &RpcCloseLevelChgTipsArg,
|
||||
) -> Result<RpcCloseLevelChgTipsRet> {
|
||||
Ok(RpcCloseLevelChgTipsRet::new())
|
||||
}
|
||||
|
||||
pub async fn on_rpc_del_new_map(
|
||||
_session: &NetworkSession,
|
||||
_arg: &RpcDelNewMapArg,
|
||||
) -> Result<RpcDelNewMapRet> {
|
||||
Ok(RpcDelNewMapRet::new())
|
||||
}
|
28
gameserver/src/net/handlers/role.rs
Normal file
28
gameserver/src/net/handlers/role.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
use super::*;
|
||||
|
||||
pub async fn on_rpc_mod_nick_name(
|
||||
session: &NetworkSession,
|
||||
arg: &RpcModNickNameArg,
|
||||
) -> Result<RpcModNickNameRet> {
|
||||
tracing::info!("creating character");
|
||||
|
||||
let player_info_changed = {
|
||||
let mut player = session.ns_prop_mgr.player_info.write();
|
||||
player.nick_name.replace(arg.nick_name.clone());
|
||||
player.avatar_id.replace(arg.avatar_id);
|
||||
|
||||
PtcPlayerInfoChangedArg {
|
||||
player_uid: player.uid.unwrap(),
|
||||
player_info: PlayerInfo {
|
||||
nick_name: Some(arg.nick_name.clone()),
|
||||
avatar_id: Some(arg.avatar_id),
|
||||
..Default::default()
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_PLAYER_INFO_CHANGED_ID, player_info_changed)
|
||||
.await?;
|
||||
Ok(RpcModNickNameRet::new())
|
||||
}
|
469
gameserver/src/net/handlers/world.rs
Normal file
469
gameserver/src/net/handlers/world.rs
Normal file
|
@ -0,0 +1,469 @@
|
|||
use qwer::{
|
||||
pdkhashmap, phashmap, phashset, PropertyDoubleKeyHashMap, PropertyHashMap, PropertyHashSet,
|
||||
};
|
||||
|
||||
use crate::config::CONFIGURATION;
|
||||
use crate::data;
|
||||
use crate::game::util;
|
||||
use crate::net::session::PlayerUID;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub async fn on_rpc_run_event_graph(
|
||||
session: &NetworkSession,
|
||||
arg: &RpcRunEventGraphArg,
|
||||
) -> Result<RpcRunEventGraphRet> {
|
||||
let unit = session.context.scene_unit_manager.get(arg.owner_uid);
|
||||
|
||||
let interact_id = match unit {
|
||||
Some(SceneUnitProtocolInfo::NpcProtocolInfo { interacts_info, .. })
|
||||
if interacts_info.len() != 0 =>
|
||||
{
|
||||
*interacts_info.iter().next().unwrap().0
|
||||
}
|
||||
Some(SceneUnitProtocolInfo::NpcProtocolInfo { tag, id, .. }) => {
|
||||
let main_city_object = data::get_main_city_object(tag, id).unwrap();
|
||||
*main_city_object.default_interact_ids.first().unwrap()
|
||||
}
|
||||
None => {
|
||||
return Ok(RpcRunEventGraphRet::error(
|
||||
ErrorCode::EntityNotExist,
|
||||
Vec::new(),
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
let mut ptc_sync_event_info = PtcSyncEventInfoArg {
|
||||
owner_type: arg.owner_type,
|
||||
owner_uid: arg.owner_uid,
|
||||
updated_events: pdkhashmap![],
|
||||
};
|
||||
|
||||
ptc_sync_event_info.updated_events.insert(
|
||||
interact_id,
|
||||
100,
|
||||
EventInfo {
|
||||
id: 100,
|
||||
cur_action_id: 101,
|
||||
action_move_path: Vec::from([101, 102, 101]),
|
||||
state: EventState::Initing,
|
||||
prev_state: EventState::WaitingClient,
|
||||
cur_action_info: ActionInfo::None {},
|
||||
cur_action_state: ActionState::Init,
|
||||
predicated_failed_actions: phashset![],
|
||||
stack_frames: Vec::new(),
|
||||
},
|
||||
);
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_SYNC_EVENT_INFO_ID, ptc_sync_event_info)
|
||||
.await?;
|
||||
|
||||
Ok(RpcRunEventGraphRet::new())
|
||||
}
|
||||
|
||||
pub async fn on_rpc_finish_event_graph_perform_show(
|
||||
session: &NetworkSession,
|
||||
arg: &RpcFinishEventGraphPerformShowArg,
|
||||
) -> Result<RpcFinishEventGraphPerformShowRet> {
|
||||
let mut ptc_sync_event_info = PtcSyncEventInfoArg {
|
||||
owner_type: EventGraphOwnerType::SceneUnit,
|
||||
owner_uid: arg.owner_uid,
|
||||
updated_events: pdkhashmap![],
|
||||
};
|
||||
|
||||
ptc_sync_event_info.updated_events.insert(
|
||||
arg.event_graph_id,
|
||||
arg.event_id,
|
||||
EventInfo {
|
||||
id: arg.event_id,
|
||||
cur_action_id: -1,
|
||||
action_move_path: Vec::from([101, 102, 101, -1]),
|
||||
state: EventState::Finished,
|
||||
prev_state: EventState::Initing,
|
||||
cur_action_info: ActionInfo::None {},
|
||||
cur_action_state: ActionState::Init,
|
||||
predicated_failed_actions: phashset![],
|
||||
stack_frames: Vec::new(),
|
||||
},
|
||||
);
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_SYNC_EVENT_INFO_ID, ptc_sync_event_info)
|
||||
.await?;
|
||||
|
||||
Ok(RpcFinishEventGraphPerformShowRet::new())
|
||||
}
|
||||
|
||||
pub async fn on_rpc_interact_with_unit(
|
||||
session: &NetworkSession,
|
||||
arg: &RpcInteractWithUnitArg,
|
||||
) -> Result<RpcInteractWithUnitRet> {
|
||||
tracing::info!(
|
||||
"InteractWithUnit: unit_uid: {}, interaction: {}",
|
||||
arg.unit_uid,
|
||||
arg.interaction
|
||||
);
|
||||
|
||||
let unit = session.context.scene_unit_manager.get(arg.unit_uid);
|
||||
|
||||
let interact_id = match unit {
|
||||
Some(SceneUnitProtocolInfo::NpcProtocolInfo { interacts_info, .. })
|
||||
if interacts_info.len() != 0 =>
|
||||
{
|
||||
*interacts_info.iter().next().unwrap().0
|
||||
}
|
||||
Some(SceneUnitProtocolInfo::NpcProtocolInfo { tag, id, .. }) => {
|
||||
let main_city_object = data::get_main_city_object(tag, id).unwrap();
|
||||
*main_city_object.default_interact_ids.first().unwrap()
|
||||
}
|
||||
None => {
|
||||
return Ok(RpcInteractWithUnitRet::error(
|
||||
ErrorCode::EntityNotExist,
|
||||
Vec::new(),
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
// 0 - ServerInteractiveSystem::TriggerEnterEvent
|
||||
// 1 - ServerInteractiveSystem::TriggerExitEvent
|
||||
// 2 - ServerInteractiveSystem::TriggerInteractDirectly
|
||||
if arg.interaction == 2 {
|
||||
let mut ptc_sync_event_info = PtcSyncEventInfoArg {
|
||||
owner_type: EventGraphOwnerType::SceneUnit,
|
||||
owner_uid: arg.unit_uid,
|
||||
updated_events: pdkhashmap![],
|
||||
};
|
||||
|
||||
ptc_sync_event_info.updated_events.insert(
|
||||
interact_id,
|
||||
100,
|
||||
EventInfo {
|
||||
id: 100,
|
||||
cur_action_id: 101,
|
||||
action_move_path: Vec::from([101]),
|
||||
state: EventState::WaitingClient,
|
||||
prev_state: EventState::Running,
|
||||
cur_action_info: ActionInfo::None {},
|
||||
cur_action_state: ActionState::Init,
|
||||
predicated_failed_actions: phashset![],
|
||||
stack_frames: Vec::new(),
|
||||
},
|
||||
);
|
||||
|
||||
session
|
||||
.push_rpc_arg(PTC_SYNC_EVENT_INFO_ID, ptc_sync_event_info)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(RpcInteractWithUnitRet::new())
|
||||
}
|
||||
|
||||
pub async fn on_rpc_leave_cur_dungeon(
|
||||
session: &NetworkSession,
|
||||
arg: &RpcLeaveCurDungeonArg,
|
||||
) -> Result<RpcLeaveCurDungeonRet> {
|
||||
|
||||
tracing::info!("Leaving dungeon: {arg:?}");
|
||||
|
||||
Box::pin(enter_main_city(session)).await?;
|
||||
Ok(RpcLeaveCurDungeonRet::new())
|
||||
|
||||
}
|
||||
|
||||
//Unfinished
|
||||
//pub async fn on_rpc_give_up_dungeon_quest_id<GiveUpDungeonQuestIdRet>(
|
||||
//session: &NetworkSession,
|
||||
//_arg: &GiveUpDungeonQuestIdArg,
|
||||
//) -> Result<GiveUpDungeonQuestIdRet> {
|
||||
//tracing::warn!("OnRpcGiveUpDungeonQuestId: giving up is not implemented yet, entering world again!");
|
||||
//Box::pin(enter_main_city(session)).await?
|
||||
|
||||
//Ok(GiveUpDungeonQuestIdRet::error(ErrorCode::Fail, Vec::new()))
|
||||
//}
|
||||
|
||||
pub async fn on_ptc_player_operation(
|
||||
_session: &NetworkSession,
|
||||
_arg: &PtcPlayerOperationArg,
|
||||
) -> Result<PtcPlayerOperationRet> {
|
||||
Ok(PtcPlayerOperationRet::new())
|
||||
}
|
||||
|
||||
pub async fn on_rpc_save_pos_in_main_city(
|
||||
_session: &NetworkSession,
|
||||
_arg: &RpcSavePosInMainCityArg,
|
||||
) -> Result<RpcSavePosInMainCityRet> {
|
||||
Ok(RpcSavePosInMainCityRet::new())
|
||||
}
|
||||
|
||||
fn create_player(id: u64) -> PlayerInfo {
|
||||
let mut player = util::create_default_player(id);
|
||||
|
||||
let pos_in_main_city = player.pos_in_main_city.as_mut().unwrap();
|
||||
pos_in_main_city.initial_pos_id.replace(2);
|
||||
pos_in_main_city.position.replace(Vector3f {
|
||||
x: 30.31,
|
||||
y: 0.58002,
|
||||
z: 11.18,
|
||||
});
|
||||
|
||||
if CONFIGURATION.skip_tutorial {
|
||||
let beginner_procedure = player.beginner_procedure_info.as_mut().unwrap();
|
||||
beginner_procedure.procedure_info.replace(6);
|
||||
player.nick_name.replace(String::from("xeondev"));
|
||||
player.avatar_id.replace(2021);
|
||||
}
|
||||
|
||||
|
||||
player
|
||||
}
|
||||
|
||||
pub async fn enter_main_city(session: &NetworkSession) -> Result<()> {
|
||||
let hall_scene_uid = session.context.dungeon_manager.get_default_scene_uid();
|
||||
|
||||
session
|
||||
.push_rpc_arg(
|
||||
PTC_ENTER_SECTION_ID,
|
||||
session
|
||||
.context
|
||||
.dungeon_manager
|
||||
.enter_scene_section(hall_scene_uid, 2)
|
||||
.take(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
session
|
||||
.push_rpc_arg(
|
||||
PTC_SYNC_SCENE_UNIT_ID,
|
||||
session.context.scene_unit_manager.sync(hall_scene_uid, 2),
|
||||
)
|
||||
.await?;
|
||||
|
||||
session
|
||||
.push_rpc_arg(
|
||||
PTC_ENTER_SCENE_ID,
|
||||
session
|
||||
.context
|
||||
.dungeon_manager
|
||||
.enter_main_city()?
|
||||
.send_changes(session)
|
||||
.await?,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn on_rpc_enter_world(
|
||||
session: &NetworkSession,
|
||||
_arg: &RpcEnterWorldArg,
|
||||
) -> Result<RpcEnterWorldRet> {
|
||||
{
|
||||
let account = session.ns_prop_mgr.account_info.read();
|
||||
|
||||
let player_uid = *account.players.as_ref().unwrap().first().unwrap(); // get first id from list
|
||||
session.set_cur_player(PlayerUID::from(player_uid), create_player(player_uid))?;
|
||||
}
|
||||
|
||||
let item_manager = &session.context.item_manager;
|
||||
item_manager.add_resource(501, 120);
|
||||
item_manager.add_resource(10, 228);
|
||||
item_manager.add_resource(100, 1337);
|
||||
|
||||
for avatar_id in data::iter_avatar_config_collection()
|
||||
.filter(|c| c.camp != 0)
|
||||
.map(|c| c.id)
|
||||
{
|
||||
item_manager.unlock_avatar(avatar_id);
|
||||
}
|
||||
|
||||
for unlock_id in data::iter_unlock_config_collection().map(|c| c.id) {
|
||||
session.context.unlock_manager.unlock(unlock_id);
|
||||
}
|
||||
|
||||
session.context.dungeon_manager.create_hall(1);
|
||||
session.context.scene_unit_manager.add_scene_units(2);
|
||||
|
||||
let quest_manager = session.context.quest_manager.clone();
|
||||
|
||||
//City Quests:
|
||||
quest_manager.add_world_quest(QuestInfo::MainCity {
|
||||
id: 10020002,
|
||||
finished_count: 0,
|
||||
collection_uid: 0,
|
||||
progress: 0,
|
||||
parent_quest_id: 0,
|
||||
state: QuestState::InProgress,
|
||||
finish_condition_progress: phashmap![],
|
||||
progress_time: 2111012,
|
||||
sort_id: 1000,
|
||||
bound_npc_and_interact: phashmap![],
|
||||
});
|
||||
|
||||
//Hollow Quests:
|
||||
|
||||
quest_manager.add_world_quest(QuestInfo::Hollow {
|
||||
id: 10010103,
|
||||
finished_count: 0,
|
||||
collection_uid: 3405096459205774,
|
||||
progress: 0,
|
||||
parent_quest_id: 0,
|
||||
state: QuestState::Ready,
|
||||
sort_id: 1002,
|
||||
statistics: phashmap![],
|
||||
statistics_ext: pdkhashmap![],
|
||||
acquired_hollow_challenge_reward: 0,
|
||||
progress_time: 0,
|
||||
finish_condition_progress: phashmap![],
|
||||
dungeon_uid: 0,
|
||||
});
|
||||
|
||||
quest_manager.add_world_quest(QuestInfo::Hollow {
|
||||
id: 10010102,
|
||||
finished_count: 0,
|
||||
collection_uid: 3405096459205774,
|
||||
progress: 0,
|
||||
parent_quest_id: 0,
|
||||
state: QuestState::Unlocked,
|
||||
sort_id: 1003,
|
||||
statistics: phashmap![],
|
||||
statistics_ext: pdkhashmap![],
|
||||
acquired_hollow_challenge_reward: 0,
|
||||
progress_time: 0,
|
||||
finish_condition_progress: phashmap![],
|
||||
dungeon_uid: 0,
|
||||
});
|
||||
|
||||
quest_manager.add_world_quest(QuestInfo::Hollow {
|
||||
id: 10010106,
|
||||
finished_count: 0,
|
||||
collection_uid: 3405096459205774,
|
||||
progress: 0,
|
||||
parent_quest_id: 0,
|
||||
state: QuestState::Ready,
|
||||
sort_id: 1004,
|
||||
statistics: phashmap![],
|
||||
statistics_ext: pdkhashmap![],
|
||||
acquired_hollow_challenge_reward: 0,
|
||||
progress_time: 0,
|
||||
finish_condition_progress: phashmap![],
|
||||
dungeon_uid: 0,
|
||||
});
|
||||
|
||||
quest_manager.add_world_quest(QuestInfo::Hollow {
|
||||
id: 10010112,
|
||||
finished_count: 0,
|
||||
collection_uid: 3405096459205774,
|
||||
progress: 0,
|
||||
parent_quest_id: 0,
|
||||
state: QuestState::Ready,
|
||||
sort_id: 1005,
|
||||
statistics: phashmap![],
|
||||
statistics_ext: pdkhashmap![],
|
||||
acquired_hollow_challenge_reward: 0,
|
||||
progress_time: 0,
|
||||
finish_condition_progress: phashmap![],
|
||||
dungeon_uid: 0,
|
||||
});
|
||||
|
||||
|
||||
quest_manager.add_world_quest(QuestInfo::Hollow {
|
||||
id: 1990035,
|
||||
finished_count: 0,
|
||||
collection_uid: 3405096459205774,
|
||||
progress: 0,
|
||||
parent_quest_id: 0,
|
||||
state: QuestState::Ready,
|
||||
sort_id: 1006,
|
||||
statistics: phashmap![],
|
||||
statistics_ext: pdkhashmap![],
|
||||
acquired_hollow_challenge_reward: 0,
|
||||
progress_time: 0,
|
||||
finish_condition_progress: phashmap![],
|
||||
dungeon_uid: 0,
|
||||
});
|
||||
|
||||
|
||||
//Where Despair Breeds
|
||||
session.context.yorozuya_quest_manager.add_hollow_quest(
|
||||
102,
|
||||
HollowQuestType::SideQuest,
|
||||
10010112,
|
||||
);
|
||||
|
||||
//The Light of Day
|
||||
session.context.yorozuya_quest_manager.add_hollow_quest(
|
||||
102,
|
||||
HollowQuestType::SideQuest,
|
||||
10010106,
|
||||
);
|
||||
|
||||
//Lost and Found
|
||||
session.context.yorozuya_quest_manager.add_hollow_quest(
|
||||
102,
|
||||
HollowQuestType::SideQuest,
|
||||
10010102,
|
||||
);
|
||||
|
||||
//Egulfed by the Hollow
|
||||
session.context.yorozuya_quest_manager.add_hollow_quest(
|
||||
102,
|
||||
HollowQuestType::SideQuest,
|
||||
10010103,
|
||||
);
|
||||
|
||||
//High-Risk 1
|
||||
session.context.yorozuya_quest_manager.add_hollow_quest(
|
||||
101,
|
||||
HollowQuestType::SideQuest,
|
||||
1990035,
|
||||
);
|
||||
|
||||
if CONFIGURATION.skip_tutorial {
|
||||
Box::pin(enter_main_city(session)).await?;
|
||||
} else {
|
||||
let fresh_scene_uid = session.context.dungeon_manager.create_fresh().take();
|
||||
session
|
||||
.push_rpc_arg(
|
||||
PTC_ENTER_SCENE_ID,
|
||||
session
|
||||
.context
|
||||
.dungeon_manager
|
||||
.enter_scene(fresh_scene_uid)
|
||||
.unwrap()
|
||||
.take(),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
session
|
||||
.push_rpc_arg(
|
||||
PTC_SYNC_SCENE_TIME_ID,
|
||||
PtcSyncSceneTimeArg {
|
||||
timestamp: 3600 * 8 * 1000,
|
||||
last_timestamp: 0,
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(RpcEnterWorldRet::new(
|
||||
session.ns_prop_mgr.serialize_player_info(),
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn on_rpc_reenter_world(
|
||||
session: &NetworkSession,
|
||||
_arg: &RpcReenterWorldArg,
|
||||
) -> Result<RpcReenterWorldRet> {
|
||||
tracing::warn!("OnRpcReenterWorld: world re-entrance is not implemented yet, kicking player!");
|
||||
|
||||
session
|
||||
.push_rpc_arg(
|
||||
PTC_KICK_PLAYER_ID,
|
||||
PtcKickPlayerArg {
|
||||
reason_id: 2,
|
||||
reason_str: String::new(),
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(RpcReenterWorldRet::error(ErrorCode::Fail, Vec::new()))
|
||||
}
|
9
gameserver/src/net/handlers/yorozuya.rs
Normal file
9
gameserver/src/net/handlers/yorozuya.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
use super::*;
|
||||
|
||||
pub async fn on_rpc_check_yorozuya_info_refresh(
|
||||
_session: &NetworkSession,
|
||||
arg: &RpcCheckYorozuyaInfoRefreshArg,
|
||||
) -> Result<RpcCheckYorozuyaInfoRefreshRet> {
|
||||
tracing::info!("Yorozuya Refresh: {arg:?}");
|
||||
Ok(RpcCheckYorozuyaInfoRefreshRet::new())
|
||||
}
|
9
gameserver/src/net/mod.rs
Normal file
9
gameserver/src/net/mod.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
pub mod gateway;
|
||||
mod handlers;
|
||||
mod packet;
|
||||
mod session;
|
||||
|
||||
pub use packet::Packet;
|
||||
pub use packet::RequestBody;
|
||||
pub use packet::ResponseBody;
|
||||
pub use session::NetworkSession;
|
78
gameserver/src/net/packet.rs
Normal file
78
gameserver/src/net/packet.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
use tokio::io::AsyncReadExt;
|
||||
use tokio::net::TcpStream;
|
||||
|
||||
use qwer::ProtocolHeader;
|
||||
|
||||
pub struct Packet {
|
||||
#[allow(unused)]
|
||||
pub to_channel: u16,
|
||||
pub header: ProtocolHeader,
|
||||
pub body: Vec<u8>,
|
||||
}
|
||||
|
||||
pub struct RequestBody {
|
||||
pub protocol_id: u16,
|
||||
pub payload: Vec<u8>,
|
||||
}
|
||||
|
||||
pub struct ResponseBody {
|
||||
pub middleware_id: u16,
|
||||
pub middleware_error_code: u16,
|
||||
pub payload: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Packet {
|
||||
pub async fn read(stream: &mut TcpStream) -> std::io::Result<Self> {
|
||||
let to_channel = stream.read_u16_le().await?;
|
||||
let body_size = stream.read_u32_le().await? as usize;
|
||||
let header_size = stream.read_u16_le().await? as usize;
|
||||
|
||||
let mut header = vec![0; header_size];
|
||||
stream.read_exact(&mut header).await?;
|
||||
|
||||
let mut body = vec![0; body_size];
|
||||
stream.read_exact(&mut body).await?;
|
||||
|
||||
Ok(Self {
|
||||
to_channel,
|
||||
header: header.into(),
|
||||
body,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for RequestBody {
|
||||
fn from(value: Vec<u8>) -> Self {
|
||||
let protocol_id = u16::from_le_bytes(value[0..2].try_into().unwrap());
|
||||
let payload_length = u32::from_be_bytes(value[2..6].try_into().unwrap()) as usize;
|
||||
let payload = value[6..payload_length + 6].to_vec();
|
||||
|
||||
Self {
|
||||
protocol_id,
|
||||
payload,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequestBody> for Vec<u8> {
|
||||
fn from(value: RequestBody) -> Self {
|
||||
let mut out = Self::new();
|
||||
|
||||
out.extend(value.protocol_id.to_le_bytes());
|
||||
out.extend((value.payload.len() as u32).to_be_bytes());
|
||||
out.extend(value.payload);
|
||||
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ResponseBody> for Vec<u8> {
|
||||
fn from(value: ResponseBody) -> Self {
|
||||
let mut out = Self::with_capacity(4 + value.payload.len());
|
||||
out.extend(value.middleware_id.to_le_bytes());
|
||||
out.extend(value.middleware_error_code.to_le_bytes());
|
||||
out.extend(value.payload);
|
||||
|
||||
out
|
||||
}
|
||||
}
|
192
gameserver/src/net/session.rs
Normal file
192
gameserver/src/net/session.rs
Normal file
|
@ -0,0 +1,192 @@
|
|||
use anyhow::Result;
|
||||
use protocol::{AccountInfo, PlayerInfo};
|
||||
use qwer::{OctData, ProtocolHeader};
|
||||
use std::collections::VecDeque;
|
||||
use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::sync::{Mutex, MutexGuard, OnceCell};
|
||||
|
||||
use crate::game::manager::net_stream;
|
||||
use crate::game::GameContext;
|
||||
|
||||
use super::handlers::ProtocolHandler;
|
||||
use super::{Packet, RequestBody, ResponseBody};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct AccountUID(pub u64);
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct PlayerUID(u64);
|
||||
|
||||
impl PlayerUID {
|
||||
pub const fn new(account_uid: AccountUID, index: usize) -> Self {
|
||||
Self(account_uid.0 * 100 + index as u64)
|
||||
}
|
||||
|
||||
pub const fn from(raw: u64) -> Self {
|
||||
Self(raw)
|
||||
}
|
||||
|
||||
pub const fn raw(&self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
struct QueueItem(pub u16, pub Vec<u8>);
|
||||
|
||||
pub struct NetworkSession {
|
||||
client_socket: Arc<Mutex<TcpStream>>,
|
||||
cur_rpc_uid: u64,
|
||||
outgoing_rpc_queue: Mutex<VecDeque<QueueItem>>,
|
||||
pub ns_prop_mgr: net_stream::PropertyManager,
|
||||
pub context: GameContext,
|
||||
account_uid: OnceCell<AccountUID>,
|
||||
player_uid: OnceCell<PlayerUID>,
|
||||
}
|
||||
|
||||
impl NetworkSession {
|
||||
pub fn new(client_socket: TcpStream) -> Self {
|
||||
let ns_prop_mgr = net_stream::PropertyManager::default();
|
||||
|
||||
Self {
|
||||
client_socket: Arc::new(Mutex::new(client_socket)),
|
||||
cur_rpc_uid: 0,
|
||||
outgoing_rpc_queue: Mutex::new(VecDeque::new()),
|
||||
context: GameContext::new(ns_prop_mgr.player_info.clone()),
|
||||
ns_prop_mgr,
|
||||
account_uid: OnceCell::new(),
|
||||
player_uid: OnceCell::new(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn client_socket(&self) -> MutexGuard<'_, TcpStream> {
|
||||
self.client_socket.lock().await
|
||||
}
|
||||
|
||||
pub fn logged_in(&self, uid: AccountUID, account: AccountInfo) -> Result<()> {
|
||||
self.account_uid.set(uid)?;
|
||||
*self.ns_prop_mgr.account_info.write() = account;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_cur_player(&self, uid: PlayerUID, player: PlayerInfo) -> Result<()> {
|
||||
self.player_uid.set(uid)?;
|
||||
*self.ns_prop_mgr.player_info.write() = player;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn account_uid(&self) -> AccountUID {
|
||||
*self.account_uid.get().unwrap()
|
||||
}
|
||||
|
||||
pub fn player_uid(&self) -> PlayerUID {
|
||||
*self.player_uid.get().unwrap()
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) -> Result<()> {
|
||||
let Some(_channel_id) = self.read_handshake().await? else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
loop {
|
||||
let packet = match Packet::read(&mut *self.client_socket().await).await {
|
||||
Ok(packet) => packet,
|
||||
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => return Ok(()),
|
||||
Err(e) => return Err(e.into()),
|
||||
};
|
||||
let request: RequestBody = packet.body.into();
|
||||
|
||||
self.cur_rpc_uid = packet.header.rpc_arg_uid;
|
||||
Box::pin(Self::on_message(self, request.protocol_id, request.payload)).await?;
|
||||
}
|
||||
}
|
||||
|
||||
async fn read_handshake(&mut self) -> Result<Option<u16>> {
|
||||
match self.client_socket().await.read_u16_le().await {
|
||||
Ok(channel_id) => Ok(Some(channel_id)),
|
||||
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => Ok(None),
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn push_rpc_arg(&self, protocol_id: u16, data: impl OctData) -> Result<()> {
|
||||
let mut payload = Vec::new();
|
||||
let mut cursor = Cursor::new(&mut payload);
|
||||
data.marshal_to(&mut cursor, 0)?;
|
||||
|
||||
self.outgoing_rpc_queue
|
||||
.lock()
|
||||
.await
|
||||
.push_back(QueueItem(protocol_id, payload));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn flush_rpc_queue(&self) -> Result<()> {
|
||||
let mut queue = self.outgoing_rpc_queue.lock().await;
|
||||
|
||||
while let Some(QueueItem(protocol_id, payload)) = queue.pop_front() {
|
||||
self.send_rpc_arg(protocol_id, payload).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_rpc_arg(&self, protocol_id: u16, payload: Vec<u8>) -> Result<()> {
|
||||
let header: Vec<u8> = ProtocolHeader::default().into();
|
||||
|
||||
let body: Vec<u8> = RequestBody {
|
||||
protocol_id,
|
||||
payload,
|
||||
}
|
||||
.into();
|
||||
|
||||
let mut packet = Vec::new();
|
||||
packet.extend(0_u16.to_le_bytes());
|
||||
packet.extend(((body.len() + 2) as u32).to_le_bytes());
|
||||
packet.extend((header.len() as u16).to_le_bytes());
|
||||
packet.extend(header);
|
||||
packet.extend(body);
|
||||
packet.extend(0_u16.to_le_bytes()); // middleware count
|
||||
|
||||
self.client_socket().await.write_all(&packet).await?;
|
||||
tracing::info!("Ptc with protocol id {protocol_id} sent");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ProtocolHandler for NetworkSession {
|
||||
async fn send_rpc_ret(&self, data: impl OctData) -> Result<()> {
|
||||
let header = ProtocolHeader {
|
||||
is_rpc_ret: true,
|
||||
rpc_arg_uid: self.cur_rpc_uid,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut payload = Vec::new();
|
||||
let mut cursor = Cursor::new(&mut payload);
|
||||
data.marshal_to(&mut cursor, 0)?;
|
||||
|
||||
let body: Vec<u8> = ResponseBody {
|
||||
middleware_id: 0,
|
||||
middleware_error_code: 0,
|
||||
payload,
|
||||
}
|
||||
.into();
|
||||
|
||||
let header_buf: Vec<u8> = header.into();
|
||||
let mut packet = Vec::new();
|
||||
packet.extend(0_u16.to_le_bytes());
|
||||
packet.extend((body.len() as u32).to_le_bytes());
|
||||
packet.extend((header_buf.len() as u16).to_le_bytes());
|
||||
packet.extend(header_buf);
|
||||
packet.extend(body);
|
||||
|
||||
self.client_socket().await.write_all(&packet).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
10
protocol/Cargo.toml
Normal file
10
protocol/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "protocol"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
byteorder.workspace = true
|
||||
hex.workspace = true
|
||||
qwer.workspace = true
|
||||
serde.workspace = true
|
699
protocol/src/enums.rs
Normal file
699
protocol/src/enums.rs
Normal file
|
@ -0,0 +1,699 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(i32)]
|
||||
pub enum ErrorCode {
|
||||
Fail = -1,
|
||||
Success = 0,
|
||||
Timeout = 1,
|
||||
EntityNotExist = 2,
|
||||
InvalidVersion = 3,
|
||||
InvalidTemplateID = 4,
|
||||
InvalidConfigVersion = 5,
|
||||
ObjectNotExist = 100,
|
||||
ConfigError = 101,
|
||||
NoEnoughRes = 102,
|
||||
NoEnoughEXP = 103,
|
||||
NoEnoughItem = 104,
|
||||
NoEnoughMaterials = 105,
|
||||
NoEnoughGoods = 106,
|
||||
NoEnoughCurrency = 107,
|
||||
CannotFindGoods = 108,
|
||||
AvatarMaxLevelLimit = 109,
|
||||
AvatarMaxStarLimit = 110,
|
||||
AvatarMaxAdvanceLevelLimit = 111,
|
||||
EquipMaxLevelLimit = 112,
|
||||
EquipMaxStarLimit = 113,
|
||||
SceneAlreadyDestroyed = 114,
|
||||
StageAlreadyDestroyed = 115,
|
||||
ErrorSrcPosition = 116,
|
||||
ErrorGraph = 117,
|
||||
NodeFinished = 118,
|
||||
NodeRunFailure = 119,
|
||||
UnknownAvatarSkill = 120,
|
||||
AvatarSkillMaxLevelLimit = 121,
|
||||
AvatarTalentMaxLevelLimit = 122,
|
||||
AvatarStarNotEnough = 123,
|
||||
InvalidActionMovePath = 124,
|
||||
ActionIDNotExist = 125,
|
||||
NickNameMaxLength = 126,
|
||||
NickNameIllegal = 127,
|
||||
Ban = 128,
|
||||
RepeatedLogin = 129,
|
||||
FuncNotOpen = 130,
|
||||
TokenError = 131,
|
||||
PlayerNotExist = 132,
|
||||
InvalidParam = 133,
|
||||
ItemBeOccupy = 134,
|
||||
ItemBeLock = 135,
|
||||
EquipGachaClose = 136,
|
||||
InvalidQuestState = 137,
|
||||
QuestMaxFinishCnt = 138,
|
||||
NoEnoughTimes = 139,
|
||||
BattleReportLimit = 140,
|
||||
BattleReportInvalid = 141,
|
||||
MaxLevelLimit = 142,
|
||||
MaxStarLimit = 143,
|
||||
MaxRefineLimit = 144,
|
||||
AlreadyGet = 145,
|
||||
RepeatedModName = 146,
|
||||
VHSStoreUnlock = 147,
|
||||
VHSStoreAlreadSlot = 148,
|
||||
VHSStoreSlotNumErr = 149,
|
||||
FuncNotUnlock = 150,
|
||||
VHSStoreRamenContinueEat = 151,
|
||||
VHSStoreAlreadyUnlock = 152,
|
||||
AFKGamePlayClose = 153,
|
||||
InitiativeItemUnlock = 154,
|
||||
InitiativeItemLevel = 155,
|
||||
PrepareAvatarsFail = 156,
|
||||
AlreadyAFK = 157,
|
||||
HollowDoEvtListNotEmpty = 158,
|
||||
HollowEvtNotCompleted = 159,
|
||||
HollowMoveFail = 160,
|
||||
BuyNumOverflow = 161,
|
||||
PackgeOverflow = 162,
|
||||
ReplacePkg = 163,
|
||||
FileLenghCheckFaild = 164,
|
||||
HashCheckFaild = 165,
|
||||
DiskNotEnough = 166,
|
||||
NotReachable = 167,
|
||||
ServerException = 168,
|
||||
RequestException = 169,
|
||||
OherDownLoadError = 170,
|
||||
QuestProgressNotEnough = 171,
|
||||
ConditionComplete = 172,
|
||||
ConditionNoComplete = 173,
|
||||
PayErrCode0 = 174,
|
||||
PayErrCode1 = 175,
|
||||
PayErrCode2 = 176,
|
||||
PayErrCode3 = 177,
|
||||
PayErrCode4 = 178,
|
||||
PayErrCode5 = 179,
|
||||
NoWhite = 180,
|
||||
NoWhiteDevice = 181,
|
||||
NoWhiteIp = 182,
|
||||
SdkError = 183,
|
||||
StopServer = 184,
|
||||
AccountServerError = 185,
|
||||
CloseServer = 187,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(i16)]
|
||||
pub enum HollowQuestType {
|
||||
Common = 0,
|
||||
MainQuest = 1,
|
||||
SideQuest = 2,
|
||||
Urgent = 3,
|
||||
UrgentSupplement = 4,
|
||||
Challenge = 5,
|
||||
ChallengeChaos = 6,
|
||||
AvatarSide = 7,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[repr(i16)]
|
||||
pub enum UnlockIDType {
|
||||
HollowCard = 1,
|
||||
HollowBuff = 2,
|
||||
HollowEvent = 3,
|
||||
HollowItem = 4,
|
||||
Curse = 5,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum FairyState {
|
||||
Unlock = 0,
|
||||
Close = 1,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(i16)]
|
||||
pub enum FightRanking {
|
||||
None = 0,
|
||||
D = 1,
|
||||
C = 2,
|
||||
B = 3,
|
||||
A = 4,
|
||||
S = 5,
|
||||
}
|
||||
|
||||
#[derive(OctData, Hash, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
|
||||
#[repr(i16)]
|
||||
pub enum BattleRewardType {
|
||||
Client = 1,
|
||||
BattleEvt = 2,
|
||||
Ext = 3,
|
||||
Fight = 4,
|
||||
Challenge = 5,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(i16)]
|
||||
pub enum MailState {
|
||||
New = 0,
|
||||
Old = 1,
|
||||
Read = 2,
|
||||
Awarded = 3,
|
||||
Removed = 4,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(i16)]
|
||||
pub enum HollowBattleEventType {
|
||||
Default = 0,
|
||||
Normal = 1,
|
||||
Elite = 2,
|
||||
Boss = 3,
|
||||
LevelEnd = 4,
|
||||
LevelFin = 5,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(i16)]
|
||||
pub enum QuestType {
|
||||
ArchiveFile = 1,
|
||||
DungeonInner = 2,
|
||||
Hollow = 3,
|
||||
Manual = 4,
|
||||
MainCity = 5,
|
||||
HollowChallenge = 6,
|
||||
ArchiveBattle = 7,
|
||||
Knowledge = 8,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(i16)]
|
||||
pub enum EventState {
|
||||
Initing = 0,
|
||||
Running = 1,
|
||||
Pause = 2,
|
||||
WaitingMsg = 3,
|
||||
WaitingClient = 4,
|
||||
Finished = 5,
|
||||
Error = 6,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(i16)]
|
||||
pub enum ActionState {
|
||||
Init = 0,
|
||||
Running = 1,
|
||||
Finished = 2,
|
||||
Error = 3,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(u8)]
|
||||
pub enum DungeonContentDropPoolType {
|
||||
Card = 0,
|
||||
BaneCard = 1,
|
||||
Arcana = 2,
|
||||
Blessing = 3,
|
||||
Curse = 4,
|
||||
Reward = 5,
|
||||
HollowItem = 6,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(i16)]
|
||||
pub enum ReportType {
|
||||
Fairy = 0,
|
||||
Dialog = 1,
|
||||
Task = 2,
|
||||
DialogInFairy = 3,
|
||||
}
|
||||
|
||||
#[derive(OctData, Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(u16)]
|
||||
pub enum UIType {
|
||||
Default = 0,
|
||||
None = 1,
|
||||
HollowQuest = 2,
|
||||
Archive = 3,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(i16)]
|
||||
pub enum ACTPerformShowMoment {
|
||||
Begin = 0,
|
||||
End = 1,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(i16)]
|
||||
pub enum HollowSystemType {
|
||||
Card = 1,
|
||||
Menu = 2,
|
||||
Curse = 3,
|
||||
Bag = 4,
|
||||
HollowItem = 5,
|
||||
HollowResultPage = 6,
|
||||
CurseInfo = 7,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(i16)]
|
||||
pub enum HollowSystemUIState {
|
||||
Normal = 0,
|
||||
Close = 1,
|
||||
Brighten = 2,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(i16)]
|
||||
pub enum HollowShopType {
|
||||
All = 0,
|
||||
Item = 1,
|
||||
Card = 2,
|
||||
Curse = 3,
|
||||
HollowItem = 4,
|
||||
Discount = 5,
|
||||
Gachashop = 6,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[repr(i16)]
|
||||
pub enum TimePeriodType {
|
||||
Random = 0,
|
||||
Morning = 1,
|
||||
Evening = 2,
|
||||
Night = 3,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[repr(i16)]
|
||||
pub enum WeatherType {
|
||||
None = -1,
|
||||
Random = 0,
|
||||
SunShine = 1,
|
||||
Fog = 2,
|
||||
Cloudy = 3,
|
||||
Rain = 4,
|
||||
Thunder = 5,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(i16)]
|
||||
pub enum PropertyType {
|
||||
Hp = 1,
|
||||
Armor = 2,
|
||||
Shield = 3,
|
||||
Stun = 4,
|
||||
Sp = 5,
|
||||
Usp = 6,
|
||||
Dead = 99,
|
||||
HpMax = 111,
|
||||
ArmorMax = 112,
|
||||
ShieldMax = 113,
|
||||
StunMax = 114,
|
||||
SpMax = 115,
|
||||
UspMax = 116,
|
||||
Atk = 121,
|
||||
BreakStun = 122,
|
||||
Def = 131,
|
||||
Crit = 201,
|
||||
CritRes = 202,
|
||||
CritDmg = 211,
|
||||
CritDmgRes = 212,
|
||||
Pen = 231,
|
||||
PenValue = 232,
|
||||
Endurance = 301,
|
||||
SpRecover = 305,
|
||||
HpHealRatio = 306,
|
||||
AddedDamageRatio = 307,
|
||||
HpMaxBattle = 1111,
|
||||
ArmorMaxBattle = 1112,
|
||||
ShieldMaxBattle = 1113,
|
||||
StunMaxBattle = 1114,
|
||||
SpBattle = 1115,
|
||||
// UspBattle = 1115,
|
||||
AtkBattle = 1121,
|
||||
BreakStunBattle = 1122,
|
||||
DefBattle = 1131,
|
||||
CritBattle = 1201,
|
||||
CritResBattle = 1202,
|
||||
CritDmgBattle = 1211,
|
||||
CritDmgResBattle = 1212,
|
||||
PenRatioBattle = 1231,
|
||||
PenDeltaBattle = 1232,
|
||||
EnduranceBattle = 1301,
|
||||
SpRecoverBattle = 1305,
|
||||
HpHealRatioBattle = 1306,
|
||||
AddedDamageRatioBattle = 1307,
|
||||
HpMaxBase = 11101,
|
||||
ArmorMaxBase = 11201,
|
||||
ShieldMaxBase = 11301,
|
||||
AtkBase = 12101,
|
||||
DefBase = 13101,
|
||||
CritBase = 20101,
|
||||
CritResBase = 20201,
|
||||
CritDmgBase = 21101,
|
||||
CritDmgResBase = 21201,
|
||||
PenBase = 23101,
|
||||
PenValueBase = 23201,
|
||||
BreakStunBase = 12201,
|
||||
StunMaxBase = 11401,
|
||||
SpMaxBase = 11501,
|
||||
EnduranceBase = 30101,
|
||||
UspMaxBase = 11601,
|
||||
SpRecoverBase = 30501,
|
||||
HpHealRatio1 = 30601,
|
||||
AddedDamageRatio1 = 30701,
|
||||
HpMaxRatio = 11102,
|
||||
ArmorMaxRatio = 11202,
|
||||
ShieldMaxRatio = 11302,
|
||||
AtkRatio = 12102,
|
||||
DefRatio = 13102,
|
||||
BreakStunRatio = 12202,
|
||||
StunMaxRatio = 11402,
|
||||
EnduranceRatio = 30102,
|
||||
SpRecoverRatio = 30502,
|
||||
HpMaxDelta = 11103,
|
||||
ArmorMaxDelta = 11203,
|
||||
ShieldMaxDelta = 11303,
|
||||
AtkDelta = 12103,
|
||||
DefDelta = 13103,
|
||||
BreakStunDelta = 12203,
|
||||
StunMaxDelta = 11403,
|
||||
SpMaxDelta = 11503,
|
||||
CritDelta = 20103,
|
||||
CritResDelta = 20203,
|
||||
CritDmgDelta = 21103,
|
||||
CritDmgResDelta = 21203,
|
||||
UspMaxDelta = 11603,
|
||||
PenDelta = 23103,
|
||||
PenValueDelta = 23203,
|
||||
EnduranceDelta = 30103,
|
||||
SpRecoverDelta = 30503,
|
||||
HpHealRatio3 = 30603,
|
||||
AddedDamageRatio3 = 30703,
|
||||
HpMaxRatioRL = 11104,
|
||||
ArmorMaxRatioRL = 11204,
|
||||
ShieldMaxRatioRL = 11304,
|
||||
AtkRatioRL = 12104,
|
||||
DefRatioRL = 13104,
|
||||
HpMaxDeltaRL = 11105,
|
||||
ArmorMaxDeltaRL = 11205,
|
||||
ShieldMaxDeltaRL = 11305,
|
||||
AtkDeltaRL = 12105,
|
||||
DefDeltaRL = 13105,
|
||||
CritRL = 20105,
|
||||
CritResRL = 20205,
|
||||
CritDmgRL = 21105,
|
||||
CritDmgResRL = 21205,
|
||||
PenRatioRL = 23105,
|
||||
PenDeltaRL = 23205,
|
||||
BreakStunRatioRL = 12204,
|
||||
BreakStunDeltaRL = 12205,
|
||||
StunMaxRatioRL = 11404,
|
||||
// StunMaxDeltaRL = 11404,
|
||||
SpMaxDeltaRL = 11505,
|
||||
UspMaxDeltaRL = 11605,
|
||||
EnduranceRatioRL = 30104,
|
||||
EnduranceDeltaRL = 30105,
|
||||
SpRecoverRatioRL = 30504,
|
||||
SpRecoverDeltaRL = 30505,
|
||||
HpHealRatioRL = 30605,
|
||||
AddedDamageRatioRL = 30705,
|
||||
MapHpreserveMaxhp = 10320,
|
||||
MapHpreserveCurhp = 10330,
|
||||
MapHpreserveAbsolute = 10340,
|
||||
ActorMaxCurHP = 10350,
|
||||
EnumCount = 10351,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(i16)]
|
||||
pub enum ScenePropertyType {
|
||||
Stamina = 1001,
|
||||
StaminaMax = 1002,
|
||||
StaminaRatio = 1003,
|
||||
StaminaDelta = 1004,
|
||||
GoldRatio = 1005,
|
||||
GoldDelta = 1006,
|
||||
CardRWeight = 1007,
|
||||
CardRWeightRatio = 1008,
|
||||
CardSRWeight = 1009,
|
||||
CardSRWeightRatio = 1010,
|
||||
CardSSRWeight = 1011,
|
||||
CardSSRWeightRatio = 1012,
|
||||
Mobility = 1013,
|
||||
BuffTurn = 1014,
|
||||
ForbiddenStamina = 1015,
|
||||
ForbiddenGold = 1016,
|
||||
OptionNum = 1017,
|
||||
ShopPrice = 1018,
|
||||
StaminaIncrease = 1019,
|
||||
StaminaOverLevel = 1020,
|
||||
DropRate = 1021,
|
||||
BanCharacter1 = 1022,
|
||||
BanCharacter2 = 1023,
|
||||
BanCharacter3 = 1024,
|
||||
PlayerView = 1025,
|
||||
ActorAddedDamageRatio = 1030,
|
||||
ActorDamageTakeRatio = 1031,
|
||||
MapHpreserveMaxhp = 1032,
|
||||
MapHpreserveCurhp = 1033,
|
||||
MapHpreserveAbsolute = 1034,
|
||||
ActorMaxCurHP = 1035,
|
||||
ShopPriceDelta = 1036,
|
||||
ShopPriceOverwriteCard = 1037,
|
||||
ShopPriceOverwriteItem = 1038,
|
||||
CardOptionHideNum = 1039,
|
||||
CardOptionForbidNum = 1040,
|
||||
HealingRatio = 1041,
|
||||
DinyRatio = 1042,
|
||||
Weather = 1043,
|
||||
TimePeriod = 1044,
|
||||
ShopPriceOverwriteCurse = 1045,
|
||||
ShopPriceOverwriteHollowItem = 1046,
|
||||
ShopPriceOverwriteDiscount = 1047,
|
||||
ShopPriceOverwriteGachashop = 1048,
|
||||
}
|
||||
|
||||
macro_rules! flag {
|
||||
($repr:ty, $(#[$attr:meta])* $name:ident { $($flag:ident = $value:expr,)* }) => {
|
||||
$(#[$attr])*
|
||||
#[repr($repr)]
|
||||
pub enum $name {
|
||||
$($flag = $value,)*
|
||||
}
|
||||
|
||||
impl From<$name> for $repr {
|
||||
fn from(flag: $name) -> $repr {
|
||||
flag as $repr
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$repr> for $name {
|
||||
fn from(flag: $repr) -> $name {
|
||||
match flag {
|
||||
$($value => $name::$flag,)*
|
||||
_ => panic!("invalid flag value: {}", flag),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl $name {
|
||||
#[must_use]
|
||||
pub fn unpack_flags(val: $repr) -> Vec<$name> {
|
||||
let mut flags = Vec::new();
|
||||
let mut val = val;
|
||||
let mut i = 0 as $repr;
|
||||
while val > 0 {
|
||||
if val & 1 == 1 {
|
||||
flags.push(unsafe { std::mem::transmute(i) });
|
||||
}
|
||||
val >>= 1;
|
||||
i += 1;
|
||||
}
|
||||
flags
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn pack_flags(flags: &[Self]) -> $repr {
|
||||
flags.iter().fold(0, |acc, &flag| acc | (flag as $repr))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
flag! {
|
||||
u32,
|
||||
#[derive(OctData, Clone, Debug, Copy)]
|
||||
HollowGridFlag {
|
||||
Core = 1,
|
||||
CanMove = 2,
|
||||
Travelled = 4,
|
||||
ShowEventType = 8,
|
||||
ShowEventID = 16,
|
||||
CanTriggerEvent = 32,
|
||||
Visible = 64,
|
||||
VisibleAtGridAround = 128,
|
||||
VisibleByTriggerEvent = 256,
|
||||
SyncToClient = 512,
|
||||
Door = 1024,
|
||||
CanTriggerMultiTimes = 2048,
|
||||
TemporaryVisibleAtAround = 4096,
|
||||
Unlocked = 8192,
|
||||
Brighten = 16384,
|
||||
Guide = 32768,
|
||||
Target = 65536,
|
||||
BrightenOnlyVisible = 131072,
|
||||
Unstable = 262144,
|
||||
}
|
||||
}
|
||||
|
||||
flag! {
|
||||
u8,
|
||||
#[derive(OctData, Clone, Debug, Copy)]
|
||||
HollowGridLink {
|
||||
None = 0,
|
||||
Up = 1,
|
||||
Down = 2,
|
||||
Right = 4,
|
||||
Left = 8,
|
||||
All = 15,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, Hash, PartialEq, Eq, Deserialize)]
|
||||
#[repr(i16)]
|
||||
pub enum NodeState {
|
||||
All = 0,
|
||||
Locked = 1,
|
||||
Unlocked = 2,
|
||||
Finished = 3,
|
||||
ShowEvent = 4,
|
||||
Door = 5,
|
||||
Brighten = 6,
|
||||
Guide = 7,
|
||||
Target = 8,
|
||||
BrightenOnlyVisible = 9,
|
||||
Unstable = 10,
|
||||
EnumCount = 11,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, Hash, PartialEq, Eq, Deserialize)]
|
||||
#[repr(i16)]
|
||||
pub enum NodeVisible {
|
||||
All = 0,
|
||||
Visible = 1,
|
||||
VisibleAtGridAround = 2,
|
||||
VisibleByTriggerEvent = 3,
|
||||
TemporaryVisibleAtAround = 4,
|
||||
EnumCount = 5,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, Hash, PartialEq, Eq, Deserialize)]
|
||||
#[repr(i16)]
|
||||
pub enum HollowEventType {
|
||||
None = 0,
|
||||
All = 1,
|
||||
Begin = 10,
|
||||
End = 20,
|
||||
#[serde(rename = "Interact_End")]
|
||||
InteractEnd = 21,
|
||||
#[serde(rename = "Battle_End")]
|
||||
BattleEnd = 22,
|
||||
#[serde(rename = "Change_Level_Interact")]
|
||||
ChangeLevelInteract = 23,
|
||||
#[serde(rename = "Change_Level_Fight")]
|
||||
ChangeLevelFight = 24,
|
||||
Battle = 30,
|
||||
#[serde(rename = "Battle_Normal")]
|
||||
BattleNormal = 31,
|
||||
#[serde(rename = "Battle_Elite")]
|
||||
BattleElite = 32,
|
||||
#[serde(rename = "Battle_Boss")]
|
||||
BattleBoss = 33,
|
||||
Dialog = 40,
|
||||
#[serde(rename = "Dialog_Positive")]
|
||||
DialogPositive = 41,
|
||||
#[serde(rename = "Dialog_Negative")]
|
||||
DialogNegative = 42,
|
||||
#[serde(rename = "Dialog_Special")]
|
||||
DialogSpecial = 43,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[repr(i16)]
|
||||
pub enum HollowShopCurrency {
|
||||
Coin = 1,
|
||||
Curse = 2,
|
||||
Random = 3,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[repr(i16)]
|
||||
pub enum QuestState {
|
||||
Unlocked = 0,
|
||||
Ready = 10,
|
||||
InProgress = 1,
|
||||
ToFinish = 2,
|
||||
Finished = 3,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(u8)]
|
||||
pub enum QuestStatisticsType {
|
||||
ArrivedLevel = 1,
|
||||
EventCount = 2,
|
||||
CostTime = 3,
|
||||
KilledEnemyCount = 4,
|
||||
ArcanaCount = 5,
|
||||
TarotCardCount = 6,
|
||||
StaminaOverLevelTimes = 7,
|
||||
RebornTimes = 8,
|
||||
FinishedEventTypeCount = 9,
|
||||
FinishedEventIDCount = 10,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[repr(i16)]
|
||||
pub enum System {
|
||||
HollowQuestUI = 0,
|
||||
VHSUI = 1,
|
||||
RoleUI = 2,
|
||||
SmithyUI = 3,
|
||||
PackageUI = 4,
|
||||
TeleportUI = 5,
|
||||
YorozuyaManualUI = 6,
|
||||
VHSStoreUI = 7,
|
||||
RamenUI = 8,
|
||||
WorkbenchUI = 9,
|
||||
GroceryUI = 10,
|
||||
VideoshopUI = 11,
|
||||
SwitchOfStoryMode = 12,
|
||||
SwitchOfQTE = 13,
|
||||
LineupSelect = 14,
|
||||
UseStoryMode = 15,
|
||||
UseManualQTEMode = 16,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[repr(i16)]
|
||||
pub enum InteractTarget {
|
||||
NPC = 0,
|
||||
TriggerBox = 1,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Copy, Debug)]
|
||||
#[repr(i16)]
|
||||
pub enum EventGraphOwnerType {
|
||||
Scene = 0,
|
||||
Section = 1,
|
||||
SceneUnit = 2,
|
||||
Hollow = 3,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[repr(i16)]
|
||||
pub enum Operator {
|
||||
Enter = 0,
|
||||
}
|
15
protocol/src/lib.rs
Normal file
15
protocol/src/lib.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use qwer::{OctData, PropertyDoubleKeyHashMap, PropertyHashMap, PropertyHashSet};
|
||||
|
||||
mod enums;
|
||||
mod polymorphic;
|
||||
mod protocol_id;
|
||||
mod rpc_ptc;
|
||||
mod structs;
|
||||
|
||||
pub use enums::*;
|
||||
pub use polymorphic::*;
|
||||
pub use protocol_id::*;
|
||||
pub use rpc_ptc::*;
|
||||
pub use structs::*;
|
929
protocol/src/polymorphic.rs
Normal file
929
protocol/src/polymorphic.rs
Normal file
|
@ -0,0 +1,929 @@
|
|||
use super::*;
|
||||
|
||||
macro_rules! polymorphic_scene_unit_protocol_info {
|
||||
(enum $name:ident { $($variant:ident { $($field:ident: $ty:ty),* $(,)? } = $tag:expr,)* }) => {
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[repr(u16)]
|
||||
#[base = 2]
|
||||
pub enum $name {
|
||||
$(
|
||||
$variant {
|
||||
uid: u64,
|
||||
tag: i32,
|
||||
$($field: $ty),*
|
||||
} = $tag,
|
||||
)*
|
||||
}
|
||||
|
||||
impl $name {
|
||||
#[must_use]
|
||||
pub const fn get_uid(&self) -> u64 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { uid, .. } => *uid,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_uid(&mut self, uid: u64) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { uid: ref mut u, .. } => *u = uid,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_tag(&self) -> i32 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { tag, .. } => *tag,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_tag(&mut self, tag: i32) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { tag: ref mut t, .. } => *t = tag,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! polymorphic_scene_info {
|
||||
(enum $name:ident { $($variant:ident { $($field:ident: $ty:ty),* $(,)? } = $tag:expr,)* }) => {
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[repr(u16)]
|
||||
#[base = 11]
|
||||
pub enum $name {
|
||||
$(
|
||||
$variant {
|
||||
uid: u64,
|
||||
id: i32,
|
||||
dungeon_uid: u64,
|
||||
end_timestamp: u64,
|
||||
back_scene_uid: u64,
|
||||
entered_times: u16,
|
||||
section_id: i32,
|
||||
open_ui: UIType,
|
||||
to_be_destroyed: bool,
|
||||
camera_x: u32,
|
||||
camera_y: u32,
|
||||
$($field: $ty),*
|
||||
} = $tag,
|
||||
)*
|
||||
}
|
||||
|
||||
impl $name {
|
||||
#[must_use]
|
||||
pub const fn get_uid(&self) -> u64 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { uid, .. } => *uid,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_uid(&mut self, uid: u64) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { uid: ref mut u, .. } => *u = uid,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_id(&self) -> i32 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { id, .. } => *id,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_id(&mut self, id: i32) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { id: ref mut i, .. } => *i = id,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_dungeon_uid(&self) -> u64 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { dungeon_uid, .. } => *dungeon_uid,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_dungeon_uid(&mut self, dungeon_uid: u64) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { dungeon_uid: ref mut d, .. } => *d = dungeon_uid,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_end_timestamp(&self) -> u64 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { end_timestamp, .. } => *end_timestamp,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_end_timestamp(&mut self, end_timestamp: u64) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { end_timestamp: ref mut e, .. } => *e = end_timestamp,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_back_scene_uid(&self) -> u64 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { back_scene_uid, .. } => *back_scene_uid,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_back_scene_uid(&mut self, back_scene_uid: u64) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { back_scene_uid: ref mut b, .. } => *b = back_scene_uid,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_entered_times(&self) -> u16 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { entered_times, .. } => *entered_times,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_entered_times(&mut self, entered_times: u16) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { entered_times: ref mut e, .. } => *e = entered_times,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_section_id(&self) -> i32 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { section_id, .. } => *section_id,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_section_id(&mut self, section_id: i32) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { section_id: ref mut s, .. } => *s = section_id,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_open_ui(&self) -> UIType {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { open_ui, .. } => *open_ui,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_open_ui(&mut self, open_ui: UIType) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { open_ui: ref mut o, .. } => *o = open_ui,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_to_be_destroyed(&self) -> bool {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { to_be_destroyed, .. } => *to_be_destroyed,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_to_be_destroyed(&mut self, to_be_destroyed: bool) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { to_be_destroyed: ref mut t, .. } => *t = to_be_destroyed,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_camera_x(&self) -> u32 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { camera_x, .. } => *camera_x,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_camera_x(&mut self, camera_x: u32) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { camera_x: ref mut c, .. } => *c = camera_x,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_camera_y(&self) -> u32 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { camera_y, .. } => *camera_y,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_camera_y(&mut self, camera_y: u32) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { camera_y: ref mut c, .. } => *c = camera_y,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! polymorphic_item_info {
|
||||
(enum $name:ident { $($variant:ident { $($field:ident: $ty:ty),* $(,)? } = $tag:expr,)* }) => {
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[repr(u16)]
|
||||
#[base = 5]
|
||||
pub enum $name {
|
||||
$(
|
||||
$variant {
|
||||
uid: u64,
|
||||
id: i32,
|
||||
count: i32,
|
||||
package: u16,
|
||||
first_get_time: u64,
|
||||
$($field: $ty),*
|
||||
} = $tag,
|
||||
)*
|
||||
}
|
||||
|
||||
impl $name {
|
||||
#[must_use]
|
||||
pub const fn get_uid(&self) -> u64 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { uid, .. } => *uid,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_uid(&mut self, uid: u64) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { uid: ref mut u, .. } => *u = uid,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_id(&self) -> i32 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { id, .. } => *id,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_id(&mut self, id: i32) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { id: ref mut i, .. } => *i = id,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_count(&self) -> i32 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { count, .. } => *count,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_count(&mut self, count: i32) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { count: ref mut c, .. } => *c = count,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_package(&self) -> u16 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { package, .. } => *package,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_package(&mut self, package: u16) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { package: ref mut p, .. } => *p = package,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_first_get_time(&self) -> u64 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { first_get_time, .. } => *first_get_time,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_first_get_time(&mut self, first_get_time: u64) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { first_get_time: ref mut f, .. } => *f = first_get_time,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! polymorphic_dungeon_table_ext {
|
||||
(enum $name:ident { $($variant:ident { $($field:ident: $ty:ty),* $(,)? } = $tag:expr,)* }) => {
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[repr(u16)]
|
||||
#[base = 0]
|
||||
pub enum $name {
|
||||
$(
|
||||
$variant {
|
||||
$($field: $ty),*
|
||||
} = $tag,
|
||||
)*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! polymorphic_scene_table_ext {
|
||||
(enum $name:ident { $($variant:ident { $($field:ident: $ty:ty),* $(,)? } = $tag:expr,)* }) => {
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[repr(u16)]
|
||||
#[base = 1]
|
||||
pub enum $name {
|
||||
$(
|
||||
$variant {
|
||||
event_graphs_info: EventGraphsInfo,
|
||||
$($field: $ty),*
|
||||
} = $tag,
|
||||
)*
|
||||
}
|
||||
|
||||
impl $name {
|
||||
#[must_use]
|
||||
pub const fn get_event_graphs_info(&self) -> &EventGraphsInfo {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { event_graphs_info, .. } => event_graphs_info,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_event_graphs_info(&mut self, event_graphs_info: EventGraphsInfo) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { event_graphs_info: ref mut e, .. } => *e = event_graphs_info,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! polymorphic_section_info_ext {
|
||||
(enum $name:ident { $($variant:ident { $($field:ident: $ty:ty),* $(,)? } = $tag:expr,)* }) => {
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[repr(u16)]
|
||||
#[base = 1]
|
||||
pub enum $name {
|
||||
$(
|
||||
$variant {
|
||||
destroy_npc_when_no_player: PropertyHashSet<u64>,
|
||||
$($field: $ty),*
|
||||
} = $tag,
|
||||
)*
|
||||
}
|
||||
|
||||
impl $name {
|
||||
#[must_use]
|
||||
pub const fn get_destroy_npc_when_no_player(&self) -> &PropertyHashSet<u64> {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { destroy_npc_when_no_player, .. } => destroy_npc_when_no_player,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_destroy_npc_when_no_player(&mut self, destroy_npc_when_no_player: PropertyHashSet<u64>) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { destroy_npc_when_no_player: ref mut d, .. } => *d = destroy_npc_when_no_player,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! polymorphic_action_info {
|
||||
(enum $name:ident { $($variant:ident { $($field:ident: $ty:ty),* $(,)? } = $tag:expr,)* }) => {
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[repr(u16)]
|
||||
#[base = 0]
|
||||
pub enum $name {
|
||||
$(
|
||||
$variant {
|
||||
$($field: $ty),*
|
||||
} = $tag,
|
||||
)*
|
||||
#[polymorphic_none]
|
||||
None {} = 0xFFFF, // weird detail, polymorphism can be empty.
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! polymorphic_event_graph_info {
|
||||
(enum $name:ident { $($variant:ident { $($field:ident: $ty:ty),* $(,)? } = $tag:expr,)* }) => {
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[repr(u16)]
|
||||
#[base = 6]
|
||||
pub enum $name {
|
||||
$(
|
||||
$variant {
|
||||
config_id: i32,
|
||||
events_info: PropertyHashMap<i32, EventInfo>,
|
||||
specials: PropertyHashMap<String, u64>,
|
||||
is_new: bool,
|
||||
finished: bool,
|
||||
list_specials: PropertyHashMap<String, Vec<u64>>,
|
||||
$($field: $ty),*
|
||||
} = $tag,
|
||||
)*
|
||||
}
|
||||
|
||||
impl $name {
|
||||
#[must_use]
|
||||
pub const fn get_config_id(&self) -> i32 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { config_id, .. } => *config_id,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_config_id(&mut self, config_id: i32) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { config_id: ref mut c, .. } => *c = config_id,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_events_info(&self) -> &PropertyHashMap<i32, EventInfo> {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { events_info, .. } => events_info,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_events_info(&mut self, events_info: PropertyHashMap<i32, EventInfo>) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { events_info: ref mut e, .. } => *e = events_info,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_specials(&self) -> &PropertyHashMap<String, u64> {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { specials, .. } => specials,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_specials(&mut self, specials: PropertyHashMap<String, u64>) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { specials: ref mut s, .. } => *s = specials,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_is_new(&self) -> bool {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { is_new, .. } => *is_new,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_is_new(&mut self, is_new: bool) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { is_new: ref mut i, .. } => *i = is_new,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_finished(&self) -> bool {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { finished, .. } => *finished,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_finished(&mut self, finished: bool) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { finished: ref mut f, .. } => *f = finished,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_list_specials(&self) -> &PropertyHashMap<String, Vec<u64>> {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { list_specials, .. } => list_specials,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_list_specials(&mut self, list_specials: PropertyHashMap<String, Vec<u64>>) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { list_specials: ref mut l, .. } => *l = list_specials,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! polymorphic_quest_info {
|
||||
(enum $name:ident { $($variant:ident { $($field:ident: $ty:ty),* $(,)? } = $tag:expr,)* }) => {
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[repr(u16)]
|
||||
#[base = 9]
|
||||
pub enum $name {
|
||||
$(
|
||||
$variant {
|
||||
id: i32,
|
||||
finished_count: i32,
|
||||
collection_uid: u64,
|
||||
progress: u16,
|
||||
parent_quest_id: i32,
|
||||
state: QuestState,
|
||||
finish_condition_progress: PropertyHashMap<i32, i32>,
|
||||
progress_time: u32,
|
||||
sort_id: u64,
|
||||
$($field: $ty),*
|
||||
} = $tag,
|
||||
)*
|
||||
}
|
||||
|
||||
impl $name {
|
||||
#[must_use]
|
||||
pub const fn get_id(&self) -> i32 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { id, .. } => *id,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_id(&mut self, id: i32) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { id: ref mut c, .. } => *c = id,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_collection_uid(&self) -> u64 {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { collection_uid, .. } => *collection_uid,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_collection_uid(&mut self, collection_uid: u64) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { collection_uid: ref mut c, .. } => *c = collection_uid,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_state(&mut self, state: QuestState) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { state: ref mut c, .. } => *c = state,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_progress(&mut self, progress: u16) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { progress: ref mut c, .. } => *c = progress,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_finished_count(&mut self, finished_count: i32) {
|
||||
match self {
|
||||
$(
|
||||
$name::$variant { finished_count: ref mut c, .. } => *c = finished_count,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
polymorphic_scene_unit_protocol_info! {
|
||||
enum SceneUnitProtocolInfo {
|
||||
NpcProtocolInfo {
|
||||
id: i32,
|
||||
quest_id: i32,
|
||||
interacts_info: PropertyHashMap<i32, InteractInfo>,
|
||||
} = 0,
|
||||
}
|
||||
}
|
||||
|
||||
polymorphic_scene_info! {
|
||||
enum SceneInfo {
|
||||
Fight {
|
||||
perform_show_progress: PropertyHashMap<ACTPerformShowMoment, u8>,
|
||||
end_hollow: bool,
|
||||
random_seed: i32,
|
||||
} = 3,
|
||||
Fresh {} = 4,
|
||||
Hall {
|
||||
// main_city_time_info: MainCityTimeInfo,
|
||||
} = 1,
|
||||
Hollow {
|
||||
event_variables: PropertyHashMap<String, i32>,
|
||||
buddy: BuddyUnitInfo,
|
||||
stress_punish_ability_random_pool: Vec<String>,
|
||||
finished: bool,
|
||||
event_weight_factor: PropertyHashMap<i32, i32>,
|
||||
shop_modification: HollowShopModification,
|
||||
last_challenge_stat: PropertyHashMap<i32, u8>,
|
||||
cur_challenge: PropertyHashSet<i32>,
|
||||
hollow_system_switch: PropertyHashMap<HollowSystemType, bool>,
|
||||
sections_info: PropertyHashMap<i32, PlayerHollowSectionInfo>,
|
||||
executing_event: bool,
|
||||
event_id: i32,
|
||||
hollow_event_graph_uid: u64,
|
||||
on_battle_success: String,
|
||||
on_battle_failure: String,
|
||||
battle_finished: bool,
|
||||
battle_success: bool,
|
||||
battle_scene_uid: u64,
|
||||
//event_graphs_info: PropertyHashMap<u64, HollowEventGraphInfo>,
|
||||
scene_global_events: PropertyHashMap<i32, u64>,
|
||||
prepare_section: PrepareSection,
|
||||
abilities_info: AbilitiesInfo,
|
||||
blackout: bool,
|
||||
hollow_system_ui_state: PropertyHashMap<HollowSystemType, HollowSystemUIState>,
|
||||
} = 2,
|
||||
}
|
||||
}
|
||||
|
||||
polymorphic_item_info! {
|
||||
enum ItemInfo {
|
||||
Arcana {
|
||||
affix_list: Vec<i32>,
|
||||
dress_index: u8,
|
||||
} = 33,
|
||||
Avatar {
|
||||
star: u8,
|
||||
exp: u32,
|
||||
level: u8,
|
||||
rank: u8,
|
||||
unlocked_talent_num: u8,
|
||||
skills: PropertyHashMap<u8, u8>,
|
||||
is_custom_by_dungeon: bool,
|
||||
robot_id: i32,
|
||||
} = 3,
|
||||
AvatarLevelUpMaterial { } = 12,
|
||||
AvatarPiece { } = 4,
|
||||
Bless {
|
||||
remain_time: i32,
|
||||
get_time: u64,
|
||||
ban_character: Vec<i32>,
|
||||
specials: PropertyHashMap<String, i32>,
|
||||
slot: u8,
|
||||
is_super_curse: bool,
|
||||
} = 32,
|
||||
Buddy { } = 8,
|
||||
Consumable { } = 10,
|
||||
Currency { } = 1,
|
||||
Equip {
|
||||
avatar_uid: u64,
|
||||
avatar_dressed_index: u8,
|
||||
rand_properties: Vec<PropertyKeyValue>,
|
||||
star: u8,
|
||||
exp: u32,
|
||||
leve: u8,
|
||||
lock: u8,
|
||||
base_rand_properties: Vec<PropertyKeyValue>,
|
||||
rand_properties_lv: Vec<i32>,
|
||||
} = 7,
|
||||
EquipLevelUpMaterial { } = 14,
|
||||
Gift { } = 51,
|
||||
HollowItem { } = 15,
|
||||
OptionalGift { } = 52,
|
||||
Resource { } = 2,
|
||||
TarotCard {
|
||||
is_mute: bool,
|
||||
specials: PropertyHashMap<String, i32>,
|
||||
} = 31,
|
||||
Useable { } = 11,
|
||||
Weapon {
|
||||
avatar_uid: u64,
|
||||
star: u8,
|
||||
exp: u32,
|
||||
level: u8,
|
||||
lock: u8,
|
||||
refine_level: u8,
|
||||
} = 5,
|
||||
WeaponLevelUpMaterial { } = 13,
|
||||
}
|
||||
}
|
||||
|
||||
polymorphic_dungeon_table_ext! {
|
||||
enum DungeonTableExt {
|
||||
Hall {} = 1,
|
||||
Hollow {
|
||||
avatars: PropertyHashSet<HollowDungeonAvatarInfo>,
|
||||
scene_properties_uid: u64,
|
||||
buddy: HollowDungeonBuddyInfo,
|
||||
} = 2,
|
||||
}
|
||||
}
|
||||
|
||||
polymorphic_section_info_ext! {
|
||||
enum SectionInfoExt {
|
||||
Hall {} = 1,
|
||||
Hollow {
|
||||
hollow_level_info: HollowLevelInfo,
|
||||
hollow_grid_map_info: HollowGridMapInfo,
|
||||
} = 0,
|
||||
}
|
||||
}
|
||||
|
||||
polymorphic_scene_table_ext! {
|
||||
enum SceneTableExt {
|
||||
Fight {} = 3,
|
||||
Fresh {} = 4,
|
||||
Hall {} = 1,
|
||||
Hollow {
|
||||
grid_random_seed: i32,
|
||||
alter_section_id: i32,
|
||||
} = 2,
|
||||
}
|
||||
}
|
||||
|
||||
polymorphic_action_info! {
|
||||
enum ActionInfo {
|
||||
ServerChoices {
|
||||
choices: Vec<ChoiceInfo>,
|
||||
finished: bool,
|
||||
} = 52,
|
||||
DropHollowItem {
|
||||
drop_item: i32,
|
||||
} = 162,
|
||||
FinishBlackout {
|
||||
finished: bool,
|
||||
show_tips: bool,
|
||||
} = 133,
|
||||
Loop {
|
||||
loop_times: u16,
|
||||
} = 141,
|
||||
Perform {
|
||||
step: u8,
|
||||
r#return: PropertyHashMap<String, i32>,
|
||||
} = 23,
|
||||
PrepareNextHollow {
|
||||
section_id: i32,
|
||||
finished: bool,
|
||||
show_other: bool,
|
||||
main_map: HollowGridMapProtocolInfo,
|
||||
} = 130,
|
||||
ActionRandomChallenge {
|
||||
choices: Vec<i32>,
|
||||
choice_result: i32,
|
||||
finished: bool,
|
||||
} = 109,
|
||||
RemoveCurse {
|
||||
curse_can_remove: Vec<u64>,
|
||||
to_remove_num: u8,
|
||||
choosed: bool,
|
||||
} = 105,
|
||||
SetHollowSystemState {
|
||||
finished: bool,
|
||||
} = 134,
|
||||
Shop {
|
||||
shop_info: PropertyHashMap<HollowShopType, ConfigShopInfo>,
|
||||
finished: bool,
|
||||
} = 62,
|
||||
SlotMachine {
|
||||
indexes: Vec<i32>,
|
||||
index: i32,
|
||||
finished: bool,
|
||||
} = 131,
|
||||
TriggerBattle {
|
||||
next_action_id: i32,
|
||||
finished: bool,
|
||||
} = 56,
|
||||
}
|
||||
}
|
||||
|
||||
polymorphic_event_graph_info! {
|
||||
enum EventGraphInfo {
|
||||
Hollow {
|
||||
fired_count: u8,
|
||||
hollow_event_template_id: i32,
|
||||
uid: u64,
|
||||
is_created_by_gm: bool,
|
||||
} = 3,
|
||||
NPC {
|
||||
sequence_of_group: u16,
|
||||
section_list_events: PropertyHashMap<String, EventListenerInfo>,
|
||||
interact_info: InteractInfo,
|
||||
hide: bool,
|
||||
} = 2,
|
||||
Section { } = 1,
|
||||
}
|
||||
}
|
||||
|
||||
polymorphic_quest_info! {
|
||||
enum QuestInfo {
|
||||
ArchiveBattle {
|
||||
statistics: PropertyHashMap<QuestStatisticsType, u64>,
|
||||
dungeon_uid: u64,
|
||||
star: u8,
|
||||
} = 7,
|
||||
ArchiveFile { } = 1,
|
||||
Challenge { } = 6,
|
||||
DungeonInner { } = 2,
|
||||
Hollow {
|
||||
statistics: PropertyHashMap<QuestStatisticsType, u64>,
|
||||
dungeon_uid: u64,
|
||||
statistics_ext: PropertyDoubleKeyHashMap<QuestStatisticsType, i32, i32>,
|
||||
acquired_hollow_challenge_reward: i32,
|
||||
} = 3,
|
||||
Knowledge { } = 8,
|
||||
MainCity {
|
||||
bound_npc_and_interact: PropertyHashMap<u64, BoundNPCAndInteractInfo>,
|
||||
} = 5,
|
||||
Manual { } = 4,
|
||||
}
|
||||
}
|
146
protocol/src/protocol_id.rs
Normal file
146
protocol/src/protocol_id.rs
Normal file
|
@ -0,0 +1,146 @@
|
|||
pub const RPC_LOGIN_ID: u16 = 100;
|
||||
pub const PTC_PLAYER_INFO_CHANGED_ID: u16 = 101;
|
||||
pub const PTC_ACCOUNT_INFO_CHANGED_ID: u16 = 102;
|
||||
pub const RPC_LOGOUT_ID: u16 = 103;
|
||||
pub const RPC_CREATE_PLAYER_ID: u16 = 104;
|
||||
pub const RPC_ENTER_WORLD_ID: u16 = 105;
|
||||
pub const RPC_AVATAR_LEVEL_UP_ID: u16 = 107;
|
||||
pub const RPC_AVATAR_STAR_UP_ID: u16 = 108;
|
||||
pub const RPC_UNDRESS_EQUIPMENT_ID: u16 = 109;
|
||||
pub const PTC_CLIENT_COMMON_ID: u16 = 110;
|
||||
pub const RPC_AVATAR_ADVANCE_ID: u16 = 111;
|
||||
pub const RPC_DRESS_EQUIPMENT_ID: u16 = 112;
|
||||
pub const RPC_GM_COMMAND_ID: u16 = 113;
|
||||
pub const PTC_HOLLOW_GRID_ID: u16 = 114;
|
||||
pub const PTC_PREPARE_SECTION_ID: u16 = 115;
|
||||
pub const PTC_PAUSE_MAIN_CITY_TIME_ID: u16 = 116;
|
||||
pub const PTC_ITEM_CHANGED_ID: u16 = 117;
|
||||
pub const PTC_ENTER_SCENE_ID: u16 = 118;
|
||||
pub const RPC_WEAPON_LOCK_ID: u16 = 119;
|
||||
pub const RPC_WEAPON_DECOMPOSE_ID: u16 = 120;
|
||||
pub const RPC_GET_SHOP_INFO_ID: u16 = 122;
|
||||
pub const PTC_SYNC_HOLLOW_GRID_MAPS_ID: u16 = 124;
|
||||
pub const RPC_BATTLE_REPORT_ID: u16 = 125;
|
||||
pub const RPC_WEAPON_LEVEL_UP_ID: u16 = 126;
|
||||
pub const RPC_WEAPON_STAR_UP_ID: u16 = 127;
|
||||
pub const PTC_SCENE_PROPERTY_CHANGED_ID: u16 = 128;
|
||||
pub const PTC_PROPERTY_CHANGED_ID: u16 = 129;
|
||||
pub const RPC_EQUIPMENT_LEVEL_UP_ID: u16 = 130;
|
||||
pub const RPC_EQUIPMENT_STAR_UP_ID: u16 = 131;
|
||||
pub const RPC_WEAPON_DRESS_ID: u16 = 132;
|
||||
pub const PTC_FAIRY_INFO_CHANGED_ID: u16 = 134;
|
||||
pub const RPC_OPEN_VHS_STORE_ID: u16 = 135;
|
||||
pub const PTC_DUNGEON_QUEST_PREPARE_TO_FINISH_ID: u16 = 136;
|
||||
pub const RPC_BEGIN_ARCHIVE_BATTLE_QUEST_ID: u16 = 137;
|
||||
pub const PTC_HOLLOW_GLOBAL_EVENT_ID: u16 = 138;
|
||||
pub const RPC_WEAPON_UN_DRESS_ID: u16 = 139;
|
||||
pub const RPC_LEAVE_CUR_DUNGEON_ID: u16 = 140;
|
||||
pub const PTC_POSITION_IN_HOLLOW_CHANGED_ID: u16 = 141;
|
||||
pub const RPC_GIVE_UP_DUNGEON_QUEST_ID: u16 = 142;
|
||||
pub const RPC_HOLLOW_CHANGE_AFFIX_ID: u16 = 143;
|
||||
pub const PTC_TRANSFORM_TO_HOLLOW_GRID_ID: u16 = 144;
|
||||
pub const PTC_BEFORE_GO_TO_HOLLOW_LEVEL_ID: u16 = 145;
|
||||
pub const RPC_FINISH_GRAPH_IN_CLIENT_ID: u16 = 146;
|
||||
pub const PTC_STAMINA_OVER_LEVEL_PUNISH_ID: u16 = 147;
|
||||
pub const PTC_DUNGEON_QUEST_FINISHED_ID: u16 = 148;
|
||||
pub const RPC_KEEP_ALIVE_ID: u16 = 149;
|
||||
pub const RPC_REENTER_WORLD_ID: u16 = 150;
|
||||
pub const PTC_GO_TO_HOLLOW_LEVEL_ID: u16 = 154;
|
||||
pub const PTC_QUEST_UNLOCKED_ID: u16 = 158;
|
||||
pub const RPC_GET_CHAT_HISTORY_CLIENT2_PLAYER_ID: u16 = 159;
|
||||
pub const RPC_SEND_CHAT_MESSAGE_CLIENT2_PLAYER_ID: u16 = 163;
|
||||
pub const PTC_RECEIVED_CHAT_MESSAGE_PLAYER2_CLIENT_ID: u16 = 165;
|
||||
pub const RPC_GET_ARCHIVE_REWARD_ID: u16 = 166;
|
||||
pub const RPC_BUY_AUTO_RECOVERY_ITEM_ID: u16 = 167;
|
||||
pub const RPC_YOROZUYA_MANUAL_RECEIVE_REWARD_ID: u16 = 168;
|
||||
pub const RPC_EQUIP_GACHA_ID: u16 = 169;
|
||||
pub const RPC_EQUIP_DECOMPOSE_ID: u16 = 170;
|
||||
pub const RPC_ADVANCE_BEGINNER_PROCEDURE_ID: u16 = 171;
|
||||
pub const RPC_EQUIP_LOCK_ID: u16 = 172;
|
||||
pub const RPC_GACHA_ID: u16 = 173;
|
||||
pub const RPC_ENTER_SECTION_ID: u16 = 175;
|
||||
pub const PTC_POSITION_ID: u16 = 176;
|
||||
pub const PTC_SYNC_EVENT_INFO_ID: u16 = 177;
|
||||
pub const RPC_RUN_EVENT_GRAPH_ID: u16 = 179;
|
||||
pub const PTC_SYNC_SCENE_UNIT_ID: u16 = 180;
|
||||
pub const RPC_INTERACT_WITH_UNIT_ID: u16 = 181;
|
||||
pub const RPC_GET_YOROZUYA_INFO_ID: u16 = 182;
|
||||
pub const RPC_START_HOLLOW_QUEST_ID: u16 = 183;
|
||||
pub const PTC_KICK_PLAYER_ID: u16 = 184;
|
||||
pub const RPC_FINISH_ACT_PERFORM_SHOW_ID: u16 = 185;
|
||||
pub const RPC_END_SLOT_MACHINE_ID: u16 = 186;
|
||||
pub const RPC_FINISH_EVENT_GRAPH_PERFORM_SHOW_ID: u16 = 187;
|
||||
pub const RPC_LEAVE_WORLD_ID: u16 = 190;
|
||||
pub const PTC_CHALLENGE_QUEST_FINISHED_ID: u16 = 193;
|
||||
pub const PTC_UNLOCK_ID: u16 = 196;
|
||||
pub const RPC_AVATAR_SKILL_LEVEL_UP_ID: u16 = 197;
|
||||
pub const RPC_SWITCH_HOLLOW_RANK_ID: u16 = 198;
|
||||
pub const RPC_AVATAR_UNLOCK_TALENT_ID: u16 = 199;
|
||||
pub const PTC_ENTER_SCENE_BEGIN_ID: u16 = 200;
|
||||
pub const PTC_HOLLOW_QUEST_UNLOCKED_BY_MAIN_CITY_QUEST_ID: u16 = 201;
|
||||
pub const RPC_SAVE_POS_IN_MAIN_CITY_ID: u16 = 202;
|
||||
pub const PTC_PLAYER_OPERATION_ID: u16 = 203;
|
||||
pub const PTC_GET_SERVER_TIMESTAMP_ID: u16 = 204;
|
||||
pub const PTC_POPUP_WINDOW_ID: u16 = 206;
|
||||
pub const PTC_SHOW_TIPS_ID: u16 = 207;
|
||||
pub const PTC_SYNC_HOLLOW_EVENT_INFO_ID: u16 = 210;
|
||||
pub const RPC_RUN_HOLLOW_EVENT_GRAPH_ID: u16 = 211;
|
||||
pub const RPC_HOLLOW_SHOPPING_ID: u16 = 213;
|
||||
pub const RPC_MAKE_CHOICE_OF_EVENT_ID: u16 = 214;
|
||||
pub const RPC_MOD_NICK_NAME_ID: u16 = 215;
|
||||
pub const RPC_DEBUG_PAY_ID: u16 = 216;
|
||||
pub const PTC_CARD_DISABLE_ID: u16 = 217;
|
||||
pub const RPC_SELECT_VHS_COLLECTION_ID: u16 = 219;
|
||||
pub const RPC_USE_INITIATIVE_ITEM_ID: u16 = 220;
|
||||
pub const RPC_GET_PLAYER_MAILS_ID: u16 = 221;
|
||||
pub const PTC_PLAYER_MAILS_RECEIVED_ID: u16 = 222;
|
||||
pub const PTC_ENTER_SCENE_END_ID: u16 = 224;
|
||||
pub const PTC_PLAYER_MAILS_REMOVED_ID: u16 = 225;
|
||||
pub const PTC_HP_OR_STRESS_CHANGED_ID: u16 = 226;
|
||||
pub const RPC_RECEIVE_VHS_STORE_REWARD_ID: u16 = 227;
|
||||
pub const RPC_DEL_NEW_RAMEN_ID: u16 = 228;
|
||||
pub const RPC_REMOVE_HOLLOW_CURSE_ID: u16 = 229;
|
||||
pub const RPC_SHOPPING_ID: u16 = 230;
|
||||
pub const RPC_WEAPON_REFINE_ID: u16 = 232;
|
||||
pub const RPC_MAKE_INITIATIVE_ITEM_ID: u16 = 234;
|
||||
pub const RPC_REFRESH_VHS_TRENDING_ID: u16 = 235;
|
||||
pub const RPC_SELECT_CHALLENGE_ID: u16 = 236;
|
||||
pub const RPC_REFRESH_SHOP_ID: u16 = 237;
|
||||
pub const PTC_ABILITY_POP_TEXT_ID: u16 = 239;
|
||||
pub const RPC_AFK_HOLLOW_QUEST_ID: u16 = 241;
|
||||
pub const PTC_ENTER_SECTION_ID: u16 = 243;
|
||||
pub const RPC_CLOSE_LEVEL_CHG_TIPS_ID: u16 = 244;
|
||||
pub const RPC_CHECK_YOROZUYA_INFO_REFRESH_ID: u16 = 245;
|
||||
pub const PTC_AVATAR_MAP_CHANGED_ID: u16 = 246;
|
||||
pub const RPC_HOLLOW_MOVE_ID: u16 = 248;
|
||||
pub const PTC_SYNC_SCENE_TIME_ID: u16 = 249;
|
||||
pub const RPC_BEGINNERBATTLE_REBEGIN_ID: u16 = 250;
|
||||
pub const RPC_END_BATTLE_ID: u16 = 251;
|
||||
pub const RPC_PREPARE_NEXT_HOLLOW_END_ID: u16 = 252;
|
||||
pub const RPC_PERFORM_TRIGGER_ID: u16 = 253;
|
||||
pub const RPC_PERFORM_JUMP_ID: u16 = 254;
|
||||
pub const RPC_PERFORM_END_ID: u16 = 255;
|
||||
pub const RPC_AWARD_PLAYER_MAIL_ID: u16 = 256;
|
||||
pub const RPC_AWARD_ALL_PLAYER_MAIL_ID: u16 = 257;
|
||||
pub const RPC_BEGINNERBATTLE_BEGIN_ID: u16 = 258;
|
||||
pub const RPC_READ_PLAYER_MAIL_ID: u16 = 263;
|
||||
pub const RPC_REMOVE_PLAYER_MAILS_FROM_CLIENT_ID: u16 = 264;
|
||||
pub const RPC_SET_PLAYER_MAIL_OLD_ID: u16 = 265;
|
||||
pub const RPC_FINISH_BLACKOUT_ID: u16 = 267;
|
||||
pub const PTC_HOLLOW_BLACKOUT_ID: u16 = 268;
|
||||
pub const RPC_BUY_VHS_COLLECTION_ID: u16 = 269;
|
||||
pub const PTC_PREVENT_ADDICTION_ID: u16 = 270;
|
||||
pub const RPC_SET_BGM_ID: u16 = 273;
|
||||
pub const RPC_SET_MAIN_CITY_OBJECT_STATE_ID: u16 = 274;
|
||||
pub const PTC_SHOW_CARD_GENRE_TIPS_ID: u16 = 276;
|
||||
pub const PTC_CONFIG_UPDATED_ID: u16 = 277;
|
||||
pub const PTC_SHOW_UNLOCK_ID_TIPS_ID: u16 = 278;
|
||||
pub const PTC_FUNCTION_SWITCH_MASK_ID: u16 = 279;
|
||||
pub const RPC_GET_AUTH_KEY_ID: u16 = 280;
|
||||
pub const RPC_ITEM_CONVERT_ID: u16 = 281;
|
||||
pub const RPC_CLICK_HOLLOW_SYSTEM_ID: u16 = 282;
|
||||
pub const RPC_EAT_RAMEN_ID: u16 = 283;
|
||||
pub const PTC_HOLLOW_PUSH_BACK_ID: u16 = 284;
|
||||
pub const RPC_BEGINNERBATTLE_END_ID: u16 = 285;
|
||||
pub const RPC_BATTLE_REBEGIN_ID: u16 = 286;
|
||||
pub const RPC_DEL_NEW_MAP_ID: u16 = 287;
|
460
protocol/src/rpc_ptc.rs
Normal file
460
protocol/src/rpc_ptc.rs
Normal file
|
@ -0,0 +1,460 @@
|
|||
use super::*;
|
||||
|
||||
// :skull:
|
||||
macro_rules! ret {
|
||||
(struct $name:ident $(< $lt:lifetime >)? {
|
||||
$(
|
||||
$(#[$attr:meta])*
|
||||
$field:ident: $ty:ty,
|
||||
)*
|
||||
}) => {
|
||||
#[derive(OctData)]
|
||||
pub struct $name $(< $lt >)? {
|
||||
pub error_code: ErrorCode,
|
||||
pub error_code_params: Vec<String>,
|
||||
$(
|
||||
$(#[$attr])*
|
||||
pub $field: $ty,
|
||||
)*
|
||||
}
|
||||
|
||||
impl $(< $lt >)? $name $(< $lt >)? {
|
||||
#[must_use]
|
||||
pub const fn new($($field: $ty,)*) -> Self {
|
||||
Self {
|
||||
error_code: ErrorCode::Success,
|
||||
error_code_params: Vec::new(),
|
||||
$($field,)*
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn error(error_code: ErrorCode, error_code_params: Vec<String>) -> Self {
|
||||
Self {
|
||||
error_code,
|
||||
error_code_params,
|
||||
$($field: Default::default(),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl $(< $lt >)? Default for $name $(< $lt >)? {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
error_code: ErrorCode::Success,
|
||||
error_code_params: Vec::new(),
|
||||
$($field: Default::default(),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
($(struct $name:ident $(< $lt:lifetime >)? { $($field:tt)* })+) => {
|
||||
$(ret!(struct $name $(< $lt >)? { $($field)* });)+
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct RpcLoginArg {
|
||||
pub account_name: String,
|
||||
pub token: String,
|
||||
pub client_protocol_sign: String,
|
||||
pub config_sign: String,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct RpcCreatePlayerArg {}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct PtcEnterSceneArg {
|
||||
pub player_uid: u64,
|
||||
pub scene_uid: u64,
|
||||
pub ext: SceneTableExt,
|
||||
pub entered_times: u16,
|
||||
pub section_id: i32,
|
||||
pub transform: Transform,
|
||||
pub open_ui: UIType,
|
||||
pub condition_config_ids: Vec<i32>,
|
||||
pub timestamp: u64,
|
||||
pub camera_x: u32,
|
||||
pub camera_y: u32,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcReenterWorldArg {}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcEnterWorldArg {}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcGetPlayerMailsArg {}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct PtcUnlockArg {
|
||||
pub unlock_id: i32,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct PtcGetServerTimestampArg {}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcAdvanceBeginnerProcedureArg {
|
||||
pub player_uid: u64,
|
||||
pub procedure_id: i32,
|
||||
pub params: i32,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcPerformTriggerArg {
|
||||
pub perform_id: i32,
|
||||
pub perform_type: i32,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcPerformEndArg {
|
||||
pub perform_id: i32,
|
||||
pub perform_type: i32,
|
||||
pub perform_uid: String,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcModNickNameArg {
|
||||
pub nick_name: String,
|
||||
pub avatar_id: i32,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcFinishActPerformShowArg {
|
||||
pub moment: ACTPerformShowMoment,
|
||||
pub step: u8,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcKeepAliveArg {}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcPerformJumpArg {
|
||||
pub perform_id: i32,
|
||||
pub perform_type: i32,
|
||||
pub perform_uid: String,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcBeginnerbattleBeginArg {
|
||||
pub battle_id: i32,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcBattleReportArg {
|
||||
pub battle_reports: Vec<BattleReport>,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcBeginnerbattleEndArg {
|
||||
pub battle_id: i32,
|
||||
pub battle_uid: String,
|
||||
pub battle_statistics: LogBattleStatistics,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcLeaveCurDungeonArg {
|
||||
pub player_uid: u64,
|
||||
pub dungeon_uid: u64,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcSavePosInMainCityArg {
|
||||
pub position: Vector3f,
|
||||
pub rotation: Vector3f,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct RpcCloseLevelChgTipsArg {}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct PtcPlayerInfoChangedArg {
|
||||
pub player_uid: u64,
|
||||
#[property_blob]
|
||||
pub player_info: PlayerInfo,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
pub struct PtcPlayerOperationArg {
|
||||
pub system: System,
|
||||
pub operator: Operator,
|
||||
pub param: i32,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct PtcScenePropertyChangedArg {
|
||||
pub player_uid: u64,
|
||||
pub is_partial: bool,
|
||||
pub changed_properties: PropertyHashMap<u16, i32>,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct PtcPropertyChangedArg {
|
||||
pub scene_unit_uid: u64,
|
||||
pub is_partial: bool,
|
||||
pub changed_properties: PropertyHashMap<u16, i32>,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct PtcSyncSceneUnitArg {
|
||||
pub scene_uid: u64,
|
||||
pub section_id: i32,
|
||||
pub is_partial: bool,
|
||||
pub removed_scene_units: Vec<u64>,
|
||||
pub scene_units: Vec<SceneUnitProtocolInfo>,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct PtcEnterSectionArg {
|
||||
pub section_id: i32,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct RpcRunEventGraphArg {
|
||||
pub owner_type: EventGraphOwnerType,
|
||||
pub owner_uid: u64,
|
||||
pub event_graph_id: i32,
|
||||
pub event_id: i32,
|
||||
pub move_path: Vec<i32>,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct RpcInteractWithUnitArg {
|
||||
pub unit_uid: u64,
|
||||
pub unit_type: InteractTarget,
|
||||
pub event_graph_id: i32,
|
||||
pub interaction: u16,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct PtcSyncEventInfoArg {
|
||||
pub owner_type: EventGraphOwnerType,
|
||||
pub owner_uid: u64,
|
||||
pub updated_events: PropertyDoubleKeyHashMap<i32, i32, EventInfo>,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct RpcCheckYorozuyaInfoRefreshArg {}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct PtcHollowQuestUnlockedByMainCityQuest {
|
||||
pub quest_id: i32,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct RpcStartHollowQuestArg {
|
||||
pub hollow_quest_id: i32,
|
||||
pub buddy: u64,
|
||||
pub initiative_item: i32,
|
||||
pub avatar_map: PropertyHashMap<i8, u64>,
|
||||
pub is_story: bool,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct PtcSyncHollowGridMapsArg {
|
||||
pub player_uid: u64,
|
||||
pub scene_uid: u64,
|
||||
pub hollow_level: i32,
|
||||
pub main_map: HollowGridMapProtocolInfo,
|
||||
pub time_period: TimePeriodType,
|
||||
pub weather: WeatherType,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct PtcPositionInHollowChangedArg {
|
||||
pub player_uid: u64,
|
||||
pub hollow_level: i32,
|
||||
pub position: u16,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct PtcSyncHollowEventInfoArg {
|
||||
pub event_graph_uid: u64,
|
||||
pub hollow_event_template_id: i32,
|
||||
pub event_graph_id: i32,
|
||||
pub updated_event: EventInfo,
|
||||
pub specials: PropertyHashMap<String, i32>,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct RpcRunHollowEventGraphArg {
|
||||
pub event_graph_uid: u64,
|
||||
pub event_id: i32,
|
||||
pub move_path: Vec<i32>,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct PtcHollowGridArg {
|
||||
pub player_uid: u64,
|
||||
pub is_partial: bool,
|
||||
pub scene_uid: u64,
|
||||
pub hollow_level: i32,
|
||||
pub grids: HashMap<u16, HollowGridProtocolInfo>,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct RpcHollowMoveArg {
|
||||
pub player_uid: u64,
|
||||
pub scene_uid: u64,
|
||||
pub hollow_level: i32,
|
||||
pub positions: Vec<u16>,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct RpcEndBattleArg {
|
||||
pub player_uid: u64,
|
||||
pub fight_ranking: FightRanking,
|
||||
pub success: bool,
|
||||
pub avatar_properties: PropertyHashMap<u64, HashMap<u16, i32>>,
|
||||
pub killed_enemy_count: u16,
|
||||
pub condition_statistics: HashMap<i32, i32>,
|
||||
pub star: u8,
|
||||
pub challenge_stat: HashMap<i32, u8>,
|
||||
pub fight_drop_infos: Vec<FightDropInfo>,
|
||||
pub challenge_result_info: PropertyHashMap<i32, ChallengeResultInfo>,
|
||||
pub battle_statistics: LogBattleStatistics,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct RpcFinishEventGraphPerformShowArg {
|
||||
pub owner_type: EventGraphOwnerType,
|
||||
pub owner_uid: u64,
|
||||
pub event_graph_id: i32,
|
||||
pub event_id: i32,
|
||||
pub step: u8,
|
||||
pub return_map: HashMap<String, i32>,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct RpcDelNewMapArg {
|
||||
pub map_type: UnlockIDType,
|
||||
pub ids: PropertyHashSet<i32>,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct PtcDungeonQuestFinishedArg {
|
||||
pub player_uid: u64,
|
||||
pub quest_id: i32,
|
||||
pub success: bool,
|
||||
pub reward_items: PropertyHashMap<u64, ItemIDCount>,
|
||||
pub statistics: PropertyHashMap<QuestStatisticsType, u64>,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct PtcSyncSceneTimeArg {
|
||||
pub timestamp: u64,
|
||||
pub last_timestamp: u64,
|
||||
}
|
||||
|
||||
#[derive(OctData, Debug)]
|
||||
pub struct PtcKickPlayerArg {
|
||||
pub reason_id: i32,
|
||||
pub reason_str: String,
|
||||
}
|
||||
|
||||
ret! {
|
||||
struct RpcLoginRet {
|
||||
account_info: PropertyBlob,
|
||||
}
|
||||
|
||||
struct RpcCreatePlayerRet {
|
||||
player_uid: u64,
|
||||
}
|
||||
|
||||
struct RpcEnterWorldRet {
|
||||
player_info: PropertyBlob,
|
||||
}
|
||||
|
||||
struct RpcReenterWorldRet {
|
||||
player_info: PropertyBlob,
|
||||
}
|
||||
|
||||
struct RpcGetPlayerMailsRet {
|
||||
mail_count: u32, // Actually List<CPlayerMailInfo>, TODO!
|
||||
}
|
||||
|
||||
struct PtcGetServerTimestampRet {
|
||||
timestamp: u64,
|
||||
base_utc_offset_milliseconds: i64,
|
||||
}
|
||||
|
||||
struct RpcAdvanceBeginnerProcedureRet {
|
||||
next_procedure_id: i32,
|
||||
}
|
||||
|
||||
struct RpcPerformTriggerRet {
|
||||
perform_uid: String,
|
||||
}
|
||||
|
||||
struct RpcPerformEndRet {
|
||||
}
|
||||
|
||||
struct RpcModNickNameRet {
|
||||
}
|
||||
|
||||
struct RpcFinishActPerformShowRet {
|
||||
}
|
||||
|
||||
struct RpcKeepAliveRet {
|
||||
}
|
||||
|
||||
struct RpcPerformJumpRet {
|
||||
}
|
||||
|
||||
struct RpcBeginnerbattleBeginRet {
|
||||
battle_uid: String,
|
||||
}
|
||||
|
||||
struct RpcBattleReportRet {
|
||||
need_index: i32,
|
||||
}
|
||||
|
||||
struct RpcBeginnerbattleEndRet {
|
||||
}
|
||||
|
||||
struct RpcLeaveCurDungeonRet {
|
||||
}
|
||||
|
||||
struct RpcSavePosInMainCityRet {
|
||||
}
|
||||
|
||||
struct RpcCloseLevelChgTipsRet {
|
||||
}
|
||||
|
||||
struct PtcPlayerOperationRet {
|
||||
}
|
||||
|
||||
struct RpcRunEventGraphRet {
|
||||
}
|
||||
|
||||
struct RpcInteractWithUnitRet {
|
||||
}
|
||||
|
||||
struct RpcCheckYorozuyaInfoRefreshRet {
|
||||
}
|
||||
|
||||
struct RpcStartHollowQuestRet {
|
||||
}
|
||||
|
||||
struct RpcRunHollowEventGraphRet {
|
||||
}
|
||||
|
||||
struct RpcHollowMoveRet {
|
||||
hollow_level: i32,
|
||||
position: u16,
|
||||
}
|
||||
|
||||
struct RpcEndBattleRet {
|
||||
hollow_event_id: i32,
|
||||
reward_items_classify: HashMap<BattleRewardType, HashMap<u64, ItemIDCount>>,
|
||||
}
|
||||
|
||||
struct RpcFinishEventGraphPerformShowRet {
|
||||
}
|
||||
|
||||
struct RpcDelNewMapRet {
|
||||
}
|
||||
}
|
1339
protocol/src/structs.rs
Normal file
1339
protocol/src/structs.rs
Normal file
File diff suppressed because it is too large
Load diff
16
qwer/Cargo.toml
Normal file
16
qwer/Cargo.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[package]
|
||||
name = "qwer"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
|
||||
[features]
|
||||
default = ["collection", "fastoct"]
|
||||
full = ["default", "protocol"]
|
||||
collection = []
|
||||
fastoct = []
|
||||
protocol = []
|
||||
|
||||
[dependencies]
|
||||
byteorder.workspace = true
|
||||
qwer-derive.workspace = true
|
||||
itertools.workspace = true
|
16
qwer/qwer-derive/Cargo.toml
Normal file
16
qwer/qwer-derive/Cargo.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[package]
|
||||
name = "qwer-derive"
|
||||
version.workspace = true
|
||||
edition = "2021"
|
||||
description = "Codegen for Zenless Zone Zero's Qwer Protocol"
|
||||
license = "MIT"
|
||||
publish = true
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
heck.workspace = true
|
||||
proc-macro2 = "1.0.78"
|
||||
quote = "1.0.35"
|
||||
syn = "2.0.52"
|
39
qwer/qwer-derive/src/lib.rs
Normal file
39
qwer/qwer-derive/src/lib.rs
Normal file
|
@ -0,0 +1,39 @@
|
|||
use proc_macro::TokenStream;
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
|
||||
mod oct_data;
|
||||
|
||||
/// Generate `OctData` implementation for structs and enums that have all fields
|
||||
/// implement `OctData`.
|
||||
///
|
||||
/// For structs, fields are written one by one in order.
|
||||
/// If the struct must pad a byte due to it being a `CPropertyObject`, the `#[property_object]`
|
||||
/// attribute must be present, and must contain the value to pad with.
|
||||
///
|
||||
/// e.g. `#[property_object(u16, 0x01)]` will pad with 0x01 as a u16.
|
||||
///
|
||||
/// In the presence of these property objects, all fields must be Optional, e.g. `Option<T>`,
|
||||
/// and must also have a tag attribute attached to them for marshalling and unmarshalling, of the
|
||||
/// form `#[tag = <number>]`.
|
||||
///
|
||||
/// For enums, the structure starts with a discriminant with the type specified in the `#[repr]` of
|
||||
/// the enum, followed by the fields of the enum one by one.
|
||||
#[proc_macro_derive(
|
||||
OctData,
|
||||
attributes(
|
||||
property_object,
|
||||
property_blob,
|
||||
skip_property,
|
||||
tag,
|
||||
root,
|
||||
base,
|
||||
polymorphic_none
|
||||
)
|
||||
)]
|
||||
pub fn derive_message(item: TokenStream) -> TokenStream {
|
||||
let parsed = parse_macro_input!(item as DeriveInput);
|
||||
match oct_data::imp(&parsed) {
|
||||
Ok(item) => item.into(),
|
||||
Err(err) => err.to_compile_error().into(),
|
||||
}
|
||||
}
|
1033
qwer/qwer-derive/src/oct_data.rs
Normal file
1033
qwer/qwer-derive/src/oct_data.rs
Normal file
File diff suppressed because it is too large
Load diff
782
qwer/src/collection.rs
Normal file
782
qwer/src/collection.rs
Normal file
|
@ -0,0 +1,782 @@
|
|||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
io::Result,
|
||||
};
|
||||
|
||||
use crate::OctData;
|
||||
|
||||
pub type DoubleKeyHashMap<K1, K2, V> = HashMap<K1, HashMap<K2, V>>;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! phashmap {
|
||||
($(($key:expr, $value:expr)),*) => {
|
||||
PropertyHashMap::Base(
|
||||
{
|
||||
let mut map = std::collections::HashMap::new();
|
||||
$(
|
||||
map.insert($key, $value);
|
||||
)*
|
||||
map
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! phashset {
|
||||
($($value:expr),*) => {
|
||||
PropertyHashSet::Base(
|
||||
{
|
||||
let mut set = std::collections::HashSet::new();
|
||||
$(
|
||||
set.insert($value);
|
||||
)*
|
||||
set
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pdkhashmap {
|
||||
($(($key1:expr, $key2:expr, $value:expr)),*) => {
|
||||
PropertyDoubleKeyHashMap::Base(
|
||||
{
|
||||
let mut map = qwer::DoubleKeyHashMap::new();
|
||||
$(
|
||||
map.entry($key1).or_insert(HashMap::new()).insert($key2, $value);
|
||||
)*
|
||||
map
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum PropertyHashMap<K, V>
|
||||
where
|
||||
K: OctData + Eq + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
Base(HashMap<K, V>),
|
||||
Modify {
|
||||
to_add: Vec<(K, V)>,
|
||||
to_remove: Vec<K>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<K, V> PropertyHashMap<K, V>
|
||||
where
|
||||
K: OctData + Eq + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
pub fn insert(&mut self, key: K, value: V) {
|
||||
match self {
|
||||
Self::Base(base) => {
|
||||
base.insert(key, value);
|
||||
}
|
||||
Self::Modify { to_add, .. } => {
|
||||
to_add.push((key, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, key: K) -> Option<V> {
|
||||
match self {
|
||||
Self::Base(base) => base.remove(&key),
|
||||
Self::Modify { to_remove, .. } => {
|
||||
to_remove.push(key);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, key: &K) -> Option<&V> {
|
||||
match self {
|
||||
Self::Base(base) => base.get(key),
|
||||
Self::Modify { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
|
||||
match self {
|
||||
Self::Base(base) => base.get_mut(key),
|
||||
Self::Modify { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
Self::Base(base) => base.len(),
|
||||
Self::Modify { to_add, to_remove } => to_add.len() + to_remove.len(),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
Self::Base(base) => base.is_empty(),
|
||||
Self::Modify { to_add, to_remove } => to_add.is_empty() && to_remove.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn iter(&self) -> std::collections::hash_map::Iter<K, V> {
|
||||
match self {
|
||||
Self::Base(base) => base.iter(),
|
||||
Self::Modify { .. } => unreachable!("PropertyHashMap::Modify::iter()"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter_mut(&mut self) -> std::collections::hash_map::IterMut<K, V> {
|
||||
match self {
|
||||
Self::Base(base) => base.iter_mut(),
|
||||
Self::Modify { .. } => unreachable!("PropertyHashMap::Modify::iter_mut()"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> IntoIterator for PropertyHashMap<K, V>
|
||||
where
|
||||
K: OctData + Eq + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
type IntoIter = std::collections::hash_map::IntoIter<K, V>;
|
||||
type Item = (K, V);
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
Self::Base(base) => base.into_iter(),
|
||||
Self::Modify { .. } => unreachable!("PropertyHashMap::Modify::into_iter()"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K, V> IntoIterator for &'a PropertyHashMap<K, V>
|
||||
where
|
||||
K: OctData + Eq + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
type IntoIter = std::collections::hash_map::Iter<'a, K, V>;
|
||||
type Item = (&'a K, &'a V);
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
PropertyHashMap::Base(base) => base.iter(),
|
||||
PropertyHashMap::Modify { .. } => unreachable!("PropertyHashMap::Modify::into_iter()"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K, V> IntoIterator for &'a mut PropertyHashMap<K, V>
|
||||
where
|
||||
K: OctData + Eq + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
type IntoIter = std::collections::hash_map::IterMut<'a, K, V>;
|
||||
type Item = (&'a K, &'a mut V);
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
PropertyHashMap::Base(base) => base.iter_mut(),
|
||||
PropertyHashMap::Modify { .. } => unreachable!("PropertyHashMap::Modify::into_iter()"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hashmap_iter() {
|
||||
let mut map = phashmap![(1, 2), (3, 4)];
|
||||
let mut expecting = vec![(1, 2), (3, 4)];
|
||||
let iter = map.iter_mut();
|
||||
for (key, value) in iter {
|
||||
assert!(expecting.contains(&(*key, *value)));
|
||||
expecting.retain(|x| x != &(*key, *value));
|
||||
*value += 1;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PropertyHashSet<T>
|
||||
where
|
||||
T: OctData + Eq + std::hash::Hash,
|
||||
{
|
||||
pub fn insert(&mut self, value: T) {
|
||||
match self {
|
||||
Self::Base(base) => {
|
||||
base.insert(value);
|
||||
}
|
||||
Self::Modify { to_add, .. } => {
|
||||
to_add.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, value: T) {
|
||||
match self {
|
||||
Self::Base(base) => {
|
||||
base.remove(&value);
|
||||
}
|
||||
Self::Modify { to_remove, .. } => {
|
||||
to_remove.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
Self::Base(base) => base.len(),
|
||||
Self::Modify { to_add, to_remove } => to_add.len() + to_remove.len(),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
Self::Base(base) => base.is_empty(),
|
||||
Self::Modify { to_add, to_remove } => to_add.is_empty() && to_remove.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn iter(&self) -> std::collections::hash_set::Iter<T> {
|
||||
match self {
|
||||
Self::Base(base) => base.iter(),
|
||||
Self::Modify { .. } => unreachable!("PropertyHashSet::Modify::iter()"),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn iter_mut(&mut self) -> std::collections::hash_set::Iter<T> {
|
||||
self.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for PropertyHashSet<T>
|
||||
where
|
||||
T: OctData + Eq + std::hash::Hash,
|
||||
{
|
||||
type IntoIter = std::collections::hash_set::IntoIter<T>;
|
||||
type Item = T;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
Self::Base(base) => base.into_iter(),
|
||||
Self::Modify { .. } => unreachable!("PropertyHashSet::Modify::into_iter()"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a PropertyHashSet<T>
|
||||
where
|
||||
T: OctData + Eq + std::hash::Hash,
|
||||
{
|
||||
type IntoIter = std::collections::hash_set::Iter<'a, T>;
|
||||
type Item = &'a T;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
PropertyHashSet::Base(base) => base.iter(),
|
||||
PropertyHashSet::Modify { .. } => unreachable!("PropertyHashSet::Modify::into_iter()"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut PropertyHashSet<T>
|
||||
where
|
||||
T: OctData + Eq + std::hash::Hash,
|
||||
{
|
||||
type IntoIter = std::collections::hash_set::Iter<'a, T>;
|
||||
type Item = &'a T;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
PropertyHashSet::Base(base) => base.iter(),
|
||||
PropertyHashSet::Modify { .. } => unreachable!("PropertyHashSet::Modify::into_iter()"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_phashmap_macro() {
|
||||
let map = phashmap![(1, 2), (3, 4)];
|
||||
assert_eq!(
|
||||
map,
|
||||
PropertyHashMap::Base([(1, 2), (3, 4)].into_iter().collect())
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum PropertyHashSet<T>
|
||||
where
|
||||
T: OctData + Eq + std::hash::Hash,
|
||||
{
|
||||
Base(HashSet<T>),
|
||||
Modify { to_add: Vec<T>, to_remove: Vec<T> },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum PropertyDoubleKeyHashMap<K1, K2, V>
|
||||
where
|
||||
K1: OctData + Eq + std::hash::Hash,
|
||||
K2: OctData + Eq + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
Base(DoubleKeyHashMap<K1, K2, V>),
|
||||
Modify {
|
||||
to_add: Vec<(K1, K2, V)>,
|
||||
to_remove: Vec<(K1, K2)>,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct PropertyDoubleKeyHashMapIterMut<'a, K1, K2, V> {
|
||||
outer_iter: std::collections::hash_map::IterMut<'a, K1, HashMap<K2, V>>,
|
||||
inner_iter: Option<std::collections::hash_map::IterMut<'a, K2, V>>,
|
||||
current_outer_key: Option<&'a K1>,
|
||||
}
|
||||
|
||||
pub struct PropertyDoubleKeyHashMapIter<'a, K1, K2, V> {
|
||||
outer_iter: std::collections::hash_map::Iter<'a, K1, HashMap<K2, V>>,
|
||||
inner_iter: Option<std::collections::hash_map::Iter<'a, K2, V>>,
|
||||
current_outer_key: Option<&'a K1>,
|
||||
}
|
||||
|
||||
pub struct PropertyDoubleKeyHashMapIntoIter<K1, K2, V> {
|
||||
outer_iter: std::collections::hash_map::IntoIter<K1, HashMap<K2, V>>,
|
||||
inner_iter: Option<std::collections::hash_map::IntoIter<K2, V>>,
|
||||
current_outer_key: Option<K1>,
|
||||
}
|
||||
|
||||
impl<'a, K1, K2, V> Iterator for PropertyDoubleKeyHashMapIterMut<'a, K1, K2, V>
|
||||
where
|
||||
K1: OctData + Eq + std::hash::Hash,
|
||||
K2: OctData + Eq + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
type Item = (&'a K1, &'a K2, &'a mut V);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
if self.inner_iter.is_none() {
|
||||
if let Some((key1, sub_map)) = self.outer_iter.next() {
|
||||
self.current_outer_key = Some(key1);
|
||||
self.inner_iter = Some(sub_map.iter_mut());
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(inner_iter) = &mut self.inner_iter {
|
||||
if let Some((key2, value)) = inner_iter.next() {
|
||||
return Some((self.current_outer_key.unwrap(), key2, value));
|
||||
}
|
||||
self.inner_iter = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K1, K2, V> Iterator for PropertyDoubleKeyHashMapIter<'a, K1, K2, V>
|
||||
where
|
||||
K1: OctData + Eq + std::hash::Hash,
|
||||
K2: OctData + Eq + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
type Item = (&'a K1, &'a K2, &'a V);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
if self.inner_iter.is_none() {
|
||||
if let Some((key1, sub_map)) = self.outer_iter.next() {
|
||||
self.current_outer_key = Some(key1);
|
||||
self.inner_iter = Some(sub_map.iter());
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(inner_iter) = &mut self.inner_iter {
|
||||
if let Some((key2, value)) = inner_iter.next() {
|
||||
return Some((self.current_outer_key.unwrap(), key2, value));
|
||||
}
|
||||
self.inner_iter = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K1, K2, V> Iterator for PropertyDoubleKeyHashMapIntoIter<K1, K2, V>
|
||||
where
|
||||
K1: OctData + Eq + std::hash::Hash + Copy,
|
||||
K2: OctData + Eq + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
type Item = (K1, K2, V);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
if self.inner_iter.is_none() {
|
||||
if let Some((key1, sub_map)) = self.outer_iter.next() {
|
||||
self.current_outer_key = Some(key1);
|
||||
self.inner_iter = Some(sub_map.into_iter());
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(inner_iter) = &mut self.inner_iter {
|
||||
if let Some((key2, value)) = inner_iter.next() {
|
||||
return Some((self.current_outer_key.unwrap(), key2, value));
|
||||
}
|
||||
self.inner_iter = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K1, K2, V> IntoIterator for PropertyDoubleKeyHashMap<K1, K2, V>
|
||||
where
|
||||
K1: OctData + Eq + std::hash::Hash + Copy,
|
||||
K2: OctData + Eq + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
type IntoIter = PropertyDoubleKeyHashMapIntoIter<K1, K2, V>;
|
||||
type Item = (K1, K2, V);
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
Self::Base(base) => PropertyDoubleKeyHashMapIntoIter {
|
||||
outer_iter: base.into_iter(),
|
||||
inner_iter: None,
|
||||
current_outer_key: None,
|
||||
},
|
||||
Self::Modify { .. } => {
|
||||
unreachable!("PropertyDoubleKeyHashMap::Modify::into_iter() is not implemented")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K1, K2, V> IntoIterator for &'a PropertyDoubleKeyHashMap<K1, K2, V>
|
||||
where
|
||||
K1: OctData + Eq + std::hash::Hash,
|
||||
K2: OctData + Eq + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
type IntoIter = PropertyDoubleKeyHashMapIter<'a, K1, K2, V>;
|
||||
type Item = (&'a K1, &'a K2, &'a V);
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
PropertyDoubleKeyHashMap::Base(base) => PropertyDoubleKeyHashMapIter {
|
||||
outer_iter: base.iter(),
|
||||
inner_iter: None,
|
||||
current_outer_key: None,
|
||||
},
|
||||
PropertyDoubleKeyHashMap::Modify { .. } => {
|
||||
unreachable!("PropertyDoubleKeyHashMap::Modify::into_iter() is not implemented")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K1, K2, V> IntoIterator for &'a mut PropertyDoubleKeyHashMap<K1, K2, V>
|
||||
where
|
||||
K1: OctData + Eq + std::hash::Hash,
|
||||
K2: OctData + Eq + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
type IntoIter = PropertyDoubleKeyHashMapIterMut<'a, K1, K2, V>;
|
||||
type Item = (&'a K1, &'a K2, &'a mut V);
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
PropertyDoubleKeyHashMap::Base(base) => PropertyDoubleKeyHashMapIterMut {
|
||||
outer_iter: base.iter_mut(),
|
||||
inner_iter: None,
|
||||
current_outer_key: None,
|
||||
},
|
||||
PropertyDoubleKeyHashMap::Modify { .. } => {
|
||||
unreachable!("PropertyDoubleKeyHashMap::Modify::into_iter() is not implemented")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K1, K2, V> PropertyDoubleKeyHashMap<K1, K2, V>
|
||||
where
|
||||
K1: OctData + Eq + std::hash::Hash,
|
||||
K2: OctData + Eq + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
pub fn insert(&mut self, key: K1, sub_key: K2, value: V) {
|
||||
match self {
|
||||
Self::Base(base) => {
|
||||
base.entry(key)
|
||||
.or_insert_with(HashMap::new)
|
||||
.insert(sub_key, value);
|
||||
}
|
||||
Self::Modify { to_add, .. } => {
|
||||
to_add.push((key, sub_key, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, key: &K1, sub_key: &K2) -> Option<&V> {
|
||||
match self {
|
||||
Self::Base(base) => base.get(key).and_then(|sub_map| sub_map.get(sub_key)),
|
||||
Self::Modify { .. } => {
|
||||
unreachable!("PropertyDoubleKeyHashMap::Modify::get() is not implemented")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, key: &K1, sub_key: &K2) -> Option<&mut V> {
|
||||
match self {
|
||||
Self::Base(base) => base
|
||||
.get_mut(key)
|
||||
.and_then(|sub_map| sub_map.get_mut(sub_key)),
|
||||
Self::Modify { .. } => {
|
||||
unreachable!("PropertyDoubleKeyHashMap::Modify::get_mut() is not implemented")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, key: K1, sub_key: K2) -> Option<V> {
|
||||
match self {
|
||||
Self::Base(base) => {
|
||||
let mut removed = None;
|
||||
base.entry(key)
|
||||
.and_modify(|sub_map| removed = sub_map.remove(&sub_key));
|
||||
removed
|
||||
}
|
||||
Self::Modify { to_remove, .. } => {
|
||||
to_remove.push((key, sub_key));
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
Self::Base(base) => base.len(),
|
||||
Self::Modify { to_add, to_remove } => to_add.len() + to_remove.len(),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
Self::Base(base) => base.is_empty(),
|
||||
Self::Modify { to_add, to_remove } => to_add.is_empty() && to_remove.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn iter(&self) -> PropertyDoubleKeyHashMapIter<K1, K2, V> {
|
||||
match self {
|
||||
Self::Base(base) => PropertyDoubleKeyHashMapIter {
|
||||
outer_iter: base.iter(),
|
||||
inner_iter: None,
|
||||
current_outer_key: None,
|
||||
},
|
||||
Self::Modify { .. } => {
|
||||
unreachable!("PropertyDoubleKeyHashMap::Modify::iter() is not implemented")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter_mut(&mut self) -> PropertyDoubleKeyHashMapIterMut<K1, K2, V> {
|
||||
match self {
|
||||
Self::Base(base) => PropertyDoubleKeyHashMapIterMut {
|
||||
outer_iter: base.iter_mut(),
|
||||
inner_iter: None,
|
||||
current_outer_key: None,
|
||||
},
|
||||
Self::Modify { .. } => {
|
||||
unreachable!("PropertyDoubleKeyHashMap::Modify::iter_mut() is not implemented")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dkhashmap_iter() {
|
||||
let mut map = PropertyDoubleKeyHashMap::Base(
|
||||
std::iter::once((1, [(2, 3), (4, 5)].into_iter().collect())).collect(),
|
||||
);
|
||||
let mut expecting = vec![(1, 2, 3), (1, 4, 5)];
|
||||
let iter = map.iter_mut();
|
||||
for (key1, key2, value) in iter {
|
||||
assert!(expecting.contains(&(*key1, *key2, *value)));
|
||||
expecting.retain(|x| x != &(*key1, *key2, *value));
|
||||
*value += 1;
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> OctData for PropertyHashMap<K, V>
|
||||
where
|
||||
K: OctData + Eq + Ord + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
fn marshal_to<W: std::io::Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
||||
match self {
|
||||
Self::Base(map) => {
|
||||
map.marshal_to(w, bt_property_tag)?;
|
||||
}
|
||||
Self::Modify { to_add, to_remove } => {
|
||||
let len = -(to_add.len() as i32 + to_remove.len() as i32);
|
||||
len.marshal_to(w, bt_property_tag)?;
|
||||
for (key, value) in to_add {
|
||||
key.marshal_to(w, bt_property_tag)?;
|
||||
false.marshal_to(w, bt_property_tag)?;
|
||||
value.marshal_to(w, bt_property_tag)?;
|
||||
}
|
||||
for key in to_remove {
|
||||
key.marshal_to(w, bt_property_tag)?;
|
||||
true.marshal_to(w, bt_property_tag)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: std::io::Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
||||
let len = i32::unmarshal_from(r, bt_property_tag)?;
|
||||
|
||||
if len >= 0 {
|
||||
let mut map = HashMap::with_capacity(len as usize);
|
||||
for _ in 0..len {
|
||||
map.insert(
|
||||
K::unmarshal_from(r, bt_property_tag)?,
|
||||
V::unmarshal_from(r, bt_property_tag)?,
|
||||
);
|
||||
}
|
||||
Ok(Self::Base(map))
|
||||
} else {
|
||||
let mut to_add = Vec::new();
|
||||
let mut to_remove = Vec::new();
|
||||
|
||||
for _ in 0..-len {
|
||||
let key = K::unmarshal_from(r, bt_property_tag)?;
|
||||
if !bool::unmarshal_from(r, bt_property_tag)? {
|
||||
to_add.push((key, V::unmarshal_from(r, bt_property_tag)?));
|
||||
} else {
|
||||
to_remove.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self::Modify { to_add, to_remove })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K> OctData for PropertyHashSet<K>
|
||||
where
|
||||
K: OctData + Eq + std::hash::Hash,
|
||||
{
|
||||
fn marshal_to<W: std::io::Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
||||
match self {
|
||||
Self::Base(set) => {
|
||||
set.marshal_to(w, bt_property_tag)?;
|
||||
}
|
||||
Self::Modify { to_add, to_remove } => {
|
||||
let len = -(to_add.len() as i32 + to_remove.len() as i32);
|
||||
len.marshal_to(w, bt_property_tag)?;
|
||||
for value in to_add {
|
||||
value.marshal_to(w, bt_property_tag)?;
|
||||
false.marshal_to(w, bt_property_tag)?;
|
||||
}
|
||||
for value in to_remove {
|
||||
value.marshal_to(w, bt_property_tag)?;
|
||||
true.marshal_to(w, bt_property_tag)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: std::io::Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
||||
let len = i32::unmarshal_from(r, bt_property_tag)?;
|
||||
|
||||
if len >= 0 {
|
||||
let mut set = HashSet::with_capacity(len as usize);
|
||||
for _ in 0..len {
|
||||
set.insert(K::unmarshal_from(r, bt_property_tag)?);
|
||||
}
|
||||
Ok(Self::Base(set))
|
||||
} else {
|
||||
let mut to_add = Vec::new();
|
||||
let mut to_remove = Vec::new();
|
||||
|
||||
for _ in 0..-len {
|
||||
let value = K::unmarshal_from(r, bt_property_tag)?;
|
||||
if !bool::unmarshal_from(r, bt_property_tag)? {
|
||||
to_add.push(value);
|
||||
} else {
|
||||
to_remove.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self::Modify { to_add, to_remove })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K1, K2, V> OctData for PropertyDoubleKeyHashMap<K1, K2, V>
|
||||
where
|
||||
K1: OctData + Eq + Ord + std::hash::Hash,
|
||||
K2: OctData + Eq + Ord + std::hash::Hash,
|
||||
V: OctData,
|
||||
{
|
||||
fn marshal_to<W: std::io::Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
||||
match self {
|
||||
Self::Base(map) => {
|
||||
map.marshal_to(w, bt_property_tag)?;
|
||||
}
|
||||
Self::Modify { to_add, to_remove } => {
|
||||
let len = -(to_add.len() as i32 + to_remove.len() as i32);
|
||||
len.marshal_to(w, bt_property_tag)?;
|
||||
for (key1, key2, value) in to_add {
|
||||
key1.marshal_to(w, bt_property_tag)?;
|
||||
key2.marshal_to(w, bt_property_tag)?;
|
||||
false.marshal_to(w, bt_property_tag)?;
|
||||
value.marshal_to(w, bt_property_tag)?;
|
||||
}
|
||||
for (key1, key2) in to_remove {
|
||||
key1.marshal_to(w, bt_property_tag)?;
|
||||
key2.marshal_to(w, bt_property_tag)?;
|
||||
true.marshal_to(w, bt_property_tag)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: std::io::Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
||||
let len = i32::unmarshal_from(r, bt_property_tag)?;
|
||||
if len >= 0 {
|
||||
let mut map = HashMap::new();
|
||||
for _ in 0..len {
|
||||
let key1 = K1::unmarshal_from(r, bt_property_tag)?;
|
||||
let key2 = K2::unmarshal_from(r, bt_property_tag)?;
|
||||
let value = V::unmarshal_from(r, bt_property_tag)?;
|
||||
map.entry(key1)
|
||||
.or_insert_with(HashMap::new)
|
||||
.insert(key2, value);
|
||||
}
|
||||
Ok(Self::Base(map))
|
||||
} else {
|
||||
let mut to_add = Vec::new();
|
||||
let mut to_remove = Vec::new();
|
||||
|
||||
for _ in 0..-len {
|
||||
let key1 = K1::unmarshal_from(r, bt_property_tag)?;
|
||||
let key2 = K2::unmarshal_from(r, bt_property_tag)?;
|
||||
if !bool::unmarshal_from(r, bt_property_tag)? {
|
||||
to_add.push((key1, key2, V::unmarshal_from(r, bt_property_tag)?));
|
||||
} else {
|
||||
to_remove.push((key1, key2));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self::Modify { to_add, to_remove })
|
||||
}
|
||||
}
|
||||
}
|
279
qwer/src/fastoct.rs
Normal file
279
qwer/src/fastoct.rs
Normal file
|
@ -0,0 +1,279 @@
|
|||
use std::{
|
||||
borrow::Cow,
|
||||
collections::{HashMap, HashSet},
|
||||
hash::Hash,
|
||||
io::{Read, Result, Write},
|
||||
};
|
||||
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt};
|
||||
use itertools::Itertools;
|
||||
|
||||
pub use qwer_derive::OctData;
|
||||
|
||||
use crate::DoubleKeyHashMap;
|
||||
|
||||
// LE encoded data
|
||||
pub trait OctData: Sized + Send + Sync {
|
||||
fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()>;
|
||||
|
||||
fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self>;
|
||||
}
|
||||
|
||||
impl OctData for bool {
|
||||
fn marshal_to<W: Write>(&self, w: &mut W, _: u16) -> Result<()> {
|
||||
w.write_u8(u8::from(*self))
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: Read>(r: &mut R, _: u16) -> Result<Self> {
|
||||
Ok(r.read_u8()? != 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl OctData for u8 {
|
||||
fn marshal_to<W: Write>(&self, w: &mut W, _: u16) -> Result<()> {
|
||||
w.write_u8(*self)
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: Read>(r: &mut R, _: u16) -> Result<Self> {
|
||||
r.read_u8()
|
||||
}
|
||||
}
|
||||
|
||||
impl OctData for i8 {
|
||||
fn marshal_to<W: Write>(&self, w: &mut W, _: u16) -> Result<()> {
|
||||
w.write_i8(*self)
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: Read>(r: &mut R, _: u16) -> Result<Self> {
|
||||
r.read_i8()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_primitive {
|
||||
($($t:ty, $write:ident, $read:ident,)*) => {
|
||||
$(
|
||||
impl OctData for $t {
|
||||
fn marshal_to<W: Write>(&self, w: &mut W, _: u16) -> Result<()> {
|
||||
w.$write::<byteorder::LittleEndian>(*self)
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: Read>(r: &mut R, _: u16) -> Result<Self> {
|
||||
r.$read::<byteorder::LittleEndian>()
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
impl_primitive! {
|
||||
u16, write_u16, read_u16,
|
||||
i16, write_i16, read_i16,
|
||||
u32, write_u32, read_u32,
|
||||
i32, write_i32, read_i32,
|
||||
u64, write_u64, read_u64,
|
||||
i64, write_i64, read_i64,
|
||||
}
|
||||
|
||||
// floats are a bit special, the bits are casted to an integer and then treated as an integer
|
||||
|
||||
impl OctData for f32 {
|
||||
fn marshal_to<W: Write>(&self, w: &mut W, _: u16) -> Result<()> {
|
||||
w.write_u32::<byteorder::LittleEndian>(self.to_bits())
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: Read>(r: &mut R, _: u16) -> Result<Self> {
|
||||
Ok(Self::from_bits(r.read_u32::<byteorder::LittleEndian>()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl OctData for f64 {
|
||||
fn marshal_to<W: Write>(&self, w: &mut W, _: u16) -> Result<()> {
|
||||
w.write_u64::<byteorder::LittleEndian>(self.to_bits())
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: Read>(r: &mut R, _: u16) -> Result<Self> {
|
||||
Ok(Self::from_bits(r.read_u64::<byteorder::LittleEndian>()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OctData for Vec<T>
|
||||
where
|
||||
T: OctData,
|
||||
{
|
||||
fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
||||
if self.is_empty() {
|
||||
(0i32).marshal_to(w, bt_property_tag)?;
|
||||
return Ok(());
|
||||
}
|
||||
(self.len() as i32).marshal_to(w, bt_property_tag)?;
|
||||
for item in self {
|
||||
item.marshal_to(w, bt_property_tag)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
||||
let len = i32::unmarshal_from(r, bt_property_tag)?;
|
||||
if len < 0 {
|
||||
let real_len = -len;
|
||||
let mut vec = Self::with_capacity(real_len as usize);
|
||||
for _ in 0..real_len {
|
||||
bool::unmarshal_from(r, bt_property_tag)?;
|
||||
vec.push(T::unmarshal_from(r, bt_property_tag)?);
|
||||
}
|
||||
Ok(vec)
|
||||
} else {
|
||||
let mut vec = Self::with_capacity(len as usize);
|
||||
for _ in 0..len {
|
||||
vec.push(T::unmarshal_from(r, bt_property_tag)?);
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> OctData for HashMap<K, V>
|
||||
where
|
||||
K: OctData + Eq + Hash + Ord,
|
||||
V: OctData,
|
||||
{
|
||||
default fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
||||
(self.len() as i32).marshal_to(w, bt_property_tag)?;
|
||||
for (key, value) in self.iter().sorted_by_key(|kv| kv.0) {
|
||||
key.marshal_to(w, bt_property_tag)?;
|
||||
value.marshal_to(w, bt_property_tag)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
default fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
||||
let len = i32::unmarshal_from(r, bt_property_tag)?;
|
||||
if len == -1 {
|
||||
return Ok(Self::new());
|
||||
}
|
||||
let mut map = Self::with_capacity(len as usize);
|
||||
for _ in 0..len {
|
||||
map.insert(
|
||||
K::unmarshal_from(r, bt_property_tag)?,
|
||||
V::unmarshal_from(r, bt_property_tag)?,
|
||||
);
|
||||
}
|
||||
Ok(map)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "collection")]
|
||||
impl<K1, K2, V> OctData for DoubleKeyHashMap<K1, K2, V>
|
||||
where
|
||||
K1: OctData + Eq + Hash + Ord,
|
||||
K2: OctData + Eq + Hash + Ord,
|
||||
V: OctData,
|
||||
{
|
||||
fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
||||
self.iter()
|
||||
.map(|(_, inner_map)| inner_map.len() as i32)
|
||||
.sum::<i32>()
|
||||
.marshal_to(w, bt_property_tag)?;
|
||||
for (key1, inner_map) in self {
|
||||
for (key2, value) in inner_map {
|
||||
key1.marshal_to(w, bt_property_tag)?;
|
||||
key2.marshal_to(w, bt_property_tag)?;
|
||||
value.marshal_to(w, bt_property_tag)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
||||
let len = i32::unmarshal_from(r, bt_property_tag)?;
|
||||
if len == -1 {
|
||||
return Ok(Self::new());
|
||||
}
|
||||
let mut map = Self::new();
|
||||
for _ in 0..len {
|
||||
let key1 = K1::unmarshal_from(r, bt_property_tag)?;
|
||||
let key2 = K2::unmarshal_from(r, bt_property_tag)?;
|
||||
let value = V::unmarshal_from(r, bt_property_tag)?;
|
||||
map.entry(key1)
|
||||
.or_insert_with(HashMap::new)
|
||||
.insert(key2, value);
|
||||
}
|
||||
Ok(map)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OctData for HashSet<T>
|
||||
where
|
||||
T: OctData + Eq + Hash,
|
||||
{
|
||||
fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
||||
(self.len() as i32).marshal_to(w, bt_property_tag)?;
|
||||
for item in self {
|
||||
item.marshal_to(w, bt_property_tag)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
||||
let len = i32::unmarshal_from(r, bt_property_tag)?;
|
||||
if len == -1 {
|
||||
return Ok(Self::new());
|
||||
}
|
||||
let mut set = Self::with_capacity(len as usize);
|
||||
for _ in 0..len {
|
||||
set.insert(T::unmarshal_from(r, bt_property_tag)?);
|
||||
}
|
||||
Ok(set)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OctData for Option<T>
|
||||
where
|
||||
T: OctData,
|
||||
{
|
||||
fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
||||
if let Some(item) = self {
|
||||
item.marshal_to(w, bt_property_tag)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
||||
Ok(Some(T::unmarshal_from(r, bt_property_tag)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl OctData for String {
|
||||
fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
||||
if self.is_empty() {
|
||||
(-1i32).marshal_to(w, bt_property_tag)?;
|
||||
return Ok(());
|
||||
}
|
||||
(self.len() as i32).marshal_to(w, bt_property_tag)?;
|
||||
w.write_all(self.as_bytes())
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
||||
let len = i32::unmarshal_from(r, bt_property_tag)?;
|
||||
if len == -1 {
|
||||
return Ok(Self::new());
|
||||
}
|
||||
let mut buf = vec![0; len as usize];
|
||||
r.read_exact(&mut buf)?;
|
||||
Ok(Self::from_utf8(buf).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> OctData for Cow<'a, T>
|
||||
where
|
||||
T: OctData + Clone,
|
||||
{
|
||||
fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
||||
self.as_ref().marshal_to(w, bt_property_tag)
|
||||
}
|
||||
|
||||
fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
||||
Ok(Cow::Owned(T::unmarshal_from(r, bt_property_tag)?))
|
||||
}
|
||||
}
|
16
qwer/src/lib.rs
Normal file
16
qwer/src/lib.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
#![allow(incomplete_features)]
|
||||
#![feature(specialization)]
|
||||
|
||||
#[cfg(feature = "collection")]
|
||||
mod collection;
|
||||
#[cfg(feature = "fastoct")]
|
||||
mod fastoct;
|
||||
#[cfg(feature = "protocol")]
|
||||
mod protocol;
|
||||
|
||||
#[cfg(feature = "collection")]
|
||||
pub use collection::*;
|
||||
#[cfg(feature = "fastoct")]
|
||||
pub use fastoct::*;
|
||||
#[cfg(feature = "protocol")]
|
||||
pub use protocol::*;
|
36
qwer/src/protocol.rs
Normal file
36
qwer/src/protocol.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
#[derive(Debug, Default)]
|
||||
pub struct ProtocolHeader {
|
||||
pub to_channel: u16,
|
||||
pub from_channel: u16,
|
||||
pub is_rpc_ret: bool,
|
||||
pub rpc_arg_uid: u64,
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for ProtocolHeader {
|
||||
fn from(value: Vec<u8>) -> Self {
|
||||
let to_channel = u16::from_le_bytes(value[0..2].try_into().unwrap());
|
||||
let from_channel = u16::from_le_bytes(value[2..4].try_into().unwrap());
|
||||
let is_rpc_ret = value[4] != 100;
|
||||
let rpc_arg_uid = u64::from_le_bytes(value[5..13].try_into().unwrap());
|
||||
|
||||
Self {
|
||||
to_channel,
|
||||
from_channel,
|
||||
is_rpc_ret,
|
||||
rpc_arg_uid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ProtocolHeader> for Vec<u8> {
|
||||
fn from(value: ProtocolHeader) -> Self {
|
||||
let mut out = Self::with_capacity(13);
|
||||
|
||||
out.extend(value.to_channel.to_le_bytes());
|
||||
out.extend(value.from_channel.to_le_bytes());
|
||||
out.push(if value.is_rpc_ret { 1 } else { 100 });
|
||||
out.extend(value.rpc_arg_uid.to_le_bytes());
|
||||
|
||||
out
|
||||
}
|
||||
}
|
24
sdkserver/Cargo.toml
Normal file
24
sdkserver/Cargo.toml
Normal file
|
@ -0,0 +1,24 @@
|
|||
[package]
|
||||
name = "sdkserver"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
axum.workspace = true
|
||||
axum-server.workspace = true
|
||||
encoding.workspace = true
|
||||
leb128.workspace = true
|
||||
anyhow.workspace = true
|
||||
env_logger.workspace = true
|
||||
tokio.workspace = true
|
||||
tracing.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
tokio-util.workspace = true
|
||||
ansi_term.workspace = true
|
||||
rand.workspace = true
|
||||
|
||||
[[bin]]
|
||||
name = "nap-sdkserver"
|
||||
path = "src/main.rs"
|
23
sdkserver/src/crypto.rs
Normal file
23
sdkserver/src/crypto.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
use encoding::all::UTF_16LE;
|
||||
use encoding::{EncoderTrap, Encoding};
|
||||
|
||||
pub fn encrypt_config(content: &str, key: &str) -> Vec<u8> {
|
||||
let mut content_bytes = UTF_16LE.encode(content, EncoderTrap::Strict).unwrap();
|
||||
let key_bytes = UTF_16LE.encode(key, EncoderTrap::Strict).unwrap();
|
||||
|
||||
for i in 0..content_bytes.len() {
|
||||
content_bytes[i] ^= key_bytes[i % key_bytes.len()];
|
||||
}
|
||||
|
||||
let k = key.as_bytes();
|
||||
|
||||
let mut out = Vec::with_capacity(4 + k.len() + 8 + content_bytes.len());
|
||||
|
||||
leb128::write::unsigned(&mut out, u64::try_from(k.len()).unwrap()).unwrap();
|
||||
out.extend_from_slice(k);
|
||||
out.extend([0u8; 4]);
|
||||
out.extend(u32::try_from(content_bytes.len()).unwrap().to_le_bytes());
|
||||
out.extend(content_bytes);
|
||||
|
||||
out
|
||||
}
|
38
sdkserver/src/data/config.rs
Normal file
38
sdkserver/src/data/config.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct ConfigInfo {
|
||||
pub min_version: String,
|
||||
pub latest_version: String,
|
||||
pub game_res_url: String,
|
||||
pub design_data_url: String,
|
||||
pub server_list_url: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct ConfigInfoGroup {
|
||||
pub version_info_groups: HashMap<String, ConfigInfo>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct AppConfig {
|
||||
pub info_groups: HashMap<String, ConfigInfoGroup>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ServerListInfo {
|
||||
pub sid: i32,
|
||||
pub server_name: String,
|
||||
pub ip: String,
|
||||
pub port: String,
|
||||
pub notice_region: String,
|
||||
pub protocol: String,
|
||||
#[serde(rename = "$Type")]
|
||||
ty: String,
|
||||
}
|
23
sdkserver/src/data/entry.rs
Normal file
23
sdkserver/src/data/entry.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct HttpRet<Ext> {
|
||||
pub error_code: i32,
|
||||
pub error_msg: Option<String>,
|
||||
pub ext: Ext,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct EntryTokenRet {
|
||||
pub birthday: String,
|
||||
pub country: String,
|
||||
pub token: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct EntryAccountServerRet {
|
||||
pub address: String,
|
||||
}
|
2
sdkserver/src/data/mod.rs
Normal file
2
sdkserver/src/data/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod config;
|
||||
pub mod entry;
|
71
sdkserver/src/main.rs
Normal file
71
sdkserver/src/main.rs
Normal file
|
@ -0,0 +1,71 @@
|
|||
use anyhow::Result;
|
||||
use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry};
|
||||
|
||||
use axum::{
|
||||
routing::{get, post},
|
||||
Router,
|
||||
};
|
||||
|
||||
mod crypto;
|
||||
mod data;
|
||||
mod services;
|
||||
|
||||
use services::{auth, config, entry, errors};
|
||||
|
||||
const HOST: &str = "0.0.0.0";
|
||||
const PORT: u16 = 21000;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
init_tracing()?;
|
||||
|
||||
let router = Router::new()
|
||||
.route(auth::RISKY_API_CHECK_ENDPOINT, post(auth::risky_api_check))
|
||||
.route(
|
||||
auth::LOGIN_WITH_PASSWORD_ENDPOINT,
|
||||
post(auth::login_with_password),
|
||||
)
|
||||
.route(
|
||||
auth::LOGIN_WITH_SESSION_TOKEN_ENDPOINT,
|
||||
post(auth::login_with_session_token),
|
||||
)
|
||||
.route(
|
||||
auth::GRANTER_LOGIN_VERIFICATION_ENDPOINT,
|
||||
post(auth::granter_login_verification),
|
||||
)
|
||||
.route(config::APP_CONFIG_ENDPOINT, get(config::application))
|
||||
.route(config::SERVER_LIST_ENDPOINT, get(config::server_list))
|
||||
.route(
|
||||
config::VERSIONS_BUNDLE_ENDPOINT,
|
||||
get(config::versions_bundle),
|
||||
)
|
||||
.route(entry::ACCOUNT_TOKEN_ENDPOINT, post(entry::account_token))
|
||||
.route(entry::ACCOUNT_SERVER_ENDPOINT, post(entry::account_server))
|
||||
.fallback(errors::not_found);
|
||||
|
||||
let bind_url = format!("{HOST}:{PORT}");
|
||||
let http_server = axum_server::bind(bind_url.parse()?);
|
||||
tracing::info!("SDK Server is listening at {bind_url}");
|
||||
|
||||
http_server.serve(router.into_make_service()).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn init_tracing() -> Result<()> {
|
||||
#[cfg(target_os = "windows")]
|
||||
ansi_term::enable_ansi_support().unwrap();
|
||||
|
||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
|
||||
let log_filter = EnvFilter::try_from_default_env()
|
||||
.unwrap_or_else(|_| EnvFilter::try_new("info").unwrap())
|
||||
.add_directive("sdkserver=debug".parse().unwrap());
|
||||
|
||||
tracing::subscriber::set_global_default(
|
||||
Registry::default()
|
||||
.with(log_filter)
|
||||
.with(tracing_subscriber::fmt::Layer::default()),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
84
sdkserver/src/services/auth.rs
Normal file
84
sdkserver/src/services/auth.rs
Normal file
|
@ -0,0 +1,84 @@
|
|||
use axum::Json;
|
||||
use serde_json::json;
|
||||
|
||||
pub const LOGIN_WITH_PASSWORD_ENDPOINT: &str = "/nap_global/mdk/shield/api/login";
|
||||
pub const LOGIN_WITH_SESSION_TOKEN_ENDPOINT: &str = "/nap_global/mdk/shield/api/verify";
|
||||
pub const GRANTER_LOGIN_VERIFICATION_ENDPOINT: &str = "/nap_global/combo/granter/login/v2/login";
|
||||
pub const RISKY_API_CHECK_ENDPOINT: &str = "/account/risky/api/check";
|
||||
|
||||
#[tracing::instrument]
|
||||
pub async fn login_with_password() -> Json<serde_json::Value> {
|
||||
tracing::info!("login_with_password");
|
||||
Json(json!({
|
||||
"data": {
|
||||
"account": {
|
||||
"area_code": "**",
|
||||
"email": "ReversedRooms",
|
||||
"country": "RU",
|
||||
"is_email_verify": "1",
|
||||
"token": "mostsecuretokenever",
|
||||
"uid": "1337"
|
||||
},
|
||||
"device_grant_required": false,
|
||||
"reactivate_required": false,
|
||||
"realperson_required": false,
|
||||
"safe_mobile_required": false
|
||||
},
|
||||
"message": "OK",
|
||||
"retcode": 0
|
||||
}))
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
pub async fn login_with_session_token() -> Json<serde_json::Value> {
|
||||
tracing::info!("login_with_session_token");
|
||||
Json(json!({
|
||||
"data": {
|
||||
"account": {
|
||||
"area_code": "**",
|
||||
"email": "ReversedRooms",
|
||||
"country": "RU",
|
||||
"is_email_verify": "1",
|
||||
"token": "mostsecuretokenever",
|
||||
"uid": "1337"
|
||||
},
|
||||
"device_grant_required": false,
|
||||
"reactivate_required": false,
|
||||
"realperson_required": false,
|
||||
"safe_mobile_required": false
|
||||
},
|
||||
"message": "OK",
|
||||
"retcode": 0
|
||||
}))
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
pub async fn granter_login_verification() -> Json<serde_json::Value> {
|
||||
tracing::info!("granter_login_verification");
|
||||
Json(json!({
|
||||
"data": {
|
||||
"account_type": 1,
|
||||
"combo_id": "1337",
|
||||
"combo_token": "9065ad8507d5a1991cb6fddacac5999b780bbd92",
|
||||
"data": "{\"guest\":false}",
|
||||
"heartbeat": false,
|
||||
"open_id": "1337"
|
||||
},
|
||||
"message": "OK",
|
||||
"retcode": 0
|
||||
}))
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
pub async fn risky_api_check() -> Json<serde_json::Value> {
|
||||
tracing::info!("risky_api_check");
|
||||
Json(json!({
|
||||
"data": {
|
||||
"id": "06611ed14c3131a676b19c0d34c0644b",
|
||||
"action": "ACTION_NONE",
|
||||
"geetest": null
|
||||
},
|
||||
"message": "OK",
|
||||
"retcode": 0
|
||||
}))
|
||||
}
|
63
sdkserver/src/services/config.rs
Normal file
63
sdkserver/src/services/config.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
use std::sync::LazyLock;
|
||||
|
||||
use axum::{body::Body, response::IntoResponse};
|
||||
use rand::Rng;
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
use crate::crypto;
|
||||
use crate::data::config::*;
|
||||
|
||||
pub const APP_CONFIG_ENDPOINT: &str = "/design_data/NAP_Publish_AppStore_0.1.0/oversea/config.bin";
|
||||
pub const SERVER_LIST_ENDPOINT: &str =
|
||||
"/design_data/NAP_Publish_AppStore_0.1.0/oversea/serverlist.bin";
|
||||
pub const VERSIONS_BUNDLE_ENDPOINT: &str = "/game_res/NAP_Publish/output_147608_1361f678bc/client/StandaloneWindows64/oversea/versions.bundle";
|
||||
|
||||
static APP_CONFIG: LazyLock<AppConfig> = LazyLock::new(|| read_config("config.json"));
|
||||
static SERVER_LIST: LazyLock<Vec<ServerListInfo>> =
|
||||
LazyLock::new(|| read_config("serverlist.json"));
|
||||
|
||||
static VERSIONS_BUNDLE: LazyLock<Box<[u8]>> = LazyLock::new(|| read_binary_data("versions.bundle"));
|
||||
|
||||
pub async fn application() -> Vec<u8> {
|
||||
crypto::encrypt_config(
|
||||
serde_json::to_string(&*APP_CONFIG).unwrap().as_str(),
|
||||
&random_xorpad(16),
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn server_list() -> Vec<u8> {
|
||||
crypto::encrypt_config(
|
||||
serde_json::to_string(&*SERVER_LIST).unwrap().as_str(),
|
||||
&random_xorpad(16),
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn versions_bundle() -> impl IntoResponse {
|
||||
Body::from(&**VERSIONS_BUNDLE)
|
||||
}
|
||||
|
||||
fn read_config<T>(file: &str) -> T
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
let data = std::fs::read_to_string(format!("assets/Application/{file}")).unwrap();
|
||||
serde_json::from_str::<T>(&data).unwrap()
|
||||
}
|
||||
|
||||
fn read_binary_data(file: &str) -> Box<[u8]> {
|
||||
std::fs::read(format!("assets/Application/{file}"))
|
||||
.unwrap()
|
||||
.into()
|
||||
}
|
||||
|
||||
fn random_xorpad(len: usize) -> String {
|
||||
const CHARSET: &[u8] = b"0123456789";
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
(0..len)
|
||||
.map(|_| {
|
||||
let idx = rng.gen_range(0..CHARSET.len());
|
||||
CHARSET[idx] as char
|
||||
})
|
||||
.collect()
|
||||
}
|
33
sdkserver/src/services/entry.rs
Normal file
33
sdkserver/src/services/entry.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
use crate::data::entry::*;
|
||||
use axum::Json;
|
||||
|
||||
pub const ACCOUNT_TOKEN_ENDPOINT: &str = "/account/token";
|
||||
pub const ACCOUNT_SERVER_ENDPOINT: &str = "/account/account_server";
|
||||
|
||||
#[tracing::instrument]
|
||||
pub async fn account_token() -> Json<HttpRet<EntryTokenRet>> {
|
||||
tracing::info!("account_token");
|
||||
|
||||
Json(HttpRet {
|
||||
error_code: 0,
|
||||
error_msg: None,
|
||||
ext: EntryTokenRet {
|
||||
birthday: String::from("01.01"),
|
||||
country: String::from("RU"),
|
||||
token: String::from("MostSecureTokenEver"),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
pub async fn account_server() -> Json<HttpRet<EntryAccountServerRet>> {
|
||||
tracing::info!("account_server");
|
||||
|
||||
Json(HttpRet {
|
||||
error_code: 0,
|
||||
error_msg: None,
|
||||
ext: EntryAccountServerRet {
|
||||
address: String::from("127.0.0.1:10301/0"),
|
||||
},
|
||||
})
|
||||
}
|
7
sdkserver/src/services/errors.rs
Normal file
7
sdkserver/src/services/errors.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
use axum::http::{StatusCode, Uri};
|
||||
use axum::response::IntoResponse;
|
||||
|
||||
pub async fn not_found(uri: Uri) -> impl IntoResponse {
|
||||
tracing::warn!("unhandled http request: {uri}");
|
||||
StatusCode::NOT_FOUND
|
||||
}
|
4
sdkserver/src/services/mod.rs
Normal file
4
sdkserver/src/services/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
pub mod auth;
|
||||
pub mod config;
|
||||
pub mod entry;
|
||||
pub mod errors;
|
Loading…
Reference in a new issue