From ba0a86e24c17b4f9a0ada323f7ebc3b32fb0b169 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期五, 14 五月 2021 10:30:22 +0800
Subject: [PATCH] 8921 【主干】【BT2】【后端】H.活动-节日活动-垃圾分类

---
 ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py                                              |   41 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearPack.py                 |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py                           |  319 ++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                       |  503 ++++++++++
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py                                                |  319 ++++++
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py                                            |  503 ++++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/MapServerConfig.ini                             |   75 +
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActGarbageSorting.py                             |   62 +
 ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py                                                  |   18 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                         |   99 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py                       |    7 
 PySysDB/PySysDBPY.h                                                                                          |   37 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py                  |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipWash.py      |    2 
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py                      |    7 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipPlus.py      |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerRefineStove.py              |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBHelpBattle.py |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py             |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActGarbageSorting.py        |  858 +++++++++++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini                                   |   28 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/QuestCommon.py            |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py             |    4 
 PySysDB/PySysDBG.h                                                                                           |   15 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                              |   31 
 25 files changed, 2,942 insertions(+), 1 deletions(-)

diff --git a/PySysDB/PySysDBG.h b/PySysDB/PySysDBG.h
index 66bb70d..62192a0 100644
--- a/PySysDB/PySysDBG.h
+++ b/PySysDB/PySysDBG.h
@@ -467,6 +467,21 @@
 	list		NotifyInfoLoop;	//全服提示信息 - 循环广播[间隔分钟, 广播key]
 };
 
+//垃圾分类活动时间表
+
+struct tagActGarbageSorting
+{
+	DWORD		_CfgID;	//配置ID
+	list		PlatformList;	//活动平台列表["平台A", "平台A", ...],配[]代表所有
+	list		ServerGroupIDList;	//服务器ID列表
+	BYTE		ActNum;	//活动分组编号, 活动类型 * 10 + 不同界面编号
+	char		StartDate;	//开启日期
+	char		EndDate;	//结束日期
+	dict		NotifyInfoStart;	//全服提示信息 - 相对开始时间
+	dict		NotifyInfoEnd;	//全服提示信息 - 相对结束时间
+	list		NotifyInfoLoop;	//全服提示信息 - 循环广播[间隔分钟, 广播key]
+};
+
 //骑宠盛宴活动
 
 struct tagActHorsePetFeast
diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 5229c44..c0be2ce 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -1432,6 +1432,43 @@
 	BYTE		NeedNotify;		//是否需要广播
 };
 
+//垃圾分类活动时间表
+
+struct tagActGarbageSorting
+{
+	DWORD		_CfgID;	//配置ID
+	char		StartDate;	//开启日期
+	char		EndDate;	//结束日期
+	WORD		LVLimit;	//限制等级
+	BYTE		CTGTypeEffValue;	//充值有效类型值
+	BYTE		TemplateID;	//模板ID
+};
+
+//垃圾分类任务产出表
+
+struct tagActGarbageTask
+{
+	DWORD		_GarbageTasklD;	//垃圾任务ID
+	DWORD		FinishNeedValue;	//完成所需进度值
+	DWORD		FinishTimeMax;	//总可完成次数,0不限
+	BYTE		AutoProduce;		//自动产生垃圾
+	list		ProduceGarbageRateList;	//随机产生垃圾概率饼图
+};
+
+//垃圾分类环保奖池表
+
+struct tagActGarbageAward
+{
+	DWORD		_TemplateID;	//奖池模板编号
+	BYTE		AwardLibType;	//奖励库类型
+	BYTE		AwardItemCount;	//选择个数
+	BYTE		UnlockAwardLimitTimes;	//抽X次后可产出(本层)
+	BYTE		AwardLibWeight;	//产出该库外权重
+	dict		LibItemInfo;	//本库物品随机库内权重(先随机库外权重,若产出再随机库内权重)
+	dict		ItemLayerLimitInfo;	//物品产出奖池层限制 {物品ID:大于等于X层可产出, ...}
+	dict		ItemAwardTimesTotalInfo;	//物品产出次数限制(所有层){物品ID:总产出次数, ...}
+};
+
 //骑宠盛宴活动
 
 struct tagActHorsePetFeast
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
index 7820c45..0a29534 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
@@ -13321,6 +13321,273 @@
 
 
 #------------------------------------------------------
+# AA 16 垃圾分类活动选择大奖 #tagCMActGarbageChooseSuperItem
+
+class  tagCMActGarbageChooseSuperItem(Structure):
+    Head = tagHead()
+    ActNum = 0    #(BYTE ActNum)//活动编号
+    SuperItemCount = 0    #(BYTE SuperItemCount)//选择物品数量
+    SuperItemIDList = list()    #(vector<DWORD> SuperItemIDList)//选择的大奖库物品ID列表,每次重新选择需要发送全部已选择的大奖物品ID,不能只发单个物品ID;
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x16
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ActNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.SuperItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.SuperItemCount):
+            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+            self.SuperItemIDList.append(value)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x16
+        self.ActNum = 0
+        self.SuperItemCount = 0
+        self.SuperItemIDList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 1
+        length += 4 * self.SuperItemCount
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.ActNum)
+        data = CommFunc.WriteBYTE(data, self.SuperItemCount)
+        for i in range(self.SuperItemCount):
+            data = CommFunc.WriteDWORD(data, self.SuperItemIDList[i])
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ActNum:%d,
+                                SuperItemCount:%d,
+                                SuperItemIDList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ActNum,
+                                self.SuperItemCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagCMActGarbageChooseSuperItem=tagCMActGarbageChooseSuperItem()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActGarbageChooseSuperItem.Head.Cmd,m_NAtagCMActGarbageChooseSuperItem.Head.SubCmd))] = m_NAtagCMActGarbageChooseSuperItem
+
+
+#------------------------------------------------------
+# AA 15 垃圾分类活动收集已完成的任务垃圾 #tagCMActGarbageGetTaskAward
+
+class  tagCMActGarbageGetTaskAward(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ActNum", c_ubyte),    #活动编号
+                  ("GarbageTaskID", c_ubyte),    #垃圾任务ID
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xAA
+        self.SubCmd = 0x15
+        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 = 0xAA
+        self.SubCmd = 0x15
+        self.ActNum = 0
+        self.GarbageTaskID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMActGarbageGetTaskAward)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 15 垃圾分类活动收集已完成的任务垃圾 //tagCMActGarbageGetTaskAward:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ActNum:%d,
+                                GarbageTaskID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ActNum,
+                                self.GarbageTaskID
+                                )
+        return DumpString
+
+
+m_NAtagCMActGarbageGetTaskAward=tagCMActGarbageGetTaskAward()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActGarbageGetTaskAward.Cmd,m_NAtagCMActGarbageGetTaskAward.SubCmd))] = m_NAtagCMActGarbageGetTaskAward
+
+
+#------------------------------------------------------
+# AA 17 垃圾分类活动抽奖 #tagCMActGarbageLottery
+
+class  tagCMActGarbageLottery(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ActNum", c_ubyte),    #活动编号
+                  ("PosNum", c_ubyte),    #玩家点击的奖励位置编号,从1开始
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xAA
+        self.SubCmd = 0x17
+        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 = 0xAA
+        self.SubCmd = 0x17
+        self.ActNum = 0
+        self.PosNum = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMActGarbageLottery)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 17 垃圾分类活动抽奖 //tagCMActGarbageLottery:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ActNum:%d,
+                                PosNum:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ActNum,
+                                self.PosNum
+                                )
+        return DumpString
+
+
+m_NAtagCMActGarbageLottery=tagCMActGarbageLottery()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActGarbageLottery.Cmd,m_NAtagCMActGarbageLottery.SubCmd))] = m_NAtagCMActGarbageLottery
+
+
+#------------------------------------------------------
+# AA 14 垃圾分类活动分类垃圾 #tagCMActGarbageSorting
+
+class  tagCMActGarbageSorting(Structure):
+    Head = tagHead()
+    ActNum = 0    #(BYTE ActNum)//活动编号
+    GarbageSortingType = 0    #(BYTE GarbageSortingType)//垃圾分类类型,即属于哪种垃圾
+    ItemIndexCount = 0    #(BYTE ItemIndexCount)//垃圾背包中的物品索引数
+    ItemIndexList = list()    #(vector<BYTE> ItemIndexList)//垃圾背包中的物品索引列表
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x14
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ActNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.GarbageSortingType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.ItemIndexCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.ItemIndexCount):
+            value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
+            self.ItemIndexList.append(value)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x14
+        self.ActNum = 0
+        self.GarbageSortingType = 0
+        self.ItemIndexCount = 0
+        self.ItemIndexList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 1
+        length += 1
+        length += 1 * self.ItemIndexCount
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.ActNum)
+        data = CommFunc.WriteBYTE(data, self.GarbageSortingType)
+        data = CommFunc.WriteBYTE(data, self.ItemIndexCount)
+        for i in range(self.ItemIndexCount):
+            data = CommFunc.WriteBYTE(data, self.ItemIndexList[i])
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ActNum:%d,
+                                GarbageSortingType:%d,
+                                ItemIndexCount:%d,
+                                ItemIndexList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ActNum,
+                                self.GarbageSortingType,
+                                self.ItemIndexCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagCMActGarbageSorting=tagCMActGarbageSorting()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActGarbageSorting.Head.Cmd,m_NAtagCMActGarbageSorting.Head.SubCmd))] = m_NAtagCMActGarbageSorting
+
+
+#------------------------------------------------------
 # AA 12 选择转盘活动物品 #tagCMActTurntableChooseItem
 
 class  tagCMActTurntableChooseItem(Structure):
@@ -13748,6 +14015,58 @@
 
 
 #------------------------------------------------------
