From f33b6bd96ee474a51123decb049d3199126b67b1 Mon Sep 17 00:00:00 2001
From: Bill <billsonnn@live.com>
Date: Sat, 8 May 2021 23:27:01 -0400
Subject: [PATCH 1/7] Update RoomPreviewer

---
 src/nitro/room/preview/RoomPreviewer.ts | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/nitro/room/preview/RoomPreviewer.ts b/src/nitro/room/preview/RoomPreviewer.ts
index 231c56ce..ffe1455a 100644
--- a/src/nitro/room/preview/RoomPreviewer.ts
+++ b/src/nitro/room/preview/RoomPreviewer.ts
@@ -850,4 +850,14 @@ export class RoomPreviewer
     {
         this._backgroundColor = color;
     }
+
+    public get width(): number
+    {
+        return this._currentPreviewCanvasWidth;
+    }
+
+    public get height(): number
+    {
+        return this._currentPreviewCanvasHeight;
+    }
 }

From c8089982c52a2577a16427d69f72b6ec2655162e Mon Sep 17 00:00:00 2001
From: Bill <billsonnn@live.com>
Date: Fri, 14 May 2021 14:45:45 -0400
Subject: [PATCH 2/7] Add NitroPoint

---
 src/room/utils/INitroPoint.ts | 3 +++
 src/room/utils/NitroPoint.ts  | 5 +++++
 src/room/utils/index.ts       | 2 ++
 3 files changed, 10 insertions(+)
 create mode 100644 src/room/utils/INitroPoint.ts
 create mode 100644 src/room/utils/NitroPoint.ts

diff --git a/src/room/utils/INitroPoint.ts b/src/room/utils/INitroPoint.ts
new file mode 100644
index 00000000..466f65a7
--- /dev/null
+++ b/src/room/utils/INitroPoint.ts
@@ -0,0 +1,3 @@
+import { IPoint } from 'pixi.js';
+
+export type INitroPoint = IPoint;
diff --git a/src/room/utils/NitroPoint.ts b/src/room/utils/NitroPoint.ts
new file mode 100644
index 00000000..67ff6136
--- /dev/null
+++ b/src/room/utils/NitroPoint.ts
@@ -0,0 +1,5 @@
+import { Point } from 'pixi.js';
+import { INitroPoint } from './INitroPoint';
+
+export class NitroPoint extends Point implements INitroPoint
+{}
diff --git a/src/room/utils/index.ts b/src/room/utils/index.ts
index 9f3fe904..6462d4d3 100644
--- a/src/room/utils/index.ts
+++ b/src/room/utils/index.ts
@@ -1,6 +1,8 @@
 export * from './ColorConverter';
+export * from './INitroPoint';
 export * from './IRoomGeometry';
 export * from './IVector3D';
+export * from './NitroPoint';
 export * from './NumberBank';
 export * from './PointMath';
 export * from './Rasterizer';

From eb1f0294417e82d24f0812c954f1a41a79e57ea7 Mon Sep 17 00:00:00 2001
From: Bill <billsonnn@live.com>
Date: Mon, 17 May 2021 12:48:29 -0400
Subject: [PATCH 3/7] Add pet breed catalog packets

---
 src/nitro/communication/NitroMessages.ts      | 38 ++++++-----
 .../messages/incoming/IncomingHeader.ts       |  1 +
 .../incoming/catalog/CatalogPetBreedsEvent.ts | 16 +++++
 .../messages/incoming/catalog/index.ts        |  1 +
 .../messages/outgoing/OutgoingHeader.ts       |  1 +
 .../CatalogRequestPetBreedsComposer.ts        | 21 ++++++
 .../messages/outgoing/catalog/index.ts        |  1 +
 .../parser/catalog/CatalogPetBreedsParser.ts  | 45 +++++++++++++
 .../messages/parser/catalog/index.ts          |  1 +
 .../catalog/utils/CatalogPetPaletteBreed.ts   | 67 +++++++++++++++++++
 .../messages/parser/catalog/utils/index.ts    |  1 +
 11 files changed, 176 insertions(+), 17 deletions(-)
 create mode 100644 src/nitro/communication/messages/incoming/catalog/CatalogPetBreedsEvent.ts
 create mode 100644 src/nitro/communication/messages/outgoing/catalog/CatalogRequestPetBreedsComposer.ts
 create mode 100644 src/nitro/communication/messages/parser/catalog/CatalogPetBreedsParser.ts
 create mode 100644 src/nitro/communication/messages/parser/catalog/utils/CatalogPetPaletteBreed.ts

diff --git a/src/nitro/communication/NitroMessages.ts b/src/nitro/communication/NitroMessages.ts
index 45c40f1b..3dae8db9 100644
--- a/src/nitro/communication/NitroMessages.ts
+++ b/src/nitro/communication/NitroMessages.ts
@@ -1,4 +1,5 @@
 import { IMessageConfiguration } from '../../core/communication/messages/IMessageConfiguration';
+import { CatalogPetBreedsEvent } from './messages';
 import { AvailabilityStatusMessageEvent } from './messages/incoming/availability/AvailabilityStatusMessageEvent';
 import { ChangeNameUpdateEvent } from './messages/incoming/avatar/ChangeNameUpdateEvent';
 import { CatalogClubEvent } from './messages/incoming/catalog/CatalogClubEvent';
@@ -17,6 +18,12 @@ import { CatalogRedeemVoucherOkEvent } from './messages/incoming/catalog/Catalog
 import { CatalogSearchEvent } from './messages/incoming/catalog/CatalogSearchEvent';
 import { CatalogSoldOutEvent } from './messages/incoming/catalog/CatalogSoldOutEvent';
 import { CatalogUpdatedEvent } from './messages/incoming/catalog/CatalogUpdatedEvent';
+import { MarketplaceAfterOrderStatusEvent } from './messages/incoming/catalog/marketplace/MarketplaceAfterOrderStatusEvent';
+import { MarketplaceCancelItemEvent } from './messages/incoming/catalog/marketplace/MarketplaceCancelItemEvent';
+import { MarketplaceOffersReceivedEvent } from './messages/incoming/catalog/marketplace/MarketplaceOffersReceivedEvent';
+import { MarketplaceOwnItemsEvent } from './messages/incoming/catalog/marketplace/MarketplaceOwnItemsEvent';
+import { MarketplaceConfigEvent } from './messages/incoming/catalog/MarketplaceConfigEvent';
+import { MarketplaceItemStatsEvent } from './messages/incoming/catalog/MarketplaceItemStatsEvent';
 import { ClientPingEvent } from './messages/incoming/client/ClientPingEvent';
 import { DesktopViewEvent } from './messages/incoming/desktop/DesktopViewEvent';
 import { AcceptFriendResultEvent } from './messages/incoming/friendlist/AcceptFriendResultEvent';
