Jelajahi Sumber

同步常规版修改

gitxsm 3 minggu lalu
induk
melakukan
0496196c04
34 mengubah file dengan 653 tambahan dan 142 penghapusan
  1. 9 4
      script/common/CommonDefine.lua
  2. 8 0
      script/common/ProtoID.lua
  3. 3 0
      script/core/ObjHuman.lua
  4. 1 1
      script/core/Timer.lua
  5. 7 1
      script/module/absAct/CommonActLoginGift.lua
  6. 3 0
      script/module/absAct/CommonActMoneyTree.lua
  7. 3 0
      script/module/bag/BagLogic.lua
  8. 14 1
      script/module/battle/BattleLogic.lua
  9. 4 0
      script/module/battle/Handler.lua
  10. 9 0
      script/module/battle/Proto.lua
  11. 101 0
      script/module/broadcast/BigRPlayerShow.lua
  12. 5 0
      script/module/broadcast/Proto.lua
  13. 9 0
      script/module/chengjiu/ChengjiuLogic.lua
  14. 21 1
      script/module/combat/BeSkill.lua
  15. 9 0
      script/module/combat/CombatBuff.lua
  16. 2 2
      script/module/combat/Skill.lua
  17. 8 2
      script/module/drawCard/Proto.lua
  18. 0 1
      script/module/elf/ElfLogic.lua
  19. 22 1
      script/module/lostTemple/lostTempleLogic.lua
  20. 136 30
      script/module/mail/MailManager.lua
  21. 28 8
      script/module/role/CreateRole.lua
  22. 22 0
      script/module/scene/Handler.lua
  23. 3 0
      script/module/serverCommerce/ServerCommerceActBattleGroundCS.lua
  24. 2 2
      script/module/serverCommerce/ServerCommerceActDefine.lua
  25. 2 67
      script/module/topup/GiftLogic.lua
  26. 3 0
      script/module/vip/VipLogic.lua
  27. 3 0
      webServer/src/channels/factory/ChannelFactory.ts
  28. 18 16
      webServer/src/channels/handlers/ZeroOneChannelHandler.ts
  29. 42 1
      webServer/src/config/channelConfig.ts
  30. 12 0
      webServer/src/config/thirdParams.ts
  31. 73 2
      webServer/src/controller/ApiController.ts
  32. 67 1
      webServer/src/mongo/mongodb.ts
  33. 3 0
      webServer/src/router/index.ts
  34. 1 1
      webServer/src/utils/msg.ts

+ 9 - 4
script/common/CommonDefine.lua

@@ -2,23 +2,28 @@ local Lang = require("common.Lang")
 
 ---------------------------------------------渠道标识--------------------------
 
-CHANNEL_TAG_MUZI = 1             -- 木子/tap
+CHANNEL_TAG_MUZI = 1             -- 木子/tap安卓
 CHANNEL_TAG_SANLI_ANDROID = 2    -- 三狸安卓
 CHANNEL_TAG_SANLI_IOS = 3        -- 三狸iOS
 CHANNEL_TAG_SANLI_QQ = 4         -- 三狸QQ大厅
 CHANNEL_TAG_SANLI_H5= 5          -- 三狸H5
 CHANNEL_TAG_SANLI_H5_4399 = 6    -- 三狸H5-4399
+CHANNEL_TAG_SANLI_360 = 7        -- 三狸360小游戏
+CHANNEL_TAG_SANLI_AIQI_H5 = 8    -- 艾七H5
+CHANNEL_TAG_MUZI_IOS = 9         -- 木子/tap IOS
+CHANNEL_TAG_SANLI_SHIYOU = 10    -- 三狸视游
+
 CHANNEL_TAG_WX = 11              -- 微信小程序,抖音游戏, 圣扬IOS
 CHANNEL_TAG_HP = 14              -- 虎扑
 CHANNEL_TAG_720 = 15             -- 720
 CHANNEL_TAG_MINNIGAME = 17       -- 美团, 华为, 淘宝
-
-
 CHANNEL_TAG_FT = 18             -- 繁体
 
+CHANNEL_TAG_GUILD1 = 23         -- 公会渠道1
+CHANNEL_TAG_GUILD2 = 24         -- 公会渠道2
 
 
-SEA_CHANNEL_ARR = {13, 18}  -- 海外渠道
+SEA_CHANNEL_ARR = {13, 18}  -- 海外渠道列表
 
 ----------------------------------------------------------------------------
 

+ 8 - 0
script/common/ProtoID.lua

@@ -1736,6 +1736,7 @@ _ENV[1776]="GC_ZHUANPAN_ONCE_REWARD_QUERY"
 _ENV[1777]="CG_ZHUANPAN_ONCE_REWARD_GET"
 _ENV[1778]="CG_ALL_HERO_BOOK_QUERY"
 _ENV[1779]="GC_ALL_HERO_BOOK_QUERY"
+_ENV[1780]="GC_DRAWCARD_OP2"
 _ENV[1781]="CG_SERVEERCOMMERCE_ACT_BATTLEGROUND_MAINPAGE_QUERY"
 _ENV[1782]="GC_SERVEERCOMMERCE_ACT_BATTLEGROUND_MAINPAGE_QUERY"
 _ENV[1783]="CG_SERVEERCOMMERCE_ACT_BATTLEGROUND_MATCHLIST_QUERY"
@@ -1809,6 +1810,10 @@ _ENV[1849]="CG_BATTLEGIFT_QUERY"
 _ENV[1850]="GC_BATTLEGIFT_QUERY"
 _ENV[1851]="CG_BATTLEGIFT_GET"
 
+-- _ENV[1852]="CG_UNION_CREATE_COND_QUERY" -- 1折版本特有功能
+-- _ENV[1853]="GC_UNION_CREATE_COND_QUERY"
+
+_ENV[1854]="GC_POWERRANK_TOPONE_LOGIN"
 
 _ENV[1896]="CG_ZHUANPAN_SUBSCRIBE_REWARD_QUERY"
 _ENV[1897]="GC_ZHUANPAN_SUBSCRIBE_REWARD_QUERY"
@@ -1827,3 +1832,6 @@ _ENV[1904]="CG_ZHUANPAN_DY_DESKTOP_SET"
 _ENV[1905]="CG_ZHUANPAN_DY_DESKTOP_QUERY"
 _ENV[1906]="GC_ZHUANPAN_DY_DESKTOP_QUERY"
 
+_ENV[1907]="CG_BATTLE_HANG_FULL_TIME_QUERY"
+_ENV[1908]="GC_BATTLE_HANG_FULL_TIME_QUERY"
+

+ 3 - 0
script/core/ObjHuman.lua

@@ -106,6 +106,7 @@ local AnotherWorldBattleNS = require("anotherWorldBattle.AnotherWorldBattleNS")
 local RoleStorageBox = require("roleSystem.RoleStorageBox")
 local BreakThroughTheme = require("battle.BreakThroughTheme")
 local BattleGift = require("battle.BattleGift")
+local BigRPlayerShow = require("broadcast.BigRPlayerShow")
 
 
 local Json = require("common.Json")
@@ -853,6 +854,8 @@ function onLogin(human, isNew)
 		msgRet.param2 = 0
 		Msg.send(msgRet,human.fd)
 	end
+
+	BigRPlayerShow.onLogin(human)
 	
 	-- 注意 这个函数写在doLogin的最后
 	MiddleLogic.onLogin(human)

+ 1 - 1
script/core/Timer.lua

@@ -126,7 +126,7 @@ function doZhengDian(hour)
         BillboardLogic.onZero()
         ChatRecord.CHAT_RECORD_REPETITION = {}
         HeroGrowUp.actLoop()
