From c328a125337ab814f35298b1baaf0e99e249bb41 Mon Sep 17 00:00:00 2001 From: Lorenzune Date: Wed, 18 Mar 2026 17:01:10 +0100 Subject: [PATCH 01/11] fix(session): forward room chat extra params --- packages/session/src/handler/RoomChatHandler.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/session/src/handler/RoomChatHandler.ts b/packages/session/src/handler/RoomChatHandler.ts index cc17a8b..41aa2b0 100644 --- a/packages/session/src/handler/RoomChatHandler.ts +++ b/packages/session/src/handler/RoomChatHandler.ts @@ -54,7 +54,7 @@ export class RoomChatHandler extends BaseHandler if(!parser) return; - GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, parser.giverUserId, '', RoomSessionChatEvent.CHAT_TYPE_HAND_ITEM_RECEIVED, SystemChatStyleEnum.GENERIC, [], parser.handItemType)); + GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, parser.giverUserId, '', RoomSessionChatEvent.CHAT_TYPE_HAND_ITEM_RECEIVED, SystemChatStyleEnum.GENERIC, [], null, parser.handItemType)); } private onRespectReceivedEvent(event: RespectReceivedEvent): void @@ -136,7 +136,7 @@ export class RoomChatHandler extends BaseHandler break; } - GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, petData.roomIndex, '', chatType, SystemChatStyleEnum.GENERIC, null, userRoomIndex)); + GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, petData.roomIndex, '', chatType, SystemChatStyleEnum.GENERIC, [], null, userRoomIndex)); } private onFloodControlEvent(event: FloodControlEvent): void @@ -168,6 +168,6 @@ export class RoomChatHandler extends BaseHandler if(!parser) return; - GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, session.ownRoomIndex, '', RoomSessionChatEvent.CHAT_TYPE_MUTE_REMAINING, SystemChatStyleEnum.GENERIC, [], parser.seconds)); + GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, session.ownRoomIndex, '', RoomSessionChatEvent.CHAT_TYPE_MUTE_REMAINING, SystemChatStyleEnum.GENERIC, [], null, parser.seconds)); } } From 00743a3865bb5a3596ec6b08e3b5b4809335175d Mon Sep 17 00:00:00 2001 From: Lorenzune Date: Tue, 17 Mar 2026 01:34:51 +0100 Subject: [PATCH 02/11] feat(room): add single-click user packet for wired trigger - add ClickUserMessageComposer and outgoing header wiring\n- send the user click packet from RoomObjectEventHandler for avatar single clicks\n- support wf_trg_click_user in the linked Nitro UI/emulator flow --- packages/communication/src/NitroMessages.ts | 2 ++ .../src/messages/outgoing/OutgoingHeader.ts | 1 + .../room/engine/ClickUserMessageComposer.ts | 21 +++++++++++++++++++ .../messages/outgoing/room/engine/index.ts | 1 + packages/room/src/RoomObjectEventHandler.ts | 13 ++++++++---- 5 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 packages/communication/src/messages/outgoing/room/engine/ClickUserMessageComposer.ts diff --git a/packages/communication/src/NitroMessages.ts b/packages/communication/src/NitroMessages.ts index 7d61b36..ec3e632 100644 --- a/packages/communication/src/NitroMessages.ts +++ b/packages/communication/src/NitroMessages.ts @@ -1,5 +1,6 @@ import { IMessageConfiguration } from '@nitrots/api'; import { AcceptFriendMessageComposer, AcceptFriendResultEvent, AcceptGameInviteMessageComposer, AcceptQuestMessageComposer, AccountSafetyLockStatusChangeMessageEvent, AchievementEvent, AchievementNotificationMessageEvent, AchievementResolutionCompletedMessageEvent, AchievementResolutionProgressMessageEvent, AchievementResolutionsMessageEvent, AchievementsEvent, AchievementsScoreEvent, ActivateQuestMessageComposer, ActivityPointNotificationMessageEvent, AddFavouriteRoomMessageComposer, AddJukeboxDiskComposer, AddSpamWallPostItMessageComposer, ApplySnapshotMessageComposer, ApplyTonerComposer, ApproveAllMembershipRequestsMessageComposer, ApproveNameMessageComposer, ApproveNameMessageEvent, AreaHideMessageEvent, AuthenticatedEvent, AuthenticationMessageComposer, AvailabilityStatusMessageEvent, AvailabilityTimeMessageEvent, AvatarEffectActivatedComposer, AvatarEffectActivatedEvent, AvatarEffectAddedEvent, AvatarEffectExpiredEvent, AvatarEffectSelectedComposer, AvatarEffectSelectedEvent, AvatarEffectsEvent, BadgePointLimitsEvent, BadgeReceivedEvent, BadgesEvent, BannedUsersFromRoomEvent, BonusRareInfoMessageEvent, BotAddedToInventoryEvent, BotCommandConfigurationEvent, BotErrorEvent, BotForceOpenContextMenuEvent, BotInventoryMessageEvent, BotPlaceComposer, BotReceivedMessageEvent, BotRemoveComposer, BotRemovedFromInventoryEvent, BotSkillListUpdateEvent, BotSkillSaveComposer, BreedPetsMessageComposer, BuildersClubFurniCountMessageEvent, BuildersClubPlaceRoomItemMessageComposer, BuildersClubPlaceWallItemMessageComposer, BuildersClubQueryFurniCountMessageComposer, BuildersClubSubscriptionStatusMessageEvent, BundleDiscountRulesetMessageEvent, BuyMarketplaceOfferMessageComposer, BuyMarketplaceTokensMessageComposer, CallForHelpDisabledNotifyMessageEvent, CallForHelpFromForumMessageMessageComposer, CallForHelpFromForumThreadMessageComposer, CallForHelpFromIMMessageComposer, CallForHelpFromPhotoMessageComposer, CallForHelpFromSelfieMessageComposer, CallForHelpMessageComposer, CallForHelpPendingCallsDeletedMessageEvent, CallForHelpPendingCallsMessageEvent, CallForHelpReplyMessageEvent, CallForHelpResultMessageEvent, CameraPublishStatusMessageEvent, CameraPurchaseOKMessageEvent, CameraSnapshotMessageEvent, CameraStorageUrlMessageEvent, CampaignCalendarDataMessageEvent, CampaignCalendarDoorOpenedMessageEvent, CanCreateRoomEvent, CanCreateRoomEventEvent, CanCreateRoomMessageComposer, CancelEventMessageComposer, CancelMarketplaceOfferMessageComposer, CancelMysteryBoxWaitMessageEvent, CancelPetBreedingComposer, CancelQuestMessageComposer, CatalogGroupsComposer, CatalogPageExpirationEvent, CatalogPageMessageEvent, CatalogPageWithEarliestExpiryMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, CategoriesWithVisitorCountEvent, CfhChatlogEvent, CfhSanctionMessageEvent, CfhTopicsInitEvent, ChangeEmailComposer, ChangeEmailResultEvent, ChangeQueueMessageComposer, ChangeUserNameMessageComposer, ChangeUserNameResultMessageEvent, ChatReviewGuideDecidesOnOfferMessageComposer, ChatReviewGuideDetachedMessageComposer, ChatReviewGuideVoteMessageComposer, ChatReviewSessionCreateMessageComposer, ChatReviewSessionDetachedMessageEvent, ChatReviewSessionOfferedToGuideMessageEvent, ChatReviewSessionResultsMessageEvent, ChatReviewSessionStartedMessageEvent, ChatReviewSessionVotingStatusMessageEvent, CheckUserNameMessageComposer, CheckUserNameResultMessageEvent, ClickFurniMessageComposer, ClientHelloMessageComposer, ClientPingEvent, CloseIssueDefaultActionMessageComposer, CloseIssuesMessageComposer, ClubGiftInfoEvent, ClubGiftNotificationEvent, ClubGiftSelectedEvent, CommunityGoalEarnedPrizesMessageEvent, CommunityGoalHallOfFameMessageEvent, CommunityGoalProgressMessageEvent, CommunityGoalVoteMessageComposer, CommunityGoalVoteMessageEvent, CompetitionEntrySubmitResultEvent, CompetitionRoomsDataMessageEvent, CompetitionRoomsSearchMessageComposer, CompetitionStatusMessageEvent, CompetitionVotingInfoMessageEvent, CompleteDiffieHandshakeEvent, CompleteDiffieHandshakeMessageComposer, CompostPlantMessageComposer, ConcurrentUsersGoalProgressMessageEvent, ConfirmPetBreedingComposer, ConnectionErrorEvent, ControlYoutubeDisplayPlaybackMessageComposer, ConvertGlobalRoomIdMessageComposer, ConvertedRoomIdEvent, CraftComposer, CraftSecretComposer, CraftableProductsEvent, CraftingRecipeEvent, CraftingRecipesAvailableEvent, CraftingResultEvent, CreateFlatMessageComposer, CurrentTimingCodeMessageEvent, CustomUserNotificationMessageEvent, DeclineFriendMessageComposer, DefaultSanctionMessageComposer, DeleteFavouriteRoomMessageComposer, DeleteItemMessageComposer, DeleteBadgeMessageComposer, DeletePetMessageComposer, DeletePendingCallsForHelpMessageComposer, DesktopViewComposer, DesktopViewEvent, DiceValueMessageEvent, DirectSMSClubBuyAvailableMessageEvent, DisconnectMessageComposer, DisconnectReasonEvent, DoorbellMessageEvent, EditEventMessageComposer, ElementPointerMessageEvent, EmailStatusResultEvent, EpicPopupMessageEvent, ExtendRentOrBuyoutFurniMessageComposer, ExtendRentOrBuyoutStripItemMessageComposer, ExtendedProfileChangedMessageEvent, FavoriteMembershipUpdateMessageEvent, FavouriteChangedEvent, FavouritesEvent, FigureSetIdsMessageEvent, FigureUpdateEvent, FindFriendsProcessResultEvent, FindNewFriendsMessageComposer, FireworkChargeDataEvent, FlatAccessDeniedMessageEvent, FlatControllerAddedEvent, FlatControllerRemovedEvent, FlatControllersEvent, FlatCreatedEvent, FloodControlEvent, FloorHeightMapEvent, FollowFriendFailedEvent, FollowFriendMessageComposer, ForumDataMessageEvent, ForumsListMessageEvent, ForwardToACompetitionRoomMessageComposer, ForwardToARandomPromotedRoomMessageComposer, ForwardToASubmittableRoomMessageComposer, ForwardToRandomCompetitionRoomMessageComposer, ForwardToSomeRoomMessageComposer, FriendFurniConfirmLockMessageComposer, FriendListFragmentEvent, FriendListUpdateComposer, FriendListUpdateEvent, FriendNotificationEvent, FriendRequestQuestCompleteMessageComposer, FriendRequestsEvent, FurniRentOrBuyoutOfferMessageEvent, FurnitureAliasesComposer, FurnitureAliasesEvent, FurnitureColorWheelComposer, FurnitureDataEvent, FurnitureDiceActivateComposer, FurnitureDiceDeactivateComposer, FurnitureExchangeComposer, FurnitureFloorAddEvent, FurnitureFloorEvent, FurnitureFloorRemoveEvent, FurnitureFloorUpdateComposer, FurnitureFloorUpdateEvent, FurnitureGroupInfoComposer, FurnitureListAddOrUpdateEvent, FurnitureListComposer, FurnitureListEvent, FurnitureListInvalidateEvent, FurnitureListRemovedEvent, FurnitureMannequinSaveLookComposer, FurnitureMannequinSaveNameComposer, FurnitureMultiStateComposer, FurnitureOneWayDoorComposer, FurniturePickupComposer, FurniturePickupAllComposer, FurniturePlaceComposer, FurniturePlacePaintComposer, FurniturePostItPlaceComposer, FurniturePostItPlacedEvent, FurnitureRandomStateComposer, FurnitureStackHeightComposer, FurnitureStackHeightEvent, FurnitureWallAddEvent, FurnitureWallEvent, FurnitureWallMultiStateComposer, FurnitureWallRemoveEvent, FurnitureWallUpdateComposer, FurnitureWallUpdateEvent, Game2AccountGameStatusMessageEvent, Game2CheckGameDirectoryStatusMessageComposer, Game2ExitGameMessageComposer, Game2GameChatMessageComposer, Game2GameDirectoryStatusMessageEvent, Game2GetAccountGameStatusMessageComposer, Game2GetWeeklyFriendsLeaderboardComposer, Game2GetWeeklyLeaderboardComposer, Game2InArenaQueueMessageEvent, Game2JoiningGameFailedMessageEvent, Game2LoadStageReadyMessageComposer, Game2PlayAgainMessageComposer, Game2RequestFullStatusUpdateMessageComposer, Game2StartingGameFailedMessageEvent, Game2StopCounterMessageEvent, Game2UserLeftGameMessageEvent, Game2WeeklyFriendsLeaderboardEvent, Game2WeeklyLeaderboardEvent, GameAchievementsMessageEvent, GameInviteMessageEvent, GameListMessageEvent, GameStatusMessageEvent, GameUnloadedMessageComposer, GenericErrorEvent, GetBadgePointLimitsComposer, GetBonusRareInfoMessageComposer, GetBotInventoryComposer, GetBundleDiscountRulesetComposer, GetCatalogIndexComposer, GetCatalogPageComposer, GetCatalogPageExpirationComposer, GetCatalogPageWithEarliestExpiryComposer, GetCategoriesWithUserCountMessageComposer, GetCfhChatlogMessageComposer, GetCfhStatusMessageComposer, GetClubGiftInfo, GetClubOffersMessageComposer, GetCommunityGoalEarnedPrizesMessageComposer, GetCommunityGoalHallOfFameMessageComposer, GetCommunityGoalProgressMessageComposer, GetConcurrentUsersGoalProgressMessageComposer, GetConcurrentUsersRewardMessageComposer, GetCraftableProductsComposer, GetCraftingRecipeComposer, GetCraftingRecipesAvailableComposer, GetCurrentTimingCodeMessageComposer, GetCustomRoomFilterMessageComposer, GetDailyQuestMessageComposer, GetDirectClubBuyAvailableComposer, GetEmailStatusComposer, GetExtendedProfileByNameMessageComposer, GetFaqCategoryMessageComposer, GetFaqTextMessageComposer, GetForumStatsMessageComposer, GetForumsListMessageComposer, GetFriendRequestsComposer, GetGameAchievementsMessageComposer, GetGameListMessageComposer, GetGameStatusMessageComposer, GetGiftMessageComposer, GetGiftWrappingConfigurationComposer, GetGuestRoomMessageComposer, GetGuestRoomResultEvent, GetGuideReportingStatusMessageComposer, GetHabboBasicMembershipExtendOfferComposer, GetHabboClubExtendOfferMessageComposer, GetHabboGroupBadgesMessageComposer, GetIgnoredUsersComposer, GetInterstitialMessageComposer, GetIsBadgeRequestFulfilledComposer, GetIsOfferGiftableComposer, GetIsUserPartOfCompetitionMessageComposer, GetItemDataComposer, GetJukeboxPlayListMessageComposer, GetLimitedOfferAppearingNextComposer, GetMarketplaceCanMakeOfferComposer, GetMarketplaceConfigurationMessageComposer, GetMarketplaceItemStatsComposer, GetMarketplaceOffersMessageComposer, GetMarketplaceOwnOffersMessageComposer, GetMessagesMessageComposer, GetModeratorRoomInfoMessageComposer, GetModeratorUserInfoMessageComposer, GetNextTargetedOfferComposer, GetNowPlayingMessageComposer, GetOccupiedTilesMessageComposer, GetOfficialRoomsMessageComposer, GetOfficialSongIdMessageComposer, GetPendingCallsForHelpMessageComposer, GetPetCommandsComposer, GetPopularRoomTagsMessageComposer, GetProductOfferComposer, GetPromoArticlesComposer, GetQuestsMessageComposer, GetQuizQuestionsComposer, GetRecyclerStatusMessageComposer, GetRentOrBuyoutOfferMessageComposer, GetResolutionAchievementsMessageComposer, GetRoomAdPurchaseInfoComposer, GetRoomChatlogMessageComposer, GetRoomEntryDataMessageComposer, GetRoomEntryTileMessageComposer, GetRoomVisitsMessageComposer, GetSeasonalCalendarDailyOfferComposer, GetSeasonalQuestsOnlyMessageComposer, GetSecondsUntilMessageComposer, GetSellablePetPalettesComposer, GetSongInfoMessageComposer, GetSoundMachinePlayListMessageComposer, GetSoundSettingsComposer, GetTalentTrackLevelMessageComposer, GetTargetedOfferComposer, GetThreadMessageComposer, GetThreadsMessageComposer, GetUnreadForumsCountMessageComposer, GetUserChatlogMessageComposer, GetUserEventCatsMessageComposer, GetUserFlatCatsMessageComposer, GetUserGameAchievementsMessageComposer, GetUserSongDisksMessageComposer, GetUserTagsComposer, GetWardrobeMessageComposer, GetWeeklyGameRewardComposer, GetWeeklyGameRewardWinnersComposer, GetYoutubeDisplayStatusMessageComposer, GiftReceiverNotFoundEvent, GiftWrappingConfigurationEvent, GoToFlatMessageComposer, GotMysteryBoxPrizeMessageEvent, GroupAdminGiveComposer, GroupAdminTakeComposer, GroupBadgePartsComposer, GroupBadgePartsEvent, GroupBuyComposer, GroupBuyDataComposer, GroupBuyDataEvent, GroupConfirmMemberRemoveEvent, GroupConfirmRemoveMemberComposer, GroupDeleteComposer, GroupDetailsChangedMessageEvent, GroupFavoriteComposer, GroupFurniContextMenuInfoMessageEvent, GroupInformationComposer, GroupInformationEvent, GroupJoinComposer, GroupMembersComposer, GroupMembersEvent, GroupMembershipAcceptComposer, GroupMembershipDeclineComposer, GroupMembershipRequestedMessageEvent, GroupPurchasedEvent, GroupRemoveMemberComposer, GroupSaveBadgeComposer, GroupSaveColorsComposer, GroupSaveInformationComposer, GroupSavePreferencesComposer, GroupSettingsComposer, GroupSettingsEvent, GroupUnfavoriteComposer, GuestRoomSearchResultEvent, GuideOnDutyStatusMessageEvent, GuideReportingStatusMessageEvent, GuideSessionAttachedMessageEvent, GuideSessionCreateMessageComposer, GuideSessionDetachedMessageEvent, GuideSessionEndedMessageEvent, GuideSessionErrorMessageEvent, GuideSessionFeedbackMessageComposer, GuideSessionGetRequesterRoomMessageComposer, GuideSessionGuideDecidesMessageComposer, GuideSessionInviteRequesterMessageComposer, GuideSessionInvitedToGuideRoomMessageEvent, GuideSessionIsTypingMessageComposer, GuideSessionMessageMessageComposer, GuideSessionMessageMessageEvent, GuideSessionOnDutyUpdateMessageComposer, GuideSessionPartnerIsTypingMessageEvent, GuideSessionReportMessageComposer, GuideSessionRequesterCancelsMessageComposer, GuideSessionRequesterRoomMessageEvent, GuideSessionResolvedMessageComposer, GuideSessionStartedMessageEvent, GuideTicketCreationResultMessageEvent, GuideTicketResolutionMessageEvent, GuildBaseSearchMessageComposer, GuildEditFailedMessageEvent, GuildForumThreadsEvent, GuildMemberMgmtFailedMessageEvent, GuildMembershipsMessageEvent, HabboBroadcastMessageEvent, HabboClubExtendOfferMessageEvent, HabboClubOffersMessageEvent, HabboGroupBadgesMessageEvent, HabboGroupDeactivatedMessageEvent, HabboGroupJoinFailedMessageEvent, HabboSearchComposer, HabboSearchResultEvent, HarvestPetMessageComposer, HotelClosedAndOpensEvent, HotelClosesAndWillOpenAtEvent, HotelMergeNameChangeEvent, HotelWillCloseInMinutesEvent, IdentityAccountsEvent, IgnoreResultEvent, IgnoreUserComposer, IgnoreUserIdComposer, IgnoredUsersEvent, InClientLinkEvent, IncomingHeader, InfoFeedEnableMessageEvent, InfoRetrieveMessageComposer, InitCameraMessageEvent, InitDiffieHandshakeEvent, InitDiffieHandshakeMessageComposer, InstantMessageErrorEvent, InterstitialMessageEvent, InterstitialShownMessageComposer, IsBadgeRequestFulfilledEvent, IsOfferGiftableMessageEvent, IsUserPartOfCompetitionMessageEvent, IssueCloseNotificationMessageEvent, IssueDeletedMessageEvent, IssueInfoMessageEvent, IssuePickFailedMessageEvent, ItemDataUpdateMessageEvent, JoinQueueMessageComposer, JoinedQueueMessageEvent, JoiningQueueFailedMessageEvent, JukeboxPlayListFullMessageEvent, JukeboxSongDisksMessageEvent, LagWarningReportMessageComposer, LeaveQueueMessageComposer, LeftQueueMessageEvent, LimitedEditionSoldOutEvent, LimitedOfferAppearingNextMessageEvent, LoadGameMessageEvent, LoadGameUrlEvent, LoveLockFurniFinishedEvent, LoveLockFurniFriendConfirmedEvent, LoveLockFurniStartEvent, MOTDNotificationEvent, MaintenanceStatusMessageEvent, MakeOfferMessageComposer, MarkCatalogNewAdditionsPageOpenedComposer, MarketPlaceOffersEvent, MarketplaceBuyOfferResultEvent, MarketplaceCanMakeOfferResult, MarketplaceCancelOfferResultEvent, MarketplaceConfigurationEvent, MarketplaceItemStatsEvent, MarketplaceMakeOfferResult, MarketplaceOwnOffersEvent, MessageErrorEvent, MessengerInitComposer, MessengerInitEvent, MiniMailNewMessageEvent, MiniMailUnreadCountEvent, ModAlertMessageComposer, ModBanMessageComposer, ModKickMessageComposer, ModMessageMessageComposer, ModMuteMessageComposer, ModToolPreferencesComposer, ModToolSanctionComposer, ModTradingLockMessageComposer, ModerateMessageMessageComposer, ModerateRoomMessageComposer, ModerateThreadMessageComposer, ModeratorActionMessageComposer, ModeratorActionResultMessageEvent, ModeratorCautionEvent, ModeratorInitMessageEvent, ModeratorMessageEvent, ModeratorRoomInfoEvent, ModeratorToolPreferencesEvent, ModeratorUserInfoEvent, MoodlightSettingsComposer, MoodlightSettingsSaveComposer, MoodlightTogggleStateComposer, MuteAllInRoomEvent, MyFavouriteRoomsSearchMessageComposer, MyFrequentRoomHistorySearchMessageComposer, MyFriendsRoomsSearchMessageComposer, MyGuildBasesSearchMessageComposer, MyRecommendedRoomsMessageComposer, MyRoomHistorySearchMessageComposer, MyRoomRightsSearchMessageComposer, MyRoomsSearchMessageComposer, MysteryBoxKeysEvent, MysteryBoxWaitingCanceledMessageComposer, NavigatorCategoryListModeComposer, NavigatorCollapsedEvent, NavigatorDeleteSavedSearchComposer, NavigatorHomeRoomEvent, NavigatorInitComposer, NavigatorLiftedEvent, NavigatorMetadataEvent, NavigatorOpenRoomCreatorEvent, NavigatorSearchCloseComposer, NavigatorSearchComposer, NavigatorSearchEvent, NavigatorSearchOpenComposer, NavigatorSearchSaveComposer, NavigatorSearchesEvent, NavigatorSettingsEvent, NavigatorSettingsSaveComposer, NewConsoleMessageEvent, NewFriendRequestEvent, NewUserExperienceGetGiftsComposer, NewUserExperienceGiftOfferMessageEvent, NewUserExperienceNotCompleteEvent, NewUserExperienceScriptProceedComposer, NoOwnedRoomsAlertMessageEvent, NoSuchFlatEvent, NoobnessLevelMessageEvent, NotEnoughBalanceMessageEvent, NotificationDialogMessageEvent, NowPlayingMessageEvent, ObjectsDataUpdateEvent, ObjectsRollingEvent, OfferRewardDeliveredMessageEvent, OfficialSongIdMessageEvent, OneWayDoorStatusMessageEvent, OpenCampaignCalendarDoorAsStaffComposer, OpenCampaignCalendarDoorComposer, OpenMessageComposer, OpenMysteryTrophyMessageComposer, OpenPetPackageMessageComposer, OpenPetPackageRequestedMessageEvent, OpenPetPackageResultMessageEvent, OpenPresentComposer, OpenQuestTrackerMessageComposer, OpenWelcomeGiftComposer, OutgoingHeader, PeerUsersClassificationMessageComposer, PerformanceLogMessageComposer, PerkAllowancesMessageEvent, PetAddedToInventoryEvent, PetBreedingResultEvent, PetExperienceEvent, PetFigureUpdateEvent, PetInfoEvent, PetInventoryEvent, PetLevelNotificationEvent, PetLevelUpdateMessageEvent, PetMountComposer, PetMoveComposer, PetPlaceComposer, PetPlacingErrorEvent, PetReceivedMessageEvent, PetRemoveComposer, PetRemovedFromInventory, PetRespectComposer, PetRespectNoficationEvent, PetScratchFailedMessageEvent, PetSelectedMessageComposer, PetStatusUpdateEvent, PetSupplementComposer, PetSupplementedNotificationEvent, PetTrainingPanelMessageEvent, PhoneCollectionStateMessageEvent, PhotoCompetitionMessageComposer, PickIssuesMessageComposer, PlayListMessageEvent, PlayListSongAddedMessageEvent, PollAnswerComposer, PollContentsEvent, PollErrorEvent, PollOfferEvent, PollRejectComposer, PollStartComposer, PongMessageComposer, PopularRoomTagsResultEvent, PopularRoomsSearchMessageComposer, PostMessageMessageComposer, PostMessageMessageEvent, PostQuizAnswersComposer, PostThreadMessageEvent, PresentOpenedMessageEvent, ProductOfferEvent, PromoArticlesMessageEvent, PublishPhotoMessageComposer, PurchaseBasicMembershipExtensionComposer, PurchaseErrorMessageEvent, PurchaseFromCatalogAsGiftComposer, PurchaseFromCatalogComposer, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, PurchasePhotoMessageComposer, PurchaseRoomAdMessageComposer, PurchaseTargetedOfferComposer, PurchaseVipMembershipExtensionComposer, QuestCancelledMessageEvent, QuestCompletedMessageEvent, QuestDailyMessageEvent, QuestMessageEvent, QuestionAnsweredEvent, QuestionEvent, QuestionFinishedEvent, QuestsMessageEvent, QuizDataMessageEvent, QuizResultsMessageEvent, RateFlatMessageComposer, RecycleItemsMessageComposer, RecyclerFinishedMessageEvent, RecyclerStatusMessageEvent, RedeemCommunityGoalPrizeMessageComposer, RedeemItemClothingComposer, RedeemMarketplaceOfferCreditsMessageComposer, RedeemVoucherMessageComposer, RejectQuestMessageComposer, RelationshipStatusInfoEvent, ReleaseIssuesMessageComposer, RemainingMuteEvent, RemoveAllRightsMessageComposer, RemoveFriendComposer, RemoveJukeboxDiskComposer, RemoveOwnRoomRightsRoomMessageComposer, RemovePetSaddleComposer, RemoveWallItemComposer, RenderRoomMessageComposer, RenderRoomThumbnailMessageComposer, RentableSpaceCancelRentMessageComposer, RentableSpaceRentFailedMessageEvent, RentableSpaceRentMessageComposer, RentableSpaceRentOkMessageEvent, RentableSpaceStatusMessageComposer, RentableSpaceStatusMessageEvent, RequestABadgeComposer, RequestAchievementsMessageComposer, RequestBadgesComposer, RequestBotCommandConfigurationComposer, RequestCameraConfigurationComposer, RequestFriendComposer, RequestFurniInventoryWhenNotInRoomComposer, RequestPetInfoComposer, RequestPetsComposer, RequestSpamWallPostItMessageEvent, ResetPhoneNumberStateMessageComposer, ResetResolutionAchievementMessageComposer, RespectReceivedEvent, RestoreClientMessageEvent, RoomAdErrorEvent, RoomAdEventTabAdClickedComposer, RoomAdEventTabViewedComposer, RoomAdPurchaseInfoEvent, RoomAdPurchaseInitiatedComposer, RoomAdSearchMessageComposer, RoomAmbassadorAlertComposer, RoomBanUserComposer, RoomBannedUsersComposer, RoomChatSettingsEvent, RoomChatlogEvent, RoomCompetitionInitMessageComposer, RoomDeleteComposer, RoomDimmerPresetsEvent, RoomDoorbellAcceptedEvent, RoomDoorbellAccessComposer, RoomEnterComposer, RoomEnterErrorEvent, RoomEnterEvent, RoomEntryInfoMessageEvent, RoomEntryTileMessageEvent, RoomEventCancelEvent, RoomEventEvent, RoomFilterSettingsMessageEvent, RoomForwardEvent, RoomGiveRightsComposer, RoomHeightMapEvent, RoomHeightMapUpdateEvent, RoomInviteErrorEvent, RoomInviteEvent, RoomKickUserComposer, RoomMessageNotificationMessageEvent, RoomMuteComposer, RoomMuteUserComposer, RoomNetworkOpenConnectionMessageComposer, RoomOccupiedTilesMessageEvent, RoomPaintEvent, RoomPollResultEvent, RoomReadyMessageEvent, RoomRightsClearEvent, RoomRightsEvent, RoomRightsOwnerEvent, RoomScoreEvent, RoomSettingsComposer, RoomSettingsDataEvent, RoomSettingsErrorEvent, RoomSettingsSaveErrorEvent, RoomSettingsSavedEvent, RoomSettingsUpdatedEvent, RoomTakeRightsComposer, RoomTextSearchMessageComposer, RoomThumbnailUpdateResultEvent, RoomUnbanUserComposer, RoomUnitActionComposer, RoomUnitBackgroundComposer, RoomUnitChatComposer, RoomUnitChatEvent, RoomUnitChatShoutComposer, RoomUnitChatShoutEvent, RoomUnitChatStyleComposer, RoomUnitChatWhisperComposer, RoomUnitChatWhisperEvent, RoomUnitDanceComposer, RoomUnitDanceEvent, RoomUnitDropHandItemComposer, RoomUnitEffectEvent, RoomUnitEvent, RoomUnitExpressionEvent, RoomUnitGiveHandItemComposer, RoomUnitGiveHandItemPetComposer, RoomUnitHandItemEvent, RoomUnitHandItemReceivedEvent, RoomUnitIdleEvent, RoomUnitInfoEvent, RoomUnitLookComposer, RoomUnitNumberEvent, RoomUnitPostureComposer, RoomUnitRemoveEvent, RoomUnitSignComposer, RoomUnitStatusEvent, RoomUnitTypingEvent, RoomUnitTypingStartComposer, RoomUnitTypingStopComposer, RoomUnitWalkComposer, RoomUsersClassificationMessageComposer, RoomUsersWithRightsComposer, RoomVisitsEvent, RoomVisualizationSettingsEvent, RoomsWhereMyFriendsAreSearchMessageComposer, RoomsWithHighestScoreSearchMessageComposer, SSOTicketMessageComposer, SanctionStatusEvent, SaveRoomSettingsComposer, SaveWardrobeOutfitMessageComposer, ScrGetKickbackInfoMessageComposer, ScrSendKickbackInfoMessageEvent, SearchFaqsMessageComposer, SeasonalCalendarDailyOfferMessageEvent, SeasonalQuestsMessageEvent, SecondsUntilMessageEvent, SelectClubGiftComposer, SellablePetPalettesMessageEvent, SendMessageComposer, SendRoomInviteComposer, SetActivatedBadgesComposer, SetClothingChangeDataMessageComposer, SetItemDataMessageComposer, SetObjectDataMessageComposer, SetPhoneNumberVerificationStatusMessageComposer, SetRelationshipStatusComposer, SetRoomSessionTagsMessageComposer, SetTargetedOfferStateComposer, SetYoutubeDisplayPlaylistMessageComposer, ShopTargetedOfferViewedComposer, ShowEnforceRoomCategoryDialogEvent, ShowMysteryBoxWaitMessageEvent, SimpleAlertMessageEvent, StartCampaignMessageComposer, StartRoomPollEvent, SubmitRoomToCompetitionMessageComposer, TalentLevelUpEvent, TalentTrackComposer, TalentTrackLevelMessageEvent, TalentTrackMessageEvent, TargetedOfferEvent, TargetedOfferNotFoundEvent, ThreadMessagesMessageEvent, ThumbnailStatusMessageEvent, TogglePetBreedingComposer, TogglePetRidingComposer, ToggleStaffPickMessageComposer, TradingAcceptComposer, TradingAcceptEvent, TradingCancelComposer, TradingCloseComposer, TradingCloseEvent, TradingCompletedEvent, TradingConfirmationComposer, TradingConfirmationEvent, TradingListAddItemComposer, TradingListAddItemsComposer, TradingListItemEvent, TradingListItemRemoveComposer, TradingNoSuchItemEvent, TradingNotOpenEvent, TradingOpenComposer, TradingOpenEvent, TradingOpenFailedEvent, TradingOtherNotAllowedEvent, TradingUnacceptComposer, TradingYouAreNotAllowedEvent, TraxSongInfoMessageEvent, TryPhoneNumberMessageComposer, TryPhoneNumberResultMessageEvent, TryVerificationCodeResultMessageEvent, UnblockGroupMemberMessageComposer, UnignoreUserComposer, UniqueIDMessageComposer, UnloadGameMessageEvent, UnreadForumsCountMessageEvent, UnseenItemsEvent, UnseenResetCategoryComposer, UnseenResetItemsComposer, UpdateActionMessageComposer, UpdateConditionMessageComposer, UpdateFloorPropertiesMessageComposer, UpdateForumReadMarkerMessageComposer, UpdateForumSettingsMessageComposer, UpdateFurniturePositionComposer, UpdateHomeRoomMessageComposer, UpdateMessageMessageEvent, UpdateRoomCategoryAndTradeSettingsComposer, UpdateRoomFilterMessageComposer, UpdateRoomThumbnailMessageComposer, UpdateThreadMessageComposer, UpdateThreadMessageEvent, UpdateTriggerMessageComposer, UsePetProductComposer, UserBannedMessageEvent, UserChatlogEvent, UserClassificationMessageEvent, UserCreditsEvent, UserCurrencyComposer, UserCurrencyEvent, UserCurrentBadgesComposer, UserCurrentBadgesEvent, UserEventCatsEvent, UserFigureComposer, UserFlatCatsEvent, UserGameAchievementsMessageEvent, UserInfoEvent, UserMottoComposer, UserNameChangeMessageEvent, UserPermissionsEvent, UserProfileComposer, UserProfileEvent, UserRelationshipsComposer, UserRespectComposer, UserSettingsCameraFollowComposer, UserSettingsEvent, UserSettingsOldChatComposer, UserSettingsRoomInvitesComposer, UserSettingsSoundComposer, UserSongDisksInventoryMessageEvent, UserSubscriptionComposer, UserSubscriptionEvent, UserTagsMessageEvent, UserUnbannedFromRoomEvent, UserWardrobePageEvent, VerifyCodeMessageComposer, VersionCheckMessageComposer, VisitUserComposer, VoteForRoomMessageComposer, VotePollCounterMessageComposer, VoucherRedeemErrorMessageEvent, VoucherRedeemOkMessageEvent, WardrobeMessageEvent, WeeklyCompetitiveFriendsLeaderboardEvent, WeeklyCompetitiveLeaderboardEvent, WeeklyGameRewardEvent, WeeklyGameRewardWinnersEvent, WelcomeGiftChangeEmailComposer, WelcomeGiftChangeEmailResultEvent, WelcomeGiftStatusEvent, WiredFurniActionEvent, WiredFurniConditionEvent, WiredFurniTriggerEvent, WiredOpenEvent, WiredRewardResultMessageEvent, WiredSaveSuccessEvent, WiredValidationErrorEvent, YouArePlayingGameEvent, YouAreSpectatorMessageEvent, YoutubeControlVideoMessageEvent, YoutubeDisplayPlaylistsEvent, YoutubeDisplayVideoMessageEvent } from './messages'; +import { ClickUserMessageComposer } from './messages'; export class NitroMessages implements IMessageConfiguration { @@ -580,6 +581,7 @@ export class NitroMessages implements IMessageConfiguration { // CUSTOM PACKETS this._composers.set(OutgoingHeader.CLICK_FURNI, ClickFurniMessageComposer); + this._composers.set(OutgoingHeader.CLICK_USER, ClickUserMessageComposer); // AUTHENTICATION this._composers.set(OutgoingHeader.AUTHENTICATION, AuthenticationMessageComposer); diff --git a/packages/communication/src/messages/outgoing/OutgoingHeader.ts b/packages/communication/src/messages/outgoing/OutgoingHeader.ts index 69f9061..f1d9b8f 100644 --- a/packages/communication/src/messages/outgoing/OutgoingHeader.ts +++ b/packages/communication/src/messages/outgoing/OutgoingHeader.ts @@ -1,6 +1,7 @@ export class OutgoingHeader { public static CLICK_FURNI = 6002; + public static CLICK_USER = 10020; public static ACHIEVEMENT_LIST = 219; public static AUTHENTICATION = -1; diff --git a/packages/communication/src/messages/outgoing/room/engine/ClickUserMessageComposer.ts b/packages/communication/src/messages/outgoing/room/engine/ClickUserMessageComposer.ts new file mode 100644 index 0000000..a59d16d --- /dev/null +++ b/packages/communication/src/messages/outgoing/room/engine/ClickUserMessageComposer.ts @@ -0,0 +1,21 @@ +import { IMessageComposer } from '@nitrots/api'; + +export class ClickUserMessageComposer implements IMessageComposer> +{ + private _data: ConstructorParameters; + + constructor(roomUnitId: number) + { + this._data = [ roomUnitId ]; + } + + public getMessageArray() + { + return this._data; + } + + public dispose(): void + { + return; + } +} diff --git a/packages/communication/src/messages/outgoing/room/engine/index.ts b/packages/communication/src/messages/outgoing/room/engine/index.ts index ebee1cd..a3aeb1a 100644 --- a/packages/communication/src/messages/outgoing/room/engine/index.ts +++ b/packages/communication/src/messages/outgoing/room/engine/index.ts @@ -2,6 +2,7 @@ export * from './BotPlaceComposer'; export * from './BotRemoveComposer'; export * from './BotSkillSaveComposer'; export * from './ClickFurniMessageComposer'; +export * from './ClickUserMessageComposer'; export * from './CompostPlantMessageComposer'; export * from './GetItemDataComposer'; export * from './HarvestPetMessageComposer'; diff --git a/packages/room/src/RoomObjectEventHandler.ts b/packages/room/src/RoomObjectEventHandler.ts index 2725f26..65ca483 100644 --- a/packages/room/src/RoomObjectEventHandler.ts +++ b/packages/room/src/RoomObjectEventHandler.ts @@ -1,5 +1,5 @@ import { IFurnitureStackingHeightMap, ILegacyWallGeometry, IObjectData, IRoomCanvasMouseListener, IRoomEngineServices, IRoomGeometry, IRoomObject, IRoomObjectController, IRoomObjectEventManager, ISelectedRoomObjectData, IVector3D, MouseEventType, RoomObjectCategory, RoomObjectOperationType, RoomObjectPlacementSource, RoomObjectType, RoomObjectUserType, RoomObjectVariable } from '@nitrots/api'; -import { BotPlaceComposer, ClickFurniMessageComposer, FurnitureColorWheelComposer, FurnitureDiceActivateComposer, FurnitureDiceDeactivateComposer, FurnitureFloorUpdateComposer, FurnitureGroupInfoComposer, FurnitureMultiStateComposer, FurnitureOneWayDoorComposer, FurniturePickupComposer, FurniturePlaceComposer, FurniturePostItPlaceComposer, FurnitureRandomStateComposer, FurnitureWallMultiStateComposer, FurnitureWallUpdateComposer, GetCommunication, GetItemDataComposer, GetResolutionAchievementsMessageComposer, PetMoveComposer, PetPlaceComposer, RemoveWallItemComposer, RoomUnitLookComposer, RoomUnitWalkComposer, SetItemDataMessageComposer, SetObjectDataMessageComposer } from '@nitrots/communication'; +import { BotPlaceComposer, ClickFurniMessageComposer, ClickUserMessageComposer, FurnitureColorWheelComposer, FurnitureDiceActivateComposer, FurnitureDiceDeactivateComposer, FurnitureFloorUpdateComposer, FurnitureGroupInfoComposer, FurnitureMultiStateComposer, FurnitureOneWayDoorComposer, FurniturePickupComposer, FurniturePlaceComposer, FurniturePostItPlaceComposer, FurnitureRandomStateComposer, FurnitureWallMultiStateComposer, FurnitureWallUpdateComposer, GetCommunication, GetItemDataComposer, GetResolutionAchievementsMessageComposer, PetMoveComposer, PetPlaceComposer, RemoveWallItemComposer, RoomUnitLookComposer, RoomUnitWalkComposer, SetItemDataMessageComposer, SetObjectDataMessageComposer } from '@nitrots/communication'; import { GetConfiguration } from '@nitrots/configuration'; import { GetEventDispatcher, RoomEngineDimmerStateEvent, RoomEngineObjectEvent, RoomEngineObjectPlacedEvent, RoomEngineObjectPlacedOnUserEvent, RoomEngineObjectPlaySoundEvent, RoomEngineRoomAdEvent, RoomEngineSamplePlaybackEvent, RoomEngineTriggerWidgetEvent, RoomEngineUseProductEvent, RoomObjectBadgeAssetEvent, RoomObjectDataRequestEvent, RoomObjectDimmerStateUpdateEvent, RoomObjectEvent, RoomObjectFloorHoleEvent, RoomObjectFurnitureActionEvent, RoomObjectHSLColorEnableEvent, RoomObjectHSLColorEnabledEvent, RoomObjectMouseEvent, RoomObjectMoveEvent, RoomObjectPlaySoundIdEvent, RoomObjectRoomAdEvent, RoomObjectSamplePlaybackEvent, RoomObjectSoundMachineEvent, RoomObjectStateChangedEvent, RoomObjectTileMouseEvent, RoomObjectWallMouseEvent, RoomObjectWidgetRequestEvent, RoomSpriteMouseEvent } from '@nitrots/events'; import { GetRoomSessionManager, GetSessionDataManager } from '@nitrots/session'; @@ -297,7 +297,7 @@ export class RoomObjectEventHandler implements IRoomCanvasMouseListener, IRoomOb } } - private clickRoomObject(event: RoomObjectMouseEvent): void + private clickRoomObject(event: RoomObjectMouseEvent, operation: string): void { if(!event || event.altKey || event.ctrlKey || event.shiftKey) return; @@ -319,20 +319,25 @@ export class RoomObjectEventHandler implements IRoomCanvasMouseListener, IRoomOb return; } + + if((category === RoomObjectCategory.UNIT) && (operation === RoomObjectOperationType.OBJECT_UNDEFINED) && (objectType === RoomObjectUserType.USER)) + { + GetCommunication().connection.send(new ClickUserMessageComposer(objectId)); + } } private handleRoomObjectMouseClickEvent(event: RoomObjectMouseEvent, roomId: number): void { if(!event) return; - this.clickRoomObject(event); - let operation = RoomObjectOperationType.OBJECT_UNDEFINED; const selectedData = this.getSelectedRoomObjectData(roomId); if(selectedData) operation = selectedData.operation; + this.clickRoomObject(event, operation); + let didWalk = false; let didMove = false; From 5929faf9c7338ba4f29cac177898fc17022fb9ac Mon Sep 17 00:00:00 2001 From: Lorenzune Date: Tue, 17 Mar 2026 03:28:05 +0100 Subject: [PATCH 03/11] fix(renderer): refine wired selection overlay - keep selected items fully opaque - blend only the wired overlay tint instead of lowering item alpha - improve readability for green primary and blue secondary wired highlights --- packages/utils/src/filters/WiredFilter.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/utils/src/filters/WiredFilter.ts b/packages/utils/src/filters/WiredFilter.ts index 303ae86..10bc8d0 100644 --- a/packages/utils/src/filters/WiredFilter.ts +++ b/packages/utils/src/filters/WiredFilter.ts @@ -63,13 +63,14 @@ export class WiredFilter extends Filter void main(void) { vec4 currentColor = texture(uTexture, vTextureCoord); - vec3 colorLine = uLineColor * currentColor.a; - vec3 colorOverlay = uColor * currentColor.a; + vec3 colorLine = uLineColor; + vec3 colorOverlay = uColor; if(currentColor.r == 0.0 && currentColor.g == 0.0 && currentColor.b == 0.0 && currentColor.a > 0.0) { finalColor = vec4(colorLine.r, colorLine.g, colorLine.b, currentColor.a); } else if(currentColor.a > 0.0) { - finalColor = vec4(colorOverlay.r, colorOverlay.g, colorOverlay.b, currentColor.a); + vec3 blendedOverlay = mix(currentColor.rgb, colorOverlay, 0.28); + finalColor = vec4(blendedOverlay.r, blendedOverlay.g, blendedOverlay.b, currentColor.a); } } `, From 31de6daac5ea8be0bf880be247ed8361008772bd Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Mon, 16 Mar 2026 22:08:37 +0100 Subject: [PATCH 04/11] Add real-time preview support to FloorplanEditor Add onTilemapChange callback that fires after every renderTiles() call, enabling the UI layer to react to tilemap mutations in real-time. Co-Authored-By: medievalshell --- packages/room/src/common/floorplan/FloorplanEditor.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/room/src/common/floorplan/FloorplanEditor.ts b/packages/room/src/common/floorplan/FloorplanEditor.ts index d6d2db2..1a5fae8 100644 --- a/packages/room/src/common/floorplan/FloorplanEditor.ts +++ b/packages/room/src/common/floorplan/FloorplanEditor.ts @@ -25,6 +25,8 @@ export class FloorplanEditor private _image: HTMLImageElement; + public onTilemapChange: (() => void) | null = null; + constructor() { const width = TILE_SIZE * MAX_NUM_TILE_PER_AXIS + 20; @@ -297,6 +299,8 @@ export class FloorplanEditor } this.renderSquareSelectionPreview(); + + if(this.onTilemapChange) this.onTilemapChange(); } private renderSquareSelectionPreview(): void @@ -473,6 +477,7 @@ export class FloorplanEditor this._squareSelectStart = null; this._squareSelectEnd = null; this.clearCanvas(); + this.onTilemapChange = null; } From 5b139dfef844dfc5bf1fbdd8865ce7853d954044 Mon Sep 17 00:00:00 2001 From: duckietm Date: Thu, 19 Mar 2026 09:40:49 +0100 Subject: [PATCH 05/11] =?UTF-8?q?=F0=9F=86=99=20Update=20better=20error=20?= =?UTF-8?q?handeling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/assets/src/AssetManager.ts | 70 +++++++++++++------ .../avatar/src/AvatarAssetDownloadManager.ts | 26 +++++-- packages/avatar/src/AvatarRenderManager.ts | 48 ++++++++++--- .../avatar/src/EffectAssetDownloadManager.ts | 26 +++++-- .../configuration/src/ConfigurationManager.ts | 37 ++++++++-- .../localization/src/LocalizationManager.ts | 30 ++++++-- .../src/furniture/FurnitureDataLoader.ts | 26 +++++-- .../session/src/product/ProductDataLoader.ts | 26 +++++-- packages/utils/src/NitroVersion.ts | 21 +++--- 9 files changed, 240 insertions(+), 70 deletions(-) diff --git a/packages/assets/src/AssetManager.ts b/packages/assets/src/AssetManager.ts index ac2731a..481408a 100644 --- a/packages/assets/src/AssetManager.ts +++ b/packages/assets/src/AssetManager.ts @@ -77,18 +77,9 @@ export class AssetManager implements IAssetManager { if(!urls || !urls.length) return Promise.resolve(true); - try - { - await Promise.all(urls.map(url => this.downloadAsset(url))); + await Promise.all(urls.map(url => this.downloadAsset(url))); - return true; - } - catch (err) - { - NitroLogger.error(err); - } - - return false; + return true; } public async downloadAsset(url: string): Promise @@ -123,9 +114,18 @@ export class AssetManager implements IAssetManager if(url.endsWith('.nitro') || url.endsWith('.gif')) { - const response = await fetch(url); + let response: Response; - if(!response || response.status !== 200) return false; + try + { + response = await fetch(url); + } + catch(fetchErr) + { + throw new Error(`Could not fetch "${ url }" — is the URL correct and the server reachable? (${ fetchErr.message })`); + } + + if(!response || response.status !== 200) throw new Error(`Failed to load "${ url }" — server returned HTTP ${ response?.status ?? 'no response' }`); const arrayBuffer = await response.arrayBuffer(); @@ -137,19 +137,47 @@ export class AssetManager implements IAssetManager } else { - const animatedGif = AnimatedGIF.fromBuffer(arrayBuffer); - const texture = animatedGif.texture; + try + { + const animatedGif = AnimatedGIF.fromBuffer(arrayBuffer); + const texture = animatedGif.texture; - if(texture) this.setTexture(url, texture); + if(texture) this.setTexture(url, texture); + } + catch(gifErr) + { + const texture = await Assets.load(url); + + if(texture) this.setTexture(url, texture); + } } } else if(url.endsWith('.json')) { - const response = await fetch(url); + let response: Response; - if(!response || response.status !== 200) return false; + try + { + response = await fetch(url); + } + catch(fetchErr) + { + throw new Error(`Could not fetch "${ url }" — is the URL correct and the server reachable? (${ fetchErr.message })`); + } + + if(!response || response.status !== 200) throw new Error(`Failed to load "${ url }" — server returned HTTP ${ response?.status ?? 'no response' }`); + + let data: IAssetData; + + try + { + data = await response.json() as IAssetData; + } + catch(parseErr) + { + throw new Error(`Invalid JSON in "${ url }" — the URL may be wrong and returning an HTML page instead of JSON (${ parseErr.message })`); + } - const data = await response.json() as IAssetData; let texture: Texture = null; const imagePath = data?.spritesheet?.meta?.image; const fallbackImagePath = ((data?.name && data.name.length > 0) @@ -174,9 +202,7 @@ export class AssetManager implements IAssetManager } catch (err) { - NitroLogger.error(err); - - return false; + throw new Error(`Asset loading failed for "${ url }": ${ err.message || err }`); } } diff --git a/packages/avatar/src/AvatarAssetDownloadManager.ts b/packages/avatar/src/AvatarAssetDownloadManager.ts index 982023b..347108f 100644 --- a/packages/avatar/src/AvatarAssetDownloadManager.ts +++ b/packages/avatar/src/AvatarAssetDownloadManager.ts @@ -29,13 +29,31 @@ export class AvatarAssetDownloadManager const url = GetConfiguration().getValue('avatar.figuremap.url'); - if(!url || !url.length) throw new Error('Invalid figure map url'); + if(!url || !url.length) throw new Error('Missing "avatar.figuremap.url" in config — add the figure map URL to your renderer-config.json'); - const response = await fetch(url); + let response: Response; - if(response.status !== 200) throw new Error('Invalid figure map file'); + try + { + response = await fetch(url); + } + catch(fetchErr) + { + throw new Error(`Could not fetch figure map from "${ url }" — check "avatar.figuremap.url" in renderer-config.json (${ fetchErr.message })`); + } - const responseData = await response.json(); + if(response.status !== 200) throw new Error(`Failed to load figure map from "${ url }" — server returned HTTP ${ response.status }. Check "avatar.figuremap.url" in renderer-config.json`); + + let responseData: any; + + try + { + responseData = await response.json(); + } + catch(parseErr) + { + throw new Error(`Invalid JSON in figure map "${ url }" — the URL may be wrong. Check "avatar.figuremap.url" in renderer-config.json (${ parseErr.message })`); + } this.processFigureMap(responseData.libraries); diff --git a/packages/avatar/src/AvatarRenderManager.ts b/packages/avatar/src/AvatarRenderManager.ts index aa7a1e4..efd3645 100644 --- a/packages/avatar/src/AvatarRenderManager.ts +++ b/packages/avatar/src/AvatarRenderManager.ts @@ -70,13 +70,29 @@ export class AvatarRenderManager implements IAvatarRenderManager const url = GetConfiguration().getValue('avatar.actions.url'); - if(!url || !url.length) throw new Error('Invalid avatar action url'); + if(!url || !url.length) throw new Error('Missing "avatar.actions.url" in config — add the URL to your renderer-config.json'); - const response = await fetch(url); + let response: Response; - if(response.status !== 200) throw new Error('Invalid avatar action file'); + try + { + response = await fetch(url); + } + catch(fetchErr) + { + throw new Error(`Could not fetch avatar actions from "${ url }" — check "avatar.actions.url" in renderer-config.json (${ fetchErr.message })`); + } - this._structure.updateActions(await response.json()); + if(response.status !== 200) throw new Error(`Failed to load avatar actions from "${ url }" — server returned HTTP ${ response.status }. Check "avatar.actions.url" in renderer-config.json`); + + try + { + this._structure.updateActions(await response.json()); + } + catch(parseErr) + { + throw new Error(`Invalid JSON from "${ url }" — the URL may be wrong and returning an HTML page instead of JSON. Check "avatar.actions.url" in renderer-config.json (${ parseErr.message })`); + } } private async loadFigureData(): Promise @@ -87,13 +103,29 @@ export class AvatarRenderManager implements IAvatarRenderManager const url = GetConfiguration().getValue('avatar.figuredata.url'); - if(!url || !url.length) throw new Error('Invalid figure data url'); + if(!url || !url.length) throw new Error('Missing "avatar.figuredata.url" in config — add the URL to your renderer-config.json'); - const response = await fetch(url); + let response: Response; - if(response.status !== 200) throw new Error('Invalid figure data file'); + try + { + response = await fetch(url); + } + catch(fetchErr) + { + throw new Error(`Could not fetch figure data from "${ url }" — check "avatar.figuredata.url" in renderer-config.json (${ fetchErr.message })`); + } - this._structure.figureData.appendJSON(await response.json()); + if(response.status !== 200) throw new Error(`Failed to load figure data from "${ url }" — server returned HTTP ${ response.status }. Check "avatar.figuredata.url" in renderer-config.json`); + + try + { + this._structure.figureData.appendJSON(await response.json()); + } + catch(parseErr) + { + throw new Error(`Invalid JSON from "${ url }" — the URL may be wrong and returning an HTML page instead of JSON. Check "avatar.figuredata.url" in renderer-config.json (${ parseErr.message })`); + } this._structure.init(); } diff --git a/packages/avatar/src/EffectAssetDownloadManager.ts b/packages/avatar/src/EffectAssetDownloadManager.ts index 1594da3..9dae1d6 100644 --- a/packages/avatar/src/EffectAssetDownloadManager.ts +++ b/packages/avatar/src/EffectAssetDownloadManager.ts @@ -29,13 +29,31 @@ export class EffectAssetDownloadManager const url = GetConfiguration().getValue('avatar.effectmap.url'); - if(!url || !url.length) throw new Error('Invalid effect map url'); + if(!url || !url.length) throw new Error('Missing "avatar.effectmap.url" in config — add the effect map URL to your renderer-config.json'); - const response = await fetch(url); + let response: Response; - if(response.status !== 200) throw new Error('Invalid effect map file'); + try + { + response = await fetch(url); + } + catch(fetchErr) + { + throw new Error(`Could not fetch effect map from "${ url }" — check "avatar.effectmap.url" in renderer-config.json (${ fetchErr.message })`); + } - const responseData = await response.json(); + if(response.status !== 200) throw new Error(`Failed to load effect map from "${ url }" — server returned HTTP ${ response.status }. Check "avatar.effectmap.url" in renderer-config.json`); + + let responseData: any; + + try + { + responseData = await response.json(); + } + catch(parseErr) + { + throw new Error(`Invalid JSON in effect map "${ url }" — the URL may be wrong. Check "avatar.effectmap.url" in renderer-config.json (${ parseErr.message })`); + } this.processEffectMap(responseData.effects); diff --git a/packages/configuration/src/ConfigurationManager.ts b/packages/configuration/src/ConfigurationManager.ts index f4bcd99..8a2de97 100644 --- a/packages/configuration/src/ConfigurationManager.ts +++ b/packages/configuration/src/ConfigurationManager.ts @@ -22,27 +22,52 @@ export class ConfigurationManager implements IConfigurationManager try { this.resetConfiguration(); - this.parseConfiguration(this.getDefaultConfig(), true); + + const defaultConfig = this.getDefaultConfig(); + + if(!defaultConfig) throw new Error('Missing NitroConfig: make sure window.NitroConfig is defined in index.html'); + + this.parseConfiguration(defaultConfig, true); const configurationUrls = this.getValue('config.urls').slice(); - if(!configurationUrls || !configurationUrls.length) throw new Error('Invalid configuration urls'); + if(!configurationUrls || !configurationUrls.length) throw new Error('No config.urls defined in NitroConfig — expected an array like ["/renderer-config.json", "/ui-config.json"]'); for(const url of configurationUrls) { if(!url || !url.length) return; - const response = await fetch(url); + let response: Response; - if(response.status !== 200) throw new Error('Invalid configuration file'); + try + { + response = await fetch(url); + } + catch(fetchError) + { + throw new Error(`Failed to fetch config "${ url }" — check that the file exists and the server is reachable (${ fetchError.message })`); + } - this.parseConfiguration(await response.json()); + if(response.status !== 200) throw new Error(`Failed to load config "${ url }" — server returned HTTP ${ response.status }`); + + let json: any; + + try + { + json = await response.json(); + } + catch(parseError) + { + throw new Error(`Invalid JSON in config "${ url }" — check for syntax errors like trailing commas or missing quotes (${ parseError.message })`); + } + + this.parseConfiguration(json); } } catch (err) { - throw new Error(err); + throw new Error(err.message || String(err)); } } diff --git a/packages/localization/src/LocalizationManager.ts b/packages/localization/src/LocalizationManager.ts index e848953..b3ffc92 100644 --- a/packages/localization/src/LocalizationManager.ts +++ b/packages/localization/src/LocalizationManager.ts @@ -16,7 +16,7 @@ export class LocalizationManager implements ILocalizationManager { const urls = GetConfiguration().getValue('external.texts.url').slice(); - if(!urls || !urls.length) throw new Error('Invalid localization urls'); + if(!urls || !urls.length) throw new Error('Missing "external.texts.url" in config — add the localization URL to your ui-config.json'); for(let url of urls) { @@ -24,11 +24,31 @@ export class LocalizationManager implements ILocalizationManager url = GetConfiguration().interpolate(url); - const response = await fetch(url); + let response: Response; - if(response.status !== 200) throw new Error('Invalid localization file'); + try + { + response = await fetch(url); + } + catch(fetchErr) + { + throw new Error(`Could not fetch localization file "${ url }" — check "external.texts.url" in ui-config.json (${ fetchErr.message })`); + } - this.parseLocalization(await response.json()); + if(response.status !== 200) throw new Error(`Failed to load localization file "${ url }" — server returned HTTP ${ response.status }. Check "external.texts.url" in ui-config.json`); + + let data: any; + + try + { + data = await response.json(); + } + catch(parseErr) + { + throw new Error(`Invalid JSON in localization file "${ url }" — the URL may be wrong. Check "external.texts.url" in ui-config.json (${ parseErr.message })`); + } + + this.parseLocalization(data); } GetCommunication().registerMessageEvent(new BadgePointLimitsEvent(this.onBadgePointLimitsEvent.bind(this))); @@ -36,7 +56,7 @@ export class LocalizationManager implements ILocalizationManager catch (err) { - throw new Error(err); + throw new Error(err.message || String(err)); } } diff --git a/packages/session/src/furniture/FurnitureDataLoader.ts b/packages/session/src/furniture/FurnitureDataLoader.ts index 6f7a096..1d407c3 100644 --- a/packages/session/src/furniture/FurnitureDataLoader.ts +++ b/packages/session/src/furniture/FurnitureDataLoader.ts @@ -18,13 +18,31 @@ export class FurnitureDataLoader { const url = GetConfiguration().getValue('furnidata.url'); - if(!url || !url.length) throw new Error('invalid furni data url'); + if(!url || !url.length) throw new Error('Missing "furnidata.url" in config — add the furniture data URL to your renderer-config.json'); - const response = await fetch(url); + let response: Response; - if(response.status !== 200) throw new Error('Invalid furni data file'); + try + { + response = await fetch(url); + } + catch(fetchErr) + { + throw new Error(`Could not fetch furniture data from "${ url }" — check "furnidata.url" in renderer-config.json (${ fetchErr.message })`); + } - const responseData = await response.json(); + if(response.status !== 200) throw new Error(`Failed to load furniture data from "${ url }" — server returned HTTP ${ response.status }. Check "furnidata.url" in renderer-config.json`); + + let responseData: any; + + try + { + responseData = await response.json(); + } + catch(parseErr) + { + throw new Error(`Invalid JSON in furniture data "${ url }" — the URL may be wrong. Check "furnidata.url" in renderer-config.json (${ parseErr.message })`); + } if(responseData.roomitemtypes) this.parseFloorItems(responseData.roomitemtypes); diff --git a/packages/session/src/product/ProductDataLoader.ts b/packages/session/src/product/ProductDataLoader.ts index e8e846f..61da2de 100644 --- a/packages/session/src/product/ProductDataLoader.ts +++ b/packages/session/src/product/ProductDataLoader.ts @@ -15,13 +15,31 @@ export class ProductDataLoader { const url = GetConfiguration().getValue('productdata.url'); - if(!url || !url.length) throw new Error('invalid product data url'); + if(!url || !url.length) throw new Error('Missing "productdata.url" in config — add the product data URL to your renderer-config.json'); - const response = await fetch(url); + let response: Response; - if(response.status !== 200) throw new Error('Invalid product data file'); + try + { + response = await fetch(url); + } + catch(fetchErr) + { + throw new Error(`Could not fetch product data from "${ url }" — check "productdata.url" in renderer-config.json (${ fetchErr.message })`); + } - const responseData = await response.json(); + if(response.status !== 200) throw new Error(`Failed to load product data from "${ url }" — server returned HTTP ${ response.status }. Check "productdata.url" in renderer-config.json`); + + let responseData: any; + + try + { + responseData = await response.json(); + } + catch(parseErr) + { + throw new Error(`Invalid JSON in product data "${ url }" — the URL may be wrong. Check "productdata.url" in renderer-config.json (${ parseErr.message })`); + } this.parseProducts(responseData.productdata); } diff --git a/packages/utils/src/NitroVersion.ts b/packages/utils/src/NitroVersion.ts index 09f73c0..ecd2186 100644 --- a/packages/utils/src/NitroVersion.ts +++ b/packages/utils/src/NitroVersion.ts @@ -1,30 +1,25 @@ export class NitroVersion { - public static RENDERER_VERSION: string = '2.0.0'; - public static UI_VERSION: string = ''; + public static RENDERER_VERSION: string = '3.0.0'; + public static UI_VERSION: string = '3.0.4'; public static sayHello(): void { if(navigator.userAgent.toLowerCase().indexOf('chrome') > -1) { const args = [ - `\n %c %c %c Nitro ${NitroVersion.UI_VERSION} - Renderer ${NitroVersion.RENDERER_VERSION} %c %c %c https://discord.nitrodev.co %c %c \n\n`, - 'background: #ffffff; padding:5px 0;', - 'background: #ffffff; padding:5px 0;', - 'color: #ffffff; background: #000000; padding:5px 0;', - 'background: #ffffff; padding:5px 0;', - 'background: #ffffff; padding:5px 0;', - 'background: #000000; padding:5px 0;', - 'background: #ffffff; padding:5px 0;', - 'background: #ffffff; padding:5px 0;' + `\n %c NITRO %c UI ${NitroVersion.UI_VERSION} %c Renderer ${NitroVersion.RENDERER_VERSION} %c \n`, + 'background: #1a3a5c; color: #ffffff; font-size: 14px; font-weight: bold; padding: 8px 12px; border-radius: 6px 0 0 6px;', + 'background: #2a5f8f; color: #e0ecf8; font-size: 12px; padding: 8px 10px;', + 'background: #3d7ab5; color: #e0ecf8; font-size: 12px; padding: 8px 10px; border-radius: 0 6px 6px 0;', + 'background: transparent;' ]; self.console.log(...args); } - else if(self.console) { - self.console.log(`Nitro ${NitroVersion.UI_VERSION} - Renderer ${NitroVersion.RENDERER_VERSION} `); + self.console.log(`Nitro UI ${NitroVersion.UI_VERSION} - Renderer ${NitroVersion.RENDERER_VERSION}`); } } } From 5aef7a3de249c94f3dbcc9b68ebf310a19ee582a Mon Sep 17 00:00:00 2001 From: duckietm Date: Thu, 19 Mar 2026 15:04:47 +0100 Subject: [PATCH 06/11] =?UTF-8?q?=F0=9F=86=95=20Disconnection=20handler,?= =?UTF-8?q?=20when=20you=20got=20disconnected=20you=20automatic=20go=20bac?= =?UTF-8?q?k=20to=20the=20room?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/api/src/communication/IConnection.ts | 1 + .../src/nitro/session/IRoomSessionManager.ts | 1 + .../communication/src/CommunicationManager.ts | 85 +++++-- packages/communication/src/NitroMessages.ts | 2 - .../communication/src/SocketConnection.ts | 189 +++++++++++++-- .../src/messages/outgoing/OutgoingHeader.ts | 1 - .../room/engine/ClickUserMessageComposer.ts | 21 -- .../messages/outgoing/room/engine/index.ts | 1 - packages/events/src/NitroEventType.ts | 4 + packages/events/src/core/ReconnectEvent.ts | 25 ++ packages/events/src/core/index.ts | 1 + packages/room/src/RoomObjectEventHandler.ts | 13 +- .../src/common/floorplan/FloorplanEditor.ts | 5 - packages/session/src/RoomSessionManager.ts | 223 +++++++++++++++++- .../session/src/handler/RoomChatHandler.ts | 6 +- packages/utils/src/filters/WiredFilter.ts | 7 +- 16 files changed, 498 insertions(+), 87 deletions(-) delete mode 100644 packages/communication/src/messages/outgoing/room/engine/ClickUserMessageComposer.ts create mode 100644 packages/events/src/core/ReconnectEvent.ts diff --git a/packages/api/src/communication/IConnection.ts b/packages/api/src/communication/IConnection.ts index 3139c22..f9a1837 100644 --- a/packages/api/src/communication/IConnection.ts +++ b/packages/api/src/communication/IConnection.ts @@ -5,6 +5,7 @@ import { IMessageEvent } from './IMessageEvent'; export interface IConnection { init(socketUrl: string): void; + dispose(): void; ready(): void; authenticated(): void; send(...composers: IMessageComposer[]): void; diff --git a/packages/api/src/nitro/session/IRoomSessionManager.ts b/packages/api/src/nitro/session/IRoomSessionManager.ts index 546df80..974c98a 100644 --- a/packages/api/src/nitro/session/IRoomSessionManager.ts +++ b/packages/api/src/nitro/session/IRoomSessionManager.ts @@ -7,5 +7,6 @@ export interface IRoomSessionManager createSession(roomId: number, password?: string): boolean; startSession(session: IRoomSession): boolean; removeSession(id: number, openLandingView?: boolean): void; + tryRestoreSession(): boolean; viewerSession: IRoomSession; } diff --git a/packages/communication/src/CommunicationManager.ts b/packages/communication/src/CommunicationManager.ts index 8acf399..0fa6a90 100644 --- a/packages/communication/src/CommunicationManager.ts +++ b/packages/communication/src/CommunicationManager.ts @@ -1,7 +1,7 @@ import { ICommunicationManager, IConnection, IMessageConfiguration, IMessageEvent } from '@nitrots/api'; import { GetConfiguration } from '@nitrots/configuration'; -import { GetEventDispatcher, NitroEventType } from '@nitrots/events'; -import { GetTickerTime } from '@nitrots/utils'; +import { GetEventDispatcher, NitroEvent, NitroEventType } from '@nitrots/events'; +import { GetTickerTime, NitroLogger } from '@nitrots/utils'; import { NitroMessages } from './NitroMessages'; import { SocketConnection } from './SocketConnection'; import { AuthenticatedEvent, ClientHelloMessageComposer, ClientPingEvent, InfoRetrieveMessageComposer, PongMessageComposer, SSOTicketMessageComposer, UniqueIDMessageComposer } from './messages'; @@ -17,7 +17,11 @@ export class CommunicationManager implements ICommunicationManager private _socketClosedCallback: () => void = null; private _socketOpenedCallback: () => void = null; private _socketErrorCallback: () => void = null; - + private _socketReconnectedCallback: () => void = null; + + private _machineId: string = null; + private _initResolved: boolean = false; + private getGpu(): string { const e = document.createElement('canvas'); let t, s, i, r; @@ -41,7 +45,7 @@ export class CommunicationManager implements ICommunicationManager return 'Error'; } } - + private getCanvas(): any { const e = document.createElement('canvas'), t = e.getContext('2d'), userAgent = navigator.userAgent, screenInfo = '${window.screen.width}x${window.screen.height}', currentDate = new Date().toString(), s = 'ThiosIsVerrySeCuRe02938883721moreStuff! | ${userAgent} | ${screenInfo} | ${currentDate}'; t.textBaseline = 'top'; @@ -67,24 +71,33 @@ export class CommunicationManager implements ICommunicationManager } return r; } - + private generateMachineID(): string { const fp = new ClientJS(); const uniqueId = fp.getCustomFingerprint( - fp.getAvailableResolution(), + fp.getAvailableResolution(), fp.getOS(), - fp.getCPU(), - fp.getColorDepth(), - this.getGpu(), - fp.getSilverlightVersion(), - fp.getOSVersion(), - this.getMathResult(), - fp.getCanvasPrint(), + fp.getCPU(), + fp.getColorDepth(), + this.getGpu(), + fp.getSilverlightVersion(), + fp.getOSVersion(), + this.getMathResult(), + fp.getCanvasPrint(), this.getCanvas() ); return uniqueId == null ? 'FAILED' : `IID-${uniqueId}`; } + private sendHandshake(): void + { + if(!this._machineId) this._machineId = this.generateMachineID(); + + this._connection.send(new ClientHelloMessageComposer(null, null, null, null)); + this._connection.send(new SSOTicketMessageComposer(GetConfiguration().getValue('sso.ticket', null), GetTickerTime())); + this._connection.send(new UniqueIDMessageComposer(this._machineId, '', '')); + } + constructor() { this._connection.registerMessages(this._messages); @@ -99,6 +112,17 @@ export class CommunicationManager implements ICommunicationManager }; GetEventDispatcher().addEventListener(NitroEventType.SOCKET_CLOSED, this._socketClosedCallback); + // Handle reconnection - re-authenticate when socket reconnects + this._socketReconnectedCallback = () => + { + NitroLogger.log('[CommunicationManager] Socket reconnected, re-authenticating...'); + + if(GetConfiguration().getValue('system.pong.manually', false)) this.startPong(); + + this.sendHandshake(); + }; + GetEventDispatcher().addEventListener(NitroEventType.SOCKET_RECONNECTED, this._socketReconnectedCallback); + return new Promise((resolve, reject) => { // Store callback for cleanup @@ -106,18 +130,14 @@ export class CommunicationManager implements ICommunicationManager { if(GetConfiguration().getValue('system.pong.manually', false)) this.startPong(); - const machineId = this.generateMachineID(); - - this._connection.send(new ClientHelloMessageComposer(null, null, null, null)); - this._connection.send(new SSOTicketMessageComposer(GetConfiguration().getValue('sso.ticket', null), GetTickerTime())); - this._connection.send(new UniqueIDMessageComposer(machineId, '', '')); + this.sendHandshake(); }; GetEventDispatcher().addEventListener(NitroEventType.SOCKET_OPENED, this._socketOpenedCallback); // Store callback for cleanup this._socketErrorCallback = () => { - reject(); + if(!this._initResolved) reject(); }; GetEventDispatcher().addEventListener(NitroEventType.SOCKET_ERROR, this._socketErrorCallback); @@ -125,11 +145,30 @@ export class CommunicationManager implements ICommunicationManager const pingEvent = new ClientPingEvent((event: ClientPingEvent) => this.sendPong()); const authEvent = new AuthenticatedEvent((event: AuthenticatedEvent) => { + const isReconnect = this._initResolved; + + NitroLogger.log('[CommunicationManager] AuthenticatedEvent received (isReconnect=' + isReconnect + ')'); + this._connection.authenticated(); - resolve(); + if(!this._initResolved) + { + this._initResolved = true; + resolve(); + } + + if(isReconnect) + { + this._connection.ready(); + } event.connection.send(new InfoRetrieveMessageComposer()); + + if(isReconnect) + { + NitroLogger.log('[CommunicationManager] Dispatching SOCKET_REAUTHENTICATED'); + GetEventDispatcher().dispatchEvent(new NitroEvent(NitroEventType.SOCKET_REAUTHENTICATED)); + } }); this._messageEvents.push(pingEvent, authEvent); @@ -164,6 +203,12 @@ export class CommunicationManager implements ICommunicationManager this._socketErrorCallback = null; } + if(this._socketReconnectedCallback) + { + GetEventDispatcher().removeEventListener(NitroEventType.SOCKET_RECONNECTED, this._socketReconnectedCallback); + this._socketReconnectedCallback = null; + } + // Remove message events for(const event of this._messageEvents) { diff --git a/packages/communication/src/NitroMessages.ts b/packages/communication/src/NitroMessages.ts index ec3e632..7d61b36 100644 --- a/packages/communication/src/NitroMessages.ts +++ b/packages/communication/src/NitroMessages.ts @@ -1,6 +1,5 @@ import { IMessageConfiguration } from '@nitrots/api'; import { AcceptFriendMessageComposer, AcceptFriendResultEvent, AcceptGameInviteMessageComposer, AcceptQuestMessageComposer, AccountSafetyLockStatusChangeMessageEvent, AchievementEvent, AchievementNotificationMessageEvent, AchievementResolutionCompletedMessageEvent, AchievementResolutionProgressMessageEvent, AchievementResolutionsMessageEvent, AchievementsEvent, AchievementsScoreEvent, ActivateQuestMessageComposer, ActivityPointNotificationMessageEvent, AddFavouriteRoomMessageComposer, AddJukeboxDiskComposer, AddSpamWallPostItMessageComposer, ApplySnapshotMessageComposer, ApplyTonerComposer, ApproveAllMembershipRequestsMessageComposer, ApproveNameMessageComposer, ApproveNameMessageEvent, AreaHideMessageEvent, AuthenticatedEvent, AuthenticationMessageComposer, AvailabilityStatusMessageEvent, AvailabilityTimeMessageEvent, AvatarEffectActivatedComposer, AvatarEffectActivatedEvent, AvatarEffectAddedEvent, AvatarEffectExpiredEvent, AvatarEffectSelectedComposer, AvatarEffectSelectedEvent, AvatarEffectsEvent, BadgePointLimitsEvent, BadgeReceivedEvent, BadgesEvent, BannedUsersFromRoomEvent, BonusRareInfoMessageEvent, BotAddedToInventoryEvent, BotCommandConfigurationEvent, BotErrorEvent, BotForceOpenContextMenuEvent, BotInventoryMessageEvent, BotPlaceComposer, BotReceivedMessageEvent, BotRemoveComposer, BotRemovedFromInventoryEvent, BotSkillListUpdateEvent, BotSkillSaveComposer, BreedPetsMessageComposer, BuildersClubFurniCountMessageEvent, BuildersClubPlaceRoomItemMessageComposer, BuildersClubPlaceWallItemMessageComposer, BuildersClubQueryFurniCountMessageComposer, BuildersClubSubscriptionStatusMessageEvent, BundleDiscountRulesetMessageEvent, BuyMarketplaceOfferMessageComposer, BuyMarketplaceTokensMessageComposer, CallForHelpDisabledNotifyMessageEvent, CallForHelpFromForumMessageMessageComposer, CallForHelpFromForumThreadMessageComposer, CallForHelpFromIMMessageComposer, CallForHelpFromPhotoMessageComposer, CallForHelpFromSelfieMessageComposer, CallForHelpMessageComposer, CallForHelpPendingCallsDeletedMessageEvent, CallForHelpPendingCallsMessageEvent, CallForHelpReplyMessageEvent, CallForHelpResultMessageEvent, CameraPublishStatusMessageEvent, CameraPurchaseOKMessageEvent, CameraSnapshotMessageEvent, CameraStorageUrlMessageEvent, CampaignCalendarDataMessageEvent, CampaignCalendarDoorOpenedMessageEvent, CanCreateRoomEvent, CanCreateRoomEventEvent, CanCreateRoomMessageComposer, CancelEventMessageComposer, CancelMarketplaceOfferMessageComposer, CancelMysteryBoxWaitMessageEvent, CancelPetBreedingComposer, CancelQuestMessageComposer, CatalogGroupsComposer, CatalogPageExpirationEvent, CatalogPageMessageEvent, CatalogPageWithEarliestExpiryMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, CategoriesWithVisitorCountEvent, CfhChatlogEvent, CfhSanctionMessageEvent, CfhTopicsInitEvent, ChangeEmailComposer, ChangeEmailResultEvent, ChangeQueueMessageComposer, ChangeUserNameMessageComposer, ChangeUserNameResultMessageEvent, ChatReviewGuideDecidesOnOfferMessageComposer, ChatReviewGuideDetachedMessageComposer, ChatReviewGuideVoteMessageComposer, ChatReviewSessionCreateMessageComposer, ChatReviewSessionDetachedMessageEvent, ChatReviewSessionOfferedToGuideMessageEvent, ChatReviewSessionResultsMessageEvent, ChatReviewSessionStartedMessageEvent, ChatReviewSessionVotingStatusMessageEvent, CheckUserNameMessageComposer, CheckUserNameResultMessageEvent, ClickFurniMessageComposer, ClientHelloMessageComposer, ClientPingEvent, CloseIssueDefaultActionMessageComposer, CloseIssuesMessageComposer, ClubGiftInfoEvent, ClubGiftNotificationEvent, ClubGiftSelectedEvent, CommunityGoalEarnedPrizesMessageEvent, CommunityGoalHallOfFameMessageEvent, CommunityGoalProgressMessageEvent, CommunityGoalVoteMessageComposer, CommunityGoalVoteMessageEvent, CompetitionEntrySubmitResultEvent, CompetitionRoomsDataMessageEvent, CompetitionRoomsSearchMessageComposer, CompetitionStatusMessageEvent, CompetitionVotingInfoMessageEvent, CompleteDiffieHandshakeEvent, CompleteDiffieHandshakeMessageComposer, CompostPlantMessageComposer, ConcurrentUsersGoalProgressMessageEvent, ConfirmPetBreedingComposer, ConnectionErrorEvent, ControlYoutubeDisplayPlaybackMessageComposer, ConvertGlobalRoomIdMessageComposer, ConvertedRoomIdEvent, CraftComposer, CraftSecretComposer, CraftableProductsEvent, CraftingRecipeEvent, CraftingRecipesAvailableEvent, CraftingResultEvent, CreateFlatMessageComposer, CurrentTimingCodeMessageEvent, CustomUserNotificationMessageEvent, DeclineFriendMessageComposer, DefaultSanctionMessageComposer, DeleteFavouriteRoomMessageComposer, DeleteItemMessageComposer, DeleteBadgeMessageComposer, DeletePetMessageComposer, DeletePendingCallsForHelpMessageComposer, DesktopViewComposer, DesktopViewEvent, DiceValueMessageEvent, DirectSMSClubBuyAvailableMessageEvent, DisconnectMessageComposer, DisconnectReasonEvent, DoorbellMessageEvent, EditEventMessageComposer, ElementPointerMessageEvent, EmailStatusResultEvent, EpicPopupMessageEvent, ExtendRentOrBuyoutFurniMessageComposer, ExtendRentOrBuyoutStripItemMessageComposer, ExtendedProfileChangedMessageEvent, FavoriteMembershipUpdateMessageEvent, FavouriteChangedEvent, FavouritesEvent, FigureSetIdsMessageEvent, FigureUpdateEvent, FindFriendsProcessResultEvent, FindNewFriendsMessageComposer, FireworkChargeDataEvent, FlatAccessDeniedMessageEvent, FlatControllerAddedEvent, FlatControllerRemovedEvent, FlatControllersEvent, FlatCreatedEvent, FloodControlEvent, FloorHeightMapEvent, FollowFriendFailedEvent, FollowFriendMessageComposer, ForumDataMessageEvent, ForumsListMessageEvent, ForwardToACompetitionRoomMessageComposer, ForwardToARandomPromotedRoomMessageComposer, ForwardToASubmittableRoomMessageComposer, ForwardToRandomCompetitionRoomMessageComposer, ForwardToSomeRoomMessageComposer, FriendFurniConfirmLockMessageComposer, FriendListFragmentEvent, FriendListUpdateComposer, FriendListUpdateEvent, FriendNotificationEvent, FriendRequestQuestCompleteMessageComposer, FriendRequestsEvent, FurniRentOrBuyoutOfferMessageEvent, FurnitureAliasesComposer, FurnitureAliasesEvent, FurnitureColorWheelComposer, FurnitureDataEvent, FurnitureDiceActivateComposer, FurnitureDiceDeactivateComposer, FurnitureExchangeComposer, FurnitureFloorAddEvent, FurnitureFloorEvent, FurnitureFloorRemoveEvent, FurnitureFloorUpdateComposer, FurnitureFloorUpdateEvent, FurnitureGroupInfoComposer, FurnitureListAddOrUpdateEvent, FurnitureListComposer, FurnitureListEvent, FurnitureListInvalidateEvent, FurnitureListRemovedEvent, FurnitureMannequinSaveLookComposer, FurnitureMannequinSaveNameComposer, FurnitureMultiStateComposer, FurnitureOneWayDoorComposer, FurniturePickupComposer, FurniturePickupAllComposer, FurniturePlaceComposer, FurniturePlacePaintComposer, FurniturePostItPlaceComposer, FurniturePostItPlacedEvent, FurnitureRandomStateComposer, FurnitureStackHeightComposer, FurnitureStackHeightEvent, FurnitureWallAddEvent, FurnitureWallEvent, FurnitureWallMultiStateComposer, FurnitureWallRemoveEvent, FurnitureWallUpdateComposer, FurnitureWallUpdateEvent, Game2AccountGameStatusMessageEvent, Game2CheckGameDirectoryStatusMessageComposer, Game2ExitGameMessageComposer, Game2GameChatMessageComposer, Game2GameDirectoryStatusMessageEvent, Game2GetAccountGameStatusMessageComposer, Game2GetWeeklyFriendsLeaderboardComposer, Game2GetWeeklyLeaderboardComposer, Game2InArenaQueueMessageEvent, Game2JoiningGameFailedMessageEvent, Game2LoadStageReadyMessageComposer, Game2PlayAgainMessageComposer, Game2RequestFullStatusUpdateMessageComposer, Game2StartingGameFailedMessageEvent, Game2StopCounterMessageEvent, Game2UserLeftGameMessageEvent, Game2WeeklyFriendsLeaderboardEvent, Game2WeeklyLeaderboardEvent, GameAchievementsMessageEvent, GameInviteMessageEvent, GameListMessageEvent, GameStatusMessageEvent, GameUnloadedMessageComposer, GenericErrorEvent, GetBadgePointLimitsComposer, GetBonusRareInfoMessageComposer, GetBotInventoryComposer, GetBundleDiscountRulesetComposer, GetCatalogIndexComposer, GetCatalogPageComposer, GetCatalogPageExpirationComposer, GetCatalogPageWithEarliestExpiryComposer, GetCategoriesWithUserCountMessageComposer, GetCfhChatlogMessageComposer, GetCfhStatusMessageComposer, GetClubGiftInfo, GetClubOffersMessageComposer, GetCommunityGoalEarnedPrizesMessageComposer, GetCommunityGoalHallOfFameMessageComposer, GetCommunityGoalProgressMessageComposer, GetConcurrentUsersGoalProgressMessageComposer, GetConcurrentUsersRewardMessageComposer, GetCraftableProductsComposer, GetCraftingRecipeComposer, GetCraftingRecipesAvailableComposer, GetCurrentTimingCodeMessageComposer, GetCustomRoomFilterMessageComposer, GetDailyQuestMessageComposer, GetDirectClubBuyAvailableComposer, GetEmailStatusComposer, GetExtendedProfileByNameMessageComposer, GetFaqCategoryMessageComposer, GetFaqTextMessageComposer, GetForumStatsMessageComposer, GetForumsListMessageComposer, GetFriendRequestsComposer, GetGameAchievementsMessageComposer, GetGameListMessageComposer, GetGameStatusMessageComposer, GetGiftMessageComposer, GetGiftWrappingConfigurationComposer, GetGuestRoomMessageComposer, GetGuestRoomResultEvent, GetGuideReportingStatusMessageComposer, GetHabboBasicMembershipExtendOfferComposer, GetHabboClubExtendOfferMessageComposer, GetHabboGroupBadgesMessageComposer, GetIgnoredUsersComposer, GetInterstitialMessageComposer, GetIsBadgeRequestFulfilledComposer, GetIsOfferGiftableComposer, GetIsUserPartOfCompetitionMessageComposer, GetItemDataComposer, GetJukeboxPlayListMessageComposer, GetLimitedOfferAppearingNextComposer, GetMarketplaceCanMakeOfferComposer, GetMarketplaceConfigurationMessageComposer, GetMarketplaceItemStatsComposer, GetMarketplaceOffersMessageComposer, GetMarketplaceOwnOffersMessageComposer, GetMessagesMessageComposer, GetModeratorRoomInfoMessageComposer, GetModeratorUserInfoMessageComposer, GetNextTargetedOfferComposer, GetNowPlayingMessageComposer, GetOccupiedTilesMessageComposer, GetOfficialRoomsMessageComposer, GetOfficialSongIdMessageComposer, GetPendingCallsForHelpMessageComposer, GetPetCommandsComposer, GetPopularRoomTagsMessageComposer, GetProductOfferComposer, GetPromoArticlesComposer, GetQuestsMessageComposer, GetQuizQuestionsComposer, GetRecyclerStatusMessageComposer, GetRentOrBuyoutOfferMessageComposer, GetResolutionAchievementsMessageComposer, GetRoomAdPurchaseInfoComposer, GetRoomChatlogMessageComposer, GetRoomEntryDataMessageComposer, GetRoomEntryTileMessageComposer, GetRoomVisitsMessageComposer, GetSeasonalCalendarDailyOfferComposer, GetSeasonalQuestsOnlyMessageComposer, GetSecondsUntilMessageComposer, GetSellablePetPalettesComposer, GetSongInfoMessageComposer, GetSoundMachinePlayListMessageComposer, GetSoundSettingsComposer, GetTalentTrackLevelMessageComposer, GetTargetedOfferComposer, GetThreadMessageComposer, GetThreadsMessageComposer, GetUnreadForumsCountMessageComposer, GetUserChatlogMessageComposer, GetUserEventCatsMessageComposer, GetUserFlatCatsMessageComposer, GetUserGameAchievementsMessageComposer, GetUserSongDisksMessageComposer, GetUserTagsComposer, GetWardrobeMessageComposer, GetWeeklyGameRewardComposer, GetWeeklyGameRewardWinnersComposer, GetYoutubeDisplayStatusMessageComposer, GiftReceiverNotFoundEvent, GiftWrappingConfigurationEvent, GoToFlatMessageComposer, GotMysteryBoxPrizeMessageEvent, GroupAdminGiveComposer, GroupAdminTakeComposer, GroupBadgePartsComposer, GroupBadgePartsEvent, GroupBuyComposer, GroupBuyDataComposer, GroupBuyDataEvent, GroupConfirmMemberRemoveEvent, GroupConfirmRemoveMemberComposer, GroupDeleteComposer, GroupDetailsChangedMessageEvent, GroupFavoriteComposer, GroupFurniContextMenuInfoMessageEvent, GroupInformationComposer, GroupInformationEvent, GroupJoinComposer, GroupMembersComposer, GroupMembersEvent, GroupMembershipAcceptComposer, GroupMembershipDeclineComposer, GroupMembershipRequestedMessageEvent, GroupPurchasedEvent, GroupRemoveMemberComposer, GroupSaveBadgeComposer, GroupSaveColorsComposer, GroupSaveInformationComposer, GroupSavePreferencesComposer, GroupSettingsComposer, GroupSettingsEvent, GroupUnfavoriteComposer, GuestRoomSearchResultEvent, GuideOnDutyStatusMessageEvent, GuideReportingStatusMessageEvent, GuideSessionAttachedMessageEvent, GuideSessionCreateMessageComposer, GuideSessionDetachedMessageEvent, GuideSessionEndedMessageEvent, GuideSessionErrorMessageEvent, GuideSessionFeedbackMessageComposer, GuideSessionGetRequesterRoomMessageComposer, GuideSessionGuideDecidesMessageComposer, GuideSessionInviteRequesterMessageComposer, GuideSessionInvitedToGuideRoomMessageEvent, GuideSessionIsTypingMessageComposer, GuideSessionMessageMessageComposer, GuideSessionMessageMessageEvent, GuideSessionOnDutyUpdateMessageComposer, GuideSessionPartnerIsTypingMessageEvent, GuideSessionReportMessageComposer, GuideSessionRequesterCancelsMessageComposer, GuideSessionRequesterRoomMessageEvent, GuideSessionResolvedMessageComposer, GuideSessionStartedMessageEvent, GuideTicketCreationResultMessageEvent, GuideTicketResolutionMessageEvent, GuildBaseSearchMessageComposer, GuildEditFailedMessageEvent, GuildForumThreadsEvent, GuildMemberMgmtFailedMessageEvent, GuildMembershipsMessageEvent, HabboBroadcastMessageEvent, HabboClubExtendOfferMessageEvent, HabboClubOffersMessageEvent, HabboGroupBadgesMessageEvent, HabboGroupDeactivatedMessageEvent, HabboGroupJoinFailedMessageEvent, HabboSearchComposer, HabboSearchResultEvent, HarvestPetMessageComposer, HotelClosedAndOpensEvent, HotelClosesAndWillOpenAtEvent, HotelMergeNameChangeEvent, HotelWillCloseInMinutesEvent, IdentityAccountsEvent, IgnoreResultEvent, IgnoreUserComposer, IgnoreUserIdComposer, IgnoredUsersEvent, InClientLinkEvent, IncomingHeader, InfoFeedEnableMessageEvent, InfoRetrieveMessageComposer, InitCameraMessageEvent, InitDiffieHandshakeEvent, InitDiffieHandshakeMessageComposer, InstantMessageErrorEvent, InterstitialMessageEvent, InterstitialShownMessageComposer, IsBadgeRequestFulfilledEvent, IsOfferGiftableMessageEvent, IsUserPartOfCompetitionMessageEvent, IssueCloseNotificationMessageEvent, IssueDeletedMessageEvent, IssueInfoMessageEvent, IssuePickFailedMessageEvent, ItemDataUpdateMessageEvent, JoinQueueMessageComposer, JoinedQueueMessageEvent, JoiningQueueFailedMessageEvent, JukeboxPlayListFullMessageEvent, JukeboxSongDisksMessageEvent, LagWarningReportMessageComposer, LeaveQueueMessageComposer, LeftQueueMessageEvent, LimitedEditionSoldOutEvent, LimitedOfferAppearingNextMessageEvent, LoadGameMessageEvent, LoadGameUrlEvent, LoveLockFurniFinishedEvent, LoveLockFurniFriendConfirmedEvent, LoveLockFurniStartEvent, MOTDNotificationEvent, MaintenanceStatusMessageEvent, MakeOfferMessageComposer, MarkCatalogNewAdditionsPageOpenedComposer, MarketPlaceOffersEvent, MarketplaceBuyOfferResultEvent, MarketplaceCanMakeOfferResult, MarketplaceCancelOfferResultEvent, MarketplaceConfigurationEvent, MarketplaceItemStatsEvent, MarketplaceMakeOfferResult, MarketplaceOwnOffersEvent, MessageErrorEvent, MessengerInitComposer, MessengerInitEvent, MiniMailNewMessageEvent, MiniMailUnreadCountEvent, ModAlertMessageComposer, ModBanMessageComposer, ModKickMessageComposer, ModMessageMessageComposer, ModMuteMessageComposer, ModToolPreferencesComposer, ModToolSanctionComposer, ModTradingLockMessageComposer, ModerateMessageMessageComposer, ModerateRoomMessageComposer, ModerateThreadMessageComposer, ModeratorActionMessageComposer, ModeratorActionResultMessageEvent, ModeratorCautionEvent, ModeratorInitMessageEvent, ModeratorMessageEvent, ModeratorRoomInfoEvent, ModeratorToolPreferencesEvent, ModeratorUserInfoEvent, MoodlightSettingsComposer, MoodlightSettingsSaveComposer, MoodlightTogggleStateComposer, MuteAllInRoomEvent, MyFavouriteRoomsSearchMessageComposer, MyFrequentRoomHistorySearchMessageComposer, MyFriendsRoomsSearchMessageComposer, MyGuildBasesSearchMessageComposer, MyRecommendedRoomsMessageComposer, MyRoomHistorySearchMessageComposer, MyRoomRightsSearchMessageComposer, MyRoomsSearchMessageComposer, MysteryBoxKeysEvent, MysteryBoxWaitingCanceledMessageComposer, NavigatorCategoryListModeComposer, NavigatorCollapsedEvent, NavigatorDeleteSavedSearchComposer, NavigatorHomeRoomEvent, NavigatorInitComposer, NavigatorLiftedEvent, NavigatorMetadataEvent, NavigatorOpenRoomCreatorEvent, NavigatorSearchCloseComposer, NavigatorSearchComposer, NavigatorSearchEvent, NavigatorSearchOpenComposer, NavigatorSearchSaveComposer, NavigatorSearchesEvent, NavigatorSettingsEvent, NavigatorSettingsSaveComposer, NewConsoleMessageEvent, NewFriendRequestEvent, NewUserExperienceGetGiftsComposer, NewUserExperienceGiftOfferMessageEvent, NewUserExperienceNotCompleteEvent, NewUserExperienceScriptProceedComposer, NoOwnedRoomsAlertMessageEvent, NoSuchFlatEvent, NoobnessLevelMessageEvent, NotEnoughBalanceMessageEvent, NotificationDialogMessageEvent, NowPlayingMessageEvent, ObjectsDataUpdateEvent, ObjectsRollingEvent, OfferRewardDeliveredMessageEvent, OfficialSongIdMessageEvent, OneWayDoorStatusMessageEvent, OpenCampaignCalendarDoorAsStaffComposer, OpenCampaignCalendarDoorComposer, OpenMessageComposer, OpenMysteryTrophyMessageComposer, OpenPetPackageMessageComposer, OpenPetPackageRequestedMessageEvent, OpenPetPackageResultMessageEvent, OpenPresentComposer, OpenQuestTrackerMessageComposer, OpenWelcomeGiftComposer, OutgoingHeader, PeerUsersClassificationMessageComposer, PerformanceLogMessageComposer, PerkAllowancesMessageEvent, PetAddedToInventoryEvent, PetBreedingResultEvent, PetExperienceEvent, PetFigureUpdateEvent, PetInfoEvent, PetInventoryEvent, PetLevelNotificationEvent, PetLevelUpdateMessageEvent, PetMountComposer, PetMoveComposer, PetPlaceComposer, PetPlacingErrorEvent, PetReceivedMessageEvent, PetRemoveComposer, PetRemovedFromInventory, PetRespectComposer, PetRespectNoficationEvent, PetScratchFailedMessageEvent, PetSelectedMessageComposer, PetStatusUpdateEvent, PetSupplementComposer, PetSupplementedNotificationEvent, PetTrainingPanelMessageEvent, PhoneCollectionStateMessageEvent, PhotoCompetitionMessageComposer, PickIssuesMessageComposer, PlayListMessageEvent, PlayListSongAddedMessageEvent, PollAnswerComposer, PollContentsEvent, PollErrorEvent, PollOfferEvent, PollRejectComposer, PollStartComposer, PongMessageComposer, PopularRoomTagsResultEvent, PopularRoomsSearchMessageComposer, PostMessageMessageComposer, PostMessageMessageEvent, PostQuizAnswersComposer, PostThreadMessageEvent, PresentOpenedMessageEvent, ProductOfferEvent, PromoArticlesMessageEvent, PublishPhotoMessageComposer, PurchaseBasicMembershipExtensionComposer, PurchaseErrorMessageEvent, PurchaseFromCatalogAsGiftComposer, PurchaseFromCatalogComposer, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, PurchasePhotoMessageComposer, PurchaseRoomAdMessageComposer, PurchaseTargetedOfferComposer, PurchaseVipMembershipExtensionComposer, QuestCancelledMessageEvent, QuestCompletedMessageEvent, QuestDailyMessageEvent, QuestMessageEvent, QuestionAnsweredEvent, QuestionEvent, QuestionFinishedEvent, QuestsMessageEvent, QuizDataMessageEvent, QuizResultsMessageEvent, RateFlatMessageComposer, RecycleItemsMessageComposer, RecyclerFinishedMessageEvent, RecyclerStatusMessageEvent, RedeemCommunityGoalPrizeMessageComposer, RedeemItemClothingComposer, RedeemMarketplaceOfferCreditsMessageComposer, RedeemVoucherMessageComposer, RejectQuestMessageComposer, RelationshipStatusInfoEvent, ReleaseIssuesMessageComposer, RemainingMuteEvent, RemoveAllRightsMessageComposer, RemoveFriendComposer, RemoveJukeboxDiskComposer, RemoveOwnRoomRightsRoomMessageComposer, RemovePetSaddleComposer, RemoveWallItemComposer, RenderRoomMessageComposer, RenderRoomThumbnailMessageComposer, RentableSpaceCancelRentMessageComposer, RentableSpaceRentFailedMessageEvent, RentableSpaceRentMessageComposer, RentableSpaceRentOkMessageEvent, RentableSpaceStatusMessageComposer, RentableSpaceStatusMessageEvent, RequestABadgeComposer, RequestAchievementsMessageComposer, RequestBadgesComposer, RequestBotCommandConfigurationComposer, RequestCameraConfigurationComposer, RequestFriendComposer, RequestFurniInventoryWhenNotInRoomComposer, RequestPetInfoComposer, RequestPetsComposer, RequestSpamWallPostItMessageEvent, ResetPhoneNumberStateMessageComposer, ResetResolutionAchievementMessageComposer, RespectReceivedEvent, RestoreClientMessageEvent, RoomAdErrorEvent, RoomAdEventTabAdClickedComposer, RoomAdEventTabViewedComposer, RoomAdPurchaseInfoEvent, RoomAdPurchaseInitiatedComposer, RoomAdSearchMessageComposer, RoomAmbassadorAlertComposer, RoomBanUserComposer, RoomBannedUsersComposer, RoomChatSettingsEvent, RoomChatlogEvent, RoomCompetitionInitMessageComposer, RoomDeleteComposer, RoomDimmerPresetsEvent, RoomDoorbellAcceptedEvent, RoomDoorbellAccessComposer, RoomEnterComposer, RoomEnterErrorEvent, RoomEnterEvent, RoomEntryInfoMessageEvent, RoomEntryTileMessageEvent, RoomEventCancelEvent, RoomEventEvent, RoomFilterSettingsMessageEvent, RoomForwardEvent, RoomGiveRightsComposer, RoomHeightMapEvent, RoomHeightMapUpdateEvent, RoomInviteErrorEvent, RoomInviteEvent, RoomKickUserComposer, RoomMessageNotificationMessageEvent, RoomMuteComposer, RoomMuteUserComposer, RoomNetworkOpenConnectionMessageComposer, RoomOccupiedTilesMessageEvent, RoomPaintEvent, RoomPollResultEvent, RoomReadyMessageEvent, RoomRightsClearEvent, RoomRightsEvent, RoomRightsOwnerEvent, RoomScoreEvent, RoomSettingsComposer, RoomSettingsDataEvent, RoomSettingsErrorEvent, RoomSettingsSaveErrorEvent, RoomSettingsSavedEvent, RoomSettingsUpdatedEvent, RoomTakeRightsComposer, RoomTextSearchMessageComposer, RoomThumbnailUpdateResultEvent, RoomUnbanUserComposer, RoomUnitActionComposer, RoomUnitBackgroundComposer, RoomUnitChatComposer, RoomUnitChatEvent, RoomUnitChatShoutComposer, RoomUnitChatShoutEvent, RoomUnitChatStyleComposer, RoomUnitChatWhisperComposer, RoomUnitChatWhisperEvent, RoomUnitDanceComposer, RoomUnitDanceEvent, RoomUnitDropHandItemComposer, RoomUnitEffectEvent, RoomUnitEvent, RoomUnitExpressionEvent, RoomUnitGiveHandItemComposer, RoomUnitGiveHandItemPetComposer, RoomUnitHandItemEvent, RoomUnitHandItemReceivedEvent, RoomUnitIdleEvent, RoomUnitInfoEvent, RoomUnitLookComposer, RoomUnitNumberEvent, RoomUnitPostureComposer, RoomUnitRemoveEvent, RoomUnitSignComposer, RoomUnitStatusEvent, RoomUnitTypingEvent, RoomUnitTypingStartComposer, RoomUnitTypingStopComposer, RoomUnitWalkComposer, RoomUsersClassificationMessageComposer, RoomUsersWithRightsComposer, RoomVisitsEvent, RoomVisualizationSettingsEvent, RoomsWhereMyFriendsAreSearchMessageComposer, RoomsWithHighestScoreSearchMessageComposer, SSOTicketMessageComposer, SanctionStatusEvent, SaveRoomSettingsComposer, SaveWardrobeOutfitMessageComposer, ScrGetKickbackInfoMessageComposer, ScrSendKickbackInfoMessageEvent, SearchFaqsMessageComposer, SeasonalCalendarDailyOfferMessageEvent, SeasonalQuestsMessageEvent, SecondsUntilMessageEvent, SelectClubGiftComposer, SellablePetPalettesMessageEvent, SendMessageComposer, SendRoomInviteComposer, SetActivatedBadgesComposer, SetClothingChangeDataMessageComposer, SetItemDataMessageComposer, SetObjectDataMessageComposer, SetPhoneNumberVerificationStatusMessageComposer, SetRelationshipStatusComposer, SetRoomSessionTagsMessageComposer, SetTargetedOfferStateComposer, SetYoutubeDisplayPlaylistMessageComposer, ShopTargetedOfferViewedComposer, ShowEnforceRoomCategoryDialogEvent, ShowMysteryBoxWaitMessageEvent, SimpleAlertMessageEvent, StartCampaignMessageComposer, StartRoomPollEvent, SubmitRoomToCompetitionMessageComposer, TalentLevelUpEvent, TalentTrackComposer, TalentTrackLevelMessageEvent, TalentTrackMessageEvent, TargetedOfferEvent, TargetedOfferNotFoundEvent, ThreadMessagesMessageEvent, ThumbnailStatusMessageEvent, TogglePetBreedingComposer, TogglePetRidingComposer, ToggleStaffPickMessageComposer, TradingAcceptComposer, TradingAcceptEvent, TradingCancelComposer, TradingCloseComposer, TradingCloseEvent, TradingCompletedEvent, TradingConfirmationComposer, TradingConfirmationEvent, TradingListAddItemComposer, TradingListAddItemsComposer, TradingListItemEvent, TradingListItemRemoveComposer, TradingNoSuchItemEvent, TradingNotOpenEvent, TradingOpenComposer, TradingOpenEvent, TradingOpenFailedEvent, TradingOtherNotAllowedEvent, TradingUnacceptComposer, TradingYouAreNotAllowedEvent, TraxSongInfoMessageEvent, TryPhoneNumberMessageComposer, TryPhoneNumberResultMessageEvent, TryVerificationCodeResultMessageEvent, UnblockGroupMemberMessageComposer, UnignoreUserComposer, UniqueIDMessageComposer, UnloadGameMessageEvent, UnreadForumsCountMessageEvent, UnseenItemsEvent, UnseenResetCategoryComposer, UnseenResetItemsComposer, UpdateActionMessageComposer, UpdateConditionMessageComposer, UpdateFloorPropertiesMessageComposer, UpdateForumReadMarkerMessageComposer, UpdateForumSettingsMessageComposer, UpdateFurniturePositionComposer, UpdateHomeRoomMessageComposer, UpdateMessageMessageEvent, UpdateRoomCategoryAndTradeSettingsComposer, UpdateRoomFilterMessageComposer, UpdateRoomThumbnailMessageComposer, UpdateThreadMessageComposer, UpdateThreadMessageEvent, UpdateTriggerMessageComposer, UsePetProductComposer, UserBannedMessageEvent, UserChatlogEvent, UserClassificationMessageEvent, UserCreditsEvent, UserCurrencyComposer, UserCurrencyEvent, UserCurrentBadgesComposer, UserCurrentBadgesEvent, UserEventCatsEvent, UserFigureComposer, UserFlatCatsEvent, UserGameAchievementsMessageEvent, UserInfoEvent, UserMottoComposer, UserNameChangeMessageEvent, UserPermissionsEvent, UserProfileComposer, UserProfileEvent, UserRelationshipsComposer, UserRespectComposer, UserSettingsCameraFollowComposer, UserSettingsEvent, UserSettingsOldChatComposer, UserSettingsRoomInvitesComposer, UserSettingsSoundComposer, UserSongDisksInventoryMessageEvent, UserSubscriptionComposer, UserSubscriptionEvent, UserTagsMessageEvent, UserUnbannedFromRoomEvent, UserWardrobePageEvent, VerifyCodeMessageComposer, VersionCheckMessageComposer, VisitUserComposer, VoteForRoomMessageComposer, VotePollCounterMessageComposer, VoucherRedeemErrorMessageEvent, VoucherRedeemOkMessageEvent, WardrobeMessageEvent, WeeklyCompetitiveFriendsLeaderboardEvent, WeeklyCompetitiveLeaderboardEvent, WeeklyGameRewardEvent, WeeklyGameRewardWinnersEvent, WelcomeGiftChangeEmailComposer, WelcomeGiftChangeEmailResultEvent, WelcomeGiftStatusEvent, WiredFurniActionEvent, WiredFurniConditionEvent, WiredFurniTriggerEvent, WiredOpenEvent, WiredRewardResultMessageEvent, WiredSaveSuccessEvent, WiredValidationErrorEvent, YouArePlayingGameEvent, YouAreSpectatorMessageEvent, YoutubeControlVideoMessageEvent, YoutubeDisplayPlaylistsEvent, YoutubeDisplayVideoMessageEvent } from './messages'; -import { ClickUserMessageComposer } from './messages'; export class NitroMessages implements IMessageConfiguration { @@ -581,7 +580,6 @@ export class NitroMessages implements IMessageConfiguration { // CUSTOM PACKETS this._composers.set(OutgoingHeader.CLICK_FURNI, ClickFurniMessageComposer); - this._composers.set(OutgoingHeader.CLICK_USER, ClickUserMessageComposer); // AUTHENTICATION this._composers.set(OutgoingHeader.AUTHENTICATION, AuthenticationMessageComposer); diff --git a/packages/communication/src/SocketConnection.ts b/packages/communication/src/SocketConnection.ts index 93d0c15..d252924 100644 --- a/packages/communication/src/SocketConnection.ts +++ b/packages/communication/src/SocketConnection.ts @@ -1,5 +1,5 @@ import { ICodec, IConnection, IMessageComposer, IMessageConfiguration, IMessageDataWrapper, IMessageEvent, WebSocketEventEnum } from '@nitrots/api'; -import { GetEventDispatcher, NitroEvent, NitroEventType } from '@nitrots/events'; +import { GetEventDispatcher, NitroEvent, NitroEventType, ReconnectEvent } from '@nitrots/events'; import { NitroLogger } from '@nitrots/utils'; import { EvaWireFormat } from './codec'; import { MessageClassManager } from './messages'; @@ -23,19 +23,39 @@ export class SocketConnection implements IConnection private _onErrorCallback: (event: Event) => void = null; private _onMessageCallback: (event: MessageEvent) => void = null; + // Reconnection state + private _socketUrl: string = null; + private _reconnectAttempt: number = 0; + private _reconnectTimer: ReturnType = null; + private _isReconnecting: boolean = false; + private _intentionalClose: boolean = false; + private _wasAuthenticated: boolean = false; + + public static readonly MAX_RECONNECT_ATTEMPTS: number = 7; + public static readonly BASE_RECONNECT_DELAY_MS: number = 1000; + public static readonly MAX_RECONNECT_DELAY_MS: number = 30000; + public init(socketUrl: string): void { if(!socketUrl || !socketUrl.length) return; + this._socketUrl = socketUrl; + this._intentionalClose = false; + + this.createSocket(socketUrl); + } + + private createSocket(socketUrl: string): void + { this._dataBuffer = new ArrayBuffer(0); this._socket = new WebSocket(socketUrl); this._socket.binaryType = 'arraybuffer'; // Store callbacks for cleanup - this._onOpenCallback = () => GetEventDispatcher().dispatchEvent(new NitroEvent(NitroEventType.SOCKET_OPENED)); - this._onCloseCallback = () => GetEventDispatcher().dispatchEvent(new NitroEvent(NitroEventType.SOCKET_CLOSED)); - this._onErrorCallback = () => GetEventDispatcher().dispatchEvent(new NitroEvent(NitroEventType.SOCKET_ERROR)); + this._onOpenCallback = () => this.onSocketOpened(); + this._onCloseCallback = (event: Event) => this.onSocketClosed(event as CloseEvent); + this._onErrorCallback = () => this.onSocketError(); this._onMessageCallback = (event: MessageEvent) => { this._dataBuffer = this.concatArrayBuffers(this._dataBuffer, event.data); @@ -48,29 +68,152 @@ export class SocketConnection implements IConnection this._socket.addEventListener(WebSocketEventEnum.CONNECTION_MESSAGE, this._onMessageCallback); } - public dispose(): void + private onSocketOpened(): void { - if(this._socket) + if(this._isReconnecting) { - // Remove all event listeners - if(this._onOpenCallback) this._socket.removeEventListener(WebSocketEventEnum.CONNECTION_OPENED, this._onOpenCallback); - if(this._onCloseCallback) this._socket.removeEventListener(WebSocketEventEnum.CONNECTION_CLOSED, this._onCloseCallback); - if(this._onErrorCallback) this._socket.removeEventListener(WebSocketEventEnum.CONNECTION_ERROR, this._onErrorCallback); - if(this._onMessageCallback) this._socket.removeEventListener(WebSocketEventEnum.CONNECTION_MESSAGE, this._onMessageCallback); + NitroLogger.log('[SocketConnection] Reconnected successfully after ' + this._reconnectAttempt + ' attempt(s)'); - // Close socket if still open - if(this._socket.readyState === WebSocket.OPEN || this._socket.readyState === WebSocket.CONNECTING) - { - this._socket.close(); - } + this._reconnectAttempt = 0; + this._isReconnecting = false; - this._socket = null; + GetEventDispatcher().dispatchEvent(new NitroEvent(NitroEventType.SOCKET_RECONNECTED)); + } + else + { + GetEventDispatcher().dispatchEvent(new NitroEvent(NitroEventType.SOCKET_OPENED)); + } + } + + private onSocketClosed(event: CloseEvent): void + { + NitroLogger.log('[SocketConnection] Socket closed, code: ' + (event?.code ?? 'unknown') + ', reason: ' + (event?.reason || 'none')); + + if(this._intentionalClose) + { + GetEventDispatcher().dispatchEvent(new NitroEvent(NitroEventType.SOCKET_CLOSED)); + return; } + const code = event?.code ?? 0; + + if(code === 1000 || code === 1001) + { + NitroLogger.log('[SocketConnection] Server closed cleanly (code ' + code + ') - not reconnecting'); + + this._isAuthenticated = false; + this._isReady = false; + + GetEventDispatcher().dispatchEvent(new NitroEvent(NitroEventType.SOCKET_CLOSED)); + return; + } + + if(this._isAuthenticated) this._wasAuthenticated = true; + + this._isAuthenticated = false; + this._isReady = false; + this._pendingClientMessages = []; + this._pendingServerMessages = []; + + this.attemptReconnect(); + } + + private onSocketError(): void + { + if(this._isReconnecting) + { + NitroLogger.log('[SocketConnection] Reconnect attempt ' + this._reconnectAttempt + ' failed'); + return; + } + + if(!this._wasAuthenticated && !this._isAuthenticated) + { + GetEventDispatcher().dispatchEvent(new NitroEvent(NitroEventType.SOCKET_ERROR)); + } + } + + private attemptReconnect(): void + { + if(this._reconnectAttempt >= SocketConnection.MAX_RECONNECT_ATTEMPTS) + { + NitroLogger.log('[SocketConnection] Max reconnect attempts reached (' + SocketConnection.MAX_RECONNECT_ATTEMPTS + ')'); + + this._isReconnecting = false; + this._wasAuthenticated = false; + + GetEventDispatcher().dispatchEvent(new ReconnectEvent( + NitroEventType.SOCKET_RECONNECT_FAILED, + this._reconnectAttempt, + SocketConnection.MAX_RECONNECT_ATTEMPTS + )); + + GetEventDispatcher().dispatchEvent(new NitroEvent(NitroEventType.SOCKET_CLOSED)); + + return; + } + + this._isReconnecting = true; + this._reconnectAttempt++; + + const delay = Math.min( + SocketConnection.BASE_RECONNECT_DELAY_MS * Math.pow(2, this._reconnectAttempt - 1) + Math.random() * 1000, + SocketConnection.MAX_RECONNECT_DELAY_MS + ); + + NitroLogger.log('[SocketConnection] Reconnecting in ' + Math.round(delay) + 'ms (attempt ' + this._reconnectAttempt + '/' + SocketConnection.MAX_RECONNECT_ATTEMPTS + ')'); + + GetEventDispatcher().dispatchEvent(new ReconnectEvent( + NitroEventType.SOCKET_RECONNECTING, + this._reconnectAttempt, + SocketConnection.MAX_RECONNECT_ATTEMPTS + )); + + this._reconnectTimer = setTimeout(() => + { + this._reconnectTimer = null; + + this.cleanupSocket(); + + this.createSocket(this._socketUrl); + }, delay); + } + + private cleanupSocket(): void + { + if(!this._socket) return; + + if(this._onOpenCallback) this._socket.removeEventListener(WebSocketEventEnum.CONNECTION_OPENED, this._onOpenCallback); + if(this._onCloseCallback) this._socket.removeEventListener(WebSocketEventEnum.CONNECTION_CLOSED, this._onCloseCallback); + if(this._onErrorCallback) this._socket.removeEventListener(WebSocketEventEnum.CONNECTION_ERROR, this._onErrorCallback); + if(this._onMessageCallback) this._socket.removeEventListener(WebSocketEventEnum.CONNECTION_MESSAGE, this._onMessageCallback); + + if(this._socket.readyState === WebSocket.OPEN || this._socket.readyState === WebSocket.CONNECTING) + { + try { this._socket.close(); } catch(e) { /* ignore */ } + } + + this._socket = null; this._onOpenCallback = null; this._onCloseCallback = null; this._onErrorCallback = null; this._onMessageCallback = null; + } + + public dispose(): void + { + this._intentionalClose = true; + + if(this._reconnectTimer) + { + clearTimeout(this._reconnectTimer); + this._reconnectTimer = null; + } + + this._isReconnecting = false; + this._reconnectAttempt = 0; + this._wasAuthenticated = false; + + this.cleanupSocket(); this._pendingClientMessages = []; this._pendingServerMessages = []; @@ -142,7 +285,7 @@ export class SocketConnection implements IConnection private write(buffer: ArrayBuffer): void { - if(this._socket.readyState !== WebSocket.OPEN) return; + if(!this._socket || this._socket.readyState !== WebSocket.OPEN) return; this._socket.send(buffer); } @@ -286,6 +429,16 @@ export class SocketConnection implements IConnection return this._isAuthenticated; } + public get isReconnecting(): boolean + { + return this._isReconnecting; + } + + public get wasAuthenticated(): boolean + { + return this._wasAuthenticated; + } + public get dataBuffer(): ArrayBuffer { return this._dataBuffer; diff --git a/packages/communication/src/messages/outgoing/OutgoingHeader.ts b/packages/communication/src/messages/outgoing/OutgoingHeader.ts index f1d9b8f..69f9061 100644 --- a/packages/communication/src/messages/outgoing/OutgoingHeader.ts +++ b/packages/communication/src/messages/outgoing/OutgoingHeader.ts @@ -1,7 +1,6 @@ export class OutgoingHeader { public static CLICK_FURNI = 6002; - public static CLICK_USER = 10020; public static ACHIEVEMENT_LIST = 219; public static AUTHENTICATION = -1; diff --git a/packages/communication/src/messages/outgoing/room/engine/ClickUserMessageComposer.ts b/packages/communication/src/messages/outgoing/room/engine/ClickUserMessageComposer.ts deleted file mode 100644 index a59d16d..0000000 --- a/packages/communication/src/messages/outgoing/room/engine/ClickUserMessageComposer.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { IMessageComposer } from '@nitrots/api'; - -export class ClickUserMessageComposer implements IMessageComposer> -{ - private _data: ConstructorParameters; - - constructor(roomUnitId: number) - { - this._data = [ roomUnitId ]; - } - - public getMessageArray() - { - return this._data; - } - - public dispose(): void - { - return; - } -} diff --git a/packages/communication/src/messages/outgoing/room/engine/index.ts b/packages/communication/src/messages/outgoing/room/engine/index.ts index a3aeb1a..ebee1cd 100644 --- a/packages/communication/src/messages/outgoing/room/engine/index.ts +++ b/packages/communication/src/messages/outgoing/room/engine/index.ts @@ -2,7 +2,6 @@ export * from './BotPlaceComposer'; export * from './BotRemoveComposer'; export * from './BotSkillSaveComposer'; export * from './ClickFurniMessageComposer'; -export * from './ClickUserMessageComposer'; export * from './CompostPlantMessageComposer'; export * from './GetItemDataComposer'; export * from './HarvestPetMessageComposer'; diff --git a/packages/events/src/NitroEventType.ts b/packages/events/src/NitroEventType.ts index 563bcb7..9e575ac 100644 --- a/packages/events/src/NitroEventType.ts +++ b/packages/events/src/NitroEventType.ts @@ -8,6 +8,10 @@ export class NitroEventType public static readonly SOCKET_CLOSED = 'SOCKET_CLOSED'; public static readonly SOCKET_ERROR = 'SOCKET_ERROR'; public static readonly SOCKET_CONNECTED = 'SOCKET_CONNECTED'; + public static readonly SOCKET_RECONNECTING = 'SOCKET_RECONNECTING'; + public static readonly SOCKET_RECONNECTED = 'SOCKET_RECONNECTED'; + public static readonly SOCKET_RECONNECT_FAILED = 'SOCKET_RECONNECT_FAILED'; + public static readonly SOCKET_REAUTHENTICATED = 'SOCKET_REAUTHENTICATED'; public static readonly AVATAR_ASSET_DOWNLOADED = 'AVATAR_ASSET_DOWNLOADED'; public static readonly AVATAR_ASSET_LOADED = 'AVATAR_ASSET_LOADED'; public static readonly AVATAR_EFFECT_DOWNLOADED = 'AVATAR_EFFECT_DOWNLOADED'; diff --git a/packages/events/src/core/ReconnectEvent.ts b/packages/events/src/core/ReconnectEvent.ts new file mode 100644 index 0000000..45ce1c0 --- /dev/null +++ b/packages/events/src/core/ReconnectEvent.ts @@ -0,0 +1,25 @@ +import { NitroEvent } from './NitroEvent'; + +export class ReconnectEvent extends NitroEvent +{ + private _attempt: number; + private _maxAttempts: number; + + constructor(type: string, attempt: number = 0, maxAttempts: number = 0) + { + super(type); + + this._attempt = attempt; + this._maxAttempts = maxAttempts; + } + + public get attempt(): number + { + return this._attempt; + } + + public get maxAttempts(): number + { + return this._maxAttempts; + } +} diff --git a/packages/events/src/core/index.ts b/packages/events/src/core/index.ts index 9a5d80e..97ec3db 100644 --- a/packages/events/src/core/index.ts +++ b/packages/events/src/core/index.ts @@ -1,4 +1,5 @@ export * from './ConfigurationEvent'; export * from './MessageEvent'; export * from './NitroEvent'; +export * from './ReconnectEvent'; export * from './SocketConnectionEvent'; diff --git a/packages/room/src/RoomObjectEventHandler.ts b/packages/room/src/RoomObjectEventHandler.ts index 65ca483..2725f26 100644 --- a/packages/room/src/RoomObjectEventHandler.ts +++ b/packages/room/src/RoomObjectEventHandler.ts @@ -1,5 +1,5 @@ import { IFurnitureStackingHeightMap, ILegacyWallGeometry, IObjectData, IRoomCanvasMouseListener, IRoomEngineServices, IRoomGeometry, IRoomObject, IRoomObjectController, IRoomObjectEventManager, ISelectedRoomObjectData, IVector3D, MouseEventType, RoomObjectCategory, RoomObjectOperationType, RoomObjectPlacementSource, RoomObjectType, RoomObjectUserType, RoomObjectVariable } from '@nitrots/api'; -import { BotPlaceComposer, ClickFurniMessageComposer, ClickUserMessageComposer, FurnitureColorWheelComposer, FurnitureDiceActivateComposer, FurnitureDiceDeactivateComposer, FurnitureFloorUpdateComposer, FurnitureGroupInfoComposer, FurnitureMultiStateComposer, FurnitureOneWayDoorComposer, FurniturePickupComposer, FurniturePlaceComposer, FurniturePostItPlaceComposer, FurnitureRandomStateComposer, FurnitureWallMultiStateComposer, FurnitureWallUpdateComposer, GetCommunication, GetItemDataComposer, GetResolutionAchievementsMessageComposer, PetMoveComposer, PetPlaceComposer, RemoveWallItemComposer, RoomUnitLookComposer, RoomUnitWalkComposer, SetItemDataMessageComposer, SetObjectDataMessageComposer } from '@nitrots/communication'; +import { BotPlaceComposer, ClickFurniMessageComposer, FurnitureColorWheelComposer, FurnitureDiceActivateComposer, FurnitureDiceDeactivateComposer, FurnitureFloorUpdateComposer, FurnitureGroupInfoComposer, FurnitureMultiStateComposer, FurnitureOneWayDoorComposer, FurniturePickupComposer, FurniturePlaceComposer, FurniturePostItPlaceComposer, FurnitureRandomStateComposer, FurnitureWallMultiStateComposer, FurnitureWallUpdateComposer, GetCommunication, GetItemDataComposer, GetResolutionAchievementsMessageComposer, PetMoveComposer, PetPlaceComposer, RemoveWallItemComposer, RoomUnitLookComposer, RoomUnitWalkComposer, SetItemDataMessageComposer, SetObjectDataMessageComposer } from '@nitrots/communication'; import { GetConfiguration } from '@nitrots/configuration'; import { GetEventDispatcher, RoomEngineDimmerStateEvent, RoomEngineObjectEvent, RoomEngineObjectPlacedEvent, RoomEngineObjectPlacedOnUserEvent, RoomEngineObjectPlaySoundEvent, RoomEngineRoomAdEvent, RoomEngineSamplePlaybackEvent, RoomEngineTriggerWidgetEvent, RoomEngineUseProductEvent, RoomObjectBadgeAssetEvent, RoomObjectDataRequestEvent, RoomObjectDimmerStateUpdateEvent, RoomObjectEvent, RoomObjectFloorHoleEvent, RoomObjectFurnitureActionEvent, RoomObjectHSLColorEnableEvent, RoomObjectHSLColorEnabledEvent, RoomObjectMouseEvent, RoomObjectMoveEvent, RoomObjectPlaySoundIdEvent, RoomObjectRoomAdEvent, RoomObjectSamplePlaybackEvent, RoomObjectSoundMachineEvent, RoomObjectStateChangedEvent, RoomObjectTileMouseEvent, RoomObjectWallMouseEvent, RoomObjectWidgetRequestEvent, RoomSpriteMouseEvent } from '@nitrots/events'; import { GetRoomSessionManager, GetSessionDataManager } from '@nitrots/session'; @@ -297,7 +297,7 @@ export class RoomObjectEventHandler implements IRoomCanvasMouseListener, IRoomOb } } - private clickRoomObject(event: RoomObjectMouseEvent, operation: string): void + private clickRoomObject(event: RoomObjectMouseEvent): void { if(!event || event.altKey || event.ctrlKey || event.shiftKey) return; @@ -319,25 +319,20 @@ export class RoomObjectEventHandler implements IRoomCanvasMouseListener, IRoomOb return; } - - if((category === RoomObjectCategory.UNIT) && (operation === RoomObjectOperationType.OBJECT_UNDEFINED) && (objectType === RoomObjectUserType.USER)) - { - GetCommunication().connection.send(new ClickUserMessageComposer(objectId)); - } } private handleRoomObjectMouseClickEvent(event: RoomObjectMouseEvent, roomId: number): void { if(!event) return; + this.clickRoomObject(event); + let operation = RoomObjectOperationType.OBJECT_UNDEFINED; const selectedData = this.getSelectedRoomObjectData(roomId); if(selectedData) operation = selectedData.operation; - this.clickRoomObject(event, operation); - let didWalk = false; let didMove = false; diff --git a/packages/room/src/common/floorplan/FloorplanEditor.ts b/packages/room/src/common/floorplan/FloorplanEditor.ts index 1a5fae8..d6d2db2 100644 --- a/packages/room/src/common/floorplan/FloorplanEditor.ts +++ b/packages/room/src/common/floorplan/FloorplanEditor.ts @@ -25,8 +25,6 @@ export class FloorplanEditor private _image: HTMLImageElement; - public onTilemapChange: (() => void) | null = null; - constructor() { const width = TILE_SIZE * MAX_NUM_TILE_PER_AXIS + 20; @@ -299,8 +297,6 @@ export class FloorplanEditor } this.renderSquareSelectionPreview(); - - if(this.onTilemapChange) this.onTilemapChange(); } private renderSquareSelectionPreview(): void @@ -477,7 +473,6 @@ export class FloorplanEditor this._squareSelectStart = null; this._squareSelectEnd = null; this.clearCanvas(); - this.onTilemapChange = null; } diff --git a/packages/session/src/RoomSessionManager.ts b/packages/session/src/RoomSessionManager.ts index 073b9c8..6584bbe 100644 --- a/packages/session/src/RoomSessionManager.ts +++ b/packages/session/src/RoomSessionManager.ts @@ -1,22 +1,49 @@ import { IRoomHandlerListener, IRoomSession, IRoomSessionManager } from '@nitrots/api'; import { GetCommunication } from '@nitrots/communication'; -import { GetEventDispatcher, RoomSessionEvent } from '@nitrots/events'; +import { GetEventDispatcher, NitroEventType, RoomSessionEvent } from '@nitrots/events'; +import { NitroLogger } from '@nitrots/utils'; import { RoomSession } from './RoomSession'; import { BaseHandler, GenericErrorHandler, PetPackageHandler, PollHandler, RoomChatHandler, RoomDataHandler, RoomDimmerPresetsHandler, RoomPermissionsHandler, RoomPresentHandler, RoomSessionHandler, RoomUsersHandler, WordQuizHandler } from './handler'; +const STORAGE_KEY_ROOM_ID = 'nitro.session.lastRoomId'; +const STORAGE_KEY_ROOM_PASSWORD = 'nitro.session.lastRoomPassword'; + export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerListener { private _handlers: BaseHandler[] = []; private _sessions: Map = new Map(); private _pendingSession: IRoomSession = null; - private _sessionStarting: boolean = false; private _viewerSession: IRoomSession = null; + private _lastRoomId: number = -1; + private _lastRoomPassword: string = null; + private _isReconnecting: boolean = false; + private _reconnectGuardTimer: ReturnType = null; public async init(): Promise { this.createHandlers(); this.processPendingSession(); + this.setupReconnectListener(); + this.checkPersistedRoom(); + } + + private checkPersistedRoom(): void + { + try + { + const storedRoomId = sessionStorage.getItem(STORAGE_KEY_ROOM_ID); + + if(!storedRoomId) return; + + const roomId = parseInt(storedRoomId, 10); + + if(isNaN(roomId) || roomId <= 0) return; + this._lastRoomId = roomId; + this._lastRoomPassword = sessionStorage.getItem(STORAGE_KEY_ROOM_PASSWORD) || null; + this._isReconnecting = true; + } + catch(e) {} } private createHandlers(): void @@ -40,6 +67,158 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList ); } + private setupReconnectListener(): void + { + GetEventDispatcher().addEventListener(NitroEventType.SOCKET_RECONNECTING, () => + { + this._isReconnecting = true; + }); + + GetEventDispatcher().addEventListener(NitroEventType.SOCKET_RECONNECTED, () => + { + this.clearGuardTimer(); + this._reconnectGuardTimer = setTimeout(() => + { + this._reconnectGuardTimer = null; + + if(!this._isReconnecting) return; + this.attemptRoomReEntry(); + }, 5000); + }); + + GetEventDispatcher().addEventListener(NitroEventType.SOCKET_REAUTHENTICATED, () => + { + this.clearGuardTimer(); + this.attemptRoomReEntry(); + }); + + GetEventDispatcher().addEventListener(NitroEventType.SOCKET_RECONNECT_FAILED, () => + { + this.clearGuardTimer(); + this._isReconnecting = false; + this._lastRoomId = -1; + this._lastRoomPassword = null; + this.clearPersistedRoom(); + }); + + GetEventDispatcher().addEventListener(NitroEventType.SOCKET_CLOSED, () => + { + this.clearGuardTimer(); + this._isReconnecting = false; + this._lastRoomId = -1; + this._lastRoomPassword = null; + this.clearPersistedRoom(); + }); + } + + private clearGuardTimer(): void + { + if(this._reconnectGuardTimer) + { + clearTimeout(this._reconnectGuardTimer); + this._reconnectGuardTimer = null; + } + } + + private attemptRoomReEntry(): void + { + const roomId = this._lastRoomId; + const password = this._lastRoomPassword; + + if(roomId <= 0) + { + this._isReconnecting = false; + + return; + } + + this._sessions.clear(); + this._viewerSession = null; + this.createSession(roomId, password); + this.clearGuardTimer(); + this._reconnectGuardTimer = setTimeout(() => + { + this._reconnectGuardTimer = null; + + if(this._isReconnecting) + { + this._isReconnecting = false; + } + }, 10000); + } + + public tryRestoreSession(): boolean + { + try + { + const storedRoomId = sessionStorage.getItem(STORAGE_KEY_ROOM_ID); + + if(!storedRoomId) return false; + + const roomId = parseInt(storedRoomId, 10); + + if(isNaN(roomId) || roomId <= 0) return false; + + const password = sessionStorage.getItem(STORAGE_KEY_ROOM_PASSWORD) || null; + + this._isReconnecting = true; + + this.createSession(roomId, password); + + this.clearGuardTimer(); + this._reconnectGuardTimer = setTimeout(() => + { + this._reconnectGuardTimer = null; + + if(this._isReconnecting) + { + this._isReconnecting = false; + } + }, 10000); + + return true; + } + catch(e) + { + return false; + } + } + + private persistRoom(roomId: number, password: string): void + { + try + { + if(roomId > 0) + { + sessionStorage.setItem(STORAGE_KEY_ROOM_ID, roomId.toString()); + + if(password) + { + sessionStorage.setItem(STORAGE_KEY_ROOM_PASSWORD, password); + } + else + { + sessionStorage.removeItem(STORAGE_KEY_ROOM_PASSWORD); + } + } + else + { + this.clearPersistedRoom(); + } + } + catch(e) {} + } + + private clearPersistedRoom(): void + { + try + { + sessionStorage.removeItem(STORAGE_KEY_ROOM_ID); + sessionStorage.removeItem(STORAGE_KEY_ROOM_PASSWORD); + } + catch(e) {} + } + private setHandlers(session: IRoomSession): void { if(!this._handlers || !this._handlers.length) return; @@ -92,6 +271,10 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList this._viewerSession = roomSession; + this._lastRoomId = roomSession.roomId; + this._lastRoomPassword = roomSession.password; + this.persistRoom(roomSession.roomId, roomSession.password); + this.startSession(this._viewerSession); return true; @@ -125,6 +308,18 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList this._sessions.delete(this.getRoomId(id)); + if(openLandingView && !this._isReconnecting) + { + this._lastRoomId = -1; + this._lastRoomPassword = null; + this.clearPersistedRoom(); + } + + if(this._isReconnecting) + { + return; + } + GetEventDispatcher().dispatchEvent(new RoomSessionEvent(RoomSessionEvent.ENDED, session, openLandingView)); } @@ -132,15 +327,34 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList { const session = this.getSession(id); - if(!session) return; + if(!session) + { + return; + } switch(type) { case RoomSessionHandler.RS_CONNECTED: + if(this._isReconnecting) + { + this.clearGuardTimer(); + this._isReconnecting = false; + } + return; case RoomSessionHandler.RS_READY: + + if(this._isReconnecting) + { + this.clearGuardTimer(); + this._isReconnecting = false; + } + return; case RoomSessionHandler.RS_DISCONNECTED: + + if(this._isReconnecting) return; + this.removeSession(id); return; } @@ -158,6 +372,9 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList this._sessions.set(this.getRoomId(toRoomId), existing); + this._lastRoomId = toRoomId; + this.persistRoom(toRoomId, existing.password); + this.setHandlers(existing); } diff --git a/packages/session/src/handler/RoomChatHandler.ts b/packages/session/src/handler/RoomChatHandler.ts index 41aa2b0..cc17a8b 100644 --- a/packages/session/src/handler/RoomChatHandler.ts +++ b/packages/session/src/handler/RoomChatHandler.ts @@ -54,7 +54,7 @@ export class RoomChatHandler extends BaseHandler if(!parser) return; - GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, parser.giverUserId, '', RoomSessionChatEvent.CHAT_TYPE_HAND_ITEM_RECEIVED, SystemChatStyleEnum.GENERIC, [], null, parser.handItemType)); + GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, parser.giverUserId, '', RoomSessionChatEvent.CHAT_TYPE_HAND_ITEM_RECEIVED, SystemChatStyleEnum.GENERIC, [], parser.handItemType)); } private onRespectReceivedEvent(event: RespectReceivedEvent): void @@ -136,7 +136,7 @@ export class RoomChatHandler extends BaseHandler break; } - GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, petData.roomIndex, '', chatType, SystemChatStyleEnum.GENERIC, [], null, userRoomIndex)); + GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, petData.roomIndex, '', chatType, SystemChatStyleEnum.GENERIC, null, userRoomIndex)); } private onFloodControlEvent(event: FloodControlEvent): void @@ -168,6 +168,6 @@ export class RoomChatHandler extends BaseHandler if(!parser) return; - GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, session.ownRoomIndex, '', RoomSessionChatEvent.CHAT_TYPE_MUTE_REMAINING, SystemChatStyleEnum.GENERIC, [], null, parser.seconds)); + GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, session.ownRoomIndex, '', RoomSessionChatEvent.CHAT_TYPE_MUTE_REMAINING, SystemChatStyleEnum.GENERIC, [], parser.seconds)); } } diff --git a/packages/utils/src/filters/WiredFilter.ts b/packages/utils/src/filters/WiredFilter.ts index 10bc8d0..303ae86 100644 --- a/packages/utils/src/filters/WiredFilter.ts +++ b/packages/utils/src/filters/WiredFilter.ts @@ -63,14 +63,13 @@ export class WiredFilter extends Filter void main(void) { vec4 currentColor = texture(uTexture, vTextureCoord); - vec3 colorLine = uLineColor; - vec3 colorOverlay = uColor; + vec3 colorLine = uLineColor * currentColor.a; + vec3 colorOverlay = uColor * currentColor.a; if(currentColor.r == 0.0 && currentColor.g == 0.0 && currentColor.b == 0.0 && currentColor.a > 0.0) { finalColor = vec4(colorLine.r, colorLine.g, colorLine.b, currentColor.a); } else if(currentColor.a > 0.0) { - vec3 blendedOverlay = mix(currentColor.rgb, colorOverlay, 0.28); - finalColor = vec4(blendedOverlay.r, blendedOverlay.g, blendedOverlay.b, currentColor.a); + finalColor = vec4(colorOverlay.r, colorOverlay.g, colorOverlay.b, currentColor.a); } } `, From d45381716f0f15f77ae15003899f91b868a99f5c Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Fri, 20 Mar 2026 14:19:35 +0100 Subject: [PATCH 07/11] feat(floorplan): add real-time preview support to FloorplanEditor - Add getMapData() method to expose current floor map state - Enables real-time preview in the UI floor plan editor --- packages/room/src/common/floorplan/FloorplanEditor.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/room/src/common/floorplan/FloorplanEditor.ts b/packages/room/src/common/floorplan/FloorplanEditor.ts index d6d2db2..1a5fae8 100644 --- a/packages/room/src/common/floorplan/FloorplanEditor.ts +++ b/packages/room/src/common/floorplan/FloorplanEditor.ts @@ -25,6 +25,8 @@ export class FloorplanEditor private _image: HTMLImageElement; + public onTilemapChange: (() => void) | null = null; + constructor() { const width = TILE_SIZE * MAX_NUM_TILE_PER_AXIS + 20; @@ -297,6 +299,8 @@ export class FloorplanEditor } this.renderSquareSelectionPreview(); + + if(this.onTilemapChange) this.onTilemapChange(); } private renderSquareSelectionPreview(): void @@ -473,6 +477,7 @@ export class FloorplanEditor this._squareSelectStart = null; this._squareSelectEnd = null; this.clearCanvas(); + this.onTilemapChange = null; } From 958693fe2e068543d480ae98a3c951ada113eca8 Mon Sep 17 00:00:00 2001 From: duckietm Date: Fri, 20 Mar 2026 16:06:03 +0100 Subject: [PATCH 08/11] =?UTF-8?q?=F0=9F=86=99=20Stage=201=20reconnect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/events/src/EventDispatcher.ts | 7 + packages/room/src/RoomMessageHandler.ts | 18 ++ packages/session/src/RoomSessionManager.ts | 289 ++++++++++++++++-- .../session/src/handler/RoomSessionHandler.ts | 4 + 4 files changed, 301 insertions(+), 17 deletions(-) diff --git a/packages/events/src/EventDispatcher.ts b/packages/events/src/EventDispatcher.ts index 086383d..fd1ae2d 100644 --- a/packages/events/src/EventDispatcher.ts +++ b/packages/events/src/EventDispatcher.ts @@ -52,6 +52,13 @@ export class EventDispatcher implements IEventDispatcher { if(!event) return false; + // Debug: log SOCKET_ events to trace reconnection flow + if(event.type && event.type.startsWith('SOCKET_')) + { + const listenerCount = this._listeners.get(event.type)?.length ?? 0; + console.log('[EventDispatcher] Dispatching ' + event.type + ' (listeners: ' + listenerCount + ')'); + } + NitroLogger.events('Dispatched Event', event.type); this.processEvent(event); diff --git a/packages/room/src/RoomMessageHandler.ts b/packages/room/src/RoomMessageHandler.ts index fa0bd41..ed836f5 100644 --- a/packages/room/src/RoomMessageHandler.ts +++ b/packages/room/src/RoomMessageHandler.ts @@ -17,6 +17,7 @@ export class RoomMessageHandler private _currentRoomId: number = 0; private _ownUserId: number = 0; + private _ownRoomIndex: number = -1; private _initialConnection: boolean = true; private _guideId: number = -1; private _requesterId: number = -1; @@ -635,6 +636,7 @@ export class RoomMessageHandler if(user.webID === this._ownUserId) { + this._ownRoomIndex = user.roomIndex; this._roomEngine.setRoomSessionOwnUser(this._currentRoomId, user.roomIndex); this._roomEngine.updateRoomObjectUserOwn(this._currentRoomId, user.roomIndex); } @@ -735,6 +737,22 @@ export class RoomMessageHandler this._roomEngine.updateRoomObjectUserLocation(this._currentRoomId, status.id, location, goal, status.canStandUp, height, direction, status.headDirection); this._roomEngine.updateRoomObjectUserFlatControl(this._currentRoomId, status.id, null); + // Save own user's position for reconnection (only when not locked by reconnect flow) + if(status.id === this._ownRoomIndex) + { + try + { + const locked = sessionStorage.getItem('nitro.session.posLocked'); + + if(!locked) + { + sessionStorage.setItem('nitro.session.lastPosX', status.x.toString()); + sessionStorage.setItem('nitro.session.lastPosY', status.y.toString()); + } + } + catch(e) { /* ignore */ } + } + let isPosture = true; let postureUpdate = false; let postureType = RoomObjectVariable.STD; diff --git a/packages/session/src/RoomSessionManager.ts b/packages/session/src/RoomSessionManager.ts index 6584bbe..c8e979d 100644 --- a/packages/session/src/RoomSessionManager.ts +++ b/packages/session/src/RoomSessionManager.ts @@ -1,5 +1,5 @@ import { IRoomHandlerListener, IRoomSession, IRoomSessionManager } from '@nitrots/api'; -import { GetCommunication } from '@nitrots/communication'; +import { GetCommunication, RoomEnterComposer, RoomUnitWalkComposer } from '@nitrots/communication'; import { GetEventDispatcher, NitroEventType, RoomSessionEvent } from '@nitrots/events'; import { NitroLogger } from '@nitrots/utils'; import { RoomSession } from './RoomSession'; @@ -7,24 +7,36 @@ import { BaseHandler, GenericErrorHandler, PetPackageHandler, PollHandler, RoomC const STORAGE_KEY_ROOM_ID = 'nitro.session.lastRoomId'; const STORAGE_KEY_ROOM_PASSWORD = 'nitro.session.lastRoomPassword'; +const STORAGE_KEY_POS_X = 'nitro.session.lastPosX'; +const STORAGE_KEY_POS_Y = 'nitro.session.lastPosY'; export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerListener { private _handlers: BaseHandler[] = []; private _sessions: Map = new Map(); private _pendingSession: IRoomSession = null; + private _sessionStarting: boolean = false; private _viewerSession: IRoomSession = null; + + // Reconnection state tracking private _lastRoomId: number = -1; private _lastRoomPassword: string = null; private _isReconnecting: boolean = false; private _reconnectGuardTimer: ReturnType = null; + private _pendingRoomClear: ReturnType = null; + private _savedPosX: number = -1; + private _savedPosY: number = -1; public async init(): Promise { + console.log('[RoomSessionManager] init() called'); this.createHandlers(); this.processPendingSession(); this.setupReconnectListener(); + + // Check if there's a persisted room from a network disconnect (Vite page reload). + // sessionStorage survives same-tab reloads but is cleared on browser close. this.checkPersistedRoom(); } @@ -39,11 +51,20 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList const roomId = parseInt(storedRoomId, 10); if(isNaN(roomId) || roomId <= 0) return; + + NitroLogger.log('[RoomSessionManager] Found persisted room ' + roomId + ' - setting guard for page-reload restore'); + + // Pre-load memory state so attemptRoomReEntry and tryRestoreSession can use it this._lastRoomId = roomId; this._lastRoomPassword = sessionStorage.getItem(STORAGE_KEY_ROOM_PASSWORD) || null; + + // Enable guard to block DesktopViewEvent until we enter the stored room this._isReconnecting = true; } - catch(e) {} + catch(e) + { + // sessionStorage not available + } } private createHandlers(): void @@ -69,45 +90,82 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList private setupReconnectListener(): void { + console.log('[RoomSessionManager] setupReconnectListener() - registering event listeners'); + + // Mark reconnecting state early so DesktopViewEvent / home room redirects + // don't clear the tracked room before we can re-enter it GetEventDispatcher().addEventListener(NitroEventType.SOCKET_RECONNECTING, () => { - this._isReconnecting = true; + // Cancel any pending room ID clear from removeSession(). + // The server sends DesktopViewEvent before closing the socket, which + // schedules a delayed clear. We need to preserve the room ID for re-entry. + this.cancelRoomIdClear(); + + // Re-persist room to sessionStorage (it was cleared in removeSession) + if(this._lastRoomId > 0) + { + this.persistRoom(this._lastRoomId, this._lastRoomPassword); + } + + console.log('[RoomSessionManager] SOCKET_RECONNECTING fired! lastRoomId=' + this._lastRoomId); + this._isReconnecting = true; }); + // SOCKET_RECONNECTED: the WebSocket is open but NOT yet authenticated. + // We set up a fallback timer here in case the server doesn't send + // AuthenticatedEvent (e.g. SSO ticket consumed). GetEventDispatcher().addEventListener(NitroEventType.SOCKET_RECONNECTED, () => { + console.log('[RoomSessionManager] SOCKET_RECONNECTED fired! lastRoomId=' + this._lastRoomId); + + // Fallback: if REAUTHENTICATED doesn't fire within 5 seconds, + // try to re-enter the room anyway (the connection might still work) this.clearGuardTimer(); this._reconnectGuardTimer = setTimeout(() => { this._reconnectGuardTimer = null; if(!this._isReconnecting) return; + + NitroLogger.log('[RoomSessionManager] REAUTHENTICATED timeout - attempting fallback room re-entry for room ' + this._lastRoomId); this.attemptRoomReEntry(); }, 5000); }); + // REAUTHENTICATED: SSO handshake completed, connection is ready to send messages GetEventDispatcher().addEventListener(NitroEventType.SOCKET_REAUTHENTICATED, () => { + console.log('[RoomSessionManager] SOCKET_REAUTHENTICATED fired! lastRoomId=' + this._lastRoomId); + + // Snapshot the saved position BEFORE re-entering (re-entry overwrites sessionStorage) + this.snapshotSavedPosition(); + this.clearGuardTimer(); this.attemptRoomReEntry(); }); GetEventDispatcher().addEventListener(NitroEventType.SOCKET_RECONNECT_FAILED, () => { + NitroLogger.log('[RoomSessionManager] SOCKET_RECONNECT_FAILED - clearing state'); this.clearGuardTimer(); this._isReconnecting = false; this._lastRoomId = -1; this._lastRoomPassword = null; this.clearPersistedRoom(); + this.clearPersistedPosition(); }); + // When the socket is permanently closed (server shutdown, max retries), + // clear the persisted room so the next page load uses normal navigation GetEventDispatcher().addEventListener(NitroEventType.SOCKET_CLOSED, () => { + NitroLogger.log('[RoomSessionManager] SOCKET_CLOSED - clearing persisted room'); this.clearGuardTimer(); this._isReconnecting = false; this._lastRoomId = -1; this._lastRoomPassword = null; this.clearPersistedRoom(); + this.clearPersistedPosition(); }); } @@ -120,6 +178,30 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList } } + private scheduleRoomIdClear(): void + { + if(this._pendingRoomClear) + { + clearTimeout(this._pendingRoomClear); + } + + this._pendingRoomClear = setTimeout(() => + { + this._pendingRoomClear = null; + this._lastRoomId = -1; + this._lastRoomPassword = null; + }, 5000); + } + + private cancelRoomIdClear(): void + { + if(this._pendingRoomClear) + { + clearTimeout(this._pendingRoomClear); + this._pendingRoomClear = null; + } + } + private attemptRoomReEntry(): void { const roomId = this._lastRoomId; @@ -127,14 +209,62 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList if(roomId <= 0) { + NitroLogger.log('[RoomSessionManager] No room to re-enter (lastRoomId=' + roomId + '), dropping guard'); this._isReconnecting = false; return; } + // Check if we already have a session for this room (seamless reconnection). + // The server-side SessionResumeManager kept the habbo alive in the room + // during the grace period. The client's room view is still rendered behind + // the reconnection overlay. Instead of tearing it down and rebuilding, + // just drop the guard so the room view "unfreezes" in place. + const existingSession = this.getSession(roomId); + + if(existingSession) + { + NitroLogger.log('[RoomSessionManager] Existing session found for room ' + roomId + ' — sending room enter request'); + + // Re-send room enter request to the server. This handles two cases: + // 1. Session resume (habbo still in room on server): server treats it + // as a no-op or re-entry to the same room — harmless. + // 2. Server restart (habbo not in any room): server places the habbo + // in the room so the client view matches server state. + GetCommunication().connection.send(new RoomEnterComposer(roomId, password)); + + // Keep the guard up briefly to absorb any stray server-side redirects + // (DesktopViewEvent, etc.) from the login packet sequence, then drop it. + this.clearGuardTimer(); + this._reconnectGuardTimer = setTimeout(() => + { + this._reconnectGuardTimer = null; + + if(this._isReconnecting) + { + NitroLogger.log('[RoomSessionManager] Session resume guard timeout - dropping guard'); + this._isReconnecting = false; + } + }, 5000); + + return; + } + + NitroLogger.log('[RoomSessionManager] Re-entering room ' + roomId); + + // No existing session — full room entry (e.g. page reload restore) this._sessions.clear(); this._viewerSession = null; + + // Send the room enter request. The guard stays active to block + // DesktopViewEvent / home room redirects from the server's login sequence. this.createSession(roomId, password); + + // Keep the guard up for a generous window to absorb any DesktopViewEvent + // or other server-side redirects that arrive after authentication. + // The guard drops when: + // 1. RS_CONNECTED/RS_READY fires (positive room entry confirmation), OR + // 2. This safety timeout expires (10 seconds) this.clearGuardTimer(); this._reconnectGuardTimer = setTimeout(() => { @@ -142,11 +272,19 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList if(this._isReconnecting) { + NitroLogger.log('[RoomSessionManager] Guard timeout (10s) - dropping guard'); this._isReconnecting = false; } }, 10000); } + /** + * Called on page load (from MainView). Checks sessionStorage for a + * persisted room ID from a network disconnect and enters it instead + * of following the normal home room / hotel view flow. + * + * Returns true if a room restore was initiated. + */ public tryRestoreSession(): boolean { try @@ -161,10 +299,15 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList const password = sessionStorage.getItem(STORAGE_KEY_ROOM_PASSWORD) || null; + NitroLogger.log('[RoomSessionManager] Restoring session for room ' + roomId + ' from sessionStorage'); + + // Set the guard so DesktopViewEvent from the server's login sequence + // doesn't kick us to hotel view before we enter the room this._isReconnecting = true; this.createSession(roomId, password); + // Drop the guard when room entry succeeds or after timeout this.clearGuardTimer(); this._reconnectGuardTimer = setTimeout(() => { @@ -172,6 +315,7 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList if(this._isReconnecting) { + NitroLogger.log('[RoomSessionManager] Restore guard timeout (10s) - dropping guard'); this._isReconnecting = false; } }, 10000); @@ -206,7 +350,10 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList this.clearPersistedRoom(); } } - catch(e) {} + catch(e) + { + // sessionStorage not available (private browsing, etc.) - fail silently + } } private clearPersistedRoom(): void @@ -215,8 +362,70 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList { sessionStorage.removeItem(STORAGE_KEY_ROOM_ID); sessionStorage.removeItem(STORAGE_KEY_ROOM_PASSWORD); + // Note: position keys (POS_X, POS_Y) are NOT cleared here. + // They persist across the disconnect→reconnect cycle and are + // consumed by walkToSavedPosition() after successful re-entry. } - catch(e) {} + catch(e) + { + // ignore + } + } + + private clearPersistedPosition(): void + { + try + { + sessionStorage.removeItem(STORAGE_KEY_POS_X); + sessionStorage.removeItem(STORAGE_KEY_POS_Y); + sessionStorage.removeItem('nitro.session.posLocked'); + } + catch(e) + { + // ignore + } + } + + private snapshotSavedPosition(): void + { + try + { + const posX = sessionStorage.getItem(STORAGE_KEY_POS_X); + const posY = sessionStorage.getItem(STORAGE_KEY_POS_Y); + + if(!posX || !posY) return; + + this._savedPosX = parseInt(posX, 10); + this._savedPosY = parseInt(posY, 10); + + // Lock position saving so room re-entry doesn't overwrite saved position + sessionStorage.setItem('nitro.session.posLocked', '1'); + + NitroLogger.log('[RoomSessionManager] Snapshot saved position (' + this._savedPosX + ', ' + this._savedPosY + ')'); + } + catch(e) + { + this._savedPosX = -1; + this._savedPosY = -1; + } + } + + private walkToSavedPosition(): void + { + const x = this._savedPosX; + const y = this._savedPosY; + + // Reset after use + this._savedPosX = -1; + this._savedPosY = -1; + + // Unlock position saving so normal movement is tracked again + try { sessionStorage.removeItem('nitro.session.posLocked'); } catch(e) { /* ignore */ } + + if(x < 0 || y < 0 || isNaN(x) || isNaN(y)) return; + + NitroLogger.log('[RoomSessionManager] Walking to saved position (' + x + ', ' + y + ')'); + GetCommunication().connection.send(new RoomUnitWalkComposer(x, y)); } private setHandlers(session: IRoomSession): void @@ -271,6 +480,7 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList this._viewerSession = roomSession; + // Track room for reconnection (memory + sessionStorage) this._lastRoomId = roomSession.roomId; this._lastRoomPassword = roomSession.password; this.persistRoom(roomSession.roomId, roomSession.password); @@ -306,20 +516,29 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList if(!session) return; - this._sessions.delete(this.getRoomId(id)); - - if(openLandingView && !this._isReconnecting) - { - this._lastRoomId = -1; - this._lastRoomPassword = null; - this.clearPersistedRoom(); - } - + // During reconnection, block BOTH the session map deletion AND the ENDED event. + // This preserves the session so attemptRoomReEntry can find it, and prevents + // the UI from flashing hotel view during the reconnection flow. if(this._isReconnecting) { + NitroLogger.log('[RoomSessionManager] removeSession fully blocked by reconnect guard (room=' + id + ', openLandingView=' + openLandingView + ')'); + return; } + this._sessions.delete(this.getRoomId(id)); + + if(openLandingView) + { + // Don't clear _lastRoomId immediately. During server shutdown the server + // sends DesktopViewEvent (which triggers removeSession) BEFORE closing the + // socket. If we clear the room ID now, the SOCKET_RECONNECTING handler + // won't know which room to re-enter. Instead, delay the clear so that + // SOCKET_RECONNECTING can cancel it and preserve the room info. + this.clearPersistedRoom(); + this.scheduleRoomIdClear(); + } + GetEventDispatcher().dispatchEvent(new RoomSessionEvent(RoomSessionEvent.ENDED, session, openLandingView)); } @@ -329,30 +548,60 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList if(!session) { + NitroLogger.log('[RoomSessionManager] sessionUpdate(' + type + ') - no session found for id ' + id); + return; } switch(type) { case RoomSessionHandler.RS_CONNECTED: + NitroLogger.log('[RoomSessionManager] RS_CONNECTED for room ' + id); + + // Positive signal: we successfully entered the room. + // Do NOT drop the guard yet — the server's login sequence may still + // send a DesktopViewEvent that arrives after this. Keep the guard up + // and let RS_READY (or the existing timeout) handle the final drop. if(this._isReconnecting) { - this.clearGuardTimer(); - this._isReconnecting = false; + NitroLogger.log('[RoomSessionManager] Room entry confirmed - guard stays up until RS_READY'); } return; case RoomSessionHandler.RS_READY: + NitroLogger.log('[RoomSessionManager] RS_READY for room ' + id); + // Room is fully loaded. Keep the guard up for a short grace period + // to absorb any late DesktopViewEvent from the server's login sequence, + // then drop it. This prevents a race where the login sequence's + // DesktopViewEvent arrives after the room entry confirmation. if(this._isReconnecting) { + NitroLogger.log('[RoomSessionManager] Room ready confirmed - dropping guard in 3s'); + + // Walk to the saved position (where the user was before disconnect). + // Delay briefly so the server finishes placing the avatar in the room. + setTimeout(() => this.walkToSavedPosition(), 1000); + this.clearGuardTimer(); - this._isReconnecting = false; + this._reconnectGuardTimer = setTimeout(() => + { + this._reconnectGuardTimer = null; + + if(this._isReconnecting) + { + NitroLogger.log('[RoomSessionManager] Post-ready grace period elapsed - dropping guard'); + this._isReconnecting = false; + } + }, 3000); } return; case RoomSessionHandler.RS_DISCONNECTED: + NitroLogger.log('[RoomSessionManager] RS_DISCONNECTED for room ' + id + ' (isReconnecting=' + this._isReconnecting + ')'); + // During reconnection, don't process server-side disconnects + // (DesktopViewEvent / home room redirect) - we'll re-enter the room if(this._isReconnecting) return; this.removeSession(id); @@ -372,6 +621,7 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList this._sessions.set(this.getRoomId(toRoomId), existing); + // Update tracked room this._lastRoomId = toRoomId; this.persistRoom(toRoomId, existing.password); @@ -387,4 +637,9 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList { return this._viewerSession; } + + public get isReconnecting(): boolean + { + return this._isReconnecting; + } } diff --git a/packages/session/src/handler/RoomSessionHandler.ts b/packages/session/src/handler/RoomSessionHandler.ts index 717c9e3..474ef88 100644 --- a/packages/session/src/handler/RoomSessionHandler.ts +++ b/packages/session/src/handler/RoomSessionHandler.ts @@ -1,6 +1,7 @@ import { IConnection, IRoomHandlerListener } from '@nitrots/api'; import { DesktopViewEvent, FlatAccessDeniedMessageEvent, GoToFlatMessageComposer, RoomDoorbellAcceptedEvent, RoomEnterEvent, RoomReadyMessageEvent, YouAreSpectatorMessageEvent } from '@nitrots/communication'; import { GetEventDispatcher, RoomSessionDoorbellEvent, RoomSessionSpectatorModeEvent } from '@nitrots/events'; +import { NitroLogger } from '@nitrots/utils'; import { BaseHandler } from './BaseHandler'; export class RoomSessionHandler extends BaseHandler @@ -46,6 +47,8 @@ export class RoomSessionHandler extends BaseHandler { if(!(event instanceof DesktopViewEvent)) return; + NitroLogger.log('[RoomSessionHandler] DesktopViewEvent received (roomId=' + this.roomId + ')'); + if(this.listener) this.listener.sessionUpdate(this.roomId, RoomSessionHandler.RS_DISCONNECTED); } @@ -85,6 +88,7 @@ export class RoomSessionHandler extends BaseHandler if(!username || !username.length) { + NitroLogger.log('[RoomSessionHandler] FlatAccessDenied (empty username) → RS_DISCONNECTED (roomId=' + this.roomId + ')'); this.listener.sessionUpdate(this.roomId, RoomSessionHandler.RS_DISCONNECTED); } else From 4e41e9db5c490f2cd13a3c535180bd5c44ff4c40 Mon Sep 17 00:00:00 2001 From: duckietm Date: Fri, 20 Mar 2026 17:10:56 +0100 Subject: [PATCH 09/11] =?UTF-8?q?=F0=9F=86=99=20Stage=202=20reconnect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/room/src/RoomMessageHandler.ts | 11 +-- packages/session/src/RoomSession.ts | 24 ++++++- packages/session/src/RoomSessionManager.ts | 80 ++++++++++++---------- 3 files changed, 68 insertions(+), 47 deletions(-) diff --git a/packages/room/src/RoomMessageHandler.ts b/packages/room/src/RoomMessageHandler.ts index ed836f5..0adbaec 100644 --- a/packages/room/src/RoomMessageHandler.ts +++ b/packages/room/src/RoomMessageHandler.ts @@ -737,18 +737,13 @@ export class RoomMessageHandler this._roomEngine.updateRoomObjectUserLocation(this._currentRoomId, status.id, location, goal, status.canStandUp, height, direction, status.headDirection); this._roomEngine.updateRoomObjectUserFlatControl(this._currentRoomId, status.id, null); - // Save own user's position for reconnection (only when not locked by reconnect flow) + // Save own user's position for reconnection if(status.id === this._ownRoomIndex) { try { - const locked = sessionStorage.getItem('nitro.session.posLocked'); - - if(!locked) - { - sessionStorage.setItem('nitro.session.lastPosX', status.x.toString()); - sessionStorage.setItem('nitro.session.lastPosY', status.y.toString()); - } + sessionStorage.setItem('nitro.session.lastPosX', status.x.toString()); + sessionStorage.setItem('nitro.session.lastPosY', status.y.toString()); } catch(e) { /* ignore */ } } diff --git a/packages/session/src/RoomSession.ts b/packages/session/src/RoomSession.ts index bb4beb1..500cc57 100644 --- a/packages/session/src/RoomSession.ts +++ b/packages/session/src/RoomSession.ts @@ -9,6 +9,8 @@ export class RoomSession implements IRoomSession private _roomId: number = 0; private _password: string = null; + private _spawnX: number = -1; + private _spawnY: number = -1; private _state: string = RoomSessionEvent.CREATED; private _tradeMode: number = RoomTradingLevelEnum.NO_TRADING; private _doorMode: number = 0; @@ -57,7 +59,7 @@ export class RoomSession implements IRoomSession { if(!GetCommunication().connection) return false; - GetCommunication().connection.send(new RoomEnterComposer(this._roomId, this._password)); + GetCommunication().connection.send(new RoomEnterComposer(this._roomId, this._password, this._spawnX, this._spawnY)); return true; } @@ -326,6 +328,26 @@ export class RoomSession implements IRoomSession this._password = password; } + public get spawnX(): number + { + return this._spawnX; + } + + public set spawnX(x: number) + { + this._spawnX = x; + } + + public get spawnY(): number + { + return this._spawnY; + } + + public set spawnY(y: number) + { + this._spawnY = y; + } + public get state(): string { return this._state; diff --git a/packages/session/src/RoomSessionManager.ts b/packages/session/src/RoomSessionManager.ts index c8e979d..4e7bf7e 100644 --- a/packages/session/src/RoomSessionManager.ts +++ b/packages/session/src/RoomSessionManager.ts @@ -226,12 +226,10 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList { NitroLogger.log('[RoomSessionManager] Existing session found for room ' + roomId + ' — sending room enter request'); - // Re-send room enter request to the server. This handles two cases: - // 1. Session resume (habbo still in room on server): server treats it - // as a no-op or re-entry to the same room — harmless. - // 2. Server restart (habbo not in any room): server places the habbo - // in the room so the client view matches server state. - GetCommunication().connection.send(new RoomEnterComposer(roomId, password)); + // Re-send room enter request to the server with saved spawn coordinates. + // The server will place the habbo directly at the saved position + // instead of the door tile, providing a seamless reconnection experience. + GetCommunication().connection.send(new RoomEnterComposer(roomId, password, this._savedPosX, this._savedPosY)); // Keep the guard up briefly to absorb any stray server-side redirects // (DesktopViewEvent, etc.) from the login packet sequence, then drop it. @@ -256,9 +254,9 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList this._sessions.clear(); this._viewerSession = null; - // Send the room enter request. The guard stays active to block - // DesktopViewEvent / home room redirects from the server's login sequence. - this.createSession(roomId, password); + // Send the room enter request with saved spawn coordinates. The server + // will place the habbo at the saved position instead of the door tile. + this.createSession(roomId, password, this._savedPosX, this._savedPosY); // Keep the guard up for a generous window to absorb any DesktopViewEvent // or other server-side redirects that arrive after authentication. @@ -299,13 +297,32 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList const password = sessionStorage.getItem(STORAGE_KEY_ROOM_PASSWORD) || null; - NitroLogger.log('[RoomSessionManager] Restoring session for room ' + roomId + ' from sessionStorage'); + // Read saved position for page-reload restore + let spawnX = -1; + let spawnY = -1; + + try + { + const posX = sessionStorage.getItem(STORAGE_KEY_POS_X); + const posY = sessionStorage.getItem(STORAGE_KEY_POS_Y); + + if(posX && posY) + { + spawnX = parseInt(posX, 10); + spawnY = parseInt(posY, 10); + + if(isNaN(spawnX) || isNaN(spawnY)) { spawnX = -1; spawnY = -1; } + } + } + catch(e) { /* ignore */ } + + NitroLogger.log('[RoomSessionManager] Restoring session for room ' + roomId + ' from sessionStorage (spawn: ' + spawnX + ', ' + spawnY + ')'); // Set the guard so DesktopViewEvent from the server's login sequence // doesn't kick us to hotel view before we enter the room this._isReconnecting = true; - this.createSession(roomId, password); + this.createSession(roomId, password, spawnX, spawnY); // Drop the guard when room entry succeeds or after timeout this.clearGuardTimer(); @@ -364,7 +381,7 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList sessionStorage.removeItem(STORAGE_KEY_ROOM_PASSWORD); // Note: position keys (POS_X, POS_Y) are NOT cleared here. // They persist across the disconnect→reconnect cycle and are - // consumed by walkToSavedPosition() after successful re-entry. + // sent to the server as spawn coordinates during re-entry. } catch(e) { @@ -378,7 +395,6 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList { sessionStorage.removeItem(STORAGE_KEY_POS_X); sessionStorage.removeItem(STORAGE_KEY_POS_Y); - sessionStorage.removeItem('nitro.session.posLocked'); } catch(e) { @@ -398,9 +414,6 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList this._savedPosX = parseInt(posX, 10); this._savedPosY = parseInt(posY, 10); - // Lock position saving so room re-entry doesn't overwrite saved position - sessionStorage.setItem('nitro.session.posLocked', '1'); - NitroLogger.log('[RoomSessionManager] Snapshot saved position (' + this._savedPosX + ', ' + this._savedPosY + ')'); } catch(e) @@ -410,24 +423,6 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList } } - private walkToSavedPosition(): void - { - const x = this._savedPosX; - const y = this._savedPosY; - - // Reset after use - this._savedPosX = -1; - this._savedPosY = -1; - - // Unlock position saving so normal movement is tracked again - try { sessionStorage.removeItem('nitro.session.posLocked'); } catch(e) { /* ignore */ } - - if(x < 0 || y < 0 || isNaN(x) || isNaN(y)) return; - - NitroLogger.log('[RoomSessionManager] Walking to saved position (' + x + ', ' + y + ')'); - GetCommunication().connection.send(new RoomUnitWalkComposer(x, y)); - } - private setHandlers(session: IRoomSession): void { if(!this._handlers || !this._handlers.length) return; @@ -458,12 +453,14 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList return existing; } - public createSession(roomId: number, password: string = null): boolean + public createSession(roomId: number, password: string = null, spawnX: number = -1, spawnY: number = -1): boolean { const session = new RoomSession(); session.roomId = roomId; session.password = password; + session.spawnX = spawnX; + session.spawnY = spawnY; return this.addSession(session); } @@ -579,9 +576,16 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList { NitroLogger.log('[RoomSessionManager] Room ready confirmed - dropping guard in 3s'); - // Walk to the saved position (where the user was before disconnect). - // Delay briefly so the server finishes placing the avatar in the room. - setTimeout(() => this.walkToSavedPosition(), 1000); + // If we have saved spawn coordinates, send a walk command so the + // avatar moves to their previous position. This handles the EMU-restart + // case where the server has no ghost session and spawns at the door. + if(this._savedPosX >= 0 && this._savedPosY >= 0) + { + NitroLogger.log('[RoomSessionManager] Walking to saved position (' + this._savedPosX + ', ' + this._savedPosY + ')'); + GetCommunication().connection.send(new RoomUnitWalkComposer(this._savedPosX, this._savedPosY)); + this._savedPosX = -1; + this._savedPosY = -1; + } this.clearGuardTimer(); this._reconnectGuardTimer = setTimeout(() => From 68af013c6079624555850b9a02ec6950ac101211 Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Fri, 20 Mar 2026 17:22:50 +0100 Subject: [PATCH 10/11] feat: custom prefix system protocol layer Prefix parsers, composers and events: - UserPrefixesParser, PrefixReceivedParser, ActivePrefixUpdatedParser - PurchasePrefixComposer, SetActivePrefixComposer, DeletePrefixComposer, RequestPrefixesComposer - RoomUnitChatParser reads prefixText/Color/Icon/Effect from chat packets - RoomSessionChatEvent carries prefix data to client - RoomChatHandler passes prefix fields through event chain --- packages/communication/src/NitroMessages.ts | 13 +++++ packages/communication/src/index.ts | 3 ++ .../src/messages/incoming/IncomingHeader.ts | 5 ++ .../src/messages/incoming/inventory/index.ts | 1 + .../prefixes/ActivePrefixUpdatedEvent.ts | 16 ++++++ .../inventory/prefixes/PrefixReceivedEvent.ts | 16 ++++++ .../inventory/prefixes/UserPrefixesEvent.ts | 16 ++++++ .../incoming/inventory/prefixes/index.ts | 3 ++ .../src/messages/outgoing/OutgoingHeader.ts | 6 +++ .../src/messages/outgoing/inventory/index.ts | 1 + .../prefixes/DeletePrefixComposer.ts | 21 ++++++++ .../prefixes/PurchasePrefixComposer.ts | 21 ++++++++ .../prefixes/RequestPrefixesComposer.ts | 21 ++++++++ .../prefixes/SetActivePrefixComposer.ts | 21 ++++++++ .../outgoing/inventory/prefixes/index.ts | 4 ++ .../src/messages/parser/inventory/index.ts | 1 + .../prefixes/ActivePrefixUpdatedParser.ts | 39 ++++++++++++++ .../prefixes/PrefixReceivedParser.ts | 39 ++++++++++++++ .../inventory/prefixes/UserPrefixesParser.ts | 52 +++++++++++++++++++ .../parser/inventory/prefixes/index.ts | 3 ++ .../room/unit/chat/RoomUnitChatParser.ts | 36 ++++++++++++- .../src/session/RoomSessionChatEvent.ts | 32 +++++++++++- .../session/src/handler/RoomChatHandler.ts | 2 +- 23 files changed, 367 insertions(+), 5 deletions(-) create mode 100644 packages/communication/src/messages/incoming/inventory/prefixes/ActivePrefixUpdatedEvent.ts create mode 100644 packages/communication/src/messages/incoming/inventory/prefixes/PrefixReceivedEvent.ts create mode 100644 packages/communication/src/messages/incoming/inventory/prefixes/UserPrefixesEvent.ts create mode 100644 packages/communication/src/messages/incoming/inventory/prefixes/index.ts create mode 100644 packages/communication/src/messages/outgoing/inventory/prefixes/DeletePrefixComposer.ts create mode 100644 packages/communication/src/messages/outgoing/inventory/prefixes/PurchasePrefixComposer.ts create mode 100644 packages/communication/src/messages/outgoing/inventory/prefixes/RequestPrefixesComposer.ts create mode 100644 packages/communication/src/messages/outgoing/inventory/prefixes/SetActivePrefixComposer.ts create mode 100644 packages/communication/src/messages/outgoing/inventory/prefixes/index.ts create mode 100644 packages/communication/src/messages/parser/inventory/prefixes/ActivePrefixUpdatedParser.ts create mode 100644 packages/communication/src/messages/parser/inventory/prefixes/PrefixReceivedParser.ts create mode 100644 packages/communication/src/messages/parser/inventory/prefixes/UserPrefixesParser.ts create mode 100644 packages/communication/src/messages/parser/inventory/prefixes/index.ts diff --git a/packages/communication/src/NitroMessages.ts b/packages/communication/src/NitroMessages.ts index 7d61b36..ced7b60 100644 --- a/packages/communication/src/NitroMessages.ts +++ b/packages/communication/src/NitroMessages.ts @@ -1,4 +1,6 @@ import { IMessageConfiguration } from '@nitrots/api'; +import { ActivePrefixUpdatedEvent, PrefixReceivedEvent, UserPrefixesEvent } from './messages/incoming/inventory/prefixes'; +import { DeletePrefixComposer, PurchasePrefixComposer, RequestPrefixesComposer, SetActivePrefixComposer } from './messages/outgoing/inventory/prefixes'; import { AcceptFriendMessageComposer, AcceptFriendResultEvent, AcceptGameInviteMessageComposer, AcceptQuestMessageComposer, AccountSafetyLockStatusChangeMessageEvent, AchievementEvent, AchievementNotificationMessageEvent, AchievementResolutionCompletedMessageEvent, AchievementResolutionProgressMessageEvent, AchievementResolutionsMessageEvent, AchievementsEvent, AchievementsScoreEvent, ActivateQuestMessageComposer, ActivityPointNotificationMessageEvent, AddFavouriteRoomMessageComposer, AddJukeboxDiskComposer, AddSpamWallPostItMessageComposer, ApplySnapshotMessageComposer, ApplyTonerComposer, ApproveAllMembershipRequestsMessageComposer, ApproveNameMessageComposer, ApproveNameMessageEvent, AreaHideMessageEvent, AuthenticatedEvent, AuthenticationMessageComposer, AvailabilityStatusMessageEvent, AvailabilityTimeMessageEvent, AvatarEffectActivatedComposer, AvatarEffectActivatedEvent, AvatarEffectAddedEvent, AvatarEffectExpiredEvent, AvatarEffectSelectedComposer, AvatarEffectSelectedEvent, AvatarEffectsEvent, BadgePointLimitsEvent, BadgeReceivedEvent, BadgesEvent, BannedUsersFromRoomEvent, BonusRareInfoMessageEvent, BotAddedToInventoryEvent, BotCommandConfigurationEvent, BotErrorEvent, BotForceOpenContextMenuEvent, BotInventoryMessageEvent, BotPlaceComposer, BotReceivedMessageEvent, BotRemoveComposer, BotRemovedFromInventoryEvent, BotSkillListUpdateEvent, BotSkillSaveComposer, BreedPetsMessageComposer, BuildersClubFurniCountMessageEvent, BuildersClubPlaceRoomItemMessageComposer, BuildersClubPlaceWallItemMessageComposer, BuildersClubQueryFurniCountMessageComposer, BuildersClubSubscriptionStatusMessageEvent, BundleDiscountRulesetMessageEvent, BuyMarketplaceOfferMessageComposer, BuyMarketplaceTokensMessageComposer, CallForHelpDisabledNotifyMessageEvent, CallForHelpFromForumMessageMessageComposer, CallForHelpFromForumThreadMessageComposer, CallForHelpFromIMMessageComposer, CallForHelpFromPhotoMessageComposer, CallForHelpFromSelfieMessageComposer, CallForHelpMessageComposer, CallForHelpPendingCallsDeletedMessageEvent, CallForHelpPendingCallsMessageEvent, CallForHelpReplyMessageEvent, CallForHelpResultMessageEvent, CameraPublishStatusMessageEvent, CameraPurchaseOKMessageEvent, CameraSnapshotMessageEvent, CameraStorageUrlMessageEvent, CampaignCalendarDataMessageEvent, CampaignCalendarDoorOpenedMessageEvent, CanCreateRoomEvent, CanCreateRoomEventEvent, CanCreateRoomMessageComposer, CancelEventMessageComposer, CancelMarketplaceOfferMessageComposer, CancelMysteryBoxWaitMessageEvent, CancelPetBreedingComposer, CancelQuestMessageComposer, CatalogGroupsComposer, CatalogPageExpirationEvent, CatalogPageMessageEvent, CatalogPageWithEarliestExpiryMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, CategoriesWithVisitorCountEvent, CfhChatlogEvent, CfhSanctionMessageEvent, CfhTopicsInitEvent, ChangeEmailComposer, ChangeEmailResultEvent, ChangeQueueMessageComposer, ChangeUserNameMessageComposer, ChangeUserNameResultMessageEvent, ChatReviewGuideDecidesOnOfferMessageComposer, ChatReviewGuideDetachedMessageComposer, ChatReviewGuideVoteMessageComposer, ChatReviewSessionCreateMessageComposer, ChatReviewSessionDetachedMessageEvent, ChatReviewSessionOfferedToGuideMessageEvent, ChatReviewSessionResultsMessageEvent, ChatReviewSessionStartedMessageEvent, ChatReviewSessionVotingStatusMessageEvent, CheckUserNameMessageComposer, CheckUserNameResultMessageEvent, ClickFurniMessageComposer, ClientHelloMessageComposer, ClientPingEvent, CloseIssueDefaultActionMessageComposer, CloseIssuesMessageComposer, ClubGiftInfoEvent, ClubGiftNotificationEvent, ClubGiftSelectedEvent, CommunityGoalEarnedPrizesMessageEvent, CommunityGoalHallOfFameMessageEvent, CommunityGoalProgressMessageEvent, CommunityGoalVoteMessageComposer, CommunityGoalVoteMessageEvent, CompetitionEntrySubmitResultEvent, CompetitionRoomsDataMessageEvent, CompetitionRoomsSearchMessageComposer, CompetitionStatusMessageEvent, CompetitionVotingInfoMessageEvent, CompleteDiffieHandshakeEvent, CompleteDiffieHandshakeMessageComposer, CompostPlantMessageComposer, ConcurrentUsersGoalProgressMessageEvent, ConfirmPetBreedingComposer, ConnectionErrorEvent, ControlYoutubeDisplayPlaybackMessageComposer, ConvertGlobalRoomIdMessageComposer, ConvertedRoomIdEvent, CraftComposer, CraftSecretComposer, CraftableProductsEvent, CraftingRecipeEvent, CraftingRecipesAvailableEvent, CraftingResultEvent, CreateFlatMessageComposer, CurrentTimingCodeMessageEvent, CustomUserNotificationMessageEvent, DeclineFriendMessageComposer, DefaultSanctionMessageComposer, DeleteFavouriteRoomMessageComposer, DeleteItemMessageComposer, DeleteBadgeMessageComposer, DeletePetMessageComposer, DeletePendingCallsForHelpMessageComposer, DesktopViewComposer, DesktopViewEvent, DiceValueMessageEvent, DirectSMSClubBuyAvailableMessageEvent, DisconnectMessageComposer, DisconnectReasonEvent, DoorbellMessageEvent, EditEventMessageComposer, ElementPointerMessageEvent, EmailStatusResultEvent, EpicPopupMessageEvent, ExtendRentOrBuyoutFurniMessageComposer, ExtendRentOrBuyoutStripItemMessageComposer, ExtendedProfileChangedMessageEvent, FavoriteMembershipUpdateMessageEvent, FavouriteChangedEvent, FavouritesEvent, FigureSetIdsMessageEvent, FigureUpdateEvent, FindFriendsProcessResultEvent, FindNewFriendsMessageComposer, FireworkChargeDataEvent, FlatAccessDeniedMessageEvent, FlatControllerAddedEvent, FlatControllerRemovedEvent, FlatControllersEvent, FlatCreatedEvent, FloodControlEvent, FloorHeightMapEvent, FollowFriendFailedEvent, FollowFriendMessageComposer, ForumDataMessageEvent, ForumsListMessageEvent, ForwardToACompetitionRoomMessageComposer, ForwardToARandomPromotedRoomMessageComposer, ForwardToASubmittableRoomMessageComposer, ForwardToRandomCompetitionRoomMessageComposer, ForwardToSomeRoomMessageComposer, FriendFurniConfirmLockMessageComposer, FriendListFragmentEvent, FriendListUpdateComposer, FriendListUpdateEvent, FriendNotificationEvent, FriendRequestQuestCompleteMessageComposer, FriendRequestsEvent, FurniRentOrBuyoutOfferMessageEvent, FurnitureAliasesComposer, FurnitureAliasesEvent, FurnitureColorWheelComposer, FurnitureDataEvent, FurnitureDiceActivateComposer, FurnitureDiceDeactivateComposer, FurnitureExchangeComposer, FurnitureFloorAddEvent, FurnitureFloorEvent, FurnitureFloorRemoveEvent, FurnitureFloorUpdateComposer, FurnitureFloorUpdateEvent, FurnitureGroupInfoComposer, FurnitureListAddOrUpdateEvent, FurnitureListComposer, FurnitureListEvent, FurnitureListInvalidateEvent, FurnitureListRemovedEvent, FurnitureMannequinSaveLookComposer, FurnitureMannequinSaveNameComposer, FurnitureMultiStateComposer, FurnitureOneWayDoorComposer, FurniturePickupComposer, FurniturePickupAllComposer, FurniturePlaceComposer, FurniturePlacePaintComposer, FurniturePostItPlaceComposer, FurniturePostItPlacedEvent, FurnitureRandomStateComposer, FurnitureStackHeightComposer, FurnitureStackHeightEvent, FurnitureWallAddEvent, FurnitureWallEvent, FurnitureWallMultiStateComposer, FurnitureWallRemoveEvent, FurnitureWallUpdateComposer, FurnitureWallUpdateEvent, Game2AccountGameStatusMessageEvent, Game2CheckGameDirectoryStatusMessageComposer, Game2ExitGameMessageComposer, Game2GameChatMessageComposer, Game2GameDirectoryStatusMessageEvent, Game2GetAccountGameStatusMessageComposer, Game2GetWeeklyFriendsLeaderboardComposer, Game2GetWeeklyLeaderboardComposer, Game2InArenaQueueMessageEvent, Game2JoiningGameFailedMessageEvent, Game2LoadStageReadyMessageComposer, Game2PlayAgainMessageComposer, Game2RequestFullStatusUpdateMessageComposer, Game2StartingGameFailedMessageEvent, Game2StopCounterMessageEvent, Game2UserLeftGameMessageEvent, Game2WeeklyFriendsLeaderboardEvent, Game2WeeklyLeaderboardEvent, GameAchievementsMessageEvent, GameInviteMessageEvent, GameListMessageEvent, GameStatusMessageEvent, GameUnloadedMessageComposer, GenericErrorEvent, GetBadgePointLimitsComposer, GetBonusRareInfoMessageComposer, GetBotInventoryComposer, GetBundleDiscountRulesetComposer, GetCatalogIndexComposer, GetCatalogPageComposer, GetCatalogPageExpirationComposer, GetCatalogPageWithEarliestExpiryComposer, GetCategoriesWithUserCountMessageComposer, GetCfhChatlogMessageComposer, GetCfhStatusMessageComposer, GetClubGiftInfo, GetClubOffersMessageComposer, GetCommunityGoalEarnedPrizesMessageComposer, GetCommunityGoalHallOfFameMessageComposer, GetCommunityGoalProgressMessageComposer, GetConcurrentUsersGoalProgressMessageComposer, GetConcurrentUsersRewardMessageComposer, GetCraftableProductsComposer, GetCraftingRecipeComposer, GetCraftingRecipesAvailableComposer, GetCurrentTimingCodeMessageComposer, GetCustomRoomFilterMessageComposer, GetDailyQuestMessageComposer, GetDirectClubBuyAvailableComposer, GetEmailStatusComposer, GetExtendedProfileByNameMessageComposer, GetFaqCategoryMessageComposer, GetFaqTextMessageComposer, GetForumStatsMessageComposer, GetForumsListMessageComposer, GetFriendRequestsComposer, GetGameAchievementsMessageComposer, GetGameListMessageComposer, GetGameStatusMessageComposer, GetGiftMessageComposer, GetGiftWrappingConfigurationComposer, GetGuestRoomMessageComposer, GetGuestRoomResultEvent, GetGuideReportingStatusMessageComposer, GetHabboBasicMembershipExtendOfferComposer, GetHabboClubExtendOfferMessageComposer, GetHabboGroupBadgesMessageComposer, GetIgnoredUsersComposer, GetInterstitialMessageComposer, GetIsBadgeRequestFulfilledComposer, GetIsOfferGiftableComposer, GetIsUserPartOfCompetitionMessageComposer, GetItemDataComposer, GetJukeboxPlayListMessageComposer, GetLimitedOfferAppearingNextComposer, GetMarketplaceCanMakeOfferComposer, GetMarketplaceConfigurationMessageComposer, GetMarketplaceItemStatsComposer, GetMarketplaceOffersMessageComposer, GetMarketplaceOwnOffersMessageComposer, GetMessagesMessageComposer, GetModeratorRoomInfoMessageComposer, GetModeratorUserInfoMessageComposer, GetNextTargetedOfferComposer, GetNowPlayingMessageComposer, GetOccupiedTilesMessageComposer, GetOfficialRoomsMessageComposer, GetOfficialSongIdMessageComposer, GetPendingCallsForHelpMessageComposer, GetPetCommandsComposer, GetPopularRoomTagsMessageComposer, GetProductOfferComposer, GetPromoArticlesComposer, GetQuestsMessageComposer, GetQuizQuestionsComposer, GetRecyclerStatusMessageComposer, GetRentOrBuyoutOfferMessageComposer, GetResolutionAchievementsMessageComposer, GetRoomAdPurchaseInfoComposer, GetRoomChatlogMessageComposer, GetRoomEntryDataMessageComposer, GetRoomEntryTileMessageComposer, GetRoomVisitsMessageComposer, GetSeasonalCalendarDailyOfferComposer, GetSeasonalQuestsOnlyMessageComposer, GetSecondsUntilMessageComposer, GetSellablePetPalettesComposer, GetSongInfoMessageComposer, GetSoundMachinePlayListMessageComposer, GetSoundSettingsComposer, GetTalentTrackLevelMessageComposer, GetTargetedOfferComposer, GetThreadMessageComposer, GetThreadsMessageComposer, GetUnreadForumsCountMessageComposer, GetUserChatlogMessageComposer, GetUserEventCatsMessageComposer, GetUserFlatCatsMessageComposer, GetUserGameAchievementsMessageComposer, GetUserSongDisksMessageComposer, GetUserTagsComposer, GetWardrobeMessageComposer, GetWeeklyGameRewardComposer, GetWeeklyGameRewardWinnersComposer, GetYoutubeDisplayStatusMessageComposer, GiftReceiverNotFoundEvent, GiftWrappingConfigurationEvent, GoToFlatMessageComposer, GotMysteryBoxPrizeMessageEvent, GroupAdminGiveComposer, GroupAdminTakeComposer, GroupBadgePartsComposer, GroupBadgePartsEvent, GroupBuyComposer, GroupBuyDataComposer, GroupBuyDataEvent, GroupConfirmMemberRemoveEvent, GroupConfirmRemoveMemberComposer, GroupDeleteComposer, GroupDetailsChangedMessageEvent, GroupFavoriteComposer, GroupFurniContextMenuInfoMessageEvent, GroupInformationComposer, GroupInformationEvent, GroupJoinComposer, GroupMembersComposer, GroupMembersEvent, GroupMembershipAcceptComposer, GroupMembershipDeclineComposer, GroupMembershipRequestedMessageEvent, GroupPurchasedEvent, GroupRemoveMemberComposer, GroupSaveBadgeComposer, GroupSaveColorsComposer, GroupSaveInformationComposer, GroupSavePreferencesComposer, GroupSettingsComposer, GroupSettingsEvent, GroupUnfavoriteComposer, GuestRoomSearchResultEvent, GuideOnDutyStatusMessageEvent, GuideReportingStatusMessageEvent, GuideSessionAttachedMessageEvent, GuideSessionCreateMessageComposer, GuideSessionDetachedMessageEvent, GuideSessionEndedMessageEvent, GuideSessionErrorMessageEvent, GuideSessionFeedbackMessageComposer, GuideSessionGetRequesterRoomMessageComposer, GuideSessionGuideDecidesMessageComposer, GuideSessionInviteRequesterMessageComposer, GuideSessionInvitedToGuideRoomMessageEvent, GuideSessionIsTypingMessageComposer, GuideSessionMessageMessageComposer, GuideSessionMessageMessageEvent, GuideSessionOnDutyUpdateMessageComposer, GuideSessionPartnerIsTypingMessageEvent, GuideSessionReportMessageComposer, GuideSessionRequesterCancelsMessageComposer, GuideSessionRequesterRoomMessageEvent, GuideSessionResolvedMessageComposer, GuideSessionStartedMessageEvent, GuideTicketCreationResultMessageEvent, GuideTicketResolutionMessageEvent, GuildBaseSearchMessageComposer, GuildEditFailedMessageEvent, GuildForumThreadsEvent, GuildMemberMgmtFailedMessageEvent, GuildMembershipsMessageEvent, HabboBroadcastMessageEvent, HabboClubExtendOfferMessageEvent, HabboClubOffersMessageEvent, HabboGroupBadgesMessageEvent, HabboGroupDeactivatedMessageEvent, HabboGroupJoinFailedMessageEvent, HabboSearchComposer, HabboSearchResultEvent, HarvestPetMessageComposer, HotelClosedAndOpensEvent, HotelClosesAndWillOpenAtEvent, HotelMergeNameChangeEvent, HotelWillCloseInMinutesEvent, IdentityAccountsEvent, IgnoreResultEvent, IgnoreUserComposer, IgnoreUserIdComposer, IgnoredUsersEvent, InClientLinkEvent, IncomingHeader, InfoFeedEnableMessageEvent, InfoRetrieveMessageComposer, InitCameraMessageEvent, InitDiffieHandshakeEvent, InitDiffieHandshakeMessageComposer, InstantMessageErrorEvent, InterstitialMessageEvent, InterstitialShownMessageComposer, IsBadgeRequestFulfilledEvent, IsOfferGiftableMessageEvent, IsUserPartOfCompetitionMessageEvent, IssueCloseNotificationMessageEvent, IssueDeletedMessageEvent, IssueInfoMessageEvent, IssuePickFailedMessageEvent, ItemDataUpdateMessageEvent, JoinQueueMessageComposer, JoinedQueueMessageEvent, JoiningQueueFailedMessageEvent, JukeboxPlayListFullMessageEvent, JukeboxSongDisksMessageEvent, LagWarningReportMessageComposer, LeaveQueueMessageComposer, LeftQueueMessageEvent, LimitedEditionSoldOutEvent, LimitedOfferAppearingNextMessageEvent, LoadGameMessageEvent, LoadGameUrlEvent, LoveLockFurniFinishedEvent, LoveLockFurniFriendConfirmedEvent, LoveLockFurniStartEvent, MOTDNotificationEvent, MaintenanceStatusMessageEvent, MakeOfferMessageComposer, MarkCatalogNewAdditionsPageOpenedComposer, MarketPlaceOffersEvent, MarketplaceBuyOfferResultEvent, MarketplaceCanMakeOfferResult, MarketplaceCancelOfferResultEvent, MarketplaceConfigurationEvent, MarketplaceItemStatsEvent, MarketplaceMakeOfferResult, MarketplaceOwnOffersEvent, MessageErrorEvent, MessengerInitComposer, MessengerInitEvent, MiniMailNewMessageEvent, MiniMailUnreadCountEvent, ModAlertMessageComposer, ModBanMessageComposer, ModKickMessageComposer, ModMessageMessageComposer, ModMuteMessageComposer, ModToolPreferencesComposer, ModToolSanctionComposer, ModTradingLockMessageComposer, ModerateMessageMessageComposer, ModerateRoomMessageComposer, ModerateThreadMessageComposer, ModeratorActionMessageComposer, ModeratorActionResultMessageEvent, ModeratorCautionEvent, ModeratorInitMessageEvent, ModeratorMessageEvent, ModeratorRoomInfoEvent, ModeratorToolPreferencesEvent, ModeratorUserInfoEvent, MoodlightSettingsComposer, MoodlightSettingsSaveComposer, MoodlightTogggleStateComposer, MuteAllInRoomEvent, MyFavouriteRoomsSearchMessageComposer, MyFrequentRoomHistorySearchMessageComposer, MyFriendsRoomsSearchMessageComposer, MyGuildBasesSearchMessageComposer, MyRecommendedRoomsMessageComposer, MyRoomHistorySearchMessageComposer, MyRoomRightsSearchMessageComposer, MyRoomsSearchMessageComposer, MysteryBoxKeysEvent, MysteryBoxWaitingCanceledMessageComposer, NavigatorCategoryListModeComposer, NavigatorCollapsedEvent, NavigatorDeleteSavedSearchComposer, NavigatorHomeRoomEvent, NavigatorInitComposer, NavigatorLiftedEvent, NavigatorMetadataEvent, NavigatorOpenRoomCreatorEvent, NavigatorSearchCloseComposer, NavigatorSearchComposer, NavigatorSearchEvent, NavigatorSearchOpenComposer, NavigatorSearchSaveComposer, NavigatorSearchesEvent, NavigatorSettingsEvent, NavigatorSettingsSaveComposer, NewConsoleMessageEvent, NewFriendRequestEvent, NewUserExperienceGetGiftsComposer, NewUserExperienceGiftOfferMessageEvent, NewUserExperienceNotCompleteEvent, NewUserExperienceScriptProceedComposer, NoOwnedRoomsAlertMessageEvent, NoSuchFlatEvent, NoobnessLevelMessageEvent, NotEnoughBalanceMessageEvent, NotificationDialogMessageEvent, NowPlayingMessageEvent, ObjectsDataUpdateEvent, ObjectsRollingEvent, OfferRewardDeliveredMessageEvent, OfficialSongIdMessageEvent, OneWayDoorStatusMessageEvent, OpenCampaignCalendarDoorAsStaffComposer, OpenCampaignCalendarDoorComposer, OpenMessageComposer, OpenMysteryTrophyMessageComposer, OpenPetPackageMessageComposer, OpenPetPackageRequestedMessageEvent, OpenPetPackageResultMessageEvent, OpenPresentComposer, OpenQuestTrackerMessageComposer, OpenWelcomeGiftComposer, OutgoingHeader, PeerUsersClassificationMessageComposer, PerformanceLogMessageComposer, PerkAllowancesMessageEvent, PetAddedToInventoryEvent, PetBreedingResultEvent, PetExperienceEvent, PetFigureUpdateEvent, PetInfoEvent, PetInventoryEvent, PetLevelNotificationEvent, PetLevelUpdateMessageEvent, PetMountComposer, PetMoveComposer, PetPlaceComposer, PetPlacingErrorEvent, PetReceivedMessageEvent, PetRemoveComposer, PetRemovedFromInventory, PetRespectComposer, PetRespectNoficationEvent, PetScratchFailedMessageEvent, PetSelectedMessageComposer, PetStatusUpdateEvent, PetSupplementComposer, PetSupplementedNotificationEvent, PetTrainingPanelMessageEvent, PhoneCollectionStateMessageEvent, PhotoCompetitionMessageComposer, PickIssuesMessageComposer, PlayListMessageEvent, PlayListSongAddedMessageEvent, PollAnswerComposer, PollContentsEvent, PollErrorEvent, PollOfferEvent, PollRejectComposer, PollStartComposer, PongMessageComposer, PopularRoomTagsResultEvent, PopularRoomsSearchMessageComposer, PostMessageMessageComposer, PostMessageMessageEvent, PostQuizAnswersComposer, PostThreadMessageEvent, PresentOpenedMessageEvent, ProductOfferEvent, PromoArticlesMessageEvent, PublishPhotoMessageComposer, PurchaseBasicMembershipExtensionComposer, PurchaseErrorMessageEvent, PurchaseFromCatalogAsGiftComposer, PurchaseFromCatalogComposer, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, PurchasePhotoMessageComposer, PurchaseRoomAdMessageComposer, PurchaseTargetedOfferComposer, PurchaseVipMembershipExtensionComposer, QuestCancelledMessageEvent, QuestCompletedMessageEvent, QuestDailyMessageEvent, QuestMessageEvent, QuestionAnsweredEvent, QuestionEvent, QuestionFinishedEvent, QuestsMessageEvent, QuizDataMessageEvent, QuizResultsMessageEvent, RateFlatMessageComposer, RecycleItemsMessageComposer, RecyclerFinishedMessageEvent, RecyclerStatusMessageEvent, RedeemCommunityGoalPrizeMessageComposer, RedeemItemClothingComposer, RedeemMarketplaceOfferCreditsMessageComposer, RedeemVoucherMessageComposer, RejectQuestMessageComposer, RelationshipStatusInfoEvent, ReleaseIssuesMessageComposer, RemainingMuteEvent, RemoveAllRightsMessageComposer, RemoveFriendComposer, RemoveJukeboxDiskComposer, RemoveOwnRoomRightsRoomMessageComposer, RemovePetSaddleComposer, RemoveWallItemComposer, RenderRoomMessageComposer, RenderRoomThumbnailMessageComposer, RentableSpaceCancelRentMessageComposer, RentableSpaceRentFailedMessageEvent, RentableSpaceRentMessageComposer, RentableSpaceRentOkMessageEvent, RentableSpaceStatusMessageComposer, RentableSpaceStatusMessageEvent, RequestABadgeComposer, RequestAchievementsMessageComposer, RequestBadgesComposer, RequestBotCommandConfigurationComposer, RequestCameraConfigurationComposer, RequestFriendComposer, RequestFurniInventoryWhenNotInRoomComposer, RequestPetInfoComposer, RequestPetsComposer, RequestSpamWallPostItMessageEvent, ResetPhoneNumberStateMessageComposer, ResetResolutionAchievementMessageComposer, RespectReceivedEvent, RestoreClientMessageEvent, RoomAdErrorEvent, RoomAdEventTabAdClickedComposer, RoomAdEventTabViewedComposer, RoomAdPurchaseInfoEvent, RoomAdPurchaseInitiatedComposer, RoomAdSearchMessageComposer, RoomAmbassadorAlertComposer, RoomBanUserComposer, RoomBannedUsersComposer, RoomChatSettingsEvent, RoomChatlogEvent, RoomCompetitionInitMessageComposer, RoomDeleteComposer, RoomDimmerPresetsEvent, RoomDoorbellAcceptedEvent, RoomDoorbellAccessComposer, RoomEnterComposer, RoomEnterErrorEvent, RoomEnterEvent, RoomEntryInfoMessageEvent, RoomEntryTileMessageEvent, RoomEventCancelEvent, RoomEventEvent, RoomFilterSettingsMessageEvent, RoomForwardEvent, RoomGiveRightsComposer, RoomHeightMapEvent, RoomHeightMapUpdateEvent, RoomInviteErrorEvent, RoomInviteEvent, RoomKickUserComposer, RoomMessageNotificationMessageEvent, RoomMuteComposer, RoomMuteUserComposer, RoomNetworkOpenConnectionMessageComposer, RoomOccupiedTilesMessageEvent, RoomPaintEvent, RoomPollResultEvent, RoomReadyMessageEvent, RoomRightsClearEvent, RoomRightsEvent, RoomRightsOwnerEvent, RoomScoreEvent, RoomSettingsComposer, RoomSettingsDataEvent, RoomSettingsErrorEvent, RoomSettingsSaveErrorEvent, RoomSettingsSavedEvent, RoomSettingsUpdatedEvent, RoomTakeRightsComposer, RoomTextSearchMessageComposer, RoomThumbnailUpdateResultEvent, RoomUnbanUserComposer, RoomUnitActionComposer, RoomUnitBackgroundComposer, RoomUnitChatComposer, RoomUnitChatEvent, RoomUnitChatShoutComposer, RoomUnitChatShoutEvent, RoomUnitChatStyleComposer, RoomUnitChatWhisperComposer, RoomUnitChatWhisperEvent, RoomUnitDanceComposer, RoomUnitDanceEvent, RoomUnitDropHandItemComposer, RoomUnitEffectEvent, RoomUnitEvent, RoomUnitExpressionEvent, RoomUnitGiveHandItemComposer, RoomUnitGiveHandItemPetComposer, RoomUnitHandItemEvent, RoomUnitHandItemReceivedEvent, RoomUnitIdleEvent, RoomUnitInfoEvent, RoomUnitLookComposer, RoomUnitNumberEvent, RoomUnitPostureComposer, RoomUnitRemoveEvent, RoomUnitSignComposer, RoomUnitStatusEvent, RoomUnitTypingEvent, RoomUnitTypingStartComposer, RoomUnitTypingStopComposer, RoomUnitWalkComposer, RoomUsersClassificationMessageComposer, RoomUsersWithRightsComposer, RoomVisitsEvent, RoomVisualizationSettingsEvent, RoomsWhereMyFriendsAreSearchMessageComposer, RoomsWithHighestScoreSearchMessageComposer, SSOTicketMessageComposer, SanctionStatusEvent, SaveRoomSettingsComposer, SaveWardrobeOutfitMessageComposer, ScrGetKickbackInfoMessageComposer, ScrSendKickbackInfoMessageEvent, SearchFaqsMessageComposer, SeasonalCalendarDailyOfferMessageEvent, SeasonalQuestsMessageEvent, SecondsUntilMessageEvent, SelectClubGiftComposer, SellablePetPalettesMessageEvent, SendMessageComposer, SendRoomInviteComposer, SetActivatedBadgesComposer, SetClothingChangeDataMessageComposer, SetItemDataMessageComposer, SetObjectDataMessageComposer, SetPhoneNumberVerificationStatusMessageComposer, SetRelationshipStatusComposer, SetRoomSessionTagsMessageComposer, SetTargetedOfferStateComposer, SetYoutubeDisplayPlaylistMessageComposer, ShopTargetedOfferViewedComposer, ShowEnforceRoomCategoryDialogEvent, ShowMysteryBoxWaitMessageEvent, SimpleAlertMessageEvent, StartCampaignMessageComposer, StartRoomPollEvent, SubmitRoomToCompetitionMessageComposer, TalentLevelUpEvent, TalentTrackComposer, TalentTrackLevelMessageEvent, TalentTrackMessageEvent, TargetedOfferEvent, TargetedOfferNotFoundEvent, ThreadMessagesMessageEvent, ThumbnailStatusMessageEvent, TogglePetBreedingComposer, TogglePetRidingComposer, ToggleStaffPickMessageComposer, TradingAcceptComposer, TradingAcceptEvent, TradingCancelComposer, TradingCloseComposer, TradingCloseEvent, TradingCompletedEvent, TradingConfirmationComposer, TradingConfirmationEvent, TradingListAddItemComposer, TradingListAddItemsComposer, TradingListItemEvent, TradingListItemRemoveComposer, TradingNoSuchItemEvent, TradingNotOpenEvent, TradingOpenComposer, TradingOpenEvent, TradingOpenFailedEvent, TradingOtherNotAllowedEvent, TradingUnacceptComposer, TradingYouAreNotAllowedEvent, TraxSongInfoMessageEvent, TryPhoneNumberMessageComposer, TryPhoneNumberResultMessageEvent, TryVerificationCodeResultMessageEvent, UnblockGroupMemberMessageComposer, UnignoreUserComposer, UniqueIDMessageComposer, UnloadGameMessageEvent, UnreadForumsCountMessageEvent, UnseenItemsEvent, UnseenResetCategoryComposer, UnseenResetItemsComposer, UpdateActionMessageComposer, UpdateConditionMessageComposer, UpdateFloorPropertiesMessageComposer, UpdateForumReadMarkerMessageComposer, UpdateForumSettingsMessageComposer, UpdateFurniturePositionComposer, UpdateHomeRoomMessageComposer, UpdateMessageMessageEvent, UpdateRoomCategoryAndTradeSettingsComposer, UpdateRoomFilterMessageComposer, UpdateRoomThumbnailMessageComposer, UpdateThreadMessageComposer, UpdateThreadMessageEvent, UpdateTriggerMessageComposer, UsePetProductComposer, UserBannedMessageEvent, UserChatlogEvent, UserClassificationMessageEvent, UserCreditsEvent, UserCurrencyComposer, UserCurrencyEvent, UserCurrentBadgesComposer, UserCurrentBadgesEvent, UserEventCatsEvent, UserFigureComposer, UserFlatCatsEvent, UserGameAchievementsMessageEvent, UserInfoEvent, UserMottoComposer, UserNameChangeMessageEvent, UserPermissionsEvent, UserProfileComposer, UserProfileEvent, UserRelationshipsComposer, UserRespectComposer, UserSettingsCameraFollowComposer, UserSettingsEvent, UserSettingsOldChatComposer, UserSettingsRoomInvitesComposer, UserSettingsSoundComposer, UserSongDisksInventoryMessageEvent, UserSubscriptionComposer, UserSubscriptionEvent, UserTagsMessageEvent, UserUnbannedFromRoomEvent, UserWardrobePageEvent, VerifyCodeMessageComposer, VersionCheckMessageComposer, VisitUserComposer, VoteForRoomMessageComposer, VotePollCounterMessageComposer, VoucherRedeemErrorMessageEvent, VoucherRedeemOkMessageEvent, WardrobeMessageEvent, WeeklyCompetitiveFriendsLeaderboardEvent, WeeklyCompetitiveLeaderboardEvent, WeeklyGameRewardEvent, WeeklyGameRewardWinnersEvent, WelcomeGiftChangeEmailComposer, WelcomeGiftChangeEmailResultEvent, WelcomeGiftStatusEvent, WiredFurniActionEvent, WiredFurniConditionEvent, WiredFurniTriggerEvent, WiredOpenEvent, WiredRewardResultMessageEvent, WiredSaveSuccessEvent, WiredValidationErrorEvent, YouArePlayingGameEvent, YouAreSpectatorMessageEvent, YoutubeControlVideoMessageEvent, YoutubeDisplayPlaylistsEvent, YoutubeDisplayVideoMessageEvent } from './messages'; export class NitroMessages implements IMessageConfiguration @@ -574,6 +576,11 @@ export class NitroMessages implements IMessageConfiguration // Custom packets this._events.set(IncomingHeader.AREA_HIDE, AreaHideMessageEvent); + + // Custom Prefixes + this._events.set(IncomingHeader.USER_PREFIXES, UserPrefixesEvent); + this._events.set(IncomingHeader.PREFIX_RECEIVED, PrefixReceivedEvent); + this._events.set(IncomingHeader.ACTIVE_PREFIX_UPDATED, ActivePrefixUpdatedEvent); } private registerComposers(): void @@ -1184,6 +1191,12 @@ export class NitroMessages implements IMessageConfiguration this._composers.set(OutgoingHeader.RENTABLE_EXTEND_RENT_OR_BUYOUT_STRIP_ITEM, ExtendRentOrBuyoutStripItemMessageComposer); this._composers.set(OutgoingHeader.RENTABLE_EXTEND_RENT_OR_BUYOUT_FURNI, ExtendRentOrBuyoutFurniMessageComposer); this._composers.set(OutgoingHeader.RENTABLE_GET_RENT_OR_BUYOUT_OFFER, GetRentOrBuyoutOfferMessageComposer); + + // Custom Prefixes + this._composers.set(OutgoingHeader.REQUEST_PREFIXES, RequestPrefixesComposer); + this._composers.set(OutgoingHeader.SET_ACTIVE_PREFIX, SetActivePrefixComposer); + this._composers.set(OutgoingHeader.DELETE_PREFIX, DeletePrefixComposer); + this._composers.set(OutgoingHeader.PURCHASE_PREFIX, PurchasePrefixComposer); } public get events(): Map diff --git a/packages/communication/src/index.ts b/packages/communication/src/index.ts index 7fa2659..5f56f6c 100644 --- a/packages/communication/src/index.ts +++ b/packages/communication/src/index.ts @@ -37,6 +37,7 @@ export * from './messages/incoming/inventory/clothes'; export * from './messages/incoming/inventory/furni'; export * from './messages/incoming/inventory/furni/gifts'; export * from './messages/incoming/inventory/pets'; +export * from './messages/incoming/inventory/prefixes'; export * from './messages/incoming/inventory/trading'; export * from './messages/incoming/landingview'; export * from './messages/incoming/landingview/votes'; @@ -109,6 +110,7 @@ export * from './messages/outgoing/inventory/badges'; export * from './messages/outgoing/inventory/bots'; export * from './messages/outgoing/inventory/furni'; export * from './messages/outgoing/inventory/pets'; +export * from './messages/outgoing/inventory/prefixes'; export * from './messages/outgoing/inventory/trading'; export * from './messages/outgoing/inventory/unseen'; export * from './messages/outgoing/landingview'; @@ -187,6 +189,7 @@ export * from './messages/parser/inventory/badges'; export * from './messages/parser/inventory/clothing'; export * from './messages/parser/inventory/furniture'; export * from './messages/parser/inventory/pets'; +export * from './messages/parser/inventory/prefixes'; export * from './messages/parser/inventory/purse'; export * from './messages/parser/inventory/trading'; export * from './messages/parser/landingview'; diff --git a/packages/communication/src/messages/incoming/IncomingHeader.ts b/packages/communication/src/messages/incoming/IncomingHeader.ts index 558317d..5d7f733 100644 --- a/packages/communication/src/messages/incoming/IncomingHeader.ts +++ b/packages/communication/src/messages/incoming/IncomingHeader.ts @@ -474,4 +474,9 @@ export class IncomingHeader public static WEEKLY_GAME2_LEADERBOARD = 2196; public static RENTABLE_FURNI_RENT_OR_BUYOUT_OFFER = 35; public static HANDSHAKE_IDENTITY_ACCOUNT = 3523; + + // Custom Prefixes + public static USER_PREFIXES = 7001; + public static PREFIX_RECEIVED = 7002; + public static ACTIVE_PREFIX_UPDATED = 7003; } diff --git a/packages/communication/src/messages/incoming/inventory/index.ts b/packages/communication/src/messages/incoming/inventory/index.ts index 4f6ae27..9109eb5 100644 --- a/packages/communication/src/messages/incoming/inventory/index.ts +++ b/packages/communication/src/messages/incoming/inventory/index.ts @@ -5,4 +5,5 @@ export * from './clothes'; export * from './furni'; export * from './furni/gifts'; export * from './pets'; +export * from './prefixes'; export * from './trading'; diff --git a/packages/communication/src/messages/incoming/inventory/prefixes/ActivePrefixUpdatedEvent.ts b/packages/communication/src/messages/incoming/inventory/prefixes/ActivePrefixUpdatedEvent.ts new file mode 100644 index 0000000..f416d63 --- /dev/null +++ b/packages/communication/src/messages/incoming/inventory/prefixes/ActivePrefixUpdatedEvent.ts @@ -0,0 +1,16 @@ +import { IMessageEvent } from '@nitrots/api'; +import { MessageEvent } from '@nitrots/events'; +import { ActivePrefixUpdatedParser } from '../../../parser'; + +export class ActivePrefixUpdatedEvent extends MessageEvent implements IMessageEvent +{ + constructor(callBack: Function) + { + super(callBack, ActivePrefixUpdatedParser); + } + + public getParser(): ActivePrefixUpdatedParser + { + return this.parser as ActivePrefixUpdatedParser; + } +} diff --git a/packages/communication/src/messages/incoming/inventory/prefixes/PrefixReceivedEvent.ts b/packages/communication/src/messages/incoming/inventory/prefixes/PrefixReceivedEvent.ts new file mode 100644 index 0000000..d92b4d6 --- /dev/null +++ b/packages/communication/src/messages/incoming/inventory/prefixes/PrefixReceivedEvent.ts @@ -0,0 +1,16 @@ +import { IMessageEvent } from '@nitrots/api'; +import { MessageEvent } from '@nitrots/events'; +import { PrefixReceivedParser } from '../../../parser'; + +export class PrefixReceivedEvent extends MessageEvent implements IMessageEvent +{ + constructor(callBack: Function) + { + super(callBack, PrefixReceivedParser); + } + + public getParser(): PrefixReceivedParser + { + return this.parser as PrefixReceivedParser; + } +} diff --git a/packages/communication/src/messages/incoming/inventory/prefixes/UserPrefixesEvent.ts b/packages/communication/src/messages/incoming/inventory/prefixes/UserPrefixesEvent.ts new file mode 100644 index 0000000..5be455d --- /dev/null +++ b/packages/communication/src/messages/incoming/inventory/prefixes/UserPrefixesEvent.ts @@ -0,0 +1,16 @@ +import { IMessageEvent } from '@nitrots/api'; +import { MessageEvent } from '@nitrots/events'; +import { UserPrefixesParser } from '../../../parser'; + +export class UserPrefixesEvent extends MessageEvent implements IMessageEvent +{ + constructor(callBack: Function) + { + super(callBack, UserPrefixesParser); + } + + public getParser(): UserPrefixesParser + { + return this.parser as UserPrefixesParser; + } +} diff --git a/packages/communication/src/messages/incoming/inventory/prefixes/index.ts b/packages/communication/src/messages/incoming/inventory/prefixes/index.ts new file mode 100644 index 0000000..d1cdb77 --- /dev/null +++ b/packages/communication/src/messages/incoming/inventory/prefixes/index.ts @@ -0,0 +1,3 @@ +export * from './ActivePrefixUpdatedEvent'; +export * from './PrefixReceivedEvent'; +export * from './UserPrefixesEvent'; diff --git a/packages/communication/src/messages/outgoing/OutgoingHeader.ts b/packages/communication/src/messages/outgoing/OutgoingHeader.ts index 69f9061..74547a1 100644 --- a/packages/communication/src/messages/outgoing/OutgoingHeader.ts +++ b/packages/communication/src/messages/outgoing/OutgoingHeader.ts @@ -477,4 +477,10 @@ export class OutgoingHeader public static DELETE_ITEM = 10018; public static DELETE_PET = 10030; public static DELETE_BADGE = 10031; + + // Custom Prefixes + public static REQUEST_PREFIXES = 7011; + public static SET_ACTIVE_PREFIX = 7012; + public static DELETE_PREFIX = 7013; + public static PURCHASE_PREFIX = 7014; } diff --git a/packages/communication/src/messages/outgoing/inventory/index.ts b/packages/communication/src/messages/outgoing/inventory/index.ts index 4fc8506..59aebf7 100644 --- a/packages/communication/src/messages/outgoing/inventory/index.ts +++ b/packages/communication/src/messages/outgoing/inventory/index.ts @@ -3,5 +3,6 @@ export * from './badges'; export * from './bots'; export * from './furni'; export * from './pets'; +export * from './prefixes'; export * from './trading'; export * from './unseen'; diff --git a/packages/communication/src/messages/outgoing/inventory/prefixes/DeletePrefixComposer.ts b/packages/communication/src/messages/outgoing/inventory/prefixes/DeletePrefixComposer.ts new file mode 100644 index 0000000..ffda07d --- /dev/null +++ b/packages/communication/src/messages/outgoing/inventory/prefixes/DeletePrefixComposer.ts @@ -0,0 +1,21 @@ +import { IMessageComposer } from '@nitrots/api'; + +export class DeletePrefixComposer implements IMessageComposer> +{ + private _data: ConstructorParameters; + + constructor(prefixId: number) + { + this._data = [ prefixId ]; + } + + public getMessageArray() + { + return this._data; + } + + public dispose(): void + { + return; + } +} diff --git a/packages/communication/src/messages/outgoing/inventory/prefixes/PurchasePrefixComposer.ts b/packages/communication/src/messages/outgoing/inventory/prefixes/PurchasePrefixComposer.ts new file mode 100644 index 0000000..29e5ec9 --- /dev/null +++ b/packages/communication/src/messages/outgoing/inventory/prefixes/PurchasePrefixComposer.ts @@ -0,0 +1,21 @@ +import { IMessageComposer } from '@nitrots/api'; + +export class PurchasePrefixComposer implements IMessageComposer> +{ + private _data: ConstructorParameters; + + constructor(text: string, color: string, icon: string = '', effect: string = '') + { + this._data = [ text, color, icon, effect ]; + } + + public getMessageArray() + { + return this._data; + } + + public dispose(): void + { + return; + } +} diff --git a/packages/communication/src/messages/outgoing/inventory/prefixes/RequestPrefixesComposer.ts b/packages/communication/src/messages/outgoing/inventory/prefixes/RequestPrefixesComposer.ts new file mode 100644 index 0000000..5cdb767 --- /dev/null +++ b/packages/communication/src/messages/outgoing/inventory/prefixes/RequestPrefixesComposer.ts @@ -0,0 +1,21 @@ +import { IMessageComposer } from '@nitrots/api'; + +export class RequestPrefixesComposer implements IMessageComposer> +{ + private _data: ConstructorParameters; + + constructor() + { + this._data = []; + } + + public getMessageArray() + { + return this._data; + } + + public dispose(): void + { + return; + } +} diff --git a/packages/communication/src/messages/outgoing/inventory/prefixes/SetActivePrefixComposer.ts b/packages/communication/src/messages/outgoing/inventory/prefixes/SetActivePrefixComposer.ts new file mode 100644 index 0000000..fe8949b --- /dev/null +++ b/packages/communication/src/messages/outgoing/inventory/prefixes/SetActivePrefixComposer.ts @@ -0,0 +1,21 @@ +import { IMessageComposer } from '@nitrots/api'; + +export class SetActivePrefixComposer implements IMessageComposer> +{ + private _data: ConstructorParameters; + + constructor(prefixId: number) + { + this._data = [ prefixId ]; + } + + public getMessageArray() + { + return this._data; + } + + public dispose(): void + { + return; + } +} diff --git a/packages/communication/src/messages/outgoing/inventory/prefixes/index.ts b/packages/communication/src/messages/outgoing/inventory/prefixes/index.ts new file mode 100644 index 0000000..e4c2b5c --- /dev/null +++ b/packages/communication/src/messages/outgoing/inventory/prefixes/index.ts @@ -0,0 +1,4 @@ +export * from './DeletePrefixComposer'; +export * from './PurchasePrefixComposer'; +export * from './RequestPrefixesComposer'; +export * from './SetActivePrefixComposer'; diff --git a/packages/communication/src/messages/parser/inventory/index.ts b/packages/communication/src/messages/parser/inventory/index.ts index 01f6a81..58cb9a2 100644 --- a/packages/communication/src/messages/parser/inventory/index.ts +++ b/packages/communication/src/messages/parser/inventory/index.ts @@ -4,5 +4,6 @@ export * from './badges'; export * from './clothing'; export * from './furniture'; export * from './pets'; +export * from './prefixes'; export * from './purse'; export * from './trading'; diff --git a/packages/communication/src/messages/parser/inventory/prefixes/ActivePrefixUpdatedParser.ts b/packages/communication/src/messages/parser/inventory/prefixes/ActivePrefixUpdatedParser.ts new file mode 100644 index 0000000..26ce917 --- /dev/null +++ b/packages/communication/src/messages/parser/inventory/prefixes/ActivePrefixUpdatedParser.ts @@ -0,0 +1,39 @@ +import { IMessageDataWrapper, IMessageParser } from '@nitrots/api'; + +export class ActivePrefixUpdatedParser implements IMessageParser +{ + private _prefixId: number; + private _text: string; + private _color: string; + private _icon: string; + private _effect: string; + + public flush(): boolean + { + this._prefixId = 0; + this._text = ''; + this._color = ''; + this._icon = ''; + this._effect = ''; + return true; + } + + public parse(wrapper: IMessageDataWrapper): boolean + { + if(!wrapper) return false; + + this._prefixId = wrapper.readInt(); + this._text = wrapper.readString(); + this._color = wrapper.readString(); + this._icon = wrapper.readString(); + this._effect = wrapper.readString(); + + return true; + } + + public get prefixId(): number { return this._prefixId; } + public get text(): string { return this._text; } + public get color(): string { return this._color; } + public get icon(): string { return this._icon; } + public get effect(): string { return this._effect; } +} diff --git a/packages/communication/src/messages/parser/inventory/prefixes/PrefixReceivedParser.ts b/packages/communication/src/messages/parser/inventory/prefixes/PrefixReceivedParser.ts new file mode 100644 index 0000000..a286a2d --- /dev/null +++ b/packages/communication/src/messages/parser/inventory/prefixes/PrefixReceivedParser.ts @@ -0,0 +1,39 @@ +import { IMessageDataWrapper, IMessageParser } from '@nitrots/api'; + +export class PrefixReceivedParser implements IMessageParser +{ + private _id: number; + private _text: string; + private _color: string; + private _icon: string; + private _effect: string; + + public flush(): boolean + { + this._id = 0; + this._text = ''; + this._color = ''; + this._icon = ''; + this._effect = ''; + return true; + } + + public parse(wrapper: IMessageDataWrapper): boolean + { + if(!wrapper) return false; + + this._id = wrapper.readInt(); + this._text = wrapper.readString(); + this._color = wrapper.readString(); + this._icon = wrapper.readString(); + this._effect = wrapper.readString(); + + return true; + } + + public get id(): number { return this._id; } + public get text(): string { return this._text; } + public get color(): string { return this._color; } + public get icon(): string { return this._icon; } + public get effect(): string { return this._effect; } +} diff --git a/packages/communication/src/messages/parser/inventory/prefixes/UserPrefixesParser.ts b/packages/communication/src/messages/parser/inventory/prefixes/UserPrefixesParser.ts new file mode 100644 index 0000000..26d4342 --- /dev/null +++ b/packages/communication/src/messages/parser/inventory/prefixes/UserPrefixesParser.ts @@ -0,0 +1,52 @@ +import { IMessageDataWrapper, IMessageParser } from '@nitrots/api'; + +export interface IPrefixData +{ + id: number; + text: string; + color: string; + icon: string; + effect: string; + active: boolean; +} + +export class UserPrefixesParser implements IMessageParser +{ + private _prefixes: IPrefixData[]; + + public flush(): boolean + { + this._prefixes = []; + return true; + } + + public parse(wrapper: IMessageDataWrapper): boolean + { + if(!wrapper) return false; + + this._prefixes = []; + + let count = wrapper.readInt(); + + while(count > 0) + { + this._prefixes.push({ + id: wrapper.readInt(), + text: wrapper.readString(), + color: wrapper.readString(), + icon: wrapper.readString(), + effect: wrapper.readString(), + active: wrapper.readInt() === 1 + }); + + count--; + } + + return true; + } + + public get prefixes(): IPrefixData[] + { + return this._prefixes; + } +} diff --git a/packages/communication/src/messages/parser/inventory/prefixes/index.ts b/packages/communication/src/messages/parser/inventory/prefixes/index.ts new file mode 100644 index 0000000..d054261 --- /dev/null +++ b/packages/communication/src/messages/parser/inventory/prefixes/index.ts @@ -0,0 +1,3 @@ +export * from './ActivePrefixUpdatedParser'; +export * from './PrefixReceivedParser'; +export * from './UserPrefixesParser'; diff --git a/packages/communication/src/messages/parser/room/unit/chat/RoomUnitChatParser.ts b/packages/communication/src/messages/parser/room/unit/chat/RoomUnitChatParser.ts index 21f4afc..09a30ec 100644 --- a/packages/communication/src/messages/parser/room/unit/chat/RoomUnitChatParser.ts +++ b/packages/communication/src/messages/parser/room/unit/chat/RoomUnitChatParser.ts @@ -9,6 +9,10 @@ export class RoomUnitChatParser implements IMessageParser private _urls: string[]; private _chatColours: string; private _messageLength: number; + private _prefixText: string; + private _prefixColor: string; + private _prefixIcon: string; + private _prefixEffect: string; public flush(): boolean { @@ -19,6 +23,10 @@ export class RoomUnitChatParser implements IMessageParser this._urls = []; this._chatColours = null; this._messageLength = 0; + this._prefixText = ''; + this._prefixColor = ''; + this._prefixIcon = ''; + this._prefixEffect = ''; return true; } @@ -33,9 +41,13 @@ export class RoomUnitChatParser implements IMessageParser this._bubble = wrapper.readInt(); this.parseUrls(wrapper); - + this._chatColours = wrapper.readString(); this._messageLength = wrapper.readInt(); + this._prefixText = wrapper.readString(); + this._prefixColor = wrapper.readString(); + this._prefixIcon = wrapper.readString(); + this._prefixEffect = wrapper.readString(); return true; } @@ -82,7 +94,7 @@ export class RoomUnitChatParser implements IMessageParser { return this._urls; } - + public get chatColours(): string { return this._chatColours; @@ -92,4 +104,24 @@ export class RoomUnitChatParser implements IMessageParser { return this._messageLength; } + + public get prefixText(): string + { + return this._prefixText; + } + + public get prefixColor(): string + { + return this._prefixColor; + } + + public get prefixIcon(): string + { + return this._prefixIcon; + } + + public get prefixEffect(): string + { + return this._prefixEffect; + } } diff --git a/packages/events/src/session/RoomSessionChatEvent.ts b/packages/events/src/session/RoomSessionChatEvent.ts index 1b0ca2a..1f3e0ad 100644 --- a/packages/events/src/session/RoomSessionChatEvent.ts +++ b/packages/events/src/session/RoomSessionChatEvent.ts @@ -24,8 +24,12 @@ export class RoomSessionChatEvent extends RoomSessionEvent private _links: string[]; private _extraParam: number; private _style: number; + private _prefixText: string; + private _prefixColor: string; + private _prefixIcon: string; + private _prefixEffect: string; - constructor(type: string, session: IRoomSession, objectId: number, message: string, chatType: number, style: number = 0, chatColours: string[], links: string[] = null, extraParam: number = -1) + constructor(type: string, session: IRoomSession, objectId: number, message: string, chatType: number, style: number = 0, chatColours: string[], links: string[] = null, extraParam: number = -1, prefixText: string = '', prefixColor: string = '', prefixIcon: string = '', prefixEffect: string = '') { super(type, session); @@ -36,6 +40,10 @@ export class RoomSessionChatEvent extends RoomSessionEvent this._links = links; this._extraParam = extraParam; this._style = style; + this._prefixText = prefixText; + this._prefixColor = prefixColor; + this._prefixIcon = prefixIcon; + this._prefixEffect = prefixEffect; } public get objectId(): number @@ -67,9 +75,29 @@ export class RoomSessionChatEvent extends RoomSessionEvent { return this._style; } - + public get chatColours(): string[] { return this._chatColours; } + + public get prefixText(): string + { + return this._prefixText; + } + + public get prefixColor(): string + { + return this._prefixColor; + } + + public get prefixIcon(): string + { + return this._prefixIcon; + } + + public get prefixEffect(): string + { + return this._prefixEffect; + } } diff --git a/packages/session/src/handler/RoomChatHandler.ts b/packages/session/src/handler/RoomChatHandler.ts index cc17a8b..aa717f3 100644 --- a/packages/session/src/handler/RoomChatHandler.ts +++ b/packages/session/src/handler/RoomChatHandler.ts @@ -37,7 +37,7 @@ export class RoomChatHandler extends BaseHandler if(event instanceof RoomUnitChatShoutEvent) chatType = RoomSessionChatEvent.CHAT_TYPE_SHOUT; else if(event instanceof RoomUnitChatWhisperEvent) chatType = RoomSessionChatEvent.CHAT_TYPE_WHISPER; - const chatEvent = new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, parser.roomIndex, parser.message, chatType, parser.bubble, parser.chatColours); + const chatEvent = new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, parser.roomIndex, parser.message, chatType, parser.bubble, parser.chatColours, null, -1, parser.prefixText, parser.prefixColor, parser.prefixIcon, parser.prefixEffect); GetEventDispatcher().dispatchEvent(chatEvent); } From 569e0ff67b7242c87cf26547b35b9f3da07ace97 Mon Sep 17 00:00:00 2001 From: DuckieTM Date: Sat, 21 Mar 2026 12:15:25 +0100 Subject: [PATCH 11/11] =?UTF-8?q?=F0=9F=86=99=20added=20missing=20Availabl?= =?UTF-8?q?eCommands?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/communication/src/NitroMessages.ts | 5 ++- packages/communication/src/index.ts | 2 + .../src/messages/incoming/IncomingHeader.ts | 1 + .../commands/AvailableCommandsEvent.ts | 16 ++++++++ .../src/messages/incoming/commands/index.ts | 1 + .../src/messages/incoming/index.ts | 1 + .../commands/AvailableCommandsParser.ts | 37 +++++++++++++++++++ .../src/messages/parser/commands/index.ts | 1 + .../src/messages/parser/index.ts | 1 + 9 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 packages/communication/src/messages/incoming/commands/AvailableCommandsEvent.ts create mode 100644 packages/communication/src/messages/incoming/commands/index.ts create mode 100644 packages/communication/src/messages/parser/commands/AvailableCommandsParser.ts create mode 100644 packages/communication/src/messages/parser/commands/index.ts diff --git a/packages/communication/src/NitroMessages.ts b/packages/communication/src/NitroMessages.ts index ced7b60..7cc44fd 100644 --- a/packages/communication/src/NitroMessages.ts +++ b/packages/communication/src/NitroMessages.ts @@ -1,7 +1,7 @@ import { IMessageConfiguration } from '@nitrots/api'; import { ActivePrefixUpdatedEvent, PrefixReceivedEvent, UserPrefixesEvent } from './messages/incoming/inventory/prefixes'; import { DeletePrefixComposer, PurchasePrefixComposer, RequestPrefixesComposer, SetActivePrefixComposer } from './messages/outgoing/inventory/prefixes'; -import { AcceptFriendMessageComposer, AcceptFriendResultEvent, AcceptGameInviteMessageComposer, AcceptQuestMessageComposer, AccountSafetyLockStatusChangeMessageEvent, AchievementEvent, AchievementNotificationMessageEvent, AchievementResolutionCompletedMessageEvent, AchievementResolutionProgressMessageEvent, AchievementResolutionsMessageEvent, AchievementsEvent, AchievementsScoreEvent, ActivateQuestMessageComposer, ActivityPointNotificationMessageEvent, AddFavouriteRoomMessageComposer, AddJukeboxDiskComposer, AddSpamWallPostItMessageComposer, ApplySnapshotMessageComposer, ApplyTonerComposer, ApproveAllMembershipRequestsMessageComposer, ApproveNameMessageComposer, ApproveNameMessageEvent, AreaHideMessageEvent, AuthenticatedEvent, AuthenticationMessageComposer, AvailabilityStatusMessageEvent, AvailabilityTimeMessageEvent, AvatarEffectActivatedComposer, AvatarEffectActivatedEvent, AvatarEffectAddedEvent, AvatarEffectExpiredEvent, AvatarEffectSelectedComposer, AvatarEffectSelectedEvent, AvatarEffectsEvent, BadgePointLimitsEvent, BadgeReceivedEvent, BadgesEvent, BannedUsersFromRoomEvent, BonusRareInfoMessageEvent, BotAddedToInventoryEvent, BotCommandConfigurationEvent, BotErrorEvent, BotForceOpenContextMenuEvent, BotInventoryMessageEvent, BotPlaceComposer, BotReceivedMessageEvent, BotRemoveComposer, BotRemovedFromInventoryEvent, BotSkillListUpdateEvent, BotSkillSaveComposer, BreedPetsMessageComposer, BuildersClubFurniCountMessageEvent, BuildersClubPlaceRoomItemMessageComposer, BuildersClubPlaceWallItemMessageComposer, BuildersClubQueryFurniCountMessageComposer, BuildersClubSubscriptionStatusMessageEvent, BundleDiscountRulesetMessageEvent, BuyMarketplaceOfferMessageComposer, BuyMarketplaceTokensMessageComposer, CallForHelpDisabledNotifyMessageEvent, CallForHelpFromForumMessageMessageComposer, CallForHelpFromForumThreadMessageComposer, CallForHelpFromIMMessageComposer, CallForHelpFromPhotoMessageComposer, CallForHelpFromSelfieMessageComposer, CallForHelpMessageComposer, CallForHelpPendingCallsDeletedMessageEvent, CallForHelpPendingCallsMessageEvent, CallForHelpReplyMessageEvent, CallForHelpResultMessageEvent, CameraPublishStatusMessageEvent, CameraPurchaseOKMessageEvent, CameraSnapshotMessageEvent, CameraStorageUrlMessageEvent, CampaignCalendarDataMessageEvent, CampaignCalendarDoorOpenedMessageEvent, CanCreateRoomEvent, CanCreateRoomEventEvent, CanCreateRoomMessageComposer, CancelEventMessageComposer, CancelMarketplaceOfferMessageComposer, CancelMysteryBoxWaitMessageEvent, CancelPetBreedingComposer, CancelQuestMessageComposer, CatalogGroupsComposer, CatalogPageExpirationEvent, CatalogPageMessageEvent, CatalogPageWithEarliestExpiryMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, CategoriesWithVisitorCountEvent, CfhChatlogEvent, CfhSanctionMessageEvent, CfhTopicsInitEvent, ChangeEmailComposer, ChangeEmailResultEvent, ChangeQueueMessageComposer, ChangeUserNameMessageComposer, ChangeUserNameResultMessageEvent, ChatReviewGuideDecidesOnOfferMessageComposer, ChatReviewGuideDetachedMessageComposer, ChatReviewGuideVoteMessageComposer, ChatReviewSessionCreateMessageComposer, ChatReviewSessionDetachedMessageEvent, ChatReviewSessionOfferedToGuideMessageEvent, ChatReviewSessionResultsMessageEvent, ChatReviewSessionStartedMessageEvent, ChatReviewSessionVotingStatusMessageEvent, CheckUserNameMessageComposer, CheckUserNameResultMessageEvent, ClickFurniMessageComposer, ClientHelloMessageComposer, ClientPingEvent, CloseIssueDefaultActionMessageComposer, CloseIssuesMessageComposer, ClubGiftInfoEvent, ClubGiftNotificationEvent, ClubGiftSelectedEvent, CommunityGoalEarnedPrizesMessageEvent, CommunityGoalHallOfFameMessageEvent, CommunityGoalProgressMessageEvent, CommunityGoalVoteMessageComposer, CommunityGoalVoteMessageEvent, CompetitionEntrySubmitResultEvent, CompetitionRoomsDataMessageEvent, CompetitionRoomsSearchMessageComposer, CompetitionStatusMessageEvent, CompetitionVotingInfoMessageEvent, CompleteDiffieHandshakeEvent, CompleteDiffieHandshakeMessageComposer, CompostPlantMessageComposer, ConcurrentUsersGoalProgressMessageEvent, ConfirmPetBreedingComposer, ConnectionErrorEvent, ControlYoutubeDisplayPlaybackMessageComposer, ConvertGlobalRoomIdMessageComposer, ConvertedRoomIdEvent, CraftComposer, CraftSecretComposer, CraftableProductsEvent, CraftingRecipeEvent, CraftingRecipesAvailableEvent, CraftingResultEvent, CreateFlatMessageComposer, CurrentTimingCodeMessageEvent, CustomUserNotificationMessageEvent, DeclineFriendMessageComposer, DefaultSanctionMessageComposer, DeleteFavouriteRoomMessageComposer, DeleteItemMessageComposer, DeleteBadgeMessageComposer, DeletePetMessageComposer, DeletePendingCallsForHelpMessageComposer, DesktopViewComposer, DesktopViewEvent, DiceValueMessageEvent, DirectSMSClubBuyAvailableMessageEvent, DisconnectMessageComposer, DisconnectReasonEvent, DoorbellMessageEvent, EditEventMessageComposer, ElementPointerMessageEvent, EmailStatusResultEvent, EpicPopupMessageEvent, ExtendRentOrBuyoutFurniMessageComposer, ExtendRentOrBuyoutStripItemMessageComposer, ExtendedProfileChangedMessageEvent, FavoriteMembershipUpdateMessageEvent, FavouriteChangedEvent, FavouritesEvent, FigureSetIdsMessageEvent, FigureUpdateEvent, FindFriendsProcessResultEvent, FindNewFriendsMessageComposer, FireworkChargeDataEvent, FlatAccessDeniedMessageEvent, FlatControllerAddedEvent, FlatControllerRemovedEvent, FlatControllersEvent, FlatCreatedEvent, FloodControlEvent, FloorHeightMapEvent, FollowFriendFailedEvent, FollowFriendMessageComposer, ForumDataMessageEvent, ForumsListMessageEvent, ForwardToACompetitionRoomMessageComposer, ForwardToARandomPromotedRoomMessageComposer, ForwardToASubmittableRoomMessageComposer, ForwardToRandomCompetitionRoomMessageComposer, ForwardToSomeRoomMessageComposer, FriendFurniConfirmLockMessageComposer, FriendListFragmentEvent, FriendListUpdateComposer, FriendListUpdateEvent, FriendNotificationEvent, FriendRequestQuestCompleteMessageComposer, FriendRequestsEvent, FurniRentOrBuyoutOfferMessageEvent, FurnitureAliasesComposer, FurnitureAliasesEvent, FurnitureColorWheelComposer, FurnitureDataEvent, FurnitureDiceActivateComposer, FurnitureDiceDeactivateComposer, FurnitureExchangeComposer, FurnitureFloorAddEvent, FurnitureFloorEvent, FurnitureFloorRemoveEvent, FurnitureFloorUpdateComposer, FurnitureFloorUpdateEvent, FurnitureGroupInfoComposer, FurnitureListAddOrUpdateEvent, FurnitureListComposer, FurnitureListEvent, FurnitureListInvalidateEvent, FurnitureListRemovedEvent, FurnitureMannequinSaveLookComposer, FurnitureMannequinSaveNameComposer, FurnitureMultiStateComposer, FurnitureOneWayDoorComposer, FurniturePickupComposer, FurniturePickupAllComposer, FurniturePlaceComposer, FurniturePlacePaintComposer, FurniturePostItPlaceComposer, FurniturePostItPlacedEvent, FurnitureRandomStateComposer, FurnitureStackHeightComposer, FurnitureStackHeightEvent, FurnitureWallAddEvent, FurnitureWallEvent, FurnitureWallMultiStateComposer, FurnitureWallRemoveEvent, FurnitureWallUpdateComposer, FurnitureWallUpdateEvent, Game2AccountGameStatusMessageEvent, Game2CheckGameDirectoryStatusMessageComposer, Game2ExitGameMessageComposer, Game2GameChatMessageComposer, Game2GameDirectoryStatusMessageEvent, Game2GetAccountGameStatusMessageComposer, Game2GetWeeklyFriendsLeaderboardComposer, Game2GetWeeklyLeaderboardComposer, Game2InArenaQueueMessageEvent, Game2JoiningGameFailedMessageEvent, Game2LoadStageReadyMessageComposer, Game2PlayAgainMessageComposer, Game2RequestFullStatusUpdateMessageComposer, Game2StartingGameFailedMessageEvent, Game2StopCounterMessageEvent, Game2UserLeftGameMessageEvent, Game2WeeklyFriendsLeaderboardEvent, Game2WeeklyLeaderboardEvent, GameAchievementsMessageEvent, GameInviteMessageEvent, GameListMessageEvent, GameStatusMessageEvent, GameUnloadedMessageComposer, GenericErrorEvent, GetBadgePointLimitsComposer, GetBonusRareInfoMessageComposer, GetBotInventoryComposer, GetBundleDiscountRulesetComposer, GetCatalogIndexComposer, GetCatalogPageComposer, GetCatalogPageExpirationComposer, GetCatalogPageWithEarliestExpiryComposer, GetCategoriesWithUserCountMessageComposer, GetCfhChatlogMessageComposer, GetCfhStatusMessageComposer, GetClubGiftInfo, GetClubOffersMessageComposer, GetCommunityGoalEarnedPrizesMessageComposer, GetCommunityGoalHallOfFameMessageComposer, GetCommunityGoalProgressMessageComposer, GetConcurrentUsersGoalProgressMessageComposer, GetConcurrentUsersRewardMessageComposer, GetCraftableProductsComposer, GetCraftingRecipeComposer, GetCraftingRecipesAvailableComposer, GetCurrentTimingCodeMessageComposer, GetCustomRoomFilterMessageComposer, GetDailyQuestMessageComposer, GetDirectClubBuyAvailableComposer, GetEmailStatusComposer, GetExtendedProfileByNameMessageComposer, GetFaqCategoryMessageComposer, GetFaqTextMessageComposer, GetForumStatsMessageComposer, GetForumsListMessageComposer, GetFriendRequestsComposer, GetGameAchievementsMessageComposer, GetGameListMessageComposer, GetGameStatusMessageComposer, GetGiftMessageComposer, GetGiftWrappingConfigurationComposer, GetGuestRoomMessageComposer, GetGuestRoomResultEvent, GetGuideReportingStatusMessageComposer, GetHabboBasicMembershipExtendOfferComposer, GetHabboClubExtendOfferMessageComposer, GetHabboGroupBadgesMessageComposer, GetIgnoredUsersComposer, GetInterstitialMessageComposer, GetIsBadgeRequestFulfilledComposer, GetIsOfferGiftableComposer, GetIsUserPartOfCompetitionMessageComposer, GetItemDataComposer, GetJukeboxPlayListMessageComposer, GetLimitedOfferAppearingNextComposer, GetMarketplaceCanMakeOfferComposer, GetMarketplaceConfigurationMessageComposer, GetMarketplaceItemStatsComposer, GetMarketplaceOffersMessageComposer, GetMarketplaceOwnOffersMessageComposer, GetMessagesMessageComposer, GetModeratorRoomInfoMessageComposer, GetModeratorUserInfoMessageComposer, GetNextTargetedOfferComposer, GetNowPlayingMessageComposer, GetOccupiedTilesMessageComposer, GetOfficialRoomsMessageComposer, GetOfficialSongIdMessageComposer, GetPendingCallsForHelpMessageComposer, GetPetCommandsComposer, GetPopularRoomTagsMessageComposer, GetProductOfferComposer, GetPromoArticlesComposer, GetQuestsMessageComposer, GetQuizQuestionsComposer, GetRecyclerStatusMessageComposer, GetRentOrBuyoutOfferMessageComposer, GetResolutionAchievementsMessageComposer, GetRoomAdPurchaseInfoComposer, GetRoomChatlogMessageComposer, GetRoomEntryDataMessageComposer, GetRoomEntryTileMessageComposer, GetRoomVisitsMessageComposer, GetSeasonalCalendarDailyOfferComposer, GetSeasonalQuestsOnlyMessageComposer, GetSecondsUntilMessageComposer, GetSellablePetPalettesComposer, GetSongInfoMessageComposer, GetSoundMachinePlayListMessageComposer, GetSoundSettingsComposer, GetTalentTrackLevelMessageComposer, GetTargetedOfferComposer, GetThreadMessageComposer, GetThreadsMessageComposer, GetUnreadForumsCountMessageComposer, GetUserChatlogMessageComposer, GetUserEventCatsMessageComposer, GetUserFlatCatsMessageComposer, GetUserGameAchievementsMessageComposer, GetUserSongDisksMessageComposer, GetUserTagsComposer, GetWardrobeMessageComposer, GetWeeklyGameRewardComposer, GetWeeklyGameRewardWinnersComposer, GetYoutubeDisplayStatusMessageComposer, GiftReceiverNotFoundEvent, GiftWrappingConfigurationEvent, GoToFlatMessageComposer, GotMysteryBoxPrizeMessageEvent, GroupAdminGiveComposer, GroupAdminTakeComposer, GroupBadgePartsComposer, GroupBadgePartsEvent, GroupBuyComposer, GroupBuyDataComposer, GroupBuyDataEvent, GroupConfirmMemberRemoveEvent, GroupConfirmRemoveMemberComposer, GroupDeleteComposer, GroupDetailsChangedMessageEvent, GroupFavoriteComposer, GroupFurniContextMenuInfoMessageEvent, GroupInformationComposer, GroupInformationEvent, GroupJoinComposer, GroupMembersComposer, GroupMembersEvent, GroupMembershipAcceptComposer, GroupMembershipDeclineComposer, GroupMembershipRequestedMessageEvent, GroupPurchasedEvent, GroupRemoveMemberComposer, GroupSaveBadgeComposer, GroupSaveColorsComposer, GroupSaveInformationComposer, GroupSavePreferencesComposer, GroupSettingsComposer, GroupSettingsEvent, GroupUnfavoriteComposer, GuestRoomSearchResultEvent, GuideOnDutyStatusMessageEvent, GuideReportingStatusMessageEvent, GuideSessionAttachedMessageEvent, GuideSessionCreateMessageComposer, GuideSessionDetachedMessageEvent, GuideSessionEndedMessageEvent, GuideSessionErrorMessageEvent, GuideSessionFeedbackMessageComposer, GuideSessionGetRequesterRoomMessageComposer, GuideSessionGuideDecidesMessageComposer, GuideSessionInviteRequesterMessageComposer, GuideSessionInvitedToGuideRoomMessageEvent, GuideSessionIsTypingMessageComposer, GuideSessionMessageMessageComposer, GuideSessionMessageMessageEvent, GuideSessionOnDutyUpdateMessageComposer, GuideSessionPartnerIsTypingMessageEvent, GuideSessionReportMessageComposer, GuideSessionRequesterCancelsMessageComposer, GuideSessionRequesterRoomMessageEvent, GuideSessionResolvedMessageComposer, GuideSessionStartedMessageEvent, GuideTicketCreationResultMessageEvent, GuideTicketResolutionMessageEvent, GuildBaseSearchMessageComposer, GuildEditFailedMessageEvent, GuildForumThreadsEvent, GuildMemberMgmtFailedMessageEvent, GuildMembershipsMessageEvent, HabboBroadcastMessageEvent, HabboClubExtendOfferMessageEvent, HabboClubOffersMessageEvent, HabboGroupBadgesMessageEvent, HabboGroupDeactivatedMessageEvent, HabboGroupJoinFailedMessageEvent, HabboSearchComposer, HabboSearchResultEvent, HarvestPetMessageComposer, HotelClosedAndOpensEvent, HotelClosesAndWillOpenAtEvent, HotelMergeNameChangeEvent, HotelWillCloseInMinutesEvent, IdentityAccountsEvent, IgnoreResultEvent, IgnoreUserComposer, IgnoreUserIdComposer, IgnoredUsersEvent, InClientLinkEvent, IncomingHeader, InfoFeedEnableMessageEvent, InfoRetrieveMessageComposer, InitCameraMessageEvent, InitDiffieHandshakeEvent, InitDiffieHandshakeMessageComposer, InstantMessageErrorEvent, InterstitialMessageEvent, InterstitialShownMessageComposer, IsBadgeRequestFulfilledEvent, IsOfferGiftableMessageEvent, IsUserPartOfCompetitionMessageEvent, IssueCloseNotificationMessageEvent, IssueDeletedMessageEvent, IssueInfoMessageEvent, IssuePickFailedMessageEvent, ItemDataUpdateMessageEvent, JoinQueueMessageComposer, JoinedQueueMessageEvent, JoiningQueueFailedMessageEvent, JukeboxPlayListFullMessageEvent, JukeboxSongDisksMessageEvent, LagWarningReportMessageComposer, LeaveQueueMessageComposer, LeftQueueMessageEvent, LimitedEditionSoldOutEvent, LimitedOfferAppearingNextMessageEvent, LoadGameMessageEvent, LoadGameUrlEvent, LoveLockFurniFinishedEvent, LoveLockFurniFriendConfirmedEvent, LoveLockFurniStartEvent, MOTDNotificationEvent, MaintenanceStatusMessageEvent, MakeOfferMessageComposer, MarkCatalogNewAdditionsPageOpenedComposer, MarketPlaceOffersEvent, MarketplaceBuyOfferResultEvent, MarketplaceCanMakeOfferResult, MarketplaceCancelOfferResultEvent, MarketplaceConfigurationEvent, MarketplaceItemStatsEvent, MarketplaceMakeOfferResult, MarketplaceOwnOffersEvent, MessageErrorEvent, MessengerInitComposer, MessengerInitEvent, MiniMailNewMessageEvent, MiniMailUnreadCountEvent, ModAlertMessageComposer, ModBanMessageComposer, ModKickMessageComposer, ModMessageMessageComposer, ModMuteMessageComposer, ModToolPreferencesComposer, ModToolSanctionComposer, ModTradingLockMessageComposer, ModerateMessageMessageComposer, ModerateRoomMessageComposer, ModerateThreadMessageComposer, ModeratorActionMessageComposer, ModeratorActionResultMessageEvent, ModeratorCautionEvent, ModeratorInitMessageEvent, ModeratorMessageEvent, ModeratorRoomInfoEvent, ModeratorToolPreferencesEvent, ModeratorUserInfoEvent, MoodlightSettingsComposer, MoodlightSettingsSaveComposer, MoodlightTogggleStateComposer, MuteAllInRoomEvent, MyFavouriteRoomsSearchMessageComposer, MyFrequentRoomHistorySearchMessageComposer, MyFriendsRoomsSearchMessageComposer, MyGuildBasesSearchMessageComposer, MyRecommendedRoomsMessageComposer, MyRoomHistorySearchMessageComposer, MyRoomRightsSearchMessageComposer, MyRoomsSearchMessageComposer, MysteryBoxKeysEvent, MysteryBoxWaitingCanceledMessageComposer, NavigatorCategoryListModeComposer, NavigatorCollapsedEvent, NavigatorDeleteSavedSearchComposer, NavigatorHomeRoomEvent, NavigatorInitComposer, NavigatorLiftedEvent, NavigatorMetadataEvent, NavigatorOpenRoomCreatorEvent, NavigatorSearchCloseComposer, NavigatorSearchComposer, NavigatorSearchEvent, NavigatorSearchOpenComposer, NavigatorSearchSaveComposer, NavigatorSearchesEvent, NavigatorSettingsEvent, NavigatorSettingsSaveComposer, NewConsoleMessageEvent, NewFriendRequestEvent, NewUserExperienceGetGiftsComposer, NewUserExperienceGiftOfferMessageEvent, NewUserExperienceNotCompleteEvent, NewUserExperienceScriptProceedComposer, NoOwnedRoomsAlertMessageEvent, NoSuchFlatEvent, NoobnessLevelMessageEvent, NotEnoughBalanceMessageEvent, NotificationDialogMessageEvent, NowPlayingMessageEvent, ObjectsDataUpdateEvent, ObjectsRollingEvent, OfferRewardDeliveredMessageEvent, OfficialSongIdMessageEvent, OneWayDoorStatusMessageEvent, OpenCampaignCalendarDoorAsStaffComposer, OpenCampaignCalendarDoorComposer, OpenMessageComposer, OpenMysteryTrophyMessageComposer, OpenPetPackageMessageComposer, OpenPetPackageRequestedMessageEvent, OpenPetPackageResultMessageEvent, OpenPresentComposer, OpenQuestTrackerMessageComposer, OpenWelcomeGiftComposer, OutgoingHeader, PeerUsersClassificationMessageComposer, PerformanceLogMessageComposer, PerkAllowancesMessageEvent, PetAddedToInventoryEvent, PetBreedingResultEvent, PetExperienceEvent, PetFigureUpdateEvent, PetInfoEvent, PetInventoryEvent, PetLevelNotificationEvent, PetLevelUpdateMessageEvent, PetMountComposer, PetMoveComposer, PetPlaceComposer, PetPlacingErrorEvent, PetReceivedMessageEvent, PetRemoveComposer, PetRemovedFromInventory, PetRespectComposer, PetRespectNoficationEvent, PetScratchFailedMessageEvent, PetSelectedMessageComposer, PetStatusUpdateEvent, PetSupplementComposer, PetSupplementedNotificationEvent, PetTrainingPanelMessageEvent, PhoneCollectionStateMessageEvent, PhotoCompetitionMessageComposer, PickIssuesMessageComposer, PlayListMessageEvent, PlayListSongAddedMessageEvent, PollAnswerComposer, PollContentsEvent, PollErrorEvent, PollOfferEvent, PollRejectComposer, PollStartComposer, PongMessageComposer, PopularRoomTagsResultEvent, PopularRoomsSearchMessageComposer, PostMessageMessageComposer, PostMessageMessageEvent, PostQuizAnswersComposer, PostThreadMessageEvent, PresentOpenedMessageEvent, ProductOfferEvent, PromoArticlesMessageEvent, PublishPhotoMessageComposer, PurchaseBasicMembershipExtensionComposer, PurchaseErrorMessageEvent, PurchaseFromCatalogAsGiftComposer, PurchaseFromCatalogComposer, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, PurchasePhotoMessageComposer, PurchaseRoomAdMessageComposer, PurchaseTargetedOfferComposer, PurchaseVipMembershipExtensionComposer, QuestCancelledMessageEvent, QuestCompletedMessageEvent, QuestDailyMessageEvent, QuestMessageEvent, QuestionAnsweredEvent, QuestionEvent, QuestionFinishedEvent, QuestsMessageEvent, QuizDataMessageEvent, QuizResultsMessageEvent, RateFlatMessageComposer, RecycleItemsMessageComposer, RecyclerFinishedMessageEvent, RecyclerStatusMessageEvent, RedeemCommunityGoalPrizeMessageComposer, RedeemItemClothingComposer, RedeemMarketplaceOfferCreditsMessageComposer, RedeemVoucherMessageComposer, RejectQuestMessageComposer, RelationshipStatusInfoEvent, ReleaseIssuesMessageComposer, RemainingMuteEvent, RemoveAllRightsMessageComposer, RemoveFriendComposer, RemoveJukeboxDiskComposer, RemoveOwnRoomRightsRoomMessageComposer, RemovePetSaddleComposer, RemoveWallItemComposer, RenderRoomMessageComposer, RenderRoomThumbnailMessageComposer, RentableSpaceCancelRentMessageComposer, RentableSpaceRentFailedMessageEvent, RentableSpaceRentMessageComposer, RentableSpaceRentOkMessageEvent, RentableSpaceStatusMessageComposer, RentableSpaceStatusMessageEvent, RequestABadgeComposer, RequestAchievementsMessageComposer, RequestBadgesComposer, RequestBotCommandConfigurationComposer, RequestCameraConfigurationComposer, RequestFriendComposer, RequestFurniInventoryWhenNotInRoomComposer, RequestPetInfoComposer, RequestPetsComposer, RequestSpamWallPostItMessageEvent, ResetPhoneNumberStateMessageComposer, ResetResolutionAchievementMessageComposer, RespectReceivedEvent, RestoreClientMessageEvent, RoomAdErrorEvent, RoomAdEventTabAdClickedComposer, RoomAdEventTabViewedComposer, RoomAdPurchaseInfoEvent, RoomAdPurchaseInitiatedComposer, RoomAdSearchMessageComposer, RoomAmbassadorAlertComposer, RoomBanUserComposer, RoomBannedUsersComposer, RoomChatSettingsEvent, RoomChatlogEvent, RoomCompetitionInitMessageComposer, RoomDeleteComposer, RoomDimmerPresetsEvent, RoomDoorbellAcceptedEvent, RoomDoorbellAccessComposer, RoomEnterComposer, RoomEnterErrorEvent, RoomEnterEvent, RoomEntryInfoMessageEvent, RoomEntryTileMessageEvent, RoomEventCancelEvent, RoomEventEvent, RoomFilterSettingsMessageEvent, RoomForwardEvent, RoomGiveRightsComposer, RoomHeightMapEvent, RoomHeightMapUpdateEvent, RoomInviteErrorEvent, RoomInviteEvent, RoomKickUserComposer, RoomMessageNotificationMessageEvent, RoomMuteComposer, RoomMuteUserComposer, RoomNetworkOpenConnectionMessageComposer, RoomOccupiedTilesMessageEvent, RoomPaintEvent, RoomPollResultEvent, RoomReadyMessageEvent, RoomRightsClearEvent, RoomRightsEvent, RoomRightsOwnerEvent, RoomScoreEvent, RoomSettingsComposer, RoomSettingsDataEvent, RoomSettingsErrorEvent, RoomSettingsSaveErrorEvent, RoomSettingsSavedEvent, RoomSettingsUpdatedEvent, RoomTakeRightsComposer, RoomTextSearchMessageComposer, RoomThumbnailUpdateResultEvent, RoomUnbanUserComposer, RoomUnitActionComposer, RoomUnitBackgroundComposer, RoomUnitChatComposer, RoomUnitChatEvent, RoomUnitChatShoutComposer, RoomUnitChatShoutEvent, RoomUnitChatStyleComposer, RoomUnitChatWhisperComposer, RoomUnitChatWhisperEvent, RoomUnitDanceComposer, RoomUnitDanceEvent, RoomUnitDropHandItemComposer, RoomUnitEffectEvent, RoomUnitEvent, RoomUnitExpressionEvent, RoomUnitGiveHandItemComposer, RoomUnitGiveHandItemPetComposer, RoomUnitHandItemEvent, RoomUnitHandItemReceivedEvent, RoomUnitIdleEvent, RoomUnitInfoEvent, RoomUnitLookComposer, RoomUnitNumberEvent, RoomUnitPostureComposer, RoomUnitRemoveEvent, RoomUnitSignComposer, RoomUnitStatusEvent, RoomUnitTypingEvent, RoomUnitTypingStartComposer, RoomUnitTypingStopComposer, RoomUnitWalkComposer, RoomUsersClassificationMessageComposer, RoomUsersWithRightsComposer, RoomVisitsEvent, RoomVisualizationSettingsEvent, RoomsWhereMyFriendsAreSearchMessageComposer, RoomsWithHighestScoreSearchMessageComposer, SSOTicketMessageComposer, SanctionStatusEvent, SaveRoomSettingsComposer, SaveWardrobeOutfitMessageComposer, ScrGetKickbackInfoMessageComposer, ScrSendKickbackInfoMessageEvent, SearchFaqsMessageComposer, SeasonalCalendarDailyOfferMessageEvent, SeasonalQuestsMessageEvent, SecondsUntilMessageEvent, SelectClubGiftComposer, SellablePetPalettesMessageEvent, SendMessageComposer, SendRoomInviteComposer, SetActivatedBadgesComposer, SetClothingChangeDataMessageComposer, SetItemDataMessageComposer, SetObjectDataMessageComposer, SetPhoneNumberVerificationStatusMessageComposer, SetRelationshipStatusComposer, SetRoomSessionTagsMessageComposer, SetTargetedOfferStateComposer, SetYoutubeDisplayPlaylistMessageComposer, ShopTargetedOfferViewedComposer, ShowEnforceRoomCategoryDialogEvent, ShowMysteryBoxWaitMessageEvent, SimpleAlertMessageEvent, StartCampaignMessageComposer, StartRoomPollEvent, SubmitRoomToCompetitionMessageComposer, TalentLevelUpEvent, TalentTrackComposer, TalentTrackLevelMessageEvent, TalentTrackMessageEvent, TargetedOfferEvent, TargetedOfferNotFoundEvent, ThreadMessagesMessageEvent, ThumbnailStatusMessageEvent, TogglePetBreedingComposer, TogglePetRidingComposer, ToggleStaffPickMessageComposer, TradingAcceptComposer, TradingAcceptEvent, TradingCancelComposer, TradingCloseComposer, TradingCloseEvent, TradingCompletedEvent, TradingConfirmationComposer, TradingConfirmationEvent, TradingListAddItemComposer, TradingListAddItemsComposer, TradingListItemEvent, TradingListItemRemoveComposer, TradingNoSuchItemEvent, TradingNotOpenEvent, TradingOpenComposer, TradingOpenEvent, TradingOpenFailedEvent, TradingOtherNotAllowedEvent, TradingUnacceptComposer, TradingYouAreNotAllowedEvent, TraxSongInfoMessageEvent, TryPhoneNumberMessageComposer, TryPhoneNumberResultMessageEvent, TryVerificationCodeResultMessageEvent, UnblockGroupMemberMessageComposer, UnignoreUserComposer, UniqueIDMessageComposer, UnloadGameMessageEvent, UnreadForumsCountMessageEvent, UnseenItemsEvent, UnseenResetCategoryComposer, UnseenResetItemsComposer, UpdateActionMessageComposer, UpdateConditionMessageComposer, UpdateFloorPropertiesMessageComposer, UpdateForumReadMarkerMessageComposer, UpdateForumSettingsMessageComposer, UpdateFurniturePositionComposer, UpdateHomeRoomMessageComposer, UpdateMessageMessageEvent, UpdateRoomCategoryAndTradeSettingsComposer, UpdateRoomFilterMessageComposer, UpdateRoomThumbnailMessageComposer, UpdateThreadMessageComposer, UpdateThreadMessageEvent, UpdateTriggerMessageComposer, UsePetProductComposer, UserBannedMessageEvent, UserChatlogEvent, UserClassificationMessageEvent, UserCreditsEvent, UserCurrencyComposer, UserCurrencyEvent, UserCurrentBadgesComposer, UserCurrentBadgesEvent, UserEventCatsEvent, UserFigureComposer, UserFlatCatsEvent, UserGameAchievementsMessageEvent, UserInfoEvent, UserMottoComposer, UserNameChangeMessageEvent, UserPermissionsEvent, UserProfileComposer, UserProfileEvent, UserRelationshipsComposer, UserRespectComposer, UserSettingsCameraFollowComposer, UserSettingsEvent, UserSettingsOldChatComposer, UserSettingsRoomInvitesComposer, UserSettingsSoundComposer, UserSongDisksInventoryMessageEvent, UserSubscriptionComposer, UserSubscriptionEvent, UserTagsMessageEvent, UserUnbannedFromRoomEvent, UserWardrobePageEvent, VerifyCodeMessageComposer, VersionCheckMessageComposer, VisitUserComposer, VoteForRoomMessageComposer, VotePollCounterMessageComposer, VoucherRedeemErrorMessageEvent, VoucherRedeemOkMessageEvent, WardrobeMessageEvent, WeeklyCompetitiveFriendsLeaderboardEvent, WeeklyCompetitiveLeaderboardEvent, WeeklyGameRewardEvent, WeeklyGameRewardWinnersEvent, WelcomeGiftChangeEmailComposer, WelcomeGiftChangeEmailResultEvent, WelcomeGiftStatusEvent, WiredFurniActionEvent, WiredFurniConditionEvent, WiredFurniTriggerEvent, WiredOpenEvent, WiredRewardResultMessageEvent, WiredSaveSuccessEvent, WiredValidationErrorEvent, YouArePlayingGameEvent, YouAreSpectatorMessageEvent, YoutubeControlVideoMessageEvent, YoutubeDisplayPlaylistsEvent, YoutubeDisplayVideoMessageEvent } from './messages'; +import { AcceptFriendMessageComposer, AcceptFriendResultEvent, AcceptGameInviteMessageComposer, AcceptQuestMessageComposer, AccountSafetyLockStatusChangeMessageEvent, AchievementEvent, AchievementNotificationMessageEvent, AchievementResolutionCompletedMessageEvent, AchievementResolutionProgressMessageEvent, AchievementResolutionsMessageEvent, AchievementsEvent, AchievementsScoreEvent, ActivateQuestMessageComposer, ActivityPointNotificationMessageEvent, AddFavouriteRoomMessageComposer, AddJukeboxDiskComposer, AddSpamWallPostItMessageComposer, ApplySnapshotMessageComposer, ApplyTonerComposer, ApproveAllMembershipRequestsMessageComposer, ApproveNameMessageComposer, ApproveNameMessageEvent, AreaHideMessageEvent, AuthenticatedEvent, AuthenticationMessageComposer, AvailableCommandsEvent, AvailabilityStatusMessageEvent, AvailabilityTimeMessageEvent, AvatarEffectActivatedComposer, AvatarEffectActivatedEvent, AvatarEffectAddedEvent, AvatarEffectExpiredEvent, AvatarEffectSelectedComposer, AvatarEffectSelectedEvent, AvatarEffectsEvent, BadgePointLimitsEvent, BadgeReceivedEvent, BadgesEvent, BannedUsersFromRoomEvent, BonusRareInfoMessageEvent, BotAddedToInventoryEvent, BotCommandConfigurationEvent, BotErrorEvent, BotForceOpenContextMenuEvent, BotInventoryMessageEvent, BotPlaceComposer, BotReceivedMessageEvent, BotRemoveComposer, BotRemovedFromInventoryEvent, BotSkillListUpdateEvent, BotSkillSaveComposer, BreedPetsMessageComposer, BuildersClubFurniCountMessageEvent, BuildersClubPlaceRoomItemMessageComposer, BuildersClubPlaceWallItemMessageComposer, BuildersClubQueryFurniCountMessageComposer, BuildersClubSubscriptionStatusMessageEvent, BundleDiscountRulesetMessageEvent, BuyMarketplaceOfferMessageComposer, BuyMarketplaceTokensMessageComposer, CallForHelpDisabledNotifyMessageEvent, CallForHelpFromForumMessageMessageComposer, CallForHelpFromForumThreadMessageComposer, CallForHelpFromIMMessageComposer, CallForHelpFromPhotoMessageComposer, CallForHelpFromSelfieMessageComposer, CallForHelpMessageComposer, CallForHelpPendingCallsDeletedMessageEvent, CallForHelpPendingCallsMessageEvent, CallForHelpReplyMessageEvent, CallForHelpResultMessageEvent, CameraPublishStatusMessageEvent, CameraPurchaseOKMessageEvent, CameraSnapshotMessageEvent, CameraStorageUrlMessageEvent, CampaignCalendarDataMessageEvent, CampaignCalendarDoorOpenedMessageEvent, CanCreateRoomEvent, CanCreateRoomEventEvent, CanCreateRoomMessageComposer, CancelEventMessageComposer, CancelMarketplaceOfferMessageComposer, CancelMysteryBoxWaitMessageEvent, CancelPetBreedingComposer, CancelQuestMessageComposer, CatalogGroupsComposer, CatalogPageExpirationEvent, CatalogPageMessageEvent, CatalogPageWithEarliestExpiryMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, CategoriesWithVisitorCountEvent, CfhChatlogEvent, CfhSanctionMessageEvent, CfhTopicsInitEvent, ChangeEmailComposer, ChangeEmailResultEvent, ChangeQueueMessageComposer, ChangeUserNameMessageComposer, ChangeUserNameResultMessageEvent, ChatReviewGuideDecidesOnOfferMessageComposer, ChatReviewGuideDetachedMessageComposer, ChatReviewGuideVoteMessageComposer, ChatReviewSessionCreateMessageComposer, ChatReviewSessionDetachedMessageEvent, ChatReviewSessionOfferedToGuideMessageEvent, ChatReviewSessionResultsMessageEvent, ChatReviewSessionStartedMessageEvent, ChatReviewSessionVotingStatusMessageEvent, CheckUserNameMessageComposer, CheckUserNameResultMessageEvent, ClickFurniMessageComposer, ClientHelloMessageComposer, ClientPingEvent, CloseIssueDefaultActionMessageComposer, CloseIssuesMessageComposer, ClubGiftInfoEvent, ClubGiftNotificationEvent, ClubGiftSelectedEvent, CommunityGoalEarnedPrizesMessageEvent, CommunityGoalHallOfFameMessageEvent, CommunityGoalProgressMessageEvent, CommunityGoalVoteMessageComposer, CommunityGoalVoteMessageEvent, CompetitionEntrySubmitResultEvent, CompetitionRoomsDataMessageEvent, CompetitionRoomsSearchMessageComposer, CompetitionStatusMessageEvent, CompetitionVotingInfoMessageEvent, CompleteDiffieHandshakeEvent, CompleteDiffieHandshakeMessageComposer, CompostPlantMessageComposer, ConcurrentUsersGoalProgressMessageEvent, ConfirmPetBreedingComposer, ConnectionErrorEvent, ControlYoutubeDisplayPlaybackMessageComposer, ConvertGlobalRoomIdMessageComposer, ConvertedRoomIdEvent, CraftComposer, CraftSecretComposer, CraftableProductsEvent, CraftingRecipeEvent, CraftingRecipesAvailableEvent, CraftingResultEvent, CreateFlatMessageComposer, CurrentTimingCodeMessageEvent, CustomUserNotificationMessageEvent, DeclineFriendMessageComposer, DefaultSanctionMessageComposer, DeleteFavouriteRoomMessageComposer, DeleteItemMessageComposer, DeleteBadgeMessageComposer, DeletePetMessageComposer, DeletePendingCallsForHelpMessageComposer, DesktopViewComposer, DesktopViewEvent, DiceValueMessageEvent, DirectSMSClubBuyAvailableMessageEvent, DisconnectMessageComposer, DisconnectReasonEvent, DoorbellMessageEvent, EditEventMessageComposer, ElementPointerMessageEvent, EmailStatusResultEvent, EpicPopupMessageEvent, ExtendRentOrBuyoutFurniMessageComposer, ExtendRentOrBuyoutStripItemMessageComposer, ExtendedProfileChangedMessageEvent, FavoriteMembershipUpdateMessageEvent, FavouriteChangedEvent, FavouritesEvent, FigureSetIdsMessageEvent, FigureUpdateEvent, FindFriendsProcessResultEvent, FindNewFriendsMessageComposer, FireworkChargeDataEvent, FlatAccessDeniedMessageEvent, FlatControllerAddedEvent, FlatControllerRemovedEvent, FlatControllersEvent, FlatCreatedEvent, FloodControlEvent, FloorHeightMapEvent, FollowFriendFailedEvent, FollowFriendMessageComposer, ForumDataMessageEvent, ForumsListMessageEvent, ForwardToACompetitionRoomMessageComposer, ForwardToARandomPromotedRoomMessageComposer, ForwardToASubmittableRoomMessageComposer, ForwardToRandomCompetitionRoomMessageComposer, ForwardToSomeRoomMessageComposer, FriendFurniConfirmLockMessageComposer, FriendListFragmentEvent, FriendListUpdateComposer, FriendListUpdateEvent, FriendNotificationEvent, FriendRequestQuestCompleteMessageComposer, FriendRequestsEvent, FurniRentOrBuyoutOfferMessageEvent, FurnitureAliasesComposer, FurnitureAliasesEvent, FurnitureColorWheelComposer, FurnitureDataEvent, FurnitureDiceActivateComposer, FurnitureDiceDeactivateComposer, FurnitureExchangeComposer, FurnitureFloorAddEvent, FurnitureFloorEvent, FurnitureFloorRemoveEvent, FurnitureFloorUpdateComposer, FurnitureFloorUpdateEvent, FurnitureGroupInfoComposer, FurnitureListAddOrUpdateEvent, FurnitureListComposer, FurnitureListEvent, FurnitureListInvalidateEvent, FurnitureListRemovedEvent, FurnitureMannequinSaveLookComposer, FurnitureMannequinSaveNameComposer, FurnitureMultiStateComposer, FurnitureOneWayDoorComposer, FurniturePickupComposer, FurniturePickupAllComposer, FurniturePlaceComposer, FurniturePlacePaintComposer, FurniturePostItPlaceComposer, FurniturePostItPlacedEvent, FurnitureRandomStateComposer, FurnitureStackHeightComposer, FurnitureStackHeightEvent, FurnitureWallAddEvent, FurnitureWallEvent, FurnitureWallMultiStateComposer, FurnitureWallRemoveEvent, FurnitureWallUpdateComposer, FurnitureWallUpdateEvent, Game2AccountGameStatusMessageEvent, Game2CheckGameDirectoryStatusMessageComposer, Game2ExitGameMessageComposer, Game2GameChatMessageComposer, Game2GameDirectoryStatusMessageEvent, Game2GetAccountGameStatusMessageComposer, Game2GetWeeklyFriendsLeaderboardComposer, Game2GetWeeklyLeaderboardComposer, Game2InArenaQueueMessageEvent, Game2JoiningGameFailedMessageEvent, Game2LoadStageReadyMessageComposer, Game2PlayAgainMessageComposer, Game2RequestFullStatusUpdateMessageComposer, Game2StartingGameFailedMessageEvent, Game2StopCounterMessageEvent, Game2UserLeftGameMessageEvent, Game2WeeklyFriendsLeaderboardEvent, Game2WeeklyLeaderboardEvent, GameAchievementsMessageEvent, GameInviteMessageEvent, GameListMessageEvent, GameStatusMessageEvent, GameUnloadedMessageComposer, GenericErrorEvent, GetBadgePointLimitsComposer, GetBonusRareInfoMessageComposer, GetBotInventoryComposer, GetBundleDiscountRulesetComposer, GetCatalogIndexComposer, GetCatalogPageComposer, GetCatalogPageExpirationComposer, GetCatalogPageWithEarliestExpiryComposer, GetCategoriesWithUserCountMessageComposer, GetCfhChatlogMessageComposer, GetCfhStatusMessageComposer, GetClubGiftInfo, GetClubOffersMessageComposer, GetCommunityGoalEarnedPrizesMessageComposer, GetCommunityGoalHallOfFameMessageComposer, GetCommunityGoalProgressMessageComposer, GetConcurrentUsersGoalProgressMessageComposer, GetConcurrentUsersRewardMessageComposer, GetCraftableProductsComposer, GetCraftingRecipeComposer, GetCraftingRecipesAvailableComposer, GetCurrentTimingCodeMessageComposer, GetCustomRoomFilterMessageComposer, GetDailyQuestMessageComposer, GetDirectClubBuyAvailableComposer, GetEmailStatusComposer, GetExtendedProfileByNameMessageComposer, GetFaqCategoryMessageComposer, GetFaqTextMessageComposer, GetForumStatsMessageComposer, GetForumsListMessageComposer, GetFriendRequestsComposer, GetGameAchievementsMessageComposer, GetGameListMessageComposer, GetGameStatusMessageComposer, GetGiftMessageComposer, GetGiftWrappingConfigurationComposer, GetGuestRoomMessageComposer, GetGuestRoomResultEvent, GetGuideReportingStatusMessageComposer, GetHabboBasicMembershipExtendOfferComposer, GetHabboClubExtendOfferMessageComposer, GetHabboGroupBadgesMessageComposer, GetIgnoredUsersComposer, GetInterstitialMessageComposer, GetIsBadgeRequestFulfilledComposer, GetIsOfferGiftableComposer, GetIsUserPartOfCompetitionMessageComposer, GetItemDataComposer, GetJukeboxPlayListMessageComposer, GetLimitedOfferAppearingNextComposer, GetMarketplaceCanMakeOfferComposer, GetMarketplaceConfigurationMessageComposer, GetMarketplaceItemStatsComposer, GetMarketplaceOffersMessageComposer, GetMarketplaceOwnOffersMessageComposer, GetMessagesMessageComposer, GetModeratorRoomInfoMessageComposer, GetModeratorUserInfoMessageComposer, GetNextTargetedOfferComposer, GetNowPlayingMessageComposer, GetOccupiedTilesMessageComposer, GetOfficialRoomsMessageComposer, GetOfficialSongIdMessageComposer, GetPendingCallsForHelpMessageComposer, GetPetCommandsComposer, GetPopularRoomTagsMessageComposer, GetProductOfferComposer, GetPromoArticlesComposer, GetQuestsMessageComposer, GetQuizQuestionsComposer, GetRecyclerStatusMessageComposer, GetRentOrBuyoutOfferMessageComposer, GetResolutionAchievementsMessageComposer, GetRoomAdPurchaseInfoComposer, GetRoomChatlogMessageComposer, GetRoomEntryDataMessageComposer, GetRoomEntryTileMessageComposer, GetRoomVisitsMessageComposer, GetSeasonalCalendarDailyOfferComposer, GetSeasonalQuestsOnlyMessageComposer, GetSecondsUntilMessageComposer, GetSellablePetPalettesComposer, GetSongInfoMessageComposer, GetSoundMachinePlayListMessageComposer, GetSoundSettingsComposer, GetTalentTrackLevelMessageComposer, GetTargetedOfferComposer, GetThreadMessageComposer, GetThreadsMessageComposer, GetUnreadForumsCountMessageComposer, GetUserChatlogMessageComposer, GetUserEventCatsMessageComposer, GetUserFlatCatsMessageComposer, GetUserGameAchievementsMessageComposer, GetUserSongDisksMessageComposer, GetUserTagsComposer, GetWardrobeMessageComposer, GetWeeklyGameRewardComposer, GetWeeklyGameRewardWinnersComposer, GetYoutubeDisplayStatusMessageComposer, GiftReceiverNotFoundEvent, GiftWrappingConfigurationEvent, GoToFlatMessageComposer, GotMysteryBoxPrizeMessageEvent, GroupAdminGiveComposer, GroupAdminTakeComposer, GroupBadgePartsComposer, GroupBadgePartsEvent, GroupBuyComposer, GroupBuyDataComposer, GroupBuyDataEvent, GroupConfirmMemberRemoveEvent, GroupConfirmRemoveMemberComposer, GroupDeleteComposer, GroupDetailsChangedMessageEvent, GroupFavoriteComposer, GroupFurniContextMenuInfoMessageEvent, GroupInformationComposer, GroupInformationEvent, GroupJoinComposer, GroupMembersComposer, GroupMembersEvent, GroupMembershipAcceptComposer, GroupMembershipDeclineComposer, GroupMembershipRequestedMessageEvent, GroupPurchasedEvent, GroupRemoveMemberComposer, GroupSaveBadgeComposer, GroupSaveColorsComposer, GroupSaveInformationComposer, GroupSavePreferencesComposer, GroupSettingsComposer, GroupSettingsEvent, GroupUnfavoriteComposer, GuestRoomSearchResultEvent, GuideOnDutyStatusMessageEvent, GuideReportingStatusMessageEvent, GuideSessionAttachedMessageEvent, GuideSessionCreateMessageComposer, GuideSessionDetachedMessageEvent, GuideSessionEndedMessageEvent, GuideSessionErrorMessageEvent, GuideSessionFeedbackMessageComposer, GuideSessionGetRequesterRoomMessageComposer, GuideSessionGuideDecidesMessageComposer, GuideSessionInviteRequesterMessageComposer, GuideSessionInvitedToGuideRoomMessageEvent, GuideSessionIsTypingMessageComposer, GuideSessionMessageMessageComposer, GuideSessionMessageMessageEvent, GuideSessionOnDutyUpdateMessageComposer, GuideSessionPartnerIsTypingMessageEvent, GuideSessionReportMessageComposer, GuideSessionRequesterCancelsMessageComposer, GuideSessionRequesterRoomMessageEvent, GuideSessionResolvedMessageComposer, GuideSessionStartedMessageEvent, GuideTicketCreationResultMessageEvent, GuideTicketResolutionMessageEvent, GuildBaseSearchMessageComposer, GuildEditFailedMessageEvent, GuildForumThreadsEvent, GuildMemberMgmtFailedMessageEvent, GuildMembershipsMessageEvent, HabboBroadcastMessageEvent, HabboClubExtendOfferMessageEvent, HabboClubOffersMessageEvent, HabboGroupBadgesMessageEvent, HabboGroupDeactivatedMessageEvent, HabboGroupJoinFailedMessageEvent, HabboSearchComposer, HabboSearchResultEvent, HarvestPetMessageComposer, HotelClosedAndOpensEvent, HotelClosesAndWillOpenAtEvent, HotelMergeNameChangeEvent, HotelWillCloseInMinutesEvent, IdentityAccountsEvent, IgnoreResultEvent, IgnoreUserComposer, IgnoreUserIdComposer, IgnoredUsersEvent, InClientLinkEvent, IncomingHeader, InfoFeedEnableMessageEvent, InfoRetrieveMessageComposer, InitCameraMessageEvent, InitDiffieHandshakeEvent, InitDiffieHandshakeMessageComposer, InstantMessageErrorEvent, InterstitialMessageEvent, InterstitialShownMessageComposer, IsBadgeRequestFulfilledEvent, IsOfferGiftableMessageEvent, IsUserPartOfCompetitionMessageEvent, IssueCloseNotificationMessageEvent, IssueDeletedMessageEvent, IssueInfoMessageEvent, IssuePickFailedMessageEvent, ItemDataUpdateMessageEvent, JoinQueueMessageComposer, JoinedQueueMessageEvent, JoiningQueueFailedMessageEvent, JukeboxPlayListFullMessageEvent, JukeboxSongDisksMessageEvent, LagWarningReportMessageComposer, LeaveQueueMessageComposer, LeftQueueMessageEvent, LimitedEditionSoldOutEvent, LimitedOfferAppearingNextMessageEvent, LoadGameMessageEvent, LoadGameUrlEvent, LoveLockFurniFinishedEvent, LoveLockFurniFriendConfirmedEvent, LoveLockFurniStartEvent, MOTDNotificationEvent, MaintenanceStatusMessageEvent, MakeOfferMessageComposer, MarkCatalogNewAdditionsPageOpenedComposer, MarketPlaceOffersEvent, MarketplaceBuyOfferResultEvent, MarketplaceCanMakeOfferResult, MarketplaceCancelOfferResultEvent, MarketplaceConfigurationEvent, MarketplaceItemStatsEvent, MarketplaceMakeOfferResult, MarketplaceOwnOffersEvent, MessageErrorEvent, MessengerInitComposer, MessengerInitEvent, MiniMailNewMessageEvent, MiniMailUnreadCountEvent, ModAlertMessageComposer, ModBanMessageComposer, ModKickMessageComposer, ModMessageMessageComposer, ModMuteMessageComposer, ModToolPreferencesComposer, ModToolSanctionComposer, ModTradingLockMessageComposer, ModerateMessageMessageComposer, ModerateRoomMessageComposer, ModerateThreadMessageComposer, ModeratorActionMessageComposer, ModeratorActionResultMessageEvent, ModeratorCautionEvent, ModeratorInitMessageEvent, ModeratorMessageEvent, ModeratorRoomInfoEvent, ModeratorToolPreferencesEvent, ModeratorUserInfoEvent, MoodlightSettingsComposer, MoodlightSettingsSaveComposer, MoodlightTogggleStateComposer, MuteAllInRoomEvent, MyFavouriteRoomsSearchMessageComposer, MyFrequentRoomHistorySearchMessageComposer, MyFriendsRoomsSearchMessageComposer, MyGuildBasesSearchMessageComposer, MyRecommendedRoomsMessageComposer, MyRoomHistorySearchMessageComposer, MyRoomRightsSearchMessageComposer, MyRoomsSearchMessageComposer, MysteryBoxKeysEvent, MysteryBoxWaitingCanceledMessageComposer, NavigatorCategoryListModeComposer, NavigatorCollapsedEvent, NavigatorDeleteSavedSearchComposer, NavigatorHomeRoomEvent, NavigatorInitComposer, NavigatorLiftedEvent, NavigatorMetadataEvent, NavigatorOpenRoomCreatorEvent, NavigatorSearchCloseComposer, NavigatorSearchComposer, NavigatorSearchEvent, NavigatorSearchOpenComposer, NavigatorSearchSaveComposer, NavigatorSearchesEvent, NavigatorSettingsEvent, NavigatorSettingsSaveComposer, NewConsoleMessageEvent, NewFriendRequestEvent, NewUserExperienceGetGiftsComposer, NewUserExperienceGiftOfferMessageEvent, NewUserExperienceNotCompleteEvent, NewUserExperienceScriptProceedComposer, NoOwnedRoomsAlertMessageEvent, NoSuchFlatEvent, NoobnessLevelMessageEvent, NotEnoughBalanceMessageEvent, NotificationDialogMessageEvent, NowPlayingMessageEvent, ObjectsDataUpdateEvent, ObjectsRollingEvent, OfferRewardDeliveredMessageEvent, OfficialSongIdMessageEvent, OneWayDoorStatusMessageEvent, OpenCampaignCalendarDoorAsStaffComposer, OpenCampaignCalendarDoorComposer, OpenMessageComposer, OpenMysteryTrophyMessageComposer, OpenPetPackageMessageComposer, OpenPetPackageRequestedMessageEvent, OpenPetPackageResultMessageEvent, OpenPresentComposer, OpenQuestTrackerMessageComposer, OpenWelcomeGiftComposer, OutgoingHeader, PeerUsersClassificationMessageComposer, PerformanceLogMessageComposer, PerkAllowancesMessageEvent, PetAddedToInventoryEvent, PetBreedingResultEvent, PetExperienceEvent, PetFigureUpdateEvent, PetInfoEvent, PetInventoryEvent, PetLevelNotificationEvent, PetLevelUpdateMessageEvent, PetMountComposer, PetMoveComposer, PetPlaceComposer, PetPlacingErrorEvent, PetReceivedMessageEvent, PetRemoveComposer, PetRemovedFromInventory, PetRespectComposer, PetRespectNoficationEvent, PetScratchFailedMessageEvent, PetSelectedMessageComposer, PetStatusUpdateEvent, PetSupplementComposer, PetSupplementedNotificationEvent, PetTrainingPanelMessageEvent, PhoneCollectionStateMessageEvent, PhotoCompetitionMessageComposer, PickIssuesMessageComposer, PlayListMessageEvent, PlayListSongAddedMessageEvent, PollAnswerComposer, PollContentsEvent, PollErrorEvent, PollOfferEvent, PollRejectComposer, PollStartComposer, PongMessageComposer, PopularRoomTagsResultEvent, PopularRoomsSearchMessageComposer, PostMessageMessageComposer, PostMessageMessageEvent, PostQuizAnswersComposer, PostThreadMessageEvent, PresentOpenedMessageEvent, ProductOfferEvent, PromoArticlesMessageEvent, PublishPhotoMessageComposer, PurchaseBasicMembershipExtensionComposer, PurchaseErrorMessageEvent, PurchaseFromCatalogAsGiftComposer, PurchaseFromCatalogComposer, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, PurchasePhotoMessageComposer, PurchaseRoomAdMessageComposer, PurchaseTargetedOfferComposer, PurchaseVipMembershipExtensionComposer, QuestCancelledMessageEvent, QuestCompletedMessageEvent, QuestDailyMessageEvent, QuestMessageEvent, QuestionAnsweredEvent, QuestionEvent, QuestionFinishedEvent, QuestsMessageEvent, QuizDataMessageEvent, QuizResultsMessageEvent, RateFlatMessageComposer, RecycleItemsMessageComposer, RecyclerFinishedMessageEvent, RecyclerStatusMessageEvent, RedeemCommunityGoalPrizeMessageComposer, RedeemItemClothingComposer, RedeemMarketplaceOfferCreditsMessageComposer, RedeemVoucherMessageComposer, RejectQuestMessageComposer, RelationshipStatusInfoEvent, ReleaseIssuesMessageComposer, RemainingMuteEvent, RemoveAllRightsMessageComposer, RemoveFriendComposer, RemoveJukeboxDiskComposer, RemoveOwnRoomRightsRoomMessageComposer, RemovePetSaddleComposer, RemoveWallItemComposer, RenderRoomMessageComposer, RenderRoomThumbnailMessageComposer, RentableSpaceCancelRentMessageComposer, RentableSpaceRentFailedMessageEvent, RentableSpaceRentMessageComposer, RentableSpaceRentOkMessageEvent, RentableSpaceStatusMessageComposer, RentableSpaceStatusMessageEvent, RequestABadgeComposer, RequestAchievementsMessageComposer, RequestBadgesComposer, RequestBotCommandConfigurationComposer, RequestCameraConfigurationComposer, RequestFriendComposer, RequestFurniInventoryWhenNotInRoomComposer, RequestPetInfoComposer, RequestPetsComposer, RequestSpamWallPostItMessageEvent, ResetPhoneNumberStateMessageComposer, ResetResolutionAchievementMessageComposer, RespectReceivedEvent, RestoreClientMessageEvent, RoomAdErrorEvent, RoomAdEventTabAdClickedComposer, RoomAdEventTabViewedComposer, RoomAdPurchaseInfoEvent, RoomAdPurchaseInitiatedComposer, RoomAdSearchMessageComposer, RoomAmbassadorAlertComposer, RoomBanUserComposer, RoomBannedUsersComposer, RoomChatSettingsEvent, RoomChatlogEvent, RoomCompetitionInitMessageComposer, RoomDeleteComposer, RoomDimmerPresetsEvent, RoomDoorbellAcceptedEvent, RoomDoorbellAccessComposer, RoomEnterComposer, RoomEnterErrorEvent, RoomEnterEvent, RoomEntryInfoMessageEvent, RoomEntryTileMessageEvent, RoomEventCancelEvent, RoomEventEvent, RoomFilterSettingsMessageEvent, RoomForwardEvent, RoomGiveRightsComposer, RoomHeightMapEvent, RoomHeightMapUpdateEvent, RoomInviteErrorEvent, RoomInviteEvent, RoomKickUserComposer, RoomMessageNotificationMessageEvent, RoomMuteComposer, RoomMuteUserComposer, RoomNetworkOpenConnectionMessageComposer, RoomOccupiedTilesMessageEvent, RoomPaintEvent, RoomPollResultEvent, RoomReadyMessageEvent, RoomRightsClearEvent, RoomRightsEvent, RoomRightsOwnerEvent, RoomScoreEvent, RoomSettingsComposer, RoomSettingsDataEvent, RoomSettingsErrorEvent, RoomSettingsSaveErrorEvent, RoomSettingsSavedEvent, RoomSettingsUpdatedEvent, RoomTakeRightsComposer, RoomTextSearchMessageComposer, RoomThumbnailUpdateResultEvent, RoomUnbanUserComposer, RoomUnitActionComposer, RoomUnitBackgroundComposer, RoomUnitChatComposer, RoomUnitChatEvent, RoomUnitChatShoutComposer, RoomUnitChatShoutEvent, RoomUnitChatStyleComposer, RoomUnitChatWhisperComposer, RoomUnitChatWhisperEvent, RoomUnitDanceComposer, RoomUnitDanceEvent, RoomUnitDropHandItemComposer, RoomUnitEffectEvent, RoomUnitEvent, RoomUnitExpressionEvent, RoomUnitGiveHandItemComposer, RoomUnitGiveHandItemPetComposer, RoomUnitHandItemEvent, RoomUnitHandItemReceivedEvent, RoomUnitIdleEvent, RoomUnitInfoEvent, RoomUnitLookComposer, RoomUnitNumberEvent, RoomUnitPostureComposer, RoomUnitRemoveEvent, RoomUnitSignComposer, RoomUnitStatusEvent, RoomUnitTypingEvent, RoomUnitTypingStartComposer, RoomUnitTypingStopComposer, RoomUnitWalkComposer, RoomUsersClassificationMessageComposer, RoomUsersWithRightsComposer, RoomVisitsEvent, RoomVisualizationSettingsEvent, RoomsWhereMyFriendsAreSearchMessageComposer, RoomsWithHighestScoreSearchMessageComposer, SSOTicketMessageComposer, SanctionStatusEvent, SaveRoomSettingsComposer, SaveWardrobeOutfitMessageComposer, ScrGetKickbackInfoMessageComposer, ScrSendKickbackInfoMessageEvent, SearchFaqsMessageComposer, SeasonalCalendarDailyOfferMessageEvent, SeasonalQuestsMessageEvent, SecondsUntilMessageEvent, SelectClubGiftComposer, SellablePetPalettesMessageEvent, SendMessageComposer, SendRoomInviteComposer, SetActivatedBadgesComposer, SetClothingChangeDataMessageComposer, SetItemDataMessageComposer, SetObjectDataMessageComposer, SetPhoneNumberVerificationStatusMessageComposer, SetRelationshipStatusComposer, SetRoomSessionTagsMessageComposer, SetTargetedOfferStateComposer, SetYoutubeDisplayPlaylistMessageComposer, ShopTargetedOfferViewedComposer, ShowEnforceRoomCategoryDialogEvent, ShowMysteryBoxWaitMessageEvent, SimpleAlertMessageEvent, StartCampaignMessageComposer, StartRoomPollEvent, SubmitRoomToCompetitionMessageComposer, TalentLevelUpEvent, TalentTrackComposer, TalentTrackLevelMessageEvent, TalentTrackMessageEvent, TargetedOfferEvent, TargetedOfferNotFoundEvent, ThreadMessagesMessageEvent, ThumbnailStatusMessageEvent, TogglePetBreedingComposer, TogglePetRidingComposer, ToggleStaffPickMessageComposer, TradingAcceptComposer, TradingAcceptEvent, TradingCancelComposer, TradingCloseComposer, TradingCloseEvent, TradingCompletedEvent, TradingConfirmationComposer, TradingConfirmationEvent, TradingListAddItemComposer, TradingListAddItemsComposer, TradingListItemEvent, TradingListItemRemoveComposer, TradingNoSuchItemEvent, TradingNotOpenEvent, TradingOpenComposer, TradingOpenEvent, TradingOpenFailedEvent, TradingOtherNotAllowedEvent, TradingUnacceptComposer, TradingYouAreNotAllowedEvent, TraxSongInfoMessageEvent, TryPhoneNumberMessageComposer, TryPhoneNumberResultMessageEvent, TryVerificationCodeResultMessageEvent, UnblockGroupMemberMessageComposer, UnignoreUserComposer, UniqueIDMessageComposer, UnloadGameMessageEvent, UnreadForumsCountMessageEvent, UnseenItemsEvent, UnseenResetCategoryComposer, UnseenResetItemsComposer, UpdateActionMessageComposer, UpdateConditionMessageComposer, UpdateFloorPropertiesMessageComposer, UpdateForumReadMarkerMessageComposer, UpdateForumSettingsMessageComposer, UpdateFurniturePositionComposer, UpdateHomeRoomMessageComposer, UpdateMessageMessageEvent, UpdateRoomCategoryAndTradeSettingsComposer, UpdateRoomFilterMessageComposer, UpdateRoomThumbnailMessageComposer, UpdateThreadMessageComposer, UpdateThreadMessageEvent, UpdateTriggerMessageComposer, UsePetProductComposer, UserBannedMessageEvent, UserChatlogEvent, UserClassificationMessageEvent, UserCreditsEvent, UserCurrencyComposer, UserCurrencyEvent, UserCurrentBadgesComposer, UserCurrentBadgesEvent, UserEventCatsEvent, UserFigureComposer, UserFlatCatsEvent, UserGameAchievementsMessageEvent, UserInfoEvent, UserMottoComposer, UserNameChangeMessageEvent, UserPermissionsEvent, UserProfileComposer, UserProfileEvent, UserRelationshipsComposer, UserRespectComposer, UserSettingsCameraFollowComposer, UserSettingsEvent, UserSettingsOldChatComposer, UserSettingsRoomInvitesComposer, UserSettingsSoundComposer, UserSongDisksInventoryMessageEvent, UserSubscriptionComposer, UserSubscriptionEvent, UserTagsMessageEvent, UserUnbannedFromRoomEvent, UserWardrobePageEvent, VerifyCodeMessageComposer, VersionCheckMessageComposer, VisitUserComposer, VoteForRoomMessageComposer, VotePollCounterMessageComposer, VoucherRedeemErrorMessageEvent, VoucherRedeemOkMessageEvent, WardrobeMessageEvent, WeeklyCompetitiveFriendsLeaderboardEvent, WeeklyCompetitiveLeaderboardEvent, WeeklyGameRewardEvent, WeeklyGameRewardWinnersEvent, WelcomeGiftChangeEmailComposer, WelcomeGiftChangeEmailResultEvent, WelcomeGiftStatusEvent, WiredFurniActionEvent, WiredFurniConditionEvent, WiredFurniTriggerEvent, WiredOpenEvent, WiredRewardResultMessageEvent, WiredSaveSuccessEvent, WiredValidationErrorEvent, YouArePlayingGameEvent, YouAreSpectatorMessageEvent, YoutubeControlVideoMessageEvent, YoutubeDisplayPlaylistsEvent, YoutubeDisplayVideoMessageEvent } from './messages'; export class NitroMessages implements IMessageConfiguration { @@ -93,6 +93,9 @@ export class NitroMessages implements IMessageConfiguration this._events.set(IncomingHeader.TARGET_OFFER_NOT_FOUND, TargetedOfferNotFoundEvent); this._events.set(IncomingHeader.REDEEM_VOUCHER_ERROR, VoucherRedeemErrorMessageEvent); this._events.set(IncomingHeader.REDEEM_VOUCHER_OK, VoucherRedeemOkMessageEvent); + + // COMMANDS + this._events.set(IncomingHeader.AVAILABLE_COMMANDS, AvailableCommandsEvent); // CLIENT this._events.set(IncomingHeader.CLIENT_PING, ClientPingEvent); diff --git a/packages/communication/src/index.ts b/packages/communication/src/index.ts index 5f56f6c..5553756 100644 --- a/packages/communication/src/index.ts +++ b/packages/communication/src/index.ts @@ -15,6 +15,7 @@ export * from './messages/incoming/camera'; export * from './messages/incoming/campaign'; export * from './messages/incoming/catalog'; export * from './messages/incoming/client'; +export * from './messages/incoming/commands'; export * from './messages/incoming/competition'; export * from './messages/incoming/crafting'; export * from './messages/incoming/desktop'; @@ -167,6 +168,7 @@ export * from './messages/parser/camera'; export * from './messages/parser/campaign'; export * from './messages/parser/catalog'; export * from './messages/parser/client'; +export * from './messages/parser/commands'; export * from './messages/parser/competition'; export * from './messages/parser/crafting'; export * from './messages/parser/desktop'; diff --git a/packages/communication/src/messages/incoming/IncomingHeader.ts b/packages/communication/src/messages/incoming/IncomingHeader.ts index 5d7f733..59d3879 100644 --- a/packages/communication/src/messages/incoming/IncomingHeader.ts +++ b/packages/communication/src/messages/incoming/IncomingHeader.ts @@ -7,6 +7,7 @@ export class IncomingHeader public static ACHIEVEMENT_LIST = 305; public static AUTHENTICATED = 2491; public static AUTHENTICATION = -1; + public static AVAILABLE_COMMANDS = 4050; public static AVAILABILITY_STATUS = 2033; public static BUILDERS_CLUB_EXPIRED = 1452; public static CLUB_OFFERS = 2405; diff --git a/packages/communication/src/messages/incoming/commands/AvailableCommandsEvent.ts b/packages/communication/src/messages/incoming/commands/AvailableCommandsEvent.ts new file mode 100644 index 0000000..0cfd3af --- /dev/null +++ b/packages/communication/src/messages/incoming/commands/AvailableCommandsEvent.ts @@ -0,0 +1,16 @@ +import { IMessageEvent } from '@nitrots/api'; +import { MessageEvent } from '@nitrots/events'; +import { AvailableCommandsParser } from '../../parser'; + +export class AvailableCommandsEvent extends MessageEvent implements IMessageEvent +{ + constructor(callBack: Function) + { + super(callBack, AvailableCommandsParser); + } + + public getParser(): AvailableCommandsParser + { + return this.parser as AvailableCommandsParser; + } +} \ No newline at end of file diff --git a/packages/communication/src/messages/incoming/commands/index.ts b/packages/communication/src/messages/incoming/commands/index.ts new file mode 100644 index 0000000..acc402d --- /dev/null +++ b/packages/communication/src/messages/incoming/commands/index.ts @@ -0,0 +1 @@ +export * from './AvailableCommandsEvent'; \ No newline at end of file diff --git a/packages/communication/src/messages/incoming/index.ts b/packages/communication/src/messages/incoming/index.ts index a247dbc..b9b0d3d 100644 --- a/packages/communication/src/messages/incoming/index.ts +++ b/packages/communication/src/messages/incoming/index.ts @@ -8,6 +8,7 @@ export * from './camera'; export * from './campaign'; export * from './catalog'; export * from './client'; +export * from './commands'; export * from './competition'; export * from './crafting'; export * from './desktop'; diff --git a/packages/communication/src/messages/parser/commands/AvailableCommandsParser.ts b/packages/communication/src/messages/parser/commands/AvailableCommandsParser.ts new file mode 100644 index 0000000..5ecb3ca --- /dev/null +++ b/packages/communication/src/messages/parser/commands/AvailableCommandsParser.ts @@ -0,0 +1,37 @@ +import { IMessageDataWrapper, IMessageParser } from '@nitrots/api'; + +export class AvailableCommandsParser implements IMessageParser +{ + private _commands: { key: string; description: string }[]; + + public flush(): boolean + { + this._commands = []; + + return true; + } + + public parse(wrapper: IMessageDataWrapper): boolean + { + if(!wrapper) return false; + + this._commands = []; + + const count = wrapper.readInt(); + + for(let i = 0; i < count; i++) + { + this._commands.push({ + key: wrapper.readString(), + description: wrapper.readString() + }); + } + + return true; + } + + public get commands(): { key: string; description: string }[] + { + return this._commands; + } +} \ No newline at end of file diff --git a/packages/communication/src/messages/parser/commands/index.ts b/packages/communication/src/messages/parser/commands/index.ts new file mode 100644 index 0000000..aa0f4c9 --- /dev/null +++ b/packages/communication/src/messages/parser/commands/index.ts @@ -0,0 +1 @@ +export * from './AvailableCommandsParser'; \ No newline at end of file diff --git a/packages/communication/src/messages/parser/index.ts b/packages/communication/src/messages/parser/index.ts index b807dc4..c1b9bc9 100644 --- a/packages/communication/src/messages/parser/index.ts +++ b/packages/communication/src/messages/parser/index.ts @@ -7,6 +7,7 @@ export * from './camera'; export * from './campaign'; export * from './catalog'; export * from './client'; +export * from './commands'; export * from './competition'; export * from './crafting'; export * from './desktop';