反编译Laya1.x场景文件资源代码

### 由于源码丢失只有一个发布后的源码 需要二次开发,只能把发布后的代码还原成工程进行二次开发。不足就是,资源已经被压缩过了,不是最高清了。代码也有被压缩过,但是不影响开发。

解决过程

技术分析。

首先是先把资源全down下来。
然后把布局文件拆分还原成工程布局文件。
再把代码拆分成一个个功能文件。
使用到工具:
	浏览器。python layaIde1.7x
	如果有version.json 那么恭喜你资源基本就全拿到了。
	如果没有那就只能采用嗅探方式获取资源了。
	获取资源后拆分大图为小图。工具可以找我拿。
	
因为是1.x 所以布局文件全都在layaUI.max.all.js文件里面  

下面直接贴代码

  1. 简单的控制台获取布局文件
		//简单的线上解析布局文件下载 然后python组装布局文件
		var script = document.createElement('script');
        script.src = "https://cdn.bootcdn.net/ajax/libs/FileSaver.js/2.0.5/FileSaver.js";
        document.getElementsByTagName('head')[0].appendChild(script);

        try {
            var isFileSaverSupported = !!new Blob;
        } catch (e) {
            console.log("不支持")
        }

		//全部布局文件
        uiMgr = {}
        for (var key in ui) {
             let uiobj = ui[key];
             let json = {className:"ui."+key,view:JSON.stringify(uiobj.uiView)}
             uiMgr[key] = json;
        }
        var blob = new Blob([JSON.stringify(uiMgr)], {type: "text/plain;charset=utf-8"});
        saveAs(blob, "uiview.json");

  1. python组装布局文件
 # coding: utf-8
import os
import sys
import time
import json   
reload(sys)  
sys.setdefaultencoding('utf8')  
'''
本代码适用于laya 1.7.X 版本 文件内嵌模式
20201117
http://resource.vuggame.cn/h5_ddzj_res_4399/

资源:https://resource.vuggame.cn/h5_ddzj_res_4399/

var script = document.createElement('script');
script.src = "https://cdn.bootcdn.net/ajax/libs/FileSaver.js/2.0.5/FileSaver.js";
document.getElementsByTagName('head')[0].appendChild(script);


try {
	var isFileSaverSupported = !!new Blob;
} catch (e) {
	console.log("不支持")
}


uiMgr = {}
for (var key in ui) {
	 let uiobj = ui[key];
	 let name = key.substring(0,key.indexOf("UI")) 
	 let json = {className:"ui."+name,view:uiobj.uiView}
	 uiMgr[name] = json;
}
var blob = new Blob([JSON.stringify(uiMgr)], {type: "text/plain;charset=utf-8"});
saveAs(blob, "uiview.json");



'''

#全局变量
cCompId = 0
PAGEDATA = {}
TOTAL_FILE = 0
gap = "\n"
kongge = " "
COMP =[]
SUC_COMP= [
	"Script", 
]
'''
读取json数据
'''
def readDataJson(jsonPath):
	if not os.path.exists( jsonPath ): 
		return None
	f = open( jsonPath, 'r' )
	fileStr = f.read() 
	jsonData = json.loads( fileStr )
	f.close() 
	return jsonData

def writeDataJson(exportName,datas):
	file = open( exportName, 'w+' )
	json_data = json.dumps( datas,indent=4 )
	#formatR = formatR.replace(" ", "");
	file.write( json_data )
	file.close()

def writeData(exportName,datas):
	file = open( exportName, 'w+' )
	file.write( datas )
	file.close()

#自增compID
def getCompID():
	global cCompId
	cCompId = cCompId + 1
	return cCompId


#设置子属性模板
def getChildTemplete():
	return {
		"nodeParent":8,
		"label":"Sprite",
		"isDirectory":False,
		"isAniNode":True,
		"hasChild":False,
		"isOpen":True,
		"child":[]	
	}

#保留被扒的ani动画
AniComPath = []
COMP = []
#组件绑定
BIND_COMP = {
	"Script":"laya/pages/ui/ScaleButton.script",
	#"DataLoading":"laya/pages/ui/DataLoading.script",
	#"FlashFigter":"laya/pages/ui/FlashFigter.script",
	#"PayTip":"laya/pages/ui/PayTip.script",
	#"RankDBQB":"laya/pages/ui/RankDBQB.script",
	#"Reward":"laya/pages/ui/Reward.script",
	#"DBQBHelp":"laya/pages/ui/DBQBHelp.script",
	#"SellDialog":"laya/pages/ui/SellDialog.script",
	#"EmailTextDialog":"laya/pages/ui/EmailTextDialog.script",
	#"RankRewardDialog":"laya/pages/ui/RankRewardDialog.script",
	#"dialogStation":"laya/pages/ui/dialogStation.script",
	#"ShopBuy":"laya/pages/ui/ShopBuy.script",
	#"GiftReward":"laya/pages/ui/GiftReward.script",
	#"ResourcesInfo":"laya/pages/ui/ResourcesInfo.script",
	#"LevelDifficulty":"laya/pages/ui/LevelDifficulty.script",
	#"FlashLevelUp":"laya/pages/ui/FlashLevelUp.script",
	#"RoleInfo":"laya/pages/ui/RoleInfo.script",
	#"GoodsInfo":"laya/pages/ui/GoodsInfo.script",
}	



