You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

extractByNode.js 8.5 kB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. const fs = require('fs');
  2. const crypto = require('crypto');
  3. const Card = require('./official-API/parseCard');
  4. const Skill = require('./official-API/parseSkill');
  5. const runDate = new Date();
  6. const officialAPI = [ //来源于官方API
  7. {
  8. code:"ja",
  9. customName:["cht","chs"]
  10. },
  11. {
  12. code:"en",
  13. customName:[]
  14. },
  15. {
  16. code:"ko",
  17. customName:[]
  18. }
  19. ];
  20. //比较两只怪物是否是同一只(在不同语言服务器)
  21. function sameCard(m1,m2)
  22. {
  23. if (m1 == undefined || m2 == undefined) return false; //是否存在
  24. if (m1.attrs[0] != m2.attrs[0]) return false; //主属性
  25. if (m1.attrs[1] != m2.attrs[1]) return false; //副属性
  26. if (m1.types.length != m2.types.length) return false; //类型长度
  27. if (m1.types.some(function(t1,ti){
  28. return m2.types[ti] == undefined || m2.types[ti] != t1;
  29. })) return false; //全部类型有任意不同的时候也返回false
  30. if (m1.maxLevel != m2.maxLevel) return false; //最大等级
  31. if (m1.collabId != m2.collabId) return false; //合作ID
  32. return true;
  33. }
  34. /*
  35. * 正式流程
  36. */
  37. officialAPI.forEach(function(lang) {
  38. console.log("正在读取官方 %s 信息",lang.code);
  39. const cardJson = fs.readFileSync("official-API/" + lang.code +"-card.json", 'utf-8'); //使用同步读取怪物
  40. const cardJsonObj = JSON.parse(cardJson);
  41. const oCards = lang.cardOriginal = cardJsonObj.card;//将字符串转换为json对象
  42. const monCards = lang.cards = [];
  43. /*oCards.forEach((oCard, idx)=>{
  44. let mid = oCard[0];
  45. if (mid === idx) //原始怪物
  46. {
  47. monCards.push(new Card(oCard));
  48. }else
  49. {
  50. const nCard = monCards[mid % 100000];
  51. if (!nCard.specialVersion) nCard.specialVersion = {};
  52. nCard.specialVersion[Math.floor(mid / 100000)] = new Card(oCard);
  53. }
  54. });*/
  55. for (let cardIndex = 0; oCards[cardIndex][0] === cardIndex; cardIndex++)
  56. {
  57. monCards.push(new Card(oCards[cardIndex]));
  58. }
  59. //加入自定义的语言
  60. lang.customName.forEach(function(lcode){
  61. console.log("正在读取自定义 " + lcode + " 信息");
  62. const ljson = fs.readFileSync("custom/" + lcode +".json", 'utf-8'); //使用同步读取
  63. const ccard = JSON.parse(ljson);//将字符串转换为json对象
  64. ccard.forEach(function(cm){ //每个文件内的名字循环
  65. let m = monCards[cm.id];
  66. if (m)
  67. {
  68. if (!m.otLangName) //如果没有其他语言名称属性,则添加一个对象属性
  69. m.otLangName = {};
  70. m.otLangName[lcode] = cm.name;
  71. if (!m.otTags) //如果没有其他语言名称属性,则添加一个对象属性
  72. m.otTags = [];
  73. let newTags = Array.from(new Set(cm.tags));
  74. newTags = newTags.filter(tag=>!m.altName.includes(tag) && !m.otTags.includes(tag));
  75. m.otTags.push(...newTags);
  76. }
  77. });
  78. });
  79. const skillJson = fs.readFileSync("official-API/" + lang.code +"-skill.json", 'utf-8'); //使用同步读取技能
  80. const skillJsonObj = JSON.parse(skillJson);
  81. const oSkills = lang.skillOriginal = skillJsonObj.skill;//将字符串转换为json对象
  82. lang.skills = oSkills.map((oc,idx)=>new Skill(idx,oc)); //每一项生成分析对象
  83. lang.cards.forEach((m,idx,arr)=>{
  84. const skill = lang.skills[m.activeSkillId];
  85. let henshinTo = null;
  86. const searchType = 202;
  87. if (skill.type == searchType)
  88. henshinTo = skill.params[0];
  89. else if (skill.type == 116 || skill.type == 118){
  90. const subskill = skill.params.map(id=>lang.skills[id]).find(subskill=>subskill.type == searchType);
  91. if (subskill)
  92. henshinTo = subskill.params[0];
  93. }
  94. if (henshinTo)
  95. {
  96. m.henshinTo = henshinTo;
  97. arr[henshinTo].henshinFrom = idx;
  98. }
  99. });
  100. });
  101. //加入其他服务器相同角色的名字
  102. for (let li = 0;li < officialAPI.length; li++)
  103. {
  104. const otherLangs = officialAPI.concat(); //复制一份原始数组,储存其他语言
  105. const lang = otherLangs.splice(li,1)[0]; //删掉并取得当前的语言
  106. const langCard = lang.cards;
  107. const langCardCount = langCard.length;
  108. for (let mi=0; mi<langCardCount; mi++)
  109. {
  110. const m = langCard[mi];
  111. const name = m.name; //当前语言的名字
  112. //名字对象
  113. otherLangs.forEach((otLang)=>{
  114. let _m = otLang.cards[mi]; //获得这种其他语言的当前这个怪物数据
  115. let isSame = sameCard(m,_m); //与原语言怪物是否是同一只
  116. const l1 = lang.code, l2 = otLang.code;
  117. if (!isSame && //如果不同时,判断特殊情况
  118. (
  119. l1 == 'ja' && (l2 == 'en' || l2 == 'ko') ||
  120. l2 == 'ja' && (l1 == 'en' || l1 == 'ko')
  121. )
  122. )
  123. { //当同id两者不同,日服和英韩服比较时的一些人工确认相同的特殊id差异卡片
  124. const langIsJa = l1 == 'ja' ? true : false; //原始语言是否是日语
  125. let diff = 0; //日语和其它语言的id差异
  126. switch(true)
  127. {
  128. case (langIsJa && mi>=671 && mi<= 680) ||
  129. (!langIsJa && mi>=1049 && mi<= 1058):
  130. //神罗 日服 671-680 等于英韩服 1049-1058
  131. diff = 378;
  132. break;
  133. case (langIsJa && mi>=669 && mi<= 670) ||
  134. (!langIsJa && mi>=934 && mi<= 935):
  135. //神罗 日服 669-670 等于英韩服 934-935
  136. diff = 265;
  137. break;
  138. case (langIsJa && mi>=924 && mi<= 935) ||
  139. (!langIsJa && mi>=669 && mi<= 680):
  140. //蝙蝠侠 日服 924-935 等于英韩服 669-680
  141. diff = -255;
  142. break;
  143. case (langIsJa && mi>=1049 && mi<= 1058) ||
  144. (!langIsJa && mi>=924 && mi<= 933):
  145. //蝙蝠侠 日服 1049-1058 等于英韩服 924-933
  146. diff = -125;
  147. break;
  148. }
  149. if (diff != 0)
  150. {
  151. _m = langIsJa ? otLang.cards[mi + diff] : otLang.cards[mi - diff];
  152. isSame = true;
  153. }
  154. }
  155. if (_m && isSame) //如果有这个怪物,且与原语言怪物是同一只
  156. {
  157. const otName = _m.name;
  158. if (/^(?:\?+|\*+|초월\s*\?+)/i.test(otName)) //名字以问号、星号、韩文的问号开头
  159. {
  160. return; //跳过
  161. }else
  162. {
  163. if (!m.otLangName) //如果没有其他语言名称属性,则添加一个对象属性
  164. m.otLangName = {};
  165. m.otLangName[otLang.code] = otName;
  166. if (_m.otLangName)
  167. { //增加储存当前语言的全部其他语言
  168. Object.entries(_m.otLangName).forEach(entry=>{
  169. const lcode = entry[0];
  170. if (lcode != l1 && !Object.keys(m.otLangName).includes(lcode)) //如果不是本来的的语言
  171. m.otLangName[lcode] = entry[1];
  172. });
  173. }
  174. }
  175. if (!m.otTags) //如果没有其他语言标签属性,则添加一个数组属性
  176. m.otTags = [];
  177. let otTags = Array.from(new Set(_m.otTags ? _m.altName.concat(_m.otTags) : _m.altName));
  178. otTags = otTags.filter(tag=>!m.altName.includes(tag) && !m.otTags.includes(tag));
  179. m.otTags.push(...otTags);
  180. }
  181. });
  182. }
  183. }
  184. var newCkeyObjs = officialAPI.map(lang=>{
  185. const lcode = lang.code;
  186. const cardStr = JSON.stringify(lang.cards);
  187. const skillStr = JSON.stringify(lang.skills);
  188. //写入Cards
  189. fs.writeFile(`./mon_${lcode}.json`,cardStr,function(err){
  190. if(err){
  191. console.error(err);
  192. }
  193. console.log(`mon_${lcode}.json 导出成功`);
  194. });
  195. //写入Skills
  196. fs.writeFile(`./skill_${lcode}.json`,skillStr,function(err){
  197. if(err){
  198. console.error(err);
  199. }
  200. console.log(`skill_${lcode}.json 导出成功`);
  201. });
  202. const cardHash = crypto.createHash('md5');
  203. const skillHash = crypto.createHash('md5');
  204. cardHash.update(cardStr, 'utf8');
  205. skillHash.update(skillStr, 'utf8');
  206. const ckeyOutObj = {
  207. code: lcode,
  208. ckey: {
  209. card: cardHash.digest('hex'),
  210. skill: skillHash.digest('hex'),
  211. },
  212. updateTime: runDate.getTime(),
  213. };
  214. return ckeyOutObj;
  215. });
  216. //读取旧的ckeyObj
  217. var ckeyObjs;
  218. fs.readFile('./ckey.json','utf-8',function(err,data){
  219. if(err)
  220. { //如果读取错误,直接使用全新ckey
  221. ckeyObjs = newCkeyObjs;
  222. } else
  223. { //如果读取正确,则读入JSON,并判断是否和旧有的一致
  224. ckeyObjs = JSON.parse(data);
  225. for (let ci=0;ci<ckeyObjs.length;ci++)
  226. {
  227. const oldCkey = ckeyObjs[ci];
  228. const newCkey = newCkeyObjs.find(nckey=>nckey.code === oldCkey.code);
  229. if (newCkey && (oldCkey.ckey.card != newCkey.ckey.card || oldCkey.ckey.skill != newCkey.ckey.skill))
  230. {
  231. ckeyObjs[ci] = newCkey;
  232. }
  233. }
  234. }
  235. fs.writeFile('./ckey.json',JSON.stringify(ckeyObjs),function(err){
  236. if(err){
  237. console.error(err);
  238. }
  239. console.log('ckey.json 导出成功');
  240. });
  241. });

智龙迷城队伍图制作工具