1836 lines
46 KiB
C++
1836 lines
46 KiB
C++
/**
|
|
* @file llparcel.cpp
|
|
* @brief A land parcel.
|
|
*
|
|
* Copyright (c) 2002-$CurrentYear$, Linden Research, Inc.
|
|
* $License$
|
|
*/
|
|
|
|
#include "linden_common.h"
|
|
|
|
#include "indra_constants.h"
|
|
#include <iostream>
|
|
|
|
#include "llparcel.h"
|
|
#include "llstreamtools.h"
|
|
|
|
#include "llmath.h"
|
|
#include "lltransactiontypes.h"
|
|
#include "lltransactionflags.h"
|
|
#include "message.h"
|
|
#include "u64.h"
|
|
|
|
static const F32 SOME_BIG_NUMBER = 1000.0f;
|
|
static const F32 SOME_BIG_NEG_NUMBER = -1000.0f;
|
|
static const char* PARCEL_OWNERSHIP_STATUS_STRING[LLParcel::OS_COUNT] =
|
|
{
|
|
"leased",
|
|
"lease_pending",
|
|
"abandoned"
|
|
};
|
|
|
|
// NOTE: Adding parcel categories also requires updating:
|
|
// * newview/app_settings/floater_directory.xml category combobox
|
|
// * Web site "create event" tools
|
|
static const char* PARCEL_CATEGORY_STRING[LLParcel::C_COUNT] =
|
|
{
|
|
"none",
|
|
"linden",
|
|
"adult",
|
|
"arts",
|
|
"store", // "business" legacy name
|
|
"educational",
|
|
"game", // "gaming" legacy name
|
|
"gather", // "hangout" legacy name
|
|
"newcomer",
|
|
"park",
|
|
"home", // "residential" legacy name
|
|
"shopping",
|
|
"stage",
|
|
"other",
|
|
};
|
|
static const char* PARCEL_CATEGORY_UI_STRING[LLParcel::C_COUNT + 1] =
|
|
{
|
|
"None",
|
|
"Linden Location",
|
|
"Adult",
|
|
"Arts & Culture",
|
|
"Business",
|
|
"Educational",
|
|
"Gaming",
|
|
"Hangout",
|
|
"Newcomer Friendly",
|
|
"Parks & Nature",
|
|
"Residential",
|
|
"Shopping",
|
|
"Stage",
|
|
"Other",
|
|
"Any", // valid string for parcel searches
|
|
};
|
|
|
|
static const char* PARCEL_ACTION_STRING[LLParcel::A_COUNT + 1] =
|
|
{
|
|
"create",
|
|
"release",
|
|
"absorb",
|
|
"absorbed",
|
|
"divide",
|
|
"division",
|
|
"acquire",
|
|
"relinquish",
|
|
"confirm",
|
|
"unknown"
|
|
};
|
|
|
|
// Timeouts for parcels
|
|
// default is 21 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 1814400000000
|
|
const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
|
|
// ***** TESTING is 10 minutes
|
|
//const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(600000000);
|
|
|
|
// group is 60 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 5184000000000
|
|
const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(5184000000000);
|
|
// ***** TESTING is 10 minutes
|
|
//const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(600000000);
|
|
|
|
// default sale timeout is 2 days -> 172800000000
|
|
const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(172800000000);
|
|
// ***** TESTING is 10 minutes
|
|
//const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(600000000);
|
|
|
|
// more grace period extensions.
|
|
const U64 SEVEN_DAYS_IN_USEC = U64L(604800000000);
|
|
|
|
// if more than 100,000s before sale revert, and no extra extension
|
|
// has been given, go ahead and extend it more. That's about 1.2 days.
|
|
const S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000;
|
|
|
|
|
|
const char* ownership_status_to_string(LLParcel::EOwnershipStatus status);
|
|
LLParcel::EOwnershipStatus ownership_string_to_status(const char* s);
|
|
//const char* revert_action_to_string(LLParcel::ESaleTimerExpireAction action);
|
|
//LLParcel::ESaleTimerExpireAction revert_string_to_action(const char* s);
|
|
const char* category_to_string(LLParcel::ECategory category);
|
|
const char* category_to_ui_string(LLParcel::ECategory category);
|
|
LLParcel::ECategory category_string_to_category(const char* s);
|
|
LLParcel::ECategory category_ui_string_to_category(const char* s);
|
|
|
|
LLParcel::LLParcel()
|
|
{
|
|
init(LLUUID::null, TRUE, FALSE, FALSE, 0, 0, 0, 0, 0, 1.f, 0);
|
|
}
|
|
|
|
|
|
LLParcel::LLParcel(const LLUUID &owner_id,
|
|
BOOL modify, BOOL terraform, BOOL damage,
|
|
time_t claim_date, S32 claim_price_per_meter,
|
|
S32 rent_price_per_meter, S32 area, S32 sim_object_limit, F32 parcel_object_bonus,
|
|
BOOL is_group_owned)
|
|
{
|
|
init( owner_id, modify, terraform, damage, claim_date,
|
|
claim_price_per_meter, rent_price_per_meter, area, sim_object_limit, parcel_object_bonus,
|
|
is_group_owned);
|
|
}
|
|
|
|
|
|
// virtual
|
|
LLParcel::~LLParcel()
|
|
{
|
|
// user list cleaned up by LLDynamicArray destructor.
|
|
}
|
|
|
|
void LLParcel::init(const LLUUID &owner_id,
|
|
BOOL modify, BOOL terraform, BOOL damage,
|
|
time_t claim_date, S32 claim_price_per_meter,
|
|
S32 rent_price_per_meter, S32 area, S32 sim_object_limit, F32 parcel_object_bonus,
|
|
BOOL is_group_owned)
|
|
{
|
|
mID.setNull();
|
|
mOwnerID = owner_id;
|
|
mGroupOwned = is_group_owned;
|
|
mClaimDate = claim_date;
|
|
mClaimPricePerMeter = claim_price_per_meter;
|
|
mRentPricePerMeter = rent_price_per_meter;
|
|
mArea = area;
|
|
mDiscountRate = 1.0f;
|
|
mDrawDistance = 512.f;
|
|
|
|
mUserLookAt.setVec(0.0f, 0.f, 0.f);
|
|
// Default to using the parcel's landing point, if any.
|
|
mLandingType = L_LANDING_POINT;
|
|
|
|
// *FIX: if owner_id != null, should be owned or sale pending,
|
|
// investigate init callers.
|
|
mStatus = OS_NONE;
|
|
mCategory = C_NONE;
|
|
mAuthBuyerID.setNull();
|
|
//mBuyerID.setNull();
|
|
//mJoinNeighbors = 0x0;
|
|
mSaleTimerExpires.setTimerExpirySec(0);
|
|
mSaleTimerExpires.stop();
|
|
mGraceExtension = 0;
|
|
//mExpireAction = STEA_REVERT;
|
|
mRecordTransaction = FALSE;
|
|
|
|
mAuctionID = 0;
|
|
mInEscrow = false;
|
|
|
|
mParcelFlags = PF_DEFAULT;
|
|
setParcelFlag(PF_CREATE_OBJECTS, modify);
|
|
setParcelFlag(PF_ALLOW_TERRAFORM, terraform);
|
|
setParcelFlag(PF_ALLOW_DAMAGE, damage);
|
|
|
|
mSalePrice = 10000;
|
|
setName(NULL);
|
|
setDesc(NULL);
|
|
setMusicURL(NULL);
|
|
setMediaURL(NULL);
|
|
mMediaID.setNull();
|
|
mMediaAutoScale = 0;
|
|
|
|
mGroupID.setNull();
|
|
|
|
mPassPrice = PARCEL_PASS_PRICE_DEFAULT;
|
|
mPassHours = PARCEL_PASS_HOURS_DEFAULT;
|
|
|
|
mAABBMin.setVec(SOME_BIG_NUMBER, SOME_BIG_NUMBER, SOME_BIG_NUMBER);
|
|
mAABBMax.setVec(SOME_BIG_NEG_NUMBER, SOME_BIG_NEG_NUMBER, SOME_BIG_NEG_NUMBER);
|
|
|
|
mLocalID = 0;
|
|
|
|
//mSimWidePrimCorrection = 0;
|
|
setMaxPrimCapacity((S32)(sim_object_limit * area / (F32)(REGION_WIDTH_METERS * REGION_WIDTH_METERS)));
|
|
setSimWideMaxPrimCapacity(0);
|
|
setSimWidePrimCount(0);
|
|
setOwnerPrimCount(0);
|
|
setGroupPrimCount(0);
|
|
setOtherPrimCount(0);
|
|
setSelectedPrimCount(0);
|
|
setTempPrimCount(0);
|
|
setCleanOtherTime(0);
|
|
setParcelPrimBonus(parcel_object_bonus);
|
|
|
|
setPreviousOwnerID(LLUUID::null);
|
|
setPreviouslyGroupOwned(FALSE);
|
|
}
|
|
|
|
void LLParcel::overrideOwner(const LLUUID& owner_id, BOOL is_group_owned)
|
|
{
|
|
// Override with system permission (LLUUID::null)
|
|
// Overridden parcels have no group
|
|
mOwnerID = owner_id;
|
|
mGroupOwned = is_group_owned;
|
|
if(mGroupOwned)
|
|
{
|
|
mGroupID = mOwnerID;
|
|
}
|
|
else
|
|
{
|
|
mGroupID.setNull();
|
|
}
|
|
mInEscrow = false;
|
|
}
|
|
|
|
void LLParcel::overrideParcelFlags(U32 flags)
|
|
{
|
|
mParcelFlags = flags;
|
|
}
|
|
|
|
void set_std_string(const char* src, std::string& dest)
|
|
{
|
|
if(src)
|
|
{
|
|
dest.assign(src);
|
|
}
|
|
else
|
|
{
|
|
#if (LL_LINUX && __GNUC__ < 3)
|
|
dest.assign(std::string(""));
|
|
#else
|
|
dest.clear();
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void LLParcel::setName(const char* name)
|
|
{
|
|
// The escaping here must match the escaping in the database
|
|
// abstraction layer.
|
|
set_std_string(name, mName);
|
|
LLStringFn::replace_nonprintable(mName, LL_UNKNOWN_CHAR);
|
|
}
|
|
|
|
void LLParcel::setDesc(const char* desc)
|
|
{
|
|
// The escaping here must match the escaping in the database
|
|
// abstraction layer.
|
|
set_std_string(desc, mDesc);
|
|
mDesc = rawstr_to_utf8(mDesc);
|
|
}
|
|
|
|
void LLParcel::setMusicURL(const char* url)
|
|
{
|
|
set_std_string(url, mMusicURL);
|
|
|
|
// The escaping here must match the escaping in the database
|
|
// abstraction layer.
|
|
// This should really filter the url in some way. Other than
|
|
// simply requiring non-printable.
|
|
LLStringFn::replace_nonprintable(mMusicURL, LL_UNKNOWN_CHAR);
|
|
}
|
|
|
|
void LLParcel::setMediaURL(const char* url)
|
|
{
|
|
set_std_string(url, mMediaURL);
|
|
|
|
// The escaping here must match the escaping in the database
|
|
// abstraction layer if it's ever added.
|
|
// This should really filter the url in some way. Other than
|
|
// simply requiring non-printable.
|
|
LLStringFn::replace_nonprintable(mMediaURL, LL_UNKNOWN_CHAR);
|
|
}
|
|
|
|
// virtual
|
|
void LLParcel::setLocalID(S32 local_id)
|
|
{
|
|
mLocalID = local_id;
|
|
}
|
|
|
|
void LLParcel::setAllParcelFlags(U32 flags)
|
|
{
|
|
mParcelFlags = flags;
|
|
}
|
|
|
|
void LLParcel::setParcelFlag(U32 flag, BOOL b)
|
|
{
|
|
if (b)
|
|
{
|
|
mParcelFlags |= flag;
|
|
}
|
|
else
|
|
{
|
|
mParcelFlags &= ~flag;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL LLParcel::allowModifyBy(const LLUUID &agent_id, const LLUUID &group_id) const
|
|
{
|
|
if (agent_id == LLUUID::null)
|
|
{
|
|
// system always can enter
|
|
return TRUE;
|
|
}
|
|
else if (isPublic())
|
|
{
|
|
return TRUE;
|
|
}
|
|
else if (agent_id == mOwnerID)
|
|
{
|
|
// owner can always perform operations
|
|
return TRUE;
|
|
}
|
|
else if (mParcelFlags & PF_CREATE_OBJECTS)
|
|
{
|
|
return TRUE;
|
|
}
|
|
else if ((mParcelFlags & PF_CREATE_GROUP_OBJECTS)
|
|
&& group_id.notNull() )
|
|
{
|
|
return (getGroupID() == group_id);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL LLParcel::allowTerraformBy(const LLUUID &agent_id) const
|
|
{
|
|
if (agent_id == LLUUID::null)
|
|
{
|
|
// system always can enter
|
|
return TRUE;
|
|
}
|
|
else if(OS_LEASED == mStatus)
|
|
{
|
|
if(agent_id == mOwnerID)
|
|
{
|
|
// owner can modify leased land
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
// otherwise check other people
|
|
return mParcelFlags & PF_ALLOW_TERRAFORM;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
bool LLParcel::isAgentBlockedFromParcel(LLParcel* parcelp,
|
|
const LLUUID& agent_id,
|
|
const std::vector<LLUUID>& group_ids,
|
|
const BOOL is_agent_identified,
|
|
const BOOL is_agent_transacted)
|
|
{
|
|
S32 current_group_access = parcelp->blockAccess(agent_id, LLUUID::null, is_agent_identified, is_agent_transacted);
|
|
S32 count;
|
|
bool is_allowed = (current_group_access == BA_ALLOWED) ? true: false;
|
|
LLUUID group_id;
|
|
|
|
count = group_ids.size();
|
|
for (int i = 0; i < count && !is_allowed; i++)
|
|
{
|
|
group_id = group_ids[i];
|
|
current_group_access = parcelp->blockAccess(agent_id, group_id, is_agent_identified, is_agent_transacted);
|
|
|
|
if (current_group_access == BA_ALLOWED) is_allowed = true;
|
|
}
|
|
|
|
return !is_allowed;
|
|
}
|
|
|
|
BOOL LLParcel::isAgentBanned(const LLUUID& agent_id) const
|
|
{
|
|
// Test ban list
|
|
if (getParcelFlag(PF_USE_BAN_LIST)
|
|
&& (mBanList.find(agent_id) != mBanList.end()))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
S32 LLParcel::blockAccess(const LLUUID& agent_id, const LLUUID& group_id,
|
|
const BOOL is_agent_identified,
|
|
const BOOL is_agent_transacted) const
|
|
{
|
|
// Test ban list
|
|
if (isAgentBanned(agent_id))
|
|
{
|
|
return BA_BANNED;
|
|
}
|
|
|
|
// Always allow owner on (unless he banned himself, useful for
|
|
// testing). We will also allow estate owners/managers in if they
|
|
// are not explicitly banned.
|
|
if (agent_id == mOwnerID)
|
|
{
|
|
return BA_ALLOWED;
|
|
}
|
|
|
|
// Special case when using pass list where group access is being restricted but not
|
|
// using access list. In this case group members are allowed only if they buy a pass.
|
|
// We return BA_NOT_IN_LIST if not in list
|
|
BOOL passWithGroup = getParcelFlag(PF_USE_PASS_LIST) && !getParcelFlag(PF_USE_ACCESS_LIST)
|
|
&& getParcelFlag(PF_USE_ACCESS_GROUP) && !mGroupID.isNull() && group_id == mGroupID;
|
|
|
|
|
|
// Test group list
|
|
if (getParcelFlag(PF_USE_ACCESS_GROUP)
|
|
&& !mGroupID.isNull()
|
|
&& group_id == mGroupID
|
|
&& !passWithGroup)
|
|
{
|
|
return BA_ALLOWED;
|
|
}
|
|
|
|
// Test access list
|
|
if (getParcelFlag(PF_USE_ACCESS_LIST) || passWithGroup )
|
|
{
|
|
if (mAccessList.find(agent_id) != mAccessList.end())
|
|
{
|
|
return BA_ALLOWED;
|
|
}
|
|
|
|
return BA_NOT_ON_LIST;
|
|
}
|
|
|
|
// If we're not doing any other limitations, all users
|
|
// can enter, unless
|
|
if ( !getParcelFlag(PF_USE_ACCESS_GROUP)
|
|
&& !getParcelFlag(PF_USE_ACCESS_LIST))
|
|
{
|
|
//If the land is group owned, and you are in the group, bypass these checks
|
|
if(getIsGroupOwned() && group_id == mGroupID)
|
|
{
|
|
return BA_ALLOWED;
|
|
}
|
|
|
|
// Test for "payment" access levels
|
|
// Anonymous - No Payment Info on File
|
|
if(getParcelFlag(PF_DENY_ANONYMOUS) && !is_agent_identified && !is_agent_transacted)
|
|
{
|
|
return BA_NO_ACCESS_LEVEL;
|
|
}
|
|
// Identified - Payment Info on File
|
|
// Must check to make sure we're only banning Identified, since Transacted accounts
|
|
// also have their identified flag set
|
|
if(getParcelFlag(PF_DENY_IDENTIFIED) && is_agent_identified && !is_agent_transacted)
|
|
{
|
|
return BA_NO_ACCESS_LEVEL;
|
|
}
|
|
// Transacted - Payment Info Used
|
|
if(getParcelFlag(PF_DENY_TRANSACTED) && is_agent_transacted)
|
|
{
|
|
return BA_NO_ACCESS_LEVEL;
|
|
}
|
|
return BA_ALLOWED;
|
|
}
|
|
|
|
return BA_NOT_IN_GROUP;
|
|
|
|
}
|
|
|
|
|
|
void LLParcel::setArea(S32 area, S32 sim_object_limit)
|
|
{
|
|
mArea = area;
|
|
setMaxPrimCapacity((S32)(sim_object_limit * area / (F32)(REGION_WIDTH_METERS * REGION_WIDTH_METERS)));
|
|
}
|
|
|
|
void LLParcel::setDiscountRate(F32 rate)
|
|
{
|
|
// this is to make sure that the rate is at least sane - this is
|
|
// not intended to enforce economy rules. It only enfoces that the
|
|
// rate is a scaler between 0 and 1.
|
|
mDiscountRate = llclampf(rate);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// File input and output
|
|
//-----------------------------------------------------------
|
|
|
|
|
|
// WARNING: Area will be wrong until you calculate it.
|
|
BOOL LLParcel::importStream(std::istream& input_stream)
|
|
{
|
|
U32 setting;
|
|
S32 secs_until_revert = 0;
|
|
|
|
skip_to_end_of_next_keyword("{", input_stream);
|
|
if (!input_stream.good())
|
|
{
|
|
llwarns << "LLParcel::importStream() - bad input_stream" << llendl;
|
|
return FALSE;
|
|
}
|
|
|
|
while (input_stream.good())
|
|
{
|
|
skip_comments_and_emptyspace(input_stream);
|
|
LLString line, keyword, value;
|
|
get_line(line, input_stream, MAX_STRING);
|
|
get_keyword_and_value(keyword, value, line);
|
|
|
|
if ("}" == keyword)
|
|
{
|
|
break;
|
|
}
|
|
else if ("parcel_id" == keyword)
|
|
{
|
|
mID.set(value.c_str());
|
|
}
|
|
else if ("status" == keyword)
|
|
{
|
|
mStatus = ownership_string_to_status(value.c_str());
|
|
}
|
|
else if ("category" == keyword)
|
|
{
|
|
mCategory = category_string_to_category(value.c_str());
|
|
}
|
|
else if ("local_id" == keyword)
|
|
{
|
|
LLString::convertToS32(value, mLocalID);
|
|
}
|
|
else if ("name" == keyword)
|
|
{
|
|
setName( value.c_str() );
|
|
}
|
|
else if ("desc" == keyword)
|
|
{
|
|
setDesc( value.c_str() );
|
|
}
|
|
else if ("music_url" == keyword)
|
|
{
|
|
setMusicURL( value.c_str() );
|
|
}
|
|
else if ("media_url" == keyword)
|
|
{
|
|
setMediaURL( value.c_str() );
|
|
}
|
|
else if ("media_id" == keyword)
|
|
{
|
|
mMediaID.set( value.c_str() );
|
|
}
|
|
else if ("media_auto_scale" == keyword)
|
|
{
|
|
LLString::convertToU8(value, mMediaAutoScale);
|
|
}
|
|
else if ("owner_id" == keyword)
|
|
{
|
|
mOwnerID.set( value.c_str() );
|
|
}
|
|
else if ("group_owned" == keyword)
|
|
{
|
|
LLString::convertToBOOL(value, mGroupOwned);
|
|
}
|
|
else if ("clean_other_time" == keyword)
|
|
{
|
|
S32 time;
|
|
LLString::convertToS32(value, time);
|
|
setCleanOtherTime(time);
|
|
}
|
|
else if ("auth_buyer_id" == keyword)
|
|
{
|
|
mAuthBuyerID.set(value.c_str());
|
|
}
|
|
else if ("snapshot_id" == keyword)
|
|
{
|
|
mSnapshotID.set(value.c_str());
|
|
}
|
|
else if ("user_location" == keyword)
|
|
{
|
|
sscanf(value.c_str(), "%f %f %f",
|
|
&mUserLocation.mV[VX],
|
|
&mUserLocation.mV[VY],
|
|
&mUserLocation.mV[VZ]);
|
|
}
|
|
else if ("user_look_at" == keyword)
|
|
{
|
|
sscanf(value.c_str(), "%f %f %f",
|
|
&mUserLookAt.mV[VX],
|
|
&mUserLookAt.mV[VY],
|
|
&mUserLookAt.mV[VZ]);
|
|
}
|
|
else if ("landing_type" == keyword)
|
|
{
|
|
S32 landing_type = 0;
|
|
LLString::convertToS32(value, landing_type);
|
|
mLandingType = (ELandingType) landing_type;
|
|
}
|
|
else if ("join_neighbors" == keyword)
|
|
{
|
|
llinfos << "found deprecated keyword join_neighbors" << llendl;
|
|
}
|
|
else if ("revert_sale" == keyword)
|
|
{
|
|
LLString::convertToS32(value, secs_until_revert);
|
|
if (secs_until_revert > 0)
|
|
{
|
|
mSaleTimerExpires.start();
|
|
mSaleTimerExpires.setTimerExpirySec((F32)secs_until_revert);
|
|
}
|
|
}
|
|
else if("extended_grace" == keyword)
|
|
{
|
|
LLString::convertToS32(value, mGraceExtension);
|
|
}
|
|
else if ("user_list_type" == keyword)
|
|
{
|
|
// deprecated
|
|
}
|
|
else if("auction_id" == keyword)
|
|
{
|
|
LLString::convertToU32(value, mAuctionID);
|
|
}
|
|
else if ("allow_modify" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_CREATE_OBJECTS, setting);
|
|
}
|
|
else if ("allow_group_modify" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_CREATE_GROUP_OBJECTS, setting);
|
|
}
|
|
else if ("allow_all_object_entry" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_ALLOW_ALL_OBJECT_ENTRY, setting);
|
|
}
|
|
else if ("allow_group_object_entry" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_ALLOW_GROUP_OBJECT_ENTRY, setting);
|
|
}
|
|
else if ("allow_deed_to_group" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_ALLOW_DEED_TO_GROUP, setting);
|
|
}
|
|
else if("contribute_with_deed" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_CONTRIBUTE_WITH_DEED, setting);
|
|
}
|
|
else if ("allow_terraform" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_ALLOW_TERRAFORM, setting);
|
|
}
|
|
else if ("allow_damage" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_ALLOW_DAMAGE, setting);
|
|
}
|
|
else if ("allow_fly" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_ALLOW_FLY, setting);
|
|
}
|
|
else if ("allow_landmark" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_ALLOW_LANDMARK, setting);
|
|
}
|
|
else if ("sound_local" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_SOUND_LOCAL, setting);
|
|
}
|
|
else if ("allow_group_scripts" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_ALLOW_GROUP_SCRIPTS, setting);
|
|
}
|
|
else if ("allow_voice_chat" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_ALLOW_VOICE_CHAT, setting);
|
|
}
|
|
else if ("use_estate_voice_chan" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_USE_ESTATE_VOICE_CHAN, setting);
|
|
}
|
|
else if ("allow_scripts" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_ALLOW_OTHER_SCRIPTS, setting);
|
|
}
|
|
else if ("for_sale" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_FOR_SALE, setting);
|
|
}
|
|
else if ("sell_w_objects" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_SELL_PARCEL_OBJECTS, setting);
|
|
}
|
|
else if ("use_pass_list" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_USE_PASS_LIST, setting);
|
|
}
|
|
else if ("show_directory" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_SHOW_DIRECTORY, setting);
|
|
}
|
|
else if ("allow_publish" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_ALLOW_PUBLISH, setting);
|
|
}
|
|
else if ("mature_publish" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_MATURE_PUBLISH, setting);
|
|
}
|
|
else if ("claim_date" == keyword)
|
|
{
|
|
// BUG: This will fail when time rolls over in 2038.
|
|
S32 time;
|
|
LLString::convertToS32(value, time);
|
|
mClaimDate = time;
|
|
}
|
|
else if ("claim_price" == keyword)
|
|
{
|
|
LLString::convertToS32(value, mClaimPricePerMeter);
|
|
}
|
|
else if ("rent_price" == keyword)
|
|
{
|
|
LLString::convertToS32(value, mRentPricePerMeter);
|
|
}
|
|
else if ("discount_rate" == keyword)
|
|
{
|
|
LLString::convertToF32(value, mDiscountRate);
|
|
}
|
|
else if ("draw_distance" == keyword)
|
|
{
|
|
LLString::convertToF32(value, mDrawDistance);
|
|
}
|
|
else if ("sale_price" == keyword)
|
|
{
|
|
LLString::convertToS32(value, mSalePrice);
|
|
}
|
|
else if ("pass_price" == keyword)
|
|
{
|
|
LLString::convertToS32(value, mPassPrice);
|
|
}
|
|
else if ("pass_hours" == keyword)
|
|
{
|
|
LLString::convertToF32(value, mPassHours);
|
|
}
|
|
else if ("box" == keyword)
|
|
{
|
|
// deprecated
|
|
}
|
|
else if ("aabb_min" == keyword)
|
|
{
|
|
sscanf(value.c_str(), "%f %f %f",
|
|
&mAABBMin.mV[VX], &mAABBMin.mV[VY], &mAABBMin.mV[VZ]);
|
|
}
|
|
else if ("use_access_group" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_USE_ACCESS_GROUP, setting);
|
|
}
|
|
else if ("use_access_list" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_USE_ACCESS_LIST, setting);
|
|
}
|
|
else if ("use_ban_list" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_USE_BAN_LIST, setting);
|
|
}
|
|
else if ("group_name" == keyword)
|
|
{
|
|
llinfos << "found deprecated keyword group_name" << llendl;
|
|
}
|
|
else if ("group_id" == keyword)
|
|
{
|
|
mGroupID.set( value.c_str() );
|
|
}
|
|
// TODO: DEPRECATED FLAG
|
|
// Flag removed from simstate files in 1.11.1
|
|
// Remove at some point where we have guarenteed this flag
|
|
// no longer exists anywhere in simstate files.
|
|
else if ("require_identified" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_DENY_ANONYMOUS, setting);
|
|
}
|
|
// TODO: DEPRECATED FLAG
|
|
// Flag removed from simstate files in 1.11.1
|
|
// Remove at some point where we have guarenteed this flag
|
|
// no longer exists anywhere in simstate files.
|
|
else if ("require_transacted" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_DENY_ANONYMOUS, setting);
|
|
setParcelFlag(PF_DENY_IDENTIFIED, setting);
|
|
}
|
|
else if ("restrict_pushobject" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_RESTRICT_PUSHOBJECT, setting);
|
|
}
|
|
else if ("deny_anonymous" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_DENY_ANONYMOUS, setting);
|
|
}
|
|
else if ("deny_identified" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_DENY_IDENTIFIED, setting);
|
|
}
|
|
else if ("deny_transacted" == keyword)
|
|
{
|
|
LLString::convertToU32(value, setting);
|
|
setParcelFlag(PF_DENY_TRANSACTED, setting);
|
|
}
|
|
else if ("access_list" == keyword)
|
|
{
|
|
S32 entry_count = 0;
|
|
LLString::convertToS32(value, entry_count);
|
|
for (S32 i = 0; i < entry_count; i++)
|
|
{
|
|
LLAccessEntry entry;
|
|
if (importAccessEntry(input_stream, &entry))
|
|
{
|
|
mAccessList[entry.mID] = entry;
|
|
}
|
|
}
|
|
}
|
|
else if ("ban_list" == keyword)
|
|
{
|
|
S32 entry_count = 0;
|
|
LLString::convertToS32(value, entry_count);
|
|
for (S32 i = 0; i < entry_count; i++)
|
|
{
|
|
LLAccessEntry entry;
|
|
if (importAccessEntry(input_stream, &entry))
|
|
{
|
|
mBanList[entry.mID] = entry;
|
|
}
|
|
}
|
|
}
|
|
else if ("renter_list" == keyword)
|
|
{
|
|
/*
|
|
S32 entry_count = 0;
|
|
LLString::convertToS32(value, entry_count);
|
|
for (S32 i = 0; i < entry_count; i++)
|
|
{
|
|
LLAccessEntry entry;
|
|
if (importAccessEntry(input_stream, &entry))
|
|
{
|
|
mRenterList.put(entry);
|
|
}
|
|
}*/
|
|
}
|
|
else if ("pass_list" == keyword)
|
|
{
|
|
// legacy - put into access list
|
|
S32 entry_count = 0;
|
|
LLString::convertToS32(value, entry_count);
|
|
for (S32 i = 0; i < entry_count; i++)
|
|
{
|
|
LLAccessEntry entry;
|
|
if (importAccessEntry(input_stream, &entry))
|
|
{
|
|
mAccessList[entry.mID] = entry;
|
|
}
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
llwarns << "Unknown keyword in parcel section: <"
|
|
<< keyword << ">" << llendl;
|
|
}
|
|
}
|
|
|
|
// this code block detects if we have loaded a 1.1 simstate file,
|
|
// and follows the conversion rules specified in
|
|
// design_docs/land/pay_for_parcel.txt.
|
|
F32 time_to_expire = 0.0f;
|
|
if(mID.isNull())
|
|
{
|
|
mID.generate();
|
|
mStatus = OS_LEASE_PENDING;
|
|
//mBuyerID = mOwnerID;
|
|
if(getIsGroupOwned())
|
|
{
|
|
time_to_expire += GROUP_USEC_CONVERSION_TIMEOUT / SEC_TO_MICROSEC;
|
|
}
|
|
else
|
|
{
|
|
time_to_expire += DEFAULT_USEC_CONVERSION_TIMEOUT / SEC_TO_MICROSEC;
|
|
}
|
|
//mExpireAction = STEA_PUBLIC;
|
|
mRecordTransaction = TRUE;
|
|
}
|
|
|
|
// this code block deals with giving an extension to pending
|
|
// parcels to the midday of 2004-01-19 if they were originally set
|
|
// for some time on 2004-01-12.
|
|
if((0 == mGraceExtension)
|
|
&& (EXTEND_GRACE_IF_MORE_THAN_SEC < secs_until_revert))
|
|
{
|
|
const S32 NEW_CONVERSION_DATE = 1074538800; // 2004-01-19T11:00:00
|
|
time_t now = time(NULL); // now in epoch
|
|
secs_until_revert = (S32)(NEW_CONVERSION_DATE - now);
|
|
time_to_expire = (F32)secs_until_revert;
|
|
mGraceExtension = 1;
|
|
}
|
|
|
|
// This code block adds yet another week to the deadline. :(
|
|
if(1 == mGraceExtension)
|
|
{
|
|
time_to_expire += SEVEN_DAYS_IN_USEC / SEC_TO_MICROSEC;
|
|
mGraceExtension = 2;
|
|
}
|
|
|
|
if (time_to_expire > 0)
|
|
{
|
|
mSaleTimerExpires.setTimerExpirySec(time_to_expire);
|
|
mSaleTimerExpires.start();
|
|
}
|
|
|
|
// successful import
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL LLParcel::importAccessEntry(std::istream& input_stream, LLAccessEntry* entry)
|
|
{
|
|
skip_to_end_of_next_keyword("{", input_stream);
|
|
while (input_stream.good())
|
|
{
|
|
skip_comments_and_emptyspace(input_stream);
|
|
LLString line, keyword, value;
|
|
get_line(line, input_stream, MAX_STRING);
|
|
get_keyword_and_value(keyword, value, line);
|
|
|
|
if ("}" == keyword)
|
|
{
|
|
break;
|
|
}
|
|
else if ("id" == keyword)
|
|
{
|
|
entry->mID.set( value.c_str() );
|
|
}
|
|
else if ("name" == keyword)
|
|
{
|
|
// deprecated
|
|
}
|
|
else if ("time" == keyword)
|
|
{
|
|
S32 when;
|
|
LLString::convertToS32(value, when);
|
|
entry->mTime = when;
|
|
}
|
|
else if ("flags" == keyword)
|
|
{
|
|
U32 setting;
|
|
LLString::convertToU32(value, setting);
|
|
entry->mFlags = setting;
|
|
}
|
|
else
|
|
{
|
|
llwarns << "Unknown keyword in parcel access entry section: <"
|
|
<< keyword << ">" << llendl;
|
|
}
|
|
}
|
|
return input_stream.good();
|
|
}
|
|
|
|
BOOL LLParcel::exportStream(std::ostream& output_stream)
|
|
{
|
|
S32 setting;
|
|
char id_string[MAX_STRING]; /* Flawfinder: ignore */
|
|
|
|
std::ios::fmtflags old_flags = output_stream.flags();
|
|
output_stream.setf(std::ios::showpoint);
|
|
output_stream << "\t{\n";
|
|
|
|
mID.toString(id_string);
|
|
output_stream << "\t\t parcel_id " << id_string << "\n";
|
|
output_stream << "\t\t status " << ownership_status_to_string(mStatus) << "\n";
|
|
output_stream << "\t\t category " << category_to_string(mCategory) << "\n";
|
|
|
|
output_stream << "\t\t local_id " << mLocalID << "\n";
|
|
|
|
const char* name = (mName.empty() ? "" : mName.c_str() );
|
|
output_stream << "\t\t name " << name << "\n";
|
|
|
|
const char* desc = (mDesc.empty() ? "" : mDesc.c_str() );
|
|
output_stream << "\t\t desc " << desc << "\n";
|
|
|
|
const char* music_url = (mMusicURL.empty() ? "" : mMusicURL.c_str() );
|
|
output_stream << "\t\t music_url " << music_url << "\n";
|
|
|
|
const char* media_url = (mMediaURL.empty() ? "" : mMediaURL.c_str() );
|
|
output_stream << "\t\t media_url " << media_url << "\n";
|
|
|
|
output_stream << "\t\t media_auto_scale " << (mMediaAutoScale ? 1 : 0) << "\n";
|
|
|
|
mMediaID.toString(id_string);
|
|
output_stream << "\t\t media_id " << id_string << "\n";
|
|
|
|
mOwnerID.toString(id_string);
|
|
output_stream << "\t\t owner_id " << id_string << "\n";
|
|
output_stream << "\t\t group_owned " << (mGroupOwned ? 1 : 0) << "\n";
|
|
output_stream << "\t\t clean_other_time " << getCleanOtherTime() << "\n";
|
|
|
|
if(!mAuthBuyerID.isNull())
|
|
{
|
|
mAuthBuyerID.toString(id_string);
|
|
output_stream << "\t\t auth_buyer_id " << id_string << "\n";
|
|
}
|
|
if (!mSnapshotID.isNull())
|
|
{
|
|
mSnapshotID.toString(id_string);
|
|
output_stream << "\t\t snapshot_id " << id_string << "\n";
|
|
}
|
|
if (!mUserLocation.isExactlyZero())
|
|
{
|
|
output_stream << "\t\t user_location "
|
|
<< (F64)mUserLocation.mV[VX]
|
|
<< " " << (F64)mUserLocation.mV[VY]
|
|
<< " " << (F64)mUserLocation.mV[VZ] << "\n";
|
|
output_stream << "\t\t user_look_at "
|
|
<< (F64)mUserLookAt.mV[VX]
|
|
<< " " << (F64)mUserLookAt.mV[VY]
|
|
<< " " << (F64)mUserLookAt.mV[VZ] << "\n";
|
|
}
|
|
output_stream << "\t\t landing_type " << mLandingType << "\n";
|
|
//if(mJoinNeighbors)
|
|
//{
|
|
// output_stream << "\t\t join_neighbors " << mJoinNeighbors << "\n";
|
|
//}
|
|
if(mSaleTimerExpires.getStarted())
|
|
{
|
|
S32 dt_sec = (S32) mSaleTimerExpires.getRemainingTimeF32()+60; // Add a minute to prevent race conditions
|
|
output_stream << "\t\t revert_sale " << dt_sec << "\n";
|
|
//output_stream << "\t\t revert_action " << revert_action_to_string(mExpireAction) << "\n";
|
|
output_stream << "\t\t extended_grace " << mGraceExtension << "\n";
|
|
}
|
|
|
|
if(0 != mAuctionID)
|
|
{
|
|
output_stream << "\t\t auction_id " << mAuctionID << "\n";
|
|
}
|
|
|
|
output_stream << "\t\t allow_modify " << getAllowModify() << "\n";
|
|
output_stream << "\t\t allow_group_modify " << getAllowGroupModify() << "\n";
|
|
output_stream << "\t\t allow_all_object_entry " << getAllowAllObjectEntry() << "\n";
|
|
output_stream << "\t\t allow_group_object_entry " << getAllowGroupObjectEntry() << "\n";
|
|
output_stream << "\t\t allow_terraform " << getAllowTerraform() << "\n";
|
|
output_stream << "\t\t allow_deed_to_group " << getAllowDeedToGroup() << "\n";
|
|
output_stream << "\t\t contribute_with_deed " << getContributeWithDeed() << "\n";
|
|
output_stream << "\t\t allow_damage " << getAllowDamage() << "\n";
|
|
output_stream << "\t\t claim_date " << (S32)mClaimDate << "\n";
|
|
output_stream << "\t\t claim_price " << mClaimPricePerMeter << "\n";
|
|
output_stream << "\t\t rent_price " << mRentPricePerMeter << "\n";
|
|
output_stream << "\t\t discount_rate " << mDiscountRate << "\n";
|
|
output_stream << "\t\t allow_fly " << (getAllowFly() ? 1 : 0) << "\n";
|
|
output_stream << "\t\t allow_landmark " << (getAllowLandmark() ? 1 : 0) << "\n";
|
|
output_stream << "\t\t sound_local " << (getSoundLocal() ? 1 : 0) << "\n";
|
|
output_stream << "\t\t allow_scripts " << (getAllowOtherScripts() ? 1 : 0) << "\n";
|
|
output_stream << "\t\t allow_group_scripts " << (getAllowGroupScripts() ? 1 : 0) << "\n";
|
|
output_stream << "\t\t allow_voice_chat " << (getVoiceEnabled() ? 1 : 0) << "\n";
|
|
output_stream << "\t\t use_estate_voice_chan " << (getVoiceUseEstateChannel() ? 1 : 0) << "\n";
|
|
output_stream << "\t\t for_sale " << (getForSale() ? 1 : 0) << "\n";
|
|
output_stream << "\t\t sell_w_objects " << (getSellWithObjects() ? 1 : 0) << "\n";
|
|
output_stream << "\t\t draw_distance " << mDrawDistance << "\n";
|
|
output_stream << "\t\t sale_price " << mSalePrice << "\n";
|
|
|
|
setting = (getParcelFlag(PF_USE_ACCESS_GROUP) ? 1 : 0);
|
|
output_stream << "\t\t use_access_group " << setting << "\n";
|
|
|
|
setting = (getParcelFlag(PF_USE_ACCESS_LIST) ? 1 : 0);
|
|
output_stream << "\t\t use_access_list " << setting << "\n";
|
|
|
|
setting = (getParcelFlag(PF_USE_BAN_LIST) ? 1 : 0);
|
|
output_stream << "\t\t use_ban_list " << setting << "\n";
|
|
|
|
mGroupID.toString(id_string);
|
|
output_stream << "\t\t group_id " << id_string << "\n";
|
|
|
|
//const char* group_name
|
|
// = (mGroupName.isEmpty() ? "" : mGroupName.c_str() );
|
|
//output_stream << "\t\t group_name " << group_name << "\n";
|
|
|
|
setting = (getParcelFlag(PF_USE_PASS_LIST) ? 1 : 0);
|
|
output_stream << "\t\t use_pass_list " << setting << "\n";
|
|
|
|
output_stream << "\t\t pass_price " << mPassPrice << "\n";
|
|
output_stream << "\t\t pass_hours " << mPassHours << "\n";
|
|
|
|
setting = (getParcelFlag(PF_SHOW_DIRECTORY) ? 1 : 0);
|
|
output_stream << "\t\t show_directory " << setting << "\n";
|
|
|
|
setting = (getParcelFlag(PF_ALLOW_PUBLISH) ? 1 : 0);
|
|
output_stream << "\t\t allow_publish " << setting << "\n";
|
|
|
|
setting = (getParcelFlag(PF_MATURE_PUBLISH) ? 1 : 0);
|
|
output_stream << "\t\t mature_publish " << setting << "\n";
|
|
|
|
setting = (getParcelFlag(PF_DENY_ANONYMOUS) ? 1 : 0);
|
|
output_stream << "\t\t deny_anonymous " << setting << "\n";
|
|
|
|
setting = (getParcelFlag(PF_DENY_IDENTIFIED) ? 1 : 0);
|
|
output_stream << "\t\t deny_identified " << setting << "\n";
|
|
|
|
setting = (getParcelFlag(PF_DENY_TRANSACTED) ? 1 : 0);
|
|
output_stream << "\t\t deny_transacted " << setting << "\n";
|
|
|
|
setting = (getParcelFlag(PF_RESTRICT_PUSHOBJECT) ? 1 : 0);
|
|
output_stream << "\t\t restrict_pushobject " << setting << "\n";
|
|
|
|
output_stream << "\t\t aabb_min "
|
|
<< mAABBMin.mV[VX]
|
|
<< " " << mAABBMin.mV[VY]
|
|
<< " " << mAABBMin.mV[VZ] << "\n";
|
|
|
|
if (!mAccessList.empty())
|
|
{
|
|
output_stream << "\t\t access_list " << mAccessList.size() << "\n";
|
|
access_map_const_iterator cit = mAccessList.begin();
|
|
access_map_const_iterator end = mAccessList.end();
|
|
|
|
for ( ; cit != end; ++cit)
|
|
{
|
|
output_stream << "\t\t{\n";
|
|
const LLAccessEntry& entry = (*cit).second;
|
|
entry.mID.toString(id_string);
|
|
output_stream << "\t\t\tid " << id_string << "\n";
|
|
output_stream << "\t\t\ttime " << entry.mTime << "\n";
|
|
output_stream << "\t\t\tflags " << entry.mFlags << "\n";
|
|
output_stream << "\t\t}\n";
|
|
}
|
|
}
|
|
|
|
if (!mBanList.empty())
|
|
{
|
|
output_stream << "\t\t ban_list " << mBanList.size() << "\n";
|
|
access_map_const_iterator cit = mBanList.begin();
|
|
access_map_const_iterator end = mBanList.end();
|
|
|
|
for ( ; cit != end; ++cit)
|
|
{
|
|
output_stream << "\t\t{\n";
|
|
const LLAccessEntry& entry = (*cit).second;
|
|
entry.mID.toString(id_string);
|
|
output_stream << "\t\t\tid " << id_string << "\n";
|
|
output_stream << "\t\t\ttime " << entry.mTime << "\n";
|
|
output_stream << "\t\t\tflags " << entry.mFlags << "\n";
|
|
output_stream << "\t\t}\n";
|
|
}
|
|
}
|
|
|
|
/*if (mRenterList.count() > 0)
|
|
{
|
|
output_stream << "\t\t renter_list " << mRenterList.count() << "\n";
|
|
for (i = 0; i < mRenterList.count(); i++)
|
|
{
|
|
output_stream << "\t\t{\n";
|
|
const LLAccessEntry& entry = mRenterList.get(i);
|
|
entry.mID.toString(id_string);
|
|
output_stream << "\t\t\tid " << id_string << "\n";
|
|
output_stream << "\t\t\ttime " << entry.mTime << "\n";
|
|
output_stream << "\t\t\tflags " << entry.mFlags << "\n";
|
|
output_stream << "\t\t}\n";
|
|
}
|
|
}*/
|
|
|
|
output_stream << "\t}\n";
|
|
output_stream.flags(old_flags);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// virtual
|
|
LLSD LLParcel::asLLSD() const
|
|
{
|
|
LLSD p;
|
|
p["parcel-id"] = getID();
|
|
p["name"] = getName();
|
|
p["desc"] = getDesc();
|
|
p["owner-id"] = getOwnerID();
|
|
p["group-id"] = getGroupID();
|
|
p["group-owned"] = (bool)getIsGroupOwned();
|
|
p["auction-id"] = (S32)getAuctionID();
|
|
p["snapshot-id"] = getSnapshotID();
|
|
p["authorized-buyer-id"] = getAuthorizedBuyerID();
|
|
p["sale-price"] = getSalePrice();
|
|
p["parcel-flags"] = (S32)getParcelFlags();
|
|
// NOTE: This list is incomplete, as this is used only for search. JC
|
|
return p;
|
|
}
|
|
|
|
// Assumes we are in a block "ParcelData"
|
|
void LLParcel::packMessage(LLMessageSystem* msg)
|
|
{
|
|
msg->addU32Fast( _PREHASH_ParcelFlags, getParcelFlags() );
|
|
msg->addS32Fast( _PREHASH_SalePrice, getSalePrice() );
|
|
msg->addStringFast( _PREHASH_Name, getName() );
|
|
msg->addStringFast( _PREHASH_Desc, getDesc() );
|
|
msg->addStringFast( _PREHASH_MusicURL, getMusicURL() );
|
|
msg->addStringFast( _PREHASH_MediaURL, getMediaURL() );
|
|
msg->addU8 ( "MediaAutoScale", getMediaAutoScale () );
|
|
msg->addUUIDFast( _PREHASH_MediaID, getMediaID() );
|
|
msg->addUUIDFast( _PREHASH_GroupID, getGroupID() );
|
|
msg->addS32Fast( _PREHASH_PassPrice, mPassPrice );
|
|
msg->addF32Fast( _PREHASH_PassHours, mPassHours );
|
|
msg->addU8Fast( _PREHASH_Category, (U8)mCategory);
|
|
msg->addUUIDFast( _PREHASH_AuthBuyerID, mAuthBuyerID);
|
|
msg->addUUIDFast( _PREHASH_SnapshotID, mSnapshotID);
|
|
msg->addVector3Fast(_PREHASH_UserLocation, mUserLocation);
|
|
msg->addVector3Fast(_PREHASH_UserLookAt, mUserLookAt);
|
|
msg->addU8Fast( _PREHASH_LandingType, (U8)mLandingType);
|
|
}
|
|
|
|
|
|
void LLParcel::unpackMessage(LLMessageSystem* msg)
|
|
{
|
|
char buffer[256]; /* Flawfinder: ignore */
|
|
|
|
msg->getU32Fast( _PREHASH_ParcelData,_PREHASH_ParcelFlags, mParcelFlags );
|
|
msg->getS32Fast( _PREHASH_ParcelData,_PREHASH_SalePrice, mSalePrice );
|
|
msg->getStringFast( _PREHASH_ParcelData,_PREHASH_Name, 256, buffer );
|
|
setName(buffer);
|
|
msg->getStringFast( _PREHASH_ParcelData,_PREHASH_Desc, 256, buffer );
|
|
setDesc(buffer);
|
|
msg->getStringFast( _PREHASH_ParcelData,_PREHASH_MusicURL, 256, buffer );
|
|
setMusicURL(buffer);
|
|
msg->getStringFast( _PREHASH_ParcelData,_PREHASH_MediaURL, 256, buffer );
|
|
setMediaURL(buffer);
|
|
|
|
// non-optimized version
|
|
msg->getU8 ( "ParcelData", "MediaAutoScale", mMediaAutoScale );
|
|
|
|
msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_MediaID, mMediaID );
|
|
msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_GroupID, mGroupID );
|
|
msg->getS32Fast( _PREHASH_ParcelData,_PREHASH_PassPrice, mPassPrice );
|
|
msg->getF32Fast( _PREHASH_ParcelData,_PREHASH_PassHours, mPassHours );
|
|
U8 category;
|
|
msg->getU8Fast( _PREHASH_ParcelData,_PREHASH_Category, category);
|
|
mCategory = (ECategory)category;
|
|
msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_AuthBuyerID, mAuthBuyerID);
|
|
msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_SnapshotID, mSnapshotID);
|
|
msg->getVector3Fast(_PREHASH_ParcelData,_PREHASH_UserLocation, mUserLocation);
|
|
msg->getVector3Fast(_PREHASH_ParcelData,_PREHASH_UserLookAt, mUserLookAt);
|
|
U8 landing_type;
|
|
msg->getU8Fast( _PREHASH_ParcelData,_PREHASH_LandingType, landing_type);
|
|
mLandingType = (ELandingType)landing_type;
|
|
}
|
|
|
|
|
|
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();
|
|
|
|
if (cit == end)
|
|
{
|
|
msg->nextBlockFast(_PREHASH_List);
|
|
msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
|
|
msg->addS32Fast(_PREHASH_Time, 0 );
|
|
msg->addU32Fast(_PREHASH_Flags, 0 );
|
|
return;
|
|
}
|
|
|
|
for ( ; cit != end; ++cit)
|
|
{
|
|
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 );
|
|
}
|
|
}
|
|
|
|
|
|
void LLParcel::unpackAccessEntries(LLMessageSystem* msg,
|
|
std::map<LLUUID,LLAccessEntry>* list)
|
|
{
|
|
LLUUID id;
|
|
S32 time;
|
|
U32 flags;
|
|
|
|
S32 i;
|
|
S32 count = msg->getNumberOfBlocksFast(_PREHASH_List);
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
msg->getUUIDFast(_PREHASH_List, _PREHASH_ID, id, i);
|
|
msg->getS32Fast( _PREHASH_List, _PREHASH_Time, time, i);
|
|
msg->getU32Fast( _PREHASH_List, _PREHASH_Flags, flags, i);
|
|
|
|
if (id.notNull())
|
|
{
|
|
LLAccessEntry entry;
|
|
entry.mID = id;
|
|
entry.mTime = time;
|
|
entry.mFlags = flags;
|
|
|
|
(*list)[entry.mID] = entry;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void LLParcel::expirePasses(S32 now)
|
|
{
|
|
access_map_iterator itor = mAccessList.begin();
|
|
while (itor != mAccessList.end())
|
|
{
|
|
const LLAccessEntry& entry = (*itor).second;
|
|
|
|
if (entry.mTime != 0 && entry.mTime < now)
|
|
{
|
|
mAccessList.erase(itor++);
|
|
}
|
|
else
|
|
{
|
|
++itor;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool LLParcel::operator==(const LLParcel &rhs) const
|
|
{
|
|
if (mOwnerID != rhs.mOwnerID)
|
|
return FALSE;
|
|
|
|
if (mParcelFlags != rhs.mParcelFlags)
|
|
return FALSE;
|
|
|
|
if (mClaimDate != rhs.mClaimDate)
|
|
return FALSE;
|
|
|
|
if (mClaimPricePerMeter != rhs.mClaimPricePerMeter)
|
|
return FALSE;
|
|
|
|
if (mRentPricePerMeter != rhs.mRentPricePerMeter)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Calculate rent
|
|
S32 LLParcel::getTotalRent() const
|
|
{
|
|
return (S32)floor(0.5f + (F32)mArea * (F32)mRentPricePerMeter * (1.0f - mDiscountRate));
|
|
}
|
|
|
|
F32 LLParcel::getAdjustedRentPerMeter() const
|
|
{
|
|
return ((F32)mRentPricePerMeter * (1.0f - mDiscountRate));
|
|
}
|
|
|
|
LLVector3 LLParcel::getCenterpoint() const
|
|
{
|
|
LLVector3 rv;
|
|
rv.mV[VX] = (getAABBMin().mV[VX] + getAABBMax().mV[VX]) * 0.5f;
|
|
rv.mV[VY] = (getAABBMin().mV[VY] + getAABBMax().mV[VY]) * 0.5f;
|
|
rv.mV[VZ] = 0.0f;
|
|
return rv;
|
|
}
|
|
|
|
void LLParcel::extendAABB(const LLVector3& box_min, const LLVector3& box_max)
|
|
{
|
|
// Patch up min corner of AABB
|
|
S32 i;
|
|
for (i=0; i<3; i++)
|
|
{
|
|
if (box_min.mV[i] < mAABBMin.mV[i])
|
|
{
|
|
mAABBMin.mV[i] = box_min.mV[i];
|
|
}
|
|
}
|
|
|
|
// Patch up max corner of AABB
|
|
for (i=0; i<3; i++)
|
|
{
|
|
if (box_max.mV[i] > mAABBMax.mV[i])
|
|
{
|
|
mAABBMax.mV[i] = box_max.mV[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL LLParcel::addToAccessList(const LLUUID& agent_id, S32 time)
|
|
{
|
|
if (!((mParcelFlags & PF_USE_ACCESS_LIST) || (mParcelFlags & PF_USE_PASS_LIST))
|
|
|| mAccessList.size() >= (U32) PARCEL_MAX_ACCESS_LIST)
|
|
{
|
|
// Not using access list, so not a rational thing to do
|
|
return FALSE;
|
|
}
|
|
if (agent_id == getOwnerID())
|
|
{
|
|
// Can't add owner to these lists
|
|
return FALSE;
|
|
}
|
|
access_map_iterator itor = mAccessList.begin();
|
|
while (itor != mAccessList.end())
|
|
{
|
|
const LLAccessEntry& entry = (*itor).second;
|
|
if (entry.mID == agent_id)
|
|
{
|
|
if (time == 0 || (entry.mTime != 0 && entry.mTime < time))
|
|
{
|
|
mAccessList.erase(itor++);
|
|
}
|
|
else
|
|
{
|
|
// existing one expires later
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
++itor;
|
|
}
|
|
}
|
|
|
|
removeFromBanList(agent_id);
|
|
|
|
LLAccessEntry new_entry;
|
|
new_entry.mID = agent_id;
|
|
new_entry.mTime = time;
|
|
new_entry.mFlags = 0x0;
|
|
mAccessList[new_entry.mID] = new_entry;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL LLParcel::addToBanList(const LLUUID& agent_id, S32 time)
|
|
{
|
|
if (!(mParcelFlags & PF_USE_BAN_LIST)
|
|
|| mBanList.size() >= (U32) PARCEL_MAX_ACCESS_LIST)
|
|
{
|
|
// Not using ban list, so not a rational thing to do
|
|
return FALSE;
|
|
}
|
|
if (agent_id == getOwnerID())
|
|
{
|
|
// Can't add owner to these lists
|
|
return FALSE;
|
|
}
|
|
|
|
access_map_iterator itor = mBanList.begin();
|
|
while (itor != mBanList.end())
|
|
{
|
|
const LLAccessEntry& entry = (*itor).second;
|
|
if (entry.mID == agent_id)
|
|
{
|
|
if (time == 0 || (entry.mTime != 0 && entry.mTime < time))
|
|
{
|
|
mBanList.erase(itor++);
|
|
}
|
|
else
|
|
{
|
|
// existing one expires later
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
++itor;
|
|
}
|
|
}
|
|
|
|
removeFromAccessList(agent_id);
|
|
|
|
LLAccessEntry new_entry;
|
|
new_entry.mID = agent_id;
|
|
new_entry.mTime = time;
|
|
new_entry.mFlags = 0x0;
|
|
mBanList[new_entry.mID] = new_entry;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL remove_from_access_array(std::map<LLUUID,LLAccessEntry>* list,
|
|
const LLUUID& agent_id)
|
|
{
|
|
BOOL removed = FALSE;
|
|
access_map_iterator itor = list->begin();
|
|
while (itor != list->end())
|
|
{
|
|
const LLAccessEntry& entry = (*itor).second;
|
|
if (entry.mID == agent_id)
|
|
{
|
|
list->erase(itor++);
|
|
removed = TRUE;
|
|
}
|
|
else
|
|
{
|
|
++itor;
|
|
}
|
|
}
|
|
return removed;
|
|
}
|
|
|
|
BOOL LLParcel::removeFromAccessList(const LLUUID& agent_id)
|
|
{
|
|
return remove_from_access_array(&mAccessList, agent_id);
|
|
}
|
|
|
|
BOOL LLParcel::removeFromBanList(const LLUUID& agent_id)
|
|
{
|
|
return remove_from_access_array(&mBanList, agent_id);
|
|
}
|
|
|
|
// static
|
|
const char* LLParcel::getOwnershipStatusString(EOwnershipStatus status)
|
|
{
|
|
return ownership_status_to_string(status);
|
|
}
|
|
|
|
// static
|
|
const char* LLParcel::getCategoryString(ECategory category)
|
|
{
|
|
return category_to_string(category);
|
|
}
|
|
|
|
// static
|
|
const char* LLParcel::getCategoryUIString(ECategory category)
|
|
{
|
|
return category_to_ui_string(category);
|
|
}
|
|
|
|
// static
|
|
LLParcel::ECategory LLParcel::getCategoryFromString(const char* string)
|
|
{
|
|
return category_string_to_category(string);
|
|
}
|
|
|
|
// static
|
|
LLParcel::ECategory LLParcel::getCategoryFromUIString(const char* string)
|
|
{
|
|
return category_ui_string_to_category(string);
|
|
}
|
|
|
|
// static
|
|
const char* LLParcel::getActionString(LLParcel::EAction action)
|
|
{
|
|
S32 index = 0;
|
|
if((action >= 0) && (action < LLParcel::A_COUNT))
|
|
{
|
|
index = action;
|
|
}
|
|
else
|
|
{
|
|
index = A_COUNT;
|
|
}
|
|
return PARCEL_ACTION_STRING[index];
|
|
}
|
|
|
|
BOOL LLParcel::isSaleTimerExpired(const U64& time)
|
|
{
|
|
if (mSaleTimerExpires.getStarted() == FALSE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
BOOL expired = mSaleTimerExpires.checkExpirationAndReset(0.0);
|
|
if (expired)
|
|
{
|
|
mSaleTimerExpires.stop();
|
|
}
|
|
return expired;
|
|
}
|
|
|
|
|
|
void LLParcel::startSale(const LLUUID& buyer_id, BOOL is_buyer_group)
|
|
{
|
|
// TODO -- this and all Sale related methods need to move out of the LLParcel
|
|
// base class and into server-side-only LLSimParcel class
|
|
setPreviousOwnerID(mOwnerID);
|
|
setPreviouslyGroupOwned(mGroupOwned);
|
|
|
|
mOwnerID = buyer_id;
|
|
mGroupOwned = is_buyer_group;
|
|
if(mGroupOwned)
|
|
{
|
|
mGroupID = mOwnerID;
|
|
}
|
|
else
|
|
{
|
|
mGroupID.setNull();
|
|
}
|
|
mSaleTimerExpires.start();
|
|
mSaleTimerExpires.setTimerExpirySec(DEFAULT_USEC_SALE_TIMEOUT / SEC_TO_MICROSEC);
|
|
mStatus = OS_LEASE_PENDING;
|
|
mClaimDate = time(NULL);
|
|
mAuctionID = 0;
|
|
// clear the autoreturn whenever land changes hands
|
|
setCleanOtherTime(0);
|
|
}
|
|
|
|
void LLParcel::expireSale(U32& type, U8& flags, LLUUID& from_id, LLUUID& to_id)
|
|
{
|
|
mSaleTimerExpires.setTimerExpirySec(0.0);
|
|
mSaleTimerExpires.stop();
|
|
setPreviousOwnerID(LLUUID::null);
|
|
setPreviouslyGroupOwned(FALSE);
|
|
setSellWithObjects(FALSE);
|
|
type = TRANS_LAND_RELEASE;
|
|
mStatus = OS_NONE;
|
|
flags = pack_transaction_flags(mGroupOwned, FALSE);
|
|
mAuthBuyerID.setNull();
|
|
from_id = mOwnerID;
|
|
mOwnerID.setNull();
|
|
to_id.setNull();
|
|
}
|
|
|
|
void LLParcel::completeSale(U32& type, U8& flags,
|
|
LLUUID& to_id)
|
|
{
|
|
mSaleTimerExpires.setTimerExpirySec(0.0);
|
|
mSaleTimerExpires.stop();
|
|
mStatus = OS_LEASED;
|
|
type = TRANS_LAND_SALE;
|
|
flags = pack_transaction_flags(mGroupOwned, mGroupOwned);
|
|
to_id = mOwnerID;
|
|
mAuthBuyerID.setNull();
|
|
|
|
// Purchased parcels are assumed to no longer be for sale.
|
|
// Otherwise someone can snipe the sale.
|
|
setForSale(FALSE);
|
|
|
|
// Turn off show directory, since it's a recurring fee that
|
|
// the buyer may not want.
|
|
setParcelFlag(PF_SHOW_DIRECTORY, FALSE);
|
|
|
|
//should be cleared on sale.
|
|
mAccessList.clear();
|
|
mBanList.clear();
|
|
|
|
}
|
|
|
|
void LLParcel::clearSale()
|
|
{
|
|
mSaleTimerExpires.setTimerExpirySec(0.0);
|
|
mSaleTimerExpires.stop();
|
|
if(isPublic())
|
|
{
|
|
mStatus = OS_NONE;
|
|
}
|
|
else
|
|
{
|
|
mStatus = OS_LEASED;
|
|
}
|
|
mAuthBuyerID.setNull();
|
|
setForSale(FALSE);
|
|
setPreviousOwnerID(LLUUID::null);
|
|
setPreviouslyGroupOwned(FALSE);
|
|
setSellWithObjects(FALSE);
|
|
}
|
|
|
|
BOOL LLParcel::isPublic() const
|
|
{
|
|
return (mOwnerID.isNull());
|
|
}
|
|
|
|
BOOL LLParcel::isBuyerAuthorized(const LLUUID& buyer_id) const
|
|
{
|
|
if(mAuthBuyerID.isNull())
|
|
{
|
|
return TRUE;
|
|
}
|
|
return (mAuthBuyerID == buyer_id);
|
|
}
|
|
|
|
void LLParcel::clearParcel()
|
|
{
|
|
overrideParcelFlags(PF_DEFAULT);
|
|
setName(NULL);
|
|
setDesc(NULL);
|
|
setMusicURL(NULL);
|
|
setMediaURL(NULL);
|
|
setMediaID(LLUUID::null);
|
|
setMediaAutoScale(0);
|
|
setInEscrow(FALSE);
|
|
setAuthorizedBuyerID(LLUUID::null);
|
|
setCategory(C_NONE);
|
|
setSnapshotID(LLUUID::null);
|
|
setUserLocation(LLVector3::zero);
|
|
setUserLookAt(LLVector3::x_axis);
|
|
setLandingType(L_LANDING_POINT);
|
|
setAuctionID(0);
|
|
setGroupID(LLUUID::null);
|
|
setPassPrice(0);
|
|
setPassHours(0.f);
|
|
mAccessList.clear();
|
|
mBanList.clear();
|
|
//mRenterList.reset();
|
|
}
|
|
|
|
void LLParcel::dump()
|
|
{
|
|
llinfos << "parcel " << mLocalID << " area " << mArea << llendl;
|
|
llinfos << " name <" << mName << ">" << llendl;
|
|
llinfos << " desc <" << mDesc << ">" << llendl;
|
|
}
|
|
|
|
const char* ownership_status_to_string(LLParcel::EOwnershipStatus status)
|
|
{
|
|
if(status >= 0 && status < LLParcel::OS_COUNT)
|
|
{
|
|
return PARCEL_OWNERSHIP_STATUS_STRING[status];
|
|
}
|
|
return "none";
|
|
}
|
|
|
|
LLParcel::EOwnershipStatus ownership_string_to_status(const char* s)
|
|
{
|
|
for(S32 i = 0; i < LLParcel::OS_COUNT; ++i)
|
|
{
|
|
if(0 == strcmp(s, PARCEL_OWNERSHIP_STATUS_STRING[i]))
|
|
{
|
|
return (LLParcel::EOwnershipStatus)i;
|
|
}
|
|
}
|
|
return LLParcel::OS_NONE;
|
|
}
|
|
|
|
//const char* revert_action_to_string(LLParcel::ESaleTimerExpireAction action)
|
|
//{
|
|
// S32 index = 0;
|
|
// if(action >= 0 && action < LLParcel::STEA_COUNT)
|
|
// {
|
|
// index = action;
|
|
// }
|
|
// return PARCEL_SALE_TIMER_ACTION[index];
|
|
//}
|
|
|
|
//LLParcel::ESaleTimerExpireAction revert_string_to_action(const char* s)
|
|
//{
|
|
// for(S32 i = 0; i < LLParcel::STEA_COUNT; ++i)
|
|
// {
|
|
// if(0 == strcmp(s, PARCEL_SALE_TIMER_ACTION[i]))
|
|
// {
|
|
// return (LLParcel::ESaleTimerExpireAction)i;
|
|
// }
|
|
// }
|
|
// return LLParcel::STEA_REVERT;
|
|
//}
|
|
|
|
const char* category_to_string(LLParcel::ECategory category)
|
|
{
|
|
S32 index = 0;
|
|
if((category >= 0) && (category < LLParcel::C_COUNT))
|
|
{
|
|
index = category;
|
|
}
|
|
return PARCEL_CATEGORY_STRING[index];
|
|
}
|
|
|
|
const char* category_to_ui_string(LLParcel::ECategory category)
|
|
{
|
|
S32 index = 0;
|
|
if((category >= 0) && (category < LLParcel::C_COUNT))
|
|
{
|
|
index = category;
|
|
}
|
|
else
|
|
{
|
|
// C_ANY = -1 , but the "Any" string is at the end of the list
|
|
index = ((S32) LLParcel::C_COUNT);
|
|
}
|
|
return PARCEL_CATEGORY_UI_STRING[index];
|
|
}
|
|
|
|
LLParcel::ECategory category_string_to_category(const char* s)
|
|
{
|
|
for(S32 i = 0; i < LLParcel::C_COUNT; ++i)
|
|
{
|
|
if(0 == strcmp(s, PARCEL_CATEGORY_STRING[i]))
|
|
{
|
|
return (LLParcel::ECategory)i;
|
|
}
|
|
}
|
|
llwarns << "Parcel category outside of possibilities " << s << llendl;
|
|
return LLParcel::C_NONE;
|
|
}
|
|
|
|
LLParcel::ECategory category_ui_string_to_category(const char* s)
|
|
{
|
|
for(S32 i = 0; i < LLParcel::C_COUNT; ++i)
|
|
{
|
|
if(0 == strcmp(s, PARCEL_CATEGORY_UI_STRING[i]))
|
|
{
|
|
return (LLParcel::ECategory)i;
|
|
}
|
|
}
|
|
// "Any" is a valid category for searches, and
|
|
// is a distinct option from "None" and "Other"
|
|
return LLParcel::C_ANY;
|
|
}
|
|
|