108 lines
12 KiB
JavaScript
108 lines
12 KiB
JavaScript
// Local component fixture, using the installed Cocos 2.4 engine and a real Asset Bundle.
|
|
// No game login, network API or real payment is called. Run: node tools/coin-madness/preview.cjs
|
|
const http = require('http');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const ts = require('typescript');
|
|
const root = path.resolve(__dirname, '../..');
|
|
const creator = process.env.COCOS_CREATOR_PATH || 'C:/ProgramData/cocos/editors/Creator/2.4.15';
|
|
const engine = path.join(creator, 'resources/engine/bin/cocos2d-js-for-preview.js');
|
|
const uuid = JSON.parse(fs.readFileSync(path.join(root, 'assets/coin_madness/prefab/CoinMadness.prefab.meta'))).uuid;
|
|
const helpUuid = JSON.parse(fs.readFileSync(path.join(root, 'assets/coin_madness/prefab/CoinMadnessHelp.prefab.meta'))).uuid;
|
|
const settlementUuid = JSON.parse(fs.readFileSync(path.join(root, 'assets/coin_madness/prefab/CoinMadnessSettlement.prefab.meta'))).uuid;
|
|
const scriptUuid = JSON.parse(fs.readFileSync(path.join(root, 'assets/coin_madness/script/CoinMadnessPanel.ts.meta'))).uuid;
|
|
const hex=scriptUuid.replaceAll('-',''), alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
const scriptId=hex.slice(0,5)+hex.slice(5).match(/.{3}/g).map(s=>alphabet[parseInt(s,16)>>6]+alphabet[parseInt(s,16)&63]).join('');
|
|
const textures = fs.readdirSync(path.join(root,'assets/coin_madness/texture'), { recursive: true }).map(n=>n.replaceAll('\\','/')).filter(n=>n.endsWith('.png') && fs.existsSync(path.join(root,'assets/coin_madness/texture',n+'.meta'))).map(file=>({file,...JSON.parse(fs.readFileSync(path.join(root,'assets/coin_madness/texture',file+'.meta')))}));
|
|
const frames=textures.map(t=>({texture:t,meta:t.subMetas[path.basename(t.file, '.png')]})).filter(f=>f.meta);
|
|
for (const file of fs.readdirSync(path.join(root,'assets/coin_madness/texture'), {recursive:true}).filter(f=>f.endsWith('.plist.meta'))) {
|
|
const atlasMeta=JSON.parse(fs.readFileSync(path.join(root,'assets/coin_madness/texture',file)));
|
|
frames.push(...Object.values(atlasMeta.subMetas).map(meta=>({texture:textures.find(t=>t.uuid===meta.rawTextureUuid),meta})));
|
|
}
|
|
const html = `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
|
|
<style>html,body{margin:0;width:100%;height:100%;overflow:hidden;background:#16394b}canvas{display:block}</style></head>
|
|
<body><canvas id="GameCanvas"></canvas><script src="/engine.js"></script><script src="/host.js"></script><script>
|
|
cc.assetManager.init({importBase:'/imports',nativeBase:'/native'});
|
|
cc.assetManager.loadBundle('/internal',error=>{if(error)throw error;
|
|
cc.game.run({id:'GameCanvas',debugMode:1,frameRate:30,renderMode:0,groupList:['default'],collisionMatrix:[[true]]},()=>{
|
|
cc.view.setDesignResolutionSize(720,1280,cc.ResolutionPolicy.SHOW_ALL);cc.view.resizeWithBrowserSize(true);
|
|
const scene=new cc.Scene(),canvas=new cc.Node('Canvas');scene.addChild(canvas);canvas.setContentSize(720,1280);
|
|
canvas.addComponent(cc.Canvas).designResolution=cc.size(720,1280);cc.director.runScene(scene);
|
|
const storage=new Map();cc.fx={GameConfig:{GM_INFO:{uid:'fixture',coin:1000,level:10}},StorageMessage:{getStorage:k=>storage.get(k),setStorage:(k,v)=>storage.set(k,v)},GameTool:{}};
|
|
window.demo={};
|
|
// The fixture serves the resident entry icon without loading the full resources bundle.
|
|
if(!cc.resources){const resources=new cc.AssetManager.Bundle();resources.init({name:'resources',paths:{},uuids:[],scenes:{},packs:{},versions:{import:[],native:[]}});}
|
|
const resourceLoad=cc.resources.load.bind(cc.resources);
|
|
cc.resources.load=(path,type,callback)=>path==='coin_madness_logo'
|
|
?cc.assetManager.loadRemote('/entry.png',(error,texture)=>callback(error,error?null:new cc.SpriteFrame(texture)))
|
|
:resourceLoad(path,type,callback);
|
|
const host=canvas.addComponent(cc.js.getClassByName('CoinMadnessHost'));
|
|
window.demo.open=()=>new Promise(resolve=>{host.open();const timer=setInterval(()=>{if(canvas.getChildByName('CoinMadness')?.getComponent('CoinMadnessPanel')?.data){clearInterval(timer);resolve();}},10);});
|
|
window.demo.close=()=>new Promise(resolve=>{host.close();cc.director.once(cc.Director.EVENT_AFTER_DRAW,resolve);});
|
|
window.demo.panel=()=>canvas.getChildByName('CoinMadness').getComponent('CoinMadnessPanel');
|
|
window.demo.action=(action,body={})=>demo.panel().run(action,body);
|
|
Object.defineProperty(demo,'data',{get:()=>demo.panel().data});
|
|
window.demo.snapshot=()=>({bundle:!!cc.assetManager.getBundle('coin_madness'),panels:canvas.children.filter(n=>n.name==='CoinMadness').length,assets:cc.assetManager.assets.count});
|
|
setTimeout(()=>{window.demo.ready=true;if(new URLSearchParams(location.search).has('open'))window.demo.open();},100);
|
|
});});</script></body></html>`;
|
|
function compile(file){return ts.transpileModule(fs.readFileSync(path.join(root,file),'utf8'),{compilerOptions:{target:ts.ScriptTarget.ES5,module:ts.ModuleKind.CommonJS}}).outputText;}
|
|
const server = http.createServer((req,res)=>{
|
|
const url = req.url.split('?')[0].replace(/^\/assets\//, '/');
|
|
if(url==='/favicon.ico'){res.statusCode=204;return res.end();}
|
|
if(url==='/entry.png'){res.setHeader('Content-Type','image/png');return fs.createReadStream(path.join(root,'assets/resources/coin_madness_logo.png')).pipe(res);}
|
|
if(url==='/'){res.setHeader('Content-Type','text/html; charset=utf-8');return res.end(html);}
|
|
if(url==='/engine.js'){res.setHeader('Content-Type','text/javascript');return fs.createReadStream(engine).pipe(res);}
|
|
if(url==='/host.js'){
|
|
const source=fs.readFileSync(path.join(root,'assets/Script/coin_madness/CoinMadnessHost.ts'),'utf8');
|
|
const output=ts.transpileModule(source,{compilerOptions:{target:ts.ScriptTarget.ES5,module:ts.ModuleKind.CommonJS,experimentalDecorators:true}}).outputText;
|
|
res.setHeader('Content-Type','text/javascript');return res.end('(function(){var exports={};function require(name){if(name.includes("GoldMinerService"))return {default:{testEnabled:()=>!!window.testService?.testAvailable(),current:()=>window.testService||null}};if(name.includes("Utils"))return {default:{serverUrl:()=>"fixture://"}};if(name.includes("MiniGameSdk"))return {MiniGameSdk:{API:{showToast:console.log}}};return {default:{get:()=>({enqueue:(k,p,run)=>run(()=>{})})}};}cc._RF.push({},"CoinMadnessHost","CoinMadnessHost");'+output+';cc._RF.pop();})();');
|
|
}
|
|
if(/^\/native\/[a-f0-9]{2}\/[a-f0-9-]+\.png$/.test(url)){
|
|
const target=path.join(root,'library/imports',url.slice('/native/'.length));
|
|
if(fs.existsSync(target)){res.setHeader('Content-Type','image/png');return fs.createReadStream(target).pipe(res);}
|
|
}
|
|
if(/^\/imports\/[a-f0-9]{2}\/[a-f0-9-]+\.json$/.test(url)){
|
|
const target=path.join(root,'library',url.slice(1));
|
|
if(fs.existsSync(target)){res.setHeader('Content-Type','application/json');return fs.createReadStream(target).pipe(res);}
|
|
const config=JSON.parse(fs.readFileSync(path.join(creator,'resources/cocos2d-x/simulator/win32/assets/internal/config.json')));
|
|
const id=path.basename(url,'.json'), entry=config.paths[id];
|
|
if(entry && entry[1]==='cc.Material'){
|
|
const material=path.join(creator,'resources/static/default-assets/resources',entry[0]+'.mtl');
|
|
if(fs.existsSync(material)){res.setHeader('Content-Type','application/json');return fs.createReadStream(material).pipe(res);}
|
|
}
|
|
}
|
|
if(url.startsWith('/internal/')){
|
|
const base=path.join(creator,'resources/cocos2d-x/simulator/win32/assets/internal');
|
|
const target=path.resolve(base,url.slice('/internal/'.length));
|
|
if(!target.startsWith(base+path.sep)||!fs.existsSync(target)){res.statusCode=404;return res.end();}
|
|
res.setHeader('Content-Type',target.endsWith('.json')?'application/json':target.endsWith('.js')?'text/javascript':'application/octet-stream');
|
|
return fs.createReadStream(target).pipe(res);
|
|
}
|
|
if(url==='/coin_madness/config.json'){res.setHeader('Content-Type','application/json');return res.end(JSON.stringify({name:'coin_madness',debug:true,importBase:'import',nativeBase:'native',deps:[],uuids:[uuid,helpUuid,settlementUuid,...textures.map(t=>t.uuid),...frames.map(f=>f.meta.uuid)],paths:{[settlementUuid]:['prefab/CoinMadnessSettlement','cc.Prefab'],[uuid]:['prefab/CoinMadness','cc.Prefab'],[helpUuid]:['prefab/CoinMadnessHelp','cc.Prefab'],...Object.fromEntries(textures.map(t=>[t.uuid,['texture/'+t.file.slice(0,-4),'cc.Texture2D']])),...Object.fromEntries(frames.map(f=>[f.meta.uuid,['texture/'+f.texture.file.slice(0,-4),'cc.SpriteFrame']]))},scenes:{},packs:{},versions:{import:[],native:[]}}));}
|
|
const frame=frames.find(f=>url==='/coin_madness/import/'+f.meta.uuid.slice(0,2)+'/'+f.meta.uuid+'.json');
|
|
if(frame){const m=frame.meta;res.setHeader('Content-Type','application/json');return res.end(JSON.stringify({__type__:'cc.SpriteFrame',content:{name:frame.texture.file.slice(0,-4),texture:frame.texture.uuid,rect:[m.trimX||0,m.trimY||0,m.width,m.height],offset:[0,0],originalSize:[m.width,m.height],capInsets:[m.borderLeft,m.borderTop,m.borderRight,m.borderBottom]}}));}
|
|
const texture=textures.find(t=>url==='/coin_madness/import/'+t.uuid.slice(0,2)+'/'+t.uuid+'.json'||url==='/coin_madness/native/'+t.uuid.slice(0,2)+'/'+t.uuid+'.png');
|
|
if(texture){
|
|
if(url.endsWith('.png')){res.setHeader('Content-Type','image/png');return res.end(fs.readFileSync(path.join(root,'assets/coin_madness/texture',texture.file)));}
|
|
res.setHeader('Content-Type','application/json');return res.end(JSON.stringify({__type__:'cc.Texture2D',content:'0,9729,9729,33071,33071,0,0,1'}));
|
|
}
|
|
if(url==='/coin_madness/index.js'){
|
|
const source=fs.readFileSync(path.join(root,'assets/coin_madness/script/CoinMadnessPanel.ts'),'utf8');
|
|
const output=ts.transpileModule(source,{compilerOptions:{target:ts.ScriptTarget.ES5,module:ts.ModuleKind.CommonJS,experimentalDecorators:true}}).outputText;
|
|
const settlement = ts.transpileModule(fs.readFileSync(path.join(root,'assets/coin_madness/script/CoinMadnessSettlement.ts'),'utf8'),{compilerOptions:{target:ts.ScriptTarget.ES5,module:ts.ModuleKind.CommonJS,experimentalDecorators:true}}).outputText;
|
|
const settlementHex = JSON.parse(fs.readFileSync(path.join(root,'assets/coin_madness/script/CoinMadnessSettlement.ts.meta'))).uuid.replaceAll('-','');
|
|
const settlementId = settlementHex.slice(0,5)+settlementHex.slice(5).match(/.{3}/g).map(s=>alphabet[parseInt(s,16)>>6]+alphabet[parseInt(s,16)&63]).join('');
|
|
const digits=ts.transpileModule(fs.readFileSync(path.join(root,'assets/coin_madness/script/CoinMadnessDigits.ts'),'utf8'),{compilerOptions:{target:ts.ScriptTarget.ES5,module:ts.ModuleKind.CommonJS,experimentalDecorators:true}}).outputText;
|
|
const digitHex=JSON.parse(fs.readFileSync(path.join(root,'assets/coin_madness/script/CoinMadnessDigits.ts.meta'))).uuid.replaceAll('-','');
|
|
const digitId=digitHex.slice(0,5)+digitHex.slice(5).match(/.{3}/g).map(s=>alphabet[parseInt(s,16)>>6]+alphabet[parseInt(s,16)&63]).join('');
|
|
res.setHeader('Content-Type','text/javascript');return res.end('(function(){var digits=(function(){var exports={};cc._RF.push({},'+JSON.stringify(digitId)+',"CoinMadnessDigits");'+digits+';cc._RF.pop();return exports;})();function require(name){return name.includes("Digits")?digits:name.includes("BrownLoadingSpinner")?spinner:{};}var spinner=(function(){var exports={};'+compile('assets/Script/BrownLoadingSpinner.ts')+';return exports;})();var exports={};cc._RF.push({},'+JSON.stringify(scriptId)+',"CoinMadnessPanel");'+output+';cc._RF.pop();var exports={};cc._RF.push({},'+JSON.stringify(settlementId)+',"CoinMadnessSettlement");'+settlement+';cc._RF.pop();})();');
|
|
}
|
|
if(url==='/coin_madness/import/'+helpUuid.slice(0,2)+'/'+helpUuid+'.json'){res.setHeader('Content-Type','application/json');return res.end(fs.readFileSync(path.join(root,'assets/coin_madness/prefab/CoinMadnessHelp.prefab')));}
|
|
if(url==='/coin_madness/import/'+settlementUuid.slice(0,2)+'/'+settlementUuid+'.json'){res.setHeader('Content-Type','application/json');return res.end(fs.readFileSync(path.join(root,'assets/coin_madness/prefab/CoinMadnessSettlement.prefab')));}
|
|
if(url==='/coin_madness/import/'+uuid.slice(0,2)+'/'+uuid+'.json'){
|
|
res.setHeader('Content-Type','application/json');return res.end(fs.readFileSync(path.join(root,'assets/coin_madness/prefab/CoinMadness.prefab')));
|
|
}
|
|
res.statusCode=404;res.end('Not found');
|
|
});
|
|
server.listen(Number(process.env.PORT)||8765,'127.0.0.1',()=>console.log('Coin Madness fixture: http://127.0.0.1:'+server.address().port));
|