【Quick 3.3】资源脚本加密及热更新(一)脚本加密

注:本文基于Quick-cocos2dx-3.3版本编写

一、脚本加密

quick框架已经封装好加密模块,与加密有关的文件在引擎目录/quick/bin下。

加密脚本:compile_scripts.bat、compile_scripts.sh

参数:

  • -i 需加密的脚本所在目录
  • -o 加密后文件输出目录
  • -e 加密方式,有xxtea_zip、xxtea_chunk两种方式,前者是打包一起加密,后者是分文件加密
  • -es 签名,用来识别代码、文件是不是加密的,一般填为"XXTEA"即可
  • -ek 密钥,简单来说就是加密和解密的钥匙,确保只有你自己知道
  • -jit 使用luajit编译脚本,quick3.3默认是用lua而不是luajit,所以此参数可不加

说明:更多可选参数可在/quick/bin/lib/compile_scripts.php找到说明,这里就不列举了

例子:(基于跨平台考虑,本系列的脚本基于python语言)

#coding=utf-8
#!/usr/bin/python
import os
import os.path
import sys, getopt
import subprocess
import shutil
import time, datetime
import platform
from hashlib import md5
import hashlib
import binascii def initEnvironment():
global APP_ROOT #工程根目录
global APP_ANDROID_ROOT #安卓根目录
global QUICK_ROOT #引擎根目录
global QUICK_BIN_DIR #引擎bin目录
global APP_RESOURCE_ROOT #生成app的资源目录
global APP_RESOURCE_RES_DIR #资源目录 global APP_BUILD_USE_JIT #是否使用jit global SCRIPT_NAME #执行脚本文件名 global BUILD_PLATFORM #生成app对应的平台 SYSTEM_TYPE = platform.system() #当前操作系统 APP_ROOT = os.getcwd() #当前目录
APP_ANDROID_ROOT = APP_ROOT + "/frameworks/runtime-src/proj.android"
QUICK_ROOT = os.getenv('QUICK_V3_ROOT') if QUICK_ROOT == None: #quick引擎目录未指定,可手动指定路径或者运行引擎目录下相应脚本
print "QUICK_V3_ROOT not set, please run setup_win.bat/setup_mac.sh in engine root or set QUICK_ROOT path"
return False if(SYSTEM_TYPE =="Windows"):
BUILD_PLATFORM = "android" #windows dafault build android
QUICK_BIN_DIR = QUICK_ROOT + "quick/bin"
SCRIPT_NAME = "/compile_scripts.bat"
else:
BUILD_PLATFORM = "ios" #mac default build ios
QUICK_BIN_DIR = QUICK_ROOT + "/quick/bin" #mac add '/'
SCRIPT_NAME = "/compile_scripts.sh" if(BUILD_PLATFORM =="ios"):
APP_BUILD_USE_JIT = False
APP_RESOURCE_ROOT = APP_ROOT + "/Resources"
APP_RESOURCE_RES_DIR = APP_RESOURCE_ROOT + "/res" else:
APP_BUILD_USE_JIT = True
APP_RESOURCE_ROOT = APP_ANDROID_ROOT + "/assets" #default build android
APP_RESOURCE_RES_DIR = APP_RESOURCE_ROOT + "/res" print 'App root: %s' %(APP_ROOT)
print 'App resource root: %s' %(APP_RESOURCE_ROOT)
return True def compileScriptFile(compileFileName, srcName, compileMode):
scriptDir = APP_RESOURCE_RES_DIR + "/code/"
if not os.path.exists(scriptDir):
os.makedirs(scriptDir)
try:
scriptsName = QUICK_BIN_DIR + SCRIPT_NAME
srcName = APP_ROOT + "/" + srcName
outputName = scriptDir + compileFileName
args = [scriptsName,'-i',srcName,'-o',outputName,'-e',compileMode,'-es','XXTEA','-ek','ilovecocos2dx'] if APP_BUILD_USE_JIT:
args.append('-jit') proc = subprocess.Popen(args, shell=False, stdout = subprocess.PIPE, stderr=subprocess.STDOUT)
while proc.poll() == None:
outputStr = proc.stdout.readline()
print outputStr,
print proc.stdout.read(),
except Exception,e:
print Exception,":",e if __name__ == '__main__':
isInit = initEnvironment() if isInit == True:
#将src目录下的所有脚本加密打包成game.zip
compileScriptFile("game.zip", "src", "xxtea_zip")

使用方法:

  1. 保存为compileScript.py文件
  2. 放到项目根目录(res、src同级目录)
  3. 运行命令行工具,cd到该目录,执行python compileScript.py
  4. 若屏幕输出 "create ZIP archive xx/xx/game.zip done". 说明执行成功

二、修改引擎

打开/frameworks/runtime-src/Classes/AppDelegate.cpp文件

在applicationDidFinishLaunching方法的最后改成如下代码

bool AppDelegate::applicationDidFinishLaunching(){
//..
//.. FileUtils *utils = FileUtils::getInstance(); const char *zipFilename ="code/game.zip"; std::string zipFilePath = utils->fullPathForFilename(zipFilename); if (zipFilePath.compare(zipFilename) == 0) //no game zip file use default lua file
{
engine->executeScriptFile(ConfigParser::getInstance()->getEntryFile().c_str());
}
else
{
stack->loadChunksFromZIP(zipFilename);
stack->executeString("require 'main'");
} return true
}

这段代码会判断res/code/game.zip是否存在,若存在则加载加密代码压缩包,否则执行旧的逻辑。这样改的好处是开发过程中可直接运行lua代码,发布版本则执行加密脚本