@@ -63,6 +70,8 @@ import { FurnitureListInvalidateEvent } from './messages/incoming/inventory/furn
 import { FurnitureListRemovedEvent } from './messages/incoming/inventory/furni/FurnitureListRemovedEvent';
 import { FurniturePostItPlacedEvent } from './messages/incoming/inventory/furni/FurniturePostItPlacedEvent';
 import { FurnitureGiftOpenedEvent } from './messages/incoming/inventory/furni/gifts/FurnitureGiftOpenedEvent';
+import { MarketplaceItemPostedEvent } from './messages/incoming/inventory/marketplace/MarketplaceItemPostedEvent';
+import { MarketplaceSellItemEvent } from './messages/incoming/inventory/marketplace/MarketplaceSellItemEvent';
 import { PetAddedToInventoryEvent } from './messages/incoming/inventory/pets/PetAddedToInventoryEvent';
 import { PetInventoryEvent } from './messages/incoming/inventory/pets/PetInventoryEvent';
 import { PetRemovedFromInventory } from './messages/incoming/inventory/pets/PetRemovedFromInventoryEvent';
@@ -203,10 +212,18 @@ import { CatalogPageComposer } from './messages/outgoing/catalog/CatalogPageComp
 import { CatalogPurchaseComposer } from './messages/outgoing/catalog/CatalogPurchaseComposer';
 import { CatalogPurchaseGiftComposer } from './messages/outgoing/catalog/CatalogPurchaseGiftComposer';
 import { CatalogRequestGiftConfigurationComposer } from './messages/outgoing/catalog/CatalogRequestGiftConfigurationComposer';
+import { CatalogRequestPetBreedsComposer } from './messages/outgoing/catalog/CatalogRequestPetBreedsComposer';
 import { CatalogRequestVipGiftsComposer } from './messages/outgoing/catalog/CatalogRequestVipGiftsComposer';
 import { CatalogRequestVipOffersComposer } from './messages/outgoing/catalog/CatalogRequestVipOffersComposer';
 import { CatalogSearchComposer } from './messages/outgoing/catalog/CatalogSearchComposer';
 import { CatalogSelectClubGiftComposer } from './messages/outgoing/catalog/CatalogSelectClubGiftComposer';
+import { MarketplaceBuyOfferComposer } from './messages/outgoing/catalog/marketplace/MarketplaceBuyOfferComposer';
+import { MarketplaceRedeemCreditsComposer } from './messages/outgoing/catalog/marketplace/MarketplaceRedeemCreditsComposer';
+import { MarketplaceRequesstItemStatsComposer } from './messages/outgoing/catalog/marketplace/MarketplaceRequesstItemStatsComposer';
+import { MarketplaceRequestComposer } from './messages/outgoing/catalog/marketplace/MarketplaceRequestComposer';
+import { MarketplaceRequestOffersComposer } from './messages/outgoing/catalog/marketplace/MarketplaceRequestOffersComposer';
+import { MarketplaceRequestOwnItemsComposer } from './messages/outgoing/catalog/marketplace/MarketplaceRequestOwnItemsComposer';
+import { MarketplaceTakeItemBackComposer } from './messages/outgoing/catalog/marketplace/MarketplaceTakeItemBackComposer';
 import { RedeemItemClothingComposer } from './messages/outgoing/catalog/RedeemItemClothingComposer';
 import { CatalogRedeemVoucherComposer } from './messages/outgoing/catalog/RedeemVoucherComposer';
 import { ClientPongComposer } from './messages/outgoing/client/ClientPongComposer';
@@ -251,6 +268,8 @@ import { SetActivatedBadgesComposer } from './messages/outgoing/inventory/badges
 import { GetBotInventoryComposer } from './messages/outgoing/inventory/bots/GetBotInventoryComposer';
 import { FurnitureList2Composer } from './messages/outgoing/inventory/furni/FurnitureList2Composer';
 import { FurnitureListComposer } from './messages/outgoing/inventory/furni/FurnitureListComposer';
+import { MarketplaceSellItemComposer } from './messages/outgoing/inventory/marketplace/MarketplaceSellItemComposer';
+import { RequestSellItemComposer } from './messages/outgoing/inventory/marketplace/RequestSellItemComposer';
 import { RequestPetsComposer } from './messages/outgoing/inventory/pets/RequestPetsComposer';
 import { TradingAcceptComposer } from './messages/outgoing/inventory/trading/TradingAcceptComposer';
 import { TradingCancelComposer } from './messages/outgoing/inventory/trading/TradingCancelComposer';
@@ -384,23 +403,6 @@ import { UserRespectComposer } from './messages/outgoing/user/UserRespectCompose
 import { UserWardrobePageComposer } from './messages/outgoing/user/wardrobe/UserWardrobePageComposer';
 import { UserWardrobeSaveComposer } from './messages/outgoing/user/wardrobe/UserWardrobeSaveComposer';
 import { MiniMailUnreadCountParser } from './messages/parser/friendlist/MiniMailUnreadCountParser';
