From 155399cb710b8b7db0e8126baa9a664475c7b916 Mon Sep 17 00:00:00 2001
From: dolphin <dolphin@lindenlab.com>
Date: Thu, 1 May 2014 13:56:45 -0700
Subject: parcel experience lists can be manipulated through the
 ParcelAccessListUpdate   message

---
 indra/llinventory/llparcel.cpp      |  79 +++++++++++++--
 indra/llinventory/llparcel.h        |  21 +++-
 indra/llinventory/llparcelflags.h   |   6 +-
 indra/newview/llfloaterauction.cpp  |  33 ++----
 indra/newview/llfloaterauction.h    |   2 +-
 indra/newview/llfloaterland.cpp     |   8 +-
 indra/newview/llviewerparcelmgr.cpp | 193 ++++++++++++++++--------------------
 indra/newview/llviewerparcelmgr.h   |   4 +
 8 files changed, 194 insertions(+), 152 deletions(-)

diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp
index 5eb5fb442d..4261148cd6 100755
--- a/indra/llinventory/llparcel.cpp
+++ b/indra/llinventory/llparcel.cpp
@@ -40,6 +40,7 @@
 #include "llsdutil_math.h"
 #include "message.h"
 #include "u64.h"
+#include "llregionflags.h"
 
 static const F32 SOME_BIG_NUMBER = 1000.0f;
 static const F32 SOME_BIG_NEG_NUMBER = -1000.0f;