注意发布版本时需要移除src目录中的代码(教程的最后会给出完整脚本,自动生成app所需资源)

【Quick 3.3】资源脚本加密及热更新(一)脚本加密的更多相关文章

  1. 【Quick 3.3】资源脚本加密及热更新(三)热更新模块

    [Quick 3.3]资源脚本加密及热更新(三)热更新模块 注:本文基于Quick-cocos2dx-3.3版本编写 一.介绍 lua相对于c++开发的优点之一是代码可以在运行的时候才加载,基于此我们 ...

  2. 【Quick 3.3】资源脚本加密及热更新(二)资源加密

    [Quick 3.3]资源脚本加密及热更新(二)资源加密 注:本文基于Quick-cocos2dx-3.3版本编写 一.介绍 在前一篇文章中介绍了代码加密,加密方式是XXTEA.对于资源文件来说,同样 ...

  3. 一步一步开发Game服务器(三)加载脚本和服务器热更新(二)完整版

    上一篇文章我介绍了如果动态加载dll文件来更新程序 一步一步开发Game服务器(三)加载脚本和服务器热更新 可是在使用过程中,也许有很多会发现,动态加载dll其实不方便,应为需要预先编译代码为dll文 ...

  4. Unity3D热更新全书-脚本(二) 两级分化

    上篇明确了我们探讨的脚本是什么:是写在文本文件里面的代码,可以作为资源加载,取得字符串再执行. 可是为什么世界上会有那么多的脚本?而其使用方法完全看起来不一样呢?这是因为每种脚本都有自己的定位,在不同 ...

  5. Unity3D热更新全书-脚本(一) 初识脚本

    开篇之前还是要先说明,这是一份给经验并不丰富的程序员阅读的文字. 有需求.有疑惑,往下看. 第一个问题什么是脚本?程序和脚本如何区分?我们给Unity编写的组件是程序还是脚本? 这些问题本文无意去解答 ...

  6. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 在脚本中使用MonoBehaviour

    继上次分析了热更新的Demo后,这次来介绍如何在热更新代码中使用MonoBehaviour. MonoBehaviour挂载到GameObject对象上的脚本的基类.平常Unity开发时,简单的做法就 ...

  7. android游戏的增量更新(资源及代码的热更新)

    需求当游戏需要更新时,不必让用户下载新的完整包,只需要通过游戏内部的更新系统自动更新差异包,达到节约用户流量和时间的目的. 大体思路:1.(游戏逻辑用lua等脚本编写的情况)这种方式的增量更新非常简单 ...

  8. Unity3D热更新全书-脚本(五) NGUI

    让我们实际的研究一下如何将NGUI和C#LightEvil结合起来. 这里使用NGUI2.7,因为他是一个开源的版本,NGUI最新的版本未经作者的许可,是不可以带入我们的开源项目使用的. 这个例子完成 ...

  9. Unity3D热更新全书-脚本(四) 用C#LightEvil搭建实际开发使用的脚本框架

    C#LightEvil之前提供了很多和Unity结合的例子,都是采用把脚本文件放置在StreamingAssets中的方法. 这样可以利用Unity的特性,放在这个目录中的CS文件会被编译器编译,我们 ...

随机推荐

  1. php--tp中页面之间的跳转

  2. Find K most Frequent items in array

    给定一个String数组,求K个出现最频繁的数. 记录一下查到的资料和思路: 1. 使用heap sorting, 先用hashmap求出单词和词频.需要额外建立一个class Node,把单词和词频 ...

  3. 深度解析javascript中的浅复制和深复制

    原文:深度解析javascript中的浅复制和深复制 在谈javascript的浅复制和深复制之前,我们有必要在来讨论下js的数据类型.我们都知道有Number,Boolean,String,Null ...

  4. jquery中is()函数

    is(expr)函数判断当前Jquery对象所匹配的元素是否存在.只要其中一种符合,就返回 true,否则返回 false. 如果 expr是个字符串,既视为Jquery的选择器,用于表示选择的元素. ...

  5. 有趣的F-String

    F-String 让人上瘾 一个工具脚本的例子 https://www.pydanny.com/python-f-string-are-fun.html 在Python3.6的发布中,我们看到他们采纳 ...

  6. JAVA字符串的处理

    问题描述: 从键盘数入若干文字,最后输入的一行"end"代表结束标记. 统计该段文字中英文字母的个数 将其中的所有单词the全部改为a,输出结果 将该段文字所有的数字串找出来输出 ...

  7. 【Java多线程】AtomicLong和LongAdder

    AtomicLong简要介绍 AtomicLong是作用是对长整形进行原子操作,显而易见,在java1.8中新加入了一个新的原子类LongAdder,该类也可以保证Long类型操作的原子性,相对于At ...

  8. 【Mysql sql inject】POST方法BASE64编码注入write-up

      翻到群里的小伙伴发出一道POST型SQL注入题,简单抓包判断出题目需要base64编码后才执行sql语句,为学习下SQL注入出题与闯关的思路+工作不是很忙,所以花点时间玩了一下,哈哈哈哈哈哈哈哈哈 ...

  9. mysqldump备份时,--master-data选项的作用是什么?

    需求描述: 今天在研究mysql的备份和恢复,使用mysqldump备份数据库时,用到--master-data选项, 在此,测试并记录选项的作用 测试过程: 1.不使用--master-data进行 ...

  10. crc32 根据字符串获取校验值

    using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text; n ...