🆙 Patch GlTextureSystem & Fix effects like BBRed

- Monkey-patch the renderer's GlTextureSystem to prevent crashes from destroyed textures
This commit is contained in:
DuckieTM
2026-02-07 19:08:39 +01:00
parent 9c43cb240e
commit 8f5a9f7188
7 changed files with 84 additions and 22 deletions
@@ -7,6 +7,7 @@ interface IWindowReflectionAvatarState
id: number;
texture: Texture;
location: IVector3D;
verticalOffset: number;
}
export class RoomWindowReflectionState
@@ -14,7 +15,7 @@ export class RoomWindowReflectionState
private static _avatars: Map<number, IWindowReflectionAvatarState> = new Map();
private static _updateId: number = 0;
public static setAvatar(id: number, texture: Texture, location: IVector3D): void
public static setAvatar(id: number, texture: Texture, location: IVector3D, verticalOffset: number = 0): void
{
if(!texture || !location) return;
@@ -25,7 +26,8 @@ export class RoomWindowReflectionState
this._avatars.set(id, {
id,
texture,
location: storedLocation
location: storedLocation,
verticalOffset
});
// Always bump updateId so reflected walk cycles stay frame-synced
@@ -76,6 +76,7 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
private _isAvatarReady: boolean;
private _needsUpdate: boolean;
private _geometryUpdateCounter: number;
private _reflectionVerticalOffset: number;
private _additions: Map<number, IAvatarAddition>;
@@ -127,6 +128,7 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
this._isAvatarReady = false;
this._needsUpdate = false;
this._geometryUpdateCounter = -1;
this._reflectionVerticalOffset = 0;
this._additions = new Map();
}
@@ -307,7 +309,7 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
sprite.offsetX = ((((-1 * scale) / 2) + _local_20[0]) - ((sprite.texture.width - scale) / 2));
sprite.offsetY = (((-(sprite.texture.height) + (scale / 4)) + _local_20[1]) + this._postureOffset);
}
if(this._isLaying)
{
if(this._layInside) sprite.relativeDepth = -0.5;
@@ -329,8 +331,6 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
}
}
this.updateWindowReflectionSource();
const typingBubble = this.getAddition(AvatarVisualization.TYPING_BUBBLE_ID) as TypingBubbleAddition;
if(typingBubble)
@@ -451,6 +451,17 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
_local_21++;
}
}
const avatarSprite = this.getSprite(AvatarVisualization.SPRITE_INDEX_AVATAR);
if(avatarSprite?.texture)
{
const baseOffsetY = (-(avatarSprite.texture.height) + (scale / 4));
this._reflectionVerticalOffset = avatarSprite.offsetY - baseOffsetY;
}
this.updateWindowReflectionSource();
}
}
@@ -1007,7 +1018,7 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
if(sprite?.texture)
{
RoomWindowReflectionState.setAvatar(this.object.id, sprite.texture, this.object.getLocation());
RoomWindowReflectionState.setAvatar(this.object.id, sprite.texture, this.object.getLocation(), this._reflectionVerticalOffset);
return;
}
@@ -91,8 +91,8 @@ export class RoomPlane implements IRoomPlane
private _windowMasks: { leftSideLoc: number; rightSideLoc: number }[] = [];
private _lastWindowReflectionUpdateId: number = -1;
private _windowReflectionFirstSeenAt: Map<number, number> = new Map();
private _windowReflectionLastVisible: Map<number, { texture: Texture; location: IVector3D }> = new Map();
private _windowReflectionFadeOut: Map<number, { texture: Texture; location: IVector3D; startedAt: number }> = new Map();
private _windowReflectionLastVisible: Map<number, { texture: Texture; location: IVector3D; verticalOffset: number }> = new Map();
private _windowReflectionFadeOut: Map<number, { texture: Texture; location: IVector3D; verticalOffset: number; startedAt: number }> = new Map();
constructor(origin: IVector3D, location: IVector3D, leftSide: IVector3D, rightSide: IVector3D, type: number, usesMask: boolean, secondaryNormals: IVector3D[], randomSeed: number, textureOffsetX: number = 0, textureOffsetY: number = 0, textureMaxX: number = 0, textureMaxY: number = 0)
{
@@ -884,8 +884,8 @@ export class RoomPlane implements IRoomPlane
const container = new Container();
const visibleAvatarIds = new Set<number>();
const addReflectionSprite = (texture: Texture, location: IVector3D, alpha: number): boolean => {
if(!texture?.source || !location || alpha < 0) return false;
const addReflectionSprite = (texture: Texture, location: IVector3D, alpha: number, verticalOffset: number = 0): boolean => {
if(!texture?.source || texture.source.destroyed || !texture.source.style || !location || alpha < 0) return false;
const relative = Vector3d.dif(location, this._location);
const planeDistance = Math.abs(Vector3d.scalarProjection(relative, this._normal));
@@ -906,7 +906,7 @@ export class RoomPlane implements IRoomPlane
if(!closestMask || (closestMask.score > 3)) return false;
const x = (canvasWidth - ((canvasWidth * leftSideLoc) / this._leftSide.length));
const y = (canvasHeight - ((canvasHeight * rightSideLoc) / this._rightSide.length));
const y = (canvasHeight - ((canvasHeight * rightSideLoc) / this._rightSide.length)) + verticalOffset;
const sprite = new Sprite(texture);
sprite.anchor.set(0.5, 1);
@@ -922,7 +922,7 @@ export class RoomPlane implements IRoomPlane
for(const avatar of avatars)
{
if(!avatar?.texture?.source || !avatar.location) continue;
if(!avatar?.texture?.source || avatar.texture.source.destroyed || !avatar.texture.source.style || !avatar.location) continue;
let firstSeenAt = this._windowReflectionFirstSeenAt.get(avatar.id);
@@ -935,7 +935,7 @@ export class RoomPlane implements IRoomPlane
const progress = (elapsed / fadeDurationMs);
const alpha = (0.4 * progress);
if(!addReflectionSprite(avatar.texture, avatar.location, alpha)) continue;
if(!addReflectionSprite(avatar.texture, avatar.location, alpha, avatar.verticalOffset || 0)) continue;
if(!this._windowReflectionFirstSeenAt.has(avatar.id)) this._windowReflectionFirstSeenAt.set(avatar.id, firstSeenAt);
@@ -947,7 +947,8 @@ export class RoomPlane implements IRoomPlane
this._windowReflectionLastVisible.set(avatar.id, {
texture: avatar.texture,
location: storedLocation
location: storedLocation,
verticalOffset: avatar.verticalOffset || 0
});
}
@@ -955,7 +956,7 @@ export class RoomPlane implements IRoomPlane
{
if(visibleAvatarIds.has(id) || this._windowReflectionFadeOut.has(id)) continue;
if(!lastVisible.texture?.source)
if(!lastVisible.texture?.source || lastVisible.texture.source.destroyed || !lastVisible.texture.source.style)
{
this._windowReflectionLastVisible.delete(id);
this._windowReflectionFirstSeenAt.delete(id);
@@ -966,6 +967,7 @@ export class RoomPlane implements IRoomPlane
this._windowReflectionFadeOut.set(id, {
texture: lastVisible.texture,
location: lastVisible.location,
verticalOffset: lastVisible.verticalOffset,
startedAt: now
});
@@ -986,7 +988,7 @@ export class RoomPlane implements IRoomPlane
const alpha = (0.4 * (1 - (elapsed / fadeDurationMs)));
if(!addReflectionSprite(fadeOut.texture, fadeOut.location, alpha)) this._windowReflectionFadeOut.delete(id);
if(!addReflectionSprite(fadeOut.texture, fadeOut.location, alpha, fadeOut.verticalOffset)) this._windowReflectionFadeOut.delete(id);
}
if(!container.children.length)
@@ -409,7 +409,7 @@ export class RoomSpriteCanvas implements IRoomRenderingCanvas
const texture = sprite.texture;
const baseTexture = texture && texture.source;
if(!texture || !baseTexture || baseTexture.destroyed) continue;
if(!texture || !baseTexture) continue;
const spriteX = ((x + sprite.offsetX) + this._screenOffsetX);
const spriteY = ((y + sprite.offsetY) + this._screenOffsetY);
@@ -29,7 +29,7 @@ export class ExtendedSprite extends Sprite
public setTexture(texture: Texture): void
{
if(!texture || texture.source?.destroyed) texture = Texture.EMPTY;
if(!texture) texture = Texture.EMPTY;
if(texture === this.texture) return;