You've already forked Nitro_Render_V3
mirror of
https://github.com/duckietm/Nitro_Render_V3.git
synced 2026-06-19 15:06:20 +00:00
feat: add room control rendering support
This commit is contained in:
@@ -80,6 +80,8 @@ export class RoomObjectVariable
|
|||||||
public static FURNITURE_BADGE_ASSET_NAME: string = 'furniture_badge_asset_name';
|
public static FURNITURE_BADGE_ASSET_NAME: string = 'furniture_badge_asset_name';
|
||||||
public static FURNITURE_BADGE_VISIBLE_IN_STATE: string = 'furniture_badge_visible_in_state';
|
public static FURNITURE_BADGE_VISIBLE_IN_STATE: string = 'furniture_badge_visible_in_state';
|
||||||
public static FURNITURE_ALPHA_MULTIPLIER: string = 'furniture_alpha_multiplier';
|
public static FURNITURE_ALPHA_MULTIPLIER: string = 'furniture_alpha_multiplier';
|
||||||
|
public static FURNITURE_CONF_INVIS_HIDDEN: string = 'furniture_conf_invis_hidden';
|
||||||
|
public static FURNITURE_AREA_HIDE_HIDDEN: string = 'furniture_area_hide_hidden';
|
||||||
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';
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -272,6 +272,8 @@ export class IncomingHeader
|
|||||||
public static WIRED_MONITOR_DATA = 5101;
|
public static WIRED_MONITOR_DATA = 5101;
|
||||||
public static WIRED_ROOM_SETTINGS_DATA = 5102;
|
public static WIRED_ROOM_SETTINGS_DATA = 5102;
|
||||||
public static WIRED_USER_VARIABLES_DATA = 5103;
|
public static WIRED_USER_VARIABLES_DATA = 5103;
|
||||||
|
public static CONF_INVIS_STATE = 5104;
|
||||||
|
public static HANDITEM_BLOCK_STATE = 5105;
|
||||||
public static WIRED_OPEN = 1830;
|
public static WIRED_OPEN = 1830;
|
||||||
public static WIRED_REWARD = 178;
|
public static WIRED_REWARD = 178;
|
||||||
public static WIRED_SAVE = 1155;
|
public static WIRED_SAVE = 1155;
|
||||||
|
|||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
import { IMessageEvent } from '@nitrots/api';
|
||||||
|
import { MessageEvent } from '@nitrots/events';
|
||||||
|
import { ConfInvisStateMessageParser } from '../../../parser';
|
||||||
|
|
||||||
|
export class ConfInvisStateMessageEvent extends MessageEvent implements IMessageEvent
|
||||||
|
{
|
||||||
|
constructor(callBack: Function)
|
||||||
|
{
|
||||||
|
super(callBack, ConfInvisStateMessageParser);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getParser(): ConfInvisStateMessageParser
|
||||||
|
{
|
||||||
|
return this.parser as ConfInvisStateMessageParser;
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
import { IMessageEvent } from '@nitrots/api';
|
||||||
|
import { MessageEvent } from '@nitrots/events';
|
||||||
|
import { HanditemBlockStateMessageParser } from '../../../parser';
|
||||||
|
|
||||||
|
export class HanditemBlockStateMessageEvent extends MessageEvent implements IMessageEvent
|
||||||
|
{
|
||||||
|
constructor(callBack: Function)
|
||||||
|
{
|
||||||
|
super(callBack, HanditemBlockStateMessageParser);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getParser(): HanditemBlockStateMessageParser
|
||||||
|
{
|
||||||
|
return this.parser as HanditemBlockStateMessageParser;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from './AreaHideMessageEvent';
|
export * from './AreaHideMessageEvent';
|
||||||
|
export * from './ConfInvisStateMessageEvent';
|
||||||
export * from './CustomUserNotificationMessageEvent';
|
export * from './CustomUserNotificationMessageEvent';
|
||||||
export * from './DiceValueMessageEvent';
|
export * from './DiceValueMessageEvent';
|
||||||
export * from './FurniRentOrBuyoutOfferMessageEvent';
|
export * from './FurniRentOrBuyoutOfferMessageEvent';
|
||||||
@@ -6,6 +7,7 @@ export * from './FurnitureAliasesEvent';
|
|||||||
export * from './FurnitureDataEvent';
|
export * from './FurnitureDataEvent';
|
||||||
export * from './FurnitureStackHeightEvent';
|
export * from './FurnitureStackHeightEvent';
|
||||||
export * from './GroupFurniContextMenuInfoMessageEvent';
|
export * from './GroupFurniContextMenuInfoMessageEvent';
|
||||||
|
export * from './HanditemBlockStateMessageEvent';
|
||||||
export * from './ItemDataUpdateMessageEvent';
|
export * from './ItemDataUpdateMessageEvent';
|
||||||
export * from './LoveLockFurniFinishedEvent';
|
export * from './LoveLockFurniFinishedEvent';
|
||||||
export * from './LoveLockFurniFriendConfirmedEvent';
|
export * from './LoveLockFurniFriendConfirmedEvent';
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ export class AreaHideMessageData
|
|||||||
private _width: number;
|
private _width: number;
|
||||||
private _length: number;
|
private _length: number;
|
||||||
private _invert: boolean;
|
private _invert: boolean;
|
||||||
|
private _wallItems: boolean;
|
||||||
|
private _invisibility: boolean;
|
||||||
|
|
||||||
constructor(wrapper: IMessageDataWrapper)
|
constructor(wrapper: IMessageDataWrapper)
|
||||||
{
|
{
|
||||||
@@ -19,6 +21,8 @@ export class AreaHideMessageData
|
|||||||
this._width = wrapper.readInt();
|
this._width = wrapper.readInt();
|
||||||
this._length = wrapper.readInt();
|
this._length = wrapper.readInt();
|
||||||
this._invert = wrapper.readBoolean();
|
this._invert = wrapper.readBoolean();
|
||||||
|
this._wallItems = wrapper.readBoolean();
|
||||||
|
this._invisibility = wrapper.readBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get furniId(): number
|
public get furniId(): number
|
||||||
@@ -55,4 +59,14 @@ export class AreaHideMessageData
|
|||||||
{
|
{
|
||||||
return this._invert;
|
return this._invert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get wallItems(): boolean
|
||||||
|
{
|
||||||
|
return this._wallItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get invisibility(): boolean
|
||||||
|
{
|
||||||
|
return this._invisibility;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import { IMessageDataWrapper } from '@nitrots/api';
|
||||||
|
|
||||||
|
export class ConfInvisStateMessageData
|
||||||
|
{
|
||||||
|
private _roomId: number;
|
||||||
|
private _active: boolean;
|
||||||
|
private _hiddenItemIds: number[];
|
||||||
|
|
||||||
|
constructor(wrapper: IMessageDataWrapper)
|
||||||
|
{
|
||||||
|
this._roomId = wrapper.readInt();
|
||||||
|
this._active = wrapper.readBoolean();
|
||||||
|
|
||||||
|
const totalHiddenItems = wrapper.readInt();
|
||||||
|
|
||||||
|
this._hiddenItemIds = [];
|
||||||
|
|
||||||
|
for(let index = 0; index < totalHiddenItems; index++)
|
||||||
|
{
|
||||||
|
this._hiddenItemIds.push(wrapper.readInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get roomId(): number
|
||||||
|
{
|
||||||
|
return this._roomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get hiddenItemIds(): number[]
|
||||||
|
{
|
||||||
|
return this._hiddenItemIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get active(): boolean
|
||||||
|
{
|
||||||
|
return this._active;
|
||||||
|
}
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
import { IMessageDataWrapper } from '@nitrots/api';
|
||||||
|
|
||||||
|
export class HanditemBlockStateMessageData
|
||||||
|
{
|
||||||
|
private _roomId: number;
|
||||||
|
private _blocked: boolean;
|
||||||
|
|
||||||
|
constructor(wrapper: IMessageDataWrapper)
|
||||||
|
{
|
||||||
|
this._roomId = wrapper.readInt();
|
||||||
|
this._blocked = wrapper.readBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
public get roomId(): number
|
||||||
|
{
|
||||||
|
return this._roomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get blocked(): boolean
|
||||||
|
{
|
||||||
|
return this._blocked;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
export * from './AreaHideMessageData';
|
export * from './AreaHideMessageData';
|
||||||
|
export * from './ConfInvisStateMessageData';
|
||||||
|
export * from './HanditemBlockStateMessageData';
|
||||||
export * from './FavoriteMembershipUpdateMessageParser';
|
export * from './FavoriteMembershipUpdateMessageParser';
|
||||||
export * from './ObjectData';
|
export * from './ObjectData';
|
||||||
export * from './ObjectsDataUpdateParser';
|
export * from './ObjectsDataUpdateParser';
|
||||||
|
|||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
import { IMessageDataWrapper, IMessageParser } from '@nitrots/api';
|
||||||
|
import { ConfInvisStateMessageData } from '../engine';
|
||||||
|
|
||||||
|
export class ConfInvisStateMessageParser implements IMessageParser
|
||||||
|
{
|
||||||
|
private _stateData: ConfInvisStateMessageData;
|
||||||
|
|
||||||
|
public flush(): boolean
|
||||||
|
{
|
||||||
|
this._stateData = null;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public parse(wrapper: IMessageDataWrapper): boolean
|
||||||
|
{
|
||||||
|
if(!wrapper) return false;
|
||||||
|
|
||||||
|
this._stateData = new ConfInvisStateMessageData(wrapper);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get stateData(): ConfInvisStateMessageData
|
||||||
|
{
|
||||||
|
return this._stateData;
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
import { IMessageDataWrapper, IMessageParser } from '@nitrots/api';
|
||||||
|
import { HanditemBlockStateMessageData } from '../engine';
|
||||||
|
|
||||||
|
export class HanditemBlockStateMessageParser implements IMessageParser
|
||||||
|
{
|
||||||
|
private _stateData: HanditemBlockStateMessageData;
|
||||||
|
|
||||||
|
public flush(): boolean
|
||||||
|
{
|
||||||
|
this._stateData = null;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public parse(wrapper: IMessageDataWrapper): boolean
|
||||||
|
{
|
||||||
|
if(!wrapper) return false;
|
||||||
|
|
||||||
|
this._stateData = new HanditemBlockStateMessageData(wrapper);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get stateData(): HanditemBlockStateMessageData
|
||||||
|
{
|
||||||
|
return this._stateData;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from './AreaHideMessageParser';
|
export * from './AreaHideMessageParser';
|
||||||
|
export * from './ConfInvisStateMessageParser';
|
||||||
export * from './CustomUserNotificationMessageParser';
|
export * from './CustomUserNotificationMessageParser';
|
||||||
export * from './DiceValueMessageParser';
|
export * from './DiceValueMessageParser';
|
||||||
export * from './FurniRentOrBuyoutOfferMessageParser';
|
export * from './FurniRentOrBuyoutOfferMessageParser';
|
||||||
@@ -6,6 +7,7 @@ export * from './FurnitureAliasesParser';
|
|||||||
export * from './FurnitureDataParser';
|
export * from './FurnitureDataParser';
|
||||||
export * from './FurnitureStackHeightParser';
|
export * from './FurnitureStackHeightParser';
|
||||||
export * from './GroupFurniContextMenuInfoMessageParser';
|
export * from './GroupFurniContextMenuInfoMessageParser';
|
||||||
|
export * from './HanditemBlockStateMessageParser';
|
||||||
export * from './ItemDataUpdateMessageParser';
|
export * from './ItemDataUpdateMessageParser';
|
||||||
export * from './LoveLockFurniFinishedParser';
|
export * from './LoveLockFurniFinishedParser';
|
||||||
export * from './LoveLockFurniFriendConfirmedParser';
|
export * from './LoveLockFurniFriendConfirmedParser';
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export class RoomEngine implements IRoomEngine, IRoomCreator, IRoomEngineService
|
|||||||
{
|
{
|
||||||
public static ROOM_OBJECT_ID: number = -1;
|
public static ROOM_OBJECT_ID: number = -1;
|
||||||
public static ROOM_OBJECT_TYPE: string = 'room';
|
public static ROOM_OBJECT_TYPE: string = 'room';
|
||||||
|
private _areaHideHoleCounts = new Map<string, number>();
|
||||||
|
|
||||||
public static CURSOR_OBJECT_ID: number = -2;
|
public static CURSOR_OBJECT_ID: number = -2;
|
||||||
public static CURSOR_OBJECT_TYPE: string = 'tile_cursor';
|
public static CURSOR_OBJECT_TYPE: string = 'tile_cursor';
|
||||||
@@ -170,6 +171,11 @@ export class RoomEngine implements IRoomEngine, IRoomCreator, IRoomEngineService
|
|||||||
existing.dispose();
|
existing.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(const key of Array.from(this._areaHideHoleCounts.keys()))
|
||||||
|
{
|
||||||
|
if(key.startsWith(roomId + ':')) this._areaHideHoleCounts.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
GetEventDispatcher().dispatchEvent(new RoomEngineEvent(RoomEngineEvent.DISPOSED, roomId));
|
GetEventDispatcher().dispatchEvent(new RoomEngineEvent(RoomEngineEvent.DISPOSED, roomId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,14 +591,106 @@ export class RoomEngine implements IRoomEngine, IRoomCreator, IRoomEngineService
|
|||||||
|
|
||||||
GetEventDispatcher().dispatchEvent(new RoomEngineAreaHideStateEvent(roomId, furniId, RoomObjectCategory.FLOOR, on));
|
GetEventDispatcher().dispatchEvent(new RoomEngineAreaHideStateEvent(roomId, furniId, RoomObjectCategory.FLOOR, on));
|
||||||
|
|
||||||
|
this.removeAreaHideFloorHoles(roomObject, roomId, furniId);
|
||||||
|
|
||||||
if(on)
|
if(on)
|
||||||
{
|
{
|
||||||
roomObject.logic.processUpdateMessage(new ObjectRoomFloorHoleUpdateMessage(ObjectRoomFloorHoleUpdateMessage.ADD, furniId, rootX, rootY, width, length, invert));
|
const rectangles = this.getAreaHideHoleRectangles(roomObject, rootX, rootY, width, length, invert);
|
||||||
|
|
||||||
|
for(let index = 0; index < rectangles.length; index++)
|
||||||
|
{
|
||||||
|
const rectangle = rectangles[index];
|
||||||
|
|
||||||
|
roomObject.logic.processUpdateMessage(new ObjectRoomFloorHoleUpdateMessage(ObjectRoomFloorHoleUpdateMessage.ADD, this.getAreaHideHoleId(furniId, index), rectangle.x, rectangle.y, rectangle.width, rectangle.length, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
this._areaHideHoleCounts.set(this.getAreaHideHoleKey(roomId, furniId), rectangles.length);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
roomObject.logic.processUpdateMessage(new ObjectRoomFloorHoleUpdateMessage(ObjectRoomFloorHoleUpdateMessage.REMOVE, furniId));
|
this._areaHideHoleCounts.delete(this.getAreaHideHoleKey(roomId, furniId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private removeAreaHideFloorHoles(roomObject: IRoomObjectController, roomId: number, furniId: number): void
|
||||||
|
{
|
||||||
|
if(!roomObject?.logic) return;
|
||||||
|
|
||||||
|
roomObject.logic.processUpdateMessage(new ObjectRoomFloorHoleUpdateMessage(ObjectRoomFloorHoleUpdateMessage.REMOVE, furniId));
|
||||||
|
|
||||||
|
const count = this._areaHideHoleCounts.get(this.getAreaHideHoleKey(roomId, furniId)) ?? 0;
|
||||||
|
|
||||||
|
for(let index = 0; index < Math.max(count, 4); index++)
|
||||||
|
{
|
||||||
|
roomObject.logic.processUpdateMessage(new ObjectRoomFloorHoleUpdateMessage(ObjectRoomFloorHoleUpdateMessage.REMOVE, this.getAreaHideHoleId(furniId, index)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getAreaHideHoleKey(roomId: number, furniId: number): string
|
||||||
|
{
|
||||||
|
return roomId + ':' + furniId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getAreaHideHoleId(furniId: number, index: number): number
|
||||||
|
{
|
||||||
|
return -((furniId * 10000) + index + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getAreaHideHoleRectangles(roomObject: IRoomObjectController, rootX: number, rootY: number, width: number, length: number, invert: boolean): { x: number, y: number, width: number, length: number }[]
|
||||||
|
{
|
||||||
|
const rectangles: { x: number, y: number, width: number, length: number }[] = [];
|
||||||
|
|
||||||
|
if(width <= 0 || length <= 0) return rectangles;
|
||||||
|
|
||||||
|
const roomMap = roomObject?.model?.getValue<RoomMapData>(RoomObjectVariable.ROOM_MAP_DATA);
|
||||||
|
const tileMap = roomMap?.tileMap;
|
||||||
|
|
||||||
|
if(!tileMap?.length) return rectangles;
|
||||||
|
|
||||||
|
const areaMinX = rootX;
|
||||||
|
const areaMinY = rootY;
|
||||||
|
const areaMaxX = (rootX + width);
|
||||||
|
const areaMaxY = (rootY + length);
|
||||||
|
const pushRectangle = (x: number, y: number, rectWidth: number) =>
|
||||||
|
{
|
||||||
|
if(rectWidth <= 0) return;
|
||||||
|
|
||||||
|
rectangles.push({ x, y, width: rectWidth, length: 1 });
|
||||||
|
};
|
||||||
|
|
||||||
|
for(let y = 0; y < tileMap.length; y++)
|
||||||
|
{
|
||||||
|
const row = tileMap[y];
|
||||||
|
|
||||||
|
if(!row?.length) continue;
|
||||||
|
|
||||||
|
let segmentStart = -1;
|
||||||
|
|
||||||
|
for(let x = 0; x <= row.length; x++)
|
||||||
|
{
|
||||||
|
const tileHeight = (x < row.length) ? row[x]?.height : Number.NEGATIVE_INFINITY;
|
||||||
|
const validTile = (tileHeight >= 0);
|
||||||
|
const inSelection = (x >= areaMinX) && (x < areaMaxX) && (y >= areaMinY) && (y < areaMaxY);
|
||||||
|
const shouldHide = validTile && (invert ? !inSelection : inSelection);
|
||||||
|
|
||||||
|
if(shouldHide)
|
||||||
|
{
|
||||||
|
if(segmentStart === -1) segmentStart = x;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(segmentStart !== -1)
|
||||||
|
{
|
||||||
|
pushRectangle(segmentStart, y, (x - segmentStart));
|
||||||
|
segmentStart = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rectangles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateObjectRoomColor(roomId: number, color: number, light: number, backgroundOnly: boolean): boolean
|
public updateObjectRoomColor(roomId: number, color: number, light: number, backgroundOnly: boolean): boolean
|
||||||
@@ -1733,6 +1831,11 @@ export class RoomEngine implements IRoomEngine, IRoomCreator, IRoomEngineService
|
|||||||
object.processUpdateMessage(new RoomObjectUpdateMessage(location, direction));
|
object.processUpdateMessage(new RoomObjectUpdateMessage(location, direction));
|
||||||
object.processUpdateMessage(new ObjectDataUpdateMessage(state, data, extra));
|
object.processUpdateMessage(new ObjectDataUpdateMessage(state, data, extra));
|
||||||
|
|
||||||
|
if(object.model && (extra === 2147483001))
|
||||||
|
{
|
||||||
|
object.model.setValue(RoomObjectVariable.FURNITURE_IS_VARIABLE_HEIGHT, 1);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { AvatarGuideStatus, IConnection, IMessageEvent, IRoomCreator, IRoomObjectController, IVector3D, LegacyDataType, ObjectRolling, PetType, RoomObjectType, RoomObjectUserType, RoomObjectVariable } from '@nitrots/api';
|
import { AvatarGuideStatus, IConnection, IMessageEvent, IRoomCreator, IRoomObjectController, IRoomObject, IVector3D, LegacyDataType, ObjectRolling, PetType, RoomObjectCategory, RoomObjectType, RoomObjectUserType, RoomObjectVariable } from '@nitrots/api';
|
||||||
import { AreaHideMessageEvent, DiceValueMessageEvent, FloorHeightMapEvent, FurnitureAliasesComposer, FurnitureAliasesEvent, FurnitureDataEvent, FurnitureFloorAddEvent, FurnitureFloorDataParser, FurnitureFloorEvent, FurnitureFloorRemoveEvent, FurnitureFloorUpdateEvent, FurnitureWallAddEvent, FurnitureWallDataParser, FurnitureWallEvent, FurnitureWallRemoveEvent, FurnitureWallUpdateEvent, GetCommunication, GetRoomEntryDataMessageComposer, GuideSessionEndedMessageEvent, GuideSessionErrorMessageEvent, GuideSessionStartedMessageEvent, IgnoreResultEvent, ItemDataUpdateMessageEvent, ObjectsDataUpdateEvent, ObjectsRollingEvent, OneWayDoorStatusMessageEvent, PetExperienceEvent, PetFigureUpdateEvent, RoomEntryTileMessageEvent, RoomEntryTileMessageParser, RoomHeightMapEvent, RoomHeightMapUpdateEvent, RoomPaintEvent, RoomReadyMessageEvent, RoomUnitChatEvent, RoomUnitChatShoutEvent, RoomUnitChatWhisperEvent, RoomUnitDanceEvent, RoomUnitEffectEvent, RoomUnitEvent, RoomUnitExpressionEvent, RoomUnitHandItemEvent, RoomUnitIdleEvent, RoomUnitInfoEvent, RoomUnitNumberEvent, RoomUnitRemoveEvent, RoomUnitStatusEvent, RoomUnitStatusMessage, RoomUnitTypingEvent, RoomVisualizationSettingsEvent, UserInfoEvent, WiredFurniMovementData, WiredMovementsEvent, WiredUserDirectionUpdateData, WiredUserMovementData, YouArePlayingGameEvent } from '@nitrots/communication';
|
import { AreaHideMessageEvent, ConfInvisStateMessageEvent, DiceValueMessageEvent, FloorHeightMapEvent, FurnitureAliasesComposer, FurnitureAliasesEvent, FurnitureDataEvent, FurnitureFloorAddEvent, FurnitureFloorDataParser, FurnitureFloorEvent, FurnitureFloorRemoveEvent, FurnitureFloorUpdateEvent, FurnitureWallAddEvent, FurnitureWallDataParser, FurnitureWallEvent, FurnitureWallRemoveEvent, FurnitureWallUpdateEvent, GetCommunication, GetRoomEntryDataMessageComposer, GuideSessionEndedMessageEvent, GuideSessionErrorMessageEvent, GuideSessionStartedMessageEvent, IgnoreResultEvent, ItemDataUpdateMessageEvent, ObjectsDataUpdateEvent, ObjectsRollingEvent, OneWayDoorStatusMessageEvent, PetExperienceEvent, PetFigureUpdateEvent, RoomEntryTileMessageEvent, RoomEntryTileMessageParser, RoomHeightMapEvent, RoomHeightMapUpdateEvent, RoomPaintEvent, RoomReadyMessageEvent, RoomUnitChatEvent, RoomUnitChatShoutEvent, RoomUnitChatWhisperEvent, RoomUnitDanceEvent, RoomUnitEffectEvent, RoomUnitEvent, RoomUnitExpressionEvent, RoomUnitHandItemEvent, RoomUnitIdleEvent, RoomUnitInfoEvent, RoomUnitNumberEvent, RoomUnitRemoveEvent, RoomUnitStatusEvent, RoomUnitStatusMessage, RoomUnitTypingEvent, RoomVisualizationSettingsEvent, UserInfoEvent, WiredFurniMovementData, WiredMovementsEvent, WiredUserDirectionUpdateData, WiredUserMovementData, YouArePlayingGameEvent } from '@nitrots/communication';
|
||||||
import { GetRoomSessionManager, GetSessionDataManager } from '@nitrots/session';
|
import { GetRoomSessionManager, GetSessionDataManager } from '@nitrots/session';
|
||||||
import { Vector3d } from '@nitrots/utils';
|
import { Vector3d } from '@nitrots/utils';
|
||||||
import { GetRoomEngine } from './GetRoomEngine';
|
import { GetRoomEngine } from './GetRoomEngine';
|
||||||
@@ -7,6 +7,16 @@ import { RoomVariableEnum } from './RoomVariableEnum';
|
|||||||
import { RoomPlaneParser } from './object/RoomPlaneParser';
|
import { RoomPlaneParser } from './object/RoomPlaneParser';
|
||||||
import { FurnitureStackingHeightMap, LegacyWallGeometry } from './utils';
|
import { FurnitureStackingHeightMap, LegacyWallGeometry } from './utils';
|
||||||
|
|
||||||
|
type AreaHideControllerState = {
|
||||||
|
rootX: number;
|
||||||
|
rootY: number;
|
||||||
|
width: number;
|
||||||
|
length: number;
|
||||||
|
invert: boolean;
|
||||||
|
wallItems: boolean;
|
||||||
|
invisibility: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export class RoomMessageHandler
|
export class RoomMessageHandler
|
||||||
{
|
{
|
||||||
private static WIRED_FURNI_ANCHOR_NONE = 0;
|
private static WIRED_FURNI_ANCHOR_NONE = 0;
|
||||||
@@ -23,6 +33,11 @@ export class RoomMessageHandler
|
|||||||
private _messageEvents: IMessageEvent[] = [];
|
private _messageEvents: IMessageEvent[] = [];
|
||||||
private _activeWiredUserMovements = new Map<number, { expiresAt: number, targetX: number, targetY: number, targetZ: number }>();
|
private _activeWiredUserMovements = new Map<number, { expiresAt: number, targetX: number, targetY: number, targetZ: number }>();
|
||||||
private _activeRoomUserWalks = new Map<number, { startedAt: number, targetX: number, targetY: number, targetZ: number, duration: number }>();
|
private _activeRoomUserWalks = new Map<number, { startedAt: number, targetX: number, targetY: number, targetZ: number, duration: number }>();
|
||||||
|
private _activeConfInvisHiddenItemIds = new Set<number>();
|
||||||
|
private _confInvisReapplyTimeouts: ReturnType<typeof setTimeout>[] = [];
|
||||||
|
private _activeAreaHideControllers = new Map<number, AreaHideControllerState>();
|
||||||
|
private _areaHideReapplyTimeouts: ReturnType<typeof setTimeout>[] = [];
|
||||||
|
private _isConfInvisControlActive = false;
|
||||||
|
|
||||||
private _currentRoomId: number = 0;
|
private _currentRoomId: number = 0;
|
||||||
private _ownUserId: number = 0;
|
private _ownUserId: number = 0;
|
||||||
@@ -62,6 +77,7 @@ export class RoomMessageHandler
|
|||||||
new ItemDataUpdateMessageEvent(this.onItemDataUpdateMessageEvent.bind(this)),
|
new ItemDataUpdateMessageEvent(this.onItemDataUpdateMessageEvent.bind(this)),
|
||||||
new OneWayDoorStatusMessageEvent(this.onOneWayDoorStatusMessageEvent.bind(this)),
|
new OneWayDoorStatusMessageEvent(this.onOneWayDoorStatusMessageEvent.bind(this)),
|
||||||
new AreaHideMessageEvent(this.onAreaHideMessageEvent.bind(this)),
|
new AreaHideMessageEvent(this.onAreaHideMessageEvent.bind(this)),
|
||||||
|
new ConfInvisStateMessageEvent(this.onConfInvisStateMessageEvent.bind(this)),
|
||||||
new RoomUnitDanceEvent(this.onRoomUnitDanceEvent.bind(this)),
|
new RoomUnitDanceEvent(this.onRoomUnitDanceEvent.bind(this)),
|
||||||
new RoomUnitEffectEvent(this.onRoomUnitEffectEvent.bind(this)),
|
new RoomUnitEffectEvent(this.onRoomUnitEffectEvent.bind(this)),
|
||||||
new RoomUnitEvent(this.onRoomUnitEvent.bind(this)),
|
new RoomUnitEvent(this.onRoomUnitEvent.bind(this)),
|
||||||
@@ -110,12 +126,16 @@ export class RoomMessageHandler
|
|||||||
this._latestEntryTileEvent = null;
|
this._latestEntryTileEvent = null;
|
||||||
this._activeWiredUserMovements.clear();
|
this._activeWiredUserMovements.clear();
|
||||||
this._activeRoomUserWalks.clear();
|
this._activeRoomUserWalks.clear();
|
||||||
|
|
||||||
if(this._planeParser)
|
if(this._planeParser)
|
||||||
{
|
{
|
||||||
this._planeParser.dispose();
|
this._planeParser.dispose();
|
||||||
this._planeParser = null;
|
this._planeParser = null;
|
||||||
}
|
}
|
||||||
|
this._activeConfInvisHiddenItemIds.clear();
|
||||||
|
this.clearConfInvisReapplyTimeouts();
|
||||||
|
this._activeAreaHideControllers.clear();
|
||||||
|
this.clearAreaHideReapplyTimeouts();
|
||||||
|
this._isConfInvisControlActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setRoomId(id: number): void
|
public setRoomId(id: number): void
|
||||||
@@ -129,6 +149,11 @@ export class RoomMessageHandler
|
|||||||
this._latestEntryTileEvent = null;
|
this._latestEntryTileEvent = null;
|
||||||
this._activeWiredUserMovements.clear();
|
this._activeWiredUserMovements.clear();
|
||||||
this._activeRoomUserWalks.clear();
|
this._activeRoomUserWalks.clear();
|
||||||
|
this._activeConfInvisHiddenItemIds.clear();
|
||||||
|
this.clearConfInvisReapplyTimeouts();
|
||||||
|
this._activeAreaHideControllers.clear();
|
||||||
|
this.clearAreaHideReapplyTimeouts();
|
||||||
|
this._isConfInvisControlActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public clearRoomId(): void
|
public clearRoomId(): void
|
||||||
@@ -137,6 +162,11 @@ export class RoomMessageHandler
|
|||||||
this._latestEntryTileEvent = null;
|
this._latestEntryTileEvent = null;
|
||||||
this._activeWiredUserMovements.clear();
|
this._activeWiredUserMovements.clear();
|
||||||
this._activeRoomUserWalks.clear();
|
this._activeRoomUserWalks.clear();
|
||||||
|
this._activeConfInvisHiddenItemIds.clear();
|
||||||
|
this.clearConfInvisReapplyTimeouts();
|
||||||
|
this._activeAreaHideControllers.clear();
|
||||||
|
this.clearAreaHideReapplyTimeouts();
|
||||||
|
this._isConfInvisControlActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private onUserInfoEvent(event: UserInfoEvent): void
|
private onUserInfoEvent(event: UserInfoEvent): void
|
||||||
@@ -383,6 +413,8 @@ export class RoomMessageHandler
|
|||||||
|
|
||||||
this._roomEngine.updateRoomObjectFloor(this._currentRoomId, parser.rollerId, null, null, 1, null);
|
this._roomEngine.updateRoomObjectFloor(this._currentRoomId, parser.rollerId, null, null, 1, null);
|
||||||
this._roomEngine.updateRoomObjectFloor(this._currentRoomId, parser.rollerId, null, null, 2, null);
|
this._roomEngine.updateRoomObjectFloor(this._currentRoomId, parser.rollerId, null, null, 2, null);
|
||||||
|
this.applyConfInvisStateToFloorObjects([ parser.rollerId ]);
|
||||||
|
this.applyAreaHideStateToFloorObjects([ parser.rollerId ]);
|
||||||
|
|
||||||
const furnitureRolling = parser.itemsRolling;
|
const furnitureRolling = parser.itemsRolling;
|
||||||
|
|
||||||
@@ -394,6 +426,8 @@ export class RoomMessageHandler
|
|||||||
|
|
||||||
this._roomEngine.rollRoomObjectFloor(this._currentRoomId, rollData.id, rollData.location, rollData.targetLocation);
|
this._roomEngine.rollRoomObjectFloor(this._currentRoomId, rollData.id, rollData.location, rollData.targetLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.scheduleAreaHideReapply(this._currentRoomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const unitRollData = parser.unitRolling;
|
const unitRollData = parser.unitRolling;
|
||||||
@@ -671,6 +705,9 @@ export class RoomMessageHandler
|
|||||||
{
|
{
|
||||||
this._roomEngine.updateRoomObjectFloor(this._currentRoomId, object.id, null, null, object.state, object.data);
|
this._roomEngine.updateRoomObjectFloor(this._currentRoomId, object.id, null, null, object.state, object.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.applyConfInvisStateToFloorObjects();
|
||||||
|
this.applyAreaHideStateToFloorObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
private onFurnitureAliasesEvent(event: FurnitureAliasesEvent): void
|
private onFurnitureAliasesEvent(event: FurnitureAliasesEvent): void
|
||||||
@@ -691,6 +728,8 @@ export class RoomMessageHandler
|
|||||||
if(!item) return;
|
if(!item) return;
|
||||||
|
|
||||||
this.addRoomObjectFurnitureFloor(this._currentRoomId, item);
|
this.addRoomObjectFurnitureFloor(this._currentRoomId, item);
|
||||||
|
this.applyConfInvisStateToFloorObjects([ item.itemId ]);
|
||||||
|
this.applyAreaHideStateToFloorObjects([ item.itemId ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onFurnitureFloorEvent(event: FurnitureFloorEvent): void
|
private onFurnitureFloorEvent(event: FurnitureFloorEvent): void
|
||||||
@@ -713,6 +752,10 @@ export class RoomMessageHandler
|
|||||||
|
|
||||||
iterator++;
|
iterator++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.applyConfInvisStateToFloorObjects();
|
||||||
|
this.applyAreaHideStateToFloorObjects();
|
||||||
|
this.scheduleAreaHideReapply(this._currentRoomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onFurnitureFloorRemoveEvent(event: FurnitureFloorRemoveEvent): void
|
private onFurnitureFloorRemoveEvent(event: FurnitureFloorRemoveEvent): void
|
||||||
@@ -727,12 +770,18 @@ export class RoomMessageHandler
|
|||||||
{
|
{
|
||||||
setTimeout(() =>
|
setTimeout(() =>
|
||||||
{
|
{
|
||||||
|
this._activeConfInvisHiddenItemIds.delete(parser.itemId);
|
||||||
|
this._activeAreaHideControllers.delete(parser.itemId);
|
||||||
this._roomEngine.removeRoomObjectFloor(this._currentRoomId, parser.itemId, (parser.isExpired) ? -1 : parser.userId, true);
|
this._roomEngine.removeRoomObjectFloor(this._currentRoomId, parser.itemId, (parser.isExpired) ? -1 : parser.userId, true);
|
||||||
|
this.applyAreaHideStateToRoomObjects();
|
||||||
}, parser.delay);
|
}, parser.delay);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
this._activeConfInvisHiddenItemIds.delete(parser.itemId);
|
||||||
|
this._activeAreaHideControllers.delete(parser.itemId);
|
||||||
this._roomEngine.removeRoomObjectFloor(this._currentRoomId, parser.itemId, (parser.isExpired) ? -1 : parser.userId, true);
|
this._roomEngine.removeRoomObjectFloor(this._currentRoomId, parser.itemId, (parser.isExpired) ? -1 : parser.userId, true);
|
||||||
|
this.applyAreaHideStateToRoomObjects();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -750,6 +799,73 @@ export class RoomMessageHandler
|
|||||||
this._roomEngine.updateRoomObjectFloor(this._currentRoomId, item.itemId, location, direction, item.data.state, item.data, item.extra);
|
this._roomEngine.updateRoomObjectFloor(this._currentRoomId, item.itemId, location, direction, item.data.state, item.data, item.extra);
|
||||||
this._roomEngine.updateRoomObjectFloorHeight(this._currentRoomId, item.itemId, item.stackHeight);
|
this._roomEngine.updateRoomObjectFloorHeight(this._currentRoomId, item.itemId, item.stackHeight);
|
||||||
this._roomEngine.updateRoomObjectFloorExpiration(this._currentRoomId, item.itemId, item.expires);
|
this._roomEngine.updateRoomObjectFloorExpiration(this._currentRoomId, item.itemId, item.expires);
|
||||||
|
this.applyConfInvisStateToFloorObjects([ item.itemId ]);
|
||||||
|
this.applyAreaHideStateToFloorObjects([ item.itemId ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private onConfInvisStateMessageEvent(event: ConfInvisStateMessageEvent): void
|
||||||
|
{
|
||||||
|
if(!(event instanceof ConfInvisStateMessageEvent) || !event.connection || !this._roomEngine) return;
|
||||||
|
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
if(!parser?.stateData) return;
|
||||||
|
if(parser.stateData.roomId !== this._currentRoomId) return;
|
||||||
|
|
||||||
|
this._isConfInvisControlActive = parser.stateData.active;
|
||||||
|
this._activeConfInvisHiddenItemIds = new Set<number>(parser.stateData.hiddenItemIds);
|
||||||
|
this.applyConfInvisStateToFloorObjects();
|
||||||
|
this.applyAreaHideStateToRoomObjects();
|
||||||
|
this.scheduleConfInvisReapply(parser.stateData.roomId);
|
||||||
|
this.scheduleAreaHideReapply(parser.stateData.roomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyConfInvisStateToFloorObjects(itemIds?: number[]): void
|
||||||
|
{
|
||||||
|
const floorObjects = ((this._roomEngine as any)?.getRoomObjects?.(this._currentRoomId, RoomObjectCategory.FLOOR) as IRoomObject[]) ?? [];
|
||||||
|
|
||||||
|
if(!floorObjects?.length) return;
|
||||||
|
|
||||||
|
const scopedIds = itemIds?.length ? new Set<number>(itemIds) : null;
|
||||||
|
|
||||||
|
for(const roomObject of floorObjects)
|
||||||
|
{
|
||||||
|
if(!roomObject?.model) continue;
|
||||||
|
if(scopedIds && !scopedIds.has(roomObject.id)) continue;
|
||||||
|
|
||||||
|
roomObject.model.setValue(RoomObjectVariable.FURNITURE_CONF_INVIS_HIDDEN, this._activeConfInvisHiddenItemIds.has(roomObject.id) ? 1 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private scheduleConfInvisReapply(roomId: number): void
|
||||||
|
{
|
||||||
|
this.clearConfInvisReapplyTimeouts();
|
||||||
|
|
||||||
|
const retryDelays = [ 0, 50, 150, 300, 600, 1000 ];
|
||||||
|
|
||||||
|
for(const delay of retryDelays)
|
||||||
|
{
|
||||||
|
const timeout = setTimeout(() =>
|
||||||
|
{
|
||||||
|
if(roomId !== this._currentRoomId) return;
|
||||||
|
|
||||||
|
this.applyConfInvisStateToFloorObjects();
|
||||||
|
}, delay);
|
||||||
|
|
||||||
|
this._confInvisReapplyTimeouts.push(timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private clearConfInvisReapplyTimeouts(): void
|
||||||
|
{
|
||||||
|
if(!this._confInvisReapplyTimeouts.length) return;
|
||||||
|
|
||||||
|
for(const timeout of this._confInvisReapplyTimeouts)
|
||||||
|
{
|
||||||
|
clearTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._confInvisReapplyTimeouts = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
private onFurnitureWallAddEvent(event: FurnitureWallAddEvent): void
|
private onFurnitureWallAddEvent(event: FurnitureWallAddEvent): void
|
||||||
@@ -761,6 +877,7 @@ export class RoomMessageHandler
|
|||||||
if(!data) return;
|
if(!data) return;
|
||||||
|
|
||||||
this.addRoomObjectFurnitureWall(this._currentRoomId, data);
|
this.addRoomObjectFurnitureWall(this._currentRoomId, data);
|
||||||
|
this.applyAreaHideStateToWallObjects([ data.itemId ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onFurnitureWallEvent(event: FurnitureWallEvent): void
|
private onFurnitureWallEvent(event: FurnitureWallEvent): void
|
||||||
@@ -783,6 +900,9 @@ export class RoomMessageHandler
|
|||||||
|
|
||||||
iterator++;
|
iterator++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.applyAreaHideStateToWallObjects();
|
||||||
|
this.scheduleAreaHideReapply(this._currentRoomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onFurnitureWallRemoveEvent(event: FurnitureWallRemoveEvent): void
|
private onFurnitureWallRemoveEvent(event: FurnitureWallRemoveEvent): void
|
||||||
@@ -794,6 +914,7 @@ export class RoomMessageHandler
|
|||||||
if(!parser) return;
|
if(!parser) return;
|
||||||
|
|
||||||
this._roomEngine.removeRoomObjectWall(this._currentRoomId, parser.itemId, parser.userId);
|
this._roomEngine.removeRoomObjectWall(this._currentRoomId, parser.itemId, parser.userId);
|
||||||
|
this.applyAreaHideStateToWallObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
private onFurnitureWallUpdateEvent(event: FurnitureWallUpdateEvent): void
|
private onFurnitureWallUpdateEvent(event: FurnitureWallUpdateEvent): void
|
||||||
@@ -813,6 +934,7 @@ export class RoomMessageHandler
|
|||||||
|
|
||||||
this._roomEngine.updateRoomObjectWall(this._currentRoomId, item.itemId, location, direction, item.state, item.stuffData);
|
this._roomEngine.updateRoomObjectWall(this._currentRoomId, item.itemId, location, direction, item.state, item.stuffData);
|
||||||
this._roomEngine.updateRoomObjectWallExpiration(this._currentRoomId, item.itemId, item.secondsToExpiration);
|
this._roomEngine.updateRoomObjectWallExpiration(this._currentRoomId, item.itemId, item.secondsToExpiration);
|
||||||
|
this.applyAreaHideStateToWallObjects([ item.itemId ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onFurnitureDataEvent(event: FurnitureDataEvent): void
|
private onFurnitureDataEvent(event: FurnitureDataEvent): void
|
||||||
@@ -822,6 +944,8 @@ export class RoomMessageHandler
|
|||||||
const parser = event.getParser();
|
const parser = event.getParser();
|
||||||
|
|
||||||
this._roomEngine.updateRoomObjectFloor(this._currentRoomId, parser.furnitureId, null, null, parser.objectData.state, parser.objectData);
|
this._roomEngine.updateRoomObjectFloor(this._currentRoomId, parser.furnitureId, null, null, parser.objectData.state, parser.objectData);
|
||||||
|
this.applyConfInvisStateToFloorObjects([ parser.furnitureId ]);
|
||||||
|
this.applyAreaHideStateToFloorObjects([ parser.furnitureId ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onItemDataUpdateMessageEvent(event: ItemDataUpdateMessageEvent): void
|
private onItemDataUpdateMessageEvent(event: ItemDataUpdateMessageEvent): void
|
||||||
@@ -831,6 +955,7 @@ export class RoomMessageHandler
|
|||||||
const parser = event.getParser();
|
const parser = event.getParser();
|
||||||
|
|
||||||
this._roomEngine.updateRoomObjectWallItemData(this._currentRoomId, parser.furnitureId, parser.data);
|
this._roomEngine.updateRoomObjectWallItemData(this._currentRoomId, parser.furnitureId, parser.data);
|
||||||
|
this.applyAreaHideStateToWallObjects([ parser.furnitureId ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onOneWayDoorStatusMessageEvent(event: OneWayDoorStatusMessageEvent): void
|
private onOneWayDoorStatusMessageEvent(event: OneWayDoorStatusMessageEvent): void
|
||||||
@@ -840,6 +965,8 @@ export class RoomMessageHandler
|
|||||||
const parser = event.getParser();
|
const parser = event.getParser();
|
||||||
|
|
||||||
this._roomEngine.updateRoomObjectFloor(this._currentRoomId, parser.itemId, null, null, parser.state, new LegacyDataType());
|
this._roomEngine.updateRoomObjectFloor(this._currentRoomId, parser.itemId, null, null, parser.state, new LegacyDataType());
|
||||||
|
this.applyConfInvisStateToFloorObjects([ parser.itemId ]);
|
||||||
|
this.applyAreaHideStateToFloorObjects([ parser.itemId ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onAreaHideMessageEvent(event: AreaHideMessageEvent): void
|
private onAreaHideMessageEvent(event: AreaHideMessageEvent): void
|
||||||
@@ -850,6 +977,26 @@ export class RoomMessageHandler
|
|||||||
const areaData = parser.areaData;
|
const areaData = parser.areaData;
|
||||||
|
|
||||||
this._roomEngine.updateAreaHide(this._currentRoomId, areaData.furniId, areaData.on, areaData.rootX, areaData.rootY, areaData.width, areaData.length, areaData.invert);
|
this._roomEngine.updateAreaHide(this._currentRoomId, areaData.furniId, areaData.on, areaData.rootX, areaData.rootY, areaData.width, areaData.length, areaData.invert);
|
||||||
|
|
||||||
|
if(areaData.on)
|
||||||
|
{
|
||||||
|
this._activeAreaHideControllers.set(areaData.furniId, {
|
||||||
|
rootX: areaData.rootX,
|
||||||
|
rootY: areaData.rootY,
|
||||||
|
width: areaData.width,
|
||||||
|
length: areaData.length,
|
||||||
|
invert: areaData.invert,
|
||||||
|
wallItems: areaData.wallItems,
|
||||||
|
invisibility: areaData.invisibility
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this._activeAreaHideControllers.delete(areaData.furniId);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.applyAreaHideStateToRoomObjects();
|
||||||
|
this.scheduleAreaHideReapply(this._currentRoomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onDiceValueMessageEvent(event: DiceValueMessageEvent): void
|
private onDiceValueMessageEvent(event: DiceValueMessageEvent): void
|
||||||
@@ -859,6 +1006,210 @@ export class RoomMessageHandler
|
|||||||
const parser = event.getParser();
|
const parser = event.getParser();
|
||||||
|
|
||||||
this._roomEngine.updateRoomObjectFloor(this._currentRoomId, parser.itemId, null, null, parser.value, new LegacyDataType());
|
this._roomEngine.updateRoomObjectFloor(this._currentRoomId, parser.itemId, null, null, parser.value, new LegacyDataType());
|
||||||
|
this.applyConfInvisStateToFloorObjects([ parser.itemId ]);
|
||||||
|
this.applyAreaHideStateToFloorObjects([ parser.itemId ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyAreaHideStateToRoomObjects(floorItemIds?: number[], wallItemIds?: number[]): void
|
||||||
|
{
|
||||||
|
this.applyAreaHideStateToFloorObjects(floorItemIds);
|
||||||
|
this.applyAreaHideStateToWallObjects(wallItemIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyAreaHideStateToFloorObjects(itemIds?: number[]): void
|
||||||
|
{
|
||||||
|
const floorObjects = ((this._roomEngine as any)?.getRoomObjects?.(this._currentRoomId, RoomObjectCategory.FLOOR) as IRoomObject[]) ?? [];
|
||||||
|
|
||||||
|
if(!floorObjects?.length) return;
|
||||||
|
|
||||||
|
const scopedIds = itemIds?.length ? new Set<number>(itemIds) : null;
|
||||||
|
|
||||||
|
for(const roomObject of floorObjects)
|
||||||
|
{
|
||||||
|
if(!roomObject?.model) continue;
|
||||||
|
if(scopedIds && !scopedIds.has(roomObject.id)) continue;
|
||||||
|
|
||||||
|
roomObject.model.setValue(RoomObjectVariable.FURNITURE_AREA_HIDE_HIDDEN, this.shouldHideRoomObjectByAreaHide(roomObject, RoomObjectCategory.FLOOR) ? 1 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyAreaHideStateToWallObjects(itemIds?: number[]): void
|
||||||
|
{
|
||||||
|
const wallObjects = ((this._roomEngine as any)?.getRoomObjects?.(this._currentRoomId, RoomObjectCategory.WALL) as IRoomObject[]) ?? [];
|
||||||
|
|
||||||
|
if(!wallObjects?.length) return;
|
||||||
|
|
||||||
|
const scopedIds = itemIds?.length ? new Set<number>(itemIds) : null;
|
||||||
|
|
||||||
|
for(const roomObject of wallObjects)
|
||||||
|
{
|
||||||
|
if(!roomObject?.model) continue;
|
||||||
|
if(scopedIds && !scopedIds.has(roomObject.id)) continue;
|
||||||
|
|
||||||
|
roomObject.model.setValue(RoomObjectVariable.FURNITURE_AREA_HIDE_HIDDEN, this.shouldHideRoomObjectByAreaHide(roomObject, RoomObjectCategory.WALL) ? 1 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private shouldHideRoomObjectByAreaHide(roomObject: IRoomObject, category: number): boolean
|
||||||
|
{
|
||||||
|
if(!roomObject?.model) return false;
|
||||||
|
|
||||||
|
const controllerState = this.getAreaHideControllerStateFromObject(roomObject, category);
|
||||||
|
|
||||||
|
if(controllerState)
|
||||||
|
{
|
||||||
|
return (controllerState.invisibility && this._isConfInvisControlActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this._activeAreaHideControllers.size) return false;
|
||||||
|
|
||||||
|
for(const activeState of this._activeAreaHideControllers.values())
|
||||||
|
{
|
||||||
|
if((activeState.width <= 0) || (activeState.length <= 0)) continue;
|
||||||
|
if((category === RoomObjectCategory.WALL) && !activeState.wallItems) continue;
|
||||||
|
|
||||||
|
const intersectsArea = (category === RoomObjectCategory.WALL)
|
||||||
|
? this.isWallObjectInsideArea(roomObject, activeState)
|
||||||
|
: this.doesFloorObjectIntersectArea(roomObject, activeState);
|
||||||
|
const shouldHide = (activeState.invert ? !intersectsArea : intersectsArea);
|
||||||
|
|
||||||
|
if(shouldHide) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private doesFloorObjectIntersectArea(roomObject: IRoomObject, areaState: AreaHideControllerState): boolean
|
||||||
|
{
|
||||||
|
if(!roomObject?.model) return false;
|
||||||
|
|
||||||
|
const location = roomObject.getLocation();
|
||||||
|
|
||||||
|
if(!location) return false;
|
||||||
|
|
||||||
|
let sizeX = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_SIZE_X);
|
||||||
|
let sizeY = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_SIZE_Y);
|
||||||
|
|
||||||
|
if(!sizeX || (sizeX < 1)) sizeX = 1;
|
||||||
|
if(!sizeY || (sizeY < 1)) sizeY = 1;
|
||||||
|
|
||||||
|
const direction = roomObject.getDirection();
|
||||||
|
const directionQuarterTurns = (((Math.trunc(((direction?.x ?? 0) + 45)) % 360) + 360) % 360) / 90;
|
||||||
|
|
||||||
|
if((directionQuarterTurns === 1) || (directionQuarterTurns === 3))
|
||||||
|
{
|
||||||
|
[ sizeX, sizeY ] = [ sizeY, sizeX ];
|
||||||
|
}
|
||||||
|
|
||||||
|
const objectMinX = location.x;
|
||||||
|
const objectMinY = location.y;
|
||||||
|
const objectMaxX = objectMinX + sizeX;
|
||||||
|
const objectMaxY = objectMinY + sizeY;
|
||||||
|
const areaMinX = areaState.rootX;
|
||||||
|
const areaMinY = areaState.rootY;
|
||||||
|
const areaMaxX = areaMinX + areaState.width;
|
||||||
|
const areaMaxY = areaMinY + areaState.length;
|
||||||
|
|
||||||
|
return (objectMinX < areaMaxX)
|
||||||
|
&& (objectMaxX > areaMinX)
|
||||||
|
&& (objectMinY < areaMaxY)
|
||||||
|
&& (objectMaxY > areaMinY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private isWallObjectInsideArea(roomObject: IRoomObject, areaState: AreaHideControllerState): boolean
|
||||||
|
{
|
||||||
|
const location = roomObject?.getLocation();
|
||||||
|
|
||||||
|
if(!location) return false;
|
||||||
|
|
||||||
|
const xCandidates = Array.from(new Set([ Math.floor(location.x), Math.ceil(location.x), Math.round(location.x) ]));
|
||||||
|
const yCandidates = Array.from(new Set([ Math.floor(location.y), Math.ceil(location.y), Math.round(location.y) ]));
|
||||||
|
|
||||||
|
for(const x of xCandidates)
|
||||||
|
{
|
||||||
|
for(const y of yCandidates)
|
||||||
|
{
|
||||||
|
if((x >= areaState.rootX)
|
||||||
|
&& (x < (areaState.rootX + areaState.width))
|
||||||
|
&& (y >= areaState.rootY)
|
||||||
|
&& (y < (areaState.rootY + areaState.length)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getAreaHideControllerStateFromObject(roomObject: IRoomObject, category: number): AreaHideControllerState
|
||||||
|
{
|
||||||
|
if(!roomObject?.model || (category !== RoomObjectCategory.FLOOR)) return null;
|
||||||
|
|
||||||
|
if(this._activeAreaHideControllers.has(roomObject.id))
|
||||||
|
{
|
||||||
|
return this._activeAreaHideControllers.get(roomObject.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this.isAreaHideControllerObject(roomObject)) return null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
rootX: (roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_AREA_HIDE_ROOT_X) ?? 0),
|
||||||
|
rootY: (roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_AREA_HIDE_ROOT_Y) ?? 0),
|
||||||
|
width: (roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_AREA_HIDE_WIDTH) ?? 0),
|
||||||
|
length: (roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_AREA_HIDE_LENGTH) ?? 0),
|
||||||
|
invert: (roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_AREA_HIDE_INVERT) === 1),
|
||||||
|
wallItems: (roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_AREA_HIDE_WALL_ITEMS) === 1),
|
||||||
|
invisibility: (roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_AREA_HIDE_INVISIBILITY) === 1)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private isAreaHideControllerObject(roomObject: IRoomObject): boolean
|
||||||
|
{
|
||||||
|
if(!roomObject?.model) return false;
|
||||||
|
|
||||||
|
const furniData = GetSessionDataManager().getFloorItemDataByName(roomObject.type);
|
||||||
|
const customParams = (furniData?.customParams || '').toLowerCase();
|
||||||
|
|
||||||
|
if(customParams.includes('area_hide_control') || customParams.includes('wf_conf_area_hide') || customParams.includes('conf_area_hide'))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stuffData = roomObject.model.getValue<number[]>(RoomObjectVariable.FURNITURE_DATA);
|
||||||
|
|
||||||
|
return Array.isArray(stuffData) && (stuffData.length >= 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
private scheduleAreaHideReapply(roomId: number): void
|
||||||
|
{
|
||||||
|
this.clearAreaHideReapplyTimeouts();
|
||||||
|
|
||||||
|
const retryDelays = [ 0, 50, 150, 300, 600, 1000 ];
|
||||||
|
|
||||||
|
for(const delay of retryDelays)
|
||||||
|
{
|
||||||
|
const timeout = setTimeout(() =>
|
||||||
|
{
|
||||||
|
if(roomId !== this._currentRoomId) return;
|
||||||
|
|
||||||
|
this.applyAreaHideStateToRoomObjects();
|
||||||
|
}, delay);
|
||||||
|
|
||||||
|
this._areaHideReapplyTimeouts.push(timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private clearAreaHideReapplyTimeouts(): void
|
||||||
|
{
|
||||||
|
if(!this._areaHideReapplyTimeouts.length) return;
|
||||||
|
|
||||||
|
for(const timeout of this._areaHideReapplyTimeouts)
|
||||||
|
{
|
||||||
|
clearTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._areaHideReapplyTimeouts = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
private onRoomUnitDanceEvent(event: RoomUnitDanceEvent): void
|
private onRoomUnitDanceEvent(event: RoomUnitDanceEvent): void
|
||||||
|
|||||||
@@ -87,6 +87,18 @@ export class RoomObjectEventHandler implements IRoomCanvasMouseListener, IRoomOb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if((event.type === MouseEventType.DOUBLE_CLICK) && (category === RoomObjectCategory.FLOOR) && object.model && (object.model.getValue<number>(RoomObjectVariable.FURNITURE_IS_VARIABLE_HEIGHT) > 0))
|
||||||
|
{
|
||||||
|
const roomIdString = object.model.getValue<string>(RoomObjectVariable.OBJECT_ROOM_ID);
|
||||||
|
const roomId = ((roomIdString && (parseInt(roomIdString.split('_')[0]) || 0)) || -1);
|
||||||
|
|
||||||
|
if((roomId >= 0) && GetEventDispatcher())
|
||||||
|
{
|
||||||
|
GetEventDispatcher().dispatchEvent(new RoomEngineTriggerWidgetEvent(RoomEngineTriggerWidgetEvent.REQUEST_STACK_HEIGHT, roomId, object.id, category));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(object.mouseHandler) object.mouseHandler.mouseEvent(event, geometry);
|
if(object.mouseHandler) object.mouseHandler.mouseEvent(event, geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -623,7 +623,17 @@ export class RoomPlaneParser
|
|||||||
}
|
}
|
||||||
_local_3++;
|
_local_3++;
|
||||||
}
|
}
|
||||||
const _local_4: Point = RoomPlaneParser.findEntranceTile(this._tileMatrix);
|
const _local_4: Point = (() =>
|
||||||
|
{
|
||||||
|
const matrixWithFloorHoles = this._tileMatrix.map((row, rowIndex) =>
|
||||||
|
{
|
||||||
|
const floorHoleRow = this._floorHoleMatrix[rowIndex] || [];
|
||||||
|
|
||||||
|
return row.map((value, columnIndex) => (floorHoleRow[columnIndex] ? RoomPlaneParser.TILE_HOLE : value));
|
||||||
|
});
|
||||||
|
|
||||||
|
return RoomPlaneParser.findEntranceTile(matrixWithFloorHoles);
|
||||||
|
})();
|
||||||
|
|
||||||
_local_3 = 0;
|
_local_3 = 0;
|
||||||
while(_local_3 < this._height)
|
while(_local_3 < this._height)
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ export class RoomLogic extends RoomObjectLogicBase
|
|||||||
switch(message.type)
|
switch(message.type)
|
||||||
{
|
{
|
||||||
case ObjectRoomFloorHoleUpdateMessage.ADD:
|
case ObjectRoomFloorHoleUpdateMessage.ADD:
|
||||||
this._planeParser.addFloorHole(message.id, message.x, message.y, message.width, message.height);
|
this._planeParser.addFloorHole(message.id, message.x, message.y, message.width, message.height, message.invert);
|
||||||
this._needsMapUpdate = true;
|
this._needsMapUpdate = true;
|
||||||
return;
|
return;
|
||||||
case ObjectRoomFloorHoleUpdateMessage.REMOVE:
|
case ObjectRoomFloorHoleUpdateMessage.REMOVE:
|
||||||
|
|||||||
@@ -25,7 +25,5 @@ export class FurnitureCustomStackHeightLogic extends FurnitureMultiStateLogic
|
|||||||
if(!this.object || !this.eventDispatcher) return;
|
if(!this.object || !this.eventDispatcher) return;
|
||||||
|
|
||||||
this.eventDispatcher.dispatchEvent(new RoomObjectWidgetRequestEvent(RoomObjectWidgetRequestEvent.STACK_HEIGHT, this.object));
|
this.eventDispatcher.dispatchEvent(new RoomObjectWidgetRequestEvent(RoomObjectWidgetRequestEvent.STACK_HEIGHT, this.object));
|
||||||
|
|
||||||
super.useObject();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -398,6 +398,13 @@ export class FurnitureLogic extends MovingObjectLogic
|
|||||||
{
|
{
|
||||||
if(!this.object || !this.eventDispatcher) return;
|
if(!this.object || !this.eventDispatcher) return;
|
||||||
|
|
||||||
|
if(this.object.model && (this.object.model.getValue<number>(RoomObjectVariable.FURNITURE_IS_VARIABLE_HEIGHT) > 0))
|
||||||
|
{
|
||||||
|
this.eventDispatcher.dispatchEvent(new RoomObjectWidgetRequestEvent(RoomObjectWidgetRequestEvent.STACK_HEIGHT, this.object));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const clickUrl = this.getAdClickUrl(this.object.model);
|
const clickUrl = this.getAdClickUrl(this.object.model);
|
||||||
|
|
||||||
if(clickUrl && clickUrl.length)
|
if(clickUrl && clickUrl.length)
|
||||||
|
|||||||
@@ -237,8 +237,11 @@ export class FurnitureVisualization extends RoomObjectSpriteVisualization
|
|||||||
this._furnitureLift = (model.getValue<number>(RoomObjectVariable.FURNITURE_LIFT_AMOUNT) || 0);
|
this._furnitureLift = (model.getValue<number>(RoomObjectVariable.FURNITURE_LIFT_AMOUNT) || 0);
|
||||||
|
|
||||||
let alphaMultiplier = model.getValue<number>(RoomObjectVariable.FURNITURE_ALPHA_MULTIPLIER);
|
let alphaMultiplier = model.getValue<number>(RoomObjectVariable.FURNITURE_ALPHA_MULTIPLIER);
|
||||||
|
const hiddenByConfInvisControl = (model.getValue<number>(RoomObjectVariable.FURNITURE_CONF_INVIS_HIDDEN) === 1);
|
||||||
|
const hiddenByAreaHideControl = (model.getValue<number>(RoomObjectVariable.FURNITURE_AREA_HIDE_HIDDEN) === 1);
|
||||||
|
|
||||||
if(isNaN(alphaMultiplier)) alphaMultiplier = 1;
|
if(isNaN(alphaMultiplier)) alphaMultiplier = 1;
|
||||||
|
if(hiddenByConfInvisControl || hiddenByAreaHideControl) alphaMultiplier = 0;
|
||||||
|
|
||||||
if(this._alphaMultiplier !== alphaMultiplier)
|
if(this._alphaMultiplier !== alphaMultiplier)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user