Greasy Fork is available in English.

MVDecoder2

Menu Editor

Този скрипт не може да бъде инсталиран директно. Това е библиотека за други скриптове и може да бъде използвана с мета-директива // @require https://update.greasyfork.org/scripts/468815/1295885/MVDecoder2.js

// ==UserScript==
// @name         MVDecoder2
// @version      0.7
// @description  KoGaMa WebSocket Decoder
// @author       Zpayer./.AMiNE.
// @match        http://*/*
// @match        https://*/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

class StreamBuffer{
	constructor(array=[]){this.index=0;this.array=new Uint8Array(array);}
	readByte(){return this.array[this.index++];}
	read(count){
		let arr=new Uint8Array(Math.min(count,this.array.length-this.index));
		for(let i=0;i<arr.length;i++)arr.set([this.readByte()],i);
		return arr;
	}
	writeByte(byte){this.array=new Uint8Array([...this.array,byte]);this.index++;}
	write(array){for(let i=0;i<array.length;i++)this.writeByte(array[i])}
}
function protoReverse(){
	return this.map(a=>new this.constructor(new Uint8Array(new this.constructor([a]).buffer).reverse().buffer)[0])
}
function protoByte(){
	return new Uint8Array(this.reversed().buffer);
}
Int32Array.prototype.bytes=protoByte;
Int32Array.prototype.reversed=protoReverse;
Int16Array.prototype.bytes=protoByte;
Int16Array.prototype.reversed=protoReverse;
Float32Array.prototype.bytes=protoByte
Float32Array.prototype.reversed=protoReverse
class TType{
	constructor(type,typeCode,value){this.type=type;this.typeCode=typeCode;this.value=value;}
	result(){return this.value}//bytes
	size(){return this.value.length}//number
	read(buf,full=0,size=-1){
		let res=new this.constructor(new Uint8Array(
			buf.read(size+1?size:this.size())
		));
		return full?res:res.value;
	}
	write(buf,full=0){
		if(full)buf.writeByte(this.typeCode);
		buf.write(this.result());
	}
}
class Byte extends TType{
	constructor(value=0){if(value.buffer){super('Byte',98,value[0])}else{super('Byte',98,value);}}
	result(full=0){return new Uint8Array([...(full?[this.typeCode]:[]),this.value]);}
	size(){return 1;}
}
class Bool extends TType{
	constructor(value=0){if(value.buffer){super('Bool',111,value[0]?1:0)}else{super('Bool',111,value?1:0);}}
	result(full=0){return new Uint8Array([...(full?[this.typeCode]:[]),this.value?1:0]);}
	size(){return 1;}
}
class Short extends TType{
	constructor(value=0){if(value.buffer){super('Short',107,new Int16Array(value.reverse().buffer)[0])}else{super('Short',107,value);}}
	result(full=0){return new Uint8Array([...(full?[this.typeCode]:[]),...new Int16Array([this.value]).bytes()]);}
	size(){return 2;}
}
class Int extends TType{
	constructor(value=0){if(value.buffer){super('Int',105,new Int32Array(value.reverse().buffer)[0])}else{super('Int',105,value);}}
	result(full=0){return new Uint8Array([...(full?[this.typeCode]:[]),...new Int32Array([this.value]).bytes()]);}
	size(){return 4;}
}
class Long extends TType{
	constructor(value=0){if(value.buffer){super('Long',108,new BigInt64Array(value.reverse().buffer)[0])}else{super('Long',108,value);}}
	result(full=0){return new Uint8Array([...(full?[this.typeCode]:[]),...new BigInt64Array([this.value]).bytes()]);}
	size(){return 8;}
}
class Float extends TType{
	constructor(value=0){if(value.buffer){super('Float',102,new Float32Array(value.reverse().buffer)[0])}else{super('Float',102,value);}}
	result(full=0){return new Uint8Array([...(full?[this.typeCode]:[]),...new Float32Array([this.value]).bytes()]);}
	size(){return 4;}
}
class Double extends TType{
	constructor(value=0){if(value.buffer){super('Double',100,new Double64Array(value.reverse().buffer)[0])}else{super('Double',100,value);}}
	result(full=0){return new Uint8Array([...(full?[this.typeCode]:[]),...new Float64Array([this.value]).bytes()]);}
	size(){return 8;}
}
class ByteArray extends TType{
	constructor(value=[]){super('ByteArray',120,new Uint8Array([...value]))}
	result(full=0){
		return new Uint8Array([
			...(full?[this.typeCode]:[]),
			...new Int(this.size()).result(),
			...this.value
		]);
	}
	size(){return this.value.length;}
	read(buf,full=0,size=-1){
		size=size+1?size:new Int().read(buf);
		let res=new this.constructor(new Uint8Array(buf.read(size)));
		return full?res:res.value;
	}
}
class Null extends TType{
	constructor(value=0){super('Null',42,null);}
	result(full=0){return new Uint8Array([...(full?[this.typeCode]:[])]);}
	size(){return 0;}
}
class String extends TType{
	constructor(value=''){if(value.buffer){super('String',115,new TextDecoder().decode(value))}else{super('String',115,value);}}
	size(){return new TextEncoder().encode(this.value).length}
	result(full=0){
		return new Uint8Array([
			...(full?[this.typeCode]:[]),
			...new Short(this.size()).result(),
			...new TextEncoder().encode(this.value)
		]);
	}
	read(buf,full=0,size=-1){
		size=size+1?size:new Short().read(buf);
		let res=new this.constructor(new Uint8Array(buf.read(size)));
		return full?res:res.value;
	}
}
class TArray extends TType{//{key:value,...}
	constructor(value=[],TValue=121){super('TArray',121,value);this.TValue=TValue;}
	size(){return this.value.length}
	result(full=0){
		let arr=[];
		for(let k in this.value){
			if(this.value[k].result){
				arr=[
					...arr,
					...this.value[k].result()
				];
			}
		}
		return new Uint8Array([
			...(full?[this.typeCode]:[]),
			...new Short(this.size()).result(),
			...new Byte(this.TValue).result(),
			...arr
		]);
	}
	read(buf,full=0,size=-1){
		size=size+1?size:new Short().read(buf);
		let b=new Byte().read(buf);//type
		let arr=new this.constructor([],b);
		if(b==121){//TArray
			arr.value=[new TArray().read(buf,full)];
			for(let i=1;i<size;i++)
				arr.value[i]=new TArray().read(buf,full);
		}else{
			if(b==120){//Array<ByteArray>
				for(let i=0;i<size;i++)
					arr.value[i]=new ByteArray().read(buf,full);
			}else{
				if(b==98){//ByteArray
					arr.value=new ByteArray().read(buf,full,size);
				}else{
					if(b==105){//IntArray
						for(let i=0;i<size;i++)
							arr.value[i]=new Int().read(buf,full);
					}else{
						if(b==68){//Dictionary
							for(let i=0;i<size;i++)
								arr.value[i]=new Dictionary().read(buf,full);
							return full?arr:arr.value;
						}
						for(let i=0;i<size;i++)
							arr.value[i]=new Call().read(buf,full,b);//other types
					}
				}
			}
		}
		return full?arr:arr.value;
	}
}
class Hashtable extends TType{//{key:value,...}
	constructor(value={}){super('Hashtable',104,value);}
	size(){return Object.keys(this.value).length}
	result(full=0){
		let arr=[];
		for(let k in this.value){
			if(this.value[k].result){
				arr=[
					...arr,
					...new Byte(Number(k)).result(1),
					...this.value[k].result(1)
				];
			}
		}
		return new Uint8Array([
			...(full?[this.typeCode]:[]),
			...new Short(this.size()).result(),
			...arr
		]);
	}
	read(buf,full=0,size=-1){
		size=size+1?size:new Short().read(buf);
		arr={};
		for(let i=0;i<size;i++){
			let key=new Call().read(buf);
			let value=new Call().read(buf,full);
			if(!(key===null)){
				arr[key]=value;
			}
		}
		let res=new this.constructor(arr);
		return full?res:res.value;
	}
}
class Dictionary extends TType{//[ {key:"",value:{}},... ]
	constructor(value=[],TKey,TValue){super('Dictionary',68,value);this.TKey=TKey;this.TValue=TValue;}
	size(){return this.value.length}