-import { RequestSellItemComposer } from './messages/outgoing/inventory/marketplace/RequestSellItemComposer';
-import { MarketplaceSellItemEvent } from './messages/incoming/inventory/marketplace/MarketplaceSellItemEvent';
-import { MarketplaceConfigEvent } from './messages/incoming/catalog/MarketplaceConfigEvent';
-import { MarketplaceItemStatsEvent } from './messages/incoming/catalog/MarketplaceItemStatsEvent';
-import { MarketplaceSellItemComposer } from './messages/outgoing/inventory/marketplace/MarketplaceSellItemComposer';
-import { MarketplaceRequesstItemStatsComposer } from './messages/outgoing/catalog/marketplace/MarketplaceRequesstItemStatsComposer';
-import { MarketplaceRequestComposer } from './messages/outgoing/catalog/marketplace/MarketplaceRequestComposer';
-import { MarketplaceRequestOwnItemsComposer } from './messages/outgoing/catalog/marketplace/MarketplaceRequestOwnItemsComposer';
-import { MarketplaceOwnItemsEvent } from './messages/incoming/catalog/marketplace/MarketplaceOwnItemsEvent';
-import { MarketplaceTakeItemBackComposer } from './messages/outgoing/catalog/marketplace/MarketplaceTakeItemBackComposer';
-import { MarketplaceCancelItemEvent } from './messages/incoming/catalog/marketplace/MarketplaceCancelItemEvent';
-import { MarketplaceRedeemCreditsComposer } from './messages/outgoing/catalog/marketplace/MarketplaceRedeemCreditsComposer';
-import { MarketplaceItemPostedEvent } from './messages/incoming/inventory/marketplace/MarketplaceItemPostedEvent';
-import { MarketplaceRequestOffersComposer } from './messages/outgoing/catalog/marketplace/MarketplaceRequestOffersComposer';
-import { MarketplaceOffersReceivedEvent } from './messages/incoming/catalog/marketplace/MarketplaceOffersReceivedEvent';
-import { MarketplaceBuyOfferComposer } from './messages/outgoing/catalog/marketplace/MarketplaceBuyOfferComposer';
-import { MarketplaceAfterOrderStatusEvent } from './messages/incoming/catalog/marketplace/MarketplaceAfterOrderStatusEvent';
 
 export class NitroMessages implements IMessageConfiguration
 {
@@ -441,6 +443,7 @@ export class NitroMessages implements IMessageConfiguration
         this._events.set(IncomingHeader.GIFT_CONFIG, CatalogGiftConfigurationEvent);
         this._events.set(IncomingHeader.REDEEM_VOUCHER_ERROR, CatalogRedeemVoucherErrorEvent);
         this._events.set(IncomingHeader.REDEEM_VOUCHER_OK, CatalogRedeemVoucherOkEvent);
+        this._events.set(IncomingHeader.CATALOG_RECEIVE_PET_BREEDS, CatalogPetBreedsEvent);
 
         // CLIENT
         this._events.set(IncomingHeader.CLIENT_PING, ClientPingEvent);
@@ -737,6 +740,7 @@ export class NitroMessages implements IMessageConfiguration
         this._composers.set(OutgoingHeader.GROUP_MEMBERSHIPS, CatalogGroupsComposer);
         this._composers.set(OutgoingHeader.GIFT_CONFIG, CatalogRequestGiftConfigurationComposer);
         this._composers.set(OutgoingHeader.CATALOG_SELECT_VIP_GIFT, CatalogSelectClubGiftComposer);
+        this._composers.set(OutgoingHeader.CATALOG_REQUESET_PET_BREEDS, CatalogRequestPetBreedsComposer);
 
         // CLIENT
         this._composers.set(OutgoingHeader.CLIENT_PONG, ClientPongComposer);
diff --git a/src/nitro/communication/messages/incoming/IncomingHeader.ts b/src/nitro/communication/messages/incoming/IncomingHeader.ts
index 3fb4db9a..6cdecd59 100644
--- a/src/nitro/communication/messages/incoming/IncomingHeader.ts
+++ b/src/nitro/communication/messages/incoming/IncomingHeader.ts
@@ -245,4 +245,5 @@ export class IncomingHeader
     public static MARKETPLACE_ITEM_POSTED          = 1359;
     public static MARKETPLACE_ITEMS_SEARCHED       = 680;
     public static MARKETPLACE_AFTER_ORDER_STATUS   = 2032;
+    public static CATALOG_RECEIVE_PET_BREEDS       = 3331;
 }
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogPetBreedsEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogPetBreedsEvent.ts
new file mode 100644
index 00000000..140ee8ed
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogPetBreedsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogPetBreedsParser } from '../../parser';
+
+export class CatalogPetBreedsEvent extends MessageEvent implements IMessageEvent
+{
+    constructor(callBack: Function)
+    {
+        super(callBack, CatalogPetBreedsParser);
+    }
+
+    public getParser(): CatalogPetBreedsParser
+    {
+        return this.parser as CatalogPetBreedsParser;
+    }
+}
diff --git a/src/nitro/communication/messages/incoming/catalog/index.ts b/src/nitro/communication/messages/incoming/catalog/index.ts
index cdda3b40..4a4179e5 100644
--- a/src/nitro/communication/messages/incoming/catalog/index.ts
+++ b/src/nitro/communication/messages/incoming/catalog/index.ts
@@ -6,6 +6,7 @@ export * from './CatalogGroupsEvent';
 export * from './CatalogModeEvent';
 export * from './CatalogPageEvent';
 export * from './CatalogPagesEvent';
+export * from './CatalogPetBreedsEvent';
 export * from './CatalogPurchaseEvent';
 export * from './CatalogPurchaseFailedEvent';
 export * from './CatalogPurchaseUnavailableEvent';
diff --git a/src/nitro/communication/messages/outgoing/OutgoingHeader.ts b/src/nitro/communication/messages/outgoing/OutgoingHeader.ts
index 95b44b25..6edbd82d 100644
--- a/src/nitro/communication/messages/outgoing/OutgoingHeader.ts
+++ b/src/nitro/communication/messages/outgoing/OutgoingHeader.ts
@@ -230,4 +230,5 @@ export class OutgoingHeader
     public static MARKETPLACE_REDEEM_CREDITS     = 2650;
     public static MARKETPLACE_REQUEST_OFFERS     = 2407;
     public static MARKETPLACE_BUY_OFFER          = 1603;
+    public static CATALOG_REQUESET_PET_BREEDS    = 1756;
 }
diff --git a/src/nitro/communication/messages/outgoing/catalog/CatalogRequestPetBreedsComposer.ts b/src/nitro/communication/messages/outgoing/catalog/CatalogRequestPetBreedsComposer.ts
new file mode 100644
index 00000000..a8ea9a15
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/catalog/CatalogRequestPetBreedsComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class CatalogRequestPetBreedsComposer implements IMessageComposer<ConstructorParameters<typeof CatalogRequestPetBreedsComposer>>
+{
+    private _data: ConstructorParameters<typeof CatalogRequestPetBreedsComposer>;
+
+    constructor(name: string)
+    {
+        this._data = [ name ];
+    }
+
+    public getMessageArray()
+    {
+        return this._data;
+    }
+
+    public dispose(): void
+    {
+        return;
+    }
+}
diff --git a/src/nitro/communication/messages/outgoing/catalog/index.ts b/src/nitro/communication/messages/outgoing/catalog/index.ts
index bc93ae00..03f9b993 100644
--- a/src/nitro/communication/messages/outgoing/catalog/index.ts
+++ b/src/nitro/communication/messages/outgoing/catalog/index.ts
@@ -4,6 +4,7 @@ export * from './CatalogPageComposer';
 export * from './CatalogPurchaseComposer';
 export * from './CatalogPurchaseGiftComposer';
 export * from './CatalogRequestGiftConfigurationComposer';
+export * from './CatalogRequestPetBreedsComposer';
 export * from './CatalogRequestVipGiftsComposer';
 export * from './CatalogRequestVipOffersComposer';
 export * from './CatalogSearchComposer';