-        LostTempleLogic.onZero()
+        -- LostTempleLogic.onZero()
 	    VoucherShopLogic.VoucherShop_OnZero()
         MainDianLogic.MaiDian_OnTime()
         ServerCommerceMiddle.CommerceMiddle_OnZero()

+ 7 - 1
script/module/absAct/CommonActLoginGift.lua

@@ -175,7 +175,7 @@ function onCharge(human, nBuyID, buyNum)
 end
 
 function updateDaily(human, funcID)
-    if isOpenAct(human, COMMONACT_LOGINGIFT_ID) then
+    if not isOpenAct(human, COMMONACT_LOGINGIFT_ID) then
         return
     end
 
@@ -187,6 +187,9 @@ end
 
 -- 查询
 function CommonActLoginGift_Query(human)
+    if not isOpenAct(human, COMMONACT_LOGINGIFT_ID) then
+        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
+    end
     local msgRet = Msg.gc.GC_ABS_COMONACT_LOGINGIFT_QUERY
     msgRet.giftDatafree[0] = 0
     msgRet.giftData68[0] = 0
@@ -254,6 +257,9 @@ end
 
 -- 领取奖励
 function CommonActLoginGift_GetReward(human, targetGiftType)
+    if not isOpenAct(human, COMMONACT_LOGINGIFT_ID) then
+        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
+    end
     local type_2_cfg = transformCfg()
     local giftArr = type_2_cfg[targetGiftType]
     if not giftArr then

+ 3 - 0
script/module/absAct/CommonActMoneyTree.lua

@@ -184,6 +184,9 @@ end
 
 -- 查询
 function CommonActMoneyTree_Query(human)
+    if not isOpenAct(human, COMMONACT_MONEYTREE_ID) then
+        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
+    end
     local msgRet = Msg.gc.GC_ABS_COMONACT_MONEYTREE_QUERY
     msgRet.rewardBasket[0] = 0
     msgRet.weighMax = BASKET_WEIGHT_MAX

+ 3 - 0
script/module/bag/BagLogic.lua

@@ -285,6 +285,9 @@ function handlerSpObj(human, itemID, itemCnt, logType)
     	return
     end
 
+	Log.write(Log.LOGID_OSS_ITEM, human.db._id, human.db.account, human.db.name, human.db.lv,
+		LogDefine.DEFINE[logType] + LogDefine.TYPE["item"] , itemID, itemCnt, 0)
+
 	local cmdstr = itemConfig.cmd and itemConfig.cmd[1]
 	if cmdstr and ItemLogic.cmd[cmdstr] then
 		ItemLogic.onlyuse(human, itemID, itemCnt, logType, true)

+ 14 - 1
script/module/battle/BattleLogic.lua

@@ -2761,6 +2761,19 @@ local function hangExpGet(human,isDiamond)
     return 0, items
 end
 
+-- 下发挂机奖励满载时间戳
+-- fullTime = expTs1 + maxHangTime
+--   若 fullTime <= now  则奖励已满,满的时刻为 fullTime
+--   若 fullTime >  now  则奖励未满,将在 fullTime 时满
+function sendHangFullTime(human)
+    local tBattleOut = BattleLogic_GetBattleOut(human)
+    if not tBattleOut then return end
+    local maxHangTime = getHangMaxTime(human)
+    local msgRet = Msg.gc.GC_BATTLE_HANG_FULL_TIME_QUERY
+    msgRet.fullTime = tBattleOut.expTs1 + maxHangTime
+    Msg.send(msgRet, human.fd)
+end
+
 -- 获取挂机收益
 function hangGet(human,isDiamond)
     local ret, items = hangExpGet(human,false)
@@ -2770,7 +2783,7 @@ function hangGet(human,isDiamond)
         return Broadcast.sendErr(human, Lang.COMMON_ADD_JINBI_LIMIT)
     elseif ret == 0 then
         query(human)
-        
+        sendHangFullTime(human)
         RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1101)
         TreasureChestLogic.TreasureChestLogic_GetAllBoxNum(human)
     end

+ 4 - 0
script/module/battle/Handler.lua

@@ -12,6 +12,10 @@ function CG_BATTLE_HANG_GET(human)
 	BattleLogic.hangGet(human)
 end
 
+function CG_BATTLE_HANG_FULL_TIME_QUERY(human)
+	BattleLogic.sendHangFullTime(human)
+end
+
 function CG_BATTLE_NODE_SET(human, msg)
 	BattleLogic.nodeSet(human, msg.battleID)
 end

+ 9 - 0
script/module/battle/Proto.lua

@@ -153,6 +153,15 @@ GC_BATTLE_HANG_QUERY = {
 CG_BATTLE_HANG_GET = {
 }
 
+-- 挂机奖励满载时间查询
+-- fullTime: 满载时刻的Unix时间戳
+--   fullTime <= 当前时间  => 已经满了,满的时间是fullTime
+--   fullTime >  当前时间  => 还没满,将在fullTime时满
+CG_BATTLE_HANG_FULL_TIME_QUERY = {}
+
+GC_BATTLE_HANG_FULL_TIME_QUERY = {
+    {"fullTime", 1, "int"},   -- 挂机满载时的时间戳
+}
 
 -- 战役节点详细信息查询
 CG_BATTLE_NODE_DETAIL_QUERY = {

+ 101 - 0
script/module/broadcast/BigRPlayerShow.lua

@@ -0,0 +1,101 @@
+-- 大R玩家实力显示
+
+local Msg = require("core.Msg")
+local ObjHuman = require("core.ObjHuman")
+local BillboardLogic = require("billboard.BillboardLogic")
+local BillboardDefine = require("billboard.BillboardDefine")
+local Util = require("common.Util")
+-- local CommonDB = require("common.CommonDB")
+
+-- local pRank1lastBroadcastTime
+
+
+-- local function getBigRPlayerData()
+--     return CommonDB.getValueByKey(CommonDB.KEY_BIGRPLAYER_SHOW_DATA)
+-- end
+
+-- local function updateBigRPlayerData(newData)
+--     CommonDB.updateValue(CommonDB.KEY_BIGRPLAYER_SHOW_DATA, newData)
+-- end
+
+-- local function getpRank1LastBroadcastTime()
+--     local data = getBigRPlayerData()
+--     return data and data.pRank1lastBroadcastTime
+-- end
+
+-- local function updatepRank1LastBroadcastTime()
+--     local data = getBigRPlayerData()
+--     data = data or {}
+--     local now  = os.time()
+--     data.pRank1lastBroadcastTime = now
+--     updateBigRPlayerData(data)
+
+--     -- 更新缓存
+--     pRank1lastBroadcastTime = now
+-- end
+
+local function isShowTips(human)
+    local bl = true
+    if not human.db.showTipsData then
+        return bl
+    end
+
+    if human.db.lv < 10 then
+        return bl
+    end
+
+    local showTipsData = human.db.showTipsData
+    local pRank1LoginShowTime = showTipsData.pRank1LoginShowTime
+    if not pRank1LoginShowTime then
+        return bl
+    end
+
+    if Util.isSameDay(pRank1LoginShowTime) then
+        bl = false
+    end
+
+    return bl
+end
+
+local function updateShowTipsData(human)
+    human.db.showTipsData = human.db.showTipsData or {}
+    human.db.showTipsData.pRank1LoginShowTime = os.time()
+end
+
+
+
+-- 战力排行榜排名第一的玩家上线的处理
+local function powerRankTopOneLogin(human)
+    -- if not pRank1lastBroadcastTime then
+    --     pRank1lastBroadcastTime = getpRank1LastBroadcastTime()
+    -- end
+
+    -- if pRank1lastBroadcastTime and Util.isSameDay(pRank1lastBroadcastTime) then
+    --     return
+    -- end
+
+    local rankList = BillboardLogic.GetRankList(BillboardDefine.TYPE_ZHANDOULI)
+    if not rankList or not rankList[1] or rankList[1].uuid ~= human.db._id then
+        return
+    end
+
+    local msg = Msg.gc.GC_POWERRANK_TOPONE_LOGIN
+    msg.playerName = human.db.name
+
+    for uuid, h in pairs(ObjHuman.onlineUuid) do
+        if uuid ~= human.db._id and isShowTips(h) then
+            Msg.send(msg, h.fd)
+
+            updateShowTipsData(h)
+        end
+    end
+
+    -- updatepRank1LastBroadcastTime()
+end
+
+
+
+
+function onLogin(human)
+    powerRankTopOneLogin(human)
+end

+ 5 - 0
script/module/broadcast/Proto.lua

@@ -3,3 +3,8 @@ GC_BROADCAST = {
 	{"displayTime",		1,	 "int"},
 	{"msg",			1,	 "string"},
 }
+
+
+GC_POWERRANK_TOPONE_LOGIN = {
+	{"playerName",			1,	 "string"},
+}

+ 9 - 0
script/module/chengjiu/ChengjiuLogic.lua

@@ -297,6 +297,10 @@ function getReward(human,taskID)
     GuideLogic.setDoSpecialGuide(human, GuideLogic.SKIPTYPE_JUMP_JIEFENG_BAOJU)
     RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_2001)
 
+    -- 刷新洗练凤凰..
+    if taskID == 402 then
+        RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_2002)
+    end
 
     local giftType
     GiftLogic = GiftLogic or require("topup.GiftLogic")