+# AA 18 垃圾分类活动奖池刷新 #tagCMGarbageAwardPoolRefresh
+
+class  tagCMGarbageAwardPoolRefresh(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ActNum", c_ubyte),    #活动编号
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xAA
+        self.SubCmd = 0x18
+        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 = 0xAA
+        self.SubCmd = 0x18
+        self.ActNum = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMGarbageAwardPoolRefresh)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 18 垃圾分类活动奖池刷新 //tagCMGarbageAwardPoolRefresh:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ActNum:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ActNum
+                                )
+        return DumpString
+
+
+m_NAtagCMGarbageAwardPoolRefresh=tagCMGarbageAwardPoolRefresh()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMGarbageAwardPoolRefresh.Cmd,m_NAtagCMGarbageAwardPoolRefresh.SubCmd))] = m_NAtagCMGarbageAwardPoolRefresh
+
+
+#------------------------------------------------------
 #AA 01 领取累计登陆礼 # tagCMGetTotalLoginDayAward
 
 class  tagCMGetTotalLoginDayAward(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
index 7a550fd..219c323 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -24638,6 +24638,509 @@
 
 
 #------------------------------------------------------
+# AA 57 垃圾收集活动玩家信息 #tagMCActGarbagePlayerInfo
+
+class  tagMCActGarbageAwardItemResult(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("ItemLibType", c_ubyte),    #物品库类型;9-固定为大奖库,非9-策划自定义库
+                  ("ItemID", c_int),    # 注意: 不同库物品ID可能相同,但个数不同
+                  ("ItemCount", c_ushort),    
+                  ("PosNum", c_ubyte),    # 被抽中时的位置编号,1~99,前端自定义展示位置编号,0代表未被抽中;
+                  ("TotalTimesNow", c_ubyte),    #当前已产出次数,不限制次数时不记录,即同样为0
+                  ]
+
+    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.ItemLibType = 0
+        self.ItemID = 0
+        self.ItemCount = 0
+        self.PosNum = 0
+        self.TotalTimesNow = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCActGarbageAwardItemResult)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 57 垃圾收集活动玩家信息 //tagMCActGarbagePlayerInfo:
+                                ItemLibType:%d,
+                                ItemID:%d,
+                                ItemCount:%d,
+                                PosNum:%d,
+                                TotalTimesNow:%d
+                                '''\
+                                %(
+                                self.ItemLibType,
+                                self.ItemID,
+                                self.ItemCount,
+                                self.PosNum,
+                                self.TotalTimesNow
+                                )
+        return DumpString
+
+
+class  tagMCActGarbagePlayerInfo(Structure):
+    Head = tagHead()
+    ActNum = 0    #(BYTE ActNum)//活动编号
+    GuideTaskFinish = 0    #(BYTE GuideTaskFinish)//引导任务是否已完成,有需要NPC对话引导任务时,则需要先完成才显示活动界面
+    EnvironmentValue = 0    #(DWORD EnvironmentValue)//当前可用环保值
+    EnvironmentValueHis = 0    #(DWORD EnvironmentValueHis)//历史环保值
+    AwardItemResult=tagMCActGarbageAwardItemResult()    #(tagMCActGarbageAwardItemResult AwardItemResult)//本次抽奖结果物品信息,可能为空
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x57
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ActNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.GuideTaskFinish,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.EnvironmentValue,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.EnvironmentValueHis,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        _pos = self.AwardItemResult.ReadData(_lpData,_pos)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x57
+        self.ActNum = 0
+        self.GuideTaskFinish = 0
+        self.EnvironmentValue = 0
+        self.EnvironmentValueHis = 0
+        self.AwardItemResult=tagMCActGarbageAwardItemResult()
+        self.AwardItemResult.Clear()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 1
+        length += 4
+        length += 4
+        length += self.AwardItemResult.GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.ActNum)
+        data = CommFunc.WriteBYTE(data, self.GuideTaskFinish)
+        data = CommFunc.WriteDWORD(data, self.EnvironmentValue)
+        data = CommFunc.WriteDWORD(data, self.EnvironmentValueHis)
+        data = CommFunc.WriteString(data,self.AwardItemResult.GetLength(),self.AwardItemResult.GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ActNum:%d,
+                                GuideTaskFinish:%d,
+                                EnvironmentValue:%d,
+                                EnvironmentValueHis:%d,
+                                AwardItemResult:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ActNum,
+                                self.GuideTaskFinish,
+                                self.EnvironmentValue,
+                                self.EnvironmentValueHis,
+                                self.AwardItemResult.OutputString()
+                                )
+        return DumpString
+
+
+m_NAtagMCActGarbagePlayerInfo=tagMCActGarbagePlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActGarbagePlayerInfo.Head.Cmd,m_NAtagMCActGarbagePlayerInfo.Head.SubCmd))] = m_NAtagMCActGarbagePlayerInfo
+
+
+#------------------------------------------------------
+# AA 55 垃圾收集活动信息 #tagMCActGarbageSortingInfo
+
+class  tagMCActGarbageAwardItem(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("ItemLibType", c_ubyte),    #物品库类型;9-固定为大奖库,非9-策划自定义库
+                  ("ItemID", c_int),    # 注意: 不同库物品ID可能相同,但个数不同
+                  ("ItemCount", c_ushort),    
+                  ("PosNum", c_ubyte),    # 被抽中时的位置编号,1~99,前端自定义展示位置编号,0代表未被抽中;
+                  ("TotalTimesNow", c_ubyte),    #当前已产出次数,不限制次数时不记录,即同样为0
+                  ("TotalTimesMax", c_ubyte),    #最大可产出次数,0不限
+                  ("LayerLimit", c_ubyte),    #大于等于X层后可产出,0不限
+                  ]
+
+    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.ItemLibType = 0
+        self.ItemID = 0
+        self.ItemCount = 0
+        self.PosNum = 0
+        self.TotalTimesNow = 0
+        self.TotalTimesMax = 0
+        self.LayerLimit = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCActGarbageAwardItem)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 55 垃圾收集活动信息 //tagMCActGarbageSortingInfo:
+                                ItemLibType:%d,
+                                ItemID:%d,
+                                ItemCount:%d,
+                                PosNum:%d,
+                                TotalTimesNow:%d,
+                                TotalTimesMax:%d,
+                                LayerLimit:%d
+                                '''\
+                                %(
+                                self.ItemLibType,
+                                self.ItemID,
+                                self.ItemCount,
+                                self.PosNum,
+                                self.TotalTimesNow,
+                                self.TotalTimesMax,
+                                self.LayerLimit
+                                )
+        return DumpString
+
+
+class  tagMCActGarbageSortingInfo(Structure):
+    Head = tagHead()
+    ActNum = 0    #(BYTE ActNum)// 活动编号
+    StartDate = ""    #(char StartDate[10])// 开始日期 y-m-d
+    EndtDate = ""    #(char EndtDate[10])// 结束日期 y-m-d
+    LimitLV = 0    #(WORD LimitLV)// 限制等级
+    LayerNum = 0    #(BYTE LayerNum)//当前奖池第几层
+    AwardItemCount = 0    #(BYTE AwardItemCount)
+    AwardItemList = list()    #(vector<tagMCActGarbageAwardItem> AwardItemList)// 奖池物品列表,已生成的,包含已选择的大奖物品
+    SuperItemCount = 0    #(BYTE SuperItemCount)
+    SuperItemList = list()    #(vector<tagMCActGarbageAwardItem> SuperItemList)// 大奖物品待选择库,由玩家从库中选择放入奖池的物品;
+    SuperItemCanChooseCount = 0    #(BYTE SuperItemCanChooseCount)// 大奖物品可选择个数
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x55
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ActNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.StartDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+        self.EndtDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+        self.LimitLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.LayerNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.AwardItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.AwardItemCount):
+            temAwardItemList = tagMCActGarbageAwardItem()
+            _pos = temAwardItemList.ReadData(_lpData, _pos)
+            self.AwardItemList.append(temAwardItemList)
+        self.SuperItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.SuperItemCount):
+            temSuperItemList = tagMCActGarbageAwardItem()
+            _pos = temSuperItemList.ReadData(_lpData, _pos)
+            self.SuperItemList.append(temSuperItemList)
+        self.SuperItemCanChooseCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x55
+        self.ActNum = 0
+        self.StartDate = ""
+        self.EndtDate = ""
+        self.LimitLV = 0
+        self.LayerNum = 0
+        self.AwardItemCount = 0
+        self.AwardItemList = list()
+        self.SuperItemCount = 0
+        self.SuperItemList = list()
+        self.SuperItemCanChooseCount = 0
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 10
+        length += 10
+        length += 2
+        length += 1
+        length += 1
+        for i in range(self.AwardItemCount):
+            length += self.AwardItemList[i].GetLength()
+        length += 1
+        for i in range(self.SuperItemCount):
+            length += self.SuperItemList[i].GetLength()
+        length += 1
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.ActNum)
+        data = CommFunc.WriteString(data, 10, self.StartDate)
+        data = CommFunc.WriteString(data, 10, self.EndtDate)
+        data = CommFunc.WriteWORD(data, self.LimitLV)
+        data = CommFunc.WriteBYTE(data, self.LayerNum)
+        data = CommFunc.WriteBYTE(data, self.AwardItemCount)
+        for i in range(self.AwardItemCount):
+            data = CommFunc.WriteString(data, self.AwardItemList[i].GetLength(), self.AwardItemList[i].GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.SuperItemCount)
+        for i in range(self.SuperItemCount):
+            data = CommFunc.WriteString(data, self.SuperItemList[i].GetLength(), self.SuperItemList[i].GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.SuperItemCanChooseCount)
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ActNum:%d,
+                                StartDate:%s,
+                                EndtDate:%s,
+                                LimitLV:%d,
+                                LayerNum:%d,
+                                AwardItemCount:%d,
+                                AwardItemList:%s,
+                                SuperItemCount:%d,
+                                SuperItemList:%s,
+                                SuperItemCanChooseCount:%d
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ActNum,
+                                self.StartDate,
+                                self.EndtDate,
+                                self.LimitLV,
+                                self.LayerNum,
+                                self.AwardItemCount,
+                                "...",
+                                self.SuperItemCount,
+                                "...",
+                                self.SuperItemCanChooseCount
+                                )
+        return DumpString
+
+
+m_NAtagMCActGarbageSortingInfo=tagMCActGarbageSortingInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActGarbageSortingInfo.Head.Cmd,m_NAtagMCActGarbageSortingInfo.Head.SubCmd))] = m_NAtagMCActGarbageSortingInfo
+
+
+#------------------------------------------------------
+# AA 56 垃圾收集活动任务进度信息 #tagMCActGarbageTaskInfo
+
+class  tagMCActGarbageTaskItem(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("ItemID", c_int),    
+                  ("ItemCount", c_ushort),    
+                  ]
+
+    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.ItemID = 0
+        self.ItemCount = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCActGarbageTaskItem)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 56 垃圾收集活动任务进度信息 //tagMCActGarbageTaskInfo:
+                                ItemID:%d,
+                                ItemCount:%d
+                                '''\
+                                %(
+                                self.ItemID,
+                                self.ItemCount
+                                )
+        return DumpString
+
+
+class  tagMCActGarbageTask(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("GarbageTaskID", c_ubyte),    #垃圾任务ID
+                  ("GarbageTaskValue", c_int),    #当前进度值,一直累加
+                  ("GarbageTaskFinishCount", c_ubyte),    #当前已完成次数; 前端计算未完成次数的进度值=max(0, 当前进度值 - (完成次数 * 单次所需进度))
+                  ]
+
+    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.GarbageTaskID = 0
+        self.GarbageTaskValue = 0
+        self.GarbageTaskFinishCount = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCActGarbageTask)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 56 垃圾收集活动任务进度信息 //tagMCActGarbageTaskInfo:
+                                GarbageTaskID:%d,
+                                GarbageTaskValue:%d,
+                                GarbageTaskFinishCount:%d
+                                '''\
+                                %(
+                                self.GarbageTaskID,
+                                self.GarbageTaskValue,
+                                self.GarbageTaskFinishCount
+                                )
+        return DumpString
+
+
+class  tagMCActGarbageTaskInfo(Structure):
+    Head = tagHead()
+    ActNum = 0    #(BYTE ActNum)// 活动编号
+    GarbageTaskCount = 0    #(BYTE GarbageTaskCount)//任务数
+    GarbageTaskList = list()    #(vector<tagMCActGarbageTask> GarbageTaskList)//任务信息列表
+    TaskItemCount = 0    #(BYTE TaskItemCount)//本次获得的垃圾收集任务奖励物品个数,可能为0
+    GarbageTaskItemList = list()    #(vector<tagMCActGarbageTaskItem> GarbageTaskItemList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x56
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ActNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.GarbageTaskCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.GarbageTaskCount):
+            temGarbageTaskList = tagMCActGarbageTask()
+            _pos = temGarbageTaskList.ReadData(_lpData, _pos)
+            self.GarbageTaskList.append(temGarbageTaskList)
+        self.TaskItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.TaskItemCount):
+            temGarbageTaskItemList = tagMCActGarbageTaskItem()
+            _pos = temGarbageTaskItemList.ReadData(_lpData, _pos)
+            self.GarbageTaskItemList.append(temGarbageTaskItemList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x56
+        self.ActNum = 0
+        self.GarbageTaskCount = 0
+        self.GarbageTaskList = list()
+        self.TaskItemCount = 0
+        self.GarbageTaskItemList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 1
+        for i in range(self.GarbageTaskCount):
+            length += self.GarbageTaskList[i].GetLength()
+        length += 1
+        for i in range(self.TaskItemCount):
+            length += self.GarbageTaskItemList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.ActNum)
+        data = CommFunc.WriteBYTE(data, self.GarbageTaskCount)
+        for i in range(self.GarbageTaskCount):
+            data = CommFunc.WriteString(data, self.GarbageTaskList[i].GetLength(), self.GarbageTaskList[i].GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.TaskItemCount)
+        for i in range(self.TaskItemCount):
+            data = CommFunc.WriteString(data, self.GarbageTaskItemList[i].GetLength(), self.GarbageTaskItemList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ActNum:%d,
+                                GarbageTaskCount:%d,
+                                GarbageTaskList:%s,
+                                TaskItemCount:%d,
+                                GarbageTaskItemList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ActNum,
+                                self.GarbageTaskCount,
+                                "...",
+                                self.TaskItemCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCActGarbageTaskInfo=tagMCActGarbageTaskInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActGarbageTaskInfo.Head.Cmd,m_NAtagMCActGarbageTaskInfo.Head.SubCmd))] = m_NAtagMCActGarbageTaskInfo
+
+
+#------------------------------------------------------
 # AA 31 成长必买活动信息 #tagMCActGrowupBuyInfo
 
 class  tagMCActGrowupBuyCTGItem(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
index d019343..3cc7e7a 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
@@ -988,6 +988,24 @@
     adict.update(bdict)
     return adict
 
+## 根据排行获取名次对应值
+#  @param orderDict {名次:obj, ...} 名次支持段跳跃
+#  @param order 名次,从1开始
+#  @param isDefaultLast 找不到的名次是否默认取最后一名的
+#  @return obj or None
+def GetOrderValueByDict(orderDict, order, isDefaultLast=True):
+    if order in orderDict:
+        return orderDict[order]
+    
+    orderList = sorted(orderDict.keys())
+    if order > 0:
+        for dOrder in orderList:
+            if order <= dOrder:
+                return orderDict[dOrder]
+        
+    # 找不到的默认取最后一名
+    return orderDict[orderList[-1]] if isDefaultLast else None
+
 ##概率相关, 这个事件是否能够出现
 # @param rate 基础几率
 # @param maxRate 最大几率
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
index b2ba2c3..d88f64e 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
@@ -33,6 +33,7 @@
 import PlayerFamilyRedPacket
 import PlayerFairyCeremony
 import PlayerNewFairyCeremony
+import PlayerActGarbageSorting
 import PlayerUniversalGameRec
 import GameWorldAverageLv
 import PlayerFamilyBoss
@@ -838,6 +839,12 @@
                         #限时抢购重置购买次数 本次活动每场不能重复
                         #dayIndex = sendMapServerMsgDict.get(ShareDefine.ActKey_DayIndex, 0)
                         PlayerStore.ResetFlashSaleBuyCnt(ipyData)
+                    elif actName == ShareDefine.OperationActionName_GarbageSorting:
+                        PlayerActGarbageSorting.OnActStart(actNum)
+                else:
+                    if actName == ShareDefine.OperationActionName_GarbageSorting:
+                        PlayerActGarbageSorting.OnActEnd(actNum)
+                        
             else:
                 GameWorld.Log("    dbActID不变: dbActID=%s,curActID=%s" % (dbActID, curActID))
                 
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
index e00284d..45ea84a 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
@@ -395,6 +395,18 @@
                         ("list", "NotifyInfoLoop", 0),
                         ),
 
