From 6a9883b425e53e714b9a930ec70b7544999611a6 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期四, 08 五月 2025 12:01:45 +0800
Subject: [PATCH] 16 卡牌服务端(db数据备档、加载;仙盟基础转到MapServer;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/__init__.py                                       |    0 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py                          |  248 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py                               | 2252 ++++++++-------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyZhenbaoge.py       |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py                                       |  617 ++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                                   |  832 +++++
 PySysDB/生成IpyGameDataPY/config.ini                                                                                       |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DirtyList.py                                         |   75 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py                                        |    5 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py                            |  643 ++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Func_11.py                            |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Zhenbaoge.py                             |    4 
 PySysDB/生成IpyGameDataPY/IpyGameDataPYTemp.py                                                                             |   10 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/__init__.py                            |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                                     |  166 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py                                   |    9 
 PySysDB/PySysDBPY.h                                                                                                      |   51 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBComm.py                                         |   74 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyZhenbaoge.py                      |  347 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py                   |  327 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventShell.py                                  |    6 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldProcess.py                   |    6 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py                              |   11 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCacheTube.py                        |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_ForbiddenFamilyAction.py |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                                       |    8 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBDataMgr.py                                      |  197 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NetPackCommon.py                                     |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyEmblem.py                         |  185 +
 /dev/null                                                                                                                |  665 ----
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini                                               |   66 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyNameRefresh.py     |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py                                         |   37 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/ServerScript.ini                                            |   14 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py                         |   12 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py                                       | 1238 +++++++++
 PySysDB/生成IpyGameDataPY/IpyGameDataPYCreater.py                                                                          |   12 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                                          |   16 
 38 files changed, 6,280 insertions(+), 1,879 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index a81dcd4..c2255da 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -1,3 +1,17 @@
+//屏蔽词
+struct	DirtyList
+{
+	WORD		ID;
+	char		Word;	//屏蔽词
+};
+
+//玩家名屏蔽词
+struct	DirtyName
+{
+	WORD		ID;
+	char		Word;	//屏蔽词
+};
+
 //称号表 #tagDienstgrad
 
 struct	tagDienstgrad
@@ -3122,6 +3136,43 @@
 	list		AwardItemList;	//奖励物品列表[[物品ID,个数,是否拍品], ...]
 };
 
+//仙盟等级表
+struct	Family
+{
+	BYTE		_FamilyLV;	//仙盟等级
+	BYTE		MemberMax;	//成员数上限
+	BYTE		DeputyLeaderMax;	//副盟主数上限
+	BYTE		EliteMax;	//精英数上限
+	DWORD		NeedExp;	//升级所需经验
+	DWORD		ZhenbaogeWeights;	//珍宝阁总权重
+};
+
+//仙盟徽章表
+struct FamilyEmblem
+{
+	BYTE		_EmblemID;	//徽章ID
+	BYTE		UnlockFamilyLV;	//解锁仙盟等级,为0时代表其他方式解锁
+	DWORD		ExpireMinutes;	//有效时长,分钟
+	DWORD		CustomFamilyID;	//定制仙盟ID
+};
+
+//仙盟珍宝阁砍价表
+struct FamilyZhenbaogeCut
+{
+	BYTE		_CutNum;	//砍价人次
+	DWORD		CutWeight;	//砍价权重
+	float		MinRatio;	//保底比值
+	float		RandRatio;	//随机比值
+};
+
+//仙盟珍宝阁物品表
+struct FamilyZhenbaogeItem
+{
+	BYTE		_ItemGroupNum;	//物品组编号
+	DWORD		ItemWeight;	//随机权重
+	list		ItemList;	//物品列表[[物品ID,个数,是否拍品], ...]
+};
+
 //仙盟阵法表
 
 struct tagFamilyZhenfa
diff --git "a/PySysDB/\347\224\237\346\210\220IpyGameDataPY/IpyGameDataPYCreater.py" "b/PySysDB/\347\224\237\346\210\220IpyGameDataPY/IpyGameDataPYCreater.py"
index 673f776..567e787 100644
--- "a/PySysDB/\347\224\237\346\210\220IpyGameDataPY/IpyGameDataPYCreater.py"
+++ "b/PySysDB/\347\224\237\346\210\220IpyGameDataPY/IpyGameDataPYCreater.py"
@@ -94,12 +94,14 @@
                 continue
             
             if "struct" in line:
-                tagIndex = line.index("tag")
+                line = line.strip()
                 if "{" in line:
-                    tableName = line[tagIndex + 3:line.index("{")]
+                    tableName = line[6:line.index("{")]
                 else:
-                    tableName = line[tagIndex + 3:]
-                tableName = tableName.replace(" ", "") # 表名英文名
+                    tableName = line[6:]
+                tableName = tableName.replace("\t", "").replace(" ", "") # 表名英文名
+                if tableName.startswith("tag"):
+                    tableName = tableName[3:]
                 continue
             
             noteInfo = " #" # 字段注释说明
@@ -115,7 +117,7 @@
             if not fieldType:
                 if "struct" not in line and "{" not in line and "}" not in line:
                     print "### 类型定义错误表 ###"
-                    print "struct tag%s" % tableName
+                    print "struct %s" % tableName
                     print line
                     raise
                 continue
diff --git "a/PySysDB/\347\224\237\346\210\220IpyGameDataPY/IpyGameDataPYTemp.py" "b/PySysDB/\347\224\237\346\210\220IpyGameDataPY/IpyGameDataPYTemp.py"
index 0a0bb50..185d462 100644
--- "a/PySysDB/\347\224\237\346\210\220IpyGameDataPY/IpyGameDataPYTemp.py"
+++ "b/PySysDB/\347\224\237\346\210\220IpyGameDataPY/IpyGameDataPYTemp.py"
@@ -11,6 +11,8 @@
 #
 # 详细描述: 读取PY表
 #
+# @note: 本脚本由 \PySysDB\生成IpyGameDataPY 生成
+#
 #-------------------------------------------------------------------------------
 #"""Version = 2018-05-10 12:00"""
 #-------------------------------------------------------------------------------
@@ -106,10 +108,12 @@
     
     def __LoadFileData(self, tableName, onlyCheck=False):
         # @param onlyCheck: 是否仅检查格式,一般启动时用
-        curPath = "<%LoadStructPath%>" + "\\PySysDB\\tag" + tableName + ".txt"
+        curPath = "<%LoadStructPath%>" + "\\PySysDB\\" + tableName + ".txt"
         if not os.path.isfile(curPath):
-            ErrLog("can not find file = %s,%s" % (tableName, curPath))
-            raise Exception("can not find file = %s,%s" % (tableName, curPath))
+            curPath = "<%LoadStructPath%>" + "\\PySysDB\\tag" + tableName + ".txt"
+            if not os.path.isfile(curPath):
+                ErrLog("can not find file = %s,%s" % (tableName, curPath))
+                raise Exception("can not find file = %s,%s" % (tableName, curPath))
         
         if not onlyCheck:
             if not hasattr(self, "ipy%sLen" % tableName):
diff --git "a/PySysDB/\347\224\237\346\210\220IpyGameDataPY/config.ini" "b/PySysDB/\347\224\237\346\210\220IpyGameDataPY/config.ini"
index 3ea7d1d..e761818 100644
--- "a/PySysDB/\347\224\237\346\210\220IpyGameDataPY/config.ini"
+++ "b/PySysDB/\347\224\237\346\210\220IpyGameDataPY/config.ini"
@@ -1,5 +1,5 @@
 [config]
 
 ; 项目根路径
-CodeProjectPath1 = E:\SnxxServerCode\ServerPython
-CodeProjectPath2 = E:\Git\SnxxServerCode\ServerPython
+CodeProjectPath1 = D:\SG_ServerCode\ServerPython
+;CodeProjectPath2 = D:\SG_ServerCode\ServerPython
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index f7a998a..e8d28a9 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -193,27 +193,27 @@
 Writer = alee
 Releaser = alee
 RegType = 0
-RegisterPackCount = 9
+RegisterPackCount = 14
 
 PacketCMD_1=0xA6
 PacketSubCMD_1=0x01
-PacketCallFunc_1=RequestAddFamilyByID
+PacketCallFunc_1=OnRequestJoinFamilyByPlayer
 
 PacketCMD_2=0xA6
 PacketSubCMD_2=0x02
-PacketCallFunc_2=RequestAddFamily
+PacketCallFunc_2=OnRequesJoinFamily
 
-PacketCMD_3=
-PacketSubCMD_3=
-PacketCallFunc_3=
+PacketCMD_3=0xA6
+PacketSubCMD_3=0x04
+PacketCallFunc_3=OnCreateFamily
 
 PacketCMD_4=0xA6
 PacketSubCMD_4=0x11
 PacketCallFunc_4=UpdateFamilyName
 
-PacketCMD_5=0xA6
-PacketSubCMD_5=0x06
-PacketCallFunc_5=OnFamilyActivityExchange
+PacketCMD_5=
+PacketSubCMD_5=
+PacketCallFunc_5=
 
 PacketCMD_6=0xA6
 PacketSubCMD_6=0x12
@@ -224,12 +224,52 @@
 PacketCallFunc_7=OnFamilyAffairOP
 
 PacketCMD_8=0xA6
-PacketSubCMD_8=0x15
-PacketCallFunc_8=OnChuangongOP
+PacketSubCMD_8=0x20
+PacketCallFunc_8=OnViewFamilyPage
 
 PacketCMD_9=0xA6
-PacketSubCMD_9=0x16
-PacketCallFunc_9=OnZhenbaogeOP
+PacketSubCMD_9=0x21
+PacketCallFunc_9=OnJoinFamilyReply
+
+PacketCMD_10=0xA6
+PacketSubCMD_10=0x22
+PacketCallFunc_10=OnChangeFamilyJoin
+
+PacketCMD_11=0xA6
+PacketSubCMD_11=0x23
+PacketCallFunc_11=OnChangeFamilyBroadcast
+
+PacketCMD_12=0xA6
+PacketSubCMD_12=0x24
+PacketCallFunc_12=OnChangeFamilyEmblem
+
+PacketCMD_13=0xA6
+PacketSubCMD_13=0x25
+PacketCallFunc_13=OnChangeFamilyMemLV
+
+PacketCMD_14=0xA6
+PacketSubCMD_14=0x26
+PacketCallFunc_14=OnGetFamilyInfo
+
+PacketCMD_15=0xA6
+PacketSubCMD_15=0x03
+PacketCallFunc_15=OnLeaveFamily
+
+PacketCMD_16=0xA6
+PacketSubCMD_16=0x05
+PacketCallFunc_16=OnDeleteFamilyMember
+
+;珍宝阁
+[PlayerFamilyZhenbaoge]
+ScriptName = Player\PlayerFamilyZhenbaoge.py
+Writer = hxp
+Releaser = hxp
+RegType = 0
+RegisterPackCount = 1
+
+PacketCMD_1=0xA6
+PacketSubCMD_1=0x16
+PacketCallFunc_1=OnZhenbaogeOP
 
 ;家族仓库
 [PlayerFamilyStore]
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 713c71b..54f17cd 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -2697,6 +2697,19 @@
 queryType_FamilyEmblem,               #仙盟徽章
 ) = range(0, Def_QueryType_Count)
 #------------------------------------------------------------------------------ 
+
+#家族某行为类型保存的条数
+ActionTypeSaveCnt = {
+              ShareDefine.Def_ActionType_FamilyPray:10 ,    #家族祈福
+              ShareDefine.Def_ActionType_FamilyArrest:7,     #家族悬赏
+              ShareDefine.Def_ActionType_FamilyMember:1,       #记录家族成员信息
+              ShareDefine.Def_ActionType_LeaderImpeachTime:1,  # 族长下线了多久
+              ShareDefine.Def_ActionType_FamilyBossFB:1,  # 记录家族boss副本信息
+              ShareDefine.Def_ActionType_FamilyStore:30,       #仓库操作记录
+              ShareDefine.Def_ActionType_OfficerModelEquip:10,  # 记录家族有职位的成员模型装备信息(盟主+副盟主*2+战斗队长*5)
+              ShareDefine.Def_ActionType_FamilyEvent:50,  # 记录家族事件
+              }
+
 #---------------------------------------------------------------------
 #数值上限 2^31 - 1
 Def_UpperLimit_DWordEx = ShareDefine.Def_UpperLimit_DWordEx
@@ -3622,7 +3635,6 @@
 Def_Player_Dict_LoginValid = "LoginValid_106"  # 新增有效登陆标记
 Def_Player_Dict_RequestAddFamilyCnt = "RequestAddFamilyCnt_107"  # 已申请加入家族的个数
 Def_Player_Dict_RequestAddFamilyID = "AddFamilyID%s_108"  # 申请加入的家族ID, %s为第几个
-Def_Player_Dict_FamilyIDChangeTime = "FamilyIDChangeTime"   # 记录玩家家族ID变更时间
 Def_Player_Dict_LastFamilyID = "LastFamilyID"   # 记录玩家上一个家族ID
 Def_Player_Dict_SingDay = "SingDay_115"  #每日签到
 Def_Player_Dict_GiveSignAward = "GiveSignAward_116"  #每日签到奖励领取
@@ -3658,7 +3670,7 @@
 Def_Player_Dict_UpdateFamilyNameItemIndex = "UpdateFamilyNameItemIndex"  # 改名物品在背包的位置
 Def_Player_Dict_UpdateFamilyName = "UpdateFamilyName"  # 改名锁
 Def_Player_Dict_FamilyDayAward = "FamilyDayAward"  # 仙盟每日奖励领奖记录
-Def_Player_Dict_FamilyMoneyDonateCount = "FamilyMoneyDonateCount"  # 仙盟今日货币捐献次数
+Def_Player_Dict_FamilyDonateRecord = "FamilyDonateRecord"  # 仙盟今日捐献记录,按位存储每种类型今日已捐献次数
 Def_Player_Dict_FamilyEmblemID = "FamilyEmblemID"  # 仙盟徽章ID
 Def_Player_Dict_FamilyZhenbaogeCut = "FamilyZhenbaogeCut" #珍宝阁今日是否已砍过价
 Def_Player_Dict_FamilyZhenbaogeBuy = "FamilyZhenbaogeBuy" #珍宝阁今日是否已购买过
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index 939ec1a..763fff9 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -15082,6 +15082,227 @@
 
 
 #------------------------------------------------------
+# A6 23 修改家族公告 #tagCMChangeFamilyBroadcast
+
+class  tagCMChangeFamilyBroadcast(Structure):
+    Head = tagHead()
+    Msg = ""    #(char Msg[200])
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA6
+        self.Head.SubCmd = 0x23
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.Msg,_pos = CommFunc.ReadString(_lpData, _pos,200)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA6
+        self.Head.SubCmd = 0x23
+        self.Msg = ""
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 200
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteString(data, 200, self.Msg)
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                Msg:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.Msg
+                                )
+        return DumpString
+
+
+m_NAtagCMChangeFamilyBroadcast=tagCMChangeFamilyBroadcast()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMChangeFamilyBroadcast.Head.Cmd,m_NAtagCMChangeFamilyBroadcast.Head.SubCmd))] = m_NAtagCMChangeFamilyBroadcast
+
+
+#------------------------------------------------------
+# A6 24 修改家族徽章 #tagCMChangeFamilyEmblem
+
+class  tagCMChangeFamilyEmblem(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("EmblemID", c_ubyte),    # 更换的徽章ID
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA6
+        self.SubCmd = 0x24
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.Cmd = 0xA6
+        self.SubCmd = 0x24
+        self.EmblemID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMChangeFamilyEmblem)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A6 24 修改家族徽章 //tagCMChangeFamilyEmblem:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                EmblemID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.EmblemID
+                                )
+        return DumpString
+
+
+m_NAtagCMChangeFamilyEmblem=tagCMChangeFamilyEmblem()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMChangeFamilyEmblem.Cmd,m_NAtagCMChangeFamilyEmblem.SubCmd))] = m_NAtagCMChangeFamilyEmblem
+
+
+#------------------------------------------------------
+# A6 22 修改收人方式 #tagCMChangeFamilyJoin
+
+class  tagCMChangeFamilyJoin(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("JoinReview", c_ubyte),    #成员加入是否需要审核,默认0自动加入
+                  ("JoinLVMin", c_ushort),    #限制最低可加入的玩家等级
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA6
+        self.SubCmd = 0x22
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.Cmd = 0xA6
+        self.SubCmd = 0x22
+        self.JoinReview = 0
+        self.JoinLVMin = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMChangeFamilyJoin)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A6 22 修改收人方式 //tagCMChangeFamilyJoin:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                JoinReview:%d,
+                                JoinLVMin:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.JoinReview,
+                                self.JoinLVMin
+                                )
+        return DumpString
+
+
+m_NAtagCMChangeFamilyJoin=tagCMChangeFamilyJoin()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMChangeFamilyJoin.Cmd,m_NAtagCMChangeFamilyJoin.SubCmd))] = m_NAtagCMChangeFamilyJoin
+
+
+#------------------------------------------------------
+# A6 25 修改家族成员职位 #tagCMChangeFamilyMemLV
+
+class  tagCMChangeFamilyMemLV(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("PlayerID", c_int),    # 目标成员ID
+                  ("FmLV", c_ubyte),    # 变更为xx职位
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA6
+        self.SubCmd = 0x25
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.Cmd = 0xA6
+        self.SubCmd = 0x25
+        self.PlayerID = 0
+        self.FmLV = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMChangeFamilyMemLV)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A6 25 修改家族成员职位 //tagCMChangeFamilyMemLV:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                PlayerID:%d,
+                                FmLV:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.PlayerID,
+                                self.FmLV
+                                )
+        return DumpString
+
+
+m_NAtagCMChangeFamilyMemLV=tagCMChangeFamilyMemLV()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMChangeFamilyMemLV.Cmd,m_NAtagCMChangeFamilyMemLV.SubCmd))] = m_NAtagCMChangeFamilyMemLV
+
+
+#------------------------------------------------------
 # A6 15 传功操作 #tagCMChuangongOP
 
 class  tagCMChuangongOP(Structure):
@@ -15210,6 +15431,122 @@
 
 m_NAtagCMRenameFamily=tagCMRenameFamily()
 ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMRenameFamily.Head.Cmd,m_NAtagCMRenameFamily.Head.SubCmd))] = m_NAtagCMRenameFamily
+
+
+#------------------------------------------------------
+# A6 04 创建家族 #tagCMCreateFamily
+
+class  tagCMCreateFamily(Structure):
+    Head = tagHead()
+    Name = ""    #(char Name[33])
+    EmblemID = 0    #(WORD EmblemID)//选择徽章ID,解锁仙盟等级为1级的均为可选ID
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA6
+        self.Head.SubCmd = 0x04
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.Name,_pos = CommFunc.ReadString(_lpData, _pos,33)
+        self.EmblemID,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA6
+        self.Head.SubCmd = 0x04
+        self.Name = ""
+        self.EmblemID = 0
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 33
+        length += 2
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteString(data, 33, self.Name)
+        data = CommFunc.WriteWORD(data, self.EmblemID)
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                Name:%s,
+                                EmblemID:%d
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.Name,
+                                self.EmblemID
+                                )
+        return DumpString
+
+
+m_NAtagCMCreateFamily=tagCMCreateFamily()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMCreateFamily.Head.Cmd,m_NAtagCMCreateFamily.Head.SubCmd))] = m_NAtagCMCreateFamily
+
+
+#------------------------------------------------------
+# A6 05 删除家族成员 #tagCMDeleteFamilyMember
+
+class  tagCMDeleteFamilyMember(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("MemberID", c_int),    
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA6
+        self.SubCmd = 0x05
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.Cmd = 0xA6
+        self.SubCmd = 0x05
+        self.MemberID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMDeleteFamilyMember)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A6 05 删除家族成员 //tagCMDeleteFamilyMember:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                MemberID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.MemberID
+                                )
+        return DumpString
+
+
+m_NAtagCMDeleteFamilyMember=tagCMDeleteFamilyMember()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMDeleteFamilyMember.Cmd,m_NAtagCMDeleteFamilyMember.SubCmd))] = m_NAtagCMDeleteFamilyMember
 
 
 #------------------------------------------------------
@@ -15353,7 +15690,7 @@
     _fields_ = [
                   ("Cmd", c_ubyte),
                   ("SubCmd", c_ubyte),
-                  ("MoneyType", c_ubyte),    # 捐献货币类型
+                  ("DonateType", c_ubyte),    # 捐献类型
                   ]
 
     def __init__(self):
@@ -15370,7 +15707,7 @@
     def Clear(self):
         self.Cmd = 0xA6
         self.SubCmd = 0x12
-        self.MoneyType = 0
+        self.DonateType = 0
         return
 
     def GetLength(self):
@@ -15383,12 +15720,12 @@
         DumpString = '''// A6 12 家族捐献货币 //tagCMFamilyMoneyDonate:
                                 Cmd:%s,
                                 SubCmd:%s,
-                                MoneyType:%d
+                                DonateType:%d
                                 '''\
                                 %(
                                 self.Cmd,
                                 self.SubCmd,
-                                self.MoneyType
+                                self.DonateType
                                 )
         return DumpString
 
@@ -15570,15 +15907,167 @@
 
 
 #------------------------------------------------------
-#A6 02  申请加入家族#tagCGRequesJoinFamily
+# A6 26 请求家族成员列表 #tagCMGetFamilyInfo
 
-class  tagCGRequesJoinFamily(Structure):
+class  tagCMGetFamilyInfo(Structure):
     _pack_ = 1
     _fields_ = [
                   ("Cmd", c_ubyte),
                   ("SubCmd", c_ubyte),
-                  ("Type", c_ubyte),    #申请类型
-                  ("AddFamilyID", c_int),    #申请加入的家族
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA6
+        self.SubCmd = 0x26
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.Cmd = 0xA6
+        self.SubCmd = 0x26
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMGetFamilyInfo)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A6 26 请求家族成员列表 //tagCMGetFamilyInfo:
+                                Cmd:%s,
+                                SubCmd:%s
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd
+                                )
+        return DumpString
+
+
+m_NAtagCMGetFamilyInfo=tagCMGetFamilyInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMGetFamilyInfo.Cmd,m_NAtagCMGetFamilyInfo.SubCmd))] = m_NAtagCMGetFamilyInfo
+
+
+#------------------------------------------------------
+# A6 21 审核请求加入家族 #tagCMJoinFamilyReply
+
+class  tagCMJoinFamilyReply(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("TagPlayerID", c_int),    #被审核玩家ID 0则代表全部
+                  ("IsOK", c_ubyte),    #是否同意其加入
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA6
+        self.SubCmd = 0x21
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.Cmd = 0xA6
+        self.SubCmd = 0x21
+        self.TagPlayerID = 0
+        self.IsOK = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMJoinFamilyReply)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A6 21 审核请求加入家族 //tagCMJoinFamilyReply:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                TagPlayerID:%d,
+                                IsOK:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.TagPlayerID,
+                                self.IsOK
+                                )
+        return DumpString
+
+
+m_NAtagCMJoinFamilyReply=tagCMJoinFamilyReply()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMJoinFamilyReply.Cmd,m_NAtagCMJoinFamilyReply.SubCmd))] = m_NAtagCMJoinFamilyReply
+
+
+#------------------------------------------------------
+# A6 03 离开家族 #tagCMLeaveFamily
+
+class  tagCMLeaveFamily(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA6
+        self.SubCmd = 0x03
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.Cmd = 0xA6
+        self.SubCmd = 0x03
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMLeaveFamily)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A6 03 离开家族 //tagCMLeaveFamily:
+                                Cmd:%s,
+                                SubCmd:%s
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd
+                                )
+        return DumpString
+
+
+m_NAtagCMLeaveFamily=tagCMLeaveFamily()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMLeaveFamily.Cmd,m_NAtagCMLeaveFamily.SubCmd))] = m_NAtagCMLeaveFamily
+
+
+#------------------------------------------------------
+# A6 02 申请加入家族#tagCMRequesJoinFamily
+
+class  tagCMRequesJoinFamily(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("Type", c_ubyte),    #申请类型,0-申请;1-撤销
+                  ("TagFamilyID", c_int),    #目标家族ID,申请时为0代表一键申请家族任意家族
                   ]
 
     def __init__(self):
@@ -15596,44 +16085,44 @@
         self.Cmd = 0xA6
         self.SubCmd = 0x02
         self.Type = 0
-        self.AddFamilyID = 0
+        self.TagFamilyID = 0
         return
 
     def GetLength(self):
-        return sizeof(tagCGRequesJoinFamily)
+        return sizeof(tagCMRequesJoinFamily)
 
     def GetBuffer(self):
         return string_at(addressof(self), self.GetLength())
 
     def OutputString(self):
-        DumpString = '''//A6 02  申请加入家族//tagCGRequesJoinFamily:
+        DumpString = '''// A6 02 申请加入家族//tagCMRequesJoinFamily:
                                 Cmd:%s,
                                 SubCmd:%s,
                                 Type:%d,
-                                AddFamilyID:%d
+                                TagFamilyID:%d
                                 '''\
                                 %(
                                 self.Cmd,
                                 self.SubCmd,
                                 self.Type,
-                                self.AddFamilyID
+                                self.TagFamilyID
                                 )
         return DumpString
 
 
-m_NAtagCGRequesJoinFamily=tagCGRequesJoinFamily()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGRequesJoinFamily.Cmd,m_NAtagCGRequesJoinFamily.SubCmd))] = m_NAtagCGRequesJoinFamily
+m_NAtagCMRequesJoinFamily=tagCMRequesJoinFamily()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMRequesJoinFamily.Cmd,m_NAtagCMRequesJoinFamily.SubCmd))] = m_NAtagCMRequesJoinFamily
 
 
 #------------------------------------------------------
-#A6 01  向玩家申请加入家族 #tagCGRequestJoinFamilyByPlayer
+# A6 01 向玩家申请加入家族 #tagCMRequestJoinFamilyByPlayer
 
-class  tagCGRequestJoinFamilyByPlayer(Structure):
+class  tagCMRequestJoinFamilyByPlayer(Structure):
     _pack_ = 1
     _fields_ = [
                   ("Cmd", c_ubyte),
                   ("SubCmd", c_ubyte),
-                  ("AddPlayerID", c_int),    #申请加入的玩家ID
+                  ("TagPlayerID", c_int),    #目标家族玩家ID
                   ]
 
     def __init__(self):
@@ -15650,31 +16139,31 @@
     def Clear(self):
         self.Cmd = 0xA6
         self.SubCmd = 0x01
-        self.AddPlayerID = 0
+        self.TagPlayerID = 0
         return
 
     def GetLength(self):
-        return sizeof(tagCGRequestJoinFamilyByPlayer)
+        return sizeof(tagCMRequestJoinFamilyByPlayer)
 
     def GetBuffer(self):
         return string_at(addressof(self), self.GetLength())
 
     def OutputString(self):
-        DumpString = '''//A6 01  向玩家申请加入家族 //tagCGRequestJoinFamilyByPlayer:
+        DumpString = '''// A6 01 向玩家申请加入家族 //tagCMRequestJoinFamilyByPlayer:
                                 Cmd:%s,
                                 SubCmd:%s,
-                                AddPlayerID:%d
+                                TagPlayerID:%d
                                 '''\
                                 %(
                                 self.Cmd,
                                 self.SubCmd,
-                                self.AddPlayerID
+                                self.TagPlayerID
                                 )
         return DumpString
 
 
-m_NAtagCGRequestJoinFamilyByPlayer=tagCGRequestJoinFamilyByPlayer()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGRequestJoinFamilyByPlayer.Cmd,m_NAtagCGRequestJoinFamilyByPlayer.SubCmd))] = m_NAtagCGRequestJoinFamilyByPlayer
+m_NAtagCMRequestJoinFamilyByPlayer=tagCMRequestJoinFamilyByPlayer()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMRequestJoinFamilyByPlayer.Cmd,m_NAtagCMRequestJoinFamilyByPlayer.SubCmd))] = m_NAtagCMRequestJoinFamilyByPlayer
 
 
 #------------------------------------------------------
@@ -15815,6 +16304,84 @@
 
 
 #------------------------------------------------------
+# A6 20 搜索家族列表 #tagCMViewFamilyPage
+
+class  tagCMViewFamilyPage(Structure):
+    Head = tagHead()
+    MsgLen = 0    #(BYTE MsgLen)//模糊搜索家族,如果输入为空,则为不限制该条件
+    Msg = ""    #(String Msg)//size = MsgLen
+    PageIndex = 0    #(BYTE PageIndex)//查询第X页索引,0~n
+    ShowCount = 0    #(BYTE ShowCount)//每页数量,前端可自行指定,最大50
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA6
+        self.Head.SubCmd = 0x20
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.MsgLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.Msg,_pos = CommFunc.ReadString(_lpData, _pos,self.MsgLen)
+        self.PageIndex,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.ShowCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA6
+        self.Head.SubCmd = 0x20
+        self.MsgLen = 0
+        self.Msg = ""
+        self.PageIndex = 0
+        self.ShowCount = 0
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += len(self.Msg)
+        length += 1
+        length += 1
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.MsgLen)
+        data = CommFunc.WriteString(data, self.MsgLen, self.Msg)
+        data = CommFunc.WriteBYTE(data, self.PageIndex)
+        data = CommFunc.WriteBYTE(data, self.ShowCount)
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                MsgLen:%d,
+                                Msg:%s,
+                                PageIndex:%d,
+                                ShowCount:%d
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.MsgLen,
+                                self.Msg,
+                                self.PageIndex,
+                                self.ShowCount
+                                )
+        return DumpString
+
+
+m_NAtagCMViewFamilyPage=tagCMViewFamilyPage()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMViewFamilyPage.Head.Cmd,m_NAtagCMViewFamilyPage.Head.SubCmd))] = m_NAtagCMViewFamilyPage
+
+
+#------------------------------------------------------
 # A6 16 珍宝阁操作 #tagCMZhenbaogeOP
 
 class  tagCMZhenbaogeOP(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 53a6757..693db8a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -32149,6 +32149,58 @@
 
 
 #------------------------------------------------------
+# A5 21 家族变更 #tagMCFamilyChange
+
+class  tagMCFamilyChange(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("Type", c_ubyte),    
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA5
+        self.SubCmd = 0x21
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.Cmd = 0xA5
+        self.SubCmd = 0x21
+        self.Type = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCFamilyChange)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A5 21 家族变更 //tagMCFamilyChange:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                Type:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.Type
+                                )
+        return DumpString
+
+
+m_NAtagMCFamilyChange=tagMCFamilyChange()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFamilyChange.Cmd,m_NAtagMCFamilyChange.SubCmd))] = m_NAtagMCFamilyChange
+
+
+#------------------------------------------------------
 # A5 06 仙盟每日福利领取状态 #tagMCFamilyDayAward
 
 class  tagMCFamilyDayAward(Structure):
@@ -32313,6 +32365,197 @@
 
 
 #------------------------------------------------------
+# A5 22 家族申请加入的玩家信息 #tagMCFamilyReqJoinInfo
+
+class  tagMCFamilyReqJoinPlayer(Structure):
+    PlayerID = 0    #(DWORD PlayerID)
+    NameLen = 0    #(BYTE NameLen)
+    Name = ""    #(String Name)//size = NameLen
+    ReqTime = 0    #(DWORD ReqTime)//申请时间戳
+    LV = 0    #(WORD LV)//等级
+    Job = 0    #(BYTE Job)//职业
+    RealmLV = 0    #(BYTE RealmLV)//境界
+    Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
+    FightPower = 0    #(DWORD FightPower)//战力,求余亿部分
+    FightPowerEx = 0    #(DWORD FightPowerEx)//战力,整除亿部分
+    ServerID = 0    #(DWORD ServerID)//所属区服ID
+    IsOnLine = 0    #(BYTE IsOnLine)//是否在线
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.NameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.Name,_pos = CommFunc.ReadString(_lpData, _pos,self.NameLen)
+        self.ReqTime,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.Job,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.RealmLV,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FightPower,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FightPowerEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.IsOnLine,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        return _pos
+
+    def Clear(self):
+        self.PlayerID = 0
+        self.NameLen = 0
+        self.Name = ""
+        self.ReqTime = 0
+        self.LV = 0
+        self.Job = 0
+        self.RealmLV = 0
+        self.Face = 0
+        self.FacePic = 0
+        self.FightPower = 0
+        self.FightPowerEx = 0
+        self.ServerID = 0
+        self.IsOnLine = 0
+        return
+
+    def GetLength(self):
+        length = 0
+        length += 4
+        length += 1
+        length += len(self.Name)
+        length += 4
+        length += 2
+        length += 1
+        length += 1
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+        length += 1
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteDWORD(data, self.PlayerID)
+        data = CommFunc.WriteBYTE(data, self.NameLen)
+        data = CommFunc.WriteString(data, self.NameLen, self.Name)
+        data = CommFunc.WriteDWORD(data, self.ReqTime)
+        data = CommFunc.WriteWORD(data, self.LV)
+        data = CommFunc.WriteBYTE(data, self.Job)
+        data = CommFunc.WriteBYTE(data, self.RealmLV)
+        data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
+        data = CommFunc.WriteDWORD(data, self.FightPower)
+        data = CommFunc.WriteDWORD(data, self.FightPowerEx)
+        data = CommFunc.WriteDWORD(data, self.ServerID)
+        data = CommFunc.WriteBYTE(data, self.IsOnLine)
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                PlayerID:%d,
+                                NameLen:%d,
+                                Name:%s,
+                                ReqTime:%d,
+                                LV:%d,
+                                Job:%d,
+                                RealmLV:%d,
+                                Face:%d,
+                                FacePic:%d,
+                                FightPower:%d,
+                                FightPowerEx:%d,
+                                ServerID:%d,
+                                IsOnLine:%d
+                                '''\
+                                %(
+                                self.PlayerID,
+                                self.NameLen,
+                                self.Name,
+                                self.ReqTime,
+                                self.LV,
+                                self.Job,
+                                self.RealmLV,
+                                self.Face,
+                                self.FacePic,
+                                self.FightPower,
+                                self.FightPowerEx,
+                                self.ServerID,
+                                self.IsOnLine
+                                )
+        return DumpString
+
+
+class  tagMCFamilyReqJoinInfo(Structure):
+    Head = tagHead()
+    ReqCnt = 0    #(BYTE ReqCnt)
+    ReqJoinList = list()    #(vector<tagMCFamilyReqJoinPlayer> ReqJoinList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA5
+        self.Head.SubCmd = 0x22
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ReqCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.ReqCnt):
+            temReqJoinList = tagMCFamilyReqJoinPlayer()
+            _pos = temReqJoinList.ReadData(_lpData, _pos)
+            self.ReqJoinList.append(temReqJoinList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA5
+        self.Head.SubCmd = 0x22
+        self.ReqCnt = 0
+        self.ReqJoinList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        for i in range(self.ReqCnt):
+            length += self.ReqJoinList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.ReqCnt)
+        for i in range(self.ReqCnt):
+            data = CommFunc.WriteString(data, self.ReqJoinList[i].GetLength(), self.ReqJoinList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ReqCnt:%d,
+                                ReqJoinList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ReqCnt,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCFamilyReqJoinInfo=tagMCFamilyReqJoinInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFamilyReqJoinInfo.Head.Cmd,m_NAtagMCFamilyReqJoinInfo.Head.SubCmd))] = m_NAtagMCFamilyReqJoinInfo
+
+
+#------------------------------------------------------
 # A5 11 打坐信息 #tagMCFamilySitInfo
 
 class  tagMCFamilySitInfo(Structure):
@@ -32370,6 +32613,239 @@
 
 m_NAtagMCFamilySitInfo=tagMCFamilySitInfo()
 ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFamilySitInfo.Cmd,m_NAtagMCFamilySitInfo.SubCmd))] = m_NAtagMCFamilySitInfo
+
+
+#------------------------------------------------------
+# A5 23 搜索家族返回列表 #tagMCFamilyViewList
+
+class  tagMCFamilyView(Structure):
+    FamilyID = 0    #(DWORD FamilyID)//家族ID
+    FamilyNameLen = 0    #(BYTE FamilyNameLen)
+    FamilyName = ""    #(String FamilyName)//size = FamilyNameLen
+    LeaderID = 0    #(DWORD LeaderID)//族长ID
+    LeaderNameLen = 0    #(BYTE LeaderNameLen)
+    LeaderName = ""    #(String LeaderName)//size = LeaderNameLen
+    FamilyLV = 0    #(BYTE FamilyLV)//家族等级
+    JoinReview = 0    #(BYTE JoinReview)//成员加入是否需要审核,默认0自动加入
+    JoinLVMin = 0    #(WORD JoinLVMin)//限制最低可加入的玩家等级
+    ServerID = 0    #(DWORD ServerID)//区服ID
+    EmblemID = 0    #(DWORD EmblemID)//徽章ID
+    FightPower = 0    #(DWORD FightPower)//总战力,求余亿部分
+    FightPowerEx = 0    #(DWORD FightPowerEx)//总战力,整除亿部分
+    MemberCount = 0    #(BYTE MemberCount)//成员人数
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        self.FamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FamilyNameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.FamilyName,_pos = CommFunc.ReadString(_lpData, _pos,self.FamilyNameLen)
+        self.LeaderID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.LeaderNameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.LeaderName,_pos = CommFunc.ReadString(_lpData, _pos,self.LeaderNameLen)
+        self.FamilyLV,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.JoinReview,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.JoinLVMin,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.ServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.EmblemID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FightPower,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FightPowerEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.MemberCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        return _pos
+
+    def Clear(self):
+        self.FamilyID = 0
+        self.FamilyNameLen = 0
+        self.FamilyName = ""
+        self.LeaderID = 0
+        self.LeaderNameLen = 0
+        self.LeaderName = ""
+        self.FamilyLV = 0
+        self.JoinReview = 0
+        self.JoinLVMin = 0
+        self.ServerID = 0
+        self.EmblemID = 0
+        self.FightPower = 0
+        self.FightPowerEx = 0
+        self.MemberCount = 0
+        return
+
+    def GetLength(self):
+        length = 0
+        length += 4
+        length += 1
+        length += len(self.FamilyName)
+        length += 4
+        length += 1
+        length += len(self.LeaderName)
+        length += 1
+        length += 1
+        length += 2
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+        length += 1
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteDWORD(data, self.FamilyID)
+        data = CommFunc.WriteBYTE(data, self.FamilyNameLen)
+        data = CommFunc.WriteString(data, self.FamilyNameLen, self.FamilyName)
+        data = CommFunc.WriteDWORD(data, self.LeaderID)
+        data = CommFunc.WriteBYTE(data, self.LeaderNameLen)
+        data = CommFunc.WriteString(data, self.LeaderNameLen, self.LeaderName)
+        data = CommFunc.WriteBYTE(data, self.FamilyLV)
+        data = CommFunc.WriteBYTE(data, self.JoinReview)
+        data = CommFunc.WriteWORD(data, self.JoinLVMin)
+        data = CommFunc.WriteDWORD(data, self.ServerID)
+        data = CommFunc.WriteDWORD(data, self.EmblemID)
+        data = CommFunc.WriteDWORD(data, self.FightPower)
+        data = CommFunc.WriteDWORD(data, self.FightPowerEx)
+        data = CommFunc.WriteBYTE(data, self.MemberCount)
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                FamilyID:%d,
+                                FamilyNameLen:%d,
+                                FamilyName:%s,
+                                LeaderID:%d,
+                                LeaderNameLen:%d,
+                                LeaderName:%s,
+                                FamilyLV:%d,
+                                JoinReview:%d,
+                                JoinLVMin:%d,
+                                ServerID:%d,
+                                EmblemID:%d,
+                                FightPower:%d,
+                                FightPowerEx:%d,
+                                MemberCount:%d
+                                '''\
+                                %(
+                                self.FamilyID,
+                                self.FamilyNameLen,
+                                self.FamilyName,
+                                self.LeaderID,
+                                self.LeaderNameLen,
+                                self.LeaderName,
+                                self.FamilyLV,
+                                self.JoinReview,
+                                self.JoinLVMin,
+                                self.ServerID,
+                                self.EmblemID,
+                                self.FightPower,
+                                self.FightPowerEx,
+                                self.MemberCount
+                                )
+        return DumpString
+
+
+class  tagMCFamilyViewList(Structure):
+    Head = tagHead()
+    MsgLen = 0    #(BYTE MsgLen)
+    Msg = ""    #(String Msg)//搜索条件原值返回
+    PageIndex = 0    #(BYTE PageIndex)//查询第X页索引,0~n
+    ShowCount = 0    #(BYTE ShowCount)//每页数量
+    TotalPage = 0    #(BYTE TotalPage)//一共有多少页
+    FamilyCount = 0    #(BYTE FamilyCount)
+    FamilyList = list()    #(vector<tagMCFamilyView> FamilyList)//本页家族信息列表
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA5
+        self.Head.SubCmd = 0x23
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.MsgLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.Msg,_pos = CommFunc.ReadString(_lpData, _pos,self.MsgLen)
+        self.PageIndex,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.ShowCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.TotalPage,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.FamilyCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.FamilyCount):
+            temFamilyList = tagMCFamilyView()
+            _pos = temFamilyList.ReadData(_lpData, _pos)
+            self.FamilyList.append(temFamilyList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA5
+        self.Head.SubCmd = 0x23
+        self.MsgLen = 0
+        self.Msg = ""
+        self.PageIndex = 0
+        self.ShowCount = 0
+        self.TotalPage = 0
+        self.FamilyCount = 0
+        self.FamilyList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += len(self.Msg)
+        length += 1
+        length += 1
+        length += 1
+        length += 1
+        for i in range(self.FamilyCount):
+            length += self.FamilyList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.MsgLen)
+        data = CommFunc.WriteString(data, self.MsgLen, self.Msg)
+        data = CommFunc.WriteBYTE(data, self.PageIndex)
+        data = CommFunc.WriteBYTE(data, self.ShowCount)
+        data = CommFunc.WriteBYTE(data, self.TotalPage)
+        data = CommFunc.WriteBYTE(data, self.FamilyCount)
+        for i in range(self.FamilyCount):
+            data = CommFunc.WriteString(data, self.FamilyList[i].GetLength(), self.FamilyList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                MsgLen:%d,
+                                Msg:%s,
+                                PageIndex:%d,
+                                ShowCount:%d,
+                                TotalPage:%d,
+                                FamilyCount:%d,
+                                FamilyList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.MsgLen,
+                                self.Msg,
+                                self.PageIndex,
+                                self.ShowCount,
+                                self.TotalPage,
+                                self.FamilyCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCFamilyViewList=tagMCFamilyViewList()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFamilyViewList.Head.Cmd,m_NAtagMCFamilyViewList.Head.SubCmd))] = m_NAtagMCFamilyViewList
 
 
 #------------------------------------------------------
@@ -32548,47 +33024,12 @@
 
 
 #------------------------------------------------------
-#A5 01  查看已申请加入的家族信息  #tagMCNotifyRequestJoinFamilyInfo
-
-class  tagRequestJoinFamily(Structure):
-    _pack_ = 1
-    _fields_ = [
-                  ("RequestFamilyID", c_int),    #申请的加入ID
-                  ]
-
-    def __init__(self):
-        self.Clear()
-        return
-
-    def ReadData(self, stringData, _pos=0, _len=0):
-        self.Clear()
-        memmove(addressof(self), stringData[_pos:], self.GetLength())
-        return _pos + self.GetLength()
-
-    def Clear(self):
-        self.RequestFamilyID = 0
-        return
-
-    def GetLength(self):
-        return sizeof(tagRequestJoinFamily)
-
-    def GetBuffer(self):
-        return string_at(addressof(self), self.GetLength())
-
-    def OutputString(self):
-        DumpString = '''//A5 01  查看已申请加入的家族信息  //tagMCNotifyRequestJoinFamilyInfo:
-                                RequestFamilyID:%d
-                                '''\
-                                %(
-                                self.RequestFamilyID
-                                )
-        return DumpString
-
+#A5 01 已申请加入的家族信息 #tagMCNotifyRequestJoinFamilyInfo
 
 class  tagMCNotifyRequestJoinFamilyInfo(Structure):
     Head = tagHead()
     RequestCount = 0    #(BYTE RequestCount)//申请的数量
-    RequestAddFamilyInfo = list()    #(vector<tagRequestJoinFamily> RequestAddFamilyInfo)//size = RequestCount
+    RequestJoinFamilyIDList = list()    #(vector<DWORD> RequestJoinFamilyIDList)//size = RequestCount
     data = None
 
     def __init__(self):
@@ -32602,9 +33043,8 @@
         _pos = self.Head.ReadData(_lpData, _pos)
         self.RequestCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
         for i in range(self.RequestCount):
-            temRequestAddFamilyInfo = tagRequestJoinFamily()
-            _pos = temRequestAddFamilyInfo.ReadData(_lpData, _pos)
-            self.RequestAddFamilyInfo.append(temRequestAddFamilyInfo)
+            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+            self.RequestJoinFamilyIDList.append(value)
         return _pos
 
     def Clear(self):
@@ -32613,15 +33053,14 @@
         self.Head.Cmd = 0xA5
         self.Head.SubCmd = 0x01
         self.RequestCount = 0
-        self.RequestAddFamilyInfo = list()
+        self.RequestJoinFamilyIDList = list()
         return
 
     def GetLength(self):
         length = 0
         length += self.Head.GetLength()
         length += 1
-        for i in range(self.RequestCount):
-            length += self.RequestAddFamilyInfo[i].GetLength()
+        length += 4 * self.RequestCount
 
         return length
 
@@ -32630,14 +33069,14 @@
         data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
         data = CommFunc.WriteBYTE(data, self.RequestCount)
         for i in range(self.RequestCount):
-            data = CommFunc.WriteString(data, self.RequestAddFamilyInfo[i].GetLength(), self.RequestAddFamilyInfo[i].GetBuffer())
+            data = CommFunc.WriteDWORD(data, self.RequestJoinFamilyIDList[i])
         return data
 
     def OutputString(self):
         DumpString = '''
                                 Head:%s,
                                 RequestCount:%d,
-                                RequestAddFamilyInfo:%s
+                                RequestJoinFamilyIDList:%s
                                 '''\
                                 %(
                                 self.Head.OutputString(),
@@ -32760,6 +33199,309 @@
 
 
 #------------------------------------------------------
+# A5 20 玩家家族信息 #tagMCRoleFamilyInfo
+
+class  tagMCRoleFamilyMember(Structure):
+    PlayerID = 0    #(DWORD PlayerID)
+    NameLen = 0    #(BYTE NameLen)
+    Name = ""    #(String Name)//size = NameLen
+    JoinTime = 0    #(DWORD JoinTime)//加入家族时时间戳
+    FmLV = 0    #(BYTE FmLV)//家族职位: 0-成员;1-精英;2-副族长;3-族长
+    LV = 0    #(WORD LV)//等级
+    Job = 0    #(BYTE Job)//职业
+    RealmLV = 0    #(BYTE RealmLV)//境界
+    Face = 0    #(DWORD Face)//基本脸型
+    FacePic = 0    #(DWORD FacePic)//头像框
+    FightPower = 0    #(DWORD FightPower)//战力,求余亿部分
+    FightPowerEx = 0    #(DWORD FightPowerEx)//战力,整除亿部分
+    ServerID = 0    #(DWORD ServerID)//所属区服ID
+    ContribTotal = 0    #(DWORD ContribTotal)//总贡献度
+    ContribWeek = 0    #(DWORD ContribWeek)//周贡献度
+    OffTime = 0    #(DWORD OffTime)// 0-在线; >0-/离线时间戳
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.NameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.Name,_pos = CommFunc.ReadString(_lpData, _pos,self.NameLen)
+        self.JoinTime,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FmLV,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.Job,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.RealmLV,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FightPower,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FightPowerEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ContribTotal,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ContribWeek,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.OffTime,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        return _pos
+
+    def Clear(self):
+        self.PlayerID = 0
+        self.NameLen = 0
+        self.Name = ""
+        self.JoinTime = 0
+        self.FmLV = 0
+        self.LV = 0
+        self.Job = 0
+        self.RealmLV = 0
+        self.Face = 0
+        self.FacePic = 0
+        self.FightPower = 0
+        self.FightPowerEx = 0
+        self.ServerID = 0
+        self.ContribTotal = 0
+        self.ContribWeek = 0
+        self.OffTime = 0
+        return
+
+    def GetLength(self):
+        length = 0
+        length += 4
+        length += 1
+        length += len(self.Name)
+        length += 4
+        length += 1
+        length += 2
+        length += 1
+        length += 1
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteDWORD(data, self.PlayerID)
+        data = CommFunc.WriteBYTE(data, self.NameLen)
+        data = CommFunc.WriteString(data, self.NameLen, self.Name)
+        data = CommFunc.WriteDWORD(data, self.JoinTime)
+        data = CommFunc.WriteBYTE(data, self.FmLV)
+        data = CommFunc.WriteWORD(data, self.LV)
+        data = CommFunc.WriteBYTE(data, self.Job)
+        data = CommFunc.WriteBYTE(data, self.RealmLV)
+        data = CommFunc.WriteDWORD(data, self.Face)
+        data = CommFunc.WriteDWORD(data, self.FacePic)
+        data = CommFunc.WriteDWORD(data, self.FightPower)
+        data = CommFunc.WriteDWORD(data, self.FightPowerEx)
+        data = CommFunc.WriteDWORD(data, self.ServerID)
+        data = CommFunc.WriteDWORD(data, self.ContribTotal)
+        data = CommFunc.WriteDWORD(data, self.ContribWeek)
+        data = CommFunc.WriteDWORD(data, self.OffTime)
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                PlayerID:%d,
+                                NameLen:%d,
+                                Name:%s,
+                                JoinTime:%d,
+                                FmLV:%d,
+                                LV:%d,
+                                Job:%d,
+                                RealmLV:%d,
+                                Face:%d,
+                                FacePic:%d,
+                                FightPower:%d,
+                                FightPowerEx:%d,
+                                ServerID:%d,
+                                ContribTotal:%d,
+                                ContribWeek:%d,
+                                OffTime:%d
+                                '''\
+                                %(
+                                self.PlayerID,
+                                self.NameLen,
+                                self.Name,
+                                self.JoinTime,
+                                self.FmLV,
+                                self.LV,
+                                self.Job,
+                                self.RealmLV,
+                                self.Face,
+                                self.FacePic,
+                                self.FightPower,
+                                self.FightPowerEx,
+                                self.ServerID,
+                                self.ContribTotal,
+                                self.ContribWeek,
+                                self.OffTime
+                                )
+        return DumpString
+
+
+class  tagMCRoleFamilyInfo(Structure):
+    Head = tagHead()
+    FamilyID = 0    #(DWORD FamilyID)
+    FamilyName = ""    #(char FamilyName[33])//家族名称
+    FamilyLV = 0    #(BYTE FamilyLV)//家族等级
+    FamilyLVExp = 0    #(DWORD FamilyLVExp)//家族等级经验
+    JoinReview = 0    #(BYTE JoinReview)//成员加入是否需要审核,默认0自动加入
+    JoinLVMin = 0    #(WORD JoinLVMin)//限制最低可加入的玩家等级
+    ServerID = 0    #(DWORD ServerID)//区服ID,创建时以族长的区服ID赋值
+    EmblemID = 0    #(DWORD EmblemID)//徽章ID
+    FightPower = 0    #(DWORD FightPower)//总战力,求余亿部分
+    FightPowerEx = 0    #(DWORD FightPowerEx)//总战力,整除亿部分
+    BroadcastLen = 0    #(WORD BroadcastLen)//公告
+    Broadcast = ""    #(String Broadcast)//size = BroadcastLen
+    LeaderID = 0    #(DWORD LeaderID)//族长玩家ID
+    MemberCount = 0    #(BYTE MemberCount)//人数
+    MemberList = list()    #(vector<tagMCRoleFamilyMember> MemberList)//size = MemberCount
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA5
+        self.Head.SubCmd = 0x20
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.FamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FamilyName,_pos = CommFunc.ReadString(_lpData, _pos,33)
+        self.FamilyLV,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.FamilyLVExp,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.JoinReview,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.JoinLVMin,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.ServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.EmblemID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FightPower,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.FightPowerEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.BroadcastLen,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.Broadcast,_pos = CommFunc.ReadString(_lpData, _pos,self.BroadcastLen)
+        self.LeaderID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.MemberCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.MemberCount):
+            temMemberList = tagMCRoleFamilyMember()
+            _pos = temMemberList.ReadData(_lpData, _pos)
+            self.MemberList.append(temMemberList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA5
+        self.Head.SubCmd = 0x20
+        self.FamilyID = 0
+        self.FamilyName = ""
+        self.FamilyLV = 0
+        self.FamilyLVExp = 0
+        self.JoinReview = 0
+        self.JoinLVMin = 0
+        self.ServerID = 0
+        self.EmblemID = 0
+        self.FightPower = 0
+        self.FightPowerEx = 0
+        self.BroadcastLen = 0
+        self.Broadcast = ""
+        self.LeaderID = 0
+        self.MemberCount = 0
+        self.MemberList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 4
+        length += 33
+        length += 1
+        length += 4
+        length += 1
+        length += 2
+        length += 4
+        length += 4
+        length += 4
+        length += 4
+        length += 2
+        length += len(self.Broadcast)
+        length += 4
+        length += 1
+        for i in range(self.MemberCount):
+            length += self.MemberList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteDWORD(data, self.FamilyID)
+        data = CommFunc.WriteString(data, 33, self.FamilyName)
+        data = CommFunc.WriteBYTE(data, self.FamilyLV)
+        data = CommFunc.WriteDWORD(data, self.FamilyLVExp)
+        data = CommFunc.WriteBYTE(data, self.JoinReview)
+        data = CommFunc.WriteWORD(data, self.JoinLVMin)
+        data = CommFunc.WriteDWORD(data, self.ServerID)
+        data = CommFunc.WriteDWORD(data, self.EmblemID)
+        data = CommFunc.WriteDWORD(data, self.FightPower)
+        data = CommFunc.WriteDWORD(data, self.FightPowerEx)
+        data = CommFunc.WriteWORD(data, self.BroadcastLen)
+        data = CommFunc.WriteString(data, self.BroadcastLen, self.Broadcast)
+        data = CommFunc.WriteDWORD(data, self.LeaderID)
+        data = CommFunc.WriteBYTE(data, self.MemberCount)
+        for i in range(self.MemberCount):
+            data = CommFunc.WriteString(data, self.MemberList[i].GetLength(), self.MemberList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                FamilyID:%d,
+                                FamilyName:%s,
+                                FamilyLV:%d,
+                                FamilyLVExp:%d,
+                                JoinReview:%d,
+                                JoinLVMin:%d,
+                                ServerID:%d,
+                                EmblemID:%d,
+                                FightPower:%d,
+                                FightPowerEx:%d,
+                                BroadcastLen:%d,
+                                Broadcast:%s,
+                                LeaderID:%d,
+                                MemberCount:%d,
+                                MemberList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.FamilyID,
+                                self.FamilyName,
+                                self.FamilyLV,
+                                self.FamilyLVExp,
+                                self.JoinReview,
+                                self.JoinLVMin,
+                                self.ServerID,
+                                self.EmblemID,
+                                self.FightPower,
+                                self.FightPowerEx,
+                                self.BroadcastLen,
+                                self.Broadcast,
+                                self.LeaderID,
+                                self.MemberCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCRoleFamilyInfo=tagMCRoleFamilyInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCRoleFamilyInfo.Head.Cmd,m_NAtagMCRoleFamilyInfo.Head.SubCmd))] = m_NAtagMCRoleFamilyInfo
+
+
+#------------------------------------------------------
 # A6 05 VIP礼包购买记录 #tagMCVIPAwardMsg
 
 class  tagMCVIPAwardMsg(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBComm.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBComm.py
new file mode 100644
index 0000000..2f85eb3
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBComm.py
@@ -0,0 +1,74 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package DB.DBComm
+#
+# @todo:DBComm
+# @author hxp
+# @date 2025-05-09
+# @version 1.0
+#
+# 详细描述: DBComm
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-05-09 12:20"""
+#-------------------------------------------------------------------------------
+
+import json
+
+class UserDataDict():
+    '''根据数据自定义字符字段转化为字典处理,减少eval,方便快速存取
+    如果需要按list存储的,建议可以定义一个key然后还是按字典存储,方便之后扩展其他属性
+   所以所有的字符扩展数据建议统一以字典的格式存储,入库时可选直接转化为json格式或直接str
+    '''
+    
+    def __init__(self, dataObj, dataAttrName, dataLenAttrName, toJson=False):
+        '''
+        @param dataObj: 数据实例对象
+        @param dataAttrName: 字符扩展属性名
+        @param dataLenAttrName: 字符扩展属性长度名
+        '''
+        self.__dataObj = dataObj
+        self.__dataAttrName = dataAttrName
+        self.__dataLenAttrName = dataLenAttrName
+        self.__toJson = toJson
+        self.__dataDict = None
+        return
+    
+    def GetData(self):
+        if self.__dataDict == None:
+            try:
+                self.__dataDict = eval(getattr(self.__dataObj, self.__dataAttrName))
+            except:
+                self.__dataDict = {}
+        return self.__dataDict
+    
+    def SetData(self, setValue):
+        '''直接设置替换数据
+        @param dataStr: 可以是任意数据格式,如果是字典会进行Json或字符串转化
+        '''
+        if not setValue:
+            dataStr = ""
+        elif isinstance(setValue, dict) and self.__toJson:
+            dataStr = json.dumps(setValue, ensure_ascii=False)
+        else:
+            dataStr = str(setValue)
+        dataStr = dataStr.replace(" ", "") # 替换空格,减少长度
+        
+        if self.__dataObj:
+            setattr(self.__dataObj, self.__dataAttrName, dataStr)
+            setattr(self.__dataObj, self.__dataLenAttrName, len(dataStr))
+            
+        if setValue != None and isinstance(setValue, dict) and self.__dataDict != setValue:
+            self.__dataDict = setValue
+        return
+    
+    def ToString(self):
+        ## 转化为字符串
+        if self.__dataDict != None:
+            self.SetData(self.__dataDict)
+        return getattr(self.__dataObj, self.__dataAttrName)
+    
+    
+    
\ No newline at end of file
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBDataMgr.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBDataMgr.py
new file mode 100644
index 0000000..977f92f
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBDataMgr.py
@@ -0,0 +1,197 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Script.DB.DBDataMgr
+#
+# @todo:DB数据管理器
+# @author hxp
+# @date 2025-05-09
+# @version 1.0
+#
+# 详细描述: DB数据管理器
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-05-09 12:20"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import PyGameData
+import DBPlayerViewCache
+import DBFamily
+
+import binascii
+import time
+import zlib
+import os
+
+BakRoot = "C:\ServerRealTimeBackup"
+BakFileType = ".bak"
+
+#临时变量,之后优化
+g_loadErr = False
+Map2ServerID = {
+                10010:87,
+                10090:89,
+                }
+    
+def OnServerStart():
+    GameWorld.DebugLog("地图服务器启动")
+    LoadServerDataBackup()
+    return
+
+def OnServerClose():
+    return
+
+def OnMinute(curMinute):
+    ServerDataBackup()
+    DBFamily.OnMinute(curMinute)
+    return
+
+#------------------------------------------- 备档 ---------------------------------------------------
+def GetBakFileSortList(bakPath):
+    ## 按备档时间倒序排序返回 [[bakTime, filePath], ...]
+    bakFileList = []
+    for parent, _, filenames in os.walk(bakPath):
+        for filename in filenames:
+            if not filename.endswith(BakFileType):
+                continue
+            fullPath = os.path.join(parent, filename)
+            bakTime = GameWorld.ToIntDef(filename[:filename.index(".")].split("_")[1])
+            bakFileList.append([bakTime, fullPath])
+    bakFileList.sort(reverse=True)
+    return bakFileList
+
+def LoadServerDataBackup():
+    ## 服务器公共数据备档加载
+    global g_loadErr
+    mapID = GameWorld.GetMap().GetMapID()
+    if mapID not in Map2ServerID:
+        return
+    serverName = "S%s" % Map2ServerID[mapID]
+    BakDir = os.path.join(BakRoot, serverName)
+    GameWorld.Log("加载备档: %s" % BakDir)
+    bakFileList = GetBakFileSortList(BakDir)
+    if not bakFileList:
+        GameWorld.Log("不存在备档!")
+        return
+    bakFilePath = bakFileList[0][1] # 取第一个为最近的一次备档
+    GameWorld.Log("读取备档: %s" % bakFilePath)
+    
+    f = open(bakFilePath, 'rb')
+    compressed_data = f.read().strip()
+    f.close()
+    
+    try:
+        decompressed_data = zlib.decompress(compressed_data)
+        bakData = binascii.a2b_hex(decompressed_data)
+    except:
+        g_loadErr = True
+        raise 
+    
+    LoadPyGameData(bakData, 0)
+    return
+
+def ServerDataBackup():
+    ## 服务器公共数据定时备档,暂时直接存盘
+    if g_loadErr:
+        GameWorld.ErrLog("加载备档已异常,暂时不在存储备档")
+        return
+    mapID = GameWorld.GetMap().GetMapID()
+    if mapID not in Map2ServerID:
+        return
+    serverName = "S%s" % Map2ServerID[mapID]
+    BakDir = os.path.join(BakRoot, serverName)
+    BackupCopyMax = 3
+    GameWorld.Log("服务器备档: %s" % serverName)
+    
+    if not os.path.exists(BakDir):
+        os.makedirs(BakDir)
+        
+    curTime = int(time.time())
+    bakFilePath = os.path.join(BakDir, "%s_%s%s" % (serverName, curTime, BakFileType))
+    bakData = GetSavePyData()
+    GameWorld.Log("Bak:%s, len=%s, %s" % (serverName, len(bakData), bakFilePath))
+    try:
+        compressed_data = zlib.compress(bakData, 9)    #最大压缩
+        GameWorld.Log("compress len=%s" % len(compressed_data))
+        fp = open(bakFilePath, "wb")
+        fp.write(compressed_data)
+        fp.close()
+    except:
+        return
+    
+    bakFileList = GetBakFileSortList(BakDir)
+    # 删除多余备档
+    for _, filePath in bakFileList[BackupCopyMax:]:
+        os.remove(filePath)
+        GameWorld.Log("删除多余备档文件: %s" % filePath)
+        
+    return
+
+#--------------------------------------------------------------------------------------------------
+
+def GetSavePyData():
+    
+    #存储数据前,一些功能业务数据先转化为存档数据
+    #...
+    
+    pyGameDataMgr = GetDBDataMgr()
+    result = pyGameDataMgr.GetSaveData()
+    GameWorld.Log("GetSavePyData!! id = %s-%s"%(id(pyGameDataMgr), len(result)))
+    result = binascii.b2a_hex(result)
+    #GameWorld.DebugLog("GetSavePyData!! result = %s-%s"%(result, len(result)))
+    # 字节码在C++转化会发生错误must be string without null bytes, not str,但是可以正常保存,错误会在下次调用便宜接口才会触发
+    # 暂时改成字符串返回,暂无解决方案
+    return result
+#    return str(len(result)) + "|" + result
+
+def LoadPyGameData(gameBuffer, pos):
+    pyGameDataMgr = GetDBDataMgr()
+    GameWorld.Log("LoadPyGameData!!id = %s %s"%(id(pyGameDataMgr), len(gameBuffer)))
+    pos = pyGameDataMgr.LoadGameData(gameBuffer, pos)
+    
+    #加载数据后,一些功能转化为功能业务数据
+    #...
+    
+    return pos
+
+class PyGameDataManager(object):
+    def __init__(self):
+        self.PlayerViewCacheMgr = DBPlayerViewCache.PlayerViewCacheMgr()
+        self.FamilyMgr = DBFamily.FamilyMgr()
+        return
+    
+    def GetSaveData(self):
+        buff = ""
+        buff += self.PlayerViewCacheMgr.GetSaveData()
+        buff += self.FamilyMgr.GetSaveData()
+        return buff
+    
+    def LoadGameData(self, gameBuffer, pos):
+        pos = self.PlayerViewCacheMgr.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
+        pos = self.FamilyMgr.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
+        return pos
+    
+def GetDBDataMgr():
+    ## py数据库表数据管理器
+    pyGameDataMgr = PyGameData.g_pyGameDataManager
+    if not pyGameDataMgr:
+        pyGameDataMgr = PyGameDataManager()
+        PyGameData.g_pyGameDataManager = pyGameDataMgr
+    return pyGameDataMgr
+
+def GetPlayerViewCacheMgr():
+    ## 玩家查看缓存数据管理器
+    dbDataMgr = GetDBDataMgr()
+    return dbDataMgr.PlayerViewCacheMgr
+
+def GetFamilyMgr():
+    ## 家族数据管理器
+    dbDataMgr = GetDBDataMgr()
+    return dbDataMgr.FamilyMgr
+
+def GetFamilyActionMgr():
+    ## 家族Action数据管理器
+    return GetFamilyMgr().GetFamilyActionMgr()
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py
new file mode 100644
index 0000000..8fce029
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py
@@ -0,0 +1,1238 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package DB.DBStruct
+#
+# @todo:DB数据结构体
+# @author hxp
+# @date 2025-05-09
+# @version 1.0
+#
+# 详细描述: CodeMaker PyGameServerSaveData.py生成
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-05-09 12:20"""
+#-------------------------------------------------------------------------------
+
+import ctypes
+from ctypes import (Structure, memset, memmove, sizeof, addressof, create_string_buffer, string_at)
+import CommFunc
+
+#玩家详细信息#tagDBPlayer
+class tagDBPlayer(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('PlayerID', ctypes.c_ulong),
+        ('AccID', ctypes.c_char * 65),
+        ('PlayerName', ctypes.c_char * 33),
+        ('AccState', ctypes.c_ubyte),
+        ('IsDeleted', ctypes.c_ubyte),
+        ('GMLevel', ctypes.c_ubyte),
+        ('Sex', ctypes.c_int),
+        ('Hair', ctypes.c_int),
+        ('HairColor', ctypes.c_int),
+        ('Face', ctypes.c_int),
+        ('FacePic', ctypes.c_int),
+        ('Job', ctypes.c_int),
+        ('RoleType', ctypes.c_ulong),
+        ('ReincarnationLv', ctypes.c_ushort),
+        ('LV', ctypes.c_int),
+        ('TotalExp', ctypes.c_ulong),
+        ('FamilyID', ctypes.c_ulong),
+        ('FamilyName', ctypes.c_char * 33),
+        ('Country', ctypes.c_int),
+        ('TeamHornor', ctypes.c_ulong),
+        ('FamilyHornor', ctypes.c_ulong),
+        ('FamilyActiveValue', ctypes.c_ulong),
+        ('LastWeekFamilyActiveValue', ctypes.c_ulong),
+        ('CountryHornor', ctypes.c_ulong),
+        ('CountryLastWeekHornor', ctypes.c_ulong),
+        ('Mate', ctypes.c_ulong),
+        ('Gold', ctypes.c_ulong),
+        ('GoldPaper', ctypes.c_ulong),
+        ('Silver', ctypes.c_ulong),
+        ('SilverPaper', ctypes.c_ulong),
+        ('FightPoint', ctypes.c_ulong),
+        ('HappyPoint', ctypes.c_ulong),
+        ('MapID', ctypes.c_ulong),
+        ('DataMapID', ctypes.c_ulong),
+        ('CopyMapID', ctypes.c_ulong),
+        ('PosX', ctypes.c_ushort),
+        ('PosY', ctypes.c_ushort),
+        ('FromMapID', ctypes.c_ulong),
+        ('FromCopyMapID', ctypes.c_ulong),
+        ('FromPosX', ctypes.c_ushort),
+        ('FromPosY', ctypes.c_ushort),
+        ('State', ctypes.c_int),
+        ('HP', ctypes.c_ulong),
+        ('MP', ctypes.c_ulong),
+        ('XP', ctypes.c_ulong),
+        ('HPRestoreSetting', ctypes.c_ushort),
+        ('MPRestoreSetting', ctypes.c_ushort),
+        ('FreePoint', ctypes.c_ulong),
+        ('FreeSkillPoint', ctypes.c_ulong),
+        ('STR', ctypes.c_int),
+        ('PNE', ctypes.c_int),
+        ('PHY', ctypes.c_int),
+        ('CON', ctypes.c_int),
+        ('TotalSTR', ctypes.c_int),
+        ('TotalPNE', ctypes.c_int),
+        ('TotalPHY', ctypes.c_int),
+        ('TotalCON', ctypes.c_int),
+        ('Setting', ctypes.c_char * 100),
+        ('PKValue', ctypes.c_ushort),
+        ('FightPower', ctypes.c_ulong),
+        ('ActiveValue', ctypes.c_ushort),
+        ('PlayerType', ctypes.c_ubyte),
+        ('BackpackLV', ctypes.c_ubyte),
+        ('WarehouseLV', ctypes.c_ubyte),
+        ('HaveWarehousePsw', ctypes.c_ubyte),
+        ('WarehousePsw', ctypes.c_char * 15),
+        ('WarehouseLocked', ctypes.c_ubyte),
+        ('WarehouseGold', ctypes.c_ulong),
+        ('WarehouseSilver', ctypes.c_ulong),
+        ('TeamID', ctypes.c_ulong),
+        ('UseGoldType', ctypes.c_ubyte),
+        ('UseSilverType', ctypes.c_ubyte),
+        ('AttackMode', ctypes.c_ubyte),
+        ('RebornMapID', ctypes.c_ushort),
+        ('RebornPosX', ctypes.c_ushort),
+        ('RebornPosY', ctypes.c_ushort),
+        ('WeekOnlineTime', ctypes.c_ulong),
+        ('LastWeekOnlineTime', ctypes.c_ulong),
+        ('LogoffTime', ctypes.c_char * 30),
+        ('IsHideMask', ctypes.c_ubyte),
+        ('DayProcessGameEventCount', ctypes.c_ulong),
+        ('LoginIP', ctypes.c_char * 20),
+        ('LoginTime', ctypes.c_char * 30),
+        ('OnlineTime', ctypes.c_ulong),
+        ('FriendFavor', ctypes.c_ulong),
+        ('TeamPrivity', ctypes.c_ulong),
+        ('OfflineMinutes', ctypes.c_ulong),
+        ('Energy', ctypes.c_ulong),
+        ('ReceivedSalary', ctypes.c_ulong),
+        ('EquipShowSwitch', ctypes.c_ulong),
+        ('LuckValue', ctypes.c_ushort),
+        ('ExAttr1', ctypes.c_ulong),
+        ('ExAttr2', ctypes.c_ulong),
+        ('ExAttr3', ctypes.c_ulong),
+        ('ExAttr4', ctypes.c_ulong),
+        ('ExAttr5', ctypes.c_ulong),
+        ('Faction', ctypes.c_int),
+        ('InfamyValue', ctypes.c_ulong),
+        ('OfficialRank', ctypes.c_ubyte),
+        ('IsFindByLabel', ctypes.c_ubyte),
+        ('IsCloseFriendLabel', ctypes.c_ubyte),
+        ('ChangeCoinPointTotal', ctypes.c_ulong),
+        ('VIPLv', ctypes.c_ubyte),
+        ('VIPLvForPhone', ctypes.c_ubyte),
+        ('PhoneVIPStartTime', ctypes.c_double),
+        ('PhoneVIPEndTime', ctypes.c_double),
+        ('VsRoomId', ctypes.c_ulong),
+        ('ExAttr6', ctypes.c_ulong),
+        ('ExAttr7', ctypes.c_ulong),
+        ('ExAttr8', ctypes.c_ulong),
+        ('ExAttr9', ctypes.c_ulong),
+        ('ExAttr10', ctypes.c_ulong),
+        ('ModelMark', ctypes.c_ulong),
+        ('FromDataMapID', ctypes.c_ulong),
+        ('LastOrderId', ctypes.c_char * 40),
+        ('PrizeCoin', ctypes.c_ulong),
+        ('ExAttr11', ctypes.c_ulong),
+        ('ExAttr12', ctypes.c_ulong),
+        ('ExAttr13', ctypes.c_ulong),
+        ('ExAttr14', ctypes.c_ulong),
+        ('CreateRoleTime', ctypes.c_char * 30),
+        ('LVEx', ctypes.c_ushort),
+        ('LV2', ctypes.c_ushort),
+        ('ExpPoint', ctypes.c_ulong),
+        ('OperateInfo', ctypes.c_ulong),
+        ('Operate', ctypes.c_char * 15),
+        ('ServerID', ctypes.c_ulong),
+        ('ExAttr15', ctypes.c_ulong),
+        ('ExAttr16', ctypes.c_ulong),
+        ('ExAttr17', ctypes.c_ulong),
+        ('ExAttr18', ctypes.c_ulong),
+        ('ExAttr19', ctypes.c_ulong),
+        ('ExAttr20', ctypes.c_ulong),
+        ('HPEx', ctypes.c_ulong),
+        ('FightPowerEx', ctypes.c_ulong),
+        ('ADOResult', ctypes.c_ulong),
+    ]
+
+    def __init__(self):
+        Structure.__init__(self)
+        self.clear()
+
+
+    def clear(self):
+        memset(addressof(self), 0, self.getLength())
+
+    def readData(self, buf, pos = 0, length = 0):
+        if not pos <= length:
+            return -1
+        if len(buf) < pos + self.getLength():
+            return -1
+        self.clear()
+        self.PlayerID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.AccID, pos = CommFunc.ReadString(buf, pos, 65)
+        self.PlayerName, pos = CommFunc.ReadString(buf, pos, 33)
+        self.AccState, pos = CommFunc.ReadBYTE(buf, pos)
+        self.IsDeleted, pos = CommFunc.ReadBYTE(buf, pos)
+        self.GMLevel, pos = CommFunc.ReadBYTE(buf, pos)
+        self.Sex, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Hair, pos = CommFunc.ReadDWORD(buf, pos)
+        self.HairColor, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Face, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FacePic, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Job, pos = CommFunc.ReadDWORD(buf, pos)
+        self.RoleType, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ReincarnationLv, pos = CommFunc.ReadWORD(buf, pos)
+        self.LV, pos = CommFunc.ReadDWORD(buf, pos)
+        self.TotalExp, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FamilyID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FamilyName, pos = CommFunc.ReadString(buf, pos, 33)
+        self.Country, pos = CommFunc.ReadDWORD(buf, pos)
+        self.TeamHornor, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FamilyHornor, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FamilyActiveValue, pos = CommFunc.ReadDWORD(buf, pos)
+        self.LastWeekFamilyActiveValue, pos = CommFunc.ReadDWORD(buf, pos)
+        self.CountryHornor, pos = CommFunc.ReadDWORD(buf, pos)
+        self.CountryLastWeekHornor, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Mate, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Gold, pos = CommFunc.ReadDWORD(buf, pos)
+        self.GoldPaper, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Silver, pos = CommFunc.ReadDWORD(buf, pos)
+        self.SilverPaper, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FightPoint, pos = CommFunc.ReadDWORD(buf, pos)
+        self.HappyPoint, pos = CommFunc.ReadDWORD(buf, pos)
+        self.MapID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.DataMapID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.CopyMapID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.PosX, pos = CommFunc.ReadWORD(buf, pos)
+        self.PosY, pos = CommFunc.ReadWORD(buf, pos)
+        self.FromMapID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FromCopyMapID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FromPosX, pos = CommFunc.ReadWORD(buf, pos)
+        self.FromPosY, pos = CommFunc.ReadWORD(buf, pos)
+        self.State, pos = CommFunc.ReadDWORD(buf, pos)
+        self.HP, pos = CommFunc.ReadDWORD(buf, pos)
+        self.MP, pos = CommFunc.ReadDWORD(buf, pos)
+        self.XP, pos = CommFunc.ReadDWORD(buf, pos)
+        self.HPRestoreSetting, pos = CommFunc.ReadWORD(buf, pos)
+        self.MPRestoreSetting, pos = CommFunc.ReadWORD(buf, pos)
+        self.FreePoint, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FreeSkillPoint, pos = CommFunc.ReadDWORD(buf, pos)
+        self.STR, pos = CommFunc.ReadDWORD(buf, pos)
+        self.PNE, pos = CommFunc.ReadDWORD(buf, pos)
+        self.PHY, pos = CommFunc.ReadDWORD(buf, pos)
+        self.CON, pos = CommFunc.ReadDWORD(buf, pos)
+        self.TotalSTR, pos = CommFunc.ReadDWORD(buf, pos)
+        self.TotalPNE, pos = CommFunc.ReadDWORD(buf, pos)
+        self.TotalPHY, pos = CommFunc.ReadDWORD(buf, pos)
+        self.TotalCON, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Setting, pos = CommFunc.ReadString(buf, pos, 100)
+        self.PKValue, pos = CommFunc.ReadWORD(buf, pos)
+        self.FightPower, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ActiveValue, pos = CommFunc.ReadWORD(buf, pos)
+        self.PlayerType, pos = CommFunc.ReadBYTE(buf, pos)
+        self.BackpackLV, pos = CommFunc.ReadBYTE(buf, pos)
+        self.WarehouseLV, pos = CommFunc.ReadBYTE(buf, pos)
+        self.HaveWarehousePsw, pos = CommFunc.ReadBYTE(buf, pos)
+        self.WarehousePsw, pos = CommFunc.ReadString(buf, pos, 15)
+        self.WarehouseLocked, pos = CommFunc.ReadBYTE(buf, pos)
+        self.WarehouseGold, pos = CommFunc.ReadDWORD(buf, pos)
+        self.WarehouseSilver, pos = CommFunc.ReadDWORD(buf, pos)
+        self.TeamID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.UseGoldType, pos = CommFunc.ReadBYTE(buf, pos)
+        self.UseSilverType, pos = CommFunc.ReadBYTE(buf, pos)
+        self.AttackMode, pos = CommFunc.ReadBYTE(buf, pos)
+        self.RebornMapID, pos = CommFunc.ReadWORD(buf, pos)
+        self.RebornPosX, pos = CommFunc.ReadWORD(buf, pos)
+        self.RebornPosY, pos = CommFunc.ReadWORD(buf, pos)
+        self.WeekOnlineTime, pos = CommFunc.ReadDWORD(buf, pos)
+        self.LastWeekOnlineTime, pos = CommFunc.ReadDWORD(buf, pos)
+        self.LogoffTime, pos = CommFunc.ReadString(buf, pos, 30)
+        self.IsHideMask, pos = CommFunc.ReadBYTE(buf, pos)
+        self.DayProcessGameEventCount, pos = CommFunc.ReadDWORD(buf, pos)
+        self.LoginIP, pos = CommFunc.ReadString(buf, pos, 20)
+        self.LoginTime, pos = CommFunc.ReadString(buf, pos, 30)
+        self.OnlineTime, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FriendFavor, pos = CommFunc.ReadDWORD(buf, pos)
+        self.TeamPrivity, pos = CommFunc.ReadDWORD(buf, pos)
+        self.OfflineMinutes, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Energy, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ReceivedSalary, pos = CommFunc.ReadDWORD(buf, pos)
+        self.EquipShowSwitch, pos = CommFunc.ReadDWORD(buf, pos)
+        self.LuckValue, pos = CommFunc.ReadWORD(buf, pos)
+        self.ExAttr1, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr2, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr3, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr4, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr5, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Faction, pos = CommFunc.ReadDWORD(buf, pos)
+        self.InfamyValue, pos = CommFunc.ReadDWORD(buf, pos)
+        self.OfficialRank, pos = CommFunc.ReadBYTE(buf, pos)
+        self.IsFindByLabel, pos = CommFunc.ReadBYTE(buf, pos)
+        self.IsCloseFriendLabel, pos = CommFunc.ReadBYTE(buf, pos)
+        self.ChangeCoinPointTotal, pos = CommFunc.ReadDWORD(buf, pos)
+        self.VIPLv, pos = CommFunc.ReadBYTE(buf, pos)
+        self.VIPLvForPhone, pos = CommFunc.ReadBYTE(buf, pos)
+        self.PhoneVIPStartTime, pos = CommFunc.ReadDouble(buf, pos)
+        self.PhoneVIPEndTime, pos = CommFunc.ReadDouble(buf, pos)
+        self.VsRoomId, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr6, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr7, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr8, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr9, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr10, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ModelMark, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FromDataMapID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.LastOrderId, pos = CommFunc.ReadString(buf, pos, 40)
+        self.PrizeCoin, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr11, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr12, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr13, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr14, pos = CommFunc.ReadDWORD(buf, pos)
+        self.CreateRoleTime, pos = CommFunc.ReadString(buf, pos, 30)
+        self.LVEx, pos = CommFunc.ReadWORD(buf, pos)
+        self.LV2, pos = CommFunc.ReadWORD(buf, pos)
+        self.ExpPoint, pos = CommFunc.ReadDWORD(buf, pos)
+        self.OperateInfo, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Operate, pos = CommFunc.ReadString(buf, pos, 15)
+        self.ServerID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr15, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr16, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr17, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr18, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr19, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ExAttr20, pos = CommFunc.ReadDWORD(buf, pos)
+        self.HPEx, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FightPowerEx, pos = CommFunc.ReadDWORD(buf, pos)
+        return self.getLength()
+
+
+    def getBuffer(self):
+        buf = create_string_buffer(self.getLength())
+        memmove(addressof(buf), addressof(self), self.getLength())
+        return string_at(addressof(buf), self.getLength())
+
+    def getLength(self):
+        return sizeof(tagDBPlayer)
+
+    def outputString(self):
+        output = '''//玩家详细信息#tagDBPlayer:
+            PlayerID = %s,
+            AccID = %s,
+            PlayerName = %s,
+            AccState = %s,
+            IsDeleted = %s,
+            GMLevel = %s,
+            Sex = %s,
+            Hair = %s,
+            HairColor = %s,
+            Face = %s,
+            FacePic = %s,
+            Job = %s,
+            RoleType = %s,
+            ReincarnationLv = %s,
+            LV = %s,
+            TotalExp = %s,
+            FamilyID = %s,
+            FamilyName = %s,
+            Country = %s,
+            TeamHornor = %s,
+            FamilyHornor = %s,
+            FamilyActiveValue = %s,
+            LastWeekFamilyActiveValue = %s,
+            CountryHornor = %s,
+            CountryLastWeekHornor = %s,
+            Mate = %s,
+            Gold = %s,
+            GoldPaper = %s,
+            Silver = %s,
+            SilverPaper = %s,
+            FightPoint = %s,
+            HappyPoint = %s,
+            MapID = %s,
+            DataMapID = %s,
+            CopyMapID = %s,
+            PosX = %s,
+            PosY = %s,
+            FromMapID = %s,
+            FromCopyMapID = %s,
+            FromPosX = %s,
+            FromPosY = %s,
+            State = %s,
+            HP = %s,
+            MP = %s,
+            XP = %s,
+            HPRestoreSetting = %s,
+            MPRestoreSetting = %s,
+            FreePoint = %s,
+            FreeSkillPoint = %s,
+            STR = %s,
+            PNE = %s,
+            PHY = %s,
+            CON = %s,
+            TotalSTR = %s,
+            TotalPNE = %s,
+            TotalPHY = %s,
+            TotalCON = %s,
+            Setting = %s,
+            PKValue = %s,
+            FightPower = %s,
+            ActiveValue = %s,
+            PlayerType = %s,
+            BackpackLV = %s,
+            WarehouseLV = %s,
+            HaveWarehousePsw = %s,
+            WarehousePsw = %s,
+            WarehouseLocked = %s,
+            WarehouseGold = %s,
+            WarehouseSilver = %s,
+            TeamID = %s,
+            UseGoldType = %s,
+            UseSilverType = %s,
+            AttackMode = %s,
+            RebornMapID = %s,
+            RebornPosX = %s,
+            RebornPosY = %s,
+            WeekOnlineTime = %s,
+            LastWeekOnlineTime = %s,
+            LogoffTime = %s,
+            IsHideMask = %s,
+            DayProcessGameEventCount = %s,
+            LoginIP = %s,
+            LoginTime = %s,
+            OnlineTime = %s,
+            FriendFavor = %s,
+            TeamPrivity = %s,
+            OfflineMinutes = %s,
+            Energy = %s,
+            ReceivedSalary = %s,
+            EquipShowSwitch = %s,
+            LuckValue = %s,
+            ExAttr1 = %s,
+            ExAttr2 = %s,
+            ExAttr3 = %s,
+            ExAttr4 = %s,
+            ExAttr5 = %s,
+            Faction = %s,
+            InfamyValue = %s,
+            OfficialRank = %s,
+            IsFindByLabel = %s,
+            IsCloseFriendLabel = %s,
+            ChangeCoinPointTotal = %s,
+            VIPLv = %s,
+            VIPLvForPhone = %s,
+            PhoneVIPStartTime = %s,
+            PhoneVIPEndTime = %s,
+            VsRoomId = %s,
+            ExAttr6 = %s,
+            ExAttr7 = %s,
+            ExAttr8 = %s,
+            ExAttr9 = %s,
+            ExAttr10 = %s,
+            ModelMark = %s,
+            FromDataMapID = %s,
+            LastOrderId = %s,
+            PrizeCoin = %s,
+            ExAttr11 = %s,
+            ExAttr12 = %s,
+            ExAttr13 = %s,
+            ExAttr14 = %s,
+            CreateRoleTime = %s,
+            LVEx = %s,
+            LV2 = %s,
+            ExpPoint = %s,
+            OperateInfo = %s,
+            Operate = %s,
+            ServerID = %s,
+            ExAttr15 = %s,
+            ExAttr16 = %s,
+            ExAttr17 = %s,
+            ExAttr18 = %s,
+            ExAttr19 = %s,
+            ExAttr20 = %s,
+            HPEx = %s,
+            FightPowerEx = %s,
+            ADOResult = %s,
+            '''%(
+                self.PlayerID,
+                self.AccID,
+                self.PlayerName,
+                self.AccState,
+                self.IsDeleted,
+                self.GMLevel,
+                self.Sex,
+                self.Hair,
+                self.HairColor,
+                self.Face,
+                self.FacePic,
+                self.Job,
+                self.RoleType,
+                self.ReincarnationLv,
+                self.LV,
+                self.TotalExp,
+                self.FamilyID,
+                self.FamilyName,
+                self.Country,
+                self.TeamHornor,
+                self.FamilyHornor,
+                self.FamilyActiveValue,
+                self.LastWeekFamilyActiveValue,
+                self.CountryHornor,
+                self.CountryLastWeekHornor,
+                self.Mate,
+                self.Gold,
+                self.GoldPaper,
+                self.Silver,
+                self.SilverPaper,
+                self.FightPoint,
+                self.HappyPoint,
+                self.MapID,
+                self.DataMapID,
+                self.CopyMapID,
+                self.PosX,
+                self.PosY,
+                self.FromMapID,
+                self.FromCopyMapID,
+                self.FromPosX,
+                self.FromPosY,
+                self.State,
+                self.HP,
+                self.MP,
+                self.XP,
+                self.HPRestoreSetting,
+                self.MPRestoreSetting,
+                self.FreePoint,
+                self.FreeSkillPoint,
+                self.STR,
+                self.PNE,
+                self.PHY,
+                self.CON,
+                self.TotalSTR,
+                self.TotalPNE,
+                self.TotalPHY,
+                self.TotalCON,
+                self.Setting,
+                self.PKValue,
+                self.FightPower,
+                self.ActiveValue,
+                self.PlayerType,
+                self.BackpackLV,
+                self.WarehouseLV,
+                self.HaveWarehousePsw,
+                self.WarehousePsw,
+                self.WarehouseLocked,
+                self.WarehouseGold,
+                self.WarehouseSilver,
+                self.TeamID,
+                self.UseGoldType,
+                self.UseSilverType,
+                self.AttackMode,
+                self.RebornMapID,
+                self.RebornPosX,
+                self.RebornPosY,
+                self.WeekOnlineTime,
+                self.LastWeekOnlineTime,
+                self.LogoffTime,
+                self.IsHideMask,
+                self.DayProcessGameEventCount,
+                self.LoginIP,
+                self.LoginTime,
+                self.OnlineTime,
+                self.FriendFavor,
+                self.TeamPrivity,
+                self.OfflineMinutes,
+                self.Energy,
+                self.ReceivedSalary,
+                self.EquipShowSwitch,
+                self.LuckValue,
+                self.ExAttr1,
+                self.ExAttr2,
+                self.ExAttr3,
+                self.ExAttr4,
+                self.ExAttr5,
+                self.Faction,
+                self.InfamyValue,
+                self.OfficialRank,
+                self.IsFindByLabel,
+                self.IsCloseFriendLabel,
+                self.ChangeCoinPointTotal,
+                self.VIPLv,
+                self.VIPLvForPhone,
+                self.PhoneVIPStartTime,
+                self.PhoneVIPEndTime,
+                self.VsRoomId,
+                self.ExAttr6,
+                self.ExAttr7,
+                self.ExAttr8,
+                self.ExAttr9,
+                self.ExAttr10,
+                self.ModelMark,
+                self.FromDataMapID,
+                self.LastOrderId,
+                self.PrizeCoin,
+                self.ExAttr11,
+                self.ExAttr12,
+                self.ExAttr13,
+                self.ExAttr14,
+                self.CreateRoleTime,
+                self.LVEx,
+                self.LV2,
+                self.ExpPoint,
+                self.OperateInfo,
+                self.Operate,
+                self.ServerID,
+                self.ExAttr15,
+                self.ExAttr16,
+                self.ExAttr17,
+                self.ExAttr18,
+                self.ExAttr19,
+                self.ExAttr20,
+                self.HPEx,
+                self.FightPowerEx,
+                self.ADOResult,
+            )
+        return output
+
+    #Char数组类型Set接口,使用该接口对此类型数据赋值,防止赋值的数据过长报错
+    def SetAccID(self,Str):
+        if len(Str)<=65:
+            self.AccID = Str
+        else:
+            self.AccID = Str[:65]
+            
+    def SetPlayerName(self,Str):
+        if len(Str)<=33:
+            self.PlayerName = Str
+        else:
+            self.PlayerName = Str[:33]
+            
+    def SetFamilyName(self,Str):
+        if len(Str)<=33:
+            self.FamilyName = Str
+        else:
+            self.FamilyName = Str[:33]
+            
+    def SetSetting(self,Str):
+        if len(Str)<=100:
+            self.Setting = Str
+        else:
+            self.Setting = Str[:100]
+            
+    def SetWarehousePsw(self,Str):
+        if len(Str)<=15:
+            self.WarehousePsw = Str
+        else:
+            self.WarehousePsw = Str[:15]
+            
+    def SetLogoffTime(self,Str):
+        if len(Str)<=30:
+            self.LogoffTime = Str
+        else:
+            self.LogoffTime = Str[:30]
+            
+    def SetLoginIP(self,Str):
+        if len(Str)<=20:
+            self.LoginIP = Str
+        else:
+            self.LoginIP = Str[:20]
+            
+    def SetLoginTime(self,Str):
+        if len(Str)<=30:
+            self.LoginTime = Str
+        else:
+            self.LoginTime = Str[:30]
+            
+    def SetLastOrderId(self,Str):
+        if len(Str)<=40:
+            self.LastOrderId = Str
+        else:
+            self.LastOrderId = Str[:40]
+            
+    def SetCreateRoleTime(self,Str):
+        if len(Str)<=30:
+            self.CreateRoleTime = Str
+        else:
+            self.CreateRoleTime = Str[:30]
+            
+    def SetOperate(self,Str):
+        if len(Str)<=15:
+            self.Operate = Str
+        else:
+            self.Operate = Str[:15]
+
+            
+# 家族表 #tagDBFamily
+class tagDBFamily(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ID', ctypes.c_ulong),
+        ('Name', ctypes.c_char * 33),
+        ('LeaderID', ctypes.c_ulong),
+        ('LV', ctypes.c_ubyte),
+        ('Exp', ctypes.c_ulong),
+        ('JoinReview', ctypes.c_ubyte),
+        ('JoinLVMin', ctypes.c_ushort),
+        ('CreateTime', ctypes.c_ulong),
+        ('ServerID', ctypes.c_ulong),
+        ('BroadcastLen', ctypes.c_ubyte),
+        ('Broadcast', ctypes.c_char_p),
+        ('FightPower', ctypes.c_ulong),
+        ('FightPowerEx', ctypes.c_ulong),
+        ('EmblemID', ctypes.c_ushort),
+        ('ADOResult', ctypes.c_ulong),
+    ]
+
+    def __init__(self):
+        Structure.__init__(self)
+        self.clear()
+
+    def clear(self):
+        self.ID = 0
+        self.Name = ''
+        self.LeaderID = 0
+        self.LV = 0
+        self.Exp = 0
+        self.JoinReview = 0
+        self.JoinLVMin = 0
+        self.CreateTime = 0
+        self.ServerID = 0
+        self.BroadcastLen = 0
+        self.Broadcast = ''
+        self.FightPower = 0
+        self.FightPowerEx = 0
+        self.EmblemID = 0
+
+    def readData(self, buf, pos = 0, length = 0):
+        if not pos <= length:
+            return -1
+        if len(buf) < pos + self.getLength():
+            return -1
+        self.clear()
+        self.ID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Name, pos = CommFunc.ReadString(buf, pos, 33)
+        self.LeaderID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.LV, pos = CommFunc.ReadBYTE(buf, pos)
+        self.Exp, pos = CommFunc.ReadDWORD(buf, pos)
+        self.JoinReview, pos = CommFunc.ReadBYTE(buf, pos)
+        self.JoinLVMin, pos = CommFunc.ReadWORD(buf, pos)
+        self.CreateTime, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ServerID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.BroadcastLen, pos = CommFunc.ReadBYTE(buf, pos)
+        tmp, pos = CommFunc.ReadString(buf, pos, self.BroadcastLen)
+        self.Broadcast = ctypes.c_char_p(tmp)
+        self.FightPower, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FightPowerEx, pos = CommFunc.ReadDWORD(buf, pos)
+        self.EmblemID, pos = CommFunc.ReadWORD(buf, pos)
+        return self.getLength()
+
+    def getBuffer(self):
+        buf = ''
+        buf = CommFunc.WriteDWORD(buf, self.ID)
+        buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 33, self.Name)
+        buf = CommFunc.WriteDWORD(buf, self.LeaderID)
+        buf = CommFunc.WriteBYTE(buf, self.LV)
+        buf = CommFunc.WriteDWORD(buf, self.Exp)
+        buf = CommFunc.WriteBYTE(buf, self.JoinReview)
+        buf = CommFunc.WriteWORD(buf, self.JoinLVMin)
+        buf = CommFunc.WriteDWORD(buf, self.CreateTime)
+        buf = CommFunc.WriteDWORD(buf, self.ServerID)
+        buf = CommFunc.WriteBYTE(buf, self.BroadcastLen)
+        buf = CommFunc.WriteString(buf, self.BroadcastLen, self.Broadcast)
+        buf = CommFunc.WriteDWORD(buf, self.FightPower)
+        buf = CommFunc.WriteDWORD(buf, self.FightPowerEx)
+        buf = CommFunc.WriteWORD(buf, self.EmblemID)
+        return buf
+
+    def getLength(self):
+        length = 0
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_char) * 33
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ubyte)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ubyte)
+        length += sizeof(ctypes.c_ushort)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ubyte)
+        length += self.BroadcastLen
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ushort)
+        return length
+
+    def outputString(self):
+        output = '''// 家族表 #tagDBFamily:
+            ID = %s,
+            Name = %s,
+            LeaderID = %s,
+            LV = %s,
+            Exp = %s,
+            JoinReview = %s,
+            JoinLVMin = %s,
+            CreateTime = %s,
+            ServerID = %s,
+            BroadcastLen = %s,
+            Broadcast = %s,
+            FightPower = %s,
+            FightPowerEx = %s,
+            EmblemID = %s,
+            ADOResult = %s,
+            '''%(
+                self.ID,
+                self.Name,
+                self.LeaderID,
+                self.LV,
+                self.Exp,
+                self.JoinReview,
+                self.JoinLVMin,
+                self.CreateTime,
+                self.ServerID,
+                self.BroadcastLen,
+                self.Broadcast,
+                self.FightPower,
+                self.FightPowerEx,
+                self.EmblemID,
+                self.ADOResult,
+            )
+        return output
+
+    #Char数组类型Set接口,使用该接口对此类型数据赋值,防止赋值的数据过长报错
+    def SetName(self,Str):
+        if len(Str)<=33:
+            self.Name = Str
+        else:
+            self.Name = Str[:33]
+            
+
+# 家族成员表 #tagDBFamilyMem
+class tagDBFamilyMem(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('PlayerID', ctypes.c_ulong),
+        ('FamilyID', ctypes.c_ulong),
+        ('JoinTime', ctypes.c_ulong),
+        ('PlayerName', ctypes.c_char * 33),
+        ('LV', ctypes.c_int),
+        ('Job', ctypes.c_int),
+        ('RealmLV', ctypes.c_ubyte),
+        ('Face', ctypes.c_int),
+        ('FacePic', ctypes.c_int),
+        ('FightPower', ctypes.c_ulong),
+        ('FightPowerEx', ctypes.c_ulong),
+        ('ServerID', ctypes.c_ulong),
+        ('OffTime', ctypes.c_ulong),
+        ('FmLV', ctypes.c_ubyte),
+        ('ContribTotal', ctypes.c_ulong),
+        ('ContribWeek', ctypes.c_ulong),
+        ('ADOResult', ctypes.c_ulong),
+    ]
+
+    def __init__(self):
+        Structure.__init__(self)
+        self.clear()
+
+
+    def clear(self):
+        memset(addressof(self), 0, self.getLength())
+
+    def readData(self, buf, pos = 0, length = 0):
+        if not pos <= length:
+            return -1
+        if len(buf) < pos + self.getLength():
+            return -1
+        self.clear()
+        self.PlayerID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FamilyID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.JoinTime, pos = CommFunc.ReadDWORD(buf, pos)
+        self.PlayerName, pos = CommFunc.ReadString(buf, pos, 33)
+        self.LV, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Job, pos = CommFunc.ReadDWORD(buf, pos)
+        self.RealmLV, pos = CommFunc.ReadBYTE(buf, pos)
+        self.Face, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FacePic, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FightPower, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FightPowerEx, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ServerID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.OffTime, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FmLV, pos = CommFunc.ReadBYTE(buf, pos)
+        self.ContribTotal, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ContribWeek, pos = CommFunc.ReadDWORD(buf, pos)
+        return self.getLength()
+
+
+    def getBuffer(self):
+        buf = create_string_buffer(self.getLength())
+        memmove(addressof(buf), addressof(self), self.getLength())
+        return string_at(addressof(buf), self.getLength())
+
+    def getLength(self):
+        return sizeof(tagDBFamilyMem)
+
+    def outputString(self):
+        output = '''// 家族成员表 #tagDBFamilyMem:
+            PlayerID = %s,
+            FamilyID = %s,
+            JoinTime = %s,
+            PlayerName = %s,
+            LV = %s,
+            Job = %s,
+            RealmLV = %s,
+            Face = %s,
+            FacePic = %s,
+            FightPower = %s,
+            FightPowerEx = %s,
+            ServerID = %s,
+            OffTime = %s,
+            FmLV = %s,
+            ContribTotal = %s,
+            ContribWeek = %s,
+            ADOResult = %s,
+            '''%(
+                self.PlayerID,
+                self.FamilyID,
+                self.JoinTime,
+                self.PlayerName,
+                self.LV,
+                self.Job,
+                self.RealmLV,
+                self.Face,
+                self.FacePic,
+                self.FightPower,
+                self.FightPowerEx,
+                self.ServerID,
+                self.OffTime,
+                self.FmLV,
+                self.ContribTotal,
+                self.ContribWeek,
+                self.ADOResult,
+            )
+        return output
+
+    #Char数组类型Set接口,使用该接口对此类型数据赋值,防止赋值的数据过长报错
+    def SetPlayerName(self,Str):
+        if len(Str)<=33:
+            self.PlayerName = Str
+        else:
+            self.PlayerName = Str[:33]
+
+
+# 家族行为表 #tagDBFamilyAction
+class tagDBFamilyAction(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('FamilyID', ctypes.c_ulong),
+        ('ActionType', ctypes.c_ubyte),
+        ('Name', ctypes.c_char * 33),
+        ('Time', ctypes.c_ulong),
+        ('Value1', ctypes.c_ulong),
+        ('Value2', ctypes.c_ulong),
+        ('Value3', ctypes.c_ulong),
+        ('Value4', ctypes.c_ulong),
+        ('Value5', ctypes.c_ulong),
+        ('Value6', ctypes.c_ulong),
+        ('DataLen', ctypes.c_ushort),
+        ('Data', ctypes.c_char_p),
+        ('ADOResult', ctypes.c_ulong),
+    ]
+
+    def __init__(self):
+        Structure.__init__(self)
+        self.clear()
+
+    def clear(self):
+        self.FamilyID = 0
+        self.ActionType = 0
+        self.Name = ''
+        self.Time = 0
+        self.Value1 = 0
+        self.Value2 = 0
+        self.Value3 = 0
+        self.Value4 = 0
+        self.Value5 = 0
+        self.Value6 = 0
+        self.DataLen = 0
+        self.Data = ''
+
+    def readData(self, buf, pos = 0, length = 0):
+        if not pos <= length:
+            return -1
+        if len(buf) < pos + self.getLength():
+            return -1
+        self.clear()
+        self.FamilyID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ActionType, pos = CommFunc.ReadBYTE(buf, pos)
+        self.Name, pos = CommFunc.ReadString(buf, pos, 33)
+        self.Time, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Value1, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Value2, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Value3, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Value4, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Value5, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Value6, pos = CommFunc.ReadDWORD(buf, pos)
+        self.DataLen, pos = CommFunc.ReadWORD(buf, pos)
+        tmp, pos = CommFunc.ReadString(buf, pos, self.DataLen)
+        self.Data = ctypes.c_char_p(tmp)
+        return self.getLength()
+
+    def getBuffer(self):
+        buf = ''
+        buf = CommFunc.WriteDWORD(buf, self.FamilyID)
+        buf = CommFunc.WriteBYTE(buf, self.ActionType)
+        buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 33, self.Name)
+        buf = CommFunc.WriteDWORD(buf, self.Time)
+        buf = CommFunc.WriteDWORD(buf, self.Value1)
+        buf = CommFunc.WriteDWORD(buf, self.Value2)
+        buf = CommFunc.WriteDWORD(buf, self.Value3)
+        buf = CommFunc.WriteDWORD(buf, self.Value4)
+        buf = CommFunc.WriteDWORD(buf, self.Value5)
+        buf = CommFunc.WriteDWORD(buf, self.Value6)
+        buf = CommFunc.WriteWORD(buf, self.DataLen)
+        buf = CommFunc.WriteString(buf, self.DataLen, self.Data)
+        return buf
+
+    def getLength(self):
+        length = 0
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ubyte)
+        length += sizeof(ctypes.c_char) * 33
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ushort)
+        length += self.DataLen
+        return length
+
+    def outputString(self):
+        output = '''// 家族行为表 #tagDBFamilyAction:
+            FamilyID = %s,
+            ActionType = %s,
+            Name = %s,
+            Time = %s,
+            Value1 = %s,
+            Value2 = %s,
+            Value3 = %s,
+            Value4 = %s,
+            Value5 = %s,
+            Value6 = %s,
+            DataLen = %s,
+            Data = %s,
+            ADOResult = %s,
+            '''%(
+                self.FamilyID,
+                self.ActionType,
+                self.Name,
+                self.Time,
+                self.Value1,
+                self.Value2,
+                self.Value3,
+                self.Value4,
+                self.Value5,
+                self.Value6,
+                self.DataLen,
+                self.Data,
+                self.ADOResult,
+            )
+        return output
+
+    #Char数组类型Set接口,使用该接口对此类型数据赋值,防止赋值的数据过长报错
+    def SetName(self,Str):
+        if len(Str)<=33:
+            self.Name = Str
+        else:
+            self.Name = Str[:33]
+            
+
+# 玩家查看缓存表 #tagDBPlayerViewCache
+class tagDBPlayerViewCache(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('PlayerID', ctypes.c_ulong),
+        ('AccID', ctypes.c_char * 65),
+        ('PlayerName', ctypes.c_char * 33),
+        ('LV', ctypes.c_int),
+        ('Job', ctypes.c_int),
+        ('RealmLV', ctypes.c_ubyte),
+        ('Face', ctypes.c_int),
+        ('FacePic', ctypes.c_int),
+        ('FamilyID', ctypes.c_ulong),
+        ('FamilyName', ctypes.c_char * 33),
+        ('FamilyEmblemID', ctypes.c_ushort),
+        ('TitleID', ctypes.c_ulong),
+        ('FightPower', ctypes.c_ulong),
+        ('FightPowerEx', ctypes.c_ulong),
+        ('ServerID', ctypes.c_ulong),
+        ('OffTime', ctypes.c_ulong),
+        ('PlusDataSize', ctypes.c_ulong),
+        ('PlusData', ctypes.c_char_p),
+        ('ADOResult', ctypes.c_ulong),
+    ]
+
+    def __init__(self):
+        Structure.__init__(self)
+        self.clear()
+
+    def clear(self):
+        self.PlayerID = 0
+        self.AccID = ''
+        self.PlayerName = ''
+        self.LV = 0
+        self.Job = 0
+        self.RealmLV = 0
+        self.Face = 0
+        self.FacePic = 0
+        self.FamilyID = 0
+        self.FamilyName = ''
+        self.FamilyEmblemID = 0
+        self.TitleID = 0
+        self.FightPower = 0
+        self.FightPowerEx = 0
+        self.ServerID = 0
+        self.OffTime = 0
+        self.PlusDataSize = 0
+        self.PlusData = ''
+
+    def readData(self, buf, pos = 0, length = 0):
+        if not pos <= length:
+            return -1
+        if len(buf) < pos + self.getLength():
+            return -1
+        self.clear()
+        self.PlayerID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.AccID, pos = CommFunc.ReadString(buf, pos, 65)
+        self.PlayerName, pos = CommFunc.ReadString(buf, pos, 33)
+        self.LV, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Job, pos = CommFunc.ReadDWORD(buf, pos)
+        self.RealmLV, pos = CommFunc.ReadBYTE(buf, pos)
+        self.Face, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FacePic, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FamilyID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FamilyName, pos = CommFunc.ReadString(buf, pos, 33)
+        self.FamilyEmblemID, pos = CommFunc.ReadWORD(buf, pos)
+        self.TitleID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FightPower, pos = CommFunc.ReadDWORD(buf, pos)
+        self.FightPowerEx, pos = CommFunc.ReadDWORD(buf, pos)
+        self.ServerID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.OffTime, pos = CommFunc.ReadDWORD(buf, pos)
+        self.PlusDataSize, pos = CommFunc.ReadDWORD(buf, pos)
+        tmp, pos = CommFunc.ReadString(buf, pos, self.PlusDataSize)
+        self.PlusData = ctypes.c_char_p(tmp)
+        return self.getLength()
+
+    def getBuffer(self):
+        buf = ''
+        buf = CommFunc.WriteDWORD(buf, self.PlayerID)
+        buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 65, self.AccID)
+        buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 33, self.PlayerName)
+        buf = CommFunc.WriteDWORD(buf, self.LV)
+        buf = CommFunc.WriteDWORD(buf, self.Job)
+        buf = CommFunc.WriteBYTE(buf, self.RealmLV)
+        buf = CommFunc.WriteDWORD(buf, self.Face)
+        buf = CommFunc.WriteDWORD(buf, self.FacePic)
+        buf = CommFunc.WriteDWORD(buf, self.FamilyID)
+        buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 33, self.FamilyName)
+        buf = CommFunc.WriteWORD(buf, self.FamilyEmblemID)
+        buf = CommFunc.WriteDWORD(buf, self.TitleID)
+        buf = CommFunc.WriteDWORD(buf, self.FightPower)
+        buf = CommFunc.WriteDWORD(buf, self.FightPowerEx)
+        buf = CommFunc.WriteDWORD(buf, self.ServerID)
+        buf = CommFunc.WriteDWORD(buf, self.OffTime)
+        buf = CommFunc.WriteDWORD(buf, self.PlusDataSize)
+        buf = CommFunc.WriteString(buf, self.PlusDataSize, self.PlusData)
+        return buf
+
+    def getLength(self):
+        length = 0
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_char) * 65
+        length += sizeof(ctypes.c_char) * 33
+        length += sizeof(ctypes.c_int)
+        length += sizeof(ctypes.c_int)
+        length += sizeof(ctypes.c_ubyte)
+        length += sizeof(ctypes.c_int)
+        length += sizeof(ctypes.c_int)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_char) * 33
+        length += sizeof(ctypes.c_ushort)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += self.PlusDataSize
+        return length
+
+    def outputString(self):
+        output = '''// 玩家查看缓存表 #tagDBPlayerViewCache:
+            PlayerID = %s,
+            AccID = %s,
+            PlayerName = %s,
+            LV = %s,
+            Job = %s,
+            RealmLV = %s,
+            Face = %s,
+            FacePic = %s,
+            FamilyID = %s,
+            FamilyName = %s,
+            FamilyEmblemID = %s,
+            TitleID = %s,
+            FightPower = %s,
+            FightPowerEx = %s,
+            ServerID = %s,
+            OffTime = %s,
+            PlusDataSize = %s,
+            PlusData = %s,
+            ADOResult = %s,
+            '''%(
+                self.PlayerID,
+                self.AccID,
+                self.PlayerName,
+                self.LV,
+                self.Job,
+                self.RealmLV,
+                self.Face,
+                self.FacePic,
+                self.FamilyID,
+                self.FamilyName,
+                self.FamilyEmblemID,
+                self.TitleID,
+                self.FightPower,
+                self.FightPowerEx,
+                self.ServerID,
+                self.OffTime,
+                self.PlusDataSize,
+                self.PlusData,
+                self.ADOResult,
+            )
+        return output
+
+    #Char数组类型Set接口,使用该接口对此类型数据赋值,防止赋值的数据过长报错
+    def SetAccID(self,Str):
+        if len(Str)<=65:
+            self.AccID = Str
+        else:
+            self.AccID = Str[:65]
+            
+    def SetPlayerName(self,Str):
+        if len(Str)<=33:
+            self.PlayerName = Str
+        else:
+            self.PlayerName = Str[:33]
+            
+    def SetFamilyName(self,Str):
+        if len(Str)<=33:
+            self.FamilyName = Str
+        else:
+            self.FamilyName = Str[:33]
+            
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py
new file mode 100644
index 0000000..d688586
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py
@@ -0,0 +1,643 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package DB.StructData.DBFamily
+#
+# @todo:DB家族相关
+# @author hxp
+# @date 2025-05-09
+# @version 1.0
+#
+# 详细描述: DB家族相关
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-05-09 12:20"""
+#-------------------------------------------------------------------------------
+
+import DBStruct
+import CommFunc
+import GameWorld
+import ShareDefine
+import PlayerControl
+import DBDataMgr
+import ChConfig
+import DBComm
+
+import time
+
+FamilyUpperLimitCount = 2000
+
+class FamilyActionData():
+    
+    def __init__(self, dbData=None, dataToJson=False):
+        self.__dbData = DBStruct.tagDBFamilyAction() if not dbData else dbData
+        self.__dataDict = DBComm.UserDataDict(self.__dbData, "Data", "DataLen", dataToJson)
+        return
+    
+    def GetFamilyID(self): return self.__dbData.FamilyID
+    def GetActionType(self): return self.__dbData.ActionType
+    def GetName(self): return self.__dbData.Name
+    def SetName(self, name): self.__dbData.Name = name
+    def GetTime(self): return self.__dbData.Time
+    def SetTime(self, setTime): self.__dbData.Time = setTime
+    def GetValue1(self): return self.__dbData.Value1
+    def SetValue1(self, value1): self.__dbData.Value1 = value1
+    def GetValue2(self): return self.__dbData.Value2
+    def SetValue2(self, value2): self.__dbData.Value2 = value2
+    def GetValue3(self): return self.__dbData.Value3
+    def SetValue3(self, value3): self.__dbData.Value3 = value3
+    def GetValue4(self): return self.__dbData.Value4
+    def SetValue4(self, value4): self.__dbData.Value4 = value4
+    def GetValue5(self): return self.__dbData.Value5
+    def SetValue5(self, value5): self.__dbData.Value5 = value5
+    def GetValue6(self): return self.__dbData.Value6
+    def SetValue6(self, value6): self.__dbData.Value6 = value6
+    def GetUserDict(self): return self.__dataDict.GetData()
+    def GetUserData(self): return self.__dataDict.ToString()
+    def SetUserData(self, value): self.__dataDict.SetData(value)
+    def GetBuffer(self):
+        self.__dataDict.ToString()
+        return self.__dbData.getBuffer()
+    
+class FamilyAction():
+    
+    def __init__(self):
+        self.familyID = 0
+        self.actionType = 0
+        self.__actionDataList = []
+        return
+    
+    def InitActionInstance(self, dbData):
+        '''初始化功能数据实例,创建或加载数据时通用,功能一般不调用
+        @param dbData: 实例对应绑定的dbData
+        @return: 成功返回实例对象,失败返回None
+        '''
+        dataToJson = False
+        # 如果需要 dataToJson,可根据ActionType在这里处理
+        if dbData.ActionType in []:
+            dataToJson = True
+        actionData = FamilyActionData(dbData, dataToJson)
+        self.__actionDataList.append(actionData)
+        return actionData
+    
+    def AddAction(self, fullClear=True):
+        ## 添加仙盟Action数据
+        # @param fullClear: 数据条数超过最大数时是否清除最早一条,并创建一条新记录
+        
+        actionData = None
+        if self.Count() >= ChConfig.ActionTypeSaveCnt.get(self.actionType, 0):
+            if not fullClear:
+                #超过记录记录不了了
+                return actionData
+            self.SortByTime()  # 按时间升序
+            self.DelAction(0)  # 删除第一个
+            
+        dbData = DBStruct.tagDBFamilyAction()
+        dbData.FamilyID = self.familyID
+        dbData.ActionType = self.actionType
+        dbData.Time = int(time.time())
+        
+        actionData = self.InitActionInstance(dbData)
+        return actionData
+    
+    def SortByTime(self):
+        self.__actionDataList.sort(key=lambda f: (f.GetTime()))
+        return
+    
+    def DelAction(self, index):
+        if 0 <= index < len(self.__actionDataList):
+            self.__actionDataList.pop(index)
+        return
+    
+    def GetOneAction(self, isAdd=False):
+        ## 获取一个action数据,仅针对只存一条数据的类型
+        aData = None
+        if self.Count():
+            aData = self.At(0)
+        elif isAdd:
+            aData = self.AddAction()
+        return aData
+    
+    def Count(self): return len(self.__actionDataList)
+    def At(self, index):
+        aData = None
+        if 0 <= index < len(self.__actionDataList):
+            aData = self.__actionDataList[index]
+        elif False:
+            aData = FamilyActionData()
+        return aData
+        
+class FamilyActionMgr():
+    
+    def __init__(self):
+        self.__familyActionDict = {} # 仙盟action信息 {familyID:{actionType:FamilyAction, ...}, ...}
+        return
+    
+    def GetFamilyAction(self, familyID, actionType):
+        if familyID not in self.__familyActionDict:
+            self.__familyActionDict[familyID] = {}
+        actionDict = self.__familyActionDict[familyID]
+        if actionType in actionDict:
+            action = actionDict[actionType]
+        else:
+            action = FamilyAction()
+            action.familyID = familyID
+            action.actionType = actionType
+            actionDict[actionType] = action
+        return action
+    
+    def DelFamilyAction(self, familyID, actionType):
+        if familyID not in self.__familyActionDict:
+            return
+        actionDict = self.__familyActionDict[familyID]
+        actionDict.pop(actionType, None)
+        return
+    
+    def ClearFamilyAction(self, familyID):
+        self.__familyActionDict.pop(familyID, None)
+        return
+    
+    def GetActionTypeList(self, familyID):
+        ## 获取有数据的action类型列表
+        return self.__familyActionDict.get(familyID, {}).keys()
+    
+class FamilyMem():
+    
+    def __init__(self, dbData=None):
+        self.__dbData = DBStruct.tagDBFamilyMem() if not dbData else dbData
+        return
+    
+    def GetPlayerID(self): return self.__dbData.PlayerID
+    def GetFamilyID(self): return self.__dbData.FamilyID
+    def GetJoinTime(self): return self.__dbData.JoinTime
+    def GetPlayerName(self): return self.__dbData.PlayerName
+    def SetPlayerName(self, playerName): self.__dbData.PlayerName = playerName
+    def GetLV(self): return self.__dbData.LV
+    def SetLV(self, lv): self.__dbData.LV = lv
+    def GetJob(self): return self.__dbData.Job
+    def SetJob(self, job): self.__dbData.Job = job
+    def GetRealmLV(self): return self.__dbData.RealmLV
+    def SetRealmLV(self, realmLV): self.__dbData.RealmLV = realmLV
+    def GetFace(self): return self.__dbData.Face
+    def SetFace(self, face): self.__dbData.Face = face
+    def GetFacePic(self): return self.__dbData.FacePic
+    def SetFacePic(self, facePic): self.__dbData.FacePic = facePic
+    def GetFightPower(self): return self.__dbData.FightPower
+    def GetFightPowerEx(self): return self.__dbData.FightPowerEx
+    def GetFightPowerTotal(self): return self.__dbData.FightPowerEx * ChConfig.Def_PerPointValue + self.__dbData.FightPower
+    def SetFightPowerTotal(self, fightPowerTotal):
+        self.__dbData.FightPower = fightPowerTotal % ChConfig.Def_PerPointValue
+        self.__dbData.FightPowerEx = fightPowerTotal / ChConfig.Def_PerPointValue
+        return
+    def GetServerID(self): return self.__dbData.ServerID
+    def SetServerID(self, serverID): self.__dbData.ServerID = serverID
+    def GetOffTime(self): return self.__dbData.OffTime
+    def SetOffTime(self, offTime): self.__dbData.OffTime = offTime
+    def GetFmLV(self): return self.__dbData.FmLV
+    def SetFmLV(self, fmLV): self.__dbData.FmLV = fmLV
+    def GetContribTotal(self): return self.__dbData.ContribTotal
+    def SetContribTotal(self, contribTotal): self.__dbData.ContribTotal = contribTotal
+    def GetContribWeek(self): return self.__dbData.ContribWeek
+    def SetContribWeek(self, contribWeek): self.__dbData.ContribWeek = contribWeek
+    def GetBuffer(self): return self.__dbData.getBuffer()
+    
+    def RefreshMemberByID(self, playerID):
+        ## 根据玩家ID更新成员数据,一般用于离线功能,如添加离线成员,直接使用查看缓存更新
+        if playerID != self.GetPlayerID():
+            return
+        viewCache = DBDataMgr.GetPlayerViewCacheMgr().FindViewCache(playerID)
+        if not viewCache:
+            return
+        self.SetPlayerName(viewCache.GetPlayerName())
+        self.SetLV(viewCache.GetLV())
+        self.SetJob(viewCache.GetJob())
+        self.SetRealmLV(viewCache.GetRealmLV())
+        self.SetFace(viewCache.GetFace())
+        self.SetFacePic(viewCache.GetFacePic())
+        self.SetServerID(viewCache.GetServerID())
+        fpChange = False
+        fightPowerTotal = viewCache.GetFightPowerTotal()
+        if self.GetFightPowerTotal() < fightPowerTotal:
+            self.SetFightPowerTotal(fightPowerTotal)
+            fpChange = True
+        return fpChange
+    
+    def RefreshMember(self, curPlayer):
+        '''刷新成员信息,仙盟成员属于永久功能数据,除非仙盟解散,所以单独存一份成员基础信息,防止过度依赖查看缓存数据引发的问题
+        @return: 战力是否变更
+        '''
+        if not curPlayer or curPlayer.GetPlayerID() != self.GetPlayerID():
+            return
+        self.SetPlayerName(curPlayer.GetPlayerName())
+        self.SetLV(curPlayer.GetLV())
+        self.SetJob(curPlayer.GetJob())
+        self.SetRealmLV(curPlayer.GetOfficialRank())
+        self.SetFace(curPlayer.GetFace())
+        self.SetFacePic(curPlayer.GetFacePic())
+        self.SetServerID(GameWorld.GetPlayerServerID(curPlayer))
+        fightPowerTotal = PlayerControl.GetFightPower(curPlayer)
+        fpChange = self.GetFightPowerTotal() != fightPowerTotal
+        self.SetFightPowerTotal(fightPowerTotal)
+        return fpChange
+    
+class Family():
+    
+    def __init__(self, dbData=None):
+        self.__dbData = DBStruct.tagDBFamily() if not dbData else dbData
+        self.__memberList = [] # [FamilyMem, ...]
+        self.__memberDict = {} # 成员字典 {playerID:FamilyMem, ...}
+        self.__familyMgr = DBDataMgr.GetFamilyMgr()
+        self.__actionMgr = DBDataMgr.GetFamilyActionMgr()
+        self.__memFightPowerChange = None # 成员战力是否有变化,默认None,代表未处理过
+        return
+    
+    def GetID(self): return self.__dbData.ID
+    def GetCreateTime(self): return self.__dbData.CreateTime
+    def GetServerID(self): return self.__dbData.ServerID
+    def GetName(self): return self.__dbData.Name
+    def SetName(self, name): self.__dbData.Name = name
+    def GetLeaderID(self): return self.__dbData.LeaderID
+    def SetLeaderID(self, leaderID): self.__dbData.LeaderID = leaderID
+    def GetLV(self): return self.__dbData.LV
+    def SetLV(self, lv): self.__dbData.LV = lv
+    def GetExp(self): return self.__dbData.Exp
+    def SetExp(self, exp): self.__dbData.Exp = exp
+    def GetJoinReview(self): return self.__dbData.JoinReview # 成员加入是否需要审核,默认0自动加入
+    def SetJoinReview(self, joinReview): self.__dbData.JoinReview = joinReview
+    def GetJoinLVMin(self): return self.__dbData.JoinLVMin
+    def SetJoinLVMin(self, JoinLVMin): self.__dbData.JoinLVMin = JoinLVMin
+    def GetBroadcast(self): return self.__dbData.Broadcast
+    def SetBroadcast(self, broadcast):
+        self.__dbData.Broadcast = broadcast
+        self.__dbData.BroadcastLen = len(self.__dbData.Broadcast)
+        return
+    def GetFightPower(self): return self.__dbData.FightPower
+    def GetFightPowerEx(self): return self.__dbData.FightPowerEx
+    def GetFightPowerTotal(self): return self.__dbData.FightPowerEx * ChConfig.Def_PerPointValue + self.__dbData.FightPower
+    def SetFightPowerTotal(self, fightPowerTotal):
+        self.__dbData.FightPower = fightPowerTotal % ChConfig.Def_PerPointValue
+        self.__dbData.FightPowerEx = fightPowerTotal / ChConfig.Def_PerPointValue
+        return
+    def GetEmblemID(self): return self.__dbData.EmblemID
+    def SetEmblemID(self, emblemID): self.__dbData.EmblemID = emblemID
+    def GetBuffer(self): return self.__dbData.getBuffer()
+        
+    ## ------------------------------------------------
+    def InitMemberInstance(self, dbData):
+        '''初始化功能数据实例,创建或加载数据时通用,功能一般不调用
+        @param dbData: 实例对应绑定的dbData
+        @return: 成功返回实例对象,失败返回None
+        '''
+        member = FamilyMem(dbData)
+        playerID = member.GetPlayerID()
+        if playerID in self.__memberDict:
+            return
+        self.__memberDict[playerID] = member
+        self.__memberList.append(member)
+        return member
+    
+    def AddMember(self, playerID):
+        member = None
+        if playerID in self.__memberDict:
+            member = self.__memberDict[playerID]
+        else:
+            dbData = DBStruct.tagDBFamilyMem()
+            dbData.PlayerID = playerID
+            dbData.FamilyID = self.GetID()
+            dbData.JoinTime = int(time.time())
+            member = self.InitMemberInstance(dbData)
+            if not member and False:
+                member = FamilyMem()
+        self.__memFightPowerChange = True
+        return member
+    
+    def DeleteMember(self, playerID):
+        delMem = self.__memberDict.pop(playerID, None)
+        if delMem in self.__memberList:
+            self.__memberList.remove(delMem)
+        self.__memFightPowerChange = True
+        return delMem
+    
+    def FindMember(self, playerID):
+        mem = None
+        if playerID in self.__memberDict:
+            mem = self.__memberDict[playerID]
+        elif False:
+            mem = FamilyMem()
+        return mem
+    
+    def GetCount(self): return len(self.__memberList)
+    def GetAt(self, index):
+        mem = None
+        if 0 <= index < len(self.__memberList):
+            mem = self.__memberList[index]
+        elif False:
+            mem = FamilyMem()
+        return mem
+    
+    def RefreshFamilyMember(self, curPlayer):
+        ## 刷新在线成员信息
+        playerID = curPlayer.GetPlayerID()
+        familyID = curPlayer.GetFamilyID()
+        if self.GetID() != familyID:
+            return
+        member = self.FindMember(playerID)
+        if not member:
+            return
+        if member.RefreshMember(curPlayer):
+            self.__memFightPowerChange = True
+        return
+    
+    def RefrshFightPowerTotal(self, checkChange=False):
+        ## 刷新总战力
+        if checkChange and self.__memFightPowerChange == False: # 默认None,首次必刷新
+            GameWorld.DebugLog("没有成员战力变化可不刷新仙盟总战力! familyID=%s" % self.GetID())
+            return
+        familyFightPowerTotal = 0
+        for index in range(self.GetCount()):
+            member = self.GetAt(index)
+            if not member:
+                continue
+            familyFightPowerTotal += member.GetFightPowerTotal()
+        self.SetFightPowerTotal(familyFightPowerTotal)
+        GameWorld.DebugLog("刷新仙盟总战力! familyID=%s" % self.GetID())
+        self.__memFightPowerChange = False
+        return familyFightPowerTotal
+    
+    def GetReqJoinPlayerInfo(self):
+        ## 获取申请加入的玩家信息
+        # @return: {playerID:申请时间戳, ...}
+        joinAction  = self.__actionMgr.GetFamilyAction(self.GetID(), ShareDefine.Def_ActionType_FamilyAdd)
+        actionData = joinAction.GetOneAction(True)
+        dataDict = actionData.GetUserDict()
+        if "ReqJoin" not in dataDict:
+            dataDict["ReqJoin"] = {}
+        return dataDict["ReqJoin"]
+    
+    def AddReqJoinPlayerID(self, playerID):
+        reqPlayerIDDict = self.GetReqJoinPlayerInfo()
+        reqPlayerIDDict[playerID] = int(time.time()) # 申请时间戳
+        self.__familyMgr.AddPlayerReqJoinFamilyID(playerID, self.GetID())
+        return
+    
+    def DelReqJoinPlayerID(self, playerID):
+        reqPlayerIDDict = self.GetReqJoinPlayerInfo()
+        if playerID in reqPlayerIDDict:
+            reqPlayerIDDict.pop(playerID)
+        self.__familyMgr.DelPlayerReqJoinFamilyID(playerID, self.GetID())
+        return
+    
+    def DelReqJoinPlayerAll(self):
+        reqPlayerIDDict = self.GetReqJoinPlayerInfo()
+        for playerID in reqPlayerIDDict.keys():
+            reqPlayerIDDict.pop(playerID)
+            self.__familyMgr.DelPlayerReqJoinFamilyID(playerID, self.GetID())
+        return
+    
+    def OnDelete(self):
+        self.DelReqJoinPlayerAll()
+        self.__actionMgr.ClearFamilyAction(self.GetID())
+        return
+    
+class FamilyMgr():
+    
+    def __init__(self):
+        self.__familyList = [] # 仙盟对象列表,可进行排序 [Family, ...]
+        self.__familyIDDict = {} # 仙盟ID对象字典,  {familyID:Family, ...}
+        self.__familyNameDict = {} # 仙盟名称对象字典,  {familyName:Family, ...}
+        self.__actionMgr = FamilyActionMgr()
+        self.__playerReqJoinDict = None # 玩家申请加入仙盟列表 {playerID:[familyID, ...], ...}
+        return
+    
+    def InitFamilyInstance(self, dbData):
+        '''初始化功能数据实例,创建或加载数据时通用,功能一般不调用
+        @param dbData: 实例对应绑定的dbData
+        @return: 成功返回实例对象,失败返回None
+        '''
+        family = Family(dbData)
+        familyID = family.GetID()
+        if familyID in self.__familyIDDict:
+            return
+        self.__familyList.append(family)
+        self.__familyIDDict[familyID] = family
+        self.__familyNameDict[family.GetName()] = family
+        return family
+    
+    def Sort(self):
+        ''' 默认排序倒序,按  仙盟总战力 -> 仙盟等级
+        '''
+        self.__familyList.sort(key=lambda f: (f.GetFightPowerTotal(), f.GetLV()), reverse=True)
+        return
+    
+    def AddFamily(self, familyID, familyName, serverID):
+        ## 创建新仙盟
+        newFamily = None
+        if familyID in self.__familyIDDict:
+            GameWorld.ErrLog("创建仙盟时ID已存在! familyID=%s" % familyID)
+            return newFamily
+        if familyName in self.__familyNameDict:
+            GameWorld.ErrLog("创建仙盟时名称已存在! familyName=%s" % familyName)
+            return newFamily
+        if len(self.__familyList) >= FamilyUpperLimitCount:
+            GameWorld.ErrLog("单服限制创建仙盟数已达上限!")
+            return newFamily
+        
+        dbData = DBStruct.tagDBFamily()
+        dbData.ID = familyID
+        dbData.Name = familyName
+        dbData.ServerID = serverID
+        dbData.CreateTime = int(time.time())
+        
+        newFamily = self.InitFamilyInstance(dbData)
+        if not newFamily and False: # 不执行,为了代码提示
+            newFamily = Family()
+        return newFamily
+    
+    def FindFamily(self, familyID):
+        family = None
+        if familyID in self.__familyIDDict:
+            family = self.__familyIDDict[familyID]
+        elif False:
+            family = Family()
+        return family
+    
+    def FindFamilyByName(self, familyName):
+        family = None
+        if familyName in self.__familyNameDict:
+            family = self.__familyNameDict[familyName]
+        elif False:
+            family = Family()
+        return family
+    
+    def DelFamily(self, familyID):
+        family = self.FindFamily(familyID)
+        if family:
+            self.__familyNameDict.pop(family.GetName(), None)
+            if family in self.__familyList:
+                self.__familyList.remove(family)
+            family.OnDelete()
+        self.__familyIDDict.pop(familyID, None)
+        return family
+    
+    def GetCount(self): return len(self.__familyList)
+    def GetAt(self, index):
+        family = None
+        if 0 <= index < len(self.__familyList):
+            family = self.__familyList[index]
+        elif False:
+            family = Family()
+        return family
+    
+    def GetPlayerFamilyID(self, playerID):
+        ## 获取玩家当前所属的仙盟ID
+        for index in range(self.GetCount()):
+            family = self.GetAt(index)
+            if family.FindMember(playerID):
+                return family.GetID()
+        return 0
+    
+    def GetFamilyActionMgr(self): return self.__actionMgr
+    
+    def GetPlayerReqJoinFamilyIDList(self, playerID):
+        ## 获取玩家申请加入的仙盟ID列表
+        if self.__playerReqJoinDict == None:
+            self.__playerReqJoinDict = {}
+            for index in xrange(self.GetCount()):
+                family = self.GetAt(index)
+                familyID = family.GetID()
+                reqPlayerIDDict = family.GetReqJoinPlayerInfo()
+                for reqID in reqPlayerIDDict.keys():
+                    if reqID not in self.__playerReqJoinDict:
+                        self.__playerReqJoinDict[reqID] = []
+                    reqFamilyIDList = self.__playerReqJoinDict[reqID]
+                    if familyID not in reqFamilyIDList:
+                        reqFamilyIDList.append(familyID)
+                        
+        if playerID not in self.__playerReqJoinDict:
+            self.__playerReqJoinDict[playerID] = []
+        return self.__playerReqJoinDict[playerID]
+    
+    def AddPlayerReqJoinFamilyID(self, playerID, familyID):
+        ## 添加玩家申请加入目标仙盟记录
+        # @return: 是否有增加记录
+        reqFamilyIDList = self.GetPlayerReqJoinFamilyIDList(playerID)
+        if familyID not in reqFamilyIDList:
+            reqFamilyIDList.append(familyID)
+            return True
+        return False
+    
+    def DelPlayerReqJoinFamilyID(self, playerID, familyID):
+        ## 删除玩家申请加入目标仙盟记录
+        # @return: 是否有删除记录
+        reqFamilyIDList = self.GetPlayerReqJoinFamilyIDList(playerID)
+        if familyID in reqFamilyIDList:
+            reqFamilyIDList.remove(familyID)
+            return True
+        return False
+    
+    def DelPlayerReqJoinFamilyIDAll(self, playerID):
+        ## 删除玩家所有的申请加入仙盟记录
+        reqFamilyIDList = self.GetPlayerReqJoinFamilyIDList(playerID)
+        for familyID in reqFamilyIDList[::-1]:
+            family = self.FindFamily(familyID)
+            if not family:
+                continue
+            family.DelReqJoinPlayerID(playerID)
+        return
+    
+    # 保存数据 存数据库和realtimebackup
+    def GetSaveData(self):
+        
+        familyDataCnt, familySavaData = 0, ""
+        membreDataCnt, memberSavaData = 0, ""
+        actionDataCnt, actionSavaData = 0, ""
+        for family in self.__familyList:
+            familyID = family.GetID()
+            familySavaData += family.GetBuffer()
+            familyDataCnt += 1
+            
+            for memIndex in range(family.GetCount()):
+                member = family.GetAt(memIndex)
+                memberSavaData += member.GetBuffer()
+                membreDataCnt += 1
+                
+            for actionType in self.__actionMgr.GetActionTypeList(familyID):
+                action = self.__actionMgr.GetFamilyAction(familyID, actionType)
+                for aIndex in range(action.Count()):
+                    actionData = action.At(aIndex)
+                    actionSavaData += actionData.GetBuffer()
+                    actionDataCnt += 1
+                    
+        saveData = ""
+        
+        saveData += CommFunc.WriteDWORD("", familyDataCnt) + familySavaData
+        GameWorld.Log("Save DBFamily count :%s len=%s" % (familyDataCnt, len(familySavaData)))
+        
+        saveData += CommFunc.WriteDWORD("", membreDataCnt) + memberSavaData
+        GameWorld.Log("Save DBFamilyMem count :%s len=%s" % (membreDataCnt, len(memberSavaData)))
+        
+        saveData += CommFunc.WriteDWORD("", actionDataCnt) + actionSavaData
+        GameWorld.Log("Save DBFamilyAction count :%s len=%s" % (actionDataCnt, len(actionSavaData)))
+        
+        return saveData
+    
+    # 从数据库载入数据
+    def LoadPyGameData(self, datas, pos, dataslen):        
+        # 仙盟
+        cnt, pos = CommFunc.ReadDWORD(datas, pos)
+        GameWorld.Log("Load DBFamily count :%s" % cnt)
+        for _ in xrange(cnt):
+            dbData = DBStruct.tagDBFamily()
+            pos += dbData.readData(datas, pos, dataslen)
+            self.InitFamilyInstance(dbData)
+        self.Sort()
+        
+        # 成员
+        cnt, pos = CommFunc.ReadDWORD(datas, pos)
+        GameWorld.Log("Load DBFamilyMem count :%s" % cnt)
+        for _ in xrange(cnt):
+            dbData = DBStruct.tagDBFamilyMem()
+            pos += dbData.readData(datas, pos, dataslen)
+            
+            familyID = dbData.FamilyID
+            family = self.FindFamily(familyID)
+            if not family:
+                continue
+            member = family.InitMemberInstance(dbData)
+            GameWorld.Log("    member:%s,familyID=%s" % (member.GetPlayerID(), familyID))
+            
+        # 行为
+        cnt, pos = CommFunc.ReadDWORD(datas, pos)
+        GameWorld.Log("Load DBFamilyAction count :%s" % cnt)
+        for _ in xrange(cnt):
+            dbData = DBStruct.tagDBFamilyAction()
+            pos += dbData.readData(datas, pos, dataslen)
+            
+            familyID = dbData.FamilyID
+            actionType = dbData.ActionType
+            family = self.FindFamily(familyID)
+            if not family:
+                continue
+            action = self.__actionMgr.GetFamilyAction(familyID, actionType)
+            action.InitActionInstance(dbData)
+            
+        return pos
+    
+def OnMinute(curMinute):
+    
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    # 每分钟刷新下仙盟战力排序
+    isSort = False
+    for index in range(familyMgr.GetCount()):
+        family = familyMgr.GetAt(index)
+        if not family:
+            continue
+        if family.RefrshFightPowerTotal(True):
+            isSort = True
+    if isSort:
+        familyMgr.Sort()
+        
+    return
+
+    
\ No newline at end of file
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py
new file mode 100644
index 0000000..a108d0d
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py
@@ -0,0 +1,327 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Script.DB.StructData.DBPlayerViewCache
+#
+# @todo:DB玩家查看缓存
+# @author hxp
+# @date 2025-05-09
+# @version 1.0
+#
+# 详细描述: DB玩家查看缓存
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-05-09 12:20"""
+#-------------------------------------------------------------------------------
+
+import DBComm
+import DBStruct
+import GameWorld
+import ShareDefine
+import PlayerControl
+import DBDataMgr
+import CommFunc
+import ChConfig
+import GameObj
+
+import random
+import time
+
+Key_UpdViewCacheTick = "UpdViewCacheTick"
+
+class PlayerViewCache():
+    
+    def __init__(self, dbData=None):
+        self.__dbData = DBStruct.tagDBPlayerViewCache() if not dbData else dbData
+        self.__plusDict = DBComm.UserDataDict(self.__dbData, "PlusData", "PlusDataSize", True)
+        return
+    
+    def GetPlayerID(self): return self.__dbData.PlayerID
+    def SetPlayerID(self, playerID): self.__dbData.PlayerID = playerID
+    def GetAccID(self): return self.__dbData.AccID
+    def SetAccID(self, accID): self.__dbData.AccID = accID
+    def GetPlayerName(self): return self.__dbData.PlayerName
+    def SetPlayerName(self, playerName): self.__dbData.PlayerName = playerName
+    def GetLV(self): return self.__dbData.LV
+    def SetLV(self, lv): self.__dbData.LV = lv
+    def GetJob(self): return self.__dbData.Job
+    def SetJob(self, job): self.__dbData.Job = job
+    def GetRealmLV(self): return self.__dbData.RealmLV
+    def SetRealmLV(self, realmLV): self.__dbData.RealmLV = realmLV
+    def GetFace(self): return self.__dbData.Face
+    def SetFace(self, face): self.__dbData.Face = face
+    def GetFacePic(self): return self.__dbData.FacePic
+    def SetFacePic(self, facePic): self.__dbData.FacePic = facePic
+    def GetFamilyID(self): return self.__dbData.FamilyID
+    def SetFamilyID(self, familyID): self.__dbData.FamilyID = familyID
+    def GetFamilyName(self): return self.__dbData.FamilyName
+    def SetFamilyName(self, familyName): self.__dbData.FamilyName = familyName
+    def GetFamilyEmblemID(self): return self.__dbData.FamilyEmblemID
+    def SetFamilyEmblemID(self, familyEmblemID): self.__dbData.FamilyEmblemID = familyEmblemID
+    def GetTitleID(self): return self.__dbData.TitleID
+    def SetTitleID(self, titleID): self.__dbData.TitleID = titleID
+    def GetFightPower(self): return self.__dbData.FightPower
+    def GetFightPowerEx(self): return self.__dbData.FightPowerEx
+    def GetFightPowerTotal(self): return self.__dbData.FightPowerEx * ChConfig.Def_PerPointValue + self.__dbData.FightPower
+    def SetFightPowerTotal(self, fightPowerTotal):
+        self.__dbData.FightPower = fightPowerTotal % ChConfig.Def_PerPointValue
+        self.__dbData.FightPowerEx = fightPowerTotal / ChConfig.Def_PerPointValue
+        return
+    def GetServerID(self): return self.__dbData.ServerID
+    def SetServerID(self, serverID): self.__dbData.ServerID = serverID
+    def GetOffTime(self): return self.__dbData.OffTime
+    def SetOffTime(self, offTime): self.__dbData.OffTime = offTime
+    def GetPlusDict(self): return self.__plusDict.GetData()
+    def GetPlusData(self): return self.__plusDict.ToString()
+    def GetBuffer(self):
+        self.__plusDict.ToString()
+        return self.__dbData.getBuffer()
+    
+    ## -----------------------------------------------------------------------
+    
+class PlayerViewCacheMgr():
+    
+    def __init__(self):
+        self.__viewCacheList = [] # [PlayerViewCache, ...]
+        self.__idIndexDict = {} # {playerID:index, ...}
+        self.__needSort = False
+        self.__serverIDRangePlayerIDDict = {} # {serverIDRangeTuple:[playerID, ...], ....}
+        return
+    
+    def InitViewCacheInstance(self, dbData):
+        '''初始化功能数据实例,创建或加载数据时通用,功能一般不调用
+        @param dbData: 实例对应绑定的dbData
+        @return: 成功返回实例对象,失败返回None
+        '''
+        playerID = dbData.PlayerID
+        self.__refreshIDIndex()
+        if playerID in self.__idIndexDict:
+            return
+        viewCache = PlayerViewCache(dbData)
+        self.__viewCacheList.append(viewCache)
+        self.__idIndexDict[playerID] = len(self.__viewCacheList) - 1
+        self.__needSort = True
+        return viewCache
+    
+    def CheckUpdViewCache(self, playerID):
+        if playerID <= ShareDefine.FackPlayerIDMax:
+            return
+        curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+        if not curPlayer:
+            return
+        lastUpdTick = curPlayer.GetDictByKey(Key_UpdViewCacheTick)
+        tick = GameWorld.GetGameWorld().GetTick()
+        if lastUpdTick and tick - lastUpdTick < 60000:
+            GameWorld.DebugLog("1分钟内只更新一次玩家缓存", playerID)
+            return
+        curPlayer.SetDict(Key_UpdViewCacheTick, tick)
+        return UpdPlayerViewCache(curPlayer)
+    
+    def FindViewCache(self, playerID, isAdd=False):
+        '''查找玩家缓存,如果不存在,则会有额外逻辑,如从redis、db直接找,
+                        跨服玩家从跨服取,可能延迟获得
+        '''
+        curCache = self.GetPlayerViewCache(playerID)
+        if curCache:
+            updCache = self.CheckUpdViewCache(playerID)
+            if updCache:
+                curCache = updCache
+                
+        # 真实玩家
+        elif playerID > ShareDefine.FackPlayerIDMax:
+            curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+            # 本服在线玩家,直接生成新数据
+            if curPlayer:
+                dbData = DBStruct.tagDBPlayerViewCache()
+                dbData.PlayerID = playerID
+                self.InitViewCacheInstance(dbData)
+                UpdPlayerViewCache(curPlayer)
+                
+            # 离线玩家
+            else:
+                pass
+                # 本服玩家,从redis或db读取重新加载读取,换句话说,本服玩家只要获取一定有查看缓存数据
+                # 跨服玩家,去子服拉取数据,理论上也一定有,但是如果需要拉数据,有一定延迟
+                # 逻辑待扩展
+                
+        # 假玩家,默认添加
+        elif ShareDefine.FackPlayerIDStart <= playerID <= ShareDefine.FackPlayerIDMax:
+            serverID = playerID % 100 + 1 # 1 ~ 100 服
+            accID = "fake%s@test@s%s" % (playerID, serverID)
+            fightPower = random.randint(1000000, 100000000) # 先随机,外层有需要的话再自己设置
+            
+            dbData = DBStruct.tagDBPlayerViewCache()
+            dbData.PlayerID = playerID
+            dbData.PlayerName = "%s%s" % (GameWorld.GbkToCode("神秘道友"), playerID)
+            dbData.AccID = accID
+            dbData.LV = random.randint(100, 200)
+            dbData.Job = random.randint(1, 2)
+            dbData.RealmLV = random.randint(5, 15)
+            dbData.FightPower = fightPower % ChConfig.Def_PerPointValue
+            dbData.FightPowerEx = fightPower / ChConfig.Def_PerPointValue
+            dbData.ServerID = serverID
+            dbData.OffTime = int(time.time()) - random.randint(1, 3600 * 24 * 10) # 随机离线 0~10天
+            curCache = self.InitViewCacheInstance(dbData)
+            
+        return curCache
+    
+    def GetPlayerViewCache(self, playerID):
+        ## 获取玩家查看缓存,仅内存中数据,无额外逻辑
+        self.__refreshIDIndex()
+        viewCache = None
+        if playerID in self.__idIndexDict:
+            index = self.__idIndexDict[playerID]
+            if index < len(self.__viewCacheList):
+                viewCache = self.__viewCacheList[index]
+                
+        if not viewCache and False:
+            viewCache = PlayerViewCache()
+            
+        return viewCache
+    
+    def GetPlayerIDListByServerIDInfo(self, serverIDList):
+        ## 根据服务器ID列表信息获取对应服务器ID范围的玩家ID战力排序列表
+        if serverIDList == None:
+            return []
+        self.Sort()
+        key = tuple(serverIDList)
+        if key not in self.__serverIDRangePlayerIDDict:
+            playerIDList = []
+            for viewCache in self.__viewCacheList:
+                playerID = viewCache.GetPlayerID()
+                serverID = viewCache.GetServerID()
+                for idInfo in serverIDList:
+                    if (isinstance(idInfo, int) and serverID == idInfo) \
+                        or ((isinstance(idInfo, tuple) or isinstance(idInfo, list)) \
+                            and len(idInfo) == 2 and idInfo[0] <= serverID <= idInfo[1]):
+                        playerIDList.append(playerID)
+            GameWorld.DebugLog("重新加载区服玩家查看缓存ID列表: %s, %s, %s" % (key, len(playerIDList), playerIDList))
+            self.__serverIDRangePlayerIDDict[key] = playerIDList
+        return self.__serverIDRangePlayerIDDict[key]
+    
+    def IsPlayerIn(self, playerID):
+        self.__refreshIDIndex()
+        return playerID in self.__idIndexDict
+    
+    def __refreshIDIndex(self):
+        if not self.__idIndexDict:
+            self.__idIndexDict = {}
+            for index, viewCache in enumerate(self.__viewCacheList):
+                self.__idIndexDict[viewCache.GetPlayerID()] = index
+        return self.__idIndexDict
+    
+    def DelPlayerViewCache(self, playerID):
+        self.__refreshIDIndex()
+        index = self.__idIndexDict.pop(playerID, -1)
+        if index >= 0 and index < len(self.__viewCacheList):
+            self.__viewCacheList.pop(index)
+        for playerIDList in self.__serverIDRangePlayerIDDict.values():
+            if playerID in playerIDList:
+                playerIDList.remove(playerID)
+        self.__idIndexDict = {}
+        self.__serverIDRangePlayerIDDict = {}
+        return
+    
+    def GetCount(self): return len(self.__viewCacheList)    
+    def At(self, index):
+        viewCache = self.__viewCacheList[index]
+        if not viewCache and False:
+            viewCache = PlayerViewCache() # 不会执行到,只为了.出代码提示
+        return viewCache
+    
+    def Sort(self):
+        ## 默认按战力倒序排
+        if not self.__needSort:
+            return
+        self.__needSort = False
+        self.__viewCacheList.sort(key=lambda v: (v.GetFightPowerTotal(), v.GetLV()), reverse=True)
+        self.__idIndexDict = {}
+        self.__serverIDRangePlayerIDDict = {}
+        self.__refreshIDIndex()
+        return
+    
+    # 保存数据 存数据库和realtimebackup
+    def GetSaveData(self):
+        savaData = ""
+        cntData = ""
+        cnt = 0
+        
+        for dbData in self.__viewCacheList:
+            cnt += 1
+            savaData += dbData.GetBuffer()
+            
+        GameWorld.Log("Save DBPlayerViewCache count :%s len=%s" % (cnt, len(savaData)))
+        return CommFunc.WriteDWORD(cntData, cnt) + savaData
+    
+    # 从数据库载入数据
+    def LoadPyGameData(self, datas, pos, dataslen):
+        cnt, pos = CommFunc.ReadDWORD(datas, pos)
+        GameWorld.Log("Load DBPlayerViewCache count :%s" % cnt)
+        
+        for _ in xrange(cnt):
+            dbData = DBStruct.tagDBPlayerViewCache()
+            pos += dbData.readData(datas, pos, dataslen)
+            self.InitViewCacheInstance(dbData)
+            
+        self.Sort()
+        return pos
+    
+def OnPlayerLogout(curPlayer):
+    if curPlayer.GetLV() >= 10:
+        UpdPlayerViewCache(curPlayer)
+        
+    return
+
+def UpdPlayerViewCache(curPlayer, isOffline=False):
+    '''更新玩家查看缓存数据,更新时机由外层自己判断,这里只做更新逻辑
+    1. 下线时强制更新一次,上线暂不更新,上线时由各功能如果有需要用到触发更新
+    2. 有需要用到缓存数据时,如果玩家在线,1分钟内多次获取时最多更新一次,没有获取缓存数据则不更新
+    '''
+    if not curPlayer:
+        return
+    
+    playerID = curPlayer.GetPlayerID()
+    curCache = DBDataMgr.GetPlayerViewCacheMgr().GetPlayerViewCache(playerID)
+    if not curCache:
+        return
+    
+    tick = GameWorld.GetGameWorld().GetTick()
+    curPlayer.SetDict(Key_UpdViewCacheTick, tick)
+    GameWorld.DebugLog("更新玩家查看缓存数据! isOffline=%s" % isOffline, playerID)
+    curCache.SetAccID(curPlayer.GetAccID())
+    curCache.SetPlayerName(curPlayer.GetPlayerName())
+    curCache.SetLV(curPlayer.GetLV())
+    curCache.SetJob(curPlayer.GetJob())
+    curCache.SetRealmLV(curPlayer.GetOfficialRank())
+    curCache.SetFace(curPlayer.GetFace())
+    curCache.SetFacePic(curPlayer.GetFacePic())
+    curCache.SetFamilyID(curPlayer.GetFamilyID())
+    curCache.SetFamilyName(curPlayer.GetFamilyName())
+    curCache.SetFamilyEmblemID(PlayerControl.GetFamilyEmblemID(curPlayer))
+    curCache.SetTitleID(PlayerControl.GetTitleID(curPlayer))
+    curCache.SetFightPowerTotal(PlayerControl.GetFightPower(curPlayer))
+    curCache.SetServerID(GameWorld.GetPlayerServerID(curPlayer))
+    if isOffline:
+        curCache.SetOffTime(int(time.time()))
+        
+    plusDict = curCache.GetPlusDict()
+        
+    #战斗属性
+    plusDict.update({
+                     "MinAtk":curPlayer.GetMinAtk(),
+                     "MaxAtk":curPlayer.GetMaxAtk(),
+                     "Def":curPlayer.GetDef(),
+                     "MaxHP":GameObj.GetMaxHP(curPlayer),
+                     "Hit":curPlayer.GetHit(),
+                     "Miss":curPlayer.GetMiss(),
+                     "SuperHitRate":curPlayer.GetSuperHitRate(), # 暴击率
+                     })
+    
+    # 功能数据
+    
+    # 其他
+    
+    return curCache
+
+    
\ No newline at end of file
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/__init__.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/__init__.py
new file mode 100644
index 0000000..1bed595
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/__init__.py
@@ -0,0 +1,4 @@
+'''
+本包主要针对数据结构体 DBStruct.py 进行二次数据封装
+仅对功能相关表底层数据逻辑进行处理,不关心功能业务逻辑
+'''
\ No newline at end of file
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/__init__.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/__init__.py
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DirtyList.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DirtyList.py
new file mode 100644
index 0000000..62cce84
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DirtyList.py
@@ -0,0 +1,75 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#---------------------------------------------------------------------
+#
+#---------------------------------------------------------------------
+##@package DirtyList
+# 存储禁言列表
+#
+# @author eggxp
+# @date 2010-3-31
+# @version 1.4
+#
+# @change: "2010-10-08 11:05" panwei 拔除服务器版本控制代码  
+# @change: "2012-05-25 16:00" jiang 字符合法性检查增加编码规则检查  
+# @change: "2012-06-28 15:00" jiang 编码格式開出配置
+# @change: "2012-09-03 10:00" whx 屏蔽转义字符
+#---------------------------------------------------------------------
+#"""Version = 2012-09-03 10:00"""
+#---------------------------------------------------------------------
+
+import GameWorld
+import ShareDefine
+import IpyGameDataPY
+
+def IsWordForbidden(inputText):
+    ## 判断是否合法
+    if not EncodingToUnicode(inputText):
+        return True
+    
+    if "\xe3\x85\xa4" in inputText:
+        GameWorld.Log("存在非法空白填充符!")
+        return True
+    
+    #屏蔽转义字符
+    for char in ShareDefine.Def_List_EscapeSequence:
+        if char in inputText:
+            return True
+        
+    #2008.12.21, 不用python的find, 改用AnsiPos
+    #出错: 对于"小红"名字不能注册, 因为"小红" ascII中包含禁用字符"『", 在第一个字节和第二个字节
+    #D0 A1 BA EC  -->  A1 BA
+    #所以改用bcb的AnsiPos
+    #AnsiPos说明:
+    #Note:  This function supports multi-byte character sets (MBCS).
+    #if inputText.find(eachLine) >= 0:
+    
+    return False # 等接口有了后再去除,暂时默认返回False
+
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in xrange(ipyDataMgr.GetDirtyListCount()):
+        ipyData = ipyDataMgr.GetDirtyListByIndex(index)
+        if GameWorld.GetGameWorld().FindStr(inputText, ipyData.GetWord()):
+            GameWorld.Log("屏蔽词: ID=%s" % (ipyData.GetID()))
+            return True
+        
+    for index in xrange(ipyDataMgr.GetDirtyNameCount()):
+        ipyData = ipyDataMgr.GetDirtyNameByIndex(index)
+        if GameWorld.GetGameWorld().FindStr(inputText, ipyData.GetWord()):
+            GameWorld.Log("玩家名屏蔽词: ID=%s" % (ipyData.GetID()))
+            return True
+        
+    return False
+
+def EncodingToUnicode(inputText):    
+    ## 检查字符的规则是否符合
+    if IpyGameDataPY.GetFuncCfg("EncodingTex", 1):
+        #不檢查
+        return True
+        
+    try:
+        unicode(inputText, IpyGameDataPY.GetFuncCfg("EncodingTex", 2))
+    except:
+        return False
+    
+    return True
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventShell.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventShell.py
index 6a56721..5297eff 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventShell.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventShell.py
@@ -3980,7 +3980,7 @@
 #@return 返回值无意义
 #@remarks 自定义函数:结束创建家族事件
 def ExitCreateFamily(curPlayer):
-    PlayerFamily.SendPack_GameServer_ClearViewFamilyState(curPlayer)
+    #PlayerFamily.SendPack_GameServer_ClearViewFamilyState(curPlayer)
     return
 
 #---------------------------------------------------------------------
@@ -4855,8 +4855,8 @@
 #  @return None
 #  @remarks
 def ViewAllFamilyInfo(index, clientData, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    PlayerFamily.SendPack_GameServer_ViewAllFamily(curPlayer)
+    #curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    #PlayerFamily.SendPack_GameServer_ViewAllFamily(curPlayer)
     return
 
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Func_11.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Func_11.py
index aa47293..c359676 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Func_11.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Func_11.py
@@ -61,7 +61,7 @@
 #        return False
     
     #开始创建家族
-    PlayerFamily.SendPack_GameServer_InputFamilyName(curPlayer)
+    #PlayerFamily.SendPack_GameServer_InputFamilyName(curPlayer)
     return True
 
 #---------------------------------------------------------------------
@@ -71,7 +71,7 @@
 # @return 返回值无意义
 # @remarks 查看家族 任务功能触发Fc_
 def WatchFamily(curPlayer, tick):
-    PlayerFamily.SendPack_GameServer_ViewAllFamily(curPlayer)
+    #PlayerFamily.SendPack_GameServer_ViewAllFamily(curPlayer)
     return
 #---------------------------------------------------------------------
 ##家族升级.
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py
new file mode 100644
index 0000000..bd743ce
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py
@@ -0,0 +1,248 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.CreateFamily
+#
+# @todo:创建假仙盟
+# @author hxp
+# @date 2025-05-09
+# @version 1.0
+#
+# 详细描述: 创建假仙盟
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-05-09 12:20"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import ShareDefine
+import IPY_PlayerDefine
+import PlayerFamily
+import DBDataMgr
+import random
+
+## 执行逻辑
+#  @param curPlayer 当前玩家
+#  @param gmList []
+#  @return None
+def OnExec(curPlayer, gmList):
+    
+    if not gmList:
+        #GameWorld.DebugAnswer(curPlayer, "创建跨服假仙盟: CreatFamily c 个数 [总战力 ServerID 等级 成员数]")
+        #GameWorld.DebugAnswer(curPlayer, "删除跨服假仙盟: CreatFamily c 0")
+        GameWorld.DebugAnswer(curPlayer, "建本服假仙盟: CreatFamily 个数 [总战力 ServerID 等级 成员数]")
+        GameWorld.DebugAnswer(curPlayer, "删本服假仙盟: CreatFamily 0")
+        GameWorld.DebugAnswer(curPlayer, "输出仙盟列表: CreatFamily pl [条数 从第x名]")
+        GameWorld.DebugAnswer(curPlayer, "输出仙盟明细: CreatFamily pf 仙盟ID")
+        GameWorld.DebugAnswer(curPlayer, "添加假申请人: CreatFamily j [申请数 仙盟ID]")
+        return
+    
+    value1 = gmList[0]
+    if value1 == "c":
+        # 跨服命令
+        return
+    
+    if value1 == "pl":
+        __printFamilyList(curPlayer, gmList)
+        return
+    
+    if value1 == "pf":
+        __printFamilyInfo(curPlayer, gmList)
+        return
+    
+    if value1 == "j":
+        __addFackRequestJoin(curPlayer, gmList)
+        return
+    
+    creatCount = value1
+    if creatCount <= 0:
+        __delFackFamily(curPlayer)
+        return
+    __createFackFamily(curPlayer, gmList)
+    return
+
+def __addFackRequestJoin(curPlayer, gmList):
+    reqCnt = gmList[1] if len(gmList) > 1 else 1
+    familyID = gmList[2] if len(gmList) > 2 else curPlayer.GetFamilyID()
+    
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        GameWorld.DebugAnswer(curPlayer, "没有该仙盟: %s" % familyID)
+        return
+    
+    reqCnt = min(reqCnt, 100)
+    fackIDList = range(1, 200)
+    random.shuffle(fackIDList)
+    addCnt = 0
+    reqDict = family.GetReqJoinPlayerInfo()
+    for fackID in fackIDList:
+        if fackID in reqDict:
+            continue
+        family.AddReqJoinPlayerID(fackID)
+        addCnt += 1
+        if addCnt >= reqCnt:
+            break
+    # 广播给有招人权限的
+    clientPack = PlayerFamily.GetPack_FamilyReqJoinInfo(familyID)
+    PlayerFamily.Broadcast_FamilyPack(familyID, clientPack, PlayerFamily.FamilyPowerID_Call)
+    GameWorld.DebugAnswer(curPlayer, "增加申请数:%s, 总申请:%s" % (addCnt, len(family.GetReqJoinPlayerInfo())))
+    return
+
+def __printFamilyList(curPlayer, gmList):
+    printCnt = gmList[1] if len(gmList) > 1 else 100
+    fromIndex = gmList[2] if len(gmList) > 2 else 0
+    
+    printAnswerCnt = 0
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    familyMgr.Sort()
+    familyCnt = familyMgr.GetCount()
+    GameWorld.DebugAnswer(curPlayer, "仙盟总数: %s" % familyCnt)
+    for index in range(fromIndex, fromIndex + printCnt):
+        if index >= familyCnt:
+            break
+        family = familyMgr.GetAt(index)
+        rank = index + 1
+        
+        text = "%s,ID:%s,LV:%s,战力:%s,成员:%s" % (rank, family.GetID(), family.GetLV(), family.GetFightPowerTotal(), family.GetCount())
+        printAnswerCnt += 1
+        if printAnswerCnt <= 100:
+            GameWorld.DebugAnswer(curPlayer, text)
+        else:
+            GameWorld.DebugLog(text)
+            
+    return
+
+def __printFamilyInfo(curPlayer, gmList):
+    familyID = gmList[1] if len(gmList) > 1 else curPlayer.GetFamilyID()
+    
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        GameWorld.DebugAnswer(curPlayer, "仙盟不存在: %s" % familyID)
+        return
+    
+    GameWorld.DebugAnswer(curPlayer, "----- 【%s】 -----" % (GameWorld.CodeToGbk(family.GetName())))
+    GameWorld.DebugAnswer(curPlayer, "仙盟ID:%s,ServerID:%s" % (familyID, family.GetServerID()))
+    GameWorld.DebugAnswer(curPlayer, "LV:%s,Exp:%s" % (family.GetLV(), family.GetExp()))
+    GameWorld.DebugAnswer(curPlayer, "审核:%s,等级条件:%s,申请数:%s" % (family.GetJoinReview(), family.GetJoinLVMin(), len(family.GetReqJoinPlayerInfo())))
+    GameWorld.DebugAnswer(curPlayer, "徽章:%s" % (family.GetEmblemID()))
+    GameWorld.DebugAnswer(curPlayer, "总战力:%s,人数:%s" % (family.GetFightPowerTotal(), family.GetCount()))
+    GameWorld.DebugAnswer(curPlayer, "盟主:%s" % (family.GetLeaderID()))
+    for index in range(family.GetCount()):
+        member = family.GetAt(index)
+        playerID = member.GetPlayerID()
+        fightPower = member.GetFightPowerTotal()
+        GameWorld.DebugAnswer(curPlayer, "%s,%s,职位:%s,战力:%s" % (index, playerID, member.GetFmLV(), fightPower))
+        
+    return
+
+def __delFackFamily(curPlayer):
+    
+    delCnt = 0
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    for index in range(familyMgr.GetCount())[::-1]:
+        family = familyMgr.GetAt(index)
+        familyID = family.GetID()
+        if familyID > ShareDefine.FackFamilyIDMax:
+            continue
+        familyMgr.DelFamily(family.GetID())
+        
+    if curPlayer:
+        GameWorld.DebugAnswer(curPlayer, "删除假仙盟数: %s,剩余:%s" % (delCnt, familyMgr.GetCount()))
+    elif GameWorld.IsCrossServer():
+        GameWorld.DebugAnswer(None, "删除跨服假仙盟: %s,剩余:%s" % (delCnt, familyMgr.GetCount()))
+    return
+
+def __createFackFamily(curPlayer, gmList):
+    ## 个数 [总战力 ServerID 等级 成员数]
+    
+    creatCount = gmList[0] if len(gmList) > 0 else 1 # 默认1个
+    familyFightPower = gmList[1] if len(gmList) > 1 else 10000000
+    serverID = gmList[2] if len(gmList) > 2 else random.randint(1, 200)
+    familyLV = gmList[3] if len(gmList) > 3 else 1 # 默认1级
+    memberCnt = gmList[4] if len(gmList) > 4 else random.randint(1, 10)
+    
+    FakeFamilyName = GameWorld.GbkToCode("神秘军团")
+    
+    fackFamilyID = ShareDefine.FackFamilyIDStart
+    fackMemID = ShareDefine.FackPlayerIDStart
+    fackMemIDMax = ShareDefine.FackPlayerIDMax
+    
+    fackMemIDList = []
+    createOKCnt = 0
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    for _ in range(min(creatCount, 100)):
+        fackFamily = familyMgr.FindFamily(fackFamilyID)
+        while fackFamily and fackFamilyID < ShareDefine.FackFamilyIDMax:
+            for m in xrange(fackFamily.GetCount()):
+                member = fackFamily.GetAt(m)
+                memID = member.GetPlayerID()
+                if memID and memID not in fackMemIDList:
+                    fackMemIDList.append(memID)
+            fackFamilyID += 1
+            fackFamily = familyMgr.FindFamily(fackFamilyID)
+            
+        if fackFamily:
+            break
+        
+        fackFamilyName = "%s%s" % (FakeFamilyName, fackFamilyID)
+        fackFamily = familyMgr.AddFamily(fackFamilyID, fackFamilyName, serverID)
+        fackFamilyID += 1
+        if not fackFamily:
+            continue
+        
+        fackFamily.SetLV(familyLV)
+        fackFamily.SetFightPowerTotal(familyFightPower)
+        fackFamily.SetEmblemID(1)
+        fackFamily.SetJoinReview(1) # 设置需要审核
+        fackFamily.SetJoinLVMin(random.randint(0, 1000))
+        
+        GameWorld.DebugLog("创建假仙盟: fackFamilyID=%s,serverID=%s,familyFightPower=%s,memberCnt=%s" 
+                           % (fackFamilyID, serverID, familyFightPower, memberCnt))
+        for _ in range(memberCnt):
+            
+            while fackMemID in fackMemIDList and fackMemID < fackMemIDMax:
+                fackMemID += 1
+                    
+            if fackMemID in fackMemIDList:
+                break
+            
+            member = fackFamily.AddMember(fackMemID)
+            if not member:
+                continue
+            
+            if not fackFamily.GetLeaderID():
+                member.SetFmLV(IPY_PlayerDefine.fmlLeader)
+                fackFamily.SetLeaderID(fackMemID)
+                
+            fackMemID += 1
+            
+        # 根据成功创建的成员平均分配总战力
+        memFightPowerTotal = familyFightPower
+        memCnt = fackFamily.GetCount()
+        avgValue = memFightPowerTotal / memCnt
+        for m in range(memCnt):
+            member = fackFamily.GetAt(m)
+            memID = member.GetPlayerID()
+            fmLV = member.GetFmLV()
+            if m == memCnt - 1:
+                memFightPower = memFightPowerTotal
+            else:
+                memFightPower = avgValue + memCnt / 2 - m
+                memFightPowerTotal -= memFightPower
+            viewCache = DBDataMgr.GetPlayerViewCacheMgr().FindViewCache(memID, True)
+            viewCache.SetFightPowerTotal(memFightPower)
+            GameWorld.DebugLog("    仙盟成员: memID=%s,memFightPower=%s,fmLV=%s" % (memID, memFightPower, fmLV))
+            member.RefreshMemberByID(memID)
+            
+        createOKCnt += 1
+        familyFightPower += 10000
+        
+    familyMgr.Sort()
+    if curPlayer:
+        GameWorld.DebugAnswer(curPlayer, "成功创建假仙盟: %s,剩余:%s" % (creatCount, familyMgr.GetCount()))
+    elif GameWorld.IsCrossServer():
+        GameWorld.DebugAnswer(None, "成功创建跨服假仙盟: %s,总:%s" % (creatCount, familyMgr.GetCount()))
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Zhenbaoge.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Zhenbaoge.py
index 2933ce4..ae37ea9 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Zhenbaoge.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Zhenbaoge.py
@@ -17,7 +17,7 @@
 
 import GameWorld
 import PlayerControl
-import PlayerFamily
+import PlayerFamilyZhenbaoge
 import ChConfig
 import time
 
@@ -49,7 +49,7 @@
     elif value1 == "d":
         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeCut, 0)
         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy, 0)
-        PlayerFamily.Sync_ZhenbaogeInfo(curPlayer)
+        PlayerFamilyZhenbaoge.Sync_ZhenbaogeInfo(curPlayer)
         GameWorld.DebugAnswer(curPlayer, "重置珍宝阁玩家今日状态OK")
         return
     
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
index 8de3a0d..c71d18d 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
@@ -1384,8 +1384,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 ToIntDef(infoList[-1][1:])
 
@@ -1879,18 +1879,12 @@
 #  @param inputText 输入的文字
 #  @return: 是否符合编码格式
 def EncodingToUnicode(inputText):
-    encodingList = ReadChConfig.GetEvalChConfig("EncodingTex")
-    
-    if len(encodingList) != 2:
-        ErrLog("EncodingTex.txt Error len != 2")
-        return False
-    
-    if encodingList[0]:
+    if IpyGameDataPY.GetFuncCfg("EncodingTex", 1):
         #不檢查
         return True
         
     try:
-        unicode(inputText, encodingList[1])
+        unicode(inputText, IpyGameDataPY.GetFuncCfg("EncodingTex", 2))
     except:
         return False
     
@@ -1898,23 +1892,10 @@
 
 
 # 获得游戏设置的字符编码
-def GetCharacterEncoding():
-    encodingList = ReadChConfig.GetEvalChConfig("EncodingTex")
-    
-    if len(encodingList) != 2:
-        ErrLog("EncodingTex.txt Error len != 2")
-        return 'utf8'
-    return encodingList[1]
-
+def GetCharacterEncoding(): return IpyGameDataPY.GetFuncCfg("EncodingTex", 2)
 
 # 服务器默认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:
@@ -1922,6 +1903,14 @@
     
     return inputText
 
+def CodeToGbk(inputText):
+    try:
+        return inputText.decode(GetCharacterEncoding()).encode(ShareDefine.Def_Game_Character_Encoding)
+    except:
+        return inputText
+    
+    return inputText
+
 def IsCrossServer():
     ## 是否跨服服务器
     return ToIntDef(ReadChConfig.GetPyMongoConfig("Merge", "IsMergeServer"), 0)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldProcess.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldProcess.py
index 397afc1..77e539c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldProcess.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldProcess.py
@@ -52,6 +52,7 @@
 import GameMap
 import NPCRealmRefresh
 import IpyGameDataPY
+import DBDataMgr
 #---------------------------------------------------------------------
 ## 副本开启
 #  @param gameWorld IPY_GameWorld
@@ -592,6 +593,9 @@
 #  @return None
 #  @remarks 函数详细说明.
 def InitGameWorld(tick):
+    if not PyGameData.g_initGame:
+        PyGameData.g_initGame = True
+        DBDataMgr.OnServerStart()
     gameWorld = GameWorld.GetGameWorld()
     ItemCommon.InitPyItem()
     EventShell.DoReloadRefresh()
@@ -777,6 +781,8 @@
     curMinute = curTime.minute
     if curMinute == PyGameData.g_mapLastProcess_Minute:
         return
+    if PyGameData.g_initGame:
+        DBDataMgr.OnMinute(curMinute)
     PyGameData.g_mapLastProcess_Minute = curMinute
     PlayerTeam.OnCheckTeamPlayerDisconnectTimeout(tick)
     
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index 49273bf..09f93a8 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -11,6 +11,8 @@
 #
 # 详细描述: 读取PY表
 #
+# @note: 本脚本由 \PySysDB\生成IpyGameDataPY 生成
+#
 #-------------------------------------------------------------------------------
 #"""Version = 2018-05-10 12:00"""
 #-------------------------------------------------------------------------------
@@ -33,6 +35,16 @@
 }
 '''
 Def_IpyTable = {
+                "DirtyList":(
+                        ("WORD", "ID", 0),
+                        ("char", "Word", 0),
+                        ),
+
+                "DirtyName":(
+                        ("WORD", "ID", 0),
+                        ("char", "Word", 0),
+                        ),
+
                 "Dienstgrad":(
                         ("DWORD", "ID", 1),
                         ("WORD", "Type", 0),
@@ -2417,6 +2429,35 @@
                         ("list", "AwardItemList", 0),
                         ),
 
+                "Family":(
+                        ("BYTE", "FamilyLV", 1),
+                        ("BYTE", "MemberMax", 0),
+                        ("BYTE", "DeputyLeaderMax", 0),
+                        ("BYTE", "EliteMax", 0),
+                        ("DWORD", "NeedExp", 0),
+                        ("DWORD", "ZhenbaogeWeights", 0),
+                        ),
+
+                "FamilyEmblem":(
+                        ("BYTE", "EmblemID", 1),
+                        ("BYTE", "UnlockFamilyLV", 0),
+                        ("DWORD", "ExpireMinutes", 0),
+                        ("DWORD", "CustomFamilyID", 0),
+                        ),
+
+                "FamilyZhenbaogeCut":(
+                        ("BYTE", "CutNum", 1),
+                        ("DWORD", "CutWeight", 0),
+                        ("float", "MinRatio", 0),
+                        ("float", "RandRatio", 0),
+                        ),
+
+                "FamilyZhenbaogeItem":(
+                        ("BYTE", "ItemGroupNum", 1),
+                        ("DWORD", "ItemWeight", 0),
+                        ("list", "ItemList", 0),
+                        ),
+
                 "FamilyZhenfa":(
                         ("BYTE", "ZhenfaType", 1),
                         ("WORD", "ZhenfaLV", 1),
@@ -2589,6 +2630,26 @@
                         ),
                 }
 
+
+# 屏蔽词
+class IPY_DirtyList():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetID(self): return self.attrTuple[0] # WORD
+    def GetWord(self): return self.attrTuple[1] # 屏蔽词 char
+
+# 玩家名屏蔽词
+class IPY_DirtyName():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetID(self): return self.attrTuple[0] # WORD
+    def GetWord(self): return self.attrTuple[1] # 屏蔽词 char
 
 # 称号表
 class IPY_Dienstgrad():
@@ -6184,6 +6245,55 @@
     def GetNeedHurtTotal(self): return self.attrTuple[2] # 所需总伤血 DWORD
     def GetAwardItemList(self): return self.attrTuple[3] # 奖励物品列表[[物品ID,个数,是否拍品], ...] list
 
+# 仙盟等级表
+class IPY_Family():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetFamilyLV(self): return self.attrTuple[0] # 仙盟等级 BYTE
+    def GetMemberMax(self): return self.attrTuple[1] # 成员数上限 BYTE
+    def GetDeputyLeaderMax(self): return self.attrTuple[2] # 副盟主数上限 BYTE
+    def GetEliteMax(self): return self.attrTuple[3] # 精英数上限 BYTE
+    def GetNeedExp(self): return self.attrTuple[4] # 升级所需经验 DWORD
+    def GetZhenbaogeWeights(self): return self.attrTuple[5] # 珍宝阁总权重 DWORD
+
+# 仙盟徽章表
+class IPY_FamilyEmblem():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetEmblemID(self): return self.attrTuple[0] # 徽章ID BYTE
+    def GetUnlockFamilyLV(self): return self.attrTuple[1] # 解锁仙盟等级,为0时代表其他方式解锁 BYTE
+    def GetExpireMinutes(self): return self.attrTuple[2] # 有效时长,分钟 DWORD
+    def GetCustomFamilyID(self): return self.attrTuple[3] # 定制仙盟ID DWORD
+
+# 仙盟珍宝阁砍价表
+class IPY_FamilyZhenbaogeCut():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetCutNum(self): return self.attrTuple[0] # 砍价人次 BYTE
+    def GetCutWeight(self): return self.attrTuple[1] # 砍价权重 DWORD
+    def GetMinRatio(self): return self.attrTuple[2] # 保底比值 float
+    def GetRandRatio(self): return self.attrTuple[3] # 随机比值 float
+
+# 仙盟珍宝阁物品表
+class IPY_FamilyZhenbaogeItem():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetItemGroupNum(self): return self.attrTuple[0] # 物品组编号 BYTE
+    def GetItemWeight(self): return self.attrTuple[1] # 随机权重 DWORD
+    def GetItemList(self): return self.attrTuple[2] # 物品列表[[物品ID,个数,是否拍品], ...] list
+
 # 仙盟阵法表
 class IPY_FamilyZhenfa():
     
@@ -6525,6 +6635,8 @@
         Log("IPY_DataMgr Reload... onlyCheck=%s" % onlyCheck)
         if not onlyCheck:
             self.ipyConfigEx = {}
+        self.__LoadFileData("DirtyList", onlyCheck)
+        self.__LoadFileData("DirtyName", onlyCheck)
         self.__LoadFileData("Dienstgrad", onlyCheck)
         self.__LoadFileData("TitleStarUp", onlyCheck)
         self.__LoadFileData("PlayerFace", onlyCheck)
@@ -6767,6 +6879,10 @@
         self.__LoadFileData("EquipPlusEvolve", onlyCheck)
         self.__LoadFileData("FamilyBossAward", onlyCheck)
         self.__LoadFileData("FamilyBossHurtAward", onlyCheck)
+        self.__LoadFileData("Family", onlyCheck)
+        self.__LoadFileData("FamilyEmblem", onlyCheck)
+        self.__LoadFileData("FamilyZhenbaogeCut", onlyCheck)
+        self.__LoadFileData("FamilyZhenbaogeItem", onlyCheck)
         self.__LoadFileData("FamilyZhenfa", onlyCheck)
         self.__LoadFileData("ItemWashMax", onlyCheck)
         self.__LoadFileData("HorsePetBossAward", onlyCheck)
@@ -6802,10 +6918,12 @@
     
     def __LoadFileData(self, tableName, onlyCheck=False):
         # @param onlyCheck: 是否仅检查格式,一般启动时用
-        curPath = ChConfig.GetDBPath() + "\\PySysDB\\tag" + tableName + ".txt"
+        curPath = ChConfig.GetDBPath() + "\\PySysDB\\" + tableName + ".txt"
         if not os.path.isfile(curPath):
-            ErrLog("can not find file = %s,%s" % (tableName, curPath))
-            raise Exception("can not find file = %s,%s" % (tableName, curPath))
+            curPath = ChConfig.GetDBPath() + "\\PySysDB\\tag" + tableName + ".txt"
+            if not os.path.isfile(curPath):
+                ErrLog("can not find file = %s,%s" % (tableName, curPath))
+                raise Exception("can not find file = %s,%s" % (tableName, curPath))
         
         if not onlyCheck:
             if not hasattr(self, "ipy%sLen" % tableName):
@@ -6998,6 +7116,20 @@
                 setList = tuple(setList)
         return setList
     
+
+    def GetDirtyListCount(self):
+        self.CheckLoadData("DirtyList")
+        return self.ipyDirtyListLen
+    def GetDirtyListByIndex(self, index):
+        self.CheckLoadData("DirtyList")
+        return self.ipyDirtyListCache[index]
+
+    def GetDirtyNameCount(self):
+        self.CheckLoadData("DirtyName")
+        return self.ipyDirtyNameLen
+    def GetDirtyNameByIndex(self, index):
+        self.CheckLoadData("DirtyName")
+        return self.ipyDirtyNameCache[index]
 
     def GetDienstgradCount(self):
         self.CheckLoadData("Dienstgrad")
@@ -8693,6 +8825,34 @@
         self.CheckLoadData("FamilyBossHurtAward")
         return self.ipyFamilyBossHurtAwardCache[index]
 
+    def GetFamilyCount(self):
+        self.CheckLoadData("Family")
+        return self.ipyFamilyLen
+    def GetFamilyByIndex(self, index):
+        self.CheckLoadData("Family")
+        return self.ipyFamilyCache[index]
+
+    def GetFamilyEmblemCount(self):
+        self.CheckLoadData("FamilyEmblem")
+        return self.ipyFamilyEmblemLen
+    def GetFamilyEmblemByIndex(self, index):
+        self.CheckLoadData("FamilyEmblem")
+        return self.ipyFamilyEmblemCache[index]
+
+    def GetFamilyZhenbaogeCutCount(self):
+        self.CheckLoadData("FamilyZhenbaogeCut")
+        return self.ipyFamilyZhenbaogeCutLen
+    def GetFamilyZhenbaogeCutByIndex(self, index):
+        self.CheckLoadData("FamilyZhenbaogeCut")
+        return self.ipyFamilyZhenbaogeCutCache[index]
+
+    def GetFamilyZhenbaogeItemCount(self):
+        self.CheckLoadData("FamilyZhenbaogeItem")
+        return self.ipyFamilyZhenbaogeItemLen
+    def GetFamilyZhenbaogeItemByIndex(self, index):
+        self.CheckLoadData("FamilyZhenbaogeItem")
+        return self.ipyFamilyZhenbaogeItemCache[index]
+
     def GetFamilyZhenfaCount(self):
         self.CheckLoadData("FamilyZhenfa")
         return self.ipyFamilyZhenfaLen
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NetPackCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NetPackCommon.py
index daa622f..2213f4d 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NetPackCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NetPackCommon.py
@@ -218,6 +218,8 @@
 #  @return 无返回值
 #  @remarks
 def SendFakePack(curPlayer, clientPack):
+    if not clientPack:
+        return
 #    Log("SendFakePack: clientPack = %s"%[clientPack.GetBuffer()])
     innerPackData = clientPack.GetBuffer()
     if len(innerPackData) < clientPack.GetLength():
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
index db3008c..1c4fbf6 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -586,8 +586,6 @@
         #---玩家上线, 宠物逻辑处理---
         PetControl.DoLogic_PetInfo_OnLogin(curPlayer, tick)
         
-        PlayerFamily.FamilyPlayerOnLoginCross(curPlayer)
-        
         PlayerTeam.OnPlayerLoginCrossServer(curPlayer)
         return
     
@@ -726,8 +724,6 @@
     #充值活动玩家登入处理
     #PlayerGoldAction.DoLogic_PlayerOnLogin(curPlayer)
     
-    # 通知玩家是否可以参加家族活动
-    #PlayerFamily.SendClientForbidFamilyAction(curPlayer)
     # 提示贵宾俱乐部信息
     #PlayerVip.NoteVIPClubInfo(curPlayer)
     
@@ -785,7 +781,7 @@
     #同步自动战斗配置记录
 #    Sync_AutoFightSetting(curPlayer)
     
-    PlayerFamily.FamilyPlayerOnLogin(curPlayer, tick)
+    PlayerFamily.OnPlayerLogin(curPlayer, tick)
     #改到 GameServerRefresh GameSever_PlayerInitOK后处理才能保证玩家已经在Gameserver注册
     #PlayerDienstgrad.RefreshBillBoardDienstgrad(curPlayer)
     # 称号
@@ -5598,9 +5594,6 @@
     # 每日免费直购礼包
     elif rewardType == ChConfig.Def_RewardType_DayFreeGoldGift:
         PlayerDailyGiftbag.OnGetDailyFreeGiftbag(curPlayer)
-    # 仙盟活跃度奖励
-    elif rewardType == ChConfig.Def_RewardType_FamilyActivity:
-        PlayerFamily.GetFamilyActivityAward(curPlayer, dataEx)
     # 仙盟联赛冠军仙盟每日俸禄奖励
     elif rewardType == ChConfig.Def_RewardType_ChampionFamilyDailyReward:
         GameLogic_FamilyWar.GetChampionFamilyDailyReward(curPlayer)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
index 4bc6a23..cdc027c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -89,6 +89,7 @@
 import PlayerTongTianLing
 import PlayerCrossRealmPK
 import FunctionNPCCommon
+import DBPlayerViewCache
 import PlayerGoldInvest
 import IPY_PlayerDefine
 import CrossRealmPlayer
@@ -1488,6 +1489,8 @@
     
     #玩家下线通知gameserver记录缓存(放在下线更新排行榜之后,方便Gameserver判断是否需要存入数据库中)
     PlayerViewCacheTube.OnPlayerLogOut(curPlayer, tick)
+    DBPlayerViewCache.OnPlayerLogout(curPlayer)
+    PlayerFamily.OnPlayerLogout(curPlayer)
     
     #玩家下线/玩家切换地图公用逻辑
     __PlayerLeaveServerLogic(curPlayer, tick, True)
@@ -7398,6 +7401,14 @@
 def GetFamilyEmblemID(curPlayer): return curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyEmblemID)
 def SetFamilyEmblemID(curPlayer, emblemID): NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyEmblemID, emblemID)
 
+# 仙盟职位,使用 GetReceivedSalary,因为FamilyMemberLV没有入库
+def GetFamilyMemberLV(curPlayer): return curPlayer.GetReceivedSalary()
+def SetFamilyMemberLV(curPlayer, fmLV):
+    #因为仙盟职位没有存DBPlayer,而跨服后又没有Family信息,所以这里做个存储,用于跨服用
+    curPlayer.SetReceivedSalary(fmLV)
+    curPlayer.SetFamilyMemberLV(fmLV) # 也同步设置该值,防止有些地方直接调用 curPlayer.GetFamilyMemberLV()
+    return
+
 # 仙盟事务速度加成
 def GetAffairSpeedPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AffairSpeedPer)
 def SetAffairSpeedPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AffairSpeedPer, value)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
index b438e41..0e9b165 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -605,7 +605,7 @@
         # 世界boss
         BossHurtMng.OnDay(curPlayer)
         # 仙盟过天
-        PlayerFamily.FamilyPlayerOnDay(curPlayer)
+        PlayerFamily.PlayerOnDay(curPlayer)
         # 重置物品每日使用次数
         ChItem.ResetItemUseCntToday(curPlayer)
         # 极品白拿
@@ -660,16 +660,6 @@
     #购买次数礼包
     PlayerActBuyCountGift.OnDay(curPlayer, onEventType)
     return
-
-
-### 服务器Onday处理数据,即不能在玩家上线时的Onday触发
-##  @param curPlayer: 当前玩家实例
-##  @return: 无
-#def PlayerServerDay(curPlayer):
-#    
-#    # 设置玩家是否可以参加家族活动
-#    #PlayerFamily.SetForbidFamilyAction(curPlayer, 0)
-#    return
 
 #---------------------------------------------------------------------
 ## 把当前这一周的在线时间算到上一周去
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py
index e7a0ee6..6e63e0f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py
@@ -13,170 +13,425 @@
 #---------------------------------------------------------------------
 #"""Version = 2017-07-12 21:00""" 
 #---------------------------------------------------------------------
-import IPY_GameWorld
-import GameWorld
-import EventShell
+
 import FBLogic
 import ChConfig
-import PlayerControl
+import GameWorld
 import ShareDefine
-import ReadChConfig
-import PlayerTruck
+import PlayerControl
 import NetPackCommon
 import ChPyNetSendPack
-import DataRecordPack
-import GameLogic_FamilyWar
-import GameLogic_FamilyBoss
-import ChMapToGamePyPack
 import PlayerFamilyTech
-import PlayerFamilyRedPacket
+import PlayerFamilyEmblem
 import PlayerFamilyZhenfa
-import PlayerTongTianLing
-import PlayerWeekParty
-import PlayerActivity
-import ItemControler
-import SkillCommon
-import BuffSkill
-import ItemCommon
-import PlayerSuccess
-import GameFuncComm
-import PlayerTJG
+import IPY_PlayerDefine
 import IpyGameDataPY
-import cPickle
+import IPY_GameWorld
+import GameFuncComm
+import ItemCommon
+import DBDataMgr
+import DirtyList
 
-import time
 import random
-#---------------------------------------------------------------------
-#家族刷新
-#class   IPY_MFamilyRefresh
-#{
-#public:
-#
-#    int      GetFamilyID();
-#
-#    char *      GetFamilyName();
-#};
-## 家族刷新
-#  @param index 玩家索引
-#  @param tick 当前时间
-#  @return None
-#  @remarks 函数详细说明.
-def GameServer_FamilyRefresh(index, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    refreshPack = IPY_GameWorld.IPY_MFamilyRefresh()
+import time
+
+#申请、审核、退出、踢人、捐献、升级
+
+Def_CreatFamily_MaxStr = 33
+
+#仙盟变更类型
+FamilyChangeTypes = (
+FamilyChangeType_None,
+FamilyChangeType_MemJoin, # 成员加入 1
+FamilyChangeType_MemLeave, # 成员退出 2
+FamilyChangeType_JoinSet, # 收人设置修改 3
+FamilyChangeType_Broadcast, # 公告修改 4
+FamilyChangeType_EChange, # 徽章修改 5
+FamilyChangeType_LeaderChange, # 盟主变更 6
+FamilyChangeType_MemFmlvChange, # 成员职位变更 7
+FamilyChangeType_MemLogin, # 成员上线 8
+FamilyChangeType_MemLogout, # 成员离线9
+) = range(10)
+
+#仙盟权限
+(
+FamilyPowerID_Call,         #招人 1
+FamilyPowerID_ChangeFmlv,   #变更职位 2
+FamilyPowerID_Broadcast,    #发布公告 3
+FamilyPowerID_Kick,         #踢人 4
+) = range(1, 1 + 4)
+
+#仙盟职位对应人数设置属性名
+Def_FmlSetAttrName = {
+                      IPY_PlayerDefine.fmlMember:"MemberMax",
+                      IPY_PlayerDefine.fmlCounsellor:"EliteMax",
+                      IPY_PlayerDefine.fmlViceLeader:"DeputyLeaderMax",
+                      }
+
+def PlayerOnDay(curPlayer):
+    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Family):
+        return
+    #每日福利奖励
+    Sync_FamilyDayRewardState(curPlayer)
+    __FamilyAffair_Refresh(curPlayer, True)
     
-    if curPlayer.GetID() != refreshPack.GetPlayerID():
-        #不是自己
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeCut, 0)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy, 0)
+    #PlayerFamilyZhenbaoge.Sync_ZhenbaogeInfo(curPlayer)
+    return
+
+def OnPlayerLogin(curPlayer, tick):
+    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Family):
+        return
+    PlayerLoginRefreshFamily(curPlayer, tick)
+    Sync_RequestAddFamilyInfo(curPlayer, False)
+    Sync_FamilyDayRewardState(curPlayer)
+    PlayerFamilyTech.Sync_PlayerFamilyTechLV(curPlayer)
+    __FamilyAffair_CheckReset(curPlayer)
+    PlayerFamilyZhenfa.OnPlayerLogin(curPlayer)
+    #PlayerFamilyZhenbaoge.Sync_ZhenbaogeInfo(curPlayer)
+    return
+
+def OnPlayerLogout(curPlayer):
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    if not familyID:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    curMember.SetOffTime(int(time.time()))
+    #XW_JZ_LeaguerLeaveline  <n color="0,190,255">{%S1%}</n><n color="255,255,0">下线了!</n>    25  -   -
+    NotifyAllFamilyMemberMsg(familyID, "XW_JZ_LeaguerLeaveline", [curPlayer.GetPlayerName()])
+    Broadcast_FamilyChange(familyID, FamilyChangeType_MemLogout, excludeIDList=[playerID])
+    return
+
+def OnWeekEx(curPlayer):
+    #重置
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyActivityAwardRecord, 0)
+    for actionid in ShareDefine.FamilyActiveIDList:
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyActivityFinishCnt%actionid, 0)
+    return
+
+def PlayerLoginRefreshFamily(curPlayer, tick):
+    ## 玩家登录时刷新家族
+    
+    playerID = curPlayer.GetPlayerID()
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    refreshFamilyID = familyMgr.GetPlayerFamilyID(playerID)
+    MapServer_FamilyRefresh(curPlayer, refreshFamilyID)
+    
+    familyID = curPlayer.GetFamilyID()
+    if not familyID:
         return
     
-    lastFamilyID = curPlayer.GetFamilyID()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    curMember.SetOffTime(0) # 在线0,脱机1,>1离线时间
+    curMember.RefreshMember(curPlayer)
+    Sync_FamilyInfo(curPlayer)
     
-#************族长变更删除发布任务*************************************************
-    if (curPlayer.GetFamilyMemberLV() == IPY_GameWorld.fmlLeader 
-        and refreshPack.GetFamilyMemberLV()!= IPY_GameWorld.fmlLeader):
-        EventShell.EventResponse_OnMemberChange(curPlayer)
-#*******************************************************************
+    #通知招人
+    if GetFamilyMemberHasPow(curMember, FamilyPowerID_Call):
+        NetPackCommon.SendFakePack(curPlayer, GetPack_FamilyReqJoinInfo(familyID))
+            
+    #XW_JZ_LeaguerOnline <n color="0,190,255">{%S1%}</n><n color="255,255,0">上线了!</n>    25  -   -
+    NotifyAllFamilyMemberMsg(familyID, "XW_JZ_LeaguerOnline", [curPlayer.GetName()], [playerID])
+    Broadcast_FamilyChange(familyID, FamilyChangeType_MemLogin, excludeIDList=[playerID])
+    
+    # 盟主上线处理
+    if curMember.GetFmLV() == IPY_PlayerDefine.fmlLeader:
+        OnFamilyLeaderLogin(curPlayer)
+    return
 
-    #---根据封包修改玩家家族属性---
-    if lastFamilyID != refreshPack.GetFamilyID():
-        curPlayer.SetFamilyID(refreshPack.GetFamilyID())
-        familyIDChangeTime = int(time.time())
-        #PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyIDChangeTime, familyIDChangeTime)
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_LastFamilyID, lastFamilyID)
-        GameWorld.Log("记录家族变更时间...familyIDChangeTime=%s,lastFamilyID=%s,nextFamilyID=%s" 
-                           % (familyIDChangeTime, lastFamilyID, refreshPack.GetFamilyID()), curPlayer.GetPlayerID())
-        
-        #触发玩家加入家族事件
-        EventShell.EventResponse_OnFamilyAdd(curPlayer)
-        
-    if curPlayer.GetFamilyName() != refreshPack.GetFamilyName():
-        curPlayer.SetFamilyName(refreshPack.GetFamilyName())
-        #通知周围玩家家族名称刷新
-        curPlayer.Notify_FamilyNameRefresh()
+def OnFamilyLeaderLogin(curPlayer):
+    ## 盟主登录额外处理
     
-    refreshFamilyLV = refreshPack.GetFamilyLV()
-    lastFamilyLV = curPlayer.GetFamilyLV()
-    if lastFamilyLV != refreshFamilyLV:
-        #任务需求,记录先前的家族等级
-        curPlayer.SetDict(ChConfig.Def_PlayerKey_FamilyLVLeave, lastFamilyLV)
+    return
+
+#// A6 04 创建家族 #tagCMCreateFamily
+#
+#struct    tagCMCreateFamily
+#{
+#    tagHead        Head;
+#    char        Name[33];
+#    WORD        EmblemID; //选择徽章ID,解锁仙盟等级为1级的均为可选ID
+#};
+def OnCreateFamily(index, clientPack, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    inputName = clientPack.Name
+    emblemID = clientPack.EmblemID
+    
+    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Family):
+        return
         
+    playerID = curPlayer.GetPlayerID()
+    playerFamilyID = curPlayer.GetFamilyID()
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    if playerFamilyID:
+        curFamily = familyMgr.FindFamily(playerFamilyID)
+        if curFamily:
+            if curFamily.FindMember(playerID):
+                #玩家已经有家族, 创建失败
+                PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_85890")
+                return
+            
+    fullFamilyName = CheckInputFamilyName(curPlayer, inputName)
+    if not fullFamilyName:
+        return
+    
+    needMoney = IpyGameDataPY.GetFuncCfg("CreateFamily", 1)
+    moneyType = IpyGameDataPY.GetFuncCfg("CreateFamily", 2)
+    if moneyType and needMoney:
+        if not PlayerControl.PayMoney(curPlayer, moneyType, needMoney, "CreateFamily"):
+            return
+        
+    newFamilyID = random.randint(10000, 20000) # 先随机,之后替换接口
+    serverID = GameWorld.GetPlayerServerID(curPlayer)
+    curFamily = familyMgr.AddFamily(newFamilyID, fullFamilyName, serverID)
+    if curFamily == None:
+        GameWorld.ErrLog("创建家族失败", playerID)
+        return
+    curFamily.SetLV(1)
+    emblemIDList = PlayerFamilyEmblem.GetDefaultFamilyEmblemIDList()
+    if not emblemID or emblemID not in emblemIDList:
+        emblemID = random.choice(emblemIDList) # 从默认徽章中随机选择一个
+    GameWorld.Log("创建仙盟: familyID=%s,playerID=%s,emblemID=%s" % (newFamilyID, playerID, emblemID))
+    curFamily.SetEmblemID(emblemID)
+    
+    #-设置家族成员属性
+    DoPlayerJionFamily(curFamily, playerID, curPlayer, IPY_PlayerDefine.fmlLeader)
+    familyMgr.Sort()
+    
+    #XW_JZ_EstablishSud <n color="255,255,0">恭喜您,家族建立成功!</n>    25  -   -
+    PlayerControl.NotifyCode(curPlayer, "XW_JZ_EstablishSud")
+    PlayerControl.WorldNotify(0, "jiazu_liubo_671654", [curPlayer.GetName(), fullFamilyName, newFamilyID])
+    #PlayerFamilyZhenbaoge.OnZhenbaogeReset(curFamily)
+    return
+
+def CheckInputFamilyName(curPlayer, inputName):
+    '''检查玩家输入的仙盟名是否合法,建盟、改名通用
+    @return: None-不合法;非空-合法的仙盟全名
+    '''
+    #C++过滤空格
+    familyName = GameWorld.GetGameWorld().GetCharTrim(inputName)
+    fullFamilyName = GetFamilyFullName(curPlayer, familyName)
+    if not fullFamilyName:
+        GameWorld.ErrLog("家族全名异常!", curPlayer.GetPlayerID())
+        return
+    
+    if DirtyList.IsWordForbidden(familyName):
+        #XW_JZ_Family_NameNoLegality 对不起,家族名称中含有非法字符
+        PlayerControl.NotifyCode(curPlayer, "XW_JZ_Family_NameNoLegality")
+        return
+    
+    if len(familyName) <= 0 or len(familyName) > Def_CreatFamily_MaxStr:
+        PlayerControl.NotifyCode(curPlayer, "GeRen_liubo_980181", [Def_CreatFamily_MaxStr / 2, Def_CreatFamily_MaxStr])
+        return
+    
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    if familyMgr.FindFamilyByName(fullFamilyName):
+        #XW_JZ_EstablishErr_Name    <n color="255,255,0">对不起,您输入的家族名已存在,建立家族失败!</n> 25  -   -
+        PlayerControl.NotifyCode(curPlayer, "XW_JZ_EstablishErr_Name")
+        return
+    
+    return fullFamilyName
+
+
+## 获取家族全名
+def GetFamilyFullName(curPlayer, familyName):
+    serverID = GameWorld.GetPlayerServerID(curPlayer)
+    
+    maxServerID = IpyGameDataPY.GetFuncCfg("FamilyNameFormat", 3)
+    if serverID > maxServerID or serverID <= 0:
+        GameWorld.ErrLog("仙盟全名 serverID=%s error! maxServerID=%s, check FamilyNameFormat.txt" % (serverID, maxServerID))
+        return ""
+    
+    specServerDict = IpyGameDataPY.GetFuncEvalCfg("FamilyNameFormat", 4, {})
+    nameFormatInfo = GameWorld.GetDictValueByRangeKey(specServerDict, serverID)
+    if not nameFormatInfo:
+        nameFormatInfo = IpyGameDataPY.GetFuncEvalCfg("FamilyNameFormat", 1)
+    if not nameFormatInfo:
+        return ""
+    nameFormat = nameFormatInfo[0]
+    paramList = [eval(pName) for pName in nameFormatInfo[1:]]
+    fullName = nameFormat % tuple(paramList)
+    
+    maxLen = IpyGameDataPY.GetFuncCfg("FamilyNameFormat", 2)
+    if len(fullName) > maxLen:
+        GameWorld.ErrLog("仙盟全名 familyName=%s,全名=%s len=%s > %s, check FamilyNameFormat.txt" % (familyName, fullName, len(fullName), maxLen))
+        PlayerControl.NotifyCode(curPlayer, "GeRen_liubo_980181", [maxLen / 2, maxLen])
+        return ""
+    
+    return fullName
+
+def DoPlayerJionFamily(family, playerID, jionPlayer, jionFamilySetLv=IPY_PlayerDefine.fmlMember, broadcastFamilyChange=True):
+    '''加入家族,支持离线玩家加入
+    @param jionPlayer: 如果是离线玩家则为None
+    '''
+    if isinstance(family, int):
+        familyID = family
+        familyMgr = DBDataMgr.GetFamilyMgr()
+        curFamily = familyMgr.FindFamily(familyID)
+    else:
+        curFamily = family
+        
+    if not curFamily:
+        return
+    
+    familyID = curFamily.GetID()
+    member = curFamily.AddMember(playerID)
+    member.SetFmLV(jionFamilySetLv)
+    if jionPlayer:
+        member.RefreshMember(jionPlayer)
+    else:
+        member.RefreshMemberByID(playerID)
+    curFamily.SetFightPowerTotal(curFamily.GetFightPowerTotal() + member.GetFightPowerTotal())
+    
+    if jionFamilySetLv == IPY_PlayerDefine.fmlLeader:
+        curFamily.SetLeaderID(playerID)
+        
+    #设置玩家身上保存的家族信息
+    if jionPlayer:
+        MapServer_FamilyRefresh(jionPlayer, familyID)
+        Sync_FamilyInfo(jionPlayer)
+        
+    if jionFamilySetLv != IPY_PlayerDefine.fmlLeader:
+        if broadcastFamilyChange:
+            Broadcast_FamilyChange(familyID, FamilyChangeType_MemJoin, excludeIDList=[playerID])
+        #通知所有家族成员, 这个人加入了家族
+        NotifyAllFamilyMemberMsg(familyID, "XW_JZ_EnterFamily", [member.GetPlayerName()], excludeIDList=[playerID])
+        if jionPlayer:
+            PlayerControl.NotifyCode(jionPlayer, 'XW_JZ_EnterFamilyInfo', [family.GetName()])
+            
+    #记录加入事件
+    tick = GameWorld.GetGameWorld().GetTick()
+    AddFamilyActionNote(member.GetPlayerName(), familyID, ShareDefine.Def_ActionType_FamilyEvent, 
+                        [ShareDefine.Def_FamilyActionEvent_MemberChange, ShareDefine.Def_FamilyMemberChange_Join, jionFamilySetLv, 0], tick)
+    
+    #玩家缓存
+    #PlayerViewCache.OnPlayerFamilyChange(jionPlayer.GetPlayerID(), curFamily.GetID(), curFamily.GetName())
+    #PlayerTeam.OnTeamMemFamilyRefresh(jionPlayer, curFamily.GetID())
+    #SetMemberFightPower(familyMember, PlayerControl.GetFightPower(jionPlayer))
+    #GetFamilyMgr().AddFamilyIDToFightPowerChangeList(curFamily.GetID(), jionPlayer.GetPlayerID())
+    return
+
+def AddFamilyActionNote(curName, familyID, actionType, actionDataList, tick, isClearNone=True, useData=""):
+    '''统一添加家族Action数据
+    '''
+    if actionType not in ShareDefine.Def_ActionTypeList:
+        #记录行为类型错误
+        GameWorld.ErrLog("记录家族行为类型:%s 错误")
+        return False
+    
+    familyAction = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(familyID, actionType)
+    actionData = familyAction.AddAction()
+    if not actionData:
+        return False
+    
+    #---设置行为对象数据---
+    actionData.SetName(curName)  # 设置名字
+    actionData.SetUserData(useData) # 设置自定义数据
+    for num, value in enumerate(actionDataList, 1):
+        setFunc = getattr(actionData, "SetValue%s" % num)
+        if setFunc:
+            setFunc(value)
+    return True
+
+def MapServer_FamilyRefresh(curPlayer, refreshFamilyID):
+    ''' 相当于GameServer调用 curPlayer.MapServer_FamilyRefresh()
+    @param familyID: 玩家更新的familyID
+    '''
+    
+    tick = GameWorld.GetGameWorld().GetTick()
+    playerID = curPlayer.GetPlayerID()
+    refreshFmLV = 0
+    refreshFamilyLV = 0
+    refreshEmblemID = 0
+    refreshFamilyName = ""
+    if refreshFamilyID:
+        familyMgr = DBDataMgr.GetFamilyMgr()
+        curFamily = familyMgr.FindFamily(refreshFamilyID)
+        if curFamily:
+            refreshFamilyLV = curFamily.GetLV()
+            refreshFamilyName = curFamily.GetName()
+            refreshEmblemID = curFamily.GetEmblemID()
+            member = curFamily.FindMember(playerID)
+            if member:
+                refreshFmLV = member.GetFmLV()
+        else:
+            refreshFamilyID = 0
+            
+    lastFamilyID = curPlayer.GetFamilyID()
+    lastFamilyLV = curPlayer.GetFamilyLV() # 仙盟等级,非职位等级
+    lastFmLV = PlayerControl.GetFamilyMemberLV(curPlayer)
+    
+    if lastFamilyID != refreshFamilyID:
+        curPlayer.SetFamilyID(refreshFamilyID)
+        
+    if curPlayer.GetFamilyName() != refreshFamilyName:
+        curPlayer.SetFamilyName(refreshFamilyName)
+        curPlayer.Notify_FamilyNameRefresh() #//04 36    周围玩家家族名刷新#tagPlayerFamilyNameRefresh
+        
+    if PlayerControl.GetFamilyEmblemID(curPlayer) != refreshEmblemID:
+        PlayerControl.SetFamilyEmblemID(curPlayer, refreshEmblemID)
+            
+    if lastFmLV != refreshFmLV:
+        PlayerControl.SetFamilyMemberLV(curPlayer, refreshFmLV)
+        
+    if lastFamilyLV != refreshFamilyLV:
         isLVUP = False
         if lastFamilyLV and refreshFamilyLV > 0:
             #触发家族升级事件
             isLVUP = True
-        
         curPlayer.SetFamilyLV(refreshFamilyLV)
         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyLV, refreshFamilyLV)
-        
-        __OnFamilyLVBuffChange(curPlayer, tick)
         #触发家族升级事件, 在SetFamilyLV之后,任务可以取等级判定
         if isLVUP:
-            EventShell.EventResponse_OnFamilyLVUp(curPlayer)
+            pass
+            #EventShell.EventResponse_OnFamilyLVUp(curPlayer)
         
-    if curPlayer.GetFamilyMemberLV() != refreshPack.GetFamilyMemberLV():
-        # 因为仙盟职位没有存DBPlayer,而跨服后又没有Family信息,所以这里做个存储,用于跨服用
-        curPlayer.SetReceivedSalary(refreshPack.GetFamilyMemberLV())
-        curPlayer.SetFamilyMemberLV(refreshPack.GetFamilyMemberLV())
-        #通知周围玩家家族职位刷新
-        #curPlayer.Notify_FamilyMemberLVRefresh()
-        GameLogic_FamilyWar.DoCheckChampionFamilyTitle(curPlayer)
-    
-    if curPlayer.GetFamilyMoney() != refreshPack.GetFamilyMoney():
-        curPlayer.SetFamilyMoney(refreshPack.GetFamilyMoney())
-    
-    if curPlayer.GetFamilyLastWeekActiveValue() != refreshPack.GetLastWeekFamilyActiveValue():
-        curPlayer.SetFamilyLastWeekActiveValue(refreshPack.GetLastWeekFamilyActiveValue())
-        
-    if PlayerControl.GetFamilyEmblemID(curPlayer) != refreshPack.GetExtra6():
-        PlayerControl.SetFamilyEmblemID(curPlayer, refreshPack.GetExtra6())
-        
-    #---处理特殊逻辑, 进入退出家族---
-
     if lastFamilyID != 0 and curPlayer.GetFamilyID() == 0:
         #玩家离开家族
         __OnLeaveFamily(curPlayer, tick)
         
-        #改变镖车身上记录的主人信息
-        PlayerTruck.ChangeTruckNoteInfo(curPlayer)
-
     elif lastFamilyID == 0 and curPlayer.GetFamilyID() != 0:
         #刚进家族并为族长,触发建家族事件
         if curPlayer.GetFamilyMemberLV() == IPY_GameWorld.fmlLeader:
-            EventShell.EventResponse_OnCreateFamily(curPlayer)
-        
+            pass
+            #EventShell.EventResponse_OnCreateFamily(curPlayer)
+            
         #进入家族触发事件
         __OnEnterFamily(curPlayer, tick)
         
-        #改变镖车身上记录的主人信息
-        PlayerTruck.ChangeTruckNoteInfo(curPlayer)
-        
     #---通知客户端刷新属性---
-    curPlayer.View_FamilyInfoRefresh()
+    curPlayer.View_FamilyInfoRefresh() #//04 30 玩家家族名字职位等信息刷新#tagPlayerInFamilyInfoRefresh
     return
 
-## 进入家族触发事件
-#  @param curPlayer 当前玩家
-#  @param tick 当前时间
-#  @return None
-#  @remarks 函数详细说明.
 def __OnEnterFamily(curPlayer, tick):
-    EventShell.EventResponse_OnFamily(curPlayer)
-    __OnFamilyLVBuffChange(curPlayer, tick)
+    ## 进入家族触发事件
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    familyMgr.DelPlayerReqJoinFamilyIDAll(curPlayer.GetPlayerID())
+    Sync_RequestAddFamilyInfo(curPlayer)
+    #EventShell.EventResponse_OnFamily(curPlayer)
     __FamilyAffair_CheckReset(curPlayer)
     PlayerFamilyTech.Sync_PlayerFamilyTechLV(curPlayer)
-    DelAddFamilyRecord(curPlayer)
-    GameLogic_FamilyWar.DoCheckChampionFamilyTitle(curPlayer)
-    GameLogic_FamilyBoss.OnEnterFamily(curPlayer)
-    PlayerFamilyRedPacket.CreatCacheRedPacktet(curPlayer)
-    PlayerFamilyZhenfa.OnEnterFamily(curPlayer)
+    #GameLogic_FamilyWar.DoCheckChampionFamilyTitle(curPlayer)
+    #GameLogic_FamilyBoss.OnEnterFamily(curPlayer)
+    #PlayerFamilyRedPacket.CreatCacheRedPacktet(curPlayer)
+    #PlayerFamilyZhenfa.OnEnterFamily(curPlayer)
     return
 
-## 退出家族触发事件
-#  @param curPlayer 当前玩家
-#  @param tick 当前时间
-#  @return None
-#  @remarks 函数详细说明.
 def __OnLeaveFamily(curPlayer, tick):
+    ## 退出家族触发事件
     #---清空家族相关信息---
     curPlayer.SetPerExp(0)
     curPlayer.SetFamilyHornor(0)
@@ -186,615 +441,761 @@
     PlayerControl.SetLeaveFamilyTimeEx(curPlayer, int(time.time()))
     
     #触发玩家离开家族的任务
-    EventShell.EventResponse_OnLeaveFamily(curPlayer)
-    
-    #设置领奖限制
-    __SetForbidFamilyAward(curPlayer)
+    #EventShell.EventResponse_OnLeaveFamily(curPlayer)
     FBLogic.OnLeaveFamily(curPlayer, tick)
-    
-    __OnFamilyLVBuffChange(curPlayer, tick)
-    #清空仓库积分
-    PlayerControl.SetPlayerCurrency(curPlayer, ShareDefine.TYPE_Price_FamilyStoreScore, 0)
-    GameLogic_FamilyWar.DoCheckChampionFamilyTitle(curPlayer)
-    PlayerFamilyZhenfa.OnLeaveFamily(curPlayer)
     return
 
-## 家族等级加持buff变更处理(进、退家族时 及 家族等级变更时)
-def __OnFamilyLVBuffChange(curPlayer, tick):
+def GetFamilyMemberHasPow(member, powerID):
+    ## 仙盟成员是否有该权限
+    powerDict = IpyGameDataPY.GetFuncEvalCfg("FamilyPower", 1, {})
+    if str(powerID) not in powerDict:
+        return False
+    needMemberLV = powerDict[str(powerID)]
+    return member.GetFmLV() >= needMemberLV
+
+def Sync_FamilyInfo(curPlayer, infoPack=None):
+    ## // A5 20 玩家家族信息 #tagMCRoleFamilyInfo
+    familyID = curPlayer.GetFamilyID()
+    if not familyID:
+        return
+    if not infoPack:
+        infoPack = GetPack_FamilyInfo(familyID)
+    NetPackCommon.SendFakePack(curPlayer, infoPack)
     return
-    # 跨服服务器不处理,防止登录跨服服务器后无战盟导致战力下降
-    if GameWorld.IsCrossServer():
+
+def GetPack_FamilyInfo(familyID):
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    curFamily = familyMgr.FindFamily(familyID)
+    if not curFamily:
         return
     
-    familyLVBuffSkillTypeID = ReadChConfig.GetEvalChConfig("FamilyLVBuff")
-    if not familyLVBuffSkillTypeID:
-        return
-    
-    # 先删后加
-    playerSkillManager = curPlayer.GetSkillManager()
-    BuffSkill.DelBuffBySkillID(curPlayer, familyLVBuffSkillTypeID, tick)
-    playerSkillManager.DeleteSkillBySkillTypeID(familyLVBuffSkillTypeID)
-    familyLV = curPlayer.GetFamilyLV()
-    GameWorld.DebugLog("__OnFamilyLVBuffChange familyLV=%s,familyLVBuffSkillTypeID=%s" % (familyLV, familyLVBuffSkillTypeID))
-    if familyLV > 0:
-        curSkill = GameWorld.GetGameData().FindSkillByType(familyLVBuffSkillTypeID , familyLV)
-        if not curSkill:
-            return
-        skillID = curSkill.GetSkillID()
-        playerSkillManager.LVUPSkillByID(skillID)
-        SkillCommon.AddBuffBySkillType(curPlayer, familyLVBuffSkillTypeID, tick, familyLV)
-    
-    curControl = PlayerControl.PlayerControl(curPlayer)
-    #curControl.CalcPassiveBuffAttr()
-    curControl.RefreshPlayerAttrByBuff()
+    clientPack = ChPyNetSendPack.tagMCRoleFamilyInfo()
+    clientPack.FamilyID = familyID
+    clientPack.FamilyName = curFamily.GetName()
+    clientPack.FamilyLV = curFamily.GetLV()
+    clientPack.FamilyLVExp = curFamily.GetExp()
+    clientPack.JoinReview = curFamily.GetJoinReview()
+    clientPack.JoinLVMin = curFamily.GetJoinLVMin()
+    clientPack.ServerID = curFamily.GetServerID()
+    clientPack.EmblemID = curFamily.GetEmblemID()
+    clientPack.FightPower = curFamily.GetFightPower()
+    clientPack.FightPowerEx = curFamily.GetFightPowerEx()
+    clientPack.Broadcast = curFamily.GetBroadcast()
+    clientPack.BroadcastLen = len(clientPack.Broadcast)
+    clientPack.LeaderID = curFamily.GetLeaderID()
+    clientPack.MemberList = []
+    for index in xrange(curFamily.GetCount()):
+        member = curFamily.GetAt(index)
+        memInfo = ChPyNetSendPack.tagMCRoleFamilyMember()
+        memInfo.PlayerID = member.GetPlayerID()
+        memInfo.JoinTime = member.GetJoinTime()
+        memInfo.Name = member.GetPlayerName()
+        memInfo.NameLen = len(memInfo.Name)
+        memInfo.LV = member.GetLV()
+        memInfo.Job = member.GetJob()
+        memInfo.RealmLV = member.GetRealmLV()
+        memInfo.Face = member.GetFace()
+        memInfo.FacePic = member.GetFacePic()
+        memInfo.FightPower = member.GetFightPower()
+        memInfo.FightPowerEx = member.GetFightPowerEx()
+        memInfo.FmLV = member.GetFmLV()
+        memInfo.ServerID = member.GetServerID()
+        memInfo.ContribTotal = member.GetContribTotal()
+        memInfo.ContribWeek = member.GetContribWeek()
+        memInfo.OffTime = member.GetOffTime()
+        clientPack.MemberList.append(memInfo)
+    clientPack.MemberCount = len(clientPack.MemberList)
+    return clientPack
+
+def Broadcast_FamilyChange(familyID, changeType=FamilyChangeType_None, powerID=None, excludeIDList=None):
+    ## // A5 21 家族变更 #tagMCFamilyChange
+    # @param excludeIDList: 不广播的成员ID列表
+    clientPack = ChPyNetSendPack.tagMCFamilyChange()
+    clientPack.Type = changeType
+    Broadcast_FamilyPack(familyID, clientPack, powerID, excludeIDList)
     return
 
-def GetPlayerChangeFamilyPastHour(curPlayer):
-    ## 获取玩家家族变更已经经过了多长时间
-    curTime = int(time.time())
-    changeTime = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyIDChangeTime)
-    return (curTime - changeTime) / 3600
+def Broadcast_FamilyPack(familyID, clientPack, powerID=None, excludeIDList=None):
+    ## 广播家族成员封包
+    # @param powerID: 可指定只发给有该权限的成员
+    # @param excludeIDList: 不广播的成员ID列表
+    if not clientPack:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    curFamily = familyMgr.FindFamily(familyID)
+    if not curFamily:
+        return
+    playerManager = GameWorld.GetPlayerManager()
+    for index in xrange(curFamily.GetCount()):
+        member = curFamily.GetAt(index)
+        playerID = member.GetPlayerID()
+        if excludeIDList and playerID in excludeIDList:
+            continue
+        
+        curPlayer = playerManager.FindPlayerByID(playerID)
+        if not curPlayer:
+            continue
+        
+        if powerID != None and not GetFamilyMemberHasPow(member, powerID):
+            continue
+        
+        NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
 
+def NotifyAllFamilyMemberMsg(familyID, code, paramList=[], excludeIDList=None):
+    ## 通知所有家族成员信息
+    # @param excludeIDList: 不通知的成员ID列表
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    curFamily = familyMgr.FindFamily(familyID)
+    if not curFamily:
+        return
+    playerManager = GameWorld.GetPlayerManager()
+    for i in xrange(curFamily.GetCount()):
+        member = curFamily.GetAt(i)
+        playerID = member.GetPlayerID()
+        if excludeIDList and playerID in excludeIDList:
+            continue
+        curPlayer = playerManager.FindPlayerByID(playerID)
+        if not curPlayer:
+            continue
+        PlayerControl.NotifyCode(curPlayer, code, paramList)
+    return
+    
+#// A6 01 向玩家申请加入家族 #tagCMRequestJoinFamilyByPlayer
 #
-#//////////////////////////////////////////////////////////////
-#//08 04 申请家族战#tagMRequestFamilyWar
-#tagMRequestFamilyWar       *   GettagMRequestFamilyWar();
-#
-#class   IPY_MRequestFamilyWar
+#struct    tagCMRequestJoinFamilyByPlayer
 #{
-#public:
-#
-#    int      GetFamilyID();
-#
-#    char *      GetFamilyName();
-#
-#    int      GetVSFamilyID();
-#
-#    char *      GetVSFamilyName();
+#    tagHead        Head;
+#    DWORD        TagPlayerID;    //目标家族玩家ID
 #};
-## 08 04 申请家族战#
-#  @param index 玩家索引
-#  @param tick 当前时间
-#  @return None
-#  @remarks 函数详细说明.
-def GameServer_RequestFamilyWar(index, tick):
-#===============================================================================
-#    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-#    pack = IPY_GameWorld.IPY_MRequestFamilyWar()
-#    familyID = pack.GetFamilyID()
-#    familyName = pack.GetFamilyName()
-#    vsFamilyID = pack.GetVSFamilyID()
-#    vsFamilyName = pack.GetVSFamilyName()
-#    FBLogic.OnRequestFamilyWar(curPlayer, familyID, familyName, vsFamilyID, vsFamilyName, tick)
-#===============================================================================
-    GameWorld.ErrLog('GameServer_RequestFamilyWar, 此接口废弃')
-    return
-#---------------------------------------------------------------------
-##玩家金钱转换为家族金钱
-# @param playerMoney 玩家金钱
-# @return 家族金钱
-# @remarks 玩家金钱转换为家族金钱
-def GetPlayerMoney_Change_FamilyMoney(playerMoney):
-    return int(playerMoney * ShareDefine.Def_PlayerMoney_Change_FamilyMoney_Rate)
-#---------------------------------------------------------------------
-##玩家活跃度转换为家族活跃度
-# @param activeValue 玩家活跃度
-# @return 家族活跃度
-# @remarks 玩家活跃度转换为家族活跃度
-def GetPlayerActiveValue_Change_ActiveValue(activeValue):
-    return activeValue
-
-#---------------------------------------------------------------------
-##累加玩家的家族活跃度
-# @param curPlayer 玩家实例
-# @param addValue 添加的数值
-# @param sendPackGameServer 是否通知GameServer累加家族活跃度
-# @param reason 来源, 原因
-# @return None
-# @remarks 累加玩家的家族活跃度
-def AddPlayerFamilyActiveValue(curPlayer, addValue, sendPackGameServer = False, reason = 0, isSysMsg=False):
-    if addValue <= 0:
-        #GameWorld.ErrLog("AddPlayerFamilyActiveValue Err = %s"%(addValue))
+def OnRequestJoinFamilyByPlayer(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    tagPlayerID = clientData.TagPlayerID
+    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID)
+    if not tagPlayer:
+        GameWorld.DebugLog("对方不在线! tagPlayerID=%s" % tagPlayerID)
         return
-    
-    curActiveValue = curPlayer.GetFamilyActiveValue()
-    totalActiveValue = curPlayer.GetLastWeekFamilyActiveValue()
-
-    #---累加玩家家族活跃度---
-    if curActiveValue < ChConfig.Def_UpperLimit_DWord:
-        #累计活跃度
-        curPlayer.SetFamilyActiveValue(min(curActiveValue + addValue, ChConfig.Def_UpperLimit_DWord))
-        curPlayer.SetLastWeekFamilyActiveValue(min(totalActiveValue + addValue, ChConfig.Def_UpperLimit_DWord))
-        
-    #增加贡献度
-    PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_Family_Contribution, addValue, isSysHint=isSysMsg)
-    
-    #流向记录:
-    DataRecordPack.DR_AddPlayerFamilyActiveValue(curPlayer, addValue, curPlayer.GetFamilyActiveValue(), reason)
-
-    #---通知世界服务器累加家族活跃度---
-    #@warning: 刀剑笑项目, 玩家家族活跃度累加同时累加家族活跃度
-    #          如果这边没有加上去在外面要处理一次累加家族活跃度
-    if not sendPackGameServer:
-        return True
-      
-    #刀剑笑要求, 玩家活跃度累加的同时累加家族活跃度 1活跃=1资金
-    SendPack_GameServer_AddFamilyDetailEx(curPlayer, addValue, addValue, resion=reason)
-    return True
-
-#---------------------------------------------------------------------
-##通知世界服务器累加家族属性
-# @param curPlayer 玩家实例
-# @param addFamilyHornor 添加家族兽粮
-# @param addFamilyMoney 添加家族资金
-# @param addFamilyActiveValue 增加家族活跃度
-# @return 返回值无意义
-# @remarks 通知世界服务器累加家族属性
-def SendPack_GameServer_AddFamilyDetail(curPlayer, addFamilyHornor = 0, addFamilyMoney = 0, addFamilyActiveValue = 0, resion=0):
-#    //增加家族荣誉
-#    int      GetAddFamilyHornor();
-#    //增加家族资金
-#    int      GetAddFamilyMoney();
-#    //增加家族活跃度
-#    int      GetFamilyActiveValue();
-#    GameWorld.Log('addFamilyHornor = %s, addFamilyMoney = %s, addFamilyActiveValue = %s'%
-#                        (addFamilyHornor, addFamilyMoney, addFamilyActiveValue))
-
-    #curPlayer.GameServer_AddFamilyDetail(addFamilyHornor, addFamilyMoney, addFamilyActiveValue)
-    #改为PY包
-    if not curPlayer.GetFamilyID():
+    tagFamilyID = tagPlayer.GetFamilyID()
+    if tagFamilyID <= 0:
+        GameWorld.DebugLog("对方没有家族! tagPlayerID=%s" % tagPlayerID)
         return
-    sendPack = ChMapToGamePyPack.tagMGAddFamilyDetail()
-    sendPack.PlayerID = curPlayer.GetPlayerID()
-    sendPack.AddFamilyHornor = addFamilyHornor
-    sendPack.AddFamilyMoney = addFamilyMoney
-    sendPack.FamilyActiveValue = addFamilyActiveValue
-    sendPack.AddResion = resion
-    NetPackCommon.SendPyPackToGameServer(sendPack)
-    GameWorld.DebugLog("AddFamilyDetail addFamilyHornor=%s,addFamilyMoney=%s,addFamilyActiveValue=%s, resion=%s" 
-                       % (addFamilyHornor, addFamilyMoney, addFamilyActiveValue, resion), curPlayer.GetPlayerID())
-    return
-#---------------------------------------------------------------------
-##通知世界服务器累加家族属性
-# @param curPlayer 玩家实例
-# @param addFamilyActiveValue 增加玩家家族活跃度
-# @param addFamilyHornor 添加家族荣誉
-# @param addFamilyMoney 添加家族资金
-# @return 返回值无意义
-# @remarks 通知世界服务器累加家族属性
-def SendPack_GameServer_AddFamilyDetailEx(curPlayer, addPlayerActiveValue, addFamilyMoney = 0, addFamilyHornor = 0, resion=0):
-    
-    #刀剑笑增加玩家活跃度默认新增家族活跃度
-    addFamilyActiveValue = GetPlayerActiveValue_Change_ActiveValue(addPlayerActiveValue)
-        
-    SendPack_GameServer_AddFamilyDetail(curPlayer, addFamilyHornor, addFamilyMoney, addFamilyActiveValue, resion)
-    
-    return
-#---------------------------------------------------------------------
-##通知GameServer, 客户端开始创建家族
-# @param curPlayer 玩家实例
-# @return 返回值无意义
-# @remarks 通知GameServer, 客户端开始创建家族
-def SendPack_GameServer_InputFamilyName(curPlayer):
-    #通知GameServer设置查看状态, 防外挂
-    curPlayer.GameServer_SetPlayerViewFamilyState(ShareDefine.TViewFamilyType_CreateFamily)
-    #通知客户端打开输入家族名界面
-    curPlayer.Frm_InputFamilyName()
+    RequestJoinTagFamily(curPlayer, tagFamilyID)
     return
 
-##通知GameServer, 客户端开始浏览家族信息
-# @param curPlayer 玩家实例
-# @return 返回值无意义
-# @remarks 通知GameServer, 客户端开始浏览家族信息
-def SendPack_GameServer_ViewAllFamily(curPlayer):
-    #通知GameServer设置查看状态, 防外挂
-    curPlayer.GameServer_SetPlayerViewFamilyState(ShareDefine.TViewFamilyType_FamilyWar)
-    #通知GameServer给客户端家族信息
-    curPlayer.GameServer_ViewAllFamily()
-    return
-
-##通知GameServer, 清除客户端浏览家族状态
-# @param curPlayer 玩家实例
-# @return 返回值无意义
-# @remarks 通知GameServer, 通知GameServer, 清除客户端浏览家族状态
-def SendPack_GameServer_ClearViewFamilyState(curPlayer):
-    #MapServer告诉GameServer自己是否在创建家族状态
-    #因为家族封包是在GameServer处理的, 防止被骗
-    if curPlayer.GetViewFamilyState() in [ShareDefine.TViewFamilyType_None, 
-                                          ShareDefine.TViewFamilyType_CreateFamily]:
-        #TViewFamilyType_CreateFamily状态在GameServer DoCreateFamily结束后解除
-        return
-    
-    curPlayer.GameServer_SetPlayerViewFamilyState(ShareDefine.TViewFamilyType_None)
-    return
-
-def __SetForbidFamilyAward(curPlayer):
-    ''' 设置家族相关活动领奖限制 
-     如果退出时今日已开始过对应活动,则设置领奖限制
-    '''
-    
-    playerID = curPlayer.GetPlayerID()
-    openState = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_FamilyActivityDayState)
-    forbidState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ForbidFamilyAward)
-    GameWorld.DebugLog("退出家族处理家族活动奖励领取限制! openState=%s,forbidState=%s" % (openState, forbidState), playerID)
-    
-    updForbidState = forbidState
-    for activityType in ShareDefine.Def_FamActivityList:
-        
-        if not openState&pow(2, activityType):
-            GameWorld.DebugLog("    该家族活动今日未开启过! 不设置限制领奖! activityType=%s" % activityType, playerID)
-            continue
-        updForbidState = updForbidState|pow(2, activityType)
-        GameWorld.DebugLog("    家族活动领奖限制 activityType=%s,updForbidState=%s" % (activityType, updForbidState), playerID)
-       
-    if updForbidState != forbidState:
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_ForbidFamilyAward, updForbidState)
-        GameWorld.DebugLog("    更新家族活动领奖限制: forbidState=%s,updForbidState=%s" % (forbidState, updForbidState), playerID)
-        
-    return
-
-## 设置玩家是否可以参加家族活动
-#  @param curPlayer 玩家实例
-#  @param isForbid 是否限制
-#  @return 返回值无意义
-def SetForbidFamilyAction(curPlayer, isForbid):
-    #===============================================================================================
-    # if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ForbidFamilyAction) != isForbid:
-    #    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_ForbidFamilyAction, isForbid)
-    # 
-    #    # 通知玩家是否可以参加家族活动
-    #    SendClientForbidFamilyAction(curPlayer)
-    #===============================================================================================
-    return
-
-
-## 通知玩家是否可以参加家族活动
-#  @param curPlayer 玩家实例
-#  @return 返回值无意义
-def SendClientForbidFamilyAction(curPlayer):
-#    isForbid = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ForbidFamilyAction)
-#    
-#    outCardsCDTime = ChPyNetSendPack.tagPyFamilyActionForbid()
-#    outCardsCDTime.Clear()
-#    
-#    outCardsCDTime.IsForbid = isForbid
-#    NetPackCommon.SendFakePack(curPlayer, outCardsCDTime)
-    return
-
-    
-#===============================================================================
-# //A6 01  向玩家申请加入家族 #tagCGRequestJoinFamilyByPlayer
-# 
-# struct    tagCGRequestJoinFamilyByPlayer
-# 
-# {
+#// A6 02 申请加入家族#tagCMRequesJoinFamily
+#
+#struct    tagCMRequesJoinFamily
+#{
 #    tagHead        Head;
-#    DWORD        AddPlayerID;    //申请加入的玩家ID
-# };
-#===============================================================================
-## 通过申请加入家族
-#  @param index: 玩家索引
-#  @param clientData: 封包结构体
-#  @param tick: 时间戳
-#  @return: None
-def RequestAddFamilyByID(index, clientData, tick):
+#    BYTE        Type;        //申请类型,0-申请;1-撤销
+#    DWORD        TagFamilyID;    //目标家族ID,申请时为0代表一键申请家族任意家族
+#};
+def OnRequesJoinFamily(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
     
-    addPlayerID = clientData.AddPlayerID    #申请进入的家族ID
-    
-    addPlayer = GameWorld.GetPlayerManager().FindPlayerByID(addPlayerID)
-    #对方下线
-    if not addPlayer:
-        return
-    
-    addFamilyID = addPlayer.GetFamilyID()
-    #对方没有家族
-    if addFamilyID <= 0:
-        return
-    
-    #申请加入
-    AddFamily(curPlayer, addFamilyID)
-    
-    #通知当前申请加入的哪些家族
-    #Sync_RequestAddFamilyInfo(curPlayer) 
-    return
-    
-    
-#===============================================================================
-# //A6 02  申请加入家族#tagCGRequesJoinFamily
-# 
-# struct    tagCGRequesJoinFamily
-# 
-# {
-#    tagHead        Head;
-#    BYTE        Type;        //申请类型
-#    DWORD        AddFamilyID;    //申请加入的家族
-# };
-#===============================================================================
-## 申请加入家族
-#  @param index: 玩家索引
-#  @param clientData: 封包结构体
-#  @param tick: 时间戳
-#  @return: None
-def RequestAddFamily(index, clientData, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    
-    addFamilyID = clientData.AddFamilyID  # 申请进入的家族ID
+    tagFamilyID = clientData.TagFamilyID  # 申请进入的家族ID
     requestType = clientData.Type   # 申请类型(申请/撤销)
-
-    if requestType == 0:
-        #申请加入
-        AddFamily(curPlayer, addFamilyID)
-        
-    elif requestType == 1:
-        DelAddFamilyRecord()
-        
     
-    #通知当前申请加入的哪些家族
-    Sync_RequestAddFamilyInfo(curPlayer) 
+    # 申请加入
+    if requestType == 0:
+        if not tagFamilyID:
+            AutoJoinFamily(curPlayer)
+        else:
+            RequestJoinTagFamily(curPlayer, tagFamilyID)
+            
+    # 撤销申请
+    elif requestType == 1:
+        CancelJoinTagFamily(curPlayer, tagFamilyID)
+        
     return
 
-def DelAddFamilyRecord(curPlayer):
-    for index in range(0, ChConfig.Def_Player_RequestAddFamilyMaxCnt):
-            
-        #申请加入的家族ID
-        requestAddFamilyID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RequestAddFamilyID%index) 
-        if not requestAddFamilyID:
-            continue
-        #本版本因为客户端没有单个取消申请的操作,此处发一次包一次性全部取消
-#            if addFamilyID != requestAddFamilyID:
-#                continue
-        
-        #申请数量-1
-        requestAddFamilyCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RequestAddFamilyCnt)
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_RequestAddFamilyCnt, requestAddFamilyCnt - 1)
-        
-        #清除撤销申请的家族ID记录
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_RequestAddFamilyID%index, 0)
-        
-        #向GameServer发送请求删除该玩家的申请家族信息情况
-        sendMsg = str(requestAddFamilyID)
-        curPlayer.GameServer_QueryPlayerByID(ChConfig.queryType_DelFamilyAction, 
-                                     ShareDefine.Def_ActionType_FamilyAdd, '', sendMsg, len(sendMsg))
+def AutoJoinFamily(curPlayer):
+    if curPlayer.GetFamilyID():
+        return
+    playerID = curPlayer.GetPlayerID()
+    playerLV = curPlayer.GetLV()
+    GameWorld.DebugLog("玩家一键自动加入家族! playerLV=%s" % playerLV, playerID)
     
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    indexList = range(familyMgr.GetCount())
+    random.shuffle(indexList) #打乱顺序
+    for index in indexList:
+        family = familyMgr.GetAt(index)
+        if not family:
+            continue
+        familyID = family.GetID()
+        lvMin = family.GetJoinLVMin()
+        if lvMin and playerLV < lvMin:
+            GameWorld.DebugLog("    等级不足的不处理! familyID=%s,lvMin=%s" % (familyID, lvMin), playerID)
+            continue
+        if family.GetJoinReview():
+            GameWorld.DebugLog("    需要审核的不处理! familyID=%s" % familyID, playerID)
+            continue
+        MemberMax = GetFamilySetting(family.GetLV(), "MemberMax")
+        if family.GetCount() >= MemberMax:
+            GameWorld.DebugLog("    成员已满的不处理! familyID=%s" % familyID, playerID)
+            continue
+        
+        #直接加入
+        DoPlayerJionFamily(family, playerID, curPlayer)
+        return
+    
+    # 可再扩展自动请求,暂时不处理
+    GameWorld.DebugLog("没有可自动进入的仙盟!")
+    return
+
+def GetFamilySetting(familyLV, fieldName):
+    ## 获取仙盟等级表对应字段值
+    if not fieldName:
+        return 0
+    ipyData = IpyGameDataPY.GetIpyGameData("Family", familyLV)
+    if not ipyData:
+        return 0
+    attrName = "Get%s" % fieldName
+    if not hasattr(ipyData, attrName):
+        return 0
+    return getattr(ipyData, attrName)()
+
+def RequestJoinTagFamily(curPlayer, familyID):
+    ## 申请加入
+    playerID = curPlayer.GetPlayerID()
+    if curPlayer.GetFamilyID():
+        GameWorld.DebugLog('已经有仙盟不能再申请加入! familyID=%s' % curPlayer.GetFamilyID(), playerID)
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    reqFamilyIDList = familyMgr.GetPlayerReqJoinFamilyIDList(playerID)
+    if playerID in reqFamilyIDList:
+        GameWorld.DebugLog('已经在申请加入仙盟列表中! familyID=%s' % familyID, playerID)
+        return
+    
+    maxReqFamilyCnt = IpyGameDataPY.GetFuncCfg("FamilyReqJoin", 2)
+    if len(reqFamilyIDList) >= maxReqFamilyCnt:
+        GameWorld.DebugLog('已经达到最大申请加入仙盟数! %s, %s' % (len(reqFamilyIDList), reqFamilyIDList), playerID)
+        return
+    
+    tagFamily = familyMgr.FindFamily(familyID)
+    if not tagFamily:
+        return
+    
+    lvMin = tagFamily.GetJoinLVMin()
+    if curPlayer.GetLV() < lvMin:
+        GameWorld.DebugLog('等级未达到该仙盟加入最低等级限制! lv=%s < %s' % (curPlayer.GetLV(), lvMin), playerID)
+        return
+    
+    # 需要审核,满员后端不限制申请,由前端自行决定是否可申请
+    if tagFamily.GetJoinReview():
+        reqPlayerIDDict = tagFamily.GetReqJoinPlayerInfo()
+        if playerID not in reqPlayerIDDict:
+            maxReqPlayerCnt = IpyGameDataPY.GetFuncCfg("FamilyReqJoin", 1)
+            if len(reqPlayerIDDict) >= maxReqPlayerCnt:
+                GameWorld.DebugLog('目标仙盟申请加入数已满! %s, %s' % (len(reqFamilyIDList), reqFamilyIDList), playerID)
+                PlayerControl.NotifyCode(curPlayer, "jiazu_pan_141056")
+                return
+            
+        tagFamily.AddReqJoinPlayerID(playerID)
+        # 广播给有招人权限的
+        Broadcast_FamilyPack(familyID, GetPack_FamilyReqJoinInfo(familyID), FamilyPowerID_Call)
+        
+        #jiazu_pan_500807:申请入帮成功!请等待帮会管理人员审批! 
+        PlayerControl.NotifyCode(curPlayer, "jiazu_pan_500807")
+        Sync_RequestAddFamilyInfo(curPlayer)
+        return
+    
+    # 不需要审核,自动加入
+    memberMax = GetFamilySetting(tagFamily.GetLV(), "MemberMax")
+    if tagFamily.GetCount() >= memberMax:
+        GameWorld.DebugLog('目标仙盟成员已满! familyLV=%s,memberMax=%s' % (tagFamily.GetLV(), memberMax), playerID)
+        return
+    
+    DoPlayerJionFamily(tagFamily, playerID, curPlayer)
+    return
+
+def CancelJoinTagFamily(curPlayer, familyID):
+    # 撤销申请
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    playerID = curPlayer.GetPlayerID()
+    tagFamily = familyMgr.FindFamily(familyID)
+    if tagFamily:
+        tagFamily.DelReqJoinPlayerID(playerID)
+    familyMgr.DelPlayerReqJoinFamilyID(playerID, familyID)
+    Broadcast_FamilyPack(familyID, GetPack_FamilyReqJoinInfo(familyID), FamilyPowerID_Call)
     Sync_RequestAddFamilyInfo(curPlayer)
     return
 
-## 通知当前申请加入的哪些家族
-#  @param curPlayer:玩家实例
-#  @return:  None
-def Sync_RequestAddFamilyInfo(curPlayer):
-    requestAddFamilyCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RequestAddFamilyCnt)
+def Sync_RequestAddFamilyInfo(curPlayer, isForce=True):
+    ## 通知当前申请加入的哪些家族
+    playerID = curPlayer.GetPlayerID()
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    reqFamilyIDList = familyMgr.GetPlayerReqJoinFamilyIDList(playerID)
+    # 非强制通知时没有申请记录的可不通知,如登录
+    if not isForce and not reqFamilyIDList:
+        return
+    clientPack = ChPyNetSendPack.tagMCNotifyRequestJoinFamilyInfo()
+    clientPack.Clear()
+    clientPack.RequestJoinFamilyIDList = reqFamilyIDList
+    clientPack.RequestCount = len(clientPack.RequestJoinFamilyIDList)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+def GetPack_FamilyReqJoinInfo(familyID):
+    ## 获取 // A5 22 家族申请加入的玩家信息 #tagMCFamilyReqJoinInfo
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    curFamily = familyMgr.FindFamily(familyID)
+    if not curFamily:
+        return
+    reqPlayerIDDict = curFamily.GetReqJoinPlayerInfo()
     
-    packList = []
-    for index in range(0, ChConfig.Def_Player_RequestAddFamilyMaxCnt):
-        familyID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RequestAddFamilyID%index)
-        if familyID == 0:
+    playerManager = GameWorld.GetPlayerManager()
+    clientPack = ChPyNetSendPack.tagMCFamilyReqJoinInfo()
+    clientPack.ReqJoinList = []
+    for playerID, reqTime in reqPlayerIDDict.items():
+        curPlayer = playerManager.FindPlayerByID(playerID)
+        reqInfo = ChPyNetSendPack.tagMCFamilyReqJoinPlayer()
+        reqInfo.PlayerID = playerID
+        reqInfo.ReqTime = reqTime
+        if curPlayer:
+            reqInfo.IsOnLine = True
+        viewCache = DBDataMgr.GetPlayerViewCacheMgr().FindViewCache(playerID)
+        if viewCache:
+            reqInfo.Name = viewCache.GetPlayerName()
+            reqInfo.NameLen = len(reqInfo.Name)
+            reqInfo.LV = viewCache.GetLV()
+            reqInfo.Job = viewCache.GetJob()
+            reqInfo.RealmLV = viewCache.GetRealmLV()
+            reqInfo.Face = viewCache.GetFace()
+            reqInfo.FacePic = viewCache.GetFacePic()
+            reqInfo.FightPower = viewCache.GetFightPower()
+            reqInfo.FightPowerEx = viewCache.GetFightPowerEx()
+            reqInfo.ServerID = viewCache.GetServerID()
+        clientPack.ReqJoinList.append(reqInfo)
+        if len(clientPack.ReqJoinList) >= 100:
+            break
+    clientPack.ReqCnt = len(clientPack.ReqJoinList)
+    return clientPack
+
+#// A6 21 审核请求加入家族 #tagCMJoinFamilyReply
+#
+#struct tagCMJoinFamilyReply
+#{
+#    tagHead    Head;
+#    DWORD    TagPlayerID;    //被审核玩家ID 0则代表全部
+#    BYTE    IsOK;        //是否同意其加入
+#};
+def OnJoinFamilyReply(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    tagPlayerID = clientData.TagPlayerID
+    isOK = clientData.IsOK
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    if familyID <= 0:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    if not GetFamilyMemberHasPow(curMember, FamilyPowerID_Call):
+        #GameWorld.DebugLog("没有招人权限,无法审核人员入盟!", playerID)
+        PlayerControl.NotifyCode(curPlayer, "XW_JZ_InviteErr_Popedom")
+        return
+    
+    GameWorld.DebugLog("审核入盟申请: tagPlayerID=%s,familyID=%s,isOK=%s" % (tagPlayerID, familyID, isOK), playerID)
+    reqPlayerIDDict = family.GetReqJoinPlayerInfo()
+    tagPlayerIDList = reqPlayerIDDict.keys()
+    if tagPlayerID:
+        if tagPlayerID not in reqPlayerIDDict:
+            GameWorld.DebugLog("不存在该申请人员! tagPlayerID=%s" % tagPlayerID)
+            return
+        tagPlayerIDList = [tagPlayerID]
+        
+    if not tagPlayerIDList:
+        GameWorld.DebugLog("没有申请人员!")
+        return
+    
+    playerManager = GameWorld.GetPlayerManager()
+    # 拒绝
+    if not isOK:
+        for tagPlayerID in tagPlayerIDList:
+            family.DelReqJoinPlayerID(tagPlayerID)
+            tagPlayer = playerManager.FindPlayerByID(tagPlayerID)
+            if not tagPlayer:
+                continue
+            Sync_RequestAddFamilyInfo(tagPlayer)
+            #jiazu_pan_592934:{%S}拒绝了您的入帮申请
+            PlayerControl.NotifyCode(tagPlayer, "jiazu_pan_592934", [family.GetName()])
+        Broadcast_FamilyPack(familyID, GetPack_FamilyReqJoinInfo(familyID), FamilyPowerID_Call)
+        return
+    
+    # 处理同意
+    offlinePlayerCanJoin = IpyGameDataPY.GetFuncCfg("FamilyReqJoin", 3)
+    MemberMax = GetFamilySetting(family.GetLV(), "MemberMax")
+    joinOKPlayerIDList = []
+    for tagPlayerID in tagPlayerIDList:
+        if family.GetCount() >= MemberMax:
+            PlayerControl.NotifyCode(curPlayer, "jiazu_lhs_202580")
+            break
+        tagPlayer = playerManager.FindPlayerByID(tagPlayerID)
+        #申请目标不在线
+        if not tagPlayer:
+            if not offlinePlayerCanJoin:
+                GameWorld.DebugLog("离线玩家无法加入仙盟! tagPlayerID=%s" % tagPlayerID, playerID)
+                PlayerControl.NotifyCode(curPlayer, "jiazu_hwj35_367906")
+                continue
+            
+        if family.FindMember(tagPlayerID):
+            GameWorld.DebugLog("已经是本盟成员! tagPlayerID=%s" % tagPlayerID, playerID)
+            PlayerControl.NotifyCode(curPlayer, "XW_JZ_InviteErr_Repeat")
             continue
         
-        requestAddFamilyInfo = ChPyNetSendPack.tagRequestJoinFamily()
-        requestAddFamilyInfo.RequestFamilyID = familyID
-        packList.append(requestAddFamilyInfo)
-    
-    requestAddFamily = ChPyNetSendPack.tagMCNotifyRequestJoinFamilyInfo()
-    requestAddFamily.Clear()
-    requestAddFamily.RequestCount = len(packList)
-    requestAddFamily.RequestAddFamilyInfo = packList
-    
-    NetPackCommon.SendFakePack(curPlayer, requestAddFamily)
+        tagFamilyID = familyMgr.GetPlayerFamilyID(tagPlayerID)
+        if tagFamilyID:
+            GameWorld.DebugLog("已经加入其他仙盟! tagPlayerID=%s,tagFamilyID=%s" % (tagPlayerID, tagFamilyID), playerID)
+            PlayerControl.NotifyCode(curPlayer, "XW_JZ_InviteErr_Repeat")
+            continue
+        
+        DoPlayerJionFamily(family, tagPlayerID, tagPlayer, broadcastFamilyChange=False)
+        joinOKPlayerIDList.append(tagPlayerID)
+        
+    if not joinOKPlayerIDList:
+        return
+    Broadcast_FamilyChange(familyID, FamilyChangeType_MemJoin, excludeIDList=joinOKPlayerIDList)
+    Broadcast_FamilyPack(familyID, GetPack_FamilyReqJoinInfo(familyID), FamilyPowerID_Call)
     return
 
-
-## 申请加入帮会
-#@param curPlayer 家族实例
-#@param familyID 家族ID
-#@return 返回值无意义
-def AddFamily(curPlayer, familyID):
+#// A6 22 修改收人方式 #tagCMChangeFamilyJoin
+#
+#struct    tagCMChangeFamilyJoin
+#{
+#    tagHead         Head;
+#    BYTE        JoinReview;    //成员加入是否需要审核,默认0自动加入
+#    WORD        JoinLVMin;    //限制最低可加入的玩家等级
+#};
+def OnChangeFamilyJoin(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    joinReview = clientData.JoinReview
+    joinLVMin = clientData.JoinLVMin
     
-    requestAddFamilyCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RequestAddFamilyCnt)
-    if requestAddFamilyCnt >= ChConfig.Def_Player_RequestAddFamilyMaxCnt:
-        # jiazu_pan_21675 改为 jiazu_lhs_31379 最多同时向%s个帮会发出申请
-        PlayerControl.NotifyCode(curPlayer, "jiazu_lhs_31379", [ChConfig.Def_Player_RequestAddFamilyMaxCnt])
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    if familyID <= 0:
         return
-        
-    #是否已经申请了
-    for index in range(0, ChConfig.Def_Player_RequestAddFamilyMaxCnt):
-        if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RequestAddFamilyID%index) == familyID:
-            GameWorld.DebugLog('已经在申请列表中')
-            #已经在申请列表中
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    if not GetFamilyMemberHasPow(curMember, FamilyPowerID_Call):
+        GameWorld.DebugLog("没有招人权限", playerID)
+        return
+    GameWorld.DebugLog("修改招人设置: familyID=%s,joinReview=%s,joinLVMin=%s" % (familyID, joinReview, joinLVMin), playerID)
+    family.SetJoinReview(joinReview)
+    family.SetJoinLVMin(joinLVMin)
+    Sync_FamilyInfo(curPlayer)
+    Broadcast_FamilyChange(familyID, FamilyChangeType_JoinSet, FamilyPowerID_Call, excludeIDList=[playerID])
+    return
+
+#// A6 23 修改家族公告 #tagCMChangeFamilyBroadcast
+#
+#struct    tagCMChangeFamilyBroadcast
+#{
+#    tagHead        Head;
+#    char        Msg[200];
+#};
+def OnChangeFamilyBroadcast(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    broadcast = clientData.Msg
+    
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    if familyID <= 0:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    if not GetFamilyMemberHasPow(curMember, FamilyPowerID_Broadcast):
+        GameWorld.DebugLog("没有修改公告权限", playerID)
+        return
+    family.SetBroadcast(broadcast)
+    GameWorld.DebugLog('更改仙盟公告: Family=%s,公告=%s' % (GameWorld.CodeToGbk(family.GetName()), GameWorld.CodeToGbk(broadcast)), playerID)
+    Sync_FamilyInfo(curPlayer)
+    Broadcast_FamilyChange(familyID, FamilyChangeType_Broadcast, excludeIDList=[playerID])
+    return
+
+#// A6 24 修改家族徽章 #tagCMChangeFamilyEmblem
+#
+#struct    tagCMChangeFamilyEmblem
+#{
+#    tagHead        Head;
+#    BYTE        EmblemID;    // 更换的徽章ID
+#};
+def OnChangeFamilyEmblem(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    changeEmblemID = clientData.EmblemID
+    PlayerFamilyEmblem.OnChangeFamilyEmblem(curPlayer, changeEmblemID)
+    return
+
+#// A6 25 修改家族成员职位 #tagCMChangeFamilyMemLV
+#
+#struct    tagCMChangeFamilyMemLV
+#{
+#    tagHead        Head;
+#    DWORD        PlayerID; // 目标成员ID
+#    BYTE        FmLV;  // 变更为xx职位
+#};
+def OnChangeFamilyMemLV(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    OnChangeFamilyMemberLV(curPlayer, clientData.PlayerID, clientData.FmLV)
+    return
+
+def OnChangeFamilyMemberLV(curPlayer, tagID, changeFmlv, isGMOP=False):
+    '''变更成员职位
+    @param curPlayer: 操作的玩家
+    @param tagID: 目标成员ID
+    @param changeFmlv: 修改为xx职位
+    @param isGMOP: 是否是GM后台发起的,如果是GM发起的,一般curPlayer传入的为目标成员ID实例
+    '''
+    if not curPlayer:
+        return
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    if familyID <= 0:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    if changeFmlv < 0 or changeFmlv > IPY_PlayerDefine.fmlLeader:
+        GameWorld.DebugLog("不存在该职位等级! changeFmlv=%s" % changeFmlv)
+        return
+    # 非GM操作的需检查权限
+    if not isGMOP:
+        if not GetFamilyMemberHasPow(curMember, FamilyPowerID_ChangeFmlv):
             return
-
-    #请求记录申请进入家族信息
-    sendMsg = cPickle.dumps([familyID, PlayerControl.GetFightPower(curPlayer)], 2)
-    curPlayer.GameServer_QueryPlayerByID(ChConfig.queryType_AddFamilyAction, 
-                                        ShareDefine.Def_ActionType_FamilyAdd, '', sendMsg, len(sendMsg))
-    
-    #等GameServer反馈结果再处理
-    return
-    
-    #记录个人申请加入的家族ID
-    for index in range(0, ChConfig.Def_Player_RequestAddFamilyMaxCnt):
-        if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RequestAddFamilyID%index) == 0:
-            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_RequestAddFamilyID%index, familyID)
-            break
+        if playerID == tagID:
+            GameWorld.DebugLog("不能任免自己的家族职位", playerID)
+            return
         
-    #记录个人申请加入家族的个数
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_RequestAddFamilyCnt, requestAddFamilyCnt + 1)
+    tagMember = family.FindMember(tagID)
+    if tagMember == None:
+        GameWorld.DebugLog("更改家族成员职位时目标成员不存在! tagID=%s" % tagID, playerID)
+        return 
     
-    return
-
-
-
-
-    
-## 战盟玩家OnDay
-#  @param curPlayer
-#  @return None
-def FamilyPlayerOnDay(curPlayer):
-    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Family):
-        return
-    #每日福利奖励
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyDayAward, 0)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyMoneyDonateCount, 0)
-    Sync_FamilyDayRewardState(curPlayer)
-    __FamilyAffair_Refresh(curPlayer, True)
-    
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeCut, 0)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy, 0)
-    Sync_ZhenbaogeInfo(curPlayer)
-    return
-
-
-## 战盟玩家OnLogin
-#  @param curPlayer
-#  @return None
-def FamilyPlayerOnLogin(curPlayer, tick):
-    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Family):
-        return
-
-    PlayerFamilyTech.Sync_PlayerFamilyTechLV(curPlayer)
-    SyncFamilyActivityInfo(curPlayer)
-    Sync_FamilyDayRewardState(curPlayer)
-    __FamilyAffair_CheckReset(curPlayer)
-    PlayerFamilyZhenfa.OnPlayerLogin(curPlayer)
-    Sync_ZhenbaogeInfo(curPlayer)
-    return
-
-def FamilyPlayerOnLoginCross(curPlayer):
-    ## 登录跨服服务器
-    crossFamilyMemberLV = curPlayer.GetReceivedSalary()
-    if crossFamilyMemberLV:
-        curPlayer.SetFamilyMemberLV(crossFamilyMemberLV)
-        GameWorld.DebugLog("跨服登录设置仙盟职位等级: %s" % crossFamilyMemberLV, curPlayer.GetPlayerID())
+    if not isGMOP:
+        if curMember.GetFmLV() != IPY_PlayerDefine.fmlLeader:
+            if changeFmlv >= curMember.GetFmLV():
+                GameWorld.DebugLog("修改的职位不能比自己高或平级! changeFmlv=%s" % changeFmlv, playerID)
+                return
+            if tagMember.GetFmLV() >= curMember.GetFmLV():
+                GameWorld.DebugLog("修改的目标成员职位不能比自己高或平级! tagFmlv=%s" % tagMember.GetFmLV(), playerID)
+                return
+            
+    if changeFmlv == IPY_PlayerDefine.fmlLeader:
+        changeType = FamilyChangeType_LeaderChange
+        ChangeFamilyLeader(family, tagMember)
         
-    return
+    else:
+        fmLVMemCnt = 0
+        for index in range(family.GetCount()):
+            familyMember = family.GetAt(index)
+            if familyMember.GetFmLV() != changeFmlv:
+                continue
+            fmLVMemCnt += 1
+            
+        maxCnt = GetFamilySetting(family.GetLV(), Def_FmlSetAttrName.get(changeFmlv, ""))
+        if fmLVMemCnt >= maxCnt:
+            # jiazu_hwj35_272921 改为 jiazu_chenxin_31379
+            PlayerControl.NotifyCode(curPlayer, "jiazu_chenxin_31379")
+            GameWorld.DebugLog("目前该职位的人数已经达到上限! changeFmlv=%s,fmLVMemCnt=%s >= %s" % (changeFmlv, fmLVMemCnt, maxCnt))
+            return
+        changeType = FamilyChangeType_MemFmlvChange
+        ChangeFamilyMemberLv(tagMember, changeFmlv)
+        
+    if isGMOP:
+        family.SetBroadcast("")
+    Sync_FamilyInfo(curPlayer)
+    Broadcast_FamilyChange(familyID, changeType, excludeIDList=[playerID, tagID])
+    return True
 
-
-
-
-## 通知GameServer增加家族相关信息值
-# @param curPlayer 玩家实例
-# @param infoDict 信息字典
-# @return 
-def Send_GameServer_PyAddFamilyInfoValue(curPlayer, infoDict={}):
-    if not isinstance(infoDict, dict) or not infoDict:
-        GameWorld.DebugLog("Send_GameServer_PyAddFamilyInfoValue infoDict=%s err!" % str(infoDict))
+def ChangeFamilyLeader(family, newLeaderMem):
+    ## 变更家族族长
+    
+    familyID = family.GetID()
+    befLeaderID = family.GetLeaderID()
+    newLeaderID = newLeaderMem.GetPlayerID()
+    if befLeaderID == newLeaderID:
         return
     
-    sendMsg = '%s'%(infoDict)
-    #GameWorld.DebugLog("Send_GameServer_PyAddFamilyInfoValue sendMsg=%s" % sendMsg)
-    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(curPlayer.GetID(), 0, 0, 'PyAddFamilyInfoValue', sendMsg, len(sendMsg))
+    befLeaderMem = family.FindMember(befLeaderID)
+    if befLeaderMem:
+        #把原族长降为普通成员
+        ChangeFamilyMemberLv(befLeaderMem, IPY_PlayerDefine.fmlMember)
+        
+    family.SetLeaderID(newLeaderID)
+    ChangeFamilyMemberLv(newLeaderMem, IPY_PlayerDefine.fmlLeader)
+    GameWorld.Log("家族设置新族长! familyID=%s,newLeaderID=%s,befLeaderID=%s" % (familyID, newLeaderID, befLeaderID))
     return
 
-#---------------------------------------------------------------------
-
-
-
-## 添加家族事件记录
-def AddFamilyEventNote(curPlayer, eventType, valueList):
-    ##同步记录到GameServer, eventType默认为value1
-    sendMsg = cPickle.dumps([eventType] + valueList, 2)
-    curPlayer.GameServer_QueryPlayerByID(ChConfig.queryType_AddFamilyAction, ShareDefine.Def_ActionType_FamilyEvent, '', sendMsg, len(sendMsg))
-    GameWorld.DebugLog("AddFamilyEventNote sendMsg=%s" % sendMsg)
-    return
-
-
-## --------------------------------- 仙盟活跃 -----------------------------------
-def OnWeekEx(curPlayer):
-    #重置
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyActivityAwardRecord, 0)
-    for actionid in ShareDefine.FamilyActiveIDList:
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyActivityFinishCnt%actionid, 0)
+def ChangeFamilyMemberLv(tagMember, changeFamilyLV):
+    ## 修改成员职位,只做修改逻辑,不做验证,验证由各调用入口自行验证
+    familyID = tagMember.GetFamilyID()
+    tagID = tagMember.GetPlayerID()
+    memName = tagMember.GetPlayerName()
+    befFamilyLV = tagMember.GetFmLV()
     
-    SyncFamilyActivityInfo(curPlayer)
+    tagMember.SetFmLV(changeFamilyLV)
+    
+    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagID)
+    if tagPlayer:
+        MapServer_FamilyRefresh(tagPlayer, familyID)
+        Sync_FamilyInfo(tagPlayer)
+        if GetFamilyMemberHasPow(tagMember, FamilyPowerID_Call):
+            NetPackCommon.SendFakePack(tagPlayer, GetPack_FamilyReqJoinInfo(familyID))
+        
+    # 记录家族事件记录信息
+    tick = GameWorld.GetGameWorld().GetTick()
+    AddFamilyActionNote(memName, familyID, ShareDefine.Def_ActionType_FamilyEvent, 
+                        [ShareDefine.Def_FamilyActionEvent_MemberChange, ShareDefine.Def_FamilyMemberChange_FMLV, changeFamilyLV, befFamilyLV], tick)
+    
+    #xx被任命为xx
+    NotifyAllFamilyMemberMsg(familyID, "XW_JZ_AppointFamily", [memName, changeFamilyLV])
+    #GetFamilyMgr().SetSyncCrossFamilyUpd(familyMember.GetFamilyID(), familyMember.GetPlayerID(), syncNow=True) # 成员职位变更
     return
 
-## 领取仙盟活跃度奖励
-#  @param curPlayer
-#  @param awardIndex
-#  @return None
-def GetFamilyActivityAward(curPlayer, awardIndex):
+#// A6 26 请求家族成员列表 #tagCMGetFamilyInfo
+#
+#struct    tagCMGetFamilyInfo
+#{
+#    tagHead        Head;
+#};
+def OnGetFamilyInfo(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    Sync_FamilyInfo(curPlayer)
     return
-    familyActiveList = IpyGameDataPY.GetFuncEvalCfg('FamilyActive')
-    familyActiveAwardList = IpyGameDataPY.GetFuncEvalCfg('FamilyActive', 2)
-    if awardIndex < 0 or awardIndex >= len(familyActiveList):
-        GameWorld.ErrLog("活跃度奖励索引不合法,index=%s,Len=%s" % (awardIndex, len(familyActiveList)))
+
+#// A6 03 离开家族 #tagCMLeaveFamily
+#
+#struct    tagCMLeaveFamily
+#{
+#    tagHead        Head;
+#};
+def OnLeaveFamily(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    if familyID <= 0:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
         return
     
-    # 判断是否已领取
-    getAwardRecord = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyActivityAwardRecord, 0)
-    if getAwardRecord & pow(2, awardIndex):
-        GameWorld.Log("已经领取过该活跃度奖励,index=%s" % (awardIndex))
+    familyLV = curMember.GetFmLV()  # 职位
+    if family.GetCount() > 1 and familyLV == IPY_PlayerDefine.fmlLeader:
+        GameWorld.DebugLog("族长在成员人数大于1时不能直接退出家族", playerID)
         return
     
+    # 功能限制退出仙盟
+    # ...
     
-    needActivity = familyActiveList[awardIndex]
-    totalActivity = __GetTotalFamilyActivity(curPlayer)#总活跃度
+    # 进出时间限制暂不做,等正式功能再补
+    #PlayerControl.SetLeaveFamilyTime(curPlayer, updTime)
     
-    # 判断活跃度
-    if totalActivity < needActivity:
-        GameWorld.Log("领奖活跃度不足,index=%s,needActivity=%s,totalActivity=%s" 
-                      % (awardIndex, needActivity, totalActivity))
+    # 执行退出
+    GameWorld.DebugLog("离开家族! familyID=%s" % familyID, playerID)
+    
+    family.DeleteMember(playerID)
+    AddFamilyActionNote(curPlayer.GetName(), familyID, ShareDefine.Def_ActionType_FamilyEvent, 
+                        [ShareDefine.Def_FamilyActionEvent_MemberChange, ShareDefine.Def_FamilyMemberChange_Leave], tick)
+    
+    #XW_JZ_LeaveFamily   <n color="0,190,255">{%S1%}</n><n color="255,255,0">退出了家族!</n>  25  -   -
+    NotifyAllFamilyMemberMsg(familyID, "XW_JZ_LeaveFamily", [curPlayer.GetName()])
+    
+    MapServer_FamilyRefresh(curPlayer, 0)
+    
+    if family.GetCount() == 0:
+        #玩家离开后, 家族没有人了 , 删除这个家族
+        familyMgr.DelFamily(familyID)
         return
-   
-    activityValue = familyActiveAwardList[awardIndex]
-    PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_FamilyActivity, activityValue)
-    
-    # 更新已领取成功标记
-    updAwardRecord = getAwardRecord | (1 << awardIndex)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyActivityAwardRecord, updAwardRecord)
-    
-    SyncFamilyActivityInfo(curPlayer)
-    GameWorld.DebugLog("领取仙盟活跃度奖励OK! index=%s,needActivity=%s,totalActivity=%s,awardRecord=%s" 
-                       % (awardIndex, needActivity, totalActivity, updAwardRecord))
+    Broadcast_FamilyChange(familyID, FamilyChangeType_MemLeave)
     return
 
-def AddFamilyActivity(curPlayer, actionid, addCnt=1):
-    return
-    ipyData = IpyGameDataPY.GetIpyGameData('FamilyActivity', actionid)
-    if not ipyData:
+#// A6 05 删除家族成员 #tagCMDeleteFamilyMember
+#
+#struct    tagCMDeleteFamilyMember
+#{
+#    tagHead        Head;
+#    DWORD        MemberID;
+#};
+def OnDeleteFamilyMember(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    tagMemberID = clientData.MemberID
+    
+    playerID = curPlayer.GetPlayerID()
+    if playerID == tagMemberID:
         return
-    if not GameFuncComm.GetFuncCanUse(curPlayer, ipyData.GetUnLockFuncID()):
+    
+    familyID = curPlayer.GetFamilyID()
+    if familyID <= 0:
         return
-    finishCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyActivityFinishCnt%actionid, 0)
-    maxCnt = ipyData.GetTotalActivityTime()
-    if finishCnt >= maxCnt:
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
         return
-    newCnt = min(maxCnt, finishCnt+addCnt)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyActivityFinishCnt%actionid, newCnt)
-    SyncFamilyActivityInfo(curPlayer, actionid)
-    GameWorld.DebugLog('    仙盟活跃完成次数 actionid=%s,newCnt=%s'%(actionid, newCnt))
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    
+    if not GetFamilyMemberHasPow(curMember, FamilyPowerID_Kick):
+        GameWorld.DebugLog("没有踢人权限!")
+        return
+    
+    tagMember = family.FindMember(tagMemberID)
+    if not tagMember:
+        return
+    
+    curFmlv = curMember.GetFmLV()
+    tagFmlv = tagMember.GetFmLV()
+    if tagFmlv >= curFmlv:
+        GameWorld.DebugLog("只能踢比自己职位低的成员! tagMemberID=%s,tagFmlv(%s) >= curFmlv(%s)" % (tagMemberID, tagFmlv, curFmlv), playerID)
+        return
+    
+    # 功能限制踢人
+    # ...
+    
+    tagPlayerName = tagMember.GetPlayerName()  # 被踢玩家名
+    tagPlayerID = tagMember.GetPlayerID()  # 被踢玩家ID
+    
+    family.DeleteMember(tagPlayerID)
+    
+    AddFamilyActionNote(tagPlayerName, familyID, ShareDefine.Def_ActionType_FamilyEvent, 
+                        [ShareDefine.Def_FamilyActionEvent_MemberChange, ShareDefine.Def_FamilyMemberChange_KickOut], tick)
+    
+    #XW_JZ_LeaveFamily   <n color="0,190,255">{%S1%}</n><n color="255,255,0">退出了家族!</n>  25  -   -
+    NotifyAllFamilyMemberMsg(familyID, "XW_JZ_LeaveFamily", [tagPlayerName])
+    
+    #删除玩家
+    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagMemberID)
+    if tagPlayer:
+        MapServer_FamilyRefresh(tagPlayer, 0)
+        
+    Broadcast_FamilyChange(familyID, FamilyChangeType_MemLeave)
     return
 
-def __GetTotalFamilyActivity(curPlayer):
-    ##获取总仙盟活跃度
-    totalPoint = 0
-    ipyDataMgr = IpyGameDataPY.IPY_Data()
-    for i in xrange(ipyDataMgr.GetFamilyActivityCount()):
-        ipyData = ipyDataMgr.GetFamilyActivityByIndex(i)
-        actionid = ipyData.GetID()
-        curTimes = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyActivityFinishCnt%actionid, 0)
-        totalPoint += curTimes/ipyData.GetSingleTimes()*ipyData.GetSingleActiveValue()
-    return totalPoint
-
-def SyncFamilyActivityInfo(curPlayer, syncActionid=-1):
-    return
-    #通知活跃领取情况
-    syncActionIDList = ShareDefine.FamilyActiveIDList if syncActionid==-1 else [syncActionid]
-    sendPack = ChPyNetSendPack.tagMCFamilyActivityInfo()
-    sendPack.Clear()
-    sendPack.AwardRecord = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyActivityAwardRecord, 0)
-    sendPack.InfoList = []
-    for actionid in syncActionIDList:
-        activityInfo = ChPyNetSendPack.tagMCFamilyActionCnt()
-        activityInfo.ActionID = actionid
-        activityInfo.FinishCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyActivityFinishCnt%actionid, 0)
-        sendPack.InfoList.append(activityInfo)
-    sendPack.Count = len(sendPack.InfoList)
-    NetPackCommon.SendFakePack(curPlayer, sendPack)
-    return
-
-#=================仙盟改名======================
 #// A6 11 家族改名 #tagCMRenameFamily
 #
 #struct tagCMRenameFamily
@@ -805,189 +1206,167 @@
 #    BYTE        ItemIndex;  //改名物品在背包中的位置
 #};
 def UpdateFamilyName(index, clientData, tick):
-    
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    if GameWorld.IsCrossServer():
-        #itemuse_lzxkoy_0:不可在跨服环境下使用改名功能。
-        PlayerControl.NotifyCode(curPlayer, "itemuse_lzxkoy_0")
-        return
-    
-    if not curPlayer.GetFamilyID():
-        return
-    
-    if curPlayer.GetDictByKey(ChConfig.Def_Player_Dict_UpdateFamilyName):
-        #正在改名中
-        GameWorld.Log("仙盟已经在改名中...", curPlayer.GetID())
-        return
-    
-    #新名字
     newName = clientData.NewName
     itemIndex = clientData.ItemIndex
-     
+    
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    if familyID <= 0:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    
+    if curMember.GetFmLV() != IPY_PlayerDefine.fmlLeader:
+        GameWorld.DebugLog("非盟主不可改名!", playerID)
+        return
+    
+    familyName = CheckInputFamilyName(curPlayer, newName)
+    if not familyName:
+        return
+    
     itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
     curItem = itemPack.GetAt(itemIndex)
-    if not ItemCommon.CheckItemCanUse(curItem):
+    if not ItemCommon.CheckItemCanUse(curItem) or curItem.GetType() != ChConfig.Def_ItemType_ChangeFamilyName:
+        GameWorld.DebugLog("没有仙盟改名道具! itemIndex=%s" % itemIndex, playerID)
         return
-    if curItem.GetType() != ChConfig.Def_ItemType_ChangeFamilyName:
-        return
-
-    #改名物品在背包的位置
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_UpdateFamilyNameItemIndex, itemIndex)
+    ItemCommon.DelItem(curPlayer, curItem, 1, True, 'UpdateFamilyName')
     
-    #设置正在改名中...
-    curPlayer.SetDict(ChConfig.Def_Player_Dict_UpdateFamilyName, 1)
+    #oldName = curFamily.GetName()
+    family.SetName(familyName)
     
-    #通知GameServer正式改名
-    newNameMsg = str(newName)
-    GameWorld.Log("UpdateFamilyName 通知GameServer正式改名为:%s"%newNameMsg, curPlayer.GetID())
-    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(curPlayer.GetID(), 0, 0, 'UpdateFamilyName', newNameMsg, len(newNameMsg))
+    infoPack = GetPack_FamilyInfo(familyID)
+    playerManager = GameWorld.GetPlayerManager()
+    for index in xrange(family.GetCount()):
+        member = family.GetAt(index)
+        memID = member.GetPlayerID()
+        player = playerManager.FindPlayerByID(memID)
+        if not player:
+            continue
+        Sync_FamilyInfo(player, infoPack)
+        player.SetFamilyName(familyName)
+        player.Notify_FamilyNameRefresh() #//04 36    周围玩家家族名刷新#tagPlayerFamilyNameRefresh
+        
+    #PlayerCompensation.SendMailByKey('FamilyNameChange', memberIDList, [], [oldName, familyName])    
+    #PlayerControl.WorldNotify(0, 'Family_ChangeName', [oldName, familyName])
     return
 
-
-## 扣除改名消耗
-#  @param curPlayer: 玩家实例
-#  @return: None
-def PayUpdateFamilyNameCost(curPlayer): 
-    itemIndex = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_UpdateFamilyNameItemIndex)
-    #扣除物品
-    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
-    curItem = itemPack.GetAt(itemIndex)
-    if curItem:
-        ItemCommon.DelItem(curPlayer, curItem, 1, True, 'UpdateFamilyName')
+#// A6 20 搜索家族列表 #tagCMViewFamilyPage
+#
+#struct    tagCMViewFamilyPage
+#{
+#    tagHead        Head;
+#    BYTE        MsgLen;        //模糊搜索家族,如果输入为空,则为不限制该条件
+#    char        Msg[MsgLen];    //size = MsgLen
+#    BYTE        PageIndex;    //查询第X页索引,0~n
+#    BYTE        ShowCount;    //每页数量,前端可自行指定,最大50
+#};
+def OnViewFamilyPage(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    msg = clientData.Msg
+    pageIndex = clientData.PageIndex
+    showCount = min(clientData.ShowCount, 50)
     
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_UpdateFamilyNameItemIndex, 0)
-    return
-
-def GetFamilyDayAward(curPlayer):
-    ##领取仙盟每日奖励 2小时脱机挂时间
-    if not curPlayer.GetFamilyID():
-        return
-    hasGot = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyDayAward)
-    if hasGot:
-        GameWorld.DebugLog('领取仙盟每日奖励 当日已领取!')
-        return
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyDayAward, 1)
-    #addTime = IpyGameDataPY.GetFuncCfg('FamilyDayAward')
-    #PlayerTJG.AddTJGTime(curPlayer, addTime)
-    #通知
-    Sync_FamilyDayRewardState(curPlayer)
-    #PlayerControl.NotifyCode(curPlayer, 'OfflinePlugSuccess', [addTime/60/60])
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    familyCount = familyMgr.GetCount()
+    totalPage = 0
     
-    return
-
-def Sync_FamilyDayRewardState(curPlayer):
-    clientPack = ChPyNetSendPack.tagMCFamilyDayAward()
-    clientPack.GetState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyDayAward)
-    clientPack.MoneyDonateCount = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyMoneyDonateCount)
+    if not msg:
+        startIndex = pageIndex * showCount
+        endIndex = startIndex + showCount - 1
+        if familyCount > 0:
+            totalPage = GameWorld.GetIntUpper(familyCount, showCount)
+            
+    # 有指定搜索内容的后端固定返回单页   
+    else:
+        pageIndex = 0
+        showCount = 20
+        totalPage = 1
+        startIndex = 0
+        endIndex = familyCount - 1
+        
+    clientPack = ChPyNetSendPack.tagMCFamilyViewList()
+    clientPack.Msg = msg
+    clientPack.MsgLen = len(clientPack.Msg)
+    clientPack.PageIndex = pageIndex
+    clientPack.ShowCount = showCount
+    clientPack.TotalPage = totalPage
+    clientPack.FamilyList = []
+    for index in range(startIndex, endIndex + 1):
+        if index >= familyCount:
+            break
+        family = familyMgr.GetAt(index)
+        if not family:
+            continue
+        if msg and msg not in family.GetName():
+            continue
+        familyView = ChPyNetSendPack.tagMCFamilyView()
+        familyView.FamilyID = family.GetID()
+        familyView.FamilyName = family.GetName()
+        familyView.FamilyNameLen = len(familyView.FamilyName)
+        familyView.LeaderID = family.GetLeaderID()
+        leaderMember = family.FindMember(familyView.LeaderID)
+        familyView.LeaderName = leaderMember.GetPlayerName() if leaderMember else ""
+        familyView.LeaderNameLen = len(familyView.LeaderName)
+        familyView.FamilyLV = family.GetLV()
+        familyView.JoinReview = family.GetJoinReview()
+        familyView.JoinLVMin = family.GetJoinLVMin()
+        familyView.ServerID = family.GetServerID()
+        familyView.EmblemID = family.GetEmblemID()
+        familyView.FightPower = family.GetFightPower()
+        familyView.FightPowerEx = family.GetFightPowerEx()
+        familyView.MemberCount = family.GetCount()
+        clientPack.FamilyList.append(familyView)
+        clientPack.FamilyCount = len(clientPack.FamilyList)
+        if clientPack.FamilyCount >= showCount:
+            break
     NetPackCommon.SendFakePack(curPlayer, clientPack)
     return
 
-
-#// A6 06 家族兑换活跃令 #tagCMFamilyActivityExchange
-#
-#struct    tagCMFamilyActivityExchange
-#{
-#    tagHead        Head;
-#    BYTE        Count;        //材料所在背包索引的数量
-#    WORD        IndexList[Count];    //材料所在背包索引列表
-#    DWORD        ItemIDList[Count];    //材料所在背包物品ID列表
-#};
-## 家族兑换活跃令 
-#  @param playerIndex 玩家索引  
-#  @param clientData 客户端封包  
-#  @param tick 时间
-#  @return None
-def OnFamilyActivityExchange(index, clientData, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    if not clientData.Count:
-        return
-    playerID = curPlayer.GetID()
-    eatIndexList = clientData.IndexList
-    eatItemIDList = clientData.ItemIDList
-    givePoint = 0 #分解得到活跃令
-    familyDonateDict = IpyGameDataPY.GetFuncEvalCfg('FamilyDonate', 1, {})
-    familyDonateSpecialDict = IpyGameDataPY.GetFuncEvalCfg('FamilyDonate', 2, {})
-    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
-    for i, index in enumerate(eatIndexList):
-        eatItem = itemPack.GetAt(index)
-        if not ItemCommon.CheckItemCanUse(eatItem):
-            GameWorld.DebugLog("物品不可用,无法兑换!itemIndex=%s" % index)
-            continue
-        eatItemID = eatItem.GetItemTypeID()
-        if eatItemID != eatItemIDList[i]:
-            GameWorld.Log('家族兑换活跃令 发的物品ID不对应index=%s eatItemID=%s,ItemIDList[i]=%s' % (index, eatItemID, eatItemIDList[i]), playerID)
-            continue
-        #if eatItem.GetIsBind():
-        #    GameWorld.DebugLog("装备已绑定,无法兑换!itemIndex=%s" % index)
-        #    continue
-        if eatItem.GetEndureReduceType():
-            GameWorld.DebugLog("有时效耐久物品,无法兑换!itemIndex=%s" % index)
-            continue
-        if eatItemID in familyDonateSpecialDict:
-            addPoint = familyDonateSpecialDict[eatItemID]
-        else:
-            if not ItemCommon.CheckItemIsEquip(eatItem):
-                GameWorld.DebugLog("非装备,无法兑换!itemIndex=%s" % index)
-                continue
-            itemColor = eatItem.GetItemColor()
-            if str(itemColor) not in familyDonateDict:
-                continue
-            isSuite = eatItem.GetSuiteID()
-            addPoint = familyDonateDict[str(itemColor)][1 if isSuite else 0]
-        itemCnt = eatItem.GetCount()
-        givePoint += addPoint * itemCnt
-        ItemCommon.DelItem(curPlayer, eatItem, itemCnt, True, ChConfig.ItemDel_FamilyStore, {'addPoint':addPoint}, True)
-    
-    if not givePoint:
-        GameWorld.DebugLog("家族兑换活跃令,没有装备可兑换!")
-        return
-    PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_FamilyActivity, givePoint)
-    
-    #通知结果
-    packData = ChPyNetSendPack.tagMCFamilyActivityExchangeResult()
-    packData.Clear()
-    packData.Point = givePoint
-    NetPackCommon.SendFakePack(curPlayer, packData)
-    return
 
 #// A6 12 家族捐献货币 #tagCMFamilyMoneyDonate
 #
 #struct     tagCMFamilyMoneyDonate
 #{
 #    tagHead        Head;
-#    BYTE        MoneyType;    // 捐献货币类型
+#    BYTE        DonateType;    // 捐献类型
 #};
 def OnFamilyMoneyDonate(index, clientData, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    moneyType = clientData.MoneyType
-    playerID = curPlayer.GetPlayerID()
-    
-    dailyDonateCountMax = IpyGameDataPY.GetFuncCfg('FamilyDonate', 3)
-    donateCount = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyMoneyDonateCount)
-    if dailyDonateCountMax and donateCount >= dailyDonateCountMax:
-        GameWorld.DebugLog("今日货币捐献次数已达上限. donateCount=%s" % donateCount, playerID)
-        return
-    
-    donatePrizeInfo = IpyGameDataPY.GetFuncEvalCfg('FamilyDonate', 4, {})
-    if str(moneyType) not in donatePrizeInfo:
-        GameWorld.DebugLog("不存在该货币类型捐献: moneyType=%s" % moneyType, playerID)
-        return
-    needMoney, contribution, familyActivity = donatePrizeInfo[str(moneyType)]
-    if not PlayerControl.PayMoney(curPlayer, moneyType, needMoney, "FamilyMoneyDonate"):
-        return
-    
-    updDonateCount = donateCount + 1
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyMoneyDonateCount, updDonateCount)
-    Sync_FamilyDayRewardState(curPlayer)
-    GameWorld.DebugLog("货币捐献: moneyType=%s,needMoney=%s,updDonateCount=%s,contribution=%s,familyActivity=%s" 
-                       % (moneyType, needMoney, updDonateCount, contribution, familyActivity), playerID)
-    
-    if contribution > 0:
-        AddPlayerFamilyActiveValue(curPlayer, contribution, True, ShareDefine.Def_AddFAVReason_FamilyDonateItem, True)
-        
-    if familyActivity > 0:
-        PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_FamilyActivity, familyActivity)
-        
+    #curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    #DonateType = clientData.DonateType
+    #playerID = curPlayer.GetPlayerID()
+    # 先屏蔽,等功能定了再改
+    return
+
+
+#---------------------------------------------------------------------
+def AddPlayerFamilyActiveValue(curPlayer, addValue, sendPackGameServer = False, reason = 0, isSysMsg=False):
+    # 多个地方用到,先保留,之后删除统一修改
+    return True
+def SendPack_GameServer_AddFamilyDetail(curPlayer, addFamilyHornor = 0, addFamilyMoney = 0, addFamilyActiveValue = 0, resion=0):
+    return
+def SendPack_GameServer_AddFamilyDetailEx(curPlayer, addPlayerActiveValue, addFamilyMoney = 0, addFamilyHornor = 0, resion=0):
+    return
+
+## ------------------------------------------------------------------------------------------------
+
+def GetFamilyDayAward(curPlayer):
+    ##领取仙盟每日奖励 2小时脱机挂时间
+    return
+
+def Sync_FamilyDayRewardState(curPlayer):
+    clientPack = ChPyNetSendPack.tagMCFamilyDayAward()
+    clientPack.GetState = 0
+    clientPack.MoneyDonateCount = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyDonateRecord)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+def AddFamilyActivity(curPlayer, actionid, addCnt=1):
     return
 
 
@@ -1195,222 +1574,3 @@
     clientPack.Count = len(clientPack.AffairInfoList)
     NetPackCommon.SendFakePack(curPlayer, clientPack)
     return
-
-##--------------------------------------------------------------------------------------------------
-##--------------------------------------- 仙盟传功 --------------------------------------------------
-#// A6 15 传功操作 #tagCMChuangongOP
-#
-#struct    tagCMChuangongOP
-#{
-#    tagHead        Head;
-#    BYTE        OPType;        // 操作类型:1-邀请;2-回应;3-领奖;
-#    DWORD        PlayerID;        // 目标玩家ID;回应时为邀请方玩家ID
-#    BYTE        OPData;        // 操作数据,可选:回应时为是否同意
-#};
-def OnChuangongOP(index, clientData, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    opType = clientData.OPType
-    tagPlayerID = clientData.PlayerID
-    opData = clientData.OPData
-    
-    if tagPlayerID and curPlayer.GetPlayerID() == tagPlayerID:
-        GameWorld.DebugLog("不能自己传功")
-        return
-    
-    if opType == 1:
-        __Chuangong_Invite(curPlayer, tagPlayerID)
-    elif opType == 2:
-        __Chuangong_Response(curPlayer, tagPlayerID, opData)
-    elif opType == 3:
-        __Chuangong_GetAward(curPlayer)
-    return
-
-def SendGameServer_FamilyChuangong(curPlayer, msgType, msgData):
-    playerID = curPlayer.GetPlayerID()
-    GameWorld.DebugLog("传功同步GameServer: msgType=%s,%s" % (msgType, msgData), playerID)
-    msgInfo = str([msgType, msgData])
-    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(playerID, 0, 0, "FamilyChuangong", msgInfo, len(msgInfo))
-    return
-
-def __CheckCanChuangong(curPlayer):
-    playerID = curPlayer.GetPlayerID()
-    remainCnt = PlayerActivity.GetDailyActionrRemainCnt(curPlayer, ShareDefine.DailyActionID_FamilyChuanGong)
-    if remainCnt <= 0:
-        GameWorld.DebugLog("没有传功次数了", playerID)
-        return
-    openServerDayLimit = IpyGameDataPY.GetFuncCfg("FamilyChuangong", 1)
-    if openServerDayLimit:
-        openServerDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay) + 1
-        if openServerDay > openServerDayLimit:
-            GameWorld.DebugLog("当前开服天不能传功: openServerDay=%s > %s" % (openServerDay, openServerDayLimit), playerID)
-            return
-    return True
-
-def __Chuangong_Invite(curPlayer, tagPlayerID):
-    ## 传功邀请
-    if not __CheckCanChuangong(curPlayer):
-        return
-    SendGameServer_FamilyChuangong(curPlayer, "Invite", [tagPlayerID])
-    return
-
-def __Chuangong_Response(curPlayer, tagPlayerID, isOK):
-    ## 传功回应
-    SendGameServer_FamilyChuangong(curPlayer, "Response", [tagPlayerID, isOK])
-    return
-
-def __Chuangong_GetAward(curPlayer):
-    ## 传功领奖
-    if not __CheckCanChuangong(curPlayer):
-        return
-    PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_FamilyChuanGong, 1)
-    
-    playerID = curPlayer.GetPlayerID()
-    fromLV = curPlayer.GetLV()
-    
-    # 给经验
-    totalExp = 0
-    giveRound = IpyGameDataPY.GetFuncCfg("FamilyChuangong", 3)
-    worldlv = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)
-    playerControl = PlayerControl.PlayerControl(curPlayer)
-    for index in range(giveRound):
-        reLV = curPlayer.GetLV()
-        reExp = PlayerControl.GetPlayerReExp(curPlayer)
-        giveExp = eval(IpyGameDataPY.GetFuncCompileCfg("FamilyChuangong", 2))
-        finalAddExp = playerControl.AddExp(giveExp, ShareDefine.Def_ViewExpType_Chuangong)
-        totalExp += finalAddExp
-        GameWorld.DebugLog("传功经验: 轮次=%s,reLV=%s,reExp=%s,finalAddExp=%s, %s" % (index, reLV, reExp, finalAddExp, totalExp), playerID)
-        
-    PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_FamilyChuanGong, 1)
-    PlayerTongTianLing.AddTongTianTaskValue(curPlayer, ChConfig.TTLTaskType_ChuanGong, 1)
-    
-    # 给物品
-    giveItemList = IpyGameDataPY.GetFuncEvalCfg("FamilyChuangong", 4)
-    ItemControler.GivePlayerItemOrMail(curPlayer, giveItemList)
-    
-    # 同步结果
-    syncItemList = []
-    for itemID, itemCount, _ in giveItemList:
-        syncItem = ChPyNetSendPack.tagMCChuangongItem()
-        syncItem.Clear()
-        syncItem.ItemID = itemID
-        syncItem.ItemCount = itemCount
-        syncItemList.append(syncItem)
-        # 有协助感谢礼盒
-        if IpyGameDataPY.GetIpyGameDataNotLog("AssistThanksGift", itemID):
-            SendGameServer_FamilyChuangong(curPlayer, "ThanksGift", [itemID])
-    clientPack = ChPyNetSendPack.tagMCChuangongResult()
-    clientPack.Clear()
-    clientPack.FromLV = fromLV
-    clientPack.ToLV = curPlayer.GetLV()
-    clientPack.Exp = totalExp % ChConfig.Def_PerPointValue
-    clientPack.ExpPoint = totalExp / ChConfig.Def_PerPointValue
-    clientPack.AwardItemList = syncItemList
-    clientPack.ItemCount = len(clientPack.AwardItemList)
-    NetPackCommon.SendFakePack(curPlayer, clientPack)
-    return
-
-##--------------------------------------------------------------------------------------------------
-##----------------------------------------- 珍宝阁 --------------------------------------------------
-#// A6 16 珍宝阁操作 #tagCMZhenbaogeOP
-#
-#struct    tagCMZhenbaogeOP
-#{
-#    tagHead     Head;
-#    BYTE    OpType;    // 操作:0-砍价;1-购买
-#};
-def OnZhenbaogeOP(index, clientData, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    opType = clientData.OpType
-    playerID = curPlayer.GetPlayerID()
-    if not curPlayer.GetFamilyID():
-        GameWorld.DebugLog("没有仙盟无法操作珍宝阁!", playerID)
-        return
-    
-    # 砍价
-    if opType == 0:
-        leaveTimeEx = PlayerControl.GetLeaveFamilyTimeEx(curPlayer)
-        cutState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeCut)
-        if cutState and leaveTimeEx:
-            cutCDTimes = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 3) * 60
-            passTimes = int(time.time()) - leaveTimeEx
-            if passTimes < cutCDTimes:
-                GameWorld.DebugLog("今日已砍价变更仙盟砍价CD中! passTimes=%s < %s" % (passTimes, cutCDTimes), playerID)
-                return
-        SendGameServer_FamilyZhenbaoge(curPlayer, "Cut", [])
-        
-    # 购买
-    elif opType == 1:
-        buyState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy)
-        if buyState:
-            GameWorld.DebugLog("珍宝阁今日已购买!", playerID)
-            return
-        moneyType = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 1)
-        playerMoneyValue = PlayerControl.GetMoney(curPlayer, moneyType)
-        SendGameServer_FamilyZhenbaoge(curPlayer, "Buy", [playerMoneyValue])
-        
-    return
-
-def SendGameServer_FamilyZhenbaoge(curPlayer, msgType, msgData):
-    playerID = curPlayer.GetPlayerID()
-    tick = GameWorld.GetGameWorld().GetTick()
-    if not GameWorld.SetPlayerTickTime(curPlayer, ChConfig.TYPE_Player_Tick_FamilyZhenbaoge, tick):
-        GameWorld.DebugLog("请求CD中...", playerID)
-        return
-    GameWorld.DebugLog("珍宝阁同步GameServer: msgType=%s,%s" % (msgType, msgData), playerID)
-    msgInfo = str([msgType, msgData])
-    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(playerID, 0, 0, "FamilyZhenbaoge", msgInfo, len(msgInfo))
-    return
-
-def GameServer_FamilyZhenbaogeRet(curPlayer, resultList):
-    curPlayer.SetTickByType(ChConfig.TYPE_Player_Tick_FamilyZhenbaoge, 0)
-    playerID = curPlayer.GetPlayerID()
-    msgType, _ = resultList[:2]
-    retData = resultList[2:]
-    GameWorld.Log("仙盟珍宝阁GameServer返回: %s" % str(resultList), playerID)
-    if msgType == "Cut":
-        cutPrice = retData[0]
-        if not cutPrice:
-            # 砍价失败不处理后续
-            return
-        PlayerControl.NotifyCode(curPlayer, "ZhenbaogeCut", [cutPrice])
-        if not curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeCut):
-            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeCut, 1)
-            Sync_ZhenbaogeInfo(curPlayer)
-        
-    elif msgType == "Buy":
-        isOK = retData[0]
-        if not isOK:
-            return
-        buyState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy)
-        if buyState:
-            #一天只能买一次,防止变更仙盟刷
-            return
-        nowPrice, giveItemList = retData[1:]
-        
-        moneyType = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 1)
-        if nowPrice > 0:
-            if not PlayerControl.PayMoney(curPlayer, moneyType, nowPrice, "Zhenbaoge"):
-                GameWorld.ErrLog("珍宝阁购买货币不足! nowPrice=%s" % nowPrice, playerID)
-                return
-        elif nowPrice < 0:
-            PlayerControl.GiveMoney(curPlayer, moneyType, -nowPrice, "Zhenbaoge")
-        else: # 0不处理
-            pass
-        
-        if giveItemList:
-            ItemControler.GivePlayerItemOrMail(curPlayer, giveItemList, event=["Zhenbaoge", False, {}], isNotifyAward=False)
-        ItemControler.NotifyGiveAwardInfo(curPlayer, giveItemList, "Zhenbaoge", moneyInfo={moneyType:0 if nowPrice > 0 else -nowPrice})
-        
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy, 1)
-        Sync_ZhenbaogeInfo(curPlayer)
-            
-    return
-
-def Sync_ZhenbaogeInfo(curPlayer):
-    clientPack = ChPyNetSendPack.tagMCFamilyZhenbaogeInfo()
-    clientPack.CutState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeCut)
-    clientPack.BuyState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy)
-    NetPackCommon.SendFakePack(curPlayer, clientPack)
-    return
-
-##--------------------------------------------------------------------------------------------------
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyEmblem.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyEmblem.py
new file mode 100644
index 0000000..d900533
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyEmblem.py
@@ -0,0 +1,185 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package PlayerFamilyEmblem
+#
+# @todo:仙盟徽章
+# @author hxp
+# @date 2024-09-09
+# @version 1.0
+#
+# 详细描述: 仙盟徽章
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-09-09 15:30"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import ShareDefine
+import IpyGameDataPY
+import PlayerFamily
+import DBDataMgr
+
+import random
+import time
+
+def GetActionEmblemID(emblemActionObj): return emblemActionObj.GetValue1()
+def SetActionEmblemID(emblemActionObj, emblemID): return emblemActionObj.SetValue1(emblemID)
+def GetActionEmblemEndTime(emblemActionObj): return emblemActionObj.GetValue2()
+def SetActionEmblemEndTime(emblemActionObj, endTime): return emblemActionObj.SetValue2(endTime)
+
+def GetDefaultFamilyEmblemIDList():
+    ## 获取默认的仙盟徽章ID列表,即所有解锁等级为1的徽章ID
+    defaultEmblemIDList = []
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetFamilyEmblemCount()):
+        ipyData = ipyDataMgr.GetFamilyEmblemByIndex(index)
+        emblemID = ipyData.GetEmblemID()
+        if ipyData.GetUnlockFamilyLV() == 1:
+            defaultEmblemIDList.append(emblemID)
+    return defaultEmblemIDList
+
+def CheckExpireEmblem():
+    ## 检查过期的勋章
+    
+    defaultEmblemIDList = []
+    curTime = int(time.time())
+    actionType = ShareDefine.Def_ActionType_FamilyEmblem
+    familyManager = DBDataMgr.GetFamilyMgr()
+    for i in xrange(familyManager.GetCount()):
+        family = familyManager.GetAt(i)
+        if not family:
+            continue
+        familyID = family.GetID()
+        familyAction = familyManager.GetFamilyActionMgr().GetFamilyAction(familyID, actionType)
+        for index in range(familyAction.Count())[::-1]: # 可能触发删除,倒序遍历
+            emblemActionObj = familyAction.At(index)
+            emblemID = GetActionEmblemID(emblemActionObj)
+            endTime = GetActionEmblemEndTime(emblemActionObj)
+            if not endTime or endTime > curTime:
+                #GameWorld.Log("检查仙盟徽章未过期! familyID=%s,emblemID=%s,endTime=%s" % (familyID, emblemID, endTime))
+                continue
+            familyAction.DelAction(index)
+            GameWorld.Log("删除过期仙盟徽章! familyID=%s,emblemID=%s,endTime=%s" % (familyID, emblemID, endTime))
+            if family.GetEmblemID() == emblemID:
+                if not defaultEmblemIDList:
+                    defaultEmblemIDList = GetDefaultFamilyEmblemIDList()
+                updEmblemID = random.choice(defaultEmblemIDList) if defaultEmblemIDList else 0
+                GameWorld.Log("仙盟佩戴徽章过期恢复随机默认徽章! familyID=%s,emblemID=%s,endTime=%s,updEmblemID=%s" % (familyID, emblemID, endTime, updEmblemID))
+                family.SetEmblemID(updEmblemID)
+                family.Broadcast_FamilyChange()
+    return
+
+def GetFamilyEmblemActionData(familyID, emblemID):
+    ## 获取仙盟时效徽章Action数据
+    actionType = ShareDefine.Def_ActionType_FamilyEmblem
+    familyAction = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(familyID, actionType)
+    for index in range(familyAction.Count()):
+        familyActionObj = familyAction.At(index)
+        if emblemID == familyActionObj.GetValue1():
+            return familyActionObj
+    return
+
+def AddFamilyEmblem(familyID, emblemID, setExpireTimes=None):
+    ## 添加仙盟徽章
+    # @param setExpireTimes: 指定的有效时长秒,0-永久,>0-有效时长秒;没有指定时直接读配置进行累加
+    if not familyID or not emblemID:
+        return
+    ipyData = IpyGameDataPY.GetIpyGameData("FamilyEmblem", emblemID)
+    if not ipyData:
+        return
+    if ipyData.GetCustomFamilyID():
+        GameWorld.Log("仙盟定制徽章不需要添加! familyID=%s,emblemID=%s" % (familyID, emblemID))
+        return
+    unlockFamilyLV = ipyData.GetUnlockFamilyLV()
+    if unlockFamilyLV:
+        GameWorld.Log("仙盟解锁的徽章不需要添加! familyID=%s,emblemID=%s" % (familyID, emblemID))
+        return
+    ipyExpireSeconds = ipyData.GetExpireMinutes() * 60
+    
+    curTime = int(time.time())
+    emblemActionObj = GetFamilyEmblemActionData(familyID, emblemID)
+    if not emblemActionObj:
+        actionType = ShareDefine.Def_ActionType_FamilyEmblem
+        familyAction = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(familyID, actionType)
+        emblemActionObj = familyAction.AddAction()
+        emblemActionObj.SetTime(curTime)
+        emblemActionObj.SetFamilyId(familyID)
+        emblemActionObj.SetActionType(actionType)
+        
+    if not emblemActionObj:
+        return
+    endTime = GetActionEmblemEndTime(emblemActionObj)
+    updEndTime = endTime
+    
+    # 指定时长的,如GM指定
+    if setExpireTimes > 0:
+        updEndTime = curTime + setExpireTimes
+        
+    # 永久
+    elif ipyExpireSeconds == 0 or setExpireTimes == 0:
+        updEndTime = 0
+        
+    else:
+        # 未过期
+        if endTime > curTime:
+            updEndTime = endTime + ipyExpireSeconds
+        else:
+            updEndTime = curTime + ipyExpireSeconds
+            
+    GameWorld.Log("添加仙盟徽章! familyID=%s,emblemID=%s,setExpireTimes=%s,endTime=%s,updEndTime=%s" 
+                  % (familyID, emblemID, setExpireTimes, endTime, updEndTime))
+    SetActionEmblemID(emblemActionObj, emblemID)
+    SetActionEmblemEndTime(emblemActionObj, updEndTime)
+    
+    # 通知
+    #PlayerFamilyAction.SendFamilyAction(emblemActionObj)
+    return emblemActionObj
+
+def OnChangeFamilyEmblem(curPlayer, emblemID):
+    ## 修改仙盟徽章
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    familyManager = PlayerFamily.GetFamilyMgr()
+    curFamily = familyManager.FindFamily(familyID)
+    if not curFamily:
+        return
+    familyID = curFamily.GetID()
+    
+    if curFamily.GetLeaderID() != playerID:
+        GameWorld.DebugLog("只有盟主可以修改徽章!", playerID)
+        return
+    
+    ipyData = IpyGameDataPY.GetIpyGameData("FamilyEmblem", emblemID)
+    if not ipyData:
+        return
+    unlockFamilyLV = ipyData.GetUnlockFamilyLV()
+    customFamilyID = ipyData.GetCustomFamilyID()
+    
+    if customFamilyID:
+        if familyID != customFamilyID:
+            GameWorld.DebugLog("不是该定制徽章所属仙盟,无法使用该徽章! emblemID=%s,customFamilyID=%s != %s" 
+                               % (emblemID, customFamilyID, familyID), playerID)
+            return
+        
+    elif unlockFamilyLV:
+        if curFamily.GetLV() < unlockFamilyLV:
+            GameWorld.DebugLog("仙盟等级不足,无法使用该徽章! emblemID=%s,unlockFamilyLV=%s" 
+                               % (emblemID, unlockFamilyLV), playerID)
+            return
+    else:
+        emblemActionObj = GetFamilyEmblemActionData(familyID, emblemID)
+        if not emblemActionObj:
+            GameWorld.DebugLog("该徽章未激活! emblemID=%s" % (emblemID), playerID)
+            return
+        endTime = GetActionEmblemEndTime(emblemActionObj)
+        if endTime and endTime <= int(time.time()):
+            GameWorld.Log("该徽章已过期! familyID=%s,emblemID=%s,endTime=%s" % (familyID, emblemID, endTime))
+            return
+        
+    GameWorld.DebugLog("更换仙盟徽章! familyID=%s,emblemID=%s" % (familyID, emblemID), playerID)
+    curFamily.SetEmblemID(emblemID)
+    #PlayerFamily.SendPack_MapServer_PlayerFamilyRefresh(curFamily)
+    curFamily.Broadcast_FamilyChange()
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyZhenbaoge.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyZhenbaoge.py
new file mode 100644
index 0000000..0922152
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyZhenbaoge.py
@@ -0,0 +1,347 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package PlayerFamilyZhenbaoge
+#
+# @todo:珍宝阁
+# @author hxp
+# @date 2024-10-29
+# @version 1.0
+#
+# 详细描述: 珍宝阁
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-10-29 17:30"""
+#-------------------------------------------------------------------------------
+
+import ChConfig
+import ShareDefine
+import IpyGameDataPY
+import PlayerFamily
+import GameWorld
+import DBDataMgr
+
+import random
+import time
+import ChPyNetSendPack
+import NetPackCommon
+import ItemControler
+import PlayerControl
+
+ActionType = ShareDefine.Def_ActionType_Zhenbaoge
+ActionGlobalID = 1 # 全局记录ID
+
+# 全局记录
+#Time    本轮开始时间戳
+#Value1    ActionGlobalID
+def GetFAPrice(gActionData): return gActionData.GetValue2()
+def SetFAPrice(gActionData, price): return gActionData.SetValue2(price)
+def GetFAIsNegative(gActionData): return gActionData.GetValue3() # 是否负值
+def SetFAIsNegative(gActionData, isNegative): return gActionData.SetValue3(isNegative)
+def GetFAPriceFinal(gActionData):
+    ## 获取最终价格
+    price = GetFAPrice(gActionData)
+    isNegative = GetFAIsNegative(gActionData)
+    return price if not isNegative else -price
+def SetFAPriceFinal(gActionData, totalPrice):
+    SetFAPrice(gActionData, abs(totalPrice))
+    SetFAIsNegative(gActionData, 1 if totalPrice < 0 else 0)
+    return
+def GetFAItemList(gActionData): return eval(gActionData.GetUseData()) # 物品列表
+def SetFAItemList(gActionData, itemList):
+    dataStr = str(itemList)
+    gActionData.SetUseData(dataStr, len(dataStr))
+    return
+
+# 成员砍价记录
+#Time    砍价时间戳
+#Name    玩家名
+def GetFAPlayerID(actionData): return actionData.GetValue1()
+def SetFAPlayerID(actionData, playerID): return actionData.SetValue1(playerID)
+def GetFACutPrice(actionData): return actionData.GetValue2() # 玩家砍了多少
+def SetFACutPrice(actionData, cutPrice): return actionData.SetValue2(cutPrice)
+def GetFABuyState(actionData): return actionData.GetValue3() # 玩家是否已购买
+def SetFABuyState(actionData, buyState): return actionData.SetValue3(buyState)
+
+def OnDayEx(family):
+    OnZhenbaogeReset(family)        
+    return
+
+def OnZhenbaogeReset(family):
+    ## 珍宝阁重置
+    
+    familyID = family.GetID()
+    
+    familyAction = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(familyID, ActionType)
+    gActionData = familyAction.AddAction()
+    SetFAPlayerID(gActionData, ActionGlobalID)
+    
+    initPrice = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 2)
+    
+    randItemList = []
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetFamilyZhenbaogeItemCount()):
+        ipyData = ipyDataMgr.GetFamilyZhenbaogeItemByIndex(index)
+        randItemList.append([ipyData.GetItemWeight(), ipyData.GetItemList()])
+        
+    itemList = GameWorld.GetResultByWeightList(randItemList, [])
+    
+    SetFAPriceFinal(gActionData, initPrice)
+    SetFAItemList(gActionData, itemList)
+    
+    #PlayerFamilyAction.SendFamilyAction(gActionData)
+    GameWorld.DebugLog("珍宝阁重置! familyID=%s,itemList=%s" % (familyID, itemList), familyID)    
+    return
+
+def GetZhenbaogeActionData(familyID, playerID):
+    ## 获取Action
+    findActionData = None
+    familyAction = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(familyID, ActionType)
+    for index in range(0, familyAction.Count()):
+        actionData = familyAction.At(index)
+        if GetFAPlayerID(actionData) == playerID:
+            findActionData = actionData
+            break
+    return findActionData
+
+def MapServer_ZhenbaogeOP(curPlayer, msgList):
+    mapID = curPlayer.GetRealMapID()
+    playerID = curPlayer.GetPlayerID()
+    GameWorld.DebugLog("MapServer_ZhenbaogeOP mapID=%s,msgList=%s" % (mapID, msgList), playerID)
+    if not msgList:
+        return
+    
+    curFamily = curPlayer.GetFamily()
+    if not curFamily:
+        return
+    
+    familyID = curFamily.GetID()
+    gActionData = GetZhenbaogeActionData(familyID, ActionGlobalID)
+    if not gActionData:
+        GameWorld.DebugLog("珍宝阁还没有刷新! familyID=%s" % familyID, playerID)
+        return
+    
+    msgType, dataMsg = msgList
+    ret = None
+    
+    if msgType == "Cut":
+        cutPrice = CalcCutPrice(curFamily, gActionData, playerID)
+        if cutPrice:
+            AddCutPrice(familyID, playerID, curPlayer.GetName(), cutPrice, gActionData)
+        ret = [cutPrice]
+        
+    elif msgType == "Buy":
+        buyRet = __DoZhenbaogeBuy(familyID, playerID, gActionData, dataMsg)
+        if buyRet:
+            ret = [True] + list(buyRet)
+        else:
+            ret = [False]
+            
+    if ret == None:
+        return
+    return msgList + (ret if isinstance(ret, list) else [ret])
+
+def CalcCutPrice(curFamily, gActionData, playerID):
+    ## 计算砍价价格
+    # @return: None-砍价限制等;>0-砍价值
+    
+    familyID = curFamily.GetID()
+    
+    familyAction = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(familyID, ActionType)
+    actionCount = familyAction.Count() # 其中1条是公共数据
+    hadCutCount = actionCount - 1
+    maxMemberCnt = PlayerFamily.GetFamilySetting(curFamily, ChConfig.Def_FamilySetting_MaxMemberCnt)
+    if hadCutCount >= maxMemberCnt:
+        GameWorld.ErrLog("已达到仙盟砍价人次上限! hadCutCount=%s >= %s,familyID=%s,familyLV=%s" 
+                         % (hadCutCount, maxMemberCnt, familyID, curFamily.GetLV()), playerID)
+        return
+    
+    actionData = GetZhenbaogeActionData(familyID, playerID)
+    if actionData and GetFACutPrice(actionData):
+        GameWorld.DebugLog("已经在该盟珍宝阁砍价过了! familyID=%s" % familyID, playerID)
+        return
+    
+    cutNum = hadCutCount + 1
+    cutIpyData = IpyGameDataPY.GetIpyGameData("FamilyZhenbaogeCut", cutNum)
+    if not cutIpyData:
+        return
+    cutWeight = cutIpyData.GetCutWeight()
+    minRatio = cutIpyData.GetMinRatio()
+    randRatio = cutIpyData.GetRandRatio()
+    totalWeight = PlayerFamily.GetFamilySetting(curFamily, ChConfig.Def_FamilySetting_ZhenbaogeWeights)
+    rand = random.random()  #随机值 0~1
+    
+    initPrice = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 2)
+    
+    cutPrice = max(1, eval(IpyGameDataPY.GetFuncCompileCfg("ZhenbaogeCut", 2)))
+    
+    nowPrice = GetFAPriceFinal(gActionData)
+    updPrice = nowPrice - cutPrice
+    
+    lowestPrice = IpyGameDataPY.GetFuncCfg("ZhenbaogeCut", 1) # 最低价格保护
+    if updPrice < lowestPrice:
+        if nowPrice > lowestPrice:
+            updPrice = int(lowestPrice - random.randint(0, 2)) # 之前还未到达最低价,固定最低价+随机0~2
+            cutPrice = nowPrice - updPrice
+        else:
+            cutPrice = random.randint(1, 2) # 低于最低价格后砍价只能随机1或2
+            updPrice = nowPrice - cutPrice
+        GameWorld.DebugLog("珍宝阁砍价计算地板价保护: cutPrice=%s,nowPrice=%s,updPrice=%s" % (cutPrice, nowPrice, updPrice), playerID)
+    else:
+        GameWorld.DebugLog("珍宝阁砍价计算: cutPrice=%s,nowPrice=%s,updPrice=%s,cutWeight=%s/%s,minRatio=%s,randRatio=%s,rand=%s,initPrice=%s" 
+                   % (cutPrice, nowPrice, updPrice, cutWeight, totalWeight, minRatio, randRatio, rand, initPrice), playerID)
+        
+    return max(1, cutPrice)
+
+def AddCutPrice(familyID, playerID, playerName, cutPrice, gActionData, isNotify=True):
+    ## 添加砍价记录
+    familyAction = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(familyID, ActionType)
+    actionData = familyAction.AddAction()
+    actionData.SetFamilyId(familyID)
+    actionData.SetActionType(ActionType)
+    actionData.SetTime(int(time.time()))
+    actionData.SetName(playerName)
+    SetFAPlayerID(actionData, playerID)
+    SetFACutPrice(actionData, cutPrice)
+    
+    # 更新最终价格
+    nowPrice = GetFAPriceFinal(gActionData)
+    updPrice = nowPrice - cutPrice    
+    SetFAPriceFinal(gActionData, updPrice)
+    GameWorld.DebugLog("珍宝阁砍价更新: playerID=%s,cutPrice=%s,nowPrice=%s,updPrice=%s,familyID=%s" 
+                       % (playerID, cutPrice, nowPrice, updPrice, familyID), playerID)
+    if isNotify:
+        pass
+        #PlayerFamilyAction.SendFamilyAction([gActionData, actionData])
+    return actionData
+
+def __DoZhenbaogeBuy(familyID, playerID, gActionData, dataMsg):
+    playerMoneyValue = dataMsg[0]
+    actionData = GetZhenbaogeActionData(familyID, playerID)
+    if not actionData:
+        GameWorld.DebugLog("珍宝阁未砍价,无法购买! familyID=%s" % familyID, playerID)
+        return
+    if GetFABuyState(actionData):
+        GameWorld.DebugLog("珍宝阁已经购买过了! familyID=%s" % familyID, playerID)
+        return
+    nowPrice = GetFAPriceFinal(gActionData)
+    if nowPrice > 0 and playerMoneyValue < nowPrice:
+        GameWorld.DebugLog("玩家当前货币不足,无法购买珍宝阁物品! playerMoneyValue=%s < %s" % (playerMoneyValue, nowPrice), playerID)
+        return
+    
+    giveItemList = GetFAItemList(gActionData)
+    GameWorld.DebugLog("珍宝阁购买! familyID=%s,nowPrice=%s,giveItemList=%s" % (familyID, nowPrice, giveItemList), playerID)
+    
+    # 设置已买
+    SetFABuyState(actionData, 1)
+    #PlayerFamilyAction.SendFamilyAction(actionData)
+    return nowPrice, giveItemList
+
+
+
+##----------------------------------------- 珍宝阁 --------------------------------------------------
+#// A6 16 珍宝阁操作 #tagCMZhenbaogeOP
+#
+#struct    tagCMZhenbaogeOP
+#{
+#    tagHead     Head;
+#    BYTE    OpType;    // 操作:0-砍价;1-购买
+#};
+def OnZhenbaogeOP(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    opType = clientData.OpType
+    playerID = curPlayer.GetPlayerID()
+    if not curPlayer.GetFamilyID():
+        GameWorld.DebugLog("没有仙盟无法操作珍宝阁!", playerID)
+        return
+    
+    # 砍价
+    if opType == 0:
+        leaveTimeEx = PlayerControl.GetLeaveFamilyTimeEx(curPlayer)
+        cutState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeCut)
+        if cutState and leaveTimeEx:
+            cutCDTimes = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 3) * 60
+            passTimes = int(time.time()) - leaveTimeEx
+            if passTimes < cutCDTimes:
+                GameWorld.DebugLog("今日已砍价变更仙盟砍价CD中! passTimes=%s < %s" % (passTimes, cutCDTimes), playerID)
+                return
+        SendGameServer_FamilyZhenbaoge(curPlayer, "Cut", [])
+        
+    # 购买
+    elif opType == 1:
+        buyState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy)
+        if buyState:
+            GameWorld.DebugLog("珍宝阁今日已购买!", playerID)
+            return
+        moneyType = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 1)
+        playerMoneyValue = PlayerControl.GetMoney(curPlayer, moneyType)
+        SendGameServer_FamilyZhenbaoge(curPlayer, "Buy", [playerMoneyValue])
+        
+    return
+
+def SendGameServer_FamilyZhenbaoge(curPlayer, msgType, msgData):
+    playerID = curPlayer.GetPlayerID()
+    tick = GameWorld.GetGameWorld().GetTick()
+    if not GameWorld.SetPlayerTickTime(curPlayer, ChConfig.TYPE_Player_Tick_FamilyZhenbaoge, tick):
+        GameWorld.DebugLog("请求CD中...", playerID)
+        return
+    GameWorld.DebugLog("珍宝阁同步GameServer: msgType=%s,%s" % (msgType, msgData), playerID)
+    msgInfo = str([msgType, msgData])
+    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(playerID, 0, 0, "FamilyZhenbaoge", msgInfo, len(msgInfo))
+    return
+
+def GameServer_FamilyZhenbaogeRet(curPlayer, resultList):
+    curPlayer.SetTickByType(ChConfig.TYPE_Player_Tick_FamilyZhenbaoge, 0)
+    playerID = curPlayer.GetPlayerID()
+    msgType, _ = resultList[:2]
+    retData = resultList[2:]
+    GameWorld.Log("仙盟珍宝阁GameServer返回: %s" % str(resultList), playerID)
+    if msgType == "Cut":
+        cutPrice = retData[0]
+        if not cutPrice:
+            # 砍价失败不处理后续
+            return
+        PlayerControl.NotifyCode(curPlayer, "ZhenbaogeCut", [cutPrice])
+        if not curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeCut):
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeCut, 1)
+            Sync_ZhenbaogeInfo(curPlayer)
+        
+    elif msgType == "Buy":
+        isOK = retData[0]
+        if not isOK:
+            return
+        buyState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy)
+        if buyState:
+            #一天只能买一次,防止变更仙盟刷
+            return
+        nowPrice, giveItemList = retData[1:]
+        
+        moneyType = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 1)
+        if nowPrice > 0:
+            if not PlayerControl.PayMoney(curPlayer, moneyType, nowPrice, "Zhenbaoge"):
+                GameWorld.ErrLog("珍宝阁购买货币不足! nowPrice=%s" % nowPrice, playerID)
+                return
+        elif nowPrice < 0:
+            PlayerControl.GiveMoney(curPlayer, moneyType, -nowPrice, "Zhenbaoge")
+        else: # 0不处理
+            pass
+        
+        if giveItemList:
+            ItemControler.GivePlayerItemOrMail(curPlayer, giveItemList, event=["Zhenbaoge", False, {}], isNotifyAward=False)
+        ItemControler.NotifyGiveAwardInfo(curPlayer, giveItemList, "Zhenbaoge", moneyInfo={moneyType:0 if nowPrice > 0 else -nowPrice})
+        
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy, 1)
+        Sync_ZhenbaogeInfo(curPlayer)
+            
+    return
+
+def Sync_ZhenbaogeInfo(curPlayer):
+    clientPack = ChPyNetSendPack.tagMCFamilyZhenbaogeInfo()
+    clientPack.CutState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeCut)
+    clientPack.BuyState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+##--------------------------------------------------------------------------------------------------
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCacheTube.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCacheTube.py
index 2b08c68..7a9b4ad 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCacheTube.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCacheTube.py
@@ -20,7 +20,7 @@
 import PlayerControl
 import IPY_GameWorld
 import ChPyNetSendPack
-import PyGameDataStruct
+import DBStruct
 import ChMapToGamePyPack
 import PlayerMagicWeapon
 import Operate_EquipStone
@@ -40,7 +40,7 @@
 import time
 import json
 
-TempDBPlayer = PyGameDataStruct.tagDBPlayer()
+TempDBPlayer = DBStruct.tagDBPlayer()
 
 Def_Process_Tick = "ProcessPlayerCache"
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyNameRefresh.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyNameRefresh.py
index ad7c5df..3829477 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyNameRefresh.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyNameRefresh.py
@@ -49,7 +49,7 @@
             PlayerFamily.PayUpdateFamilyNameCost(curFindPlayer)
         
         #清除改名锁
-        curFindPlayer.SetDict(ChConfig.Def_Player_Dict_UpdateFamilyName, 0)
+        #curFindPlayer.SetDict(ChConfig.Def_Player_Dict_UpdateFamilyName, 0)
     return
 
 #---------------------------------------------------------------------
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyZhenbaoge.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyZhenbaoge.py
index 325d665..0b25851 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyZhenbaoge.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyZhenbaoge.py
@@ -15,7 +15,7 @@
 #"""Version = 2024-10-29 17:30"""
 #-------------------------------------------------------------------------------
 
-import PlayerFamily
+import PlayerFamilyZhenbaoge
 
 #---------------------------------------------------------------------
 #逻辑实现
@@ -39,7 +39,7 @@
 #  @return None
 #  @remarks 函数详细说明.
 def DoResult(curPlayer, callFunName, funResult, tick):
-    PlayerFamily.GameServer_FamilyZhenbaogeRet(curPlayer, eval(funResult))
+    PlayerFamilyZhenbaoge.GameServer_FamilyZhenbaogeRet(curPlayer, eval(funResult))
     return
 
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_ForbiddenFamilyAction.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_ForbiddenFamilyAction.py
index 4d1ef3e..7590972 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_ForbiddenFamilyAction.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_ForbiddenFamilyAction.py
@@ -28,7 +28,7 @@
     forbidFamilyAction = GameWorld.ToIntDef(funResult)
 
     # 设置玩家是否可以参加家族活动
-    PlayerFamily.SetForbidFamilyAction(curPlayer, forbidFamilyAction)
+    #PlayerFamily.SetForbidFamilyAction(curPlayer, forbidFamilyAction)
     return
 
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
index 395f224..b6294d7 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
@@ -14,6 +14,11 @@
 #-------------------------------------------------------------------------------
 #"""Version = 2017-09-05 21:30"""
 #-------------------------------------------------------------------------------
+
+g_initGame = False
+
+g_pyGameDataManager = None
+
 g_mapIDTxtInfo = {} # MapID.txt 加载的信息
 g_realmDiffPlayerDict = {} # 境界难度玩家信息 {realm:[playerID, ...], ...}
 g_realmDiffNPCRefresh = {} # {(lineID, realm):{refreshID:tagNPCRefresh, ...}}
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameDataStruct.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameDataStruct.py
deleted file mode 100644
index 7af8c46..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameDataStruct.py
+++ /dev/null
@@ -1,665 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#
-##@package E:/GameSVN/U3DGame/ProjectSServer/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
-# @todo: 
-#
-# @author: Alee
-# @date 2017-8-21 下午04:21:36
-# @version 1.0
-#
-# @note: CodeMaker PyGameServerSaveData.py生成
-#
-#---------------------------------------------------------------------
-import ctypes
-from ctypes import (Structure, memset, memmove, sizeof, addressof, create_string_buffer, string_at)
-import CommFunc
-
-#玩家详细信息#tagDBPlayer
-class tagDBPlayer(Structure):
-    _pack_ = 1
-    _fields_ = [
-        ('PlayerID', ctypes.c_ulong),
-        ('AccID', ctypes.c_char * 65),
-        ('PlayerName', ctypes.c_char * 33),
-        ('AccState', ctypes.c_ubyte),
-        ('IsDeleted', ctypes.c_ubyte),
-        ('GMLevel', ctypes.c_ubyte),
-        ('Sex', ctypes.c_int),
-        ('Hair', ctypes.c_int),
-        ('HairColor', ctypes.c_int),
-        ('Face', ctypes.c_int),
-        ('FacePic', ctypes.c_int),
-        ('Job', ctypes.c_int),
-        ('RoleType', ctypes.c_ulong),
-        ('ReincarnationLv', ctypes.c_ushort),
-        ('LV', ctypes.c_int),
-        ('TotalExp', ctypes.c_ulong),
-        ('FamilyID', ctypes.c_ulong),
-        ('FamilyName', ctypes.c_char * 33),
-        ('Country', ctypes.c_int),
-        ('TeamHornor', ctypes.c_ulong),
-        ('FamilyHornor', ctypes.c_ulong),
-        ('FamilyActiveValue', ctypes.c_ulong),
-        ('LastWeekFamilyActiveValue', ctypes.c_ulong),
-        ('CountryHornor', ctypes.c_ulong),
-        ('CountryLastWeekHornor', ctypes.c_ulong),
-        ('Mate', ctypes.c_ulong),
-        ('Gold', ctypes.c_ulong),
-        ('GoldPaper', ctypes.c_ulong),
-        ('Silver', ctypes.c_ulong),
-        ('SilverPaper', ctypes.c_ulong),
-        ('FightPoint', ctypes.c_ulong),
-        ('HappyPoint', ctypes.c_ulong),
-        ('MapID', ctypes.c_ulong),
-        ('DataMapID', ctypes.c_ulong),
-        ('CopyMapID', ctypes.c_ulong),
-        ('PosX', ctypes.c_ushort),
-        ('PosY', ctypes.c_ushort),
-        ('FromMapID', ctypes.c_ulong),
-        ('FromCopyMapID', ctypes.c_ulong),
-        ('FromPosX', ctypes.c_ushort),
-        ('FromPosY', ctypes.c_ushort),
-        ('State', ctypes.c_int),
-        ('HP', ctypes.c_ulong),
-        ('MP', ctypes.c_ulong),
-        ('XP', ctypes.c_ulong),
-        ('HPRestoreSetting', ctypes.c_ushort),
-        ('MPRestoreSetting', ctypes.c_ushort),
-        ('FreePoint', ctypes.c_ulong),
-        ('FreeSkillPoint', ctypes.c_ulong),
-        ('STR', ctypes.c_int),
-        ('PNE', ctypes.c_int),
-        ('PHY', ctypes.c_int),
-        ('CON', ctypes.c_int),
-        ('TotalSTR', ctypes.c_int),
-        ('TotalPNE', ctypes.c_int),
-        ('TotalPHY', ctypes.c_int),
-        ('TotalCON', ctypes.c_int),
-        ('Setting', ctypes.c_char * 100),
-        ('PKValue', ctypes.c_ushort),
-        ('FightPower', ctypes.c_ulong),
-        ('ActiveValue', ctypes.c_ushort),
-        ('PlayerType', ctypes.c_ubyte),
-        ('BackpackLV', ctypes.c_ubyte),
-        ('WarehouseLV', ctypes.c_ubyte),
-        ('HaveWarehousePsw', ctypes.c_ubyte),
-        ('WarehousePsw', ctypes.c_char * 15),
-        ('WarehouseLocked', ctypes.c_ubyte),
-        ('WarehouseGold', ctypes.c_ulong),
-        ('WarehouseSilver', ctypes.c_ulong),
-        ('TeamID', ctypes.c_ulong),
-        ('UseGoldType', ctypes.c_ubyte),
-        ('UseSilverType', ctypes.c_ubyte),
-        ('AttackMode', ctypes.c_ubyte),
-        ('RebornMapID', ctypes.c_ushort),
-        ('RebornPosX', ctypes.c_ushort),
-        ('RebornPosY', ctypes.c_ushort),
-        ('WeekOnlineTime', ctypes.c_ulong),
-        ('LastWeekOnlineTime', ctypes.c_ulong),
-        ('LogoffTime', ctypes.c_char * 30),
-        ('IsHideMask', ctypes.c_ubyte),
-        ('DayProcessGameEventCount', ctypes.c_ulong),
-        ('LoginIP', ctypes.c_char * 20),
-        ('LoginTime', ctypes.c_char * 30),
-        ('OnlineTime', ctypes.c_ulong),
-        ('FriendFavor', ctypes.c_ulong),
-        ('TeamPrivity', ctypes.c_ulong),
-        ('OfflineMinutes', ctypes.c_ulong),
-        ('Energy', ctypes.c_ulong),
-        ('ReceivedSalary', ctypes.c_ulong),
-        ('EquipShowSwitch', ctypes.c_ulong),
-        ('LuckValue', ctypes.c_ushort),
-        ('ExAttr1', ctypes.c_ulong),
-        ('ExAttr2', ctypes.c_ulong),
-        ('ExAttr3', ctypes.c_ulong),
-        ('ExAttr4', ctypes.c_ulong),
-        ('ExAttr5', ctypes.c_ulong),
-        ('Faction', ctypes.c_int),
-        ('InfamyValue', ctypes.c_ulong),
-        ('OfficialRank', ctypes.c_ubyte),
-        ('IsFindByLabel', ctypes.c_ubyte),
-        ('IsCloseFriendLabel', ctypes.c_ubyte),
-        ('ChangeCoinPointTotal', ctypes.c_ulong),
-        ('VIPLv', ctypes.c_ubyte),
-        ('VIPLvForPhone', ctypes.c_ubyte),
-        ('PhoneVIPStartTime', ctypes.c_double),
-        ('PhoneVIPEndTime', ctypes.c_double),
-        ('VsRoomId', ctypes.c_ulong),
-        ('ExAttr6', ctypes.c_ulong),
-        ('ExAttr7', ctypes.c_ulong),
-        ('ExAttr8', ctypes.c_ulong),
-        ('ExAttr9', ctypes.c_ulong),
-        ('ExAttr10', ctypes.c_ulong),
-        ('ModelMark', ctypes.c_ulong),
-        ('FromDataMapID', ctypes.c_ulong),
-        ('LastOrderId', ctypes.c_char * 40),
-        ('PrizeCoin', ctypes.c_ulong),
-        ('ExAttr11', ctypes.c_ulong),
-        ('ExAttr12', ctypes.c_ulong),
-        ('ExAttr13', ctypes.c_ulong),
-        ('ExAttr14', ctypes.c_ulong),
-        ('CreateRoleTime', ctypes.c_char * 30),
-        ('LVEx', ctypes.c_ushort),
-        ('LV2', ctypes.c_ushort),
-        ('ExpPoint', ctypes.c_ulong),
-        ('OperateInfo', ctypes.c_ulong),
-        ('Operate', ctypes.c_char * 15),
-        ('ServerID', ctypes.c_ulong),
-        ('ExAttr15', ctypes.c_ulong),
-        ('ExAttr16', ctypes.c_ulong),
-        ('ExAttr17', ctypes.c_ulong),
-        ('ExAttr18', ctypes.c_ulong),
-        ('ExAttr19', ctypes.c_ulong),
-        ('ExAttr20', ctypes.c_ulong),
-        ('HPEx', ctypes.c_ulong),
-        ('FightPowerEx', ctypes.c_ulong),
-        ('ADOResult', ctypes.c_ulong),
-    ]
-
-    def __init__(self):
-        Structure.__init__(self)
-        self.clear()
-
-
-    def clear(self):
-        memset(addressof(self), 0, self.getLength())
-
-    def readData(self, buf, pos = 0, length = 0):
-        if not pos <= length:
-            return -1
-        if len(buf) < pos + self.getLength():
-            return -1
-        self.clear()
-        self.PlayerID, pos = CommFunc.ReadDWORD(buf, pos)
-        self.AccID, pos = CommFunc.ReadString(buf, pos, 65)
-        self.PlayerName, pos = CommFunc.ReadString(buf, pos, 33)
-        self.AccState, pos = CommFunc.ReadBYTE(buf, pos)
-        self.IsDeleted, pos = CommFunc.ReadBYTE(buf, pos)
-        self.GMLevel, pos = CommFunc.ReadBYTE(buf, pos)
-        self.Sex, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Hair, pos = CommFunc.ReadDWORD(buf, pos)
-        self.HairColor, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Face, pos = CommFunc.ReadDWORD(buf, pos)
-        self.FacePic, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Job, pos = CommFunc.ReadDWORD(buf, pos)
-        self.RoleType, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ReincarnationLv, pos = CommFunc.ReadWORD(buf, pos)
-        self.LV, pos = CommFunc.ReadDWORD(buf, pos)
-        self.TotalExp, pos = CommFunc.ReadDWORD(buf, pos)
-        self.FamilyID, pos = CommFunc.ReadDWORD(buf, pos)
-        self.FamilyName, pos = CommFunc.ReadString(buf, pos, 33)
-        self.Country, pos = CommFunc.ReadDWORD(buf, pos)
-        self.TeamHornor, pos = CommFunc.ReadDWORD(buf, pos)
-        self.FamilyHornor, pos = CommFunc.ReadDWORD(buf, pos)
-        self.FamilyActiveValue, pos = CommFunc.ReadDWORD(buf, pos)
-        self.LastWeekFamilyActiveValue, pos = CommFunc.ReadDWORD(buf, pos)
-        self.CountryHornor, pos = CommFunc.ReadDWORD(buf, pos)
-        self.CountryLastWeekHornor, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Mate, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Gold, pos = CommFunc.ReadDWORD(buf, pos)
-        self.GoldPaper, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Silver, pos = CommFunc.ReadDWORD(buf, pos)
-        self.SilverPaper, pos = CommFunc.ReadDWORD(buf, pos)
-        self.FightPoint, pos = CommFunc.ReadDWORD(buf, pos)
-        self.HappyPoint, pos = CommFunc.ReadDWORD(buf, pos)
-        self.MapID, pos = CommFunc.ReadDWORD(buf, pos)
-        self.DataMapID, pos = CommFunc.ReadDWORD(buf, pos)
-        self.CopyMapID, pos = CommFunc.ReadDWORD(buf, pos)
-        self.PosX, pos = CommFunc.ReadWORD(buf, pos)
-        self.PosY, pos = CommFunc.ReadWORD(buf, pos)
-        self.FromMapID, pos = CommFunc.ReadDWORD(buf, pos)
-        self.FromCopyMapID, pos = CommFunc.ReadDWORD(buf, pos)
-        self.FromPosX, pos = CommFunc.ReadWORD(buf, pos)
-        self.FromPosY, pos = CommFunc.ReadWORD(buf, pos)
-        self.State, pos = CommFunc.ReadDWORD(buf, pos)
-        self.HP, pos = CommFunc.ReadDWORD(buf, pos)
-        self.MP, pos = CommFunc.ReadDWORD(buf, pos)
-        self.XP, pos = CommFunc.ReadDWORD(buf, pos)
-        self.HPRestoreSetting, pos = CommFunc.ReadWORD(buf, pos)
-        self.MPRestoreSetting, pos = CommFunc.ReadWORD(buf, pos)
-        self.FreePoint, pos = CommFunc.ReadDWORD(buf, pos)
-        self.FreeSkillPoint, pos = CommFunc.ReadDWORD(buf, pos)
-        self.STR, pos = CommFunc.ReadDWORD(buf, pos)
-        self.PNE, pos = CommFunc.ReadDWORD(buf, pos)
-        self.PHY, pos = CommFunc.ReadDWORD(buf, pos)
-        self.CON, pos = CommFunc.ReadDWORD(buf, pos)
-        self.TotalSTR, pos = CommFunc.ReadDWORD(buf, pos)
-        self.TotalPNE, pos = CommFunc.ReadDWORD(buf, pos)
-        self.TotalPHY, pos = CommFunc.ReadDWORD(buf, pos)
-        self.TotalCON, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Setting, pos = CommFunc.ReadString(buf, pos, 100)
-        self.PKValue, pos = CommFunc.ReadWORD(buf, pos)
-        self.FightPower, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ActiveValue, pos = CommFunc.ReadWORD(buf, pos)
-        self.PlayerType, pos = CommFunc.ReadBYTE(buf, pos)
-        self.BackpackLV, pos = CommFunc.ReadBYTE(buf, pos)
-        self.WarehouseLV, pos = CommFunc.ReadBYTE(buf, pos)
-        self.HaveWarehousePsw, pos = CommFunc.ReadBYTE(buf, pos)
-        self.WarehousePsw, pos = CommFunc.ReadString(buf, pos, 15)
-        self.WarehouseLocked, pos = CommFunc.ReadBYTE(buf, pos)
-        self.WarehouseGold, pos = CommFunc.ReadDWORD(buf, pos)
-        self.WarehouseSilver, pos = CommFunc.ReadDWORD(buf, pos)
-        self.TeamID, pos = CommFunc.ReadDWORD(buf, pos)
-        self.UseGoldType, pos = CommFunc.ReadBYTE(buf, pos)
-        self.UseSilverType, pos = CommFunc.ReadBYTE(buf, pos)
-        self.AttackMode, pos = CommFunc.ReadBYTE(buf, pos)
-        self.RebornMapID, pos = CommFunc.ReadWORD(buf, pos)
-        self.RebornPosX, pos = CommFunc.ReadWORD(buf, pos)
-        self.RebornPosY, pos = CommFunc.ReadWORD(buf, pos)
-        self.WeekOnlineTime, pos = CommFunc.ReadDWORD(buf, pos)
-        self.LastWeekOnlineTime, pos = CommFunc.ReadDWORD(buf, pos)
-        self.LogoffTime, pos = CommFunc.ReadString(buf, pos, 30)
-        self.IsHideMask, pos = CommFunc.ReadBYTE(buf, pos)
-        self.DayProcessGameEventCount, pos = CommFunc.ReadDWORD(buf, pos)
-        self.LoginIP, pos = CommFunc.ReadString(buf, pos, 20)
-        self.LoginTime, pos = CommFunc.ReadString(buf, pos, 30)
-        self.OnlineTime, pos = CommFunc.ReadDWORD(buf, pos)
-        self.FriendFavor, pos = CommFunc.ReadDWORD(buf, pos)
-        self.TeamPrivity, pos = CommFunc.ReadDWORD(buf, pos)
-        self.OfflineMinutes, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Energy, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ReceivedSalary, pos = CommFunc.ReadDWORD(buf, pos)
-        self.EquipShowSwitch, pos = CommFunc.ReadDWORD(buf, pos)
-        self.LuckValue, pos = CommFunc.ReadWORD(buf, pos)
-        self.ExAttr1, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr2, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr3, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr4, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr5, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Faction, pos = CommFunc.ReadDWORD(buf, pos)
-        self.InfamyValue, pos = CommFunc.ReadDWORD(buf, pos)
-        self.OfficialRank, pos = CommFunc.ReadBYTE(buf, pos)
-        self.IsFindByLabel, pos = CommFunc.ReadBYTE(buf, pos)
-        self.IsCloseFriendLabel, pos = CommFunc.ReadBYTE(buf, pos)
-        self.ChangeCoinPointTotal, pos = CommFunc.ReadDWORD(buf, pos)
-        self.VIPLv, pos = CommFunc.ReadBYTE(buf, pos)
-        self.VIPLvForPhone, pos = CommFunc.ReadBYTE(buf, pos)
-        self.PhoneVIPStartTime, pos = CommFunc.ReadDouble(buf, pos)
-        self.PhoneVIPEndTime, pos = CommFunc.ReadDouble(buf, pos)
-        self.VsRoomId, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr6, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr7, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr8, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr9, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr10, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ModelMark, pos = CommFunc.ReadDWORD(buf, pos)
-        self.FromDataMapID, pos = CommFunc.ReadDWORD(buf, pos)
-        self.LastOrderId, pos = CommFunc.ReadString(buf, pos, 40)
-        self.PrizeCoin, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr11, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr12, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr13, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr14, pos = CommFunc.ReadDWORD(buf, pos)
-        self.CreateRoleTime, pos = CommFunc.ReadString(buf, pos, 30)
-        self.LVEx, pos = CommFunc.ReadWORD(buf, pos)
-        self.LV2, pos = CommFunc.ReadWORD(buf, pos)
-        self.ExpPoint, pos = CommFunc.ReadDWORD(buf, pos)
-        self.OperateInfo, pos = CommFunc.ReadDWORD(buf, pos)
-        self.Operate, pos = CommFunc.ReadString(buf, pos, 15)
-        self.ServerID, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr15, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr16, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr17, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr18, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr19, pos = CommFunc.ReadDWORD(buf, pos)
-        self.ExAttr20, pos = CommFunc.ReadDWORD(buf, pos)
-        self.HPEx, pos = CommFunc.ReadDWORD(buf, pos)
-        self.FightPowerEx, pos = CommFunc.ReadDWORD(buf, pos)
-        return self.getLength()
-
-
-    def getBuffer(self):
-        buf = create_string_buffer(self.getLength())
-        memmove(addressof(buf), addressof(self), self.getLength())
-        return string_at(addressof(buf), self.getLength())
-
-    def getLength(self):
-        return sizeof(tagDBPlayer)
-
-    def outputString(self):
-        output = '''//玩家详细信息#tagDBPlayer:
-            PlayerID = %s,
-            AccID = %s,
-            PlayerName = %s,
-            AccState = %s,
-            IsDeleted = %s,
-            GMLevel = %s,
-            Sex = %s,
-            Hair = %s,
-            HairColor = %s,
-            Face = %s,
-            FacePic = %s,
-            Job = %s,
-            RoleType = %s,
-            ReincarnationLv = %s,
-            LV = %s,
-            TotalExp = %s,
-            FamilyID = %s,
-            FamilyName = %s,
-            Country = %s,
-            TeamHornor = %s,
-            FamilyHornor = %s,
-            FamilyActiveValue = %s,
-            LastWeekFamilyActiveValue = %s,
-            CountryHornor = %s,
-            CountryLastWeekHornor = %s,
-            Mate = %s,
-            Gold = %s,
-            GoldPaper = %s,
-            Silver = %s,
-            SilverPaper = %s,
-            FightPoint = %s,
-            HappyPoint = %s,
-            MapID = %s,
-            DataMapID = %s,
-            CopyMapID = %s,
-            PosX = %s,
-            PosY = %s,
-            FromMapID = %s,
-            FromCopyMapID = %s,
-            FromPosX = %s,
-            FromPosY = %s,
-            State = %s,
-            HP = %s,
-            MP = %s,
-            XP = %s,
-            HPRestoreSetting = %s,
-            MPRestoreSetting = %s,
-            FreePoint = %s,
-            FreeSkillPoint = %s,
-            STR = %s,
-            PNE = %s,
-            PHY = %s,
-            CON = %s,
-            TotalSTR = %s,
-            TotalPNE = %s,
-            TotalPHY = %s,
-            TotalCON = %s,
-            Setting = %s,
-            PKValue = %s,
-            FightPower = %s,
-            ActiveValue = %s,
-            PlayerType = %s,
-            BackpackLV = %s,
-            WarehouseLV = %s,
-            HaveWarehousePsw = %s,
-            WarehousePsw = %s,
-            WarehouseLocked = %s,
-            WarehouseGold = %s,
-            WarehouseSilver = %s,
-            TeamID = %s,
-            UseGoldType = %s,
-            UseSilverType = %s,
-            AttackMode = %s,
-            RebornMapID = %s,
-            RebornPosX = %s,
-            RebornPosY = %s,
-            WeekOnlineTime = %s,
-            LastWeekOnlineTime = %s,
-            LogoffTime = %s,
-            IsHideMask = %s,
-            DayProcessGameEventCount = %s,
-            LoginIP = %s,
-            LoginTime = %s,
-            OnlineTime = %s,
-            FriendFavor = %s,
-            TeamPrivity = %s,
-            OfflineMinutes = %s,
-            Energy = %s,
-            ReceivedSalary = %s,
-            EquipShowSwitch = %s,
-            LuckValue = %s,
-            ExAttr1 = %s,
-            ExAttr2 = %s,
-            ExAttr3 = %s,
-            ExAttr4 = %s,
-            ExAttr5 = %s,
-            Faction = %s,
-            InfamyValue = %s,
-            OfficialRank = %s,
-            IsFindByLabel = %s,
-            IsCloseFriendLabel = %s,
-            ChangeCoinPointTotal = %s,
-            VIPLv = %s,
-            VIPLvForPhone = %s,
-            PhoneVIPStartTime = %s,
-            PhoneVIPEndTime = %s,
-            VsRoomId = %s,
-            ExAttr6 = %s,
-            ExAttr7 = %s,
-            ExAttr8 = %s,
-            ExAttr9 = %s,
-            ExAttr10 = %s,
-            ModelMark = %s,
-            FromDataMapID = %s,
-            LastOrderId = %s,
-            PrizeCoin = %s,
-            ExAttr11 = %s,
-            ExAttr12 = %s,
-            ExAttr13 = %s,
-            ExAttr14 = %s,
-            CreateRoleTime = %s,
-            LVEx = %s,
-            LV2 = %s,
-            ExpPoint = %s,
-            OperateInfo = %s,
-            Operate = %s,
-            ServerID = %s,
-            ExAttr15 = %s,
-            ExAttr16 = %s,
-            ExAttr17 = %s,
-            ExAttr18 = %s,
-            ExAttr19 = %s,
-            ExAttr20 = %s,
-            HPEx = %s,
-            FightPowerEx = %s,
-            ADOResult = %s,
-            '''%(
-                self.PlayerID,
-                self.AccID,
-                self.PlayerName,
-                self.AccState,
-                self.IsDeleted,
-                self.GMLevel,
-                self.Sex,
-                self.Hair,
-                self.HairColor,
-                self.Face,
-                self.FacePic,
-                self.Job,
-                self.RoleType,
-                self.ReincarnationLv,
-                self.LV,
-                self.TotalExp,
-                self.FamilyID,
-                self.FamilyName,
-                self.Country,
-                self.TeamHornor,
-                self.FamilyHornor,
-                self.FamilyActiveValue,
-                self.LastWeekFamilyActiveValue,
-                self.CountryHornor,
-                self.CountryLastWeekHornor,
-                self.Mate,
-                self.Gold,
-                self.GoldPaper,
-                self.Silver,
-                self.SilverPaper,
-                self.FightPoint,
-                self.HappyPoint,
-                self.MapID,
-                self.DataMapID,
-                self.CopyMapID,
-                self.PosX,
-                self.PosY,
-                self.FromMapID,
-                self.FromCopyMapID,
-                self.FromPosX,
-                self.FromPosY,
-                self.State,
-                self.HP,
-                self.MP,
-                self.XP,
-                self.HPRestoreSetting,
-                self.MPRestoreSetting,
-                self.FreePoint,
-                self.FreeSkillPoint,
-                self.STR,
-                self.PNE,
-                self.PHY,
-                self.CON,
-                self.TotalSTR,
-                self.TotalPNE,
-                self.TotalPHY,
-                self.TotalCON,
-                self.Setting,
-                self.PKValue,
-                self.FightPower,
-                self.ActiveValue,
-                self.PlayerType,
-                self.BackpackLV,
-                self.WarehouseLV,
-                self.HaveWarehousePsw,
-                self.WarehousePsw,
-                self.WarehouseLocked,
-                self.WarehouseGold,
-                self.WarehouseSilver,
-                self.TeamID,
-                self.UseGoldType,
-                self.UseSilverType,
-                self.AttackMode,
-                self.RebornMapID,
-                self.RebornPosX,
-                self.RebornPosY,
-                self.WeekOnlineTime,
-                self.LastWeekOnlineTime,
-                self.LogoffTime,
-                self.IsHideMask,
-                self.DayProcessGameEventCount,
-                self.LoginIP,
-                self.LoginTime,
-                self.OnlineTime,
-                self.FriendFavor,
-                self.TeamPrivity,
-                self.OfflineMinutes,
-                self.Energy,
-                self.ReceivedSalary,
-                self.EquipShowSwitch,
-                self.LuckValue,
-                self.ExAttr1,
-                self.ExAttr2,
-                self.ExAttr3,
-                self.ExAttr4,
-                self.ExAttr5,
-                self.Faction,
-                self.InfamyValue,
-                self.OfficialRank,
-                self.IsFindByLabel,
-                self.IsCloseFriendLabel,
-                self.ChangeCoinPointTotal,
-                self.VIPLv,
-                self.VIPLvForPhone,
-                self.PhoneVIPStartTime,
-                self.PhoneVIPEndTime,
-                self.VsRoomId,
-                self.ExAttr6,
-                self.ExAttr7,
-                self.ExAttr8,
-                self.ExAttr9,
-                self.ExAttr10,
-                self.ModelMark,
-                self.FromDataMapID,
-                self.LastOrderId,
-                self.PrizeCoin,
-                self.ExAttr11,
-                self.ExAttr12,
-                self.ExAttr13,
-                self.ExAttr14,
-                self.CreateRoleTime,
-                self.LVEx,
-                self.LV2,
-                self.ExpPoint,
-                self.OperateInfo,
-                self.Operate,
-                self.ServerID,
-                self.ExAttr15,
-                self.ExAttr16,
-                self.ExAttr17,
-                self.ExAttr18,
-                self.ExAttr19,
-                self.ExAttr20,
-                self.HPEx,
-                self.FightPowerEx,
-                self.ADOResult,
-            )
-        return output
-
-    #Char数组类型Set接口,使用该接口对此类型数据赋值,防止赋值的数据过长报错
-    def SetAccID(self,Str):
-        if len(Str)<=65:
-            self.AccID = Str
-        else:
-            self.AccID = Str[:65]
-            
-    def SetPlayerName(self,Str):
-        if len(Str)<=33:
-            self.PlayerName = Str
-        else:
-            self.PlayerName = Str[:33]
-            
-    def SetFamilyName(self,Str):
-        if len(Str)<=33:
-            self.FamilyName = Str
-        else:
-            self.FamilyName = Str[:33]
-            
-    def SetSetting(self,Str):
-        if len(Str)<=100:
-            self.Setting = Str
-        else:
-            self.Setting = Str[:100]
-            
-    def SetWarehousePsw(self,Str):
-        if len(Str)<=15:
-            self.WarehousePsw = Str
-        else:
-            self.WarehousePsw = Str[:15]
-            
-    def SetLogoffTime(self,Str):
-        if len(Str)<=30:
-            self.LogoffTime = Str
-        else:
-            self.LogoffTime = Str[:30]
-            
-    def SetLoginIP(self,Str):
-        if len(Str)<=20:
-            self.LoginIP = Str
-        else:
-            self.LoginIP = Str[:20]
-            
-    def SetLoginTime(self,Str):
-        if len(Str)<=30:
-            self.LoginTime = Str
-        else:
-            self.LoginTime = Str[:30]
-            
-    def SetLastOrderId(self,Str):
-        if len(Str)<=40:
-            self.LastOrderId = Str
-        else:
-            self.LastOrderId = Str[:40]
-            
-    def SetCreateRoleTime(self,Str):
-        if len(Str)<=30:
-            self.CreateRoleTime = Str
-        else:
-            self.CreateRoleTime = Str[:30]
-            
-    def SetOperate(self,Str):
-        if len(Str)<=15:
-            self.Operate = Str
-        else:
-            self.Operate = Str[:15]
-            
-            
\ No newline at end of file
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index 12d464c..c6b2c9a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -38,6 +38,14 @@
 #支持超20亿数值的数值点单位数值, 1亿
 Def_PerPointValue = 100000000
 
+#假玩家ID
+FackPlayerIDStart = 1
+FackPlayerIDMax = 9999
+
+#假仙盟ID
+FackFamilyIDStart = 1
+FackFamilyIDMax = 9999
+
 #---刀剑笑, 特殊事件枚举---
 (
 TYPE_Event_MakeItem,                        #///<= 1,  开始打造
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/ServerScript.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/ServerScript.ini
index 35cf95a..55716ea 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/ServerScript.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/ServerScript.ini
@@ -115,20 +115,6 @@
 PacketSubCMD_11=0x5
 PacketCallFunc_11=GameServer_PlayerCoinToGold
 
-[PlayerFamily]
-ScriptName = Player\PlayerFamily.py
-Writer = eggxp
-Releaser = eggxp
-RegType = 0
-RegisterPackCount = 2
-PacketCMD_1=0x5
-PacketSubCMD_1=0x1
-PacketCallFunc_1=GameServer_FamilyRefresh
-
-PacketCMD_2=0x8
-PacketSubCMD_2=0x4
-PacketCallFunc_2=GameServer_RequestFamilyWar
-
 [PlayerFriend]
 ScriptName = Player\PlayerFriend.py
 Writer = eggxp

--
Gitblit v1.8.0