diff --git a/src/api/room/widgets/ChatBubbleUtilities.ts b/src/api/room/widgets/ChatBubbleUtilities.ts index fff0a14..2f6d54c 100644 --- a/src/api/room/widgets/ChatBubbleUtilities.ts +++ b/src/api/room/widgets/ChatBubbleUtilities.ts @@ -5,6 +5,7 @@ export class ChatBubbleUtilities public static AVATAR_COLOR_CACHE: Map = new Map(); public static AVATAR_IMAGE_CACHE: Map = new Map(); public static PET_IMAGE_CACHE: Map = new Map(); + private static PET_IMAGE_PENDING_CACHE: Map> = new Map(); private static placeHolderImageUrl: string = ''; @@ -49,19 +50,70 @@ export class ChatBubbleUtilities public static async getPetImage(figure: string, direction: number, _arg_3: boolean, scale: number = 64, posture: string = null) { - let existing = this.PET_IMAGE_CACHE.get((figure + posture)); + const cacheKey = `${ figure }-${ posture || 'std' }-${ direction }-${ scale }`; + let existing = this.PET_IMAGE_CACHE.get(cacheKey); if(existing) return existing; - const figureData = new PetFigureData(figure); - const typeId = figureData.typeId; - const image = GetRoomEngine().getRoomObjectPetImage(typeId, figureData.paletteId, figureData.color, new Vector3d((direction * 45)), scale, null, false, 0, figureData.customParts, posture); + const pending = this.PET_IMAGE_PENDING_CACHE.get(cacheKey); - if(image) + if(pending) return pending; + + const resultPromise = (async () => { - existing = await TextureUtils.generateImageUrl(image.data); + const figureData = new PetFigureData(figure); + const typeId = figureData.typeId; - this.PET_IMAGE_CACHE.set((figure + posture), existing); + const getImageUrl = async (imageResult) => + { + if(!imageResult) return null; + + const image = await imageResult.getImage(); + + if(image) return image.src; + if(imageResult.data) return TextureUtils.generateImageUrl(imageResult.data); + + return null; + }; + + let listenerResolve = null; + + const listenerPromise = new Promise(resolve => + { + listenerResolve = resolve; + }); + + const imageResult = GetRoomEngine().getRoomObjectPetImage(typeId, figureData.paletteId, figureData.color, new Vector3d((direction * 45)), scale, { + imageReady: async result => listenerResolve(await getImageUrl(result)), + imageFailed: () => listenerResolve(null) + }, false, 0, figureData.customParts, posture); + + let resolvedImage: string = null; + + if(imageResult?.id > 0) + { + resolvedImage = await Promise.race([ + listenerPromise, + new Promise(resolve => setTimeout(() => resolve(null), 2500)) + ]); + } + + if(!resolvedImage) resolvedImage = await getImageUrl(imageResult); + + if(resolvedImage) this.PET_IMAGE_CACHE.set(cacheKey, resolvedImage); + + return resolvedImage; + })(); + + this.PET_IMAGE_PENDING_CACHE.set(cacheKey, resultPromise); + + try + { + existing = await resultPromise; + } + finally + { + this.PET_IMAGE_PENDING_CACHE.delete(cacheKey); } return existing; diff --git a/src/components/room/widgets/chat/ChatWidgetMessageView.tsx b/src/components/room/widgets/chat/ChatWidgetMessageView.tsx index 16e97c4..9163f2b 100644 --- a/src/components/room/widgets/chat/ChatWidgetMessageView.tsx +++ b/src/components/room/widgets/chat/ChatWidgetMessageView.tsx @@ -85,7 +85,7 @@ export const ChatWidgetMessageView: FC = ({ style={ { maxWidth: getBubbleWidth } }>
{ chat.imageUrl && chat.imageUrl.length > 0 && ( -
+
) }
diff --git a/src/css/chat/chats.css b/src/css/chat/chats.css index 7d9c173..865f17e 100644 --- a/src/css/chat/chats.css +++ b/src/css/chat/chats.css @@ -34,7 +34,7 @@ } &.bubble-0 { - border-image-source: url('@/assets/images/chat/chatbubbles/bubble_0_transparent.png'); + border-image-source: url('@/assets/images/chat/chatbubbles/bubble_0.png'); .pointer { background: url('@/assets/images/chat/chatbubbles/bubble_0_1_33_34_pointer.png');