From 2fca4ba3abab2ea232d64ef084be1991506d57a2 Mon Sep 17 00:00:00 2001 From: hxp <ale99527@vip.qq.com> Date: 星期四, 27 六月 2024 16:32:51 +0800 Subject: [PATCH] 10178 【越南】【香港】【主干】挂机奖励(屏蔽跨服上线通知:古宝、神通、战令、福地、挂机) --- ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py | 257 +++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 216 insertions(+), 41 deletions(-) diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py index ae54f4e..03aa70c 100644 --- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py +++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py @@ -15,7 +15,6 @@ # @change: "2013-03-20 18:00" Alee 添加DEBUG输出函数DebugLog # @change: "2013-09-10 20:10" Alee 函数DebugLog改用GetDebugLevel才有效 # @change: "2014-05-16 10:30" xmnathan 增加交易所管理器接口 -# @change: "2014-08-01 15:30" xmnathan 增加天梯竞技场管理器接口 # @change: "2014-09-22 10:00" xmnathan 增加GM工具补偿管理器接口 # @change: "2015-01-14 00:30" hxp 增加服务器平台区服ID获取 # @change: "2015-01-14 20:30" hxp 增加CanHappen函数 @@ -116,6 +115,14 @@ result = int(input) return result + except ValueError: + return defValue + +def ToFloat(input, defValue = 0): + try: + result = float(input) + return result + except ValueError: return defValue @@ -450,8 +457,8 @@ ##获取玩家所属区服ID # @param curPlayer # @return -def GetPlayerServerID(curPlayer): - accID = curPlayer.GetAccID() +def GetPlayerServerID(curPlayer): return GetAccIDServerID(curPlayer.GetAccID()) +def GetAccIDServerID(accID): infoList = accID.split(Def_AccID_Split_Sign) return 0 if len(infoList) < 3 else int(infoList[-1][1:]) @@ -539,31 +546,90 @@ #--------------------------------------------------------------------- -def GetOperationActionDateStr(dateInfo, openServerDay): - '''获取运营活动对应日期,存数字代表开服天配置,需要转化为对应的日期 - @param dateInfo: 运营活动表配置的日期信息, 如果是纯数字代表开服天 - @param openServerDay: 当前开服天 - ''' - if not dateInfo: - curDateTime = datetime.datetime.today() - return "%d-%d-%d" % (curDateTime.year, curDateTime.month, curDateTime.day) - if dateInfo.startswith("W"): - curDateTime = datetime.datetime.today() - curWeekday = curDateTime.weekday() + 1 - actionWeekday = int(dateInfo[1:]) - actionDateTime = curDateTime + datetime.timedelta(days=(actionWeekday-curWeekday)) - return "%d-%d-%d" % (actionDateTime.year, actionDateTime.month, actionDateTime.day) - if dateInfo.startswith("Mix"): - diffDay = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_MixServerDay) + 1 - actionServerDay = int(dateInfo[3:]) - elif not dateInfo.isdigit(): - return dateInfo - else: - diffDay = openServerDay - actionServerDay = int(dateInfo) +def GetTemplateID(ipyData, cfgID, dayIndex): + if cfgID == None or dayIndex == None or not ipyData: + return 0 + templateIDList = ipyData.GetTemplateIDList() + if not templateIDList: + return 0 + templateID = templateIDList[-1] if dayIndex >= len(templateIDList) else templateIDList[dayIndex] + return templateID + +def GetTemplateIDByList(templateIDList, dayIndex): + if dayIndex == None: + return 0 + if not templateIDList: + return 0 + templateID = templateIDList[-1] if dayIndex >= len(templateIDList) else templateIDList[dayIndex] + return templateID + +def GetOperationActionDateStr(ipyData): + ## 获取运营活动对应日期,存数字代表开服天配置,需要转化为对应的日期 curDateTime = datetime.datetime.today() - actionDateTime = curDateTime + datetime.timedelta(days=(actionServerDay-diffDay)) - return "%d-%d-%d" % (actionDateTime.year, actionDateTime.month, actionDateTime.day) + startDateStr = ipyData.GetStartDate() + endDateStr = ipyData.GetEndDate() + if not startDateStr: + startDateStr = "%d-%d-%d" % (curDateTime.year, curDateTime.month, curDateTime.day) + if not endDateStr: + endDateStr = "%d-%d-%d" % (curDateTime.year, curDateTime.month, curDateTime.day) + + # 日期直接返回 + if startDateStr.count("-") == 2 and "W" not in startDateStr: + return startDateStr, endDateStr + + # 开服天 + if startDateStr.isdigit(): + diffDay = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ServerDay) + 1 + startDateTime = curDateTime + datetime.timedelta(days=(int(startDateStr)-diffDay)) + endDateTime = curDateTime + datetime.timedelta(days=(int(endDateStr)-diffDay)) + + # 合服天 + elif startDateStr.startswith("Mix"): + diffDay = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_MixServerDay) + 1 + startDateTime = curDateTime + datetime.timedelta(days=(int(startDateStr[3:])-diffDay)) + endDateTime = curDateTime + datetime.timedelta(days=(int(endDateStr[3:])-diffDay)) + + # 周循环, 直接配置 Wx 或 Wx|有效开始日期 或 Wx|有效结束日期 + elif startDateStr.startswith("W"): + curWeekday = curDateTime.weekday() + 1 + + startWeekDateInfo = startDateStr.split("|") + startWeekInfo = startWeekDateInfo[0] + startWeekday = int(startWeekInfo[1:]) + startDateTime = curDateTime + datetime.timedelta(days=(startWeekday-curWeekday)) + + # 限制开启循环日期 + if len(startWeekDateInfo) > 1: + startLoopDateStr = startWeekDateInfo[1] + startLoopDateTime = ChangeStrToDatetime(startLoopDateStr, ChConfig.TYPE_Time_YmdFormat) + if startLoopDateTime > startDateTime: + startDateTime = startLoopDateTime + + startWeekDay = startDateTime.weekday() + 1 # 实际开启活动是周几,不一定和配置的周几一样,可能从中间被截断开始 + + # 处理周循环的结束日期 + endWeekDateInfo = endDateStr.split("|") + endWeekInfo = endWeekDateInfo[0] + endWeekday = int(endWeekInfo[1:]) + endDateTime = startDateTime + datetime.timedelta(days=(endWeekday-startWeekDay)) + if len(endWeekDateInfo) > 1: + endLoopDateStr = endWeekDateInfo[1] + endLoopDateTime = ChangeStrToDatetime(endLoopDateStr, ChConfig.TYPE_Time_YmdFormat) + if endDateTime > endLoopDateTime: + endDateTime = endLoopDateTime + + # 只配置结束日期的时候可能导致开始日期计算出来比结束日期还大,即当前时间超过结束日期,且 配置还存在的情况 + if startDateTime > endDateTime: + startDateTime = endDateTime # 反正都无法开启,随便给个日期,不超过结束日期即可 + + # 默认 + else: + startDateTime = curDateTime + endDateTime = curDateTime + + startDateStr = "%d-%d-%d" % (startDateTime.year, startDateTime.month, startDateTime.day) + endDateStr = "%d-%d-%d" % (endDateTime.year, endDateTime.month, endDateTime.day) + return startDateStr, endDateStr ##获得系统时间 # @param 无意义 @@ -571,6 +637,11 @@ # @remarks 获得系统时间 def GetServerTime(): return datetime.datetime.today() + +def GetWeekOfYear(): + ## 一年中的第几周, 1代表第1周 + return datetime.datetime.isocalendar(datetime.datetime.today())[1] + #--------------------------------------------------------------------- ##获取2个时间之间差异的TimeDelta类实例 # @param compareTimeStr 比较的时间字符, 如"2010-05-26 11:21:25" @@ -840,6 +911,8 @@ timeStr = datetime.datetime.strptime(timeStr, timeFormat).timetuple() return int(time.mktime(timeStr)) +def ChangeStrToDatetime(timeStr, timeFormat=ChConfig.TYPE_Time_Format): + return datetime.datetime.strptime(timeStr, timeFormat) ##获取与当前时间相差天数的datetime格式数据 # @param diffDays 差距天数 @@ -869,6 +942,17 @@ if IsCrossServer(): return ReadChConfig.GetPyMongoConfig("Merge", "CrossZoneName") return PyGameData.g_crossZoneName + +def GetCrossServerTimeStr(): + ## 跨服服务器时间 + if IsCrossServer(): + return GetCurrentDataTimeStr() + lastCrossServerTime, lastServerTime, _ = PyGameData.g_crossServerTimeInfo + if not lastCrossServerTime: + return GetCurrentDataTimeStr() + curTime = int(time.time()) + crossServerTime = lastCrossServerTime + (curTime - lastServerTime) + return ChangeTimeNumToStr(crossServerTime) ## 获取玩家的区服名,仅在跨服有效 # @param curPlayer 玩家实例 @@ -916,8 +1000,9 @@ # @param itemList 待选列表 # @return object def GetResultByRandomList(randList, defValue=None, maxRateValue=ChConfig.Def_MaxRateValue): - rate = random.randint(0, maxRateValue) - + if not randList: + return defValue + rate = random.randint(0, randList[-1][0]) return GetResultByRiseList(randList, rate, defValue) ## 增长列表(类似饼图)从中获得指定的信息 @@ -936,16 +1021,59 @@ ## 从列表中产生物品,[[权重, object], ....] # @param weightList 待选列表 -def GetResultByWeightList(weightList): +def GetResultByWeightList(weightList, defValue=None): randList = [] weight = 0 for info in weightList: weight += info[0] randList.append([weight, info[1] if len(info) == 2 else info[1:]]) if not randList: - return + return defValue rate = random.randint(1, randList[-1][0]) - return GetResultByRiseList(randList, rate) + return GetResultByRiseList(randList, rate, defValue) + +## 获得对应数位的值 +# @param numValue 数值 +# @param dataIndex 数位索引 +# @return 获得的值 +def GetDataByDigitPlace(numValue, dataIndex): + return (numValue/pow(10, dataIndex))%10 + + +## 设置对应数位的值 +# @param numValue 数值 +# @param dataIndex 数位索引 +# @param dataValue 当前修改数值 +# @return 获得的值 +def ChangeDataByDigitPlace(numValue, dataIndex, dataValue): + + if dataValue < 0 or dataValue > 9 or dataIndex > ShareDefine.Def_PDictDigitCnt: + return numValue + + # 获得对应数位的值 + lastTagLV = GetDataByDigitPlace(numValue, dataIndex) + + numValue += pow(10, dataIndex)*(dataValue - lastTagLV) + return numValue + +def GetBitValue(dataValue, index): + """ 得到某个字节值中某一位(Bit)的值 + @param dataValue: 待取值的字节值 + @param index: 待读取位的序号,从右向左0开始,0-7为一个完整字节的8个位 + @return: 返回读取该位的值,0或1 + """ + return 1 if dataValue & (1 << index) else 0 + +def SetBitValue(dataValue, index, val): + """ 更改某个字节值中某一位(Bit)的值 + @param dataValue: 准备更改的字节原值 + @param index: 待更改位的序号,从右向左0开始,0-7为一个完整字节的8个位 + @param val: 目标位预更改的值,0或1 + @return: 返回更改后字节的值 + """ + if val: + return dataValue | (1 << index) + return dataValue & ~(1 << index) ## 根据字典key获取value值 # @return @@ -983,6 +1111,24 @@ adict.update(bdict) return adict +## 根据排行获取名次对应值 +# @param orderDict {名次:obj, ...} 名次支持段跳跃 +# @param order 名次,从1开始 +# @param isDefaultLast 找不到的名次是否默认取最后一名的 +# @return obj or None +def GetOrderValueByDict(orderDict, order, isDefaultLast=True, defaultValue=None): + if order in orderDict: + return orderDict[order] + + orderList = sorted(orderDict.keys()) + if order > 0: + for dOrder in orderList: + if order <= dOrder: + return orderDict[dOrder] + + # 找不到的默认取最后一名 + return orderDict[orderList[-1]] if isDefaultLast else defaultValue + ##概率相关, 这个事件是否能够出现 # @param rate 基础几率 # @param maxRate 最大几率 @@ -994,15 +1140,34 @@ return 0 -def DebugAnswer(curPlayer, text): +def DebugAnswer(curPlayer, text, isLog=True): '''转码后再发DebugAnswer''' #=========================================================================== # if not GetGameWorld().GetDebugLevel(): # return #=========================================================================== - DebugLog(text) + if isLog: + DebugLog(text) text = text.decode(ShareDefine.Def_Game_Character_Encoding).encode(GetCharacterEncoding()) curPlayer.DebugAnswer(text) + return + +def CrossServerMsg_DebugAnswer(msgData): + playerID, text = msgData + curPlayer = GetPlayerManager().FindPlayerByID(playerID) + if not curPlayer: + return + curPlayer.DebugAnswer(text) + return + +def DebugAnswerCross(playerID, serverGroupID, text): + DebugLog(text) + text = text.decode(ShareDefine.Def_Game_Character_Encoding).encode(GetCharacterEncoding()) + + import CrossRealmMsg + dataMsg = [playerID, text] + serverGroupIDList = [serverGroupID] + CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_DebugAnswer, dataMsg, serverGroupIDList) return def GetMap(mapID): return IpyGameDataPY.GetIpyGameData("ChinMap", mapID) @@ -1049,15 +1214,25 @@ return inputText +def RaiseException(errorMsg, playerID=0): + ## 处理抛出异常信息,debug下直接抛出异常报错信息,否则发送运维邮件提醒 + ErrLog(errorMsg, playerID) + if GetGameWorld().GetDebugLevel(): + raise Exception(errorMsg) + else: + SendGameError("GameServerRaiseException", errorMsg) + return -# 向运维发送邮件,用于需要紧急处理的信息 -# 此处不包含服务器报错的汇报 -def SendGameStateMail(msgInfo): - # 使用方式 向OpenStateUrl 发送Type为GameWarning,那么就会收到一封游戏内容警告邮件,信息为MsgInfo +def SendGameError(errType, msgInfo=""): + ''' 向运维发送邮件,用于需要紧急处理的信息 + @param errType: 错误类型,自定义即可 + @param msgInfo: 错误信息,可选 + ''' getUrl = ReadChConfig.GetPyMongoConfig("EventReport", "OpenStateUrl") groupID = ReadChConfig.GetPyMongoConfig("platform", "GroupID") userDBName = ReadChConfig.GetPyMongoConfig("connect", "USER_DB_NAME") - getUrl = getUrl + "?Type=GameWarning&groupID=%s&userDBName=%s&MsgInfo=%s"%(groupID, userDBName, urllib.quote_plus(msgInfo)) - + getUrl = getUrl + "?Type=%s&groupID=%s&userDBName=%s"%(errType, groupID, userDBName) + if msgInfo: + getUrl = getUrl + "&MsgInfo=%s" % urllib.quote_plus(msgInfo) GetGameWorld().EventReport_EventReport("", "", "", "", 0, getUrl) - \ No newline at end of file + return -- Gitblit v1.8.0