KPD

Kogama Packet Decoder

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/441869/1034053/KPD.js

  1. // ==UserScript==
  2. // @name KPD
  3. // @license MIT
  4. // @version 1.1
  5. // @description Kogama Packet Decoder
  6. // @author 0vC4
  7. // @namespace https://greasyfork.org/users/670183
  8. // @match http://*/*
  9. // @match https://*/*
  10. // @grant none
  11. // @run-at document-start
  12. // ==/UserScript==
  13.  
  14.  
  15.  
  16.  
  17.  
  18. const KPD = (() => {
  19. const code2type = code => Object.fromEntries(Object.entries(code).map(a=>a.reverse()));
  20.  
  21. const PhotonCode = {ClientKey:1,ModeKey:2,ServerKey:1,InitEncryption:0,Ping:1,Ok:0};
  22. const MVOpCode = {RegisterWorldObject:0,UnregisterWorldObject:1,UpdateWorldObject:2,UpdateWorldObjectData:3,UpdateWorldObjectDataPartial:4,RemoveWorldObjectDataPartial:5,TransferOwnership:6,UpdatePrototype:7,UpdatePrototypeScale:8,AddLink:9,RemoveLink:10,PublishPlanet:11,AddPrototypeToInventory:12,RemoveItemFromInventory:13,UpdateInventorySlots:14,RequestFriendshipByProfileId:15,RequestAcceptFriendship:16,RequestRejectFriendship:17,TriggerBoxEnter:18,TriggerBoxExit:19,LockHierarchy:20,UploadScreenshot:21,RequestWoUniquePrototype:22,ReportCaptureFlag:23,ResetLogicChunk:24,UpdateWorldObjectRunTimeData:25,UpdateLineOfFire:26,WorldObjectRPCOperation:27,PostGameMsg:28,SetTeam:29,AddObjectLink:30,RemoveObjectLink:31,TransferWorldObjectsToGroup:32,CloneWorldObjectTree:33,AddPlanetToPlanet:34,PurchaseProduct:35,GetNextGameBatch:36,RequestBuiltInItem:37,AddItemToWorld:38,AddWorldObjectToInventory:39,AddWorldObjectToInventoryDev:40,SetActiveAvatar:41,ResetAvatar:42,GetMarketPlaceItem:43,AddItemToMarketPlace:44,RemoveItemFromMarketPlace:45,SetAvatarAccessorySlot:46,AttachWorldObjectToSeat:47,DetachWorldObjectFromVehicle:48,SpawnVehicleWithDriver:49,ClientLog:50,UpdateAvatarAccessoryOffset:51,RuntimeEvent:52,ResetTerrain:53,AddAvatarToAvatarShopInventory:54,DeleteAvatarFromShopInventory:55,LevelChanged:56,Ban:57,Syncronize:58,SwitchAvatar:59,SyncronizePing:60,JoinNotification:61,UploadBytes:62,Notification:63,CloneWorldObjectTreeWithPosition:64,CloneTempWorldObjectWithOriginalReference:65,LogicActivateRequest:66,AdminOperation:67,OwnerOperation:68,ResetFirstTimeEvents:83,SetFirstTimeEvent:84,OverrideFirstTimeEvent:85,GetResetAvatar:86,ClaimPlayingNewGameRewardedGold:87,PostChatMsg:88,SetSayChatBubbleVisible:93,ReportReachedTimeAttackFlag:94,RequestAccessoryData:95,UnEquipAccessory:96,SetHighlightToSeen:97,ResetHighlights:98,UpdateAvatarAccessoryScale:99,GetThemesData:100,SetMouseSensitivity:101,StartSessionTime:102,ResetPlayerPlanetData:103,GetHighScoreList:104,SetGamePassTierOperation:105,SetGamePassTierToSeenOperation:106,SetEarningsReportToSeenOperation:107,GetTopHighScoreList:108,ClaimGamePointWelcomeReward:109,UpdateGold:110,SetActiveSpawnRole:111,CustomDevCommands:112,CreateSpawnRole:113,GetAvatarBodies:114,SetSpawnRoleBody:115,TogglePreviewTierOperation:116,ClaimRewardedAdXP:117,IncrementStatRequest:118,Undefined:119,Join:255,Leave:254,RaiseEvent:253,SetProperties:252,GetProperties:251,Ping:249};
  23. const MVECode = {NoCodeSet:0,UnregisterWorldObject:1,UpdateWorldObject:2,UpdateWorldObjectData:3,UpdateWorldObjectDataPartial:4,RemoveWorldObjectDataPartial:5,TransferOwnership:6,UpdateNetworkInput:7,RegisterPrototype:8,UnregisterPrototype:9,UpdatePrototype:10,UpdatePrototypeScale:11,UpdateTerrain:12,AddLink:13,RemoveLink:14,RemoveItemFromInventory:15,FriendRequest:16,FriendUpdate:17,TriggerBoxEnter:18,TriggerBoxExit:19,TriggerBoxStayBegin:20,TriggerBoxStayEnd:21,Clone:22,LockHierarchy:23,BlueprintCreationDone:24,WoUniquePrototype:25,GameStateChange:26,SyncAvatarStatus:27,ResetLogicChunk:28,UpdateWorldObjectRunTimeData:29,PickupItemStateChange:30,UpdateLineOfFire:31,WorldObjectRPCEvent:32,XPReceivedEvent:33,PostGameMsgEvent:34,SetTeam:35,AddObjectLink:36,RemoveObjectLink:37,TransferWorldObjectsToGroup:38,CloneWorldObjectTree:39,GetGameBatch:40,GameQueryReady:41,PostWinnerReport:42,CollectiblePickedUp:43,SetWorldObjectsToPurchasedEvent:44,AchievementUnlockedEvent:45,AttachWorldObjectToSeat:46,DetachWorldObjectFromVehicle:47,SpawnVehicleWithDriver:48,Reward:49,RuntimeEvent:50,ResetTerrainEvent:51,UpdateGameStat:52,UpdateGameStatType:53,UpdateAvatarMetaData:54,LevelChanged:55,GameBoostEvent:56,NotificationEvent:57,RequestMaterials:58,GetPlanetOwnershipTypes:59,GetItemCategories:60,SetupUserPlayMode:61,GameSnapshotData:62,SetActorReady:63,RequestFriends:64,GetItemInventory:65,GetItemShopInventory:66,GetBuiltInItemBusinessData:67,LargeDBQueryAvatarShopInventory:68,InitializeAvatarEdit:69,GetActiveAvatar:70,PendingByteDataBatch:71,SwitchAvatar:72,SyncronizePing:73,StartRewardCountDown:74,RewardIsReady:75,NumberOfPendingRewards:76,JoinNotification:77,CloneWorldObjectTreeWithPosition:78,CloneTempWorldObjectWithOriginalReferenceEvent:79,LogicObjectFiringStateChange:80,LogicFrame:81,CollectTheItemDropOff:82,LogicFastForward:83,LogicFastForwardEventImmediate:84,ForceDetachWorldObjectFromVehicle:85,XPReward:86,GetProfileMetaData:87,ServerError:88,SetSayChatBubbleVisible:89,GetPublishedPlanetProfileData:90,PlayerPlanetData:91,PlayerPlanetRemote:92,HighScores:93,GoldRewardedForLevel:94,NextLevelGoldReward:95,PlayerTierStateCalculatorChanged:96,GetProjectEarnings:97,TopHighScores:98,GetKogamaVat:99,GetSubscriptionPerksData:100,SetupUserAvatarEdit:101,SetupUserBuildMode:102,SetActiveSpawnRole:103,ReplicateSpawnRoleData:104,SetSpawnRoleBody:105,XPRewardedAdReady:106,Join:255,Leave:254,PropertiesChanged:253};
  24. const GpCode = {
  25. Unknown: 0,
  26. Null: 42,
  27. Dictionary: 68,
  28. StringArray: 97,
  29. Byte: 98,
  30. Custom: 99,
  31. Double: 100,
  32. EventData: 101,
  33. Float: 102,
  34. Hashtable: 104,
  35. Integer: 105,
  36. Short: 107,
  37. Long: 108,
  38. IntegerArray: 110,
  39. Boolean: 111,
  40. OperationResponse: 112,
  41. OperationRequest: 113,
  42. String: 115,
  43. ByteArray: 120,
  44. Array: 121,
  45. ObjectArray: 122
  46. };
  47.  
  48. const GpType = code2type(GpCode);
  49. const MVEType = code2type(MVECode);
  50. const MVOpType = code2type(MVOpCode);
  51. const PhotonType = code2type(PhotonCode);
  52.  
  53.  
  54.  
  55.  
  56.  
  57. const take = arr => new DataView(Uint8Array.from(arr).buffer);
  58. const put = (num, typed) => [...new Uint8Array(typed.of(num).buffer).reverse()];
  59. const GpValue = {
  60. get: {
  61. Unknown: arr => ({Type: GpType[arr.shift()], Value: null}),
  62. Null: arr => ({Type: GpType[arr.shift()], Value: null}),
  63. Dictionary: arr => {
  64. let Type = GpType[arr.shift()];
  65. let TKey = GpType[arr.shift()];
  66. let TValue = GpType[arr.shift()];
  67. let Size = take(arr.splice(0,2)).getInt16();
  68. let Value = [];
  69.  
  70. let i = 0;
  71. while (i++ < Size) {
  72. if (!(TKey == "Unknown" || TKey == "Null")) arr.unshift(GpCode[TKey]);
  73. let key = GpValue.get[GpType[arr[0]]](arr);
  74.  
  75. if (!(TValue == "Unknown" || TValue == "Null")) arr.unshift(GpCode[TValue]);
  76. let value = GpValue.get[GpType[arr[0]]](arr);
  77.  
  78. Value.push([key, value]);
  79. }
  80.  
  81. return {Type, TKey, TValue, Size, Value,
  82. get (key) {
  83. let slot = this.Value.find(s=>s[0].Value == key);
  84. if (slot) return slot[1];
  85. return null;
  86. },
  87. keys () {
  88. return this.Value.map(s=>s[0].Value);
  89. },
  90. set (key, value) {
  91. let slot = this.Value.find(s=>s[0].Value == key.Value);
  92. if (slot) slot[1] = value;
  93. else this.Value.push([key, value]);
  94. }
  95. };
  96. },
  97. StringArray: arr => {
  98. /*
  99. let Type = GpType[arr.shift()];
  100. let Size = take(arr.splice(0,2)).getInt16();
  101. let Value = [];
  102.  
  103. let i = 0;
  104. while (i++ < Size) {
  105. let value = GpValue.get[arr[0]](arr);
  106. Value.push(value);
  107. }
  108.  
  109. return {Type, Size, Value};
  110. */
  111. console.log(GpType[arr[0]], arr.slice(0));
  112. },
  113. Byte: arr => ({Type: GpType[arr.shift()], Value: take(arr.splice(0,1)).getUint8()}),
  114. Custom: arr => {
  115. /*
  116. let Type = GpType[arr.shift()];
  117. let Size = take(arr.splice(0,2)).getInt16();
  118. let Value = [];
  119.  
  120. let i = 0;
  121. while (i++ < Size) {
  122. let value = GpValue.get[arr[0]](arr);
  123. Value.push(value);
  124. }
  125.  
  126. return {Type, Size, Value};
  127. */
  128. console.log(GpType[arr[0]], arr.slice(0));
  129. },
  130. Double: arr => ({Type: GpType[arr.shift()], Value: take(arr.splice(0,8)).getFloat64()}),
  131. EventData: arr => {
  132. /*
  133. let Type = GpType[arr.shift()];
  134. let Size = take(arr.splice(0,2)).getInt16();
  135. let Value = [];
  136.  
  137. let i = 0;
  138. while (i++ < Size) {
  139. let value = GpValue.get[arr[0]](arr);
  140. Value.push(value);
  141. }
  142.  
  143. return {Type, Size, Value};
  144. */
  145. console.log(GpType[arr[0]], arr.slice(0));
  146. },
  147. Float: arr => ({Type: GpType[arr.shift()], Value: take(arr.splice(0,4)).getFloat32()}),
  148. Hashtable: arr => {
  149. let Type = GpType[arr.shift()];
  150. let Size = take(arr.splice(0,2)).getInt16();
  151. let Value = [];
  152.  
  153. let i = 0;
  154. while (i++ < Size) {
  155. let key = GpValue.get[GpType[arr[0]]](arr);
  156. let value = GpValue.get[GpType[arr[0]]](arr);
  157. Value.push([key,value]);
  158. }
  159.  
  160. return {Type, Size, Value};
  161. },
  162. Integer: arr => ({Type: GpType[arr.shift()], Value: take(arr.splice(0,4)).getInt32()}),
  163. Short: arr => ({Type: GpType[arr.shift()], Value: take(arr.splice(0,2)).getInt16()}),
  164. Long: arr => ({Type: GpType[arr.shift()], Value: take(arr.splice(0,8)).getBigInt64()}),
  165. IntegerArray: arr => {
  166. /*
  167. let Type = GpType[arr.shift()];
  168. let Size = take(arr.splice(0,2)).getInt16();
  169. let Value = [];
  170.  
  171. let i = 0;
  172. while (i++ < Size) {
  173. let value = GpValue.get[arr[0]](arr);
  174. Value.push(value);
  175. }
  176.  
  177. return {Type, Size, Value};
  178. */
  179. console.log(GpType[arr[0]], arr.slice(0));
  180. },
  181. Boolean: arr => ({Type: GpType[arr.shift()], Value: take(arr.splice(0,1)).getUint8() > 0}),
  182. OperationResponse: arr => {
  183. /*
  184. let Type = GpType[arr.shift()];
  185. let Size = take(arr.splice(0,2)).getInt16();
  186. let Value = [];
  187.  
  188. let i = 0;
  189. while (i++ < Size) {
  190. let value = GpValue.get[arr[0]](arr);
  191. Value.push(value);
  192. }
  193.  
  194. return {Type, Size, Value};
  195. */
  196. console.log(GpType[arr[0]], arr.slice(0));
  197. },
  198. OperationRequest: arr => {
  199. /*
  200. let Type = GpType[arr.shift()];
  201. let Size = take(arr.splice(0,2)).getInt16();
  202. let Value = [];
  203.  
  204. let i = 0;
  205. while (i++ < Size) {
  206. let value = GpValue.get[arr[0]](arr);
  207. Value.push(value);
  208. }
  209.  
  210. return {Type, Size, Value};
  211. */
  212. console.log(GpType[arr[0]], arr.slice(0));
  213. },
  214. String: arr => {
  215. let Type = GpType[arr.shift()];
  216. let Size = take(arr.splice(0,2)).getInt16();
  217. let Value = new TextDecoder().decode(Uint8Array.from(arr.splice(0, Size)));
  218. return {Type, Size, Value};
  219. },
  220. ByteArray: arr => {
  221. let Type = GpType[arr.shift()];
  222. let Size = take(arr.splice(0,4)).getInt32();
  223. let Value = Uint8Array.from(arr.splice(0, Size));
  224. return {Type, Size, Value};
  225. },
  226. Array: arr => {
  227. let Type = GpType[arr.shift()];
  228. let Size = take(arr.splice(0,2)).getInt16();
  229. let TValue = GpType[arr.shift()];
  230. let Value = [];
  231.  
  232. let i = 0;
  233. while (i++ < Size) {
  234. arr.unshift(GpCode[TValue]);
  235. let value = GpValue.get[GpType[arr[0]]](arr);
  236. Value.push(value);
  237. }
  238.  
  239. return {Type, Size, TValue, Value};
  240. },
  241. ObjectArray: arr => {
  242. /*
  243. let Type = GpType[arr.shift()];
  244. let Size = take(arr.splice(0,2)).getInt16();
  245. let Value = [];
  246.  
  247. let i = 0;
  248. while (i++ < Size) {
  249. let value = GpValue.get[arr[0]](arr);
  250. Value.push(value);
  251. }
  252.  
  253. return {Type, Size, Value};
  254. */
  255. console.log(GpType[arr[0]], arr.slice(0));
  256. }
  257. },
  258.  
  259.  
  260.  
  261. set: {
  262. Unknown: data => [GpCode[data.Type]],
  263. Null: data => [GpCode[data.Type]],
  264. Dictionary: data => {
  265. let arr = [GpCode[data.Type], GpCode[data.TKey], GpCode[data.TValue], ...put(data.Size, Int16Array)];
  266.  
  267. for (let slot of data.Value) {
  268. let key = GpValue.set[slot[0].Type](slot[0]);
  269. if (!(data.TKey == "Unknown" || data.TKey == "Null")) key.splice(0,1);
  270.  
  271. let value = GpValue.set[slot[1].Type](slot[1]);
  272. if (!(data.TValue == "Unknown" || data.TValue == "Null")) value.splice(0,1);
  273.  
  274. arr.push(...key, ...value);
  275. }
  276.  
  277. return arr;
  278. },
  279. StringArray: data => [GpCode[data.Type]],
  280. Byte: data => [GpCode[data.Type], ...put(data.Value, Uint8Array)],
  281. Custom: data => [GpCode[data.Type]],
  282. Double: data => [GpCode[data.Type], ...put(data.Value, Float64Array)],
  283. EventData: data => [GpCode[data.Type]],
  284. Float: data => [GpCode[data.Type], ...put(data.Value, Float32Array)],
  285. Hashtable: data => {
  286. let arr = [GpCode[data.Type], ...put(data.Size, Int16Array)];
  287.  
  288. for (let slot of data.Value) {
  289. let key = GpValue.set[slot[0].Type](slot[0]);
  290. let value = GpValue.set[slot[1].Type](slot[1]);
  291. arr.push(...key,...value);
  292. }
  293.  
  294. return arr;
  295. },
  296. Integer: data => [GpCode[data.Type], ...put(data.Value, Int32Array)],
  297. Short: data => [GpCode[data.Type], ...put(data.Value, Int16Array)],
  298. Long: data => [GpCode[data.Type], ...put(data.Value, BigInt64Array)],
  299. IntegerArray: data => [GpCode[data.Type]],
  300. Boolean: data => [GpCode[data.Type], ...put(data.Value > 0, Uint8Array)],
  301. OperationResponse: data => [GpCode[data.Type]],
  302. OperationRequest: data => [GpCode[data.Type]],
  303. String: data => [GpCode[data.Type], ...put(data.Size, Int16Array), ...new TextEncoder().encode(data.Value)],
  304. ByteArray: data => [GpCode[data.Type], ...put(data.Size, Int32Array), ...data.Value],
  305. Array: data => {
  306. let arr = [GpCode[data.Type], ...put(data.Size, Int16Array), GpCode[data.TValue]];
  307.  
  308. for (let value of data.Value) {
  309. arr.push(...GpValue.set[value.Type](value).slice(1));
  310. }
  311.  
  312. return arr;
  313. },
  314. ObjectArray: data => [GpCode[data.Type]]
  315. }
  316. };
  317.  
  318.  
  319.  
  320.  
  321.  
  322. const typeOf = packet => {
  323. const MagicNumber = packet[0];
  324. if (MagicNumber == 0xF0) return "Ping";
  325. const flag = packet[1]&127;
  326. const code = packet[2];
  327. if (flag == 7 && code == PhotonCode.Ping) return "Ping";
  328.  
  329. return {
  330. 1: "Connected",
  331. 2: MVOpType[code],
  332. 3: MVOpType[code],
  333. 4: MVEType[code],
  334. 6: "Ping",
  335. 7: MVOpType[code],
  336. 8: "UnknownMessage",
  337. 9: "Unknown"
  338. }[flag] || "Unknown";
  339. };
  340.  
  341.  
  342.  
  343.  
  344.  
  345. const getParams = packet => {
  346. const data = {};
  347.  
  348. const size = take(packet.splice(0,2)).getInt16();
  349. let i = 0;
  350.  
  351. while (i < size) {
  352. data[packet.shift()] = GpValue.get[GpType[packet[0]]](packet);
  353. i++;
  354. }
  355.  
  356. return data;
  357. };
  358. const decode = packet => {
  359. const type = typeOf(packet);
  360. if (type == "Ping" || type == "Unknown" || type == "Connected") return null;
  361.  
  362. const flag = packet[1]&127;
  363. if (flag != 1 && (packet[1]&128) > 0) return null; //need decrypt message
  364.  
  365. const data = {};
  366. data.magicNumber = packet.shift();
  367. data.flag = packet.shift();
  368. if (flag == 8) {
  369. data.message = GpValue.get[GpType[packet[0]]](packet);
  370. return data;
  371. }
  372.  
  373. data.opCode = (flag == 4 ? MVEType : MVOpType)[packet.shift()];
  374. if (flag == 3 || flag == 7) {
  375. data.returnCode = take(packet.splice(0,2)).getInt16();
  376. data.debugMessage = GpValue.get[GpType[packet[0]]](packet);
  377. }
  378. data.params = getParams(packet);
  379.  
  380. return data;
  381. };
  382.  
  383.  
  384.  
  385.  
  386.  
  387. const setParams = data => {
  388. const packet = [];
  389.  
  390. packet.push(...put(Object.keys(data.params).length, Int16Array));
  391.  
  392. for (const slot in data.params) {
  393. const value = data.params[slot];
  394. packet.push(+slot, ...GpValue.set[value.Type](value));
  395. }
  396.  
  397. return packet;
  398. };
  399. const encode = data => {
  400. if (typeof data == null) return null;
  401. if (typeof data !== 'object') return [...data];
  402.  
  403. const packet = [];
  404. packet.push(data.magicNumber, data.flag);
  405.  
  406. const flag = data.flag&127;
  407. if (flag == 8) {
  408. packet.push(...GpValue.set[data.message.Type](data.message));
  409. return packet;
  410. }
  411.  
  412. packet.push((flag == 4 ? MVECode : MVOpCode)[data.opCode]);
  413. if (flag == 3 || flag == 7) {
  414. packet.push(...put(data.returnCode, Int16Array));
  415. packet.push(...GpValue.set[data.debugMessage.Type](data.debugMessage));
  416. }
  417. packet.push(...setParams(data));
  418.  
  419. return packet;
  420. };
  421.  
  422.  
  423.  
  424.  
  425.  
  426. return {
  427. typeOf,
  428. decode,
  429. encode
  430. };
  431. })();
  432. // 0vC4#7152