diff --git a/src/nitro/communication/messages/parser/catalog/CatalogPetBreedsParser.ts b/src/nitro/communication/messages/parser/catalog/CatalogPetBreedsParser.ts
new file mode 100644
index 00000000..44f27f2f
--- /dev/null
+++ b/src/nitro/communication/messages/parser/catalog/CatalogPetBreedsParser.ts
@@ -0,0 +1,45 @@
+import { IMessageDataWrapper } from '../../../../../core/communication/messages/IMessageDataWrapper';
+import { IMessageParser } from '../../../../../core/communication/messages/IMessageParser';
+import { CatalogPetPaletteBreed } from './utils';
+
+export class CatalogPetBreedsParser implements IMessageParser
+{
+    private _productCode: string;
+    private _palettes: CatalogPetPaletteBreed[];
+
+    public flush(): boolean
+    {
+        this._productCode   = '';
+        this._palettes      = [];
+
+        return true;
+    }
+
+    public parse(wrapper: IMessageDataWrapper): boolean
+    {
+        if(!wrapper) return false;
+
+        this._productCode = wrapper.readString();
+
+        let totalPalettes = wrapper.readInt();
+
+        while(totalPalettes > 0)
+        {
+            this._palettes.push(new CatalogPetPaletteBreed(wrapper));
+
+            totalPalettes--;
+        }
+
+        return true;
+    }
+
+    public get productCode(): string
+    {
+        return this._productCode;
+    }
+
+    public get palettes(): CatalogPetPaletteBreed[]
+    {
+        return this._palettes;
+    }
+}
diff --git a/src/nitro/communication/messages/parser/catalog/index.ts b/src/nitro/communication/messages/parser/catalog/index.ts
index 936dd7f2..1ec017ed 100644
--- a/src/nitro/communication/messages/parser/catalog/index.ts
+++ b/src/nitro/communication/messages/parser/catalog/index.ts
@@ -6,6 +6,7 @@ export * from './CatalogGroupsParser';
 export * from './CatalogModeParser';
 export * from './CatalogPageParser';
 export * from './CatalogPagesParser';
+export * from './CatalogPetBreedsParser';
 export * from './CatalogPurchaseFailedParser';
 export * from './CatalogPurchaseParser';
 export * from './CatalogPurchaseUnavailableParser';
diff --git a/src/nitro/communication/messages/parser/catalog/utils/CatalogPetPaletteBreed.ts b/src/nitro/communication/messages/parser/catalog/utils/CatalogPetPaletteBreed.ts
new file mode 100644
index 00000000..111ea9db
--- /dev/null
+++ b/src/nitro/communication/messages/parser/catalog/utils/CatalogPetPaletteBreed.ts
@@ -0,0 +1,67 @@
+import { IMessageDataWrapper } from '../../../../../../core/communication/messages/IMessageDataWrapper';
+
+export class CatalogPetPaletteBreed
+{
+    private _type: number;
+    private _breedId: number;
+    private _paletteId: number;
+    private _sellable: boolean;
+    private _rare: boolean;
+
+    constructor(wrapper: IMessageDataWrapper)
+    {
+        if(!wrapper) throw new Error('invalid_wrapper');
+
+        this.flush();
+        this.parse(wrapper);
+    }
+
+    public flush(): boolean
+    {
+        this._type      = -1;
+        this._breedId   = -1;
+        this._paletteId = -1;
+        this._sellable  = false;
+        this._rare      = false;
+
+        return true;
+    }
+
+    public parse(wrapper: IMessageDataWrapper): boolean
+    {
+        if(!wrapper) return false;
+
+        this._type      = wrapper.readInt();
+        this._breedId   = wrapper.readInt();
+        this._paletteId = wrapper.readInt();
+        this._sellable  = wrapper.readBoolean();
+        this._rare      = wrapper.readBoolean();
+
+        return true;
+    }
+
+    public get type(): number
+    {
+        return this._type;
+    }
+
+    public get breedId(): number
+    {
+        return this._breedId;
+    }
+
+    public get paletteId(): number
+    {
+        return this._paletteId;
+    }
+
+    public get sellable(): boolean
+    {
+        return this._sellable;
+    }
+
+    public get rare(): boolean
+    {
+        return this._rare;
+    }
+}
diff --git a/src/nitro/communication/messages/parser/catalog/utils/index.ts b/src/nitro/communication/messages/parser/catalog/utils/index.ts
index bc58d202..74778bea 100644
--- a/src/nitro/communication/messages/parser/catalog/utils/index.ts
+++ b/src/nitro/communication/messages/parser/catalog/utils/index.ts
@@ -4,6 +4,7 @@ export * from './CatalogGroupData';
 export * from './CatalogLocalizationData';
 export * from './CatalogPageData';
 export * from './CatalogPageOfferData';
+export * from './CatalogPetPaletteBreed';
 export * from './CatalogProductOfferData';
 export * from './CatalogPurchaseData';
 export * from './CatalogSearchData';

From 4eae19ae055f302d67d24a914f098cdd81275cc6 Mon Sep 17 00:00:00 2001
From: Bill <billsonnn@live.com>
Date: Mon, 17 May 2021 22:50:30 -0400
Subject: [PATCH 4/7] Rename packets

---
 src/nitro/communication/NitroMessages.ts         |  4 ++--
 .../incoming/catalog/CatalogPetBreedsEvent.ts    | 16 ----------------
 .../incoming/catalog/SellablePetPalettesEvent.ts | 16 ++++++++++++++++
 .../messages/incoming/catalog/index.ts           |  2 +-
 .../parser/catalog/CatalogPetBreedsParser.ts     | 10 +++++-----
 ...PaletteBreed.ts => SellablePetPaletteData.ts} |  2 +-
 .../messages/parser/catalog/utils/index.ts       |  2 +-
 7 files changed, 26 insertions(+), 26 deletions(-)
 delete mode 100644 src/nitro/communication/messages/incoming/catalog/CatalogPetBreedsEvent.ts
 create mode 100644 src/nitro/communication/messages/incoming/catalog/SellablePetPalettesEvent.ts
 rename src/nitro/communication/messages/parser/catalog/utils/{CatalogPetPaletteBreed.ts => SellablePetPaletteData.ts} (97%)

diff --git a/src/nitro/communication/NitroMessages.ts b/src/nitro/communication/NitroMessages.ts
index 3dae8db9..df391a83 100644
--- a/src/nitro/communication/NitroMessages.ts
+++ b/src/nitro/communication/NitroMessages.ts
@@ -1,5 +1,5 @@
 import { IMessageConfiguration } from '../../core/communication/messages/IMessageConfiguration';
-import { CatalogPetBreedsEvent } from './messages';
+import { SellablePetPalettesEvent } from './messages';
 import { AvailabilityStatusMessageEvent } from './messages/incoming/availability/AvailabilityStatusMessageEvent';
 import { ChangeNameUpdateEvent } from './messages/incoming/avatar/ChangeNameUpdateEvent';
 import { CatalogClubEvent } from './messages/incoming/catalog/CatalogClubEvent';
@@ -443,7 +443,7 @@ export class NitroMessages implements IMessageConfiguration
         this._events.set(IncomingHeader.GIFT_CONFIG, CatalogGiftConfigurationEvent);
         this._events.set(IncomingHeader.REDEEM_VOUCHER_ERROR, CatalogRedeemVoucherErrorEvent);
         this._events.set(IncomingHeader.REDEEM_VOUCHER_OK, CatalogRedeemVoucherOkEvent);