+                "ActGarbageSorting":(
+                        ("DWORD", "CfgID", 1),
+                        ("list", "PlatformList", 0),
+                        ("list", "ServerGroupIDList", 0),
+                        ("BYTE", "ActNum", 0),
+                        ("char", "StartDate", 0),
+                        ("char", "EndDate", 0),
+                        ("dict", "NotifyInfoStart", 0),
+                        ("dict", "NotifyInfoEnd", 0),
+                        ("list", "NotifyInfoLoop", 0),
+                        ),
+
                 "ActHorsePetFeast":(
                         ("DWORD", "CfgID", 1),
                         ("list", "PlatformList", 0),
@@ -1507,6 +1519,31 @@
     def GetNotifyInfoEnd(self): return self.NotifyInfoEnd # 全服提示信息 - 相对结束时间
     def GetNotifyInfoLoop(self): return self.NotifyInfoLoop # 全服提示信息 - 循环广播[间隔分钟, 广播key]
 
+# 垃圾分类活动时间表
+class IPY_ActGarbageSorting():
+    
+    def __init__(self):
+        self.CfgID = 0
+        self.PlatformList = []
+        self.ServerGroupIDList = []
+        self.ActNum = 0
+        self.StartDate = ""
+        self.EndDate = ""
+        self.NotifyInfoStart = {}
+        self.NotifyInfoEnd = {}
+        self.NotifyInfoLoop = []
+        return
+        
+    def GetCfgID(self): return self.CfgID # 配置ID
+    def GetPlatformList(self): return self.PlatformList # 活动平台列表["平台A", "平台A", ...],配[]代表所有
+    def GetServerGroupIDList(self): return self.ServerGroupIDList # 服务器ID列表
+    def GetActNum(self): return self.ActNum # 活动分组编号, 活动类型 * 10 + 不同界面编号
+    def GetStartDate(self): return self.StartDate # 开启日期
+    def GetEndDate(self): return self.EndDate # 结束日期
+    def GetNotifyInfoStart(self): return self.NotifyInfoStart # 全服提示信息 - 相对开始时间
+    def GetNotifyInfoEnd(self): return self.NotifyInfoEnd # 全服提示信息 - 相对结束时间
+    def GetNotifyInfoLoop(self): return self.NotifyInfoLoop # 全服提示信息 - 循环广播[间隔分钟, 广播key]
+
 # 骑宠盛宴活动
 class IPY_ActHorsePetFeast():
     
@@ -2331,6 +2368,8 @@
         self.ipyActCostRebateLen = len(self.ipyActCostRebateCache)
         self.ipyActCollectWordsCache = self.__LoadFileData("ActCollectWords", IPY_ActCollectWords)
         self.ipyActCollectWordsLen = len(self.ipyActCollectWordsCache)
+        self.ipyActGarbageSortingCache = self.__LoadFileData("ActGarbageSorting", IPY_ActGarbageSorting)
+        self.ipyActGarbageSortingLen = len(self.ipyActGarbageSortingCache)
         self.ipyActHorsePetFeastCache = self.__LoadFileData("ActHorsePetFeast", IPY_ActHorsePetFeast)
         self.ipyActHorsePetFeastLen = len(self.ipyActHorsePetFeastCache)
         self.ipyActBossRebornCache = self.__LoadFileData("ActBossReborn", IPY_ActBossReborn)
@@ -2631,6 +2670,8 @@
     def GetActCostRebateByIndex(self, index): return self.ipyActCostRebateCache[index]
     def GetActCollectWordsCount(self): return self.ipyActCollectWordsLen
     def GetActCollectWordsByIndex(self, index): return self.ipyActCollectWordsCache[index]
+    def GetActGarbageSortingCount(self): return self.ipyActGarbageSortingLen
+    def GetActGarbageSortingByIndex(self, index): return self.ipyActGarbageSortingCache[index]
     def GetActHorsePetFeastCount(self): return self.ipyActHorsePetFeastLen
     def GetActHorsePetFeastByIndex(self, index): return self.ipyActHorsePetFeastCache[index]
     def GetActBossRebornCount(self): return self.ipyActBossRebornLen
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActGarbageSorting.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActGarbageSorting.py
new file mode 100644
index 0000000..f70f387
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActGarbageSorting.py
@@ -0,0 +1,62 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package PlayerActGarbageSorting
+#
+# @todo:垃圾收集
+# @author hxp
+# @date 2021-05-13
+# @version 1.0
+#
+# 详细描述: 垃圾收集
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2021-05-13 19:30"""
+#-------------------------------------------------------------------------------
+import PlayerBillboard
+import ShareDefine
+import GameWorld
+import IpyGameDataPY
+import PlayerCompensation
+
+
+def OnActStart(actNum):
+    ## 活动开启
+    PlayerBillboard.ClearBillboardByIndex(ShareDefine.Def_BT_Environment)
+    return
+
+
+def OnActEnd(actNum):
+    ## 活动结束
+    
+    # 发放排行奖励
+    GameWorld.Log("=== 垃圾分类活动结束!发放环保榜单奖励! === actNum=%s" % actNum)
+    billBoard = GameWorld.GetBillboard().FindBillboard(ShareDefine.Def_BT_Environment)
+    if not billBoard:
+        return
+    
+    orderAwardDict = IpyGameDataPY.GetFuncEvalCfg("GarbageSortingAward", 1, {})
+    
+    for index in xrange(billBoard.GetCount()):
+        billBoardData = billBoard.At(index)
+        if not billBoardData:
+            continue
+        
+        order = index + 1
+        
+        awardItemList = GameWorld.GetOrderValueByDict(orderAwardDict, order, False)
+        if not awardItemList:
+            break
+        
+        playerID = billBoardData.GetID()
+        name2 = billBoardData.GetName2()
+        cmpValue = billBoardData.GetCmpValue()
+        
+        GameWorld.Log("    发放环保榜单奖励: order=%s,playerID=%s,cmpValue=%s,awardItemList=%s, %s" 
+                      % (order, playerID, cmpValue, awardItemList, name2))
+        
+        PlayerCompensation.SendMailByKey("GarbageSortingMail30", [playerID], awardItemList, [order])
+        
+    PlayerBillboard.ClearBillboardByIndex(ShareDefine.Def_BT_Environment)
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/MapServerConfig.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/MapServerConfig.ini
new file mode 100644
index 0000000..62a0bfd
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/MapServerConfig.ini
@@ -0,0 +1,75 @@
+[RolePackConfig]
+;2000///<所有背包总量限制
+;玩家背包配置
+PackTypeCnt=35
+
+;已删除物品rptDeleted//已无用
+PackCnt00=0
+;装备rptEquip//一定要与枚举RoleEquipType的最大值匹配
+PackCnt01=167
+;物品rptItem
+PackCnt02=200
+;垃圾桶(回收站)rptRecycle
+PackCnt03=6
+;拆解物品栏rptBreakItem
+PackCnt04=0
+;仓库rptWarehouse
+PackCnt05=80
+;称号背包rptTitle
+PackCnt06=0
+;合成背包rptCompose
+PackCnt07=0
+;鉴定背包rptIdentify
+PackCnt08=0
+;拆解准备背包rptBreakPrepare
+PackCnt09=0
+;合成结果背包rptResult
+PackCnt10=0
+;封爵背包rptInvestiture
+PackCnt11=0
+;坐骑背包rptHorse
+PackCnt12=0
+;万能背包rptAnyWhere 
+PackCnt13=8
+;法宝背包rptFabao
+PackCnt14=0
+;坐骑装备背包rptHorseEquip
+PackCnt15=0
+;衣服外套背包rptCabinetDressCoat
+PackCnt16= 0
+;武器外套背包rptCabinetWeaponCoat
+PackCnt17=0
+;时装坐骑背包rptCabinetHorse
+PackCnt18=0
+;宝石合成背包rptJewelMerge
+PackCnt19=0 
+;宝石合成结果背包rptJewelMergeResult
+PackCnt20=0 
+;精魄槽rptFineSoulSlot
+PackCnt21=0
+;宠物装备1rptPetEquip1
+PackCnt22=0
+;宠物装备2rptPetEquip2
+PackCnt23=0
+;宠物装备3rptPetEquip3
+PackCnt24=0
+;宠物装备4rptPetEquip4
+PackCnt25=0
+;宠物装备5rptPetEquip5
+PackCnt26=0
+;收集系统,宠物收纳柜背包rptPetCabinetPet
+PackCnt27=0
+;临时交换背包
+PackCnt28=1
+;临时存放背包
+PackCnt29=10
+;寻宝背包	
+PackCnt30=100
+;宠物背包
+PackCnt31=50
+;神兽物品背包
+PackCnt32=100
+;神兽装备背包
+PackCnt33=100
+;垃圾分类背包
+PackCnt34=30
\ No newline at end of file
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index d33e547..67c1ef2 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -1382,6 +1382,34 @@
 PacketSubCMD_2=0x06
 PacketCallFunc_2=OnActWishingDrag
 
+;垃圾分类活动
+[PlayerActGarbageSorting]
+ScriptName = Player\PlayerActGarbageSorting.py
+Writer = hxp
+Releaser = hxp
+RegType = 0
+RegisterPackCount = 5
+
+PacketCMD_1=0xAA
+PacketSubCMD_1=0x14
+PacketCallFunc_1=OnActGarbageSorting
+
+PacketCMD_2=0xAA
+PacketSubCMD_2=0x15
+PacketCallFunc_2=OnActGarbageGetTaskAward
+
+PacketCMD_3=0xAA
+PacketSubCMD_3=0x16
+PacketCallFunc_3=OnActGarbageChooseSuperItem
+
+PacketCMD_4=0xAA
+PacketSubCMD_4=0x17
+PacketCallFunc_4=OnActGarbageLottery
+
+PacketCMD_5=0xAA
+PacketSubCMD_5=0x18
+PacketCallFunc_5=OnActGarbageAwardPoolRefresh
+
 ;集字活动
 [PlayerActCollectWords]
 ScriptName = Player\PlayerActCollectWords.py
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 82c39d9..c651a40 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -858,6 +858,8 @@
 Def_PackCnt_DogzItem = 100
 #初始化神兽装备格子数
 Def_PackCnt_DogzEquip = 100
+#初始化垃圾分类格子数
+Def_PackCnt_Garbage = 30
 #初始化装备栏2
 Def_PackCnt_Equip2 = 0
 #初始化回收站
@@ -1101,6 +1103,7 @@
                                     ShareDefine.rptPet,
                                     ShareDefine.rptDogzItem,
                                     ShareDefine.rptDogzEquip,
+                                    ShareDefine.rptGarbage,
                                     ]
 
 #装备可强化背包列表
@@ -3885,6 +3888,18 @@
 Def_PDict_TurntableItemID = "TurntableItemID_%s_%s"  # 转盘物品ID*10+物品库类型,参数:(活动编号, 物品编号)
 Def_PDict_TurntableItemCount = "TurntableCount_%s_%s"  # 转盘物品个数,参数:(活动编号, 物品编号)
 Def_PDict_TurntableItemState = "TurntableItemState_%s"  # 转盘物品是否已抽中,按物品编号二进制位代表是否已抽中,参数:(活动编号)
+
+#垃圾分类活动
+Def_PDict_GarbageSortingID = "ActGSID_%s"  # 玩家身上的活动ID,唯一标识,取活动开始日期time值,参数:(活动编号)
+Def_PDict_GarbageSortingWorldLV = "ActGSWorldLV_%s" #玩家身上的活动世界等级,参数:(活动编号)
+Def_PDict_GarbageGuideState = "ActGSGuideState_%s" #活动引导任务状态,不影响活动数据,仅前端展示需要用到,参数:(活动编号)
+Def_PDict_GarbageTaskValue = "ActGSTaskValue_%s_%s" # 任务总进度值,参数(活动编号, 任务ID)
+Def_PDict_GarbageTaskFinishCount = "ActGSTaskFinishCount_%s_%s" # 任务已完成次数,参数(活动编号, 任务ID)
+Def_PDict_GarbageEnvironmentValue = "ActGSEnvValue_%s" # 当前可用环保值,参数(活动编号)
+Def_PDict_GarbageEnvironmentValueHis = "ActGSEnvValueHis_%s" # 历史最高环保值,参数(活动编号)
+Def_PDict_GarbageAwardLayerInfo = "ActGSAwardLayerInfo_%s" # 奖池层级信息: 累计抽奖次数*100+层数,参数:(活动编号)
+Def_PDict_GarbageAwardItemInfo = "ActGSItemInfo_%s_%s_%s"  # 奖池物品ID*100+抽中位置编号,参数:(活动编号, 库类型, 物品编号)
+Def_PDict_GarbageAwardItemTimes = "ActGSItemTimes_%s_%s_%s"  # 奖池物品累计产出次数,有限制次数的才记录,参数:(活动编号, 库类型, 物品ID)
 #-------------------------------------------------------------------------------
 
 #开服活动,Def_PDictType_OpenServerCampaign
@@ -5559,6 +5574,22 @@
 Def_LoginAct_EquipWash, #洗炼 18
 ) = range(1, 18+1)
 
+#垃圾分类 - 垃圾产出任务
+GarbageTaskList = (
+Def_GarbageTask_Activity, # 获得活跃值    1
+Def_GarbageTask_ActivityPlace, # 活跃修炼    2
+Def_GarbageTask_HelpBattle, # 助战登记    3
+Def_GarbageTask_KillNPC, # 击杀小怪    4
+Def_GarbageTask_RefineStove, # 炼丹    5
+Def_GarbageTask_KillBoss, # 打宝 - 本服    6
+Def_GarbageTask_CrossPK, # 跨服PK    7
+Def_GarbageTask_CrossBoss, # 跨服Boss    8
+Def_GarbageTask_CrossCollect, # 跨服采集宝箱    9
+Def_GarbageTask_EquipPlus, # 强化    10
+Def_GarbageTask_EquipWash, # 洗炼    11
+Def_GarbageTask_UseGold, # 消费仙玉    12
+Def_GarbageTask_CTG, # 充值仙玉    13
+) = range(1, 1 + 13)
 
 # 套装枚举,普通套装,强化套装
 (EquipSuitType_Normal,
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index 7820c45..0a29534 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -13321,6 +13321,273 @@
 
 
 #------------------------------------------------------
+# AA 16 垃圾分类活动选择大奖 #tagCMActGarbageChooseSuperItem
+
+class  tagCMActGarbageChooseSuperItem(Structure):
+    Head = tagHead()
+    ActNum = 0    #(BYTE ActNum)//活动编号
+    SuperItemCount = 0    #(BYTE SuperItemCount)//选择物品数量
+    SuperItemIDList = list()    #(vector<DWORD> SuperItemIDList)//选择的大奖库物品ID列表,每次重新选择需要发送全部已选择的大奖物品ID,不能只发单个物品ID;
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x16
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ActNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.SuperItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.SuperItemCount):
+            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+            self.SuperItemIDList.append(value)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x16
+        self.ActNum = 0
+        self.SuperItemCount = 0
+        self.SuperItemIDList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 1
+        length += 4 * self.SuperItemCount
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.ActNum)
+        data = CommFunc.WriteBYTE(data, self.SuperItemCount)
+        for i in range(self.SuperItemCount):
+            data = CommFunc.WriteDWORD(data, self.SuperItemIDList[i])
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ActNum:%d,
+                                SuperItemCount:%d,
+                                SuperItemIDList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ActNum,
+                                self.SuperItemCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagCMActGarbageChooseSuperItem=tagCMActGarbageChooseSuperItem()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActGarbageChooseSuperItem.Head.Cmd,m_NAtagCMActGarbageChooseSuperItem.Head.SubCmd))] = m_NAtagCMActGarbageChooseSuperItem
+
+
+#------------------------------------------------------
+# AA 15 垃圾分类活动收集已完成的任务垃圾 #tagCMActGarbageGetTaskAward
+
+class  tagCMActGarbageGetTaskAward(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ActNum", c_ubyte),    #活动编号
+                  ("GarbageTaskID", c_ubyte),    #垃圾任务ID
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xAA
+        self.SubCmd = 0x15
+        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 = 0xAA
+        self.SubCmd = 0x15
+        self.ActNum = 0
+        self.GarbageTaskID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMActGarbageGetTaskAward)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 15 垃圾分类活动收集已完成的任务垃圾 //tagCMActGarbageGetTaskAward:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ActNum:%d,
+                                GarbageTaskID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ActNum,
+                                self.GarbageTaskID
+                                )
+        return DumpString
+
+
+m_NAtagCMActGarbageGetTaskAward=tagCMActGarbageGetTaskAward()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActGarbageGetTaskAward.Cmd,m_NAtagCMActGarbageGetTaskAward.SubCmd))] = m_NAtagCMActGarbageGetTaskAward
+
+
+#------------------------------------------------------
+# AA 17 垃圾分类活动抽奖 #tagCMActGarbageLottery
+
+class  tagCMActGarbageLottery(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ActNum", c_ubyte),    #活动编号
+                  ("PosNum", c_ubyte),    #玩家点击的奖励位置编号,从1开始
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xAA
+        self.SubCmd = 0x17
+        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 = 0xAA
+        self.SubCmd = 0x17
+        self.ActNum = 0
+        self.PosNum = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMActGarbageLottery)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 17 垃圾分类活动抽奖 //tagCMActGarbageLottery:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ActNum:%d,
+                                PosNum:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ActNum,
+                                self.PosNum
+                                )
+        return DumpString
+
+
+m_NAtagCMActGarbageLottery=tagCMActGarbageLottery()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActGarbageLottery.Cmd,m_NAtagCMActGarbageLottery.SubCmd))] = m_NAtagCMActGarbageLottery
+
+
+#------------------------------------------------------
+# AA 14 垃圾分类活动分类垃圾 #tagCMActGarbageSorting
+
+class  tagCMActGarbageSorting(Structure):
+    Head = tagHead()
+    ActNum = 0    #(BYTE ActNum)//活动编号
+    GarbageSortingType = 0    #(BYTE GarbageSortingType)//垃圾分类类型,即属于哪种垃圾
+    ItemIndexCount = 0    #(BYTE ItemIndexCount)//垃圾背包中的物品索引数
+    ItemIndexList = list()    #(vector<BYTE> ItemIndexList)//垃圾背包中的物品索引列表
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x14
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ActNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.GarbageSortingType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.ItemIndexCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.ItemIndexCount):
+            value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
+            self.ItemIndexList.append(value)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x14
+        self.ActNum = 0
+        self.GarbageSortingType = 0
+        self.ItemIndexCount = 0
+        self.ItemIndexList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 1
+        length += 1
+        length += 1 * self.ItemIndexCount
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.ActNum)
+        data = CommFunc.WriteBYTE(data, self.GarbageSortingType)
+        data = CommFunc.WriteBYTE(data, self.ItemIndexCount)
+        for i in range(self.ItemIndexCount):
+            data = CommFunc.WriteBYTE(data, self.ItemIndexList[i])
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ActNum:%d,
+                                GarbageSortingType:%d,
+                                ItemIndexCount:%d,
+                                ItemIndexList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ActNum,
+                                self.GarbageSortingType,
+                                self.ItemIndexCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagCMActGarbageSorting=tagCMActGarbageSorting()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActGarbageSorting.Head.Cmd,m_NAtagCMActGarbageSorting.Head.SubCmd))] = m_NAtagCMActGarbageSorting
+
+
+#------------------------------------------------------
 # AA 12 选择转盘活动物品 #tagCMActTurntableChooseItem
 
 class  tagCMActTurntableChooseItem(Structure):
@@ -13748,6 +14015,58 @@
 
 
 #------------------------------------------------------
+# AA 18 垃圾分类活动奖池刷新 #tagCMGarbageAwardPoolRefresh
+
+class  tagCMGarbageAwardPoolRefresh(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ActNum", c_ubyte),    #活动编号
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xAA
+        self.SubCmd = 0x18
+        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 = 0xAA
+        self.SubCmd = 0x18
+        self.ActNum = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMGarbageAwardPoolRefresh)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 18 垃圾分类活动奖池刷新 //tagCMGarbageAwardPoolRefresh:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ActNum:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ActNum
+                                )
+        return DumpString
+
+
+m_NAtagCMGarbageAwardPoolRefresh=tagCMGarbageAwardPoolRefresh()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMGarbageAwardPoolRefresh.Cmd,m_NAtagCMGarbageAwardPoolRefresh.SubCmd))] = m_NAtagCMGarbageAwardPoolRefresh
+
+
+#------------------------------------------------------
 #AA 01 领取累计登陆礼 # tagCMGetTotalLoginDayAward
 
 class  tagCMGetTotalLoginDayAward(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 7a550fd..219c323 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -24638,6 +24638,509 @@
 
 
 #------------------------------------------------------
+# AA 57 垃圾收集活动玩家信息 #tagMCActGarbagePlayerInfo
+
+class  tagMCActGarbageAwardItemResult(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("ItemLibType", c_ubyte),    #物品库类型;9-固定为大奖库,非9-策划自定义库
+                  ("ItemID", c_int),    # 注意: 不同库物品ID可能相同,但个数不同
+                  ("ItemCount", c_ushort),    
+                  ("PosNum", c_ubyte),    # 被抽中时的位置编号,1~99,前端自定义展示位置编号,0代表未被抽中;
+                  ("TotalTimesNow", c_ubyte),    #当前已产出次数,不限制次数时不记录,即同样为0
+                  ]
+
+    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.ItemLibType = 0
+        self.ItemID = 0
+        self.ItemCount = 0
+        self.PosNum = 0
+        self.TotalTimesNow = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCActGarbageAwardItemResult)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 57 垃圾收集活动玩家信息 //tagMCActGarbagePlayerInfo:
+                                ItemLibType:%d,
+                                ItemID:%d,
+                                ItemCount:%d,
+                                PosNum:%d,
+                                TotalTimesNow:%d
+                                '''\
+                                %(
+                                self.ItemLibType,
+                                self.ItemID,
+                                self.ItemCount,
+                                self.PosNum,
+                                self.TotalTimesNow
+                                )
+        return DumpString
+
+
+class  tagMCActGarbagePlayerInfo(Structure):
+    Head = tagHead()
+    ActNum = 0    #(BYTE ActNum)//活动编号
+    GuideTaskFinish = 0    #(BYTE GuideTaskFinish)//引导任务是否已完成,有需要NPC对话引导任务时,则需要先完成才显示活动界面
+    EnvironmentValue = 0    #(DWORD EnvironmentValue)//当前可用环保值
+    EnvironmentValueHis = 0    #(DWORD EnvironmentValueHis)//历史环保值
+    AwardItemResult=tagMCActGarbageAwardItemResult()    #(tagMCActGarbageAwardItemResult AwardItemResult)//本次抽奖结果物品信息,可能为空
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x57
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ActNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.GuideTaskFinish,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.EnvironmentValue,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.EnvironmentValueHis,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        _pos = self.AwardItemResult.ReadData(_lpData,_pos)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x57
+        self.ActNum = 0
+        self.GuideTaskFinish = 0
+        self.EnvironmentValue = 0
+        self.EnvironmentValueHis = 0
+        self.AwardItemResult=tagMCActGarbageAwardItemResult()
+        self.AwardItemResult.Clear()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 1
+        length += 4
+        length += 4
+        length += self.AwardItemResult.GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.ActNum)
+        data = CommFunc.WriteBYTE(data, self.GuideTaskFinish)
+        data = CommFunc.WriteDWORD(data, self.EnvironmentValue)
+        data = CommFunc.WriteDWORD(data, self.EnvironmentValueHis)
+        data = CommFunc.WriteString(data,self.AwardItemResult.GetLength(),self.AwardItemResult.GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ActNum:%d,
+                                GuideTaskFinish:%d,
+                                EnvironmentValue:%d,
+                                EnvironmentValueHis:%d,
+                                AwardItemResult:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ActNum,
+                                self.GuideTaskFinish,
+                                self.EnvironmentValue,
+                                self.EnvironmentValueHis,
+                                self.AwardItemResult.OutputString()
+                                )
+        return DumpString
+
+
+m_NAtagMCActGarbagePlayerInfo=tagMCActGarbagePlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActGarbagePlayerInfo.Head.Cmd,m_NAtagMCActGarbagePlayerInfo.Head.SubCmd))] = m_NAtagMCActGarbagePlayerInfo
+
+
+#------------------------------------------------------
+# AA 55 垃圾收集活动信息 #tagMCActGarbageSortingInfo
+
+class  tagMCActGarbageAwardItem(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("ItemLibType", c_ubyte),    #物品库类型;9-固定为大奖库,非9-策划自定义库
+                  ("ItemID", c_int),    # 注意: 不同库物品ID可能相同,但个数不同
+                  ("ItemCount", c_ushort),    
+                  ("PosNum", c_ubyte),    # 被抽中时的位置编号,1~99,前端自定义展示位置编号,0代表未被抽中;
+                  ("TotalTimesNow", c_ubyte),    #当前已产出次数,不限制次数时不记录,即同样为0
+                  ("TotalTimesMax", c_ubyte),    #最大可产出次数,0不限
+                  ("LayerLimit", c_ubyte),    #大于等于X层后可产出,0不限
+                  ]
+
+    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.ItemLibType = 0
+        self.ItemID = 0
+        self.ItemCount = 0
+        self.PosNum = 0
+        self.TotalTimesNow = 0
+        self.TotalTimesMax = 0
+        self.LayerLimit = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCActGarbageAwardItem)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 55 垃圾收集活动信息 //tagMCActGarbageSortingInfo:
+                                ItemLibType:%d,
+                                ItemID:%d,
+                                ItemCount:%d,
+                                PosNum:%d,
+                                TotalTimesNow:%d,
+                                TotalTimesMax:%d,
+                                LayerLimit:%d
+                                '''\
+                                %(
+                                self.ItemLibType,
+                                self.ItemID,
+                                self.ItemCount,
+                                self.PosNum,
+                                self.TotalTimesNow,
+                                self.TotalTimesMax,
+                                self.LayerLimit
+                                )
+        return DumpString
+
+
+class  tagMCActGarbageSortingInfo(Structure):
+    Head = tagHead()
+    ActNum = 0    #(BYTE ActNum)// 活动编号
+    StartDate = ""    #(char StartDate[10])// 开始日期 y-m-d
+    EndtDate = ""    #(char EndtDate[10])// 结束日期 y-m-d
+    LimitLV = 0    #(WORD LimitLV)// 限制等级
+    LayerNum = 0    #(BYTE LayerNum)//当前奖池第几层
+    AwardItemCount = 0    #(BYTE AwardItemCount)
+    AwardItemList = list()    #(vector<tagMCActGarbageAwardItem> AwardItemList)// 奖池物品列表,已生成的,包含已选择的大奖物品
+    SuperItemCount = 0    #(BYTE SuperItemCount)
+    SuperItemList = list()    #(vector<tagMCActGarbageAwardItem> SuperItemList)// 大奖物品待选择库,由玩家从库中选择放入奖池的物品;
+    SuperItemCanChooseCount = 0    #(BYTE SuperItemCanChooseCount)// 大奖物品可选择个数
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x55
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ActNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.StartDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+        self.EndtDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+        self.LimitLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.LayerNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.AwardItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.AwardItemCount):
+            temAwardItemList = tagMCActGarbageAwardItem()
+            _pos = temAwardItemList.ReadData(_lpData, _pos)
+            self.AwardItemList.append(temAwardItemList)
+        self.SuperItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.SuperItemCount):
+            temSuperItemList = tagMCActGarbageAwardItem()
+            _pos = temSuperItemList.ReadData(_lpData, _pos)
+            self.SuperItemList.append(temSuperItemList)
+        self.SuperItemCanChooseCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x55
+        self.ActNum = 0
+        self.StartDate = ""
+        self.EndtDate = ""
+        self.LimitLV = 0
+        self.LayerNum = 0
+        self.AwardItemCount = 0
+        self.AwardItemList = list()
+        self.SuperItemCount = 0
+        self.SuperItemList = list()
+        self.SuperItemCanChooseCount = 0
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 10
+        length += 10
+        length += 2
+        length += 1
+        length += 1
+        for i in range(self.AwardItemCount):
+            length += self.AwardItemList[i].GetLength()
+        length += 1
+        for i in range(self.SuperItemCount):
+            length += self.SuperItemList[i].GetLength()
+        length += 1
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.ActNum)
+        data = CommFunc.WriteString(data, 10, self.StartDate)
+        data = CommFunc.WriteString(data, 10, self.EndtDate)
+        data = CommFunc.WriteWORD(data, self.LimitLV)
+        data = CommFunc.WriteBYTE(data, self.LayerNum)
+        data = CommFunc.WriteBYTE(data, self.AwardItemCount)
+        for i in range(self.AwardItemCount):
+            data = CommFunc.WriteString(data, self.AwardItemList[i].GetLength(), self.AwardItemList[i].GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.SuperItemCount)
+        for i in range(self.SuperItemCount):
+            data = CommFunc.WriteString(data, self.SuperItemList[i].GetLength(), self.SuperItemList[i].GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.SuperItemCanChooseCount)
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ActNum:%d,
+                                StartDate:%s,
+                                EndtDate:%s,
+                                LimitLV:%d,
+                                LayerNum:%d,
+                                AwardItemCount:%d,
+                                AwardItemList:%s,
+                                SuperItemCount:%d,
+                                SuperItemList:%s,
+                                SuperItemCanChooseCount:%d
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ActNum,
+                                self.StartDate,
+                                self.EndtDate,
+                                self.LimitLV,
+                                self.LayerNum,
+                                self.AwardItemCount,
+                                "...",
+                                self.SuperItemCount,
+                                "...",
+                                self.SuperItemCanChooseCount
+                                )
+        return DumpString
+
+
+m_NAtagMCActGarbageSortingInfo=tagMCActGarbageSortingInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActGarbageSortingInfo.Head.Cmd,m_NAtagMCActGarbageSortingInfo.Head.SubCmd))] = m_NAtagMCActGarbageSortingInfo
+
+
+#------------------------------------------------------
+# AA 56 垃圾收集活动任务进度信息 #tagMCActGarbageTaskInfo
+
+class  tagMCActGarbageTaskItem(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("ItemID", c_int),    
+                  ("ItemCount", c_ushort),    
+                  ]
+
+    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.ItemID = 0
+        self.ItemCount = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCActGarbageTaskItem)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 56 垃圾收集活动任务进度信息 //tagMCActGarbageTaskInfo:
+                                ItemID:%d,
+                                ItemCount:%d
+                                '''\
+                                %(
+                                self.ItemID,
+                                self.ItemCount
+                                )
+        return DumpString
+
+
+class  tagMCActGarbageTask(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("GarbageTaskID", c_ubyte),    #垃圾任务ID
+                  ("GarbageTaskValue", c_int),    #当前进度值,一直累加
+                  ("GarbageTaskFinishCount", c_ubyte),    #当前已完成次数; 前端计算未完成次数的进度值=max(0, 当前进度值 - (完成次数 * 单次所需进度))
+                  ]
+
+    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.GarbageTaskID = 0
+        self.GarbageTaskValue = 0
+        self.GarbageTaskFinishCount = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCActGarbageTask)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 56 垃圾收集活动任务进度信息 //tagMCActGarbageTaskInfo:
+                                GarbageTaskID:%d,
+                                GarbageTaskValue:%d,
+                                GarbageTaskFinishCount:%d
+                                '''\
+                                %(
+                                self.GarbageTaskID,
+                                self.GarbageTaskValue,
+                                self.GarbageTaskFinishCount
+                                )
+        return DumpString
+
+
+class  tagMCActGarbageTaskInfo(Structure):
+    Head = tagHead()
+    ActNum = 0    #(BYTE ActNum)// 活动编号
+    GarbageTaskCount = 0    #(BYTE GarbageTaskCount)//任务数
+    GarbageTaskList = list()    #(vector<tagMCActGarbageTask> GarbageTaskList)//任务信息列表
+    TaskItemCount = 0    #(BYTE TaskItemCount)//本次获得的垃圾收集任务奖励物品个数,可能为0
+    GarbageTaskItemList = list()    #(vector<tagMCActGarbageTaskItem> GarbageTaskItemList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x56
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ActNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.GarbageTaskCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.GarbageTaskCount):
+            temGarbageTaskList = tagMCActGarbageTask()
+            _pos = temGarbageTaskList.ReadData(_lpData, _pos)
+            self.GarbageTaskList.append(temGarbageTaskList)
+        self.TaskItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.TaskItemCount):
+            temGarbageTaskItemList = tagMCActGarbageTaskItem()
+            _pos = temGarbageTaskItemList.ReadData(_lpData, _pos)
+            self.GarbageTaskItemList.append(temGarbageTaskItemList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x56
+        self.ActNum = 0
+        self.GarbageTaskCount = 0
+        self.GarbageTaskList = list()
+        self.TaskItemCount = 0
+        self.GarbageTaskItemList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 1
+        for i in range(self.GarbageTaskCount):
+            length += self.GarbageTaskList[i].GetLength()
+        length += 1
+        for i in range(self.TaskItemCount):
+            length += self.GarbageTaskItemList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.ActNum)
+        data = CommFunc.WriteBYTE(data, self.GarbageTaskCount)
+        for i in range(self.GarbageTaskCount):
+            data = CommFunc.WriteString(data, self.GarbageTaskList[i].GetLength(), self.GarbageTaskList[i].GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.TaskItemCount)
+        for i in range(self.TaskItemCount):
+            data = CommFunc.WriteString(data, self.GarbageTaskItemList[i].GetLength(), self.GarbageTaskItemList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ActNum:%d,
+                                GarbageTaskCount:%d,
+                                GarbageTaskList:%s,
+                                TaskItemCount:%d,
+                                GarbageTaskItemList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ActNum,
+                                self.GarbageTaskCount,
+                                "...",
+                                self.TaskItemCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCActGarbageTaskInfo=tagMCActGarbageTaskInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActGarbageTaskInfo.Head.Cmd,m_NAtagMCActGarbageTaskInfo.Head.SubCmd))] = m_NAtagMCActGarbageTaskInfo
+
+
+#------------------------------------------------------
 # AA 31 成长必买活动信息 #tagMCActGrowupBuyInfo
 
 class  tagMCActGrowupBuyCTGItem(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipPlus.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipPlus.py
index b4b1147..5a888a9 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipPlus.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipPlus.py
@@ -36,6 +36,7 @@
 import ChPyNetSendPack
 import NetPackCommon
 import PlayerWeekParty
+import PlayerActGarbageSorting
 #-------------------------------------------------------------------------------------------
 
 #===============================================================================
@@ -198,6 +199,7 @@
         
     #GameWorld.DebugLog("强化成就数据: classLV=%s,plusLVCountDict=%s" % (classLV, plusLVCountDict))
     PlayerSuccess.UpdateSuccessProgressByConditions(curPlayer, ShareDefine.SuccType_EquipPlus, plusLVCountDict)
+    PlayerActGarbageSorting.AddActGarbageTaskProgress(curPlayer, ChConfig.Def_GarbageTask_EquipPlus)
     return
 
 def DoLogic_OnEquipPartStarLVChange(curPlayer, packType, classLV):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipWash.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipWash.py
index 3d369a6..65af626 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipWash.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipWash.py
@@ -22,6 +22,7 @@
 import PlayerControl
 import PlayerSuccess
 import IPY_GameWorld
+import PlayerActGarbageSorting
 import DataRecordPack
 import PlayerActLogin
 import ShareDefine
@@ -295,6 +296,7 @@
     if isRefreshAttr:
         RefreshEquipWashAttr(curPlayer, classLV)
     PlayerActLogin.AddLoginAwardActionCnt(curPlayer, ChConfig.Def_LoginAct_EquipWash, 1)
+    PlayerActGarbageSorting.AddActGarbageTaskProgress(curPlayer, ChConfig.Def_GarbageTask_EquipWash)
     return
 
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/QuestCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/QuestCommon.py
index da87f73..15fa16f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/QuestCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/QuestCommon.py
@@ -35,6 +35,7 @@
 import ChPyNetSendPack
 import NetPackCommon
 import EventShell
+import PlayerActGarbageSorting
 #---------------------------------------------------------------------
 #所有任务的索引
 FindQuestFunc = None
@@ -207,6 +208,8 @@
         # 剧情任务完成处理
         OnStoryMissionFinish(curPlayer, missionID)
         
+        PlayerActGarbageSorting.OnFinishTask(curPlayer, missionID)
+        
         EventReport.WriteEvent_mission_log(curPlayer, curQuestData, 1, isFinish, failReason)
     
 #    # 镖车完成特殊处理
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearPack.py
index c3ab53a..0d28f0c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearPack.py
@@ -26,7 +26,7 @@
 #  @remarks 函数详细说明.
 def OnExec(curPlayer, playerList):
     if not playerList:
-        GameWorld.DebugAnswer(curPlayer, "背包类型:1-装备;2-背包;5-仓库;30-寻宝;32-神兽;33-神兽装备;")
+        GameWorld.DebugAnswer(curPlayer, "背包类型:1-装备;2-背包;5-仓库;30-寻宝;32-神兽;33-神兽装备;34-垃圾收集")
         return
     
     if len(playerList) == 1:
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBHelpBattle.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBHelpBattle.py
index bbb7e4d..b3dd416 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBHelpBattle.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBHelpBattle.py
@@ -21,6 +21,7 @@
 import ChPyNetSendPack
 import NetPackCommon
 import PlayerViewCacheTube
+import PlayerActGarbageSorting
 import FBCommon
 import IpyGameDataPY
 import ShareDefine
@@ -107,6 +108,7 @@
         checkInInfo = (checkInCount + 1) * 10 + 1
         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HelpBattleCheckInCount, checkInInfo)
         PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_HelpBattleCheckIn)
+        PlayerActGarbageSorting.AddActGarbageTaskProgress(curPlayer, ChConfig.Def_GarbageTask_HelpBattle)
         
         # 没有数据缓存的话,马上同步一次
         if not haveViewCache:
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index 14367cd..f566635 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -1143,6 +1143,34 @@
                         ("BYTE", "NeedNotify", 0),
                         ),
 
+                "ActGarbageSorting":(
+                        ("DWORD", "CfgID", 1),
+                        ("char", "StartDate", 0),
+                        ("char", "EndDate", 0),
+                        ("WORD", "LVLimit", 0),
+                        ("BYTE", "CTGTypeEffValue", 0),
+                        ("BYTE", "TemplateID", 0),
+                        ),
+
+                "ActGarbageTask":(
+                        ("DWORD", "GarbageTasklD", 1),
+                        ("DWORD", "FinishNeedValue", 0),
+                        ("DWORD", "FinishTimeMax", 0),
+                        ("BYTE", "AutoProduce", 0),
+                        ("list", "ProduceGarbageRateList", 0),
+                        ),
+
+                "ActGarbageAward":(
+                        ("DWORD", "TemplateID", 1),
+                        ("BYTE", "AwardLibType", 0),
+                        ("BYTE", "AwardItemCount", 0),
+                        ("BYTE", "UnlockAwardLimitTimes", 0),
+                        ("BYTE", "AwardLibWeight", 0),
+                        ("dict", "LibItemInfo", 0),
+                        ("dict", "ItemLayerLimitInfo", 0),
+                        ("dict", "ItemAwardTimesTotalInfo", 0),
+                        ),
+
                 "ActHorsePetFeast":(
                         ("DWORD", "CfgID", 1),
                         ("char", "StartDate", 0),
@@ -4145,6 +4173,65 @@
     def GetNeedItemList(self): return self.NeedItemList # 所需物品信息列表 [[物品ID,个数,是否绑定], ...]
     def GetNeedNotify(self): return self.NeedNotify # 是否需要广播
 
+# 垃圾分类活动时间表
+class IPY_ActGarbageSorting():
+    
+    def __init__(self):
+        self.CfgID = 0
+        self.StartDate = ""
+        self.EndDate = ""
+        self.LVLimit = 0
+        self.CTGTypeEffValue = 0
+        self.TemplateID = 0
+        return
+        
+    def GetCfgID(self): return self.CfgID # 配置ID
+    def GetStartDate(self): return self.StartDate # 开启日期
+    def GetEndDate(self): return self.EndDate # 结束日期
+    def GetLVLimit(self): return self.LVLimit # 限制等级
+    def GetCTGTypeEffValue(self): return self.CTGTypeEffValue # 充值有效类型值
+    def GetTemplateID(self): return self.TemplateID # 模板ID
+
+# 垃圾分类任务产出表
+class IPY_ActGarbageTask():
+    
+    def __init__(self):
+        self.GarbageTasklD = 0
+        self.FinishNeedValue = 0
+        self.FinishTimeMax = 0
+        self.AutoProduce = 0
+        self.ProduceGarbageRateList = []
+        return
+        
+    def GetGarbageTasklD(self): return self.GarbageTasklD # 垃圾任务ID
+    def GetFinishNeedValue(self): return self.FinishNeedValue # 完成所需进度值
+    def GetFinishTimeMax(self): return self.FinishTimeMax # 总可完成次数,0不限
+    def GetAutoProduce(self): return self.AutoProduce # 自动产生垃圾
+    def GetProduceGarbageRateList(self): return self.ProduceGarbageRateList # 随机产生垃圾概率饼图
+
+# 垃圾分类环保奖池表
+class IPY_ActGarbageAward():
+    
+    def __init__(self):
+        self.TemplateID = 0
+        self.AwardLibType = 0
+        self.AwardItemCount = 0
+        self.UnlockAwardLimitTimes = 0
+        self.AwardLibWeight = 0
+        self.LibItemInfo = {}
+        self.ItemLayerLimitInfo = {}
+        self.ItemAwardTimesTotalInfo = {}
+        return
+        
+    def GetTemplateID(self): return self.TemplateID # 奖池模板编号
+    def GetAwardLibType(self): return self.AwardLibType # 奖励库类型
+    def GetAwardItemCount(self): return self.AwardItemCount # 选择个数
+    def GetUnlockAwardLimitTimes(self): return self.UnlockAwardLimitTimes # 抽X次后可产出(本层)
+    def GetAwardLibWeight(self): return self.AwardLibWeight # 产出该库外权重
+    def GetLibItemInfo(self): return self.LibItemInfo # 本库物品随机库内权重(先随机库外权重,若产出再随机库内权重)
+    def GetItemLayerLimitInfo(self): return self.ItemLayerLimitInfo # 物品产出奖池层限制 {物品ID:大于等于X层可产出, ...}
+    def GetItemAwardTimesTotalInfo(self): return self.ItemAwardTimesTotalInfo # 物品产出次数限制(所有层){物品ID:总产出次数, ...}
+
 # 骑宠盛宴活动
 class IPY_ActHorsePetFeast():
     
@@ -5807,6 +5894,12 @@
         self.ipyActCollectWordsLen = len(self.ipyActCollectWordsCache)
         self.ipyCollectWordsExchangeCache = self.__LoadFileData("CollectWordsExchange", IPY_CollectWordsExchange)
         self.ipyCollectWordsExchangeLen = len(self.ipyCollectWordsExchangeCache)
+        self.ipyActGarbageSortingCache = self.__LoadFileData("ActGarbageSorting", IPY_ActGarbageSorting)
+        self.ipyActGarbageSortingLen = len(self.ipyActGarbageSortingCache)
+        self.ipyActGarbageTaskCache = self.__LoadFileData("ActGarbageTask", IPY_ActGarbageTask)
+        self.ipyActGarbageTaskLen = len(self.ipyActGarbageTaskCache)
+        self.ipyActGarbageAwardCache = self.__LoadFileData("ActGarbageAward", IPY_ActGarbageAward)
+        self.ipyActGarbageAwardLen = len(self.ipyActGarbageAwardCache)
         self.ipyActHorsePetFeastCache = self.__LoadFileData("ActHorsePetFeast", IPY_ActHorsePetFeast)
         self.ipyActHorsePetFeastLen = len(self.ipyActHorsePetFeastCache)
         self.ipyActBossRebornCache = self.__LoadFileData("ActBossReborn", IPY_ActBossReborn)
@@ -6343,6 +6436,12 @@
     def GetActCollectWordsByIndex(self, index): return self.ipyActCollectWordsCache[index]
     def GetCollectWordsExchangeCount(self): return self.ipyCollectWordsExchangeLen
     def GetCollectWordsExchangeByIndex(self, index): return self.ipyCollectWordsExchangeCache[index]
+    def GetActGarbageSortingCount(self): return self.ipyActGarbageSortingLen
+    def GetActGarbageSortingByIndex(self, index): return self.ipyActGarbageSortingCache[index]
+    def GetActGarbageTaskCount(self): return self.ipyActGarbageTaskLen
+    def GetActGarbageTaskByIndex(self, index): return self.ipyActGarbageTaskCache[index]
+    def GetActGarbageAwardCount(self): return self.ipyActGarbageAwardLen
+    def GetActGarbageAwardByIndex(self, index): return self.ipyActGarbageAwardCache[index]
     def GetActHorsePetFeastCount(self): return self.ipyActHorsePetFeastLen
     def GetActHorsePetFeastByIndex(self, index): return self.ipyActHorsePetFeastCache[index]
     def GetActBossRebornCount(self): return self.ipyActBossRebornLen
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 b08e2a9..89670e8 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -106,6 +106,7 @@
 import PlayerActCollectWords
 import PlayerActTotalRecharge
 import PlayerActRechargePrize
+import PlayerActGarbageSorting
 import PlayerActRechargeRebateGold
 import PlayerActManyDayRecharge
 import PlayerActSingleRecharge
@@ -720,6 +721,8 @@
     PlayerFeastTravel.OnPlayerLogin(curPlayer)
     # 登录奖励活动
     PlayerActLogin.OnLogin(curPlayer)
+    # 垃圾分类活动
+    PlayerActGarbageSorting.OnPlayerLogin(curPlayer)
     # 多日连充活动
     PlayerActManyDayRecharge.OnPlayerLogin(curPlayer)
     # 单笔累充活动
@@ -1327,6 +1330,10 @@
     curPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptDogzEquip)
     curPack.SetCount(ChConfig.Def_PackCnt_DogzEquip)
     curPack.Sync_PackCanUseCount()
+    #初始化垃圾分类背包
+    curPack = itemManager.GetPack(ShareDefine.rptGarbage)
+    curPack.SetCount(ChConfig.Def_PackCnt_Garbage)
+    curPack.Sync_PackCanUseCount()
     
     #初始化临时交换背包
     curPack = itemManager.GetPack(ShareDefine.rptTempSwap)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActGarbageSorting.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActGarbageSorting.py
new file mode 100644
index 0000000..177a4ce
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActGarbageSorting.py
@@ -0,0 +1,858 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.PlayerActGarbageSorting
+#
+# @todo:垃圾分类活动
+# @author hxp
+# @date 2021-05-13
+# @version 1.0
+#
+# 详细描述: 垃圾分类活动
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2021-05-13 19:30"""
+#-------------------------------------------------------------------------------
+
+import PyGameData
+import ShareDefine
+import PlayerControl
+import IpyGameDataPY
+import ItemControler
+import ChPyNetSendPack
+import NetPackCommon
+import GameWorld
+import ChConfig
+import ItemCommon
+import PlayerBillboard
+import QuestCommon
+
+Def_SuperLibType = 9 # 大奖库类型固定为9
+
+def OnPlayerLogin(curPlayer):
+    
+    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_GarbageSorting, {}).values():
+        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
+        isReset = __CheckPlayerGarbageSortingAction(curPlayer, actNum)
+        if not isReset:
+            # 活动中同步活动信息
+            if actInfo.get(ShareDefine.ActKey_State):
+                Sync_GarbageSortingActionInfo(curPlayer, actNum)
+                Sync_GarbageSortingPlayerInfo(curPlayer, actNum)
+                Sync_GarbageTaskInfo(curPlayer, actNum)
+    return
+
+def RefreshGarbageSortingActionInfo(actNum):
+    ## 收到GameServer同步的活动信息,刷新活动信息
+    playerManager = GameWorld.GetPlayerManager()
+    for index in xrange(playerManager.GetPlayerCount()):
+        curPlayer = playerManager.GetPlayerByIndex(index)
+        if curPlayer.GetID() == 0:
+            continue
+        __CheckPlayerGarbageSortingAction(curPlayer, actNum)
+    return
+
+def __CheckPlayerGarbageSortingAction(curPlayer, actNum):
+    ## 检查玩家活动数据信息
+    
+    playerID = curPlayer.GetPlayerID()
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_GarbageSorting, actNum)
+    actID = actInfo.get(ShareDefine.ActKey_ID, 0)
+    state = actInfo.get(ShareDefine.ActKey_State, 0)
+    cfgID = actInfo.get(ShareDefine.ActKey_CfgID, 0)
+    
+    playerActID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageSortingID % actNum) # 玩家身上的活动ID
+    
+    # 活动ID 相同的话不处理
+    if actID == playerActID:
+        GameWorld.DebugLog("垃圾分类活动ID不变,不处理!actNum=%s,actID=%s" % (actNum, actID), playerID)
+        return
+    
+    actWorldLV = actInfo.get(ShareDefine.ActKey_WorldLV, 0)
+    
+    GameWorld.DebugLog("垃圾分类重置! actNum=%s,actID=%s,playerActID=%s,state=%s,cfgID=%s" 
+                       % (actNum, actID, playerActID, state, cfgID), playerID)
+    
+    guideTaskID = IpyGameDataPY.GetFuncCfg("GarbageSorting", 1)
+    if guideTaskID:
+        if state:
+            curMission = QuestCommon.AddNewMission(curPlayer, guideTaskID)
+            if curMission:
+                QuestCommon.SetPlayerMissionState(curPlayer, curMission, 1)
+        else:
+            QuestCommon.DeleteMission(curPlayer, guideTaskID)
+            
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageSortingID % actNum, actID)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageSortingWorldLV % actNum, actWorldLV)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageGuideState % actNum, 0)
+    for taskID in ChConfig.GarbageTaskList:
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageTaskValue % (actNum, taskID), 0)
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageTaskFinishCount % (actNum, taskID), 0)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageEnvironmentValue % actNum, 0)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageEnvironmentValueHis % actNum, 0)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageAwardLayerInfo % actNum, 0)
+    
+    ipyData = IpyGameDataPY.GetIpyGameData("ActGarbageSorting", cfgID) if cfgID else None
+    templateID = ipyData.GetTemplateID() if ipyData else 0
+    awardIpyDataList = IpyGameDataPY.GetIpyGameDataList("ActGarbageAward", templateID) if templateID else []
+    if awardIpyDataList:
+        for awardIpyData in awardIpyDataList:
+            libType = awardIpyData.GetAwardLibType()
+            libItemCount = awardIpyData.GetAwardItemCount()
+            for num in xrange(libItemCount):
+                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageAwardItemInfo % (actNum, libType, num), 0)
+                
+            itemAwardTimesTotalInfo = awardIpyData.GetItemAwardTimesTotalInfo()
+            for itemID in itemAwardTimesTotalInfo.keys():
+                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageAwardItemTimes % (actNum, libType, itemID), 0)
+                
+        # 活动中,生成新奖池    
+        if state:
+            __RefreshGarbageAwardPool(curPlayer, actInfo, awardIpyDataList)
+            
+    Sync_GarbageSortingActionInfo(curPlayer, actNum)
+    Sync_GarbageSortingPlayerInfo(curPlayer, actNum)
+    Sync_GarbageTaskInfo(curPlayer, actNum)
+    return True
+
+def OnFinishTask(curPlayer, taskID):
+    guideTaskID = IpyGameDataPY.GetFuncCfg("GarbageSorting", 1)
+    if not guideTaskID:
+        return
+    
+    if taskID != guideTaskID:
+        return
+    
+    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_GarbageSorting, {}).values():
+        if not actInfo.get(ShareDefine.ActKey_State):
+            continue
+        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageGuideState % actNum, 1)
+        Sync_GarbageSortingPlayerInfo(curPlayer, actNum)
+        
+    return
+
+def AddActGarbageTaskProgress(curPlayer, taskID, addValue=1, valueInfo=None):
+    ## 增加垃圾收集任务进度
+    # @param valueInfo: taskID 对应的自定义扩展信息值
+    if addValue <= 0:
+        return
+    
+    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_GarbageSorting, {}).values():
+        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
+        if not actInfo.get(ShareDefine.ActKey_State):
+            #GameWorld.DebugLog("垃圾分类活动未开启! actNum=%s" % actNum)
+            continue
+        
+        if taskID == ChConfig.Def_GarbageTask_CTG:
+            cfgID = actInfo.get(ShareDefine.ActKey_CfgID, 0)
+            if not cfgID:
+                continue
+            
+            ipyData = IpyGameDataPY.GetIpyGameData("ActGarbageSorting", cfgID)
+            if not ipyData:
+                continue
+            
+            coinType = valueInfo
+            ctgTypeEffValue = ipyData.GetCTGTypeEffValue()
+            if not ctgTypeEffValue & pow(2, coinType):
+                #GameWorld.DebugLog("垃圾分类活动充值类型对该活动无效! actNum=%s,coinType=%s,ctgTypeEffValue=%s" 
+                #                   % (actNum, coinType, ctgTypeEffValue), curPlayer.GetPlayerID())
+                continue
+            
+        taskIpyData = IpyGameDataPY.GetIpyGameData("ActGarbageTask", taskID)
+        if not taskIpyData:
+            continue
+        maxFinishCount = taskIpyData.GetFinishTimeMax()
+        maxValue = ChConfig.Def_UpperLimit_DWord
+        if maxFinishCount:
+            maxValue = min(maxValue, taskIpyData.GetFinishNeedValue() * maxFinishCount)
+            
+        curValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageTaskValue % (actNum, taskID))
+        updValue = min(curValue + addValue, maxValue)
+        if curValue >= maxValue:
+            #GameWorld.DebugLog("该垃圾分类活动任务已达到最大进度值!actNum=%s,taskID=%s,curValue(%s) >= maxValue(%s)" 
+            #                   % (actNum, taskID, curValue, maxValue))
+            continue
+        
+        #GameWorld.DebugLog("增加垃圾分类活动任务进度: actNum=%s,taskID=%s,curValue=%s,addValue=%s,updValue=%s" 
+        #                   % (actNum, taskID, curValue, addValue, updValue))
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageTaskValue % (actNum, taskID), updValue)
+        
+        # 完成时自动产生垃圾
+        if taskIpyData.GetAutoProduce():
+            if __DoCheckFinishGarbageTask(curPlayer, actNum, taskID, taskIpyData):
+                continue
+            
+        Sync_GarbageTaskInfo(curPlayer, actNum, taskID)
+        
+    return
+
+def __DoCheckFinishGarbageTask(curPlayer, actNum, taskID, taskIpyData=None):
+    ## 检查完成垃圾收集任务
+    
+    if not taskIpyData:
+        taskIpyData = IpyGameDataPY.GetIpyGameData("ActGarbageTask", taskID)
+    if not taskIpyData:
+        return
+    curFinishCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageTaskFinishCount % (actNum, taskID))
+    maxFinishCount = taskIpyData.GetFinishTimeMax()
+    if maxFinishCount and curFinishCount >= maxFinishCount:
+        GameWorld.DebugLog("该垃圾分类活动任务已达到最大完成次数!actNum=%s,taskID=%s,curFinishCount=%s" % (actNum, taskID, curFinishCount))
+        return
+    
+    curValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageTaskValue % (actNum, taskID))
+    updFinishCount = curValue / taskIpyData.GetFinishNeedValue()
+    if maxFinishCount:
+        updFinishCount = min(maxFinishCount, updFinishCount)
+    addFinishCount = updFinishCount - curFinishCount
+    if addFinishCount <= 0:
+        #GameWorld.DebugLog("垃圾分类活动任务未完成,无法领取!actNum=%s,taskID=%s,curValue=%s,curFinishCount=%s,updFinishCount=%s" 
+        #                   % (actNum, taskID, curValue, curFinishCount, updFinishCount))
+        return
+    
+    #GameWorld.DebugLog("垃圾分类活动任务完成,给奖励! actNum=%s,taskID=%s,curValue=%s,curFinishCount=%s,addFinishCount=%s,updFinishCount=%s" 
+    #                   % (actNum, taskID, curValue, curFinishCount, addFinishCount, updFinishCount))
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageTaskFinishCount % (actNum, taskID), updFinishCount)
+    
+    # 给垃圾收集奖励
+    giveItemDict = {}
+    rateList = taskIpyData.GetProduceGarbageRateList()
+    for _ in xrange(addFinishCount):
+        itemInfo = GameWorld.GetResultByRandomList(rateList)
+        if not itemInfo:
+            continue
+        itemID, itemCount, isAuctionItem = itemInfo
+        befItemCount = giveItemDict[itemID][1] if itemID in giveItemDict else 0
+        giveItemDict[itemID] = [itemID, befItemCount + itemCount, isAuctionItem]
+    giveItemList = giveItemDict.values()
+    
+    ItemControler.GivePlayerItemOrMail(curPlayer, giveItemList)
+    
+    Sync_GarbageTaskInfo(curPlayer, actNum, taskID, giveItemList)
+    return True
+
+#// AA 14 垃圾分类活动分类垃圾 #tagCMActGarbageSorting
+#
+#struct    tagCMActGarbageSorting
+#{
+#    tagHead        Head;
+#    BYTE        ActNum;        //活动编号
+#    BYTE        GarbageSortingType;    //垃圾分类类型,即属于哪种垃圾
+#    BYTE        ItemIndexCount;        //垃圾背包中的物品索引数
+#    BYTE        ItemIndexList[ItemIndexCount];    //垃圾背包中的物品索引列表
+#};
+def OnActGarbageSorting(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    actNum = clientData.ActNum
+    sortingType = clientData.GarbageSortingType
+    itemIndexList = clientData.ItemIndexList
+    
+    playerID = curPlayer.GetPlayerID()
+    
+    GameWorld.DebugLog("垃圾分类投放: sortingType=%s,itemIndexList=%s" % (sortingType, itemIndexList), playerID)
+    
+    environmentValueInfo = IpyGameDataPY.GetFuncEvalCfg("GarbageSorting", 2)
+    addEnvValueTotal = 0
+    garbagePack = curPlayer.GetItemManager().GetPack(ShareDefine.rptGarbage)
+    for index in itemIndexList:
+        if index >= garbagePack.GetCount():
+            continue
+        curItem = garbagePack.GetAt(index)
+        if not ItemCommon.CheckItemCanUse(curItem):
+            continue
+        itemID = curItem.GetItemTypeID()
+        itemSortingType = curItem.GetEffectByIndex(0).GetEffectValue(0)
+        if sortingType == itemSortingType:
+            delCount = curItem.GetCount()
+            addEnvValue = environmentValueInfo[0] * delCount
+            PlayerControl.NotifyCode(curPlayer, "GarbageSortingRight", [addEnvValue])
+        else:
+            delCount = 1 # 错误只扣除1一个
+            addEnvValue = environmentValueInfo[1] * delCount
+            PlayerControl.NotifyCode(curPlayer, "GarbageSortingWrong", [addEnvValue])
+            
+        ItemControler.SetItemCount(curItem, max(0, curItem.GetCount() - delCount))
+        addEnvValueTotal += addEnvValue
+        GameWorld.DebugLog("    index=%s,itemID=%s,itemSortingType=%s,delCount=%s,addEnvValue=%s" 
+                           % (index, itemID, itemSortingType, delCount, addEnvValue), playerID)
+        
+    if not addEnvValueTotal:
+        return
+    
+    curEnvValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageEnvironmentValue % actNum) + addEnvValueTotal
+    hisEnvValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageEnvironmentValueHis % actNum) + addEnvValueTotal
+    
+    GameWorld.DebugLog("    addEnvValueTotal=%s,curEnvValue=%s,hisEnvValue=%s" % (addEnvValueTotal, curEnvValue, hisEnvValue), playerID)
+    
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageEnvironmentValue % actNum, curEnvValue)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageEnvironmentValueHis % actNum, hisEnvValue)
+    
+    PlayerBillboard.UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_Environment, hisEnvValue)
+    
+    Sync_GarbageSortingPlayerInfo(curPlayer, actNum)
+    return
+
+
+#// AA 15 垃圾分类活动收集已完成的任务垃圾 #tagCMActGarbageGetTaskAward
+#
+#struct    tagCMActGarbageGetTaskAward
+#{
+#    tagHead        Head;
+#    BYTE        ActNum;        //活动编号
+#    BYTE        GarbageTaskID;    //垃圾任务ID
+#};
+def OnActGarbageGetTaskAward(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    actNum = clientData.ActNum
+    taskID = clientData.GarbageTaskID
+    __DoCheckFinishGarbageTask(curPlayer, actNum, taskID)
+    return
+
+
+#// AA 16 垃圾分类活动选择大奖 #tagCMActGarbageChooseSuperItem
+#
+#struct    tagCMActGarbageChooseSuperItem
+#{
+#    tagHead        Head;
+#    BYTE        ActNum;        //活动编号
+#    BYTE        SuperItemCount;    //选择物品数量
+#    DWORD        SuperItemIDList[SuperItemCount];    //选择的大奖库物品ID列表,每次重新选择需要发送全部已选择的大奖物品ID,不能只发单个物品ID;
+#};
+def OnActGarbageChooseSuperItem(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    actNum = clientData.ActNum
+    superItemIDList = clientData.SuperItemIDList
+    
+    GameWorld.DebugLog("垃圾分类活动选择大奖: actNum=%s,superItemIDList=%s" % (actNum, superItemIDList))
+    
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_GarbageSorting, actNum)
+    if not actInfo.get(ShareDefine.ActKey_State):
+        return
+    
+    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
+    ipyData = IpyGameDataPY.GetIpyGameData("ActGarbageSorting", cfgID)
+    if not ipyData:
+        return
+    
+    templateID = ipyData.GetTemplateID()
+    if not templateID:
+        return
+    
+    actWorldLV = actInfo.get(ShareDefine.ActKey_WorldLV, 0)
+    awardIpyDataList = IpyGameDataPY.GetIpyGameDataList("ActGarbageAward", templateID)
+    if not awardIpyDataList:
+        return
+    
+    superAwardIpyData = None
+    for awardIpyData in awardIpyDataList:
+        libType = awardIpyData.GetAwardLibType()
+        if libType == Def_SuperLibType:
+            superAwardIpyData = awardIpyData
+            break
+    
+    if not superAwardIpyData:
+        GameWorld.ErrLog("没有配置垃圾分类活动大奖库! cfgID=%s,actNum=%s,templateID=%s" % (cfgID, actNum, templateID))
+        return
+    
+    superLibItemCount = superAwardIpyData.GetAwardItemCount()
+    if len(superItemIDList) != superLibItemCount:
+        GameWorld.ErrLog("垃圾分类活动选择大奖个数错误! cfgID=%s,actNum=%s,templateID=%s,superLibItemCount=%s,reqSuperItemIDList=%s" 
+                         % (cfgID, actNum, templateID, superLibItemCount, superItemIDList))        
+        return
+    
+    posNumItemIDList = [] # 已抽中的大奖物品ID
+    libType = superAwardIpyData.GetAwardLibType()
+    for num in xrange(superLibItemCount):
+        itemInfoValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageAwardItemInfo % (actNum, libType, num))
+        if not itemInfoValue:
+            break
+        itemID, posNum = itemInfoValue / 100, itemInfoValue % 100
+        if posNum and itemID not in superItemIDList:
+            GameWorld.ErrLog("垃圾分类活动选择大奖ID错误! 已抽中的大奖ID为必选ID! posNum=%s, itemID=%s not in superItemIDList=%s" 
+                             % (posNum, itemID, superItemIDList))
+            return
+        
+        if posNum:
+            posNumItemIDList.append(itemID)
+            
+    GameWorld.DebugLog("    已抽中的大奖ID! %s" % posNumItemIDList)
+    
+    layerInfoValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageAwardLayerInfo % actNum)
+    layerNum = layerInfoValue % 100
+    
+    libItemDict = __GetGarbageAwardLibItem(superAwardIpyData.GetLibItemInfo(), actWorldLV)
+    layerLimitInfo = superAwardIpyData.GetItemLayerLimitInfo()
+    awardTimesTotalInfo = superAwardIpyData.GetItemAwardTimesTotalInfo()
+    
+    replaceSuperItemIDList = [] # 需要替换的大奖ID列表
+    
+    for selectItemID in superItemIDList:
+        if selectItemID in posNumItemIDList:
+            GameWorld.DebugLog("        已抽中的大奖ID,不验证!selectItemID=%s" % (selectItemID))
+            continue
+        
+        if selectItemID not in libItemDict:
+            GameWorld.ErrLog("垃圾分类活动选择大奖ID错误! 大奖ID不存在大奖库中! selectItemID=%s not in libItemDict=%s" 
+                             % (selectItemID, libItemDict))
+            return
+        
+        layerLimit = layerLimitInfo.get(selectItemID, 0)
+        if layerLimit > layerNum:
+            GameWorld.ErrLog("垃圾分类活动选择大奖ID错误! 大奖ID该层不能选择! selectItemID=%s layerLimit(%s) > layerNum(%s)" 
+                             % (selectItemID, layerLimit, layerNum))
+            return
+        
+        totalTimesLimit = awardTimesTotalInfo.get(selectItemID, 0)
+        if totalTimesLimit:
+            totalTimesNow = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageAwardItemTimes % (actNum, libType, selectItemID))
+            if totalTimesNow >= totalTimesLimit:
+                GameWorld.ErrLog("垃圾分类活动选择大奖ID错误! 大奖ID已达到最大奖励次数,不能选择! selectItemID=%s totalTimesNow(%s) >= totalTimesLimit(%s)" 
+                                 % (selectItemID, totalTimesNow, totalTimesLimit))
+                return
+                
+        replaceSuperItemIDList.append(selectItemID)
+        
+    GameWorld.DebugLog("    验证通过,可替换大奖ID! replaceSuperItemIDList=%s" % replaceSuperItemIDList)
+    if not replaceSuperItemIDList:
+        return
+    
+    for num in xrange(superLibItemCount):
+        itemInfoValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageAwardItemInfo % (actNum, libType, num))
+        itemID, posNum = itemInfoValue / 100, itemInfoValue % 100
+        if itemID in posNumItemIDList:
+            GameWorld.DebugLog("        已抽中的大奖ID,不替换!itemID=%s" % (itemID))
+            continue
+        replaceSuperItemID = replaceSuperItemIDList.pop(0)
+        updItemInfoValue = replaceSuperItemID * 100 + posNum
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageAwardItemInfo % (actNum, libType, num), updItemInfoValue)
+        GameWorld.DebugLog("        替换大奖ID选择!num=%s,itemID=%s,posNum=%s,replaceSuperItemID=%s,updItemInfoValue=%s" 
+                           % (num, itemID, posNum, replaceSuperItemID, updItemInfoValue))
+        
+        if not replaceSuperItemIDList:
+            break
+        
+    Sync_GarbageSortingActionInfo(curPlayer, actNum)
+    return
+
+#// AA 18 垃圾分类活动奖池刷新 #tagCMGarbageAwardPoolRefresh
+#
+#struct    tagCMGarbageAwardPoolRefresh
+#{
+#    tagHead        Head;
+#    BYTE        ActNum;        //活动编号
+#};
+def OnActGarbageAwardPoolRefresh(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    actNum = clientData.ActNum
+    
+    GameWorld.DebugLog("垃圾分类活动奖池刷新: actNum=%s" % (actNum))
+    
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_GarbageSorting, actNum)
+    if not actInfo.get(ShareDefine.ActKey_State):
+        return
+    
+    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
+    ipyData = IpyGameDataPY.GetIpyGameData("ActGarbageSorting", cfgID)
+    if not ipyData:
+        return
+    
+    templateID = ipyData.GetTemplateID()
+    if not templateID:
+        return
+    
+    awardIpyDataList = IpyGameDataPY.GetIpyGameDataList("ActGarbageAward", templateID)
+    if not awardIpyDataList:
+        return
+    
+    if not __RefreshGarbageAwardPool(curPlayer, actInfo, awardIpyDataList):
+        return
+    
+    Sync_GarbageSortingActionInfo(curPlayer, actNum)
+    return
+
+def __RefreshGarbageAwardPool(curPlayer, actInfo, awardIpyDataList):
+    ## 刷新垃圾收集环保奖池物品
+    
+    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
+    actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
+    actWorldLV = actInfo.get(ShareDefine.ActKey_WorldLV, 0)
+    
+    layerInfoValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageAwardLayerInfo % actNum)
+    layerNum = layerInfoValue % 100
+    
+    GameWorld.DebugLog("刷新垃圾收集环保奖池物品: cfgID=%s,actNum=%s,actWorldLV=%s,layerNum=%s" % (cfgID, actNum, actWorldLV, layerNum))
+    
+    if layerNum:
+        # 非0层,验证大奖是否已抽完,抽完才可以刷新奖池层
+        superLib = False
+        for awardIpyData in awardIpyDataList:
+            libType = awardIpyData.GetAwardLibType()
+            if libType != Def_SuperLibType:
+                continue
+            superLib = True
+            libItemCount = awardIpyData.GetAwardItemCount()
+            for num in xrange(libItemCount):
+                itemInfoValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageAwardItemInfo % (actNum, libType, num))
+                itemID, posNum = itemInfoValue / 100, itemInfoValue % 100
+                if itemID and not posNum:
+                    GameWorld.ErrLog("有大奖未抽中!无法刷新环保奖池! cfgID=%s,actNum=%s,layerNum=%s,num=%s,itemID=%s,posNum=%s" 
+                                     % (cfgID, actNum, layerNum, num, itemID, posNum))
+                    return
+            break
+        if not superLib:
+            GameWorld.ErrLog("奖池配置没有大奖库!无法刷新环保奖池! cfgID=%s,actNum=%s,layerNum=%s,superLib=%s" % (cfgID, actNum, layerNum, superLib))
+            return
+        
+    layerNum += 1 # 可刷新奖池,默认+1层
+    GameWorld.DebugLog("    可刷新奖池!下一层: layerNum=%s" % (layerNum))
+    
+    refreshLibDict = {}
+    for awardIpyData in awardIpyDataList:
+        libType = awardIpyData.GetAwardLibType()
+        libItemCount = awardIpyData.GetAwardItemCount()
+        libItemDict = __GetGarbageAwardLibItem(awardIpyData.GetLibItemInfo(), actWorldLV)
+        layerLimitInfo = awardIpyData.GetItemLayerLimitInfo()
+        awardTimesTotalInfo = awardIpyData.GetItemAwardTimesTotalInfo()
+        
+        canRandItemDict = {}
+        for itemID, libItemInfo in libItemDict.items():
+            _, weight = libItemInfo
+            
+            layerLimit = layerLimitInfo.get(itemID, 0)
+            if layerLimit > layerNum:
+                GameWorld.DebugLog("        该层不能选择该奖品! itemID=%s layerLimit(%s) > layerNum(%s)" 
+                                 % (itemID, layerLimit, layerNum))
+                continue
+            
+            totalTimesLimit = awardTimesTotalInfo.get(itemID, 0)
+            if totalTimesLimit:
+                totalTimesNow = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageAwardItemTimes % (actNum, libType, itemID))
+                if totalTimesNow >= totalTimesLimit:
+                    GameWorld.DebugLog("        奖品ID已达到最大奖励次数,不能选择! itemID=%s totalTimesNow(%s) >= totalTimesLimit(%s)" 
+                                       % (itemID, totalTimesNow, totalTimesLimit))
+                    continue
+                
+            canRandItemDict[itemID] = [weight, itemID]
+            
+        if libItemCount > len(canRandItemDict):
+            GameWorld.ErrLog("奖品库配置可选择奖品个数不够!无法刷新环保奖池! cfgID=%s,actNum=%s,libType=%s,layerNum=%s,libItemCount=%s > %s canRandItemDict(%s)" 
+                             % (cfgID, actNum, libType, layerNum, libItemCount, len(canRandItemDict), canRandItemDict))
+            return
+        
+        refreshLibDict[libType] = [libItemCount, canRandItemDict]
+        
+    for libType, refreshInfo in refreshLibDict.items():
+        libItemCount, canRandItemDict = refreshInfo
+        GameWorld.DebugLog("    随机奖池物品: libType=%s,libItemCount=%s,canRandItemDict=%s, %s" % (libType, libItemCount, len(canRandItemDict), canRandItemDict))
+        
+        if libType == Def_SuperLibType:
+            # 大奖直接重置,系统不生成,由玩家手动选择
+            for num in xrange(libItemCount):
+                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageAwardItemInfo % (actNum, libType, num), 0)
+            continue
+        
+        for num in xrange(libItemCount):
+            weightList = canRandItemDict.values()
+            randItemID = GameWorld.GetResultByWeightList(weightList)
+            canRandItemDict.pop(randItemID, None)
+            
+            posNum = 0
+            itemInfoValue = randItemID * 100 + posNum
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageAwardItemInfo % (actNum, libType, num), itemInfoValue)
+            GameWorld.DebugLog("        随机生成奖品! libType=%s,num=%s,randItemID=%s" % (libType, num, randItemID))
+            
+    playCount = 0 # 每层重置抽奖次数
+    layerInfoValue = playCount * 100 + layerNum
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageAwardLayerInfo % actNum, layerInfoValue)
+    GameWorld.DebugLog("    刷新完成! playCount=%s,layerNum=%s,layerInfoValue=%s" % (playCount, layerNum, layerInfoValue))
+    return True
+
+#// AA 17 垃圾分类活动抽奖 #tagCMActGarbageLottery
+#
+#struct    tagCMActGarbageLottery
+#{
+#    tagHead        Head;
+#    BYTE        ActNum;        //活动编号
+#    BYTE        PosNum;        //玩家点击的奖励位置编号,从1开始
+#};
+def OnActGarbageLottery(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    actNum = clientData.ActNum
+    reqPosNum = clientData.PosNum
+    
+    GameWorld.DebugLog("垃圾分类活动抽奖: actNum=%s,reqPosNum=%s" % (actNum, reqPosNum))
+    
+    if reqPosNum <= 0:
+        return
+    
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_GarbageSorting, actNum)
+    if not actInfo.get(ShareDefine.ActKey_State):
+        return
+    
+    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
+    ipyData = IpyGameDataPY.GetIpyGameData("ActGarbageSorting", cfgID)
+    if not ipyData:
+        return
+    
+    templateID = ipyData.GetTemplateID()
+    if not templateID:
+        return
+    
+    actWorldLV = actInfo.get(ShareDefine.ActKey_WorldLV, 0)
+    awardIpyDataList = IpyGameDataPY.GetIpyGameDataList("ActGarbageAward", templateID)
+    if not awardIpyDataList:
+        return
+    
+    costEnvValue = IpyGameDataPY.GetFuncCfg("GarbageSorting", 3)
+    curEnvValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageEnvironmentValue % actNum)
+    if curEnvValue < costEnvValue:
+        GameWorld.DebugLog("    环保值不足,无法抽奖! curEnvValue(%s) < costEnvValue(%s)" % (curEnvValue, costEnvValue))
+        return
+    
+    layerInfoValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageAwardLayerInfo % actNum)
+    playCount, layerNum = layerInfoValue / 100, layerInfoValue % 100
+    
+    posNumMax = 0
+    randLibItemDict = {}
+    for awardIpyData in awardIpyDataList:
+        libType = awardIpyData.GetAwardLibType()
+        libItemCount = awardIpyData.GetAwardItemCount()
+        unlockLimitTimes = awardIpyData.GetUnlockAwardLimitTimes()
+        libWeight = awardIpyData.GetAwardLibWeight()
+        posNumMax += libItemCount
+        
+        if libType == Def_SuperLibType:
+            for num in xrange(libItemCount):
+                itemInfoValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageAwardItemInfo % (actNum, libType, num))
+                if not itemInfoValue:
+                    GameWorld.DebugLog("    未选择大奖!无法抽奖! libType=%s,num=%s,itemInfoValue=%s" % (libType, num, itemInfoValue))         
+                    return
+                
+        if unlockLimitTimes and playCount < unlockLimitTimes:
+            GameWorld.DebugLog("    该库当前抽奖次数无法解锁! libType=%s,playCount(%s) < unlockLimitTimes(%s)" % (libType, playCount, unlockLimitTimes))
+            continue
+        
+        awardTimesTotalInfo = awardIpyData.GetItemAwardTimesTotalInfo()
+        libItemDict = __GetGarbageAwardLibItem(awardIpyData.GetLibItemInfo(), actWorldLV)
+        canRandItemList = []
+        for num in xrange(libItemCount):
+            itemInfoValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageAwardItemInfo % (actNum, libType, num))
+            if not itemInfoValue:            
+                return
+            
+            itemID, posNum = itemInfoValue / 100, itemInfoValue % 100
+            if itemID not in libItemDict:
+                continue
+            
+            if posNum:
+                GameWorld.DebugLog("    该奖品已被抽中! libType=%s,itemID=%s,posNum=%s" % (libType, itemID, posNum))
+                if posNum == reqPosNum:
+                    GameWorld.ErrLog("    该位置已经有抽奖结果,无法重复选择抽奖! libType=%s,num=%s,itemInfoValue=%s,posNum=%s" 
+                                     % (libType, num, itemInfoValue, posNum))                
+                    return                
+                continue
+            
+            itemCount, weight = libItemDict[itemID]
+            isAddTimes = (itemID in awardTimesTotalInfo)
+            canRandItemList.append([weight, itemID, itemCount, num, isAddTimes])
+            
+        if canRandItemList:
+            randLibItemDict[libType] = [libWeight, libType, canRandItemList]
+            GameWorld.DebugLog("        该库有机会抽到物品: libType=%s,libWeight=%s,canRandItemList=%s" % (libType, libWeight, canRandItemList))
+        else:
+            GameWorld.DebugLog("        该库物品已全被抽完: libType=%s,libWeight=%s,canRandItemList=%s" % (libType, libWeight, canRandItemList))
+            
+    if reqPosNum > posNumMax:
+        GameWorld.DebugLog("    请求位置异常,无法抽奖! reqPosNum(%s) > posNumMax(%s)" % (reqPosNum, posNumMax))
+        return
+    
+    if not randLibItemDict:
+        GameWorld.DebugLog("    没有可抽奖的奖品了,无法抽奖!")
+        return
+    
+    randLibInfo = GameWorld.GetResultByWeightList(randLibItemDict.values())
+    if not randLibInfo:
+        return
+    libType, canRandItemList = randLibInfo
+    randItemInfo = GameWorld.GetResultByWeightList(canRandItemList)
+    if not randItemInfo:
+        return
+    itemID, itemCount, num, isAddTimes = randItemInfo
+    
+    # 扣除抽奖消耗环保值
+    updEnvValue = curEnvValue - costEnvValue
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageEnvironmentValue % actNum, updEnvValue)
+    
+    # 更新已抽中值
+    updItemInfoValue = itemID * 100 + reqPosNum
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageAwardItemInfo % (actNum, libType, num), updItemInfoValue)
+    
+    totalTimesNow = 0
+    if isAddTimes:
+        totalTimesNow = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageAwardItemTimes % (actNum, libType, itemID)) + 1
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageAwardItemTimes % (actNum, libType, itemID), totalTimesNow)
+        
+    playCount += 1
+    layerInfoValue = playCount * 100 + layerNum
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GarbageAwardLayerInfo % actNum, layerInfoValue)
+    
+    GameWorld.DebugLog("    抽中物品: layerNum=%s,libType=%s,itemID=%s,itemCount=%s,num=%s,reqPosNum=%s,updItemInfoValue=%s,totalTimesNow=%s,updEnvValue=%s,playCount=%s(%s)" 
+                       % (layerNum, libType, itemID, itemCount, num, reqPosNum, updItemInfoValue, totalTimesNow, updEnvValue, playCount, layerInfoValue))
+    
+    # 给物品
+    isAuctionItem = 0
+    itemList = [[itemID, itemCount, isAuctionItem]]
+    ItemControler.GivePlayerItemOrMail(curPlayer, itemList, event=["ActGarbageLottery", False, {}])
+    
+    # 广播
+    if libType == Def_SuperLibType:
+        PlayerControl.WorldNotify(0, "GarbageSorting%s" % actNum, [curPlayer.GetPlayerName(), itemID, itemCount])
+        
+    # 通知
+    awardItemInfo = [libType, itemID, itemCount, reqPosNum, totalTimesNow]
+    Sync_GarbageSortingPlayerInfo(curPlayer, actNum, awardItemInfo)
+    return
+
+def Sync_GarbageTaskInfo(curPlayer, actNum, taskID=0, awardItemList=None):
+    ## 通知垃圾收集任务信息
+    syncTaskIDList = [taskID] if taskID else ChConfig.GarbageTaskList
+    clientPack = ChPyNetSendPack.tagMCActGarbageTaskInfo()
+    clientPack.ActNum = actNum
+    clientPack.GarbageTaskList = []
+    for taskID in syncTaskIDList:
+        task = ChPyNetSendPack.tagMCActGarbageTask()
+        task.GarbageTaskID = taskID
+        task.GarbageTaskValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageTaskValue % (actNum, taskID))
+        task.GarbageTaskFinishCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageTaskFinishCount % (actNum, taskID))
+        clientPack.GarbageTaskList.append(task)
+    clientPack.GarbageTaskCount = len(clientPack.GarbageTaskList)
+    
+    if awardItemList:
+        for itemID, itemCount, _ in awardItemList:
+            item = ChPyNetSendPack.tagMCActGarbageTaskItem()
+            item.ItemID = itemID
+            item.ItemCount = itemCount
+            clientPack.GarbageTaskItemList.append(item)
+        clientPack.TaskItemCount = len(clientPack.GarbageTaskItemList)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+def Sync_GarbageSortingPlayerInfo(curPlayer, actNum, awardItemInfo=None):
+    ## 通知玩家数据信息
+    # @param awardItemInfo: 抽奖物品信息 [libType, itemID, itemCount, posNum, totalTimesNow]
+    
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_GarbageSorting, actNum)
+    if not actInfo.get(ShareDefine.ActKey_State):
+        return
+    
+    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
+    ipyData = IpyGameDataPY.GetIpyGameData("ActGarbageSorting", cfgID)
+    if not ipyData:
+        return
+    
+    guideTaskID = IpyGameDataPY.GetFuncCfg("GarbageSorting", 1)
+    
+    clientPack = ChPyNetSendPack.tagMCActGarbagePlayerInfo()
+    clientPack.ActNum = actNum
+    clientPack.GuideTaskFinish = 1 if not guideTaskID else curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageGuideState % actNum)
+    clientPack.EnvironmentValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageEnvironmentValue % actNum)
+    clientPack.EnvironmentValueHis = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageEnvironmentValueHis % actNum)
+    
+    if awardItemInfo:
+        libType, itemID, itemCount, posNum, totalTimesNow = awardItemInfo
+        awardItem = ChPyNetSendPack.tagMCActGarbageAwardItemResult()
+        awardItem.ItemLibType = libType
+        awardItem.ItemID = itemID
+        awardItem.ItemCount = itemCount
+        awardItem.PosNum = posNum
+        awardItem.TotalTimesNow = totalTimesNow
+        clientPack.AwardItemResult = awardItem
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+def Sync_GarbageSortingActionInfo(curPlayer, actNum):
+    ## 通知活动信息
+    
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_GarbageSorting, actNum)
+    if not actInfo.get(ShareDefine.ActKey_State):
+        return
+    
+    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
+    ipyData = IpyGameDataPY.GetIpyGameData("ActGarbageSorting", cfgID)
+    if not ipyData:
+        return
+    
+    templateID = ipyData.GetTemplateID()
+    if not templateID:
+        return
+    
+    actWorldLV = actInfo.get(ShareDefine.ActKey_WorldLV, 0)
+    openServerDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay) + 1
+    
+    layerInfoValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageAwardLayerInfo % actNum)
+    layerNum = layerInfoValue % 100
+    
+    clientPack = ChPyNetSendPack.tagMCActGarbageSortingInfo()
+    clientPack.ActNum = actNum
+    clientPack.StartDate = GameWorld.GetOperationActionDateStr(ipyData.GetStartDate(), openServerDay)
+    clientPack.EndtDate = GameWorld.GetOperationActionDateStr(ipyData.GetEndDate(), openServerDay)
+    clientPack.LimitLV = ipyData.GetLVLimit()
+    clientPack.LayerNum = layerNum
+    clientPack.AwardItemList = [] # 奖池物品列表
+    awardIpyDataList = IpyGameDataPY.GetIpyGameDataList("ActGarbageAward", templateID)
+    if awardIpyDataList:
+        for awardIpyData in awardIpyDataList:
+            libType = awardIpyData.GetAwardLibType()
+            libItemCount = awardIpyData.GetAwardItemCount()
+            libItemDict = __GetGarbageAwardLibItem(awardIpyData.GetLibItemInfo(), actWorldLV)
+            layerLimitInfo = awardIpyData.GetItemLayerLimitInfo()
+            awardTimesTotalInfo = awardIpyData.GetItemAwardTimesTotalInfo()
+            
+            # 奖池物品列表,已生成的,包含已选择的大奖物品
+            for num in xrange(libItemCount):
+                itemInfoValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageAwardItemInfo % (actNum, libType, num))
+                if not itemInfoValue:
+                    break
+                itemID, posNum = itemInfoValue / 100, itemInfoValue % 100
+                if itemID not in libItemDict:
+                    continue
+                libItemInfo = libItemDict[itemID]
+                
+                awardItem = ChPyNetSendPack.tagMCActGarbageAwardItem()
+                awardItem.ItemLibType = libType
+                awardItem.ItemID = itemID
+                awardItem.ItemCount = libItemInfo[0]
+                awardItem.PosNum = posNum
+                awardItem.TotalTimesMax = awardTimesTotalInfo.get(itemID, 0)
+                awardItem.TotalTimesNow = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GarbageAwardItemTimes % (actNum, libType, itemID))
+                awardItem.LayerLimit = layerLimitInfo.get(itemID, 0)
+                clientPack.AwardItemList.append(awardItem)
+                
+            # 大奖物品待选择库,全部同步
+            if libType == Def_SuperLibType:
+                for itemID, libItemInfo in libItemDict.items():
+                    awardItem = ChPyNetSendPack.tagMCActGarbageAwardItem()
+                    awardItem.ItemLibType = libType
+                    awardItem.ItemID = itemID
+                    awardItem.ItemCount = libItemInfo[0]
+                    awardItem.TotalTimesMax = awardTimesTotalInfo.get(itemID, 0)
+                    awardItem.LayerLimit = layerLimitInfo.get(itemID, 0)
+                    clientPack.SuperItemList.append(awardItem)
+                clientPack.SuperItemCount = len(clientPack.SuperItemList)
+                clientPack.SuperItemCanChooseCount = libItemCount
+                
+    clientPack.AwardItemCount = len(clientPack.AwardItemList)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+def __GetGarbageAwardLibItem(libItemInfo, actWorldLV):
+    ## 获取奖励库物品信息字典,支持按世界等级范围配置的格式
+    keyList = libItemInfo.keys()
+    if not keyList:
+        return {}
+    if isinstance(keyList[0], tuple) and len(keyList[0]) == 2:
+        return GameWorld.GetDictValueByRangeKey(libItemInfo, actWorldLV, {})
+    return libItemInfo
+
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 9fe81cd..f683c33 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -80,6 +80,7 @@
 import PlayerRefineStove
 import PlayerFamilyTech
 import PlayerCostRebate
