Merge branch 'duckietm:main' into main

This commit is contained in:
Lorenzune
2026-03-18 17:20:08 +01:00
committed by GitHub
4 changed files with 65 additions and 10 deletions
+1 -1
View File
@@ -35,7 +35,7 @@
"howler": "^2.2.4", "howler": "^2.2.4",
"pako": "^2.1.0", "pako": "^2.1.0",
"pixi-filters": "^6.1.5", "pixi-filters": "^6.1.5",
"pixi.js": "^8.16.0" "pixi.js": "^8.17.1"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.13.0", "@eslint/js": "^9.13.0",
@@ -3,7 +3,7 @@ import { GetAssetManager } from '@nitrots/assets';
import { GetConfiguration } from '@nitrots/configuration'; import { GetConfiguration } from '@nitrots/configuration';
import { GetEventDispatcher, RoomCameraWidgetManagerEvent } from '@nitrots/events'; import { GetEventDispatcher, RoomCameraWidgetManagerEvent } from '@nitrots/events';
import { TextureUtils } from '@nitrots/utils'; import { TextureUtils } from '@nitrots/utils';
import { BLEND_MODES, ColorMatrix, ColorMatrixFilter, Container, Filter, Sprite, Texture } from 'pixi.js'; import { BLEND_MODES, ColorMatrix, ColorMatrixFilter, Container, Filter, RenderTexture, Sprite, Texture } from 'pixi.js';
import { RoomCameraWidgetEffect } from './RoomCameraWidgetEffect'; import { RoomCameraWidgetEffect } from './RoomCameraWidgetEffect';
const COLOR_MATRIX_OFFSET_INDICES = [4, 9, 14, 19] as const; const COLOR_MATRIX_OFFSET_INDICES = [4, 9, 14, 19] as const;
@@ -112,7 +112,12 @@ export class RoomCameraWidgetManager implements IRoomCameraWidgetManager
container.filters = filters; container.filters = filters;
return await TextureUtils.generateImage(container); const resolution = texture.source.resolution || 1;
const renderTexture = RenderTexture.create({ width: texture.width, height: texture.height, resolution });
TextureUtils.writeToTexture(container, renderTexture);
return await TextureUtils.generateImage(renderTexture);
} }
public get effects(): Map<string, IRoomCameraWidgetEffect> public get effects(): Map<string, IRoomCameraWidgetEffect>
@@ -1,7 +1,10 @@
import { IMessageComposer } from '@nitrots/api'; import { IMessageComposer } from '@nitrots/api';
import { TextureUtils } from '@nitrots/utils'; import { NitroLogger, TextureUtils } from '@nitrots/utils';
import { RenderTexture } from 'pixi.js'; import { RenderTexture } from 'pixi.js';
const MAX_IMAGE_BYTES = 2 * 1024 * 1024;
const PNG_MAGIC_BYTES = [0x89, 0x50, 0x4E, 0x47];
export class RenderRoomMessageComposer implements IMessageComposer<ConstructorParameters<typeof RenderRoomMessageComposer>> export class RenderRoomMessageComposer implements IMessageComposer<ConstructorParameters<typeof RenderRoomMessageComposer>>
{ {
private _data: any; private _data: any;
@@ -27,16 +30,63 @@ export class RenderRoomMessageComposer implements IMessageComposer<ConstructorPa
if(!url) return; if(!url) return;
const base64Data = url.split(',')[1]; this.processBase64(url);
const binaryData = Uint8Array.from(atob(base64Data), c => c.charCodeAt(0));
this._data.push(binaryData.byteLength, binaryData.buffer);
} }
public assignBase64(base64: string): void public assignBase64(base64: string): void
{ {
this.processBase64(base64);
}
private processBase64(base64: string): void
{
if(!base64 || !base64.includes(','))
{
NitroLogger.error('Camera: invalid base64 data URL');
return;
}
if(!base64.startsWith('data:image/png'))
{
NitroLogger.error('Camera: rejected non-PNG image data');
return;
}
const base64Data = base64.split(',')[1]; const base64Data = base64.split(',')[1];
const binaryData = Uint8Array.from(atob(base64Data), c => c.charCodeAt(0));
if(!base64Data || !base64Data.length)
{
NitroLogger.error('Camera: empty base64 payload');
return;
}
let binaryData: Uint8Array;
try
{
binaryData = Uint8Array.from(atob(base64Data), c => c.charCodeAt(0));
}
catch(e)
{
NitroLogger.error('Camera: failed to decode base64 data');
return;
}
if(binaryData.byteLength > MAX_IMAGE_BYTES)
{
NitroLogger.error(`Camera: image too large (${binaryData.byteLength} bytes, max ${MAX_IMAGE_BYTES})`);
return;
}
if(binaryData.length < 4
|| binaryData[0] !== PNG_MAGIC_BYTES[0]
|| binaryData[1] !== PNG_MAGIC_BYTES[1]
|| binaryData[2] !== PNG_MAGIC_BYTES[2]
|| binaryData[3] !== PNG_MAGIC_BYTES[3])
{
NitroLogger.error('Camera: binary data does not have valid PNG header');
return;
}
this._data.push(binaryData.byteLength, binaryData.buffer); this._data.push(binaryData.byteLength, binaryData.buffer);
} }
@@ -30,7 +30,7 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
private static BASE_Y_SCALE: number = 1000; private static BASE_Y_SCALE: number = 1000;
private static AVATAR_SPRITE_DEFAULT_DEPTH: number = -0.01; private static AVATAR_SPRITE_DEFAULT_DEPTH: number = -0.01;
private static AVATAR_OWN_DEPTH_ADJUST: number = 0.001; private static AVATAR_OWN_DEPTH_ADJUST: number = 0.001;
private static AVATAR_SPRITE_LAYING_DEPTH: number = 0.2; private static AVATAR_SPRITE_LAYING_DEPTH: number = 0.002;
protected _data: AvatarVisualizationData; protected _data: AvatarVisualizationData;