c1_lua/lua/app/first/first.lua
2023-04-26 15:09:23 +08:00

597 lines
20 KiB
Lua

local First = {}
local json = require "rapidjson"
local firstText = require "app/first/first_text"
local FIRST_ROOT_PREFAB_PATH = "assets/first/ui/first_root.prefab"
local FIRST_UI_PREFAB_PATH = "assets/first/ui/first.prefab"
local BFLaunchMgr = CS.BF.BFMain.Instance.GameLaunchMgr
local BFPlatform = CS.BF.BFPlatform
local BFSDKManager = CS.BF.BFMain.Instance.SDKMgr
local PlayerPrefs = CS.UnityEngine.PlayerPrefs
local TYPE_BF_TOUCH_EVENT = typeof(CS.BF.UITouchEvent)
local TYPE_TEXT = typeof(CS.UnityEngine.UI.Text)
local VISIBLE_SCALE = { x = 1, y = 1, z = 1}
local NOT_VISIBLE_SCALE = { x = 0, y = 0, z = 0}
local EVENT_UP_INSIDE = 3
local REQUEST_ADDR_TIME_OUT = 3 -- 请求版本信息的超时时间
local REQUEST_ADDR_MAX_RETRY_TIMES = 2 -- 最大重试次数
local REQUEST_ADDR_ERROR_TYPE = {
VALUE_INVALID = "VALUE_INVALID",
REQUEST_FAIL = "REQUEST_FAIL",
TIME_OUT = "TIME_OUT"
}
local LANGUAGES = {
["en"] = true,
["cn"] = true,
["zh"] = true,
-- ["id"] = true, -- 印尼
-- ["vi"] = true, -- 越南
-- ["fr"] = true, -- 法语
-- ["de"] = true, -- 德语
-- ["pt"] = true, -- 葡萄牙
-- ["ja"] = true, -- 日本
-- ["ko"] = true, -- 韩国
}
function First:init()
self:initLanguage()
self:initLaunchRequester()
end
function First:initLanguage()
self.language = PlayerPrefs.GetString("SELECTED_LANGUAGE", "")
print("first init language " .. self.language)
if not LANGUAGES[self.language] then
self.language = self:getSystemLanguage()
if self.language == nil then
self.language = BFPlatform.GetCurrentLanguageInfo():GetFallbackLanguage()
end
PlayerPrefs.SetString("SELECTED_LANGUAGE", self.language)
end
self.stringMap = firstText.data
self.strNoNetwork = self.stringMap["STR_NO_NETWORK_CONNECTION"][self.language]
self.strOK = self.stringMap["STR_OK"][self.language]
self.strGoto = self.stringMap["STR_GOTO"][self.language]
self.strCancel = self.stringMap["STR_CANCEL"][self.language]
self.strDownloading = self.stringMap["STR_DOWNLOADING_RES"][self.language]
self.strRepair = self.stringMap["STR_REPAIR_RES"][self.language]
-- 对话框提示文字
self.dialogStr = {
[1] = self.stringMap["DIALOG_STR_1"][self.language],
[2] = self.stringMap["DIALOG_STR_2"][self.language],
[3] = self.stringMap["DIALOG_STR_3"][self.language],
[4] = self.stringMap["DIALOG_STR_4"][self.language],
[5] = self.stringMap["DIALOG_STR_5"][self.language],
[6] = self.stringMap["DIALOG_STR_6"][self.language],
[100] = self.stringMap["DIALOG_STR_100"][self.language],
}
-- 进度条提示文字
self.sliderStr = {
[1] = self.stringMap["SLIDER_STR_1"][self.language],
[2] = self.stringMap["SLIDER_STR_2"][self.language],
[3] = self.stringMap["SLIDER_STR_3"][self.language],
[4] = self.stringMap["SLIDER_STR_4"][self.language],
[5] = self.stringMap["SLIDER_STR_5"][self.language],
[6] = self.stringMap["SLIDER_STR_6"][self.language],
}
end
function First:getSystemLanguage()
local sdkLanguage = BFSDKManager:GetLanguage()
print("first get sdk language " .. sdkLanguage)
local languageInfo = self:splitString(sdkLanguage, "_")
if not languageInfo or #languageInfo ~= 2 then
print("first return system language nil")
return nil
end
local language = languageInfo[1]
local country = languageInfo[2]
if language and language == "zh" then
if country and country == "CN" then
language = "cn"
end
end
if not LANGUAGES[language] then
language = nil
end
if language then
print("first return system language " .. language)
else
print("first return system language nil")
end
return language
end
function First:splitString(input, delimiter)
input = tostring(input)
delimiter = tostring(delimiter)
if (delimiter=='') then return false end
local pos, arr = 0, {}
for st, sp in function() return string.find(input, delimiter, pos, true) end do
table.insert(arr, string.sub(input, pos, st - 1))
pos = sp + 1
end
table.insert(arr, string.sub(input, pos))
return arr
end
function First:initLaunchRequester()
local lr = BFLaunchMgr.LaunchRequester
-- 当前多语言
lr:SetLanguageName(self.language)
-- 第一次请求版本号
lr:SetFirstRequestAction(function(version, identifier, onGetVersion)
self:requestAddress(onGetVersion)
end)
-- 对话框
lr:SetShowDialogAction(function(eCode, okCallback)
local str = self.dialogStr[eCode] or ""
self:showDialog(str, okCallback)
end)
-- 多选对话框
lr:SetShowDialogComplexAction(function(eCode, okCallback, cancelCallback)
local str = self.dialogStr[eCode] or ""
if eCode == 1 or eCode == 6 then -- 前往商店的时候设置一下确认按钮的文本
self:showDialogComplex(str, okCallback, cancelCallback, self.strGoto)
else
self:showDialogComplex(str, okCallback, cancelCallback)
end
end)
-- 隐藏对话框
lr:SetHideDialogAction(function()
self:hideDialog()
end)
-- 进度条
lr:SetUpdateSliderAction(function(sliderCode, progress)
local str = self.sliderStr[sliderCode]
self:showSlider()
self:setSliderText(str)
self:setSliderPercentText("")
end)
-- 隐藏进度条
lr:SetHideSliderAction(function()
self:hideSlider()
end)
-- 预检查完成
lr:SetPreCheckEndCallback(function()
self:onPreCheckEnd()
end)
-- 获取到总进度
lr:SetGetTotalLengthCallback(function(totalSize)
self.downloadTotalSize = totalSize
local mb = totalSize / 1048576
if mb < 0.01 then
mb = 0.01
end
self.downloadTotalSizeStr = string.format("%sMB", (mb - mb % 0.01))
local str
local isRepair = BFLaunchMgr.LaunchRequester.isAutoRepair
if isRepair then
str = string.format(self.strRepair, 0, self.downloadTotalSizeStr)
else
str = string.format(self.strDownloading, 0, self.downloadTotalSizeStr)
end
self:showSlider()
self:setSliderText(str)
self:setSliderPercentText("")
end)
-- 下载更新
lr:SetDownloadingCallback(function(size)
local mb = size / 1048576
if mb < 0.01 then
mb = 0.01
end
local sizeStr = string.format("%sMB", (mb - mb % 0.01))
local str
local isRepair = BFLaunchMgr.LaunchRequester.isAutoRepair
if isRepair then
str = string.format(self.strRepair, sizeStr, self.downloadTotalSizeStr)
else
str = string.format(self.strDownloading, sizeStr, self.downloadTotalSizeStr)
end
local progress = size / (self.downloadTotalSize or 1)
self:showSlider()
self:setSliderText(str)
self:setSliderPercentText(math.floor(progress * 100) .. "%")
end)
-- 启动成功
lr:AddLaunchSuccCallback(function()
CS.UnityEngine.Object.Destroy(self.firstUI)
CS.UnityEngine.Object.Destroy(self.firstRoot)
self.firstUI = nil
self.firstRoot = nil
end)
end
function First:showUI()
local firstAb = BFLaunchMgr:GetFirstAB()
self.firstAb = firstAb
local firstRootAsset = self.firstAb:LoadAsset(FIRST_ROOT_PREFAB_PATH, typeof(CS.UnityEngine.GameObject))
self.firstRoot = CS.UnityEngine.Object.Instantiate(firstRootAsset)
self.canvasTrans = self.firstRoot.transform:Find("canvas")
if BFLaunchMgr.LaunchRequester.launchSucceed then
self:showFirstUI()
else
self:showLogo()
end
end
function First:loadFirstUI()
if not self.firstUI then
local firstUIAsset = self.firstAb:LoadAsset(FIRST_UI_PREFAB_PATH, typeof(CS.UnityEngine.GameObject))
self.firstUI = CS.UnityEngine.Object.Instantiate(firstUIAsset)
self.firstUI.transform:SetParent(self.canvasTrans, false)
self.progressText = self.firstUI.transform:Find("progress_text")
self.sliderPercentText = self.progressText:GetComponent(TYPE_TEXT)
self.sliderText = self.firstUI.transform:Find("slider_text"):GetComponent(TYPE_TEXT)
local logoEn = self.firstUI.transform:Find("logo_en")
local logoZH = self.firstUI.transform:Find("logo_zh")
local logoCn = self.firstUI.transform:Find("logo_cn")
if self.language == "zh" then
logoZH.localScale = VISIBLE_SCALE
logoEn.localScale = NOT_VISIBLE_SCALE
logoCn.localScale = NOT_VISIBLE_SCALE
elseif self.language == "cn" then
logoCn.localScale = VISIBLE_SCALE
logoEn.localScale = NOT_VISIBLE_SCALE
logoZH.localScale = NOT_VISIBLE_SCALE
else
logoEn.localScale = VISIBLE_SCALE
logoZH.localScale = NOT_VISIBLE_SCALE
logoCn.localScale = NOT_VISIBLE_SCALE
end
self.dialogTrans = self.firstUI.transform:Find("message_box")
self.confirmBtnTrans = self.firstUI.transform:Find("message_box/title_bg_img/ok_btn")
local confirmBtn = self.confirmBtnTrans:GetComponent(TYPE_BF_TOUCH_EVENT)
confirmBtn:AddTouchEventListener(function(eventType, x, y)
if eventType == EVENT_UP_INSIDE and self.confirmCallback then
self.confirmCallback()
self:hideDialog()
end
end)
self.confirmText = self.firstUI.transform:Find("message_box/title_bg_img/ok_btn/text"):GetComponent(TYPE_TEXT)
self.confirmText.text = self.strOK
self.cancelBtnTrans = self.firstUI.transform:Find("message_box/title_bg_img/cancel_btn")
local cancelBtn = self.cancelBtnTrans:GetComponent(TYPE_BF_TOUCH_EVENT)
cancelBtn:AddTouchEventListener(function(eventType, x, y)
if eventType == EVENT_UP_INSIDE and self.cancelCallback then
self.cancelCallback()
self:hideDialog()
end
end)
local cancelText = self.firstUI.transform:Find("message_box/title_bg_img/cancel_btn/text"):GetComponent(TYPE_TEXT)
cancelText.text = self.strCancel
self.contentText = self.firstUI.transform:Find("message_box/title_bg_img/content_tx"):GetComponent(TYPE_TEXT)
local versionText = self.firstUI.transform:Find("version"):GetComponent(TYPE_TEXT)
local appVersionText = self.stringMap["STR_APP_VERSION"][self.language]
if appVersionText == nil then
appVersionText = "App: "
end
local version = BFLaunchMgr:GetCurrentVersion()
versionText.text = appVersionText .. version
end
end
---- 请求地址信息
function First:requestAddress(callback, times, totalTimes)
local responded = false
if (self.hasReceiveAddrSuccess == nil) then
self.hasReceiveAddrSuccess = false
end
if (self.showAddrErrorBox == nil) then
self.showAddrErrorBox = false
end
if times == nil then -- 本次循环的连接次数,每次连接会进行一定次数的自动重连
times = 0
end
if totalTimes == nil then -- 用于标记唯一ID
totalTimes = 0
end
times = times + 1
totalTimes = totalTimes + 1
local connectStartTimes = os.clock()
local loginCenterUrl = BFPlatform.GetLoginCenterURL()
local version = BFLaunchMgr:GetCurrentVersion()
local args = {
project_id = "b6",
version = version,
device_id = CS.UnityEngine.SystemInfo.deviceUniqueIdentifier,
bundle_id = CS.UnityEngine.Application.identifier,
env = "release",
}
local platform = "Editor"
if CS.UnityEngine.Application.platform == CS.UnityEngine.RuntimePlatform.Android then
platform = "Android"
elseif CS.UnityEngine.Application.platform == CS.UnityEngine.RuntimePlatform.IPhonePlayer then
platform = "iOS"
end
loginCenterUrl = loginCenterUrl .. "?platform=" .. CS.System.Uri.EscapeDataString(platform)
-- lua这边直接构建好参数
for k, v in pairs(args) do
loginCenterUrl = loginCenterUrl .. "&" .. k .. "=" .. CS.System.Uri.EscapeDataString(v)
end
local guid = CS.BF.BFMain.Instance.SDKMgr.BFLoginSDKMgr:GetNewPlayerGuid()
loginCenterUrl = loginCenterUrl .. "&random=" .. CS.System.Uri.EscapeDataString(guid)
CS.BF.BFMain.Instance.SDKMgr.BFLoginSDKMgr:GetWithURL(loginCenterUrl, function (req, rsp)
if rsp and rsp.IsSuccess == true then
if rsp.Data then -- 有数据就算成功
local serverResult = json.decode(rsp.Data)
if serverResult then
responded = true
-- 如果已经成功过了 不作处理
if self.hasReceiveAddrSuccess then
return
end
self.hasReceiveAddrSuccess = true
self.requestAddressRsp = rsp.Data
if not self.showAddrErrorBox then
self:setShenHeLanguageAndReqATT()
-- 上报版本请求成功
local args = {
request_version_current = version,
request_version_url = loginCenterUrl,
request_version_connect_time = (os.clock() - connectStartTimes)*1000,
request_version_retry_times = totalTimes - 1,
request_version_result = "success",
}
CS.BF.BFMain.Instance.SDKMgr.BFThirdReportSDKMgr:PostThinkingAnalyticsEvent("client_request_version", json.encode(args))
-- 走后续步骤
if callback then
callback(rsp.Data)
end
end
else
self:tryShowRequestAddrErrorBox(connectStartTimes, callback, REQUEST_ADDR_ERROR_TYPE.REQUEST_FAIL, times, totalTimes)
end
else
self:tryShowRequestAddrErrorBox(connectStartTimes, callback, REQUEST_ADDR_ERROR_TYPE.REQUEST_FAIL, times, totalTimes)
end
else
self:tryShowRequestAddrErrorBox(connectStartTimes, callback, REQUEST_ADDR_ERROR_TYPE.REQUEST_FAIL, times, totalTimes)
end
end)
CS.BF.BFMain.Instance.TaskMgr:EasyTimer(REQUEST_ADDR_TIME_OUT, function()
if not responded and not self.hasReceiveAddrSuccess and not self.showAddrErrorBox then
self:tryShowRequestAddrErrorBox(connectStartTimes, callback, REQUEST_ADDR_ERROR_TYPE.TIME_OUT, times, totalTimes)
end
end)
end
-- 请求地址失败的处理
function First:tryShowRequestAddrErrorBox(connectStartTimes, callback, reqAddrErrorType, times, totalTimes)
if self.recordReqAddrFailTimes == nil then
self.recordReqAddrFailTimes = {}
end
local hasRecord = self.recordReqAddrFailTimes[totalTimes] ~= nil
print("tryShowRequestAddrErrorBox errorType:" .. reqAddrErrorType .. " hasRecord:" .. tostring(hasRecord) .. " times:" .. times .. " totalTimes:" .. totalTimes)
if times > REQUEST_ADDR_MAX_RETRY_TIMES then
if not self.showAddrErrorBox then
if self.hasReceiveAddrSuccess then
return
end
self.hasReceiveAddrSuccess = true
CS.BF.BFMain.IsStandAlone = true
self:setShenHeLanguageAndReqATT()
if callback then
callback("")
end
end
else -- 静默重试
-- 重试
if not hasRecord then
CS.BF.BFMain.Instance.TaskMgr:EasyTimer(0, function()
self:requestAddress(callback, times, totalTimes) -- 重新开始
end)
end
end
-- 失败上报
if not hasRecord then
self.recordReqAddrFailTimes[totalTimes] = 1
local args = {
request_version_current = BFLaunchMgr:GetCurrentVersion(),
request_version_url = BFPlatform.GetLoginCenterURL(),
request_version_connect_time = (os.clock() - connectStartTimes)*1000,
request_version_error_type = reqAddrErrorType,
request_version_retry_times = totalTimes - 1,
request_version_result = "failed",
}
CS.BF.BFMain.Instance.SDKMgr.BFThirdReportSDKMgr:PostThinkingAnalyticsEvent("client_request_version", json.encode(args))
end
end
-- 审核包特殊处理,语言设置,并且如果是ios则请求ATT
function First:setShenHeLanguageAndReqATT()
end
function First:showFirstUI()
self:loadFirstUI()
self:hideSlider()
self:hideDialog()
end
-- 隐藏确认框
function First:hideDialog()
if self.dialogTrans then
self.dialogTrans.gameObject:SetActive(false)
end
end
-- 隐藏slider
function First:hideSlider()
if self.dialogTrans then
self.progressText.gameObject:SetActive(false)
end
end
-- 显示slider
function First:showSlider()
self.progressText.gameObject:SetActive(true)
end
-- 设置slider文本
function First:setSliderText(str)
self.sliderText.text = str
end
-- 设置slider的文本
function First:setSliderPercentText(value)
self.sliderPercentText.text = value
end
-- 显示对话框, ok
function First:showDialog(contentStr, callback)
self.dialogTrans.gameObject:SetActive(true)
self.contentText.text = contentStr
self.confirmText.text = self.strOK
self.confirmCallback = callback
self.cancelBtnTrans.gameObject:SetActive(false)
self.confirmBtnTrans.localPosition = {
x = 0,
y = -161,
z = 0
}
end
-- 显示对话框, ok cancel
function First:showDialogComplex(contentStr, okCallback, cancelCallback, confirmStr)
self.dialogTrans.gameObject:SetActive(true)
self.contentText.text = contentStr
self.confirmText.text = confirmStr or self.strOK
self.confirmCallback = okCallback
self.cancelCallback = cancelCallback
self.cancelBtnTrans.gameObject:SetActive(true)
self.confirmBtnTrans.localPosition = {
x = 138,
y = -161,
z = 0
}
end
-- 显示项目logo
function First:showLogo()
self.logoEnd = true
if self.preCheckEnd then
self:onLogoEnd()
end
end
-- logo播放完毕
function First:onLogoEnd()
self:loadFirstUI()
self:hideSlider()
self:hideDialog()
self:showSlider()
BFLaunchMgr.LaunchRequester:PreCheckNextProcess()
end
-- 预检查完成
function First:onPreCheckEnd()
self.preCheckEnd = true
if self.logoEnd then
self:onLogoEnd()
end
end
function First:compareVersionThan(version1, version2, include)
if not version1 or not version2 then
return false
end
local versionStrs = self:split(version1, ".")
local versionNum1 = tonumber(versionStrs[1])
local versionNum2 = tonumber(versionStrs[2])
local versionNum3 = tonumber(versionStrs[3])
local versionStrs2 = self:split(version2, ".")
local versionNum21 = tonumber(versionStrs2[1])
local versionNum22 = tonumber(versionStrs2[2])
local versionNum23 = tonumber(versionStrs2[3])
if not versionNum1 or not versionNum2 or not versionNum3 or not versionNum21 or not versionNum22 or not versionNum23 then
return false
end
if versionNum1 > versionNum21 then
return true, true
elseif versionNum1 < versionNum21 then
return false
end
if versionNum2 > versionNum22 then
return true, true
elseif versionNum2 < versionNum22 then
return false
end
if versionNum3 > versionNum23 then
return true
elseif versionNum3 < versionNum23 then
return false
end
if include then
return true
end
return false
end
function First:split(input, delimiter)
input = tostring(input)
delimiter = tostring(delimiter)
if (delimiter=='') then return false end
local pos,arr = 0, {}
for st,sp in function() return string.find(input, delimiter, pos, true) end do
table.insert(arr, string.sub(input, pos, st - 1))
pos = sp + 1
end
table.insert(arr, string.sub(input, pos))
return arr
end
First:init()
First:showUI()
return First