Merge pull request #39 from duckietm/Dev

Dev
This commit is contained in:
DuckieTM
2026-03-31 16:03:51 +02:00
committed by GitHub
30 changed files with 718 additions and 265 deletions
+3 -3
View File
@@ -24,9 +24,9 @@ export interface IRoomCreator
getRoomObjectUser(roomId: number, objectId: number): IRoomObjectController; getRoomObjectUser(roomId: number, objectId: number): IRoomObjectController;
removeRoomObjectUser(roomId: number, objectId: number): void; removeRoomObjectUser(roomId: number, objectId: number): void;
getRoomObjectFloor(roomId: number, objectId: number): IRoomObjectController; getRoomObjectFloor(roomId: number, objectId: number): IRoomObjectController;
addFurnitureFloor(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra?: number, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, synchronized?: boolean, realRoomObject?: boolean, sizeZ?: number): boolean; addFurnitureFloor(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra?: number, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, synchronized?: boolean, realRoomObject?: boolean, sizeZ?: number, allowStack?: boolean, allowSit?: boolean, allowLay?: boolean, allowWalk?: boolean, dimensionsX?: number, dimensionsY?: number, teleportTargetId?: number): boolean;
addFurnitureFloorByTypeName(roomId: number, id: number, typeName: string, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra?: number, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, synchronized?: boolean, realRoomObject?: boolean, sizeZ?: number): boolean; addFurnitureFloorByTypeName(roomId: number, id: number, typeName: string, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra?: number, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, synchronized?: boolean, realRoomObject?: boolean, sizeZ?: number, allowStack?: boolean, allowSit?: boolean, allowLay?: boolean, allowWalk?: boolean, dimensionsX?: number, dimensionsY?: number, teleportTargetId?: number): boolean;
addFurnitureWall(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, extra: string, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, realRoomObject?: boolean): boolean; addFurnitureWall(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, extra: string, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, realRoomObject?: boolean, allowStack?: boolean, allowSit?: boolean, allowLay?: boolean, allowWalk?: boolean, dimensionsX?: number, dimensionsY?: number, teleportTargetId?: number): boolean;
removeRoomObjectFloor(roomId: number, objectId: number, userId?: number, _arg_4?: boolean): void; removeRoomObjectFloor(roomId: number, objectId: number, userId?: number, _arg_4?: boolean): void;
removeRoomObjectWall(roomId: number, objectId: number, userId?: number): void; removeRoomObjectWall(roomId: number, objectId: number, userId?: number): void;
updateRoomObjectFloor(roomId: number, objectId: number, location: IVector3D, direction: IVector3D, state: number, data: IObjectData, extra?: number): boolean; updateRoomObjectFloor(roomId: number, objectId: number, location: IVector3D, direction: IVector3D, state: number, data: IObjectData, extra?: number): boolean;
+3 -3
View File
@@ -46,9 +46,9 @@ export interface IRoomEngine
updateRoomObjectWallLocation(roomId: number, objectId: number, location: IVector3D): boolean; updateRoomObjectWallLocation(roomId: number, objectId: number, location: IVector3D): boolean;
addRoomObjectUser(roomId: number, objectId: number, location: IVector3D, direction: IVector3D, headDirection: number, type: number, figure: string): boolean; addRoomObjectUser(roomId: number, objectId: number, location: IVector3D, direction: IVector3D, headDirection: number, type: number, figure: string): boolean;
updateRoomObjectUserLocation(roomId: number, objectId: number, location: IVector3D, targetLocation: IVector3D, canStandUp?: boolean, baseY?: number, direction?: IVector3D, headDirection?: number, skipLocationFix?: boolean, isSlide?: boolean, duration?: number): boolean; updateRoomObjectUserLocation(roomId: number, objectId: number, location: IVector3D, targetLocation: IVector3D, canStandUp?: boolean, baseY?: number, direction?: IVector3D, headDirection?: number, skipLocationFix?: boolean, isSlide?: boolean, duration?: number): boolean;
addFurnitureFloor(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra?: number, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, synchronized?: boolean, realRoomObject?: boolean, sizeZ?: number): boolean; addFurnitureFloor(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra?: number, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, synchronized?: boolean, realRoomObject?: boolean, sizeZ?: number, allowStack?: boolean, allowSit?: boolean, allowLay?: boolean, allowWalk?: boolean, dimensionsX?: number, dimensionsY?: number, teleportTargetId?: number): boolean;
addFurnitureFloorByTypeName(roomId: number, id: number, typeName: string, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra?: number, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, synchronized?: boolean, realRoomObject?: boolean, sizeZ?: number): boolean; addFurnitureFloorByTypeName(roomId: number, id: number, typeName: string, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra?: number, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, synchronized?: boolean, realRoomObject?: boolean, sizeZ?: number, allowStack?: boolean, allowSit?: boolean, allowLay?: boolean, allowWalk?: boolean, dimensionsX?: number, dimensionsY?: number, teleportTargetId?: number): boolean;
addFurnitureWall(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, extra: string, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, realRoomObject?: boolean): boolean; addFurnitureWall(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, extra: string, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, realRoomObject?: boolean, allowStack?: boolean, allowSit?: boolean, allowLay?: boolean, allowWalk?: boolean, dimensionsX?: number, dimensionsY?: number, teleportTargetId?: number): boolean;
initalizeTemporaryObjectsByType(type: string, _arg_2: boolean): void; initalizeTemporaryObjectsByType(type: string, _arg_2: boolean): void;
updateRoomObjectFloor(roomId: number, objectId: number, location: IVector3D, direction: IVector3D, state: number, data: IObjectData, extra?: number): boolean; updateRoomObjectFloor(roomId: number, objectId: number, location: IVector3D, direction: IVector3D, state: number, data: IObjectData, extra?: number): boolean;
updateRoomObjectWall(roomId: number, objectId: number, location: IVector3D, direction: IVector3D, state: number, extra?: string): boolean; updateRoomObjectWall(roomId: number, objectId: number, location: IVector3D, direction: IVector3D, state: number, extra?: string): boolean;
@@ -22,9 +22,9 @@ export interface IRoomEngineServices
getRoomObjectCursor(roomId: number): IRoomObjectController; getRoomObjectCursor(roomId: number): IRoomObjectController;
getRoomObjectSelectionArrow(roomId: number): IRoomObjectController; getRoomObjectSelectionArrow(roomId: number): IRoomObjectController;
addRoomObjectUser(roomId: number, objectId: number, location: IVector3D, direction: IVector3D, headDirection: number, type: number, figure: string): boolean; addRoomObjectUser(roomId: number, objectId: number, location: IVector3D, direction: IVector3D, headDirection: number, type: number, figure: string): boolean;
addFurnitureFloor(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra?: number, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, synchronized?: boolean, realRoomObject?: boolean, sizeZ?: number): boolean; addFurnitureFloor(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra?: number, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, synchronized?: boolean, realRoomObject?: boolean, sizeZ?: number, allowStack?: boolean, allowSit?: boolean, allowLay?: boolean, allowWalk?: boolean, dimensionsX?: number, dimensionsY?: number, teleportTargetId?: number): boolean;
addFurnitureFloorByTypeName(roomId: number, id: number, typeName: string, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra?: number, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, synchronized?: boolean, realRoomObject?: boolean, sizeZ?: number): boolean; addFurnitureFloorByTypeName(roomId: number, id: number, typeName: string, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra?: number, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, synchronized?: boolean, realRoomObject?: boolean, sizeZ?: number, allowStack?: boolean, allowSit?: boolean, allowLay?: boolean, allowWalk?: boolean, dimensionsX?: number, dimensionsY?: number, teleportTargetId?: number): boolean;
addFurnitureWall(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, extra: string, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, realRoomObject?: boolean): boolean; addFurnitureWall(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, extra: string, expires?: number, usagePolicy?: number, ownerId?: number, ownerName?: string, realRoomObject?: boolean, allowStack?: boolean, allowSit?: boolean, allowLay?: boolean, allowWalk?: boolean, dimensionsX?: number, dimensionsY?: number, teleportTargetId?: number): boolean;
removeRoomObjectFloor(roomId: number, objectId: number, userId?: number, _arg_4?: boolean): void; removeRoomObjectFloor(roomId: number, objectId: number, userId?: number, _arg_4?: boolean): void;
removeRoomObjectWall(roomId: number, objectId: number, userId?: number): void; removeRoomObjectWall(roomId: number, objectId: number, userId?: number): void;
removeRoomObjectUser(roomId: number, objectId: number): void; removeRoomObjectUser(roomId: number, objectId: number): void;
@@ -83,6 +83,13 @@ export class RoomObjectVariable
public static FURNITURE_USAGE_POLICY: string = 'furniture_usage_policy'; public static FURNITURE_USAGE_POLICY: string = 'furniture_usage_policy';
public static FURNITURE_OWNER_ID: string = 'furniture_owner_id'; public static FURNITURE_OWNER_ID: string = 'furniture_owner_id';
public static FURNITURE_OWNER_NAME: string = 'furniture_owner_name'; public static FURNITURE_OWNER_NAME: string = 'furniture_owner_name';
public static FURNITURE_ALLOW_STACK: string = 'furniture_allow_stack';
public static FURNITURE_ALLOW_SIT: string = 'furniture_allow_sit';
public static FURNITURE_ALLOW_LAY: string = 'furniture_allow_lay';
public static FURNITURE_ALLOW_WALK: string = 'furniture_allow_walk';
public static FURNITURE_DIMENSIONS_X: string = 'furniture_dimensions_x';
public static FURNITURE_DIMENSIONS_Y: string = 'furniture_dimensions_y';
public static FURNITURE_TELEPORT_TARGET_ID: string = 'furniture_teleport_target_id';
public static FURNITURE_ROOM_BACKGROUND_COLOR_HUE: string = 'furniture_room_background_color_hue'; public static FURNITURE_ROOM_BACKGROUND_COLOR_HUE: string = 'furniture_room_background_color_hue';
public static FURNITURE_ROOM_BACKGROUND_COLOR_SATURATION: string = 'furniture_room_background_color_saturation'; public static FURNITURE_ROOM_BACKGROUND_COLOR_SATURATION: string = 'furniture_room_background_color_saturation';
public static FURNITURE_ROOM_BACKGROUND_COLOR_LIGHTNESS: string = 'furniture_room_background_color_lightness'; public static FURNITURE_ROOM_BACKGROUND_COLOR_LIGHTNESS: string = 'furniture_room_background_color_lightness';
@@ -24,6 +24,7 @@ export interface IFurnitureData
purchaseCouldBeUsedForBuyout: boolean; purchaseCouldBeUsedForBuyout: boolean;
rentCouldBeUsedForBuyout: boolean; rentCouldBeUsedForBuyout: boolean;
availableForBuildersClub: boolean; availableForBuildersClub: boolean;
allowStack: boolean;
canStandOn: boolean; canStandOn: boolean;
canSitOn: boolean; canSitOn: boolean;
canLayOn: boolean; canLayOn: boolean;
@@ -57,6 +57,11 @@ export interface IRoomSession
allowPets: boolean; allowPets: boolean;
controllerLevel: number; controllerLevel: number;
ownRoomIndex: number; ownRoomIndex: number;
groupId: number;
hotelTimeZone: string;
hotelTimeSnapshotMs: number;
hotelTimeSyncMs: number;
roomItemLimit: number;
isGuildRoom: boolean; isGuildRoom: boolean;
isRoomOwner: boolean; isRoomOwner: boolean;
isDecorating: boolean; isDecorating: boolean;
@@ -23,4 +23,6 @@ export interface IRoomUserData
petLevel: number; petLevel: number;
botSkills: number[]; botSkills: number[];
isModerator: boolean; isModerator: boolean;
roomEntryMethod: string;
roomEntryTeleportId: number;
} }
+2
View File
@@ -285,6 +285,8 @@ export class AvatarImage implements IAvatarImage, IAvatarEffectListener
const container = this.buildAvatarContainer(avatarCanvas, setType); const container = this.buildAvatarContainer(avatarCanvas, setType);
if(!container) return null;
GetRenderer().render({ GetRenderer().render({
target: this._activeTexture, target: this._activeTexture,
container: container, container: container,
@@ -117,7 +117,12 @@ export class RoomCameraWidgetManager implements IRoomCameraWidgetManager
TextureUtils.writeToTexture(container, renderTexture); TextureUtils.writeToTexture(container, renderTexture);
return await TextureUtils.generateImage(renderTexture); const image = await TextureUtils.generateImage(renderTexture);
container.destroy({ children: true });
renderTexture.destroy(true);
return image;
} }
public get effects(): Map<string, IRoomCameraWidgetEffect> public get effects(): Map<string, IRoomCameraWidgetEffect>
@@ -62,7 +62,8 @@ export class CommunicationManager implements ICommunicationManager
t.shadowColor = 'blue'; t.shadowColor = 'blue';
t.fillRect(-20, 10, 234, 5); t.fillRect(-20, 10, 234, 5);
const i = e.toDataURL(); const i = e.toDataURL();
document.body.appendChild(e); e.width = 0;
e.height = 0;
let r = 0; let r = 0;
if (i.length === 0) return 'nothing!'; if (i.length === 0) return 'nothing!';
for (let n = 0; n < i.length; n++) { for (let n = 0; n < i.length; n++) {
@@ -11,6 +11,9 @@ export class GetGuestRoomResultMessageParser implements IMessageParser
private _isGroupMember: boolean; private _isGroupMember: boolean;
private _moderation: RoomModerationSettings; private _moderation: RoomModerationSettings;
private _chat: RoomChatSettings; private _chat: RoomChatSettings;
private _hotelTimeZoneId: string;
private _hotelCurrentTimeMs: number;
private _roomItemLimit: number;
public flush(): boolean public flush(): boolean
{ {
@@ -21,6 +24,9 @@ export class GetGuestRoomResultMessageParser implements IMessageParser
this._isGroupMember = false; this._isGroupMember = false;
this._moderation = null; this._moderation = null;
this._chat = null; this._chat = null;
this._hotelTimeZoneId = null;
this._hotelCurrentTimeMs = 0;
this._roomItemLimit = 0;
return true; return true;
} }
@@ -39,6 +45,13 @@ export class GetGuestRoomResultMessageParser implements IMessageParser
this.data.canMute = wrapper.readBoolean(); this.data.canMute = wrapper.readBoolean();
this._chat = new RoomChatSettings(wrapper); this._chat = new RoomChatSettings(wrapper);
if(wrapper.bytesAvailable)
{
this._hotelTimeZoneId = wrapper.readString();
this._hotelCurrentTimeMs = Number(wrapper.readString()) || 0;
if(wrapper.bytesAvailable) this._roomItemLimit = wrapper.readInt();
}
return true; return true;
} }
@@ -76,4 +89,19 @@ export class GetGuestRoomResultMessageParser implements IMessageParser
{ {
return this._chat; return this._chat;
} }
public get hotelTimeZoneId(): string
{
return this._hotelTimeZoneId;
}
public get hotelCurrentTimeMs(): number
{
return this._hotelCurrentTimeMs;
}
public get roomItemLimit(): number
{
return this._roomItemLimit;
}
} }
@@ -25,6 +25,13 @@ export class FurnitureFloorDataParser
private _usagePolicy: number; private _usagePolicy: number;
private _userId: number; private _userId: number;
private _username: string; private _username: string;
private _allowStack: boolean;
private _allowSit: boolean;
private _allowLay: boolean;
private _allowWalk: boolean;
private _dimensionsX: number;
private _dimensionsY: number;
private _teleportTargetId: number;
constructor(wrapper: IMessageDataWrapper) constructor(wrapper: IMessageDataWrapper)
{ {
@@ -51,6 +58,13 @@ export class FurnitureFloorDataParser
this._usagePolicy = 0; this._usagePolicy = 0;
this._userId = 0; this._userId = 0;
this._username = null; this._username = null;
this._allowStack = false;
this._allowSit = false;
this._allowLay = false;
this._allowWalk = false;
this._dimensionsX = 0;
this._dimensionsY = 0;
this._teleportTargetId = 0;
return true; return true;
} }
@@ -72,6 +86,13 @@ export class FurnitureFloorDataParser
this._expires = wrapper.readInt(); this._expires = wrapper.readInt();
this._usagePolicy = wrapper.readInt(); this._usagePolicy = wrapper.readInt();
this._userId = wrapper.readInt(); this._userId = wrapper.readInt();
this._allowStack = (wrapper.readInt() === 1);
this._allowSit = (wrapper.readInt() === 1);
this._allowLay = (wrapper.readInt() === 1);
this._allowWalk = (wrapper.readInt() === 1);
this._dimensionsX = wrapper.readInt();
this._dimensionsY = wrapper.readInt();
this._teleportTargetId = wrapper.readInt();
this._username = null; this._username = null;
if(this._spriteId < 0) this._spriteName = wrapper.readString(); if(this._spriteId < 0) this._spriteName = wrapper.readString();
@@ -149,6 +170,41 @@ export class FurnitureFloorDataParser
return this._username; return this._username;
} }
public get allowStack(): boolean
{
return this._allowStack;
}
public get allowSit(): boolean
{
return this._allowSit;
}
public get allowLay(): boolean
{
return this._allowLay;
}
public get allowWalk(): boolean
{
return this._allowWalk;
}
public get dimensionsX(): number
{
return this._dimensionsX;
}
public get dimensionsY(): number
{
return this._dimensionsY;
}
public get teleportTargetId(): number
{
return this._teleportTargetId;
}
public set username(username: string) public set username(username: string)
{ {
this._username = username; this._username = username;
@@ -11,6 +11,13 @@ export class FurnitureWallDataParser
private _usagePolicy: number; private _usagePolicy: number;
private _userId: number; private _userId: number;
private _username: string; private _username: string;
private _allowStack: boolean;
private _allowSit: boolean;
private _allowLay: boolean;
private _allowWalk: boolean;
private _dimensionsX: number;
private _dimensionsY: number;
private _teleportTargetId: number;
private _width: number; private _width: number;
private _height: number; private _height: number;
@@ -40,6 +47,13 @@ export class FurnitureWallDataParser
this._usagePolicy = -1; this._usagePolicy = -1;
this._userId = 0; this._userId = 0;
this._username = null; this._username = null;
this._allowStack = false;
this._allowSit = false;
this._allowLay = false;
this._allowWalk = false;
this._dimensionsX = 0;
this._dimensionsY = 0;
this._teleportTargetId = 0;
this._width = 0; this._width = 0;
this._height = 0; this._height = 0;
@@ -64,6 +78,13 @@ export class FurnitureWallDataParser
this._secondsToExpiration = wrapper.readInt(); this._secondsToExpiration = wrapper.readInt();
this._usagePolicy = wrapper.readInt(); this._usagePolicy = wrapper.readInt();
this._userId = wrapper.readInt(); this._userId = wrapper.readInt();
this._allowStack = (wrapper.readInt() === 1);
this._allowSit = (wrapper.readInt() === 1);
this._allowLay = (wrapper.readInt() === 1);
this._allowWalk = (wrapper.readInt() === 1);
this._dimensionsX = wrapper.readInt();
this._dimensionsY = wrapper.readInt();
this._teleportTargetId = wrapper.readInt();
this._username = null; this._username = null;
const state = parseFloat(this._stuffData); const state = parseFloat(this._stuffData);
@@ -191,6 +212,41 @@ export class FurnitureWallDataParser
return this._username; return this._username;
} }
public get allowStack(): boolean
{
return this._allowStack;
}
public get allowSit(): boolean
{
return this._allowSit;
}
public get allowLay(): boolean
{
return this._allowLay;
}
public get allowWalk(): boolean
{
return this._allowWalk;
}
public get dimensionsX(): number
{
return this._dimensionsX;
}
public get dimensionsY(): number
{
return this._dimensionsY;
}
public get teleportTargetId(): number
{
return this._teleportTargetId;
}
public set username(username: string) public set username(username: string)
{ {
this._username = username; this._username = username;
@@ -135,6 +135,9 @@ export class RoomUnitParser implements IMessageParser
} }
} }
user.roomEntryMethod = wrapper.readString();
user.roomEntryTeleportId = wrapper.readInt();
i++; i++;
} }
@@ -35,6 +35,8 @@ export class UserMessageData
private _petPosture: string = ''; private _petPosture: string = '';
private _botSkills: number[] = []; private _botSkills: number[] = [];
private _isModerator: boolean = false; private _isModerator: boolean = false;
private _roomEntryMethod: string = 'unknown';
private _roomEntryTeleportId: number = 0;
private _isReadOnly: boolean = false; private _isReadOnly: boolean = false;
constructor(k: number) constructor(k: number)
@@ -442,4 +444,30 @@ export class UserMessageData
this._isModerator = k; this._isModerator = k;
} }
} }
public get roomEntryMethod(): string
{
return this._roomEntryMethod;
}
public set roomEntryMethod(k: string)
{
if(!this._isReadOnly)
{
this._roomEntryMethod = k;
}
}
public get roomEntryTeleportId(): number
{
return this._roomEntryTeleportId;
}
public set roomEntryTeleportId(k: number)
{
if(!this._isReadOnly)
{
this._roomEntryTeleportId = k;
}
}
} }
+20 -6
View File
@@ -819,6 +819,13 @@ export class RoomEngine implements IRoomEngine, IRoomCreator, IRoomEngineService
model.setValue(RoomObjectVariable.FURNITURE_USAGE_POLICY, data.usagePolicy); model.setValue(RoomObjectVariable.FURNITURE_USAGE_POLICY, data.usagePolicy);
model.setValue(RoomObjectVariable.FURNITURE_OWNER_ID, data.ownerId); model.setValue(RoomObjectVariable.FURNITURE_OWNER_ID, data.ownerId);
model.setValue(RoomObjectVariable.FURNITURE_OWNER_NAME, data.ownerName); model.setValue(RoomObjectVariable.FURNITURE_OWNER_NAME, data.ownerName);
model.setValue(RoomObjectVariable.FURNITURE_ALLOW_STACK, data.allowStack ? 1 : 0);
model.setValue(RoomObjectVariable.FURNITURE_ALLOW_SIT, data.allowSit ? 1 : 0);
model.setValue(RoomObjectVariable.FURNITURE_ALLOW_LAY, data.allowLay ? 1 : 0);
model.setValue(RoomObjectVariable.FURNITURE_ALLOW_WALK, data.allowWalk ? 1 : 0);
model.setValue(RoomObjectVariable.FURNITURE_DIMENSIONS_X, data.dimensionsX);
model.setValue(RoomObjectVariable.FURNITURE_DIMENSIONS_Y, data.dimensionsY);
model.setValue(RoomObjectVariable.FURNITURE_TELEPORT_TARGET_ID, data.teleportTargetId);
} }
if(!this.updateRoomObjectFloor(roomId, id, data.location, data.direction, data.state, data.data, data.extra)) return false; if(!this.updateRoomObjectFloor(roomId, id, data.location, data.direction, data.state, data.data, data.extra)) return false;
@@ -879,6 +886,13 @@ export class RoomEngine implements IRoomEngine, IRoomCreator, IRoomEngineService
model.setValue(RoomObjectVariable.FURNITURE_USAGE_POLICY, data.usagePolicy); model.setValue(RoomObjectVariable.FURNITURE_USAGE_POLICY, data.usagePolicy);
model.setValue(RoomObjectVariable.FURNITURE_OWNER_ID, data.ownerId); model.setValue(RoomObjectVariable.FURNITURE_OWNER_ID, data.ownerId);
model.setValue(RoomObjectVariable.FURNITURE_OWNER_NAME, data.ownerName); model.setValue(RoomObjectVariable.FURNITURE_OWNER_NAME, data.ownerName);
model.setValue(RoomObjectVariable.FURNITURE_ALLOW_STACK, data.allowStack ? 1 : 0);
model.setValue(RoomObjectVariable.FURNITURE_ALLOW_SIT, data.allowSit ? 1 : 0);
model.setValue(RoomObjectVariable.FURNITURE_ALLOW_LAY, data.allowLay ? 1 : 0);
model.setValue(RoomObjectVariable.FURNITURE_ALLOW_WALK, data.allowWalk ? 1 : 0);
model.setValue(RoomObjectVariable.FURNITURE_DIMENSIONS_X, data.dimensionsX);
model.setValue(RoomObjectVariable.FURNITURE_DIMENSIONS_Y, data.dimensionsY);
model.setValue(RoomObjectVariable.FURNITURE_TELEPORT_TARGET_ID, data.teleportTargetId);
} }
if(!this.updateRoomObjectWall(roomId, id, data.location, data.direction, data.state, extra)) return false; if(!this.updateRoomObjectWall(roomId, id, data.location, data.direction, data.state, extra)) return false;
@@ -1667,33 +1681,33 @@ export class RoomEngine implements IRoomEngine, IRoomCreator, IRoomEngineService
if(GetEventDispatcher()) GetEventDispatcher().dispatchEvent(new RoomEngineObjectEvent(RoomEngineObjectEvent.REMOVED, roomId, objectId, category)); if(GetEventDispatcher()) GetEventDispatcher().dispatchEvent(new RoomEngineObjectEvent(RoomEngineObjectEvent.REMOVED, roomId, objectId, category));
} }
public addFurnitureFloor(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra: number = NaN, expires: number = -1, usagePolicy: number = 0, ownerId: number = 0, ownerName: string = '', synchronized: boolean = true, realRoomObject: boolean = true, sizeZ: number = -1): boolean public addFurnitureFloor(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra: number = NaN, expires: number = -1, usagePolicy: number = 0, ownerId: number = 0, ownerName: string = '', synchronized: boolean = true, realRoomObject: boolean = true, sizeZ: number = -1, allowStack: boolean = false, allowSit: boolean = false, allowLay: boolean = false, allowWalk: boolean = false, dimensionsX: number = 0, dimensionsY: number = 0, teleportTargetId: number = 0): boolean
{ {
const instanceData = this.getRoomInstanceData(roomId); const instanceData = this.getRoomInstanceData(roomId);
if(!instanceData) return false; if(!instanceData) return false;
const furnitureData = new RoomFurnitureData(id, typeId, null, location, direction, state, objectData, extra, expires, usagePolicy, ownerId, ownerName, synchronized, realRoomObject, sizeZ); const furnitureData = new RoomFurnitureData(id, typeId, null, location, direction, state, objectData, extra, expires, usagePolicy, ownerId, ownerName, synchronized, realRoomObject, sizeZ, allowStack, allowSit, allowLay, allowWalk, dimensionsX, dimensionsY, teleportTargetId);
instanceData.addPendingFurnitureFloor(furnitureData); instanceData.addPendingFurnitureFloor(furnitureData);
return true; return true;
} }
public addFurnitureFloorByTypeName(roomId: number, id: number, typeName: string, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra: number = NaN, expires: number = -1, usagePolicy: number = 0, ownerId: number = 0, ownerName: string = '', synchronized: boolean = true, realRoomObject: boolean = true, sizeZ: number = -1): boolean public addFurnitureFloorByTypeName(roomId: number, id: number, typeName: string, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra: number = NaN, expires: number = -1, usagePolicy: number = 0, ownerId: number = 0, ownerName: string = '', synchronized: boolean = true, realRoomObject: boolean = true, sizeZ: number = -1, allowStack: boolean = false, allowSit: boolean = false, allowLay: boolean = false, allowWalk: boolean = false, dimensionsX: number = 0, dimensionsY: number = 0, teleportTargetId: number = 0): boolean
{ {
const instanceData = this.getRoomInstanceData(roomId); const instanceData = this.getRoomInstanceData(roomId);
if(!instanceData) return false; if(!instanceData) return false;
const furnitureData = new RoomFurnitureData(id, 0, typeName, location, direction, state, objectData, extra, expires, usagePolicy, ownerId, ownerName, synchronized, realRoomObject, sizeZ); const furnitureData = new RoomFurnitureData(id, 0, typeName, location, direction, state, objectData, extra, expires, usagePolicy, ownerId, ownerName, synchronized, realRoomObject, sizeZ, allowStack, allowSit, allowLay, allowWalk, dimensionsX, dimensionsY, teleportTargetId);
instanceData.addPendingFurnitureFloor(furnitureData); instanceData.addPendingFurnitureFloor(furnitureData);
return true; return true;
} }
public addFurnitureWall(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, extra: string, expires: number = -1, usagePolicy: number = 0, ownerId: number = 0, ownerName: string = '', realRoomObject: boolean = true): boolean public addFurnitureWall(roomId: number, id: number, typeId: number, location: IVector3D, direction: IVector3D, state: number, extra: string, expires: number = -1, usagePolicy: number = 0, ownerId: number = 0, ownerName: string = '', realRoomObject: boolean = true, allowStack: boolean = false, allowSit: boolean = false, allowLay: boolean = false, allowWalk: boolean = false, dimensionsX: number = 0, dimensionsY: number = 0, teleportTargetId: number = 0): boolean
{ {
const instanceData = this.getRoomInstanceData(roomId); const instanceData = this.getRoomInstanceData(roomId);
@@ -1703,7 +1717,7 @@ export class RoomEngine implements IRoomEngine, IRoomCreator, IRoomEngineService
objectData.setString(extra); objectData.setString(extra);
const furnitureData = new RoomFurnitureData(id, typeId, null, location, direction, state, objectData, NaN, expires, usagePolicy, ownerId, ownerName, true, realRoomObject); const furnitureData = new RoomFurnitureData(id, typeId, null, location, direction, state, objectData, NaN, expires, usagePolicy, ownerId, ownerName, true, realRoomObject, -1, allowStack, allowSit, allowLay, allowWalk, dimensionsX, dimensionsY, teleportTargetId);
instanceData.addPendingFurnitureWall(furnitureData); instanceData.addPendingFurnitureWall(furnitureData);
+3 -3
View File
@@ -1167,11 +1167,11 @@ export class RoomMessageHandler
if(data.spriteName) if(data.spriteName)
{ {
this._roomEngine.addFurnitureFloorByTypeName(roomId, data.itemId, data.spriteName, location, direction, data.state, data.data, data.extra, data.expires, data.usagePolicy, data.userId, data.username, true, true, data.stackHeight); this._roomEngine.addFurnitureFloorByTypeName(roomId, data.itemId, data.spriteName, location, direction, data.state, data.data, data.extra, data.expires, data.usagePolicy, data.userId, data.username, true, true, data.stackHeight, data.allowStack, data.allowSit, data.allowLay, data.allowWalk, data.dimensionsX, data.dimensionsY, data.teleportTargetId);
} }
else else
{ {
this._roomEngine.addFurnitureFloor(roomId, data.itemId, data.spriteId, location, direction, data.state, data.data, data.extra, data.expires, data.usagePolicy, data.userId, data.username, true, true, data.stackHeight); this._roomEngine.addFurnitureFloor(roomId, data.itemId, data.spriteId, location, direction, data.state, data.data, data.extra, data.expires, data.usagePolicy, data.userId, data.username, true, true, data.stackHeight, data.allowStack, data.allowSit, data.allowLay, data.allowWalk, data.dimensionsX, data.dimensionsY, data.teleportTargetId);
} }
} }
@@ -1196,7 +1196,7 @@ export class RoomMessageHandler
const direction = new Vector3d(wallGeometry.getDirection(data.direction)); const direction = new Vector3d(wallGeometry.getDirection(data.direction));
this._roomEngine.addFurnitureWall(roomId, data.itemId, data.spriteId, location, direction, data.state, data.stuffData, data.secondsToExpiration, data.usagePolicy, data.userId, data.username); this._roomEngine.addFurnitureWall(roomId, data.itemId, data.spriteId, location, direction, data.state, data.stuffData, data.secondsToExpiration, data.usagePolicy, data.userId, data.username, true, data.allowStack, data.allowSit, data.allowLay, data.allowWalk, data.dimensionsX, data.dimensionsY, data.teleportTargetId);
} }
private onIgnoreResultEvent(event: IgnoreResultEvent): void private onIgnoreResultEvent(event: IgnoreResultEvent): void
@@ -283,6 +283,8 @@ export class FurnitureBadgeDisplayVisualization extends FurnitureAnimatedVisuali
tempCtx.putImageData(patchData, 0, 0); tempCtx.putImageData(patchData, 0, 0);
accCtx.drawImage(tempCanvas, frame.dims.left, frame.dims.top); accCtx.drawImage(tempCanvas, frame.dims.left, frame.dims.top);
tempCanvas.width = 0;
tempCanvas.height = 0;
// Create a new canvas for this frame and create a texture from it // Create a new canvas for this frame and create a texture from it
const frameCanvas = document.createElement('canvas'); const frameCanvas = document.createElement('canvas');
@@ -299,6 +301,9 @@ export class FurnitureBadgeDisplayVisualization extends FurnitureAnimatedVisuali
frameDelays.push(frame.delay || 10); frameDelays.push(frame.delay || 10);
} }
accCanvas.width = 0;
accCanvas.height = 0;
// Create AnimatedSprite with frame textures // Create AnimatedSprite with frame textures
if(this._frameTextures.length > 1) if(this._frameTextures.length > 1)
{ {
@@ -340,6 +345,13 @@ export class FurnitureBadgeDisplayVisualization extends FurnitureAnimatedVisuali
ctx.clearRect(0, 0, badgeCanvas.width, badgeCanvas.height); ctx.clearRect(0, 0, badgeCanvas.width, badgeCanvas.height);
ctx.drawImage(img, 0, 0, badgeCanvas.width, badgeCanvas.height); ctx.drawImage(img, 0, 0, badgeCanvas.width, badgeCanvas.height);
tex.source.update(); tex.source.update();
img.onload = null;
img.onerror = null;
};
img.onerror = () =>
{
img.onload = null;
img.onerror = null;
}; };
img.src = badgeUrl; img.src = badgeUrl;
} }
@@ -28,10 +28,19 @@ export class FurnitureDynamicThumbnailVisualization extends IsometricImageFurniV
if (image.complete && image.width > 0 && image.height > 0) { if (image.complete && image.width > 0 && image.height > 0) {
const texture = Texture.from(image); const texture = Texture.from(image);
texture.source.scaleMode = 'linear'; texture.source.scaleMode = 'linear';
this.setThumbnailImages(texture, thumbnailUrl); // Pass URL here
this.setThumbnailImages(texture, thumbnailUrl);
} else { } else {
console.error("Image failed to load properly:", thumbnailUrl); this.setThumbnailImages(null);
} }
image.onload = null;
image.onerror = null;
};
image.onerror = () => {
this.setThumbnailImages(null);
image.onload = null;
image.onerror = null;
}; };
} else { } else {
this.setThumbnailImages(null); this.setThumbnailImages(null);
@@ -5,6 +5,13 @@ export class FurnitureYoutubeVisualization extends FurnitureDynamicThumbnailVisu
{ {
protected static THUMBNAIL_URL: string = 'THUMBNAIL_URL'; protected static THUMBNAIL_URL: string = 'THUMBNAIL_URL';
constructor()
{
super();
this._hasOutline = false;
}
protected getThumbnailURL(): string protected getThumbnailURL(): string
{ {
if(!this.object) return null; if(!this.object) return null;
@@ -1,15 +1,16 @@
import { IGraphicAsset } from '@nitrots/api'; import { IGraphicAsset } from '@nitrots/api';
import { GetRenderer, TextureUtils } from '@nitrots/utils'; import { GetRenderer } from '@nitrots/utils';
import { Container, Graphics, Matrix, Sprite, Texture, RenderTexture } from 'pixi.js'; import { Container, Matrix, Sprite, Texture, RenderTexture } from 'pixi.js';
import { FurnitureAnimatedVisualization } from './FurnitureAnimatedVisualization'; import { FurnitureAnimatedVisualization } from './FurnitureAnimatedVisualization';
export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualization { export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualization {
protected static THUMBNAIL: string = 'THUMBNAIL'; protected static THUMBNAIL: string = 'THUMBNAIL';
private _thumbnailAssetNameNormal: string;
private _thumbnailImageNormal: Texture; private _thumbnailImageNormal: Texture;
private _thumbnailDirection: number; private _thumbnailDirection: number;
private _thumbnailChanged: boolean; private _thumbnailChanged: boolean;
private _thumbnailLayerId: number;
private _thumbnailTexture: Texture;
private _uniqueId: string; private _uniqueId: string;
private _photoUrl: string; private _photoUrl: string;
protected _hasOutline: boolean; protected _hasOutline: boolean;
@@ -17,10 +18,11 @@ export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualiza
constructor() { constructor() {
super(); super();
this._thumbnailAssetNameNormal = null;
this._thumbnailImageNormal = null; this._thumbnailImageNormal = null;
this._thumbnailDirection = -1; this._thumbnailDirection = -1;
this._thumbnailChanged = false; this._thumbnailChanged = false;
this._thumbnailLayerId = -1;
this._thumbnailTexture = null;
this._uniqueId = `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`; this._uniqueId = `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
this._photoUrl = null; this._photoUrl = null;
} }
@@ -56,13 +58,14 @@ export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualiza
return; return;
} }
const thumbnailAssetName = this.getThumbnailAssetName(64);
if (this._thumbnailImageNormal) { if (this._thumbnailImageNormal) {
this.addThumbnailAsset(this._thumbnailImageNormal, 64); this.addThumbnailAsset(this._thumbnailImageNormal, 64);
} else { } else {
const layerId = 2; if (this._thumbnailTexture instanceof RenderTexture) {
const sprite = this.getSprite(layerId); this._thumbnailTexture.destroy(true);
}
this._thumbnailTexture = null;
this._thumbnailLayerId = -1;
} }
this._thumbnailChanged = false; this._thumbnailChanged = false;
@@ -76,21 +79,16 @@ export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualiza
const layerTag = this.getLayerTag(scale, this.direction, layerId); const layerTag = this.getLayerTag(scale, this.direction, layerId);
if (layerTag === IsometricImageFurniVisualization.THUMBNAIL) { if (layerTag === IsometricImageFurniVisualization.THUMBNAIL) {
this._thumbnailLayerId = layerId;
const assetName = (this.cacheSpriteAssetName(scale, layerId, false) + this.getFrameNumber(scale, layerId)); const assetName = (this.cacheSpriteAssetName(scale, layerId, false) + this.getFrameNumber(scale, layerId));
const asset = this.getAsset(assetName, layerId); const asset = this.getAsset(assetName, layerId);
const thumbnailAssetName = `${this.getThumbnailAssetName(scale)}-${this._uniqueId}`;
const transformedTexture = this.generateTransformedThumbnail(k, asset || { width: 64, height: 64 });
// Use the original asset's registered offsets so the thumbnail is drawn at the if (asset) {
// furniture-defined sprite position. Fall back to centering when no asset exists. if (this._thumbnailTexture instanceof RenderTexture) {
const offsetX = asset ? asset.offsetX : -Math.floor(transformedTexture.width / 2); this._thumbnailTexture.destroy(true);
const offsetY = asset ? asset.offsetY : -Math.floor(transformedTexture.height / 2); }
this._thumbnailTexture = this.generateTransformedThumbnail(k, asset);
this.asset.addAsset(thumbnailAssetName, transformedTexture, true, offsetX, offsetY, false, false);
const placedSprite = this.getSprite(layerId);
if (placedSprite) {
placedSprite.texture = transformedTexture;
} }
return; return;
@@ -100,78 +98,117 @@ export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualiza
} }
} }
protected generateTransformedThumbnail(texture: Texture, asset: IGraphicAsset): Texture { protected updateSprite(scale: number, layerId: number): void {
const scaleFactor = (asset?.width || 64) / texture.width; super.updateSprite(scale, layerId);
const verticalScale = 1.0265;
const matrix = new Matrix();
const frameThickness = 20;
const frameColor = 0x000000;
switch (this.direction) { if (this._thumbnailTexture && this._thumbnailLayerId === layerId) {
const sprite = this.getSprite(layerId);
if (sprite) {
sprite.texture = this._thumbnailTexture;
}
}
}
protected generateTransformedThumbnail(texture: Texture, asset: IGraphicAsset): Texture {
const assetWidth = asset.width;
const assetHeight = asset.height;
let outlineTexture: RenderTexture = null;
if(this._hasOutline)
{
const borderSize = 20;
const bgWidth = texture.width + borderSize * 2;
const bgHeight = texture.height + borderSize * 2;
const container = new Container();
const background = new Sprite(Texture.WHITE);
background.tint = 0x000000;
background.width = bgWidth;
background.height = bgHeight;
const imageSprite = new Sprite(texture);
imageSprite.position.set(borderSize, borderSize);
container.addChild(background, imageSprite);
outlineTexture = RenderTexture.create({ width: bgWidth, height: bgHeight, resolution: 1 });
GetRenderer().render({ container, target: outlineTexture, clear: true });
texture = outlineTexture;
}
texture.source.scaleMode = 'linear';
const texW = texture.width;
const texH = texture.height;
const scaleX = assetWidth / texW;
const scaleY = assetHeight / texH;
const matrix = new Matrix();
switch(this.direction)
{
case 2: case 2:
matrix.a = scaleFactor; matrix.a = scaleX;
matrix.b = (-0.5 * scaleFactor); matrix.b = -(0.5 * scaleX);
matrix.c = 0; matrix.c = 0;
matrix.d = (scaleFactor * verticalScale); matrix.d = (scaleY / 1.6);
matrix.tx = 0; matrix.tx = 0;
matrix.ty = (0.5 * scaleFactor * texture.width); matrix.ty = (0.5 * scaleX * texW);
break; break;
case 0: case 0:
case 4: case 4:
matrix.a = scaleFactor; matrix.a = scaleX;
matrix.b = (0.5 * scaleFactor); matrix.b = (0.5 * scaleX);
matrix.c = 0; matrix.c = 0;
matrix.d = (scaleFactor * verticalScale); matrix.d = (scaleY / 1.6);
matrix.tx = 0; matrix.tx = 0;
matrix.ty = 0; matrix.ty = 0;
break; break;
default: default:
matrix.a = scaleFactor; matrix.a = scaleX;
matrix.b = 0; matrix.b = 0;
matrix.c = 0; matrix.c = 0;
matrix.d = scaleFactor; matrix.d = scaleY;
matrix.tx = 0; matrix.tx = 0;
matrix.ty = 0; matrix.ty = 0;
} }
const imgWidth = texture.width; // Calculate transformed corners manually for accurate bounds
const imgHeight = texture.height; const corners = [
const flatWidth = imgWidth + frameThickness * 2; { x: matrix.tx, y: matrix.ty },
const flatHeight = imgHeight + frameThickness * 2; { x: matrix.a * texW + matrix.tx, y: matrix.b * texW + matrix.ty },
const flatRenderTexture = TextureUtils.createAndFillRenderTexture(flatWidth, flatHeight, frameColor); { x: matrix.c * texH + matrix.tx, y: matrix.d * texH + matrix.ty },
const imageSprite = new Sprite(texture); { x: matrix.a * texW + matrix.c * texH + matrix.tx, y: matrix.b * texW + matrix.d * texH + matrix.ty }
imageSprite.position.set(frameThickness, frameThickness); ];
TextureUtils.writeToTexture(imageSprite, flatRenderTexture, false);
const flatTexture = flatRenderTexture;
const transformedSprite = new Sprite(flatTexture);
transformedSprite.setFromMatrix(matrix);
const width = 80;
const height = 80;
const finalContainer = new Container();
const posX = (width - transformedSprite.width) / 2;
const posY = (height - transformedSprite.height) / 2;
transformedSprite.position.set(posX, posY);
finalContainer.addChild(transformedSprite);
const renderTexture = RenderTexture.create({ width, height, resolution: 1 }); let minX = corners[0].x, minY = corners[0].y;
GetRenderer().render({ container: finalContainer, target: renderTexture, clear: true }); let maxX = corners[0].x, maxY = corners[0].y;
for (const corner of corners) {
if (corner.x < minX) minX = corner.x;
if (corner.y < minY) minY = corner.y;
if (corner.x > maxX) maxX = corner.x;
if (corner.y > maxY) maxY = corner.y;
}
const renderWidth = Math.ceil(maxX - minX);
const renderHeight = Math.ceil(maxY - minY);
matrix.tx -= minX;
matrix.ty -= minY;
const transformedSprite = new Sprite(texture);
transformedSprite.setFromMatrix(matrix);
const renderTexture = RenderTexture.create({ width: renderWidth, height: renderHeight, resolution: 1 });
GetRenderer().render({ container: transformedSprite, target: renderTexture, clear: true });
if (outlineTexture) {
outlineTexture.destroy(true);
}
return renderTexture; return renderTexture;
} }
protected getSpriteAssetName(scale: number, layerId: number): string {
if (this._thumbnailImageNormal && (this.getLayerTag(scale, this.direction, layerId) === IsometricImageFurniVisualization.THUMBNAIL)) {
return `${this.getThumbnailAssetName(scale)}-${this._uniqueId}`;
}
return super.getSpriteAssetName(scale, layerId);
}
protected getThumbnailAssetName(scale: number): string {
return this.cacheSpriteAssetName(scale, 2, false) + this.getFrameNumber(scale, 2);
}
protected getFullThumbnailAssetName(k: number, _arg_2: number): string {
return [this._type, k, 'thumb', _arg_2].join('_');
}
} }
@@ -867,203 +867,218 @@ export class RoomPlane implements IRoomPlane
} }
private renderWindowReflections(): void private renderWindowReflections(): void
{
if(!this._planeTexture || !this._leftSide || !this._rightSide || !this._normal) return;
if(this._leftSide.length <= 0 || this._rightSide.length <= 0) return;
const now = Date.now();
const fadeDurationMs = 150;
const avatars = RoomWindowReflectionState.getAvatars();
const canvasWidth = this._landscapeRenderWidth;
const canvasHeight = this._landscapeRenderHeight;
if(canvasWidth <= 0 || canvasHeight <= 0) return;
const container = new Container();
const visibleAvatarIds = new Set<number>();
const addReflectionSprite = (
texture: Texture,
oppositeTexture: Texture,
location: IVector3D,
alpha: number,
verticalOffset: number = 0,
direction: number = 0,
avatarId: number = -1
): boolean =>
{ {
if(!this._planeTexture || !this._leftSide || !this._rightSide || !this._normal) return; if(!texture?.source || texture.source.destroyed || !texture.source.style || !location || alpha < 0)
return false;
if(this._leftSide.length <= 0 || this._rightSide.length <= 0) return; const relative = Vector3d.dif(location, this._location);
const planeDistance = Math.abs(Vector3d.scalarProjection(relative, this._normal));
const now = Date.now(); if(planeDistance > 0.8) return false;
const fadeDurationMs = 150;
const avatars = RoomWindowReflectionState.getAvatars();
const canvasWidth = this._landscapeRenderWidth;
const canvasHeight = this._landscapeRenderHeight;
if(canvasWidth <= 0 || canvasHeight <= 0) return; const leftSideLoc = Vector3d.scalarProjection(relative, this._leftSide);
const rightSideLoc = Vector3d.scalarProjection(relative, this._rightSide);
const container = new Container(); const closestMask = this._windowMasks.reduce((best, mask) =>
const visibleAvatarIds = new Set<number>();
const addReflectionSprite = (texture: Texture, oppositeTexture: Texture, location: IVector3D, alpha: number, verticalOffset: number = 0, direction: number = 0, avatarId: number = -1): 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));
if(planeDistance > 0.8) return false;
const leftSideLoc = Vector3d.scalarProjection(relative, this._leftSide);
const rightSideLoc = Vector3d.scalarProjection(relative, this._rightSide);
const closestMask = this._windowMasks.reduce((best, mask) => {
const score = Math.abs(mask.leftSideLoc - leftSideLoc) + Math.abs(mask.rightSideLoc - rightSideLoc);
if(!best || (score < best.score)) return { mask, score };
return best;
}, null as { mask: { leftSideLoc: number; rightSideLoc: number }; score: number } | null);
if(!closestMask || (closestMask.score > 3)) return false;
const x = (canvasWidth - ((canvasWidth * leftSideLoc) / this._leftSide.length));
const y = (canvasHeight - ((canvasHeight * rightSideLoc) / this._rightSide.length)) + verticalOffset;
const toPlaneX = (this._location.x - location.x);
const toPlaneY = (this._location.y - location.y);
const toPlaneLength = Math.hypot(toPlaneX, toPlaneY);
const facingRadians = ((((direction - 90) % 360) + 360) % 360) * (Math.PI / 180);
const facingX = Math.cos(facingRadians);
const facingY = Math.sin(facingRadians);
const facingWindow = (toPlaneLength > 0.001)
? (((facingX * toPlaneX) + (facingY * toPlaneY)) / toPlaneLength) > 0.5
: false;
const deltaLeft = Math.abs(closestMask.mask.leftSideLoc - leftSideLoc);
const deltaRight = Math.abs(closestMask.mask.rightSideLoc - rightSideLoc);
const isInFrontOfWindow = ((closestMask.score <= 2) && ((deltaLeft <= 0.9) || (deltaRight <= 0.9)));
const shouldMirror = isInFrontOfWindow;
const normal2DLength = Math.hypot(this._normal.x, this._normal.y);
const normalX = (normal2DLength > 0.0001) ? (this._normal.x / normal2DLength) : 0;
const normalY = (normal2DLength > 0.0001) ? (this._normal.y / normal2DLength) : 0;
const normalFacingDot = Math.abs((facingX * normalX) + (facingY * normalY));
const transitionLow = 0.6;
const transitionHigh = 0.8;
let oppositeWeight = 0;
if(shouldMirror && oppositeTexture)
{
if(normalFacingDot >= transitionHigh) oppositeWeight = 1;
else if(normalFacingDot > transitionLow) oppositeWeight = (normalFacingDot - transitionLow) / (transitionHigh - transitionLow);
}
if(oppositeWeight < 1)
{
const sprite = new Sprite(texture);
sprite.anchor.set(0.5, 1);
sprite.position.set(Math.trunc(x), Math.trunc(y));
sprite.scale.set(1, 1);
sprite.tint = 0xCFE3FF;
sprite.alpha = alpha * (1 - oppositeWeight);
container.addChild(sprite);
}
if(oppositeWeight > 0 && oppositeTexture)
{
const sprite = new Sprite(oppositeTexture);
sprite.anchor.set(0.5, 1);
sprite.position.set(Math.trunc(x), Math.trunc(y));
sprite.scale.set(1, 1);
sprite.tint = 0xCFE3FF;
sprite.alpha = alpha * oppositeWeight;
container.addChild(sprite);
}
return true;
};
for(const avatar of avatars)
{ {
if(!avatar?.texture?.source || avatar.texture.source.destroyed || !avatar.texture.source.style || !avatar.location) continue; const score = Math.abs(mask.leftSideLoc - leftSideLoc) + Math.abs(mask.rightSideLoc - rightSideLoc);
let firstSeenAt = this._windowReflectionFirstSeenAt.get(avatar.id); if(!best || (score < best.score)) return { mask, score };
if(firstSeenAt === undefined) return best;
{ }, null as { mask: { leftSideLoc: number; rightSideLoc: number }; score: number } | null);
firstSeenAt = now;
}
const elapsed = Math.min(fadeDurationMs, Math.max(0, (now - firstSeenAt))); if(!closestMask || (closestMask.score > 3)) return false;
const progress = (elapsed / fadeDurationMs);
const alpha = (0.4 * progress);
if(!addReflectionSprite(avatar.texture, avatar.oppositeTexture, avatar.location, alpha, avatar.verticalOffset || 0, avatar.direction || 0, avatar.id)) continue; const x = (canvasWidth - ((canvasWidth * leftSideLoc) / this._leftSide.length));
const y = (canvasHeight - ((canvasHeight * rightSideLoc) / this._rightSide.length)) + verticalOffset;
if(!this._windowReflectionFirstSeenAt.has(avatar.id)) this._windowReflectionFirstSeenAt.set(avatar.id, firstSeenAt); const toPlaneX = (this._location.x - location.x);
const toPlaneY = (this._location.y - location.y);
const toPlaneLength = Math.hypot(toPlaneX, toPlaneY);
visibleAvatarIds.add(avatar.id); const facingRadians = ((((direction - 90) % 360) + 360) % 360) * (Math.PI / 180);
this._windowReflectionFadeOut.delete(avatar.id); const facingX = Math.cos(facingRadians);
const facingY = Math.sin(facingRadians);
const facingWindow = (toPlaneLength > 0.001)
? (((facingX * toPlaneX) + (facingY * toPlaneY)) / toPlaneLength) > 0.5
: false;
const storedLocation = new Vector3d(); const deltaLeft = Math.abs(closestMask.mask.leftSideLoc - leftSideLoc);
storedLocation.assign(avatar.location); const deltaRight = Math.abs(closestMask.mask.rightSideLoc - rightSideLoc);
this._windowReflectionLastVisible.set(avatar.id, { const isInFrontOfWindow = ((closestMask.score <= 2) && ((deltaLeft <= 0.9) || (deltaRight <= 0.9)));
texture: avatar.texture, const shouldMirror = isInFrontOfWindow;
oppositeTexture: avatar.oppositeTexture,
location: storedLocation, const normal2DLength = Math.hypot(this._normal.x, this._normal.y);
verticalOffset: avatar.verticalOffset || 0, const normalX = (normal2DLength > 0.0001) ? (this._normal.x / normal2DLength) : 0;
direction: avatar.direction || 0 const normalY = (normal2DLength > 0.0001) ? (this._normal.y / normal2DLength) : 0;
}); const normalFacingDot = Math.abs((facingX * normalX) + (facingY * normalY));
const transitionLow = 0.6;
const transitionHigh = 0.8;
let oppositeWeight = 0;
if(shouldMirror && oppositeTexture)
{
if(normalFacingDot >= transitionHigh) oppositeWeight = 1;
else if(normalFacingDot > transitionLow)
oppositeWeight = (normalFacingDot - transitionLow) / (transitionHigh - transitionLow);
} }
for(const [id, lastVisible] of this._windowReflectionLastVisible) if(oppositeWeight < 1)
{ {
if(visibleAvatarIds.has(id) || this._windowReflectionFadeOut.has(id)) continue; const sprite = new Sprite(texture);
sprite.anchor.set(0.5, 1);
if(!lastVisible.texture?.source || lastVisible.texture.source.destroyed || !lastVisible.texture.source.style) sprite.position.set(Math.trunc(x), Math.trunc(y));
{ sprite.tint = 0xCFE3FF;
this._windowReflectionLastVisible.delete(id); sprite.alpha = alpha * (1 - oppositeWeight);
this._windowReflectionFirstSeenAt.delete(id); container.addChild(sprite);
continue;
}
this._windowReflectionFadeOut.set(id, {
texture: lastVisible.texture,
oppositeTexture: lastVisible.oppositeTexture,
location: lastVisible.location,
verticalOffset: lastVisible.verticalOffset,
direction: lastVisible.direction,
startedAt: now
});
this._windowReflectionLastVisible.delete(id);
this._windowReflectionFirstSeenAt.delete(id);
} }
for(const [id, fadeOut] of this._windowReflectionFadeOut) if(oppositeWeight > 0 && oppositeTexture)
{ {
const elapsed = (now - fadeOut.startedAt); const sprite = new Sprite(oppositeTexture);
sprite.anchor.set(0.5, 1);
if(elapsed >= fadeDurationMs) sprite.position.set(Math.trunc(x), Math.trunc(y));
{ sprite.tint = 0xCFE3FF;
this._windowReflectionFadeOut.delete(id); sprite.alpha = alpha * oppositeWeight;
container.addChild(sprite);
continue;
}
const alpha = (0.4 * (1 - (elapsed / fadeDurationMs)));
if(!addReflectionSprite(fadeOut.texture, fadeOut.oppositeTexture, fadeOut.location, alpha, fadeOut.verticalOffset, fadeOut.direction, id)) this._windowReflectionFadeOut.delete(id);
} }
if(!container.children.length) return true;
{ };
container.destroy({ children: true });
if(!avatars.length) for(const avatar of avatars)
{ {
this._windowReflectionFirstSeenAt.clear(); if(!avatar?.texture?.source || avatar.texture.source.destroyed || !avatar.texture.source.style || !avatar.location)
this._windowReflectionLastVisible.clear(); continue;
}
return; let firstSeenAt = this._windowReflectionFirstSeenAt.get(avatar.id);
}
if(this._maskFilter) container.filters = [this._maskFilter]; if(firstSeenAt === undefined) firstSeenAt = now;
GetRenderer().render({ const elapsed = Math.min(fadeDurationMs, Math.max(0, (now - firstSeenAt)));
target: this._planeTexture, const alpha = (0.4 * (elapsed / fadeDurationMs));
container,
transform: this.getMatrixForDimensions(canvasWidth, canvasHeight), if(!addReflectionSprite(
clear: false avatar.texture,
avatar.oppositeTexture,
avatar.location,
alpha,
avatar.verticalOffset || 0,
avatar.direction || 0,
avatar.id))
continue;
if(!this._windowReflectionFirstSeenAt.has(avatar.id))
this._windowReflectionFirstSeenAt.set(avatar.id, firstSeenAt);
visibleAvatarIds.add(avatar.id);
this._windowReflectionFadeOut.delete(avatar.id);
const storedLocation = new Vector3d();
storedLocation.assign(avatar.location);
this._windowReflectionLastVisible.set(avatar.id, {
texture: avatar.texture,
oppositeTexture: avatar.oppositeTexture,
location: storedLocation,
verticalOffset: avatar.verticalOffset || 0,
direction: avatar.direction || 0
});
}
// move to fade-out (NO destruction)
for(const [id, lastVisible] of this._windowReflectionLastVisible)
{
if(visibleAvatarIds.has(id) || this._windowReflectionFadeOut.has(id)) continue;
this._windowReflectionFadeOut.set(id, {
...lastVisible,
startedAt: now
}); });
container.destroy({ children: true }); this._windowReflectionLastVisible.delete(id);
this._windowReflectionFirstSeenAt.delete(id);
} }
// fade-out rendering (NO destruction)
for(const [id, fadeOut] of this._windowReflectionFadeOut)
{
const elapsed = (now - fadeOut.startedAt);
if(elapsed >= fadeDurationMs)
{
this._windowReflectionFadeOut.delete(id);
continue;
}
const alpha = (0.4 * (1 - (elapsed / fadeDurationMs)));
if(!addReflectionSprite(
fadeOut.texture,
fadeOut.oppositeTexture,
fadeOut.location,
alpha,
fadeOut.verticalOffset,
fadeOut.direction,
id))
{
this._windowReflectionFadeOut.delete(id);
}
}
if(!container.children.length)
{
container.destroy({ children: true });
if(!avatars.length)
{
this._windowReflectionFirstSeenAt.clear();
this._windowReflectionLastVisible.clear();
}
return;
}
if(this._maskFilter) container.filters = [this._maskFilter];
GetRenderer().render({
target: this._planeTexture,
container,
transform: this.getMatrixForDimensions(canvasWidth, canvasHeight),
clear: false
});
container.destroy({ children: true });
}
private updateCorners(geometry: IRoomGeometry): void private updateCorners(geometry: IRoomGeometry): void
{ {
this._cornerA.assign(geometry.getScreenPosition(this._location)); this._cornerA.assign(geometry.getScreenPosition(this._location));
+50 -1
View File
@@ -18,8 +18,15 @@ export class RoomFurnitureData
private _synchronized: boolean; private _synchronized: boolean;
private _realRoomObject: boolean; private _realRoomObject: boolean;
private _sizeZ: number; private _sizeZ: number;
private _allowStack: boolean;
private _allowSit: boolean;
private _allowLay: boolean;
private _allowWalk: boolean;
private _dimensionsX: number;
private _dimensionsY: number;
private _teleportTargetId: number;
constructor(id: number, typeId: number, type: string, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra: number = NaN, expires: number = -1, usagePolicy: number = 0, ownerId: number = 0, ownerName: string = '', synchronized: boolean = true, realRoomObject: boolean = true, sizeZ: number = -1) constructor(id: number, typeId: number, type: string, location: IVector3D, direction: IVector3D, state: number, objectData: IObjectData, extra: number = NaN, expires: number = -1, usagePolicy: number = 0, ownerId: number = 0, ownerName: string = '', synchronized: boolean = true, realRoomObject: boolean = true, sizeZ: number = -1, allowStack: boolean = false, allowSit: boolean = false, allowLay: boolean = false, allowWalk: boolean = false, dimensionsX: number = 0, dimensionsY: number = 0, teleportTargetId: number = 0)
{ {
this._id = id; this._id = id;
this._typeId = typeId; this._typeId = typeId;
@@ -34,6 +41,13 @@ export class RoomFurnitureData
this._synchronized = synchronized; this._synchronized = synchronized;
this._realRoomObject = realRoomObject; this._realRoomObject = realRoomObject;
this._sizeZ = sizeZ; this._sizeZ = sizeZ;
this._allowStack = allowStack;
this._allowSit = allowSit;
this._allowLay = allowLay;
this._allowWalk = allowWalk;
this._dimensionsX = dimensionsX;
this._dimensionsY = dimensionsY;
this._teleportTargetId = teleportTargetId;
this._location = new Vector3d(); this._location = new Vector3d();
this._direction = new Vector3d(); this._direction = new Vector3d();
@@ -116,4 +130,39 @@ export class RoomFurnitureData
{ {
return this._sizeZ; return this._sizeZ;
} }
public get allowStack(): boolean
{
return this._allowStack;
}
public get allowSit(): boolean
{
return this._allowSit;
}
public get allowLay(): boolean
{
return this._allowLay;
}
public get allowWalk(): boolean
{
return this._allowWalk;
}
public get dimensionsX(): number
{
return this._dimensionsX;
}
public get dimensionsY(): number
{
return this._dimensionsY;
}
public get teleportTargetId(): number
{
return this._teleportTargetId;
}
} }
+55
View File
@@ -17,6 +17,11 @@ export class RoomSession implements IRoomSession
private _allowPets: boolean = false; private _allowPets: boolean = false;
private _controllerLevel: number = RoomControllerLevel.NONE; private _controllerLevel: number = RoomControllerLevel.NONE;
private _ownRoomIndex: number = -1; private _ownRoomIndex: number = -1;
private _groupId: number = 0;
private _hotelTimeZone: string = 'UTC';
private _hotelTimeSnapshotMs: number = 0;
private _hotelTimeSyncMs: number = 0;
private _roomItemLimit: number = 0;
private _isGuildRoom: boolean = false; private _isGuildRoom: boolean = false;
private _isRoomOwner: boolean = false; private _isRoomOwner: boolean = false;
private _isDecorating: boolean = false; private _isDecorating: boolean = false;
@@ -398,6 +403,56 @@ export class RoomSession implements IRoomSession
return this._ownRoomIndex; return this._ownRoomIndex;
} }
public get groupId(): number
{
return this._groupId;
}
public set groupId(groupId: number)
{
this._groupId = groupId;
}
public get hotelTimeZone(): string
{
return this._hotelTimeZone;
}
public set hotelTimeZone(timeZone: string)
{
this._hotelTimeZone = (timeZone || 'UTC');
}
public get hotelTimeSnapshotMs(): number
{
return this._hotelTimeSnapshotMs;
}
public set hotelTimeSnapshotMs(value: number)
{
this._hotelTimeSnapshotMs = value;
}
public get hotelTimeSyncMs(): number
{
return this._hotelTimeSyncMs;
}
public set hotelTimeSyncMs(value: number)
{
this._hotelTimeSyncMs = value;
}
public get roomItemLimit(): number
{
return this._roomItemLimit;
}
public set roomItemLimit(value: number)
{
this._roomItemLimit = value;
}
public get isGuildRoom(): boolean public get isGuildRoom(): boolean
{ {
return this._isGuildRoom; return this._isGuildRoom;
+22
View File
@@ -28,6 +28,8 @@ export class RoomUserData implements IRoomUserData
private _hasBreedingPermission: boolean; private _hasBreedingPermission: boolean;
private _botSkills: number[]; private _botSkills: number[];
private _isModerator: boolean; private _isModerator: boolean;
private _roomEntryMethod: string = 'unknown';
private _roomEntryTeleportId: number = 0;
constructor(k: number) constructor(k: number)
{ {
@@ -288,4 +290,24 @@ export class RoomUserData implements IRoomUserData
{ {
this._isModerator = k; this._isModerator = k;
} }
public get roomEntryMethod(): string
{
return this._roomEntryMethod;
}
public set roomEntryMethod(k: string)
{
this._roomEntryMethod = k;
}
public get roomEntryTeleportId(): number
{
return this._roomEntryTeleportId;
}
public set roomEntryTeleportId(k: number)
{
this._roomEntryTeleportId = k;
}
} }
@@ -248,6 +248,7 @@ export class BadgeImageManager
if(!renderedLayers) return false; if(!renderedLayers) return false;
const texture = TextureUtils.generateTexture(container); const texture = TextureUtils.generateTexture(container);
container.destroy({ children: true });
GetAssetManager().setTexture(groupBadge.code, texture); GetAssetManager().setTexture(groupBadge.code, texture);
GetEventDispatcher().dispatchEvent(new BadgeImageReadyEvent(groupBadge.code, texture)); GetEventDispatcher().dispatchEvent(new BadgeImageReadyEvent(groupBadge.code, texture));
@@ -24,6 +24,7 @@ export class FurnitureData implements IFurnitureData
private _purchaseCouldBeUsedForBuyout: boolean; private _purchaseCouldBeUsedForBuyout: boolean;
private _rentCouldBeUsedForBuyout: boolean; private _rentCouldBeUsedForBuyout: boolean;
private _availableForBuildersClub: boolean; private _availableForBuildersClub: boolean;
private _allowStack: boolean;
private _canStandOn: boolean; private _canStandOn: boolean;
private _canSitOn: boolean; private _canSitOn: boolean;
private _canLayOn: boolean; private _canLayOn: boolean;
@@ -32,7 +33,7 @@ export class FurnitureData implements IFurnitureData
private _environment: string; private _environment: string;
private _rare: boolean; private _rare: boolean;
constructor(type: FurnitureType, id: number, fullName: string, className: string, category: string, localizedName: string, description: string, revision: number, tileSizeX: number, tileSizeY: number, tileSizeZ: number, colors: number[], hadIndexedColor: boolean, colorIndex: number, adUrl: string, purchaseOfferId: number, purchaseCouldBeUsedForBuyout: boolean, rentOfferId: number, rentCouldBeUsedForBuyout: boolean, availableForBuildersClub: boolean, customParams: string, specialType: number, canStandOn: boolean, canSitOn: boolean, canLayOn: boolean, excludedfromDynamic: boolean, furniLine: string, environment: string, rare: boolean) constructor(type: FurnitureType, id: number, fullName: string, className: string, category: string, localizedName: string, description: string, revision: number, tileSizeX: number, tileSizeY: number, tileSizeZ: number, colors: number[], hadIndexedColor: boolean, colorIndex: number, adUrl: string, purchaseOfferId: number, purchaseCouldBeUsedForBuyout: boolean, rentOfferId: number, rentCouldBeUsedForBuyout: boolean, availableForBuildersClub: boolean, customParams: string, specialType: number, allowStack: boolean, canStandOn: boolean, canSitOn: boolean, canLayOn: boolean, excludedfromDynamic: boolean, furniLine: string, environment: string, rare: boolean)
{ {
this._type = type; this._type = type;
this._id = id; this._id = id;
@@ -56,6 +57,7 @@ export class FurnitureData implements IFurnitureData
this._customParams = customParams; this._customParams = customParams;
this._specialType = specialType; this._specialType = specialType;
this._availableForBuildersClub = availableForBuildersClub; this._availableForBuildersClub = availableForBuildersClub;
this._allowStack = allowStack;
this._canStandOn = canStandOn; this._canStandOn = canStandOn;
this._canSitOn = canSitOn; this._canSitOn = canSitOn;
this._canLayOn = canLayOn; this._canLayOn = canLayOn;
@@ -180,6 +182,11 @@ export class FurnitureData implements IFurnitureData
return this._availableForBuildersClub; return this._availableForBuildersClub;
} }
public get allowStack(): boolean
{
return this._allowStack;
}
public get canStandOn(): boolean public get canStandOn(): boolean
{ {
return this._canStandOn; return this._canStandOn;
@@ -82,8 +82,9 @@ export class FurnitureDataLoader
const className = classSplit[0]; const className = classSplit[0];
const colorIndex = ((classSplit.length > 1) ? parseInt(classSplit[1]) : 0); const colorIndex = ((classSplit.length > 1) ? parseInt(classSplit[1]) : 0);
const hasColorIndex = (classSplit.length > 1); const hasColorIndex = (classSplit.length > 1);
const allowStack = this.resolveBooleanFlag(furniture.allowstack, furniture.allow_stack, furniture.allowStack);
const furnitureData = new FurnitureData(FurnitureType.FLOOR, furniture.id, furniture.classname, className, furniture.category, furniture.name, furniture.description, furniture.revision, furniture.xdim, furniture.ydim, 0, colors, hasColorIndex, colorIndex, furniture.adurl, furniture.offerid, furniture.buyout, furniture.rentofferid, furniture.rentbuyout, furniture.bc, furniture.customparams, furniture.specialtype, furniture.canstandon, furniture.cansiton, furniture.canlayon, furniture.excludeddynamic, furniture.furniline, furniture.environment, furniture.rare); const furnitureData = new FurnitureData(FurnitureType.FLOOR, furniture.id, furniture.classname, className, furniture.category, furniture.name, furniture.description, furniture.revision, furniture.xdim, furniture.ydim, 0, colors, hasColorIndex, colorIndex, furniture.adurl, furniture.offerid, furniture.buyout, furniture.rentofferid, furniture.rentbuyout, furniture.bc, furniture.customparams, furniture.specialtype, allowStack, furniture.canstandon, furniture.cansiton, furniture.canlayon, furniture.excludeddynamic, furniture.furniline, furniture.environment, furniture.rare);
this._floorItems.set(furnitureData.id, furnitureData); this._floorItems.set(furnitureData.id, furnitureData);
@@ -99,7 +100,8 @@ export class FurnitureDataLoader
{ {
if(!furniture) continue; if(!furniture) continue;
const furnitureData = new FurnitureData(FurnitureType.WALL, furniture.id, furniture.classname, furniture.classname, furniture.category, furniture.name, furniture.description, furniture.revision, 0, 0, 0, null, false, 0, furniture.adurl, furniture.offerid, furniture.buyout, furniture.rentofferid, furniture.rentbuyout, furniture.bc, null, furniture.specialtype, false, false, false, furniture.excludeddynamic, furniture.furniline, furniture.environment, furniture.rare); const allowStack = this.resolveBooleanFlag(furniture.allowstack, furniture.allow_stack, furniture.allowStack);
const furnitureData = new FurnitureData(FurnitureType.WALL, furniture.id, furniture.classname, furniture.classname, furniture.category, furniture.name, furniture.description, furniture.revision, 0, 0, 0, null, false, 0, furniture.adurl, furniture.offerid, furniture.buyout, furniture.rentofferid, furniture.rentbuyout, furniture.bc, null, furniture.specialtype, allowStack, false, false, false, furniture.excludeddynamic, furniture.furniline, furniture.environment, furniture.rare);
this._wallItems.set(furnitureData.id, furnitureData); this._wallItems.set(furnitureData.id, furnitureData);
@@ -121,4 +123,26 @@ export class FurnitureDataLoader
return; return;
} }
} }
private resolveBooleanFlag(...values: any[]): boolean
{
for(const value of values)
{
if(value === undefined || value === null) continue;
if(typeof value === 'string')
{
const normalized = value.trim().toLowerCase();
if(!normalized.length) continue;
if([ '1', 'true', 'yes' ].includes(normalized)) return true;
if([ '0', 'false', 'no' ].includes(normalized)) return false;
}
return !!value;
}
return false;
}
} }
@@ -29,6 +29,11 @@ export class RoomDataHandler extends BaseHandler
const roomData = parser.data; const roomData = parser.data;
roomSession.tradeMode = roomData.tradeMode; roomSession.tradeMode = roomData.tradeMode;
roomSession.groupId = roomData.habboGroupId;
roomSession.hotelTimeZone = (parser.hotelTimeZoneId || 'UTC');
roomSession.hotelTimeSnapshotMs = parser.hotelCurrentTimeMs;
roomSession.hotelTimeSyncMs = Date.now();
roomSession.roomItemLimit = parser.roomItemLimit;
roomSession.isGuildRoom = (roomData.habboGroupId !== 0); roomSession.isGuildRoom = (roomData.habboGroupId !== 0);
roomSession.doorMode = roomData.doorMode; roomSession.doorMode = roomData.doorMode;
roomSession.allowPets = roomData.allowPets; roomSession.allowPets = roomData.allowPets;
@@ -78,6 +78,8 @@ export class RoomUsersHandler extends BaseHandler
userData.petLevel = user.petLevel; userData.petLevel = user.petLevel;
userData.botSkills = user.botSkills; userData.botSkills = user.botSkills;
userData.isModerator = user.isModerator; userData.isModerator = user.isModerator;
userData.roomEntryMethod = user.roomEntryMethod;
userData.roomEntryTeleportId = user.roomEntryTeleportId;
if(!session.userDataManager.getUserData(user.roomIndex)) usersToAdd.push(userData); if(!session.userDataManager.getUserData(user.roomIndex)) usersToAdd.push(userData);