@@ -376,6 +380,11 @@ function checkTaskState(human)
             human.db.chengjiu.task = human.db.chengjiu.task or {}
             human.db.chengjiu.task[k] = CJ_TASK_STATE_1
             RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_2001)
+            -- 同时刷新秘宝/圣遗物/精灵入口的红点(强制发送,确保可解封时客户端能看到提示)
+            -- RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_2002,true)
+            -- RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_2006, true)
+            -- RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_2021, true)
+            -- RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_2031, true)
             local msgRet = Msg.gc.GC_DAILYSHARE_SET
             msgRet.type = 2
             msgRet.desc = v.desc

+ 21 - 1
script/module/combat/BeSkill.lua

@@ -507,6 +507,7 @@ end
 -- 连击检测
 local function comboCheck(targetObj, side)
 	if Skill.GroupSkillCnt ~= 1 then return end--技能包首次技能攻击才能触发
+	if CombatImpl.isFanji or CombatImpl.comboType > 0 then return end
 
 	for _,pos in ipairs(CombatDefine.SIDE2POS[side]) do
 		local obj = CombatImpl.objList[pos]
@@ -514,6 +515,25 @@ local function comboCheck(targetObj, side)
 			for _, skillInfo in ipairs(obj.beSkillList[BESKILL_TYPE72] or {}) do
 				local skillCfg = Skill.GetSkillConfig(skillInfo[1])
 				if skillCfg and skillCfg.cmd == "comboProb" then
+					local targetType = skillCfg.beSkillArgs[2] or 0
+					local targetList = skillCfg.beSkillArgs[3]
+					if targetType <= 0 or not targetList then
+						return
+					end
+
+					local bl = false
+					if targetType == 1 then -- 职业
+						if table.find(targetList, targetObj.job) then
+							bl = true
+						end
+					elseif targetType == 2 then -- 种族
+						if table.find(targetList, targetObj.camp) then
+							bl = true
+						end
+					end
+
+					if not bl then return end
+
 					local comboProbVal = skillCfg.beSkillArgs[1] or 0
 					local randval = math.random(0, 10000)
 					if comboProbVal >= randval then
@@ -834,7 +854,7 @@ function onHit(attacker,targets,skillID)
 
 
 	local target = targets[1]
-	if target and target.side == defendSide and CombatObj.getValue(attacker,RoleDefine.RATE_COMBAT_NOW) > 0 then
+	if target and target.side == defendSide and CombatObj.getValue(attacker,RoleDefine.HURT_COMBAT_NOW) > 0 then
 		if attacker.beSkillList[BESKILL_TYPE73] then
 			for _,v in ipairs(attacker.beSkillList[BESKILL_TYPE73]) do
 				use(attacker,targets,v)

+ 9 - 0
script/module/combat/CombatBuff.lua

@@ -306,9 +306,18 @@ local function isMiankong(obj, cmd, attacker, skillKongRate)
 	end
 end
 
+local sp_notBan_buff_list = {
+	["hp"] = true,
+}
+
 -- 是否可能被禁止增加buff
 local function isBanBuff(obj, cmd)
+	if sp_notBan_buff_list[cmd] then
+		return false
+	end
+
 	initCombatBufferType()
+
 	if BUFFER_COMBAT_TYPE[cmd] and BUFFER_COMBAT_TYPE[cmd] == 2 then
 		local res, _, ind = isStatus(obj, { "linglun" })
 		if not res then

+ 2 - 2
script/module/combat/Skill.lua

@@ -659,11 +659,11 @@ function CMD.hurt(obj,skillConfig,skillTargets)
 		hp = calcHp(obj,target,calcType,rate,limit)
 		if hp ~= 0 then
 			local d, _, extraHandleTb = CombatObj.updateHp(target,-hp,nil,true, obj.pos,CombatObj.EXTRA_HP_TYPE)
-			if d ~= 0 then
+			-- if d ~= 0 then
 				CombatImpl.setExtraHit(target,-hp,CMD2ID["hurt"])
 				CombatObj.onHpCB(target,d, obj.pos)
 				ret[#ret+1] = target
-			end
+			-- end
 
 			if extraHandleTb then
 				ExtraHandle(target, extraHandleTb)

+ 8 - 2
script/module/drawCard/Proto.lua

@@ -8,7 +8,7 @@ DrawCardNet = {
 	{"leftFreeTime",1,		"int"},	   -- 免费倒计时
 	{"leftFreeCnt",	1,		"int"},	   -- 剩余免费次数
 	{"items",		3,		ItemData}, -- {1次消耗道具,10次消耗道具}
-	{"zuanshi",		3,		"short"},  -- {1次消耗钻石,10次消耗钻石}0为不能用钻石
+	{"zuanshi",		3,		"int"},  -- {1次消耗钻石,10次消耗钻石}0为不能用钻石
 	{"isFirst",		1,		"byte"},   -- 是否首次十连
 	{"canBuy",		1,		"byte"},   -- 可否购买
 }
@@ -27,7 +27,7 @@ GC_DRAWCARD_QUERY = {
 
 CG_DRAWCARD_OP = {
 	{"id",				1,		"byte"}, --1 基础召唤 2 高级召唤 3 友情召唤 0 积分召唤
-	{"op",				1,		"byte"}, --1 1次 2 10次
+	{"op",				1,		"byte"}, --1 1次 2 10次, 3-100次
     {"skip",		    1,		"byte"}, --是否跳过
     {"isAct",           1,      "int"}, --是否选取up活动
 }
@@ -50,6 +50,12 @@ GC_DRAWCARD_OP = {
 	{"nHighCnt",		1,		"int"},		-- 高级抽卡次数
 }
 
+GC_DRAWCARD_OP2 = {
+	{"heros",			30,		HeroNiceNet},	-- 召唤获得英雄
+    {"items",			30,		ItemData}, 		-- 自动分解获得道具
+	{"isEnd",			1,		"byte"},		-- 是否发完, 0-没有, 1-发完
+}
+
 CG_DRAWCARD_SKIP_SET = {
 	{"skip",		    1,		"byte"},   -- 是否跳过
 }

+ 0 - 1
script/module/elf/ElfLogic.lua

@@ -257,7 +257,6 @@ end
 local function updateDot(human, targetQuality)
     local cfgHtbl = generateCfgByQuality(targetQuality)
 
-    -- 该品质的所有精灵不能升星和升级了
     if not dotJudgment(human, cfgHtbl) then
         local dotID = 0
         if targetQuality == 1 then

+ 22 - 1
script/module/lostTemple/lostTempleLogic.lua

@@ -46,6 +46,13 @@ DAY_1s = 86400
 --跳过战斗需要的战力
 local SHOWQUICKPOWER = 0 --2000000
 
+local function resetDB(human)
+    local query = { _id = human.db._id }
+    LuaMongo.remove(DB.db_lost_temple, query)
+end
+
+
+
 function initAfterHot()
 
 end
@@ -113,7 +120,7 @@ function onZero()
     -- LuaMongo.remove(DB.db_lost_temple)
 
     -- 修改: 延迟60s再清除数据
-    Timer.addLater(60, LuaMongo.remove, DB.db_lost_temple)
+    -- Timer.addLater(60, LuaMongo.remove, DB.db_lost_temple)
 
     -- 已经关闭
     -- if (openDay - 7 + 1) % 2 ~= 0 then
@@ -127,6 +134,8 @@ function updateDaily(human)
         return
     end
 
+    resetDB(human)
+
     print("[lostTempleLogic - updateDaily] 天数刷新 玩家移除lostTemple数据 name = "..human.db.name)
     human.lostTemple = nil
     
@@ -1340,6 +1349,10 @@ end
 
 -- 查询一键扫荡状态
 function LostTemple_OneClickSweep_Query(human)
+    if not isOpen(human) then
+        return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED)
+    end
+
     local msgRet = Msg.gc.GC_LOGT_TEMPLE_ONECLICK_SWEEP_QUERY
     msgRet.state = 0
 
@@ -1357,6 +1370,9 @@ end
 
 -- 查询一键扫荡奖励
 function LostTemple_OneClickSweep_Award(human)
+    if not isOpen(human) then
+        return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED)
+    end
     local msgRet = Msg.gc.GC_LOGT_TEMPLE_ONECLICK_SWEEP_AWARD
     msgRet.awardArr[0] = 0
 