-        this._events.set(IncomingHeader.CATALOG_RECEIVE_PET_BREEDS, CatalogPetBreedsEvent);
+        this._events.set(IncomingHeader.CATALOG_RECEIVE_PET_BREEDS, SellablePetPalettesEvent);
 
         // CLIENT
         this._events.set(IncomingHeader.CLIENT_PING, ClientPingEvent);
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogPetBreedsEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogPetBreedsEvent.ts
deleted file mode 100644
index 140ee8ed..00000000
--- a/src/nitro/communication/messages/incoming/catalog/CatalogPetBreedsEvent.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
-import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
-import { CatalogPetBreedsParser } from '../../parser';
-
-export class CatalogPetBreedsEvent extends MessageEvent implements IMessageEvent
-{
-    constructor(callBack: Function)
-    {
-        super(callBack, CatalogPetBreedsParser);
-    }
-
-    public getParser(): CatalogPetBreedsParser
-    {
-        return this.parser as CatalogPetBreedsParser;
-    }
-}
diff --git a/src/nitro/communication/messages/incoming/catalog/SellablePetPalettesEvent.ts b/src/nitro/communication/messages/incoming/catalog/SellablePetPalettesEvent.ts
new file mode 100644
index 00000000..83ad8337
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/SellablePetPalettesEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { SellablePetPalettesParser } from '../../parser';
+
+export class SellablePetPalettesEvent extends MessageEvent implements IMessageEvent
+{
+    constructor(callBack: Function)
+    {
+        super(callBack, SellablePetPalettesParser);
+    }
+
+    public getParser(): SellablePetPalettesParser
+    {
+        return this.parser as SellablePetPalettesParser;
+    }
+}
diff --git a/src/nitro/communication/messages/incoming/catalog/index.ts b/src/nitro/communication/messages/incoming/catalog/index.ts
index 4a4179e5..ffda2bbb 100644
--- a/src/nitro/communication/messages/incoming/catalog/index.ts
+++ b/src/nitro/communication/messages/incoming/catalog/index.ts
@@ -6,7 +6,6 @@ export * from './CatalogGroupsEvent';
 export * from './CatalogModeEvent';
 export * from './CatalogPageEvent';
 export * from './CatalogPagesEvent';
-export * from './CatalogPetBreedsEvent';
 export * from './CatalogPurchaseEvent';
 export * from './CatalogPurchaseFailedEvent';
 export * from './CatalogPurchaseUnavailableEvent';
@@ -18,3 +17,4 @@ export * from './CatalogUpdatedEvent';
 export * from './marketplace';
 export * from './MarketplaceConfigEvent';
 export * from './MarketplaceItemStatsEvent';
+export * from './SellablePetPalettesEvent';
diff --git a/src/nitro/communication/messages/parser/catalog/CatalogPetBreedsParser.ts b/src/nitro/communication/messages/parser/catalog/CatalogPetBreedsParser.ts
index 44f27f2f..e72296be 100644
--- a/src/nitro/communication/messages/parser/catalog/CatalogPetBreedsParser.ts
+++ b/src/nitro/communication/messages/parser/catalog/CatalogPetBreedsParser.ts
@@ -1,11 +1,11 @@
 import { IMessageDataWrapper } from '../../../../../core/communication/messages/IMessageDataWrapper';
 import { IMessageParser } from '../../../../../core/communication/messages/IMessageParser';
-import { CatalogPetPaletteBreed } from './utils';
+import { SellablePetPaletteData } from './utils';
 
-export class CatalogPetBreedsParser implements IMessageParser
+export class SellablePetPalettesParser implements IMessageParser
 {
     private _productCode: string;
-    private _palettes: CatalogPetPaletteBreed[];
+    private _palettes: SellablePetPaletteData[];
 
     public flush(): boolean
     {
@@ -25,7 +25,7 @@ export class CatalogPetBreedsParser implements IMessageParser
 
         while(totalPalettes > 0)
         {
-            this._palettes.push(new CatalogPetPaletteBreed(wrapper));
+            this._palettes.push(new SellablePetPaletteData(wrapper));
 
             totalPalettes--;
         }
@@ -38,7 +38,7 @@ export class CatalogPetBreedsParser implements IMessageParser
         return this._productCode;
     }
 
-    public get palettes(): CatalogPetPaletteBreed[]
+    public get palettes(): SellablePetPaletteData[]
     {
         return this._palettes;
     }
diff --git a/src/nitro/communication/messages/parser/catalog/utils/CatalogPetPaletteBreed.ts b/src/nitro/communication/messages/parser/catalog/utils/SellablePetPaletteData.ts
similarity index 97%
rename from src/nitro/communication/messages/parser/catalog/utils/CatalogPetPaletteBreed.ts
rename to src/nitro/communication/messages/parser/catalog/utils/SellablePetPaletteData.ts
index 111ea9db..b7d4dd1b 100644
--- a/src/nitro/communication/messages/parser/catalog/utils/CatalogPetPaletteBreed.ts
+++ b/src/nitro/communication/messages/parser/catalog/utils/SellablePetPaletteData.ts
@@ -1,6 +1,6 @@
 import { IMessageDataWrapper } from '../../../../../../core/communication/messages/IMessageDataWrapper';
 
-export class CatalogPetPaletteBreed
+export class SellablePetPaletteData
 {
     private _type: number;
     private _breedId: number;
diff --git a/src/nitro/communication/messages/parser/catalog/utils/index.ts b/src/nitro/communication/messages/parser/catalog/utils/index.ts
index 74778bea..41e3c62f 100644
--- a/src/nitro/communication/messages/parser/catalog/utils/index.ts
+++ b/src/nitro/communication/messages/parser/catalog/utils/index.ts
@@ -4,7 +4,6 @@ export * from './CatalogGroupData';
 export * from './CatalogLocalizationData';
 export * from './CatalogPageData';
 export * from './CatalogPageOfferData';
-export * from './CatalogPetPaletteBreed';
 export * from './CatalogProductOfferData';
 export * from './CatalogPurchaseData';
 export * from './CatalogSearchData';
@@ -14,4 +13,5 @@ export * from './ICatalogPageParser';
 export * from './MarketplaceOfferData';
 export * from './MarketplaceOfferItem';
 export * from './MarketplaceOwnItem';
+export * from './SellablePetPaletteData';
 export * from './_Str_5178';

From 5325c65b1046e09618268649b81dc070fb872071 Mon Sep 17 00:00:00 2001
From: Bill <billsonnn@live.com>
Date: Tue, 18 May 2021 21:47:12 -0400
Subject: [PATCH 5/7] Fix issue with empty furnidata

---
 src/nitro/session/SessionDataManager.ts | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/nitro/session/SessionDataManager.ts b/src/nitro/session/SessionDataManager.ts
index 1dbb20f5..72a996ea 100644
--- a/src/nitro/session/SessionDataManager.ts
+++ b/src/nitro/session/SessionDataManager.ts
@@ -220,8 +220,6 @@ export class SessionDataManager extends NitroManager implements ISessionDataMana
             furnitureData.push(data);
         }
 
-        if(!furnitureData || !furnitureData.length) return null;
-
         return furnitureData;
     }
 

