feat: 前端改为通过签名地址读取生成资源
This commit is contained in:
@@ -15,6 +15,7 @@ import {
|
||||
import {HostileNpcAnimator} from '../HostileNpcAnimator';
|
||||
import {MedievalNpcAnimator} from '../MedievalNpcAnimator';
|
||||
import {getRenderableNpcFacing} from '../npcRenderUtils';
|
||||
import {ResolvedAssetImage} from '../ResolvedAssetImage';
|
||||
import {NpcAffinityEffectBadge} from './NpcAffinityEffectBadge';
|
||||
import {
|
||||
DialogueBubbleIcon,
|
||||
@@ -408,7 +409,7 @@ export function GameCanvasEntityLayer({
|
||||
<div className={ROLE_CHARACTER_FRAME_CLASS}>
|
||||
{encounter.kind === 'treasure' ? (
|
||||
<div className="flex h-20 w-20 items-center justify-center rounded-2xl border border-amber-400/30 bg-amber-500/15 shadow-[0_0_20px_rgba(255,255,255,0.12)]">
|
||||
<img
|
||||
<ResolvedAssetImage
|
||||
src={encounter.npcAvatar || '/Icons/47_treasure.png'}
|
||||
alt={encounter.npcName}
|
||||
className="h-12 w-12 object-contain"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {AnimatePresence, motion} from 'motion/react';
|
||||
|
||||
import { useResolvedAssetReadUrl } from '../../hooks/useResolvedAssetReadUrl';
|
||||
import {type ScenePresetInfo, WorldType} from '../../types';
|
||||
import {CHROME_ICONS, getNineSliceStyle, UI_CHROME} from '../../uiAssets';
|
||||
import {PixelIcon} from '../PixelIcon';
|
||||
@@ -24,11 +25,19 @@ export function GameCanvasSceneLayer({
|
||||
onSceneNameClick = null,
|
||||
onBackgroundLoadError,
|
||||
}: GameCanvasSceneLayerProps) {
|
||||
const {
|
||||
resolvedUrl: resolvedBackgroundSrc,
|
||||
shouldResolve: shouldResolveBackground,
|
||||
} = useResolvedAssetReadUrl(backgroundSrc);
|
||||
// 签名地址未返回前先显示渐变底色,避免浏览器直接访问私有原图触发 403。
|
||||
const displayBackgroundSrc =
|
||||
resolvedBackgroundSrc || (!shouldResolveBackground ? backgroundSrc : '');
|
||||
|
||||
return (
|
||||
<>
|
||||
{!backgroundLoadFailed ? (
|
||||
{!backgroundLoadFailed && displayBackgroundSrc ? (
|
||||
<img
|
||||
src={backgroundSrc}
|
||||
src={displayBackgroundSrc}
|
||||
alt={currentScenePreset?.name || 'Scene background'}
|
||||
className="absolute inset-0 h-full w-full object-cover"
|
||||
style={{imageRendering: 'pixelated'}}
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, {useEffect, useState} from 'react';
|
||||
|
||||
import {getCharacterById} from '../../data/characterPresets';
|
||||
import {METERS_TO_PIXELS} from '../../data/hostileNpcs';
|
||||
import { useResolvedAssetReadUrl } from '../../hooks/useResolvedAssetReadUrl';
|
||||
import {
|
||||
buildMedievalNpcVisual,
|
||||
buildMedievalNpcVisualFromCustomWorldVisual,
|
||||
@@ -266,6 +267,15 @@ export function SceneEncounterNpcSprite({
|
||||
facing: 'left' | 'right';
|
||||
className?: string;
|
||||
}) {
|
||||
const rawEncounterImageSrc = encounter.imageSrc?.trim() ?? '';
|
||||
const {
|
||||
resolvedUrl: resolvedEncounterImageSrc,
|
||||
shouldResolve: shouldResolveEncounterImage,
|
||||
} = useResolvedAssetReadUrl(rawEncounterImageSrc);
|
||||
const displayEncounterImageSrc =
|
||||
resolvedEncounterImageSrc
|
||||
|| (!shouldResolveEncounterImage ? rawEncounterImageSrc : '');
|
||||
|
||||
if (encounter.visual) {
|
||||
return (
|
||||
<MedievalNpcAnimator
|
||||
@@ -277,10 +287,14 @@ export function SceneEncounterNpcSprite({
|
||||
);
|
||||
}
|
||||
|
||||
if (encounter.imageSrc?.trim()) {
|
||||
if (rawEncounterImageSrc && shouldResolveEncounterImage && !displayEncounterImageSrc) {
|
||||
return <div className={`h-full w-full ${className ?? ''}`.trim()} />;
|
||||
}
|
||||
|
||||
if (displayEncounterImageSrc) {
|
||||
return (
|
||||
<img
|
||||
src={encounter.imageSrc.trim()}
|
||||
src={displayEncounterImageSrc}
|
||||
alt={encounter.npcName}
|
||||
className={`h-full w-full object-contain ${className ?? ''}`.trim()}
|
||||
style={{
|
||||
|
||||
Reference in New Issue
Block a user