+import PlayerActGarbageSorting
 import GY_Query_CrossRealmReg
 import PlayerCrossRealmPK
 import FunctionNPCCommon
@@ -3174,6 +3175,7 @@
         PlayerCostRebate.AddCostRebateGold(curPlayer, costType, price, infoDict)
         PlayerFeastTravel.AddFeastTravelTaskValue(curPlayer, ChConfig.Def_FeastTravel_UseGold, price)
         PlayerActTurntable.OnPlayerUseGold(curPlayer, price)
+        PlayerActGarbageSorting.AddActGarbageTaskProgress(curPlayer, ChConfig.Def_GarbageTask_UseGold, price)
     else:
         GameWorld.DebugLog("不计入消费活动的消费类型!costType=%s" % costType, curPlayer.GetPlayerID())
         
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py
index 61cd3aa..5bcf74b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py
@@ -23,6 +23,7 @@
 import ChPyNetSendPack
 import CrossRealmPlayer
 import FunctionNPCCommon
+import PlayerActGarbageSorting
 import DataRecordPack
 import PlayerWeekParty
 import IPY_GameWorld
@@ -364,6 +365,7 @@
         PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_CrossReamPK)
         PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_CrossPK, 1)
         PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_FeastRedPack_CrossPK, 1)
+        PlayerActGarbageSorting.AddActGarbageTaskProgress(curPlayer, ChConfig.Def_GarbageTask_CrossPK)
     else:
         GameWorld.Log("    不同天的PK结算不增加今日PK次数! ", playerID)
         
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 11b4627..159b497 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -77,6 +77,7 @@
 import CrossActCTGBillboard
 import PlayerActCollectWords
 import PlayerActTotalRecharge