def readChild(value):
	array = [] 
	for each in value: 
		d = getChildTemplete() 
		d.update({"compId":str(getCompID())}) 
		#//属性级别
		child3 = each.items()
		for k, v in child3:
			
			#修复脚本类型组件
			if k == "type":
				#处理动画文件
				if v == "Animation":
					aniPath = each.get("props").get("source")
					if aniPath in AniComPath:
						pass
					else:
						AniComPath.append(aniPath)
				
				source = BIND_COMP.get(v)
				if source:
					d.update({"source":source})
					d.update({"label":v})
					
				#if v in COMP:
					#pass
				#else:
					#COMP.append(v)
		 
			if k == "child":
				if len(v)>1:
					d.update({ "hasChild":True })
					d.update({ "isDirectory":True })
				d.update({ k:readChild(v) })
			else: 
				d.update({ k:v })
		array.append(d) 
	return array

 

def reloadJson(items): 
	configs = {
		"x":0,
		"type":"View",
		"selectedBox":2, 
		"selecteID":3,
		"nodeParent":-1,
		"label":"View",
		"isOpen":True,
		"isDirectory":False,
		"isAniNode":False,
   		"hasChild":False,
		"compId":getCompID(),
		"props":{},
		"child":[],
		"animations":[],
	}
	for key, value in items:
		if key == "type":
			configs.update( { key:value })
		if key == "props": 
			value.update({ "sceneColor":"#000000" })
			configs.update( { key:value }) 
		if key == "child":
			configs.update({key:readChild(value)})
		if key == "animations":
			print "animations"
			configs.update( { key:value })  

	return configs

def zuChild(items,num): 
	subXml = ""  
	for each in items:
		objs = each  
		subXml2 = ""
		TYPE = objs.get("type")
		subXml2 = getKG(num+1) + "<" + TYPE
		child = objs.get("child")
		for key, value in objs.items():
			if key != "child" and key!= "type":
				subXml2 += " " + key +'="'+str(value)+'"'
		subXml2 += ">"
		if child:
			subXml2 +=  gap + zuChild(child,num+1) + gap 
		subXml2 += getKG(num+1) +"</"+TYPE+">" 
		subXml +=subXml2
	return subXml

def getKG(num):
	ge = ""
	num = num*2
	for i in range(num):
		ge += kongge 
	return ge


def ZU(data): 
	uiXml ="<"
	TYPE = data.get("type")
	uiXml += TYPE
	child = data.get("child")
	for k, v in data.items():
		if k != "child" and k !="type": 
			uiXml += getKG(1) + k +'="' + str(v)+'"'
			 
	uiXml += ">" + gap + zuChild(child,1) + gap + "</"+TYPE+">"
	return uiXml

#组装.ui文件
def packageUI(view,fileName):
	global cCompId
	cCompId = 0
	items = view.items()
	configs = reloadJson(items) 
	#UI = ZU(configs)
	#保存为场景文件
	#writeData(fileName,UI) 
	writeDataJson(fileName,configs)
	global TOTAL_FILE
	TOTAL_FILE = TOTAL_FILE + 1
	writeDataJson("arary.json",COMP)
	

if __name__=='__main__':

	if len( sys.argv ) < 2:
		tdir = raw_input("Enter your targerDir: ")
	else:
		tdir = sys.argv[1]
	if len( sys.argv ) < 3:
		odir = raw_input("Enter your outPath: ")
	else:
		odir = sys.argv[2]

	target = os.path.join(os.getcwd(),tdir)
	outDir = os.path.join(os.getcwd(),odir)
	
	viewJson = readDataJson( os.path.join(target,"uiview.json"))
	
	#所有布局文件
	for key in viewJson:
		obj = viewJson.get(key)
		className = obj["className"]
		view = obj["view"]
		#开始解析布局
		packageUI(view,os.path.join(outDir,key+".ui"))


总结: 遇事不要慌,发个朋友圈 。

最后还是没有解决自定义type这块类型的问题。有时间在折腾吧

```