	result(full=0){
		let arr=[];
		for(let i in this.value){
			arr=[
				...arr,
				...this.value[i].key.result(this.TKey==0),
				...this.value[i].value.result(this.TValue==0)
			];
		}
		return new Uint8Array([
			...(full?[this.typeCode]:[]),
			...new Byte(this.TKey).result(),
			...new Byte(this.TValue).result(),
			...new Short(this.size()).result(),
			...arr
		]);
	}
	read(buf,full=0,size=-1){
		let TKey=new Byte().read(buf);
		let TValue=new Byte().read(buf);
		size=new Short().read(buf);
		let arr=[];
		for(let i=0;i<size;i++){
			let key=new Call().read(buf,full,TKey||-1);
			let value=new Call().read(buf,full,TValue||-1);
			if(!(key===null)){
				arr.push({key,value});
			}
		}
		let res=new this.constructor(arr,TKey,TValue);
		return full?res:res.value;
	}
}
class Call{
	constructor(){}
	read(buf,full=0,type=-1){
		type=type+1?type:new Byte().read(buf);
		if(!type)throw "No type: "+type;
		if(!GpType[type])throw "Unknown typeCode: "+type;
		return new GpType[type]().read(buf,full)
	}
}
const GpType={
	0:0&&Unknown,
	42:Null,

	111:Bool,
	98:Byte,
	107:Short,
	105:Int,
	108:Long,
	102:Float,
	100:Double,
	115:String,

	121:TArray,
	120:ByteArray,
	119:0&&IntArray,
	97:0&&StringArray,
	122:0&&ObjectArray,

	104:Hashtable,
	68:Dictionary,

	99:0&&Custom,
	101:0&&EventData,
	113:0&&OperationRequest,
	112:0&&OperationResponse
};
function parseSocket(arr0,full=1){
	if(arr0.length==3)return {header:[...arr0.slice(0,2)],opCode:arr0[2],result:function(){return toSocket(this)}};
	//243,2,opCode,length,length
	let buf=new StreamBuffer(arr0);buf.index=3;
	let arr={header:[...arr0.slice(0,2)],opCode:arr0[2],size:new Short().read(buf)};
	for(let i=0;i<arr.size;i++){
		let slot=new Byte().read(buf);
		arr[slot]=new Call().read(buf,full);
	}
	arr.result=function(){return toSocket(this)};
	return arr;
}
function toSocket(arr){
	let buf=new StreamBuffer();
	buf.write(arr.header);
	buf.writeByte(arr.opCode);
	if(arr.size>-1){
		new Short(arr.size).write(buf);
		if(arr.size>0){
			for(let k in arr){
				if(Number(k)>0){
					buf.writeByte(Number(k));
					arr[k].write(buf,1);
				}
			}
		}
	}
	return buf.array;
}
function w7bit(buf,n){
	for(;n>=128;n>>=7)buf.writeByte((n|128)%256);
	buf.writeByte(n%256);
};
function r7bit(buf){
	let num=0;
	let num2=0;
	while(num2!=35){
		let b=buf.readByte();
		num|=(b&127)<<num2;
		if((b&128)==0){return num;}
		num2+=7;
	}
};
window.getDictPackerDataTypes=top.getDictPackerDataTypes={}
let TypeGameSapShot={
'0':'Int',
    '1':'Int Array',
    '2':'Float',
    '3':'Float Array',
    '5':'Bool',
    '6':'Bool Array',
    '7':'String',
    '8':'Dictionary',
    '9':'Byte',
    '10':'Long',
    '11':'Long Array',
}
function getDictPacker(buf){
	let data={};
	let num=new Int().read(buf);
	if(num>1e3)throw "what is it?";
	for(let i2=0;i2<num;i2++){
		const key=new String().read(buf,0,r7bit(buf));
		const type=new Byte().read(buf);
        getDictPackerDataTypes[key]=TypeGameSapShot[type]
		let value=0;
		let len2=0;
		switch(type){
			case 0:
				value=new Int().read(buf);
			break;
			case 1://int array
				value=[];
				len2=new Int().read(buf);
				for(let i=0;i<len2;i++){
					value.push(new Int().read(buf));
				}
			break;
			case 2:
				value=new Float().read(buf);
			break;
			case 3:
				value=[];
				len2=new Int().read(buf);
				for(let i=0;i<len2;i++){
					value.push(new Float().read(buf));
				}
			break;
			case 5:
				value=new Bool().read(buf);
			break;
			case 6:
				value=[];
				len2=new Int().read(buf);
				for(let i=0;i<len2;i++){
					value.push(new Bool().read(buf));
				}
			break;
			case 7:
				value=new String().read(buf,0,r7bit(buf));
			break;
			case 8:
				value=getDictPacker(buf)
			break;
			case 9:
				value=new Byte().read(buf);
			break;
			case 10:
				value=new Long().read(buf);
			break;
			case 11:
				value=[];
				len2=new Int().read(buf);
				for(let i=0;i<len2;i++){
					value.push(new Long().read(buf));
				}
			break;
		}
		data[key]=value;
	}
	return data;
}
const take = arr => new DataView(Uint8Array.from(arr).buffer);
function gett(arr, l = 1) {
            if (!arr.i) arr.i = 0;
            arr.i += l;
            return arr.slice(arr.i - l, arr.i);
        };
        const getCubes = arr => {
            arr=Object.values(arr)
            let chunk = [];

            let num = take(gett(arr, 4)).getInt32();
            for (let i = 0; i < num; i++) {
                let cube = {};
                cube.x = take(gett(arr, 2)).getInt16();
                cube.y = take(gett(arr, 2)).getInt16();
                cube.z = take(gett(arr, 2)).getInt16();
                cube.flags = gett(arr);
                if ((cube.flags & 1) == 0) cube.shape = gett(arr, 8);
                if ((cube.flags & 2) == 0) cube.materials = gett(arr, 6);
                else cube.id = gett(arr);
                chunk.push(cube);

                for (let i2 = 1; i2 < (cube.flags >> 2); i2++) {
                    let clone = Object.assign({}, cube);
                    if ((cube.flags & 1) == 0) clone.shape = [...cube.shape];
                    if ((cube.flags & 2) == 0) clone.materials = [...cube.materials];
                    clone.x += i2;
                    chunk.push(clone);
                }
            }

            return chunk;
        };