@@ -627,8 +628,8 @@ void LLParcel::unpackMessage(LLMessageSystem* msg)
 void LLParcel::packAccessEntries(LLMessageSystem* msg,
 								 const std::map<LLUUID,LLAccessEntry>& list)
 {
-    access_map_const_iterator cit = list.begin();
-    access_map_const_iterator end = list.end();
+    LLAccessEntry::map::const_iterator cit = list.begin();
+    LLAccessEntry::map::const_iterator end = list.end();
     
     if (cit == end)
     {
@@ -679,9 +680,28 @@ void LLParcel::unpackAccessEntries(LLMessageSystem* msg,
 }
 
 
+void LLParcel::unpackExperienceEntries( LLMessageSystem* msg, U32 type )
+{
+	LLUUID id;
+
+	S32 i;
+	S32 count = msg->getNumberOfBlocksFast(_PREHASH_List);
+	for (i = 0; i < count; i++)
+	{
+		msg->getUUIDFast(_PREHASH_List, _PREHASH_ID, id, i);
+
+		if (id.notNull())
+		{
+			mExperienceKeys[id]=type;
+		}
+	}
+}
+
+
+
 void LLParcel::expirePasses(S32 now)
 {
-    access_map_iterator itor = mAccessList.begin();
+    LLAccessEntry::map::iterator itor = mAccessList.begin();
     while (itor != mAccessList.end())
     {
         const LLAccessEntry& entry = (*itor).second;
@@ -771,7 +791,7 @@ BOOL LLParcel::addToAccessList(const LLUUID& agent_id, S32 time)
 		// Can't add owner to these lists
 		return FALSE;
 	}
-	access_map_iterator itor = mAccessList.begin();
+	LLAccessEntry::map::iterator itor = mAccessList.begin();
 	while (itor != mAccessList.end())
 	{
 		const LLAccessEntry& entry = (*itor).second;
@@ -816,7 +836,7 @@ BOOL LLParcel::addToBanList(const LLUUID& agent_id, S32 time)
 		return FALSE;
 	}
     
-    access_map_iterator itor = mBanList.begin();
+    LLAccessEntry::map::iterator itor = mBanList.begin();
     while (itor != mBanList.end())
     {
         const LLAccessEntry& entry = (*itor).second;
@@ -852,7 +872,7 @@ BOOL remove_from_access_array(std::map<LLUUID,LLAccessEntry>* list,
                               const LLUUID& agent_id)
 {
     BOOL removed = FALSE;
-    access_map_iterator itor = list->begin();
+    LLAccessEntry::map::iterator itor = list->begin();
     while (itor != list->end())
     {
         const LLAccessEntry& entry = (*itor).second;
@@ -1097,7 +1117,8 @@ void LLParcel::clearParcel()
 void LLParcel::dump()
 {
     llinfos << "parcel " << mLocalID << " area " << mArea << llendl;
-    llinfos << "	 name <" << mName << ">" << llendl;
+
+	llinfos << "	 name <" << mName << ">" << llendl;
     llinfos << "	 desc <" << mDesc << ">" << llendl;
 }
 
@@ -1195,3 +1216,47 @@ LLParcel::ECategory category_ui_string_to_category(const std::string& s)
     // is a distinct option from "None" and "Other"
     return LLParcel::C_ANY;
 }
+
+LLAccessEntry::map LLParcel::getExperienceKeysByType( U32 type ) const
+{
+	LLAccessEntry::map access;
+	LLAccessEntry entry;
+	xp_type_map_t::const_iterator it = mExperienceKeys.begin();
+	for(/**/; it != mExperienceKeys.end(); ++it)
+	{
+		if(it->second == type)
+		{
+			entry.mID = it->first;
+			access[entry.mID] = entry;
+		}
+	}
+	return access;
+}
+
+void LLParcel::clearExperienceKeysByType( U32 type )
+{
+	xp_type_map_t::iterator it = mExperienceKeys.begin();
+	while(it != mExperienceKeys.end())
+	{
+		if(it->second == type)
+		{
+			mExperienceKeys.erase(it++);
+		}
+		else
+		{
+			++it;
+		}
+	}
+}
+
+void LLParcel::setExperienceKeyType( const LLUUID& experience_key, U32 type )
+{
+	if(type == EXPERIENCE_KEY_TYPE_NONE)
+	{
+		mExperienceKeys.erase(experience_key);
+	}
+	else
+	{
+		mExperienceKeys[experience_key] = type;
+	}
+}
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index c4363a48df..fe76531317 100755
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -130,9 +130,11 @@ class LLSD;
 class LLAccessEntry
 {
 public:
+
+	typedef std::map<LLUUID,LLAccessEntry> map;
+
 	LLAccessEntry()
-	:	mID(),
-		mTime(0),
+	:	mTime(0),
 		mFlags(0)
 	{}
 
@@ -141,8 +143,6 @@ public:
 	U32			mFlags;		// Not used - currently should always be zero
 };
 
-typedef std::map<LLUUID,LLAccessEntry>::iterator access_map_iterator;
-typedef std::map<LLUUID,LLAccessEntry>::const_iterator access_map_const_iterator;
 
 class LLParcel
 {
@@ -320,6 +320,9 @@ public:
 	void	unpackAccessEntries(LLMessageSystem* msg,
 								std::map<LLUUID,LLAccessEntry>* list);
 
+	void	unpackExperienceEntries(LLMessageSystem* msg, U32 type);
+
+
 	void	setAABBMin(const LLVector3& min)	{ mAABBMin = min; }
 	void	setAABBMax(const LLVector3& max)	{ mAABBMax = max; }
 
@@ -665,6 +668,16 @@ public:
 	std::map<LLUUID,LLAccessEntry>	mTempBanList;
 	std::map<LLUUID,LLAccessEntry>	mTempAccessList;
 
+	typedef std::map<LLUUID, U32> xp_type_map_t;
+
+	void setExperienceKeyType(const LLUUID& experience_key, U32 type);
+	U32 getExperienceKeyType(const LLUUID& experience_key)const;
+	LLAccessEntry::map getExperienceKeysByType(U32 type)const;
+	void clearExperienceKeysByType(U32 type);
+
+private:
+	xp_type_map_t mExperienceKeys;
+
 };
 
 
diff --git a/indra/llinventory/llparcelflags.h b/indra/llinventory/llparcelflags.h
index b1a917df73..25b27a281a 100755
--- a/indra/llinventory/llparcelflags.h
+++ b/indra/llinventory/llparcelflags.h
@@ -90,8 +90,10 @@ const U32 PF_DEFAULT =  PF_ALLOW_FLY
                         | PF_USE_ESTATE_VOICE_CHAN;
 
 // Access list flags
-const U32 AL_ACCESS  = (1 << 0);
-const U32 AL_BAN     = (1 << 1);
+const U32 AL_ACCESS				= (1 << 0);
+const U32 AL_BAN					= (1 << 1);
+const U32 AL_ALLOW_EXPERIENCE	= (1 << 3);
+const U32 AL_BLOCK_EXPERIENCE	= (1 << 4);
 //const U32 AL_RENTER  = (1 << 2);
 
 // Block access return values. BA_ALLOWED is the only success case
diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp
index 3c40e2d4bc..fb1c51557f 100755
--- a/indra/newview/llfloaterauction.cpp
+++ b/indra/newview/llfloaterauction.cpp
@@ -376,13 +376,16 @@ void LLFloaterAuction::doResetParcel()
 		msg->sendReliable(region->getHost());
 
 		// Clear the access lists
-		clearParcelAccessLists(parcelp, region);
+		clearParcelAccessList(parcelp, region, AL_ACCESS);
+		clearParcelAccessList(parcelp, region, AL_BAN);
+		clearParcelAccessList(parcelp, region, AL_ALLOW_EXPERIENCE);
+		clearParcelAccessList(parcelp, region, AL_BLOCK_EXPERIENCE);
 	}
 }
 
 
 
-void LLFloaterAuction::clearParcelAccessLists(LLParcel* parcel, LLViewerRegion* region)
+void LLFloaterAuction::clearParcelAccessList(LLParcel* parcel, LLViewerRegion* region, U32 list)
 {
 	if (!region || !parcel) return;
 
@@ -391,15 +394,12 @@ void LLFloaterAuction::clearParcelAccessLists(LLParcel* parcel, LLViewerRegion*
 
 	LLMessageSystem* msg = gMessageSystem;
 
-	// Clear access list
-	//	parcel->mAccessList.clear();
-
 	msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
 	msg->nextBlockFast(_PREHASH_AgentData);
 	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
 	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
 	msg->nextBlockFast(_PREHASH_Data);
-	msg->addU32Fast(_PREHASH_Flags, AL_ACCESS);
+	msg->addU32Fast(_PREHASH_Flags, list);
 	msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
 	msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
 	msg->addS32Fast(_PREHASH_SequenceID, 1);			// sequence_id
@@ -412,27 +412,6 @@ void LLFloaterAuction::clearParcelAccessLists(LLParcel* parcel, LLViewerRegion*
 	msg->addU32Fast(_PREHASH_Flags,	0 );
 
 	msg->sendReliable( region->getHost() );
-
-	// Send message for empty ban list
-	//parcel->mBanList.clear();
-	msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
-	msg->nextBlockFast(_PREHASH_AgentData);
-	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
-	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
-	msg->nextBlockFast(_PREHASH_Data);
-	msg->addU32Fast(_PREHASH_Flags, AL_BAN);
-	msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
-	msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
-	msg->addS32Fast(_PREHASH_SequenceID, 1);		// sequence_id
-	msg->addS32Fast(_PREHASH_Sections, 0);			// num_sections
-
-	// pack an empty block since there will be no data
-	msg->nextBlockFast(_PREHASH_List);
-	msg->addUUIDFast(_PREHASH_ID,  LLUUID::null );
-	msg->addS32Fast(_PREHASH_Time, 0 );
-	msg->addU32Fast(_PREHASH_Flags,	0 );
-
-	msg->sendReliable( region->getHost() );
 }
 
 
diff --git a/indra/newview/llfloaterauction.h b/indra/newview/llfloaterauction.h
index 9c0c0f7775..c83a11ba8b 100755
--- a/indra/newview/llfloaterauction.h
+++ b/indra/newview/llfloaterauction.h
@@ -67,7 +67,7 @@ private:
 
 	void doResetParcel();
 	void doSellToAnyone();
-	void clearParcelAccessLists( LLParcel* parcel, LLViewerRegion* region );
+	void clearParcelAccessList( LLParcel* parcel, LLViewerRegion* region, U32 list);
 	void cleanupAndClose();
 
 private:
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index b16ef6dd79..cced45ac26 100755
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -2398,7 +2398,7 @@ void LLPanelLandAccess::refresh()
 			getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count));
 			getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST));
 
-			for (access_map_const_iterator cit = parcel->mAccessList.begin();
+			for (LLAccessEntry::map::const_iterator cit = parcel->mAccessList.begin();
 				 cit != parcel->mAccessList.end(); ++cit)
 			{
 				const LLAccessEntry& entry = (*cit).second;
@@ -2444,7 +2444,7 @@ void LLPanelLandAccess::refresh()
 			getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count));
 			getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST));
 
