mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
Merge pull request #2 from ctrlaltdavid/fix/can-rez-attachment
Amend "can rez avatar entities" functionality
This commit is contained in:
commit
87def7a113
20 changed files with 389 additions and 52 deletions
|
@ -1124,15 +1124,11 @@ void AvatarMixer::handleOctreePacket(QSharedPointer<ReceivedMessage> message, Sh
|
|||
}
|
||||
|
||||
case PacketType::EntityData:
|
||||
if (senderNode->getCanRezAvatarEntities()) {
|
||||
_entityViewer.processDatagram(*message, senderNode);
|
||||
}
|
||||
_entityViewer.processDatagram(*message, senderNode);
|
||||
break;
|
||||
|
||||
case PacketType::EntityErase:
|
||||
if (senderNode->getCanRezAvatarEntities()) {
|
||||
_entityViewer.processEraseMessage(*message, senderNode);
|
||||
}
|
||||
_entityViewer.processEraseMessage(*message, senderNode);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -269,7 +269,14 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message,
|
|||
// the avatar mixer uses the negative value of the sent version
|
||||
instanceVersionRef = -packetTraitVersion;
|
||||
} else {
|
||||
_avatar->processTraitInstance(traitType, instanceID, message.read(traitSize));
|
||||
// Don't accept avatar entity data for distribution unless sender has rez permissions on the domain.
|
||||
// The sender shouldn't be sending avatar entity data, however this provides a back-up.
|
||||
if (sendingNode.getCanRezAvatarEntities()) {
|
||||
_avatar->processTraitInstance(traitType, instanceID, message.read(traitSize));
|
||||
} else {
|
||||
message.read(traitSize);
|
||||
}
|
||||
|
||||
instanceVersionRef = packetTraitVersion;
|
||||
}
|
||||
|
||||
|
@ -290,6 +297,27 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message,
|
|||
}
|
||||
}
|
||||
|
||||
void AvatarMixerClientData::emulateDeleteEntitiesTraitsMessage(const QList<QUuid>& avatarEntityIDs) {
|
||||
// Emulates processSetTraitsMessage() actions on behalf of an avatar whose canRezAvatarEntities permission has been removed.
|
||||
// The source avatar should be removing its avatar entities. However, this provides a back-up.
|
||||
|
||||
for (const auto& entityID : avatarEntityIDs) {
|
||||
auto traitType = AvatarTraits::AvatarEntity;
|
||||
auto& instanceVersionRef = _lastReceivedTraitVersions.getInstanceValueRef(traitType, entityID);
|
||||
|
||||
_avatar->processDeletedTraitInstance(traitType, entityID);
|
||||
// Mixer doesn't need deleted IDs.
|
||||
_avatar->getAndClearRecentlyRemovedIDs();
|
||||
|
||||
// to track a deleted instance but keep version information
|
||||
// the avatar mixer uses the negative value of the sent version
|
||||
// Because there is no originating message from an avatar we enlarge the magnitude by 1.
|
||||
instanceVersionRef = -instanceVersionRef - 1;
|
||||
}
|
||||
|
||||
_lastReceivedTraitsChange = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
void AvatarMixerClientData::processBulkAvatarTraitsAckMessage(ReceivedMessage& message) {
|
||||
// Avatar Traits flow control marks each outgoing avatar traits packet with a
|
||||
// sequence number. The mixer caches the traits sent in the traits packet.
|
||||
|
|
|
@ -132,6 +132,7 @@ public:
|
|||
int processPackets(const SlaveSharedData& slaveSharedData); // returns number of packets processed
|
||||
|
||||
void processSetTraitsMessage(ReceivedMessage& message, const SlaveSharedData& slaveSharedData, Node& sendingNode);
|
||||
void emulateDeleteEntitiesTraitsMessage(const QList<QUuid>& avatarEntityIDs);
|
||||
void processBulkAvatarTraitsAckMessage(ReceivedMessage& message);
|
||||
void checkSkeletonURLAgainstWhitelist(const SlaveSharedData& slaveSharedData, Node& sendingNode,
|
||||
AvatarTraits::TraitVersion traitVersion);
|
||||
|
|
|
@ -432,6 +432,17 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
|||
}
|
||||
}
|
||||
|
||||
// The source avatar should be removing its avatar entities. However, provide a back-up.
|
||||
if (sendAvatar) {
|
||||
if (!sourceAvatarNode->getCanRezAvatarEntities()) {
|
||||
auto sourceAvatarNodeData = reinterpret_cast<AvatarMixerClientData*>(sourceAvatarNode->getLinkedData());
|
||||
auto avatarEntityIDs = sourceAvatarNodeData->getAvatar().getAvatarEntityIDs();
|
||||
if (avatarEntityIDs.count() > 0) {
|
||||
sourceAvatarNodeData->emulateDeleteEntitiesTraitsMessage(avatarEntityIDs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sendAvatar) {
|
||||
AvatarDataSequenceNumber lastSeqToReceiver = destinationNodeData->getLastBroadcastSequenceNumber(sourceAvatarNode->getLocalID());
|
||||
AvatarDataSequenceNumber lastSeqFromSender = sourceAvatarNodeData->getLastReceivedSequenceNumber();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": 2.4,
|
||||
"version": 2.5,
|
||||
"settings": [
|
||||
{
|
||||
"name": "metaverse",
|
||||
|
@ -338,7 +338,7 @@
|
|||
"name": "standard_permissions",
|
||||
"type": "table",
|
||||
"label": "Domain-Wide User Permissions",
|
||||
"help": "Indicate which types of users can have which <a data-toggle='tooltip' data-html=true title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether a user can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether a user change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether a user can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether a user can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether a user can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether a user can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether a user can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Rez Certified</strong><br />Sets whether a user can create new certified entities.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Note that permissions assigned to a specific user will supersede any parameter-level permissions that might otherwise apply to that user. Additionally, if more than one parameter is applicable to a given user, the permissions given to that user will be the sum of all applicable parameters. For example, let’s say only localhost users can connect and only logged in users can lock and unlock entities. If a user is both logged in and on localhost then they will be able to both connect and lock/unlock entities.</p>'>domain-wide permissions</a>.",
|
||||
"help": "Indicate which types of users can have which <a data-toggle='tooltip' data-html=true title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether a user can connect to the domain.</li><li><strong>Rez Avatar Entities</strong><br />Sets whether a user can rez avatar entities.</li><li><strong>Lock / Unlock</strong><br />Sets whether a user change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether a user can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether a user can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether a user can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether a user can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether a user can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Rez Certified</strong><br />Sets whether a user can create new certified entities.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Note that permissions assigned to a specific user will supersede any parameter-level permissions that might otherwise apply to that user. Additionally, if more than one parameter is applicable to a given user, the permissions given to that user will be the sum of all applicable parameters. For example, let’s say only localhost users can connect and only logged in users can lock and unlock entities. If a user is both logged in and on localhost then they will be able to both connect and lock/unlock entities.</p>'>domain-wide permissions</a>.",
|
||||
"caption": "Standard Permissions",
|
||||
"can_add_new_rows": false,
|
||||
"groups": [
|
||||
|
@ -347,8 +347,8 @@
|
|||
"span": 1
|
||||
},
|
||||
{
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether a user can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether a user change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether a user can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether a user can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether a user can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether a user can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether a user can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether a user can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Note that permissions assigned to a specific user will supersede any parameter-level permissions that might otherwise apply to that user. Additionally, if more than one parameter is applicable to a given user, the permissions given to that user will be the sum of all applicable parameters. For example, let’s say only localhost users can connect and only logged in users can lock and unlock entities. If a user is both logged in and on localhost then they will be able to both connect and lock/unlock entities.</p>'>?</a>",
|
||||
"span": 11
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether a user can connect to the domain.</li><li><strong>Rez Avatar Entities</strong><br />Sets whether a user can rez avatar entities.</li><li><strong>Lock / Unlock</strong><br />Sets whether a user change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether a user can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether a user can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether a user can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether a user can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether a user can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether a user can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Note that permissions assigned to a specific user will supersede any parameter-level permissions that might otherwise apply to that user. Additionally, if more than one parameter is applicable to a given user, the permissions given to that user will be the sum of all applicable parameters. For example, let’s say only localhost users can connect and only logged in users can lock and unlock entities. If a user is both logged in and on localhost then they will be able to both connect and lock/unlock entities.</p>'>?</a>",
|
||||
"span": 12
|
||||
}
|
||||
],
|
||||
"columns": [
|
||||
|
@ -365,7 +365,7 @@
|
|||
},
|
||||
{
|
||||
"name": "id_can_rez_avatar_entities",
|
||||
"label": "Rez Attachments",
|
||||
"label": "Rez Avatar Entities",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
|
@ -492,8 +492,8 @@
|
|||
"span": 1
|
||||
},
|
||||
{
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether users in specific groups can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether users in specific groups can change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether users in specific groups can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether users in specific groups can create new entities with a finite lifetime.</li><li><strong>Rez Temporary</strong><br />Sets whether users in specific groups can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether a users in specific groups can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether a user can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether users in specific groups can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether user in specific groups can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether a user can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Permissions granted to a specific user will be a union of the permissions granted to the groups they are in, as well as permissions from the previous section. Group permissions are only granted if the user doesn’t have their own row in the per-account section, below.</p>'>?</a>",
|
||||
"span": 11
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether users in specific groups can connect to the domain.</li><li><strong>Rez Avatar Entities</strong><br />Sets whether a user can rez avatar entities.</li><li><strong>Lock / Unlock</strong><br />Sets whether users in specific groups can change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether users in specific groups can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether users in specific groups can create new entities with a finite lifetime.</li><li><strong>Rez Temporary</strong><br />Sets whether users in specific groups can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether a users in specific groups can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether a user can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether users in specific groups can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether user in specific groups can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether a user can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Permissions granted to a specific user will be a union of the permissions granted to the groups they are in, as well as permissions from the previous section. Group permissions are only granted if the user doesn’t have their own row in the per-account section, below.</p>'>?</a>",
|
||||
"span": 12
|
||||
}
|
||||
],
|
||||
"columns": [
|
||||
|
@ -535,7 +535,7 @@
|
|||
},
|
||||
{
|
||||
"name": "id_can_rez_avatar_entities",
|
||||
"label": "Rez Attachments",
|
||||
"label": "Rez Avatar Entities",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
|
@ -628,8 +628,8 @@
|
|||
"span": 1
|
||||
},
|
||||
{
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether users in specific groups can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether users in specific groups can change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether users in specific groups can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether users in specific groups can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether a users in specific groups can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether a user can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether users in specific groups can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether user in specific groups can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether users in specific groups can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property</li></ul><p>Permissions granted to a specific user will be a union of the permissions granted to the groups they are in. Group permissions are only granted if the user doesn’t have their own row in the per-account section, below.</p>'>?</a>",
|
||||
"span": 11
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether users in specific groups can connect to the domain.</li><li><strong>Rez Avatar Entities</strong><br />Sets whether a user can rez avatar entities.</li><li><strong>Lock / Unlock</strong><br />Sets whether users in specific groups can change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether users in specific groups can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether users in specific groups can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether a users in specific groups can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether a user can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether users in specific groups can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether user in specific groups can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether users in specific groups can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property</li></ul><p>Permissions granted to a specific user will be a union of the permissions granted to the groups they are in. Group permissions are only granted if the user doesn’t have their own row in the per-account section, below.</p>'>?</a>",
|
||||
"span": 12
|
||||
}
|
||||
],
|
||||
"columns": [
|
||||
|
@ -668,7 +668,7 @@
|
|||
},
|
||||
{
|
||||
"name": "id_can_rez_avatar_entities",
|
||||
"label": "Rez Attachments",
|
||||
"label": "Rez Avatar Entities",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
|
@ -756,8 +756,8 @@
|
|||
"span": 1
|
||||
},
|
||||
{
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether a user can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether a user change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether a user can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether a user can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether a user can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether a user can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether a user can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether a user can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Note that permissions assigned to a specific user will supersede any parameter-level or group permissions that might otherwise apply to that user.</p>'>?</a>",
|
||||
"span": 11
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether a user can connect to the domain.</li><li><strong>Rez Avatar Entities</strong><br />Sets whether a user can rez avatar entities.</li><li><strong>Lock / Unlock</strong><br />Sets whether a user change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether a user can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether a user can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether a user can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether a user can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether a user can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether a user can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Note that permissions assigned to a specific user will supersede any parameter-level or group permissions that might otherwise apply to that user.</p>'>?</a>",
|
||||
"span": 12
|
||||
}
|
||||
],
|
||||
"columns": [
|
||||
|
@ -774,7 +774,7 @@
|
|||
},
|
||||
{
|
||||
"name": "id_can_rez_avatar_entities",
|
||||
"label": "Rez Attachments",
|
||||
"label": "Rez Avatar Entities",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
|
@ -862,8 +862,8 @@
|
|||
"span": 1
|
||||
},
|
||||
{
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide IP Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether users from specific IPs can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether users from specific IPs can change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether users from specific IPs can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether users from specific IPs can create new entities with a finite lifetime.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether users from specific IPs can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether users from specific IPs can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether users from specific IPs can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether users from specific IPs can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether users from specific IPs can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Note that permissions assigned to a specific IP will supersede any parameter-level permissions that might otherwise apply to that user (from groups or standard permissions above). IP address permissions are overriden if the user has their own row in the users section.</p>'>?</a>",
|
||||
"span": 11
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide IP Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether users from specific IPs can connect to the domain.</li><li><strong>Rez Avatar Entities</strong><br />Sets whether a user can rez avatar entities.</li><li><strong>Lock / Unlock</strong><br />Sets whether users from specific IPs can change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether users from specific IPs can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether users from specific IPs can create new entities with a finite lifetime.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether users from specific IPs can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether users from specific IPs can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether users from specific IPs can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether users from specific IPs can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether users from specific IPs can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Note that permissions assigned to a specific IP will supersede any parameter-level permissions that might otherwise apply to that user (from groups or standard permissions above). IP address permissions are overriden if the user has their own row in the users section.</p>'>?</a>",
|
||||
"span": 12
|
||||
}
|
||||
],
|
||||
"columns": [
|
||||
|
@ -880,7 +880,7 @@
|
|||
},
|
||||
{
|
||||
"name": "id_can_rez_avatar_entities",
|
||||
"label": "Rez Attachments",
|
||||
"label": "Rez Avatar Entities",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
|
@ -968,8 +968,8 @@
|
|||
"span": 1
|
||||
},
|
||||
{
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide MAC Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether users with specific MACs can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether users from specific MACs can change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether users with specific MACs can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether users with specific MACs can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether users with specific MACs can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether users with specific MACs can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether users with specific MACs can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether users with specific MACs can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether users with specific MACs can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Note that permissions assigned to a specific MAC will supersede any parameter-level permissions that might otherwise apply to that user (from groups or standard permissions above). MAC address permissions are overriden if the user has their own row in the users section.</p>'>?</a>",
|
||||
"span": 11
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide MAC Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether users with specific MACs can connect to the domain.</li><li><strong>Rez Avatar Entities</strong><br />Sets whether a user can rez avatar entities.</li><li><strong>Lock / Unlock</strong><br />Sets whether users from specific MACs can change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether users with specific MACs can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether users with specific MACs can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether users with specific MACs can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether users with specific MACs can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether users with specific MACs can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether users with specific MACs can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether users with specific MACs can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Note that permissions assigned to a specific MAC will supersede any parameter-level permissions that might otherwise apply to that user (from groups or standard permissions above). MAC address permissions are overriden if the user has their own row in the users section.</p>'>?</a>",
|
||||
"span": 12
|
||||
}
|
||||
],
|
||||
"columns": [
|
||||
|
@ -986,7 +986,7 @@
|
|||
},
|
||||
{
|
||||
"name": "id_can_rez_avatar_entities",
|
||||
"label": "Rez Attachments",
|
||||
"label": "Rez Avatar Entities",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
|
@ -1074,8 +1074,8 @@
|
|||
"span": 1
|
||||
},
|
||||
{
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide Machine Fingerprint Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether users with specific Machine Fingerprints can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether users from specific Machine Fingerprints can change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether users with specific Machine Fingerprints can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether users with specific Machine Fingerprints can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether users with specific Machine Fingerprints can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether users with specific Machine Fingerprints can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether users with specific Machine Fingerprints can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether users with specific Machine Fingerprints can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether users with specific Machine Fingerprints can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Note that permissions assigned to a specific Machine Fingerprint will supersede any parameter-level permissions that might otherwise apply to that user (from groups or standard permissions above). Machine Fingerprint address permissions are overriden if the user has their own row in the users section.</p>'>?</a>",
|
||||
"span": 11
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide Machine Fingerprint Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether users with specific Machine Fingerprints can connect to the domain.</li><li><strong>Rez Avatar Entities</strong><br />Sets whether a user can rez avatar entities.</li><li><strong>Lock / Unlock</strong><br />Sets whether users from specific Machine Fingerprints can change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether users with specific Machine Fingerprints can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether users with specific Machine Fingerprints can create new entities with a finite lifetime.</li><li><strong>Rez Certified</strong><br />Sets whether users with specific Machine Fingerprints can create new certified entities.</li><li><strong>Rez Temporary Certified</strong><br />Sets whether users with specific Machine Fingerprints can create new certified entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether users with specific Machine Fingerprints can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether users with specific Machine Fingerprints can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether users with specific Machine Fingerprints can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Note that permissions assigned to a specific Machine Fingerprint will supersede any parameter-level permissions that might otherwise apply to that user (from groups or standard permissions above). Machine Fingerprint address permissions are overriden if the user has their own row in the users section.</p>'>?</a>",
|
||||
"span": 12
|
||||
}
|
||||
],
|
||||
"columns": [
|
||||
|
@ -1092,7 +1092,7 @@
|
|||
},
|
||||
{
|
||||
"name": "id_can_rez_avatar_entities",
|
||||
"label": "Rez Attachments",
|
||||
"label": "Rez Avatar Entities",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
|
|
|
@ -363,9 +363,6 @@ void DomainServerSettingsManager::setupConfigMap(const QString& userConfigFilena
|
|||
foreach (auto permissionsSet, permissionsSets) {
|
||||
for (auto entry : permissionsSet) {
|
||||
const auto& userKey = entry.first;
|
||||
|
||||
permissionsSet[userKey]->set(NodePermissions::Permission::canRezAvatarEntities);
|
||||
|
||||
if (onlyEditorsAreRezzers) {
|
||||
if (permissionsSet[userKey]->can(NodePermissions::Permission::canAdjustLocks)) {
|
||||
permissionsSet[userKey]->set(NodePermissions::Permission::canRezPermanentEntities);
|
||||
|
@ -530,6 +527,28 @@ void DomainServerSettingsManager::setupConfigMap(const QString& userConfigFilena
|
|||
*newAdminRoles = adminRoles;
|
||||
}
|
||||
|
||||
if (oldVersion < 2.5) {
|
||||
// Default values for new canRezAvatarEntities permission.
|
||||
unpackPermissions();
|
||||
std::list<std::unordered_map<NodePermissionsKey, NodePermissionsPointer>> permissionsSets{
|
||||
_standardAgentPermissions.get(),
|
||||
_agentPermissions.get(),
|
||||
_ipPermissions.get(),
|
||||
_macPermissions.get(),
|
||||
_machineFingerprintPermissions.get(),
|
||||
_groupPermissions.get(),
|
||||
_groupForbiddens.get()
|
||||
};
|
||||
foreach (auto permissionsSet, permissionsSets) {
|
||||
for (auto entry : permissionsSet) {
|
||||
const auto& userKey = entry.first;
|
||||
if (permissionsSet[userKey]->can(NodePermissions::Permission::canConnectToDomain)) {
|
||||
permissionsSet[userKey]->set(NodePermissions::Permission::canRezAvatarEntities);
|
||||
}
|
||||
}
|
||||
}
|
||||
packPermissions();
|
||||
}
|
||||
|
||||
// write the current description version to our settings
|
||||
*versionVariant = _descriptionVersion;
|
||||
|
@ -1451,6 +1470,8 @@ QJsonObject DomainServerSettingsManager::settingsResponseObjectForType(const QSt
|
|||
SettingsBackupFlag settingsBackupFlag) {
|
||||
QJsonObject responseObject;
|
||||
|
||||
responseObject["version"] = _descriptionVersion; // Domain settings version number.
|
||||
|
||||
if (!typeValue.isEmpty() || authentication == Authenticated) {
|
||||
// convert the string type value to a QJsonValue
|
||||
QJsonValue queryType = typeValue.isEmpty() ? QJsonValue() : QJsonValue(typeValue.toInt());
|
||||
|
|
|
@ -518,7 +518,12 @@ Rectangle {
|
|||
glyphText: "\ue02e"
|
||||
|
||||
onClicked: {
|
||||
adjustWearables.open(currentAvatar);
|
||||
if (!AddressManager.isConnected || Entities.canRezAvatarEntities()) {
|
||||
adjustWearables.open(currentAvatar);
|
||||
} else {
|
||||
Window.alert("You cannot use wearables on this domain.")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -529,7 +534,11 @@ Rectangle {
|
|||
glyphText: wearablesFrozen ? hifi.glyphs.lock : hifi.glyphs.unlock;
|
||||
|
||||
onClicked: {
|
||||
emitSendToScript({'method' : 'toggleWearablesFrozen'});
|
||||
if (!AddressManager.isConnected || Entities.canRezAvatarEntities()) {
|
||||
emitSendToScript({'method' : 'toggleWearablesFrozen'});
|
||||
} else {
|
||||
Window.alert("You cannot use wearables on this domain.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1306,6 +1306,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
_entityServerConnectionTimer.setSingleShot(true);
|
||||
connect(&_entityServerConnectionTimer, &QTimer::timeout, this, &Application::setFailedToConnectToEntityServer);
|
||||
|
||||
connect(&domainHandler, &DomainHandler::confirmConnectWithoutAvatarEntities,
|
||||
this, &Application::confirmConnectWithoutAvatarEntities);
|
||||
|
||||
connect(&domainHandler, &DomainHandler::connectedToDomain, this, [this]() {
|
||||
if (!isServerlessMode()) {
|
||||
_entityServerConnectionTimer.setInterval(ENTITY_SERVER_ADDED_TIMEOUT);
|
||||
|
@ -9172,6 +9175,32 @@ void Application::setShowBulletConstraintLimits(bool value) {
|
|||
_physicsEngine->setShowBulletConstraintLimits(value);
|
||||
}
|
||||
|
||||
void Application::confirmConnectWithoutAvatarEntities() {
|
||||
|
||||
if (_confirmConnectWithoutAvatarEntitiesDialog) {
|
||||
// Dialog is already displayed.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!getMyAvatar()->hasAvatarEntities()) {
|
||||
// No avatar entities so continue with login.
|
||||
DependencyManager::get<NodeList>()->getDomainHandler().setCanConnectWithoutAvatarEntities(true);
|
||||
return;
|
||||
}
|
||||
|
||||
QString continueMessage = "Your wearables will not display on this domain. Continue?";
|
||||
_confirmConnectWithoutAvatarEntitiesDialog = OffscreenUi::asyncQuestion("Continue Without Wearables", continueMessage,
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if (_confirmConnectWithoutAvatarEntitiesDialog->getDialogItem()) {
|
||||
QObject::connect(_confirmConnectWithoutAvatarEntitiesDialog, &ModalDialogListener::response, this, [=](QVariant answer) {
|
||||
QObject::disconnect(_confirmConnectWithoutAvatarEntitiesDialog, &ModalDialogListener::response, this, nullptr);
|
||||
_confirmConnectWithoutAvatarEntitiesDialog = nullptr;
|
||||
bool shouldConnect = (static_cast<QMessageBox::StandardButton>(answer.toInt()) == QMessageBox::Yes);
|
||||
DependencyManager::get<NodeList>()->getDomainHandler().setCanConnectWithoutAvatarEntities(shouldConnect);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Application::createLoginDialog() {
|
||||
const glm::vec3 LOGIN_DIMENSIONS { 0.89f, 0.5f, 0.01f };
|
||||
const auto OFFSET = glm::vec2(0.7f, -0.1f);
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <shared/ConicalViewFrustum.h>
|
||||
#include <shared/FileLogger.h>
|
||||
#include <RunningMarker.h>
|
||||
#include <OffscreenUI.h>
|
||||
|
||||
#include "avatar/MyAvatar.h"
|
||||
#include "FancyCamera.h"
|
||||
|
@ -325,6 +326,8 @@ public:
|
|||
int getOtherAvatarsReplicaCount() { return DependencyManager::get<AvatarHashMap>()->getReplicaCount(); }
|
||||
void setOtherAvatarsReplicaCount(int count) { DependencyManager::get<AvatarHashMap>()->setReplicaCount(count); }
|
||||
|
||||
void confirmConnectWithoutAvatarEntities();
|
||||
|
||||
bool getLoginDialogPoppedUp() const { return _loginDialogPoppedUp; }
|
||||
void createLoginDialog();
|
||||
void updateLoginDialogPosition();
|
||||
|
@ -723,6 +726,8 @@ private:
|
|||
bool _loginDialogPoppedUp{ false };
|
||||
bool _desktopRootItemCreated{ false };
|
||||
|
||||
ModalDialogListener* _confirmConnectWithoutAvatarEntitiesDialog { nullptr };
|
||||
|
||||
bool _developerMenuVisible{ false };
|
||||
QString _previousAvatarSkeletonModel;
|
||||
float _previousAvatarTargetScale;
|
||||
|
|
|
@ -35,6 +35,7 @@ void ConnectionMonitor::init() {
|
|||
connect(&domainHandler, &DomainHandler::connectedToDomain, this, &ConnectionMonitor::stopTimer);
|
||||
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ConnectionMonitor::stopTimer);
|
||||
connect(&domainHandler, &DomainHandler::redirectToErrorDomainURL, this, &ConnectionMonitor::stopTimer);
|
||||
connect(&domainHandler, &DomainHandler::confirmConnectWithoutAvatarEntities, this, &ConnectionMonitor::stopTimer);
|
||||
connect(this, &ConnectionMonitor::setRedirectErrorState, &domainHandler, &DomainHandler::setRedirectErrorState);
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
connect(accountManager.data(), &AccountManager::loginComplete, this, &ConnectionMonitor::startTimer);
|
||||
|
|
|
@ -278,6 +278,9 @@ MyAvatar::MyAvatar(QThread* thread) :
|
|||
// when we leave a domain we lift whatever restrictions that domain may have placed on our scale
|
||||
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &MyAvatar::leaveDomain);
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
connect(nodeList.data(), &NodeList::canRezAvatarEntitiesChanged, this, &MyAvatar::handleCanRezAvatarEntitiesChanged);
|
||||
|
||||
_bodySensorMatrix = deriveBodyFromHMDSensor();
|
||||
|
||||
using namespace recording;
|
||||
|
@ -1533,7 +1536,19 @@ void MyAvatar::storeAvatarEntityDataPayload(const QUuid& entityID, const QByteAr
|
|||
|
||||
void MyAvatar::clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFromTree) {
|
||||
// NOTE: the requiresRemovalFromTree argument is unused
|
||||
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp) << "Ignoring clearAvatarEntity() because don't have canRezAvatarEntities permission on domain";
|
||||
return;
|
||||
}
|
||||
|
||||
AvatarData::clearAvatarEntity(entityID);
|
||||
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
// Don't delete potentially non-rezzed avatar entities from cache, otherwise they're removed from settings.
|
||||
return;
|
||||
}
|
||||
|
||||
_avatarEntitiesLock.withWriteLock([&] {
|
||||
_cachedAvatarEntityBlobsToDelete.push_back(entityID);
|
||||
});
|
||||
|
@ -1564,6 +1579,29 @@ void MyAvatar::sanitizeAvatarEntityProperties(EntityItemProperties& properties)
|
|||
properties.markAllChanged();
|
||||
}
|
||||
|
||||
void MyAvatar::addAvatarEntitiesToTree() {
|
||||
AvatarEntityMap::const_iterator constItr = _cachedAvatarEntityBlobs.begin();
|
||||
while (constItr != _cachedAvatarEntityBlobs.end()) {
|
||||
QUuid id = constItr.key();
|
||||
_entitiesToAdd.push_back(id); // worked once: hat shown. then unshown when permissions removed but then entity was deleted somewhere along the line!
|
||||
++constItr;
|
||||
}
|
||||
}
|
||||
|
||||
bool MyAvatar::hasAvatarEntities() const {
|
||||
return _cachedAvatarEntityBlobs.count() > 0;
|
||||
}
|
||||
|
||||
void MyAvatar::handleCanRezAvatarEntitiesChanged(bool canRezAvatarEntities) {
|
||||
if (canRezAvatarEntities) {
|
||||
// Start displaying avatar entities.
|
||||
addAvatarEntitiesToTree();
|
||||
} else {
|
||||
// Stop displaying avatar entities.
|
||||
removeAvatarEntitiesFromTree();
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::handleChangedAvatarEntityData() {
|
||||
// NOTE: this is a per-frame update
|
||||
if (getID().isNull() ||
|
||||
|
@ -1583,6 +1621,8 @@ void MyAvatar::handleChangedAvatarEntityData() {
|
|||
return;
|
||||
}
|
||||
|
||||
bool canRezAvatarEntites = DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities();
|
||||
|
||||
// We collect changes to AvatarEntities and then handle them all in one spot per frame: handleChangedAvatarEntityData().
|
||||
// Basically this is a "transaction pattern" with an extra complication: these changes can come from two
|
||||
// "directions" and the "authoritative source" of each direction is different, so we maintain two distinct sets
|
||||
|
@ -1669,12 +1709,15 @@ void MyAvatar::handleChangedAvatarEntityData() {
|
|||
continue;
|
||||
}
|
||||
sanitizeAvatarEntityProperties(properties);
|
||||
entityTree->withWriteLock([&] {
|
||||
EntityItemPointer entity = entityTree->addEntity(id, properties);
|
||||
if (entity) {
|
||||
packetSender->queueEditAvatarEntityMessage(entityTree, id);
|
||||
}
|
||||
});
|
||||
if (canRezAvatarEntites) {
|
||||
entityTree->withWriteLock([&] {
|
||||
EntityItemPointer entity = entityTree->addEntity(id, properties);
|
||||
if (entity) {
|
||||
packetSender->queueEditAvatarEntityMessage(entityTree, id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// CHANGE real entities
|
||||
|
@ -1692,7 +1735,7 @@ void MyAvatar::handleChangedAvatarEntityData() {
|
|||
skip = true;
|
||||
}
|
||||
});
|
||||
if (!skip) {
|
||||
if (!skip && canRezAvatarEntites) {
|
||||
sanitizeAvatarEntityProperties(properties);
|
||||
entityTree->withWriteLock([&] {
|
||||
if (entityTree->updateEntity(id, properties)) {
|
||||
|
@ -1834,6 +1877,11 @@ AvatarEntityMap MyAvatar::getAvatarEntityData() const {
|
|||
return data;
|
||||
}
|
||||
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp) << "Ignoring getAvatarEntityData() because don't have canRezAvatarEntities permission on domain";
|
||||
return data;
|
||||
}
|
||||
|
||||
QList<QUuid> avatarEntityIDs;
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
avatarEntityIDs = _packedAvatarEntityData.keys();
|
||||
|
@ -1879,6 +1927,12 @@ void MyAvatar::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) {
|
|||
// avatarEntityData is expected to be a map of QByteArrays that represent EntityItemProperties objects from JavaScript,
|
||||
// aka: unfortunately-formatted-binary-blobs because we store them in non-human-readable format in Settings.
|
||||
//
|
||||
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp) << "Ignoring setAvatarEntityData() because don't have canRezAvatarEntities permission on domain";
|
||||
return;
|
||||
}
|
||||
|
||||
if (avatarEntityData.size() > MAX_NUM_AVATAR_ENTITIES) {
|
||||
// the data is suspect
|
||||
qCDebug(interfaceapp) << "discard suspect AvatarEntityData with size =" << avatarEntityData.size();
|
||||
|
@ -1939,6 +1993,12 @@ void MyAvatar::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) {
|
|||
|
||||
void MyAvatar::updateAvatarEntity(const QUuid& entityID, const QByteArray& entityData) {
|
||||
// NOTE: this is an invokable Script call
|
||||
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp) << "Ignoring updateAvatarEntity() because don't have canRezAvatarEntities permission on domain";
|
||||
return;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
_avatarEntitiesLock.withWriteLock([&] {
|
||||
auto data = QJsonDocument::fromBinaryData(entityData);
|
||||
|
@ -2565,6 +2625,13 @@ QVariantList MyAvatar::getAvatarEntitiesVariant() {
|
|||
QVariantList avatarEntitiesData;
|
||||
auto treeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr;
|
||||
|
||||
if (entityTree && !DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp)
|
||||
<< "Ignoring getAvatarEntitiesVariant() because don't have canRezAvatarEntities permission on domain";
|
||||
return avatarEntitiesData;
|
||||
}
|
||||
|
||||
if (entityTree) {
|
||||
QList<QUuid> avatarEntityIDs;
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
|
@ -2897,6 +2964,11 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName,
|
|||
);
|
||||
return;
|
||||
}
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp) << "Ignoring attach() because don't have canRezAvatarEntities permission on domain";
|
||||
return;
|
||||
}
|
||||
|
||||
AttachmentData data;
|
||||
data.modelURL = modelURL;
|
||||
data.jointName = jointName;
|
||||
|
@ -2918,6 +2990,11 @@ void MyAvatar::detachOne(const QString& modelURL, const QString& jointName) {
|
|||
);
|
||||
return;
|
||||
}
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp) << "Ignoring detachOne() because don't have canRezAvatarEntities permission on domain";
|
||||
return;
|
||||
}
|
||||
|
||||
QUuid entityID;
|
||||
if (findAvatarEntity(modelURL, jointName, entityID)) {
|
||||
DependencyManager::get<EntityScriptingInterface>()->deleteEntity(entityID);
|
||||
|
@ -2933,6 +3010,11 @@ void MyAvatar::detachAll(const QString& modelURL, const QString& jointName) {
|
|||
);
|
||||
return;
|
||||
}
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp) << "Ignoring detachAll() because don't have canRezAvatarEntities permission on domain";
|
||||
return;
|
||||
}
|
||||
|
||||
QUuid entityID;
|
||||
while (findAvatarEntity(modelURL, jointName, entityID)) {
|
||||
DependencyManager::get<EntityScriptingInterface>()->deleteEntity(entityID);
|
||||
|
@ -2946,6 +3028,11 @@ void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData)
|
|||
Q_ARG(const QVector<AttachmentData>&, attachmentData));
|
||||
return;
|
||||
}
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp) << "Ignoring setAttachmentData() because don't have canRezAvatarEntities permission on domain";
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<EntityItemProperties> newEntitiesProperties;
|
||||
for (auto& data : attachmentData) {
|
||||
QUuid entityID;
|
||||
|
@ -2968,6 +3055,12 @@ void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData)
|
|||
|
||||
QVector<AttachmentData> MyAvatar::getAttachmentData() const {
|
||||
QVector<AttachmentData> attachmentData;
|
||||
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp) << "Ignoring getAttachmentData() because don't have canRezAvatarEntities permission on domain";
|
||||
return attachmentData;
|
||||
}
|
||||
|
||||
QList<QUuid> avatarEntityIDs;
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
avatarEntityIDs = _packedAvatarEntityData.keys();
|
||||
|
@ -2982,6 +3075,13 @@ QVector<AttachmentData> MyAvatar::getAttachmentData() const {
|
|||
|
||||
QVariantList MyAvatar::getAttachmentsVariant() const {
|
||||
QVariantList result;
|
||||
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp)
|
||||
<< "Ignoring getAttachmentsVariant() because don't have canRezAvatarEntities permission on domain";
|
||||
return result;
|
||||
}
|
||||
|
||||
for (const auto& attachment : getAttachmentData()) {
|
||||
result.append(attachment.toVariant());
|
||||
}
|
||||
|
@ -2994,6 +3094,13 @@ void MyAvatar::setAttachmentsVariant(const QVariantList& variant) {
|
|||
Q_ARG(const QVariantList&, variant));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp)
|
||||
<< "Ignoring setAttachmentsVariant() because don't have canRezAvatarEntities permission on domain";
|
||||
return;
|
||||
}
|
||||
|
||||
QVector<AttachmentData> newAttachments;
|
||||
newAttachments.reserve(variant.size());
|
||||
for (const auto& attachmentVar : variant) {
|
||||
|
@ -4065,7 +4172,8 @@ float MyAvatar::getGravity() {
|
|||
void MyAvatar::setSessionUUID(const QUuid& sessionUUID) {
|
||||
QUuid oldSessionID = getSessionUUID();
|
||||
Avatar::setSessionUUID(sessionUUID);
|
||||
bool sendPackets = !DependencyManager::get<NodeList>()->getSessionUUID().isNull();
|
||||
bool sendPackets = !DependencyManager::get<NodeList>()->getSessionUUID().isNull()
|
||||
&& DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities();
|
||||
if (!sendPackets) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1454,6 +1454,7 @@ public:
|
|||
|
||||
void removeWornAvatarEntity(const EntityItemID& entityID);
|
||||
void clearWornAvatarEntities();
|
||||
bool hasAvatarEntities() const;
|
||||
|
||||
/**jsdoc
|
||||
* Checks whether your avatar is flying.
|
||||
|
@ -1939,6 +1940,8 @@ public:
|
|||
|
||||
void avatarEntityDataToJson(QJsonObject& root) const override;
|
||||
|
||||
void storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& payload) override;
|
||||
|
||||
/**jsdoc
|
||||
* @comment Uses the base class's JSDoc.
|
||||
*/
|
||||
|
@ -2277,12 +2280,6 @@ public slots:
|
|||
*/
|
||||
bool getEnableMeshVisible() const override;
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.storeAvatarEntityDataPayload
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
void storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& payload) override;
|
||||
|
||||
/**jsdoc
|
||||
* @comment Uses the base class's JSDoc.
|
||||
*/
|
||||
|
@ -2656,6 +2653,7 @@ private slots:
|
|||
|
||||
protected:
|
||||
void handleChangedAvatarEntityData();
|
||||
void handleCanRezAvatarEntitiesChanged(bool canRezAvatarEntities);
|
||||
virtual void beParentOfChild(SpatiallyNestablePointer newChild) const override;
|
||||
virtual void forgetChild(SpatiallyNestablePointer newChild) const override;
|
||||
virtual void recalculateChildCauterization() const override;
|
||||
|
@ -2710,6 +2708,7 @@ private:
|
|||
void attachmentDataToEntityProperties(const AttachmentData& data, EntityItemProperties& properties);
|
||||
AttachmentData entityPropertiesToAttachmentData(const EntityItemProperties& properties) const;
|
||||
bool findAvatarEntity(const QString& modelURL, const QString& jointName, QUuid& entityID);
|
||||
void addAvatarEntitiesToTree();
|
||||
|
||||
bool cameraInsideHead(const glm::vec3& cameraPosition) const;
|
||||
|
||||
|
|
|
@ -3046,6 +3046,24 @@ void AvatarData::clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFr
|
|||
}
|
||||
}
|
||||
|
||||
void AvatarData::clearAvatarEntities() {
|
||||
QList<QUuid> avatarEntityIDs;
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
avatarEntityIDs = _packedAvatarEntityData.keys();
|
||||
});
|
||||
for (const auto& entityID : avatarEntityIDs) {
|
||||
clearAvatarEntity(entityID);
|
||||
}
|
||||
}
|
||||
|
||||
QList<QUuid> AvatarData::getAvatarEntityIDs() const {
|
||||
QList<QUuid> avatarEntityIDs;
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
avatarEntityIDs = _packedAvatarEntityData.keys();
|
||||
});
|
||||
return avatarEntityIDs;
|
||||
}
|
||||
|
||||
AvatarEntityMap AvatarData::getAvatarEntityData() const {
|
||||
// overridden where needed
|
||||
// NOTE: the return value is expected to be a map of unfortunately-formatted-binary-blobs
|
||||
|
|
|
@ -1186,6 +1186,10 @@ public:
|
|||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE virtual void clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFromTree = true);
|
||||
|
||||
void clearAvatarEntities();
|
||||
|
||||
QList<QUuid> getAvatarEntityIDs() const;
|
||||
|
||||
/**jsdoc
|
||||
* Enables blend shapes set using {@link Avatar.setBlendshape} or {@link MyAvatar.setBlendshape} to be transmitted to other
|
||||
|
|
|
@ -487,6 +487,15 @@ QUuid EntityScriptingInterface::addEntityInternal(const EntityItemProperties& pr
|
|||
|
||||
_activityTracking.addedEntityCount++;
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
if (entityHostType == entity::HostType::AVATAR && !nodeList->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(entities) << "Ignoring addEntity() because don't have canRezAvatarEntities permission on domain";
|
||||
// Only need to intercept methods that may add an avatar entity because avatar entities are removed from the tree when
|
||||
// the user doesn't have canRezAvatarEntities permission.
|
||||
return QUuid();
|
||||
}
|
||||
|
||||
EntityItemProperties propertiesWithSimID = properties;
|
||||
propertiesWithSimID.setEntityHostType(entityHostType);
|
||||
if (entityHostType == entity::HostType::AVATAR) {
|
||||
|
@ -499,7 +508,6 @@ QUuid EntityScriptingInterface::addEntityInternal(const EntityItemProperties& pr
|
|||
}
|
||||
|
||||
// the created time will be set in EntityTree::addEntity by recordCreationTime()
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
auto sessionID = nodeList->getSessionUUID();
|
||||
propertiesWithSimID.setLastEditedBy(sessionID);
|
||||
|
||||
|
|
|
@ -126,6 +126,8 @@ void DomainHandler::hardReset(QString reason) {
|
|||
emit resetting();
|
||||
|
||||
softReset(reason);
|
||||
_haveAskedConnectWithoutAvatarEntities = false;
|
||||
_canConnectWithoutAvatarEntities = false;
|
||||
_isInErrorState = false;
|
||||
emit redirectErrorStateChanged(_isInErrorState);
|
||||
|
||||
|
@ -364,10 +366,14 @@ void DomainHandler::setIsConnected(bool isConnected) {
|
|||
_lastDomainConnectionError = -1;
|
||||
emit connectedToDomain(_domainURL);
|
||||
|
||||
// FIXME: Reinstate the requestDomainSettings() call here in version 2021.2.0 instead of having it in
|
||||
// NodeList::processDomainServerList().
|
||||
/*
|
||||
if (_domainURL.scheme() == URL_SCHEME_HIFI && !_domainURL.host().isEmpty()) {
|
||||
// we've connected to new domain - time to ask it for global settings
|
||||
requestDomainSettings();
|
||||
}
|
||||
*/
|
||||
|
||||
} else {
|
||||
emit disconnectedFromDomain();
|
||||
|
@ -375,6 +381,24 @@ void DomainHandler::setIsConnected(bool isConnected) {
|
|||
}
|
||||
}
|
||||
|
||||
void DomainHandler::setCanConnectWithoutAvatarEntities(bool canConnect) {
|
||||
_canConnectWithoutAvatarEntities = canConnect;
|
||||
_haveAskedConnectWithoutAvatarEntities = true;
|
||||
}
|
||||
|
||||
bool DomainHandler::canConnectWithoutAvatarEntities() {
|
||||
if (!_canConnectWithoutAvatarEntities && !_haveAskedConnectWithoutAvatarEntities) {
|
||||
if (_isConnected) {
|
||||
// Already connected so don't ask. (Permission removed from user while in the domain.)
|
||||
setCanConnectWithoutAvatarEntities(true);
|
||||
} else {
|
||||
// Ask whether to connect to the domain.
|
||||
emit confirmConnectWithoutAvatarEntities();
|
||||
}
|
||||
}
|
||||
return _canConnectWithoutAvatarEntities;
|
||||
}
|
||||
|
||||
void DomainHandler::connectedToServerless(std::map<QString, QString> namedPaths) {
|
||||
_namedPaths = namedPaths;
|
||||
setIsConnected(true);
|
||||
|
|
|
@ -98,6 +98,7 @@ public:
|
|||
Node::LocalID getLocalID() const { return _localID; }
|
||||
void setLocalID(Node::LocalID localID) { _localID = localID; }
|
||||
|
||||
QString getScheme() const { return _domainURL.scheme(); }
|
||||
QString getHostname() const { return _domainURL.host(); }
|
||||
|
||||
QUrl getErrorDomainURL(){ return _errorDomainURL; }
|
||||
|
@ -133,6 +134,9 @@ public:
|
|||
bool isConnected() const { return _isConnected; }
|
||||
void setIsConnected(bool isConnected);
|
||||
|
||||
void setCanConnectWithoutAvatarEntities(bool canConnect);
|
||||
bool canConnectWithoutAvatarEntities();
|
||||
|
||||
bool isServerless() const { return _domainURL.scheme() != URL_SCHEME_HIFI; }
|
||||
bool getInterstitialModeEnabled() const;
|
||||
void setInterstitialModeEnabled(bool enableInterstitialMode);
|
||||
|
@ -252,6 +256,7 @@ signals:
|
|||
void completedSocketDiscovery();
|
||||
|
||||
void resetting();
|
||||
void confirmConnectWithoutAvatarEntities();
|
||||
void connectedToDomain(QUrl domainURL);
|
||||
void disconnectedFromDomain();
|
||||
|
||||
|
@ -287,6 +292,8 @@ private:
|
|||
HifiSockAddr _iceServerSockAddr;
|
||||
NetworkPeer _icePeer;
|
||||
bool _isConnected { false };
|
||||
bool _haveAskedConnectWithoutAvatarEntities { false };
|
||||
bool _canConnectWithoutAvatarEntities { false };
|
||||
bool _isInErrorState { false };
|
||||
QJsonObject _settingsObject;
|
||||
QString _pendingPath;
|
||||
|
|
|
@ -94,6 +94,12 @@ NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort)
|
|||
// send a ping punch immediately
|
||||
connect(&_domainHandler, &DomainHandler::icePeerSocketsReceived, this, &NodeList::pingPunchForDomainServer);
|
||||
|
||||
// FIXME: Can remove this temporary work-around in version 2021.2.0. (New protocol version implies a domain server upgrade.)
|
||||
// Adjust our canRezAvatarEntities permissions on older domains that do not have this setting.
|
||||
// DomainServerList and DomainSettings packets can come in either order so need to adjust with both occurrences.
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
connect(&_domainHandler, &DomainHandler::settingsReceived, this, &NodeList::adjustCanRezAvatarEntitiesPerSettings);
|
||||
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
|
||||
// assume that we may need to send a new DS check in anytime a new keypair is generated
|
||||
|
@ -726,6 +732,11 @@ void NodeList::processDomainServerList(QSharedPointer<ReceivedMessage> message)
|
|||
// pull the permissions/right/privileges for this node out of the stream
|
||||
NodePermissions newPermissions;
|
||||
packetStream >> newPermissions;
|
||||
// FIXME: Can remove this temporary work-around in version 2021.2.0. (New protocol version implies a domain server upgrade.)
|
||||
// Adjust our canRezAvatarEntities permissions on older domains that do not have this setting.
|
||||
// DomainServerList and DomainSettings packets can come in either order so need to adjust with both occurrences.
|
||||
bool adjustedPermissions = adjustCanRezAvatarEntitiesPermissions(_domainHandler.getSettingsObject(), newPermissions, false);
|
||||
|
||||
// Is packet authentication enabled?
|
||||
bool isAuthenticated;
|
||||
packetStream >> isAuthenticated;
|
||||
|
@ -781,7 +792,7 @@ void NodeList::processDomainServerList(QSharedPointer<ReceivedMessage> message)
|
|||
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::ReceiveDSList);
|
||||
|
||||
if (_domainHandler.isConnected() && _domainHandler.getUUID() != domainUUID) {
|
||||
// Recieved packet from different domain.
|
||||
// Received packet from different domain.
|
||||
qWarning() << "IGNORING DomainList packet from" << domainUUID << "while connected to"
|
||||
<< _domainHandler.getUUID() << ": sent " << pingLagTime << " msec ago.";
|
||||
qWarning(networking) << "DomainList request lag (interface->ds): " << domainServerRequestLag << "msec";
|
||||
|
@ -809,6 +820,23 @@ void NodeList::processDomainServerList(QSharedPointer<ReceivedMessage> message)
|
|||
setSessionLocalID(newLocalID);
|
||||
setSessionUUID(newUUID);
|
||||
|
||||
// FIXME: Remove this call to requestDomainSettings() and reinstate the one in DomainHandler::setIsConnected(), in version
|
||||
// 2021.2.0. (New protocol version implies a domain server upgrade.)
|
||||
if (!_domainHandler.isConnected()
|
||||
&& _domainHandler.getScheme() == URL_SCHEME_HIFI && !_domainHandler.getHostname().isEmpty()) {
|
||||
// We're about to connect but we need the domain settings (in particular, the node permissions) in order to adjust the
|
||||
// canRezAvatarEntities permission above before using the permissions in determining whether or not to connect without
|
||||
// avatar entities rezzing below.
|
||||
_domainHandler.requestDomainSettings();
|
||||
}
|
||||
|
||||
// Don't continue login to the domain if have avatar entities and don't have permissions to rez them, unless user has OKed
|
||||
// continuing login.
|
||||
if (!newPermissions.can(NodePermissions::Permission::canRezAvatarEntities)
|
||||
&& (!adjustedPermissions || !_domainHandler.canConnectWithoutAvatarEntities())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if this was the first domain-server list from this domain, we've now connected
|
||||
if (!_domainHandler.isConnected()) {
|
||||
_domainHandler.setLocalID(domainLocalID);
|
||||
|
@ -1368,3 +1396,35 @@ void NodeList::setRequestsDomainListData(bool isRequesting) {
|
|||
void NodeList::startThread() {
|
||||
moveToNewNamedThread(this, "NodeList Thread", QThread::TimeCriticalPriority);
|
||||
}
|
||||
|
||||
|
||||
// FIXME: Can remove this work-around in version 2021.2.0. (New protocol version implies a domain server upgrade.)
|
||||
bool NodeList::adjustCanRezAvatarEntitiesPermissions(const QJsonObject& domainSettingsObject,
|
||||
NodePermissions& permissions, bool notify) {
|
||||
|
||||
if (domainSettingsObject.isEmpty()) {
|
||||
// Don't have enough information to adjust yet.
|
||||
return false; // Failed to adjust.
|
||||
}
|
||||
|
||||
const double CANREZAVATARENTITIES_INTRODUCED_VERSION = 2.5;
|
||||
auto version = domainSettingsObject.value("version");
|
||||
if (version.isUndefined() || version.isDouble() && version.toDouble() < CANREZAVATARENTITIES_INTRODUCED_VERSION) {
|
||||
// On domains without the canRezAvatarEntities permission available, set it to the same as canConnectToDomain.
|
||||
if (permissions.can(NodePermissions::Permission::canConnectToDomain)) {
|
||||
if (!permissions.can(NodePermissions::Permission::canRezAvatarEntities)) {
|
||||
permissions.set(NodePermissions::Permission::canRezAvatarEntities);
|
||||
if (notify) {
|
||||
emit canRezAvatarEntitiesChanged(permissions.can(NodePermissions::Permission::canRezAvatarEntities));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true; // Successfully adjusted.
|
||||
}
|
||||
|
||||
// FIXME: Can remove this work-around in version 2021.2.0. (New protocol version implies a domain server upgrade.)
|
||||
void NodeList::adjustCanRezAvatarEntitiesPerSettings(const QJsonObject& domainSettingsObject) {
|
||||
adjustCanRezAvatarEntitiesPermissions(domainSettingsObject, _permissions, true);
|
||||
}
|
||||
|
|
|
@ -123,6 +123,11 @@ public slots:
|
|||
|
||||
void processUsernameFromIDReply(QSharedPointer<ReceivedMessage> message);
|
||||
|
||||
// FIXME: Can remove these work-arounds in version 2021.2.0. (New protocol version implies a domain server upgrade.)
|
||||
bool adjustCanRezAvatarEntitiesPermissions(const QJsonObject& domainSettingsObject, NodePermissions& permissions,
|
||||
bool notify);
|
||||
void adjustCanRezAvatarEntitiesPerSettings(const QJsonObject& domainSettingsObject);
|
||||
|
||||
#if (PR_BUILD || DEV_BUILD)
|
||||
void toggleSendNewerDSConnectVersion(bool shouldSendNewerVersion) { _shouldSendNewerVersion = shouldSendNewerVersion; }
|
||||
#endif
|
||||
|
|
|
@ -68,7 +68,7 @@ NodePermissions::NodePermissions(QMap<QString, QVariant> perms) {
|
|||
permissions |= perms["id_can_kick"].toBool() ? Permission::canKick : Permission::none;
|
||||
permissions |= perms["id_can_replace_content"].toBool() ? Permission::canReplaceDomainContent : Permission::none;
|
||||
permissions |= perms["id_can_get_and_set_private_user_data"].toBool() ? Permission::canGetAndSetPrivateUserData : Permission::none;
|
||||
permissions |= perms["id_can_rez_attachments"].toBool() ? Permission::canRezAvatarEntities : Permission::none;
|
||||
permissions |= perms["id_can_rez_avatar_entities"].toBool() ? Permission::canRezAvatarEntities : Permission::none;
|
||||
}
|
||||
|
||||
QVariant NodePermissions::toVariant(QHash<QUuid, GroupRank> groupRanks) {
|
||||
|
@ -173,6 +173,9 @@ QDebug operator<<(QDebug debug, const NodePermissions& perms) {
|
|||
if (perms.can(NodePermissions::Permission::canGetAndSetPrivateUserData)) {
|
||||
debug << " get-and-set-private-user-data";
|
||||
}
|
||||
if (perms.can(NodePermissions::Permission::canRezAvatarEntities)) {
|
||||
debug << " rez-avatar-entities";
|
||||
}
|
||||
debug.nospace() << "]";
|
||||
return debug.nospace();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue