您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Kogama Packet Decoder
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/441869/1034053/KPD.js
// ==UserScript== // @name KPD // @license MIT // @version 1.1 // @description Kogama Packet Decoder // @author 0vC4 // @namespace http://greasyfork.icu/users/670183 // @match http://*/* // @match https://*/* // @grant none // @run-at document-start // ==/UserScript== const KPD = (() => { const code2type = code => Object.fromEntries(Object.entries(code).map(a=>a.reverse())); const PhotonCode = {ClientKey:1,ModeKey:2,ServerKey:1,InitEncryption:0,Ping:1,Ok:0}; 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}; 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}; const GpCode = { Unknown: 0, Null: 42, Dictionary: 68, StringArray: 97, Byte: 98, Custom: 99, Double: 100, EventData: 101, Float: 102, Hashtable: 104, Integer: 105, Short: 107, Long: 108, IntegerArray: 110, Boolean: 111, OperationResponse: 112, OperationRequest: 113, String: 115, ByteArray: 120, Array: 121, ObjectArray: 122 }; const GpType = code2type(GpCode); const MVEType = code2type(MVECode); const MVOpType = code2type(MVOpCode); const PhotonType = code2type(PhotonCode); const take = arr => new DataView(Uint8Array.from(arr).buffer); const put = (num, typed) => [...new Uint8Array(typed.of(num).buffer).reverse()]; const GpValue = { get: { Unknown: arr => ({Type: GpType[arr.shift()], Value: null}), Null: arr => ({Type: GpType[arr.shift()], Value: null}), Dictionary: arr => { let Type = GpType[arr.shift()]; let TKey = GpType[arr.shift()]; let TValue = GpType[arr.shift()]; let Size = take(arr.splice(0,2)).getInt16(); let Value = []; let i = 0; while (i++ < Size) { if (!(TKey == "Unknown" || TKey == "Null")) arr.unshift(GpCode[TKey]); let key = GpValue.get[GpType[arr[0]]](arr); if (!(TValue == "Unknown" || TValue == "Null")) arr.unshift(GpCode[TValue]); let value = GpValue.get[GpType[arr[0]]](arr); Value.push([key, value]); } return {Type, TKey, TValue, Size, Value, get (key) { let slot = this.Value.find(s=>s[0].Value == key); if (slot) return slot[1]; return null; }, keys () { return this.Value.map(s=>s[0].Value); }, set (key, value) { let slot = this.Value.find(s=>s[0].Value == key.Value); if (slot) slot[1] = value; else this.Value.push([key, value]); } }; }, StringArray: arr => { /* let Type = GpType[arr.shift()]; let Size = take(arr.splice(0,2)).getInt16(); let Value = []; let i = 0; while (i++ < Size) { let value = GpValue.get[arr[0]](arr); Value.push(value); } return {Type, Size, Value}; */ console.log(GpType[arr[0]], arr.slice(0)); }, Byte: arr => ({Type: GpType[arr.shift()], Value: take(arr.splice(0,1)).getUint8()}), Custom: arr => { /* let Type = GpType[arr.shift()]; let Size = take(arr.splice(0,2)).getInt16(); let Value = []; let i = 0; while (i++ < Size) { let value = GpValue.get[arr[0]](arr); Value.push(value); } return {Type, Size, Value}; */ console.log(GpType[arr[0]], arr.slice(0)); }, Double: arr => ({Type: GpType[arr.shift()], Value: take(arr.splice(0,8)).getFloat64()}), EventData: arr => { /* let Type = GpType[arr.shift()]; let Size = take(arr.splice(0,2)).getInt16(); let Value = []; let i = 0; while (i++ < Size) { let value = GpValue.get[arr[0]](arr); Value.push(value); } return {Type, Size, Value}; */ console.log(GpType[arr[0]], arr.slice(0)); }, Float: arr => ({Type: GpType[arr.shift()], Value: take(arr.splice(0,4)).getFloat32()}), Hashtable: arr => { let Type = GpType[arr.shift()]; let Size = take(arr.splice(0,2)).getInt16(); let Value = []; let i = 0; while (i++ < Size) { let key = GpValue.get[GpType[arr[0]]](arr); let value = GpValue.get[GpType[arr[0]]](arr); Value.push([key,value]); } return {Type, Size, Value}; }, Integer: arr => ({Type: GpType[arr.shift()], Value: take(arr.splice(0,4)).getInt32()}), Short: arr => ({Type: GpType[arr.shift()], Value: take(arr.splice(0,2)).getInt16()}), Long: arr => ({Type: GpType[arr.shift()], Value: take(arr.splice(0,8)).getBigInt64()}), IntegerArray: arr => { /* let Type = GpType[arr.shift()]; let Size = take(arr.splice(0,2)).getInt16(); let Value = []; let i = 0; while (i++ < Size) { let value = GpValue.get[arr[0]](arr); Value.push(value); } return {Type, Size, Value}; */ console.log(GpType[arr[0]], arr.slice(0)); }, Boolean: arr => ({Type: GpType[arr.shift()], Value: take(arr.splice(0,1)).getUint8() > 0}), OperationResponse: arr => { /* let Type = GpType[arr.shift()]; let Size = take(arr.splice(0,2)).getInt16(); let Value = []; let i = 0; while (i++ < Size) { let value = GpValue.get[arr[0]](arr); Value.push(value); } return {Type, Size, Value}; */ console.log(GpType[arr[0]], arr.slice(0)); }, OperationRequest: arr => { /* let Type = GpType[arr.shift()]; let Size = take(arr.splice(0,2)).getInt16(); let Value = []; let i = 0; while (i++ < Size) { let value = GpValue.get[arr[0]](arr); Value.push(value); } return {Type, Size, Value}; */ console.log(GpType[arr[0]], arr.slice(0)); }, String: arr => { let Type = GpType[arr.shift()]; let Size = take(arr.splice(0,2)).getInt16(); let Value = new TextDecoder().decode(Uint8Array.from(arr.splice(0, Size))); return {Type, Size, Value}; }, ByteArray: arr => { let Type = GpType[arr.shift()]; let Size = take(arr.splice(0,4)).getInt32(); let Value = Uint8Array.from(arr.splice(0, Size)); return {Type, Size, Value}; }, Array: arr => { let Type = GpType[arr.shift()]; let Size = take(arr.splice(0,2)).getInt16(); let TValue = GpType[arr.shift()]; let Value = []; let i = 0; while (i++ < Size) { arr.unshift(GpCode[TValue]); let value = GpValue.get[GpType[arr[0]]](arr); Value.push(value); } return {Type, Size, TValue, Value}; }, ObjectArray: arr => { /* let Type = GpType[arr.shift()]; let Size = take(arr.splice(0,2)).getInt16(); let Value = []; let i = 0; while (i++ < Size) { let value = GpValue.get[arr[0]](arr); Value.push(value); } return {Type, Size, Value}; */ console.log(GpType[arr[0]], arr.slice(0)); } }, set: { Unknown: data => [GpCode[data.Type]], Null: data => [GpCode[data.Type]], Dictionary: data => { let arr = [GpCode[data.Type], GpCode[data.TKey], GpCode[data.TValue], ...put(data.Size, Int16Array)]; for (let slot of data.Value) { let key = GpValue.set[slot[0].Type](slot[0]); if (!(data.TKey == "Unknown" || data.TKey == "Null")) key.splice(0,1); let value = GpValue.set[slot[1].Type](slot[1]); if (!(data.TValue == "Unknown" || data.TValue == "Null")) value.splice(0,1); arr.push(...key, ...value); } return arr; }, StringArray: data => [GpCode[data.Type]], Byte: data => [GpCode[data.Type], ...put(data.Value, Uint8Array)], Custom: data => [GpCode[data.Type]], Double: data => [GpCode[data.Type], ...put(data.Value, Float64Array)], EventData: data => [GpCode[data.Type]], Float: data => [GpCode[data.Type], ...put(data.Value, Float32Array)], Hashtable: data => { let arr = [GpCode[data.Type], ...put(data.Size, Int16Array)]; for (let slot of data.Value) { let key = GpValue.set[slot[0].Type](slot[0]); let value = GpValue.set[slot[1].Type](slot[1]); arr.push(...key,...value); } return arr; }, Integer: data => [GpCode[data.Type], ...put(data.Value, Int32Array)], Short: data => [GpCode[data.Type], ...put(data.Value, Int16Array)], Long: data => [GpCode[data.Type], ...put(data.Value, BigInt64Array)], IntegerArray: data => [GpCode[data.Type]], Boolean: data => [GpCode[data.Type], ...put(data.Value > 0, Uint8Array)], OperationResponse: data => [GpCode[data.Type]], OperationRequest: data => [GpCode[data.Type]], String: data => [GpCode[data.Type], ...put(data.Size, Int16Array), ...new TextEncoder().encode(data.Value)], ByteArray: data => [GpCode[data.Type], ...put(data.Size, Int32Array), ...data.Value], Array: data => { let arr = [GpCode[data.Type], ...put(data.Size, Int16Array), GpCode[data.TValue]]; for (let value of data.Value) { arr.push(...GpValue.set[value.Type](value).slice(1)); } return arr; }, ObjectArray: data => [GpCode[data.Type]] } }; const typeOf = packet => { const MagicNumber = packet[0]; if (MagicNumber == 0xF0) return "Ping"; const flag = packet[1]&127; const code = packet[2]; if (flag == 7 && code == PhotonCode.Ping) return "Ping"; return { 1: "Connected", 2: MVOpType[code], 3: MVOpType[code], 4: MVEType[code], 6: "Ping", 7: MVOpType[code], 8: "UnknownMessage", 9: "Unknown" }[flag] || "Unknown"; }; const getParams = packet => { const data = {}; const size = take(packet.splice(0,2)).getInt16(); let i = 0; while (i < size) { data[packet.shift()] = GpValue.get[GpType[packet[0]]](packet); i++; } return data; }; const decode = packet => { const type = typeOf(packet); if (type == "Ping" || type == "Unknown" || type == "Connected") return null; const flag = packet[1]&127; if (flag != 1 && (packet[1]&128) > 0) return null; //need decrypt message const data = {}; data.magicNumber = packet.shift(); data.flag = packet.shift(); if (flag == 8) { data.message = GpValue.get[GpType[packet[0]]](packet); return data; } data.opCode = (flag == 4 ? MVEType : MVOpType)[packet.shift()]; if (flag == 3 || flag == 7) { data.returnCode = take(packet.splice(0,2)).getInt16(); data.debugMessage = GpValue.get[GpType[packet[0]]](packet); } data.params = getParams(packet); return data; }; const setParams = data => { const packet = []; packet.push(...put(Object.keys(data.params).length, Int16Array)); for (const slot in data.params) { const value = data.params[slot]; packet.push(+slot, ...GpValue.set[value.Type](value)); } return packet; }; const encode = data => { if (typeof data == null) return null; if (typeof data !== 'object') return [...data]; const packet = []; packet.push(data.magicNumber, data.flag); const flag = data.flag&127; if (flag == 8) { packet.push(...GpValue.set[data.message.Type](data.message)); return packet; } packet.push((flag == 4 ? MVECode : MVOpCode)[data.opCode]); if (flag == 3 || flag == 7) { packet.push(...put(data.returnCode, Int16Array)); packet.push(...GpValue.set[data.debugMessage.Type](data.debugMessage)); } packet.push(...setParams(data)); return packet; }; return { typeOf, decode, encode }; })(); // 0vC4#7152