-			for (access_map_const_iterator cit = parcel->mBanList.begin();
+			for (LLAccessEntry::map::const_iterator cit = parcel->mBanList.begin();
 				 cit != parcel->mBanList.end(); ++cit)
 			{
 				const LLAccessEntry& entry = (*cit).second;
@@ -2752,8 +2752,8 @@ void LLPanelLandAccess::callbackAvatarCBAccess(const uuid_vec_t& ids)
 		LLUUID id = ids[0];
 		LLParcel* parcel = mParcel->getParcel();
 		if (parcel)
-		{
-			parcel->addToAccessList(id, 0);
+		{			
+			parcel->addToAccessList(id, 0);		
 			LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(AL_ACCESS);
 			refresh();
 		}
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index e361fad9de..2fdae9d091 100755
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -205,8 +205,8 @@ void LLViewerParcelMgr::dump()
 	mCurrentParcel->dump();
 	llinfos << "banning " << mCurrentParcel->mBanList.size() << llendl;
 	
-	access_map_const_iterator cit = mCurrentParcel->mBanList.begin();
-	access_map_const_iterator end = mCurrentParcel->mBanList.end();
+	LLAccessEntry::map::const_iterator cit = mCurrentParcel->mBanList.begin();
+	LLAccessEntry::map::const_iterator end = mCurrentParcel->mBanList.end();
 	for ( ; cit != end; ++cit)
 	{
 		llinfos << "ban id " << (*cit).first << llendl;
@@ -892,7 +892,7 @@ void LLViewerParcelMgr::sendParcelAccessListRequest(U32 flags)
 	if (!region) return;
 
 	LLMessageSystem *msg = gMessageSystem;
-	
+
 
 	if (flags & AL_BAN) 
 	{
@@ -902,6 +902,14 @@ void LLViewerParcelMgr::sendParcelAccessListRequest(U32 flags)
 	{
 		mCurrentParcel->mAccessList.clear();
 	}		
+	if (flags & AL_ALLOW_EXPERIENCE) 
+	{
+		mCurrentParcel->clearExperienceKeysByType(EXPERIENCE_KEY_TYPE_ALLOWED);
+	}
+	if (flags & AL_BLOCK_EXPERIENCE) 
+	{
+		mCurrentParcel->clearExperienceKeysByType(EXPERIENCE_KEY_TYPE_BLOCKED);
+	}		
 
 	// Only the headers differ
 	msg->newMessageFast(_PREHASH_ParcelAccessListRequest);
@@ -1657,7 +1665,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
 			}
 
 			// Request access list information for this land
-			parcel_mgr.sendParcelAccessListRequest(AL_ACCESS | AL_BAN);
+			parcel_mgr.sendParcelAccessListRequest(AL_ACCESS | AL_BAN | AL_ALLOW_EXPERIENCE | AL_BLOCK_EXPERIENCE);
 
 			// Request dwell for this land, if it's not public land.
 			parcel_mgr.mSelectedDwell = DWELL_NAN;
@@ -1822,6 +1830,14 @@ void LLViewerParcelMgr::processParcelAccessListReply(LLMessageSystem *msg, void
 	{
 		parcel->unpackAccessEntries(msg, &(parcel->mBanList) );
 	}
+	else if (message_flags & AL_ALLOW_EXPERIENCE)
+	{
+		parcel->unpackExperienceEntries(msg, EXPERIENCE_KEY_TYPE_ALLOWED);
+	}
+	else if (message_flags & AL_BLOCK_EXPERIENCE)
+	{
+		parcel->unpackExperienceEntries(msg, EXPERIENCE_KEY_TYPE_BLOCKED);
+	}
 	/*else if (message_flags & AL_RENTER)
 	{
 		parcel->unpackAccessEntries(msg, &(parcel->mRenterList) );
@@ -1856,10 +1872,6 @@ void LLViewerParcelMgr::processParcelDwellReply(LLMessageSystem* msg, void**)
 
 void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which)
 {
-
-	LLUUID transactionUUID;
-	transactionUUID.generate();
-
 	if (!mSelected)
 	{
 		return;
@@ -1868,125 +1880,92 @@ void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which)
 	LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
 	if (!region) return;
 
-	LLMessageSystem* msg = gMessageSystem;
-
 	LLParcel* parcel = mCurrentParcel;
 	if (!parcel) return;
 
 	if (which & AL_ACCESS)
 	{	
-		S32 count = parcel->mAccessList.size();
-		S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET);
-		S32 sequence_id = 1;
-		BOOL start_message = TRUE;
-		BOOL initial = TRUE;
-
-		access_map_const_iterator cit = parcel->mAccessList.begin();
-		access_map_const_iterator end = parcel->mAccessList.end();
-		while ( (cit != end) || initial ) 
-		{	
-			if (start_message) 
-			{
-				msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
-				msg->nextBlockFast(_PREHASH_AgentData);
-				msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
-				msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
-				msg->nextBlockFast(_PREHASH_Data);
-				msg->addU32Fast(_PREHASH_Flags, AL_ACCESS);
-				msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
-				msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
-				msg->addS32Fast(_PREHASH_SequenceID, sequence_id);
-				msg->addS32Fast(_PREHASH_Sections, num_sections);
-				start_message = FALSE;
-
-				if (initial && (cit == end))
-				{
-					// pack an empty block if there will be no data
-					msg->nextBlockFast(_PREHASH_List);
-					msg->addUUIDFast(_PREHASH_ID,  LLUUID::null );
-					msg->addS32Fast(_PREHASH_Time, 0 );
-					msg->addU32Fast(_PREHASH_Flags,	0 );
-				}
+		sendParcelAccessListUpdate(AL_ACCESS, parcel->mAccessList, region, parcel->getLocalID());
+	}
 
-				initial = FALSE;
-				sequence_id++;
+	if (which & AL_BAN)
+	{	
+		sendParcelAccessListUpdate(AL_BAN, parcel->mBanList, region, parcel->getLocalID());
+	}
 
-			}
-			
-			while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES)) 
-			{
+	if(which & AL_ALLOW_EXPERIENCE)
+	{
+		sendParcelAccessListUpdate(AL_ALLOW_EXPERIENCE, parcel->getExperienceKeysByType(EXPERIENCE_KEY_TYPE_ALLOWED), region, parcel->getLocalID());
+	}
+	if(which & AL_BLOCK_EXPERIENCE)
+	{
+		sendParcelAccessListUpdate(AL_BLOCK_EXPERIENCE, parcel->getExperienceKeysByType(EXPERIENCE_KEY_TYPE_BLOCKED), region, parcel->getLocalID());
+	}
+}
 
-				const LLAccessEntry& entry = (*cit).second;
-				
-				msg->nextBlockFast(_PREHASH_List);
-				msg->addUUIDFast(_PREHASH_ID,  entry.mID );
-				msg->addS32Fast(_PREHASH_Time, entry.mTime );
-				msg->addU32Fast(_PREHASH_Flags,	entry.mFlags );
-				++cit;
-			}
+void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 flags, const LLAccessEntry::map& entries, LLViewerRegion* region, S32 parcel_local_id)
+{
+	S32 count = entries.size();
+	S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET);
+	S32 sequence_id = 1;
+	BOOL start_message = TRUE;
+	BOOL initial = TRUE;
 
-			start_message = TRUE;
-			msg->sendReliable( region->getHost() );
-		}
-	}
+	LLUUID transactionUUID;
+	transactionUUID.generate();
 
-	if (which & AL_BAN)
-	{	
-		S32 count = parcel->mBanList.size();
-		S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET);
-		S32 sequence_id = 1;
-		BOOL start_message = TRUE;
-		BOOL initial = TRUE;
-
-		access_map_const_iterator cit = parcel->mBanList.begin();
-		access_map_const_iterator end = parcel->mBanList.end();
-		while ( (cit != end) || initial ) 
-		{
-			if (start_message) 
-			{
-				msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
-				msg->nextBlockFast(_PREHASH_AgentData);
-				msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
-				msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
-				msg->nextBlockFast(_PREHASH_Data);
-				msg->addU32Fast(_PREHASH_Flags, AL_BAN);
-				msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
-				msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
-				msg->addS32Fast(_PREHASH_SequenceID, sequence_id);
-				msg->addS32Fast(_PREHASH_Sections, num_sections);
-				start_message = FALSE;
-
-				if (initial && (cit == end))
-				{
-					// pack an empty block if there will be no data
-					msg->nextBlockFast(_PREHASH_List);
-					msg->addUUIDFast(_PREHASH_ID,  LLUUID::null );
-					msg->addS32Fast(_PREHASH_Time, 0 );
-					msg->addU32Fast(_PREHASH_Flags,	0 );
-				}
 
-				initial = FALSE;
-				sequence_id++;
+	LLMessageSystem* msg = gMessageSystem;
 
-			}
-			
-			while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES)) 
+	LLAccessEntry::map::const_iterator cit = entries.begin();
+	LLAccessEntry::map::const_iterator  end = entries.end();
+	while ( (cit != end) || initial ) 
+	{
+		if (start_message) 
+		{
+			msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
+			msg->nextBlockFast(_PREHASH_AgentData);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
+			msg->nextBlockFast(_PREHASH_Data);
+			msg->addU32Fast(_PREHASH_Flags, flags);
+			msg->addS32(_PREHASH_LocalID,  parcel_local_id);
+			msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
+			msg->addS32Fast(_PREHASH_SequenceID, sequence_id);
+			msg->addS32Fast(_PREHASH_Sections, num_sections);
+			start_message = FALSE;
+
+			if (initial && (cit == end))
 			{
-				const LLAccessEntry& entry = (*cit).second;
-				
+				// pack an empty block if there will be no data
 				msg->nextBlockFast(_PREHASH_List);
-				msg->addUUIDFast(_PREHASH_ID,  entry.mID );
-				msg->addS32Fast(_PREHASH_Time, entry.mTime );
-				msg->addU32Fast(_PREHASH_Flags,	entry.mFlags );
-				++cit;
+				msg->addUUIDFast(_PREHASH_ID,  LLUUID::null );
+				msg->addS32Fast(_PREHASH_Time, 0 );
+				msg->addU32Fast(_PREHASH_Flags,	0 );
 			}
 
-			start_message = TRUE;
-			msg->sendReliable( region->getHost() );
+			initial = FALSE;
+			sequence_id++;
+
 		}
+
+		while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES)) 
+		{
+			const LLAccessEntry& entry = (*cit).second;
+
+			msg->nextBlockFast(_PREHASH_List);
+			msg->addUUIDFast(_PREHASH_ID,  entry.mID );
+			msg->addS32Fast(_PREHASH_Time, entry.mTime );
+			msg->addU32Fast(_PREHASH_Flags,	entry.mFlags );
+			++cit;
+		}
+
+		start_message = TRUE;
+		msg->sendReliable( region->getHost() );
 	}
 }
 
+
 void LLViewerParcelMgr::deedLandToGroup()
 {
 	std::string group_name;
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 9da49bb3f3..9b74377613 100755
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -220,6 +220,10 @@ public:
 	// Takes an Access List flag, like AL_ACCESS or AL_BAN
 	void	sendParcelAccessListUpdate(U32 which);
 
+	static void sendParcelAccessListUpdate(U32 flags, const std::map<LLUUID, class LLAccessEntry>& entries, LLViewerRegion* region, S32 parcel_local_id);
+	static void sendParcelExperienceUpdate( const U32 flags, uuid_vec_t experience_ids, LLViewerRegion* region, S32 parcel_local_id );
+
+
 	// Takes an Access List flag, like AL_ACCESS or AL_BAN
 	void	sendParcelAccessListRequest(U32 flags);
 
-- 
cgit v1.2.3