fix(textures): DecodeSolidColor null-safe against null ColorValue
A Base1Solid (or OrigTextureId==0) Surface can carry a null ColorValue; DecodeSolidColor dereferenced it (color.Alpha) and threw NullReferenceException. It is called directly from TextureCache.DecodeFromDats, OUTSIDE DecodeRenderSurface's try/catch, so the NRE crashed the whole client. Surfaced by the D.2b chrome prove-out feeding UI surface ids. Guard null -> Magenta (the decoder's existing "undecodable" sentinel). Test added. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c9eef1d7cd
commit
66888d2c8e
2 changed files with 22 additions and 0 deletions
|
|
@ -80,6 +80,11 @@ public static class SurfaceDecoder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static DecodedTexture DecodeSolidColor(DatReaderWriter.Types.ColorARGB color, float translucency)
|
public static DecodedTexture DecodeSolidColor(DatReaderWriter.Types.ColorARGB color, float translucency)
|
||||||
{
|
{
|
||||||
|
// Malformed Base1Solid (or OrigTextureId==0) surface with no color value:
|
||||||
|
// signal undecodable (Magenta) instead of NRE. This method is called
|
||||||
|
// directly from TextureCache.DecodeFromDats, OUTSIDE DecodeRenderSurface's
|
||||||
|
// try/catch, so it must be null-safe itself.
|
||||||
|
if (color is null) return DecodedTexture.Magenta;
|
||||||
float opacity = Math.Clamp(1f - translucency, 0f, 1f);
|
float opacity = Math.Clamp(1f - translucency, 0f, 1f);
|
||||||
byte alpha = (byte)Math.Clamp(color.Alpha * opacity, 0f, 255f);
|
byte alpha = (byte)Math.Clamp(color.Alpha * opacity, 0f, 255f);
|
||||||
return new DecodedTexture(
|
return new DecodedTexture(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
using AcDream.Core.Textures;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AcDream.Core.Tests.Textures;
|
||||||
|
|
||||||
|
public class SurfaceDecoderSolidColorTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void DecodeSolidColor_NullColor_ReturnsMagenta_DoesNotThrow()
|
||||||
|
{
|
||||||
|
// A malformed Base1Solid surface can carry a null ColorValue. DecodeSolidColor
|
||||||
|
// is called outside DecodeRenderSurface's try/catch (from TextureCache), so it
|
||||||
|
// must be null-safe itself — return the undecodable sentinel, never NRE.
|
||||||
|
var result = SurfaceDecoder.DecodeSolidColor(null!, 0f);
|
||||||
|
Assert.Equal(DecodedTexture.Magenta, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue