Move all the access list checks into a single function

This adds nicer methods to the Character object for checking someone
against the various player/character access lists.
This commit is contained in:
Jean-Baptiste Emmanuel Zorg 2025-03-29 17:42:56 +01:00
parent 1a185e0318
commit 347644356d
10 changed files with 124 additions and 36 deletions
BondageClub

View file

@ -732,7 +732,7 @@ function FriendListLoadFriendList(data) {
} else if (Player.SubmissivesList.has(memberNumber)) { } else if (Player.SubmissivesList.has(memberNumber)) {
Type = "Submissive"; Type = "Submissive";
} }
const canDelete = Type === "Friend" && Player.FriendList.includes(memberNumber) || Type === "Submissive" && Player.SubmissivesList.has(memberNumber); const canDelete = Type === "Friend" && Player.HasOnFriendlist(memberNumber) || Type === "Submissive" && Player.SubmissivesList.has(memberNumber);
friendRawData.push({ friendRawData.push({
memberName: memberName, memberName: memberName,
@ -946,7 +946,7 @@ function FriendListLoadFriendList(data) {
function FriendListDelete(MemberNumber) { function FriendListDelete(MemberNumber) {
if (FriendListConfirmDelete.includes(MemberNumber)) { if (FriendListConfirmDelete.includes(MemberNumber)) {
FriendListConfirmDelete.splice(FriendListConfirmDelete.indexOf(MemberNumber), 1); FriendListConfirmDelete.splice(FriendListConfirmDelete.indexOf(MemberNumber), 1);
if (Player.FriendList.includes(MemberNumber)) { if (Player.HasOnFriendlist(MemberNumber)) {
Player.FriendList.splice(Player.FriendList.indexOf(MemberNumber), 1); Player.FriendList.splice(Player.FriendList.indexOf(MemberNumber), 1);
} }
Player.SubmissivesList.delete(MemberNumber); Player.SubmissivesList.delete(MemberNumber);

View file

@ -362,42 +362,42 @@ function ChatRoomIsViewActive(viewName)
* Checks if the player can add the current character to her whitelist. * Checks if the player can add the current character to her whitelist.
* @returns {boolean} - TRUE if the current character is not in the player's whitelist nor blacklist. * @returns {boolean} - TRUE if the current character is not in the player's whitelist nor blacklist.
*/ */
function ChatRoomCanAddWhiteList() { return ((CurrentCharacter != null) && (CurrentCharacter.MemberNumber != null) && (Player.WhiteList.indexOf(CurrentCharacter.MemberNumber) < 0) && (Player.BlackList.indexOf(CurrentCharacter.MemberNumber) < 0)); } function ChatRoomCanAddWhiteList() { return CurrentCharacter && !CurrentCharacter.IsWhitelisted() && !CurrentCharacter.IsBlacklisted(); }
/** /**
* Checks if the player can add the current character to her blacklist. * Checks if the player can add the current character to her blacklist.
* @returns {boolean} - TRUE if the current character is not in the player's whitelist nor blacklist. * @returns {boolean} - TRUE if the current character is not in the player's whitelist nor blacklist.
*/ */
function ChatRoomCanAddBlackList() { return ((CurrentCharacter != null) && (CurrentCharacter.MemberNumber != null) && (Player.WhiteList.indexOf(CurrentCharacter.MemberNumber) < 0) && (Player.BlackList.indexOf(CurrentCharacter.MemberNumber) < 0)); } function ChatRoomCanAddBlackList() { return CurrentCharacter && !CurrentCharacter.IsWhitelisted() && !CurrentCharacter.IsBlacklisted(); }
/** /**
* Checks if the player can remove the current character from her whitelist. * Checks if the player can remove the current character from her whitelist.
* @returns {boolean} - TRUE if the current character is in the player's whitelist, but not her blacklist. * @returns {boolean} - TRUE if the current character is in the player's whitelist, but not her blacklist.
*/ */
function ChatRoomCanRemoveWhiteList() { return ((CurrentCharacter != null) && (CurrentCharacter.MemberNumber != null) && (Player.WhiteList.indexOf(CurrentCharacter.MemberNumber) >= 0)); } function ChatRoomCanRemoveWhiteList() { return CurrentCharacter && CurrentCharacter.IsWhitelisted(); }
/** /**
* Checks if the player can remove the current character from her blacklist. * Checks if the player can remove the current character from her blacklist.
* @returns {boolean} - TRUE if the current character is in the player's blacklist, but not her whitelist. * @returns {boolean} - TRUE if the current character is in the player's blacklist, but not her whitelist.
*/ */
function ChatRoomCanRemoveBlackList() { return ((CurrentCharacter != null) && (CurrentCharacter.MemberNumber != null) && (Player.BlackList.indexOf(CurrentCharacter.MemberNumber) >= 0)); } function ChatRoomCanRemoveBlackList() { return CurrentCharacter && CurrentCharacter.IsBlacklisted(); }
/** /**
* Checks if the player can add the current character to her friendlist * Checks if the player can add the current character to her friendlist
* @returns {boolean} - TRUE if the current character is not in the player's friendlist yet. * @returns {boolean} - TRUE if the current character is not in the player's friendlist yet.
*/ */
function ChatRoomCanAddFriend() { return ((CurrentCharacter != null) && (CurrentCharacter.MemberNumber != null) && (Player.FriendList.indexOf(CurrentCharacter.MemberNumber) < 0)); } function ChatRoomCanAddFriend() { return CurrentCharacter && !CurrentCharacter.IsFriend(); }
/** /**
* Checks if the player can remove the current character from her friendlist. * Checks if the player can remove the current character from her friendlist.
* @returns {boolean} - TRUE if the current character is in the player's friendlist. * @returns {boolean} - TRUE if the current character is in the player's friendlist.
*/ */
function ChatRoomCanRemoveFriend() { return ((CurrentCharacter != null) && (CurrentCharacter.MemberNumber != null) && (Player.FriendList.indexOf(CurrentCharacter.MemberNumber) >= 0)); } function ChatRoomCanRemoveFriend() { return CurrentCharacter && CurrentCharacter.IsFriend(); }
/** /**
* Checks if the player can add the current character to her ghostlist * Checks if the player can add the current character to her ghostlist
* @returns {boolean} - TRUE if the current character is not in the player's ghostlist yet. * @returns {boolean} - TRUE if the current character is not in the player's ghostlist yet.
*/ */
function ChatRoomCanAddGhost() { return ((CurrentCharacter != null) && (CurrentCharacter.MemberNumber != null) && (Player.GhostList.indexOf(CurrentCharacter.MemberNumber) < 0)); } function ChatRoomCanAddGhost() { return CurrentCharacter && !CurrentCharacter?.IsGhosted(); }
/** /**
* Checks if the player can remove the current character from her ghostlist. * Checks if the player can remove the current character from her ghostlist.
* @returns {boolean} - TRUE if the current character is in the player's ghostlist. * @returns {boolean} - TRUE if the current character is in the player's ghostlist.
*/ */
function ChatRoomCanRemoveGhost() { return ((CurrentCharacter != null) && (CurrentCharacter.MemberNumber != null) && (Player.GhostList.indexOf(CurrentCharacter.MemberNumber) >= 0)); } function ChatRoomCanRemoveGhost() { return CurrentCharacter && CurrentCharacter.IsGhosted(); }
/** /**
* Checks if the player can change the current character's clothes * Checks if the player can change the current character's clothes
* @returns {boolean} - TRUE if the player can change the character's clothes and is allowed to. * @returns {boolean} - TRUE if the player can change the character's clothes and is allowed to.
@ -1493,9 +1493,9 @@ function DrawStatus(C, X, Y, Zoom) {
*/ */
function ChatRoomDrawCharacterStatusIcons(C, CharX, CharY, Zoom) function ChatRoomDrawCharacterStatusIcons(C, CharX, CharY, Zoom)
{ {
if (Player.WhiteList.includes(C.MemberNumber)) { if (C.IsWhitelisted()) {
DrawImageResize("Icons/Small/WhiteList.png", CharX + 70 * Zoom, CharY, 40 * Zoom, 40 * Zoom); DrawImageResize("Icons/Small/WhiteList.png", CharX + 70 * Zoom, CharY, 40 * Zoom, 40 * Zoom);
} else if (Player.BlackList.includes(C.MemberNumber)) { } else if (C.IsBlacklisted()) {
DrawImageResize("Icons/Small/BlackList.png", CharX + 70 * Zoom, CharY, 40 * Zoom, 40 * Zoom); DrawImageResize("Icons/Small/BlackList.png", CharX + 70 * Zoom, CharY, 40 * Zoom, 40 * Zoom);
} }
// Unobtrusive but prominent warnings to alert user they are in focus mode -- drawn on player and all focused (visible) characters // Unobtrusive but prominent warnings to alert user they are in focus mode -- drawn on player and all focused (visible) characters
@ -1504,9 +1504,9 @@ function ChatRoomDrawCharacterStatusIcons(C, CharX, CharY, Zoom)
DrawImageResize("Icons/Small/FocusEnabledWarning.png", CharX + 30 * Zoom, CharY, 40 * Zoom, 40 * Zoom); DrawImageResize("Icons/Small/FocusEnabledWarning.png", CharX + 30 * Zoom, CharY, 40 * Zoom, 40 * Zoom);
DrawImageResize("Icons/Small/FocusEnabledWarning.png", CharX + 30 * Zoom, CharY + 950 * Zoom, 40 * Zoom, 40 * Zoom); DrawImageResize("Icons/Small/FocusEnabledWarning.png", CharX + 30 * Zoom, CharY + 950 * Zoom, 40 * Zoom, 40 * Zoom);
} }
if (Player.GhostList.includes(C.MemberNumber)) { if (C.IsGhosted()) {
DrawImageResize("Icons/Small/GhostList.png", CharX + 110 * Zoom, CharY, 40 * Zoom, 40 * Zoom); DrawImageResize("Icons/Small/GhostList.png", CharX + 110 * Zoom, CharY, 40 * Zoom, 40 * Zoom);
} else if (Player.FriendList.includes(C.MemberNumber)) { } else if (C.IsFriend()) {
DrawImageResize("Icons/Small/FriendList.png", CharX + 110 * Zoom, CharY, 40 * Zoom, 40 * Zoom); DrawImageResize("Icons/Small/FriendList.png", CharX + 110 * Zoom, CharY, 40 * Zoom, 40 * Zoom);
} }
if (C.IsBirthday()) if (C.IsBirthday())
@ -3483,7 +3483,7 @@ var ChatRoomMessageHandlers = [
if (data.Type === "Action" && data.Content === "ServerUpdateRoom") if (data.Type === "Action" && data.Content === "ServerUpdateRoom")
return false; return false;
if (Player.GhostList.indexOf(data.Sender) >= 0) if (Player.HasOnGhostlist(data.Sender))
return true; return true;
} }
}, },
@ -6124,7 +6124,7 @@ function ChatRoomNotificationRaiseChatJoin(C) {
else if (!settings.Owner && !settings.Lovers && !settings.Friendlist && !settings.Subs) raise = true; else if (!settings.Owner && !settings.Lovers && !settings.Friendlist && !settings.Subs) raise = true;
else if (settings.Owner && Player.IsOwnedByMemberNumber(C.MemberNumber)) raise = true; else if (settings.Owner && Player.IsOwnedByMemberNumber(C.MemberNumber)) raise = true;
else if (settings.Lovers && C.IsLoverOfPlayer()) raise = true; else if (settings.Lovers && C.IsLoverOfPlayer()) raise = true;
else if (settings.Friendlist && Player.FriendList.includes(C.MemberNumber)) raise = true; else if (settings.Friendlist && C.IsFriend()) raise = true;
else if (settings.Subs && C.IsOwnedByPlayer()) raise = true; else if (settings.Subs && C.IsOwnedByPlayer()) raise = true;
} }
return raise; return raise;
@ -6157,7 +6157,7 @@ function ChatRoomCheckForLastChatRoomUpdates() {
// Check whether the chatroom contains at least one "safe" character (a friend, owner, or non-blacklisted player) // Check whether the chatroom contains at least one "safe" character (a friend, owner, or non-blacklisted player)
const ContainsSafeCharacters = ChatRoomCharacter.length === 1 || ChatRoomCharacter.some((Char) => { const ContainsSafeCharacters = ChatRoomCharacter.length === 1 || ChatRoomCharacter.some((Char) => {
return !Char.IsPlayer() && ( return !Char.IsPlayer() && (
Player.FriendList.includes(Char.MemberNumber) || Char.IsFriend() ||
Player.IsOwnedByMemberNumber(Char.MemberNumber) || Player.IsOwnedByMemberNumber(Char.MemberNumber) ||
!Blacklist.includes(Char.MemberNumber) !Blacklist.includes(Char.MemberNumber)
); );

View file

@ -1132,7 +1132,7 @@ function ChatSearchGetFilterReasons(Room) {
Reasons.push("TempHidden"); Reasons.push("TempHidden");
// is creator on ghostlist? // is creator on ghostlist?
if (Player.GhostList.indexOf(Room.CreatorMemberNumber) != -1) if (Player.HasOnGhostlist(Room.CreatorMemberNumber))
Reasons.push("GhostList"); Reasons.push("GhostList");
return Reasons; return Reasons;

View file

@ -1595,7 +1595,7 @@ function PandoraPenitentiaryDoActivity(Activity) {
function PandoraPenitentiaryHiddenMessage(SenderCharacter, Interaction) { function PandoraPenitentiaryHiddenMessage(SenderCharacter, Interaction) {
// Make sure we can process the Pandora packet // Make sure we can process the Pandora packet
if (!Interaction.startsWith("Pandora") || (Interaction.indexOf("|") <= 0) || !PandoraPenitentiaryIsInmate(Player) || !PandoraPenitentiaryIsGuard(SenderCharacter) || Player.BlackList.includes(SenderCharacter.MemberNumber)) return; if (!Interaction.startsWith("Pandora") || (Interaction.indexOf("|") <= 0) || !PandoraPenitentiaryIsInmate(Player) || !PandoraPenitentiaryIsGuard(SenderCharacter) || SenderCharacter.IsBlacklisted()) return;
// Make sure we target the player (ALL targets everyone) // Make sure we target the player (ALL targets everyone)
let Target = Interaction.split("|")[1]; let Target = Interaction.split("|")[1];

View file

@ -726,6 +726,30 @@ function CharacterCreate(CharacterAssetFamily, Type, CharacterID) {
hooks.forEach((hook) => hook()); // If there's a hook, call it hooks.forEach((hook) => hook()); // If there's a hook, call it
} }
}, },
HasOnGhostlist: function(target) {
return CharacterIsOnList(this, target, "ghost");
},
HasOnBlacklist: function(target) {
return CharacterIsOnList(this, target, "black");
},
HasOnWhitelist: function(target) {
return CharacterIsOnList(this, target, "white");
},
HasOnFriendlist: function(target) {
return CharacterIsOnList(this, target, "friend");
},
IsGhosted: function() {
return Player.HasOnGhostlist(this);
},
IsBlacklisted: function() {
return Player.HasOnBlacklist(this);
},
IsWhitelisted: function() {
return Player.HasOnWhitelist(this);
},
IsFriend: function() {
return Player.HasOnFriendlist(this);
}
}; };
// Add the character to the cache // Add the character to the cache
@ -1411,8 +1435,7 @@ function CharacterRefresh(C, Push = true, RefreshDialog = true) {
|| C.IsPlayer() || C.IsPlayer()
|| !(Player.OnlineSettings && Player.OnlineSettings.DisableAnimations) || !(Player.OnlineSettings && Player.OnlineSettings.DisableAnimations)
) && ( ) && (
!Player.GhostList !C.IsGhosted()
|| Player.GhostList.indexOf(C.MemberNumber) == -1
); );
C.HasScriptedAssets = !!C.Appearance.find(CA => CA.Asset.DynamicScriptDraw); C.HasScriptedAssets = !!C.Appearance.find(CA => CA.Asset.DynamicScriptDraw);
@ -2416,3 +2439,23 @@ function CharacterSetActivePose(C, poseName, forceChange=false) {
function CharacterCanChangeToPose(C, poseName) { function CharacterCanChangeToPose(C, poseName) {
return PoseCanChangeUnaided(C, poseName); return PoseCanChangeUnaided(C, poseName);
} }
/**
* Check a character against another one's access lists
* @param {Character} listOwner - The character to check against
* @param {Character | number} listTarget - The character or member number to check for
* @param {"black" | "white" | "ghost" | "friend"} list
*/
function CharacterIsOnList(listOwner, listTarget, list) {
const num = typeof listTarget === "number" ? listTarget : listTarget.MemberNumber;
switch (list) {
case "black":
return listOwner.BlackList.includes(num);
case "white":
return listOwner.WhiteList.includes(num);
case "ghost":
return listOwner.IsPlayer() && listOwner.GhostList.includes(num);
case "friend":
return listOwner.IsPlayer() && listOwner.FriendList.includes(num);
}
}

View file

@ -101,7 +101,7 @@ function CommonDrawAppearanceBuild(C, {
// Before drawing hook, receives all processed data. Any of them can be overriden if returned inside an object. // Before drawing hook, receives all processed data. Any of them can be overriden if returned inside an object.
// CAREFUL! The dynamic function should not contain heavy computations, and should not have any side effects. // CAREFUL! The dynamic function should not contain heavy computations, and should not have any side effects.
// Watch out for object references. // Watch out for object references.
if (asset.DynamicBeforeDraw && (!Player.GhostList || Player.GhostList.indexOf(C.MemberNumber) == -1)) { if (asset.DynamicBeforeDraw && !C.IsGhosted()) {
/** @type {DynamicDrawingData} */ /** @type {DynamicDrawingData} */
const DrawingData = { const DrawingData = {
C, X, Y, CA: item, GroupName: groupName, Color: layerColor, Opacity: opacity, Property: item.Property, A: asset, G: parentAssetName, AG: group, L: layerSegment, Pose: pose, LayerType: layerType, BlinkExpression: blinkExpressionSegment, C, X, Y, CA: item, GroupName: groupName, Color: layerColor, Opacity: opacity, Property: item.Property, A: asset, G: parentAssetName, AG: group, L: layerSegment, Pose: pose, LayerType: layerType, BlinkExpression: blinkExpressionSegment,
@ -257,7 +257,7 @@ function CommonDrawAppearanceBuild(C, {
// After drawing hook, receives all processed data. // After drawing hook, receives all processed data.
// CAREFUL! The dynamic function should not contain heavy computations, and should not have any side effects. // CAREFUL! The dynamic function should not contain heavy computations, and should not have any side effects.
// Watch out for object references. // Watch out for object references.
if (asset.DynamicAfterDraw && (!Player.GhostList || Player.GhostList.indexOf(C.MemberNumber) == -1)) { if (asset.DynamicAfterDraw && !C.IsGhosted()) {
/** @type {DynamicDrawingData} */ /** @type {DynamicDrawingData} */
const DrawingData = { const DrawingData = {
C, X, Y, CA: item, GroupName: groupName, Property: item.Property, Color: layerColor, Opacity: opacity, A: asset, G: parentAssetName, AG: group, L: layerSegment, Pose: pose, LayerType: layerType, BlinkExpression: blinkExpressionSegment, drawCanvas, drawCanvasBlink, AlphaMasks: masks, C, X, Y, CA: item, GroupName: groupName, Property: item.Property, Color: layerColor, Opacity: opacity, A: asset, G: parentAssetName, AG: group, L: layerSegment, Pose: pose, LayerType: layerType, BlinkExpression: blinkExpressionSegment, drawCanvas, drawCanvasBlink, AlphaMasks: masks,

View file

@ -1695,7 +1695,7 @@ function InventoryIsPermissionLimited(C, AssetName, AssetGroup, AssetType) {
function InventoryCheckLimitedPermission(C, Item, ItemType) { function InventoryCheckLimitedPermission(C, Item, ItemType) {
if (!InventoryIsPermissionLimited(C, Item.Asset.DynamicName(Player), Item.Asset.Group.Name, ItemType)) return true; if (!InventoryIsPermissionLimited(C, Item.Asset.DynamicName(Player), Item.Asset.Group.Name, ItemType)) return true;
if ((C.IsPlayer()) || C.IsLoverOfPlayer() || C.IsOwnedByPlayer()) return true; if ((C.IsPlayer()) || C.IsLoverOfPlayer() || C.IsOwnedByPlayer()) return true;
if ((C.ItemPermission < 3) && !(C.WhiteList.indexOf(Player.MemberNumber) < 0)) return true; if ((C.ItemPermission < 3) && C.HasOnWhitelist(Player)) return true;
return false; return false;
} }

View file

@ -1029,18 +1029,16 @@ function ServerChatRoomGetAllowItem(Source, Target) {
if ((Target.ItemPermission <= 0) || (Source.MemberNumber == Target.MemberNumber) || Target.IsOwnedByCharacter(Source)) return true; if ((Target.ItemPermission <= 0) || (Source.MemberNumber == Target.MemberNumber) || Target.IsOwnedByCharacter(Source)) return true;
// At one, we allow if the source isn't on the blacklist // At one, we allow if the source isn't on the blacklist
if ((Target.ItemPermission == 1) && (Target.BlackList.indexOf(Source.MemberNumber) < 0)) return true; if ((Target.ItemPermission == 1) && !Target.HasOnBlacklist(Source)) return true;
var LoversNumbers = CharacterGetLoversNumbers(Target, true);
// At two, we allow if the source is Dominant compared to the Target (25 points allowed) or on whitelist or a lover // At two, we allow if the source is Dominant compared to the Target (25 points allowed) or on whitelist or a lover
if ((Target.ItemPermission == 2) && (Target.BlackList.indexOf(Source.MemberNumber) < 0) && ((ReputationCharacterGet(Source, "Dominant") + 25 >= ReputationCharacterGet(Target, "Dominant")) || (Target.WhiteList.indexOf(Source.MemberNumber) >= 0) || (LoversNumbers.indexOf(Source.MemberNumber) >= 0))) return true; if ((Target.ItemPermission == 2) && (!Target.HasOnBlacklist(Source) && ((ReputationCharacterGet(Source, "Dominant") + 25 >= ReputationCharacterGet(Target, "Dominant")) || Target.HasOnWhitelist(Source) || Source.IsLoverOfCharacter(Target)))) return true;
// At three, we allow if the source is on the whitelist of the Target or a lover // At three, we allow if the source is on the whitelist of the Target or a lover
if ((Target.ItemPermission == 3) && ((Target.WhiteList.indexOf(Source.MemberNumber) >= 0) || (LoversNumbers.indexOf(Source.MemberNumber) >= 0))) return true; if ((Target.ItemPermission == 3) && (Target.HasOnWhitelist(Source) || Source.IsLoverOfCharacter(Target))) return true;
// At four, we allow if the source is a lover // At four, we allow if the source is a lover
if ((Target.ItemPermission == 4) && (LoversNumbers.indexOf(Source.MemberNumber) >= 0)) return true; if ((Target.ItemPermission == 4) && (Source.IsLoverOfCharacter(Target))) return true;
// No valid combo, we don't allow the item // No valid combo, we don't allow the item
return false; return false;

View file

@ -1696,7 +1696,6 @@ interface Character {
LimitedItems?: never; LimitedItems?: never;
/** A record with all asset- and type-specific permission settings */ /** A record with all asset- and type-specific permission settings */
PermissionItems: Partial<Record<`${AssetGroupName}/${string}`, ItemPermissions>>; PermissionItems: Partial<Record<`${AssetGroupName}/${string}`, ItemPermissions>>;
WhiteList: number[];
HeightModifier: number; HeightModifier: number;
MemberNumber?: number; MemberNumber?: number;
ItemPermission: 0 | 1 | 2 | 3 | 4 | 5; ItemPermission: 0 | 1 | 2 | 3 | 4 | 5;
@ -1819,6 +1818,50 @@ interface Character {
HasVagina: () => boolean; HasVagina: () => boolean;
IsFlatChested: () => boolean; IsFlatChested: () => boolean;
WearingCollar: () => boolean; WearingCollar: () => boolean;
/**
* Check if the player is ghosting the given target character (or member number)
*/
HasOnGhostlist: (this: PlayerCharacter, target?: Character | number) => boolean;
/**
* Check if the player is blacklisting the given target character (or member number)
*/
HasOnBlacklist: (target?: Character | number) => boolean;
/**
* Check if the player is whitelisting the given target character (or member number)
*/
HasOnWhitelist: (target?: Character | number) => boolean;
/**
* Check if the player is friend with the given target character (or member number)
*/
HasOnFriendlist: (this: PlayerCharacter, target?: Character | number) => boolean;
/**
* Check if this character is ghosted by the player
*/
IsGhosted: () => boolean;
/**
* Check if this character is blacklisted by the player
*/
IsBlacklisted: () => boolean;
/**
* Check if this character is whitelisted by the player
*/
IsWhitelisted: () => boolean;
/**
* Check if this character is friended by the player
*/
IsFriend: () => boolean;
/**
* List of whitelisted member numbers for the character
*
* Do not manipulate directly. Use {@link ChatRoomListUpdate}
*/
WhiteList: number[];
/**
* List of blacklisted member numbers for the character
*
* Do not manipulate directly. Use {@link ChatRoomListUpdate}
*/
BlackList: number[];
// Properties created in other places // Properties created in other places
ArousalSettings: ArousalSettingsType; ArousalSettings: ArousalSettingsType;
@ -1831,7 +1874,6 @@ interface Character {
OnlineSharedSettings?: CharacterOnlineSharedSettings; // technically never as it is Online-only OnlineSharedSettings?: CharacterOnlineSharedSettings; // technically never as it is Online-only
Game?: CharacterGameParameters; // technically never as it is Online-only Game?: CharacterGameParameters; // technically never as it is Online-only
MapData?: ChatRoomMapData; MapData?: ChatRoomMapData;
BlackList: number[];
RunScripts?: boolean; RunScripts?: boolean;
HasScriptedAssets?: boolean; HasScriptedAssets?: boolean;
Cage?: boolean; Cage?: boolean;
@ -2046,7 +2088,12 @@ interface PlayerCharacter extends Character {
GraphicsSettings: GraphicsSettingsType; GraphicsSettings: GraphicsSettingsType;
NotificationSettings: NotificationSettingsType; NotificationSettings: NotificationSettingsType;
OnlineSharedSettings: CharacterOnlineSharedSettings; // technically never as it is Online-only OnlineSharedSettings: CharacterOnlineSharedSettings; // technically never as it is Online-only
GhostList?: number[]; /**
* List of ghosted member numbers for the player
*
* Do not manipulate directly. Use {@link ChatRoomListUpdate}
*/
GhostList: number[];
Wardrobe: ItemBundle[][]; Wardrobe: ItemBundle[][];
WardrobeCharacterNames: string[]; WardrobeCharacterNames: string[];
SavedExpressions?: ({ Group: ExpressionGroupName, CurrentExpression?: ExpressionName }[] | null)[]; SavedExpressions?: ({ Group: ExpressionGroupName, CurrentExpression?: ExpressionName }[] | null)[];
@ -4386,7 +4433,7 @@ interface PreferenceExtensionsSettingItem {
* Called when the extension screen is about to exit. * Called when the extension screen is about to exit.
* *
* Happens either through a click of the exit button, or the ESC key. * Happens either through a click of the exit button, or the ESC key.
* This will **not** be called if a disconnect happens, so clean up should be * This will **not** be called if a disconnect happens, so clean up should be
* done in {@link PreferenceExtensionsSettingItem.unload}. * done in {@link PreferenceExtensionsSettingItem.unload}.
* *
* @returns {boolean | void} If you have some validation that needs to happen * @returns {boolean | void} If you have some validation that needs to happen

View file

@ -50,7 +50,7 @@ function ValidationCreateDiffParams(C, sourceMemberNumber) {
// We can't know the details about other peoples' friendlist/whitelist, so assume an update is safe - their // We can't know the details about other peoples' friendlist/whitelist, so assume an update is safe - their
// validation will correct it if not. // validation will correct it if not.
const fromFriend = C.IsPlayer() ? C.FriendList.includes(sourceMemberNumber) : true; const fromFriend = C.IsPlayer() ? C.FriendList.includes(sourceMemberNumber) : true;
const fromWhitelist = C.IsPlayer() ? C.WhiteList.includes(sourceMemberNumber) : true; const fromWhitelist = C.IsPlayer() ? C.HasOnWhitelist(sourceMemberNumber) : true;
const permissions = /** @type {ScriptPermissionLevel[]} */([ const permissions = /** @type {ScriptPermissionLevel[]} */([
fromSelf && ScriptPermissionLevel.SELF, fromSelf && ScriptPermissionLevel.SELF,
@ -571,7 +571,7 @@ function ValidationIsItemBlockedOrLimited(C, sourceMemberNumber, groupName, asse
if (!InventoryIsPermissionLimited(C, assetName, groupName, type)) return false; if (!InventoryIsPermissionLimited(C, assetName, groupName, type)) return false;
if (C.IsLoverOfMemberNumber(sourceMemberNumber) || C.IsOwnedByMemberNumber(sourceMemberNumber)) return false; if (C.IsLoverOfMemberNumber(sourceMemberNumber) || C.IsOwnedByMemberNumber(sourceMemberNumber)) return false;
// The item is limited so if the source is on their whitelist, it's permitted // The item is limited so if the source is on their whitelist, it's permitted
if (C.WhiteList.includes(sourceMemberNumber)) return false; if (C.HasOnWhitelist(sourceMemberNumber)) return false;
// Otherwise, the item is limited, and the source doesn't have permission // Otherwise, the item is limited, and the source doesn't have permission
return true; return true;
} }