+import PlayerActGarbageSorting
 import PlayerActRechargeRebateGold
 import PlayerActManyDayRecharge
 import PlayerActSingleRecharge
@@ -1367,6 +1368,9 @@
             elif actionName == ShareDefine.OperationActionName_TotalRecharge:
                 PlayerActTotalRecharge.RefreshTotalRechargeActionInfo(actNum)
                 
+            elif actionName == ShareDefine.OperationActionName_GarbageSorting:
+                PlayerActGarbageSorting.RefreshGarbageSortingActionInfo(actNum)
+                
             elif actionName == ShareDefine.OperationActionName_ManyDayRecharge:
                 PlayerActManyDayRecharge.RefreshManyDayRechargeActionInfo(actNum)
                 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerRefineStove.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerRefineStove.py
index 6b44bc0..50930c2 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerRefineStove.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerRefineStove.py
@@ -31,6 +31,7 @@
 import PlayerActivity
 import PlayerFairyCeremony
 import PlayerNewFairyCeremony
+import PlayerActGarbageSorting
 import PlayerActLogin
 import PlayerVip
 
@@ -253,6 +254,7 @@
         PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_RefineStove, refineTimes)
         PlayerNewFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_RefineStove, refineTimes)
         PlayerActLogin.AddLoginAwardActionCnt(curPlayer, ChConfig.Def_LoginAct_Alchemy, refineTimes)
+        PlayerActGarbageSorting.AddActGarbageTaskProgress(curPlayer, ChConfig.Def_GarbageTask_RefineStove, refineTimes)
     return
 
 

--
Gitblit v1.8.0