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

2041 lines
53 KiB

  1. require("luaScript.Tools.EvalServerScript");
  2. require("luaScript.Tools.List")
  3. require("luaScript.Tools.ConfigConverter");
  4. bit32 = bit32 or require("bit")
  5. -- 异或
  6. function getNumXor(num1, num2)
  7. local ret=bit32.bxor(num1,num2);
  8. return ret;
  9. end
  10. --或
  11. function getNumOr(num1,num2)
  12. local ret=bit32.bor(num1,num2);
  13. return ret;
  14. end
  15. --与
  16. function getNumBand(num1,num2)
  17. local ret=bit32.band(num1,num2);
  18. return ret;
  19. end
  20. --取反
  21. function getNumNot(num1,num2)
  22. local ret=bit32.bnot(num1,num2);
  23. return ret;
  24. end
  25. -- 格式化时间函数, 把以秒为单位的数字转换成
  26. -- {day = num, hours = num, min = num, second = num的形式}
  27. function formatTime(second)
  28. if second < 0 then
  29. return { day = 0; hours = 0; min = 0; second = 0;};
  30. end;
  31. local t = {};
  32. t.day = math.floor(second / 86400);
  33. second = second % 86400;
  34. t.hours = math.floor(second / 3600);
  35. second = second % 3600;
  36. t.min = math.floor(second / 60);
  37. t.second = second % 60;
  38. return t;
  39. end
  40. --返回的时间表格式化一下
  41. function formatTime2(second)
  42. local t = formatTime(second);
  43. t.hours = string.format("%02d",t.hours);
  44. t.min = string.format("%02d",t.min);
  45. t.second = string.format("%02d",t.second);
  46. return t;
  47. end
  48. -- 格式化时间成字符串
  49. -- 如果是1秒则返回是01
  50. -- 返回的是xx:xx:xx:xx:xx
  51. function formatTimeToStr(second)
  52. local data = formatTime(second)
  53. if data.day > 0 then
  54. return string.format("%.2d天%.2d:%.2d:%.2d", data.day, data.hours, data.min, data.second)
  55. elseif data.hours > 0 then
  56. return string.format("%.2d:%.2d:%.2d", data.hours, data.min, data.second)
  57. else
  58. return string.format("%.2d:%.2d", data.min, data.second)
  59. end
  60. end
  61. -- 格式化时间成字符串,排行榜格式
  62. function formatTimeToRankStr(second)
  63. local data = formatTime(second)
  64. if data.day > 0 then
  65. return string.format(LN.SEASON_TIME_DAY_HOUR, data.day, data.hours)
  66. elseif data.hours > 0 then
  67. return string.format(LN.SEASON_TIME_HOUR, data.hours)
  68. elseif data.min > 0 then
  69. return string.format(LN.SEASON_TIME_MINUTE, data.min)
  70. else
  71. return string.format(LN.SEASON_TIME_SECOND, data.second)
  72. end
  73. end
  74. -- 获取今天的日期,返回的结果格式是"2017-12-23"
  75. function getTodayString()
  76. local t = os.time()
  77. local d = os.date('*t', t)
  78. local str = string.format("%04d-%02d-%02d", d.year, d.month, d.day);
  79. return str;
  80. end
  81. -- AES 128/ECB/PKCS5Padding加密
  82. function AES_encode(postData, aesKey)
  83. if postData == nil or aesKey == nil then
  84. return ""
  85. end
  86. local jsonData = json.encode(postData);
  87. --print("加密前的数据", table.tostring(jsonData))
  88. -- 使用aes加密
  89. local aesData = aes.encode(aesKey, jsonData)
  90. local base64Data = base64.encode(aesData)
  91. --print("加密后的数据", base64Data)
  92. return base64Data
  93. end
  94. -- AES 128/ECB/PKCS5Padding解密
  95. function AES_decode(data, aesKey)
  96. if data == nil or aesKey == nil then
  97. return ""
  98. end
  99. --print("解密前的原始数据", data)
  100. local jsonData = json.decode(aes.decode(aesKey, base64.decode(data)));
  101. --print("解密后的jsonData", table.tostring(jsonData))
  102. return jsonData
  103. end
  104. -- 把123#123格式转换成ccp(123,123)
  105. function toPosition(str)
  106. local numberArray = toNumberArray("#")(str)
  107. if #numberArray ~= 2 then
  108. return cc.p(0,0)
  109. else
  110. return cc.p(numberArray[1] , numberArray[2]);
  111. end
  112. end
  113. -- 传入一个相机和屏幕的像素位置,获取xz平面的一个世界位置
  114. function convertScreenToWorldPos(Camera, ScreenX, ScreenY)
  115. local floorPlane = cc.Plane:new(cc.vec3(0,1,0) , 0);
  116. -- 计算出mainlayer的世界位置
  117. local screenSize = cc.Director:getInstance():getWinSizeInPixels();
  118. local ray = Camera:pickRay(ScreenX / screenSize.width , ScreenY / screenSize.height);
  119. local distance = ray:intersectsPlane(floorPlane);
  120. if distance >= 0 then
  121. return ray:getPoint(distance);
  122. end
  123. return ray:getPoint(0);
  124. end
  125. -- 根据一个世界位置和一个相机计算投影后的位置
  126. function projectPosByWorldPos(camera, worldPos)
  127. local screenSize = cc.Director:getInstance():getWinSizeInPixels()
  128. -- 获取对应的屏幕位置
  129. local clientPos = camera:project(cc.Rectangle:new(screenSize.width, screenSize.height), worldPos);
  130. return cc.p(clientPos.x, screenSize.height - clientPos.y);
  131. end
  132. -- 创建顺序播放的动画序列
  133. function createActionArray(...)
  134. local arg = {...}
  135. if #arg == 1 then
  136. local v = arg[1];
  137. if type(v) == "function" then
  138. return cc.CallFunc:create(v);
  139. else
  140. return v;
  141. end
  142. else
  143. local action = nil;
  144. local actionArray = {};
  145. for i,v in ipairs(arg) do
  146. if type(v) == "function" then
  147. table.insert(actionArray , cc.CallFunc:create(v));
  148. else
  149. table.insert(actionArray , v);
  150. end
  151. end
  152. local action = cc.Sequence:create(actionArray);
  153. return action;
  154. end
  155. end
  156. -- 创建同时播放的动画序列
  157. function createSpawnActions(...)
  158. local arg = {...}
  159. if #arg == 1 then
  160. local v = arg[1];
  161. if type(v) == "function" then
  162. return cc.CallFunc:create(v);
  163. else
  164. return v;
  165. end
  166. else
  167. local action = nil;
  168. local actionArray = {};
  169. for i,v in ipairs(arg) do
  170. if type(v) == "function" then
  171. table.insert(actionArray , cc.CallFunc:create(v));
  172. else
  173. table.insert(actionArray , v);
  174. end
  175. end
  176. local action = cc.Spawn:create(actionArray);
  177. return action;
  178. end
  179. end
  180. -- 创建动态时间动画序列
  181. function createDynamicTimeActionArray(...)
  182. local arg = {...}
  183. if #arg == 1 then
  184. local v = arg[1];
  185. if type(v) == "function" then
  186. return cc.CallFunc:create(v);
  187. else
  188. return v;
  189. end
  190. else
  191. local action = nil;
  192. local actionArray = {};
  193. for i,v in ipairs(arg) do
  194. if type(v) == "function" then
  195. table.insert(actionArray , cc.CallFunc:create(v));
  196. else
  197. table.insert(actionArray , v);
  198. end
  199. end
  200. local action = cc.DynamicTimeSequence:create(actionArray);
  201. return action;
  202. end
  203. end
  204. -- 尚未实现的弹出提示
  205. function onImplementClick()
  206. showTooltip(RT("not implement"));
  207. end
  208. EaseType =
  209. {
  210. [1] = function(action , param)return action end,
  211. [2] = function(action , param)return cc.EaseRateAction:create(action , param) end,
  212. [3] = function(action , param)return cc.EaseIn:create(action , param) end,
  213. [4] = function(action , param)return cc.EaseOut:create(action , param) end,
  214. [5] = function(action , param)return cc.EaseInOut:create(action , param) end,
  215. [6] = function(action , param)return cc.EaseExponentialIn:create(action) end,
  216. [7] = function(action , param)return cc.EaseExponentialOut:create(action) end,
  217. [8] = function(action , param)return cc.EaseExponentialInOut:create(action) end,
  218. [9] = function(action , param)return cc.EaseSineIn:create(action) end,
  219. [10] = function(action , param)return cc.EaseSineOut:create(action) end,
  220. [11] = function(action , param)return cc.EaseSineInOut:create(action) end,
  221. [12] = function(action , param)return cc.EaseElastic:create(action , param) end,
  222. [13] = function(action , param)return cc.EaseElasticIn:create(action , param) end,
  223. [14] = function(action , param)return cc.EaseElasticOut:create(action , param) end,
  224. [15] = function(action , param)return cc.EaseElasticInOut:create(action , param) end,
  225. [16] = function(action , param)return cc.EaseBounce:create(action) end,
  226. [17] = function(action , param)return cc.EaseBounceIn:create(action) end,
  227. [18] = function(action , param)return cc.EaseBounceOut:create(action) end,
  228. [19] = function(action , param)return cc.EaseBounceInOut:create(action) end,
  229. [20] = function(action , param)return cc.EaseBackIn:create(action) end,
  230. [21] = function(action , param)return cc.EaseBackOut:create(action) end,
  231. [22] = function(action , param)return cc.EaseBackInOut:create(action) end,
  232. }
  233. --[[
  234. 创建节点的淡入淡出效果
  235. --]]
  236. function createEaseAction(easeType , param , action)
  237. local easeFunction = EaseType[easeType];
  238. if easeFunction then
  239. return easeFunction(action , param);
  240. else
  241. return action;
  242. end
  243. end
  244. -- 创建震动Action
  245. -- @rate 频率 每秒多少次
  246. -- @range 振动幅度 {x=10, y=0} 左右振动10像素,上下振动0像素
  247. -- @times 播放次数,-1表示无限
  248. function createShakeAction(rate , range , times)
  249. -- 每次所需时间
  250. local oneSeconds = 1 / rate / 4;
  251. local oneShakeAction = createActionArray(cc.EaseSineOut:create(cc.MoveBy:create(oneSeconds , cc.p(-range.width / 2 , -range.height / 2)))
  252. , cc.EaseSineInOut:create(cc.MoveBy:create(oneSeconds * 2 , cc.p(range.width , range.height)))
  253. , cc.EaseSineIn:create(cc.MoveBy:create(oneSeconds , cc.p(-range.width / 2 , -range.height / 2)))
  254. )
  255. if times == -1 then
  256. return cc.RepeatForever:create(oneShakeAction);
  257. else
  258. return cc.Repeat:create(oneShakeAction , times);
  259. end
  260. end
  261. -- 创建旋转Action
  262. -- @roundPerSecond 每秒转动多少圈
  263. -- @rounds 需要旋转多少圈,-1则无限
  264. -- @reverse 是否反方向旋转
  265. function createRotationAction(roundPerSecond , rounds , reverse)
  266. local angle;
  267. if reverse then
  268. angle = -360;
  269. else
  270. angle = 360;
  271. end
  272. local action = cc.RotateBy:create(1 / roundPerSecond , angle);
  273. if rounds == -1 then
  274. return cc.RepeatForever:create(action);
  275. else
  276. return cc.Repeat:create(action , rounds);
  277. end
  278. end
  279. -- 创建旋转Action
  280. -- @angle 旋转多少度
  281. -- @speed 每秒转动多少度
  282. function createRotationReverseAction(angle , speed , easeType , easeParam)
  283. local oneRoundTime = math.abs(angle) / speed;
  284. return createEaseAction(easeType , easeParam , createActionArray(cc.RotateBy:create(oneRoundTime , angle) , cc.RotateBy:create(oneRoundTime , -angle)));
  285. end
  286. -- 创建缩放Action
  287. -- @scale 放大到多少
  288. -- @seconds 动画时长
  289. function createScaleReverseAction(scale , seconds , easeType , easeParam)
  290. return createEaseAction(easeType , easeParam , createActionArray(cc.ScaleTo:create(seconds / 2 , scale) , cc.ScaleTo:create(seconds / 2 , 1)));
  291. end
  292. -- 在下一帧执行一次函数func
  293. function runInNextFrame(func , ...)
  294. local arg = {...}
  295. local function exec()
  296. func(unpack(arg));
  297. end
  298. cc.Director:getInstance():getScheduler():performFunctionInCocosThread(exec)
  299. end
  300. -- 延迟delaySeconds这么多秒后执行
  301. function runDelay(delaySeconds, func , ...)
  302. local id
  303. local arg = {...}
  304. local function unschedule()
  305. if id then
  306. cc.Director:getInstance():getScheduler():unscheduleScriptEntry(id);
  307. id = nil;
  308. end
  309. end
  310. local function exec()
  311. if id then
  312. cc.Director:getInstance():getScheduler():unscheduleScriptEntry(id);
  313. id = nil;
  314. end
  315. func(unpack(arg));
  316. end
  317. id = cc.Director:getInstance():getScheduler():scheduleScriptFunc(exec, delaySeconds, false)
  318. return unschedule;
  319. end
  320. -- 在下一帧延迟多少秒后执行
  321. function runDelayInNextFrame(delaySeconds, func)
  322. local function nextFrameFunc()
  323. runDelay(delaySeconds, func)
  324. end
  325. runInNextFrame(nextFrameFunc)
  326. end
  327. -- 使当前页面在屏幕居中
  328. function centerWindow(ui)
  329. local size = ui:getContentSize();
  330. local sizeScreen = cc.Director:getInstance():getWinSize();
  331. ui:setPosition(ui.Parent:convertToNodeSpace(ccp((sizeScreen.width - size.width) / 2 , (sizeScreen.height - size.height) / 2)));
  332. end
  333. -- 把字符串替换成replaceTable中的词义
  334. function replaceStringByTable(str , replaceTable)
  335. local newString = str;
  336. for i , v in pairs(replaceTable) do
  337. if type(v) == "string" or type(v) == "number" then
  338. local newV = string.gsub(v , "%%" , "%%%%");
  339. newString = string.gsub(newString , "%[" .. i .. "%]" , newV);
  340. end
  341. end
  342. return newString;
  343. end
  344. -- 创建一个下划线按钮
  345. -- @title 名字
  346. -- @fontSize 字体大小
  347. -- @color 字体颜色
  348. -- @onClick 点击回调的函数
  349. function createLabelButtonHtmlText(title, fontSize, color, onClick)
  350. if not title then
  351. return "";
  352. end
  353. local function createLuaControl()
  354. local label = cc.Label:createWithTTF(title, "res/default/msyh.ttc" , fontSize);
  355. local size = label:getContentSize();
  356. local layer = cc.Layer:create();
  357. layer:setContentSize(label:getContentSize());
  358. local ui = loadUI("res/ui/ui_tongyong/tongyong_xiahuaxian.ui")
  359. ui.Items.HtmlCtrl_wenzi:setText(title);
  360. ui.Items.HtmlCtrl_wenzi:setColor(color);
  361. ui.Items.Layout_1:setTouchEnabled(true);
  362. ui.Items.Layout_1:registerClick(onClick);
  363. local lineSize = ui.Items.Layout_xian:getSize()
  364. ui.Items.Layout_xian:setSize(cc.size(size.width, lineSize.height))
  365. ui.Items.Layout_xian:setBackGroundColor(color)
  366. layer:addChild(ui)
  367. return layer
  368. end
  369. return "<lua create=\"" .. functionToString(createLuaControl) .. "\"/>";
  370. end
  371. -- str 格式这样 r_g_b_a 255_232_139_255
  372. function stringToColorWithSeparate(str)
  373. local colorStr = string.split(str, "_");
  374. if(#colorStr==3)then
  375. local color = cc.c3b(tonumber(colorStr[1]),tonumber(colorStr[2]),tonumber(colorStr[3]));
  376. return color;
  377. elseif(#colorStr==4)then
  378. local color = cc.c4b(tonumber(colorStr[1]),tonumber(colorStr[2]),tonumber(colorStr[3]),tonumber(colorStr[3]));
  379. return color;
  380. end
  381. end
  382. function createLabelButtonHtmlText2(title, color, onClick)
  383. if not title then
  384. return "";
  385. end
  386. local function createLuaControl()
  387. local label = cc.HtmlCtrl:create()
  388. label:setAutoSize(true);
  389. label:setText(title);
  390. local size = label:getContentSize();
  391. local layer = cc.Layer:create();
  392. layer:setContentSize(label:getContentSize());
  393. local ui = loadUI("res/ui/ui_tongyong/tongyong_xiahuaxian.ui")
  394. ui.Items.HtmlCtrl_wenzi:setText(title);
  395. ui.Items.Layout_1:setTouchEnabled(true);
  396. ui.Items.Layout_1:registerClick(onClick);
  397. local lineSize = ui.Items.Layout_xian:getSize()
  398. ui.Items.Layout_xian:setSize(cc.size(size.width, lineSize.height))
  399. ui.Items.Layout_xian:setBackGroundColor(color)
  400. layer:addChild(ui)
  401. return layer
  402. end
  403. return "<lua create=\"" .. functionToString(createLuaControl) .. "\"/>";
  404. end
  405. -- 显示退出确认对话框
  406. function showExitDialog(text)
  407. local function onOk(id)
  408. cc.Director:getInstance():endToLua();
  409. end
  410. local function onCancel()
  411. end
  412. showConfirmDialog(text, onOk, onCancel)
  413. end
  414. -- 重启游戏
  415. function restartGame()
  416. cc.Application:getInstance():restart();
  417. end
  418. -- 显示重启确认对话框
  419. function showRestartDialog(text)
  420. local function onOk()
  421. restartGame();
  422. end
  423. local function onCancel()
  424. end
  425. showConfirmDialog(text, onOk, onCancel)
  426. end
  427. local XmlFilter =
  428. {
  429. ["<"] = "&lt;";
  430. [">"] = "&gt;";
  431. ["&"] = "&amp;";
  432. ["'"] = "&apos;";
  433. ["\""] = "&quot;";
  434. }
  435. local function replaceIt(c)
  436. return XmlFilter[c] or c;
  437. end
  438. -- 把XML转义符全部替换
  439. function replaceXmlByFilter(str)
  440. return string.gsub(str , "[%&%>%<%'%\"]" , replaceIt);
  441. end
  442. --[[
  443. -- 获取首个屏蔽字出现的位置和结束位置
  444. -- 没有屏蔽字出现则返回nil, nil;
  445. function findMaskWord(str)
  446. local wordList = Config.MaskWord;
  447. local startPos;
  448. local endPos;
  449. for k, v in pairs(wordList) do
  450. startPos, endPos = string.find(str, v.maskWord);
  451. if startPos or endPos then
  452. print(v.maskWord);
  453. return startPos, endPos;
  454. end
  455. end
  456. return nil, nil;
  457. end
  458. ]]
  459. -- 把一个utf8的字符串转换成utf32的table数组
  460. function Utf8To32(utf8str)
  461. assert(type(utf8str) == "string")
  462. local res, seq, val = {}, 0, nil
  463. for i = 1, #utf8str do
  464. local c = string.byte(utf8str, i)
  465. if seq == 0 then
  466. table.insert(res, val)
  467. seq = c < 0x80 and 1 or c < 0xE0 and 2 or c < 0xF0 and 3 or
  468. c < 0xF8 and 4 or --c < 0xFC and 5 or c < 0xFE and 6 or
  469. error("invalid UTF-8 character sequence")
  470. val = bit32.band(c, 2^(8-seq) - 1)
  471. else
  472. val = bit32.bor(bit32.lshift(val, 6), bit32.band(c, 0x3F))
  473. end
  474. seq = seq - 1
  475. end
  476. table.insert(res, val)
  477. return res
  478. end
  479. function Utf8Table(utf8str)
  480. assert(type(utf8str) == "string")
  481. local res = {}
  482. for i = 1, #utf8str do
  483. local c = string.byte(utf8str, i)
  484. table.insert(res, c)
  485. end
  486. table.insert(res, val)
  487. return res
  488. end
  489. local char = string.char
  490. local function tail(n, k)
  491. local u, r=''
  492. for i=1,k do
  493. n,r = math.floor(n/0x40), n%0x40
  494. u = char(r+0x80) .. u
  495. end
  496. return u, n
  497. end
  498. -- 把一个utf32字符数字,转换成utf8字符串
  499. function Utf32To8(a)
  500. local n = a;
  501. local r;
  502. local u;
  503. if n<0x80 then -- 1 byte
  504. return char(n)
  505. elseif n<0x800 then -- 2 byte
  506. u, n = tail(n, 1)
  507. return char(n+0xc0) .. u
  508. elseif n<0x10000 then -- 3 byte
  509. u, n = tail(n, 2)
  510. return char(n+0xe0) .. u
  511. elseif n<0x200000 then -- 4 byte
  512. u, n = tail(n, 3)
  513. return char(n+0xf0) .. u
  514. elseif n<0x4000000 then -- 5 byte
  515. u, n = tail(n, 4)
  516. return char(n+0xf8) .. u
  517. else -- 6 byte
  518. u, n = tail(n, 5)
  519. return char(n+0xfc) .. u
  520. end
  521. end
  522. MaskCodeType =
  523. {
  524. NAME = 1;
  525. CHAT = 2;
  526. }
  527. local emojiTable = require("luaScript.Tools.Emoji");
  528. -- 保存所有正则表达式
  529. local g_batchRegex = {};
  530. -- 动态构造正则表达式批量处理
  531. -- maskCode 屏蔽范围:1表示命名2表示聊天3表示聊天和命名
  532. function getBatchRegex(maskCode)
  533. maskCode = maskCode or 0xffffffff;
  534. -- 构造正则表达式批量处理
  535. local batchRegex = g_batchRegex[maskCode];
  536. if batchRegex == nil then
  537. batchRegex = cc.BatchRegex:new();
  538. g_batchRegex[maskCode] = batchRegex;
  539. if maskCode == 3 or maskCode == 2 then
  540. for i , v in ipairs(string.split(LN.MASK_PATTERNS , "\n")) do
  541. if v ~= "" then
  542. batchRegex:add(v);
  543. end
  544. end
  545. end
  546. -- 名字
  547. if maskCode == 3 or maskCode == 1 then
  548. for i , v in ipairs(string.split(LN.MASK_PATTERNS_NAME , "\n")) do
  549. if v ~= "" then
  550. batchRegex:add(v);
  551. end
  552. end
  553. end
  554. end
  555. return batchRegex;
  556. end
  557. -- 检测字符串里是否有屏蔽字
  558. -- 有屏蔽字返回false, 没有返回true
  559. function checkMaskWord(str, maskCode)
  560. local regex = getBatchRegex(maskCode);
  561. local result = regex:search(str);
  562. if #result > 0 then
  563. print('在字符串 "' .. str .. '" 发现屏蔽字 ' .. result[1]);
  564. return false , result[1];
  565. end
  566. -- 表情也屏蔽
  567. local names32 = Utf8To32(str);
  568. local namesRet = "";
  569. for i , v in ipairs(names32) do
  570. local emoji = emojiTable[v];
  571. if emoji then
  572. if type(emoji) == "table" then
  573. local val = names32[i + 1];
  574. if val then
  575. if emoji[val] then
  576. return false , "表情";
  577. end
  578. end
  579. else
  580. return false , "表情";
  581. end
  582. end
  583. end
  584. return true;
  585. end
  586. -- 替换字符串里可能有的屏蔽字, 效率低下, 求改成c++版本
  587. -- @replaceChar 屏蔽字替换成的字符, 默认为"*";
  588. function replaceMaskWord(str, replaceChar, maskCode)
  589. require("luaScript.Tools.Utf16");
  590. replaceChar = replaceChar or "*";
  591. print("replaceChar" , replaceChar);
  592. local regex = getBatchRegex(maskCode);
  593. print("regex" , regex);
  594. return regex:replace(str , replaceChar);
  595. end
  596. local XmlFilter =
  597. {
  598. [60] = "&lt;";
  599. [62] = "&gt;";
  600. [38] = "&amp;";
  601. [39] = "&apos;";
  602. [34] = "&quot;";
  603. }
  604. -- 表情库
  605. function createEmojiHtml(emojiValue , value2)
  606. local emoji = emojiTable[emojiValue];
  607. if emoji then
  608. if type(emoji) == "table" then
  609. if value2 then
  610. local emoji = emoji[value2];
  611. if emoji then
  612. return "<img width='24' height='24' src='" .. emoji .. "'/>";
  613. end
  614. end
  615. else
  616. return "<img width='24' height='24' src='" .. emoji .. "'/>";
  617. end
  618. end
  619. return XmlFilter[emojiValue] or Utf32To8(emojiValue);
  620. end
  621. -- 把聊天中的表情文字替换掉
  622. function replaceChatEmoji(str)
  623. local utf32 = Utf8To32(str);
  624. local text = "";
  625. for i , v in ipairs(utf32) do
  626. text = text .. createEmojiHtml(v , utf32[i + 1]);
  627. end
  628. return text;
  629. end
  630. -- 在waitView关闭后执行
  631. function runInWaitViewEnd(func , ...)
  632. if g_WaitViewInstance then
  633. local arg = {...};
  634. local function onCloseWaitView()
  635. game:unregEvent("onCloseWaitView");
  636. func(unpack(arg));
  637. end
  638. game:regEvent("onCloseWaitView" , onCloseWaitView);
  639. else
  640. func(...);
  641. end
  642. end
  643. -- 显示平台相关的等待窗口
  644. function showPlatformWaitView()
  645. local platformPlugin = PluginManager:getInstance():loadPlugin("AnalyticsPlatform");
  646. if platformPlugin then
  647. platformPlugin:call("showWaitView");
  648. end
  649. end
  650. -- 关闭平台相关的等待窗口
  651. function closePlatformWaitView()
  652. local platformPlugin = PluginManager:getInstance():loadPlugin("AnalyticsPlatform");
  653. if platformPlugin then
  654. platformPlugin:call("closeWaitView");
  655. end
  656. end
  657. -- 显示滚动公告
  658. function showFloatTooltip(msg)
  659. local homeView = cc.Director:getInstance():getRunningScene();
  660. local html = cc.HtmlCtrl:create('<font size="30" color="#FFFFFF" stroke="size:3;color:#000000" name="res/default/msyh.ttc">' .. replaceXmlByFilter(msg) .. '</font>');
  661. if homeView.mFloatBar == nil then
  662. homeView.mFloatBar = cc.LayerColor:create(cc.c4b(0,0,0,76));
  663. homeView:addChild(homeView.mFloatBar);
  664. end
  665. local winSize = cc.Director:getInstance():getWinSize();
  666. homeView.mFloatBar:removeAllChildren();
  667. homeView.mFloatBar:addChild(html);
  668. homeView.mFloatBar:setContentSize(cc.size(winSize.width , html:getHeight()));
  669. homeView.mFloatBar:setPosition(cc.p(0 , winSize.height - html:getContentSize().height));
  670. html:setAnchorPoint(cc.p(0,0));
  671. html:setPosition(cc.p(1280 , (homeView.mFloatBar:getContentSize().height - html:getContentSize().height) / 2));
  672. local function onEnd()
  673. homeView.mFloatBar:removeFromParent();
  674. homeView.mFloatBar = nil;
  675. end
  676. print("width " , html:getContentSize().width , html:getContentSize().height , winSize.width , html:getWidth() , html:getHeight());
  677. -- 多少像素每秒
  678. local speed = 30;
  679. html:runActions(cc.MoveTo:create(html:getContentSize().width / speed , cc.p( - html:getContentSize().width , 0)) , onEnd);
  680. end
  681. local function sortFunc(a,b)
  682. local numA = tonumber(a)
  683. local numB = tonumber(b)
  684. if numA ~= nil and numB ~= nil then
  685. return numA < numB
  686. else
  687. return a < b
  688. end
  689. end
  690. -- 根据Key排序 :从小到大
  691. function pairsByKeys (t)
  692. local a = {}
  693. for n in pairs(t) do table.insert(a, n) end
  694. table.sort(a, sortFunc)
  695. local i = 0 -- iterator variable
  696. local iter = function () -- iterator function
  697. i = i + 1
  698. if a[i] == nil then
  699. return nil
  700. else
  701. return a[i], t[a[i]]
  702. end
  703. end
  704. return iter
  705. end
  706. local function sortFuncEx(a,b)
  707. local numA = tonumber(a)
  708. local numB = tonumber(b)
  709. if numA ~= nil and numB ~= nil then
  710. return numA > numB
  711. else
  712. return a > b
  713. end
  714. end
  715. -- 根据Key排序(从大到小)
  716. function pairsByKeysEx (t)
  717. local a = {}
  718. for n in pairs(t) do table.insert(a, n) end
  719. table.sort(a, sortFuncEx)
  720. local i = 0 -- iterator variable
  721. local iter = function () -- iterator function
  722. i = i + 1
  723. if a[i] == nil then
  724. return nil
  725. else
  726. return a[i], t[a[i]]
  727. end
  728. end
  729. return iter
  730. end
  731. function getNetTimeOutNum()
  732. if g_netTimeOut then
  733. return g_netTimeOut
  734. else
  735. return 10;
  736. end
  737. end
  738. function sortListByFunc(list, sortFunc)
  739. local a = {}
  740. for _, v in pairs(list) do table.insert(a, v) end
  741. if not sortFunc then return; end
  742. table.sort(a, sortFunc)
  743. return a;
  744. end
  745. local stQuery =
  746. {
  747. "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p"
  748. , "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O"
  749. , "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", [0] = "0"
  750. };
  751. -- 10进制转62进制, 注意数值太大会导致溢出
  752. function dec2ST(decNum)
  753. local ret = "";
  754. local num = 0;
  755. if type(decNum) == "string" then
  756. num = tonumber(decNum);
  757. elseif type(decNum) == "number" then
  758. num = decNum;
  759. else
  760. return ret;
  761. end;
  762. local h;
  763. repeat
  764. h = math.floor(num / 62);
  765. local m = num % 62;
  766. ret = ret .. stQuery[m];
  767. num = h;
  768. until h <= 0;
  769. return string.reverse(ret);
  770. end;
  771. -- 16进制转62进制, 注意数值太大会导致溢出
  772. function hex2ST(str)
  773. local ret = "";
  774. local num = 0;
  775. if type(str) == "string" then
  776. local len = string.len(str);
  777. for i = 1, len do
  778. local c = string.sub(str, i, i);
  779. local ascii = string.byte(c);
  780. if ascii >= 48 and ascii <= 57 then
  781. num = num * 16 + ascii - 48;
  782. elseif ascii >= 65 and ascii <= 70 then
  783. num = num * 16 + ascii - 65 + 10;
  784. elseif ascii >= 97 and ascii <= 102 then
  785. num = num * 16 + ascii - 97 + 10;
  786. end
  787. end
  788. else
  789. return ret;
  790. end;
  791. local h;
  792. repeat
  793. h = math.floor(num / 62);
  794. local m = num % 62;
  795. ret = ret .. stQuery[m];
  796. num = h;
  797. until h <= 0;
  798. return string.reverse(ret);
  799. end;
  800. function alignString(str, alignSize, maxSize)
  801. local len = string.len(str);
  802. local alignStr = str;
  803. if maxSize then
  804. if len < maxSize then
  805. for i = 1, maxSize - len do
  806. alignStr = "0" .. alignStr;
  807. end
  808. end;
  809. else
  810. local m = len % alignSize;
  811. if m > 0 then
  812. for i = 1, (alignSize - m) do
  813. alignStr = "0" .. alignStr;
  814. end
  815. end;
  816. end
  817. return alignStr;
  818. end;
  819. -- 16进制转62进制 支持大数, 但只有压缩效果(4位16进制用3位62进制表示), 数值不相等
  820. function hex2STEx(str)
  821. local ret ="";
  822. local len = string.len(str);
  823. local alignStr = str;
  824. local alignSize = 4;
  825. -- 对齐字符串
  826. local m = len % alignSize;
  827. if m > 0 then
  828. for i = 1, (alignSize - m) do
  829. alignStr = "0" .. alignStr;
  830. end
  831. len = len + alignSize - m;
  832. end;
  833. local i = 1;
  834. while i < len do
  835. local s = string.sub(alignStr, i, i + alignSize - 1);
  836. ret = ret .. hex2ST(s);
  837. i = i + alignSize;
  838. end;
  839. return ret;
  840. end
  841. -- 播放UI的从上往下掉落的动画
  842. function fallDownUI(ui)
  843. if not isUIAniEnabled() then
  844. return;
  845. end
  846. local oldPosY = ui:getPositionY();
  847. ui:setPositionY( cc.Director:getInstance():getVisibleSize().height);
  848. ui:runActions(cc.EaseSineInOut:create(cc.MoveTo:create(0.3 , cc.p(ui:getPositionX() , oldPosY - 15)))
  849. , cc.EaseSineInOut:create(cc.MoveBy:create(0.2 , cc.p(0 , 45)))
  850. , cc.EaseSineIn:create(cc.MoveBy:create(0.2 , cc.p(0 , -30)))
  851. );
  852. end
  853. -- 播放UI放大动画
  854. function scaleUI(ui)
  855. if not isUIAniEnabled() then
  856. return;
  857. end
  858. local oldScaleX = ui:getScaleX();
  859. local oldScaleY = ui:getScaleY();
  860. ui:setScaleX(0);
  861. ui:setScaleY(0);
  862. ui:runActions(cc.EaseSineInOut:create(cc.ScaleTo:create(0.2 , oldScaleX + 0.05 , oldScaleY + 0.05))
  863. , cc.EaseSineInOut:create(cc.ScaleTo:create(0.1 , oldScaleX - 0.05 , oldScaleY - 0.05))
  864. , cc.EaseSineIn:create(cc.ScaleTo:create(0.1 , oldScaleX , oldScaleY))
  865. );
  866. end
  867. -- 播放UI的从上往下掉落的动画
  868. function moveDownUI(ui)
  869. if not isUIAniEnabled() then
  870. return;
  871. end
  872. local oldPosY = ui:getPositionY();
  873. ui:setPositionY( cc.Director:getInstance():getVisibleSize().height);
  874. ui:runActions(cc.EaseExponentialOut:create(cc.MoveTo:create(0.5 , cc.p(ui:getPositionX() , oldPosY)))
  875. );
  876. end
  877. -- 播放UI的从下往上掉落的动画
  878. function moveUpUI(ui)
  879. if not isUIAniEnabled() then
  880. return;
  881. end
  882. local oldPosY = ui:getPositionY();
  883. ui:setPositionY(-ui.ContentSize.height);
  884. ui:runActions(cc.EaseExponentialOut:create(cc.MoveTo:create(0.5 , cc.p(ui:getPositionX() , oldPosY)))
  885. );
  886. end
  887. -- 播放UI的从右往左掉落的动画
  888. function moveLeftUI(ui)
  889. if not isUIAniEnabled() then
  890. return;
  891. end
  892. local oldPosX = ui:getPositionX();
  893. ui:setPositionX(cc.Director:getInstance():getVisibleSize().width);
  894. ui:runActions(cc.EaseExponentialOut:create(cc.MoveTo:create(0.5 , cc.p(oldPosX , ui:getPositionY())))
  895. );
  896. end
  897. -- 播放UI的从左往右掉落的动画
  898. function moveRightUI(ui)
  899. if not isUIAniEnabled() then
  900. return;
  901. end
  902. local oldPosX = ui:getPositionX();
  903. ui:setPositionX(- cc.Director:getInstance():getVisibleSize().width);
  904. ui:runActions(cc.EaseExponentialOut:create(cc.MoveTo:create(0.5 , cc.p(oldPosX , ui:getPositionY())))
  905. );
  906. end
  907. -- 播放UI放大动画
  908. function scaleAndMoveUI(ui , sourcePos)
  909. if not isUIAniEnabled() then
  910. return;
  911. end
  912. local oldScaleX = ui:getScaleX();
  913. local oldScaleY = ui:getScaleY();
  914. ui:setScaleX(0);
  915. ui:setScaleY(0);
  916. ui:runActions(cc.EaseExponentialOut:create(cc.ScaleTo:create(0.5 , oldScaleX , oldScaleY))
  917. );
  918. local oldX = ui:getPositionX();
  919. local oldY = ui:getPositionY();
  920. ui:setPosition(sourcePos);
  921. ui:runAction(cc.EaseExponentialOut:create(cc.MoveTo:create(0.5 , cc.p(oldX , oldY))));
  922. end
  923. function beijingDate(formatStr, time)
  924. assert(formatStr and type(formatStr) == "string", "formatStr必须是字符串类型");
  925. time = time or os.time();
  926. local convert2Zone = 8;
  927. local timeZone = tonumber(os.date("%H", 0));
  928. local d = tonumber(os.date("%d", 0));
  929. if d ~= 1 then timeZone = timeZone - 24; end;
  930. if timeZone ~= convert2Zone then
  931. time = time - (timeZone - convert2Zone) * 3600;
  932. end
  933. return os.date(formatStr, time);
  934. end
  935. AutoCallback =
  936. {
  937. cbList = {};
  938. id = nil;
  939. lastIndex = 1;
  940. };
  941. -- 指定每天的某一时刻之前x秒运行一次回调
  942. -- @func 回调函数
  943. -- @hour 小时, 默认0点
  944. -- @min 分, 默认0分
  945. -- @sec 秒, 默认0秒
  946. -- @beforeSec 提前秒数, 可为负数, 达到之后多少秒执行的效果, 默认0秒
  947. -- @thresholdValue 误差阀值, 0为过期不候, 默认为0
  948. -- @return 此回调的句柄, 用于反注册
  949. function AutoCallback:runBeforeTime(func, hour, min, sec, beforeSec, thresholdValue)
  950. assert(func, "回调函数不能为空");
  951. hour = hour or 0;
  952. min = min or 0;
  953. sec = sec or 0;
  954. beforeSec = beforeSec or 0;
  955. thresholdValue = thresholdValue or 0;
  956. local param =
  957. {
  958. func = func;
  959. hour = hour;
  960. min = min;
  961. sec = sec;
  962. thresholdValue = thresholdValue;
  963. beforeSec = beforeSec;
  964. bHasRun = false;
  965. }
  966. local handler = self.lastIndex;
  967. self.cbList[handler] = param;
  968. self.lastIndex = handler + 1;
  969. if not self.id then
  970. self.id = cc.Director:getInstance():getScheduler():scheduleScriptFunc(function() self:update();end
  971. , 1
  972. , false);
  973. end
  974. return handler;
  975. end;
  976. -- 指定每天的某一时刻运行一次回调
  977. -- @func 回调函数
  978. -- @hour 小时, 默认0点
  979. -- @min 分, 默认0分
  980. -- @sec 秒, 默认0秒
  981. -- @thresholdValue 误差阀值, 0为过期不候, 默认为0
  982. -- @return 此回调的句柄, 用于反注册
  983. function AutoCallback:runAtTime(func, hour, min, sec, thresholdValue)
  984. return self:runBeforeTime(func, hour, min, sec, 0, thresholdValue);
  985. end;
  986. function AutoCallback:update()
  987. local bHave = next(self.cbList);
  988. if not bHave then
  989. cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.id);
  990. self.id = nil;
  991. return;
  992. end
  993. local curServerTime = getCurServerTime();
  994. --[[
  995. local year = tonumber(os.date("%Y", curServerTime));
  996. local month = tonumber(os.date("%m", curServerTime));
  997. local day = tonumber(os.date("%d", curServerTime));
  998. ]]
  999. local curServerTimeTable = BeijingTime.dateFunc(curServerTime);
  1000. local year = curServerTimeTable.year;
  1001. local month = curServerTimeTable.month;
  1002. local day = curServerTimeTable.day;
  1003. for k, v in pairs(self.cbList) do
  1004. --local cbTime = os.time({year = year, month = month, day = day, hour = v.hour, min = v.min, sec = v.sec});
  1005. local cbTime = BeijingTime.timeFunc({year = year, month = month, day = day, hour = v.hour, min = v.min, sec = v.sec});
  1006. cbTime = cbTime - v.beforeSec;
  1007. local interval = curServerTime - cbTime;
  1008. if v.bHasRun then
  1009. if interval < 0 or interval > v.thresholdValue then
  1010. v.bHasRun = false;
  1011. end
  1012. else
  1013. if interval >= 0 and interval <= v.thresholdValue then
  1014. v.func();
  1015. v.bHasRun = true;
  1016. end
  1017. end;
  1018. end
  1019. end;
  1020. function AutoCallback:removeCB(handler)
  1021. assert(handler, "句柄不能为空");
  1022. self.cbList[handler] = nil;
  1023. end;
  1024. function logAppEvent(event)
  1025. if plugins.analytics then
  1026. plugins.analytics:logEvent(event , {});
  1027. end
  1028. end
  1029. -- 显示内嵌网页
  1030. function showWebView(url , width , height , posX , posY)
  1031. print("showWebView" ,url , width , height , posX , posY);
  1032. local platformPlugin = PluginManager:getInstance():loadPlugin("AnalyticsPlatform");
  1033. if platformPlugin then
  1034. local visibleSize = cc.Director:getInstance():getVisibleSize();
  1035. local frameSize = cc.Director:getInstance():getOpenGLView():getFrameSize();
  1036. platformPlugin:call("openWebView" , url , width / visibleSize.width * frameSize.width , height / visibleSize.height * frameSize.height
  1037. , posX / visibleSize.width * frameSize.width , posY / visibleSize.height * frameSize.height);
  1038. end
  1039. end
  1040. -- 关闭内嵌网页
  1041. function closeWebView()
  1042. local platformPlugin = PluginManager:getInstance():loadPlugin("AnalyticsPlatform");
  1043. if platformPlugin then
  1044. platformPlugin:call("closeWebView");
  1045. end
  1046. end
  1047. -- 在目标窗口的旁边创建一个Tooltip,并返回创建好的tooltip节点
  1048. -- targetContainer 目标参考容器节点
  1049. -- targetNode 目标参考点的节点
  1050. -- tipsText tooltip的文本内容
  1051. -- tipsWidth 文本宽度,可选值
  1052. function createTooltip(targetContainer , targetNode , tipsText , tipsWidth, dir)
  1053. local tips = loadUI("res/ui/ui_tongyong/tips.ui");
  1054. -- 定义一个函数给外部用
  1055. function tips:setText(text)
  1056. tips.Items.HtmlCtrl_1:setText(text);
  1057. end
  1058. --tips.Items.HtmlCtrl_1:setTextAreaSize(cc.size(tipsWidth or 0 , 0));
  1059. tips:setText(tipsText);
  1060. -- 强制计算一遍布局,以便让screenLayoutNode里的getContentSize能取到准确的位置
  1061. tips:requestDoLayout();
  1062. tips:doLayout();
  1063. -- targetContainer:addChild(tips)
  1064. app.mainScene.showDialogNode:addChild(tips);
  1065. -- 关注targetContainer退出的消息(兼容以前的版本)
  1066. local function onNodeEvent(node , eventType)
  1067. if eventType == cc.NodeEvent.OnExit then
  1068. -- 移除悬浮框
  1069. if not tolua.isnull(tips) then
  1070. tips:removeFromParent()
  1071. end
  1072. end
  1073. end
  1074. targetContainer:addNodeEventListener(onNodeEvent)
  1075. -- 让他每帧执行布局计算
  1076. autoScreenLayoutNode(targetContainer , targetNode , tips, nil, dir);
  1077. return tips;
  1078. end
  1079. -- 在目标窗口的旁边创建一个Tooltip,并返回创建好的tooltip节点
  1080. -- targetContainer 目标参考容器节点
  1081. -- targetNode 目标参考点的节点
  1082. -- tipsText tooltip的文本内容
  1083. -- tipsWidth 文本宽度,可选值
  1084. function createTooltip2(targetContainer , targetNode , tipsText , tipsWidth)
  1085. local tips = loadUI("res/ui/ui_maoxian/mx_guanka_xinxi_texin_tips.ui");
  1086. -- 定义一个函数给外部用
  1087. function tips:setText(text)
  1088. tips.Items.HtmlCtrl_3:setText(text);
  1089. end
  1090. --tips.Items.HtmlCtrl_1:setTextAreaSize(cc.size(tipsWidth or 0 , 0));
  1091. tips:setText(tipsText);
  1092. -- 强制计算一遍布局,以便让screenLayoutNode里的getContentSize能取到准确的位置
  1093. tips:requestDoLayout();
  1094. tips:doLayout();
  1095. targetContainer:addChild(tips);
  1096. -- 让他每帧执行布局计算
  1097. autoScreenLayoutNode(targetContainer , targetNode , tips);
  1098. --[[
  1099. tips:playClip("fadeIn" ,
  1100. function()
  1101. tips.FadeInEnd = true;
  1102. if tips.DestroyRequest then
  1103. tips:playClip("fadeOut"
  1104. , function()
  1105. tips:removeFromParent();
  1106. end
  1107. );
  1108. end
  1109. end
  1110. )
  1111. local remove = tips.removeFromParent;
  1112. function tips:removeFromParent()
  1113. if self.FadeInEnd then
  1114. self:playClip("fadeOut"
  1115. , function()remove(tip);end
  1116. );
  1117. else
  1118. self.DestroyRequest = true;
  1119. end
  1120. end
  1121. --]]
  1122. return tips;
  1123. end
  1124. ---- 显示一个特别Tooltip,并自动销毁
  1125. function showDiffTooltip(tipsText,autoRemove)
  1126. local tips = loadUI("res/ui/ui_tongyong/t_buzu_tishi.ui");
  1127. tips.Items.HtmlCtr_miaoshu:setText(tipsText);
  1128. if(autoRemove)then
  1129. local winSize = cc.Director:getInstance():getWinSize();
  1130. tips:setTranslation(winSize.width / 2 , winSize.height /3* 2 , 0);
  1131. app.mainScene:addChild(tips , UIZOrder.TipsOrder);
  1132. local t = app.config.GlobalClient.TASK_TOOL_TIPS_TIME.number/1000;
  1133. local delayRemove = function()
  1134. tips:runActions(cc.DelayTime:create(t) , function()
  1135. tips:playClip("danchu",function()
  1136. tips:removeFromParent();
  1137. end)
  1138. end);
  1139. end
  1140. tips:playClip("danru",delayRemove);
  1141. else
  1142. app:showUI(tips,transparency or 204);
  1143. tips:playClip("danru");
  1144. end
  1145. return tips;
  1146. end
  1147. function showTooltipWithHtmlText(htmlText)
  1148. local tips = loadUI("res/ui/ui_tongyong/texttips.ui");
  1149. tips.Items.Text:setText(htmlText);
  1150. local director = cc.Director:getInstance();
  1151. app.mainScene:addChild(tips , UIZOrder.TipsOrder);
  1152. local winSize = director:getWinSize();
  1153. tips:requestDoLayout();
  1154. tips:doLayout();
  1155. tips.Items.Layout_1:setAutoSize(false);
  1156. tips.Items.Layout_1:setUpdateBackgroundWithChildren(false);
  1157. local t = 1
  1158. local delayRemove = function()
  1159. tips.Items.Layout_3:runActions(cc.DelayTime:create(t) , function()
  1160. tips.Items.Layout_3:playClip("danchu",function()
  1161. tips:removeFromParent();
  1162. end)
  1163. end);
  1164. end
  1165. tips.Items.Layout_3:playClip("danru",delayRemove);
  1166. return tips;
  1167. end
  1168. -- 显示一个Tooltip,并自动销毁
  1169. function showTooltip(tipsText)
  1170. if (not tipsText) or tipsText == "" then
  1171. return
  1172. end
  1173. if app.club_php.clubID and app.club_php.clubID ~= 0 then
  1174. if app.club_php:getCestIsOpen(app.club_php.clubID) then
  1175. tipsText = string.gsub(tipsText, "玩家", "选手")
  1176. tipsText = string.gsub(tipsText, "成员", "选手")
  1177. tipsText = string.gsub(tipsText, "亲友圈", "赛事")
  1178. tipsText = string.gsub(tipsText, "茶馆", "赛事")
  1179. end
  1180. end
  1181. logD("showTooltip() : " .. tipsText)
  1182. --local model = '<font size="26" color="ffffff" stroke="size:2;color:#000000" name="res/default/msyh.ttc">%s</font>'
  1183. local strTips = string.format("%s", tipsText)
  1184. showTooltipWithHtmlText(strTips)
  1185. end
  1186. function showDropTip(tipsText)
  1187. app:dropNotice(tipsText)
  1188. end
  1189. -- 显示对话框
  1190. -- btnCallbackOk : 点击确定时的回调
  1191. -- btnCallbackCancel : 点击取消时的回调,如果为空,则不显示取消按钮
  1192. -- fontSize : 显示内容字体大小
  1193. -- imgpath : 替换确定按钮图片路径
  1194. -- notice:备注
  1195. -- bShowKeFu: 显示联系客服的按钮
  1196. function showConfirmDialog(textContent, btnCallbackOk, btnCallbackCancel, fontSize, imgpath, notice, bShowKeFu)
  1197. local view;
  1198. local ui = loadUI("res/ui/ui_tongyong/ui_querenjiemian.ui");
  1199. ui:setAnchorPoint(cc.p(0.5, 0.5));
  1200. logD(textContent)
  1201. -- 内容
  1202. ui.Items.Text_Content:setText(textContent or "");
  1203. if fontSize then
  1204. ui.Items.Text_Content:setFontSize(fontSize)
  1205. end
  1206. -- 确认按钮
  1207. local function onButtonClickOk()
  1208. playBtnEffect()
  1209. if btnCallbackOk then
  1210. btnCallbackOk();
  1211. end
  1212. view:removeFromParent();
  1213. end
  1214. ui.Items.Button_OK:registerClick(onButtonClickOk);
  1215. if imgpath then
  1216. ui.Items.Button_OK:loadTextureNormal(imgpath)
  1217. end
  1218. -- 取消按钮
  1219. local function onButtonClickCancel()
  1220. playBtnEffect()
  1221. if btnCallbackCancel then
  1222. btnCallbackCancel();
  1223. end
  1224. view:removeFromParent();
  1225. end
  1226. if btnCallbackCancel then
  1227. ui.Items.Button_Cancel:registerClick(onButtonClickCancel);
  1228. else
  1229. ui.Items.Button_Cancel:removeFromParent();
  1230. end
  1231. if notice then
  1232. ui.Items.Text_notice:setText(tostring(notice))
  1233. else
  1234. ui.Items.Text_notice:setVisible(false)
  1235. end
  1236. if bShowKeFu then
  1237. local function onButtonClickKeFu()
  1238. playBtnEffect()
  1239. local tt =
  1240. {
  1241. action = "collecturl.getDataByUid";
  1242. app_id = getAppId(); --应用id
  1243. };
  1244. local phpUrl = getGlobalPhpUrl()
  1245. httpPost(phpUrl, tt, function(status, response)
  1246. if status == "successed" then
  1247. local data = json.decode(response)
  1248. if data.code == 200 and data.result ~= null then
  1249. app.plugin:callUrl(data.result.kefuurl)
  1250. end
  1251. else
  1252. local url = "http://cs.zxtycest.com/addons/kefu?gameid=47"
  1253. app.plugin:callUrl(url)
  1254. end
  1255. end)
  1256. end
  1257. ui.Items.Button_KeFu:registerClick(onButtonClickKeFu);
  1258. else
  1259. ui.Items.Button_KeFu:setVisible(false)
  1260. end
  1261. view = app:showWaitUI(ui, nil, nil, 9999);
  1262. return view;
  1263. end
  1264. -- 显示一个不可关闭的对话框
  1265. -- btnCallbackOk : 点击确定时的回调
  1266. -- btnCallbackCancel : 点击取消时的回调,如果为空,则不显示取消按钮
  1267. -- fontSize : 显示内容字体大小
  1268. -- imgpath : 替换确定按钮图片路径
  1269. -- notice:备注
  1270. -- bShowKeFu: 显示联系客服的按钮
  1271. function showConfirmDialogNotClose(textContent, btnCallbackOk, btnCallbackCancel, fontSize, imgpath, notice, bShowKeFu)
  1272. local view;
  1273. local ui = loadUI("res/ui/ui_tongyong/ui_querenjiemian.ui");
  1274. ui:setAnchorPoint(cc.p(0.5, 0.5));
  1275. logD(textContent)
  1276. -- 内容
  1277. ui.Items.Text_Content:setText(textContent or "");
  1278. if fontSize then
  1279. ui.Items.Text_Content:setFontSize(fontSize)
  1280. end
  1281. -- 确认按钮
  1282. local function onButtonClickOk()
  1283. playBtnEffect()
  1284. if btnCallbackOk then
  1285. btnCallbackOk();
  1286. end
  1287. end
  1288. ui.Items.Button_OK:registerClick(onButtonClickOk);
  1289. if imgpath then
  1290. ui.Items.Button_OK:loadTextureNormal(imgpath)
  1291. end
  1292. ui.Items.Button_Cancel:removeFromParent();
  1293. if notice then
  1294. ui.Items.Text_notice:setText(tostring(notice))
  1295. else
  1296. ui.Items.Text_notice:setVisible(false)
  1297. end
  1298. if bShowKeFu then
  1299. local function onButtonClickKeFu()
  1300. playBtnEffect()
  1301. local tt =
  1302. {
  1303. action = "collecturl.getDataByUid";
  1304. app_id = getAppId(); --应用id
  1305. };
  1306. local phpUrl = getGlobalPhpUrl()
  1307. httpPost(phpUrl, tt, function(status, response)
  1308. if status == "successed" then
  1309. local data = json.decode(response)
  1310. if data.code == 200 and data.result ~= null then
  1311. app.plugin:callUrl(data.result.kefuurl)
  1312. end
  1313. else
  1314. local url = "http://cs.zxtycest.com/addons/kefu?gameid=47"
  1315. app.plugin:callUrl(url)
  1316. end
  1317. end)
  1318. end
  1319. ui.Items.Button_KeFu:registerClick(onButtonClickKeFu);
  1320. else
  1321. ui.Items.Button_KeFu:setVisible(false)
  1322. end
  1323. view = app:showWaitUI(ui, nil, nil, 9999);
  1324. ui:bindEvent(app, "showConfirmDialogNotClose",function ()
  1325. view:removeFromParent()
  1326. end)
  1327. return view;
  1328. end
  1329. -- 播放UI声音文件
  1330. -- soundFile 声音文件名
  1331. function playUISound(filePath , streamBuffer)
  1332. if app.systemSetting.info.sound then
  1333. --print("播放UI声音" , filePath , debug.traceback());
  1334. return cc.AudioController:getInstance():playSound(filePath , streamBuffer or false);
  1335. end
  1336. end
  1337. -- 播放一个飞行ce
  1338. -- @ceFile 技能文件
  1339. -- @targetPoints 飞行技能的源坐标点
  1340. -- @effectPoints 飞行技能的目标坐标点
  1341. -- @onHit 被击触发函数,默认可以不设置
  1342. function playFlyEffect(ceFile, parentNode, targetPoints, effectPoints, onHit, onEndFunc)
  1343. --print("播放的技能资源名称:" .. ceFile)
  1344. -- 载入技能
  1345. local ce = createCombineEffect(ceFile);
  1346. if ce then
  1347. --创建一个源模型、源点、目标模型、目标点
  1348. local params = createDefaultCombineEffectParams();
  1349. params.ParentNode = parentNode;
  1350. params.CameraNode = app:getMainCameraNode();
  1351. params.SourcePos = effectPoints
  1352. params.TargetPos = targetPoints
  1353. local onStartEventFunc = nil
  1354. if onHit then
  1355. local hasOnHitEvent = false;
  1356. for i , v in pairs(ce:getChildren()) do
  1357. if v:getStartEventName() == "OnHit" then
  1358. hasOnHitEvent = true;
  1359. break;
  1360. end
  1361. end
  1362. if not hasOnHitEvent then
  1363. error("技能文件没配置OnHit事件:" , ceFile);
  1364. end
  1365. -- 绑定技能事件
  1366. local function onStartEvent(eventName , params)
  1367. -- 播放被击效果
  1368. if eventName == "OnHit" then
  1369. -- 只触发一次
  1370. if onHit then
  1371. onHit();
  1372. end
  1373. end
  1374. end
  1375. onStartEventFunc = onStartEvent;
  1376. end
  1377. -- 播放技能
  1378. local ceAction = cc.CombineEffectAction:createWithInstance(ce, params, onStartEventFunc, onEndFunc)
  1379. parentNode:runAction(ceAction)
  1380. return ceAction;
  1381. -- 如果没配技能,则直接触发被击
  1382. else
  1383. if onHit then
  1384. onHit();
  1385. end
  1386. end
  1387. end
  1388. function playModeCeEffect(ceFile, parentNode, sourceNode, targetPoints, effectPoints, onHit, onEndFunc)
  1389. --print("播放的技能资源名称:" .. ceFile)
  1390. -- 载入技能
  1391. local ce = createCombineEffect(ceFile);
  1392. if ce then
  1393. --创建一个源模型、源点、目标模型、目标点
  1394. local params = createDefaultCombineEffectParams();
  1395. params.ParentNode = parentNode;
  1396. params.CameraNode = app:getMainCameraNode();
  1397. params.SourcePos = effectPoints
  1398. params.TargetPos = targetPoints
  1399. params.SourceNode = sourceNode;
  1400. local onStartEventFunc = nil
  1401. if onHit then
  1402. local hasOnHitEvent = false;
  1403. for i , v in pairs(ce:getChildren()) do
  1404. if v:getStartEventName() == "OnHit" then
  1405. hasOnHitEvent = true;
  1406. break;
  1407. end
  1408. end
  1409. if not hasOnHitEvent then
  1410. error("技能文件没配置OnHit事件:" , ceFile);
  1411. end
  1412. -- 绑定技能事件
  1413. local function onStartEvent(eventName , params)
  1414. -- 播放被击效果
  1415. if eventName == "OnHit" then
  1416. -- 只触发一次
  1417. if onHit then
  1418. onHit();
  1419. end
  1420. end
  1421. end
  1422. onStartEventFunc = onStartEvent;
  1423. end
  1424. -- 播放技能
  1425. local ceAction = cc.CombineEffectAction:createWithInstance(ce, params, onStartEventFunc, onEndFunc)
  1426. parentNode:runAction(ceAction)
  1427. return ceAction;
  1428. -- 如果没配技能,则直接触发被击
  1429. else
  1430. if onHit then
  1431. onHit();
  1432. end
  1433. end
  1434. end
  1435. -- 回收所有资源
  1436. function collectMemory()
  1437. print("start collectMemory");
  1438. -- 卸载光效池
  1439. clearEffectCache();
  1440. -- 卸载没有使用的纹理
  1441. cc.BundleCache:getInstance():removeUnusedScenes();
  1442. cc.MaterialCache:getInstance():removeUnusedMaterials();
  1443. cc.AudioCache:getInstance():removeUnusedAudioBuffers();
  1444. cc.SpriteFrameCache:getInstance():unloadUnusedSpriteFrames(10);
  1445. cc.Director:getInstance():getTextureCache():removeUnusedTextures();
  1446. print("lua回收前的内存", collectgarbage("count"))
  1447. collectgarbage("collect")
  1448. print("lua回收后的内存", collectgarbage("count"))
  1449. print("finish collectMemory");
  1450. end
  1451. -- 是否安卓测试包
  1452. function isAndroidTestVersion()
  1453. return isAndroidPlatform() and app.config.Setting.LanguageType == 1;
  1454. end
  1455. -- 自动创建xml文件
  1456. function newLocalXmlFile(fileName)
  1457. local tempXmlPath = cc.FileUtils:getInstance():getWritablePath() .. fileName .. ".xml";
  1458. local file = io.open(tempXmlPath,"rb");
  1459. local tempXmlData;
  1460. if file then
  1461. local data = file:read("*a");
  1462. if data then
  1463. tempXmlData = xml.eval(data);
  1464. end
  1465. file:close();
  1466. end
  1467. if tempXmlData == nil then
  1468. tempXmlData = xml.new(fileName);
  1469. end
  1470. return tempXmlData, tempXmlPath;
  1471. end
  1472. -- 刪除XML文件
  1473. function deleteXmlFile(fileName)
  1474. local tempXmlPath = cc.FileUtils:getInstance():getWritablePath() .. fileName .. ".xml";
  1475. local removeOver = os.remove(tempXmlPath)
  1476. return removeOver
  1477. end
  1478. local UserConfigFileName = "UserConfig"
  1479. local xmlData, xmlPath = newLocalXmlFile(UserConfigFileName);
  1480. local XmlFileTable = {}
  1481. function initLocalXmlFile(fileName)
  1482. if not XmlFileTable[fileName] then
  1483. local xmlMsgData, xmlMsgPath = newLocalXmlFile(fileName);
  1484. XmlFileTable[fileName] = {};
  1485. XmlFileTable[fileName].data = xmlMsgData;
  1486. XmlFileTable[fileName].path = xmlMsgPath;
  1487. end
  1488. end
  1489. -- xml 以xml格式保存玩家数据
  1490. function saveUserXml(eName, eValue, fileName)
  1491. if not fileName then
  1492. fileName = UserConfigFileName;
  1493. end
  1494. if not XmlFileTable[fileName] then
  1495. initLocalXmlFile(fileName);
  1496. end
  1497. local fileData = XmlFileTable[fileName];
  1498. fileData.data[eName] = eValue;
  1499. xml.save(fileData.data , fileData.path);
  1500. end
  1501. -- xml 载入玩家xml数据
  1502. function loadUserXml(eName, fileName)
  1503. if not fileName then
  1504. fileName = UserConfigFileName;
  1505. end
  1506. if not XmlFileTable[fileName] then
  1507. initLocalXmlFile(fileName);
  1508. end
  1509. local fileData = XmlFileTable[fileName];
  1510. return fileData.data[eName] or "";
  1511. end
  1512. function escape(s)
  1513. return (string.gsub(s, "([^A-Za-z0-9_])", function(c)
  1514. return string.format("%%%02x", string.byte(c))
  1515. end))
  1516. end
  1517. function unescape(s)
  1518. return (string.gsub(s, "%%(%x%x)", function(hex)
  1519. return string.char(tonumber(hex, 16))
  1520. end))
  1521. end
  1522. local PasswordKey = "dfdsfsdf#*%&^*&#$^(*&@#^%*(&@#%^sdfdsfdsfwezhangsandfsdf";
  1523. function saveUserInfo(key,value)
  1524. saveUserXml(tostring(key) , escape(md5.crypt(tostring(value) , PasswordKey)));
  1525. end
  1526. function loadUserInfo(key)
  1527. local value = loadUserXml(tostring(key));
  1528. if value ~= "" then
  1529. return md5.decrypt(unescape(value) , PasswordKey);
  1530. else
  1531. return value;
  1532. end
  1533. end
  1534. local function checkUserConfig()
  1535. local key = "20190712"
  1536. local value = loadUserInfo(key)
  1537. if not value or value == "" then
  1538. XmlFileTable[UserConfigFileName] = nil
  1539. deleteXmlFile(UserConfigFileName)
  1540. initLocalXmlFile(UserConfigFileName);
  1541. saveUserInfo(key, 1);
  1542. end
  1543. end
  1544. if not EditorMode then
  1545. checkUserConfig();
  1546. end
  1547. -- 是否正在加载场景
  1548. LoadingScene = false;
  1549. -- 是否在解析xml过程中立即加载资源
  1550. function isImmediatelyLoad()
  1551. return EditorMode or LoadingScene;
  1552. end
  1553. function tableToPostUrl(tb)
  1554. local postUrl = "";
  1555. for k,v in pairs(tb) do
  1556. postUrl = postUrl.."&"..k.."="..v;
  1557. end
  1558. postUrl = string.sub(postUrl,2,-1);
  1559. print("post url is :",postUrl);
  1560. return postUrl;
  1561. end
  1562. -- 显示内嵌网页
  1563. function showWebView(url , width , height , posX , posY)
  1564. print("showWebView" ,url , width , height , posX , posY);
  1565. if PluginDevice then
  1566. local visibleSize = cc.Director:getInstance():getVisibleSize();
  1567. local frameSize = cc.Director:getInstance():getOpenGLView():getFrameSize();
  1568. PluginDevice:callVoid("openWebView" , url , width / visibleSize.width * frameSize.width , height / visibleSize.height * frameSize.height
  1569. , posX / visibleSize.width * frameSize.width , posY / visibleSize.height * frameSize.height);
  1570. end
  1571. end
  1572. -- 关闭内嵌网页
  1573. function closeWebView()
  1574. if PluginDevice then
  1575. PluginDevice:callVoid("closeWebView");
  1576. end
  1577. end
  1578. -- Node的每帧更新回调
  1579. -- stopCondition如果为值则代表最大时间,到达时间就取消定时器
  1580. -- stopCondition如果为函数则为停止定时器的回调函数
  1581. function scheduleUpdateScriptFunc(targetNode, stopCondition, callback)
  1582. if not targetNode then
  1583. return
  1584. end
  1585. local sum = 0
  1586. local function onFrameUpdate(t)
  1587. sum = sum + t
  1588. if type(stopCondition) == "function" then
  1589. local result = stopCondition()
  1590. if result then
  1591. -- 停止定时器
  1592. targetNode:unscheduleUpdate()
  1593. end
  1594. else
  1595. if sum >= stopCondition then
  1596. -- 停止定时器
  1597. targetNode:unscheduleUpdate()
  1598. end
  1599. end
  1600. callback(sum, t)
  1601. end
  1602. targetNode:scheduleUpdateWithPriorityLua(onFrameUpdate, 0)
  1603. end
  1604. -- 截取指定节点的字符串,中文算两个、英文算一个
  1605. function substr(str, endPos)
  1606. local pos = 0;
  1607. local size = #str;
  1608. local nextIndex = 1;
  1609. local len = 0;
  1610. for i = 1, size do
  1611. if i >= nextIndex then
  1612. local curByte = string.byte(str, i)
  1613. local byteCount = 1;
  1614. if curByte>0 and curByte<=127 then
  1615. byteCount = 1
  1616. elseif curByte>=192 and curByte<223 then
  1617. byteCount = 2
  1618. elseif curByte>=224 and curByte<239 then
  1619. byteCount = 3
  1620. elseif curByte>=240 and curByte<=247 then
  1621. byteCount = 4
  1622. end
  1623. nextIndex = i + byteCount;
  1624. if len >= endPos then
  1625. break;
  1626. end
  1627. if byteCount == 1 then
  1628. len = len + 1;
  1629. else
  1630. len = len + 2;
  1631. end
  1632. pos = pos + byteCount;
  1633. end
  1634. end
  1635. return string.sub(str, 1, pos);
  1636. end
  1637. -- 获取名字的长度,一个中文算2个长度单位,一个英文字符算一个长度单位
  1638. function getStringLen(str)
  1639. assert(type(str) == "string")
  1640. local len = 0;
  1641. local size = #str;
  1642. local nextIndex = 1;
  1643. for i = 1, size do
  1644. if i >= nextIndex then
  1645. local curByte = string.byte(str, i)
  1646. local byteCount = 1;
  1647. if curByte>0 and curByte<=127 then
  1648. byteCount = 1
  1649. elseif curByte>=192 and curByte<223 then
  1650. byteCount = 2
  1651. elseif curByte>=224 and curByte<239 then
  1652. byteCount = 3
  1653. elseif curByte>=240 and curByte<=247 then
  1654. byteCount = 4
  1655. end
  1656. nextIndex = i + byteCount;
  1657. if byteCount == 1 then
  1658. len = len + 1;
  1659. else
  1660. len = len + 2;
  1661. end
  1662. end
  1663. end
  1664. return len;
  1665. end
  1666. -- 系统自带的base64编码和解码好像有问题,在某些设备上可能出现缺少最后一个字符的情况
  1667. -- 所以自己写一个
  1668. function ToBase64(source_str)
  1669. local b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  1670. local s64 = ''
  1671. local str = source_str
  1672. while #str > 0 do
  1673. local bytes_num = 0
  1674. local buf = 0
  1675. for byte_cnt=1,3 do
  1676. buf = (buf * 256)
  1677. if #str > 0 then
  1678. buf = buf + string.byte(str, 1, 1)
  1679. str = string.sub(str, 2)
  1680. bytes_num = bytes_num + 1
  1681. end
  1682. end
  1683. for group_cnt=1,(bytes_num+1) do
  1684. b64char = math.fmod(math.floor(buf/262144), 64) + 1
  1685. s64 = s64 .. string.sub(b64chars, b64char, b64char)
  1686. buf = buf * 64
  1687. end
  1688. for fill_cnt=1,(3-bytes_num) do
  1689. s64 = s64 .. '='
  1690. end
  1691. end
  1692. return s64
  1693. end
  1694. function FromBase64(str64)
  1695. local b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  1696. local temp={}
  1697. for i=1,64 do
  1698. temp[string.sub(b64chars,i,i)] = i
  1699. end
  1700. temp['=']=0
  1701. local str=""
  1702. for i=1,#str64,4 do
  1703. if i>#str64 then
  1704. break
  1705. end
  1706. local data = 0
  1707. local str_count=0
  1708. for j=0,3 do
  1709. local str1=string.sub(str64,i+j,i+j)
  1710. if not temp[str1] then
  1711. return
  1712. end
  1713. if temp[str1] < 1 then
  1714. data = data * 64
  1715. else
  1716. data = data * 64 + temp[str1]-1
  1717. str_count = str_count + 1
  1718. end
  1719. end
  1720. for j=16,0,-8 do
  1721. if str_count > 0 then
  1722. str=str..string.char(math.floor(data/math.pow(2,j)))
  1723. data=math.mod(data,math.pow(2,j))
  1724. str_count = str_count - 1
  1725. end
  1726. end
  1727. end
  1728. return str
  1729. end
  1730. local clubXmlData, clubXmlPath = newLocalXmlFile("ClubConfig");
  1731. local XmlFileClubTable = {
  1732. ["ClubConfig"] = { data = clubXmlData, path = clubXmlPath },
  1733. }
  1734. -- xml 以xml格式保存茶馆数据
  1735. function saveClubXml(eName, eValue, fileName)
  1736. if not fileName then
  1737. fileName = "ClubConfig";
  1738. else
  1739. initLocalXmlFile(fileName);
  1740. end
  1741. local fileData = XmlFileClubTable[fileName];
  1742. fileData.data[eName] = eValue;
  1743. xml.save(fileData.data , fileData.path);
  1744. end
  1745. -- xml 载入茶馆xml数据
  1746. function loadClubXml(eName, fileName)
  1747. if not fileName then
  1748. fileName = "ClubConfig";
  1749. else
  1750. initLocalXmlFile(fileName);
  1751. end
  1752. local fileData = XmlFileClubTable[fileName];
  1753. return fileData.data[eName] or "";
  1754. end
  1755. local clubPasswordKey = "dfdsfsdf#*%&^*&#$^(*&@#^%*(&@#%^sdfdsfdsfwefsdfsdf";
  1756. function saveClubInfo(key,value)
  1757. saveClubXml(tostring(key) , escape(md5.crypt(tostring(value) , clubPasswordKey)));
  1758. end
  1759. function loadClubInfo(key)
  1760. local value = loadClubXml(tostring(key));
  1761. if value ~= "" then
  1762. return md5.decrypt(unescape(value) , clubPasswordKey);
  1763. else
  1764. return value;
  1765. end
  1766. end