| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #---------------------------------------------------------------------  | 
| #  | 
| #---------------------------------------------------------------------  | 
| ##@package GameWorldProcess  | 
| # @todo: ¸±±¾ÊÀ½çÂ߼ѻ·´¦ÀíÆ÷  | 
| #  | 
| # @author eggxp  | 
| # @date 2010-4-20  | 
| # @version 3.1  | 
| #  | 
| # @note: ¸±±¾ÊÀ½çÂ߼ѻ·´¦ÀíÆ÷  | 
| #  | 
| # @change: "2010-08-23 11:30" panwei NPCÖÜÆÚµôÂäÐÂÔö´¦Àí¼ä¸ô  | 
| # @change: "2010-09-17 14:00" panwei ProcessCurrentChangeMapAskÐÂÔöÕϰµãÑéÖ¤  | 
| # @change: "2011-04-07 14:30" panwei PsycoÓÅ»¯  | 
| # @change: "2011-05-03 20:10" panwei ¸±±¾ÐÂÔöµ÷ÊÔÊä³ö  | 
| # @change: "2011-05-19 10:00" panwei ¸±±¾¿ªÆôºÍ¹Ø±ÕÂß¼ÐÞ¸Ä  | 
| # @change: "2011-06-21 11:00" Alee ÓÅ»¯¸±±¾¹Ø±Õ´úÂë  | 
| # @change: "2011-06-23 17:30" panwei ChangeMapAskÐÂÔö¸±±¾×´Ì¬ÑéÖ¤, »ØÊÕÖеĸ±±¾²»ÈýøÈë  | 
| # @change: "2011-07-04 16:30" panwei ¸±±¾¿ªÆôÂß¼ÐÞ¸Ä, ·À·¶Á¬Ðø¿ªÆô2´Î(2¸öÍæ¼Òͬʱ½øÈë¿ÉÖØÏÖ)  | 
| # @change: "2011-07-06 10:30" panwei ¸±±¾¿ªÆôÂß¼ÐÂÔöÇå³ýÍæ¼ÒÀ뿪ʱ¼äÂß¼, ²¢ÔÚ¸±±¾¹Ø±Õʱ, Ìí¼ÓÊä³ö  | 
| # @change: "2011-09-13 13:00" panwei ÌØÊ⸱±¾ChangeMapAsk²»ÑéÖ¤ÊÇ·ñ¸±±¾ÒÑÂú  | 
| # @change: "2012-12-20 20:40" Alee ¶¨Ê±Æ¥Å侺¼¼ºÍ»ã±¨Ö÷ÌâÅÅÐÐ  | 
| # @change: "2013-06-04 23:00" Alee Ìí¼Ó¼¶Áª¼ÆÊ±Æ÷ ¹¥»÷Âß¼  | 
| # @change: "2014-02-12 16:10" Alee ×ÔÉìËõ¸±±¾¸ù¾ÝÍæ¼Ò½øÈ뿪Æô£¬Ö÷¶¯µ÷ÓÃÒ»´Î£¬±ÜÃâ¼ä¸ôµ÷ÓÃʱ»úδ´¥·¢µ¼ÖÂÂß¼´íÂÒ  | 
| # @change: "2014-12-22 21:30" hxp µØÍ¼¶îÍâµôÂÊ´¦Àí  | 
| # @change: "2015-01-14 00:30" hxp Ôö¼Óʼþ»ã±¨³õʼ»¯  | 
| # @change: "2015-03-21 16:00" hxp ÌØÊâ·Ç×ÔÉìËõµØÍ¼Í˳ö¹Ø±Õ¸±±¾¼ì²â  | 
| # @change: "2015-03-31 01:10" ljd ·ÖÖÓ´¥·¢ºÍÕû°ëСʱ´¥·¢Èë¿Ú¡¢Îå·ÖÖÓ´¥·¢  | 
| # @change: "2015-07-28 11:10" ljd Ê±Ð§¹ó×å·ÖÖÓ´¥·¢  | 
| # @change: "2016-07-13 18:00" hxp ÔÚÏßÔùËÍѰ±¦Ãâ·Ñ´ÎÊý´¥·¢  | 
| # @change: "2016-07-27 20:00" Alee Ð޸Ĵò¿ªÎļþ³¬Ê±¹Ø±Õ  | 
| # @change: "2016-08-22 18:00" hxp Í¬²½ÐéÄâ·ÖÏßÈËÊý  | 
| # @change: "2016-09-02 23:00" hxp ´«ËÍÄ¿±êΪÕϰµãʱȡ¸½½üËæ»ú¿ÉÒÆ¶¯µã  | 
| #---------------------------------------------------------------------  | 
| import IPY_GameWorld  | 
| import GameWorld  | 
| import ChConfig  | 
| import PlayerControl  | 
| import FamilyRobBoss  | 
| import NPCCustomRefresh  | 
| import EventShell  | 
| import FBLogic  | 
| import FBCommon  | 
| import ShareDefine  | 
| import EventReport  | 
| import ItemCommon  | 
| import PyGameData  | 
| import PlayerTeam  | 
| import GameMap  | 
| import NPCRealmRefresh  | 
| #---------------------------------------------------------------------  | 
| ## ¸±±¾¿ªÆô  | 
| #  @param gameWorld IPY_GameWorld  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __OpenFB(gameWorld, tick):  | 
|     if gameWorld.GetOpenFBTick() != 0:  | 
|         GameWorld.ErrLog("FB Open! lineID = %s, openState = %s, OpenFBTick = %s"%(  | 
|                                                 gameWorld.GetLineID(), gameWorld.GetOpenState(), gameWorld.GetOpenFBTick()))  | 
|         return  | 
|       | 
|     #¸±±¾¿ªÆô  | 
|     GameWorld.Log("FB Open! lineID = %s, openState = %s"%(gameWorld.GetLineID(), gameWorld.GetOpenState()))  | 
|       | 
|     #---ÉèÖø±±¾×´Ì¬---  | 
|     gameWorld.SetOpenState(IPY_GameWorld.fbosOpen)  | 
|     gameWorld.SetOpenFBTick(tick)  | 
|     gameWorld.SetCloseFBTick(0)  | 
|     #³õʼ»¯¸±±¾  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     gameFB.SetFBStep(0)  | 
|     gameFB.SetFBStepTick(tick)  | 
|       | 
|     #µ÷Óø±±¾¿ªÆô´¥·¢Æ÷  | 
|     FBLogic.OnOpenFB(tick)  | 
|       | 
|     GameServer_DynamicLineMapStateChange(gameWorld, IPY_GameWorld.fbosOpen)  | 
|     return  | 
|   | 
| ## ¸±±¾¹Ø±Õ  | 
| #  @param gameWorld IPY_GameWorld  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __CloseFB(gameWorld, tick):  | 
|     #¹Ø±Õ¸±±¾  | 
|     FBLogic.OnCloseFB(tick)  | 
|       | 
|     gameWorld.SetOpenFBTick(0)  | 
|     gameWorld.SetCloseFBTick(0)  | 
|     gameWorld.SetFBFirstOpen(0)  | 
|       | 
|     gameFBMgr = gameWorld.GetGameFB()   | 
|     gameFBMgr.SetPlayerLogoffTick(0)  | 
|     gameFBMgr.SetIsSafeClose(0)  | 
|       | 
|     lineID = gameWorld.GetLineID()  | 
|     copyMapID = gameWorld.GetCopyMapID()  | 
|     GameWorld.Log("FB Close! lineID = %s, openState = %s"%(lineID, gameWorld.GetOpenState()))  | 
|       | 
|     gameWorld.SetOpenState(IPY_GameWorld.fbosClosed)  | 
|     gameMap = gameWorld.GetMap()  | 
|       | 
|     fbType = gameMap.GetMapFBType()  | 
|     if fbType == 0:  | 
|         return  | 
|       | 
|     if fbType == IPY_GameWorld.fbtSingle:  | 
|         ownerID = gameFBMgr.GetGameFBDictByKey(ChConfig.Def_FB_SingleFBPlayerID)  | 
|         if ownerID in PyGameData.g_fbHelpBattlePlayerDict:  | 
|             PyGameData.g_fbHelpBattlePlayerDict.pop(ownerID)  | 
|             GameWorld.DebugLog("Çå³ýµ¥È˸±±¾¾µÏñÖúÕ½ÐÅÏ¢: ownerID=%s" % ownerID)  | 
|     elif fbType == IPY_GameWorld.fbtTeam:  | 
|         teamID = gameWorld.GetPropertyID()  | 
|         if teamID in PyGameData.g_teamFBMemRelationDict:  | 
|             PyGameData.g_teamFBMemRelationDict.pop(teamID)  | 
|             GameWorld.DebugLog("Çå³ý×é¶Ó¸±±¾¶ÓÔ±¹ØÏµÐÅÏ¢: teamID=%s" % teamID)  | 
|               | 
|     #¸±±¾¹Ø±ÕʱͳһÇå¹Ö  | 
|     FBCommon.ClearFBNPC()  | 
|       | 
|     if lineID in PyGameData.g_fbRobotJobDict:  | 
|         PyGameData.g_fbRobotJobDict.pop(lineID)  | 
|           | 
|     mapID = FBCommon.GetRecordMapID(gameMap.GetMapID())  | 
|     #ÇåÀíÎïÆ·  | 
|     unPickItemDict = {}  | 
|     mapItem_List = []  | 
|     mapItemManager = GameWorld.GetMapItemManager()  | 
|     for index in xrange(mapItemManager.GetMapItemCount()):  | 
|         curMapItem = mapItemManager.GetMapItemByIndex(index)  | 
|         mapItem_List.append(curMapItem)  | 
|           | 
|     for mapItem in mapItem_List:  | 
|         if not mapItem or mapItem.IsEmpty():  | 
|             continue  | 
|           | 
|         if fbType == IPY_GameWorld.fbtSingle:  | 
|             ownerID = gameFBMgr.GetGameFBDictByKey(ChConfig.Def_FB_SingleFBPlayerID)  | 
|         elif mapItem.GetOwnerType() == ChConfig.Def_NPCHurtTypePlayer:  | 
|             ownerID = mapItem.GetOwnerID()  | 
|         else:  | 
|             ownerID = 0  | 
|               | 
|         curItem = mapItem.GetItem()  | 
|         if ownerID and curItem.GetType() != ChConfig.Def_ItemType_Money:  | 
|             mailItemList = unPickItemDict.get(ownerID, [])  | 
|             mailItemList.append(ItemCommon.GetMailItemDict(curItem))  | 
|             unPickItemDict[ownerID] = mailItemList  | 
|               | 
|         mapItem.Disappear()  | 
|           | 
|     #·¢ËÍδʰȡµÄÎïÆ·¸øÍæ¼Ò  | 
|     if mapID in ChConfig.Def_SendUnPickItemMailMapIDList and unPickItemDict:  | 
|         isCrossServer = GameWorld.IsCrossServer()  | 
|         playerServerGroupIDDict = PyGameData.g_crossPlayerServerGroupIDInfo.get(copyMapID, {})  | 
|         for ownerID, mailItemList in unPickItemDict.items():  | 
|             GameWorld.Log("·¢ËÍδʰȡµÄÎïÆ·¸øÍæ¼Ò: %s" % mailItemList, ownerID)  | 
|             if isCrossServer:  | 
|                 serverGroupID = playerServerGroupIDDict.get(ownerID, 0)  | 
|                 PlayerControl.SendCrossMail(serverGroupID, "ItemNoPickUp", [ownerID], mailItemList, [gameWorld.GetMapID()])  | 
|             else:  | 
|                 PlayerControl.SendMailByKey("ItemNoPickUp", [ownerID], mailItemList, [gameWorld.GetMapID()])  | 
|           | 
|     playerManager = gameWorld.GetMapCopyPlayerManager()  | 
|       | 
|     GameServer_DynamicLineMapStateChange(gameWorld, IPY_GameWorld.fbosClosed)  | 
|       | 
|     #µØÍ¼¹Ø±Õʱ£¬Íæ¼Ò»¹Ã»Í˳ö£¬ÉèÖÃÑÓ³Ù¹Ø±Õ  | 
|     if playerManager.GetPlayerCount() > 0:  | 
|         GameWorld.Log("¹Ø±Õ¸±±¾Ê±»¹ÓÐÍæ¼Ò! %s" % playerManager.GetPlayerCount())  | 
|         gameWorld.SetOpenState(IPY_GameWorld.fbosWaitForClose)  | 
|         return  | 
|       | 
|     #µØÍ¼Ã»ÓÐÍæ¼Ò, ¹Ø±Õ¸±±¾  | 
|     gameWorld.SetOpenState(IPY_GameWorld.fbosClosed)  | 
|     #¸ù¾ÝÊÇ·ñÊÕËõÐÍFB´¦Àí  | 
|     FreeOrClearFBByAutoSize(gameWorld)  | 
|       | 
|     gameWorld.SetPropertyID(0)  | 
|     PyGameData.g_crossPlayerServerGroupIDInfo.pop(copyMapID, None)  | 
|     return  | 
|   | 
| def GameServer_DynamicLineMapStateChange(gameWorld, state):  | 
|     mapID = FBCommon.GetRecordMapID(gameWorld.GetMapID())  | 
|     if mapID not in ChConfig.Def_CrossDynamicLineMap:  | 
|         return  | 
|       | 
|     mapID = gameWorld.GetMapID()  | 
|     realMapID, copyMapID = gameWorld.GetRealMapID(), gameWorld.GetCopyMapID()  | 
|     if state == IPY_GameWorld.fbosWaitForClose:  | 
|         crossFuncLineDataCache = FBLogic.OnGetCrossFuncLineDataCache()  | 
|         msgInfo = [mapID, realMapID, copyMapID, state, crossFuncLineDataCache]  | 
|     else:  | 
|         msgInfo = [mapID, realMapID, copyMapID, state]  | 
|           | 
|     msgInfo = str(msgInfo)  | 
|     GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "DynamicLineMapStateChange", msgInfo, len(msgInfo))  | 
|     GameWorld.Log("DynamicLineMapStateChange realMapID=%s, copyMapID=%s, PropertyID=%s, state=%s" % (realMapID, copyMapID, gameWorld.GetPropertyID(), state))  | 
|     return  | 
|   | 
| ##¸ù¾Ý±íÖеÄÊÕËõÀàÐÍÊÍ·Å»òÕßÇå¿Õ¸±±¾×´Ì¬  | 
| # @param gameWorld µØÍ¼ÊµÀý  | 
| # @return ÎÞÒâÒå  | 
| def FreeOrClearFBByAutoSize(gameWorld):  | 
|     if gameWorld.GetMap().GetAutoSize() == 0:  | 
|         #Çå¿Õ¸±±¾Ïà¹ØÖµ£¨Èç×ֵ䣬ʱÖÓ£¬ÅÅÐеȣ©  | 
|         gameFB = GameWorld.GetGameFB()  | 
|         gameFB.Clear()  | 
|     else:  | 
|         #OnCloseFB ÀïÓд¦ÀíÊͷŵÄÂß¼  | 
|         gameWorld.OnCloseFB()  | 
|           | 
|           | 
| ## Ìá³öÍæ¼Ò²¢¹Ø±Õ¸±±¾  | 
| #  @param gameWorld IPY_GameWorld  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __KickAllPlayerAndCloseFB(gameWorld, tick):  | 
|     if gameWorld.GetOpenState() != IPY_GameWorld.fbosOpen:  | 
|         #ÒѾ¹Ø±ÕÁË  | 
|         return  | 
|       | 
|     #ʱ¼äµ½ÁË, Ìß³ö  | 
|     playerManager = gameWorld.GetMapCopyPlayerManager()  | 
|       | 
|     for i in range(playerManager.GetPlayerCount()):  | 
|         curPlayer = playerManager.GetPlayerByIndex(i)  | 
|         #À뿪¸±±¾  | 
|         #FBLogic.DoExitFBLogic(curPlayer,tick)  | 
|         PlayerControl.PlayerLeaveFB(curPlayer)  | 
|       | 
|     GameWorld.GetGameFB().GameServer_FbInfoRefresh(0)   | 
|     GameWorld.Log("---------------%d"%playerManager.GetPlayerCount())  | 
|     __CloseFB(gameWorld, tick)  | 
|     return  | 
|   | 
| ## Ê±¼äµ½ÁËÌß³öÍæ¼Ò  | 
| #  @param gameWorld IPY_GameWorld  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __ProcessTimeKickPlayer(gameWorld, tick):  | 
|     #ʱ¼äµ½ÁËÌß³öÍæ¼Ò  | 
|     openTick = gameWorld.GetOpenFBTick()  | 
|     if openTick == 0:  | 
|         #GameWorld.Log('a' + str(openTick))  | 
|         return  | 
|       | 
|     existTime = GameWorld.GetMap().GetExistTime()  | 
|     if existTime == 0:  | 
|         #GameWorld.Log('b' + str(existTime))  | 
|         return  | 
|       | 
|     if tick - gameWorld.GetOpenFBTick() <= existTime:  | 
|         #GameWorld.Log('c' + str(tick - gameWorld.GetOpenFBTick()))  | 
|         return  | 
|       | 
|     #¸±±¾´¥·¢Æ÷µ÷Óà  | 
|     FBLogic.DoFBTimeOut(tick)  | 
|       | 
|     playerManager = gameWorld.GetMapCopyPlayerManager()  | 
|       | 
|     for i in range(0, playerManager.GetPlayerCount()):  | 
|         curPlayer = playerManager.GetPlayerByIndex(i)  | 
|           | 
|         playerExistTime = tick - curPlayer.GetLoginTick()  | 
|         if playerExistTime < existTime / 2:  | 
|             #Õâ¸öÍæ¼Ò´æÔÚʱ¼ä¹ý¶Ì, ²»ÄÜ´¥·¢¸±±¾½áÊøµÄʼþ  | 
|             continue  | 
|   | 
|         #¸±±¾Ê±¼äµ½ÁË, µ÷ÓÃʱ¼äµ½ÏìÓ¦  | 
|         EventShell.EventResponse_OnFBTimeOut(curPlayer)  | 
|       | 
|     #Êä³öµ÷ÊÔÐÅÏ¢  | 
|     GameWorld.Log('__ProcessTimeKickPlayer! LineID = %s, openState = %s'%(gameWorld.GetLineID(), gameWorld.GetOpenState()))  | 
|       | 
|     ##ÌßÈË  | 
|     __KickAllPlayerAndCloseFB(gameWorld, tick)  | 
|     GameServer_DynamicLineMapStateChange(gameWorld, IPY_GameWorld.fbosClosed)  | 
|     return  | 
|   | 
| ## ¸±±¾Ìß³öÍæ¼ÒÂß¼  | 
| #  @param gameWorld IPY_GameWorld  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __ProcessFBDelayKickPlayer(gameWorld, tick):  | 
|     #¸±±¾ÑÓ³ÙÌß³öÍæ¼ÒÂß¼  | 
|     closeFBTick = gameWorld.GetCloseFBTick()  | 
|       | 
|     if closeFBTick == 0:  | 
|         return  | 
|       | 
|     #¸±±¾ÒѾ¹Ø±Õ  | 
|     if gameWorld.GetOpenState() == IPY_GameWorld.fbosClosed:  | 
|         gameWorld.SetCloseFBTick(0)  | 
|         return  | 
|       | 
|     if tick - closeFBTick <= ChConfig.Def_FBKickPlayerTime:  | 
|         #ʱ¼äûÓе½  | 
|         return  | 
|       | 
|     #Êä³öµ÷ÊÔÐÅÏ¢  | 
|     GameWorld.Log('__ProcessFBDelayKickPlayer! LineID = %s, openState = %s'%(gameWorld.GetLineID(), gameWorld.GetOpenState()))  | 
|       | 
|     #ÌßÈË  | 
|     __KickAllPlayerAndCloseFB(gameWorld, tick)  | 
|     return  | 
|   | 
| ## Åжϸ±±¾ÊÇ·ñ¿ªÆô¸±±¾  | 
| #  @param gameWorld IPY_GameWorld  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __ProcessOpen(gameWorld, tick):  | 
|     if not gameWorld.GetFBFirstOpen():  | 
|         return  | 
|       | 
|     #µ÷ÓýӿڿªÆô¸±±¾  | 
|     __OpenFB(gameWorld, tick)  | 
|       | 
|     #¹Ø±Õ±ê־λ  | 
|     gameWorld.SetFBFirstOpen(0)  | 
|     return  | 
|   | 
|   | 
| ## ×ÔÉìËõ¸±±¾¸ù¾ÝÍæ¼Ò½øÈ뿪Æô£¬Ö÷¶¯µ÷ÓÃÒ»´Î£¬±ÜÃâ¼ä¸ôµ÷ÓÃʱ»úδ´¥·¢µ¼ÖÂÂß¼´íÂÒ  | 
| #  @param tick  | 
| #  @return None  | 
| def EnterOpenFB(tick):  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     if GameWorld.GetMap().GetAutoSize() == 0:  | 
|         return  | 
|       | 
|     # C++ÒѾÉèÖø±±¾´ò¿ª±êʶ£¬Õâ±ß²»Åж¨¸±±¾×´Ì¬  | 
|     __ProcessOpen(gameWorld, tick)  | 
|       | 
|       | 
| ## Åжϸ±±¾ÊÇ·ñ×Ô¶¯¹Ø±Õ  | 
| #  @param gameWorld IPY_GameWorld  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __ProcessClose(gameWorld, tick):  | 
|     #¸±±¾Î´³õʼ»¯  | 
|     if not gameWorld.GetInitOK() :  | 
|         return  | 
|       | 
|     playerManager = gameWorld.GetMapCopyPlayerManager()  | 
|       | 
|     #¸±±¾Öл¹ÓÐÈË  | 
|     if playerManager.GetPlayerCount() != 0:  | 
|         return  | 
|       | 
|     #ÌØÊ⸱±¾,²»Ö´ÐÐÕâ¸öÂß¼  | 
|     if not IsNoPlayerNeedCloseFB():  | 
|         return  | 
|       | 
|     gameFB = GameWorld.GetGameFB()  | 
|     fbIndex = gameWorld.GetCurGameWorldIndex()  | 
|     if fbIndex in PyGameData.g_lastExitFBType:  | 
|         '''ÀÏģʽ¸ù¾Ý GetPlayerLogoffTick()¡¢GetIsSafeClose()ÅжϵϰÔÚijЩÇé¿öÏ»áÓÐÒþ²Øbug  | 
|                             ÒòΪµ±¸±±¾ÖÐÍæ¼ÒͬʱÍ˳öʱ¿ÉÄܳöÏÖ  GameWorld.GetMapCopyPlayerManager().GetPlayerCount() != 1 µÄÇé¿ö  | 
|                             ËùÒÔÀÏÂß¼´æÔÚ¸±±¾ÎÞ·¨¹Ø±ÕµÄbug£¬ÕâÀïֻʹÓÃÐÂģʽ£¬ÀÏģʽÔݲ»×öÐ޸쬽ö×ö¼æÈݺ󱸴¦Àí  | 
|         '''  | 
|         exitFBType, exitTick = PyGameData.g_lastExitFBType[fbIndex]  | 
|         if exitFBType == 1:  | 
|             passTick = tick - exitTick  | 
|             if passTick < ChConfig.Def_EmptyFBKeepTime:  | 
|                 #GameWorld.DebugLog("×îºóÒ»¸öÍæ¼ÒÀëÏßÍ˳öµÄ£¬¸±±¾±£»¤ÖУ¡tick=%s,exitTick=%s,passTick=%s"   | 
|                 #                   % (tick, exitTick, passTick), fbIndex)  | 
|                 return  | 
|             #GameWorld.DebugLog("×îºóÒ»¸öÍæ¼ÒÀëÏßÍ˳öµÄ£¬¸±±¾±£»¤³¬Ê±£¬¹Ø±Õ¸±±¾£¡tick=%s,exitTick=%s,passTick=%s"   | 
|             #                   % (tick, exitTick, passTick), fbIndex)  | 
|         #else:  | 
|         #    GameWorld.DebugLog("×îºóÒ»¸öÍæ¼ÒÖ÷¶¯Í˳öµÄ£¬Ö±½Ó¹Ø±Õ¸±±¾£¡", fbIndex)  | 
|         PyGameData.g_lastExitFBType.pop(fbIndex)  | 
|         #GameWorld.DebugLog("PyGameData.g_lastExitFBType=%s" % PyGameData.g_lastExitFBType, fbIndex)  | 
|     else:  | 
|         logOffTick = gameFB.GetPlayerLogoffTick()  | 
|   | 
|         if logOffTick == 0:  | 
|             return  | 
|       | 
|         if (not gameFB.GetIsSafeClose()) and tick - logOffTick < ChConfig.Def_EmptyFBKeepTime:  | 
|             #GameWorld.Log(str(tick - logOffTick))  | 
|             #²»Êǰ²È«¶ÏÏßµÄÇé¿öÏÂ, ·µ»Ø  | 
|             return  | 
|   | 
|     #Êä³öµ÷ÊÔÐÅÏ¢  | 
|     GameWorld.Log('__ProcessClose! LineID = %s, openState = %s, isSafeClose = %s'%(  | 
|                                             gameWorld.GetLineID(), gameWorld.GetOpenState(), gameFB.GetIsSafeClose()))  | 
|       | 
|     #ÌßÈË  | 
|     __KickAllPlayerAndCloseFB(gameWorld, tick)  | 
|     return  | 
|   | 
| ## Ñ»·Ë¢ÐµØÍ¼·þÎñÆ÷״̬  | 
| #  @param gameWorld IPY_GameWorld  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __ProcessRefreshMapServerState(gameWorld, tick):  | 
|     if not PyGameData.g_needRefreshMapServerState:  | 
|         return  | 
|       | 
|     #¹Ì¶¨Ò»·ÖÖÓË¢ÐÂÒ»´Î  | 
|     if tick - gameWorld.GetSyncMapServerStateTick() < 10*1000:  | 
|         return  | 
|       | 
|     #Ö»ÓÐÆÕͨµØÍ¼²ÅË¢ÐÂÏß·  | 
|     gameMap = GameWorld.GetMap()  | 
|       | 
|     if gameMap.GetMapFBType() != IPY_GameWorld.fbtNull:  | 
|         return  | 
|       | 
|     gameWorld.SetSyncMapServerStateTick(tick)  | 
|     gameWorld.GameServer_MapServerState()  | 
|     PyGameData.g_needRefreshMapServerState = False  | 
|     return  | 
|   | 
| ## »Ø±¨µ±Ç°µØÍ¼·þÎñÆ÷ÈËÊý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __ProcessMapServerAcPlayer(tick):  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     lastTick = gameWorld.GetTickByType(ChConfig.TYPE_Map_Tick_MapAcPlayer)  | 
|       | 
|     if lastTick == -1:  | 
|         #·þÎñÆ÷δ³õʼ»¯  | 
|         return  | 
|       | 
|     if tick - lastTick < ChConfig.TYPE_Map_Tick_Time[ChConfig.TYPE_Map_Tick_MapAcPlayer]:  | 
|         return  | 
|       | 
|     #ÉèÖõ±Ç°Ê±¼ä  | 
|     gameWorld.SetTickByType(ChConfig.TYPE_Map_Tick_MapAcPlayer , tick)  | 
|     return  | 
|   | 
|   | 
| ## ´¦Àíµ±Ç°Çл»µØÍ¼ÇëÇ󣨵¥¸ö£©  | 
| #  @param gameWorld IPY_GameWorld  | 
| #  @param askStruct ÇëÇóÐÅÏ¢(IPY_BMChangeMapAsk)  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return IPY_GameWorld.cmeAccept  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __ProcessCurrentChangeMapAsk(gameWorld, askStruct, tick):  | 
|     gameMap = GameWorld.GetMap()  | 
|   | 
|     #¼ì²âÄ¿±êÊÇ·ñΪÕϰµã  | 
|     if not gameMap.CanMove(askStruct.GetPosX(), askStruct.GetPosY()):  | 
|         nearPosX, nearPosY = GameMap.GetNearbyPosByDis(askStruct.GetPosX(), askStruct.GetPosY(), ChConfig.Def_RebornPos_Area_Range)  | 
|         if nearPosX == 0 and nearPosY == 0:  | 
|             GameWorld.ErrLog('´«ËÍÖÁÄ¿±êµãΪÕϰµã, ´«ËÍʧ°Ü, mapid = %s, posX = %s, posY = %s'%(  | 
|                                         askStruct.GetMapID(), askStruct.GetPosX(), askStruct.GetPosY()))  | 
|             return IPY_GameWorld.cmeCustom, '04BBF813-7A30-47A8-927DE1ACCC4F378E'  | 
|       | 
|     #---·Çϵͳ·ÖÅäµÄ·¿¼äÑéÖ¤---  | 
|     if askStruct.GetMapID() not in ChConfig.Def_FB_SystemAssignMapIDList:  | 
|       | 
|         if not gameWorld.GetPlayerManager().IsPlayerCanLogin():  | 
|             #ÈËÊýÒÑÂú  | 
|             return IPY_GameWorld.cmePlayerFull  | 
|   | 
|         if gameMap.GetAutoSize() and gameWorld.IsMapCopyFull(gameWorld.GetBMChangeMapAskCount()):  | 
|             #ÈËÊýÒÑÂú  | 
|             return IPY_GameWorld.cmePlayerFull  | 
|   | 
|     #¼ì²é¸±±¾×´Ì¬ÊÇ·ñ¿ÉÒԵǼ  | 
|     checkRet = FBCommon.CheckFBStateCanEnter(askStruct)  | 
|     if type(checkRet) not in [tuple, list]:  | 
|         checkRet = (checkRet, "FB_andyshao_861048")  | 
|     canEnter, notifyMark = checkRet  | 
|     if not canEnter:  | 
|         #¸±±¾¹Ø±ÕÖÐ, ÇëÉÔºó  | 
|         return IPY_GameWorld.cmeCustom, notifyMark  | 
|       | 
|     changeMapAskResult = FBLogic.OnChangeMapAsk(askStruct, tick)  | 
|   | 
|     if changeMapAskResult == None:  | 
|         #ÔÊÐí½øÈë  | 
|         return IPY_GameWorld.cmeAccept  | 
|   | 
|     #¸±±¾´«Ëͽá¹û  | 
|     return changeMapAskResult  | 
|   | 
| ## ´¦ÀíÇл»µØÍ¼ÇëÇó  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __ProcessChangeMapAsk(tick):  | 
|     #´¦ÀíÇл»µØÍ¼ÇëÇó(changemapAsk)  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     for i in range(gameWorld.GetBMChangeMapAskCount()):  | 
|         ask = gameWorld.GetBMChangeMapAskAt(i)  | 
|         result = __ProcessCurrentChangeMapAsk(gameWorld, ask, tick)  | 
|         if type(result) == int:  | 
|             result = (result, '')  | 
|           | 
|         gameWorld.RouteServer_ChangeMapAnswer(ask.GetPlayerID(), result[0] , result[1])  | 
|           | 
|     gameWorld.ClearBMChangeMapAsk()  | 
|     return  | 
|   | 
| ## ¸±±¾×ÜÈë¿Ú  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def OnGameWorldProcess(tick):  | 
|     GameWorld.GetPsycoFunc(__Func_OnGameWorldProcess)(tick)  | 
|     return  | 
|       | 
| ## ¸±±¾×ÜÈë¿Ú  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __Func_OnGameWorldProcess(tick):  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     if not gameWorld.GetInitOK() :  | 
|         return  | 
|       | 
|     __ProcessOpen(gameWorld, tick)  | 
|       | 
|     __ProcessTimeKickPlayer(gameWorld, tick) # ´¦Àí¸±±¾Éú´æÖÜÆÚÇ¿¹Ø¸±±¾  | 
|       | 
|     __ProcessFBDelayKickPlayer(gameWorld, tick) # ¹Ø±Õ¸±±¾ÑÓ³ÙÌß³öÍæ¼Ò  | 
|       | 
|     __ProcessClose(gameWorld, tick) # ×ÔÉìËõ¸±±¾¹Ø±ÕÂß¼  | 
|       | 
|     __ProcessMapServerAcPlayer(tick)  | 
|       | 
|     __ProcessChangeMapAsk(tick)  | 
|       | 
|     #´¦Àí¸±±¾Âß¼  | 
|     FBLogic.OnProcess(tick)  | 
|       | 
|     #֪ͨMapServer, Ë¢ÐÂ×Ô¼ºµÄ״̬  | 
|     __ProcessRefreshMapServerState(gameWorld, tick)  | 
|       | 
|     #֪ͨRouteServer ÏûÏ¢  | 
|     __ProcessRouteServer(gameWorld, tick)  | 
|       | 
|     #ÿ·ÖÖÓ´¥·¢  | 
|     __RefreshOnMinute(tick)  | 
|     #Îå·ÖÖÓ´¥·¢  | 
|     __RefreshOnFiveMinute(tick)  | 
|     #¶¨Ê±¼ì²â¹Ø±Õ³¬Ê±Îļþ  | 
|     EventReport.OnTimeCloseScribeTxt()  | 
|       | 
|     #ÏÉÃ˹éÊôboss¶¨Ê±´¦Àí  | 
|     FamilyRobBoss.OnFamilyOwnerBossProcess(tick)  | 
|       | 
|     #µØÍ¼×Ô¶¨ÒåËæ»úË¢¹Ö  | 
|     NPCCustomRefresh.ProcessMapRandomRefreshNPC(gameWorld, tick)  | 
|     NPCRealmRefresh.ProcessRealmNPCRefresh(gameWorld, tick)  | 
|     return  | 
|   | 
| ## Í¨ÖªRouteServer ÏûÏ¢  | 
| #  @param gameWorld IPY_GameWorld  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __ProcessRouteServer(gameWorld, tick):  | 
|       | 
|     lastTick = gameWorld.GetTickByType(ChConfig.TYPE_Map_Tick_SendMsg_RouteServer)  | 
|       | 
|     if lastTick == -1:  | 
|         #·þÎñÆ÷δ³õʼ»¯  | 
|         return  | 
|       | 
|     if tick - lastTick < ChConfig.TYPE_Map_Tick_Time[ChConfig.TYPE_Map_Tick_SendMsg_RouteServer]:  | 
|         return  | 
|       | 
|     #ÉèÖõ±Ç°Ê±¼ä  | 
|     gameWorld.SetTickByType(ChConfig.TYPE_Map_Tick_SendMsg_RouteServer , tick)  | 
|       | 
|     GameWorld.GetGameWorld().SendHeartBeat()  | 
|     return  | 
|   | 
| ## ³õʼ»¯gameWorld  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def InitGameWorld(tick):  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     ItemCommon.InitPyItem()  | 
|     EventShell.DoReloadRefresh()  | 
|     #´¦Àí¸±±¾Âß¼  | 
|     FBLogic.OnInit(tick)  | 
|     #³õʼ»¯µØÍ¼Ê±ÖÓ  | 
|     gameWorld.SetTickTypeCount(ChConfig.TYPE_Map_Tick_Count)  | 
|     #³õʼ»¯Ê¼þ±¨¸æ  | 
|     EventReport.InitDllAppID()  | 
|     #ÏòGameServer×¢²áÆÕͨµØÍ¼Æô¶¯³É¹¦ÐÅÏ¢  | 
|     GameServer_CommMapServerInitOK(gameWorld)  | 
|     #³õʼ»¯ÓÎÏ·ÊÀ½çµÄ×îºóÒ»²½  | 
|     gameWorld.SetInitOK(True)  | 
|     #֪ͨBalanceServer×Ô¼º³õʼ»¯ºÃÁË  | 
|     gameWorld.BalanceServer_MapServerInitOK()  | 
|     return  | 
|   | 
| def GameServer_CommMapServerInitOK(gameWorld):  | 
|     '''  | 
|     Í¨ÖªGameServerµØÍ¼Æô¶¯Íê±Ï  | 
|     GetMapID=10010,GetLineID=0,GetRealMapID=10010,GetCopyMapID=0,GetLineNO=-1  | 
|     GetMapID=10010,GetLineID=1,GetRealMapID=10010,GetCopyMapID=1,GetLineNO=-1  | 
|     GetMapID=10010,GetLineID=2,GetRealMapID=10010,GetCopyMapID=2,GetLineNO=-1  | 
|     GetMapID=10010,GetLineID=3,GetRealMapID=10010,GetCopyMapID=3,GetLineNO=-1  | 
|     GetMapID=10010,GetLineID=4,GetRealMapID=10010,GetCopyMapID=4,GetLineNO=-1  | 
|     GetMapID=10010,GetLineID=5,GetRealMapID=10011,GetCopyMapID=0,GetLineNO=-1  | 
|     GetMapID=10010,GetLineID=6,GetRealMapID=10011,GetCopyMapID=1,GetLineNO=-1  | 
|     GetMapID=10010,GetLineID=7,GetRealMapID=10011,GetCopyMapID=2,GetLineNO=-1  | 
|     GameWorld.DebugLog("GetMapID=%s,GetLineID=%s,GetRealMapID=%s,GetCopyMapID=%s,GetLineNO=%s"   | 
|                        % (gameWorld.GetMapID(), gameWorld.GetLineID(), gameWorld.GetRealMapID(), gameWorld.GetCopyMapID(), gameWorld.GetLineNO()))  | 
|     '''  | 
|     # ÆÕͨµØÍ¼Í¨ÖªGameServerÆô¶¯OK  | 
|     if GameWorld.GetMap().GetMapFBType() == IPY_GameWorld.fbtNull:  | 
|         msgInfo = str([gameWorld.GetMapID(), gameWorld.GetLineID(), gameWorld.GetRealMapID(), gameWorld.GetCopyMapID()])  | 
|         GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "CommMapServerInitOK", msgInfo, len(msgInfo))  | 
|           | 
|     dataMapID = FBCommon.GetRecordMapID(gameWorld.GetMapID())  | 
|     if dataMapID in ChConfig.Def_CrossDynamicLineMap and gameWorld.GetCopyMapID() == gameWorld.GetGameWorldCount() - 1:  | 
|         msgInfo = str([gameWorld.GetRealMapID(), gameWorld.GetGameWorldCount()])  | 
|         GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "DynamicLineMapInitOK", msgInfo, len(msgInfo))  | 
|           | 
|     return  | 
|   | 
|   | 
| ## ¹Ø±Õ¸±±¾  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def CloseFB(tick):  | 
|     GameWorld.GetGameWorld().SetCloseFBTick(tick)  | 
|       | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     GameServer_DynamicLineMapStateChange(gameWorld, IPY_GameWorld.fbosWaitForClose)  | 
|     return  | 
|   | 
| ## Íæ¼ÒÀ뿪µØÍ¼Ê±£¬³¢ÊԹرո±±¾  | 
| #  @param ÎÞ  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def OnPlayerLeaveMapCloseFB():  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|       | 
|     #¹Ø±Õ¸±±¾  | 
|     gameMap = gameWorld.GetMap()  | 
|     if gameMap.GetMapFBType() == 0:  | 
|         return  | 
|       | 
|     if not IsNoPlayerNeedCloseFB():  | 
|         return  | 
|       | 
|     playerManager = gameWorld.GetMapCopyPlayerManager()  | 
|     if playerManager.GetPlayerCount() == 1:  | 
|         #Èç¹ûÊÇ·þÎñÆ÷ÖÐ×îºóÒ»¸öÈËÀ뿪, Ôò¹Øµô¸±±¾  | 
|         __CloseFB(GameWorld.GetGameWorld(), GameWorld.GetGameWorld().GetTick())      | 
|   | 
|   | 
| def IsNoPlayerNeedCloseFB():  | 
|     ## ¸±±¾ÖÐÎÞÍæ¼ÒÊÇ·ñÐèÒª×Ô¶¯¹Ø±ÕµÄ¸±±¾  | 
|     if GameWorld.GetMap().GetAutoSize():  | 
|         if GameWorld.GetMap().GetMapID() in ChConfig.Def_NoPlayerNotCloseAutoSizeMap:  | 
|             return False  | 
|         return True  | 
|     else:  | 
|         if GameWorld.GetMap().GetMapID() in ChConfig.Def_NoPlayerCloseNotAutoSizeMap:  | 
|             return True  | 
|         return False  | 
|       | 
| #//08 06 ¸ù¾Ý¹ú¼Òͳ¼ÆµÄÍæ¼ÒÊýÄ¿#tagMPlayerCountByCountry  | 
| #tagMPlayerCountByCountry       *   GettagMPlayerCountByCountry();  | 
| #  | 
| #class   IPY_MPlayerCountByCountry  | 
| #{  | 
| #public:  | 
| #  | 
| #    int      GetCountry1Count();  | 
| #  | 
| #    int      GetCountry2Count();  | 
| #  | 
| #    int      GetCountry3Count();  | 
| #  | 
| #    int      GetCountryOtherCount();  | 
| #};  | 
| ## GameSever»ñµÃ¹ú¼®ÈËÊý   | 
| #  @param index  | 
| #  @param tick  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.    | 
| def GameSever_PlayerCountByCountry(index, tick):  | 
|     pack = IPY_GameWorld.IPY_MPlayerCountByCountry()  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     #GameSever»ñµÃ¹ú¼®ÈËÊý£¬ÉèÖãº1¡¢ÇØ 2¡¢Îº 3¡¢³þ 4¡¢ÎÞ¹ú¼®  | 
|     gameWorld.SetPlayerByCountryCount(1, pack.GetCountry1Count())  | 
|     gameWorld.SetPlayerByCountryCount(2, pack.GetCountry2Count())  | 
|     gameWorld.SetPlayerByCountryCount(3, pack.GetCountry3Count())  | 
|     gameWorld.SetPlayerByCountryCount(0, pack.GetCountryOtherCount())  | 
|       | 
|     return  | 
|   | 
|   | 
| #===========================================================================  | 
| # //¼¶Áª¼ÆÊ±Æ÷  | 
| # //×¢²á(Ãû³Æ(ͬÃû»áɾ³ýÖØ½¨),¼ä¸ô,Py»Øµ÷Ãû,µ÷ÓôÎÊý£¨Ä¬ÈÏΪ-1ÎÞÏÞÑ»·£¬Îª0ʱ»á±»×Ô¶¯É¾³ý£©,  | 
| #            ÊÇ·ñÖ´Ðв¹×ãµ÷ÓôÎÊýµÄÐÞÕý¹æÔò£¨Ä¬Èϲ»Ö´ÐУ©)  | 
| # void                    RegLvTimer( char * Name, int interval, char* szPyModuleName,  | 
| #                                    char* szPyFuncName, int nTimerKey,  | 
| #                                    int livecycle = -1, bool isNeedTrigger = false);  | 
| #===========================================================================  | 
| ##×¢²á¼¶Áª¼ÆÊ±Æ÷  | 
| # @param tick  | 
| # @return None  | 
| def RegLvTimer(tick):  | 
|     GameWorld.Log("×¢²á¼¶Áª¼ÆÊ±Æ÷")  | 
|     GameWorld.GetGameWorld().RegLvTimer("ProcessFight", 130,   | 
|                                         "PlayerState", "PlayerProcessFight", 1)   | 
|       | 
|     #Á¢¼´Æô¶¯  | 
|     GameWorld.GetGameWorld().StartLvTimer("ProcessFight", tick)  | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
|   | 
| ## Îå·ÖÖÓˢР | 
| # @param tick  | 
| # @return None  | 
| def __RefreshOnFiveMinute(tick):  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     lastTick = gameWorld.GetTickByType(ChConfig.TYPE_Map_Tick_ProcessFiveMinute)  | 
|     tickInterval = ChConfig.TYPE_Map_Tick_Time[ChConfig.TYPE_Map_Tick_ProcessFiveMinute]  | 
|     if tick - lastTick < tickInterval:  | 
|         return  | 
|     gameWorld.SetTickByType(ChConfig.TYPE_Map_Tick_ProcessFiveMinute, tick)  | 
|       | 
| #    playerManager = GameWorld.GetMapCopyPlayerManager()  | 
| #    for index in xrange(playerManager.GetPlayerCount()):  | 
| #        curPlayer = playerManager.GetPlayerByIndex(index)  | 
| #        if not curPlayer:  | 
| #            continue  | 
|           | 
|     return  | 
|   | 
| ## °´·ÖÖÓˢР | 
| # @param tick  | 
| # @return None  | 
| def __RefreshOnMinute(tick):  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     lastTick = gameWorld.GetTickByType(ChConfig.TYPE_Map_Tick_ProcessMinute)  | 
|     tickInterval = ChConfig.TYPE_Map_Tick_Time[ChConfig.TYPE_Map_Tick_ProcessMinute]  | 
|     if tick - lastTick < tickInterval:  | 
|         return  | 
|     gameWorld.SetTickByType(ChConfig.TYPE_Map_Tick_ProcessMinute, tick)  | 
|       | 
|     curTime = GameWorld.GetCurrentTime()  | 
|       | 
|     __OnMapMinute(curTime, tick)  | 
|       | 
|     playerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     for index in xrange(playerManager.GetPlayerCount()):  | 
|         curPlayer = playerManager.GetPlayerByIndex(index)  | 
|         if not curPlayer:  | 
|             continue  | 
|           | 
|         __ProcessHalfHour(curPlayer, curTime, tick)  | 
|     return  | 
|   | 
| def __OnMapMinute(curTime, tick):  | 
|     ## µØÍ¼²ã¼¶Ã¿·ÖÖÓ´¦Àí, Ã¿·ÖÖÓ×î¶àÖ»»á´¦ÀíÒ»´Î, ÎÞÊÓÐéÄâ·ÖÏß  | 
|     curMinute = curTime.minute  | 
|     if curMinute == PyGameData.g_mapLastProcess_Minute:  | 
|         return  | 
|     PyGameData.g_mapLastProcess_Minute = curMinute  | 
|     PlayerTeam.OnCheckTeamPlayerDisconnectTimeout(tick)  | 
|     return  | 
|   | 
|   | 
| ## Õû°ëСʱ´¥·¢ <00ºÍ30·ÖÖÓʱ´¥·¢>  | 
| # @param curPlayer  | 
| # @param curTime µ±Ç°Ê±¼ä¶ÔÏó  | 
| # @param tick  | 
| # @return None  | 
| def __ProcessHalfHour(curPlayer, curTime, tick):  | 
|     if curTime.minute not in [0, 30]:  | 
|         return  | 
|       | 
|     EventShell.EventResponse_OnHalfHour(curPlayer)  | 
|     return  |