- // ==UserScript==
- // @name KPD
- // @license MIT
- // @version 1.1
- // @description Kogama Packet Decoder
- // @author 0vC4
- // @namespace https://greasyfork.org/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