From 40be434792d3242414c4da4a1d845fbfca1b03b0 Mon Sep 17 00:00:00 2001
From: Bill <billsonnn@live.com>
Date: Sat, 22 May 2021 12:16:40 -0400
Subject: [PATCH 6/7] Add packets

---
 src/nitro/communication/NitroMessages.ts      |  4 ++-
 .../messages/incoming/IncomingHeader.ts       |  1 +
 .../catalog/CatalogApproveNameResultEvent.ts  | 16 +++++++++
 .../messages/incoming/catalog/index.ts        |  1 +
 .../messages/outgoing/OutgoingHeader.ts       |  1 +
 .../user/ApproveNameMessageComposer.ts        | 21 +++++++++++
 .../messages/outgoing/user/index.ts           |  1 +
 .../catalog/CatalogApproveNameResultParser.ts | 36 +++++++++++++++++++
 .../messages/parser/catalog/index.ts          |  1 +
 9 files changed, 81 insertions(+), 1 deletion(-)
 create mode 100644 src/nitro/communication/messages/incoming/catalog/CatalogApproveNameResultEvent.ts
 create mode 100644 src/nitro/communication/messages/outgoing/user/ApproveNameMessageComposer.ts
 create mode 100644 src/nitro/communication/messages/parser/catalog/CatalogApproveNameResultParser.ts

diff --git a/src/nitro/communication/NitroMessages.ts b/src/nitro/communication/NitroMessages.ts
index df391a83..54ad2d5e 100644
--- a/src/nitro/communication/NitroMessages.ts
+++ b/src/nitro/communication/NitroMessages.ts
@@ -1,5 +1,5 @@
 import { IMessageConfiguration } from '../../core/communication/messages/IMessageConfiguration';
-import { SellablePetPalettesEvent } from './messages';
+import { ApproveNameMessageComposer, CatalogApproveNameResultEvent, SellablePetPalettesEvent } from './messages';
 import { AvailabilityStatusMessageEvent } from './messages/incoming/availability/AvailabilityStatusMessageEvent';
 import { ChangeNameUpdateEvent } from './messages/incoming/avatar/ChangeNameUpdateEvent';
 import { CatalogClubEvent } from './messages/incoming/catalog/CatalogClubEvent';
@@ -444,6 +444,7 @@ export class NitroMessages implements IMessageConfiguration
         this._events.set(IncomingHeader.REDEEM_VOUCHER_ERROR, CatalogRedeemVoucherErrorEvent);
         this._events.set(IncomingHeader.REDEEM_VOUCHER_OK, CatalogRedeemVoucherOkEvent);
         this._events.set(IncomingHeader.CATALOG_RECEIVE_PET_BREEDS, SellablePetPalettesEvent);
+        this._events.set(IncomingHeader.CATALOG_APPROVE_NAME_RESULT, CatalogApproveNameResultEvent);
 
         // CLIENT
         this._events.set(IncomingHeader.CLIENT_PING, ClientPingEvent);
@@ -938,6 +939,7 @@ export class NitroMessages implements IMessageConfiguration
         this._composers.set(OutgoingHeader.ROOM_MUTE, RoomMuteComposer);
 
         // USER
+        this._composers.set(OutgoingHeader.APPROVE_NAME, ApproveNameMessageComposer);
         this._composers.set(OutgoingHeader.USER_RESPECT, UserRespectComposer);
 
         // DATA
diff --git a/src/nitro/communication/messages/incoming/IncomingHeader.ts b/src/nitro/communication/messages/incoming/IncomingHeader.ts
index 6cdecd59..35522812 100644
--- a/src/nitro/communication/messages/incoming/IncomingHeader.ts
+++ b/src/nitro/communication/messages/incoming/IncomingHeader.ts
@@ -246,4 +246,5 @@ export class IncomingHeader
     public static MARKETPLACE_ITEMS_SEARCHED       = 680;
     public static MARKETPLACE_AFTER_ORDER_STATUS   = 2032;
     public static CATALOG_RECEIVE_PET_BREEDS       = 3331;
+    public static CATALOG_APPROVE_NAME_RESULT      = 1503;
 }
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogApproveNameResultEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogApproveNameResultEvent.ts
new file mode 100644
index 00000000..d10cea5f
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogApproveNameResultEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogApproveNameResultParser } from '../../parser';
+
+export class CatalogApproveNameResultEvent extends MessageEvent implements IMessageEvent
+{
+    constructor(callBack: Function)
+    {
+        super(callBack, CatalogApproveNameResultParser);
+    }
+
+    public getParser(): CatalogApproveNameResultParser
+    {
+        return this.parser as CatalogApproveNameResultParser;
+    }
+}
diff --git a/src/nitro/communication/messages/incoming/catalog/index.ts b/src/nitro/communication/messages/incoming/catalog/index.ts
index ffda2bbb..518c657a 100644
--- a/src/nitro/communication/messages/incoming/catalog/index.ts
+++ b/src/nitro/communication/messages/incoming/catalog/index.ts
@@ -1,3 +1,4 @@
+export * from './CatalogApproveNameResultEvent';
 export * from './CatalogClubEvent';
 export * from './CatalogClubGiftsEvent';
 export * from './CatalogGiftConfigurationEvent';
diff --git a/src/nitro/communication/messages/outgoing/OutgoingHeader.ts b/src/nitro/communication/messages/outgoing/OutgoingHeader.ts
index 6edbd82d..52a7906d 100644
--- a/src/nitro/communication/messages/outgoing/OutgoingHeader.ts
+++ b/src/nitro/communication/messages/outgoing/OutgoingHeader.ts
@@ -231,4 +231,5 @@ export class OutgoingHeader
     public static MARKETPLACE_REQUEST_OFFERS     = 2407;
     public static MARKETPLACE_BUY_OFFER          = 1603;
     public static CATALOG_REQUESET_PET_BREEDS    = 1756;
+    public static APPROVE_NAME                   = 2109;
 }
