#!/usr/bin/python
|
# -*- coding: GBK -*-
|
#---------------------------------------------------------------------
|
#
|
#---------------------------------------------------------------------
|
##@package GameWorld
|
# @todo: ³£Óú¯Êý¶¨Òå
|
#
|
# @author: eggxp
|
# @date 2010-03-31
|
# @version 2.4
|
#
|
# @change: "2012-12-21 11:00" jiang ÐÂÔöº¯ÊýÍæ¼Òʱ¼ä¼ä¸ôRefurbishPlayerTick
|
# @change: "2013-01-18 18:45" hyx Ôö¼Ó»ñÈ¡Íæ¼ÒÇø·þÃûµÄ½Ó¿Ú
|
# @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º¯Êý
|
# @change: "2015-06-08 20:30" hxp Ôö¼Ó»ñÈ¡channelCode
|
# @change: "2015-10-22 23:00" hxp Ôö¼Ó»ñÈ¡×Ó·þserverID
|
# @change: "2016-03-28 17:00" hxp Ôö¼Ó´´½Ç¸ÄÃûGetPlayerFullName
|
# @change: "2016-07-18 19:00" hxp Ôö¼Ó»ñȡƽ̨Õ˺Å
|
#---------------------------------------------------------------------
|
#"""Version = 2016-07-18 19:00"""
|
#---------------------------------------------------------------------
|
import IPY_GameServer
|
import LogUI
|
import ChConfig
|
import IpyGameDataPY
|
import PyGameData
|
import ReadChConfig
|
import PlayerDBGSEvent
|
import ConfigParser
|
import GameConfig
|
import ShareDefine
|
import CommFunc
|
import datetime
|
import os
|
import math
|
import sys
|
import time
|
import random
|
import copy
|
#import psyco
|
#---------------------------------------------------------------------
|
GameWorldData = IPY_GameServer.IPY_GameWorld()
|
#---------------------------------------------------------------------
|
|
ServerRootPath = "" # ·þÎñÆ÷¸ù·¾¶
|
MergeServerID = 0 # ±¾×Ó·þµÄ¿ç·þID
|
|
#---------------------------------------------------------------------
|
|
## º¯Êýµ÷ÓÃ
|
# @param curCallObj ʵÀý£¨¿ÉÄÜÊÇij¸öÎļþÃû£©
|
# @param callName ʵÀýµÄij¸öÊôÐÔ
|
# @return ÊôÐÔ
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def ParseNameGetObj(curCallObj, callName):
|
callList = callName.split(".")
|
if len(callList) <= 1:
|
return None
|
|
for curCallName in callList:
|
if hasattr(curCallObj, curCallName) != True:
|
#ÎÞ´ËÊôÐÔ
|
return None
|
|
curCallObj = getattr(curCallObj, curCallName)
|
|
return curCallObj
|
|
## Íⲿµ÷ÓõĻñÈ¡ÊôÐÔ£¬ÇÒÊÇ¿ÉÒÔcallµÄ
|
# @param curCallObj ʵÀý£¨¿ÉÄÜÊÇij¸öÎļþÃû£©
|
# @param callName ʵÀýµÄij¸öÊôÐÔ
|
# @return ¿ÉÒÔcallµÄÊôÐÔ
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetExecFunc(curCallObj, callName):
|
curCallObj = ParseNameGetObj(curCallObj, callName)
|
|
if curCallObj == None:
|
return None
|
|
if callable(curCallObj) != True:
|
#²»¿Éµ÷ÓÃ
|
return None
|
|
return curCallObj
|
|
##¸¡µãÊýÏòÉÏÈ¡Õû
|
# @param x ÊäÈëµÄÊý
|
# @return ·µ»ØÖµ, ÏòÉÏÈ¡ÕûºóµÄÖµ
|
# @remarks ¸¡µãÊýÏòÉÏÈ¡Õû
|
def GetFloatUpper(x):
|
return int(math.ceil(x))
|
|
## ÏòÉÏÈ¡Õû(²ÎÊý -> Öµ,³ýÊý)
|
# @param x Öµ
|
# @param div ³ýÊý
|
# @return int
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetIntUpper(x, div):
|
return int(math.ceil(x / float(div)))
|
|
## ×Ö·û´®×ª»»ÎªÕûÐÍ, Èç¹û²»ÄÜת»», ·µ»ØÄ¬ÈÏÖµ
|
# @param input ×Ö·û´®
|
# @param defValue ĬÈÏÖµ
|
# @return int or ĬÈÏÖµ
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def ToIntDef(input, defValue = 0):
|
try:
|
result = int(input)
|
return result
|
|
except ValueError:
|
return defValue
|
|
## ÅжÏ2¸ö¶ÔÏóÊÇ·ñͬ¹ú¼®
|
# @param srcObj Æðµã¶ÔÏó
|
# @param desObj Ä¿±ê¶ÔÏó
|
# @return True or False
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def IsSameCountry(srcObj, desObj):
|
#ͬ¹ú¼®
|
if srcObj.GetCountry() == desObj.GetCountry() :
|
return True
|
#Ò»ÈËÊÇÐÂÊÖ,ͬ¹ú¼®
|
if srcObj.GetCountry() == 1 or desObj.GetCountry() == 1 :
|
return True
|
return False
|
|
## ¼ì²éÊÇ·ñÊÇGM
|
# @param curPlayer
|
# @return None
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def IsGM(curPlayer):
|
#0:²»ÊÇGM 90:ÄÚ²¿²âÊÔ
|
if curPlayer.GetGMLevel() in [0 , 90]:
|
return
|
|
return True
|
|
## »ñµÃµ±Ç°ÏµÍ³Ê±¼ä
|
# @param
|
# @return µ±Ç°Ê±¼ä
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetCurrentDataTimeStr():
|
curTimeStr = str(GetServerTime())
|
curTimeStr = curTimeStr.split(".")[0]
|
return curTimeStr
|
|
## »ñµÃϵͳʱ¼ä(²ÎÊý -> ʱ¼äÁбí)
|
# @param timeStr ʱ¼äÁбí
|
# @return ʱ¼ädatetime¸ñʽ
|
# @remarks »ñµÃϵͳʱ¼ä(²ÎÊý -> ʱ¼äÁбí)
|
def GetDateTimeByStr(timeStr):
|
timeStr = timeStr.strip().split(".")[0]
|
try:
|
return datetime.datetime.strptime(timeStr, ChConfig.TYPE_Time_Format)
|
except BaseException , e :
|
Log("%s : %s"%(e, timeStr))
|
return
|
|
return
|
|
## »ñµÃÖ¸¶¨µÄʱ¼ä¸ñʽ
|
# @param timeStr ʱ¼äÁбí
|
# @param timeFormat Ö¸¶¨µÄת»»¸ñʽ
|
# @return ʱ¼ädatetime¸ñʽ
|
# @remarks »ñµÃÖ¸¶¨µÄʱ¼ä¸ñʽ
|
def GetDateTimeByFormatStr(timeStr, timeFormat):
|
timeStr = timeStr.strip().split(".")[0]
|
try:
|
return datetime.datetime.strptime(timeStr, timeFormat)
|
except BaseException , e :
|
Log("%s : %s"%(e, timeStr))
|
return
|
|
return
|
#######################################################################
|
## »ñÈ¡GameWorldEventManager
|
# @param
|
# @return GameWorldEventManager
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetGameWorldEventManager():
|
global GameWorldData
|
return GameWorldData.GetGameWorldEventManager()
|
|
## »ñÈ¡GameWorld
|
# @param
|
# @return GameWorld
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetGameWorld():
|
global GameWorldData
|
return GameWorldData
|
|
## »ñÈ¡PlayerManager
|
# @param
|
# @return PlayerManager
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetPlayerManager():
|
global GameWorldData
|
return GameWorldData.GetPlayerManager()
|
|
## »ñÈ¡TeamManager
|
# @param
|
# @return TeamManager
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetTeamManager():
|
global GameWorldData
|
return GameWorldData.GetTeamManager()
|
|
## »ñÈ¡TruckMananger
|
# @param
|
# @return TruckMananger
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetTruckMananger():
|
global GameWorldData
|
return GameWorldData.GetTruckManager()
|
|
## »ñÈ¡FamilyManager
|
# @param
|
# @return FamilyManager
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetFamilyManager():
|
global GameWorldData
|
return GameWorldData.GetFamilyManager()
|
|
## »ñÈ¡Billboard
|
# @param
|
# @return Billboard
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetBillboard():
|
global GameWorldData
|
return GameWorldData.GetBillboardManager()
|
|
|
## »ñÈ¡MailManager
|
# @param
|
# @return MailManager
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetMailManager():
|
global GameWorldData
|
return GameWorldData.GetAllMailList()
|
|
## »ñÈ¡¼Ò×å¿Æ¼¼¹ÜÀíÆ÷
|
# @param
|
# @return FamilyTechManager
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetFamilyTechManager():
|
global GameWorldData
|
return GameWorldData.GetFamilyTechMgr()
|
|
## »ñÈ¡¾º¼¼³¡¹ÜÀíÆ÷
|
# @param
|
# @return FamilyTechManager
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetVSRoomManager():
|
global GameWorldData
|
return GameWorldData.GetVSRoomMgr()
|
|
## »ñÈ¡½±³Í±í¹ÜÀíÆ÷
|
# @param
|
# @return VsRewardMgr
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetVsRewardManager():
|
global GameWorldData
|
return GameWorldData.GetVsRewardMgr()
|
|
|
## »ñÈ¡°ï»áÐÐΪ¹ÜÀíÆ÷
|
# @param
|
# @return VsRewardMgr
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetFamilyActionManager():
|
global GameWorldData
|
return GameWorldData.GetFamilyActionMgr()
|
|
## »ñÈ¡¸±±¾Í¨¹Ø¼Ç¼¹ÜÀíÆ÷
|
# @param
|
# @return VsRewardMgr
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetFBPassRecManager():
|
global GameWorldData
|
return GameWorldData.GetFBPassRecMgr()
|
|
## »ñÈ¡Íæ¼ÒÐÅϢͨÓüǼ¹ÜÀíÆ÷
|
# @param
|
# @return VsRewardMgr
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetUniversalRecMgr():
|
global GameWorldData
|
return GameWorldData.GetUniversalRecMgr()
|
|
## ½»Ò×Ëù¹ÜÀíÆ÷
|
# @param
|
# @return BourseManager
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetBourseManager():
|
global GameWorldData
|
return GameWorldData.GetBourseManager()
|
|
## GM¹¤¾ß²¹³¥¹ÜÀíÆ÷
|
# @param
|
# @return HightLadderMgr
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetCompensationMgr():
|
global GameWorldData
|
return GameWorldData.GetCompensationMgr()
|
|
#######################################################################
|
## ÖØÐ¼ÓÔØ
|
# @param tick µ±Ç°Ê±¼ä
|
# @return None
|
# @remarks
|
def DoReload(tick):
|
if __GetPsycoIsOpen():
|
#Psyco¿ªÆô
|
PsycoReload(tick)
|
return
|
|
#Psyco¹Ø±Õ
|
__DoReload(tick)
|
return
|
|
## ÖØÐ¼ÓÔØ
|
# @param tick µ±Ç°Ê±¼ä
|
# @return None
|
# @remarks
|
def __DoReload(tick):
|
for name, reloadPath in sys.modules.items():
|
try:
|
if GetGameWorld().GetDictByKey("Reload") == 1 and name in ["PyGameData"]:
|
DebugLog("²»ÖضÁ %s"%name)
|
continue
|
reload(reloadPath)
|
except Exception:
|
continue
|
GetGameWorld().SetDict("Reload", 1)
|
Log("Reload Begin : time = %s"%GetCurrentDataTimeStr())
|
return
|
#---------------------------------------------------------------------
|
## Õý³£ÈÕ¼Ç
|
# @param msg ÐÅÏ¢
|
# @param playerID Íæ¼ÒID
|
# @param par
|
# @return None
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def Log(msg , playerID = 0, par = 0):
|
LogUI.Msg('%s\t%s\t%s'%(par, playerID, msg))
|
return
|
|
## Òì³£ÈÕ¼Ç
|
# @param msg ÐÅÏ¢
|
# @param playerID Íæ¼ÒID
|
# @param par
|
# @return None
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def ErrLog(msg, playerID = 0, par = 0):
|
LogUI.Msg('%s\t%s\t###Error:%s'%(par, playerID, msg))
|
return
|
|
##DEBUGµ÷ÊÔÊä³öÐÅÏ¢
|
# @param msg ÏûÏ¢
|
# @param playerID Íæ¼ÒID
|
# @param par ÏûÏ¢²ÎÊý
|
# @return ·µ»ØÖµÎÞÒâÒå
|
def DebugLog(msg, playerID = 0, par = 0):
|
if not GetGameWorld().GetDebugLevel():
|
return
|
|
LogUI.Msg('%s\t%s\tPyDebug:%s'%(par, playerID, msg))
|
return
|
|
#---------------------------------------------------------------------
|
##»ñµÃµ±Ç°·þÎñÆ÷¿ç·þID
|
# @param ÎÞ
|
# @return
|
def GetMergeServerID():
|
global MergeServerID
|
|
if not MergeServerID:
|
rootPath = ChConfig.GetServerRootPath()
|
mergeServerIniFile = rootPath + "\\ZoneServerGroup\\rungate\\InterfaceServer\\MultiServerWarProxyServer\\Config\\config.ini"
|
if not os.path.isfile(mergeServerIniFile):
|
ErrLog('ÎÞ·¨ÕÒµ½Îļþ = %s'%(mergeServerIniFile))
|
raise Exception('ÎÞ·¨ÕÒµ½Îļþ = %s'%(mergeServerIniFile))
|
|
mergeServerIni = ConfigParser.ConfigParser()
|
mergeServerIni.read(mergeServerIniFile)
|
|
section, option = "Config", "ServerID"
|
if not mergeServerIni.has_option(section, option):
|
ErrLog("%s ÕÒ²»µ½ÅäÖÃ: section=%s,option=%s" % (mergeServerIniFile, section, option))
|
return 0
|
|
MergeServerID = ToIntDef(mergeServerIni.get(section, option))
|
Log("¶ÁÈ¡ MergeServerID=%s" % MergeServerID)
|
|
return MergeServerID
|
|
## »ñµÃµ±Ç°·þÎñÆ÷µÄ°æ±¾ºÅ
|
# @param
|
# @return ServerVersion
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetServerVersion():
|
return GetGameWorld().GetServerVersion()
|
|
def GetServerGroupID():
|
## ·þÎñÆ÷×éID£¬±ØÐëΨһ£¬´ú±íÕą̂ÎïÀí·þÎñÆ÷
|
return ToIntDef(ReadChConfig.GetPyMongoConfig("platform", "GroupID"), 0)
|
|
def GetPlatformServerNum(platform):
|
# »ñÈ¡·þÎñÆ÷µÄƽ̨±àºÅ
|
platformNumDict = ReadChConfig.GetDBEvalChConfig("DBPlatformNum")
|
#===========================================================================
|
# if platform not in platformNumDict:
|
# ErrLog("DBPlatformNumûÓÐÅäÖø÷þÎñÆ÷ƽ̨Ëù¶ÔÓ¦µÄ±àºÅ£¡platfrom=%s" % platform)
|
# raise Exception("DBPlatformNumûÓÐÅäÖø÷þÎñÆ÷ƽ̨Ëù¶ÔÓ¦µÄ±àºÅ£¡platfrom=%s" % platform)
|
#===========================================================================
|
return platformNumDict.get(platform, 0)
|
|
##»ñµÃµ±Ç°·þÎñÆ÷ƽ̨
|
# @param ÎÞ
|
# @return
|
def GetPlatform():
|
return ReadChConfig.GetPyMongoConfig("platform", "PlatformName")
|
|
#===============================================================================
|
# ##»ñµÃµ±Ç°·þÎñÆ÷ID
|
# # @param ÎÞ
|
# # @return
|
# def GetServerID():
|
# return ToIntDef(GetServerSID()[1:], 0)
|
#===============================================================================
|
|
#===============================================================================
|
# def GetServerSID():
|
# ##»ñµÃµ±Ç°·þÎñÆ÷ID, ´øsµÄ
|
# return ReadChConfig.GetPyMongoConfig("platform", "ServerID")
|
#===============================================================================
|
|
Def_AccID_Split_Sign = "@"
|
|
##Íæ¼ÒÓÎÏ·Õ˺Ÿñʽ: ƽ̨Õ˺Å@ƽ̨Ãû@sÇø·þID, ƽ̨Õ˺ſÉÄÜ´ø@£¬ÈçÓÊÏäyhlz123@qq.com@173on_lan@s519
|
##»ñÈ¡Íæ¼ÒËùÊôÇø·þID
|
# @param curPlayer
|
# @return
|
def GetPlayerServerID(curPlayer):
|
accID = curPlayer.GetAccID()
|
infoList = accID.split(Def_AccID_Split_Sign)
|
return 0 if len(infoList) < 3 else int(infoList[-1][1:])
|
|
def GetPlayerServerSID(curPlayer):
|
# ·µ»Øº¬sµÄserverID
|
accID = curPlayer.GetAccID()
|
infoList = accID.split(Def_AccID_Split_Sign)
|
return "" if len(infoList) < 3 else infoList[-1]
|
|
def GetPlayerMainServerID(accIDPlatform):
|
# Íæ¼ÒºÏ·þºóËùÊôÖ÷·þID
|
# @param accIDPlatform: Íæ¼ÒÕ˺ÅËùÊôµÄƽ̨
|
mainServerID = ToIntDef(ReadChConfig.GetPyMongoConfig("platform", "%sMainServerID" % accIDPlatform), None)
|
if mainServerID != None:
|
return mainServerID
|
return 0
|
|
|
#===============================================================================
|
# ƽ̨ID = appid
|
# ÔËÓªID = spid
|
# ·þÎñÆ÷Õ˺Ÿü¸Ä
|
# ÔÏÈÕ˺Å×éºÏΪ
|
# ÔËÓªÌṩµÄÍæ¼ÒÕ˺ÅID + ƽ̨ID + Çø·þ×é³É
|
#
|
# ÒòΪIOSºÍ°²×¿ÔÚÖ§³Ö»ì·þµÄÇé¿öÏ£¬»¹ÒªÄÜÖ§³Öͬһ¸ö½ÇÉ«ºÅ£¬¹ÊÒýÈëÒ»¸öеÄÔËÓªID£¨¿Í»§¶Ë´ò°üÅäÖã©£¬ÒÔ±£Ö¤Íæ¼ÒÕ˺ÅΪͬһ¸ö
|
# Õ˺Å×éºÏ±ä¸ü
|
# ÔËÓªÌṩµÄÍæ¼ÒÕ˺ÅID + ÔËÓªID + Çø·þ×é³É
|
#
|
# ÔÓÎÏ·Öлñȡƽ̨ID½Ó¿Ú±ä¸ü
|
# 1. db ´ÓÊý¾Ý¿âÖеÄÕ˺űí»ñÈ¡AppID
|
# 2. GameServerºÍMapServer ½Ó¿Ú¸ÄΪGetOperator ²Î¿¼ GetPlayerPlatform
|
#===============================================================================
|
|
##»ñÈ¡Íæ¼ÒËùÊôƽ̨
|
def GetPlayerPlatform(curPlayer):
|
return curPlayer.GetAccountInfo().GetOperator()
|
|
##»ñȡƽ̨Õ˺Å
|
def GetPlatformAccID(gameAccID):
|
infoList = gameAccID.split(Def_AccID_Split_Sign)
|
paInfoList = infoList[:-2]
|
platformAccID = Def_AccID_Split_Sign.join(paInfoList)
|
return platformAccID
|
|
##»ñÈ¡Íæ¼ÒÕ˺ÅËùÊôƵµÀ
|
# @param curPlayer
|
# @return
|
def GetPlayerChannelCode(curPlayer):
|
userDataDict = GetUserData(curPlayer)
|
return userDataDict.get("channel_code", "")
|
|
## »ñÈ¡Óû§ÐÅÏ¢×Öµä
|
# @param curPlayer
|
# @param key
|
# @param default
|
# @return
|
def GetUserData(curPlayer):
|
playerUserDataStr = curPlayer.GetUserData()
|
|
if not playerUserDataStr:
|
return {}
|
|
try:
|
curPlayerUserData = eval(playerUserDataStr)
|
except:
|
ErrLog("data error UserData = %s"%playerUserDataStr )
|
return {}
|
|
if not isinstance(curPlayerUserData, dict):
|
ErrLog("type error UserData = %s"%playerUserDataStr )
|
return {}
|
|
return curPlayerUserData
|
|
## »ñµÃ²éѯµÄÍæ¼ÒËùÔڵĵØÍ¼ID
|
# @param tagPlayer Ä¿±êÍæ¼Ò
|
# @return RealMapID
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def GetQueryPlayerMapID(tagPlayer):
|
if not tagPlayer or not tagPlayer.GetInitOK():
|
return 0
|
|
return tagPlayer.GetRealMapID()
|
|
#---------------------------------------------------------------------
|
|
def GetOperationActionDateStr(dateInfo, openServerDay):
|
'''»ñÈ¡ÔËÓª»î¶¯¶ÔÓ¦ÈÕÆÚ£¬´æÊý×Ö´ú±í¿ª·þÌìÅäÖã¬ÐèҪת»¯Îª¶ÔÓ¦µÄÈÕÆÚ
|
@param dateInfo: ÔËÓª»î¶¯±íÅäÖõÄÈÕÆÚÐÅÏ¢, Èç¹ûÊÇ´¿Êý×Ö´ú±í¿ª·þÌì
|
@param openServerDay: µ±Ç°¿ª·þÌì
|
'''
|
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)
|
curDateTime = datetime.datetime.today()
|
actionDateTime = curDateTime + datetime.timedelta(days=(actionServerDay-diffDay))
|
return "%d-%d-%d" % (actionDateTime.year, actionDateTime.month, actionDateTime.day)
|
|
##»ñµÃϵͳʱ¼ä
|
# @param ÎÞÒâÒå
|
# @return ϵͳʱ¼ä
|
# @remarks »ñµÃϵͳʱ¼ä
|
def GetServerTime():
|
return datetime.datetime.today()
|
#---------------------------------------------------------------------
|
##»ñÈ¡2¸öʱ¼äÖ®¼ä²îÒìµÄTimeDeltaÀàʵÀý
|
# @param compareTimeStr ±È½ÏµÄʱ¼ä×Ö·û, Èç"2010-05-26 11:21:25"
|
# @return class timedelta ʵÀý »ò None
|
# @remarks »ñÈ¡2¸öʱ¼äÖ®¼ä²îÒìµÄTimeDeltaÀàʵÀý
|
def __GetPastTimeDelta(compareTimeStr):
|
#ÏÖÔÚʱ¼ä
|
curDataTime = GetServerTime()
|
#±È½Ïʱ¼ä
|
compareDataTime = GetDateTimeByStr(compareTimeStr)
|
#»ñȡת»»ºóµÄʱ¼äÒì³£
|
if curDataTime == None or compareDataTime == None:
|
return
|
|
return (curDataTime - compareDataTime)
|
#---------------------------------------------------------------------
|
##»ñµÃÓëÏÖʵʱ¼ä²î¾àµÄÌìÊý
|
# @param dateTimeStr ±È½Ïʱ¼ä×Ö·û Èç"2010-05-26 11:21:25"
|
# @return ·µ»ØÖµ, Ïà²îµÄÌìÊý
|
# @remarks »ñµÃÓëÏÖʵʱ¼ä²î¾àµÄÌìÊý
|
def GetPastDay(dateTimeStr):
|
pastTimeDelta = __GetPastTimeDelta(dateTimeStr)
|
|
if pastTimeDelta == None:
|
ErrLog("GetPastDay Err dateTimeStr = %s"%(dateTimeStr))
|
return 0
|
|
return pastTimeDelta.days
|
|
#---------------------------------------------------------------------
|
##»ñµÃÓëÏÖʵʱ¼ä²î¾àµÄСʱÊý
|
# @param dateTimeStr ±È½Ïʱ¼ä×Ö·û Èç"2010-05-26 11:21:25"
|
# @return ·µ»ØÖµ, Ïà²îµÄСʱÊý
|
# @remarks »ñµÃÓëÏÖʵʱ¼ä²î¾àµÄСʱÊý
|
def GetPastHour(dateTimeStr):
|
pastTimeDelta = __GetPastTimeDelta(dateTimeStr)
|
|
if pastTimeDelta == None:
|
ErrLog("GetPastHour Err dateTimeStr = %s"%(dateTimeStr))
|
return 0
|
|
return pastTimeDelta.days * 24 + pastTimeDelta.seconds / 3600
|
|
#---------------------------------------------------------------------
|
##»ñµÃÓëÏÖʵʱ¼ä²î¾àµÄÃëÊý
|
# @param dateTimeStr ±È½Ïʱ¼ä×Ö·û Èç"2010-05-26 11:21:25"
|
# @return ·µ»ØÖµ, Ïà²îµÄÃëÊý
|
# @remarks »ñµÃÓëÏÖʵʱ¼ä²î¾àµÄÃëÊý
|
def GetPastSeconds(dateTimeStr):
|
pastTimeDelta = __GetPastTimeDelta(dateTimeStr)
|
|
if pastTimeDelta == None:
|
ErrLog("GetPastSeconds Err dateTimeStr = %s"%(dateTimeStr))
|
return 0
|
|
return pastTimeDelta.days * 24 * 60 * 60 + pastTimeDelta.seconds
|
|
#---------------------------------------------------------------------
|
##ÉèÖÃÊÀ½ç·þÎñÆ÷×Öµä
|
# @param key ×ÖµäÖµ
|
# @param tick ʱ¼ä´Á
|
# @return ²¼¶ûÖµ
|
# @remarks ÉèÖÃÊÀ½ç·þÎñÆ÷×Öµä
|
def SetWorldDictKey(key, tick):
|
worldMgr = GetGameWorld()
|
lastTick = worldMgr.GetTickByType(key)
|
|
if lastTick == -1:
|
#δ³õʼ»¯²»·¢ÐÅÏ¢
|
return False
|
|
if tick - lastTick < ChConfig.TYPE_Tick_Time[key]:
|
return False
|
|
worldMgr.SetTickByType(key, tick)
|
return True
|
#---------------------------------------------------------------------
|
##ÉèÖÃÍæ¼Ò×Öµä
|
# @param curPlayer Íæ¼ÒʵÀý
|
# @param key ×ÖµäÖµ
|
# @param lastTick ³ÖÐøÊ±¼ä
|
# @param tick ʱ¼ä´Á
|
# @return ²¼¶ûÖµ
|
# @remarks ÉèÖÃÍæ¼Ò×Öµä
|
def SetPlayerDictKey(curPlayer, key, lastTick, tick):
|
key = str(key)
|
curPlayerKeyValue = curPlayer.GetDictByKey(key)
|
#µÚÒ»´Î¼Ç¼
|
if not curPlayerKeyValue:
|
curPlayer.SetDict(key, tick)
|
return True
|
|
if tick - curPlayerKeyValue < lastTick:
|
#ʱ¼äδµ½
|
return False
|
|
curPlayer.SetDict(key, tick)
|
return True
|
|
|
## Ë¢ÐÂÍæ¼Ò¸öÈËʱ¼ä
|
# @param curPlayer Íæ¼ÒʵÀý
|
# @param tickType ʱ¼äÀàÐÍ
|
# @param tick ʱ¼ä´Á
|
# @return ²¼¶ûÖµ
|
def RefurbishPlayerTick(curPlayer, tickType, tick):
|
|
dictKey = "Player_Tick_%s"%tickType
|
lastTick = curPlayer.GetDictByKey(dictKey)
|
|
#µÚÒ»´Î¼Ç¼
|
if not lastTick:
|
curPlayer.SetDict(dictKey, tick)
|
return True
|
|
#¼ä¸ôδµ½
|
if tick - lastTick < ChConfig.TYPE_Player_Tick_Time[tickType]:
|
#ʱ¼äδµ½
|
return False
|
|
curPlayer.SetDict(dictKey, tick)
|
return True
|
|
|
##¹ã²¥MapServer£¬'+'·Ö¸ôkey ºÍValue, ÓÃÓÚÖ»´¦ÀíMapServerµÄ SetGameWorldDictµÄ²ÎÊý
|
# @param keyName ×ÖµäÃû
|
# @param value Öµ
|
# @param mapID µØÍ¼ID£¬0Ϊȫ¹ã²¥
|
# @return ÎÞ
|
# @remarks ¹ã²¥MapServer£¬'+'·Ö¸ôkey ºÍValue, ÓÃÓÚÖ»´¦ÀíMapServerµÄ SetGameWorldDictµÄ²ÎÊý
|
def SendMapServerMsgEx(keyName, value, mapID = 0, routeServerIndex = 1):
|
GetGameWorld().SendMapServerMsg(mapID, "%s%s%s" % (keyName, ShareDefine.Def_Notify_Separator, value), routeServerIndex)
|
return
|
|
def SendCommMapServerMsg(keyName, value):
|
## ¹ã²¥¸ø³£¹æµØÍ¼ÐÅÏ¢£¬¸±±¾²»»áÊÕµ½
|
sendMapIDList = []
|
for mapLineInfo, routeServerIndex in PyGameData.g_commMapLineRouteDict.items():
|
if mapLineInfo not in PyGameData.g_commMapLineInfo:
|
continue
|
realMapID = PyGameData.g_commMapLineInfo[mapLineInfo][0]
|
if realMapID in sendMapIDList:
|
continue
|
sendMapIDList.append(realMapID)
|
SendMapServerMsgEx(keyName, value, realMapID, routeServerIndex)
|
return
|
#---------------------------------------------------------------------
|
##»ñÈ¡²é¿´Ò³ÊýµÄÆðʼË÷ÒýºÍ½áÊøË÷Òý.
|
# @param viewPageIndex ²é¿´Ë÷Òý
|
# @param singePageCnt µ¥Ò³ÊýÁ¿
|
# @param totalCnt ×ÜÁ¿
|
# @return ¿ªÊ¼Ë÷Òý, ½áÊøË÷Òý
|
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦
|
def GetViewPageBeginIndexAndEndIndex(viewPageIndex, singePageCnt, totalCnt):
|
endIndex = max((viewPageIndex + 1) * singePageCnt - 1, 0)
|
#¼ÓÒ»¸ö·À·¶, ±ÜÃⳬ³öÉÏÏÞ
|
endIndex = max(min(endIndex, totalCnt - 1), 0)
|
#»ñÈ¡¿ªÆôË÷Òý
|
startIndex = min(viewPageIndex * singePageCnt, endIndex)
|
return startIndex, endIndex
|
|
#---------------------------------------------------------------------
|
##»ñÈ¡Ó뵱ǰʱ¼äÏà²îÌìÊýµÄdatetime¸ñʽÊý¾Ý
|
# @param diffDays ²î¾àÌìÊý
|
# @return datetime ÀàÐÍÊý¾Ý
|
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦
|
def GetDatetimeByDiffDays(diffDays):
|
return GetServerTime() + datetime.timedelta(days = diffDays)
|
|
#---------------------------------------------------------------------
|
##»ñµÃÓÅ»¯µÄº¯ÊýÖ¸Õë
|
# @param func º¯ÊýÖ¸Õë
|
# @return ÓÅ»¯ºóµÄº¯ÊýÖ¸Õë
|
# @remarks
|
def GetPsycoFunc(func):
|
return func
|
# if not __GetPsycoIsOpen():
|
# #¹Ø±Õpsyco, ·µ»ØÔº¯Êý
|
# return func
|
#
|
# return psyco.proxy(func)
|
|
#---------------------------------------------------------------------
|
##»ñÈ¡psyco¿ª¹Ø
|
# @param ÎÞ²ÎÊý
|
# @return ²¼¶ûÖµ
|
# @remarks
|
def __GetPsycoIsOpen():
|
return ReadChConfig.GetEvalChConfig('PsycoSwitch')
|
|
##ÖØÐ¼ÓÔØ½Å±¾.
|
# @param tick ʱ¼ä´Á
|
# @return ·µ»ØÖµÎÞÒâÒå
|
# @remarks ÖØÐ¼ÓÔØ½Å±¾
|
def PsycoReload(tick):
|
if not SetWorldDictKey(ChConfig.TYPE_ReloadScript, tick):
|
#¼ä¸ôδµ½
|
return
|
|
moduleNameList = []
|
for moduleName in sys.modules.keys():
|
moduleNameList.append([moduleName, moduleName.split(".")[-1]])
|
|
TravelFile(ChConfig.GameServerPath, "", moduleNameList)
|
Log("PsycoReload Begin : time = %s"%GetCurrentDataTimeStr())
|
return
|
|
## ±éÀúÎļþ
|
# @param scriptPath
|
# @param filePath
|
# @return None
|
# @remarks º¯ÊýÏêϸ˵Ã÷.
|
def TravelFile(scriptPath, filePath, moduleNameList):
|
|
for fileName in os.listdir(scriptPath + filePath):
|
|
if fileName.startswith("."):
|
continue
|
|
curModuleName = fileName.split('.')[0]
|
for reloadName, moduleName in moduleNameList:
|
if curModuleName != moduleName:
|
continue
|
|
module = sys.modules.get(reloadName)
|
|
if not module:
|
continue
|
|
reload(module)
|
|
#ÊÇÎļþ¼Ð
|
if os.path.isdir(scriptPath + filePath + "\\" + fileName):
|
TravelFile(scriptPath, filePath + "\\" + fileName + "\\", moduleNameList)
|
|
return
|
|
|
## È«¾Öº¯Êý¼òҪ˵Ã÷£º×ª»¯³Éʱ¡¢·Ö¡¢Ãë
|
# @param ²ÎÊý£ºÊ±¼ä£¨ºÁÃë¼¶£©
|
# @return ·µ»ØÖµ£ºÊ±¡¢·Ö¡¢Ãë
|
# @remarks º¯ÊýÏêϸ˵Ã÷£º
|
def ChangeInputTime(inputTime):
|
curTimeHour = int(inputTime/1000)/3600
|
curTimeMinute = int(inputTime/1000)/60%60
|
curTimeSecond = int(inputTime/1000)%60
|
return curTimeHour,curTimeMinute,curTimeSecond
|
|
|
## Êýֵʱ¼äת»»³Éʱ¼ä¸ñʽ
|
# @param timeNum: Êýֵʱ¼ä
|
# @return: 2012-03-30 22:16:41 <type 'datetime.datetime'>
|
def ChangeTimeNumToStr(timeNum, timeFormat=ChConfig.TYPE_Time_Format):
|
return time.strftime(timeFormat, time.localtime(timeNum))
|
|
## Êýֵʱ¼äת»»³Éʱ¼ä¸ñʽ
|
# @param timeNum: Êýֵʱ¼ä
|
# @return: 2012-03-30 22:16:41 <type 'datetime.datetime'>
|
def ChangeTimeNumToDatetime(timeNum, timeFormat=ChConfig.TYPE_Time_Format):
|
timeStr = time.strftime(timeFormat, time.localtime(timeNum))
|
return datetime.datetime.strptime(timeStr, timeFormat)
|
|
## ʱ¼ä¸ñʽת»»³ÉÊýֵʱ¼ä£¬¿É²Î¿¼datetime.datetime.fromtimestamp(102645645)
|
# @param timeNum
|
# @return ʱ¼äÊýÖµ 1970ÄêÆð
|
def ChangeTimeStrToNum(timeStr, timeFormat=ChConfig.TYPE_Time_Format):
|
timeStr = datetime.datetime.strptime(timeStr, timeFormat).timetuple()
|
return int(time.mktime(timeStr))
|
|
|
##»ñÈ¡Ó뵱ǰʱ¼äÏà²îÌìÊýµÄdatetime¸ñʽÊý¾Ý
|
# @param diffDays ²î¾àÌìÊý
|
# @return datetime ÀàÐÍÊý¾Ý
|
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦
|
def GetDatetimeBySubDays(diffDays):
|
return datetime.datetime.today() - datetime.timedelta(days = diffDays)
|
|
def IsCrossServer():
|
## ÊÇ·ñ¿ç·þ·þÎñÆ÷
|
return ToIntDef(ReadChConfig.GetPyMongoConfig("Merge", "IsMergeServer"), 0)
|
|
def IsCrossRealmOpen():
|
## ÊÇ·ñ¿ªÆô¿ç·þ»î¶¯
|
return ReadChConfig.GetPyMongoConfig("Merge", "MergeServerIP") or IsCrossServer()
|
|
def GetCrossZoneName():
|
## ¿ç·þ·þÎñÆ÷·ÖÇøÃû£¬±ê¼ÇÒ»Æð¿ç·þ·ÖÇøµÄÃû×Ö£¬ÅäÖÃÔÚ¿ç·þ·þÎñÆ÷£¬×Ó·þ²»ÓÃÅäÖã¬ÓÉ¿ç·þ·þÎñÆ÷ͬ²½
|
if IsCrossServer():
|
return ReadChConfig.GetPyMongoConfig("Merge", "CrossZoneName")
|
return PyGameData.g_crossZoneName
|
|
## »ñÈ¡Íæ¼ÒµÄÇø·þÃû£¬½öÔÚ¿ç·þÓÐЧ
|
# @param curPlayer Íæ¼ÒʵÀý
|
# @return: Çø·þÃû
|
def GetAreaName(curPlayer):
|
operator = curPlayer.GetAccountInfo().GetOperator()
|
areaID = curPlayer.GetAccountInfo().GetAreaID()
|
|
# "%s-%s"%(operator, areaID)
|
areaNameInfo = ReadChConfig.GetEvalChConfig("AreaNameInfo")
|
areaName = eval(areaNameInfo.get("NameExpr", ""))
|
|
return areaName
|
|
|
## »ñÈ¡Íæ¼ÒµÄÇø·þÃûCRC£¬½öÔÚ¿ç·þÓÐЧ
|
# @param curPlayer Íæ¼ÒʵÀý
|
# @return: Çø·þÃû
|
def GetAreaCrc(curPlayer):
|
areaName = GetAreaName(curPlayer)
|
return CommFunc.GetStrCrc(areaName)
|
|
|
## »ñÈ¡Íæ¼ÒÈ«Ãû£¬Ò»°ã´´½Ç¼°¸ÄÃûʱÓÃ
|
def GetPlayerFullName(curPlayer, playerName, serverID):
|
roleNameFormat = eval(ReadChConfig.GetChConfig("RoleNameFormat"))
|
nameFormat, paramList, maxLen, maxServerID, specServerDict = roleNameFormat
|
if serverID > maxServerID or serverID <= 0:
|
ErrLog("GetPlayerFullName serverID=%s error! maxServerID=%s, check RoleNameFormat.txt" % (serverID, maxServerID))
|
return ""
|
|
nameFormatInfo = GetDictValueByRangeKey(specServerDict, serverID)
|
if nameFormatInfo:
|
nameFormat, paramList = nameFormatInfo
|
|
fullName = nameFormat % tuple(paramList)
|
if len(fullName) > maxLen:
|
ErrLog("GetPlayerFullName playerName=%s,È«Ãû=%s len=%s > %s, check RoleNameFormat.txt" % (playerName, fullName, len(fullName), maxLen))
|
return ""
|
|
return fullName
|
|
|
## ´ÓÁбíÖвúÉúÎïÆ·£¬[[¼¸ÂÊ£¬object], ....],Íò·ÖÂÊ
|
# @param itemList ´ýÑ¡Áбí
|
# @return object
|
def GetResultByRandomList(randList, defValue=None, maxRateValue=ChConfig.Def_MaxRateValue):
|
rate = random.randint(0, maxRateValue)
|
|
return GetResultByRiseList(randList, rate, defValue)
|
|
## Ôö³¤ÁÐ±í£¨ÀàËÆ±ýͼ£©´ÓÖлñµÃÖ¸¶¨µÄÐÅÏ¢
|
# @param itemList ´ýÑ¡Áбí
|
# @param point Ö¸¶¨Öµ
|
# @return µÚ¶þ¸öΪ¾ßÌåÐÅÏ¢ or None
|
# @remarks Áбí½á¹¹£¬Ã¿¸öÔªËØÎªÐ¡ÁÐ±í£¬Ð¡ÁÐ±í³¤¶ÈΪ2£¬µÚÒ»¸öÔªËØÎª±È½ÏÖµ£¬µÚ¶þ¸öΪ¾ßÌåÐÅÏ¢
|
def GetResultByRiseList(riseList, point, defValue=None):
|
for smallList in riseList:
|
if point > smallList[0]:
|
continue
|
|
return smallList[1]
|
|
return defValue
|
|
## ¸ù¾Ý×Öµäkey»ñÈ¡valueÖµ
|
# @return
|
def GetDictValueByKey(attrDict, findKey, defaultValue=None):
|
|
if findKey in attrDict:
|
return attrDict[findKey]
|
|
for key, value in attrDict.items():
|
|
if isinstance(key, tuple) and findKey in key:
|
return value
|
|
return defaultValue
|
|
## ¸ù¾Ý×Öµäkey·¶Î§»ñÈ¡valueÖµ
|
def GetDictValueByRangeKey(srcDict, findKey, defaultValue=None):
|
|
if findKey in srcDict:
|
return srcDict[findKey]
|
|
for rangeKey, value in srcDict.items():
|
if isinstance(rangeKey, tuple) and len(rangeKey) == 2 and rangeKey[0] <= findKey <= rangeKey[1]:
|
return value
|
|
return defaultValue
|
|
def CombineSumDict(adict, bdict):
|
# ½«bdictÊý¾ÝºÏ²¢µ½adict, ÏàͬkeyÖµµÄÊý¾ÝÏà¼Ó
|
bdict = copy.deepcopy(bdict)
|
for key, value in adict.items():
|
if key not in bdict:
|
continue
|
adict[key] = value + bdict.pop(key)
|
adict.update(bdict)
|
return adict
|
|
##¸ÅÂÊÏà¹Ø, Õâ¸öʼþÊÇ·ñÄܹ»³öÏÖ
|
# @param rate »ù´¡¼¸ÂÊ
|
# @param maxRate ×î´ó¼¸ÂÊ
|
# @return ·µ»ØÖµ. ÊÇ·ñͨ¹ý¼ì²é
|
# @remarks ¸ÅÂÊÏà¹Ø, Õâ¸öʼþÊÇ·ñÄܹ»³öÏÖ
|
def CanHappen(rate, maxRate=ShareDefine.Def_MaxRateValue):
|
if random.randint(0, maxRate -1) < rate:
|
return 1
|
|
return 0
|
|
def DebugAnswer(curPlayer, text):
|
'''תÂëºóÔÙ·¢DebugAnswer'''
|
#===========================================================================
|
# if not GetGameWorld().GetDebugLevel():
|
# return
|
#===========================================================================
|
DebugLog(text)
|
text = text.decode(ShareDefine.Def_Game_Character_Encoding).encode(GetCharacterEncoding())
|
curPlayer.DebugAnswer(text)
|
return
|
|
def GetMap(mapID): return IpyGameDataPY.GetIpyGameData("ChinMap", mapID)
|
|
def GetNPCData(npcID): return IpyGameDataPY.GetIpyGameData("ChinNPC", npcID)
|
|
# »ñµÃÓÎÏ·ÉèÖõÄ×Ö·û±àÂë, ͳһµ÷ÓñãÓÚº£Íâ°æ±¾
|
def GetCharacterEncoding():
|
encodingList = ReadChConfig.GetEvalChConfig("EncodingTex")
|
|
if len(encodingList) != 2:
|
ErrLog("EncodingTex.txt Error len != 2")
|
return 'utf8'
|
return encodingList[1]
|
|
|
# ·þÎñÆ÷ĬÈÏGBK£¬×ªÅäÖñàÂëÈçUTF8£¬Ò»°ãÓÃÓÚÓëÏÔʾ²ã½»»¥£¬²»ÅжÏÊÇ·ñbase64
|
def GbkToCode(inputText):
|
encodingList = ReadChConfig.GetEvalChConfig("EncodingTex")
|
|
if len(encodingList) != 2:
|
ErrLog("EncodingTex.txt Error len != 2")
|
return inputText
|
|
try:
|
return inputText.decode(ShareDefine.Def_Game_Character_Encoding).encode(GetCharacterEncoding())
|
except:
|
return inputText
|
|
return inputText
|
|
# ·þÎñÆ÷ĬÈÏGBK£¬×ªÅäÖñàÂëÈçUTF8£¬Ò»°ãÓÃÓÚÓëÏÔʾ²ã½»»¥£¬²»ÅжÏÊÇ·ñbase64
|
def CodeToGBK(inputText):
|
encodingList = ReadChConfig.GetEvalChConfig("EncodingTex")
|
|
if len(encodingList) != 2:
|
ErrLog("EncodingTex.txt Error len != 2")
|
return inputText
|
|
try:
|
return inputText.decode(GetCharacterEncoding()).encode(ShareDefine.Def_Game_Character_Encoding)
|
except:
|
return inputText
|
|
return inputText
|
|
|
# ÏòÔËά·¢ËÍÓʼþ£¬ÓÃÓÚÐèÒª½ô¼±´¦ÀíµÄÐÅÏ¢
|
# ´Ë´¦²»°üº¬·þÎñÆ÷±¨´íµÄ»ã±¨
|
def SendGameStateMail(msgInfo):
|
# ʹÓ÷½Ê½ ÏòOpenStateUrl ·¢ËÍTypeΪGameWarning£¬ÄÇô¾Í»áÊÕµ½Ò»·âÓÎÏ·ÄÚÈݾ¯¸æÓʼþ£¬ÐÅϢΪ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, msgInfo)
|
|
GetGameWorld().EventReport_EventReport("", "", "", "", 0, getUrl)
|
|