function Enum (_){
var g={};
var c=0;
_.replaceAll(' ','').replaceAll('\t','').split(',').map(p=>{
    if(p.includes('//')&&p.includes('\n')){
        p=p.replace(/\/\/.*?\n/g, "");
            }
        if(p.includes('\n')){
        p=p.replaceAll('\n','')
        }
    if(p!=''){
    if(p.includes('=')){
g[p.split('=')[0]]=JSON.parse(p.split('=')[1])
c=p.split('=')[1]
    }else{
    g[p]=c
    }}
    c++
})
return g
}
let WorldObjectCode=Enum(`

		// Token: 0x04000277 RID: 631

		PlayModeAvatar,
		// Token: 0x04000278 RID: 632

		CubeModel,
		// Token: 0x04000279 RID: 633

		PointLight,
		// Token: 0x0400027A RID: 634

		TriggerBox,
		// Token: 0x0400027B RID: 635

		Mover,
		// Token: 0x0400027C RID: 636

		Path,
		// Token: 0x0400027D RID: 637

		PathNode,
		// Token: 0x0400027E RID: 638

		SpawnPoint,
		// Token: 0x0400027F RID: 639

		CubeModelPrototypeTerrain,
		// Token: 0x04000280 RID: 640

		Group,
		// Token: 0x04000281 RID: 641

		Action,
		// Token: 0x04000282 RID: 642

		BlueprintActivator,
		// Token: 0x04000283 RID: 643

		ParticleEmitter,
		// Token: 0x04000284 RID: 644

		SoundEmitter,
		// Token: 0x04000285 RID: 645

		BlueprintFire,
		// Token: 0x04000286 RID: 646

		BlueprintSmoke,
		// Token: 0x04000287 RID: 647

		BlueprintExplosion,
		// Token: 0x04000288 RID: 648

		Flag,
		// Token: 0x04000289 RID: 649

		TestLogicCube,
		// Token: 0x0400028A RID: 650

		Battery,
		// Token: 0x0400028B RID: 651

		ToggleBox,
		// Token: 0x0400028C RID: 652

		Negate,
		// Token: 0x0400028D RID: 653

		And,
		// Token: 0x0400028E RID: 654

		Explosives,
		// Token: 0x0400028F RID: 655

		TextMsg,
		// Token: 0x04000290 RID: 656

		Fire,
		// Token: 0x04000291 RID: 657

		Smoke,
		// Token: 0x04000292 RID: 658

		TimeTrigger,
		// Token: 0x04000293 RID: 659

		Teleporter,
		// Token: 0x04000294 RID: 660

		Goal,
		// Token: 0x04000295 RID: 661

		PickupItemHealthPack,
		// Token: 0x04000296 RID: 662

		PickupItemCenterGun,
		// Token: 0x04000297 RID: 663

		CubeModelTerrainFineGrained,
		// Token: 0x04000298 RID: 664

		PressurePlate,
		// Token: 0x04000299 RID: 665

		PickupItemImpulseGun,
		// Token: 0x0400029A RID: 666

		PickupItemBazookaGun,
		// Token: 0x0400029B RID: 667

		PickupItemRailGun,
		// Token: 0x0400029C RID: 668

		PickupItemSpawner,
		// Token: 0x0400029D RID: 669

		Skybox,
		// Token: 0x0400029E RID: 670

		SpawnPointRed,
		// Token: 0x0400029F RID: 671

		SpawnPointGreen,
		// Token: 0x040002A0 RID: 672

		SpawnPointYellow,
		// Token: 0x040002A1 RID: 673

		SpawnPointBlue,
		// Token: 0x040002A2 RID: 674

		ModelToggle,
		// Token: 0x040002A3 RID: 675

		WaterPlane,
		// Token: 0x040002A4 RID: 676

		Blueprint,
		// Token: 0x040002A5 RID: 677

		PulseBox,
		// Token: 0x040002A6 RID: 678

		RandomBox,
		// Token: 0x040002A7 RID: 679

		SentryGun,
		// Token: 0x040002A8 RID: 680

		CollectibleItem,
		// Token: 0x040002A9 RID: 681

		MovingPlatformNode,
		// Token: 0x040002AA RID: 682

		WaterPlanePreset,
		// Token: 0x040002AB RID: 683

		LightPreset,
		// Token: 0x040002AC RID: 684

		Ghost,
		// Token: 0x040002AD RID: 685

		PickupCubeGun,
		// Token: 0x040002AE RID: 686

		CheckPoint,
		// Token: 0x040002AF RID: 687

		HoverCraft,
		// Token: 0x040002B0 RID: 688

		WorldObjectSpawnerVehicle,
		// Token: 0x040002B1 RID: 689

		MonoPlane,
		// Token: 0x040002B2 RID: 690

		JetPack,
		// Token: 0x040002B3 RID: 691

		RoundCube,
		// Token: 0x040002B4 RID: 692

		AdvancedGhost,
		// Token: 0x040002B5 RID: 693

		HamsterWheel,
		// Token: 0x040002B6 RID: 694

		KillLimit,
		// Token: 0x040002B7 RID: 695

		OculusKillLimit,
		// Token: 0x040002B8 RID: 696

		CountingCube,
		// Token: 0x040002B9 RID: 697

		VehicleEnergy = 118,
		// Token: 0x040002BA RID: 698

		WorldObjectSpawnerVehicleEnergy,
		// Token: 0x040002BB RID: 699

		Jakob6,
		// Token: 0x040002BC RID: 700

		Jakob7,
		// Token: 0x040002BD RID: 701

		Jakob8,
		// Token: 0x040002BE RID: 702

		Jakob9,
		// Token: 0x040002BF RID: 703

		Jakob10,
		// Token: 0x040002C0 RID: 704

		Jakob11,
		// Token: 0x040002C1 RID: 705

		Jakob12,
		// Token: 0x040002C2 RID: 706

		Jakob13,
		// Token: 0x040002C3 RID: 707

		Jakob14,
		// Token: 0x040002C4 RID: 708

		Jakob15,
		// Token: 0x040002C5 RID: 709

		GamePoint,
		// Token: 0x040002C6 RID: 710

		GamePassProgressionDataObject,
		// Token: 0x040002C7 RID: 711

		Christian3,
		// Token: 0x040002C8 RID: 712

		BuildModeAvatar,
		// Token: 0x040002C9 RID: 713

		AvatarSpawnRoleCreator,
		// Token: 0x040002CA RID: 714

		GameOptionsDataObject,
		// Token: 0x040002CB RID: 715

		ModelTransparency,
		// Token: 0x040002CC RID: 716

		Christian8,
		// Token: 0x040002CD RID: 717

		Christian9,
		// Token: 0x040002CE RID: 718

		Christian10,
		// Token: 0x040002CF RID: 719

		Christian11,
		// Token: 0x040002D0 RID: 720

		Christian12,
		// Token: 0x040002D1 RID: 721

		Christian13,
		// Token: 0x040002D2 RID: 722

		Christian14,
		// Token: 0x040002D3 RID: 723

		Christian15,
		// Token: 0x040002D4 RID: 724

		CameraSettings,
		// Token: 0x040002D5 RID: 725

		GravityCube,
		// Token: 0x040002D6 RID: 726

		GameCoin = 148,
		// Token: 0x040002D7 RID: 727

		GameCoinChest,
		// Token: 0x040002D8 RID: 728

		Theme,
		// Token: 0x040002D9 RID: 729

		Door,
		// Token: 0x040002DA RID: 730

		DoorBlueprint,
		// Token: 0x040002DB RID: 731

		PickupMeleeWeapon,
		// Token: 0x040002DC RID: 732

		PickupMeleeWeaponBlueprint,
		// Token: 0x040002DD RID: 733

		PickupCostume,
		// Token: 0x040002DE RID: 734

		PickupCostumeBlueprint,
		// Token: 0x040002DF RID: 735

		Caspar13,
		// Token: 0x040002E0 RID: 736

		Caspar14,
		// Token: 0x040002E1 RID: 737

		Caspar15,
		// Token: 0x040002E2 RID: 738

		ShrinkGun,
		// Token: 0x040002E3 RID: 739

		TeamEditor,
		// Token: 0x040002E4 RID: 740

		TriggerCube,
		// Token: 0x040002E5 RID: 741

		Thomas4,
		// Token: 0x040002E6 RID: 742

		CollectTheItemCollectableInstance,
		// Token: 0x040002E7 RID: 743

		ShootableButton,
		// Token: 0x040002E8 RID: 744

		UseLever,
		// Token: 0x040002E9 RID: 745

		CollectTheItemDropOff,
		// Token: 0x040002EA RID: 746

		CollectTheItemCollectable,
		// Token: 0x040002EB RID: 747

		CollectTheItem,
		// Token: 0x040002EC RID: 748

		WindTurbine,
		// Token: 0x040002ED RID: 749

		GlobalSoundEmitter,
		// Token: 0x040002EE RID: 750

		Mathias3,
		// Token: 0x040002EF RID: 751

		Mathias4,
		// Token: 0x040002F0 RID: 752

		Mathias5,
		// Token: 0x040002F1 RID: 753

		Mathias6,
		// Token: 0x040002F2 RID: 754

		Mathias7,
		// Token: 0x040002F3 RID: 755

		Mathias8,
		// Token: 0x040002F4 RID: 756

		Mathias9,
		// Token: 0x040002F5 RID: 757

		Mathias10,
		// Token: 0x040002F6 RID: 758

		TimeAttackFlag,
		// Token: 0x040002F7 RID: 759

		GamePointChest,
		// Token: 0x040002F8 RID: 760

		Marcus3,
		// Token: 0x040002F9 RID: 761

		Marcus4,
		// Token: 0x040002FA RID: 762

		Marcus5,
		// Token: 0x040002FB RID: 763

		Marcus6,
		// Token: 0x040002FC RID: 764

		Marcus7,
		// Token: 0x040002FD RID: 765

		Marcus8,
		// Token: 0x040002FE RID: 766

		Marcus9,
		// Token: 0x040002FF RID: 767

		Marcus10

`)
const WorldObjectType = Object.fromEntries(Object.entries(WorldObjectCode).map(a => a.reverse()));