diff --git a/src/nitro/communication/messages/outgoing/user/ApproveNameMessageComposer.ts b/src/nitro/communication/messages/outgoing/user/ApproveNameMessageComposer.ts
new file mode 100644
index 00000000..64ef6ace
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/user/ApproveNameMessageComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class ApproveNameMessageComposer implements IMessageComposer<ConstructorParameters<typeof ApproveNameMessageComposer>>
+{
+    private _data: ConstructorParameters<typeof ApproveNameMessageComposer>;
+
+    constructor(name: string, type: number)
+    {
+        this._data = [ name, type ];
+    }
+
+    public getMessageArray()
+    {
+        return this._data;
+    }
+
+    public dispose(): void
+    {
+        return;
+    }
+}
diff --git a/src/nitro/communication/messages/outgoing/user/index.ts b/src/nitro/communication/messages/outgoing/user/index.ts
index c946f640..006b940b 100644
--- a/src/nitro/communication/messages/outgoing/user/index.ts
+++ b/src/nitro/communication/messages/outgoing/user/index.ts
@@ -1,3 +1,4 @@
+export * from './ApproveNameMessageComposer';
 export * from './data';
 export * from './inventory';
 export * from './settings';
diff --git a/src/nitro/communication/messages/parser/catalog/CatalogApproveNameResultParser.ts b/src/nitro/communication/messages/parser/catalog/CatalogApproveNameResultParser.ts
new file mode 100644
index 00000000..c16a7100
--- /dev/null
+++ b/src/nitro/communication/messages/parser/catalog/CatalogApproveNameResultParser.ts
@@ -0,0 +1,36 @@
+import { IMessageDataWrapper } from '../../../../../core/communication/messages/IMessageDataWrapper';
+import { IMessageParser } from '../../../../../core/communication/messages/IMessageParser';
+
+export class CatalogApproveNameResultParser implements IMessageParser
+{
+    private _result: number;
+    private _validationInfo: string;
+
+    public flush(): boolean
+    {
+        this._result            = -1;
+        this._validationInfo    = '';
+
+        return true;
+    }
+
+    public parse(wrapper: IMessageDataWrapper): boolean
+    {
+        if(!wrapper) return false;
+
+        this._result            = wrapper.readInt();
+        this._validationInfo    = wrapper.readString();
+
+        return true;
+    }
+
+    public get result(): number
+    {
+        return this._result;
+    }
+
+    public get validationInfo(): string
+    {
+        return this._validationInfo;
+    }
+}
diff --git a/src/nitro/communication/messages/parser/catalog/index.ts b/src/nitro/communication/messages/parser/catalog/index.ts
index 1ec017ed..dfe50c21 100644
--- a/src/nitro/communication/messages/parser/catalog/index.ts
+++ b/src/nitro/communication/messages/parser/catalog/index.ts
@@ -1,3 +1,4 @@
+export * from './CatalogApproveNameResultParser';
 export * from './CatalogClubGiftsParser';
 export * from './CatalogClubParser';
 export * from './CatalogGiftConfigurationParser';

From 33da59c3c2d5665bd04f26843509a07007a2c0e3 Mon Sep 17 00:00:00 2001
From: Bill <billsonnn@live.com>
Date: Sat, 22 May 2021 12:16:52 -0400
Subject: [PATCH 7/7] Updates

---
 src/nitro/room/IRoomEngine.ts           |  2 ++
 src/nitro/room/PetColorResult.ts        | 18 +++++++-------
 src/nitro/room/RoomContentLoader.ts     | 33 +++++++++++++++++++++++++
 src/nitro/room/RoomEngine.ts            |  8 ++++++
 src/nitro/room/preview/RoomPreviewer.ts | 29 ++++++++++++++++++----
 5 files changed, 76 insertions(+), 14 deletions(-)

diff --git a/src/nitro/room/IRoomEngine.ts b/src/nitro/room/IRoomEngine.ts
index 596b5b6e..f46405dd 100644
--- a/src/nitro/room/IRoomEngine.ts
+++ b/src/nitro/room/IRoomEngine.ts
@@ -15,6 +15,7 @@ import { IGetImageListener } from './IGetImageListener';
 import { ImageResult } from './ImageResult';
 import { IObjectData } from './object/data/IObjectData';
 import { RoomMapData } from './object/RoomMapData';
+import { PetColorResult } from './PetColorResult';
 import { RoomContentLoader } from './RoomContentLoader';
 import { RoomObjectEventHandler } from './RoomObjectEventHandler';
 
@@ -73,6 +74,7 @@ export interface IRoomEngine extends INitroManager
     getRoomObjectPetImage(typeId: number, paletteId: number, color: number, direction: IVector3D, scale: number, listener: IGetImageListener, headOnly?: boolean, bgColor?: number, customParts?: PetCustomPart[], posture?: string): ImageResult;
     selectRoomObject(roomId: number, objectId: number, objectCategory: number): void;
     _Str_8675(): void;
+    getPetColorResult(petIndex: number, paletteIndex: number): PetColorResult;
     cancelRoomObjectPlacement(): void;
     getFurnitureFloorName(typeId: number): string;
     useRoomObject(objectId: number, category: number): boolean;
diff --git a/src/nitro/room/PetColorResult.ts b/src/nitro/room/PetColorResult.ts
index 6a471b26..d6a3bfa7 100644
--- a/src/nitro/room/PetColorResult.ts
+++ b/src/nitro/room/PetColorResult.ts
@@ -10,16 +10,16 @@ export class PetColorResult
     private _isMaster: boolean;
     private _layerTags: string[];
 
-    constructor(k: number, _arg_2: number, _arg_3: number, _arg_4: number, _arg_5: string, _arg_6: boolean, _arg_7: string[])
+    constructor(primaryColor: number, secondaryColor: number, breed: number, tag: number, id: string, isMaster: boolean, layerTags: string[])
     {
         this._layerTags         = [];
-        this._primaryColor      = (k & 0xFFFFFF);
-        this._secondaryColor    = (_arg_2 & 0xFFFFFF);
-        this._breed             = _arg_3;
-        this._tag               = (((_arg_4 > -1) && (_arg_4 < PetColorResult._Str_12950.length)) ? PetColorResult._Str_12950[_arg_4] : '');
-        this._id                = _arg_5;
-        this._isMaster          = _arg_6;
-        this._layerTags         = _arg_7;
+        this._primaryColor      = (primaryColor & 0xFFFFFF);
+        this._secondaryColor    = (secondaryColor & 0xFFFFFF);
+        this._breed             = breed;
+        this._tag               = (((tag > -1) && (tag < PetColorResult._Str_12950.length)) ? PetColorResult._Str_12950[tag] : '');
+        this._id                = id;
+        this._isMaster          = isMaster;
+        this._layerTags         = layerTags;
     }
 
     public get _Str_5845(): number
@@ -56,4 +56,4 @@ export class PetColorResult
     {
         return this._layerTags;
     }