@@ -1372,6 +1388,9 @@ end
 
 -- 进行一键扫荡
 function LostTemple_OneClickSweep_Do(human)
+    if not isOpen(human) then
+        return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED)
+    end
     local isBuyKing = HeroGrowUp.isBuyKing(human)
     if not isBuyKing or isBuyKing ~= 1 then
         return Broadcast.sendErr(human, Lang.LOST_NO_BUY)
@@ -1411,6 +1430,8 @@ function LostTemple_OneClickSweep_Do(human)
 
     YunYingLogic.onCallBack(human, "lostTempleCombat", 1)
 
+    TriggerLogic.PublishEvent(TriggerDefine.LOSTTEMPLE_PASS_LAYER, human.db._id, 3)
+
     LostTemple_OneClickSweep_Query(human)
 
     RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1208)

+ 136 - 30
script/module/mail/MailManager.lua

@@ -9,6 +9,7 @@ local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
 local RoleSystemDefine = require("roleSystem.RoleSystemDefine") 
 local RoleDBLogic = require("role.RoleDBLogic")
 local MailExcel = require("excel.mail")
+local CommonDB = require("common.CommonDB")
 
 SYSTEM = 1 				-- 系统邮件
 GONGGAO = 2 				-- 公告
@@ -75,7 +76,8 @@ function add(type,receiverUuid,title,content,items,senderName,sender,time,fbTime
         mail.flag = 1
     end
 	LuaMongo.insert(DB.db_mail, mail)
-	RoleSystemLogic.onDotByUuid(receiverUuid, RoleSystemDefine.ROLE_SYS_ID_204)
+	-- 检测红点会调用getMails(), 短时间插入多封邮件加上玩家邮件数量过多,会发生段错误
+	-- RoleSystemLogic.onDotByUuid(receiverUuid, RoleSystemDefine.ROLE_SYS_ID_204)
 	return mail
 
 end
@@ -156,45 +158,149 @@ local function cmpMail(a, b)
 end
 
 local mails = {}
-function getMails(receiverUuid,mailType)
-	for key in ipairs(mails) do 
-		mails[key] = nil
-	end
+-- function getMails(receiverUuid,mailType)
+-- 	for key in ipairs(mails) do 
+-- 		mails[key] = nil
+-- 	end
+
+-- 	FIELD_RECEIVER.receiverUuid = receiverUuid
+-- 	FIELD_RECEIVER.type = mailType
+
+--     LuaMongo.find(DB.db_mail,{["$query"]=FIELD_RECEIVER})
+    
+-- 	local lastTime = os.time() - 7 * 86400
+--     local mailCnt = 0
+-- 	while true do
+-- 		local mail = {}
+-- 		-- if not LuaMongo.next(mail) then
+-- 		-- 	break
+-- 		-- end
 
-	FIELD_RECEIVER.receiverUuid = receiverUuid
-	FIELD_RECEIVER.type = mailType
+-- 		local res, err = pcall(function ()
+-- 			return LuaMongo.next(mail)
+-- 		end)
 
-    LuaMongo.find(DB.db_mail,{["$query"]=FIELD_RECEIVER})
+-- 		if not res then
+-- 			Log.write(Log.LOGID_DEBUG, "MailManager.getMails err = ".. err)
+-- 			break
+-- 		end
+
+-- 		if not err then
+-- 			break
+-- 		end
+
+--        if mail.expireTime then  -- 有指定过期时间
+--             if mail.time > os.time() - mail.expireTime then
+-- 			    mailCnt = mailCnt + 1
+-- 			    mails[mailCnt] = mail
+--             end
+--        elseif mail.time > lastTime then -- 没有就用默认过期时间
+--             mailCnt = mailCnt + 1
+-- 			mails[mailCnt] = mail
+--        end
+-- 	end
     
-	local lastTime = os.time() - 7 * 86400
+--     if mailCnt > MAIL_MAX_CNT then
+-- 		table.sort(mails, cmpMail)
+-- 		for i = MAIL_MAX_CNT + 1, mailCnt do
+-- 			mails[i] = nil
+-- 		end
+-- 	end    
+-- 	return mails
+-- end
+
+-- 替换原有的 getMails 函数
+function getMails(receiverUuid, mailType)
+    -- 1. 清空缓存表
+    for i = 1, #mails do mails[i] = nil end
+
+    local now = os.time()
     local mailCnt = 0
-	while true do
-		local mail = {}
-		if not LuaMongo.next(mail) then
-			break
-		end
+    local tempMails = {}
+    local SCAN_LIMIT = 2000  -- 单次分段查询安全上限
+    local foundEnough = false
+
+    -- 2.将时间划分为多个小窗口,避免单次 find 触发底层 OOM
+    -- 窗口设计:最近7天 -> 7~14天 -> 14~30天 -> 30~60天
+    local timeWindows = {
+        {now - 7*86400,   now},
+        {now - 14*86400,  now - 7*86400},
+        {now - 30*86400,  now - 14*86400},
+        {now - 60*86400,  now - 30*86400}
+    }
+	-- 60天 -> 开服
+	local serverOpenTime = CommonDB.getServerOpenTime()
+	timeWindows[#timeWindows+1] = { serverOpenTime, now - 60*86400 }
+
+    for _, window in ipairs(timeWindows) do
+        if foundEnough then break end
+
+        -- 使用最简平铺查询,彻底避开 C 扩展解析缺陷
+        local query = {
+            receiverUuid = receiverUuid,
+            type = mailType,
+            time = { ["$gte"] = window[1], ["$lte"] = window[2] }
+        }
 
-       if mail.expireTime then  -- 有指定过期时间
-            if mail.time > os.time() - mail.expireTime then
-			    mailCnt = mailCnt + 1
-			    mails[mailCnt] = mail
+        LuaMongo.find(DB.db_mail, query)
+
+        local mail = {}
+        local scanCnt = 0
+        while true do
+            local has_next = LuaMongo.next(mail)
+            if not has_next then break end
+            
+            scanCnt = scanCnt + 1
+            if scanCnt > SCAN_LIMIT then 
+                Log.write(Log.LOGID_DEBUG, string.format("Mail segment limit hit! uuid=%s window=%d~%d", 
+                    receiverUuid, window[1], window[2]))
+                break 
             end
-       elseif mail.time > lastTime then -- 没有就用默认过期时间
+
+            -- 浅拷贝隔离 C 驱动内部 Buffer
+            local m = {}
+            for k, v in pairs(mail) do m[k] = v end
+            tempMails[#tempMails + 1] = m
+
+            -- 清空复用表
+            for k in pairs(mail) do mail[k] = nil end
+        end
+
+        -- 如果已收集足够多数据(留足过滤冗余),提前终止后续窗口查询
+        if #tempMails >= 500 then 
+            foundEnough = true 
+            break 
+        end
+    end
+
+    -- 3.按时间倒序排序,确保后续取到的是“最新”的
+    table.sort(tempMails, cmpMail)
+
+    -- 4. 过滤过期邮件,精准截取最新 100 条
+    for _, m in ipairs(tempMails) do
+        if type(m.time) ~= "number" then m.time = 0 end
+
+        local isExpired = false
+        local expireTime = m.expireTime
+        if expireTime and type(expireTime) == "number" then
+            if m.time <= now - expireTime then isExpired = true end
+        elseif m.time <= now - 7 * 86400 then
+            isExpired = true
+        end
+
+        if not isExpired then
             mailCnt = mailCnt + 1
-			mails[mailCnt] = mail
-       end
-	end
-    
-    if mailCnt > MAIL_MAX_CNT then
-		table.sort(mails, cmpMail)
-		for i = MAIL_MAX_CNT + 1, mailCnt do
-			mails[i] = nil
-		end
-	end    
-	return mails
+            mails[mailCnt] = m
+            if mailCnt >= MAIL_MAX_CNT then break end -- 达到 100 条立即退出
+        end
+    end
+
+    return mails
 end
 
 
+
+
 function saveMail(mail)
     FIELD_ID._id = mail._id
     LuaMongo.update(DB.db_mail, FIELD_ID, mail)

+ 28 - 8
script/module/role/CreateRole.lua

@@ -42,9 +42,20 @@ local NEW_ROLE_MAIL_ID = 7023
 -- 特定渠道列表
 local TARGET_CHANNEL_ARRAY = {1, 9}
 
-local function sendMail(human)
-	local mailCfg = MailExcel.mail[NEW_ROLE_MAIL_ID]
-    MailManager.add(MailManager.SYSTEM, human.db._id, mailCfg.title, mailCfg.content, nil, mailCfg.senderName or "GM")
+-- 用于公会渠道创角时发送奖励邮件的邮件Id
+local CHANNEL_GUILD_MAIL_ID = 7037
+
+-- 公会渠道创角奖励
+local channel_guild_createRole_rewards = {{102,8888}, {124,20}, {1208,2}, {111,1000000}, {112,1000}, {101,2000000}, {510,4}}
+
+
+local function sendMail(human, mailId, items)
+	local mailCfg = MailExcel.mail[mailId]
+	if not mailCfg then
+		return
+	end
+
+    MailManager.add(MailManager.SYSTEM, human.db._id, mailCfg.title, mailCfg.content, items, mailCfg.senderName or "GM")
 end
 
 
@@ -101,6 +112,19 @@ function creatFakeDb(account, serverTag)
     return db
 end
 
+-- 创角时针对渠道的额外处理
+local function channelHandle(human)
+	-- 特定渠道用户创角时发送的邮件
+	if table.find(TARGET_CHANNEL_ARRAY, human.phpChanelID) then
+		sendMail(human, NEW_ROLE_MAIL_ID)
+	end
+
+	-- 公会渠道创角时发送奖励邮件
+	if human.phpChanelID == CommonDefine.CHANNEL_TAG_GUILD1 or human.phpChanelID == CommonDefine.CHANNEL_TAG_GUILD2 then
+		sendMail(human, CHANNEL_GUILD_MAIL_ID, channel_guild_createRole_rewards)
+	end
+end
+
 
 function createNewRole(human)
 	if _G.is_middle == true then
@@ -141,11 +165,7 @@ function createNewRole(human)
 
 	DataCache.Insert_PlayerUuidList(human.db._id, human.db.lv)
 
-	-- 特定渠道用户创角时发送的邮件
-	if table.find(TARGET_CHANNEL_ARRAY, human.phpChanelID) then
-		sendMail(human)
-	end
-
+	channelHandle(human)
 
 	ReportManager.register(human)
 end

+ 22 - 0
script/module/scene/Handler.lua

@@ -37,10 +37,28 @@ local function isBan(uuid, channelId, account, appId)
 	return BanLogic.CheckBan(uuid, channelId, account, appId)
 end
 
+-- 判断是否属于白名单IP
+local function isWhiteIp(ip)
+	if not ip then
+		return false
+	end
+
+	if not Config.WHITEIP_LIST or #Config.WHITEIP_LIST == 0 then
+		return true
+	end
+
+	if table.find(Config.WHITEIP_LIST, ip) then
+		return true
+	end
+
+	return false
+end
+
 
 --在线玩家列表不再从 ObjHuman.onlineAccount 获取, 改为从 ObjHuman.onlineNewUniqueTag 获取
 function CG_TEST_PROTO(fd,msg)
 	-- print("============ CG_TEST_PROTO============", msg.param)
+	Log.write(Log.LOGID_DEBUG, "[CG_TEST_PROTO]=" .. tostring(msg.param))
 	local param = Json.Decode(msg.param)
 	local uTag
 	if param.type == "UseCDKV2" or param.type == "UseCDK" or param.type == "UseFixCDK" then
@@ -220,6 +238,10 @@ function CG_ASK_LOGIN(fd, msg)
 		return sendDisconnect(fd, CommonDefine.DISCONNECT_AUTH_FAIL)
 	end
 
+	if Config.IS_CHECK_IP == true and not isWhiteIp(msg.ip) then
+		return
+	end
+
 
 	--如果在线人数大于最大可容纳在线人数时,断开链接
 	local onlineCnt = ObjHuman.getOnlineCnt()

+ 3 - 0
script/module/serverCommerce/ServerCommerceActBattleGroundCS.lua

@@ -497,6 +497,9 @@ function BG_N2C_Act_End(msg)
 
     local fd_2_PlayerList = {}
     local joinList = battleGroundData.joinList
+    if not joinList then
+        return
+    end
 
     local serverIdxMin = MiddleConnect.MiddleConnect_ConfServerID2TrueServerID(warZoneServerIdMin)
     local serverIdxMax = MiddleConnect.MiddleConnect_ConfServerID2TrueServerID(warZoneServerIdMax)

+ 2 - 2
script/module/serverCommerce/ServerCommerceActDefine.lua

@@ -9,8 +9,8 @@ COMMERCEACT_BEGINTIME = 0               -- 开启时间
 COMMERCEACT_ENDTIME = 23                -- 结束时间
 COMMERCEACT_LASTDAY = 7                 -- 持续时间
 COMMERCEACT_BEGINDELATTIME = 10 * 60    -- 延迟10分钟开始
-COMMERCEACT_INITSERVERTIME =4 * 60     -- 普通服 起服3分钟请求活动是否开始
-COMMERCEACT_INITOPENDAY = 3 * 60        -- 中心服2分钟后请求普通服开服时间
+COMMERCEACT_INITSERVERTIME = 10 * 60 --4 * 60     -- 普通服 起服3分钟请求活动是否开始
+COMMERCEACT_INITOPENDAY = 9 * 60 -- 3 * 60        -- 中心服2分钟后请求普通服开服时间
 COMMERCEACT_RANKUPDATE = 150            -- 普通服 5 分钟请求排行榜数据
 COMMERCEACT_ENDBATCH = 3                -- 结束批次
 

+ 2 - 67
script/module/topup/GiftLogic.lua

@@ -160,7 +160,7 @@ local handler = {
     [PRINCIPAL_LINE_EVNET] = function(human,param)
         for id,cfg in pairs(GiftExcel) do 
             -- 触发新礼包
-            if cfg.trigger == PRINCIPAL_LINE_EVNET and cfg.param[1] == param.id then 
+            if cfg.trigger == PRINCIPAL_LINE_EVNET and cfg.param[1] <= param.id then 
                 genGift(human,id)
             end
         end
@@ -168,7 +168,7 @@ local handler = {
     [EVAL_TOWER_EVENT] = function(human,param)
         for id,cfg in pairs(GiftExcel) do 
             -- 触发新礼包
-            if cfg.trigger == EVAL_TOWER_EVENT and cfg.param[1] == param.id then 
+            if cfg.trigger == EVAL_TOWER_EVENT and cfg.param[1] <= param.id then 
                 genGift(human,id)
             end
         end
@@ -191,71 +191,6 @@ local handler = {
             end
         end
     end,
-
-    -- [GIFT_UPGRADE_LV_EVENT] = function (human,param)
-    --     for id,cfg in pairs(GiftExcel) do
-    --         -- 触发新礼包
-    --         if cfg.trigger == GIFT_UPGRADE_LV_EVENT and cfg.param[1] == param.newLv then
-    --             genGift(human,id)
-    --         end
-    --     end
-    -- end,
-
-    -- [GIFT_TALISMAN_UPGRADE_STAR] = function (human,param)
-    --     for id,cfg in pairs(GiftExcel) do
-    --         -- 触发新礼包
-    --         if cfg.trigger == GIFT_TALISMAN_UPGRADE_STAR and cfg.param[1] == param.newLv then
-    --             genGift(human,id)
-    --         end
-    --     end
-    -- end,
-
-    -- [GIFT_WINNERRELIC_UPGRADE_STAR] = function (human,param)
-    --     for id,cfg in pairs(GiftExcel) do
-    --         -- 触发新礼包
-    --         if cfg.trigger == GIFT_WINNERRELIC_UPGRADE_STAR and cfg.param[1] == param.newLv then
-    --             genGift(human,id)
-    --         end
-    --     end
-    -- end,
-
-    -- [GIFT_ELF_UPGRADE_STAR] = function (human,param)
-    --     for id,cfg in pairs(GiftExcel) do
-    --         -- 触发新礼包
-    --         if cfg.trigger == GIFT_ELF_UPGRADE_STAR and cfg.param[1] == param.newLv then
-    --             genGift(human,id)
-    --         end
-    --     end
-    -- end,
-
-
-    -- [GIFT_TALISMAN_OPEN] = function (human)
-    --     for id,cfg in pairs(GiftExcel) do
-    --         -- 触发新礼包
-    --         if cfg.trigger == GIFT_TALISMAN_OPEN then
-    --             genGift(human,id)
-    --         end
-    --     end
-    -- end,
-
-    -- [GIFT_WINNERRELIC_OPEN] = function (human)
-    --     for id,cfg in pairs(GiftExcel) do
-    --         -- 触发新礼包
-    --         if cfg.trigger == GIFT_WINNERRELIC_OPEN then
-    --             genGift(human,id)
-    --         end
-    --     end
-    -- end,
-
-    -- [GIFT_ELF_OPEN] = function (human)
-    --     for id,cfg in pairs(GiftExcel) do
-    --         -- 触发新礼包
-    --         if cfg.trigger == GIFT_ELF_OPEN then
-    --             genGift(human,id)
-    --         end
-    --     end
-    -- end,
-
 }
 
 local handler2 = {

+ 3 - 0
script/module/vip/VipLogic.lua

@@ -45,6 +45,9 @@ VIP_POWER19 = 19	-- o
 -- VIP_POWER20 = 21	-- o激活专属背景
 VIP_POWER21 = 21	-- o抽卡 卷轴折扣特权
 VIP_POWER22 = 22    -- o抽卡 钻石特权
+
+VIP_POWER23 = 23	-- 100抽卡 卷轴折扣特权
+VIP_POWER24 = 24    -- 100抽卡 钻石特权
 -- 礼包状态
 local LIBAO_STATE_CANT = 0 		-- 不可购买
 local LIBAO_STATE_CAN = 1 		-- 可购买

+ 3 - 0
webServer/src/channels/factory/ChannelFactory.ts

@@ -59,6 +59,9 @@ class ChannelFactory {
     this.registerHandler(18, new HongKongTaiwanChannelHandler()); // 港台渠道
     this.registerHandler(20, new ZeroOneChannelHandler()); // 0.1渠道
     this.registerHandler(21, new QingtianChannelHandler()); // 晴天SDK
+    this.registerHandler(22, new ZeroOneChannelHandler()); // 1折渠道
+    this.registerHandler(23, new ZeroOneChannelHandler()); // 逍遥浪人
+    this.registerHandler(24, new ZeroOneChannelHandler()); // 逍遥浪人50倍返利
   }
 
   /**

+ 18 - 16
webServer/src/channels/handlers/ZeroOneChannelHandler.ts

@@ -25,14 +25,15 @@ export class ZeroOneChannelHandler implements ChannelHandler {
         const data = ctx.request.body as any;
         const {token, uid, channel_code, product_code} = data || {};
         const finalProductCode = product_code || config.loginConfig?.productCode;
+        const tag = `[渠道${config.channelId}]`;
 
         if (!token || !uid) {
-            logger.warn("0.1渠道登录验证失败: 缺少必要参数", {token, uid});
+            logger.warn(`${tag}登录验证失败: 缺少必要参数`, {token, uid});
             return {code: 0, msg: "缺少必要参数 token 或 uid"};
         }
 
         if (!finalProductCode) {
-            logger.error("0.1渠道登录验证失败: 未配置productCode");
+            logger.error(`${tag}登录验证失败: 未配置productCode`);
             return {code: 0, msg: "服务器未配置productCode"};
         }
 
@@ -46,20 +47,20 @@ export class ZeroOneChannelHandler implements ChannelHandler {
             params.channel_code = channel_code;
         }
 
-        logger.info("0.1渠道登录验证请求", {url: requestUrl, params});
+        logger.info(`${tag}登录验证请求`, {url: requestUrl, params});
 
         try {
             const response = await axios.get(requestUrl, {params, timeout: 8000});
-            logger.info("0.1渠道登录验证响应", {data: response.data});
+            logger.info(`${tag}登录验证响应`, {data: response.data});
 
             if (response.data == "1") {
                 return {code: 1, msg: "success"};
             }
 
-            logger.warn("0.1渠道登录验证失败: 接口返回非1", {data: response.data});
+            logger.warn(`${tag}登录验证失败: 接口返回非1`, {data: response.data});
             return {code: 0, msg: "登录验证失败"};
         } catch (error) {
-            logger.error("0.1渠道登录验证异常", error);
+            logger.error(`${tag}登录验证异常`, error);
             return {code: 0, msg: "登录验证异常"};
         }
     }
@@ -71,11 +72,12 @@ export class ZeroOneChannelHandler implements ChannelHandler {
      */
     async handlePayment(ctx: Context, config: ChannelConfig): Promise<PaymentResult> {
         const data = ctx.request.body as any;
-        logger.info("0.1渠道支付回调参数", {url: ctx.href, params: data});
+        const tag = `[渠道${config.channelId}]`;
+        logger.info(`${tag}支付回调参数`, {url: ctx.href, params: data});
 
         const {nt_data, sign, md5Sign} = data || {};
         if (!nt_data || !sign || !md5Sign) {
-            logger.warn("0.1渠道支付回调失败: 缺少必要参数", {nt_data, sign, md5Sign});
+            logger.warn(`${tag}支付回调失败: 缺少必要参数`, {nt_data, sign, md5Sign});
             return {code: 0, msg: "缺少必要参数"};
         }
 
@@ -83,12 +85,12 @@ export class ZeroOneChannelHandler implements ChannelHandler {
         const callbackKey = config.paymentConfig?.callbackKey;
 
         if (!md5Key || !callbackKey) {
-            logger.error("0.1渠道支付回调失败: 未配置QuickSDK密钥");
+            logger.error(`${tag}支付回调失败: 未配置QuickSDK密钥`);
             return {code: 0, msg: "服务器未配置渠道密钥"};
         }
 
         if (!SignatureVerifier.verifyQuickSign(data, md5Key)) {
-            logger.warn("0.1渠道支付回调失败: 签名验证失败");
+            logger.warn(`${tag}支付回调失败: 签名验证失败`);
             return {code: 0, msg: "签名验证失败"};
         }
 
@@ -103,12 +105,12 @@ export class ZeroOneChannelHandler implements ChannelHandler {
             const amountStr = message.amount?.[0];
 
             if (!orderId || !outTradeNo || typeof status === "undefined" || !amountStr) {
-                logger.error("0.1渠道支付回调失败: XML缺少必要字段", {message});
+                logger.error(`${tag}支付回调失败: XML缺少必要字段`, {message});
                 return {code: 0, msg: "回调数据不完整"};
             }
 
             if (status !== "0") {
-                logger.warn("0.1渠道支付状态非成功", {status});
+                logger.warn(`${tag}支付状态非成功`, {status});
                 return {code: 0, msg: "支付状态失败"};
             }
 
@@ -124,7 +126,7 @@ export class ZeroOneChannelHandler implements ChannelHandler {
 
             const orderInfo = validation.orderInfo;
             if (Number(orderInfo.amount) !== amount) {
-                logger.warn("0.1渠道支付金额不匹配", {
+                logger.warn(`${tag}支付金额不匹配`, {
                     orderId,
                     requestAmount: amount,
                     orderAmount: orderInfo.amount
@@ -132,17 +134,17 @@ export class ZeroOneChannelHandler implements ChannelHandler {
                 return {code: 0, msg: "订单金额不一致"};
             }
 
-            logger.info(`0.1渠道支付订单${orderId}开始发货`);
+            logger.info(`${tag}支付订单${orderId}开始发货`);
             const result = await PaymentHelper.deliverOrder(
                 orderInfo,
                 ctx.request.ip,
                 validation.url,
                 outTradeNo
             );
-            logger.info(`0.1渠道支付订单${orderId}发货完成`, {result});
+            logger.info(`${tag}支付订单${orderId}发货完成`, {result});
             return result;
         } catch (error) {
-            logger.error("0.1渠道支付回调解析异常", error);
+            logger.error(`${tag}支付回调解析异常`, error);
             return {code: 0, msg: "回调解析异常"};
         }
     }

+ 42 - 1
webServer/src/config/channelConfig.ts

@@ -49,7 +49,9 @@ import {
     HKT_IOS_CALLBACK_KEY,
     HKT_DOMAIN, TAOBAO_CALLBACK_SECRET, TAOBAO_APP_ID, TAOBAO_APP_SECRET,
     ZERO_ONE_QUICK_MD5_KEY, ZERO_ONE_QUICK_CALLBACK_KEY, ZERO_ONE_QUICK_PRODUCT_CODE,
-    QINGTIAN_MD5_KEY, QINGTIAN_CALLBACK_KEY, QINGTIAN_PRODUCT_CODE
+    QINGTIAN_MD5_KEY, QINGTIAN_CALLBACK_KEY, QINGTIAN_PRODUCT_CODE,
+    XIAOYAO_QUICK_MD5_KEY, XIAOYAO_QUICK_CALLBACK_KEY, XIAOYAO_QUICK_PRODUCT_CODE,
+    XIAOYAO50_QUICK_MD5_KEY, XIAOYAO50_QUICK_CALLBACK_KEY, XIAOYAO50_QUICK_PRODUCT_CODE
 } from "./thirdParams";
 
 // 渠道配置接口定义
@@ -362,4 +364,43 @@ export const channelConfigs: Record<number, ChannelConfig> = {
             productCode: QINGTIAN_PRODUCT_CODE,
         },
     },
+    22: {
+        // 0.1渠道 QuickSDK
+        channelId: 22,
+        name: "1zhe",
+        platform: "",
+        paymentConfig: {
+            signKey: ZERO_ONE_QUICK_MD5_KEY,
+            callbackKey: ZERO_ONE_QUICK_CALLBACK_KEY,
+        },
+        loginConfig: {
+            productCode: ZERO_ONE_QUICK_PRODUCT_CODE,
+        },
+    },
+    23: {
+        // 逍遥浪人 QuickSDK
+        channelId: 23,
+        name: "逍遥浪人",
+        platform: "",
+        paymentConfig: {
+            signKey: XIAOYAO_QUICK_MD5_KEY,
+            callbackKey: XIAOYAO_QUICK_CALLBACK_KEY,
+        },
+        loginConfig: {
+            productCode: XIAOYAO_QUICK_PRODUCT_CODE,
+        },
+    },
+    24: {
+        // 逍遥浪人50倍返利 QuickSDK
+        channelId: 24,
+        name: "逍遥浪人50倍",
+        platform: "",
+        paymentConfig: {
+            signKey: XIAOYAO50_QUICK_MD5_KEY,
+            callbackKey: XIAOYAO50_QUICK_CALLBACK_KEY,
+        },
+        loginConfig: {
+            productCode: XIAOYAO50_QUICK_PRODUCT_CODE,
+        },
+    },
 };

+ 12 - 0
webServer/src/config/thirdParams.ts

@@ -154,6 +154,18 @@ export const QINGTIAN_CALLBACK_KEY = "63878163435949505046358619235401";
 export const QINGTIAN_MD5_KEY = "ntyf5ezxywtqt4r16uhqrx5zwix2mzez";
 export const QINGTIAN_GAME_ID = "1007";
 
+// 逍遥浪人渠道(渠道23)
+export const XIAOYAO_QUICK_MD5_KEY = "yiggjf92qibwczxddjoxqjhnl638jaeh";
+export const XIAOYAO_QUICK_CALLBACK_KEY = "77756454315558905031309394863250";
+export const XIAOYAO_QUICK_PRODUCT_CODE = "17185838183889697860233357135277";
+export const XIAOYAO_QUICK_PRODUCT_KEY = "98557938";
+
+// 逍遥浪人50倍返利渠道(渠道24)
+export const XIAOYAO50_QUICK_MD5_KEY = "lotikkteclyc6ns7yqcwxdwh4kauwtji";
+export const XIAOYAO50_QUICK_CALLBACK_KEY = "87669945324907280135575078884672";
+export const XIAOYAO50_QUICK_PRODUCT_CODE = "50723129629881286488573382954330";
+export const XIAOYAO50_QUICK_PRODUCT_KEY = "40281578";
+
 // 港台渠道(Quick海外SDK)
 // 安卓配置
 export const HKT_ANDROID_PRODUCT_CODE = "34455834768674171358576585112815";

+ 73 - 2
webServer/src/controller/ApiController.ts

@@ -18,7 +18,7 @@ import {
 import {PaymentHelper} from "../utils/PaymentHelper";
 import {SignatureVerifier} from "../utils/SignatureVerifier";
 import {ChannelConfigManager} from "../utils/ChannelConfigManager";
-import {getRoleInfoByUidAndServerId} from "../mongo/mongodb";
+import {getRoleInfoByUidAndServerId, getRoleListByUserId} from "../mongo/mongodb";
 import {min} from "moment-timezone";
 
 // platform内存缓存,key: ip:device_no,TTL 5分钟
@@ -612,9 +612,21 @@ class ApiController {
                 }
                 break;
             case 14:
+            case 20:
+                ctx.body = result.code === 1 ? "SUCCESS" : "Fail";
+                break;
             case 21:
                 ctx.body = result.code === 1 ? "SUCCESS" : "Fail";
                 break;
+            case 22:
+                ctx.body = result.code === 1 ? "SUCCESS" : "Fail";
+                break;
+            case 23:
+                ctx.body = result.code === 1 ? "SUCCESS" : "Fail";
+                break;
+            case 24:
+                ctx.body = result.code === 1 ? "SUCCESS" : "Fail";
+                break;
             default:
                 ctx.body = result;
         }
@@ -852,7 +864,7 @@ class ApiController {
                 }
                 let minSid = 1
                 if (tag == 11) {
-                    minSid = Math.floor(((servers[0].sid || 1) - 1) / 10) * 10 + 1
+                    minSid = servers.length //新号没有角色,minsid = 最新的服
                 }
 
                 data.push({
@@ -1191,6 +1203,11 @@ class ApiController {
                 "VIP777",
                 "VIP888",
                 "QINGMINGLB",
+                "yxlb666",
+                "yxlb777",
+                "yxlb888",
+                "yxlb999",
+                "WUYILB"
             ];
             let param: string = "";
 
@@ -1617,7 +1634,61 @@ class ApiController {
         }
     }
 
+    /**
+     * 通过 userId 查询该账号在各区服的角色列表
+     * 请求参数(GET/POST 均可):uid、channel_id
+     * 返回:[{ roleId, roleName, zhandouli, serverName, serverId, createTime }]
+     */
+    async getUserRoleList(ctx) {
+        const uid = ctx.query.uid || ctx.request.body?.uid;
+        const tag = ctx.query.channel_id || ctx.request.body?.channel_id || 1;
+
+        logger.info('getUserRoleList 请求参数:', {uid, tag});
+
+        if (!uid) {
+            ctx.body = ApiController.fail('uid 不能为空', -1);
+            return;
+        }
+
+        // 1. 查询该用户进入过的所有区服(join game_server 取 db_name 和区服名)
+        const enterServerList: any[] = await Server.getEnterServerListByUid(uid, tag);
+
+        logger.info('getUserRoleList enterServerList:', {
+            count: enterServerList?.length,
+            first: enterServerList?.[0] ? {
+                server_id: enterServerList[0].server_id,
+                db_name: enterServerList[0].db_name,
+                name: enterServerList[0].name,
+            } : null,
+        });
+
+        if (!enterServerList || enterServerList.length === 0) {
+            ctx.body = ApiController.success('请求成功', 1, false, []);
+            return;
+        }
 
+        // 去重(同一 server_id 可能有多条进区记录,取最新一条即可)
+        const seen = new Set<string>();
+        const uniqueServers = enterServerList.filter((s) => {
+            if (seen.has(String(s.server_id))) return false;
+            seen.add(String(s.server_id));
+            return true;
+        });
+
+        // 2. 并发查询每个区服的 MongoDB 角色信息
+        const roleList = await getRoleListByUserId(
+            uniqueServers.map((s) => ({
+                server_id: s.server_id,
+                db_name: s.db_name,
+                name: s.name,
+            })),
+            tag,
+            uid
+        );
+
+        logger.info('getUserRoleList 返回角色列表:', {uid, count: roleList.length});
+        ctx.body = ApiController.success('请求成功', 1, false, roleList);
+    }
 }
 
 module.exports = new ApiController();

+ 67 - 1
webServer/src/mongo/mongodb.ts

@@ -169,4 +169,70 @@ async function insertMailToPlayer(
     }
 }
 
-export { getDb, getCollection, closeConnection, getRoleInfoById, connectToMongo, getGuildInfoById, getRoleInfoByUidAndServerId, insertMailToPlayer };
+/**
+ * 批量查询某用户在多个区服的角色信息
+ * @param serverList  已加入区服列表,每项包含 { server_id, db_name, name (区服名) }
+ * @param tag         渠道标识(用于拼 newUniqueTag)
+ * @param uid         用户账号
+ */
+async function getRoleListByUserId(
+    serverList: Array<{ server_id: string; db_name: string; name: string }>,
+    tag: number | string,
+    uid: string
+): Promise<Array<{
+    roleId: string;
+    roleName: string;
+    roleLevel: number;
+    zhandouli: number;
+    serverName: string;
+    serverId: string;
+    createTime: number;
+}>> {
+    const results: Array<{
+        roleId: string;
+        roleName: string;
+        roleLevel: number;
+        zhandouli: number;
+        serverName: string;
+        serverId: string;
+        createTime: number;
+    }> = [];
+
+    if (!client) {
+        await connectToMongo();
+    }
+
+    for (const server of serverList) {
+        console.log(`[getRoleListByUserId] server:`, JSON.stringify(server));
+        if (!server.db_name) {
+            console.log(`[getRoleListByUserId] 跳过 server_id=${server.server_id},db_name 为空`);
+            continue;
+        }
+        try {
+            const database = client!.db(server.db_name);
+            const collection = database.collection('char');
+            const newUniqueTag = `${tag}|${server.server_id}|${uid}`;
+            console.log(`[getRoleListByUserId] 查询 db=${server.db_name} newUniqueTag=${newUniqueTag}`);
+            // MongoDB v2.x 使用 fields 而非 projection
+            const doc = await collection.findOne({ newUniqueTag });
+            console.log(`[getRoleListByUserId] 查询结果:`, doc ? `找到 name=${doc.name}` : 'null');
+            if (doc) {
+                results.push({
+                    roleId: doc._id.toString(),
+                    roleName: doc.name || '',
+                    roleLevel: doc.lv || 0,
+                    zhandouli: doc.zhandouli || 0,
+                    serverName: server.name || '',
+                    serverId: server.server_id,
+                    createTime: doc.createTime || 0,
+                });
+            }
+        } catch (error) {
+            console.error(`[getRoleListByUserId] 查询区服 ${server.server_id} 异常:`, error);
+        }
+    }
+
+    return results;
+}
+
+export { getDb, getCollection, closeConnection, getRoleInfoById, connectToMongo, getGuildInfoById, getRoleInfoByUidAndServerId, insertMailToPlayer, getRoleListByUserId };

+ 3 - 0
webServer/src/router/index.ts

@@ -92,4 +92,7 @@ router.post("/qqReport", TencentController.qqReport);
 // mianyou开服同步
 router.post("/mianyou/syncServer", ApiController.mianyouSyncServer);
 
+// 通过 userId 查询角色列表(战力、角色名、角色id、区服、创建时间)
+router.get("/getUserRoleList", ApiController.getUserRoleList);
+
 module.exports = router;

+ 1 - 1
webServer/src/utils/msg.ts

@@ -256,7 +256,7 @@ export default class Msg {
   }
 
   CG_TEST_PROTO(account: string, param: string, server_id = 1) {
-    console.log("发送CDK道具消息", this.websocket.readyState, this.isConnect);
+    console.log("发送CDK道具消息", this.websocket.readyState, this.isConnect,param,server_id,account);
     if (this.isConnect != true || this.websocket.readyState != 1) return false;
     this.sendBufLen = 4;
     this.writeString(account);