function getPackerInfo(BytePacker){
	let result={proto:[],woList:[],links:[],objectLinks:[]};
	let buf=new StreamBuffer(BytePacker)

	/*prototypes*/
	count=new Int().read(buf);
	for(let i=0;i<count;i++){
		let id=new Int().read(buf);
		let scale=new Float().read(buf);
		let authorId=new Int().read(buf);
		let data= getCubes(new ByteArray().read(buf))
		result.proto.push({id,scale,authorId,data});
	}
	/*worldObjects*/
	count=new Int().read(buf);//11812
	for(let i=0;i<count;i++){
		let id=new Int().read(buf);
		let groupId=new Int().read(buf);
		let itemId=new Int().read(buf);
		let woType=new Int().read(buf);
        let woTypeId=woType
        woType = WorldObjectType[woType]|| woType;
		let posX=new Float().read(buf);
		let posY=new Float().read(buf);
		let posZ=new Float().read(buf);
		let rotationX=new Float().read(buf);
		let rotationY=new Float().read(buf);
		let rotationZ=new Float().read(buf);
		let rotationW=new Float().read(buf);
		let scaleX=new Float().read(buf);
		let scaleY=new Float().read(buf);
		let scaleZ=new Float().read(buf);
		let data=getDictPacker(buf);
		let owner=new Byte().read(buf);
		let ownerID=null;
		if((owner&1)!=0){
			ownerID=new Int().read(buf);
		}
		if((owner&2)!=0){
			ownerID=new Int().read(buf);
		}
		let data2=getDictPacker(buf);
		result.woList.push({
			id,groupId,itemId,woType,woTypeId,
			pos:[posX,posY,posZ],
			rotation:[rotationX,rotationY,rotationZ,rotationW],
			scale:[scaleX,scaleY,scaleZ],
			data,
			owner,
			ownerID,
			data2
		});
	}
	/*links*/
	count=new Int().read(buf);
	for(let i=0;i<count;i++){
		let id=new Int().read(buf);
		let input=new Int().read(buf);
		let output=new Int().read(buf);
		result.links.push({id,input,output});
	}
	/*objectLinks*/
	count=new Int().read(buf);
	for(let i=0;i<count;i++){
		let id=new Int().read(buf);
		let connectorWOID=new Int().read(buf);
		let WOID=new Int().read(buf);
		result.objectLinks.push({id,WOID,connectorWOID});
	}
result.woList.forEach(l=>{
result.links.forEach(m=>{
if(l.id==m.input){
l.Link=m
l.LinkType='input'
}
if(l.id==m.output){
l.Link=m
l.LinkType='output'
}
})
result.objectLinks.forEach(m=>{
if(l.id==m.connectorWOID){
l.ObjectLink=m
l.ObjectLinkType='connectorWOID'
}
if(l.id==m.WOID){
l.ObjectLink=m
l.ObjectLinkType='WOID'
}
})
result.proto.forEach(M=>{
    if(l.data.protoTypeID==M.id){
l.proto=M
    }
})
})

	return result.woList;
}
const BytePacker=()=>{
    const t = new Worker(window.URL.createObjectURL(new Blob(["onmessage=" + (e => {
            let t = e.data.buffer,
                a = {
                    proto: [],
                    woList: [],
                    links: [],
                    oLinks: []
                };
            const r = Object.fromEntries(Object.entries({
                    PlayModeAvatar: 0,
                    CubeModel: 1,
                    PointLight: 2,
                    TriggerBox: 3,
                    Mover: 4,
                    Path: 5,
                    PathNode: 6,
                    SpawnPoint: 7,
                    CubeModelPrototypeTerrain: 8,
                    Group: 9,
                    Action: 10,
                    BlueprintActivator: 11,
                    ParticleEmitter: 12,
                    SoundEmitter: 13,
                    BlueprintFire: 14,
                    BlueprintSmoke: 15,
                    BlueprintExplosion: 16,
                    Flag: 17,
                    TestLogicCube: 18,
                    Battery: 19,
                    ToggleBox: 20,
                    Negate: 21,
                    And: 22,
                    Explosives: 23,
                    TextMsg: 24,
                    Fire: 25,
                    Smoke: 26,
                    TimeTrigger: 27,
                    Teleporter: 28,
                    Goal: 29,
                    PickupItemHealthPack: 30,
                    PickupItemCenterGun: 31,
                    CubeModelTerrainFineGrained: 32,
                    PressurePlate: 33,
                    PickupItemImpulseGun: 34,
                    PickupItemBazookaGun: 35,
                    PickupItemRailGun: 36,
                    PickupItemSpawner: 37,
                    Skybox: 38,
                    SpawnPointRed: 39,
                    SpawnPointGreen: 40,
                    SpawnPointYellow: 41,
                    SpawnPointBlue: 42,
                    ModelToggle: 43,
                    WaterPlane: 44,
                    Blueprint: 45,
                    PulseBox: 46,
                    RandomBox: 47,
                    SentryGun: 48,
                    CollectibleItem: 49,
                    MovingPlatformNode: 50,
                    WaterPlanePreset: 51,
                    LightPreset: 52,
                    Ghost: 53,
                    PickupCubeGun: 54,
                    CheckPoint: 55,
                    HoverCraft: 56,
                    WorldObjectSpawnerVehicle: 57,
                    MonoPlane: 58,
                    JetPack: 59,
                    RoundCube: 60,
                    AdvancedGhost: 61,
                    HamsterWheel: 62,
                    KillLimit: 63,
                    OculusKillLimit: 64,
                    CountingCube: 65,
                    Jakob4: 118,
                    Jakob5: 119,
                    Jakob6: 120,
                    Jakob7: 121,
                    Jakob8: 122,
                    Jakob9: 123,
                    Jakob10: 124,
                    Jakob11: 125,
                    Jakob12: 126,
                    Jakob13: 127,
                    Jakob14: 128,
                    Jakob15: 129,
                    GamePoint: 130,
                    GamePassProgressionDataObject: 131,
                    Christian3: 132,
                    BuildModeAvatar: 133,
                    AvatarSpawnRoleCreator: 134,
                    GameOptionsDataObject: 135,
                    Christian7: 136,
                    Christian8: 137,
                    Christian9: 138,
                    Christian10: 139,
                    Christian11: 140,
                    Christian12: 141,
                    Christian13: 142,
                    Christian14: 143,
                    Christian15: 144,
                    CameraSettings: 145,
                    GravityCube: 146,
                    GameCoin: 148,
                    GameCoinChest: 149,
                    Theme: 150,
                    Caspar7: 151,
                    Caspar8: 152,
                    Caspar9: 153,
                    Caspar10: 154,
                    Caspar11: 155,
                    Caspar12: 156,
                    Caspar13: 157,
                    Caspar14: 158,
                    Caspar15: 159,
                    ShrinkGun: 160,
                    TeamEditor: 161,
                    TriggerCube: 162,
                    Thomas4: 163,
                    CollectTheItemCollectableInstance: 164,
                    ShootableButton: 165,
                    UseLever: 166,
                    CollectTheItemDropOff: 167,
                    CollectTheItemCollectable: 168,
                    CollectTheItem: 169,
                    WindTurbine: 170,
                    GlobalSoundEmitter: 171,
                    Mathias3: 172,
                    Mathias4: 173,
                    Mathias5: 174,
                    Mathias6: 175,
                    Mathias7: 176,
                    Mathias8: 177,
                    Mathias9: 178,
                    Mathias10: 179,
                    TimeAttackFlag: 180,
                    GamePointChest: 181,
                    Marcus3: 182,
                    Marcus4: 183,
                    Marcus5: 184,
                    Marcus6: 185,
                    Marcus7: 186,
                    Marcus8: 187,
                    Marcus9: 188,
                    Marcus10: 189
                }).map(e => e.reverse())),
                i = e => new DataView(Uint8Array.from(e).buffer),
                s = e => {
                    let t = [],
                        a = i(e.splice(0, 4)).getInt32();
                    for (let r = 0; r < a; r++) {
                        let a = {};
                        a.x = i(e.splice(0, 2)).getInt16(),
                            a.y = i(e.splice(0, 2)).getInt16(),
                            a.z = i(e.splice(0, 2)).getInt16(),
                            a.flags = e.shift(),
                            0 == (1 & a.flags) && (a.corners = e.splice(0, 8)),
                            0 == (2 & a.flags) ? a.materials = e.splice(0, 6) : a.material = e.shift(), t.push([a.pos, a]);
                        for (let e = 1; e < a.flags >> 2; e++) {
                            let r = Object.assign({}, a);
                            0 == (1 & a.flags) && (r.corners = [...a.corners]), 0 == (2 & a.flags) && (r.materials = [...a.materials]), r.x += e, t.push([r.pos, r])
                        }
                    }
                    return t
                },
                l = e => {
                    let t = (e => {
                        let t = 0,
                            a = 0;
                        for (; 35 != a;) {
                            let r = e[a / 7];
                            if (t |= (127 & r) << a, 0 == (128 & r)) return [t, a / 7 + 1];
                            a += 7
                        }
                    })(e);
                    return e.splice(0, t[1]), (new TextDecoder).decode(new Uint8Array([...e.splice(0, t[0])]))
                },
                n = e => {
                    let t = i(e.splice(0, 4)).getInt32();
                    if (t > 1e3) throw "Hashtable size limit";
                    for (let r = 0; r < t; r++) {
                        let t = l(e),
                            r = 0,
                            s = 0;
                        switch (i(e.splice(0, 1)).getUint8()) {
                        case 0:
                            r = i(e.splice(0, 4)).getInt32();
                            break;
                        case 1:
                            r = [], s = i(e.splice(0, 4)).getInt32();
                            for (let t = 0; t < s; t++) r.push(i(e.splice(0, 4)).getInt32());
                            break;
                        case 2:
                            r = i(e.splice(0, 4)).getFloat32();
                            break;
                        case 3:
                            r = [], s = i(e.splice(0, 4)).getInt32();
                            for (let t = 0; t < s; t++) r.push(i(e.splice(0, 4)).getFloat32());
                            break;
                        case 5:
                            r = i(e.splice(0, 1)).getUint8() > 0;
                            break;
                        case 6:
                            r = [], s = i(e.splice(0, 4)).getInt32();
                            for (let t = 0; t < s; t++) r.push(i(e.splice(0, 1)).getUint8() > 0);
                            break;
                        case 7:
                            r = l(e);
                            break;
                        case 8:
                            r = n(e);
                            break;
                        case 9:
                            r = i(e.splice(0, 1)).getUint8();
                            break;
                        case 10:
                            r = i(e.splice(0, 8)).getBigInt64();
                            break;
                        case 11:
                            r = [], s = i(e.splice(0, 4)).getInt32();
                            for (let t = 0; t < s; t++) r.push(i(e.splice(0, 8)).getBigInt64())
                        }
                        a[t] = r
                    }
                };
            num = i(t.splice(0, 4)).getInt32();
            for (let e = 0; e < num; e++) {
                let e = {};
                    e.id = i(t.splice(0, 4)).getInt32(),
                    e.scale = i(t.splice(0, 4)).getFloat32(),
                    e.profileId = i(t.splice(0, 4)).getInt32(),
                    e.cubes = s(t.splice(0, i(t.splice(0, 4)).getInt32())),
                    a.proto.push(e)
            }
            num = i(t.splice(0, 4)).getInt32();
            for (let e = 0; e < num; e++) {
                let e = i(t.splice(0, 4)).getInt32(),
                    s = i(t.splice(0, 4)).getInt32(),
                    l = i(t.splice(0, 4)).getInt32(),
                    p = i(t.splice(0, 4)).getInt32();
                p = r[p] || p;
                let o = i(t.splice(0, 4)).getFloat32(),
                    c = i(t.splice(0, 4)).getFloat32(),
                    u = i(t.splice(0, 4)).getFloat32(),
                    g = i(t.splice(0, 4)).getFloat32(),
                    h = i(t.splice(0, 4)).getFloat32(),
                    m = i(t.splice(0, 4)).getFloat32(),
                    I = i(t.splice(0, 4)).getFloat32(),
                    d = i(t.splice(0, 4)).getFloat32(),
                    f = i(t.splice(0, 4)).getFloat32(),
                    b = i(t.splice(0, 4)).getFloat32(),
                    C = n(t),
                    y = i(t.splice(0, 1)).getUint8(),
                    k = null;
                0 != (1 & y) && (k = i(t.splice(0, 4)).getInt32()), 0 != (2 & y) && (k = i(t.splice(0, 4)).getInt32());
                let A = n(t);
                a.woList.push({
                    woType: p,
                    data2: A,
                    data: C,
                    id: e,
                    groupId: s,
                    itemId: l,
                    pos: {
                        x: o,
                        y: c,
                        z: u
                    },
                    rot: {
                        x: g,
                        y: h,
                        z: m,
                        w: I
                    },
                    scale: {
                        x: d,
                        y: f,
                        z: b
                    },
                    owner: y,
                    ownerId: k,
                })
            }
            num = i(t.splice(0, 4)).getInt32();
            for (let e = 0; e < num; e++) {
                let e = i(t.splice(0, 4)).getInt32(),
                    r = i(t.splice(0, 4)).getInt32(),
                    s = i(t.splice(0, 4)).getInt32();
                a.links.push({
                    id: e,
                    input: r,
                    output: s
                })
            }
            num = i(t.splice(0, 4)).getInt32();
            for (let e = 0; e < num; e++) {
                let e = i(t.splice(0, 4)).getInt32(),
                    r = i(t.splice(0, 4)).getInt32(),
                    s = i(t.splice(0, 4)).getInt32();
                a.oLinks.push({
                    id: e,
                    WOID: s,
                    connectorWOID: r
                })
            }
            self.postMessage(a)
        }).toString()], {
            type: "text/javascript"
        }))),
        a = e => new DataView(Uint8Array.from(e).buffer),
        r = (e, t) => [...new Uint8Array(t.of(e).buffer).reverse()];
    return {
        getWorld(e, a) {
            t.postMessage({
                buffer: e
            }), t.onmessage = (e => a(e.data))
        },
        getAvatarsMeta(e) {
            let t = {},
                r = a(e.splice(0, 4)).getInt32();
            for (let i = 0; i < r; i++) {
                t[a(e.splice(0, 4)).getInt32()] = this.getAvatarMeta(e)
            }
            return t
        },
        setAvatarsMeta(e) {
            let t = [];
            t.push(...r(Object.keys(e).length, Int32Array));
            for (let a in e) t.push(...r(a, Int32Array)), t.push(...this.setAvatarMeta(e[a]));
            return t
        },
        getAvatarMeta(e) {
            let t = {};
            return t.avatarId = a(e.splice(0, 4)).getInt32(), t.name = (e => {
                let t = (e => {
                        let t = 0,
                            a = 0;
                        for (; 35 != a;) {
                            let r = e[a / 7];
                            if (t |= (127 & r) << a, 0 == (128 & r)) return [t, a / 7 + 1];
                            a += 7
                        }
                    })(e),
                    a = t[0],
                    r = t[1];
                return e.splice(0, r), (new TextDecoder).decode(new Uint8Array([...e.splice(0, a)]))
            })(e), t.priceGold = a(e.splice(0, 4)).getInt32(), t.isOnMarketPlace = a(e.shift()).getUint8() > 0, t.canBeSoldOnMarketPlace = a(e.shift()).getUint8() > 0, t
        },
        setAvatarMeta(e) {
            let t = [];
            return t.push(...r(e.avatarId, Int32Array)), t.push(...(e => {
                let t = [],
                    a = (e => {
                        let t = [];
                        for (; e >= 128; e >>= 7) t.push((128 | e) % 256);
                        return t.push(e % 256), t
                    })(e.length);
                return t.push(a), t.push(...(new TextEncoder).encode(e)), t
            })(e.name)), t.push(...r(e.priceGold, Int32Array)), t.push(e.isOnMarketPlace > 0), t.push(e.canBeSoldOnMarketPlace > 0), t
        },
        getRPC(e) {
            let t = {};
            return t.flags = e.shift(), 0 != (1 & t.flags) && (t.interaction = e.shift()), 0 != (2 & t.flags) ? t.damage = a(e.splice(0, 4)).getFloat32() : t.damage = {
                9: 11.5,
                6: 110,
                4: 100,
                7: 13,
                14: 12.5,
                19: 12.5,
                5: 15,
                15: 15,
                24: 12,
                26: 25
            } [t.interaction] || 0, 0 != (4 & t.flags) ? (t.x = a(e.splice(0, 4)).getFloat32(), t.y = a(e.splice(0, 4)).getFloat32(), t.z = a(e.splice(0, 4)).getFloat32()) : Object.assign(t, {
                x: 0,
                y: 0,
                z: 0
            }), 0 != (8 & t.flags) ? t.type = e.shift() : t.type = 0, t
        },
        setRPC(e) {
            let t = [];
            return t.push(e.flags || 15), 0 != (1 & e.flags) && t.push(e.interaction || 0), 0 != (2 & e.flags) && t.push(...r(e.damage || 0, Float32Array)), 0 != (4 & e.flags) && t.push(...r(e.x || 0, Float32Array), ...r(e.y || 0, Float32Array), ...r(e.z || 0, Float32Array)), 0 != (8 & e.flags) && t.push(e.type || 0), t
        },
        getRuntime(t) {
            let r = {};
            const i = Object.fromEntries(Object.entries({
                Undefined: 0,
                FineGrainedSingleCubeAdd: 1,
                FineGrainedSingleCubeRemove: 2,
                Bazooka: 3,
                AvatarImpact25: 4,
                FineGrainedSingleCubeRemovedAddedFineGrainedCube: 5,
                VehicleImpact25: 6,
                AvatarImpact50: 7,
                AvatarImpact75: 8,
                VehicleImpact50: 9,
                VehicleImpact75: 10,
                SwordTerrainDestroy: 15,
                ImpulseGunImpact: 16
            }).map(e => e.reverse()));
            let s = t.shift();
            return r.type = i[s] || "Undefined", 1 == s || 2 == s || 5 == s ? (r.material = -1, "FineGrainedSingleCubeAdd" == r.type && (r.material = t.shift()), r.x = a(t.splice(0, 2)).getInt16(), r.y = a(t.splice(0, 2)).getInt16(), r.z = a(t.splice(0, 2)).getInt16()) : (3 == s || 4 == s || s >= 6 && s <= 10 || 15 == s || 16 == s) && (r.x = a(t.splice(0, 2)).getInt16(), r.y = a(t.splice(0, 2)).getInt16(), r.z = a(t.splice(0, 2)).getInt16()),r
        },
        setRuntime(e) {
            let t = [];
            const a = {
                Undefined: 0,
                FineGrainedSingleCubeAdd: 1,
                FineGrainedSingleCubeRemove: 2,
                Bazooka: 3,
                AvatarImpact25: 4,
                FineGrainedSingleCubeRemovedAddedFineGrainedCube: 5,
                VehicleImpact25: 6,
                AvatarImpact50: 7,
                AvatarImpact75: 8,
                VehicleImpact50: 9,
                VehicleImpact75: 10,
                SwordTerrainDestroy: 15,
                ImpulseGunImpact: 16
            };
            let i = a[e.type];
            t.push(i)
            if(i==1)t.push(e.material > -1 ? e.material : 0)
            t.push(...r(e.x,Int16Array))
            t.push(...r(e.y,Int16Array))
            t.push(...r(e.z,Int16Array))
            return t
        },
        getCube(e) {
            let t = {};
            return t.action = e.shift(), t.pos = [a(e.splice(0, 2)).getInt16(),a(e.splice(0, 2)).getInt16(),a(e.splice(0, 2)).getInt16()], t.material = -1, 0 == t.action ? t : (t.flags = e.shift(), 0 == (1 & t.flags) && (t.corners = e.splice(0, 8)), 0 == (2 & t.flags) ? t.materials = e.splice(0, 6) : t.material = e.shift(), t)
        },
        setCube(e) {
            let t = [];
            return t.push(e.material > -1 ? e.action : 0), t.push(...r(e.x, Int16Array)), t.push(...r(e.y, Int16Array)), t.push(...r(e.z, Int16Array)), e.material < 0 ? new Uint8Array(t) : (t.push(e.flags), 0 == (1 & e.flags) && t.push(...e.corners || [20, 120, 124, 24, 4, 104, 100, 0]), 0 == (2 & e.flags) ? t.push(...e.materials || [e.material, e.material, e.material, e.material, e.material, e.material]) : t.push(e.material), new Uint8Array(t))
        }
    }
}
const GetSize=(e)=>{
var c=0
function containsNumbers(str) {
  return /\d/.test(str);
}
Object.entries(e).forEach(l=>{
if(containsNumbers(l[0])){
c++
}
})
return c
}