-}
\ No newline at end of file
+}
diff --git a/src/nitro/room/RoomContentLoader.ts b/src/nitro/room/RoomContentLoader.ts
index 46275f86..ecfaac32 100644
--- a/src/nitro/room/RoomContentLoader.ts
+++ b/src/nitro/room/RoomContentLoader.ts
@@ -19,6 +19,7 @@ import { RoomObjectCategory } from './object/RoomObjectCategory';
 import { RoomObjectUserType } from './object/RoomObjectUserType';
 import { RoomObjectVariable } from './object/RoomObjectVariable';
 import { RoomObjectVisualizationType } from './object/RoomObjectVisualizationType';
+import { PetColorResult } from './PetColorResult';
 
 export class RoomContentLoader implements IFurnitureDataListener
 {
@@ -51,6 +52,7 @@ export class RoomContentLoader implements IFurnitureDataListener
     private _wallItemTypeIds: Map<string, number>;
     private _furniRevisions: Map<string, number>;
     private _pets: { [index: string]: number };
+    private _petColors: Map<number, Map<number, PetColorResult>>;
     private _objectAliases: Map<string, string>;
     private _objectOriginalNames: Map<string, string>;
 
@@ -77,6 +79,7 @@ export class RoomContentLoader implements IFurnitureDataListener
         this._wallItemTypeIds               = new Map();
         this._furniRevisions                = new Map();
         this._pets                          = {};
+        this._petColors                     = new Map();
         this._objectAliases                 = new Map();
         this._objectOriginalNames           = new Map();
 
@@ -250,6 +253,15 @@ export class RoomContentLoader implements IFurnitureDataListener
         return name.substr(0, index);
     }
 
+    public getPetColorResult(petIndex: number, paletteIndex: number): PetColorResult
+    {
+        const colorResults = this._petColors.get(petIndex);
+
+        if(!colorResults) return null;
+
+        return colorResults.get(paletteIndex);
+    }
+
     public getCollection(name: string): IGraphicAssetCollection
     {
         if(!name) return null;
@@ -304,6 +316,27 @@ export class RoomContentLoader implements IFurnitureDataListener
         const collection = new GraphicAssetCollection(data, spritesheet);
 
         this._collections.set(collection.name, collection);
+
+        const petIndex = this._pets[collection.name];
+
+        if(petIndex !== undefined)
+        {
+            const keys = collection.getPaletteNames();
+            const palettes: Map<number, PetColorResult> = new Map();
+
+            for(const key of keys)
+            {
+                const palette = collection.getPalette(key);
+
+                const breed = 0;
+                const primaryColor = palette.primaryColor;
+                const secondaryColor = palette.secondaryColor;
+
+                palettes.set(parseInt(key), new PetColorResult(primaryColor, secondaryColor, breed, -1, key, false, []));
+            }
+
+            this._petColors.set(petIndex, palettes);
+        }
     }
 
     public getPlaceholderName(type: string): string
diff --git a/src/nitro/room/RoomEngine.ts b/src/nitro/room/RoomEngine.ts
index 0433a9e2..d54ff4a5 100644
--- a/src/nitro/room/RoomEngine.ts
+++ b/src/nitro/room/RoomEngine.ts
@@ -94,6 +94,7 @@ import { RoomObjectCategory } from './object/RoomObjectCategory';
 import { RoomObjectUserType } from './object/RoomObjectUserType';
 import { RoomObjectVariable } from './object/RoomObjectVariable';
 import { RoomObjectVisualizationFactory } from './object/RoomObjectVisualizationFactory';
+import { PetColorResult } from './PetColorResult';
 import { RoomContentLoader } from './RoomContentLoader';
 import { RoomMessageHandler } from './RoomMessageHandler';
 import { RoomObjectEventHandler } from './RoomObjectEventHandler';
@@ -3527,6 +3528,13 @@ export class RoomEngine extends NitroManager implements IRoomEngine, IRoomCreato
         return (this._roomContentLoader.getCollection(name) !== null);
     }
 
+    public getPetColorResult(petIndex: number, paletteIndex: number): PetColorResult
+    {
+        if(!this._roomContentLoader) return null;
+
+        return this._roomContentLoader.getPetColorResult(petIndex, paletteIndex);
+    }
+
     public modifyRoomObjectData(objectId: number, objectCategory: number, colorHex: string, text: string): boolean
     {
         if(!this._roomObjectEventHandler || (objectCategory !== RoomObjectCategory.WALL)) return false;
diff --git a/src/nitro/room/preview/RoomPreviewer.ts b/src/nitro/room/preview/RoomPreviewer.ts
index ffe1455a..90757f2c 100644
--- a/src/nitro/room/preview/RoomPreviewer.ts
+++ b/src/nitro/room/preview/RoomPreviewer.ts
@@ -52,6 +52,7 @@ export class RoomPreviewer
     private _previousAutomaticStateChangeTime: number;
     private _addViewOffset: Point;
     private _backgroundColor: number = 305148561;
+    private _backgroundSprite: Sprite = null;
     private _disableUpdate: boolean = false;
 
     constructor(roomEngine: IRoomEngine, roomId: number = 1)
@@ -85,6 +86,13 @@ export class RoomPreviewer
             this._roomEngine.events.removeEventListener(RoomEngineEvent.INITIALIZED, this.onRoomInitializedonRoomInitialized);
         }
 
+        if(this._backgroundSprite)
+        {
+            this._backgroundSprite.destroy();
+
+            this._backgroundSprite = null;
+        }
+
         if(this._planeParser)
         {
             this._planeParser.dispose();
@@ -438,13 +446,18 @@ export class RoomPreviewer
 
             if(displayObject && (this._backgroundColor !== null))
             {
-                const background = new Sprite(Texture.WHITE);
+                let backgroundSprite = this._backgroundSprite;
 
-                background.width    = width;
-                background.height   = height;
-                background.tint     = this._backgroundColor;
+                if(!backgroundSprite)
+                {
+                    backgroundSprite = new Sprite(Texture.WHITE);
 
-                displayObject.addChildAt(background, 0);
+                    displayObject.addChildAt(backgroundSprite, 0);
+                }
+
+                backgroundSprite.width    = width;
+                backgroundSprite.height   = height;
+                backgroundSprite.tint     = this._backgroundColor;
             }
 
             this._roomEngine.setRoomInstanceRenderingCanvasMask(this._previewRoomId, RoomPreviewer.PREVIEW_CANVAS_ID, true);
@@ -469,6 +482,12 @@ export class RoomPreviewer
             this._currentPreviewCanvasWidth     = width;
             this._currentPreviewCanvasHeight    = height;
 
+            if(this._backgroundSprite)
+            {
+                this._backgroundSprite.width    = width;
+                this._backgroundSprite.height   = height;
+            }
+
             this._roomEngine.initializeRoomInstanceRenderingCanvas(this._previewRoomId, RoomPreviewer.PREVIEW_CANVAS_ID, width, height);
         }
     }