diff --git a/.browserslistrc b/.browserslistrc
new file mode 100644
index 00000000..0ccadaf3
--- /dev/null
+++ b/.browserslistrc
@@ -0,0 +1,18 @@
+# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
+# For additional information regarding the format and rule options, please see:
+# https://github.com/browserslist/browserslist#queries
+
+# For the full list of supported browsers by the Angular framework, please see:
+# https://angular.io/guide/browser-support
+
+# You can see what browsers were selected by your queries by running:
+# npx browserslist
+
+last 1 Chrome version
+last 1 Firefox version
+last 2 Edge major versions
+last 2 Safari major versions
+last 2 iOS major versions
+Firefox ESR
+not IE 9-10 # Angular support for IE 9-10 has been deprecated and will be removed as of Angular v11. To opt-in, remove the 'not' prefix on this line.
+not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..07926923
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,16 @@
+# Editor configuration, see https://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 4
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.ts]
+quote_type = single
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 00000000..75a1859d
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,132 @@
+{
+ "env": {
+ "browser": true,
+ "es2021": true,
+ "node": true
+ },
+ "extends": [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "parser": "@typescript-eslint/parser",
+ "parserOptions": {
+ "ecmaVersion": 12,
+ "sourceType": "module"
+ },
+ "plugins": [
+ "@typescript-eslint"
+ ],
+ "rules": {
+ "indent": [
+ "error",
+ 4,
+ {
+ "SwitchCase": 1
+ }
+ ],
+ "no-trailing-spaces": [
+ "error",
+ {
+ "skipBlankLines": false,
+ "ignoreComments": true
+ }
+ ],
+ "linebreak-style": [
+ "off"
+ ],
+ "quotes": [
+ "error",
+ "single"
+ ],
+ "semi": [
+ "error",
+ "always"
+ ],
+ "brace-style": [
+ "error",
+ "allman"
+ ],
+ "object-curly-spacing": [
+ "error",
+ "always"
+ ],
+ "keyword-spacing": [
+ "error",
+ {
+ "overrides":
+ {
+ "if":
+ {
+ "after": false
+ },
+ "for":
+ {
+ "after": false
+ },
+ "while":
+ {
+ "after": false
+ },
+ "switch":
+ {
+ "after": false
+ }
+ }
+ }
+ ],
+ "@typescript-eslint/no-explicit-any": [
+ "off"
+ ],
+ "@typescript-eslint/explicit-module-boundary-types": [
+ "off",
+ {
+ "allowedNames": [
+ "getMessageArray"
+ ]
+ }
+ ],
+ "@typescript-eslint/ban-ts-comment": [
+ "off"
+ ],
+ "@typescript-eslint/no-empty-function": [
+ "error",
+ {
+ "allow": [
+ "functions",
+ "arrowFunctions",
+ "generatorFunctions",
+ "methods",
+ "generatorMethods",
+ "constructors"
+ ]
+ }
+ ],
+ "@typescript-eslint/no-unused-vars": [
+ "off"
+ ],
+ "@typescript-eslint/no-inferrable-types": [
+ "error",
+ {
+ "ignoreParameters": true,
+ "ignoreProperties": true
+ }
+ ],
+ "@typescript-eslint/ban-types": [
+ "error",
+ {
+ "types":
+ {
+ "String": true,
+ "Boolean": true,
+ "Number": true,
+ "Symbol": true,
+ "{}": false,
+ "Object": false,
+ "object": false,
+ "Function": false
+ },
+ "extendDefaults": true
+ }
+ ]
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..1413af91
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,51 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+
+# compiled output
+/dist
+/tmp
+/out-tsc
+# Only exists if Bazel was run
+/bazel-out
+
+# dependencies
+/node_modules
+
+# profiling files
+chrome-profiler-events*.json
+speed-measure-plugin*.json
+
+# IDEs and editors
+/.idea
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+
+# IDE - VSCode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+.history/*
+
+# misc
+/.sass-cache
+/connect.lock
+/coverage
+/libpeerconnection.log
+npm-debug.log
+yarn-error.log
+testem.log
+/typings
+.git
+
+# System Files
+.DS_Store
+Thumbs.db
+
+*.zip
+*.as
+*.bin
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 00000000..7072af81
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,30 @@
+image: node:15.6
+
+stages:
+ - test
+ - build
+
+
+ESLinter:
+ stage: test
+ script:
+ - npm i
+ - node ./node_modules/eslint/bin/eslint.js src/
+ cache:
+ key: ${CI_COMMIT_BRANCH}
+ paths:
+ - node_modules
+
+Build Nitro:
+ stage: build
+ script:
+ - npm i
+ - npm run build-prod
+ cache:
+ key: ${CI_COMMIT_BRANCH}
+ paths:
+ - node_modules
+ artifacts:
+ expire_in: 2 weeks
+ paths:
+ - dist/*
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 00000000..7b328b85
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,16 @@
+{
+ "typescript.tsdk": "node_modules\\typescript\\lib",
+ "typescript.preferences.importModuleSpecifier": "relative",
+ "typescript.preferences.quoteStyle": "single",
+ "typescript.format.placeOpenBraceOnNewLineForControlBlocks": true,
+ "typescript.format.placeOpenBraceOnNewLineForFunctions": true,
+ "editor.codeActionsOnSave": {
+ "source.fixAll": true,
+ "source.organizeImports": true,
+ },
+ "emmet.showExpandedAbbreviation": "never",
+ "git.ignoreLimitWarning": true,
+ "files.eol": "\n",
+ "files.insertFinalNewline": true,
+ "files.trimFinalNewlines": true
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..f288702d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/index.ts b/index.ts
new file mode 100644
index 00000000..8420b109
--- /dev/null
+++ b/index.ts
@@ -0,0 +1 @@
+export * from './src';
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..2ea7846f
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,1747 @@
+{
+ "name": "nitro-renderer",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.12.11",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
+ "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.12.11",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
+ "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.13.10",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz",
+ "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.12.11",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ }
+ }
+ },
+ "@eslint/eslintrc": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz",
+ "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.4",
+ "debug": "^4.1.1",
+ "espree": "^7.3.0",
+ "globals": "^12.1.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^3.13.1",
+ "minimatch": "^3.0.4",
+ "strip-json-comments": "^3.1.1"
+ },
+ "dependencies": {
+ "globals": {
+ "version": "12.4.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
+ "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.8.1"
+ }
+ },
+ "ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true
+ }
+ }
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
+ "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.4",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz",
+ "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz",
+ "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.4",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@pixi/accessibility": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/accessibility/-/accessibility-5.3.8.tgz",
+ "integrity": "sha512-DBkUUPIDfaw1hXFLTOsmZ401JSyu286rS2UB79ClxvVtDfGI7pR+Hgq1PuNeoQSiO9Db32W4grvuxYTulO2jkQ==",
+ "requires": {
+ "@pixi/core": "5.3.8",
+ "@pixi/display": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/app": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/app/-/app-5.3.8.tgz",
+ "integrity": "sha512-eekP/tIPlERZOiWOCVKgOCc66JoAHDP7yT9DBw2LtCKswvP83iwN0PX5YR/u6Z05kUW5y8t4bigfLqEqc4uChw==",
+ "requires": {
+ "@pixi/core": "5.3.8",
+ "@pixi/display": "5.3.8"
+ }
+ },
+ "@pixi/constants": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/constants/-/constants-5.3.8.tgz",
+ "integrity": "sha512-vTkgBgiox2pLj2ZK/X37O6rFjsLic6CYa+rSCCMo8lCwipG/dgizYoAVIsmZy30tFgg1xYzI6qOw3MSVXupp8Q=="
+ },
+ "@pixi/core": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/core/-/core-5.3.8.tgz",
+ "integrity": "sha512-mbl7//UbNaIZJbS8R8g5o6cHAMW7xaJWW/dNazSJ9057Fpq5g3e3E2rreNTEILfC29cxm2sXDmgK5a9agoqJaA==",
+ "requires": {
+ "@pixi/constants": "5.3.8",
+ "@pixi/math": "5.3.8",
+ "@pixi/runner": "5.3.8",
+ "@pixi/settings": "5.3.8",
+ "@pixi/ticker": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/display": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/display/-/display-5.3.8.tgz",
+ "integrity": "sha512-ch7g63ox3iow/NEGbrArLfUMJVLVF+FpdFAp72uEweIzlcyzOQV6AcQTHtiRy4+tM6LdlcLSJXJISqGKt2R0Dg==",
+ "requires": {
+ "@pixi/math": "5.3.8",
+ "@pixi/settings": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/extract": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/extract/-/extract-5.3.8.tgz",
+ "integrity": "sha512-z09D+5qmGQilbBXhR3xlZCixkTb6+1bSo6jGsbQxpu3xaF0ogh1HB76SJ2Wi1vwba9Q/PMb6RlawdEAg+sRFMg==",
+ "requires": {
+ "@pixi/core": "5.3.8",
+ "@pixi/math": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/filter-adjustment": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-adjustment/-/filter-adjustment-3.1.1.tgz",
+ "integrity": "sha512-N+qbkofBn5tiGn2Ubg52AEoPOM69VIO5TEHsBtm5oh2S4m/rb6FnnqPji/FzwK89iLvtYmJdbwWAYi87PWnE3Q=="
+ },
+ "@pixi/filter-alpha": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-alpha/-/filter-alpha-5.3.8.tgz",
+ "integrity": "sha512-4vOmuWDLBiMbdQ2S3PmxzrzpPOrlzZVZ8iPEkQrBCYZ4dIuZY7NaV+9tneIK66dDfVI6OA8Ai304LH22nhC81Q==",
+ "requires": {
+ "@pixi/core": "5.3.8"
+ }
+ },
+ "@pixi/filter-blur": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-blur/-/filter-blur-5.3.8.tgz",
+ "integrity": "sha512-biNqbfFIDbvOJJ+NiE9G0XojnuMQqtbcaDIiOScRoY3o3yCMjjcUxUMYrZ4xnTGGtEH23OKGUTZVf53qTQ4wiw==",
+ "requires": {
+ "@pixi/core": "5.3.8",
+ "@pixi/settings": "5.3.8"
+ }
+ },
+ "@pixi/filter-color-matrix": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-color-matrix/-/filter-color-matrix-5.3.8.tgz",
+ "integrity": "sha512-0Ag08uPKVoHWQSAIhS27Bs/b50NVMZ+3fUdNg9jgyrRthD/Uc2ljfkIJRa95Mj31YJBS15Giu4BGfefpe1i3zw==",
+ "requires": {
+ "@pixi/core": "5.3.8"
+ }
+ },
+ "@pixi/filter-displacement": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-displacement/-/filter-displacement-5.3.8.tgz",
+ "integrity": "sha512-OQYBK3oOId8VZV7KRYYdt196EYsG0cjAmQQT7P3/IETLIP6Mba+Bd/GtyxGEIBHcb7R5DebuvN4sVQtNgkRKlw==",
+ "requires": {
+ "@pixi/core": "5.3.8",
+ "@pixi/math": "5.3.8"
+ }
+ },
+ "@pixi/filter-fxaa": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-fxaa/-/filter-fxaa-5.3.8.tgz",
+ "integrity": "sha512-eOfrp46AEjkAM1U+6k9Ga/5ezEwr1+7yGS3VijZBHntZTYKFhmGGOXrQxxL4KuslrfTV/smAflEr22U+A2H98A==",
+ "requires": {
+ "@pixi/core": "5.3.8"
+ }
+ },
+ "@pixi/filter-noise": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-noise/-/filter-noise-5.3.8.tgz",
+ "integrity": "sha512-+MOz3GpB9XpH7d0B/HAz8zOp164UMKnE64Q9QI094X4KjXWj24RKZea8xFcOaOy9xKi57qqyo+3pLwqFB8ffsw==",
+ "requires": {
+ "@pixi/core": "5.3.8"
+ }
+ },
+ "@pixi/graphics": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/graphics/-/graphics-5.3.8.tgz",
+ "integrity": "sha512-auqwS6ZnDlNoerddLCoMpEzgq0o09WHH7XxwfTK75hJwBaFX1RO/nasfvCx2wAtWZxAYCaABfR8WnWZfrsBSqA==",
+ "requires": {
+ "@pixi/constants": "5.3.8",
+ "@pixi/core": "5.3.8",
+ "@pixi/display": "5.3.8",
+ "@pixi/math": "5.3.8",
+ "@pixi/sprite": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/interaction": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/interaction/-/interaction-5.3.8.tgz",
+ "integrity": "sha512-i9KS9TNVK/PEwyjZH2iqui9xroy0R48u/QL4Q8+VQpwbeDlz+WlPWoW5R7rpUwtHd9H6mLWpGR3sdWOmS7fMsA==",
+ "requires": {
+ "@pixi/core": "5.3.8",
+ "@pixi/display": "5.3.8",
+ "@pixi/math": "5.3.8",
+ "@pixi/ticker": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/loaders": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/loaders/-/loaders-5.3.8.tgz",
+ "integrity": "sha512-0M2e/gkBBqJW695wz9DcsYN7IY992FKqb9uOEhFFjCn2bkK9WsR6M/JBvTlTk4LOvEg81b1/J51bkucpXWx1Cg==",
+ "requires": {
+ "@pixi/core": "5.3.8",
+ "@pixi/utils": "5.3.8",
+ "resource-loader": "^3.0.1"
+ }
+ },
+ "@pixi/math": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/math/-/math-5.3.8.tgz",
+ "integrity": "sha512-MZekzC9W391KU2NyzbRHrgYfjPKguzU5cRLbaEw9dgDabLh3/Yzob1KVg8dngIITPbi5yBmoX7zh7ZHEA1NRPQ=="
+ },
+ "@pixi/mesh": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mesh/-/mesh-5.3.8.tgz",
+ "integrity": "sha512-/CQdTypiLgSZqKx9z89cJlLQ8/FaUrc8M3HjmL8Vy5F320ERCR1YLDc6gOzyohK71wDxkUud5VbNz5woQVSBxw==",
+ "requires": {
+ "@pixi/constants": "5.3.8",
+ "@pixi/core": "5.3.8",
+ "@pixi/display": "5.3.8",
+ "@pixi/math": "5.3.8",
+ "@pixi/settings": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/mesh-extras": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mesh-extras/-/mesh-extras-5.3.8.tgz",
+ "integrity": "sha512-+lHcmvslKsmlixiJW87/t5diRy7p+tvqQbXMG4/3Vzv3dBEGq453hMIknlLr2xLGyzBtboCHObzwKfeE4tvHTw==",
+ "requires": {
+ "@pixi/constants": "5.3.8",
+ "@pixi/core": "5.3.8",
+ "@pixi/math": "5.3.8",
+ "@pixi/mesh": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/mixin-cache-as-bitmap": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mixin-cache-as-bitmap/-/mixin-cache-as-bitmap-5.3.8.tgz",
+ "integrity": "sha512-Y4z3yvMldRUU99I+FBOl+j+TCq7CXN2ysNED/vMD2YpfilS2/8dQcAqRNEOBXCdSixd6+QHBuc0+PWR6M7irKg==",
+ "requires": {
+ "@pixi/core": "5.3.8",
+ "@pixi/display": "5.3.8",
+ "@pixi/math": "5.3.8",
+ "@pixi/settings": "5.3.8",
+ "@pixi/sprite": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/mixin-get-child-by-name": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mixin-get-child-by-name/-/mixin-get-child-by-name-5.3.8.tgz",
+ "integrity": "sha512-6Z4C2SucwC1w2xa260VxU+uIkP8FhwnZWDfY0rxyxecWxvkM7ULsIU9szoUYUJvLJnpxRi4Xb6rXNPxXyzis9Q==",
+ "requires": {
+ "@pixi/display": "5.3.8"
+ }
+ },
+ "@pixi/mixin-get-global-position": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mixin-get-global-position/-/mixin-get-global-position-5.3.8.tgz",
+ "integrity": "sha512-o2ZKmTxDvoibGBZ8LP3qJZ3cHe7L447qsuHPPLYOPmA5hqG49YchwmKMwV6tn96C8yDECaVn429Hu5hZEI7UlA==",
+ "requires": {
+ "@pixi/display": "5.3.8",
+ "@pixi/math": "5.3.8"
+ }
+ },
+ "@pixi/particles": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/particles/-/particles-5.3.8.tgz",
+ "integrity": "sha512-XAehJJ9SsLwlZF1Qkkir0ejPZ0YgCg8MbxzmrxBUbhH1NyHJLFm+K2S7Bp12FdR/hZwTENF7GMGVRH+o86u3hw==",
+ "requires": {
+ "@pixi/constants": "5.3.8",
+ "@pixi/core": "5.3.8",
+ "@pixi/display": "5.3.8",
+ "@pixi/math": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/polyfill": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/polyfill/-/polyfill-5.3.8.tgz",
+ "integrity": "sha512-AIXfAjYD7dfP2C+TX3482YterwGE876amqmk6EzMZCI3vvsvDJUGT/Dx6lSOU5zbcUbJ9t3Ybz81xQYpaEhv/Q==",
+ "requires": {
+ "es6-promise-polyfill": "^1.2.0",
+ "object-assign": "^4.1.1"
+ }
+ },
+ "@pixi/prepare": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/prepare/-/prepare-5.3.8.tgz",
+ "integrity": "sha512-DbYxQdziypsdQJaRKwdmODkIy2mQHETEFlVWou0XwVy+WB8VBlSnHZ57cVEY8l6Z0hJ93Vo4K6j5qIRi9MRjJA==",
+ "requires": {
+ "@pixi/core": "5.3.8",
+ "@pixi/display": "5.3.8",
+ "@pixi/graphics": "5.3.8",
+ "@pixi/settings": "5.3.8",
+ "@pixi/text": "5.3.8",
+ "@pixi/ticker": "5.3.8"
+ }
+ },
+ "@pixi/runner": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/runner/-/runner-5.3.8.tgz",
+ "integrity": "sha512-6Y9v9OHd5FFv6s0M4AGHnG3qvLiTBM5T5RnlEqMNMsqH6CWSDq0mNJA5HQD65q5ViK8HM6MYPm2nwwkYq5AICQ=="
+ },
+ "@pixi/settings": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/settings/-/settings-5.3.8.tgz",
+ "integrity": "sha512-/NSd9v6+IbG3GjzIoNwy7rgPg6kwwWy54pcaiM3Wv3zjkwhkVySK4m3h892Wa2z5lFvrHEH9zewGJwEpUH/FMA==",
+ "requires": {
+ "ismobilejs": "^1.1.0"
+ }
+ },
+ "@pixi/sprite": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/sprite/-/sprite-5.3.8.tgz",
+ "integrity": "sha512-r+WeX5cti3VKu6U+hZeSiY4UC8912FjNU7M5bA/gev9CfUKv3fNwKYshPfzOkTPua8dFwI1U6tplYu5rSPMBmw==",
+ "requires": {
+ "@pixi/constants": "5.3.8",
+ "@pixi/core": "5.3.8",
+ "@pixi/display": "5.3.8",
+ "@pixi/math": "5.3.8",
+ "@pixi/settings": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/sprite-animated": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/sprite-animated/-/sprite-animated-5.3.8.tgz",
+ "integrity": "sha512-zLnzmCJJ++Hyyy1LPh5Lt4icPuy8C+vL59yVj3nAYzqq/G26rFuHELexB0iwKBPE9yQYuaUQhFgOPgW4vFqLAw==",
+ "requires": {
+ "@pixi/core": "5.3.8",
+ "@pixi/sprite": "5.3.8",
+ "@pixi/ticker": "5.3.8"
+ }
+ },
+ "@pixi/sprite-tiling": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/sprite-tiling/-/sprite-tiling-5.3.8.tgz",
+ "integrity": "sha512-SvCAvajihsaNx/xX4s6waEqPLVkI5W86h31kpoqdPj3zXhoLbpZh6t2TWbcRJmgjM1GvBNy14gWtelBq8UF7Mg==",
+ "requires": {
+ "@pixi/constants": "5.3.8",
+ "@pixi/core": "5.3.8",
+ "@pixi/display": "5.3.8",
+ "@pixi/math": "5.3.8",
+ "@pixi/sprite": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/spritesheet": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/spritesheet/-/spritesheet-5.3.8.tgz",
+ "integrity": "sha512-KqTsW2LViI1UjZTycfI0x3m+yZqV8zfIm/CiDAmtujUPAu8sU78jzByc8ke7FaFC6waDsfAKTKu4fBqSu7aH1w==",
+ "requires": {
+ "@pixi/core": "5.3.8",
+ "@pixi/loaders": "5.3.8",
+ "@pixi/math": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/text": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/text/-/text-5.3.8.tgz",
+ "integrity": "sha512-qarv4kXSrtroJy5dbmF0Vld7L8teeQxsV5N1g1Fjhi4uUCb43ioR9euBHIjju33kOLDYYXXw6L78XIe/cW6nIw==",
+ "requires": {
+ "@pixi/core": "5.3.8",
+ "@pixi/math": "5.3.8",
+ "@pixi/settings": "5.3.8",
+ "@pixi/sprite": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/text-bitmap": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/text-bitmap/-/text-bitmap-5.3.8.tgz",
+ "integrity": "sha512-jJVAc/y7Mo/DLw8n14A1AFmhQe8rw5d+vCg/1k4hw0Oru4l2QU/8AA940kPeuky4Sj0hMLf9UWAS6A3gOo5ZTA==",
+ "requires": {
+ "@pixi/core": "5.3.8",
+ "@pixi/display": "5.3.8",
+ "@pixi/loaders": "5.3.8",
+ "@pixi/math": "5.3.8",
+ "@pixi/mesh": "5.3.8",
+ "@pixi/settings": "5.3.8",
+ "@pixi/text": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "@pixi/ticker": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/ticker/-/ticker-5.3.8.tgz",
+ "integrity": "sha512-WoVi8btR0X2/fXJgt/oRy2gm32ECnibqUkxl0MOcLuxg7cHDZKFA5PwNK/eIx5hZZ2xM/ztoPtEohWV6LqLryw==",
+ "requires": {
+ "@pixi/settings": "5.3.8"
+ }
+ },
+ "@pixi/utils": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@pixi/utils/-/utils-5.3.8.tgz",
+ "integrity": "sha512-LljIFFOFcXLyLzXqIYwcXUqz6NsAUbwxb7Som9Gm3i1usGIqPRX4R08Iaf4L6OKA7417gSrRmbYdT0Hje/0ikA==",
+ "requires": {
+ "@pixi/constants": "5.3.8",
+ "@pixi/settings": "5.3.8",
+ "earcut": "^2.1.5",
+ "eventemitter3": "^3.1.0",
+ "url": "^0.11.0"
+ }
+ },
+ "@types/json-schema": {
+ "version": "7.0.7",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
+ "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "14.14.35",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.35.tgz",
+ "integrity": "sha512-Lt+wj8NVPx0zUmUwumiVXapmaLUcAk3yPuHCFVXras9k5VT9TdhJqKqGVUQCD60OTMCl0qxJ57OiTL0Mic3Iag==",
+ "dev": true
+ },
+ "@types/pako": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.1.tgz",
+ "integrity": "sha512-GdZbRSJ3Cv5fiwT6I0SQ3ckeN2PWNqxd26W9Z2fCK1tGrrasGy4puvNFtnddqH9UJFMQYXxEuuB7B8UK+LLwSg==",
+ "dev": true
+ },
+ "@typescript-eslint/eslint-plugin": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.18.0.tgz",
+ "integrity": "sha512-Lzkc/2+7EoH7+NjIWLS2lVuKKqbEmJhtXe3rmfA8cyiKnZm3IfLf51irnBcmow8Q/AptVV0XBZmBJKuUJTe6cQ==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/experimental-utils": "4.18.0",
+ "@typescript-eslint/scope-manager": "4.18.0",
+ "debug": "^4.1.1",
+ "functional-red-black-tree": "^1.0.1",
+ "lodash": "^4.17.15",
+ "regexpp": "^3.0.0",
+ "semver": "^7.3.2",
+ "tsutils": "^3.17.1"
+ }
+ },
+ "@typescript-eslint/experimental-utils": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.18.0.tgz",
+ "integrity": "sha512-92h723Kblt9JcT2RRY3QS2xefFKar4ZQFVs3GityOKWQYgtajxt/tuXIzL7sVCUlM1hgreiV5gkGYyBpdOwO6A==",
+ "dev": true,
+ "requires": {
+ "@types/json-schema": "^7.0.3",
+ "@typescript-eslint/scope-manager": "4.18.0",
+ "@typescript-eslint/types": "4.18.0",
+ "@typescript-eslint/typescript-estree": "4.18.0",
+ "eslint-scope": "^5.0.0",
+ "eslint-utils": "^2.0.0"
+ }
+ },
+ "@typescript-eslint/parser": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.18.0.tgz",
+ "integrity": "sha512-W3z5S0ZbecwX3PhJEAnq4mnjK5JJXvXUDBYIYGoweCyWyuvAKfGHvzmpUzgB5L4cRBb+cTu9U/ro66dx7dIimA==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/scope-manager": "4.18.0",
+ "@typescript-eslint/types": "4.18.0",
+ "@typescript-eslint/typescript-estree": "4.18.0",
+ "debug": "^4.1.1"
+ }
+ },
+ "@typescript-eslint/scope-manager": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.18.0.tgz",
+ "integrity": "sha512-olX4yN6rvHR2eyFOcb6E4vmhDPsfdMyfQ3qR+oQNkAv8emKKlfxTWUXU5Mqxs2Fwe3Pf1BoPvrwZtwngxDzYzQ==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "4.18.0",
+ "@typescript-eslint/visitor-keys": "4.18.0"
+ }
+ },
+ "@typescript-eslint/types": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.18.0.tgz",
+ "integrity": "sha512-/BRociARpj5E+9yQ7cwCF/SNOWwXJ3qhjurMuK2hIFUbr9vTuDeu476Zpu+ptxY2kSxUHDGLLKy+qGq2sOg37A==",
+ "dev": true
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.18.0.tgz",
+ "integrity": "sha512-wt4xvF6vvJI7epz+rEqxmoNQ4ZADArGQO9gDU+cM0U5fdVv7N+IAuVoVAoZSOZxzGHBfvE3XQMLdy+scsqFfeg==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "4.18.0",
+ "@typescript-eslint/visitor-keys": "4.18.0",
+ "debug": "^4.1.1",
+ "globby": "^11.0.1",
+ "is-glob": "^4.0.1",
+ "semver": "^7.3.2",
+ "tsutils": "^3.17.1"
+ }
+ },
+ "@typescript-eslint/visitor-keys": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.18.0.tgz",
+ "integrity": "sha512-Q9t90JCvfYaN0OfFUgaLqByOfz8yPeTAdotn/XYNm5q9eHax90gzdb+RJ6E9T5s97Kv/UHWKERTmqA0jTKAEHw==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "4.18.0",
+ "eslint-visitor-keys": "^2.0.0"
+ }
+ },
+ "acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
+ "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
+ "dev": true
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true
+ },
+ "astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+ "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "debug": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+ "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "dev": true
+ },
+ "dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "earcut": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.2.tgz",
+ "integrity": "sha512-eZoZPPJcUHnfRZ0PjLvx2qBordSiO8ofC3vt+qACLM95u+4DovnbYNpQtJh0DNsWj8RnxrQytD4WA8gj5cRIaQ=="
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^4.1.1"
+ }
+ },
+ "es6-promise-polyfill": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/es6-promise-polyfill/-/es6-promise-polyfill-1.2.0.tgz",
+ "integrity": "sha1-84kl8jyz4+jObNqP93T867sJDN4="
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "eslint": {
+ "version": "7.22.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.22.0.tgz",
+ "integrity": "sha512-3VawOtjSJUQiiqac8MQc+w457iGLfuNGLFn8JmF051tTKbh5/x/0vlcEj8OgDCaw7Ysa2Jn8paGshV7x2abKXg==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "7.12.11",
+ "@eslint/eslintrc": "^0.4.0",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.0.1",
+ "doctrine": "^3.0.0",
+ "enquirer": "^2.3.5",
+ "eslint-scope": "^5.1.1",
+ "eslint-utils": "^2.1.0",
+ "eslint-visitor-keys": "^2.0.0",
+ "espree": "^7.3.1",
+ "esquery": "^1.4.0",
+ "esutils": "^2.0.2",
+ "file-entry-cache": "^6.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^5.0.0",
+ "globals": "^13.6.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^3.13.1",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash": "^4.17.21",
+ "minimatch": "^3.0.4",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "progress": "^2.0.0",
+ "regexpp": "^3.1.0",
+ "semver": "^7.2.1",
+ "strip-ansi": "^6.0.0",
+ "strip-json-comments": "^3.1.0",
+ "table": "^6.0.4",
+ "text-table": "^0.2.0",
+ "v8-compile-cache": "^2.0.3"
+ },
+ "dependencies": {
+ "ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "eslint-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+ "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz",
+ "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
+ "dev": true
+ },
+ "espree": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
+ "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
+ "dev": true,
+ "requires": {
+ "acorn": "^7.4.0",
+ "acorn-jsx": "^5.3.1",
+ "eslint-visitor-keys": "^1.3.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true
+ }
+ }
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "esquery": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+ "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+ "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+ "dev": true
+ }
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.2.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+ "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+ "dev": true
+ }
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "eventemitter3": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
+ "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q=="
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
+ "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.0",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.2",
+ "picomatch": "^2.2.1"
+ }
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "fastq": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
+ "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^3.0.4"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "requires": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "flatted": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz",
+ "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
+ "dev": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "globals": {
+ "version": "13.6.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.6.0.tgz",
+ "integrity": "sha512-YFKCX0SiPg7l5oKYCJ2zZGxcXprVXHcSnVuvzrT3oSENQonVLqM5pf9fN5dLGZGyCjhw8TN8Btwe/jKnZ0pjvQ==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true
+ }
+ }
+ },
+ "globby": {
+ "version": "11.0.2",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz",
+ "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==",
+ "dev": true,
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.1.1",
+ "ignore": "^5.1.4",
+ "merge2": "^1.3.0",
+ "slash": "^3.0.0"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "ignore": {
+ "version": "5.1.8",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+ "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+ "dev": true
+ },
+ "import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "ismobilejs": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz",
+ "integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw=="
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+ "dev": true
+ },
+ "levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
+ "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.1",
+ "picomatch": "^2.0.5"
+ }
+ },
+ "mini-signals": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mini-signals/-/mini-signals-1.2.0.tgz",
+ "integrity": "sha1-RbCAE8X65RokqhqTXNMXye1yHXQ="
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "requires": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ }
+ },
+ "pako": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-2.0.3.tgz",
+ "integrity": "sha512-WjR1hOeg+kki3ZIOjaf4b5WVcay1jaliKSYiEaB1XzwhMQZJxRdQRv0V31EKBYlxb4T7SK3hjfc/jxyU64BoSw=="
+ },
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
+ "parse-uri": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/parse-uri/-/parse-uri-1.0.3.tgz",
+ "integrity": "sha512-upMnGxNcm+45So85HoguwZTVZI9u11i36DdxJfGF2HYWS2eh3TIx7+/tTi7qrEq15qzGkVhsKjesau+kCk48pA=="
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
+ "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+ "dev": true
+ },
+ "pixi.js": {
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-5.3.8.tgz",
+ "integrity": "sha512-kDqkWhuAkc42lD+ldVTaS439q7D7uo9FM/wCP26jUNAFlYAp75IcALEgXuBh6HEjp51enGkRvwX9+fIiA5F9ug==",
+ "requires": {
+ "@pixi/accessibility": "5.3.8",
+ "@pixi/app": "5.3.8",
+ "@pixi/constants": "5.3.8",
+ "@pixi/core": "5.3.8",
+ "@pixi/display": "5.3.8",
+ "@pixi/extract": "5.3.8",
+ "@pixi/filter-alpha": "5.3.8",
+ "@pixi/filter-blur": "5.3.8",
+ "@pixi/filter-color-matrix": "5.3.8",
+ "@pixi/filter-displacement": "5.3.8",
+ "@pixi/filter-fxaa": "5.3.8",
+ "@pixi/filter-noise": "5.3.8",
+ "@pixi/graphics": "5.3.8",
+ "@pixi/interaction": "5.3.8",
+ "@pixi/loaders": "5.3.8",
+ "@pixi/math": "5.3.8",
+ "@pixi/mesh": "5.3.8",
+ "@pixi/mesh-extras": "5.3.8",
+ "@pixi/mixin-cache-as-bitmap": "5.3.8",
+ "@pixi/mixin-get-child-by-name": "5.3.8",
+ "@pixi/mixin-get-global-position": "5.3.8",
+ "@pixi/particles": "5.3.8",
+ "@pixi/polyfill": "5.3.8",
+ "@pixi/prepare": "5.3.8",
+ "@pixi/runner": "5.3.8",
+ "@pixi/settings": "5.3.8",
+ "@pixi/sprite": "5.3.8",
+ "@pixi/sprite-animated": "5.3.8",
+ "@pixi/sprite-tiling": "5.3.8",
+ "@pixi/spritesheet": "5.3.8",
+ "@pixi/text": "5.3.8",
+ "@pixi/text-bitmap": "5.3.8",
+ "@pixi/ticker": "5.3.8",
+ "@pixi/utils": "5.3.8"
+ }
+ },
+ "prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true
+ },
+ "progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "dev": true
+ },
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
+ },
+ "queue-microtask": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz",
+ "integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==",
+ "dev": true
+ },
+ "regexpp": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
+ "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
+ "dev": true
+ },
+ "require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true
+ },
+ "resource-loader": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/resource-loader/-/resource-loader-3.0.1.tgz",
+ "integrity": "sha512-fBuCRbEHdLCI1eglzQhUv9Rrdcmqkydr1r6uHE2cYHvRBrcLXeSmbE/qI/urFt8rPr/IGxir3BUwM5kUK8XoyA==",
+ "requires": {
+ "mini-signals": "^1.2.0",
+ "parse-uri": "^1.0.0"
+ }
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ },
+ "semver": {
+ "version": "7.3.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
+ "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ }
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
+ "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "table": {
+ "version": "6.0.7",
+ "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz",
+ "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^7.0.2",
+ "lodash": "^4.17.20",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.0"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.2.1.tgz",
+ "integrity": "sha512-+nu0HDv7kNSOua9apAVc979qd932rrZeb3WOvoiD31A/p1mIE5/9bN2027pE2rOPYEdS3UHzsvof4hY+lM9/WQ==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ }
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "tslib": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
+ "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
+ },
+ "tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ }
+ }
+ },
+ "type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
+ "type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true
+ },
+ "typescript": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz",
+ "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==",
+ "dev": true
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ }
+ }
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ }
+ },
+ "v8-compile-cache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+ "dev": true
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "xml2js": {
+ "version": "0.4.23",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
+ "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
+ "requires": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~11.0.0"
+ }
+ },
+ "xmlbuilder": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..476a1d60
--- /dev/null
+++ b/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "nitro-renderer",
+ "version": "1.0.0",
+ "scripts": {
+ "eslint": "eslint ./src --fix"
+ },
+ "private": true,
+ "dependencies": {
+ "@pixi/filter-adjustment": "^3.1.1",
+ "pako": "^2.0.3",
+ "pixi.js": "^5.3.3",
+ "tslib": "^2.0.0",
+ "xml2js": "^0.4.23"
+ },
+ "devDependencies": {
+ "@types/node": "^14.14.35",
+ "@types/pako": "^1.0.1",
+ "@typescript-eslint/eslint-plugin": "^4.15.0",
+ "@typescript-eslint/parser": "^4.15.0",
+ "eslint": "^7.19.0",
+ "typescript": "~4.2.3"
+ }
+}
diff --git a/src/core/INitroCore.ts b/src/core/INitroCore.ts
new file mode 100644
index 00000000..a3f6da74
--- /dev/null
+++ b/src/core/INitroCore.ts
@@ -0,0 +1,11 @@
+import { IAssetManager } from './asset/IAssetManager';
+import { IDisposable } from './common/disposable/IDisposable';
+import { ICommunicationManager } from './communication/ICommunicationManager';
+import { IConfigurationManager } from './configuration/IConfigurationManager';
+
+export interface INitroCore extends IDisposable
+{
+ configuration: IConfigurationManager;
+ asset: IAssetManager;
+ communication: ICommunicationManager;
+}
\ No newline at end of file
diff --git a/src/core/NitroCore.ts b/src/core/NitroCore.ts
new file mode 100644
index 00000000..d7a44636
--- /dev/null
+++ b/src/core/NitroCore.ts
@@ -0,0 +1,60 @@
+import { AssetManager } from './asset/AssetManager';
+import { IAssetManager } from './asset/IAssetManager';
+import { Disposable } from './common/disposable/Disposable';
+import { CommunicationManager } from './communication/CommunicationManager';
+import { ICommunicationManager } from './communication/ICommunicationManager';
+import { ConfigurationManager } from './configuration/ConfigurationManager';
+import { IConfigurationManager } from './configuration/IConfigurationManager';
+import { INitroCore } from './INitroCore';
+
+export class NitroCore extends Disposable implements INitroCore
+{
+ private _configuration: IConfigurationManager;
+ private _communication: ICommunicationManager;
+ private _asset: IAssetManager;
+
+ constructor()
+ {
+ super();
+
+ window.console.log.apply(console, [
+ '\n%c _ ___ __ \n / | / (_) /__________ \n / |/ / / __/ ___/ __ \\ \n / /| / / /_/ / / /_/ / \n /_/ |_/_/\\__/_/ \\____/ \n \n Thanks for using Nitro \n To report bugs or issues \n join us on Discord \n https://discord.gg/66UR68FPgy \n \n',
+ 'color: #FFFFFF; background: #000000; padding:0px 0;' ]);
+
+ this._configuration = new ConfigurationManager();
+ this._communication = new CommunicationManager();
+ this._asset = new AssetManager();
+ }
+
+ protected onDispose(): void
+ {
+ if(this._asset)
+ {
+ this._asset.dispose();
+
+ this._asset = null;
+ }
+
+ if(this._communication)
+ {
+ this._communication.dispose();
+
+ this._communication = null;
+ }
+ }
+
+ public get configuration(): IConfigurationManager
+ {
+ return this._configuration;
+ }
+
+ public get communication(): ICommunicationManager
+ {
+ return this._communication;
+ }
+
+ public get asset(): IAssetManager
+ {
+ return this._asset;
+ }
+}
\ No newline at end of file
diff --git a/src/core/asset/AssetManager.ts b/src/core/asset/AssetManager.ts
new file mode 100644
index 00000000..8b0ec9cb
--- /dev/null
+++ b/src/core/asset/AssetManager.ts
@@ -0,0 +1,319 @@
+import { BaseTexture, ILoaderOptions, Loader, LoaderResource, Spritesheet, Texture } from 'pixi.js';
+import { GraphicAssetCollection } from '../../room/object/visualization/utils/GraphicAssetCollection';
+import { IGraphicAsset } from '../../room/object/visualization/utils/IGraphicAsset';
+import { IGraphicAssetCollection } from '../../room/object/visualization/utils/IGraphicAssetCollection';
+import { Disposable } from '../common/disposable/Disposable';
+import { INitroLogger } from '../common/logger/INitroLogger';
+import { NitroLogger } from '../common/logger/NitroLogger';
+import { IAssetManager } from './IAssetManager';
+import { IAssetData } from './interfaces';
+import { NitroBundle } from './NitroBundle';
+
+export class AssetManager extends Disposable implements IAssetManager
+{
+ private _logger: INitroLogger;
+ private _textures: Map;
+ private _collections: Map;
+ private _pendingUrls: Map;
+
+ constructor()
+ {
+ super();
+
+ this._logger = new NitroLogger(this.constructor.name);
+ this._textures = new Map();
+ this._collections = new Map();
+ this._pendingUrls = new Map();
+ }
+
+ public static removeFileExtension(name: string): string
+ {
+ return (name.substring(0, name.lastIndexOf('.')) || name);
+ }
+
+ public getTexture(name: string): Texture
+ {
+ if(!name) return null;
+
+ const existing = this._textures.get(name);
+
+ if(!existing) return null;
+
+ return existing;
+ }
+
+ public setTexture(name: string, texture: Texture): void
+ {
+ if(!name || !texture) return;
+
+ this._textures.set(name, texture);
+ }
+
+ public getAsset(name: string): IGraphicAsset
+ {
+ if(!name) return null;
+
+ for(const collection of this._collections.values())
+ {
+ if(!collection) continue;
+
+ const existing = collection.getAsset(name);
+
+ if(!existing) continue;
+
+ return existing;
+ }
+
+ return null;
+ }
+
+ public getCollection(name: string): IGraphicAssetCollection
+ {
+ if(!name) return null;
+
+ const existing = this._collections.get(name);
+
+ if(!existing) return null;
+
+ return existing;
+ }
+
+ public createCollection(data: IAssetData, spritesheet: Spritesheet): IGraphicAssetCollection
+ {
+ if(!data) return null;
+
+ const collection = new GraphicAssetCollection(data, spritesheet);
+
+ if(collection)
+ {
+ for(const [ name, texture ] of collection.textures.entries()) this.setTexture(name, texture);
+
+ this._collections.set(collection.name, collection);
+ }
+ }
+
+ public downloadAsset(assetUrl: string, cb: Function): boolean
+ {
+ return this.downloadAssets([ assetUrl ], cb);
+ }
+
+ public downloadAssets(assetUrls: string[], cb: Function): boolean
+ {
+ if(!assetUrls || !assetUrls.length)
+ {
+ cb(true);
+
+ return true;
+ }
+
+ const totalToDownload = assetUrls.length;
+
+ let totalDownloaded = 0;
+
+ const onDownloaded = (loader: Loader, resource: LoaderResource, flag: boolean) =>
+ {
+ if(loader) loader.destroy();
+
+ if(!flag)
+ {
+ this._logger.error('Failed to download asset: ' + resource.url);
+
+ cb(false);
+
+ return;
+ }
+
+ totalDownloaded++;
+
+ if(totalDownloaded === totalToDownload) cb(true);
+ };
+
+ for(const url of assetUrls)
+ {
+ if(!url) continue;
+
+ const loader = new Loader();
+
+ const options: ILoaderOptions = {
+ crossOrigin: false,
+ xhrType: url.endsWith('.nitro') ? 'arraybuffer' : 'json'
+ };
+
+ loader
+ .use((resource: LoaderResource, next: Function) => this.assetLoader(loader, resource, next, onDownloaded))
+ .add(url, options)
+ .load();
+ }
+
+ return true;
+ }
+
+ private assetLoader(loader: Loader, resource: LoaderResource, next: Function, onDownloaded: Function): void
+ {
+ if(!resource || resource.error)
+ {
+ if(resource && resource.texture) resource.texture.destroy(true);
+
+ onDownloaded(loader, resource, false);
+
+ return;
+ }
+
+ if(resource.extension === 'nitro')
+ {
+ const nitroBundle = new NitroBundle(resource.data);
+ const assetData = (nitroBundle.jsonFile as IAssetData);
+
+ if(!assetData || !assetData.type)
+ {
+ onDownloaded(loader, resource, false);
+
+ return;
+ }
+
+ if(assetData.spritesheet && Object.keys(assetData.spritesheet).length)
+ {
+ const baseTexture = nitroBundle.baseTexture;
+
+ if(!baseTexture)
+ {
+ onDownloaded(loader, resource, false);
+
+ return;
+ }
+
+ if(baseTexture.valid)
+ {
+ const spritesheet = new Spritesheet(baseTexture, assetData.spritesheet);
+
+ spritesheet.parse(textures =>
+ {
+ this.createCollection(assetData, spritesheet);
+
+ onDownloaded(loader, resource, true);
+ });
+ }
+ else
+ {
+ baseTexture.once('loaded', () =>
+ {
+ baseTexture.removeAllListeners();
+
+ const spritesheet = new Spritesheet(baseTexture, assetData.spritesheet);
+
+ spritesheet.parse(textures =>
+ {
+ this.createCollection(assetData, spritesheet);
+
+ onDownloaded(loader, resource, true);
+ });
+ });
+
+ baseTexture.once('error', () =>
+ {
+ baseTexture.removeAllListeners();
+
+ onDownloaded(loader, resource, false);
+ });
+ }
+
+ return;
+ }
+
+ this.createCollection(assetData, null);
+
+ onDownloaded(loader, resource, true);
+ }
+
+ else if(resource.type === LoaderResource.TYPE.JSON)
+ {
+ const assetData = (resource.data as IAssetData);
+
+ if(!assetData || !assetData.type)
+ {
+ onDownloaded(loader, resource, false);
+
+ return;
+ }
+
+ if(assetData.spritesheet && Object.keys(assetData.spritesheet).length)
+ {
+ const imageName = (assetData.spritesheet.meta && assetData.spritesheet.meta.image);
+
+ if(!imageName || !imageName.length)
+ {
+ onDownloaded(loader, resource, false);
+
+ return;
+ }
+
+ const imageUrl = (resource.url.substring(0, (resource.url.lastIndexOf('/') + 1)) + imageName);
+ const baseTexture = BaseTexture.from(imageUrl);
+
+ if(baseTexture.valid)
+ {
+ const spritesheet = new Spritesheet(baseTexture, assetData.spritesheet);
+
+ spritesheet.parse(textures =>
+ {
+ this.createCollection(assetData, spritesheet);
+
+ onDownloaded(loader, resource, true);
+ });
+ }
+ else
+ {
+ baseTexture.once('loaded', () =>
+ {
+ baseTexture.removeAllListeners();
+
+ const spritesheet = new Spritesheet(baseTexture, assetData.spritesheet);
+
+ spritesheet.parse(textures =>
+ {
+ this.createCollection(assetData, spritesheet);
+
+ onDownloaded(loader, resource, true);
+ });
+ });
+
+ baseTexture.once('error', () =>
+ {
+ baseTexture.removeAllListeners();
+
+ onDownloaded(loader, resource, false);
+ });
+ }
+
+ return;
+ }
+
+ this.createCollection(assetData, null);
+
+ onDownloaded(loader, resource, true);
+
+ return;
+ }
+
+ if(resource.type === LoaderResource.TYPE.IMAGE)
+ {
+ if(resource.texture.valid)
+ {
+ this.setTexture(resource.name, resource.texture);
+
+ onDownloaded(loader, resource, true);
+ }
+ else
+ {
+ onDownloaded(loader, resource, false);
+ }
+
+ return;
+ }
+ }
+
+ public get collections(): Map
+ {
+ return this._collections;
+ }
+}
diff --git a/src/core/asset/IAssetManager.ts b/src/core/asset/IAssetManager.ts
new file mode 100644
index 00000000..7745c71d
--- /dev/null
+++ b/src/core/asset/IAssetManager.ts
@@ -0,0 +1,19 @@
+
+import { Spritesheet, Texture } from 'pixi.js';
+import { GraphicAssetCollection } from '../../room/object/visualization/utils/GraphicAssetCollection';
+import { IGraphicAsset } from '../../room/object/visualization/utils/IGraphicAsset';
+import { IGraphicAssetCollection } from '../../room/object/visualization/utils/IGraphicAssetCollection';
+import { IAssetData } from './interfaces';
+
+export interface IAssetManager
+{
+ dispose(): void;
+ getTexture(name: string): Texture;
+ setTexture(name: string, texture: Texture): void;
+ getAsset(name: string): IGraphicAsset;
+ getCollection(name: string): IGraphicAssetCollection;
+ createCollection(data: IAssetData, spritesheet: Spritesheet): IGraphicAssetCollection;
+ downloadAssets(urls: string[], cb: Function): void;
+ downloadAsset(url: string, cb: Function): void;
+ collections: Map;
+}
\ No newline at end of file
diff --git a/src/core/asset/NitroBundle.ts b/src/core/asset/NitroBundle.ts
new file mode 100644
index 00000000..00837ea8
--- /dev/null
+++ b/src/core/asset/NitroBundle.ts
@@ -0,0 +1,71 @@
+import { Data, inflate } from 'pako';
+import { BaseTexture } from 'pixi.js';
+import { BinaryReader } from '../communication/codec/BinaryReader';
+
+export class NitroBundle
+{
+ private static TEXT_DECODER: TextDecoder = new TextDecoder('utf-8');
+
+ private _jsonFile: Object = null;
+ private _image: string = null;
+ private _imageData: Uint8Array = null;
+ private _baseTexture: BaseTexture = null;
+
+ constructor(arrayBuffer: ArrayBuffer)
+ {
+ this.parse(arrayBuffer);
+ }
+
+ private static arrayBufferToBase64(buffer: ArrayBuffer): string
+ {
+ let binary = '';
+
+ const bytes = new Uint8Array(buffer);
+ const len = bytes.byteLength;
+
+ for(let i = 0; i < len; i++) (binary += String.fromCharCode(bytes[i]));
+
+ return window.btoa(binary);
+ }
+
+ public parse(arrayBuffer: ArrayBuffer): void
+ {
+ const binaryReader = new BinaryReader(arrayBuffer);
+
+ let fileCount = binaryReader.readShort();
+
+ while(fileCount > 0)
+ {
+ const fileNameLength = binaryReader.readShort();
+ const fileName = binaryReader.readBytes(fileNameLength).toString();
+ const fileLength = binaryReader.readInt();
+ const buffer = binaryReader.readBytes(fileLength);
+
+ if(fileName.endsWith('.json'))
+ {
+ const decompressed = inflate((buffer.toArrayBuffer() as Data));
+
+ this._jsonFile = JSON.parse(NitroBundle.TEXT_DECODER.decode(decompressed));
+ }
+ else
+ {
+ const decompressed = inflate((buffer.toArrayBuffer() as Data));
+ const base64 = NitroBundle.arrayBufferToBase64(decompressed);
+
+ this._baseTexture = new BaseTexture('data:image/png;base64,' + base64);
+ }
+
+ fileCount--;
+ }
+ }
+
+ get jsonFile(): Object
+ {
+ return this._jsonFile;
+ }
+
+ public get baseTexture(): BaseTexture
+ {
+ return this._baseTexture;
+ }
+}
diff --git a/src/core/asset/index.ts b/src/core/asset/index.ts
new file mode 100644
index 00000000..a66a117d
--- /dev/null
+++ b/src/core/asset/index.ts
@@ -0,0 +1,4 @@
+export * from './AssetManager';
+export * from './IAssetManager';
+export * from './interfaces';
+export * from './NitroBundle';
diff --git a/src/core/asset/interfaces/IAsset.ts b/src/core/asset/interfaces/IAsset.ts
new file mode 100644
index 00000000..f4e4fb4d
--- /dev/null
+++ b/src/core/asset/interfaces/IAsset.ts
@@ -0,0 +1,9 @@
+export interface IAsset
+{
+ source?: string;
+ x?: number;
+ y?: number;
+ flipH?: boolean;
+ flipV?: boolean;
+ usesPalette?: boolean;
+}
diff --git a/src/core/asset/interfaces/IAssetAlias.ts b/src/core/asset/interfaces/IAssetAlias.ts
new file mode 100644
index 00000000..5c14027d
--- /dev/null
+++ b/src/core/asset/interfaces/IAssetAlias.ts
@@ -0,0 +1,6 @@
+export interface IAssetAlias
+{
+ link?: string;
+ flipH?: boolean;
+ flipV?: boolean;
+}
diff --git a/src/core/asset/interfaces/IAssetData.ts b/src/core/asset/interfaces/IAssetData.ts
new file mode 100644
index 00000000..2af33ca5
--- /dev/null
+++ b/src/core/asset/interfaces/IAssetData.ts
@@ -0,0 +1,26 @@
+import { IAssetAnimation } from './animation';
+import { IAsset } from './IAsset';
+import { IAssetAlias } from './IAssetAlias';
+import { IAssetDimension } from './IAssetDimension';
+import { IAssetPalette } from './IAssetPalette';
+import { ISpritesheetData } from './spritesheet';
+import { IAssetVisualizationData } from './visualization';
+
+export interface IAssetData {
+ type?: string;
+ name?: string;
+ visualizationType?: string;
+ logicType?: string;
+ maskType?: string;
+ credits?: string;
+ soundSample?: number;
+ action?: { link?: string, startState?: number };
+ spritesheet?: ISpritesheetData;
+ dimensions?: IAssetDimension;
+ directions?: number[];
+ assets?: { [index: string]: IAsset };
+ aliases?: { [index: string]: IAssetAlias };
+ animations?: { [index: string]: IAssetAnimation };
+ palettes?: { [index: string]: IAssetPalette };
+ visualizations?: IAssetVisualizationData[];
+}
diff --git a/src/core/asset/interfaces/IAssetDimension.ts b/src/core/asset/interfaces/IAssetDimension.ts
new file mode 100644
index 00000000..4a4629fa
--- /dev/null
+++ b/src/core/asset/interfaces/IAssetDimension.ts
@@ -0,0 +1,6 @@
+export interface IAssetDimension
+{
+ x: number;
+ y: number;
+ z?: number;
+}
\ No newline at end of file
diff --git a/src/core/asset/interfaces/IAssetPalette.ts b/src/core/asset/interfaces/IAssetPalette.ts
new file mode 100644
index 00000000..5102e95f
--- /dev/null
+++ b/src/core/asset/interfaces/IAssetPalette.ts
@@ -0,0 +1,8 @@
+export interface IAssetPalette
+{
+ id?: number;
+ source?: string;
+ color1?: string;
+ color2?: string;
+ rgb?: [ number, number, number ][];
+}
diff --git a/src/core/asset/interfaces/animation/IAssetAnimation.ts b/src/core/asset/interfaces/animation/IAssetAnimation.ts
new file mode 100644
index 00000000..b35e0eb9
--- /dev/null
+++ b/src/core/asset/interfaces/animation/IAssetAnimation.ts
@@ -0,0 +1,23 @@
+import { IAssetAnimationAdd } from './IAssetAnimationAdd';
+import { IAssetAnimationAvatar } from './IAssetAnimationAvatar';
+import { IAssetAnimationDirection } from './IAssetAnimationDirection';
+import { IAssetAnimationFrame } from './IAssetAnimationFrame';
+import { IAssetAnimationOverride } from './IAssetAnimationOverride';
+import { IAssetAnimationRemove } from './IAssetAnimationRemove';
+import { IAssetAnimationShadow } from './IAssetAnimationShadow';
+import { IAssetAnimationSprite } from './IAssetAnimationSprite';
+
+export interface IAssetAnimation
+{
+ name?: string;
+ desc?: string;
+ resetOnToggle?: boolean;
+ directions?: IAssetAnimationDirection[];
+ shadows?: IAssetAnimationShadow[];
+ adds?: IAssetAnimationAdd[];
+ removes?: IAssetAnimationRemove[];
+ sprites?: IAssetAnimationSprite[];
+ frames?: IAssetAnimationFrame[];
+ avatars?: IAssetAnimationAvatar[];
+ overrides?: IAssetAnimationOverride[];
+}
diff --git a/src/core/asset/interfaces/animation/IAssetAnimationAdd.ts b/src/core/asset/interfaces/animation/IAssetAnimationAdd.ts
new file mode 100644
index 00000000..3da37c6a
--- /dev/null
+++ b/src/core/asset/interfaces/animation/IAssetAnimationAdd.ts
@@ -0,0 +1,8 @@
+export interface IAssetAnimationAdd
+{
+ id?: string;
+ align?: string;
+ blend?: string;
+ ink?: number;
+ base?: string;
+}
diff --git a/src/core/asset/interfaces/animation/IAssetAnimationAvatar.ts b/src/core/asset/interfaces/animation/IAssetAnimationAvatar.ts
new file mode 100644
index 00000000..dcd030ef
--- /dev/null
+++ b/src/core/asset/interfaces/animation/IAssetAnimationAvatar.ts
@@ -0,0 +1,6 @@
+export interface IAssetAnimationAvatar
+{
+ ink?: number;
+ foreground?: string;
+ background?: string;
+}
diff --git a/src/core/asset/interfaces/animation/IAssetAnimationDirection.ts b/src/core/asset/interfaces/animation/IAssetAnimationDirection.ts
new file mode 100644
index 00000000..0c18eaef
--- /dev/null
+++ b/src/core/asset/interfaces/animation/IAssetAnimationDirection.ts
@@ -0,0 +1,4 @@
+export interface IAssetAnimationDirection
+{
+ offset?: number;
+}
diff --git a/src/core/asset/interfaces/animation/IAssetAnimationFrame.ts b/src/core/asset/interfaces/animation/IAssetAnimationFrame.ts
new file mode 100644
index 00000000..b8b88a05
--- /dev/null
+++ b/src/core/asset/interfaces/animation/IAssetAnimationFrame.ts
@@ -0,0 +1,8 @@
+import { IAssetAnimationFramePart } from './IAssetAnimationFramePart';
+
+export interface IAssetAnimationFrame
+{
+ repeats?: number;
+ fxs?: IAssetAnimationFramePart[];
+ bodyparts?: IAssetAnimationFramePart[];
+}
diff --git a/src/core/asset/interfaces/animation/IAssetAnimationFramePart.ts b/src/core/asset/interfaces/animation/IAssetAnimationFramePart.ts
new file mode 100644
index 00000000..ac8c093a
--- /dev/null
+++ b/src/core/asset/interfaces/animation/IAssetAnimationFramePart.ts
@@ -0,0 +1,14 @@
+import { IAssetAnimationFramePartItem } from './IAssetAnimationFramePartItem';
+
+export interface IAssetAnimationFramePart
+{
+ id?: string;
+ frame?: number;
+ base?: string;
+ action?: string;
+ dx?: number;
+ dy?: number;
+ dz?: number;
+ dd?: number;
+ items?: IAssetAnimationFramePartItem[];
+}
diff --git a/src/core/asset/interfaces/animation/IAssetAnimationFramePartItem.ts b/src/core/asset/interfaces/animation/IAssetAnimationFramePartItem.ts
new file mode 100644
index 00000000..45a76423
--- /dev/null
+++ b/src/core/asset/interfaces/animation/IAssetAnimationFramePartItem.ts
@@ -0,0 +1,5 @@
+export interface IAssetAnimationFramePartItem
+{
+ id?: string;
+ base?: string;
+}
diff --git a/src/core/asset/interfaces/animation/IAssetAnimationOverride.ts b/src/core/asset/interfaces/animation/IAssetAnimationOverride.ts
new file mode 100644
index 00000000..3d568330
--- /dev/null
+++ b/src/core/asset/interfaces/animation/IAssetAnimationOverride.ts
@@ -0,0 +1,8 @@
+import { IAssetAnimationFrame } from './IAssetAnimationFrame';
+
+export interface IAssetAnimationOverride
+{
+ name?: string;
+ override?: string;
+ frames?: IAssetAnimationFrame[];
+}
diff --git a/src/core/asset/interfaces/animation/IAssetAnimationRemove.ts b/src/core/asset/interfaces/animation/IAssetAnimationRemove.ts
new file mode 100644
index 00000000..ac65fb59
--- /dev/null
+++ b/src/core/asset/interfaces/animation/IAssetAnimationRemove.ts
@@ -0,0 +1,4 @@
+export interface IAssetAnimationRemove
+{
+ id?: string;
+}
diff --git a/src/core/asset/interfaces/animation/IAssetAnimationShadow.ts b/src/core/asset/interfaces/animation/IAssetAnimationShadow.ts
new file mode 100644
index 00000000..dfe22a88
--- /dev/null
+++ b/src/core/asset/interfaces/animation/IAssetAnimationShadow.ts
@@ -0,0 +1,4 @@
+export interface IAssetAnimationShadow
+{
+ id?: string;
+}
diff --git a/src/core/asset/interfaces/animation/IAssetAnimationSprite.ts b/src/core/asset/interfaces/animation/IAssetAnimationSprite.ts
new file mode 100644
index 00000000..afc7b055
--- /dev/null
+++ b/src/core/asset/interfaces/animation/IAssetAnimationSprite.ts
@@ -0,0 +1,11 @@
+import { IAssetAnimationSpriteDirection } from './IAssetAnimationSpriteDirection';
+
+export interface IAssetAnimationSprite
+{
+ id?: string;
+ member?: string;
+ directions?: number;
+ staticY?: number;
+ ink?: number;
+ directionList?: IAssetAnimationSpriteDirection[];
+}
diff --git a/src/core/asset/interfaces/animation/IAssetAnimationSpriteDirection.ts b/src/core/asset/interfaces/animation/IAssetAnimationSpriteDirection.ts
new file mode 100644
index 00000000..746719d6
--- /dev/null
+++ b/src/core/asset/interfaces/animation/IAssetAnimationSpriteDirection.ts
@@ -0,0 +1,7 @@
+export interface IAssetAnimationSpriteDirection
+{
+ id?: number;
+ dx?: number;
+ dy?: number;
+ dz?: number;
+}
diff --git a/src/core/asset/interfaces/animation/index.ts b/src/core/asset/interfaces/animation/index.ts
new file mode 100644
index 00000000..56543d0b
--- /dev/null
+++ b/src/core/asset/interfaces/animation/index.ts
@@ -0,0 +1,12 @@
+export * from './IAssetAnimation';
+export * from './IAssetAnimationAdd';
+export * from './IAssetAnimationAvatar';
+export * from './IAssetAnimationDirection';
+export * from './IAssetAnimationFrame';
+export * from './IAssetAnimationFramePart';
+export * from './IAssetAnimationFramePartItem';
+export * from './IAssetAnimationOverride';
+export * from './IAssetAnimationRemove';
+export * from './IAssetAnimationShadow';
+export * from './IAssetAnimationSprite';
+export * from './IAssetAnimationSpriteDirection';
diff --git a/src/core/asset/interfaces/index.ts b/src/core/asset/interfaces/index.ts
new file mode 100644
index 00000000..eb113bd8
--- /dev/null
+++ b/src/core/asset/interfaces/index.ts
@@ -0,0 +1,8 @@
+export * from './animation';
+export * from './IAsset';
+export * from './IAssetAlias';
+export * from './IAssetData';
+export * from './IAssetDimension';
+export * from './IAssetPalette';
+export * from './spritesheet';
+export * from './visualization';
diff --git a/src/core/asset/interfaces/spritesheet/ISpritesheetData.ts b/src/core/asset/interfaces/spritesheet/ISpritesheetData.ts
new file mode 100644
index 00000000..24389cc7
--- /dev/null
+++ b/src/core/asset/interfaces/spritesheet/ISpritesheetData.ts
@@ -0,0 +1,8 @@
+import { ISpritesheetFrame } from './ISpritesheetFrame';
+import { ISpritesheetMeta } from './ISpritesheetMeta';
+
+export interface ISpritesheetData
+{
+ meta?: ISpritesheetMeta;
+ frames?: { [index: string]: ISpritesheetFrame };
+}
diff --git a/src/core/asset/interfaces/spritesheet/ISpritesheetFrame.ts b/src/core/asset/interfaces/spritesheet/ISpritesheetFrame.ts
new file mode 100644
index 00000000..0833b502
--- /dev/null
+++ b/src/core/asset/interfaces/spritesheet/ISpritesheetFrame.ts
@@ -0,0 +1,25 @@
+export interface ISpritesheetFrame
+{
+ frame: {
+ x: number;
+ y: number;
+ w: number;
+ h: number;
+ };
+ rotated: boolean;
+ trimmed: boolean;
+ spriteSourceSize: {
+ x: number;
+ y: number;
+ w: number;
+ h: number;
+ };
+ sourceSize: {
+ w: number;
+ h: number;
+ };
+ pivot: {
+ x: number;
+ y: number;
+ };
+}
diff --git a/src/core/asset/interfaces/spritesheet/ISpritesheetMeta.ts b/src/core/asset/interfaces/spritesheet/ISpritesheetMeta.ts
new file mode 100644
index 00000000..3a74f7bc
--- /dev/null
+++ b/src/core/asset/interfaces/spritesheet/ISpritesheetMeta.ts
@@ -0,0 +1,12 @@
+export interface ISpritesheetMeta
+{
+ app: string;
+ version: string;
+ image: string;
+ format: string;
+ size: {
+ w: number;
+ h: number;
+ };
+ scale: string;
+}
diff --git a/src/core/asset/interfaces/spritesheet/index.ts b/src/core/asset/interfaces/spritesheet/index.ts
new file mode 100644
index 00000000..9c94e8ba
--- /dev/null
+++ b/src/core/asset/interfaces/spritesheet/index.ts
@@ -0,0 +1,3 @@
+export * from './ISpritesheetData';
+export * from './ISpritesheetFrame';
+export * from './ISpritesheetMeta';
diff --git a/src/core/asset/interfaces/visualization/IAssetVisualizationData.ts b/src/core/asset/interfaces/visualization/IAssetVisualizationData.ts
new file mode 100644
index 00000000..e0a2d1de
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/IAssetVisualizationData.ts
@@ -0,0 +1,19 @@
+import { IAssetVisualAnimation } from './animation/IAssetVisualAnimation';
+import { IAssetColor } from './color/IAssetColor';
+import { IAssetGesture } from './gestures/IAssetGesture';
+import { IAssetVisualizationDirection } from './IAssetVisualizationDirection';
+import { IAssetVisualizationLayer } from './IAssetVisualizationLayer';
+import { IAssetPosture } from './postures/IAssetPosture';
+
+export interface IAssetVisualizationData
+{
+ size?: number;
+ layerCount?: number;
+ angle?: number;
+ layers?: { [index: string]: IAssetVisualizationLayer };
+ colors?: { [index: string]: IAssetColor };
+ directions?: { [index: string]: IAssetVisualizationDirection };
+ animations?: { [index: string]: IAssetVisualAnimation };
+ postures?: { [index: string]: IAssetPosture };
+ gestures?: { [index: string]: IAssetGesture };
+}
diff --git a/src/core/asset/interfaces/visualization/IAssetVisualizationDirection.ts b/src/core/asset/interfaces/visualization/IAssetVisualizationDirection.ts
new file mode 100644
index 00000000..cc628f10
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/IAssetVisualizationDirection.ts
@@ -0,0 +1,6 @@
+import { IAssetVisualizationLayer } from './IAssetVisualizationLayer';
+
+export interface IAssetVisualizationDirection
+{
+ layers?: { [index: string]: IAssetVisualizationLayer };
+}
diff --git a/src/core/asset/interfaces/visualization/IAssetVisualizationLayer.ts b/src/core/asset/interfaces/visualization/IAssetVisualizationLayer.ts
new file mode 100644
index 00000000..61fcf56e
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/IAssetVisualizationLayer.ts
@@ -0,0 +1,10 @@
+export interface IAssetVisualizationLayer
+{
+ x?: number;
+ y?: number;
+ z?: number;
+ alpha?: number;
+ ink?: string;
+ tag?: string;
+ ignoreMouse?: boolean;
+}
\ No newline at end of file
diff --git a/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimation.ts b/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimation.ts
new file mode 100644
index 00000000..4e714389
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimation.ts
@@ -0,0 +1,10 @@
+import { IAssetVisualAnimationLayer } from './IAssetVisualAnimationLayer';
+
+export interface IAssetVisualAnimation
+{
+ transitionTo?: number;
+ transitionFrom?: number;
+ immediateChangeFrom?: string;
+ randomStart?: boolean;
+ layers?: { [index: string]: IAssetVisualAnimationLayer };
+}
diff --git a/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimationLayer.ts b/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimationLayer.ts
new file mode 100644
index 00000000..2a274ea6
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimationLayer.ts
@@ -0,0 +1,9 @@
+import { IAssetVisualAnimationSequence } from './IAssetVisualAnimationSequence';
+
+export interface IAssetVisualAnimationLayer
+{
+ loopCount?: number;
+ frameRepeat?: number;
+ random?: number;
+ frameSequences?: { [index: string]: IAssetVisualAnimationSequence };
+}
diff --git a/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimationSequence.ts b/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimationSequence.ts
new file mode 100644
index 00000000..bb25104c
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimationSequence.ts
@@ -0,0 +1,8 @@
+import { IAssetVisualAnimationSequenceFrame } from './IAssetVisualAnimationSequenceFrame';
+
+export interface IAssetVisualAnimationSequence
+{
+ loopCount?: number;
+ random?: number;
+ frames?: { [index: string]: IAssetVisualAnimationSequenceFrame };
+}
diff --git a/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimationSequenceFrame.ts b/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimationSequenceFrame.ts
new file mode 100644
index 00000000..196631e5
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimationSequenceFrame.ts
@@ -0,0 +1,11 @@
+import { IAssetVisualAnimationSequenceFrameOffset } from './IAssetVisualAnimationSequenceFrameOffset';
+
+export interface IAssetVisualAnimationSequenceFrame
+{
+ id?: number;
+ x?: number;
+ y?: number;
+ randomX?: number;
+ randomY?: number;
+ offsets?: { [index: string]: IAssetVisualAnimationSequenceFrameOffset };
+}
diff --git a/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimationSequenceFrameOffset.ts b/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimationSequenceFrameOffset.ts
new file mode 100644
index 00000000..bc85461b
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/animation/IAssetVisualAnimationSequenceFrameOffset.ts
@@ -0,0 +1,6 @@
+export interface IAssetVisualAnimationSequenceFrameOffset
+{
+ direction?: number;
+ x?: number;
+ y?: number;
+}
diff --git a/src/core/asset/interfaces/visualization/animation/index.ts b/src/core/asset/interfaces/visualization/animation/index.ts
new file mode 100644
index 00000000..19b332cc
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/animation/index.ts
@@ -0,0 +1,5 @@
+export * from './IAssetVisualAnimation';
+export * from './IAssetVisualAnimationLayer';
+export * from './IAssetVisualAnimationSequence';
+export * from './IAssetVisualAnimationSequenceFrame';
+export * from './IAssetVisualAnimationSequenceFrameOffset';
diff --git a/src/core/asset/interfaces/visualization/color/IAssetColor.ts b/src/core/asset/interfaces/visualization/color/IAssetColor.ts
new file mode 100644
index 00000000..29ebc750
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/color/IAssetColor.ts
@@ -0,0 +1,6 @@
+import { IAssetColorLayer } from './IAssetColorLayer';
+
+export interface IAssetColor
+{
+ layers?: { [index: string]: IAssetColorLayer };
+}
diff --git a/src/core/asset/interfaces/visualization/color/IAssetColorLayer.ts b/src/core/asset/interfaces/visualization/color/IAssetColorLayer.ts
new file mode 100644
index 00000000..7a1372e2
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/color/IAssetColorLayer.ts
@@ -0,0 +1,4 @@
+export interface IAssetColorLayer
+{
+ color?: number;
+}
diff --git a/src/core/asset/interfaces/visualization/color/index.ts b/src/core/asset/interfaces/visualization/color/index.ts
new file mode 100644
index 00000000..00aff50c
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/color/index.ts
@@ -0,0 +1,2 @@
+export * from './IAssetColor';
+export * from './IAssetColorLayer';
diff --git a/src/core/asset/interfaces/visualization/gestures/IAssetGesture.ts b/src/core/asset/interfaces/visualization/gestures/IAssetGesture.ts
new file mode 100644
index 00000000..ddf3752f
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/gestures/IAssetGesture.ts
@@ -0,0 +1,5 @@
+export interface IAssetGesture
+{
+ id?: string;
+ animationId?: number;
+}
diff --git a/src/core/asset/interfaces/visualization/gestures/index.ts b/src/core/asset/interfaces/visualization/gestures/index.ts
new file mode 100644
index 00000000..2c6e978a
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/gestures/index.ts
@@ -0,0 +1 @@
+export * from './IAssetGesture';
diff --git a/src/core/asset/interfaces/visualization/index.ts b/src/core/asset/interfaces/visualization/index.ts
new file mode 100644
index 00000000..334bddcc
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/index.ts
@@ -0,0 +1,7 @@
+export * from './animation';
+export * from './color';
+export * from './gestures';
+export * from './IAssetVisualizationData';
+export * from './IAssetVisualizationDirection';
+export * from './IAssetVisualizationLayer';
+export * from './postures';
diff --git a/src/core/asset/interfaces/visualization/postures/IAssetPosture.ts b/src/core/asset/interfaces/visualization/postures/IAssetPosture.ts
new file mode 100644
index 00000000..33138514
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/postures/IAssetPosture.ts
@@ -0,0 +1,5 @@
+export interface IAssetPosture
+{
+ id?: string;
+ animationId?: number;
+}
diff --git a/src/core/asset/interfaces/visualization/postures/index.ts b/src/core/asset/interfaces/visualization/postures/index.ts
new file mode 100644
index 00000000..c24c1b93
--- /dev/null
+++ b/src/core/asset/interfaces/visualization/postures/index.ts
@@ -0,0 +1 @@
+export * from './IAssetPosture';
diff --git a/src/core/common/INitroManager.ts b/src/core/common/INitroManager.ts
new file mode 100644
index 00000000..d502b2b3
--- /dev/null
+++ b/src/core/common/INitroManager.ts
@@ -0,0 +1,12 @@
+import { IEventDispatcher } from '../events/IEventDispatcher';
+import { IDisposable } from './disposable/IDisposable';
+import { INitroLogger } from './logger/INitroLogger';
+
+export interface INitroManager extends IDisposable
+{
+ init(): void;
+ logger: INitroLogger;
+ events: IEventDispatcher;
+ isLoaded: boolean;
+ isLoading: boolean;
+}
\ No newline at end of file
diff --git a/src/core/common/IUpdateReceiver.ts b/src/core/common/IUpdateReceiver.ts
new file mode 100644
index 00000000..51608b4c
--- /dev/null
+++ b/src/core/common/IUpdateReceiver.ts
@@ -0,0 +1,6 @@
+import { IDisposable } from './disposable/IDisposable';
+
+export interface IUpdateReceiver extends IDisposable
+{
+ update(time: number): void;
+}
\ No newline at end of file
diff --git a/src/core/common/NitroManager.ts b/src/core/common/NitroManager.ts
new file mode 100644
index 00000000..091e175c
--- /dev/null
+++ b/src/core/common/NitroManager.ts
@@ -0,0 +1,78 @@
+import { EventDispatcher } from '../events/EventDispatcher';
+import { IEventDispatcher } from '../events/IEventDispatcher';
+import { Disposable } from './disposable/Disposable';
+import { INitroManager } from './INitroManager';
+import { INitroLogger } from './logger/INitroLogger';
+import { NitroLogger } from './logger/NitroLogger';
+
+export class NitroManager extends Disposable implements INitroManager
+{
+ private _logger: INitroLogger;
+
+ private _events: IEventDispatcher;
+
+ private _isLoaded: boolean;
+ private _isLoading: boolean;
+
+ constructor(logger: INitroLogger = null)
+ {
+ super();
+
+ this._logger = logger instanceof NitroLogger ? logger : new NitroLogger(this.constructor.name);
+
+ this._events = new EventDispatcher();
+
+ this._isLoaded = false;
+ this._isLoading = false;
+ }
+
+ public init(): void
+ {
+ if(this._isLoaded || this._isLoading || this.isDisposing) return;
+
+ this._isLoading = true;
+
+ this.onInit();
+
+ this._isLoaded = true;
+ this._isLoading = false;
+ }
+
+ protected onInit(): void
+ {
+ return;
+ }
+
+ protected onDispose(): void
+ {
+ if(this._events) this._events.dispose();
+
+ super.onDispose();
+ }
+
+ public reload(): void
+ {
+ this.dispose();
+ this.init();
+ }
+
+ public get logger(): INitroLogger
+ {
+ return this._logger;
+ }
+
+ public get events(): IEventDispatcher
+ {
+ return this._events;
+ }
+
+ public get isLoaded(): boolean
+ {
+ return this._isLoaded;
+ }
+
+ public get isLoading(): boolean
+ {
+ return this._isLoading;
+ }
+}
\ No newline at end of file
diff --git a/src/core/common/disposable/Disposable.ts b/src/core/common/disposable/Disposable.ts
new file mode 100644
index 00000000..0b77bcf7
--- /dev/null
+++ b/src/core/common/disposable/Disposable.ts
@@ -0,0 +1,40 @@
+import { IDisposable } from './IDisposable';
+
+export class Disposable implements IDisposable
+{
+ protected _isDisposed: boolean;
+ protected _isDisposing: boolean;
+
+ constructor()
+ {
+ this._isDisposed = false;
+ this._isDisposing = false;
+ }
+
+ public dispose(): void
+ {
+ if(this._isDisposed || this._isDisposing) return;
+
+ this._isDisposing = true;
+
+ this.onDispose();
+
+ this._isDisposed = true;
+ this._isDisposing = false;
+ }
+
+ protected onDispose(): void
+ {
+ return;
+ }
+
+ public get disposed(): boolean
+ {
+ return this._isDisposed;
+ }
+
+ public get isDisposing(): boolean
+ {
+ return this._isDisposing;
+ }
+}
\ No newline at end of file
diff --git a/src/core/common/disposable/IDisposable.ts b/src/core/common/disposable/IDisposable.ts
new file mode 100644
index 00000000..b9f60402
--- /dev/null
+++ b/src/core/common/disposable/IDisposable.ts
@@ -0,0 +1,5 @@
+export interface IDisposable
+{
+ dispose(): void;
+ disposed: boolean;
+}
\ No newline at end of file
diff --git a/src/core/common/disposable/index.ts b/src/core/common/disposable/index.ts
new file mode 100644
index 00000000..2edb6e9f
--- /dev/null
+++ b/src/core/common/disposable/index.ts
@@ -0,0 +1,2 @@
+export * from './Disposable';
+export * from './IDisposable';
diff --git a/src/core/common/index.ts b/src/core/common/index.ts
new file mode 100644
index 00000000..50a8f018
--- /dev/null
+++ b/src/core/common/index.ts
@@ -0,0 +1,5 @@
+export * from './disposable';
+export * from './INitroManager';
+export * from './IUpdateReceiver';
+export * from './logger';
+export * from './NitroManager';
diff --git a/src/core/common/logger/INitroLogger.ts b/src/core/common/logger/INitroLogger.ts
new file mode 100644
index 00000000..cbfd1979
--- /dev/null
+++ b/src/core/common/logger/INitroLogger.ts
@@ -0,0 +1,8 @@
+export interface INitroLogger
+{
+ log(message: string): void;
+ error(message: string, trace?: string): void;
+ warn(message: string): void;
+ description: string | number;
+ print: boolean;
+}
\ No newline at end of file
diff --git a/src/core/common/logger/NitroLogger.ts b/src/core/common/logger/NitroLogger.ts
new file mode 100644
index 00000000..d2074498
--- /dev/null
+++ b/src/core/common/logger/NitroLogger.ts
@@ -0,0 +1,89 @@
+import { INitroLogger } from './INitroLogger';
+
+export class NitroLogger implements INitroLogger
+{
+ private static LAST_TIMESTAMP: number = Date.now();
+
+ private _name: string;
+ private _description: string | number;
+ private _print: boolean;
+
+ constructor(name: string, description: string | number = null)
+ {
+ this._name = name;
+ this._description = description;
+ this._print = true;
+ }
+
+ public log(message: string): void
+ {
+ this.printMessage(message, 'log');
+ }
+
+ public error(message: string, trace?: string): void
+ {
+ this.printMessage(trace || message, 'error');
+ }
+
+ public warn(message: string): void
+ {
+ this.printMessage(message, 'warn');
+ }
+
+ public printMessage(message: string, modus: string): void
+ {
+ if(!this._print) return;
+
+ NitroLogger.log(message, this._name, modus);
+ }
+
+ public static log(message: string, name: string = 'Nitro', modus: string = null): void
+ {
+ const logString = `[Nitro] ${ new Date().toDateString() } [${ name }] ${ message } ${ this.getTimestamp() }`;
+
+ switch(modus)
+ {
+ case 'error':
+ console.error(logString);
+ break;
+ case 'warn':
+ console.warn(logString);
+ break;
+ case 'log':
+ default:
+ console.log(logString);
+ break;
+ }
+ }
+
+ public static getTimestamp(): string
+ {
+ const now = Date.now();
+
+ const result = ` +${ now - NitroLogger.LAST_TIMESTAMP || 0 }ms`;
+
+ this.LAST_TIMESTAMP = now;
+
+ return result;
+ }
+
+ public get description(): string | number
+ {
+ return this._description;
+ }
+
+ public set description(description: string | number)
+ {
+ this._description = description;
+ }
+
+ public get print(): boolean
+ {
+ return this._print;
+ }
+
+ public set print(flag: boolean)
+ {
+ this._print = flag;
+ }
+}
diff --git a/src/core/common/logger/index.ts b/src/core/common/logger/index.ts
new file mode 100644
index 00000000..147aa164
--- /dev/null
+++ b/src/core/common/logger/index.ts
@@ -0,0 +1,2 @@
+export * from './INitroLogger';
+export * from './NitroLogger';
diff --git a/src/core/communication/CommunicationManager.ts b/src/core/communication/CommunicationManager.ts
new file mode 100644
index 00000000..1ecb4b59
--- /dev/null
+++ b/src/core/communication/CommunicationManager.ts
@@ -0,0 +1,53 @@
+import { Disposable } from '../common/disposable/Disposable';
+import { IUpdateReceiver } from '../common/IUpdateReceiver';
+import { IConnection } from './connections/IConnection';
+import { IConnectionStateListener } from './connections/IConnectionStateListener';
+import { SocketConnection } from './connections/SocketConnection';
+import { ICommunicationManager } from './ICommunicationManager';
+
+export class CommunicationManager extends Disposable implements ICommunicationManager, IUpdateReceiver
+{
+ private _connections: IConnection[]
+
+ constructor()
+ {
+ super();
+
+ this._connections = [];
+ }
+
+ protected onDispose(): void
+ {
+ if(!this._connections || !this._connections.length) return;
+
+ for(const connection of this._connections.values()) connection && connection.dispose();
+ }
+
+ public createConnection(stateListener: IConnectionStateListener = null): IConnection
+ {
+ const connection = new SocketConnection(this, stateListener);
+
+ if(!connection) return;
+
+ this._connections.push(connection);
+
+ return connection;
+ }
+
+ public update(time: number): void
+ {
+ let index = 0;
+
+ while(index < this._connections.length)
+ {
+ const connection = this._connections[index];
+
+ connection.processReceivedData();
+
+ if(this.disposed) return;
+
+ if(connection.disposed) this._connections.splice(index, 1);
+ else index++;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/core/communication/ICommunicationManager.ts b/src/core/communication/ICommunicationManager.ts
new file mode 100644
index 00000000..532e0be4
--- /dev/null
+++ b/src/core/communication/ICommunicationManager.ts
@@ -0,0 +1,8 @@
+import { IDisposable } from '../common/disposable/IDisposable';
+import { IConnection } from './connections/IConnection';
+import { IConnectionStateListener } from './connections/IConnectionStateListener';
+
+export interface ICommunicationManager extends IDisposable
+{
+ createConnection(stateListener?: IConnectionStateListener): IConnection;
+}
\ No newline at end of file
diff --git a/src/core/communication/codec/BinaryReader.ts b/src/core/communication/codec/BinaryReader.ts
new file mode 100644
index 00000000..6409eb82
--- /dev/null
+++ b/src/core/communication/codec/BinaryReader.ts
@@ -0,0 +1,62 @@
+export class BinaryReader
+{
+ private _position: number;
+ private _dataView: DataView;
+
+ constructor(buffer: ArrayBuffer)
+ {
+ this._position = 0;
+ this._dataView = new DataView(buffer);
+ }
+
+ public readByte(): number
+ {
+ const byte = this._dataView.getInt8(this._position);
+
+ this._position++;
+
+ return byte;
+ }
+
+ public readBytes(length: number): BinaryReader
+ {
+ const buffer = new BinaryReader(this._dataView.buffer.slice(this._position, this._position + length));
+
+ this._position += length;
+
+ return buffer;
+ }
+
+ public readShort(): number
+ {
+ const short = this._dataView.getInt16(this._position);
+
+ this._position += 2;
+
+ return short;
+ }
+
+ public readInt(): number
+ {
+ const int = this._dataView.getInt32(this._position);
+
+ this._position += 4;
+
+ return int;
+ }
+
+ public remaining(): number
+ {
+ return this._dataView.byteLength - this._position;
+ }
+
+ public toString(encoding?: string): string
+ {
+ return new TextDecoder().decode(this._dataView.buffer);
+ }
+
+ public toArrayBuffer(): ArrayBuffer
+ {
+ return this._dataView.buffer;
+ }
+}
\ No newline at end of file
diff --git a/src/core/communication/codec/BinaryWriter.ts b/src/core/communication/codec/BinaryWriter.ts
new file mode 100644
index 00000000..8eae1ef7
--- /dev/null
+++ b/src/core/communication/codec/BinaryWriter.ts
@@ -0,0 +1,94 @@
+export class BinaryWriter
+{
+ private _buffer: Uint8Array;
+
+ constructor()
+ {
+ this._buffer = new Uint8Array();
+ }
+
+ public writeByte(byte: number): BinaryWriter
+ {
+ const array = new Uint8Array(1);
+
+ array[0] = byte;
+
+ this.appendArray(array);
+
+ return this;
+ }
+
+ public writeBytes(bytes: ArrayBuffer): BinaryWriter
+ {
+ const array = new Uint8Array(bytes);
+
+ this.appendArray(array);
+
+ return this;
+ }
+
+ public writeShort(short: number): BinaryWriter
+ {
+ const array = new Uint8Array(2);
+
+ array[0] = short >> 8;
+ array[1] = short & 0xFF;
+
+ this.appendArray(array);
+
+ return this;
+ }
+
+ public writeInt(integer: number): BinaryWriter
+ {
+ const array = new Uint8Array(4);
+
+ array[0] = integer >> 24;
+ array[1] = integer >> 16;
+ array[2] = integer >> 8;
+ array[3] = integer & 0xFF;
+
+ this.appendArray(array);
+
+ return this;
+ }
+
+ public writeString(string: string, includeLength: boolean = true): BinaryWriter
+ {
+ const array = new TextEncoder().encode(string);
+
+ if(includeLength)
+ {
+ this.writeShort(array.length);
+ this.appendArray(array);
+ }
+ else
+ {
+ this.appendArray(array);
+ }
+
+ return this;
+ }
+
+ private appendArray(array: Uint8Array): void
+ {
+ if(!array) return;
+
+ const mergedArray = new Uint8Array(this._buffer.length + array.length);
+
+ mergedArray.set(this._buffer);
+ mergedArray.set(array, this._buffer.length);
+
+ this._buffer = mergedArray;
+ }
+
+ public getBuffer(): ArrayBuffer
+ {
+ return this._buffer.buffer;
+ }
+
+ public toString(encoding?: string): string
+ {
+ return new TextDecoder(encoding).decode(this._buffer);
+ }
+}
\ No newline at end of file
diff --git a/src/core/communication/codec/Byte.ts b/src/core/communication/codec/Byte.ts
new file mode 100644
index 00000000..dbcb29cd
--- /dev/null
+++ b/src/core/communication/codec/Byte.ts
@@ -0,0 +1,14 @@
+export class Byte
+{
+ private _value: number;
+
+ constructor(value: number)
+ {
+ this._value = value;
+ }
+
+ public get value(): number
+ {
+ return this._value;
+ }
+}
\ No newline at end of file
diff --git a/src/core/communication/codec/ICodec.ts b/src/core/communication/codec/ICodec.ts
new file mode 100644
index 00000000..824d7f80
--- /dev/null
+++ b/src/core/communication/codec/ICodec.ts
@@ -0,0 +1,9 @@
+import { BinaryWriter } from './BinaryWriter';
+import { IConnection } from '../connections/IConnection';
+import { IMessageDataWrapper } from '../messages/IMessageDataWrapper';
+
+export interface ICodec
+{
+ encode(header: number, messages: any[]): BinaryWriter;
+ decode(connection: IConnection): IMessageDataWrapper[];
+}
\ No newline at end of file
diff --git a/src/core/communication/codec/Short.ts b/src/core/communication/codec/Short.ts
new file mode 100644
index 00000000..f23125e4
--- /dev/null
+++ b/src/core/communication/codec/Short.ts
@@ -0,0 +1,14 @@
+export class Short
+{
+ private _value: number;
+
+ constructor(value: number)
+ {
+ this._value = value;
+ }
+
+ public get value(): number
+ {
+ return this._value;
+ }
+}
\ No newline at end of file
diff --git a/src/core/communication/codec/evawire/EvaWireDataWrapper.ts b/src/core/communication/codec/evawire/EvaWireDataWrapper.ts
new file mode 100644
index 00000000..c03c45e1
--- /dev/null
+++ b/src/core/communication/codec/evawire/EvaWireDataWrapper.ts
@@ -0,0 +1,65 @@
+import { IMessageDataWrapper } from '../../messages/IMessageDataWrapper';
+import { BinaryReader } from '../BinaryReader';
+
+export class EvaWireDataWrapper implements IMessageDataWrapper
+{
+ private _header: number;
+ private _buffer: BinaryReader;
+
+ constructor(header: number, buffer: BinaryReader)
+ {
+ this._header = header;
+ this._buffer = buffer;
+ }
+
+ public readByte(): number
+ {
+ if(!this._buffer) return -1;
+
+ return this._buffer.readByte();
+ }
+
+ public readBytes(length: number): BinaryReader
+ {
+ if(!this._buffer) return null;
+
+ return this._buffer.readBytes(length);
+ }
+
+ public readBoolean(): boolean
+ {
+ return (this.readByte() === 1);
+ }
+
+ public readShort(): number
+ {
+ if(!this._buffer) return -1;
+
+ return this._buffer.readShort();
+ }
+
+ public readInt(): number
+ {
+ if(!this._buffer) return -1;
+
+ return this._buffer.readInt();
+ }
+
+ public readString(): string
+ {
+ const length = this.readShort();
+ const buffer = this._buffer.readBytes(length);
+
+ return buffer.toString('utf8');
+ }
+
+ public get header(): number
+ {
+ return this._header;
+ }
+
+ public get bytesAvailable(): boolean
+ {
+ return (this._buffer && (this._buffer.remaining() > 0));
+ }
+}
\ No newline at end of file
diff --git a/src/core/communication/codec/evawire/EvaWireFormat.ts b/src/core/communication/codec/evawire/EvaWireFormat.ts
new file mode 100644
index 00000000..d591e09c
--- /dev/null
+++ b/src/core/communication/codec/evawire/EvaWireFormat.ts
@@ -0,0 +1,87 @@
+import { IConnection } from '../../connections/IConnection';
+import { IMessageDataWrapper } from '../../messages/IMessageDataWrapper';
+import { BinaryReader } from '../BinaryReader';
+import { BinaryWriter } from '../BinaryWriter';
+import { Byte } from '../Byte';
+import { ICodec } from '../ICodec';
+import { Short } from '../Short';
+import { EvaWireDataWrapper } from './EvaWireDataWrapper';
+
+export class EvaWireFormat implements ICodec
+{
+ public encode(header: number, messages: any[]): BinaryWriter
+ {
+ const writer = new BinaryWriter();
+
+ writer.writeShort(header);
+
+ for(const value of messages)
+ {
+ let type: string = typeof value;
+
+ if(type === 'object')
+ {
+ if(value === null) type = 'null';
+ else if(value instanceof Byte) type = 'byte';
+ else if(value instanceof Short) type = 'short';
+ }
+
+ switch(type)
+ {
+ case 'null':
+ writer.writeShort(0);
+ break;
+ case 'byte':
+ writer.writeByte(value.value);
+ break;
+ case 'short':
+ writer.writeShort(value.value);
+ break;
+ case 'number':
+ writer.writeInt(value);
+ break;
+ case 'boolean':
+ writer.writeByte(value ? 1 : 0);
+ break;
+ case 'string':
+ if(!value) writer.writeShort(0);
+ else
+ {
+ writer.writeString(value, true);
+ }
+ break;
+ }
+ }
+
+ const buffer = writer.getBuffer();
+
+ if(!buffer) return null;
+
+ return new BinaryWriter().writeInt(buffer.byteLength).writeBytes(buffer);
+ }
+
+ public decode(connection: IConnection): IMessageDataWrapper[]
+ {
+ if(!connection || !connection.dataBuffer || !connection.dataBuffer.byteLength) return null;
+
+ const wrappers: IMessageDataWrapper[] = [];
+
+ while(connection.dataBuffer.byteLength)
+ {
+ if(connection.dataBuffer.byteLength < 4) break;
+
+ const container = new BinaryReader(connection.dataBuffer);
+ const length = container.readInt();
+
+ if(length > (connection.dataBuffer.byteLength - 4)) break;
+
+ const extracted = container.readBytes(length);
+
+ wrappers.push(new EvaWireDataWrapper(extracted.readShort(), extracted));
+
+ connection.dataBuffer = connection.dataBuffer.slice(length + 4);
+ }
+
+ return wrappers;
+ }
+}
\ No newline at end of file
diff --git a/src/core/communication/codec/evawire/index.ts b/src/core/communication/codec/evawire/index.ts
new file mode 100644
index 00000000..6b63cda9
--- /dev/null
+++ b/src/core/communication/codec/evawire/index.ts
@@ -0,0 +1,2 @@
+export * from './EvaWireDataWrapper';
+export * from './EvaWireFormat';
diff --git a/src/core/communication/codec/index.ts b/src/core/communication/codec/index.ts
new file mode 100644
index 00000000..ae6e3432
--- /dev/null
+++ b/src/core/communication/codec/index.ts
@@ -0,0 +1,6 @@
+export * from './BinaryReader';
+export * from './BinaryWriter';
+export * from './Byte';
+export * from './evawire';
+export * from './ICodec';
+export * from './Short';
diff --git a/src/core/communication/connections/IConnection.ts b/src/core/communication/connections/IConnection.ts
new file mode 100644
index 00000000..a00a07db
--- /dev/null
+++ b/src/core/communication/connections/IConnection.ts
@@ -0,0 +1,19 @@
+import { IEventDispatcher } from '../../events/IEventDispatcher';
+import { IMessageComposer } from '../messages/IMessageComposer';
+import { IMessageConfiguration } from '../messages/IMessageConfiguration';
+import { IMessageEvent } from '../messages/IMessageEvent';
+
+export interface IConnection extends IEventDispatcher
+{
+ init(socketUrl: string): void;
+ dispose(): void;
+ onReady(): void;
+ authenticated(): void;
+ send(...composers: IMessageComposer[]): void;
+ processReceivedData(): void;
+ registerMessages(configuration: IMessageConfiguration): void;
+ addMessageEvent(event: IMessageEvent): void;
+ removeMessageEvent(event: IMessageEvent): void;
+ isAuthenticated: boolean;
+ dataBuffer: ArrayBuffer;
+}
\ No newline at end of file
diff --git a/src/core/communication/connections/IConnectionStateListener.ts b/src/core/communication/connections/IConnectionStateListener.ts
new file mode 100644
index 00000000..d140fd03
--- /dev/null
+++ b/src/core/communication/connections/IConnectionStateListener.ts
@@ -0,0 +1,4 @@
+export interface IConnectionStateListener
+{
+ connectionInit(socketUrl: string): void;
+}
\ No newline at end of file
diff --git a/src/core/communication/connections/SocketConnection.ts b/src/core/communication/connections/SocketConnection.ts
new file mode 100644
index 00000000..3114ef41
--- /dev/null
+++ b/src/core/communication/connections/SocketConnection.ts
@@ -0,0 +1,368 @@
+import { Nitro } from '../../../nitro/Nitro';
+import { NitroLogger } from '../../common/logger/NitroLogger';
+import { EventDispatcher } from '../../events/EventDispatcher';
+import { EvaWireFormat } from '../codec/evawire/EvaWireFormat';
+import { ICodec } from '../codec/ICodec';
+import { SocketConnectionEvent } from '../events/SocketConnectionEvent';
+import { ICommunicationManager } from '../ICommunicationManager';
+import { IMessageComposer } from '../messages/IMessageComposer';
+import { IMessageConfiguration } from '../messages/IMessageConfiguration';
+import { IMessageDataWrapper } from '../messages/IMessageDataWrapper';
+import { IMessageEvent } from '../messages/IMessageEvent';
+import { MessageClassManager } from '../messages/MessageClassManager';
+import { WebSocketEventEnum } from './enums/WebSocketEventEnum';
+import { IConnection } from './IConnection';
+import { IConnectionStateListener } from './IConnectionStateListener';
+
+export class SocketConnection extends EventDispatcher implements IConnection
+{
+ private _communicationManager: ICommunicationManager;
+ private _stateListener: IConnectionStateListener;
+ private _socket: WebSocket;
+ private _messages: MessageClassManager;
+ private _codec: ICodec;
+ private _dataBuffer: ArrayBuffer;
+ private _isReady: boolean;
+
+ private _pendingClientMessages: IMessageComposer[];
+ private _pendingServerMessages: IMessageDataWrapper[];
+
+ private _isAuthenticated: boolean;
+
+ constructor(communicationManager: ICommunicationManager, stateListener: IConnectionStateListener)
+ {
+ super();
+
+ this._communicationManager = communicationManager;
+ this._stateListener = stateListener;
+ this._socket = null;
+ this._messages = new MessageClassManager();
+ this._codec = new EvaWireFormat();
+ this._dataBuffer = null;
+ this._isReady = false;
+
+ this._pendingClientMessages = [];
+ this._pendingServerMessages = [];
+
+ this._isAuthenticated = false;
+
+ this.onOpen = this.onOpen.bind(this);
+ this.onClose = this.onClose.bind(this);
+ this.onError = this.onError.bind(this);
+ this.onMessage = this.onMessage.bind(this);
+ }
+
+ public init(socketUrl: string): void
+ {
+ if(this._stateListener)
+ {
+ this._stateListener.connectionInit(socketUrl);
+ }
+
+ this.createSocket(socketUrl);
+ }
+
+ protected onDispose(): void
+ {
+ super.onDispose();
+
+ this.destroySocket();
+
+ this._communicationManager = null;
+ this._stateListener = null;
+ this._messages = null;
+ this._codec = null;
+ this._dataBuffer = null;
+ }
+
+ public onReady(): void
+ {
+ if(this._isReady) return;
+
+ this._isReady = true;
+
+ if(this._pendingServerMessages && this._pendingServerMessages.length) this.processWrappers(...this._pendingServerMessages);
+
+ if(this._pendingClientMessages && this._pendingClientMessages.length) this.send(...this._pendingClientMessages);
+
+ this._pendingServerMessages = [];
+ this._pendingClientMessages = [];
+ }
+
+ private createSocket(socketUrl: string): void
+ {
+ if(!socketUrl) return;
+
+ this.destroySocket();
+
+ this._dataBuffer = new ArrayBuffer(0);
+ this._socket = new WebSocket(socketUrl);
+
+ this._socket.addEventListener(WebSocketEventEnum.CONNECTION_OPENED, this.onOpen);
+ this._socket.addEventListener(WebSocketEventEnum.CONNECTION_CLOSED, this.onClose);
+ this._socket.addEventListener(WebSocketEventEnum.CONNECTION_ERROR, this.onError);
+ this._socket.addEventListener(WebSocketEventEnum.CONNECTION_MESSAGE, this.onMessage);
+ }
+
+ private destroySocket(): void
+ {
+ if(!this._socket) return;
+
+ this._socket.removeEventListener(WebSocketEventEnum.CONNECTION_OPENED, this.onOpen);
+ this._socket.removeEventListener(WebSocketEventEnum.CONNECTION_CLOSED, this.onClose);
+ this._socket.removeEventListener(WebSocketEventEnum.CONNECTION_ERROR, this.onError);
+ this._socket.removeEventListener(WebSocketEventEnum.CONNECTION_MESSAGE, this.onMessage);
+
+ if(this._socket.readyState === WebSocket.OPEN) this._socket.close();
+
+ this._socket = null;
+ }
+
+ private onOpen(event: Event): void
+ {
+ this.dispatchConnectionEvent(SocketConnectionEvent.CONNECTION_OPENED, event);
+ }
+
+ private onClose(event: CloseEvent): void
+ {
+ this.dispatchConnectionEvent(SocketConnectionEvent.CONNECTION_CLOSED, event);
+ }
+
+ private onError(event: Event): void
+ {
+ this.dispatchConnectionEvent(SocketConnectionEvent.CONNECTION_ERROR, event);
+ }
+
+ private onMessage(event: MessageEvent): void
+ {
+ if(!event) return;
+
+ this.dispatchConnectionEvent(SocketConnectionEvent.CONNECTION_MESSAGE, event);
+
+ const reader = new FileReader();
+
+ reader.readAsArrayBuffer(event.data);
+
+ reader.onloadend = () =>
+ {
+ this._dataBuffer = this.concatArrayBuffers(this._dataBuffer, (reader.result as ArrayBuffer));
+
+ this.processReceivedData();
+ };
+ }
+
+ private dispatchConnectionEvent(type: string, event: Event): void
+ {
+ this.dispatchEvent(new SocketConnectionEvent(type, this, event));
+ }
+
+ public authenticated(): void
+ {
+ this._isAuthenticated = true;
+ }
+
+ public send(...composers: IMessageComposer[]): boolean
+ {
+ if(this.disposed || !composers) return false;
+
+ composers = [ ...composers ];
+
+ if(this._isAuthenticated && !this._isReady)
+ {
+ if(!this._pendingClientMessages) this._pendingClientMessages = [];
+
+ this._pendingClientMessages.push(...composers);
+
+ return false;
+ }
+
+ for(const composer of composers)
+ {
+ if(!composer) continue;
+
+ const header = this._messages.getComposerId(composer);
+
+ if(header === -1)
+ {
+ NitroLogger.log(`Unknown Composer: ${ composer.constructor.name }`);
+
+ continue;
+ }
+
+ const message = composer.getMessageArray();
+ const encoded = this._codec.encode(header, message);
+
+ if(!encoded)
+ {
+ if(Nitro.instance.getConfiguration('communication.packet.log')) console.log(`Encoding Failed: ${ composer.constructor.name }`);
+
+ continue;
+ }
+
+ if(Nitro.instance.getConfiguration('communication.packet.log')) console.log(`OutgoingComposer: [${ header }] ${ composer.constructor.name }`, message);
+
+ this.write(encoded.getBuffer());
+ }
+
+ return true;
+ }
+
+ private write(buffer: ArrayBuffer): void
+ {
+ if(this._socket.readyState !== WebSocket.OPEN) return;
+
+ this._socket.send(buffer);
+ }
+
+ public processReceivedData(): void
+ {
+ try
+ {
+ this.processData();
+ }
+
+ catch (err)
+ {
+ NitroLogger.log(err);
+ }
+ }
+
+ private processData(): void
+ {
+ const wrappers = this.splitReceivedMessages();
+
+ if(!wrappers || !wrappers.length) return;
+
+ if(this._isAuthenticated && !this._isReady)
+ {
+ if(!this._pendingServerMessages) this._pendingServerMessages = [];
+
+ this._pendingServerMessages.push(...wrappers);
+
+ return;
+ }
+
+ this.processWrappers(...wrappers);
+ }
+
+ private processWrappers(...wrappers: IMessageDataWrapper[]): void
+ {
+ if(!wrappers || !wrappers.length) return;
+
+ for(const wrapper of wrappers)
+ {
+ if(!wrapper) continue;
+
+ const messages = this.getMessagesForWrapper(wrapper);
+
+ if(!messages || !messages.length) continue;
+
+ if(Nitro.instance.getConfiguration('communication.packet.log'))
+ {
+ console.log(`IncomingMessage: [${ wrapper.header }] ${ messages[0].constructor.name }`, messages[0].parser);
+ }
+
+ this.handleMessages(...messages);
+ }
+ }
+
+ private splitReceivedMessages(): IMessageDataWrapper[]
+ {
+ if(!this._dataBuffer || !this._dataBuffer.byteLength) return null;
+
+ return this._codec.decode(this);
+ }
+
+ private concatArrayBuffers(buffer1: ArrayBuffer, buffer2: ArrayBuffer): ArrayBuffer
+ {
+ const array = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
+
+ array.set(new Uint8Array(buffer1), 0);
+ array.set(new Uint8Array(buffer2), buffer1.byteLength);
+
+ return array.buffer;
+ }
+
+ private getMessagesForWrapper(wrapper: IMessageDataWrapper): IMessageEvent[]
+ {
+ if(!wrapper) return null;
+
+ const events = this._messages.getEvents(wrapper.header);
+
+ if(!events || !events.length)
+ {
+ if(Nitro.instance.getConfiguration('communication.packet.log'))
+ {
+ console.log(`IncomingMessage: [${ wrapper.header }] UNREGISTERED`, wrapper);
+ }
+
+ return;
+ }
+
+ try
+ {
+ const parser = events[0].parser;
+
+ if(!parser || !parser.flush() || !parser.parse(wrapper)) return null;
+ }
+
+ catch (e)
+ {
+ NitroLogger.log(`Error parsing message: ${ e }`, events[0].constructor.name);
+
+ return null;
+ }
+
+ return events;
+ }
+
+ private handleMessages(...messages: IMessageEvent[]): void
+ {
+ messages = [ ...messages ];
+
+ for(const message of messages)
+ {
+ if(!message) continue;
+
+ message.connection = this;
+
+ if(message.callBack) message.callBack(message);
+ }
+ }
+
+ public registerMessages(configuration: IMessageConfiguration): void
+ {
+ if(!configuration) return;
+
+ this._messages.registerMessages(configuration);
+ }
+
+ public addMessageEvent(event: IMessageEvent): void
+ {
+ if(!event || !this._messages) return;
+
+ this._messages.registerMessageEvent(event);
+ }
+
+ public removeMessageEvent(event: IMessageEvent): void
+ {
+ if(!event || !this._messages) return;
+
+ this._messages.removeMessageEvent(event);
+ }
+
+ public get isAuthenticated(): boolean
+ {
+ return this._isAuthenticated;
+ }
+
+ public get dataBuffer(): ArrayBuffer
+ {
+ return this._dataBuffer;
+ }
+
+ public set dataBuffer(buffer: ArrayBuffer)
+ {
+ this._dataBuffer = buffer;
+ }
+}
diff --git a/src/core/communication/connections/enums/ClientDeviceCategoryEnum.ts b/src/core/communication/connections/enums/ClientDeviceCategoryEnum.ts
new file mode 100644
index 00000000..01619fef
--- /dev/null
+++ b/src/core/communication/connections/enums/ClientDeviceCategoryEnum.ts
@@ -0,0 +1,5 @@
+export class ClientDeviceCategoryEnum
+{
+ public static UNKNOWN: number = 0;
+ public static BROWSER: number = 1;
+}
\ No newline at end of file
diff --git a/src/core/communication/connections/enums/ClientPlatformEnum.ts b/src/core/communication/connections/enums/ClientPlatformEnum.ts
new file mode 100644
index 00000000..e74abddd
--- /dev/null
+++ b/src/core/communication/connections/enums/ClientPlatformEnum.ts
@@ -0,0 +1,7 @@
+export class ClientPlatformEnum
+{
+ public static UNKNOWN: number = 0;
+ public static FLASH: number = 1;
+ public static HTML5: number = 2;
+
+}
\ No newline at end of file
diff --git a/src/core/communication/connections/enums/WebSocketEventEnum.ts b/src/core/communication/connections/enums/WebSocketEventEnum.ts
new file mode 100644
index 00000000..36a3c458
--- /dev/null
+++ b/src/core/communication/connections/enums/WebSocketEventEnum.ts
@@ -0,0 +1,7 @@
+export class WebSocketEventEnum
+{
+ public static CONNECTION_OPENED = 'open';
+ public static CONNECTION_CLOSED = 'close';
+ public static CONNECTION_ERROR = 'error';
+ public static CONNECTION_MESSAGE = 'message';
+}
\ No newline at end of file
diff --git a/src/core/communication/connections/enums/index.ts b/src/core/communication/connections/enums/index.ts
new file mode 100644
index 00000000..42a22708
--- /dev/null
+++ b/src/core/communication/connections/enums/index.ts
@@ -0,0 +1,3 @@
+export * from './ClientDeviceCategoryEnum';
+export * from './ClientPlatformEnum';
+export * from './WebSocketEventEnum';
diff --git a/src/core/communication/connections/index.ts b/src/core/communication/connections/index.ts
new file mode 100644
index 00000000..a8e8e168
--- /dev/null
+++ b/src/core/communication/connections/index.ts
@@ -0,0 +1,4 @@
+export * from './enums';
+export * from './IConnection';
+export * from './IConnectionStateListener';
+export * from './SocketConnection';
diff --git a/src/core/communication/events/SocketConnectionEvent.ts b/src/core/communication/events/SocketConnectionEvent.ts
new file mode 100644
index 00000000..51a18fec
--- /dev/null
+++ b/src/core/communication/events/SocketConnectionEvent.ts
@@ -0,0 +1,31 @@
+import { NitroEvent } from '../../events/NitroEvent';
+import { IConnection } from '../connections/IConnection';
+
+export class SocketConnectionEvent extends NitroEvent
+{
+ public static CONNECTION_OPENED = 'SCE_OPEN';
+ public static CONNECTION_CLOSED = 'SCE_CLOSED';
+ public static CONNECTION_ERROR = 'SCE_ERROR';
+ public static CONNECTION_MESSAGE = 'SCE_MESSAGE';
+
+ private _connection: IConnection;
+ private _originalEvent: Event;
+
+ constructor(type: string, connection: IConnection, originalEvent: Event)
+ {
+ super(type);
+
+ this._connection = connection;
+ this._originalEvent = event;
+ }
+
+ public get connection(): IConnection
+ {
+ return this._connection;
+ }
+
+ public get originalEvent(): Event
+ {
+ return this._originalEvent;
+ }
+}
\ No newline at end of file
diff --git a/src/core/communication/events/index.ts b/src/core/communication/events/index.ts
new file mode 100644
index 00000000..1093b131
--- /dev/null
+++ b/src/core/communication/events/index.ts
@@ -0,0 +1 @@
+export * from './SocketConnectionEvent';
diff --git a/src/core/communication/index.ts b/src/core/communication/index.ts
new file mode 100644
index 00000000..b34d744e
--- /dev/null
+++ b/src/core/communication/index.ts
@@ -0,0 +1,6 @@
+export * from './codec';
+export * from './CommunicationManager';
+export * from './connections';
+export * from './events';
+export * from './ICommunicationManager';
+export * from './messages';
diff --git a/src/core/communication/messages/IMessageComposer.ts b/src/core/communication/messages/IMessageComposer.ts
new file mode 100644
index 00000000..eb09bc82
--- /dev/null
+++ b/src/core/communication/messages/IMessageComposer.ts
@@ -0,0 +1,5 @@
+export interface IMessageComposer
+{
+ dispose(): void;
+ getMessageArray(): T;
+}
\ No newline at end of file
diff --git a/src/core/communication/messages/IMessageConfiguration.ts b/src/core/communication/messages/IMessageConfiguration.ts
new file mode 100644
index 00000000..03efd30a
--- /dev/null
+++ b/src/core/communication/messages/IMessageConfiguration.ts
@@ -0,0 +1,5 @@
+export interface IMessageConfiguration
+{
+ events: Map;
+ composers: Map;
+}
\ No newline at end of file
diff --git a/src/core/communication/messages/IMessageDataWrapper.ts b/src/core/communication/messages/IMessageDataWrapper.ts
new file mode 100644
index 00000000..0623d859
--- /dev/null
+++ b/src/core/communication/messages/IMessageDataWrapper.ts
@@ -0,0 +1,13 @@
+import { BinaryReader } from '../codec/BinaryReader';
+
+export interface IMessageDataWrapper
+{
+ readByte(): number;
+ readBytes(length: number): BinaryReader;
+ readBoolean(): boolean;
+ readShort(): number;
+ readInt(): number;
+ readString(): string;
+ header: number;
+ bytesAvailable: boolean;
+}
\ No newline at end of file
diff --git a/src/core/communication/messages/IMessageEvent.ts b/src/core/communication/messages/IMessageEvent.ts
new file mode 100644
index 00000000..58b802d9
--- /dev/null
+++ b/src/core/communication/messages/IMessageEvent.ts
@@ -0,0 +1,11 @@
+import { IConnection } from '../connections/IConnection';
+import { IMessageParser } from './IMessageParser';
+
+export interface IMessageEvent
+{
+ dispose(): void;
+ callBack: Function;
+ parserClass: Function;
+ parser: IMessageParser;
+ connection: IConnection;
+}
\ No newline at end of file
diff --git a/src/core/communication/messages/IMessageParser.ts b/src/core/communication/messages/IMessageParser.ts
new file mode 100644
index 00000000..f10a50d5
--- /dev/null
+++ b/src/core/communication/messages/IMessageParser.ts
@@ -0,0 +1,7 @@
+import { IMessageDataWrapper } from './IMessageDataWrapper';
+
+export interface IMessageParser
+{
+ flush(): boolean;
+ parse(wrapper: IMessageDataWrapper): boolean;
+}
\ No newline at end of file
diff --git a/src/core/communication/messages/MessageClassManager.ts b/src/core/communication/messages/MessageClassManager.ts
new file mode 100644
index 00000000..c5dbdb0d
--- /dev/null
+++ b/src/core/communication/messages/MessageClassManager.ts
@@ -0,0 +1,145 @@
+import { IMessageComposer } from './IMessageComposer';
+import { IMessageConfiguration } from './IMessageConfiguration';
+import { IMessageEvent } from './IMessageEvent';
+import { MessageEvent } from './MessageEvent';
+
+export class MessageClassManager
+{
+ private _messageIdByEvent: Map;
+ private _messageIdByComposer: Map;
+ private _messageInstancesById: Map;
+
+ constructor()
+ {
+ this._messageIdByEvent = new Map();
+ this._messageIdByComposer = new Map();
+ this._messageInstancesById = new Map();
+ }
+
+ public dispose(): void
+ {
+ this._messageIdByEvent.clear();
+ this._messageIdByComposer.clear();
+ this._messageInstancesById.clear();
+ }
+
+ public registerMessages(configuration: IMessageConfiguration): void
+ {
+ for(const [ header, handler ] of configuration.events) this.registerMessageEventClass(header, handler);
+
+ for(const [ header, handler ] of configuration.composers) this.registerMessageComposerClass(header, handler);
+ }
+
+ private registerMessageEventClass(header: number, handler: Function): void
+ {
+ if(!header || !handler) return;
+
+ const existing = this._messageIdByEvent.get(handler);
+
+ if(existing) return;
+
+ this._messageIdByEvent.set(handler, header);
+ }
+
+ private registerMessageComposerClass(header: number, handler: Function): void
+ {
+ if(!header || !handler) return;
+
+ const existing = this._messageIdByComposer.get(handler);
+
+ if(existing) return;
+
+ this._messageIdByComposer.set(handler, header);
+ }
+
+ public registerMessageEvent(event: IMessageEvent): void
+ {
+ if(!event) return;
+
+ const header = this.getEventId(event);
+
+ if(!header) return;
+
+ let existing = this._messageInstancesById.get(header);
+
+ if(!existing || !existing.length)
+ {
+ existing = [];
+
+ this._messageInstancesById.set(header, existing);
+
+ //@ts-ignore
+ event.parser = new event.parserClass();
+ }
+ else
+ {
+ event.parser = existing[0].parser;
+ }
+
+ existing.push(event);
+ }
+
+ public removeMessageEvent(event: IMessageEvent): void
+ {
+ if(!event) return;
+
+ const header = this.getEventId(event);
+
+ if(!header) return;
+
+ const existing = this._messageInstancesById.get(header);
+
+ if(!existing) return;
+
+ for(const [ index, message ] of existing.entries())
+ {
+ if(!message) continue;
+
+ if(message !== event) continue;
+
+ existing.splice(index, 1);
+
+ if(existing.length === 0) this._messageInstancesById.delete(header);
+
+ message.dispose();
+
+ return;
+ }
+ }
+
+ public getEvents(header: number): IMessageEvent[]
+ {
+ if(!header) return;
+
+ const existing = this._messageInstancesById.get(header);
+
+ if(!existing) return;
+
+ return existing;
+ }
+
+ public getEventId(event: IMessageEvent): number
+ {
+ if(!event) return -1;
+
+ //@ts-ignore
+ const name = (event instanceof MessageEvent ? event.constructor : event) as Function;
+
+ const existing = this._messageIdByEvent.get(name);
+
+ if(!existing) return -1;
+
+ return existing;
+ }
+
+ public getComposerId(composer: IMessageComposer): number
+ {
+ if(!composer) return -1;
+
+ const existing = this._messageIdByComposer.get(composer.constructor);
+
+ if(!existing) return -1;
+
+ return existing;
+ }
+}
diff --git a/src/core/communication/messages/MessageEvent.ts b/src/core/communication/messages/MessageEvent.ts
new file mode 100644
index 00000000..0c66b659
--- /dev/null
+++ b/src/core/communication/messages/MessageEvent.ts
@@ -0,0 +1,57 @@
+import { IConnection } from '../connections/IConnection';
+import { IMessageEvent } from './IMessageEvent';
+import { IMessageParser } from './IMessageParser';
+
+export class MessageEvent implements IMessageEvent
+{
+ private _callBack: Function;
+ private _parserClass: Function;
+ private _parser: IMessageParser;
+ private _connection: IConnection;
+
+ constructor(callBack: Function, parser: { new(): IMessageParser })
+ {
+ this._callBack = callBack;
+ this._parserClass = parser;
+ this._parser = null;
+ this._connection = null;
+ }
+
+ public dispose(): void
+ {
+ this._callBack = null;
+ this._parserClass = null;
+ this._parser = null;
+ this._connection = null;
+ }
+
+ public get callBack(): Function
+ {
+ return this._callBack;
+ }
+
+ public get parserClass(): Function
+ {
+ return this._parserClass;
+ }
+
+ public get parser(): IMessageParser
+ {
+ return this._parser;
+ }
+
+ public set parser(parser: IMessageParser)
+ {
+ this._parser = parser;
+ }
+
+ public get connection(): IConnection
+ {
+ return this._connection;
+ }
+
+ public set connection(connection: IConnection)
+ {
+ this._connection = connection;
+ }
+}
\ No newline at end of file
diff --git a/src/core/communication/messages/index.ts b/src/core/communication/messages/index.ts
new file mode 100644
index 00000000..5cc8eb81
--- /dev/null
+++ b/src/core/communication/messages/index.ts
@@ -0,0 +1,7 @@
+export * from './IMessageComposer';
+export * from './IMessageConfiguration';
+export * from './IMessageDataWrapper';
+export * from './IMessageEvent';
+export * from './IMessageParser';
+export * from './MessageClassManager';
+export * from './MessageEvent';
diff --git a/src/core/configuration/ConfigurationEvent.ts b/src/core/configuration/ConfigurationEvent.ts
new file mode 100644
index 00000000..959fa8e4
--- /dev/null
+++ b/src/core/configuration/ConfigurationEvent.ts
@@ -0,0 +1,12 @@
+import { NitroEvent } from '../events/NitroEvent';
+
+export class ConfigurationEvent extends NitroEvent
+{
+ public static LOADED: string = 'NCE_LOADED';
+ public static FAILED: string = 'NCE_FAILED';
+
+ constructor(type: string)
+ {
+ super(type);
+ }
+}
\ No newline at end of file
diff --git a/src/core/configuration/ConfigurationManager.ts b/src/core/configuration/ConfigurationManager.ts
new file mode 100644
index 00000000..bcd93c31
--- /dev/null
+++ b/src/core/configuration/ConfigurationManager.ts
@@ -0,0 +1,137 @@
+import { NitroManager } from '../common/NitroManager';
+import { AdvancedMap } from '../utils/AdvancedMap';
+import { ConfigurationEvent } from './ConfigurationEvent';
+import { IConfigurationManager } from './IConfigurationManager';
+
+export class ConfigurationManager extends NitroManager implements IConfigurationManager
+{
+ private _definitions: AdvancedMap;
+
+ constructor()
+ {
+ super();
+
+ this._definitions = new AdvancedMap();
+
+ this.onConfigurationLoaded = this.onConfigurationLoaded.bind(this);
+ }
+
+ protected onInit(): void
+ {
+ //@ts-ignore
+ this.loadConfigurationFromUrl(NitroConfig.configurationUrl);
+ }
+
+ public loadConfigurationFromUrl(url: string): void
+ {
+ if(!url || (url === ''))
+ {
+ this.dispatchConfigurationEvent(ConfigurationEvent.FAILED);
+
+ return;
+ }
+
+ fetch(url)
+ .then(response => response.json())
+ .then(data => this.onConfigurationLoaded(data))
+ .catch(err => this.onConfigurationFailed(err));
+ }
+
+ private onConfigurationLoaded(data: { [index: string]: any }): void
+ {
+ if(!data) return;
+
+ if(this.parseConfiguration(data))
+ {
+ this.dispatchConfigurationEvent(ConfigurationEvent.LOADED);
+
+ return;
+ }
+
+ this.dispatchConfigurationEvent(ConfigurationEvent.FAILED);
+ }
+
+ private onConfigurationFailed(error: Error): void
+ {
+ this.dispatchConfigurationEvent(ConfigurationEvent.FAILED);
+ }
+
+ private dispatchConfigurationEvent(type: string): void
+ {
+ this.events && this.events.dispatchEvent(new ConfigurationEvent(type));
+ }
+
+ private parseConfiguration(data: { [index: string]: any }): boolean
+ {
+ if(!data) return false;
+
+ try
+ {
+ const regex = new RegExp(/\${(.*?)}/g);
+
+ for(const key in data)
+ {
+ let value = data[key];
+
+ if(typeof value === 'string')
+ {
+ value = this.interpolate((value as string), regex);
+ }
+
+ this._definitions.add(key, value);
+ }
+
+ return true;
+ }
+
+ catch (e)
+ {
+ this.logger.error(e.stack);
+
+ return false;
+ }
+ }
+
+ public interpolate(value: string, regex: RegExp = null): string
+ {
+ if(!regex) regex = new RegExp(/\${(.*?)}/g);
+
+ const pieces = value.match(regex);
+
+ if(pieces && pieces.length)
+ {
+ for(const piece of pieces)
+ {
+ const existing = (this._definitions.getValue(this.removeInterpolateKey(piece)) as string);
+
+ if(existing) (value = value.replace(piece, existing));
+ }
+ }
+
+ return value;
+ }
+
+ private removeInterpolateKey(value: string): string
+ {
+ return value.replace('${', '').replace('}', '');
+ }
+
+ public getValue(key: string, value: T = null): T
+ {
+ let existing = this._definitions.getValue(key);
+
+ if(existing === undefined)
+ {
+ this.logger.warn(`Missing configuration key: ${ key }`);
+
+ existing = value;
+ }
+
+ return (existing as T);
+ }
+
+ public setValue(key: string, value: string): void
+ {
+ this._definitions.add(key, value);
+ }
+}
diff --git a/src/core/configuration/IConfigurationManager.ts b/src/core/configuration/IConfigurationManager.ts
new file mode 100644
index 00000000..1d18a8f4
--- /dev/null
+++ b/src/core/configuration/IConfigurationManager.ts
@@ -0,0 +1,8 @@
+import { INitroManager } from '../common/INitroManager';
+
+export interface IConfigurationManager extends INitroManager
+{
+ interpolate(value: string, regex?: RegExp): string;
+ getValue(key: string, value?: T): T;
+ setValue(key: string, value: string): void;
+}
\ No newline at end of file
diff --git a/src/core/configuration/index.ts b/src/core/configuration/index.ts
new file mode 100644
index 00000000..cac646dd
--- /dev/null
+++ b/src/core/configuration/index.ts
@@ -0,0 +1,3 @@
+export * from './ConfigurationEvent';
+export * from './ConfigurationManager';
+export * from './IConfigurationManager';
diff --git a/src/core/events/EventDispatcher.ts b/src/core/events/EventDispatcher.ts
new file mode 100644
index 00000000..773e7c68
--- /dev/null
+++ b/src/core/events/EventDispatcher.ts
@@ -0,0 +1,112 @@
+import { Nitro } from '../../nitro/Nitro';
+import { Disposable } from '../common/disposable/Disposable';
+import { IDisposable } from '../common/disposable/IDisposable';
+import { INitroLogger } from '../common/logger/INitroLogger';
+import { NitroLogger } from '../common/logger/NitroLogger';
+import { IEventDispatcher } from './IEventDispatcher';
+
+export class EventDispatcher extends Disposable implements IEventDispatcher, IDisposable
+{
+ private _logger: INitroLogger;
+ private _listeners: Map;
+
+ constructor()
+ {
+ super();
+
+ this._logger = new NitroLogger(this.constructor.name);
+ this._listeners = new Map();
+ }
+
+ protected onDispose(): void
+ {
+ this.removeAllListeners();
+
+ super.onDispose();
+ }
+
+ public addEventListener(type: string, callback: Function): void
+ {
+ if(!type || !callback) return;
+
+ const existing = this._listeners.get(type);
+
+ if(!existing)
+ {
+ this._listeners.set(type, [ callback ]);
+
+ return;
+ }
+
+ existing.push(callback);
+ }
+
+ public removeEventListener(type: string, callback: any): void
+ {
+ if(!type || !callback) return;
+
+ const existing = this._listeners.get(type);
+
+ if(!existing || !existing.length) return;
+
+ for(const [ i, cb ] of existing.entries())
+ {
+ if(!cb || (cb !== callback)) continue;
+
+ existing.splice(i, 1);
+
+ if(!existing.length) this._listeners.delete(type);
+
+ return;
+ }
+ }
+
+ public dispatchEvent(event: Event): boolean
+ {
+ if(!event) return false;
+
+ if(Nitro.instance.getConfiguration('system.dispatcher.log')) this._logger.log(`DISPATCHED: ${ event.type }`);
+
+ this.processEvent(event);
+
+ return true;
+ }
+
+ private processEvent(event: Event): void
+ {
+ const existing = this._listeners.get(event.type);
+
+ if(!existing || !existing.length) return;
+
+ const callbacks = [];
+
+ for(const callback of existing)
+ {
+ if(!callback) continue;
+
+ callbacks.push(callback);
+ }
+
+ while(callbacks.length)
+ {
+ const callback = callbacks.shift();
+
+ try
+ {
+ callback(event);
+ }
+
+ catch (err)
+ {
+ this._logger.error(err.stack);
+
+ return;
+ }
+ }
+ }
+
+ public removeAllListeners(): void
+ {
+ this._listeners.clear();
+ }
+}
diff --git a/src/core/events/IEventDispatcher.ts b/src/core/events/IEventDispatcher.ts
new file mode 100644
index 00000000..50a6019a
--- /dev/null
+++ b/src/core/events/IEventDispatcher.ts
@@ -0,0 +1,9 @@
+import { IDisposable } from '../common/disposable/IDisposable';
+
+export interface IEventDispatcher extends IDisposable
+{
+ addEventListener(type: string, callback: Function): void
+ removeEventListener(type: string, callback: Function): void;
+ removeAllListeners(): void;
+ dispatchEvent(event: Event): boolean;
+}
\ No newline at end of file
diff --git a/src/core/events/ILinkEventTracker.ts b/src/core/events/ILinkEventTracker.ts
new file mode 100644
index 00000000..311567d0
--- /dev/null
+++ b/src/core/events/ILinkEventTracker.ts
@@ -0,0 +1,5 @@
+export interface ILinkEventTracker
+{
+ linkReceived(link: string): void;
+ eventUrlPrefix: string;
+}
\ No newline at end of file
diff --git a/src/core/events/IWorkerEventTracker.ts b/src/core/events/IWorkerEventTracker.ts
new file mode 100644
index 00000000..cde3c203
--- /dev/null
+++ b/src/core/events/IWorkerEventTracker.ts
@@ -0,0 +1,4 @@
+export interface IWorkerEventTracker
+{
+ workerMessageReceived(message: { [index: string]: any }): void;
+}
diff --git a/src/core/events/NitroEvent.ts b/src/core/events/NitroEvent.ts
new file mode 100644
index 00000000..f6d3743a
--- /dev/null
+++ b/src/core/events/NitroEvent.ts
@@ -0,0 +1,4 @@
+export class NitroEvent extends Event
+{
+ public static COMPLETE: string = 'NITRO_COMPLETE';
+}
\ No newline at end of file
diff --git a/src/core/events/index.ts b/src/core/events/index.ts
new file mode 100644
index 00000000..17a287bc
--- /dev/null
+++ b/src/core/events/index.ts
@@ -0,0 +1,5 @@
+export * from './EventDispatcher';
+export * from './IEventDispatcher';
+export * from './ILinkEventTracker';
+export * from './IWorkerEventTracker';
+export * from './NitroEvent';
diff --git a/src/core/index.ts b/src/core/index.ts
new file mode 100644
index 00000000..3fbcc8d6
--- /dev/null
+++ b/src/core/index.ts
@@ -0,0 +1,8 @@
+export * from './asset';
+export * from './common';
+export * from './communication';
+export * from './configuration';
+export * from './events';
+export * from './INitroCore';
+export * from './NitroCore';
+export * from './utils';
diff --git a/src/core/utils/AdvancedMap.ts b/src/core/utils/AdvancedMap.ts
new file mode 100644
index 00000000..4683d487
--- /dev/null
+++ b/src/core/utils/AdvancedMap.ts
@@ -0,0 +1,157 @@
+import { IDisposable } from '../common/disposable/IDisposable';
+
+export class AdvancedMap implements IDisposable
+{
+ private _length: number;
+ private _dictionary: Map;
+ private _array: U[];
+ private _keys: T[];
+
+ constructor()
+ {
+ this._length = 0;
+ this._dictionary = new Map();
+ this._array = [];
+ this._keys = [];
+ }
+
+ public get length(): number
+ {
+ return this._length;
+ }
+
+ public get disposed(): boolean
+ {
+ return (!this._dictionary);
+ }
+
+ public dispose(): void
+ {
+ if(!this._dictionary)
+ {
+ for(const key of this._dictionary.keys()) this._dictionary.delete(key);
+
+ this._dictionary = null;
+ }
+
+ this._length = 0;
+ this._array = null;
+ this._keys = null;
+ }
+
+ public reset(): void
+ {
+ for(const key of this._dictionary.keys()) this._dictionary.delete(key);
+
+ this._length = 0;
+ this._array = [];
+ this._keys = [];
+ }
+
+ public unshift(key: T, value: U): boolean
+ {
+ if(this._dictionary.get(key) !== null) return false;
+
+ this._dictionary.set(key, value);
+
+ this._array.unshift(value);
+ this._keys.unshift(key);
+
+ this._length++;
+
+ return true;
+ }
+
+ public add(key: T, value: U): boolean
+ {
+ if(this._dictionary.get(key) !== undefined) return false;
+
+ this._dictionary.set(key, value);
+
+ this._array[this._length] = value;
+ this._keys[this._length] = key;
+
+ this._length++;
+
+ return true;
+ }
+
+ public remove(key: T): U
+ {
+ const value = this._dictionary.get(key);
+
+ if(!value) return null;
+
+ const index = this._array.indexOf(value);
+
+ if(index >= 0)
+ {
+ this._array.splice(index, 1);
+ this._keys.splice(index, 1);
+
+ this._length--;
+ }
+
+ this._dictionary.delete(key);
+
+ return value;
+ }
+
+ public getWithIndex(index: number): U
+ {
+ if((index < 0) || (index >= this._length)) return null;
+
+ return this._array[index];
+ }
+
+ public getKey(index: number): T
+ {
+ if((index < 0) || (index >= this._length)) return null;
+
+ return this._keys[index];
+ }
+
+ public getKeys(): T[]
+ {
+ return this._keys.slice();
+ }
+
+ public hasKey(key: T): boolean
+ {
+ return (this._keys.indexOf(key) > -1);
+ }
+
+ public getValue(key: T): U
+ {
+ return this._dictionary.get(key);
+ }
+
+ public getValues(): U[]
+ {
+ return this._array.slice();
+ }
+
+ public hasValue(value: U): boolean
+ {
+ return (this._array.indexOf(value) > -1);
+ }
+
+ public indexOf(value: U): number
+ {
+ return this._array.indexOf(value);
+ }
+
+ public concatenate(newValues: AdvancedMap): void
+ {
+ for(const k of newValues._keys) this.add(k, newValues.getValue(k));
+ }
+
+ public clone(): AdvancedMap
+ {
+ const map = new AdvancedMap();
+
+ map.concatenate(this);
+
+ return map;
+ }
+}
\ No newline at end of file
diff --git a/src/core/utils/NitroTimer.ts b/src/core/utils/NitroTimer.ts
new file mode 100644
index 00000000..3cf960c7
--- /dev/null
+++ b/src/core/utils/NitroTimer.ts
@@ -0,0 +1,43 @@
+export class NitroTimer
+{
+ private _elapsedTime: number;
+ private _percision: number;
+ private _timer: any;
+
+ constructor(percision: number = 1)
+ {
+ this._elapsedTime = 0;
+ this._percision = percision;
+ this._timer = null;
+
+ this.start();
+ }
+
+ public start(): void
+ {
+ this._elapsedTime = 0;
+
+ if(!this._timer)
+ {
+ this._timer = setInterval(() => this.increase(), this._percision);
+ }
+ }
+
+ public stop(): void
+ {
+ if(this._timer)
+ {
+ clearTimeout(this._timer);
+ }
+ }
+
+ private increase(): void
+ {
+ this._elapsedTime += this._percision;
+ }
+
+ public getTimer(): number
+ {
+ return this._elapsedTime;
+ }
+}
\ No newline at end of file
diff --git a/src/core/utils/index.ts b/src/core/utils/index.ts
new file mode 100644
index 00000000..0eb447c2
--- /dev/null
+++ b/src/core/utils/index.ts
@@ -0,0 +1,2 @@
+export * from './AdvancedMap';
+export * from './NitroTimer';
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 00000000..4b0e0413
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1 @@
+export * from './core';
diff --git a/src/nitro/INitro.ts b/src/nitro/INitro.ts
new file mode 100644
index 00000000..5f1009c1
--- /dev/null
+++ b/src/nitro/INitro.ts
@@ -0,0 +1,45 @@
+import { Application } from 'pixi.js';
+import { IEventDispatcher } from '../core/events/IEventDispatcher';
+import { ILinkEventTracker } from '../core/events/ILinkEventTracker';
+import { IWorkerEventTracker } from '../core/events/IWorkerEventTracker';
+import { INitroCore } from '../core/INitroCore';
+import { NitroTimer } from '../core/utils/NitroTimer';
+import { IRoomManager } from '../room/IRoomManager';
+import { IAvatarRenderManager } from './avatar/IAvatarRenderManager';
+import { INitroCommunicationManager } from './communication/INitroCommunicationManager';
+import { INitroLocalizationManager } from './localization/INitroLocalizationManager';
+import { IRoomEngine } from './room/IRoomEngine';
+import { IRoomSessionManager } from './session/IRoomSessionManager';
+import { ISessionDataManager } from './session/ISessionDataManager';
+
+export interface INitro extends Application
+{
+ init(): void;
+ dispose(): void;
+ getConfiguration(key: string, value?: T): T;
+ getLocalization(key: string): string;
+ getLocalizationWithParameter(key: string, parameter: string, replacement: string): string;
+ getLocalizationWithParameters(key: string, parameters: string[], replacements: string[]): string;
+ addWorkerEventTracker(tracker: IWorkerEventTracker): void;
+ removeWorkerEventTracker(tracker: IWorkerEventTracker): void;
+ createWorkerEvent(message: { [index: string]: any }): void;
+ sendWorkerEvent(message: { [index: string]: any }): void;
+ addLinkEventTracker(tracker: ILinkEventTracker): void;
+ removeLinkEventTracker(tracker: ILinkEventTracker): void;
+ createLinkEvent(link: string): void;
+ nitroTimer: NitroTimer;
+ core: INitroCore;
+ events: IEventDispatcher;
+ localization: INitroLocalizationManager;
+ communication: INitroCommunicationManager;
+ avatar: IAvatarRenderManager;
+ roomEngine: IRoomEngine;
+ sessionDataManager: ISessionDataManager;
+ roomSessionManager: IRoomSessionManager;
+ roomManager: IRoomManager;
+ width: number;
+ height: number;
+ time: number;
+ isReady: boolean;
+ isDisposed: boolean;
+}
diff --git a/src/nitro/Nitro.ts b/src/nitro/Nitro.ts
new file mode 100644
index 00000000..053fd75e
--- /dev/null
+++ b/src/nitro/Nitro.ts
@@ -0,0 +1,417 @@
+import { Application, SCALE_MODES, settings } from 'pixi.js';
+import { ConfigurationEvent } from '../core/configuration/ConfigurationEvent';
+import { EventDispatcher } from '../core/events/EventDispatcher';
+import { IEventDispatcher } from '../core/events/IEventDispatcher';
+import { ILinkEventTracker } from '../core/events/ILinkEventTracker';
+import { IWorkerEventTracker } from '../core/events/IWorkerEventTracker';
+import { NitroEvent } from '../core/events/NitroEvent';
+import { INitroCore } from '../core/INitroCore';
+import { NitroCore } from '../core/NitroCore';
+import { NitroTimer } from '../core/utils/NitroTimer';
+import { IRoomManager } from '../room/IRoomManager';
+import { RoomManager } from '../room/RoomManager';
+import { AvatarRenderManager } from './avatar/AvatarRenderManager';
+import { IAvatarRenderManager } from './avatar/IAvatarRenderManager';
+import { INitroCommunicationManager } from './communication/INitroCommunicationManager';
+import { NitroCommunicationManager } from './communication/NitroCommunicationManager';
+import { LegacyExternalInterface } from './externalInterface/LegacyExternalInterface';
+import { GameMessageHandler } from './game/GameMessageHandler';
+import { INitro } from './INitro';
+import { INitroLocalizationManager } from './localization/INitroLocalizationManager';
+import { NitroLocalizationManager } from './localization/NitroLocalizationManager';
+import { RoomEngineEvent } from './room/events/RoomEngineEvent';
+import { IRoomEngine } from './room/IRoomEngine';
+import { RoomEngine } from './room/RoomEngine';
+import { IRoomSessionManager } from './session/IRoomSessionManager';
+import { ISessionDataManager } from './session/ISessionDataManager';
+import { RoomSessionManager } from './session/RoomSessionManager';
+import { SessionDataManager } from './session/SessionDataManager';
+import { HabboWebTools } from './utils/HabboWebTools';
+
+LegacyExternalInterface.available;
+
+settings.FAIL_IF_MAJOR_PERFORMANCE_CAVEAT = false;
+settings.SCALE_MODE = SCALE_MODES.NEAREST;
+
+export class Nitro extends Application implements INitro
+{
+ public static WEBGL_CONTEXT_LOST: string = 'NE_WEBGL_CONTEXT_LOST';
+ public static WEBGL_UNAVAILABLE: string = 'NE_WEBGL_UNAVAILABLE';
+ public static RELEASE_VERSION: string = 'NITRO-0-4-0';
+ public static READY: string = 'NE_READY';
+
+ private static INSTANCE: INitro = null;
+
+ private _nitroTimer: NitroTimer;
+ private _worker: Worker;
+ private _core: INitroCore;
+ private _events: IEventDispatcher;
+ private _localization: INitroLocalizationManager;
+ private _communication: INitroCommunicationManager;
+ private _avatar: IAvatarRenderManager;
+ private _roomEngine: IRoomEngine;
+ private _sessionDataManager: ISessionDataManager;
+ private _roomSessionManager: IRoomSessionManager;
+ private _roomManager: IRoomManager;
+ private _linkTrackers: ILinkEventTracker[];
+ private _workerTrackers: IWorkerEventTracker[];
+
+ private _isReady: boolean;
+ private _isDisposed: boolean;
+
+ constructor(core: INitroCore, options?: {
+ autoStart?: boolean;
+ width?: number;
+ height?: number;
+ view?: HTMLCanvasElement;
+ transparent?: boolean;
+ autoDensity?: boolean;
+ antialias?: boolean;
+ preserveDrawingBuffer?: boolean;
+ resolution?: number;
+ forceCanvas?: boolean;
+ backgroundColor?: number;
+ clearBeforeRender?: boolean;
+ powerPreference?: string;
+ sharedTicker?: boolean;
+ sharedLoader?: boolean;
+ resizeTo?: Window | HTMLElement;
+ })
+ {
+ super(options);
+
+ if(!Nitro.INSTANCE) Nitro.INSTANCE = this;
+
+ this._nitroTimer = new NitroTimer();
+ this._worker = new Worker('../nitro-worker.worker', { type: 'module' });
+ this._core = core;
+ this._events = new EventDispatcher();
+ this._localization = new NitroLocalizationManager();
+ this._communication = new NitroCommunicationManager(core.communication);
+ this._avatar = new AvatarRenderManager();
+ this._roomEngine = new RoomEngine(this._communication);
+ this._sessionDataManager = new SessionDataManager(this._communication);
+ this._roomSessionManager = new RoomSessionManager(this._communication, this._roomEngine);
+ this._roomManager = new RoomManager(this._roomEngine, this._roomEngine.visualizationFactory, this._roomEngine.logicFactory);
+ this._linkTrackers = [];
+ this._workerTrackers = [];
+
+ this._isReady = false;
+ this._isDisposed = false;
+
+ this._core.configuration.events.addEventListener(ConfigurationEvent.LOADED, this.onConfigurationLoadedEvent.bind(this));
+ this._roomEngine.events.addEventListener(RoomEngineEvent.ENGINE_INITIALIZED, this.onRoomEngineReady.bind(this));
+
+ this._worker.onmessage = this.createWorkerEvent.bind(this);
+ }
+
+ public static bootstrap(): void
+ {
+ if(Nitro.INSTANCE)
+ {
+ Nitro.INSTANCE.dispose();
+
+ Nitro.INSTANCE = null;
+ }
+
+ const canvas = document.createElement('canvas');
+
+ canvas.id = 'client-wrapper';
+ canvas.className = 'client-canvas';
+
+ const instance = new this(new NitroCore(), {
+ transparent: true,
+ autoDensity: true,
+ resolution: window.devicePixelRatio,
+ width: window.innerWidth,
+ height: window.innerHeight,
+ view: canvas
+ });
+
+ canvas.addEventListener('webglcontextlost', () => instance.events.dispatchEvent(new NitroEvent(Nitro.WEBGL_CONTEXT_LOST)));
+
+ //@ts-ignore
+ const sso = (NitroConfig.sso as string);
+
+ instance.communication.demo.setSSO(sso);
+ }
+
+ public init(): void
+ {
+ if(this._isReady || this._isDisposed) return;
+
+ if(this._avatar) this._avatar.init();
+
+ if(this._roomEngine)
+ {
+ this._roomEngine.sessionDataManager = this._sessionDataManager;
+ this._roomEngine.roomSessionManager = this._roomSessionManager;
+ this._roomEngine.roomManager = this._roomManager;
+
+ if(this._sessionDataManager) this._sessionDataManager.init();
+ if(this._roomSessionManager) this._roomSessionManager.init();
+
+ this._roomEngine.init();
+ }
+
+ new GameMessageHandler(this._communication.connection);
+
+ if(!this._communication.connection)
+ {
+ throw new Error('No connection found');
+ }
+
+ this._isReady = true;
+ }
+
+ public dispose(): void
+ {
+ if(this._isDisposed) return;
+
+ if(this._roomManager)
+ {
+ this._roomManager.dispose();
+
+ this._roomManager = null;
+ }
+
+ if(this._roomSessionManager)
+ {
+ this._roomSessionManager.dispose();
+
+ this._roomSessionManager = null;
+ }
+
+ if(this._sessionDataManager)
+ {
+ this._sessionDataManager.dispose();
+
+ this._sessionDataManager = null;
+ }
+
+ if(this._roomEngine)
+ {
+ this._roomEngine.dispose();
+
+ this._roomEngine = null;
+ }
+
+ if(this._avatar)
+ {
+ this._avatar.dispose();
+
+ this._avatar = null;
+ }
+
+ if(this._communication)
+ {
+ this._communication.dispose();
+
+ this._communication = null;
+ }
+
+ super.destroy();
+
+ this._isDisposed = true;
+ this._isReady = false;
+ }
+
+ private onConfigurationLoadedEvent(event: ConfigurationEvent): void
+ {
+ const animationFPS = this.getConfiguration('animation.fps', 24);
+ const limitsFPS = this.getConfiguration('limits.fps', true);
+
+ Nitro.instance.ticker.maxFPS = animationFPS;
+ }
+
+ private onRoomEngineReady(event: RoomEngineEvent): void
+ {
+ this.startSendingHeartBeat();
+ }
+
+ public getConfiguration(key: string, value: T = null): T
+ {
+ return this._core.configuration.getValue(key, value);
+ }
+
+ public getLocalization(key: string): string
+ {
+ return this._localization.getValue(key);
+ }
+
+ public getLocalizationWithParameter(key: string, parameter: string, replacement: string): string
+ {
+ return this._localization.getValueWithParameter(key, parameter, replacement);
+ }
+
+ public getLocalizationWithParameters(key: string, parameters: string[], replacements: string[]): string
+ {
+ return this._localization.getValueWithParameters(key, parameters, replacements);
+ }
+
+ public addWorkerEventTracker(tracker: IWorkerEventTracker): void
+ {
+ if(this._workerTrackers.indexOf(tracker) >= 0) return;
+
+ this._workerTrackers.push(tracker);
+ }
+
+ public removeWorkerEventTracker(tracker: IWorkerEventTracker): void
+ {
+ const index = this._workerTrackers.indexOf(tracker);
+
+ if(index === -1) return;
+
+ this._workerTrackers.splice(index, 1);
+ }
+
+ public createWorkerEvent(message: MessageEvent): void
+ {
+ if(!message) return;
+
+ const data: { [index: string]: any } = message.data;
+
+ for(const tracker of this._workerTrackers)
+ {
+ if(!tracker) continue;
+
+ tracker.workerMessageReceived(data);
+ }
+ }
+
+ public sendWorkerEvent(message: { [index: string]: any }): void
+ {
+ if(!message || !this._worker) return;
+
+ this._worker.postMessage(message);
+ }
+
+ public addLinkEventTracker(tracker: ILinkEventTracker): void
+ {
+ if(this._linkTrackers.indexOf(tracker) >= 0) return;
+
+ this._linkTrackers.push(tracker);
+ }
+
+ public removeLinkEventTracker(tracker: ILinkEventTracker): void
+ {
+ const index = this._linkTrackers.indexOf(tracker);
+
+ if(index === -1) return;
+
+ this._linkTrackers.splice(index, 1);
+ }
+
+ public createLinkEvent(link: string): void
+ {
+ if(!link || (link === '')) return;
+
+ for(const tracker of this._linkTrackers)
+ {
+ if(!tracker) continue;
+
+ const prefix = tracker.eventUrlPrefix;
+
+ if(prefix.length > 0)
+ {
+ if(link.substr(0, prefix.length) === prefix) tracker.linkReceived(link);
+ }
+ else
+ {
+ tracker.linkReceived(link);
+ }
+ }
+ }
+
+ private startSendingHeartBeat(): void
+ {
+ this.sendHeartBeat();
+
+ setInterval(this.sendHeartBeat, 10000);
+ }
+
+ private sendHeartBeat(): void
+ {
+ HabboWebTools.sendHeartBeat();
+ }
+
+ public get nitroTimer(): NitroTimer
+ {
+ return this._nitroTimer;
+ }
+
+ public get core(): INitroCore
+ {
+ return this._core;
+ }
+
+ public get events(): IEventDispatcher
+ {
+ return this._events;
+ }
+
+ public get localization(): INitroLocalizationManager
+ {
+ return this._localization;
+ }
+
+ public get communication(): INitroCommunicationManager
+ {
+ return this._communication;
+ }
+
+ public get avatar(): IAvatarRenderManager
+ {
+ return this._avatar;
+ }
+
+ public get roomEngine(): IRoomEngine
+ {
+ return this._roomEngine;
+ }
+
+ public get sessionDataManager(): ISessionDataManager
+ {
+ return this._sessionDataManager;
+ }
+
+ public get roomSessionManager(): IRoomSessionManager
+ {
+ return this._roomSessionManager;
+ }
+
+ public get roomManager(): IRoomManager
+ {
+ return this._roomManager;
+ }
+
+ public get width(): number
+ {
+ return (this.renderer.width / this.renderer.resolution);
+ }
+
+ public get height(): number
+ {
+ return (this.renderer.height / this.renderer.resolution);
+ }
+
+ public get time(): number
+ {
+ return this.ticker.lastTime;
+ }
+
+ public get isReady(): boolean
+ {
+ return this._isReady;
+ }
+
+ public get isDisposed(): boolean
+ {
+ return this._isDisposed;
+ }
+
+ public static get instance(): INitro
+ {
+ return this.INSTANCE || null;
+ }
+}
diff --git a/src/nitro/avatar/AvatarAssetDownloadLibrary.ts b/src/nitro/avatar/AvatarAssetDownloadLibrary.ts
new file mode 100644
index 00000000..76a72914
--- /dev/null
+++ b/src/nitro/avatar/AvatarAssetDownloadLibrary.ts
@@ -0,0 +1,74 @@
+import { IAssetManager } from '../../core/asset/IAssetManager';
+import { EventDispatcher } from '../../core/events/EventDispatcher';
+import { AvatarRenderLibraryEvent } from './events/AvatarRenderLibraryEvent';
+
+export class AvatarAssetDownloadLibrary extends EventDispatcher
+{
+ public static DOWNLOAD_COMPLETE: string = 'AADL_DOWNLOAD_COMPLETE';
+
+ private static NOT_LOADED: number = 0;
+ private static LOADING: number = 1;
+ private static LOADED: number = 2;
+
+ private _state: number;
+ private _libraryName: string;
+ private _revision: string;
+ private _downloadUrl: string;
+ private _assets: IAssetManager;
+
+ constructor(id: string, revision: string, assets: IAssetManager, assetUrl: string)
+ {
+ super();
+
+ this._state = AvatarAssetDownloadLibrary.NOT_LOADED;
+ this._libraryName = id;
+ this._revision = revision;
+ this._downloadUrl = assetUrl;
+ this._assets = assets;
+
+ this._downloadUrl = this._downloadUrl.replace(/%libname%/gi, this._libraryName);
+ this._downloadUrl = this._downloadUrl.replace(/%revision%/gi, this._revision);
+
+ const asset = this._assets.getCollection(this._libraryName);
+
+ if(asset) this._state = AvatarAssetDownloadLibrary.LOADED;
+ }
+
+ public downloadAsset(): void
+ {
+ if(!this._assets || (this._state === AvatarAssetDownloadLibrary.LOADING) || (this._state === AvatarAssetDownloadLibrary.LOADED)) return;
+
+ const asset = this._assets.getCollection(this._libraryName);
+
+ if(asset)
+ {
+ this._state = AvatarAssetDownloadLibrary.LOADED;
+
+ this.dispatchEvent(new AvatarRenderLibraryEvent(AvatarRenderLibraryEvent.DOWNLOAD_COMPLETE, this));
+
+ return;
+ }
+
+ this._state = AvatarAssetDownloadLibrary.LOADING;
+
+ this._assets.downloadAsset(this._downloadUrl, (flag: boolean) =>
+ {
+ if(flag)
+ {
+ this._state = AvatarAssetDownloadLibrary.LOADED;
+
+ this.dispatchEvent(new AvatarRenderLibraryEvent(AvatarRenderLibraryEvent.DOWNLOAD_COMPLETE, this));
+ }
+ });
+ }
+
+ public get libraryName(): string
+ {
+ return this._libraryName;
+ }
+
+ public get isLoaded(): boolean
+ {
+ return (this._state === AvatarAssetDownloadLibrary.LOADED);
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/AvatarAssetDownloadManager.ts b/src/nitro/avatar/AvatarAssetDownloadManager.ts
new file mode 100644
index 00000000..c69d75ee
--- /dev/null
+++ b/src/nitro/avatar/AvatarAssetDownloadManager.ts
@@ -0,0 +1,343 @@
+import { IAssetManager } from '../../core/asset/IAssetManager';
+import { NitroLogger } from '../../core/common/logger/NitroLogger';
+import { EventDispatcher } from '../../core/events/EventDispatcher';
+import { NitroEvent } from '../../core/events/NitroEvent';
+import { Nitro } from '../Nitro';
+import { AvatarAssetDownloadLibrary } from './AvatarAssetDownloadLibrary';
+import { AvatarStructure } from './AvatarStructure';
+import { AvatarRenderEvent } from './events/AvatarRenderEvent';
+import { AvatarRenderLibraryEvent } from './events/AvatarRenderLibraryEvent';
+import { IAvatarFigureContainer } from './IAvatarFigureContainer';
+import { IAvatarImageListener } from './IAvatarImageListener';
+
+export class AvatarAssetDownloadManager extends EventDispatcher
+{
+ public static DOWNLOADER_READY: string = 'AADM_DOWNLOADER_READY';
+ public static LIBRARY_LOADED: string = 'AADM_LIBRARY_LOADED';
+
+ private static MAX_DOWNLOADS: number = 2;
+
+ private _assets: IAssetManager;
+ private _structure: AvatarStructure;
+
+ private _missingMandatoryLibs: string[];
+ private _figureMap: Map;
+ private _pendingContainers: [ IAvatarFigureContainer, IAvatarImageListener ][];
+ private _figureListeners: Map;
+ private _incompleteFigures: Map;
+ private _pendingDownloadQueue: AvatarAssetDownloadLibrary[];
+ private _currentDownloads: AvatarAssetDownloadLibrary[];
+ private _libraryNames: string[];
+ private _isReady: boolean;
+
+ constructor(assets: IAssetManager, structure: AvatarStructure)
+ {
+ super();
+
+ this._assets = assets;
+ this._structure = structure;
+
+ this._missingMandatoryLibs = Nitro.instance.getConfiguration('avatar.mandatory.libraries');
+ this._figureMap = new Map();
+ this._pendingContainers = [];
+ this._figureListeners = new Map();
+ this._incompleteFigures = new Map();
+ this._pendingDownloadQueue = [];
+ this._currentDownloads = [];
+ this._libraryNames = [];
+ this._isReady = false;
+
+ this.onLibraryLoaded = this.onLibraryLoaded.bind(this);
+ this.onAvatarRenderReady = this.onAvatarRenderReady.bind(this);
+
+ this.loadFigureMap();
+
+ this._structure.renderManager.events.addEventListener(AvatarRenderEvent.AVATAR_RENDER_READY, this.onAvatarRenderReady);
+ }
+
+ private loadFigureMap(): void
+ {
+ const request = new XMLHttpRequest();
+
+ try
+ {
+ request.open('GET', Nitro.instance.getConfiguration('avatar.figuremap.url'));
+
+ request.send();
+
+ request.onloadend = e =>
+ {
+ if(request.responseText)
+ {
+ const data = JSON.parse(request.responseText);
+
+ this.processFigureMap(data.libraries);
+
+ this.processMissingLibraries();
+
+ this._isReady = true;
+
+ this.dispatchEvent(new NitroEvent(AvatarAssetDownloadManager.DOWNLOADER_READY));
+ }
+ };
+
+ request.onerror = e =>
+ {
+ throw new Error('invalid_avatar_figure_map');
+ };
+ }
+
+ catch (e)
+ {
+ NitroLogger.log(e);
+ }
+ }
+
+ private processFigureMap(data: any): void
+ {
+ if(!data) return;
+
+ for(const library of data)
+ {
+ if(!library) continue;
+
+ const id = (library.id as string);
+ const revision = (library.revision || '');
+
+ if(this._libraryNames.indexOf(id) >= 0) continue;
+
+ this._libraryNames.push(id);
+
+ const downloadLibrary = new AvatarAssetDownloadLibrary(id, revision, this._assets, Nitro.instance.getConfiguration('avatar.asset.url'));
+
+ downloadLibrary.addEventListener(AvatarRenderLibraryEvent.DOWNLOAD_COMPLETE, this.onLibraryLoaded);
+
+ for(const part of library.parts)
+ {
+ const id = (part.id as string);
+ const type = (part.type as string);
+ const partString = (type + ':' + id);
+
+ let existing = this._figureMap.get(partString);
+
+ if(!existing) existing = [];
+
+ existing.push(downloadLibrary);
+
+ this._figureMap.set(partString, existing);
+ }
+ }
+ }
+
+ private onAvatarRenderReady(event: NitroEvent): void
+ {
+ if(!event) return;
+
+ for(const [ container, listener ] of this._pendingContainers)
+ {
+ this.downloadAvatarFigure(container, listener);
+ }
+
+ this._pendingContainers = [];
+ }
+
+ private onLibraryLoaded(event: AvatarRenderLibraryEvent): void
+ {
+ if(!event || !event.library) return;
+
+ const loadedFigures: string[] = [];
+
+ for(const [ figure, libraries ] of this._incompleteFigures.entries())
+ {
+ let isReady = true;
+
+ for(const library of libraries)
+ {
+ if(!library || library.isLoaded) continue;
+
+ isReady = false;
+
+ break;
+ }
+
+ if(isReady)
+ {
+ loadedFigures.push(figure);
+
+ const listeners = this._figureListeners.get(figure);
+
+ if(listeners)
+ {
+ for(const listener of listeners)
+ {
+ if(!listener || listener.disposed) continue;
+
+ listener.resetFigure(figure);
+ }
+ }
+
+ this._figureListeners.delete(figure);
+
+ this.dispatchEvent(new NitroEvent(AvatarAssetDownloadManager.LIBRARY_LOADED));
+ }
+ }
+
+ for(const figure of loadedFigures)
+ {
+ if(!figure) continue;
+
+ this._incompleteFigures.delete(figure);
+ }
+
+ let index = 0;
+
+ while(index < this._currentDownloads.length)
+ {
+ const download = this._currentDownloads[index];
+
+ if(download)
+ {
+ if(download.libraryName === event.library.libraryName) this._currentDownloads.splice(index, 1);
+ }
+
+ index++;
+ }
+ }
+
+ public processMissingLibraries(): void
+ {
+ const libraries = this._missingMandatoryLibs.slice();
+
+ for(const library of libraries)
+ {
+ if(!library) continue;
+
+ const map = this._figureMap.get(library);
+
+ if(map) for(const avatar of map) avatar && this.downloadLibrary(avatar);
+ }
+ }
+
+ public isAvatarFigureContainerReady(container: IAvatarFigureContainer): boolean
+ {
+ if(!this._isReady || !this._structure.renderManager.isReady)
+ {
+ return false;
+ }
+
+ const pendingLibraries = this.getAvatarFigurePendingLibraries(container);
+
+ return !pendingLibraries.length;
+ }
+
+ private getAvatarFigurePendingLibraries(container: IAvatarFigureContainer): AvatarAssetDownloadLibrary[]
+ {
+ const pendingLibraries: AvatarAssetDownloadLibrary[] = [];
+
+ if(!container || !this._structure) return pendingLibraries;
+
+ const figureData = this._structure.figureData;
+
+ if(!figureData) return pendingLibraries;
+
+ const setKeys = container._Str_1016();
+
+ for(const key of setKeys)
+ {
+ const set = figureData._Str_740(key);
+
+ if(!set) continue;
+
+ const figurePartSet = set._Str_1020(container.getPartSetId(key));
+
+ if(!figurePartSet) continue;
+
+ for(const part of figurePartSet._Str_806)
+ {
+ if(!part) continue;
+
+ const name = (part.type + ':' + part.id);
+ const existing = this._figureMap.get(name);
+
+ if(existing === undefined) continue;
+
+ for(const library of existing)
+ {
+ if(!library || library.isLoaded) continue;
+
+ if(pendingLibraries.indexOf(library) >= 0) continue;
+
+ pendingLibraries.push(library);
+ }
+ }
+ }
+
+ return pendingLibraries;
+ }
+
+ public downloadAvatarFigure(container: IAvatarFigureContainer, listener: IAvatarImageListener): void
+ {
+ if(!this._isReady || !this._structure.renderManager.isReady)
+ {
+ this._pendingContainers.push([ container, listener ]);
+
+ return;
+ }
+
+ const figure = container._Str_1008();
+ const pendingLibraries = this.getAvatarFigurePendingLibraries(container);
+
+ if(pendingLibraries && pendingLibraries.length)
+ {
+ if(listener && !listener.disposed)
+ {
+ let listeners = this._figureListeners.get(figure);
+
+ if(!listeners)
+ {
+ listeners = [];
+
+ this._figureListeners.set(figure, listeners);
+ }
+
+ listeners.push(listener);
+ }
+
+ this._incompleteFigures.set(figure, pendingLibraries);
+
+ for(const library of pendingLibraries)
+ {
+ if(!library) continue;
+
+ this.downloadLibrary(library);
+ }
+ }
+ else
+ {
+ if(listener && !listener.disposed) listener.resetFigure(figure);
+ }
+ }
+
+ private downloadLibrary(library: AvatarAssetDownloadLibrary): void
+ {
+ if(!library || library.isLoaded) return;
+
+ if((this._pendingDownloadQueue.indexOf(library) >= 0) || (this._currentDownloads.indexOf(library) >= 0)) return;
+
+ this._pendingDownloadQueue.push(library);
+
+ this.processDownloadQueue();
+ }
+
+ private processDownloadQueue(): void
+ {
+ while(this._pendingDownloadQueue.length)
+ {
+ const library = this._pendingDownloadQueue[0];
+
+ library.downloadAsset();
+
+ this._currentDownloads.push(this._pendingDownloadQueue.shift());
+ }
+ }
+}
diff --git a/src/nitro/avatar/AvatarFigureContainer.ts b/src/nitro/avatar/AvatarFigureContainer.ts
new file mode 100644
index 00000000..8b0fc32c
--- /dev/null
+++ b/src/nitro/avatar/AvatarFigureContainer.ts
@@ -0,0 +1,116 @@
+import { IAvatarFigureContainer } from './IAvatarFigureContainer';
+
+export class AvatarFigureContainer implements IAvatarFigureContainer
+{
+ private _parts: Map>;
+
+ constructor(figure: string)
+ {
+ this._parts = new Map();
+
+ this.parseFigure(figure);
+ }
+
+ public _Str_1016(): IterableIterator
+ {
+ return this.partSets().keys();
+ }
+
+ public _Str_744(k: string): boolean
+ {
+ return this.partSets().get(k) !== null;
+ }
+
+ public getPartSetId(k: string): number
+ {
+ const existing = this.partSets().get(k);
+
+ if(!existing) return 0;
+
+ return existing.get('setid');
+ }
+
+ public _Str_815(k: string): number[]
+ {
+ const existing = this.partSets().get(k);
+
+ if(!existing) return null;
+
+ return existing.get('colorids');
+ }
+
+ public _Str_830(k: string, _arg_2: number, _arg_3: number[]): void
+ {
+ const set: Map = new Map();
+
+ set.set('type', k);
+ set.set('setid', _arg_2);
+ set.set('colorids', _arg_3);
+
+ const existingSets = this.partSets();
+
+ existingSets.delete(k);
+ existingSets.set(k, set);
+ }
+
+ public _Str_923(k: string): void
+ {
+ this.partSets().delete(k);
+ }
+
+ public _Str_1008(): string
+ {
+ const parts: string[] = [];
+
+ for(const key of this.partSets().keys())
+ {
+ if(!key) continue;
+
+ let setParts = [];
+
+ setParts.push(key);
+ setParts.push(this.getPartSetId(key));
+
+ setParts = setParts.concat(this._Str_815(key));
+
+ parts.push(setParts.join('-'));
+ }
+
+ return parts.join('.');
+ }
+
+ private partSets(): Map>
+ {
+ if(!this._parts) this._parts = new Map();
+
+ return this._parts;
+ }
+
+ private parseFigure(figure: string): void
+ {
+ if(!figure) figure = '';
+
+ for(const part of figure.split('.'))
+ {
+ const pieces = part.split('-');
+
+ if(pieces.length >= 2)
+ {
+ const type = pieces[0];
+ const setId = parseInt(pieces[1]);
+ const colors = [];
+
+ let index = 2;
+
+ while(index < pieces.length)
+ {
+ colors.push(parseInt(pieces[index]));
+
+ index++;
+ }
+
+ this._Str_830(type, setId, colors);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/AvatarImage.ts b/src/nitro/avatar/AvatarImage.ts
new file mode 100644
index 00000000..7f7ab6eb
--- /dev/null
+++ b/src/nitro/avatar/AvatarImage.ts
@@ -0,0 +1,1055 @@
+import { Container, filters, Rectangle, RenderTexture, Sprite, Texture } from 'pixi.js';
+import { AdvancedMap } from '../../core/utils/AdvancedMap';
+import { IGraphicAsset } from '../../room/object/visualization/utils/IGraphicAsset';
+import { TextureUtils } from '../../room/utils/TextureUtils';
+import { Nitro } from '../Nitro';
+import { ActiveActionData } from './actions/ActiveActionData';
+import { IActionDefinition } from './actions/IActionDefinition';
+import { IActiveActionData } from './actions/IActiveActionData';
+import { AssetAliasCollection } from './alias/AssetAliasCollection';
+import { IAnimationLayerData } from './animation/IAnimationLayerData';
+import { IAvatarDataContainer } from './animation/IAvatarDataContainer';
+import { ISpriteDataContainer } from './animation/ISpriteDataContainer';
+import { AvatarFigureContainer } from './AvatarFigureContainer';
+import { AvatarStructure } from './AvatarStructure';
+import { AvatarImageCache } from './cache/AvatarImageCache';
+import { EffectAssetDownloadManager } from './EffectAssetDownloadManager';
+import { AvatarAction } from './enum/AvatarAction';
+import { AvatarDirectionAngle } from './enum/AvatarDirectionAngle';
+import { AvatarScaleType } from './enum/AvatarScaleType';
+import { AvatarSetType } from './enum/AvatarSetType';
+import { IAvatarEffectListener } from './IAvatarEffectListener';
+import { IAvatarFigureContainer } from './IAvatarFigureContainer';
+import { IAvatarImage } from './IAvatarImage';
+import { IPartColor } from './structure/figure/IPartColor';
+
+export class AvatarImage implements IAvatarImage, IAvatarEffectListener
+{
+ private static CHANNELS_EQUAL: string = 'CHANNELS_EQUAL';
+ private static CHANNELS_UNIQUE: string = 'CHANNELS_UNIQUE';
+ private static CHANNELS_RED: string = 'CHANNELS_RED';
+ private static CHANNELS_GREEN: string = 'CHANNELS_GREEN';
+ private static CHANNELS_BLUE: string = 'CHANNELS_BLUE';
+ private static CHANNELS_DESATURATED: string = 'CHANNELS_DESATURATED';
+ private static DEFAULT_ACTION: string = 'Default';
+ private static DEFAULT_DIRECTION: number = 2;
+ private static DEFAULT_AVATAR_SET: string = AvatarSetType.FULL;
+
+ protected _structure: AvatarStructure;
+ protected _scale: string;
+ protected _mainDirection: number;
+ protected _headDirection: number;
+ protected _mainAction: IActiveActionData;
+ protected _disposed: boolean;
+ protected _canvasOffsets: number[];
+ protected _assets: AssetAliasCollection;
+ protected _cache: AvatarImageCache;
+ protected _figure: AvatarFigureContainer;
+ protected _avatarSpriteData: IAvatarDataContainer;
+ protected _actions: ActiveActionData[];
+ protected _image: RenderTexture;
+ protected _reusableTexture: RenderTexture;
+
+ private _defaultAction: IActiveActionData;
+ private _frameCounter: number = 0;
+ private _directionOffset: number = 0;
+ private _changes: boolean;
+ private _sprites: ISpriteDataContainer[];
+ private _isAnimating: boolean = false;
+ private _animationHasResetOnToggle: boolean = false;
+ private _actionsSorted: boolean = false;
+ private _sortedActions: IActiveActionData[];
+ private _lastActionsString: string;
+ private _currentActionsString: string;
+ private _fullImageCache: AdvancedMap;
+ private _fullImageCacheSize: number = 5;
+ protected _isCachedImage: boolean = false;
+ private _useFullImageCache: boolean = false;
+ private _effectIdInUse: number = -1;
+ private _animationFrameCount: number;
+ private _cachedBodyParts: string[];
+ private _cachedBodyPartsDirection: number = -1;
+ private _cachedBodyPartsGeometryType: string = null;
+ private _cachedBodyPartsAvatarSet: string = null;
+ private _effectManager: EffectAssetDownloadManager;
+ private _effectListener: IAvatarEffectListener;
+
+ constructor(k: AvatarStructure, _arg_2: AssetAliasCollection, _arg_3: AvatarFigureContainer, _arg_4: string, _arg_5: EffectAssetDownloadManager, _arg_6: IAvatarEffectListener = null)
+ {
+ this._canvasOffsets = [];
+ this._actions = [];
+ this._cachedBodyParts = [];
+ this._changes = true;
+ this._disposed = false;
+ this._effectManager = _arg_5;
+ this._structure = k;
+ this._assets = _arg_2;
+ this._scale = _arg_4;
+ this._effectListener = _arg_6;
+ if(this._scale == null)
+ {
+ this._scale = AvatarScaleType.LARGE;
+ }
+ if(_arg_3 == null)
+ {
+ _arg_3 = new AvatarFigureContainer('hr-893-45.hd-180-2.ch-210-66.lg-270-82.sh-300-91.wa-2007-.ri-1-');
+ }
+ this._figure = _arg_3;
+ this._cache = new AvatarImageCache(this._structure, this, this._assets, this._scale);
+ this.setDirection(AvatarImage.DEFAULT_AVATAR_SET, AvatarImage.DEFAULT_DIRECTION);
+ this._actions = [];
+ this._defaultAction = new ActiveActionData(AvatarAction.POSTURE_STAND);
+ this._defaultAction._Str_742 = this._structure._Str_1675(AvatarImage.DEFAULT_ACTION);
+ this.resetActions();
+ this._fullImageCache = new AdvancedMap();
+ this._animationFrameCount = 0;
+ }
+
+ public getServerRenderData(): any[]
+ {
+ this.getAvatarPartsForCamera(AvatarSetType.FULL);
+
+ return this._cache._Str_1009();
+ }
+
+ public dispose(): void
+ {
+ if(this._disposed) return;
+
+ this._structure = null;
+ this._assets = null;
+ this._mainAction = null;
+ this._figure = null;
+ this._avatarSpriteData = null;
+ this._actions = null;
+
+ if(this._image)
+ {
+ this._image.destroy();
+
+ this._image = null;
+ }
+
+ if(this._cache)
+ {
+ this._cache.dispose();
+ this._cache = null;
+ }
+
+ if(this._fullImageCache)
+ {
+ for(const k of this._fullImageCache.getValues()) (k && k.destroy());
+
+ this._fullImageCache = null;
+ }
+
+ this._image = null;
+ this._canvasOffsets = null;
+ this._disposed = true;
+ }
+
+ public get disposed(): boolean
+ {
+ return this._disposed;
+ }
+
+ public getFigure(): IAvatarFigureContainer
+ {
+ return this._figure;
+ }
+
+ public getScale(): string
+ {
+ return this._scale;
+ }
+
+ public getPartColor(k: string): IPartColor
+ {
+ return this._structure._Str_867(this._figure, k);
+ }
+
+ public setDirection(k: string, _arg_2: number): void
+ {
+ _arg_2 = (_arg_2 + this._directionOffset);
+
+ if(_arg_2 < AvatarDirectionAngle.MIN_DIRECTION)
+ {
+ _arg_2 = (AvatarDirectionAngle.MAX_DIRECTION + (_arg_2 + 1));
+ }
+
+ if(_arg_2 > AvatarDirectionAngle.MAX_DIRECTION)
+ {
+ _arg_2 = (_arg_2 - (AvatarDirectionAngle.MAX_DIRECTION + 1));
+ }
+
+ if(this._structure._Str_1939(k))
+ {
+ this._mainDirection = _arg_2;
+ }
+
+ if((k === AvatarSetType.HEAD) || (k === AvatarSetType.FULL))
+ {
+ if((k === AvatarSetType.HEAD) && (this.isHeadTurnPreventedByAction()))
+ {
+ _arg_2 = this._mainDirection;
+ }
+
+ this._headDirection = _arg_2;
+ }
+
+ this._cache.setDirection(k, _arg_2);
+ this._changes = true;
+ }
+
+ public setDirectionAngle(k: string, _arg_2: number): void
+ {
+ this.setDirection(k, Math.floor(_arg_2 / 45));
+ }
+
+ public getSprites(): ISpriteDataContainer[]
+ {
+ return this._sprites;
+ }
+
+ public getCanvasOffsets(): number[]
+ {
+ return this._canvasOffsets;
+ }
+
+ public getLayerData(k: ISpriteDataContainer): IAnimationLayerData
+ {
+ return this._structure._Str_1881(k.animation.id, this._frameCounter, k.id);
+ }
+
+ public updateAnimationByFrames(k: number = 1): void
+ {
+ this._frameCounter += k;
+ this._changes = true;
+ }
+
+ public resetAnimationFrameCounter(): void
+ {
+ this._frameCounter = 0;
+ this._changes = true;
+ }
+
+ private getFullImageCacheKey(): string
+ {
+ if(!this._useFullImageCache) return null;
+
+ if(((this._sortedActions.length == 1) && (this._mainDirection == this._headDirection)))
+ {
+ return (this._mainDirection + this._currentActionsString) + (this._frameCounter % 4);
+ }
+
+ if(this._sortedActions.length == 2)
+ {
+ for(const k of this._sortedActions)
+ {
+ if(((k._Str_695 == 'fx') && ((((k._Str_727 == '33') || (k._Str_727 == '34')) || (k._Str_727 == '35')) || (k._Str_727 == '36'))))
+ {
+ return (this._mainDirection + this._currentActionsString) + 0;
+ }
+
+ if(((k._Str_695 == 'fx') && ((k._Str_727 == '38') || (k._Str_727 == '39'))))
+ {
+ return (((this._mainDirection + '_') + this._headDirection) + this._currentActionsString) + (this._frameCounter % 11);
+ }
+
+ if((k._Str_695 === 'dance') && ((k._Str_727 === '1') || (k._Str_727 === '2') || (k._Str_727 === '3') || (k._Str_727 === '4')))
+ {
+ let frame = (this._frameCounter % 8);
+
+ if((k._Str_727 === '3')) frame = (this._frameCounter % 10);
+
+ if((k._Str_727 === '4')) frame = (this._frameCounter % 16);
+
+ return (((this._mainDirection + k._Str_695) + k._Str_727) + frame);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private getBodyParts(k: string, _arg_2: string, _arg_3: number): string[]
+ {
+ if((((!(_arg_3 == this._cachedBodyPartsDirection)) || (!(_arg_2 == this._cachedBodyPartsGeometryType))) || (!(k == this._cachedBodyPartsAvatarSet))))
+ {
+ this._cachedBodyPartsDirection = _arg_3;
+ this._cachedBodyPartsGeometryType = _arg_2;
+ this._cachedBodyPartsAvatarSet = k;
+ this._cachedBodyParts = this._structure._Str_755(k, _arg_2, _arg_3);
+ }
+ return this._cachedBodyParts;
+ }
+
+ public getAvatarPartsForCamera(k: string): void
+ {
+ let _local_4: string;
+ if(this._mainAction == null)
+ {
+ return;
+ }
+ const _local_2 = this._structure._Str_1664(this._scale, this._mainAction._Str_742._Str_868);
+ if(_local_2 == null)
+ {
+ return;
+ }
+ const _local_3 = this.getBodyParts(k, this._mainAction._Str_742._Str_868, this._mainDirection);
+ let _local_6 = (_local_3.length - 1);
+ while(_local_6 >= 0)
+ {
+ _local_4 = _local_3[_local_6];
+ const _local_5 = this._cache._Str_1629(_local_4, this._frameCounter, true);
+ _local_6--;
+ }
+ }
+
+ public getImage(setType: string, hightlight: boolean, scale: number = 1, cache: boolean = true): RenderTexture
+ {
+ if(!this._changes) return this._image;
+
+ if(!this._mainAction) return null;
+
+ if(!this._actionsSorted) this.endActionAppends();
+
+ const avatarCanvas = this._structure._Str_1664(this._scale, this._mainAction._Str_742._Str_868);
+
+ if(!avatarCanvas) return null;
+
+ if(this._image && ((this._image.width !== avatarCanvas.width) || (this._image.height !== avatarCanvas.height)))
+ {
+ if(this._reusableTexture)
+ {
+ this._reusableTexture.destroy(true);
+
+ this._reusableTexture = null;
+ }
+
+ this._image = null;
+ this._isCachedImage = false;
+ }
+
+ const _local_6 = this.getBodyParts(setType, this._mainAction._Str_742._Str_868, this._mainDirection);
+
+ this._image = null;
+
+ const container = new Container();
+
+ let isCachable = true;
+ let partCount = (_local_6.length - 1);
+
+ while(partCount >= 0)
+ {
+ const set = _local_6[partCount];
+ const part = this._cache._Str_1629(set, this._frameCounter);
+
+ if(part)
+ {
+ const partCacheContainer = part.image;
+
+ if(!partCacheContainer)
+ {
+ container.destroy({
+ children: true
+ });
+
+ return null;
+ }
+
+ isCachable = ((isCachable) && (part._Str_1807));
+
+ const point = part._Str_1076.clone();
+
+ if(point)
+ {
+ point.x += avatarCanvas.offset.x;
+ point.y += avatarCanvas.offset.y;
+
+ point.x += avatarCanvas._Str_1076.x;
+ point.y += avatarCanvas._Str_1076.y;
+
+ const partContainer = new Container();
+
+ partContainer.addChild(partCacheContainer);
+
+ if(partContainer)
+ {
+ partContainer.position.set(point.x, point.y);
+
+ container.addChild(partContainer);
+ }
+ }
+ }
+
+ partCount--;
+ }
+
+ if(this._avatarSpriteData && this._avatarSpriteData._Str_832) this.convertToGrayscale(container);
+
+ if(!cache)
+ {
+ return TextureUtils.generateTexture(container, new Rectangle(0, 0, avatarCanvas.width, avatarCanvas.height));
+ }
+
+ if(this._reusableTexture)
+ {
+ Nitro.instance.renderer.render(container, this._reusableTexture, true);
+ }
+ else
+ {
+ this._reusableTexture = TextureUtils.generateTexture(container, new Rectangle(0, 0, avatarCanvas.width, avatarCanvas.height));
+ }
+
+ if(!this._reusableTexture) return null;
+
+ if(this._avatarSpriteData && this._avatarSpriteData._Str_832)
+ {
+ //this._reusableTexture = this.applyPalette(this._reusableTexture, this._avatarSpriteData.reds);
+ }
+
+ this._image = this._reusableTexture;
+ this._changes = false;
+
+ return this._image;
+ }
+
+ // public applyPalette(texture: RenderTexture, reds: number[] = [], greens: number[] = [], blues: number[] = []): RenderTexture
+ // {
+ // const textureCanvas = Nitro.instance.renderer.extract.canvas(texture);
+ // const textureCtx = textureCanvas.getContext('2d');
+ // const textureImageData = textureCtx.getImageData(0, 0, textureCanvas.width, textureCanvas.height);
+ // const data = textureImageData.data;
+
+ // for(const i = 0; i < data.length; i += 4)
+ // {
+ // let paletteColor = this._palette[data[ i + 1 ]];
+
+ // if(paletteColor === undefined) paletteColor = [ 0, 0, 0 ];
+
+ // data[ i ] = paletteColor[0];
+ // data[ i + 1 ] = paletteColor[1];
+ // data[ i + 2 ] = paletteColor[2];
+ // }
+
+ // textureCtx.putImageData(textureImageData, 0, 0);
+
+ // return Texture.from(textureCanvas);
+ // }
+
+ public getImageAsSprite(setType: string, scale: number = 1): Sprite
+ {
+ if(!this._mainAction) return null;
+
+ if(!this._actionsSorted) this.endActionAppends();
+
+ const avatarCanvas = this._structure._Str_1664(this._scale, this._mainAction._Str_742._Str_868);
+
+ if(!avatarCanvas) return null;
+
+ const setTypes = this.getBodyParts(setType, this._mainAction._Str_742._Str_868, this._mainDirection);
+ const container = new Sprite();
+ const sprite = new Sprite(Texture.EMPTY);
+
+ sprite.width = avatarCanvas.width;
+ sprite.height = avatarCanvas.height;
+
+ container.addChild(sprite);
+
+ let partCount = (setTypes.length - 1);
+
+ while(partCount >= 0)
+ {
+ const set = setTypes[partCount];
+ const part = this._cache._Str_1629(set, this._frameCounter);
+
+ if(part)
+ {
+ const partCacheContainer = part.image;
+
+ if(!partCacheContainer)
+ {
+ container.destroy({
+ children: true
+ });
+
+ return null;
+ }
+
+ const point = part._Str_1076.clone();
+
+ if(point)
+ {
+ point.x += avatarCanvas.offset.x;
+ point.y += avatarCanvas.offset.y;
+
+ point.x += avatarCanvas._Str_1076.x;
+ point.y += avatarCanvas._Str_1076.y;
+
+ const partContainer = new Container();
+
+ partContainer.addChild(partCacheContainer);
+
+ partContainer.position.set(point.x, point.y);
+
+ container.addChild(partContainer);
+ }
+ }
+
+ partCount--;
+ }
+
+ return container;
+ }
+
+ public getCroppedImage(setType: string, scale: number = 1): HTMLImageElement
+ {
+ if(!this._mainAction) return null;
+
+ if(!this._actionsSorted) this.endActionAppends();
+
+ const avatarCanvas = this._structure._Str_1664(this._scale, this._mainAction._Str_742._Str_868);
+
+ if(!avatarCanvas) return null;
+
+ const setTypes = this.getBodyParts(setType, this._mainAction._Str_742._Str_868, this._mainDirection);
+ const container = new Container();
+ const sprite = new Sprite(Texture.EMPTY);
+
+ sprite.width = avatarCanvas.width;
+ sprite.height = avatarCanvas.height;
+
+ container.addChild(sprite);
+
+ let partCount = (setTypes.length - 1);
+
+ while(partCount >= 0)
+ {
+ const set = setTypes[partCount];
+ const part = this._cache._Str_1629(set, this._frameCounter);
+
+ if(part)
+ {
+ const partCacheContainer = part.image;
+
+ if(!partCacheContainer)
+ {
+ container.destroy({
+ children: true
+ });
+
+ return null;
+ }
+
+ const point = part._Str_1076.clone();
+
+ if(point)
+ {
+ point.x += avatarCanvas.offset.x;
+ point.y += avatarCanvas.offset.y;
+
+ point.x += avatarCanvas._Str_1076.x;
+ point.y += avatarCanvas._Str_1076.y;
+
+ const partContainer = new Container();
+
+ partContainer.addChild(partCacheContainer);
+
+ if(partContainer)
+ {
+ partContainer.position.set(point.x, point.y);
+
+ container.addChild(partContainer);
+ }
+ }
+ }
+
+ partCount--;
+ }
+
+ const image = Nitro.instance.renderer.extract.image(container);
+
+ if(!image) return null;
+
+ return image;
+ }
+
+ protected getFullImage(k: string): RenderTexture
+ {
+ const existing = this._fullImageCache.getValue(k);
+
+ if(existing)
+ {
+ if(!existing.valid)
+ {
+ this._fullImageCache.remove(k);
+
+ existing.destroy(true);
+ }
+
+ return existing;
+ }
+
+ return null;
+ }
+
+ protected cacheFullImage(k: string, _arg_2: RenderTexture): void
+ {
+ const existing = this._fullImageCache.getValue(k);
+
+ if(existing)
+ {
+ this._fullImageCache.remove(k);
+
+ existing.destroy(true);
+ }
+
+ if(this._fullImageCache.length === this._fullImageCacheSize)
+ {
+ const oldestKey = this._fullImageCache.getKey(0);
+
+ if(oldestKey)
+ {
+ const removed = this._fullImageCache.remove(oldestKey);
+
+ removed.destroy(true);
+ }
+ }
+
+ this._fullImageCache.add(k, _arg_2);
+ }
+
+ public getAsset(k: string): IGraphicAsset
+ {
+ return this._assets.getAsset(k);
+ }
+
+ public getDirection(): number
+ {
+ return this._mainDirection;
+ }
+
+ public initActionAppends(): void
+ {
+ this._actions = [];
+ this._actionsSorted = false;
+ this._currentActionsString = '';
+ this._useFullImageCache = false;
+ }
+
+ public endActionAppends(): void
+ {
+ let k:ActiveActionData;
+
+ if(!this.sortActions()) return;
+
+ for(const k of this._sortedActions)
+ {
+ if(k._Str_695 === AvatarAction.EFFECT)
+ {
+ if(!this._effectManager.isAvatarEffectReady(parseInt(k._Str_727))) this._effectManager.downloadAvatarEffect(parseInt(k._Str_727), this);
+ }
+ }
+
+ this.resetActions();
+ this.setActionsToParts();
+ }
+
+ public appendAction(k: string, ..._args: any[]): boolean
+ {
+ let _local_3 = '';
+
+ this._actionsSorted = false;
+
+ if(_args && (_args.length > 0)) _local_3 = _args[0];
+
+ if((_local_3 !== undefined) && (_local_3 !== null)) _local_3 = _local_3.toString();
+
+ switch(k)
+ {
+ case AvatarAction.POSTURE:
+ switch(_local_3)
+ {
+ case AvatarAction.POSTURE_LAY:
+ if(this._mainDirection == 0)
+ {
+ this.setDirection(AvatarSetType.FULL, 4);
+ }
+ else
+ {
+ this.setDirection(AvatarSetType.FULL, 2);
+ }
+ // eslint-disable-next-line no-fallthrough
+ case AvatarAction.POSTURE_WALK:
+ case AvatarAction.POSTURE_STAND:
+ this._useFullImageCache = true;
+ this._useFullImageCache = true;
+ // eslint-disable-next-line no-fallthrough
+ case AvatarAction.POSTURE_SWIM:
+ case AvatarAction.POSTURE_FLOAT:
+ case AvatarAction.POSTURE_SIT:
+ case AvatarAction.SNOWWAR_RUN:
+ case AvatarAction.SNOWWAR_DIE_FRONT:
+ case AvatarAction.SNOWWAR_DIE_BACK:
+ case AvatarAction.SNOWWAR_PICK:
+ case AvatarAction.SNOWWAR_THROW:
+ this.addActionData(_local_3);
+ break;
+ }
+ break;
+ case AvatarAction.GESTURE:
+ switch(_local_3)
+ {
+ case AvatarAction.GESTURE_AGGRAVATED:
+ case AvatarAction.GESTURE_SAD:
+ case AvatarAction.GESTURE_SMILE:
+ case AvatarAction.GESTURE_SURPRISED:
+ this.addActionData(_local_3);
+ break;
+ }
+ break;
+ case AvatarAction.EFFECT:
+ if((((((_local_3 === '33') || (_local_3 === '34')) || (_local_3 === '35')) || (_local_3 === '36')) || (_local_3 === '38')) || (_local_3 === '39'))
+ {
+ this._useFullImageCache = true;
+ }
+ // eslint-disable-next-line no-fallthrough
+ case AvatarAction.DANCE:
+ case AvatarAction.TALK:
+ case AvatarAction.EXPRESSION_WAVE:
+ case AvatarAction.SLEEP:
+ case AvatarAction.SIGN:
+ case AvatarAction.EXPRESSION_RESPECT:
+ case AvatarAction.EXPRESSION_BLOW_A_KISS:
+ case AvatarAction.EXPRESSION_LAUGH:
+ case AvatarAction.EXPRESSION_CRY:
+ case AvatarAction.EXPRESSION_IDLE:
+ case AvatarAction.EXPRESSION_SNOWBOARD_OLLIE:
+ case AvatarAction.EXPRESSION_SNOWBORD_360:
+ case AvatarAction.EXPRESSION_RIDE_JUMP:
+ this.addActionData(k, _local_3);
+ break;
+ case AvatarAction.CARRY_OBJECT:
+ case AvatarAction.USE_OBJECT: {
+ const _local_4 = this._structure._Str_2018(k);
+ if(_local_4) _local_3 = _local_4._Str_1350(_local_3);
+ this.addActionData(k, _local_3);
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ protected addActionData(k: string, _arg_2: string=''): void
+ {
+ let _local_3:ActiveActionData;
+ if(!this._actions) this._actions = [];
+
+ let _local_4 = 0;
+ while(_local_4 < this._actions.length)
+ {
+ _local_3 = this._actions[_local_4];
+ if(((_local_3._Str_695 == k) && (_local_3._Str_727 == _arg_2)))
+ {
+ return;
+ }
+ _local_4++;
+ }
+ this._actions.push(new ActiveActionData(k, _arg_2, this._frameCounter));
+ }
+
+ public isAnimating(): boolean
+ {
+ return (this._isAnimating) || (this._animationFrameCount > 1);
+ }
+
+ private resetActions(): boolean
+ {
+ this._animationHasResetOnToggle = false;
+ this._isAnimating = false;
+ this._sprites = [];
+ this._avatarSpriteData = null;
+ this._directionOffset = 0;
+ this._structure._Str_2101(this);
+ this._mainAction = this._defaultAction;
+ this._mainAction._Str_742 = this._defaultAction._Str_742;
+ this.resetBodyPartCache(this._defaultAction);
+ return true;
+ }
+
+ private isHeadTurnPreventedByAction(): boolean
+ {
+ let _local_2: IActionDefinition;
+ let _local_3: ActiveActionData;
+ let k: boolean;
+ if(this._sortedActions == null)
+ {
+ return false;
+ }
+ for(const _local_3 of this._sortedActions)
+ {
+ _local_2 = this._structure._Str_2018(_local_3._Str_695);
+ if(((!(_local_2 == null)) && (_local_2._Str_715(_local_3._Str_727))))
+ {
+ k = true;
+ }
+ }
+ return k;
+ }
+
+ private sortActions(): boolean
+ {
+ let _local_2: boolean;
+ let _local_3: boolean;
+ let _local_4:ActiveActionData;
+ let _local_5: number;
+ let k: boolean;
+
+ this._currentActionsString = '';
+ this._sortedActions = this._structure._Str_711(this._actions);
+ this._animationFrameCount = this._structure._Str_1936(this._sortedActions);
+
+ if(!this._sortedActions)
+ {
+ this._canvasOffsets = [ 0, 0, 0 ];
+
+ if(this._lastActionsString !== '')
+ {
+ k = true;
+
+ this._lastActionsString = '';
+ }
+ }
+ else
+ {
+ this._canvasOffsets = this._structure._Str_781(this._sortedActions, this._scale, this._mainDirection);
+
+ for(const _local_4 of this._sortedActions)
+ {
+ this._currentActionsString = (this._currentActionsString + (_local_4._Str_695 + _local_4._Str_727));
+
+ if(_local_4._Str_695 === AvatarAction.EFFECT)
+ {
+ const _local_5 = parseInt(_local_4._Str_727);
+
+ if(this._effectIdInUse !== _local_5) _local_2 = true;
+
+ this._effectIdInUse = _local_5;
+
+ _local_3 = true;
+ }
+ }
+
+ if(!_local_3)
+ {
+ if(this._effectIdInUse > -1) _local_2 = true;
+
+ this._effectIdInUse = -1;
+ }
+
+ if(_local_2) this._cache._Str_1086(0);
+
+ if(this._lastActionsString != this._currentActionsString)
+ {
+ k = true;
+
+ this._lastActionsString = this._currentActionsString;
+ }
+ }
+
+ this._actionsSorted = true;
+
+ return k;
+ }
+
+ private setActionsToParts(): void
+ {
+ if(!this._sortedActions == null) return;
+
+ const _local_3: number = Nitro.instance.time;
+ const _local_4: string[] = [];
+
+ for(const k of this._sortedActions) _local_4.push(k._Str_695);
+
+ for(const k of this._sortedActions)
+ {
+ if((k && k._Str_742) && k._Str_742._Str_861)
+ {
+ const _local_2 = this._structure._Str_720(((k._Str_742.state + '.') + k._Str_727));
+
+ if(_local_2 && _local_2._Str_1892())
+ {
+ const _local_5 = _local_2._Str_1571();
+
+ if(_local_5)
+ {
+ for(const _local_6 of _local_5)
+ {
+ if(_local_4.indexOf(_local_6) >= 0) k._Str_707 = _local_2._Str_707(_local_6);
+ }
+ }
+ }
+
+ if(_local_2 && _local_2.resetOnToggle)
+ {
+ this._animationHasResetOnToggle = true;
+ }
+ }
+ }
+
+ for(const k of this._sortedActions)
+ {
+ if(!((!(k)) || (!(k._Str_742))))
+ {
+ if(k._Str_742._Str_861 && (k._Str_727 === '')) k._Str_727 = '1';
+
+ this.setActionToParts(k, _local_3);
+
+ if(k._Str_742._Str_861)
+ {
+ this._isAnimating = k._Str_742._Str_801(k._Str_727);
+
+ const _local_2 = this._structure._Str_720(((k._Str_742.state + '.') + k._Str_727));
+
+ if(_local_2)
+ {
+ this._sprites = this._sprites.concat(_local_2._Str_786);
+
+ if(_local_2._Str_776()) this._directionOffset = _local_2._Str_1493.offset;
+
+ if(_local_2._Str_872()) this._avatarSpriteData = _local_2._Str_1475;
+ }
+ }
+ }
+ }
+ }
+
+ private setActionToParts(k: IActiveActionData, _arg_2: number): void
+ {
+ if(((k == null) || (k._Str_742 == null)))
+ {
+ return;
+ }
+ if(k._Str_742._Str_778 == '')
+ {
+ return;
+ }
+ if(k._Str_742._Str_779)
+ {
+ this._mainAction = k;
+ this._cache._Str_2014(k._Str_742._Str_868);
+ }
+ this._cache._Str_1565(k, _arg_2);
+ this._changes = true;
+ }
+
+ private resetBodyPartCache(k: IActiveActionData): void
+ {
+ if(!k) return;
+
+ if(k._Str_742._Str_778 === '') return;
+
+ if(k._Str_742._Str_779)
+ {
+ this._mainAction = k;
+ this._cache._Str_2014(k._Str_742._Str_868);
+ }
+
+ this._cache._Str_741(k);
+ this._changes = true;
+ }
+
+ public get avatarSpriteData(): IAvatarDataContainer
+ {
+ return this._avatarSpriteData;
+ }
+
+ private convertToGrayscale(container: Container, channel: string = 'CHANNELS_EQUAL'): Container
+ {
+ let _local_3 = 0.33;
+ let _local_4 = 0.33;
+ let _local_5 = 0.33;
+ const _local_6 = 1;
+
+ switch(channel)
+ {
+ case AvatarImage.CHANNELS_UNIQUE:
+ _local_3 = 0.3;
+ _local_4 = 0.59;
+ _local_5 = 0.11;
+ break;
+ case AvatarImage.CHANNELS_RED:
+ _local_3 = 1;
+ _local_4 = 0;
+ _local_5 = 0;
+ break;
+ case AvatarImage.CHANNELS_GREEN:
+ _local_3 = 0;
+ _local_4 = 1;
+ _local_5 = 0;
+ break;
+ case AvatarImage.CHANNELS_BLUE:
+ _local_3 = 0;
+ _local_4 = 0;
+ _local_5 = 1;
+ break;
+ case AvatarImage.CHANNELS_DESATURATED:
+ _local_3 = 0.3086;
+ _local_4 = 0.6094;
+ _local_5 = 0.082;
+ break;
+ }
+
+ const colorFilter = new filters.ColorMatrixFilter();
+
+ colorFilter.matrix = [_local_3, _local_4, _local_5, 0, 0, _local_3, _local_4, _local_5, 0, 0, _local_3, _local_4, _local_5, 0, 0, 0, 0, 0, 1, 0];
+
+ container.filters = [ colorFilter ];
+
+ return container;
+ }
+
+ private errorThis(k: string): void
+ {
+ }
+
+ private logThis(k: string): void
+ {
+ }
+
+ public isPlaceholder(): boolean
+ {
+ return false;
+ }
+
+ public forceActionUpdate(): void
+ {
+ this._lastActionsString = '';
+ }
+
+ public get animationHasResetOnToggle(): boolean
+ {
+ return this._animationHasResetOnToggle;
+ }
+
+ public get mainAction(): string
+ {
+ return this._mainAction._Str_695;
+ }
+
+ public resetEffect(effect: number): void
+ {
+ if(effect === this._effectIdInUse)
+ {
+ this.resetActions();
+ this.setActionsToParts();
+
+ this._animationHasResetOnToggle = true;
+ this._changes = true;
+
+ if(this._effectListener) this._effectListener.resetEffect(effect);
+ }
+ }
+}
diff --git a/src/nitro/avatar/AvatarImageBodyPartContainer.ts b/src/nitro/avatar/AvatarImageBodyPartContainer.ts
new file mode 100644
index 00000000..941ea6dc
--- /dev/null
+++ b/src/nitro/avatar/AvatarImageBodyPartContainer.ts
@@ -0,0 +1,88 @@
+import { Container, Point } from 'pixi.js';
+
+export class AvatarImageBodyPartContainer
+{
+ private _image: Container;
+ private _regPoint: Point;
+ private _offset: Point;
+ private _isCacheable: boolean;
+
+ constructor(k: Container, _arg_2: Point, _arg_3: boolean)
+ {
+ this._image = k;
+ this._regPoint = _arg_2;
+ this._offset = new Point(0, 0);
+ this._regPoint = _arg_2;
+ this._isCacheable = _arg_3;
+
+ this._Str_1225();
+ }
+
+ public dispose(): void
+ {
+ if(this._image)
+ {
+ this._image.destroy({
+ children: true
+ });
+ }
+
+ this._image = null;
+ this._regPoint = null;
+ this._offset = null;
+ }
+
+ private _Str_1225(): void
+ {
+ // this._regPoint.x = this._regPoint.x;
+ // this._regPoint.y = this._regPoint.y;
+ // this._offset.x = this._offset.x;
+ // this._offset.y = this._offset.y;
+ }
+
+ public _Str_1387(k: Point): void
+ {
+ this._regPoint = k;
+
+ this._Str_1225();
+ }
+
+ public get image(): Container
+ {
+ return this._image;
+ }
+
+ public set image(k: Container)
+ {
+ if(this._image && (this._image !== k))
+ {
+ this._image.destroy({
+ children: true
+ });
+ }
+
+ this._image = k;
+ }
+
+ public get _Str_1076(): Point
+ {
+ const clone = this._regPoint.clone();
+
+ clone.x += this._offset.x;
+ clone.y += this._offset.y;
+
+ return clone;
+ }
+
+ public set offset(k: Point)
+ {
+ this._offset = k;
+
+ this._Str_1225();
+ }
+
+ public get _Str_1807(): boolean
+ {
+ return this._isCacheable;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/AvatarImagePartContainer.ts b/src/nitro/avatar/AvatarImagePartContainer.ts
new file mode 100644
index 00000000..02e10d9a
--- /dev/null
+++ b/src/nitro/avatar/AvatarImagePartContainer.ts
@@ -0,0 +1,137 @@
+import { AdjustmentFilter } from '@pixi/filter-adjustment';
+import { IActionDefinition } from './actions/IActionDefinition';
+import { AnimationFrame } from './structure/animation/AnimationFrame';
+import { IPartColor } from './structure/figure/IPartColor';
+
+export class AvatarImagePartContainer
+{
+ private _bodyPartId: string;
+ private _partType: string;
+ private _flippedPartType: string;
+ private _partId: string;
+ private _color: IPartColor;
+ private _frames: AnimationFrame[];
+ private _action: IActionDefinition;
+ private _isColorable: boolean;
+ private _isBlendable: boolean;
+ private _blendTransform: AdjustmentFilter;
+ private _paletteMapId: number;
+
+ constructor(k: string, _arg_2: string, _arg_3: string, _arg_4: IPartColor, _arg_5: AnimationFrame[], _arg_6: IActionDefinition, _arg_7: boolean, _arg_8: number, _arg_9: string = '', _arg_10: boolean = false, _arg_11: number = 1)
+ {
+ this._bodyPartId = k;
+ this._partType = _arg_2;
+ this._partId = _arg_3;
+ this._color = _arg_4;
+ this._frames = _arg_5;
+ this._action = _arg_6;
+ this._isColorable = _arg_7;
+ this._paletteMapId = _arg_8;
+ this._flippedPartType = _arg_9;
+ this._isBlendable = _arg_10;
+ this._blendTransform = null;
+
+ if(this._partType === 'ey') this._isColorable = false;
+ }
+
+ public _Str_1674(k: number): number
+ {
+ if(!this._frames || !this._frames.length) return 0;
+
+ const frameNumber = (k % this._frames.length);
+
+ if(this._frames[frameNumber] instanceof AnimationFrame)
+ {
+ return this._frames[frameNumber].number;
+ }
+
+ return frameNumber;
+ }
+
+ public _Str_2258(k: number): AnimationFrame
+ {
+ const frameNumber = (k % this._frames.length);
+
+ if(this._frames && (this._frames.length > frameNumber))
+ {
+ if(this._frames[frameNumber] instanceof AnimationFrame)
+ {
+ return this._frames[frameNumber];
+ }
+ }
+
+ return null;
+ }
+
+ public _Str_1206(k: number): string
+ {
+ const frameNumber = (k % this._frames.length);
+
+ if(this._frames && (this._frames.length > frameNumber))
+ {
+ if(this._frames[frameNumber] instanceof AnimationFrame)
+ {
+ const frame = this._frames[frameNumber];
+
+ return (this._Str_1502 + ':' + frame._Str_778 + ':' + frame.number);
+ }
+ }
+
+ return (this._Str_1502 + ':' + frameNumber);
+ }
+
+ public get _Str_1360(): string
+ {
+ return this._bodyPartId;
+ }
+
+ public get _Str_1669(): string
+ {
+ return this._partType;
+ }
+
+ public get _Str_1502(): string
+ {
+ return this._partId;
+ }
+
+ public get color(): IPartColor
+ {
+ return this._color;
+ }
+
+ public get action(): IActionDefinition
+ {
+ return this._action;
+ }
+
+ public get isColorable(): boolean
+ {
+ return this._isColorable;
+ }
+
+ public set isColorable(k: boolean)
+ {
+ this._isColorable = k;
+ }
+
+ public get _Str_1406(): number
+ {
+ return this._paletteMapId;
+ }
+
+ public get _Str_1666(): string
+ {
+ return this._flippedPartType;
+ }
+
+ public get _Str_1184(): boolean
+ {
+ return this._isBlendable;
+ }
+
+ public toString(): string
+ {
+ return [ this._bodyPartId, this._partType, this._partId ].join(':');
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/AvatarRenderManager.ts b/src/nitro/avatar/AvatarRenderManager.ts
new file mode 100644
index 00000000..ea201067
--- /dev/null
+++ b/src/nitro/avatar/AvatarRenderManager.ts
@@ -0,0 +1,477 @@
+import { Parser } from 'xml2js';
+import { IAssetManager } from '../../core/asset/IAssetManager';
+import { NitroManager } from '../../core/common/NitroManager';
+import { NitroEvent } from '../../core/events/NitroEvent';
+import { IGraphicAsset } from '../../room/object/visualization/utils/IGraphicAsset';
+import { Nitro } from '../Nitro';
+import { FigureDataContainer } from '../utils/FigureDataContainer';
+import { AssetAliasCollection } from './alias/AssetAliasCollection';
+import { AvatarAssetDownloadManager } from './AvatarAssetDownloadManager';
+import { AvatarFigureContainer } from './AvatarFigureContainer';
+import { AvatarImage } from './AvatarImage';
+import { AvatarStructure } from './AvatarStructure';
+import * as HabboAvatarAnimations from './data/HabboAvatarAnimations.json';
+import * as HabboAvatarGeometry from './data/HabboAvatarGeometry.json';
+import * as HabboAvatarPartSets from './data/HabboAvatarPartSets.json';
+import { EffectAssetDownloadManager } from './EffectAssetDownloadManager';
+import { AvatarSetType } from './enum/AvatarSetType';
+import { AvatarRenderEvent } from './events/AvatarRenderEvent';
+import { IAvatarEffectListener } from './IAvatarEffectListener';
+import { IAvatarFigureContainer } from './IAvatarFigureContainer';
+import { IAvatarImage } from './IAvatarImage';
+import { IAvatarImageListener } from './IAvatarImageListener';
+import { IAvatarRenderManager } from './IAvatarRenderManager';
+import { PlaceHolderAvatarImage } from './PlaceHolderAvatarImage';
+import { AvatarStructureDownload } from './structure/AvatarStructureDownload';
+import { IFigurePartSet } from './structure/figure/IFigurePartSet';
+import { IFigureSetData } from './structure/IFigureSetData';
+import { IStructureData } from './structure/IStructureData';
+
+export class AvatarRenderManager extends NitroManager implements IAvatarRenderManager
+{
+ private static DEFAULT_FIGURE: string = 'hd-99999-99999';
+
+ private _aliasCollection: AssetAliasCollection;
+
+ private _structure: AvatarStructure;
+ private _avatarAssetDownloadManager: AvatarAssetDownloadManager;
+ private _effectAssetDownloadManager: EffectAssetDownloadManager;
+
+ private _placeHolderFigure: AvatarFigureContainer;
+
+ private _figureMapReady: boolean;
+ private _effectMapReady: boolean;
+ private _actionsReady: boolean;
+ private _structureReady: boolean;
+ private _geometryReady: boolean;
+ private _partSetsReady: boolean;
+ private _animationsReady: boolean;
+ private _isReady: boolean;
+
+ constructor()
+ {
+ super();
+
+ this._structure = null;
+ this._avatarAssetDownloadManager = null;
+
+ this._placeHolderFigure = null;
+
+ this._figureMapReady = false;
+ this._effectMapReady = false;
+ this._actionsReady = false;
+ this._geometryReady = false;
+ this._partSetsReady = false;
+ this._animationsReady = false;
+ this._isReady = false;
+
+ this.onAvatarAssetDownloaderReady = this.onAvatarAssetDownloaderReady.bind(this);
+ this.onAvatarAssetDownloaded = this.onAvatarAssetDownloaded.bind(this);
+ this.onEffectAssetDownloaderReady = this.onEffectAssetDownloaderReady.bind(this);
+ this.onEffectAssetDownloaded = this.onEffectAssetDownloaded.bind(this);
+ this.onAvatarStructureDownloadDone = this.onAvatarStructureDownloadDone.bind(this);
+ }
+
+ public onInit(): void
+ {
+ this._structure = new AvatarStructure(this);
+
+ this.loadGeometry();
+ this.loadPartSets();
+ this.loadActions();
+ this.loadAnimations();
+ this.loadFigureData();
+
+ this._aliasCollection = new AssetAliasCollection(this, Nitro.instance.core.asset);
+
+ this._aliasCollection.init();
+
+ if(!this._avatarAssetDownloadManager)
+ {
+ this._avatarAssetDownloadManager = new AvatarAssetDownloadManager(Nitro.instance.core.asset, this._structure);
+
+ this._avatarAssetDownloadManager.addEventListener(AvatarAssetDownloadManager.DOWNLOADER_READY, this.onAvatarAssetDownloaderReady);
+ this._avatarAssetDownloadManager.addEventListener(AvatarAssetDownloadManager.LIBRARY_LOADED, this.onAvatarAssetDownloaded);
+ }
+
+ if(!this._effectAssetDownloadManager)
+ {
+ this._effectAssetDownloadManager = new EffectAssetDownloadManager(Nitro.instance.core.asset, this._structure);
+
+ this._effectAssetDownloadManager.addEventListener(EffectAssetDownloadManager.DOWNLOADER_READY, this.onEffectAssetDownloaderReady);
+ this._effectAssetDownloadManager.addEventListener(EffectAssetDownloadManager.LIBRARY_LOADED, this.onEffectAssetDownloaded);
+ }
+
+ this.checkReady();
+ }
+
+ public onDispose(): void
+ {
+ if(this._avatarAssetDownloadManager)
+ {
+ this._avatarAssetDownloadManager.removeEventListener(AvatarAssetDownloadManager.DOWNLOADER_READY, this.onAvatarAssetDownloaderReady);
+
+ this._avatarAssetDownloadManager.removeEventListener(AvatarAssetDownloadManager.LIBRARY_LOADED, this.onAvatarAssetDownloaded);
+ }
+
+ if(this._effectAssetDownloadManager)
+ {
+ this._effectAssetDownloadManager.removeEventListener(EffectAssetDownloadManager.DOWNLOADER_READY, this.onEffectAssetDownloaderReady);
+
+ this._effectAssetDownloadManager.removeEventListener(EffectAssetDownloadManager.LIBRARY_LOADED, this.onEffectAssetDownloaded);
+ }
+ }
+
+ private loadGeometry(): void
+ {
+ if(!this._structure) return;
+
+ this._structure._Str_1825(HabboAvatarGeometry.geometry);
+
+ this._geometryReady = true;
+
+ this.checkReady();
+ }
+
+ private loadPartSets(): void
+ {
+ if(!this._structure) return;
+
+ this._structure._Str_1296(HabboAvatarPartSets.partSets);
+
+ this._partSetsReady = true;
+
+ this.checkReady();
+ }
+
+ private loadActions(): void
+ {
+ const defaultActions = Nitro.instance.getConfiguration('avatar.default.actions');
+
+ if(defaultActions) this._structure._Str_1060(Nitro.instance.core.asset, defaultActions);
+
+ const request = new XMLHttpRequest();
+
+ try
+ {
+ request.open('GET', Nitro.instance.getConfiguration('avatar.actions.url'));
+
+ request.send();
+
+ request.onloadend = e =>
+ {
+ if(!this._structure) return;
+
+ this._structure._Str_1620(JSON.parse(request.responseText));
+
+ this._actionsReady = true;
+
+ this.checkReady();
+ };
+
+ request.onerror = e =>
+ {
+ throw new Error('invalid_avatar_actions');
+ };
+ }
+
+ catch (e)
+ {
+ this.logger.error(e);
+ }
+ }
+
+ private loadAnimations(): void
+ {
+ if(!this._structure) return;
+
+ this._structure._Str_2229(HabboAvatarAnimations.animations);
+
+ this._animationsReady = true;
+
+ this.checkReady();
+ }
+
+ private loadFigureData(): void
+ {
+ const defaultFigureData = Nitro.instance.getConfiguration('avatar.default.figuredata');
+
+ if(defaultFigureData)
+ {
+ const parser = new Parser();
+
+ parser.parseString(defaultFigureData, (err: Error, results: any) =>
+ {
+ if(err || !results || !results.figuredata) throw new Error('invalid_default_figure_data');
+
+ if(this._structure) this._structure._Str_1569(results.figuredata);
+ });
+ }
+
+ const structureDownloader = new AvatarStructureDownload(Nitro.instance.getConfiguration('avatar.figuredata.url'), (this._structure.figureData as IFigureSetData));
+
+ structureDownloader.addEventListener(AvatarStructureDownload.AVATAR_STRUCTURE_DONE, this.onAvatarStructureDownloadDone);
+ }
+
+ private onAvatarStructureDownloadDone(event: NitroEvent): void
+ {
+ this._structureReady = true;
+
+ this._structure.init();
+
+ this.checkReady();
+ }
+
+ private onAvatarAssetDownloaderReady(event: NitroEvent): void
+ {
+ if(!event) return;
+
+ this._figureMapReady = true;
+
+ this.checkReady();
+ }
+
+ private onAvatarAssetDownloaded(event: NitroEvent): void
+ {
+ if(!event) return;
+
+ this._aliasCollection.reset();
+ }
+
+ private onEffectAssetDownloaderReady(event: NitroEvent): void
+ {
+ if(!event) return;
+
+ this._effectMapReady = true;
+
+ this.checkReady();
+ }
+
+ private onEffectAssetDownloaded(event: NitroEvent): void
+ {
+ if(!event) return;
+
+ this._aliasCollection.reset();
+ }
+
+ private checkReady(): void
+ {
+ if(this._isReady) return;
+
+ if(!this._geometryReady || !this._partSetsReady || !this._actionsReady || !this._animationsReady || !this._figureMapReady || !this._effectMapReady || !this._structureReady) return;
+
+ this._isReady = true;
+
+ if(this.events) this.events.dispatchEvent(new NitroEvent(AvatarRenderEvent.AVATAR_RENDER_READY));
+ }
+
+ public createFigureContainer(figure: string): IAvatarFigureContainer
+ {
+ return new AvatarFigureContainer(figure);
+ }
+
+ public isFigureContainerReady(container: IAvatarFigureContainer): boolean
+ {
+ if(!this._avatarAssetDownloadManager) return false;
+
+ return this._avatarAssetDownloadManager.isAvatarFigureContainerReady(container);
+ }
+
+ public createAvatarImage(figure: string, size: string, gender: string, listener: IAvatarImageListener = null, effectListener: IAvatarEffectListener = null): IAvatarImage
+ {
+ if(!this._structure || !this._avatarAssetDownloadManager) return null;
+
+ const figureContainer = new AvatarFigureContainer(figure);
+
+ if(gender) this.validateAvatarFigure(figureContainer, gender);
+
+ if(this._avatarAssetDownloadManager.isAvatarFigureContainerReady(figureContainer))
+ {
+ return new AvatarImage(this._structure, this._aliasCollection, figureContainer, size, this._effectAssetDownloadManager, effectListener);
+ }
+
+ if(!this._placeHolderFigure) this._placeHolderFigure = new AvatarFigureContainer(AvatarRenderManager.DEFAULT_FIGURE);
+
+ this._avatarAssetDownloadManager.downloadAvatarFigure(figureContainer, listener);
+
+ return new PlaceHolderAvatarImage(this._structure, this._aliasCollection, this._placeHolderFigure, size, this._effectAssetDownloadManager);
+ }
+
+ public downloadAvatarFigure(container: IAvatarFigureContainer, listener: IAvatarImageListener): void
+ {
+ if(!this._avatarAssetDownloadManager) return;
+
+ this._avatarAssetDownloadManager.downloadAvatarFigure(container, listener);
+ }
+
+ private validateAvatarFigure(container: AvatarFigureContainer, gender: string): boolean
+ {
+ let isValid = false;
+
+ const typeIds = this._structure._Str_1733(gender, 2);
+
+ if(typeIds)
+ {
+ const figureData = this._structure.figureData;
+
+ for(const id of typeIds)
+ {
+ if(!container._Str_744(id))
+ {
+ const figurePartSet = this._structure._Str_2264(id, gender);
+
+ if(figurePartSet)
+ {
+ container._Str_830(id, figurePartSet.id, [0]);
+
+ isValid = true;
+ }
+ }
+ else
+ {
+ const setType = figureData._Str_740(id);
+
+ if(setType)
+ {
+ const figurePartSet = setType._Str_1020(container.getPartSetId(id));
+
+ if(!figurePartSet)
+ {
+ const partSet = this._structure._Str_2264(id, gender);
+
+ if(partSet)
+ {
+ container._Str_830(id, partSet.id, [0]);
+
+ isValid = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return !(isValid);
+ }
+
+ public getFigureClubLevel(container: IAvatarFigureContainer, gender: string, searchParts: string[]): number
+ {
+ if(!this._structure) return 0;
+
+ const figureData = this._structure.figureData;
+ const parts = Array.from(container._Str_1016());
+
+ let clubLevel = 0;
+
+ for(const part of parts)
+ {
+ const set = figureData._Str_740(part);
+ const setId = container.getPartSetId(part);
+ const partSet = set._Str_1020(setId);
+
+ if(partSet)
+ {
+ clubLevel = Math.max(partSet.clubLevel, clubLevel);
+
+ const palette = figureData._Str_783(set._Str_734);
+ const colors = container._Str_815(part);
+
+ for(const colorId of colors)
+ {
+ const color = palette._Str_751(colorId);
+
+ clubLevel = Math.max(color.clubLevel, clubLevel);
+ }
+ }
+ }
+
+ if(!searchParts) searchParts = this._structure._Str_1695(AvatarSetType.FULL);
+
+ for(const part of searchParts)
+ {
+ const set = figureData._Str_740(part);
+
+ if(parts.indexOf(part) === -1) clubLevel = Math.max(set._Str_1002(gender), clubLevel);
+ }
+
+ return clubLevel;
+ }
+
+ public isValidFigureSetForGender(setId: number, gender: string): boolean
+ {
+ const structure = this.structureData;
+ const partSet = structure._Str_938(setId);
+
+ return !!(partSet && ((partSet.gender.toUpperCase() === 'U') || (partSet.gender.toUpperCase() === gender.toUpperCase())));
+ }
+
+ public getFigureStringWithFigureIds(k: string, _arg_2: string, _arg_3: number[]): string
+ {
+ const container = new FigureDataContainer();
+
+ container._Str_2153(k, _arg_2);
+
+ const partSets: IFigurePartSet[] = this._Str_1667(_arg_3);
+
+ for(const partSet of partSets)
+ {
+ container._Str_2088(partSet.type, partSet.id, container.getColourIds(partSet.type));
+ }
+
+ return container._Str_1008();
+ }
+
+ private _Str_1667(k: number[]): IFigurePartSet[]
+ {
+ const structure = this.structureData;
+ const partSets: IFigurePartSet[] = [];
+
+ for(const _local_4 of k)
+ {
+ const partSet = structure._Str_938(_local_4);
+
+ if(partSet) partSets.push(partSet);
+ }
+
+ return partSets;
+ }
+
+ public _Str_838(k: string, _arg_2: number): string[]
+ {
+ if(!this._structure) return null;
+
+ return this._structure._Str_1733(k, _arg_2);
+ }
+
+ public getAssetByName(name: string): IGraphicAsset
+ {
+ return this._aliasCollection.getAsset(name);
+ }
+
+ public get assets(): IAssetManager
+ {
+ return Nitro.instance.core.asset;
+ }
+
+ public get isReady(): boolean
+ {
+ return this._isReady;
+ }
+
+ public get structure(): AvatarStructure
+ {
+ return this._structure;
+ }
+
+ public get structureData(): IStructureData
+ {
+ if(this._structure) return this._structure.figureData;
+
+ return null;
+ }
+
+ public get downloadManager(): AvatarAssetDownloadManager
+ {
+ return this._avatarAssetDownloadManager;
+ }
+}
diff --git a/src/nitro/avatar/AvatarStructure.ts b/src/nitro/avatar/AvatarStructure.ts
new file mode 100644
index 00000000..4f6377e7
--- /dev/null
+++ b/src/nitro/avatar/AvatarStructure.ts
@@ -0,0 +1,653 @@
+import { Point } from 'pixi.js';
+import { IAssetManager } from '../../core/asset/IAssetManager';
+import { IAssetAnimation } from '../../core/asset/interfaces';
+import { EventDispatcher } from '../../core/events/EventDispatcher';
+import { ActionDefinition } from './actions/ActionDefinition';
+import { AvatarActionManager } from './actions/AvatarActionManager';
+import { IActionDefinition } from './actions/IActionDefinition';
+import { IActiveActionData } from './actions/IActiveActionData';
+import { Animation } from './animation/Animation';
+import { AnimationLayerData } from './animation/AnimationLayerData';
+import { AnimationManager } from './animation/AnimationManager';
+import { AvatarImagePartContainer } from './AvatarImagePartContainer';
+import { AvatarRenderManager } from './AvatarRenderManager';
+import { AvatarDirectionAngle } from './enum/AvatarDirectionAngle';
+import { AvatarModelGeometry } from './geometry/AvatarModelGeometry';
+import { IAvatarFigureContainer } from './IAvatarFigureContainer';
+import { IAvatarImage } from './IAvatarImage';
+import { IAvatarRenderManager } from './IAvatarRenderManager';
+import { AnimationAction } from './structure/animation/AnimationAction';
+import { AnimationFrame } from './structure/animation/AnimationFrame';
+import { AnimationData } from './structure/AnimationData';
+import { AvatarCanvas } from './structure/AvatarCanvas';
+import { IFigurePartSet } from './structure/figure/IFigurePartSet';
+import { IPartColor } from './structure/figure/IPartColor';
+import { FigureSetData } from './structure/FigureSetData';
+import { IStructureData } from './structure/IStructureData';
+import { PartSetsData } from './structure/PartSetsData';
+
+export class AvatarStructure extends EventDispatcher
+{
+ private _renderManager: AvatarRenderManager;
+ private _geometry: AvatarModelGeometry;
+ private _figureData: FigureSetData;
+ private _partSetsData: PartSetsData;
+ private _animationData: AnimationData;
+ private _animationManager: AnimationManager;
+ private _mandatorySetTypeIds: { [index: string]: { [index: number]: string[] } };
+ private _actionManager: AvatarActionManager;
+ private _defaultAction: IActionDefinition;
+
+ constructor(renderManager: AvatarRenderManager)
+ {
+ super();
+
+ this._renderManager = renderManager;
+ this._geometry = null;
+ this._figureData = new FigureSetData();
+ this._partSetsData = new PartSetsData();
+ this._animationData = new AnimationData();
+ this._animationManager = new AnimationManager();
+ this._mandatorySetTypeIds = {};
+ this._actionManager = null;
+ this._defaultAction = null;
+ }
+
+ public init(): void
+ {
+
+ }
+
+ public dispose(): void
+ {
+ if(this.disposed) return;
+
+ super.dispose();
+
+ this._renderManager = null;
+ this._figureData = null;
+ this._partSetsData = null;
+ this._animationData = null;
+ this._mandatorySetTypeIds = null;
+ }
+
+ public _Str_1825(k: any): void
+ {
+ if(!k) return;
+
+ this._geometry = new AvatarModelGeometry(k);
+ }
+
+ public _Str_1060(k: IAssetManager, _arg_2: any): void
+ {
+ if(!_arg_2) return;
+
+ this._actionManager = new AvatarActionManager(k, _arg_2);
+ this._defaultAction = this._actionManager._Str_1027();
+ }
+
+ public _Str_1620(data: any): void
+ {
+ this._actionManager._Str_1620(data);
+
+ this._defaultAction = this._actionManager._Str_1027();
+ }
+
+ public _Str_1296(k: any): boolean
+ {
+ if(!k) return false;
+
+ if(this._partSetsData.parse(k))
+ {
+ this._partSetsData._Str_1102('ri')._Str_1583 = true;
+ this._partSetsData._Str_1102('li')._Str_1583 = true;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public _Str_2229(k: any): boolean
+ {
+ if(!k) return false;
+
+ return this._animationData.parse(k);
+ }
+
+ public _Str_1569(k: any): boolean
+ {
+ if(!k) return false;
+
+ return this._figureData.parse(k);
+ }
+
+ public _Str_882(data: any): void
+ {
+ this._figureData._Str_1133(data);
+ }
+
+ public _Str_1849(k: IAssetManager, _arg_2: string = 'fx', _arg_3: number = 200): void
+ {
+ let index = 0;
+
+ while(index < _arg_3)
+ {
+ const collection = k.getCollection((_arg_2 + index));
+
+ if(collection)
+ {
+ const animationData = collection.data;
+
+ this._animationManager._Str_2061(this, animationData.animations);
+ }
+
+ index++;
+ }
+ }
+
+ public _Str_2061(data: { [index: string]: IAssetAnimation }): void
+ {
+ this._animationManager._Str_2061(this, data);
+ }
+
+ public _Str_867(k: IAvatarFigureContainer, _arg_2: string, _arg_3: number = 0): IPartColor
+ {
+ const _local_4 = k._Str_815(_arg_2);
+
+ if((!(_local_4)) || (_local_4.length < _arg_3)) return null;
+
+ const _local_5 = this._figureData._Str_740(_arg_2);
+
+ if(_local_5 == null) return null;
+
+ const _local_6 = this._figureData._Str_783(_local_5._Str_734);
+
+ if(!_local_6) return null;
+
+ return _local_6._Str_751(_local_4[_arg_3]);
+ }
+
+ public _Str_1881(animation: string, frameCount: number, spriteId: string): AnimationLayerData
+ {
+ return this._animationManager._Str_607(animation, frameCount, spriteId) as AnimationLayerData;
+ }
+
+ public _Str_720(k: string): Animation
+ {
+ return this._animationManager._Str_720(k) as Animation;
+ }
+
+ public _Str_1675(k: string): ActionDefinition
+ {
+ return this._actionManager._Str_1675(k);
+ }
+
+ public _Str_2018(k: string): ActionDefinition
+ {
+ return this._actionManager._Str_2018(k);
+ }
+
+ public _Str_1939(k: string): boolean
+ {
+ return this._geometry._Str_1939(k);
+ }
+
+ public _Str_711(k: IActiveActionData[]): IActiveActionData[]
+ {
+ return this._actionManager._Str_711(k);
+ }
+
+ public _Str_1936(k: IActiveActionData[]): number
+ {
+ let _local_2 = 0;
+
+ for(const _local_3 of k)
+ {
+ _local_2 = Math.max(_local_2, this._animationData._Str_1408(_local_3._Str_742));
+ }
+ return _local_2;
+ }
+
+ public _Str_1733(k: string, _arg_2: number): string[]
+ {
+ if(!this._mandatorySetTypeIds[k])
+ {
+ this._mandatorySetTypeIds[k] = [];
+ }
+
+ if(this._mandatorySetTypeIds[k][_arg_2])
+ {
+ return this._mandatorySetTypeIds[k][_arg_2];
+ }
+
+ this._mandatorySetTypeIds[k][_arg_2] = this._figureData._Str_1733(k, _arg_2);
+
+ return this._mandatorySetTypeIds[k][_arg_2];
+ }
+
+ public _Str_2264(k: string, _arg_2: string): IFigurePartSet
+ {
+ return this._figureData._Str_2264(k, _arg_2);
+ }
+
+ public _Str_781(k: IActiveActionData[], _arg_2: string, _arg_3: number): number[]
+ {
+ return this._actionManager._Str_781(k, _arg_2, _arg_3);
+ }
+
+ public _Str_1664(k: string, _arg_2: string): AvatarCanvas
+ {
+ return this._geometry._Str_1664(k, _arg_2);
+ }
+
+ public _Str_2101(k: IAvatarImage): void
+ {
+ this._geometry._Str_2101(k);
+ }
+
+ public _Str_2021(k: IActiveActionData, _arg_2: IAvatarImage): string[]
+ {
+ let _local_3: string[] = [];
+
+ const _local_4: string[] = [];
+ const _local_5 = k._Str_742._Str_868;
+
+ if(k._Str_742._Str_861)
+ {
+ const _local_7 = ((k._Str_742.state + '.') + k._Str_727);
+ const _local_8 = this._animationManager._Str_720(_local_7);
+
+ if(_local_8)
+ {
+ _local_3 = _local_8._Str_1065(0, k._Str_707);
+
+ if(_local_8._Str_706())
+ {
+ const _local_11 = {
+ id: '',
+ x: 0,
+ y: 0,
+ z: 0,
+ radius: 0.01,
+ nx: 0,
+ ny: 0,
+ nz: -1,
+ double: 1
+ };
+
+ const _local_12 = {
+ setType: ''
+ };
+
+ for(const _local_13 of _local_8._Str_687)
+ {
+ const _local_6 = this._geometry._Str_1919(_local_5, _local_13.align);
+
+ if(_local_6)
+ {
+ _local_11.id = _local_13.id;
+ _local_6._Str_2020(_local_11, _arg_2);
+
+ _local_12.setType = _local_13.id;
+
+ const _local_10 = this._partSetsData._Str_1520(_local_12);
+ _local_10._Str_1583 = true;
+
+ if(_local_13.base === '') _local_10._Str_1734 = 1;
+
+ if(_local_4.indexOf(_local_6.id) === -1) _local_4.push(_local_6.id);
+ }
+ }
+ }
+ }
+
+ for(const _local_9 of _local_3)
+ {
+ const _local_6 = this._geometry._Str_1919(_local_5, _local_9);
+
+ if(_local_6 && (_local_4.indexOf(_local_6.id) === -1)) _local_4.push(_local_6.id);
+ }
+ }
+ else
+ {
+ _local_3 = this._partSetsData._Str_1795(k._Str_742);
+
+ for(const _local_14 of _local_3)
+ {
+ const _local_6 = this._geometry._Str_1701(_local_5, _local_14, _arg_2);
+
+ if(_local_6 && (_local_4.indexOf(_local_6.id) === -1)) _local_4.push(_local_6.id);
+ }
+ }
+
+ return _local_4;
+ }
+
+ public _Str_1695(k: string): string[]
+ {
+ return this._geometry._Str_1307(k);
+ }
+
+ public _Str_755(k: string, _arg_2: string, _arg_3: number): string[]
+ {
+ const _local_4 = AvatarDirectionAngle.DIRECTION_TO_ANGLE[_arg_3];
+
+ return this._geometry._Str_2250(k, _local_4, _arg_2);
+ }
+
+ public _Str_1888(k:IActiveActionData, _arg_2: number, _arg_3: number, _arg_4: string): Point
+ {
+ const _local_5 = this._animationData._Str_2244(k._Str_742);
+
+ if(_local_5) return _local_5._Str_1888(_arg_2, _arg_3, _arg_4);
+
+ return AnimationAction._Str_1934;
+ }
+
+ public _Str_713(k: string, _arg_2:IAvatarFigureContainer, _arg_3:IActiveActionData, _arg_4: string, _arg_5: number, removes: string[], _arg_7: IAvatarImage, _arg_8: Map = null): AvatarImagePartContainer[]
+ {
+ const _local_10: Animation = null;
+ let _local_34: IActionDefinition = null;
+
+ let _local_20: AnimationFrame[] = [];
+ let _local_36:IPartColor = null;
+
+ if(!_arg_3 == null) return [];
+
+ const _local_9 = this._partSetsData._Str_1795(_arg_3._Str_742);
+ const _local_11: AvatarImagePartContainer[] = [];
+ let _local_14: any[] = [ 0 ];
+ const _local_15 = this._animationData._Str_2244(_arg_3._Str_742);
+
+ if(_arg_3._Str_742._Str_861)
+ {
+ const _local_24 = ((_arg_3._Str_742.state + '.') + _arg_3._Str_727);
+ const _local_10 = this._animationManager._Str_720(_local_24);
+
+ if(_local_10)
+ {
+ _local_14 = this._Str_1768(_local_10._Str_2185(_arg_3._Str_707));
+
+ for(const _local_25 of _local_10._Str_1065(0, _arg_3._Str_707))
+ {
+ if(_local_25 === k)
+ {
+ const _local_26 = this._geometry._Str_1919(_arg_4, _local_25);
+
+ if(_local_26)
+ {
+ for(const _local_27 of _local_26._Str_1883(_arg_7))
+ {
+ _local_9.push(_local_27.id);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ const _local_16 = this._geometry._Str_713(_arg_4, k, _arg_5, _local_9, _arg_7);
+ const _local_21 = _arg_2._Str_1016();
+
+ for(const _local_17 of _local_21)
+ {
+ if(_arg_8)
+ {
+ if(_arg_8.get(_local_17)) continue;
+ }
+
+ const _local_28 = _arg_2.getPartSetId(_local_17);
+ const _local_29 = _arg_2._Str_815(_local_17);
+ const _local_30 = this._figureData._Str_740(_local_17);
+
+
+
+ if(_local_30)
+ {
+ const _local_31 = this._figureData._Str_783(_local_30._Str_734);
+
+ if(_local_31)
+ {
+ const _local_32 = _local_30._Str_1020(_local_28);
+
+ if(_local_32)
+ {
+ removes = removes.concat(_local_32._Str_790);
+
+ for(const _local_33 of _local_32._Str_806)
+ {
+ if(_local_16.indexOf(_local_33.type) > -1)
+ {
+ if(_local_15)
+ {
+ const _local_19 = _local_15._Str_989(_local_33.type);
+
+ if(_local_19)
+ {
+ _local_20 = _local_19.frames;
+ }
+ else
+ {
+ _local_20 = _local_14;
+ }
+ }
+ else
+ {
+ _local_20 = _local_14;
+ }
+
+ _local_34 = _arg_3._Str_742;
+
+ if(_local_9.indexOf(_local_33.type) === -1) _local_34 = this._defaultAction;
+
+ const _local_13 = this._partSetsData._Str_1102(_local_33.type);
+
+ let _local_35 = (!_local_13) ? _local_33.type : _local_13._Str_1693;
+
+ if(!_local_35 || (_local_35 === '')) _local_35 = _local_33.type;
+
+ if(_local_29 && (_local_29.length > (_local_33._Str_827 - 1)))
+ {
+ _local_36 = _local_31._Str_751(_local_29[(_local_33._Str_827 - 1)]);
+ }
+
+ const _local_37 = (_local_33._Str_827 > 0);
+ const _local_18 = new AvatarImagePartContainer(k, _local_33.type, _local_33.id.toString(), _local_36, _local_20, _local_34, _local_37, _local_33.paletteMap, _local_35);
+
+ _local_11.push(_local_18);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ const _local_22: AvatarImagePartContainer[] = [];
+
+ for(const _local_12 of _local_16)
+ {
+ let _local_39: IPartColor = null;
+ let _local_38 = false;
+
+ const _local_40 = ((_arg_8) && (_arg_8.get(_local_12)));
+
+ for(const _local_23 of _local_11)
+ {
+ if(_local_23._Str_1669 === _local_12)
+ {
+ if(_local_40)
+ {
+ _local_39 = _local_23.color;
+ }
+ else
+ {
+ _local_38 = true;
+
+ if(removes.indexOf(_local_12) === -1) _local_22.push(_local_23);
+ }
+ }
+ }
+
+ if(!_local_38)
+ {
+ if(_local_40)
+ {
+ const _local_41 = _arg_8.get(_local_12);
+
+ let _local_42 = 0;
+ let _local_43 = 0;
+
+ while(_local_43 < _local_41.length)
+ {
+ _local_42 = (_local_42 + _local_41.charCodeAt(_local_43));
+ _local_43++;
+ }
+
+ if(_local_15)
+ {
+ const _local_19 = _local_15._Str_989(_local_12);
+
+ if(_local_19)
+ {
+ _local_20 = _local_19.frames;
+ }
+ else
+ {
+ _local_20 = _local_14;
+ }
+ }
+ else
+ {
+ _local_20 = _local_14;
+ }
+
+ const _local_18 = new AvatarImagePartContainer(k, _local_12, _local_41, _local_39, _local_20, _arg_3._Str_742, (!(_local_39 == null)), -1, _local_12, false, 1);
+
+ _local_22.push(_local_18);
+ }
+ else
+ {
+ if(_local_9.indexOf(_local_12) > -1)
+ {
+ const _local_44 = this._geometry._Str_1701(_arg_4, _local_12, _arg_7);
+
+ if(k !== _local_44.id)
+ {
+ //
+ }
+ else
+ {
+ const _local_13 = this._partSetsData._Str_1102(_local_12);
+
+ let _local_45 = false;
+ let _local_46 = 1;
+
+ if(_local_13._Str_1583)
+ {
+ let _local_47 = '1';
+
+ if(_arg_3._Str_727 !== '')
+ {
+ _local_47 = _arg_3._Str_727;
+ }
+
+ if(_local_13._Str_2234())
+ {
+ _local_47 = _local_13._Str_1734.toString();
+ }
+
+ if(_local_10 != null)
+ {
+ const _local_48 = _local_10._Str_1550(_local_12);
+
+ if(_local_48)
+ {
+ _local_45 = _local_48._Str_1096;
+ _local_46 = _local_48.blend;
+ }
+ }
+
+ if(_local_15)
+ {
+ const _local_19 = _local_15._Str_989(_local_12);
+
+ if(_local_19)
+ {
+ _local_20 = _local_19.frames;
+ }
+ else
+ {
+ _local_20 = _local_14;
+ }
+ }
+ else
+ {
+ _local_20 = _local_14;
+ }
+
+ const _local_18 = new AvatarImagePartContainer(k, _local_12, _local_47, null, _local_20, _arg_3._Str_742, false, -1, _local_12, _local_45, _local_46);
+
+ _local_22.push(_local_18);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return _local_22;
+ }
+
+ private _Str_1768(k: number): number[]
+ {
+ const _local_2: number[] = [];
+
+ let index = 0;
+
+ while(index < k)
+ {
+ _local_2.push(index);
+
+ index++;
+ }
+
+ return _local_2;
+ }
+
+ public _Str_672(): string[]
+ {
+ if(this._actionManager)
+ {
+ const k = this._actionManager._Str_1675('CarryItem').params;
+
+ const _local_2 = [];
+
+ for(const _local_3 of k.values()) _local_2.push(_local_3);
+
+ return _local_2;
+ }
+
+ return [];
+ }
+
+ public get renderManager(): IAvatarRenderManager
+ {
+ return this._renderManager;
+ }
+
+ public get figureData(): IStructureData
+ {
+ return this._figureData;
+ }
+
+ public get partData(): PartSetsData
+ {
+ return this._partSetsData;
+ }
+
+ public get animationManager(): AnimationManager
+ {
+ return this._animationManager;
+ }
+}
diff --git a/src/nitro/avatar/EffectAssetDownloadLibrary.ts b/src/nitro/avatar/EffectAssetDownloadLibrary.ts
new file mode 100644
index 00000000..7899805d
--- /dev/null
+++ b/src/nitro/avatar/EffectAssetDownloadLibrary.ts
@@ -0,0 +1,86 @@
+import { IAssetManager } from '../../core/asset/IAssetManager';
+import { IAssetAnimation } from '../../core/asset/interfaces';
+import { EventDispatcher } from '../../core/events/EventDispatcher';
+import { AvatarRenderEffectLibraryEvent } from './events/AvatarRenderEffectLibraryEvent';
+
+export class EffectAssetDownloadLibrary extends EventDispatcher
+{
+ public static DOWNLOAD_COMPLETE: string = 'EADL_DOWNLOAD_COMPLETE';
+
+ private static NOT_LOADED: number = 0;
+ private static LOADING: number = 1;
+ private static LOADED: number = 2;
+
+ private _state: number;
+ private _libraryName: string;
+ private _revision: string;
+ private _downloadUrl: string;
+ private _assets: IAssetManager;
+ private _animation: { [index: string]: IAssetAnimation };
+
+ constructor(id: string, revision: string, assets: IAssetManager, assetUrl: string)
+ {
+ super();
+
+ this._state = EffectAssetDownloadLibrary.NOT_LOADED;
+ this._libraryName = id;
+ this._revision = revision;
+ this._downloadUrl = assetUrl;
+ this._assets = assets;
+ this._animation = null;
+
+ this._downloadUrl = this._downloadUrl.replace(/%libname%/gi, this._libraryName);
+ this._downloadUrl = this._downloadUrl.replace(/%revision%/gi, this._revision);
+
+ const asset = this._assets.getCollection(this._libraryName);
+
+ if(asset) this._state = EffectAssetDownloadLibrary.LOADED;
+ }
+
+ public downloadAsset(): void
+ {
+ if(!this._assets || (this._state === EffectAssetDownloadLibrary.LOADING) || (this._state === EffectAssetDownloadLibrary.LOADED)) return;
+
+ const asset = this._assets.getCollection(this._libraryName);
+
+ if(asset)
+ {
+ this._state = EffectAssetDownloadLibrary.LOADED;
+
+ this.dispatchEvent(new AvatarRenderEffectLibraryEvent(AvatarRenderEffectLibraryEvent.DOWNLOAD_COMPLETE, this));
+
+ return;
+ }
+
+ this._state = EffectAssetDownloadLibrary.LOADING;
+
+ this._assets.downloadAsset(this._downloadUrl, (flag: boolean) =>
+ {
+ if(flag)
+ {
+ this._state = EffectAssetDownloadLibrary.LOADED;
+
+ const collection = this._assets.getCollection(this._libraryName);
+
+ if(collection) this._animation = collection.data.animations;
+
+ this.dispatchEvent(new AvatarRenderEffectLibraryEvent(AvatarRenderEffectLibraryEvent.DOWNLOAD_COMPLETE, this));
+ }
+ });
+ }
+
+ public get libraryName(): string
+ {
+ return this._libraryName;
+ }
+
+ public get animation(): { [index: string]: IAssetAnimation }
+ {
+ return this._animation;
+ }
+
+ public get isLoaded(): boolean
+ {
+ return (this._state === EffectAssetDownloadLibrary.LOADED);
+ }
+}
diff --git a/src/nitro/avatar/EffectAssetDownloadManager.ts b/src/nitro/avatar/EffectAssetDownloadManager.ts
new file mode 100644
index 00000000..c34c03fd
--- /dev/null
+++ b/src/nitro/avatar/EffectAssetDownloadManager.ts
@@ -0,0 +1,302 @@
+import { IAssetManager } from '../../core/asset/IAssetManager';
+import { NitroLogger } from '../../core/common/logger/NitroLogger';
+import { EventDispatcher } from '../../core/events/EventDispatcher';
+import { NitroEvent } from '../../core/events/NitroEvent';
+import { Nitro } from '../Nitro';
+import { AvatarStructure } from './AvatarStructure';
+import { EffectAssetDownloadLibrary } from './EffectAssetDownloadLibrary';
+import { AvatarRenderEffectLibraryEvent } from './events/AvatarRenderEffectLibraryEvent';
+import { AvatarRenderEvent } from './events/AvatarRenderEvent';
+import { IAvatarEffectListener } from './IAvatarEffectListener';
+
+export class EffectAssetDownloadManager extends EventDispatcher
+{
+ public static DOWNLOADER_READY: string = 'EADM_DOWNLOADER_READY';
+ public static LIBRARY_LOADED: string = 'EADM_LIBRARY_LOADED';
+
+ private static MAX_DOWNLOADS: number = 2;
+
+ private _assets: IAssetManager;
+ private _structure: AvatarStructure;
+
+ private _missingMandatoryLibs: string[];
+ private _effectMap: Map;
+ private _initDownloadBuffer: [ number, IAvatarEffectListener][];
+ private _effectListeners: Map;
+ private _incompleteEffects: Map;
+ private _pendingDownloadQueue: EffectAssetDownloadLibrary[];
+ private _currentDownloads: EffectAssetDownloadLibrary[];
+ private _libraryNames: string[];
+ private _isReady: boolean;
+
+ constructor(assets: IAssetManager, structure: AvatarStructure)
+ {
+ super();
+
+ this._assets = assets;
+ this._structure = structure;
+
+ this._missingMandatoryLibs = Nitro.instance.getConfiguration('avatar.mandatory.effect.libraries');
+ this._effectMap = new Map();
+ this._effectListeners = new Map();
+ this._incompleteEffects = new Map();
+ this._initDownloadBuffer = [];
+ this._pendingDownloadQueue = [];
+ this._currentDownloads = [];
+ this._libraryNames = [];
+ this._isReady = false;
+
+ this.onLibraryLoaded = this.onLibraryLoaded.bind(this);
+ this.onAvatarRenderReady = this.onAvatarRenderReady.bind(this);
+
+ this.loadEffectMap();
+
+ this._structure.renderManager.events.addEventListener(AvatarRenderEvent.AVATAR_RENDER_READY, this.onAvatarRenderReady);
+ }
+
+ private loadEffectMap(): void
+ {
+ const request = new XMLHttpRequest();
+
+ try
+ {
+ request.open('GET', Nitro.instance.getConfiguration('avatar.effectmap.url'));
+
+ request.send();
+
+ request.onloadend = e =>
+ {
+ if(request.responseText)
+ {
+ const data = JSON.parse(request.responseText);
+
+ this.processEffectMap(data.effects);
+
+ this.processMissingLibraries();
+
+ this._isReady = true;
+
+ this.dispatchEvent(new NitroEvent(EffectAssetDownloadManager.DOWNLOADER_READY));
+ }
+ };
+
+ request.onerror = e =>
+ {
+ throw new Error('invalid_avatar_effect_map');
+ };
+ }
+
+ catch (e)
+ {
+ NitroLogger.log(e);
+ }
+ }
+
+ private processEffectMap(data: any): void
+ {
+ if(!data) return;
+
+ for(const effect of data)
+ {
+ if(!effect) continue;
+
+ const id = (effect.id as string);
+ const lib = (effect.lib as string);
+ const revision = (effect.revision || '');
+
+ if(this._libraryNames.indexOf(lib) >= 0) continue;
+
+ this._libraryNames.push(lib);
+
+ const downloadLibrary = new EffectAssetDownloadLibrary(lib, revision, this._assets, Nitro.instance.getConfiguration('avatar.asset.effect.url'));
+
+ downloadLibrary.addEventListener(AvatarRenderEffectLibraryEvent.DOWNLOAD_COMPLETE, this.onLibraryLoaded);
+
+ let existing = this._effectMap.get(id);
+
+ if(!existing) existing = [];
+
+ existing.push(downloadLibrary);
+
+ this._effectMap.set(id, existing);
+ }
+ }
+
+ public downloadAvatarEffect(id: number, listener: IAvatarEffectListener): void
+ {
+ if(!this._isReady || !this._structure.renderManager.isReady)
+ {
+ this._initDownloadBuffer.push([ id, listener ]);
+
+ return;
+ }
+
+ const pendingLibraries = this.getAvatarEffectPendingLibraries(id);
+
+ if(pendingLibraries && pendingLibraries.length)
+ {
+ if(listener && !listener.disposed)
+ {
+ let listeners = this._effectListeners.get(id.toString());
+
+ if(!listeners) listeners = [];
+
+ listeners.push(listener);
+
+ this._effectListeners.set(id.toString(), listeners);
+ }
+
+ this._incompleteEffects.set(id.toString(), pendingLibraries);
+
+ for(const library of pendingLibraries)
+ {
+ if(!library) continue;
+
+ this.downloadLibrary(library);
+ }
+ }
+ else
+ {
+ if(listener && !listener.disposed) listener.resetEffect(id);
+ }
+ }
+
+ private onAvatarRenderReady(event: NitroEvent): void
+ {
+ if(!event) return;
+
+ for(const [ id, listener ] of this._initDownloadBuffer)
+ {
+ this.downloadAvatarEffect(id, listener);
+ }
+
+ this._initDownloadBuffer = [];
+ }
+
+ private onLibraryLoaded(event: AvatarRenderEffectLibraryEvent): void
+ {
+ if(!event || !event.library) return;
+
+ const loadedEffects: string[] = [];
+
+ this._structure._Str_2061(event.library.animation);
+
+ for(const [ id, libraries ] of this._incompleteEffects.entries())
+ {
+ let isReady = true;
+
+ for(const library of libraries)
+ {
+ if(!library || library.isLoaded) continue;
+
+ isReady = false;
+
+ break;
+ }
+
+ if(isReady)
+ {
+ loadedEffects.push(id);
+
+ const listeners = this._effectListeners.get(id);
+
+ for(const listener of listeners)
+ {
+ if(!listener || listener.disposed) continue;
+
+ listener.resetEffect(parseInt(id));
+ }
+
+ this._effectListeners.delete(id);
+
+ this.dispatchEvent(new NitroEvent(EffectAssetDownloadManager.LIBRARY_LOADED));
+ }
+ }
+
+ for(const id of loadedEffects) this._incompleteEffects.delete(id);
+
+ let index = 0;
+
+ while(index < this._currentDownloads.length)
+ {
+ const download = this._currentDownloads[index];
+
+ if(download)
+ {
+ if(download.libraryName === event.library.libraryName) this._currentDownloads.splice(index, 1);
+ }
+
+ index++;
+ }
+ }
+
+ public processMissingLibraries(): void
+ {
+ const libraries = this._missingMandatoryLibs.slice();
+
+ for(const library of libraries)
+ {
+ if(!library) continue;
+
+ const map = this._effectMap.get(library);
+
+ if(map) for(const effect of map) effect && this.downloadLibrary(effect);
+ }
+ }
+
+ public isAvatarEffectReady(effect: number): boolean
+ {
+ if(!this._isReady || !this._structure.renderManager.isReady)
+ {
+ return false;
+ }
+
+ const pendingLibraries = this.getAvatarEffectPendingLibraries(effect);
+
+ return !pendingLibraries.length;
+ }
+
+ private getAvatarEffectPendingLibraries(id: number): EffectAssetDownloadLibrary[]
+ {
+ const pendingLibraries: EffectAssetDownloadLibrary[] = [];
+
+ if(!this._structure) return pendingLibraries;
+
+ const libraries = this._effectMap.get(id.toString());
+
+ if(libraries)
+ {
+ for(const library of libraries)
+ {
+ if(!library || library.isLoaded) continue;
+
+ if(pendingLibraries.indexOf(library) === -1) pendingLibraries.push(library);
+ }
+ }
+
+ return pendingLibraries;
+ }
+
+ private downloadLibrary(library: EffectAssetDownloadLibrary): void
+ {
+ if(!library || library.isLoaded) return;
+
+ if((this._pendingDownloadQueue.indexOf(library) >= 0) || (this._currentDownloads.indexOf(library) >= 0)) return;
+
+ this._pendingDownloadQueue.push(library);
+
+ this.processDownloadQueue();
+ }
+
+ private processDownloadQueue(): void
+ {
+ while(this._pendingDownloadQueue.length)
+ {
+ const library = this._pendingDownloadQueue[0];
+
+ library.downloadAsset();
+
+ this._currentDownloads.push(this._pendingDownloadQueue.shift());
+ }
+ }
+}
diff --git a/src/nitro/avatar/IAvatarEffectListener.ts b/src/nitro/avatar/IAvatarEffectListener.ts
new file mode 100644
index 00000000..c0fd5cf3
--- /dev/null
+++ b/src/nitro/avatar/IAvatarEffectListener.ts
@@ -0,0 +1,6 @@
+import { IDisposable } from '../../core/common/disposable/IDisposable';
+
+export interface IAvatarEffectListener extends IDisposable
+{
+ resetEffect(effect: number): void;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/IAvatarFigureContainer.ts b/src/nitro/avatar/IAvatarFigureContainer.ts
new file mode 100644
index 00000000..4a9cbbb3
--- /dev/null
+++ b/src/nitro/avatar/IAvatarFigureContainer.ts
@@ -0,0 +1,10 @@
+export interface IAvatarFigureContainer
+{
+ _Str_1016(): IterableIterator;
+ _Str_744(_arg_1: string): boolean;
+ getPartSetId(_arg_1: string): number;
+ _Str_815(_arg_1: string): number[];
+ _Str_830(_arg_1: string, _arg_2: number, _arg_3: number[]): void;
+ _Str_923(_arg_1: string): void;
+ _Str_1008(): string;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/IAvatarImage.ts b/src/nitro/avatar/IAvatarImage.ts
new file mode 100644
index 00000000..b88bade6
--- /dev/null
+++ b/src/nitro/avatar/IAvatarImage.ts
@@ -0,0 +1,37 @@
+import { RenderTexture, Sprite } from 'pixi.js';
+import { IDisposable } from '../../core/common/disposable/IDisposable';
+import { IGraphicAsset } from '../../room/object/visualization/utils/IGraphicAsset';
+import { IAnimationLayerData } from './animation/IAnimationLayerData';
+import { IAvatarDataContainer } from './animation/IAvatarDataContainer';
+import { ISpriteDataContainer } from './animation/ISpriteDataContainer';
+import { IAvatarFigureContainer } from './IAvatarFigureContainer';
+import { IPartColor } from './structure/figure/IPartColor';
+
+export interface IAvatarImage extends IDisposable
+{
+ getServerRenderData(): any;
+ setDirection(_arg_1: string, _arg_2: number): void;
+ setDirectionAngle(_arg_1: string, _arg_2: number): void;
+ updateAnimationByFrames(_arg_1?: number): void;
+ getScale(): string;
+ getSprites(): ISpriteDataContainer[];
+ getLayerData(_arg_1: ISpriteDataContainer): IAnimationLayerData;
+ getImage(setType: string, hightlight: boolean, scale?: number, cache?: boolean): RenderTexture;
+ getImageAsSprite(setType: string, scale?: number): Sprite;
+ getCroppedImage(setType: string, scale?: number): HTMLImageElement;
+ getAsset(_arg_1: string): IGraphicAsset;
+ getDirection(): number;
+ getFigure(): IAvatarFigureContainer;
+ getPartColor(_arg_1: string): IPartColor;
+ isAnimating(): boolean;
+ getCanvasOffsets(): number[];
+ initActionAppends(): void;
+ endActionAppends(): void;
+ appendAction(_arg_1: string, ..._args: any[]): boolean;
+ avatarSpriteData: IAvatarDataContainer;
+ isPlaceholder(): boolean;
+ forceActionUpdate(): void;
+ animationHasResetOnToggle: boolean;
+ resetAnimationFrameCounter(): void;
+ mainAction: string;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/IAvatarImageListener.ts b/src/nitro/avatar/IAvatarImageListener.ts
new file mode 100644
index 00000000..9a0b0ddf
--- /dev/null
+++ b/src/nitro/avatar/IAvatarImageListener.ts
@@ -0,0 +1,6 @@
+import { IDisposable } from '../../core/common/disposable/IDisposable';
+
+export interface IAvatarImageListener extends IDisposable
+{
+ resetFigure(figure: string): void;
+}
diff --git a/src/nitro/avatar/IAvatarRenderManager.ts b/src/nitro/avatar/IAvatarRenderManager.ts
new file mode 100644
index 00000000..ac3f3fed
--- /dev/null
+++ b/src/nitro/avatar/IAvatarRenderManager.ts
@@ -0,0 +1,28 @@
+import { IAssetManager } from '../../core/asset/IAssetManager';
+import { INitroManager } from '../../core/common/INitroManager';
+import { IGraphicAsset } from '../../room/object/visualization/utils/IGraphicAsset';
+import { AvatarAssetDownloadManager } from './AvatarAssetDownloadManager';
+import { AvatarStructure } from './AvatarStructure';
+import { IAvatarEffectListener } from './IAvatarEffectListener';
+import { IAvatarFigureContainer } from './IAvatarFigureContainer';
+import { IAvatarImage } from './IAvatarImage';
+import { IAvatarImageListener } from './IAvatarImageListener';
+import { IStructureData } from './structure/IStructureData';
+
+export interface IAvatarRenderManager extends INitroManager
+{
+ createFigureContainer(figure: string): IAvatarFigureContainer;
+ isFigureContainerReady(container: IAvatarFigureContainer): boolean;
+ createAvatarImage(figure: string, size: string, gender: string, listener?: IAvatarImageListener, effectListener?: IAvatarEffectListener): IAvatarImage;
+ downloadAvatarFigure(container: IAvatarFigureContainer, listener: IAvatarImageListener): void;
+ getFigureClubLevel(container: IAvatarFigureContainer, gender: string, searchParts: string[]): number;
+ isValidFigureSetForGender(setId: number, gender: string): boolean;
+ getFigureStringWithFigureIds(k: string, _arg_2: string, _arg_3: number[]): string;
+ _Str_838(k: string, _arg_2: number): string[];
+ getAssetByName(name: string): IGraphicAsset;
+ assets: IAssetManager;
+ isReady: boolean;
+ structure: AvatarStructure;
+ structureData: IStructureData;
+ downloadManager: AvatarAssetDownloadManager;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/IOutfit.ts b/src/nitro/avatar/IOutfit.ts
new file mode 100644
index 00000000..e797d6ff
--- /dev/null
+++ b/src/nitro/avatar/IOutfit.ts
@@ -0,0 +1,5 @@
+export interface IOutfit
+{
+ figure: string;
+ gender: string;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/PlaceHolderAvatarImage.ts b/src/nitro/avatar/PlaceHolderAvatarImage.ts
new file mode 100644
index 00000000..15847812
--- /dev/null
+++ b/src/nitro/avatar/PlaceHolderAvatarImage.ts
@@ -0,0 +1,18 @@
+import { AssetAliasCollection } from './alias/AssetAliasCollection';
+import { AvatarFigureContainer } from './AvatarFigureContainer';
+import { AvatarImage } from './AvatarImage';
+import { AvatarStructure } from './AvatarStructure';
+import { EffectAssetDownloadManager } from './EffectAssetDownloadManager';
+
+export class PlaceHolderAvatarImage extends AvatarImage
+{
+ constructor(k: AvatarStructure, _arg_2: AssetAliasCollection, _arg_3: AvatarFigureContainer, _arg_4: string, _arg_5: EffectAssetDownloadManager)
+ {
+ super(k, _arg_2, _arg_3, _arg_4, _arg_5, null);
+ }
+
+ public isPlaceholder(): boolean
+ {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/actions/ActionDefinition.ts b/src/nitro/avatar/actions/ActionDefinition.ts
new file mode 100644
index 00000000..df5b4b52
--- /dev/null
+++ b/src/nitro/avatar/actions/ActionDefinition.ts
@@ -0,0 +1,224 @@
+import { ActionType } from './ActionType';
+import { IActionDefinition } from './IActionDefinition';
+
+export class ActionDefinition implements IActionDefinition
+{
+ private _id: string;
+ private _state: string;
+ private _precedence: number;
+ private _activePartSet: string;
+ private _assetPartDefinition: string;
+ private _lay: string;
+ private _geometryType: string;
+ private _isMain: boolean;
+ private _isDefault: boolean;
+ private _isAnimation: boolean;
+ private _startFromFrameZero: boolean;
+ private _prevents: string[];
+ private _preventHeadTurn: boolean;
+ private _types: Map;
+ private _params: Map;
+ private _defaultParameterValue: string;
+ private _canvasOffsets: Map>;
+
+ constructor(data: any)
+ {
+ this._id = data.id;
+ this._state = data.state;
+ this._precedence = data.precedence;
+ this._activePartSet = data.activePartSet;
+ this._assetPartDefinition = data.assetPartDefinition;
+ this._lay = data.lay;
+ this._geometryType = data.geometryType;
+ this._isMain = data.main || false;
+ this._isDefault = data.isDefault || false;
+ this._isAnimation = data.animation || false;
+ this._startFromFrameZero = data.startFromFrameZero || false;
+ this._prevents = data.prevents || [];
+ this._preventHeadTurn = data.preventHeadTurn || false;
+ this._types = new Map();
+ this._params = new Map();
+ this._defaultParameterValue = '';
+ this._canvasOffsets = null;
+
+ if(data.params && (data.params.length > 0))
+ {
+ for(const param of data.params)
+ {
+ if(!param) continue;
+
+ if(param.id === 'default') this._defaultParameterValue = param.value;
+ else this._params.set(param.id, param.value);
+ }
+ }
+
+ if(data.types && (data.types.length > 0))
+ {
+ for(const type of data.types)
+ {
+ if(!type) continue;
+
+ const action = new ActionType(type);
+
+ this._types.set(action.id, action);
+ }
+ }
+ }
+
+ public _Str_772(k: string, _arg_2: number, _arg_3: number[]): void
+ {
+ if(!this._canvasOffsets) this._canvasOffsets = new Map();
+
+ let existing = this._canvasOffsets.get(k);
+
+ if(!existing)
+ {
+ existing = new Map();
+
+ this._canvasOffsets.set(k, existing);
+ }
+
+ existing.set(_arg_2, _arg_3);
+ }
+
+ public _Str_805(k: string, _arg_2: number): number[]
+ {
+ if(!this._canvasOffsets) return null;
+
+ const existing = this._canvasOffsets.get(k);
+
+ if(!existing) return null;
+
+ return existing.get(_arg_2);
+ }
+
+ public getType(id: string): ActionType
+ {
+ if(!id) return null;
+
+ const existing = this._types.get(parseInt(id));
+
+ if(!existing) return null;
+
+ return existing;
+ }
+
+ public _Str_1350(id: string): string
+ {
+ if(!id) return '';
+
+ const existing = this._params.get(id);
+
+ if(!existing) return this._defaultParameterValue;
+
+ return existing;
+ }
+
+ public _Str_733(type: string): string[]
+ {
+ return this._prevents.concat(this._Str_1889(type));
+ }
+
+ private _Str_1889(type: string): string[]
+ {
+ if(!type) return [];
+
+ const existing = this._types.get(parseInt(type));
+
+ if(!existing) return [];
+
+ return existing.prevents;
+ }
+
+ public _Str_715(k: string): boolean
+ {
+ if(!k) return this._preventHeadTurn;
+
+ const type = this.getType(k);
+
+ if(!type) return this._preventHeadTurn;
+
+ return type._Str_1891;
+ }
+
+ public _Str_801(k: string): boolean
+ {
+ if(!k) return true;
+
+ const type = this.getType(k);
+
+ if(!type) return true;
+
+ return type._Str_801;
+ }
+
+ public get id(): string
+ {
+ return this._id;
+ }
+
+ public get state(): string
+ {
+ return this._state;
+ }
+
+ public get precedence(): number
+ {
+ return this._precedence;
+ }
+
+ public get activePartSet(): string
+ {
+ return this._activePartSet;
+ }
+
+ public get _Str_778(): string
+ {
+ return this._assetPartDefinition;
+ }
+
+ public get lay(): string
+ {
+ return this._lay;
+ }
+
+ public get _Str_868(): string
+ {
+ return this._geometryType;
+ }
+
+ public get _Str_779(): boolean
+ {
+ return this._isMain;
+ }
+
+ public get _Str_804(): boolean
+ {
+ return this._isDefault;
+ }
+
+ public get _Str_861(): boolean
+ {
+ return this._isAnimation;
+ }
+
+ public get _Str_812(): boolean
+ {
+ return this._startFromFrameZero;
+ }
+
+ public get prevents(): string[]
+ {
+ return this._prevents;
+ }
+
+ public get preventHeadTurn(): boolean
+ {
+ return this._preventHeadTurn;
+ }
+
+ public get params(): Map
+ {
+ return this._params;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/actions/ActionType.ts b/src/nitro/avatar/actions/ActionType.ts
new file mode 100644
index 00000000..5694bb1f
--- /dev/null
+++ b/src/nitro/avatar/actions/ActionType.ts
@@ -0,0 +1,44 @@
+export class ActionType
+{
+ private _id: number;
+ private _value: number;
+ private _prevents: string[];
+ private _preventHeadTurn: boolean;
+ private _isAnimated: boolean;
+
+ constructor(data: any)
+ {
+ this._id = parseInt(data.id);
+ this._value = parseInt(data.id);
+ this._prevents = data.prevents || [];
+ this._preventHeadTurn = data.preventHeadTurn || false;
+ this._isAnimated = true;
+
+ if((data.animated !== undefined) && (data.animated === false)) this._isAnimated = false;
+ }
+
+ public get id(): number
+ {
+ return this._id;
+ }
+
+ public get value(): number
+ {
+ return this._value;
+ }
+
+ public get prevents(): string[]
+ {
+ return this._prevents;
+ }
+
+ public get _Str_1891(): boolean
+ {
+ return this._preventHeadTurn;
+ }
+
+ public get _Str_801(): boolean
+ {
+ return this._isAnimated;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/actions/ActiveActionData.ts b/src/nitro/avatar/actions/ActiveActionData.ts
new file mode 100644
index 00000000..7e2ce117
--- /dev/null
+++ b/src/nitro/avatar/actions/ActiveActionData.ts
@@ -0,0 +1,74 @@
+import { IActionDefinition } from './IActionDefinition';
+import { IActiveActionData } from './IActiveActionData';
+
+export class ActiveActionData implements IActiveActionData
+{
+ private _actionType: string;
+ private _actionParameter: string;
+ private _definition: IActionDefinition;
+ private _startFrame: number;
+ private _overridingAction: string;
+
+ constructor(action: string, parameter: string = '', startFrame: number = 0)
+ {
+ this._actionType = action || '';
+ this._actionParameter = parameter || '';
+ this._definition = null;
+ this._startFrame = startFrame || 0;
+ this._overridingAction = null;
+ }
+
+ public dispose(): void
+ {
+ this._actionType = null;
+ this._actionParameter = null;
+ this._definition = null;
+ }
+
+ public get id(): string
+ {
+ if(!this._definition) return '';
+
+ return this._definition.id + '_' + this._actionParameter;
+ }
+
+ public get _Str_695(): string
+ {
+ return this._actionType;
+ }
+
+ public get _Str_727(): string
+ {
+ return this._actionParameter;
+ }
+
+ public set _Str_727(parameter: string)
+ {
+ this._actionParameter = parameter;
+ }
+
+ public get _Str_742(): IActionDefinition
+ {
+ return this._definition;
+ }
+
+ public set _Str_742(definition: IActionDefinition)
+ {
+ this._definition = definition;
+ }
+
+ public get _Str_664(): number
+ {
+ return this._startFrame;
+ }
+
+ public get _Str_707(): string
+ {
+ return this._overridingAction;
+ }
+
+ public set _Str_707(action: string)
+ {
+ this._overridingAction = action;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/actions/AvatarActionManager.ts b/src/nitro/avatar/actions/AvatarActionManager.ts
new file mode 100644
index 00000000..6f56586c
--- /dev/null
+++ b/src/nitro/avatar/actions/AvatarActionManager.ts
@@ -0,0 +1,187 @@
+import { IAssetManager } from '../../../core/asset/IAssetManager';
+import { ActionDefinition } from './ActionDefinition';
+import { IActiveActionData } from './IActiveActionData';
+
+export class AvatarActionManager
+{
+ private _assets: IAssetManager;
+ private _actions: Map;
+ private _defaultAction: ActionDefinition;
+
+ constructor(k: IAssetManager, data: any)
+ {
+ this._assets = k;
+ this._actions = new Map();
+ this._defaultAction = null;
+
+ this._Str_1620(data);
+ }
+
+ public _Str_1620(data: any): void
+ {
+ if(!data) return;
+
+ for(const action of data.actions)
+ {
+ if(!action || !action.state) continue;
+
+ const definition = new ActionDefinition(action);
+
+ this._actions.set(definition.state, definition);
+ }
+
+ if(data.actionOffsets) this._Str_1767(data.actionOffsets);
+ }
+
+ private _Str_1767(offsets: any): void
+ {
+ if(!offsets || !offsets.length) return;
+
+ for(const offset of offsets)
+ {
+ const action = this._actions.get(offset.action);
+
+ if(!action) continue;
+
+ for(const canvasOffset of offset.offsets)
+ {
+ const size = (canvasOffset.size || '');
+ const direction = canvasOffset.direction;
+
+ if((size === '') || (direction === undefined)) continue;
+
+ const x = (canvasOffset.x || 0);
+ const y = (canvasOffset.y || 0);
+ const z = (canvasOffset.z || 0);
+
+ action._Str_772(size, direction, [ x, y, z ]);
+ }
+ }
+ }
+
+ public _Str_1675(id: string): ActionDefinition
+ {
+ if(!id) return null;
+
+ for(const action of this._actions.values())
+ {
+ if(!action || (action.id !== id)) continue;
+
+ return action;
+ }
+
+ return null;
+ }
+
+ public _Str_2018(state: string): ActionDefinition
+ {
+ const existing = this._actions.get(state);
+
+ if(!existing) return null;
+
+ return existing;
+ }
+
+ public _Str_1027(): ActionDefinition
+ {
+ if(this._defaultAction) return this._defaultAction;
+
+ for(const action of this._actions.values())
+ {
+ if(!action || !action._Str_804) continue;
+
+ this._defaultAction = action;
+
+ return action;
+ }
+
+ return null;
+ }
+
+ public _Str_781(k: IActiveActionData[], _arg_2: string, _arg_3: number): number[]
+ {
+ let canvasOffsets: number[] = [];
+
+ for(const activeAction of k)
+ {
+ if(!activeAction) continue;
+
+ const action = this._actions.get(activeAction._Str_695);
+ const offsets = action && action._Str_805(_arg_2, _arg_3);
+
+ if(offsets) canvasOffsets = offsets;
+ }
+
+ return canvasOffsets;
+ }
+
+ public _Str_711(actions: IActiveActionData[]): IActiveActionData[]
+ {
+ if(!actions) return null;
+
+ actions = this._Str_1247(actions);
+
+ const validatedActions: IActiveActionData[] = [];
+
+ for(const action of actions)
+ {
+ if(!action) continue;
+
+ const definition = this._actions.get(action._Str_695);
+
+ if(!definition) continue;
+
+ action._Str_742 = definition;
+
+ validatedActions.push(action);
+ }
+
+ validatedActions.sort(this.sortByPrecedence);
+
+ return validatedActions;
+ }
+
+ private _Str_1247(actions: IActiveActionData[]): IActiveActionData[]
+ {
+ let preventions: string[] = [];
+ const activeActions: IActiveActionData[] = [];
+
+ for(const action of actions)
+ {
+ if(!action) continue;
+
+ const localAction = this._actions.get(action._Str_695);
+
+ if(localAction) preventions = preventions.concat(localAction._Str_733(action._Str_727));
+ }
+
+ for(const action of actions)
+ {
+ if(!action) continue;
+
+ let actionType = action._Str_695;
+
+ if(action._Str_695 === 'fx') actionType = (actionType + ('.' + action._Str_727));
+
+ if(preventions.indexOf(actionType) >= 0) continue;
+
+ activeActions.push(action);
+ }
+
+ return activeActions;
+ }
+
+ private sortByPrecedence(actionOne: IActiveActionData, actionTwo: IActiveActionData): number
+ {
+ if(!actionOne || !actionTwo) return 0;
+
+ const precedenceOne = actionOne._Str_742.precedence;
+ const precedenceTwo = actionTwo._Str_742.precedence;
+
+ if(precedenceOne < precedenceTwo) return 1;
+
+ if(precedenceOne > precedenceTwo) return -1;
+
+ return 0;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/actions/IActionDefinition.ts b/src/nitro/avatar/actions/IActionDefinition.ts
new file mode 100644
index 00000000..a2edafb0
--- /dev/null
+++ b/src/nitro/avatar/actions/IActionDefinition.ts
@@ -0,0 +1,20 @@
+
+export interface IActionDefinition
+{
+ id: string;
+ state: string;
+ precedence: number;
+ activePartSet: string;
+ _Str_779: boolean;
+ _Str_804: boolean;
+ _Str_778: string;
+ lay: string;
+ _Str_868: string;
+ _Str_861: boolean;
+ _Str_812: boolean;
+ _Str_801(_arg_1: string): boolean;
+ _Str_733(_arg_1: string): string[];
+ _Str_715(_arg_1: string): boolean;
+ _Str_772(_arg_1: string, _arg_2: number, _arg_3: []): void;
+ _Str_805(_arg_1: string, _arg_2: number): number[];
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/actions/IActiveActionData.ts b/src/nitro/avatar/actions/IActiveActionData.ts
new file mode 100644
index 00000000..1e6bacc7
--- /dev/null
+++ b/src/nitro/avatar/actions/IActiveActionData.ts
@@ -0,0 +1,11 @@
+import { IActionDefinition } from './IActionDefinition';
+
+export interface IActiveActionData
+{
+ id: string;
+ _Str_695: string;
+ _Str_727: string;
+ _Str_664: number;
+ _Str_742: IActionDefinition;
+ _Str_707: string;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/alias/AssetAlias.ts b/src/nitro/avatar/alias/AssetAlias.ts
new file mode 100644
index 00000000..99da1e1d
--- /dev/null
+++ b/src/nitro/avatar/alias/AssetAlias.ts
@@ -0,0 +1,37 @@
+import { IAssetAlias } from '../../../core/asset/interfaces';
+
+export class AssetAlias
+{
+ private _name: string;
+ private _link: string;
+ private _flipH: boolean;
+ private _flipV: boolean;
+
+ constructor(name: string, alias: IAssetAlias)
+ {
+ this._name = name;
+ this._link = alias.link;
+ this._flipH = alias.flipH;
+ this._flipV = alias.flipV;
+ }
+
+ public get name(): string
+ {
+ return this._name;
+ }
+
+ public get link(): string
+ {
+ return this._link;
+ }
+
+ public get flipH(): boolean
+ {
+ return this._flipH;
+ }
+
+ public get flipV(): boolean
+ {
+ return this._flipV;
+ }
+}
diff --git a/src/nitro/avatar/alias/AssetAliasCollection.ts b/src/nitro/avatar/alias/AssetAliasCollection.ts
new file mode 100644
index 00000000..85b2f009
--- /dev/null
+++ b/src/nitro/avatar/alias/AssetAliasCollection.ts
@@ -0,0 +1,90 @@
+import { IAssetManager } from '../../../core/asset/IAssetManager';
+import { IGraphicAsset } from '../../../room/object/visualization/utils/IGraphicAsset';
+import { AvatarRenderManager } from '../AvatarRenderManager';
+import { AssetAlias } from './AssetAlias';
+
+export class AssetAliasCollection
+{
+ private _assets: IAssetManager;
+ private _aliases: Map;
+ private _avatarRenderManager: AvatarRenderManager;
+ private _missingAssetNames: string[];
+
+ constructor(k: AvatarRenderManager, _arg_2: IAssetManager)
+ {
+ this._avatarRenderManager = k;
+ this._aliases = new Map();
+ this._assets = _arg_2;
+ this._missingAssetNames = [];
+ }
+
+ public dispose(): void
+ {
+ this._assets = null;
+ this._aliases = null;
+ }
+
+ public reset(): void
+ {
+ this.init();
+ }
+
+ public init(): void
+ {
+ for(const collection of this._assets.collections.values())
+ {
+ if(!collection) continue;
+
+ const aliases = collection.data && collection.data.aliases;
+
+ if(!aliases) continue;
+
+ for(const name in aliases)
+ {
+ const alias = aliases[name];
+
+ if(!alias) continue;
+
+ this._aliases.set(name, new AssetAlias(name, alias));
+ }
+ }
+ }
+
+ public _Str_1044(k: string): boolean
+ {
+ const alias = this._aliases.get(k);
+
+ if(alias) return true;
+
+ return false;
+ }
+
+ public _Str_2125(k: string): string
+ {
+ let _local_2 = k;
+ let _local_3 = 5;
+
+ while(this._Str_1044(_local_2) && (_local_3 >= 0))
+ {
+ const _local_4 = this._aliases.get(_local_2);
+
+ _local_2 = _local_4.link;
+ _local_3--;
+ }
+
+ return _local_2;
+ }
+
+ public getAsset(name: string): IGraphicAsset
+ {
+ if(!this._assets) return null;
+
+ name = this._Str_2125(name);
+
+ const asset = this._assets.getAsset(name);
+
+ if(!asset) return null;
+
+ return asset;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/animation/AddDataContainer.ts b/src/nitro/avatar/animation/AddDataContainer.ts
new file mode 100644
index 00000000..5320b45b
--- /dev/null
+++ b/src/nitro/avatar/animation/AddDataContainer.ts
@@ -0,0 +1,61 @@
+import { IAssetAnimationAdd } from '../../../core/asset/interfaces';
+
+export class AddDataContainer
+{
+ private _id: string;
+ private _align: string;
+ private _base: string;
+ private _ink: number;
+ private _blend: number;
+
+ constructor(k: IAssetAnimationAdd)
+ {
+ this._id = k.id || '';
+ this._align = k.align || '';
+ this._base = k.base || '';
+ this._ink = k.ink || 0;
+ this._blend = 0;
+
+ const _local_2 = k.blend;
+
+ if(_local_2)
+ {
+ if(_local_2.length > 0)
+ {
+ this._blend = parseInt(_local_2);
+
+ if(this._blend > 1) this._blend = (this._blend / 100);
+ }
+ }
+ }
+
+ public get id(): string
+ {
+ return this._id;
+ }
+
+ public get align(): string
+ {
+ return this._align;
+ }
+
+ public get base(): string
+ {
+ return this._base;
+ }
+
+ public get ink(): number
+ {
+ return this._ink;
+ }
+
+ public get blend(): number
+ {
+ return this._blend;
+ }
+
+ public get _Str_1096(): boolean
+ {
+ return this._blend !== 1;
+ }
+}
diff --git a/src/nitro/avatar/animation/Animation.ts b/src/nitro/avatar/animation/Animation.ts
new file mode 100644
index 00000000..43d4bac8
--- /dev/null
+++ b/src/nitro/avatar/animation/Animation.ts
@@ -0,0 +1,312 @@
+import { IAssetAnimation, IAssetAnimationFrame } from '../../../core/asset/interfaces';
+import { AvatarStructure } from '../AvatarStructure';
+import { AddDataContainer } from './AddDataContainer';
+import { AnimationLayerData } from './AnimationLayerData';
+import { AvatarDataContainer } from './AvatarDataContainer';
+import { DirectionDataContainer } from './DirectionDataContainer';
+import { IAnimation } from './IAnimation';
+import { SpriteDataContainer } from './SpriteDataContainer';
+
+export class Animation implements IAnimation
+{
+ private static _Str_2211: any[] = [];
+
+ private _id: string;
+ private _description: string;
+ private _frames: AnimationLayerData[][];
+ private _spriteData: SpriteDataContainer[];
+ private _avatarData: AvatarDataContainer;
+ private _directionData: DirectionDataContainer;
+ private _removeData: string[];
+ private _addData: AddDataContainer[];
+ private _overriddenActions: Map;
+ private _overrideFrames: Map;
+ private _resetOnToggle: boolean;
+
+ constructor(k: AvatarStructure, _arg_2: IAssetAnimation)
+ {
+ this._id = _arg_2.name;
+ this._description = this._id;
+ this._frames = [];
+ this._spriteData = null;
+ this._avatarData = null;
+ this._directionData = null;
+ this._removeData = null;
+ this._addData = null;
+ this._overriddenActions = null;
+ this._overrideFrames = null;
+ this._resetOnToggle = (_arg_2.resetOnToggle || false);
+
+ if(_arg_2.sprites && _arg_2.sprites.length)
+ {
+ this._spriteData = [];
+
+ for(const sprite of _arg_2.sprites) this._spriteData.push(new SpriteDataContainer(this, sprite));
+ }
+
+ if(_arg_2.avatars && _arg_2.avatars.length) this._avatarData = new AvatarDataContainer(_arg_2.avatars[0]);
+
+ if(_arg_2.directions && _arg_2.directions.length) this._directionData = new DirectionDataContainer(_arg_2.directions[0]);
+
+ if(_arg_2.removes && _arg_2.removes.length)
+ {
+ this._removeData = [];
+
+ for(const remove of _arg_2.removes) this._removeData.push(remove.id);
+ }
+
+ if(_arg_2.adds && _arg_2.adds.length)
+ {
+ this._addData = [];
+
+ for(const add of _arg_2.adds) this._addData.push(new AddDataContainer(add));
+ }
+
+ if(_arg_2.overrides && _arg_2.overrides.length)
+ {
+ this._overrideFrames = new Map();
+ this._overriddenActions = new Map();
+
+ for(const override of _arg_2.overrides)
+ {
+ const name = override.name;
+ const value = override.override;
+
+ this._overriddenActions.set(value, name);
+
+ const frames: AnimationLayerData[][] = [];
+
+ this._Str_1031(frames, override.frames, k);
+
+ this._overrideFrames.set(name, frames);
+ }
+ }
+
+ this._Str_1031(this._frames, _arg_2.frames, k);
+ }
+
+ private _Str_1031(frames: AnimationLayerData[][], _arg_2: IAssetAnimationFrame[], _arg_3: AvatarStructure): void
+ {
+ if(!_arg_2 || !_arg_2.length) return;
+
+ for(const frame of _arg_2)
+ {
+ let repeats = 1;
+
+ if(frame.repeats && (frame.repeats > 1)) repeats = frame.repeats;
+
+ let index = 0;
+
+ while(index < repeats)
+ {
+ const layers: AnimationLayerData[] = [];
+
+ if(frame.bodyparts && frame.bodyparts.length)
+ {
+ for(const bodyPart of frame.bodyparts)
+ {
+ const definition = _arg_3._Str_1675(bodyPart.action);
+ const layer = new AnimationLayerData(bodyPart, AnimationLayerData.BODYPART, definition);
+
+ layers.push(layer);
+ }
+ }
+
+ if(frame.fxs && frame.fxs.length)
+ {
+ for(const fx of frame.fxs)
+ {
+ const definition = _arg_3._Str_1675(fx.action);
+ const layer = new AnimationLayerData(fx, AnimationLayerData.FX, definition);
+
+ layers.push(layer);
+ }
+ }
+
+ frames.push(layers);
+
+ index++;
+ }
+ }
+ }
+
+ public _Str_2185(k: string = null): number
+ {
+ if(!k) return this._frames.length;
+
+ if(this._overrideFrames)
+ {
+ const _local_2 = this._overrideFrames.get(k);
+
+ if(_local_2) return _local_2.length;
+ }
+
+ return 0;
+ }
+
+ public _Str_1892(): boolean
+ {
+ if(!this._overriddenActions) return false;
+
+ return (this._overriddenActions.size > 0);
+ }
+
+ public _Str_1571(): string[]
+ {
+ if(!this._overriddenActions) return null;
+
+ const keys: string[] = [];
+
+ for(const key of this._overriddenActions.keys()) keys.push(key);
+
+ return keys;
+ }
+
+ public _Str_707(k: string): string
+ {
+ if(!this._overriddenActions) return null;
+
+ return this._overriddenActions.get(k);
+ }
+
+ private _Str_2259(frameCount: number, _arg_2: string = null): AnimationLayerData[]
+ {
+ if(frameCount < 0) frameCount = 0;
+
+ let layers: AnimationLayerData[] = [];
+
+ if(!_arg_2)
+ {
+ if(this._frames.length > 0)
+ {
+ layers = this._frames[(frameCount % this._frames.length)];
+ }
+ }
+ else
+ {
+ const overrideLayers = this._overrideFrames.get(_arg_2);
+
+ if(overrideLayers && (overrideLayers.length > 0))
+ {
+ layers = overrideLayers[(frameCount % overrideLayers.length)];
+ }
+ }
+
+ return layers;
+ }
+
+ public _Str_1065(k: number, _arg_2: string=null): string[]
+ {
+ const _local_3: string[] = [];
+
+ for(const layer of this._Str_2259(k, _arg_2))
+ {
+ if(layer.type === AnimationLayerData.BODYPART)
+ {
+ _local_3.push(layer.id);
+ }
+
+ else if(layer.type === AnimationLayerData.FX)
+ {
+ if(this._addData && this._addData.length)
+ {
+ for(const _local_5 of this._addData)
+ {
+ if(_local_5.id === layer.id) _local_3.push(_local_5.align);
+ }
+ }
+ }
+ }
+
+ return _local_3;
+ }
+
+ public _Str_607(frameCount: number, spriteId: string, _arg_3: string = null): AnimationLayerData
+ {
+ for(const layer of this._Str_2259(frameCount, _arg_3))
+ {
+ if(layer.id === spriteId) return layer;
+
+ if(layer.type === AnimationLayerData.FX)
+ {
+ if(this._addData && this._addData.length)
+ {
+ for(const addData of this._addData)
+ {
+ if(((addData.align === spriteId) && (addData.id === layer.id))) return layer;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public _Str_872(): boolean
+ {
+ return this._avatarData !== null;
+ }
+
+ public _Str_776(): boolean
+ {
+ return this._directionData !== null;
+ }
+
+ public _Str_706(): boolean
+ {
+ return this._addData !== null;
+ }
+
+ public _Str_1550(k: string): AddDataContainer
+ {
+ if(this._addData)
+ {
+ for(const _local_2 of this._addData)
+ {
+ if(_local_2.id === k) return _local_2;
+ }
+ }
+
+ return null;
+ }
+
+ public get id(): string
+ {
+ return this._id;
+ }
+
+ public get _Str_786(): SpriteDataContainer[]
+ {
+ return this._spriteData || Animation._Str_2211;
+ }
+
+ public get _Str_1475(): AvatarDataContainer
+ {
+ return this._avatarData;
+ }
+
+ public get _Str_1493(): DirectionDataContainer
+ {
+ return this._directionData;
+ }
+
+ public get _Str_652(): string[]
+ {
+ return this._removeData || Animation._Str_2211;
+ }
+
+ public get _Str_687(): AddDataContainer[]
+ {
+ return this._addData || Animation._Str_2211;
+ }
+
+ public toString(): string
+ {
+ return this._description;
+ }
+
+ public get resetOnToggle(): boolean
+ {
+ return this._resetOnToggle;
+ }
+}
diff --git a/src/nitro/avatar/animation/AnimationLayerData.ts b/src/nitro/avatar/animation/AnimationLayerData.ts
new file mode 100644
index 00000000..5a28dcd3
--- /dev/null
+++ b/src/nitro/avatar/animation/AnimationLayerData.ts
@@ -0,0 +1,112 @@
+import { IAssetAnimationFramePart } from '../../../core/asset/interfaces/animation/IAssetAnimationFramePart';
+import { ActiveActionData } from '../actions/ActiveActionData';
+import { IActionDefinition } from '../actions/IActionDefinition';
+import { IActiveActionData } from '../actions/IActiveActionData';
+import { IAnimationLayerData } from './IAnimationLayerData';
+
+export class AnimationLayerData implements IAnimationLayerData
+{
+ public static BODYPART: string = 'bodypart';
+ public static FX: string = 'fx';
+
+ private _id: string;
+ private _action: IActiveActionData;
+ private _animationFrame: number;
+ private _dx: number;
+ private _dy: number;
+ private _dz: number;
+ private _directionOffset: number;
+ private _type: string;
+ private _base: string;
+ private _items: Map;
+
+ constructor(k: IAssetAnimationFramePart, _arg_2: string, _arg_3: IActionDefinition)
+ {
+ this._id = k.id;
+ this._animationFrame = (k.frame || 0);
+ this._dx = (k.dx || 0);
+ this._dy = (k.dy || 0);
+ this._dz = (k.dz || 0);
+ this._directionOffset = (k.dd || 0);
+ this._type = _arg_2;
+ this._base = (k.base || '');
+ this._items = new Map();
+
+ if(k.items) for(const _local_4 of k.items) this._items.set(_local_4.id, _local_4.base);
+
+ let _local_5 = '';
+
+ if(this._base !== '') _local_5 = this._Str_2108().toString();
+
+ if(_arg_3)
+ {
+ this._action = new ActiveActionData(_arg_3.state, this.base);
+ this._action._Str_742 = _arg_3;
+ }
+ }
+
+ public get items(): Map
+ {
+ return this._items;
+ }
+
+ private _Str_2108(): number
+ {
+ let k = 0;
+ let index = 0;
+
+ while(index < this._base.length)
+ {
+ k = (k + this._base.charCodeAt(index));
+
+ index++;
+ }
+
+ return k;
+ }
+
+ public get id(): string
+ {
+ return this._id;
+ }
+
+ public get _Str_891(): number
+ {
+ return this._animationFrame;
+ }
+
+ public get dx(): number
+ {
+ return this._dx;
+ }
+
+ public get dy(): number
+ {
+ return this._dy;
+ }
+
+ public get dz(): number
+ {
+ return this._dz;
+ }
+
+ public get dd(): number
+ {
+ return this._directionOffset;
+ }
+
+ public get type(): string
+ {
+ return this._type;
+ }
+
+ public get base(): string
+ {
+ return this._base;
+ }
+
+ public get action(): IActiveActionData
+ {
+ return this._action;
+ }
+}
diff --git a/src/nitro/avatar/animation/AnimationManager.ts b/src/nitro/avatar/animation/AnimationManager.ts
new file mode 100644
index 00000000..f1204c3a
--- /dev/null
+++ b/src/nitro/avatar/animation/AnimationManager.ts
@@ -0,0 +1,50 @@
+import { IAssetAnimation } from '../../../core/asset/interfaces';
+import { AvatarStructure } from '../AvatarStructure';
+import { Animation } from './Animation';
+import { IAnimation } from './IAnimation';
+import { IAnimationLayerData } from './IAnimationLayerData';
+import { IAnimationManager } from './IAnimationManager';
+
+export class AnimationManager implements IAnimationManager
+{
+ private _animations: Map;
+
+ constructor()
+ {
+ this._animations = new Map();
+ }
+
+ public _Str_2061(structure: AvatarStructure, _arg_2: { [index: string]: IAssetAnimation }): boolean
+ {
+ const animationData = _arg_2[Object.keys(_arg_2)[0]];
+
+ const animation = new Animation(structure, animationData);
+
+ this._animations.set(animationData.name, animation);
+
+ return true;
+ }
+
+ public _Str_720(animation: string): Animation
+ {
+ const existing = this._animations.get(animation);
+
+ if(!existing) return null;
+
+ return existing;
+ }
+
+ public _Str_607(animation: string, frameCount: number, spriteId: string): IAnimationLayerData
+ {
+ const existing = this._Str_720(animation);
+
+ if(!existing) return null;
+
+ return existing._Str_607(frameCount, spriteId);
+ }
+
+ public get animations(): Map
+ {
+ return this._animations;
+ }
+}
diff --git a/src/nitro/avatar/animation/AvatarDataContainer.ts b/src/nitro/avatar/animation/AvatarDataContainer.ts
new file mode 100644
index 00000000..466b033a
--- /dev/null
+++ b/src/nitro/avatar/animation/AvatarDataContainer.ts
@@ -0,0 +1,137 @@
+import { AdjustmentFilter } from '@pixi/filter-adjustment';
+import { IAssetAnimationAvatar } from '../../../core/asset/interfaces';
+import { IAvatarDataContainer } from './IAvatarDataContainer';
+
+export class AvatarDataContainer implements IAvatarDataContainer
+{
+ private _ink: number;
+ private _foreGround: number;
+ private _backGround: number;
+ private _colorTransform: AdjustmentFilter;
+ private _rgb: number;
+ private _r: number;
+ private _g: number;
+ private _b: number;
+ private _redMultiplier: number;
+ private _greenMultiplier: number;
+ private _blueMultiplier: number;
+ private _alphaMultiplier: number;
+ private _colorMap: Map;
+ private _paletteIsGrayscale: boolean;
+
+ constructor(k: IAssetAnimationAvatar)
+ {
+ this._ink = k.ink;
+
+ let foreground = k.foreground;
+ let background = k.background;
+
+ foreground = foreground.replace('#', '');
+ background = background.replace('#', '');
+
+ this._foreGround = parseInt(foreground, 16);
+ this._backGround = parseInt(background, 16);
+ this._colorTransform = null;
+ this._rgb = parseInt(foreground, 16);
+ this._r = ((this._rgb >> 16) & 0xFF);
+ this._g = ((this._rgb >> 8) & 0xFF);
+ this._b = ((this._rgb >> 0) & 0xFF);
+ this._redMultiplier = ((this._r / 0xFF) * 1);
+ this._greenMultiplier = ((this._g / 0xFF) * 1);
+ this._blueMultiplier = ((this._b / 0xFF) * 1);
+ this._alphaMultiplier = 1;
+ this._paletteIsGrayscale = true;
+
+ if(this._ink === 37)
+ {
+ this._alphaMultiplier = 0.5;
+ this._paletteIsGrayscale = false;
+ }
+
+ this._colorMap = this._Str_1181(this._backGround, this._foreGround);
+ }
+
+ public get ink(): number
+ {
+ return this._ink;
+ }
+
+ public get colorTransform(): AdjustmentFilter
+ {
+ return this._colorTransform;
+ }
+
+ public get reds(): number[]
+ {
+ return this._colorMap.get('reds');
+ }
+
+ public get greens(): number[]
+ {
+ return this._colorMap.get('greens');
+ }
+
+ public get blues(): number[]
+ {
+ return this._colorMap.get('blues');
+ }
+
+ public get alphas(): number[]
+ {
+ return this._colorMap.get('alphas');
+ }
+
+ public get _Str_832(): boolean
+ {
+ return this._paletteIsGrayscale;
+ }
+
+ private _Str_1181(k: number, _arg_2: number): Map
+ {
+ const _local_3 = ((k >> 24) & 0xFF);
+ const _local_4 = ((k >> 16) & 0xFF);
+ const _local_5 = ((k >> 8) & 0xFF);
+ const _local_6 = ((k >> 0) & 0xFF);
+ const _local_7 = ((_arg_2 >> 24) & 0xFF);
+ const _local_8 = ((_arg_2 >> 16) & 0xFF);
+ const _local_9 = ((_arg_2 >> 8) & 0xFF);
+ const _local_10 = ((_arg_2 >> 0) & 0xFF);
+ const _local_11 = ((_local_7 - _local_3) / 0xFF);
+ const _local_12 = ((_local_8 - _local_4) / 0xFF);
+ const _local_13 = ((_local_9 - _local_5) / 0xFF);
+ const _local_14 = ((_local_10 - _local_6) / 0xFF);
+ const _local_15: Map = new Map();
+ const _local_16: number[] = [];
+ const _local_17: number[] = [];
+ const _local_18: number[] = [];
+ const _local_19: number[] = [];
+ let _local_20 = _local_3;
+ let _local_21 = _local_4;
+ let _local_22 = _local_5;
+ let _local_23 = _local_6;
+ let _local_24 = 0;
+ while(_local_24 < 0x0100)
+ {
+ if((((_local_21 == _local_4) && (_local_22 == _local_5)) && (_local_23 == _local_6)))
+ {
+ _local_20 = 0;
+ }
+ _local_20 = (_local_20 + _local_11);
+ _local_21 = (_local_21 + _local_12);
+ _local_22 = (_local_22 + _local_13);
+ _local_23 = (_local_23 + _local_14);
+ _local_19.push((_local_20 << 24));
+ _local_16.push(((((_local_20 << 24) | (_local_21 << 16)) | (_local_22 << 8)) | _local_23));
+ _local_17.push(((((_local_20 << 24) | (_local_21 << 16)) | (_local_22 << 8)) | _local_23));
+ _local_18.push(((((_local_20 << 24) | (_local_21 << 16)) | (_local_22 << 8)) | _local_23));
+ _local_24++;
+ }
+
+ _local_15.set('alphas', _local_16);
+ _local_15.set('reds', _local_16);
+ _local_15.set('greens', _local_17);
+ _local_15.set('blues', _local_18);
+
+ return _local_15;
+ }
+}
diff --git a/src/nitro/avatar/animation/DirectionDataContainer.ts b/src/nitro/avatar/animation/DirectionDataContainer.ts
new file mode 100644
index 00000000..d9ae4627
--- /dev/null
+++ b/src/nitro/avatar/animation/DirectionDataContainer.ts
@@ -0,0 +1,16 @@
+import { IAssetAnimationDirection } from '../../../core/asset/interfaces';
+
+export class DirectionDataContainer
+{
+ private _offset: number;
+
+ constructor(k: IAssetAnimationDirection)
+ {
+ this._offset = k.offset;
+ }
+
+ public get offset(): number
+ {
+ return this._offset;
+ }
+}
diff --git a/src/nitro/avatar/animation/IAnimation.ts b/src/nitro/avatar/animation/IAnimation.ts
new file mode 100644
index 00000000..9cadcf60
--- /dev/null
+++ b/src/nitro/avatar/animation/IAnimation.ts
@@ -0,0 +1,11 @@
+export interface IAnimation
+{
+ _Str_872(): boolean;
+ _Str_776(): boolean;
+ _Str_706(): boolean;
+ id: string;
+ _Str_786: any;
+ _Str_652: any;
+ _Str_687: any;
+ resetOnToggle: boolean;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/animation/IAnimationLayerData.ts b/src/nitro/avatar/animation/IAnimationLayerData.ts
new file mode 100644
index 00000000..4c5b8449
--- /dev/null
+++ b/src/nitro/avatar/animation/IAnimationLayerData.ts
@@ -0,0 +1,12 @@
+import { IActiveActionData } from '../actions/IActiveActionData';
+
+export interface IAnimationLayerData
+{
+ id: string;
+ action: IActiveActionData;
+ _Str_891: number;
+ dx: number;
+ dy: number;
+ dz: number;
+ dd: number;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/animation/IAnimationManager.ts b/src/nitro/avatar/animation/IAnimationManager.ts
new file mode 100644
index 00000000..31ce0d06
--- /dev/null
+++ b/src/nitro/avatar/animation/IAnimationManager.ts
@@ -0,0 +1,9 @@
+import { IAnimation } from './IAnimation';
+import { IAnimationLayerData } from './IAnimationLayerData';
+
+export interface IAnimationManager
+{
+ animations: Map;
+ _Str_720(_arg_1: string): IAnimation;
+ _Str_607(_arg_1: string, _arg_2: number, _arg_3: string): IAnimationLayerData;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/animation/IAvatarDataContainer.ts b/src/nitro/avatar/animation/IAvatarDataContainer.ts
new file mode 100644
index 00000000..7cb2fbb3
--- /dev/null
+++ b/src/nitro/avatar/animation/IAvatarDataContainer.ts
@@ -0,0 +1,12 @@
+import { AdjustmentFilter } from '@pixi/filter-adjustment';
+
+export interface IAvatarDataContainer
+{
+ ink: number;
+ colorTransform: AdjustmentFilter;
+ _Str_832: boolean;
+ reds: number[];
+ greens: number[];
+ blues: number[];
+ alphas: number[];
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/animation/ISpriteDataContainer.ts b/src/nitro/avatar/animation/ISpriteDataContainer.ts
new file mode 100644
index 00000000..2dc43444
--- /dev/null
+++ b/src/nitro/avatar/animation/ISpriteDataContainer.ts
@@ -0,0 +1,14 @@
+import { IAnimation } from './IAnimation';
+
+export interface ISpriteDataContainer
+{
+ animation: IAnimation;
+ id: string;
+ ink: number;
+ member: string;
+ _Str_949: boolean;
+ _Str_767: boolean;
+ _Str_809(_arg_1: number): number;
+ _Str_739(_arg_1: number): number;
+ _Str_839(_arg_1: number): number;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/animation/SpriteDataContainer.ts b/src/nitro/avatar/animation/SpriteDataContainer.ts
new file mode 100644
index 00000000..eece75bd
--- /dev/null
+++ b/src/nitro/avatar/animation/SpriteDataContainer.ts
@@ -0,0 +1,96 @@
+import { IAssetAnimationSprite } from '../../../core/asset/interfaces';
+import { IAnimation } from './IAnimation';
+import { ISpriteDataContainer } from './ISpriteDataContainer';
+
+export class SpriteDataContainer implements ISpriteDataContainer
+{
+ private _animation: IAnimation;
+ private _id: string;
+ private _ink: number;
+ private _member: string;
+ private _hasDirections: boolean;
+ private _hasStaticY: boolean;
+ private _dx: number[];
+ private _dy: number[];
+ private _dz: number[];
+
+ constructor(k: IAnimation, _arg_2: IAssetAnimationSprite)
+ {
+ this._animation = k;
+ this._id = _arg_2.id;
+ this._ink = _arg_2.ink;
+ this._member = _arg_2.member;
+ this._hasStaticY = _arg_2.staticY ? true : false;
+ this._hasDirections = _arg_2.directions ? true : false;
+ this._dx = [];
+ this._dy = [];
+ this._dz = [];
+
+ const directions = _arg_2.directionList;
+
+ if(directions && directions.length)
+ {
+ for(const direction of directions)
+ {
+ const id = direction.id;
+
+ if(id === undefined) continue;
+
+ this._dx[id] = (direction.dx || 0);
+ this._dy[id] = (direction.dy || 0);
+ this._dz[id] = (direction.dz || 0);
+ }
+ }
+ }
+
+ public _Str_809(k: number): number
+ {
+ if(k < this._dx.length) return this._dx[k];
+
+ return 0;
+ }
+
+ public _Str_739(k: number): number
+ {
+ if(k < this._dy.length) return this._dy[k];
+
+ return 0;
+ }
+
+ public _Str_839(k: number): number
+ {
+ if(k < this._dz.length) return this._dz[k];
+
+ return 0;
+ }
+
+ public get animation(): IAnimation
+ {
+ return this._animation;
+ }
+
+ public get id(): string
+ {
+ return this._id;
+ }
+
+ public get ink(): number
+ {
+ return this._ink;
+ }
+
+ public get member(): string
+ {
+ return this._member;
+ }
+
+ public get _Str_949(): boolean
+ {
+ return this._hasDirections;
+ }
+
+ public get _Str_767(): boolean
+ {
+ return this._hasStaticY;
+ }
+}
diff --git a/src/nitro/avatar/cache/AvatarImageActionCache.ts b/src/nitro/avatar/cache/AvatarImageActionCache.ts
new file mode 100644
index 00000000..28a49923
--- /dev/null
+++ b/src/nitro/avatar/cache/AvatarImageActionCache.ts
@@ -0,0 +1,96 @@
+import { IActiveActionData } from '../actions/IActiveActionData';
+import { AvatarImageBodyPartCache } from './AvatarImageBodyPartCache';
+
+export class AvatarImageActionCache
+{
+ private _Str_586: Map;
+ private _Str_1233: IActiveActionData;
+ private _Str_1188: number;
+ private _disposed: boolean;
+
+ constructor()
+ {
+ this._Str_586 = new Map();
+ }
+
+ public _Str_1565(k: IActiveActionData, _arg_2: number): void
+ {
+ if(!this._Str_1233) this._Str_1233 = k;
+
+ const _local_3 = this._Str_1961(this._Str_1233);
+
+ if(_local_3) _local_3._Str_1108(_arg_2);
+
+ this._Str_1233 = k;
+ }
+
+ public dispose(): void
+ {
+ if(!this._disposed)
+ {
+ if(!this._Str_586) return;
+
+ this._Str_2089(0, 2147483647);
+
+ this._Str_586.clear();
+
+ this._Str_586 = null;
+ this._disposed = true;
+ }
+ }
+
+ public _Str_2089(k: number, _arg_2: number): void
+ {
+ if(!this._Str_586 || this._disposed) return;
+
+ for(const [ key, cache ] of this._Str_586.entries())
+ {
+ if(!cache) continue;
+
+ const _local_3 = cache._Str_1815();
+
+ if((_arg_2 - _local_3) >= k)
+ {
+ cache.dispose();
+
+ this._Str_586.delete(key);
+ }
+ }
+ }
+
+ public _Str_2244():IActiveActionData
+ {
+ return this._Str_1233;
+ }
+
+ public setDirection(k: number): void
+ {
+ this._Str_1188 = k;
+ }
+
+ public getDirection(): number
+ {
+ return this._Str_1188;
+ }
+
+ public _Str_1961(k: IActiveActionData=null): AvatarImageBodyPartCache
+ {
+ if(!this._Str_1233) return null;
+
+ if(!k) k = this._Str_1233;
+
+ if(k._Str_707) return this._Str_586.get(k._Str_707);
+
+ return this._Str_586.get(k.id);
+ }
+
+ public _Str_1765(k: IActiveActionData, _arg_2: AvatarImageBodyPartCache): void
+ {
+ if(k._Str_707) this._Str_586.set(k._Str_707, _arg_2);
+ else this._Str_586.set(k.id, _arg_2);
+ }
+
+ private _Str_587(k: string): void
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/cache/AvatarImageBodyPartCache.ts b/src/nitro/avatar/cache/AvatarImageBodyPartCache.ts
new file mode 100644
index 00000000..dc331e8f
--- /dev/null
+++ b/src/nitro/avatar/cache/AvatarImageBodyPartCache.ts
@@ -0,0 +1,57 @@
+import { Nitro } from '../../Nitro';
+import { AvatarImageDirectionCache } from './AvatarImageDirectionCache';
+
+export class AvatarImageBodyPartCache
+{
+ private _Str_586: Map;
+ private _Str_1509: number;
+
+ constructor()
+ {
+ this._Str_586 = new Map();
+
+ this._Str_1108(Nitro.instance.time);
+ }
+
+ public dispose(): void
+ {
+ this._Str_587('[dispose]');
+
+ if(!this._Str_586) return;
+
+ for(const direction of this._Str_586.values())
+ {
+ if(direction) direction.dispose();
+ }
+
+ this._Str_586.clear();
+ }
+
+ public _Str_2070(k: number): AvatarImageDirectionCache
+ {
+ const existing = this._Str_586.get(k.toString());
+
+ if(!existing) return null;
+
+ return existing;
+ }
+
+ public _Str_2168(k: number, _arg_2: AvatarImageDirectionCache): void
+ {
+ this._Str_586.set(k.toString(), _arg_2);
+ }
+
+ public _Str_1108(k: number): void
+ {
+ this._Str_1509 = k;
+ }
+
+ public _Str_1815(): number
+ {
+ return this._Str_1509;
+ }
+
+ private _Str_587(k: string): void
+ {
+ }
+}
diff --git a/src/nitro/avatar/cache/AvatarImageCache.ts b/src/nitro/avatar/cache/AvatarImageCache.ts
new file mode 100644
index 00000000..9c2bb85a
--- /dev/null
+++ b/src/nitro/avatar/cache/AvatarImageCache.ts
@@ -0,0 +1,527 @@
+import { Container, Matrix, Point, Rectangle, Sprite, Texture } from 'pixi.js';
+import { RoomObjectSpriteData } from '../../../room/data/RoomObjectSpriteData';
+import { Nitro } from '../../Nitro';
+import { IActiveActionData } from '../actions/IActiveActionData';
+import { AssetAliasCollection } from '../alias/AssetAliasCollection';
+import { AnimationLayerData } from '../animation/AnimationLayerData';
+import { AvatarImageBodyPartContainer } from '../AvatarImageBodyPartContainer';
+import { AvatarImagePartContainer } from '../AvatarImagePartContainer';
+import { AvatarStructure } from '../AvatarStructure';
+import { AvatarDirectionAngle } from '../enum/AvatarDirectionAngle';
+import { AvatarFigurePartType } from '../enum/AvatarFigurePartType';
+import { AvatarScaleType } from '../enum/AvatarScaleType';
+import { GeometryType } from '../enum/GeometryType';
+import { IAvatarImage } from '../IAvatarImage';
+import { AvatarCanvas } from '../structure/AvatarCanvas';
+import { AvatarImageActionCache } from './AvatarImageActionCache';
+import { AvatarImageBodyPartCache } from './AvatarImageBodyPartCache';
+import { AvatarImageDirectionCache } from './AvatarImageDirectionCache';
+import { ImageData } from './ImageData';
+
+export class AvatarImageCache
+{
+ private static _Str_2189: number = 60000;
+
+ private _structure: AvatarStructure;
+ private _avatar: IAvatarImage;
+ private _assets: AssetAliasCollection;
+ private _scale: string;
+ private _cache: Map;
+ private _canvas: AvatarCanvas;
+ private _disposed: boolean;
+ private _geometryType: string;
+ private _unionImages: ImageData[];
+ private _matrix: Matrix;
+ private _serverRenderData: RoomObjectSpriteData[];
+
+ constructor(k: AvatarStructure, _arg_2: IAvatarImage, _arg_3: AssetAliasCollection, _arg_4: string)
+ {
+ this._structure = k;
+ this._avatar = _arg_2;
+ this._assets = _arg_3;
+ this._scale = _arg_4;
+ this._cache = new Map();
+ this._canvas = null;
+ this._disposed = false;
+ this._unionImages = [];
+ this._matrix = new Matrix();
+ this._serverRenderData = [];
+ }
+
+ public dispose(): void
+ {
+ if(this._disposed) return;
+
+ this._structure = null;
+ this._avatar = null;
+ this._assets = null;
+ this._canvas = null;
+ this._disposed = true;
+
+ if(this._cache)
+ {
+ for(const cache of this._cache.values())
+ {
+ if(!cache) continue;
+
+ cache.dispose();
+ }
+
+ this._cache = null;
+ }
+
+ if(this._unionImages)
+ {
+ for(const image of this._unionImages)
+ {
+ if(!image) continue;
+
+ image.dispose();
+ }
+
+ this._unionImages = [];
+ }
+ }
+
+ public _Str_1086(k: number = 60000): void
+ {
+ const time = Nitro.instance.time;
+
+ if(this._cache)
+ {
+ for(const cache of this._cache.values())
+ {
+ if(!cache) continue;
+
+ cache._Str_2089(k, time);
+ }
+ }
+ }
+
+ public _Str_741(k: IActiveActionData): void
+ {
+ if(this._cache)
+ {
+ for(const cache of this._cache.values())
+ {
+ if(!cache) continue;
+
+ cache._Str_1565(k, 0);
+ }
+ }
+ }
+
+ public setDirection(k: string, _arg_2: number): void
+ {
+ const parts = this._structure._Str_1695(k);
+
+ if(parts)
+ {
+ for(const part of parts)
+ {
+ const actionCache = this._Str_1050(part);
+
+ if(!actionCache) continue;
+
+ actionCache.setDirection(_arg_2);
+ }
+ }
+ }
+
+ public _Str_1565(k: IActiveActionData, _arg_2: number): void
+ {
+ const _local_3 = this._structure._Str_2021(k, this._avatar);
+
+ for(const _local_4 of _local_3)
+ {
+ const _local_5 = this._Str_1050(_local_4);
+
+ if(_local_5) _local_5._Str_1565(k, _arg_2);
+ }
+ }
+
+ public _Str_2014(k: string): void
+ {
+ if(this._geometryType === k) return;
+
+ if((((this._geometryType === GeometryType.SITTING) && (k === GeometryType.VERTICAL)) || ((this._geometryType === GeometryType.VERTICAL) && (k === GeometryType.SITTING)) || ((this._geometryType === GeometryType.SNOWWARS_HORIZONTAL) && (k = GeometryType.SNOWWARS_HORIZONTAL))))
+ {
+ this._geometryType = k;
+ this._canvas = null;
+
+ return;
+ }
+
+ this._Str_1086(0);
+
+ this._geometryType = k;
+ this._canvas = null;
+ }
+
+ public _Str_1629(k: string, frameNumber: number, _arg_3: boolean = false): AvatarImageBodyPartContainer
+ {
+ let _local_4 = this._Str_1050(k);
+
+ if(!_local_4)
+ {
+ _local_4 = new AvatarImageActionCache();
+
+ this._cache.set(k, _local_4);
+ }
+
+ let _local_5 = _local_4.getDirection();
+ let _local_7 = _local_4._Str_2244();
+ let frameCount = frameNumber;
+
+ if(_local_7._Str_742._Str_812) frameCount -= _local_7._Str_664;
+
+ let _local_8 = _local_7;
+ let _local_9: string[] = [];
+ let _local_10: Map = new Map();
+ const _local_11 = new Point();
+
+ if(!((!(_local_7)) || (!(_local_7._Str_742))))
+ {
+ if(_local_7._Str_742._Str_861)
+ {
+ let _local_15 = _local_5;
+
+ const _local_16 = this._structure._Str_720(((_local_7._Str_742.state + '.') + _local_7._Str_727));
+ const _local_17 = (frameNumber - _local_7._Str_664);
+
+ if(_local_16)
+ {
+ const _local_18 = _local_16._Str_607(_local_17, k, _local_7._Str_707);
+
+ if(_local_18)
+ {
+ _local_15 = (_local_5 + _local_18.dd);
+
+ if(_local_18.dd < 0)
+ {
+ if(_local_15 < 0)
+ {
+ _local_15 = (8 + _local_15);
+ }
+ else if(_local_15 > 7) _local_15 = (8 - _local_15);
+ }
+ else
+ {
+ if(_local_15 < 0)
+ {
+ _local_15 = (_local_15 + 8);
+ }
+ else if(_local_15 > 7) _local_15 = (_local_15 - 8);
+ }
+
+ if(this._scale === AvatarScaleType.LARGE)
+ {
+ _local_11.x = _local_18.dx;
+ _local_11.y = _local_18.dy;
+ }
+ else
+ {
+ _local_11.x = (_local_18.dx / 2);
+ _local_11.y = (_local_18.dy / 2);
+ }
+
+ frameCount = _local_18._Str_891;
+
+ if(_local_18.action)
+ {
+ _local_7 = _local_18.action;
+ }
+
+ if(_local_18.type === AnimationLayerData.BODYPART)
+ {
+ if(_local_18.action != null)
+ {
+ _local_8 = _local_18.action;
+ }
+
+ _local_5 = _local_15;
+ }
+ else if(_local_18.type === AnimationLayerData.FX) _local_5 = _local_15;
+
+ _local_10 = _local_18.items;
+ }
+
+ _local_9 = _local_16._Str_652;
+ }
+ }
+ }
+
+ let _local_12 = _local_4._Str_1961(_local_8);
+
+ if(!_local_12 || _arg_3)
+ {
+ _local_12 = new AvatarImageBodyPartCache();
+ _local_4._Str_1765(_local_8, _local_12);
+ }
+
+ let _local_13 = _local_12._Str_2070(_local_5);
+
+ if(!_local_13 || _arg_3)
+ {
+ const _local_19 = this._structure._Str_713(k, this._avatar.getFigure(), _local_8, this._geometryType, _local_5, _local_9, this._avatar, _local_10);
+
+ _local_13 = new AvatarImageDirectionCache(_local_19);
+
+ _local_12._Str_2168(_local_5, _local_13);
+ }
+
+ let _local_14 = _local_13._Str_1629(frameCount);
+
+ if(!_local_14 || _arg_3)
+ {
+ const _local_20 = _local_13._Str_1699();
+
+ _local_14 = this._Str_1834(_local_5, _local_20, frameCount, _local_7, _arg_3);
+
+ if(_local_14 && !_arg_3)
+ {
+ if(_local_14._Str_1807) _local_13._Str_1924(_local_14, frameCount);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ const offset = this._structure._Str_1888(_local_8, _local_5, frameCount, k);
+
+ _local_11.x += offset.x;
+ _local_11.y += offset.y;
+
+ _local_14.offset = _local_11;
+
+ return _local_14;
+ }
+
+ public _Str_1009(): any[]
+ {
+ this._serverRenderData = [];
+
+ return this._serverRenderData;
+ }
+
+ public _Str_1050(k: string): AvatarImageActionCache
+ {
+ let existing = this._cache.get(k);
+
+ if(!existing)
+ {
+ existing = new AvatarImageActionCache();
+
+ this._cache.set(k, existing);
+ }
+
+ return existing;
+ }
+
+ private _Str_1834(direction: number, containers: AvatarImagePartContainer[], frameCount: number, _arg_4: IActiveActionData, renderServerData: boolean = false): AvatarImageBodyPartContainer
+ {
+ if(!containers || !containers.length) return null;
+
+ if(!this._canvas)
+ {
+ this._canvas = this._structure._Str_1664(this._scale, this._geometryType);
+
+ if(!this._canvas) return null;
+ }
+
+ const isFlipped = AvatarDirectionAngle.DIRECTION_IS_FLIPPED[direction] || false;
+ let assetPartDefinition = _arg_4._Str_742._Str_778;
+ let isCacheable = true;
+ let containerIndex = (containers.length - 1);
+
+ while(containerIndex >= 0)
+ {
+ const container = containers[containerIndex];
+
+ let color = 16777215;
+
+ if(!((direction == 7) && ((container._Str_1669 === 'fc') || (container._Str_1669 === 'ey'))))
+ {
+ if(!((container._Str_1669 === 'ri') && !container._Str_1502))
+ {
+ const partId = container._Str_1502;
+ const animationFrame = container._Str_2258(frameCount);
+
+ let partType = container._Str_1669;
+ let frameNumber = 0;
+
+ if(animationFrame)
+ {
+ frameNumber = animationFrame.number;
+
+ if((animationFrame._Str_778) && (animationFrame._Str_778 !== '')) assetPartDefinition = animationFrame._Str_778;
+ }
+ else frameNumber = container._Str_1674(frameCount);
+
+ let assetDirection = direction;
+ let flipH = false;
+
+ if(isFlipped)
+ {
+ if(((assetPartDefinition === 'wav') && (((partType === AvatarFigurePartType.LEFT_HAND) || (partType === AvatarFigurePartType.LEFT_SLEEVE)) || (partType === AvatarFigurePartType.LEFT_COAT_SLEEVE))) || ((assetPartDefinition === 'drk') && (((partType === AvatarFigurePartType.RIGHT_HAND) || (partType === AvatarFigurePartType.RIGHT_SLEEVE)) || (partType === AvatarFigurePartType.RIGHT_COAT_SLEEVE))) || ((assetPartDefinition === 'blw') && (partType === AvatarFigurePartType.RIGHT_HAND)) || ((assetPartDefinition === 'sig') && (partType === AvatarFigurePartType.LEFT_HAND)) || ((assetPartDefinition === 'respect') && (partType === AvatarFigurePartType.LEFT_HAND)) || (partType === AvatarFigurePartType.RIGHT_HAND_ITEM) || (partType === AvatarFigurePartType.LEFT_HAND_ITEM) || (partType === AvatarFigurePartType.CHEST_PRINT))
+ {
+ flipH = true;
+ }
+ else
+ {
+ if(direction === 4) assetDirection = 2;
+ else if(direction === 5) assetDirection = 1;
+ else if(direction === 6) assetDirection = 0;
+
+ if(container._Str_1666 !== partType) partType = container._Str_1666;
+ }
+ }
+
+ let assetName = (this._scale + '_' + assetPartDefinition + '_' + partType + '_' + partId + '_' + assetDirection + '_' + frameNumber);
+ let asset = this._assets.getAsset(assetName);
+
+ if(!asset)
+ {
+ assetName = (this._scale + '_std_' + partType + '_' + partId + '_' + assetDirection + '_0');
+ asset = this._assets.getAsset(assetName);
+ }
+
+ if(asset)
+ {
+ const texture = asset.texture;
+
+ if(!texture || !texture.valid || !texture.baseTexture)
+ {
+ isCacheable = false;
+ }
+ else
+ {
+ if(container.isColorable && container.color) color = container.color._Str_915;
+
+ const offset = new Point(-(asset.x), -(asset.y));
+
+ if(flipH) offset.x = (offset.x + ((this._scale === AvatarScaleType.LARGE) ? 65 : 31));
+
+ if(renderServerData)
+ {
+ const spriteData = new RoomObjectSpriteData();
+
+ spriteData.name = this._assets._Str_2125(assetName);
+ spriteData.x = (-(offset.x) - 33);
+ spriteData.y = -(offset.y);
+ spriteData.z = (this._serverRenderData.length * -0.0001);
+ spriteData.width = asset.rectangle.width;
+ spriteData.height = asset.rectangle.height;
+ spriteData.flipH = flipH;
+
+ if(assetPartDefinition === 'lay') spriteData.x = (spriteData.x + 53);
+
+ if(isFlipped)
+ {
+ spriteData.flipH = (!(spriteData.flipH));
+
+ if(spriteData.flipH) spriteData.x = (-(spriteData.x) - texture.width);
+ else spriteData.x = (spriteData.x + 65);
+ }
+
+ if(container.isColorable) spriteData.color = `${ color }`;
+
+ this._serverRenderData.push(spriteData);
+ }
+
+ this._unionImages.push(new ImageData(texture, asset.rectangle, offset, flipH, color));
+ }
+ }
+ }
+ }
+
+ containerIndex--;
+ }
+
+ if(!this._unionImages.length) return null;
+
+ const imageData = this._Str_1236(this._unionImages, isFlipped);
+ const canvasOffset = ((this._scale === AvatarScaleType.LARGE) ? (this._canvas.height - 16) : (this._canvas.height - 8));
+ const offset = new Point(-(imageData._Str_1076.x), (canvasOffset - imageData._Str_1076.y));
+
+ if(isFlipped && (assetPartDefinition !== 'lay')) offset.x = (offset.x + ((this._scale === AvatarScaleType.LARGE) ? 67 : 31));
+
+ let imageIndex = (this._unionImages.length - 1);
+
+ while(imageIndex >= 0)
+ {
+ const _local_17 = this._unionImages.pop();
+
+ if(_local_17) _local_17.dispose();
+
+ imageIndex--;
+ }
+
+ return new AvatarImageBodyPartContainer(imageData.container, offset, isCacheable);
+ }
+
+ private _Str_1652(k: number): string
+ {
+ let _local_2: string = (k * 0xFF).toString(16);
+ if(_local_2.length < 2)
+ {
+ _local_2 = ('0' + _local_2);
+ }
+ return _local_2;
+ }
+
+ private _Str_1236(k: ImageData[], isFlipped: boolean): ImageData
+ {
+ const bounds = new Rectangle();
+
+ for(const data of k) data && bounds.enlarge(data._Str_1567);
+
+ const point = new Point(-(bounds.x), -(bounds.y));
+ const container = new Container();
+
+ const sprite = new Sprite(Texture.EMPTY);
+
+ sprite.width = bounds.width;
+ sprite.height = bounds.height;
+
+ container.addChild(sprite);
+
+ for(const data of k)
+ {
+ if(!data) continue;
+
+ const texture = data.texture;
+ const color = data.color;
+ const flipH = (!(isFlipped && data.flipH) && (isFlipped || data.flipH));
+ const regPoint = point.clone();
+
+ regPoint.x -= data._Str_1076.x;
+ regPoint.y -= data._Str_1076.y;
+
+ if(isFlipped) regPoint.x = (container.width - (regPoint.x + data.rect.width));
+
+ if(flipH)
+ {
+ this._matrix.a = -1;
+ this._matrix.tx = ((data.rect.x + data.rect.width) + regPoint.x);
+ this._matrix.ty = (regPoint.y - data.rect.y);
+ }
+ else
+ {
+ this._matrix.a = 1;
+ this._matrix.tx = (regPoint.x - data.rect.x);
+ this._matrix.ty = (regPoint.y - data.rect.y);
+ }
+
+ const sprite = new Sprite(texture);
+
+ sprite.tint = color;
+ sprite.transform.setFromMatrix(this._matrix);
+
+ container.addChild(sprite);
+ }
+
+ return new ImageData(null, container.getLocalBounds(), point, isFlipped, null, container);
+ }
+}
diff --git a/src/nitro/avatar/cache/AvatarImageDirectionCache.ts b/src/nitro/avatar/cache/AvatarImageDirectionCache.ts
new file mode 100644
index 00000000..c78d56aa
--- /dev/null
+++ b/src/nitro/avatar/cache/AvatarImageDirectionCache.ts
@@ -0,0 +1,59 @@
+import { AvatarImageBodyPartContainer } from '../AvatarImageBodyPartContainer';
+import { AvatarImagePartContainer } from '../AvatarImagePartContainer';
+
+export class AvatarImageDirectionCache
+{
+ private _partList: AvatarImagePartContainer[];
+ private _images: Map;
+
+ constructor(k: AvatarImagePartContainer[])
+ {
+ this._partList = k;
+ this._images = new Map();
+ }
+
+ public dispose(): void
+ {
+ for(const image of this._images.values()) image && image.dispose();
+
+ this._images = null;
+ }
+
+ public _Str_1699(): AvatarImagePartContainer[]
+ {
+ return this._partList;
+ }
+
+ public _Str_1629(k: number): AvatarImageBodyPartContainer
+ {
+ const existing = this._images.get(this._Str_2219(k));
+
+ if(!existing) return null;
+
+ return existing;
+ }
+
+ public _Str_1924(k: AvatarImageBodyPartContainer, _arg_2: number): void
+ {
+ const name = this._Str_2219(_arg_2);
+
+ const existing = this._images.get(name);
+
+ if(existing) existing.dispose();
+
+ this._images.set(name, k);
+ }
+
+ private _Str_2219(k: number): string
+ {
+ let name = '';
+
+ for(const part of this._partList) name += (part._Str_1206(k) + '/');
+
+ return name;
+ }
+
+ private _Str_587(k: string): void
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/cache/ImageData.ts b/src/nitro/avatar/cache/ImageData.ts
new file mode 100644
index 00000000..6f478d5b
--- /dev/null
+++ b/src/nitro/avatar/cache/ImageData.ts
@@ -0,0 +1,65 @@
+import { Container, Point, Rectangle, Texture } from 'pixi.js';
+
+export class ImageData
+{
+ private _texture: Texture;
+ private _container: Container;
+ private _rect: Rectangle;
+ private _regPoint: Point;
+ private _flipH: boolean;
+ private _color: number;
+
+ constructor(texture: Texture, rectangle: Rectangle, _arg_3: Point, flipH: boolean, color: number, container: Container = null)
+ {
+ this._texture = texture;
+ this._container = container;
+ this._rect = rectangle;
+ this._regPoint = _arg_3;
+ this._flipH = flipH;
+ this._color = color;
+
+ if(flipH) this._regPoint.x = (-(this._regPoint.x) + rectangle.width);
+ }
+
+ public dispose(): void
+ {
+ this._texture = null;
+ this._regPoint = null;
+ this._color = null;
+ }
+
+ public get texture(): Texture
+ {
+ return this._texture;
+ }
+
+ public get container(): Container
+ {
+ return this._container;
+ }
+
+ public get rect(): Rectangle
+ {
+ return this._rect;
+ }
+
+ public get _Str_1076(): Point
+ {
+ return this._regPoint;
+ }
+
+ public get flipH(): boolean
+ {
+ return this._flipH;
+ }
+
+ public get color(): number
+ {
+ return this._color;
+ }
+
+ public get _Str_1567(): Rectangle
+ {
+ return new Rectangle(-(this._regPoint.x), -(this._regPoint.y), this._rect.width, this._rect.height);
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/data/HabboAvatarAnimations.json b/src/nitro/avatar/data/HabboAvatarAnimations.json
new file mode 100644
index 00000000..d6f6ca59
--- /dev/null
+++ b/src/nitro/avatar/data/HabboAvatarAnimations.json
@@ -0,0 +1,827 @@
+{
+ "animations": [
+ {
+ "id": "Move",
+ "parts": [
+ {
+ "setType": "bd",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wlk"
+ }
+ ]
+ },
+ {
+ "setType": "bds",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wlk"
+ }
+ ]
+ },
+ {
+ "setType": "ss",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wlk"
+ }
+ ]
+ },
+ {
+ "setType": "lg",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wlk"
+ }
+ ]
+ },
+ {
+ "setType": "sh",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wlk"
+ }
+ ]
+ },
+ {
+ "setType": "lh",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wlk"
+ }
+ ]
+ },
+ {
+ "setType": "lhs",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wlk"
+ }
+ ]
+ },
+ {
+ "setType": "ls",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wlk"
+ }
+ ]
+ },
+ {
+ "setType": "lc",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wlk"
+ }
+ ]
+ },
+ {
+ "setType": "rh",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wlk"
+ }
+ ]
+ },
+ {
+ "setType": "rhs",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wlk"
+ }
+ ]
+ },
+ {
+ "setType": "rs",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wlk"
+ }
+ ]
+ },
+ {
+ "setType": "rc",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wlk"
+ }
+ ]
+ },
+ {
+ "setType": "ch",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wlk"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wlk"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "Wave",
+ "parts": [
+ {
+ "setType": "lh",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wav"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wav"
+ }
+ ]
+ },
+ {
+ "setType": "lhs",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wav"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wav"
+ }
+ ]
+ },
+ {
+ "setType": "ls",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wav"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wav"
+ }
+ ]
+ },
+ {
+ "setType": "lc",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wav"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wav"
+ }
+ ]
+ },
+ {
+ "setType": "ch",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wav"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wav"
+ },
+ {
+ "number": 2,
+ "assetPartDefinition": "wav"
+ },
+ {
+ "number": 3,
+ "assetPartDefinition": "wav"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "Talk",
+ "parts": [
+ {
+ "setType": "hd",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "spk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "spk"
+ }
+ ]
+ },
+ {
+ "setType": "fc",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "spk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "spk"
+ }
+ ]
+ },
+ {
+ "setType": "fa",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "spk"
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "spk"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "Sign",
+ "parts": [
+ {
+ "setType": "lh",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "sig"
+ }
+ ]
+ },
+ {
+ "setType": "li",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "sig"
+ }
+ ]
+ },
+ {
+ "setType": "ls",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wav"
+ }
+ ]
+ },
+ {
+ "setType": "lc",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wav"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "Respect",
+ "parts": [
+ {
+ "setType": "lh",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "respect",
+ "repeats": 15
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "respect",
+ "repeats": 15
+ }
+ ]
+ },
+ {
+ "setType": "ls",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wav",
+ "repeats": 15
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wav",
+ "repeats": 15
+ }
+ ]
+ },
+ {
+ "setType": "lc",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "wav",
+ "repeats": 15
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "wav",
+ "repeats": 15
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "Blow",
+ "parts": [
+ {
+ "setType": "rh",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "blw",
+ "repeats": 10
+ },
+ {
+ "number": 1,
+ "assetPartDefinition": "blw",
+ "repeats": 10
+ }
+ ]
+ },
+ {
+ "setType": "rs",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "drk"
+ }
+ ]
+ },
+ {
+ "setType": "rc",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "drk"
+ }
+ ]
+ },
+ {
+ "setType": "ri",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": ""
+ }
+ ]
+ },
+ {
+ "setType": "ey",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "std",
+ "repeats": 10
+ },
+ {
+ "number": 0,
+ "assetPartDefinition": "eyb",
+ "repeats": 10
+ }
+ ]
+ },
+ {
+ "setType": "fc",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "std",
+ "repeats": 10
+ },
+ {
+ "number": 0,
+ "assetPartDefinition": "blw",
+ "repeats": 10
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "Laugh",
+ "parts": [
+ {
+ "setType": "rh",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "blw"
+ }
+ ]
+ },
+ {
+ "setType": "rs",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "drk"
+ }
+ ]
+ },
+ {
+ "setType": "rc",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "drk"
+ }
+ ]
+ },
+ {
+ "setType": "ri",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": ""
+ }
+ ]
+ },
+ {
+ "setType": "ey",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "std",
+ "repeats": 2
+ }
+ ]
+ },
+ {
+ "setType": "fc",
+ "frames": [
+ {
+ "number": 0,
+ "assetPartDefinition": "sml"
+ }
+ ]
+ }
+ ],
+ "offsets": {
+ "frames": [
+ {
+ "id": 0,
+ "directions": [
+ {
+ "id": 0,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 1
+ }
+ ]
+ },
+ {
+ "id": 1,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 1
+ }
+ ]
+ },
+ {
+ "id": 2,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 1
+ }
+ ]
+ },
+ {
+ "id": 3,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 1
+ }
+ ]
+ },
+ {
+ "id": 4,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 1
+ }
+ ]
+ },
+ {
+ "id": 5,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 1
+ }
+ ]
+ },
+ {
+ "id": 6,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 1
+ }
+ ]
+ },
+ {
+ "id": 7,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 1
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": 1,
+ "directions": [
+ {
+ "id": 0,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 0
+ }
+ ]
+ },
+ {
+ "id": 1,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 0
+ }
+ ]
+ },
+ {
+ "id": 2,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 0
+ }
+ ]
+ },
+ {
+ "id": 3,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 0
+ }
+ ]
+ },
+ {
+ "id": 4,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 0
+ }
+ ]
+ },
+ {
+ "id": 5,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 0
+ }
+ ]
+ },
+ {
+ "id": 6,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 0
+ }
+ ]
+ },
+ {
+ "id": 7,
+ "bodyParts": [
+ {
+ "id": "head",
+ "dx": 0,
+ "dy": 0
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/data/HabboAvatarGeometry.json b/src/nitro/avatar/data/HabboAvatarGeometry.json
new file mode 100644
index 00000000..5f19f16b
--- /dev/null
+++ b/src/nitro/avatar/data/HabboAvatarGeometry.json
@@ -0,0 +1,1830 @@
+{
+ "geometry": {
+ "direction": 0,
+ "camera": {
+ "x": 0,
+ "y": 0,
+ "z": 10
+ },
+ "canvases": [
+ {
+ "scale": "h",
+ "geometries": [
+ {
+ "id": "vertical",
+ "width": 90,
+ "height": 130,
+ "dx": 0,
+ "dy": 0
+ },
+ {
+ "id": "sitting",
+ "width": 90,
+ "height": 130,
+ "dx": 0,
+ "dy": 0
+ },
+ {
+ "id": "horizontal",
+ "width": 128,
+ "height": 80,
+ "dx": 30,
+ "dy": 0
+ },
+ {
+ "id": "swhorizontal",
+ "width": 192,
+ "height": 120,
+ "dx": 0,
+ "dy": -40
+ }
+ ]
+ },
+ {
+ "scale": "sh",
+ "geometries": [
+ {
+ "id": "vertical",
+ "width": 45,
+ "height": 72,
+ "dx": 0,
+ "dy": 0
+ },
+ {
+ "id": "sitting",
+ "width": 45,
+ "height": 72,
+ "dx": 0,
+ "dy": 0
+ },
+ {
+ "id": "horizontal",
+ "width": 64,
+ "height": 50,
+ "dx": 15,
+ "dy": -10
+ },
+ {
+ "id": "swhorizontal",
+ "width": 96,
+ "height": 70,
+ "dx": 0,
+ "dy": -20
+ },
+ {
+ "id": "swim",
+ "width": 64,
+ "height": 70,
+ "dx": 25,
+ "dy": 10
+ }
+ ]
+ }
+ ],
+ "avatarSets": [
+ {
+ "id": "full",
+ "avatarSets": [
+ {
+ "id": "body",
+ "main": true,
+ "bodyParts": [
+ {
+ "id": "top"
+ },
+ {
+ "id": "bottom"
+ },
+ {
+ "id": "behind"
+ },
+ {
+ "id": "torso"
+ },
+ {
+ "id": "leftitem"
+ },
+ {
+ "id": "rightitem"
+ },
+ {
+ "id": "leftarm"
+ },
+ {
+ "id": "rightarm"
+ }
+ ]
+ },
+ {
+ "id": "head",
+ "bodyParts": [
+ {
+ "id": "head"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "types": [
+ {
+ "id": "vertical",
+ "bodyParts": [
+ {
+ "id": "top",
+ "x": 0,
+ "y": 0,
+ "z": 0.0,
+ "radius": 2.0
+ },
+ {
+ "id": "bottom",
+ "x": 0,
+ "y": 0,
+ "z": 0.0,
+ "radius": 0.001
+ },
+ {
+ "id": "behind",
+ "x": 0,
+ "y": 0,
+ "z": 0.2,
+ "radius": 0.3
+ },
+ {
+ "id": "torso",
+ "x": 0,
+ "y": 0,
+ "z": 0.0,
+ "radius": 0.4,
+ "items": [
+ {
+ "id": "bd",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "bds",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "ch",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.04,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "sh",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "lg",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.03,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ss",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.04,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "cp",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.045,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "wa",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.05,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "cc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.06,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ca",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.07,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "leftitem",
+ "x": 0,
+ "y": 0,
+ "z": -0.29,
+ "radius": 0.3,
+ "items": [
+ {
+ "id": "li",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "rightitem",
+ "x": 0,
+ "y": 0,
+ "z": -0.29,
+ "radius": 0.3,
+ "items": [
+ {
+ "id": "ri",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "leftarm",
+ "x": -1,
+ "y": 0,
+ "z": -0.51,
+ "radius": 0.5,
+ "items": [
+ {
+ "id": "lh",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "lhs",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ls",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "lc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.025,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "rightarm",
+ "x": 1,
+ "y": 0,
+ "z": -0.51,
+ "radius": 0.5,
+ "items": [
+ {
+ "id": "rh",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "rhs",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "rs",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "rc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.025,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "head",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.5,
+ "items": [
+ {
+ "id": "hd",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "fc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ey",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.03,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "hr",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.04,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "hrb",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.05,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "fa",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.06,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ea",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.07,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ha",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.08,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "he",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.09,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "sitting",
+ "bodyParts": [
+ {
+ "id": "top",
+ "x": 0,
+ "y": 0,
+ "z": 0.0,
+ "radius": 2.0
+ },
+ {
+ "id": "bottom",
+ "x": 0,
+ "y": 0,
+ "z": 0.0,
+ "radius": 0.001
+ },
+ {
+ "id": "behind",
+ "x": 0,
+ "y": 0,
+ "z": 0.2,
+ "radius": 0.3
+ },
+ {
+ "id": "torso",
+ "x": 0,
+ "y": 0,
+ "z": 0.0,
+ "radius": 0.4,
+ "items": [
+ {
+ "id": "bd",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "bds",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "ch",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.03,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "sh",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.04,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "lg",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ss",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.04,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "cp",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.045,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "wa",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.05,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "cc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.06,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ca",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.07,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "leftitem",
+ "x": 0,
+ "y": 0,
+ "z": -0.29,
+ "radius": 0.3,
+ "items": [
+ {
+ "id": "li",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "rightitem",
+ "x": 0,
+ "y": 0,
+ "z": -0.29,
+ "radius": 0.3,
+ "items": [
+ {
+ "id": "ri",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "leftarm",
+ "x": -1,
+ "y": 0,
+ "z": -0.51,
+ "radius": 0.5,
+ "items": [
+ {
+ "id": "lh",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "lhs",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ls",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "lc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.025,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "rightarm",
+ "x": 1,
+ "y": 0,
+ "z": -0.51,
+ "radius": 0.5,
+ "items": [
+ {
+ "id": "rh",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "rhs",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "rs",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "rc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.025,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "head",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.5,
+ "items": [
+ {
+ "id": "hd",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "fc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ey",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.03,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "hr",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.04,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "hrb",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.05,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "fa",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.06,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ea",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.07,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ha",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.08,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "he",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.09,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "horizontal",
+ "bodyParts": [
+ {
+ "id": "torso",
+ "x": 0,
+ "y": 0,
+ "z": 0.0,
+ "radius": 0.4,
+ "items": [
+ {
+ "id": "bd",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "bds",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "ch",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "cp",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.025,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "sh",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.04,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "lg",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.03,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ss",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.03,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "wa",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.05,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "cc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.06,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ca",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.07,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "leftitem",
+ "x": 0,
+ "y": 0,
+ "z": -0.29,
+ "radius": 0.3,
+ "items": [
+ {
+ "id": "li",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "rightitem",
+ "x": 0,
+ "y": 0,
+ "z": -0.29,
+ "radius": 0.3,
+ "items": [
+ {
+ "id": "ri",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "leftarm",
+ "x": -1,
+ "y": 0,
+ "z": -0.51,
+ "radius": 0.6,
+ "items": [
+ {
+ "id": "lh",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "lhs",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ls",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "lc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.025,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "rightarm",
+ "x": 1,
+ "y": 0,
+ "z": -0.51,
+ "radius": 0.6,
+ "items": [
+ {
+ "id": "rh",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "rhs",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "rs",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "rc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.025,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "head",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.5,
+ "items": [
+ {
+ "id": "hd",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "fc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ey",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.03,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "hr",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.04,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "hrb",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.05,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "fa",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.06,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ea",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.07,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ha",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.08,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "he",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.09,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "swhorizontal",
+ "bodyParts": [
+ {
+ "id": "torso",
+ "x": 0,
+ "y": 0,
+ "z": 0.0,
+ "radius": 0.4,
+ "items": [
+ {
+ "id": "bd",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "bds",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "ch",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "cp",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.025,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "sh",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.04,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "lg",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.03,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ss",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.03,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "wa",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.05,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "cc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.06,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ca",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.07,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "leftitem",
+ "x": 0,
+ "y": 0,
+ "z": -0.29,
+ "radius": 0.3,
+ "items": [
+ {
+ "id": "li",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "rightitem",
+ "x": 0,
+ "y": 0,
+ "z": -0.29,
+ "radius": 0.3,
+ "items": [
+ {
+ "id": "ri",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "leftarm",
+ "x": -1,
+ "y": 0,
+ "z": -0.51,
+ "radius": 0.6,
+ "items": [
+ {
+ "id": "lh",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "lhs",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ls",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "lc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.025,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "rightarm",
+ "x": 1,
+ "y": 0,
+ "z": -0.51,
+ "radius": 0.6,
+ "items": [
+ {
+ "id": "rh",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "rhs",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "rs",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "rc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.025,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "head",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.5,
+ "items": [
+ {
+ "id": "hd",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "fc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ey",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.03,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "hr",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.04,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "hrb",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.05,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "fa",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.06,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ea",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.07,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ha",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.08,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "he",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.09,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "swim",
+ "bodyParts": [
+ {
+ "id": "torso",
+ "x": 0,
+ "y": 0,
+ "z": 0.0,
+ "radius": 0.4,
+ "items": [
+ {
+ "id": "bds",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "ss",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.03,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ },
+ {
+ "id": "head",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.5,
+ "items": [
+ {
+ "id": "hd",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.01,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "fc",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.02,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ey",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.03,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "hr",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.04,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "hrb",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.05,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": true
+ },
+ {
+ "id": "fa",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.06,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ea",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.07,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "ha",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.08,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ },
+ {
+ "id": "he",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "radius": 0.09,
+ "nx": 0,
+ "ny": 0,
+ "nz": -1,
+ "double": false
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/data/HabboAvatarPartSets.json b/src/nitro/avatar/data/HabboAvatarPartSets.json
new file mode 100644
index 00000000..eba04fa2
--- /dev/null
+++ b/src/nitro/avatar/data/HabboAvatarPartSets.json
@@ -0,0 +1,418 @@
+{
+ "partSets": {
+ "partSet": [
+ {
+ "setType": "ri",
+ "flippedSetType": "ri"
+ },
+ {
+ "setType": "ri",
+ "flippedSetType": "ri"
+ },
+ {
+ "setType": "rh",
+ "flippedSetType": "lh"
+ },
+ {
+ "setType": "rhs",
+ "flippedSetType": "lhs"
+ },
+ {
+ "setType": "rs",
+ "swim": "0",
+ "flippedSetType": "ls"
+ },
+ {
+ "setType": "rc",
+ "flippedSetType": "lc"
+ },
+ {
+ "setType": "bd"
+ },
+ {
+ "setType": "bds"
+ },
+ {
+ "setType": "ss"
+ },
+ {
+ "setType": "sh"
+ },
+ {
+ "setType": "lg"
+ },
+ {
+ "setType": "ch"
+ },
+ {
+ "setType": "cp"
+ },
+ {
+ "setType": "cc"
+ },
+ {
+ "setType": "hd"
+ },
+ {
+ "setType": "fc"
+ },
+ {
+ "setType": "ey"
+ },
+ {
+ "setType": "hr"
+ },
+ {
+ "setType": "hrb",
+ "removeSetType": "hr"
+ },
+ {
+ "setType": "li",
+ "flippedSetType": "li"
+ },
+ {
+ "setType": "lh",
+ "flippedSetType": "rh"
+ },
+ {
+ "setType": "lhs",
+ "flippedSetType": "rhs"
+ },
+ {
+ "setType": "ls",
+ "flippedSetType": "rs"
+ },
+ {
+ "setType": "lc",
+ "flippedSetType": "rc"
+ },
+ {
+ "setType": "wa"
+ },
+ {
+ "setType": "ea"
+ },
+ {
+ "setType": "ca"
+ },
+ {
+ "setType": "fa"
+ },
+ {
+ "setType": "ha"
+ },
+ {
+ "setType": "he"
+ }
+ ],
+ "activePartSets": [
+ {
+ "id": "figure",
+ "activeParts": [
+ {
+ "setType": "rh"
+ },
+ {
+ "setType": "rh"
+ },
+ {
+ "setType": "rhs"
+ },
+ {
+ "setType": "rs"
+ },
+ {
+ "setType": "rc"
+ },
+ {
+ "setType": "bd"
+ },
+ {
+ "setType": "bds"
+ },
+ {
+ "setType": "ss"
+ },
+ {
+ "setType": "sh"
+ },
+ {
+ "setType": "lg"
+ },
+ {
+ "setType": "ch"
+ },
+ {
+ "setType": "cp"
+ },
+ {
+ "setType": "cc"
+ },
+ {
+ "setType": "wa"
+ },
+ {
+ "setType": "hd"
+ },
+ {
+ "setType": "fc"
+ },
+ {
+ "setType": "ey"
+ },
+ {
+ "setType": "hr"
+ },
+ {
+ "setType": "hrb"
+ },
+ {
+ "setType": "lh"
+ },
+ {
+ "setType": "lhs"
+ },
+ {
+ "setType": "ls"
+ },
+ {
+ "setType": "lc"
+ },
+ {
+ "setType": "ea"
+ },
+ {
+ "setType": "ca"
+ },
+ {
+ "setType": "fa"
+ },
+ {
+ "setType": "ha"
+ },
+ {
+ "setType": "he"
+ }
+ ]
+ },
+ {
+ "id": "head",
+ "activeParts": [
+ {
+ "setType": "hd"
+ },
+ {
+ "setType": "fc"
+ },
+ {
+ "setType": "ey"
+ },
+ {
+ "setType": "hr"
+ },
+ {
+ "setType": "hrb"
+ },
+ {
+ "setType": "ea"
+ },
+ {
+ "setType": "fa"
+ },
+ {
+ "setType": "ha"
+ },
+ {
+ "setType": "he"
+ }
+ ]
+ },
+ {
+ "id": "speak",
+ "activeParts": [
+ {
+ "setType": "hd"
+ },
+ {
+ "setType": "hr"
+ },
+ {
+ "setType": "hrb"
+ },
+ {
+ "setType": "fc"
+ },
+ {
+ "setType": "fa"
+ },
+ {
+ "setType": "ha"
+ }
+ ]
+ },
+ {
+ "id": "gesture",
+ "activeParts": [
+ {
+ "setType": "ey"
+ },
+ {
+ "setType": "fc"
+ }
+ ]
+ },
+ {
+ "id": "eye",
+ "activeParts": [
+ {
+ "setType": "ey"
+ }
+ ]
+ },
+ {
+ "id": "handRight",
+ "activeParts": [
+ {
+ "setType": "rh"
+ },
+ {
+ "setType": "rhs"
+ },
+ {
+ "setType": "rs"
+ },
+ {
+ "setType": "rc"
+ },
+ {
+ "setType": "ri"
+ }
+ ]
+ },
+ {
+ "id": "handRightAndHead",
+ "activeParts": [
+ {
+ "setType": "rh"
+ },
+ {
+ "setType": "rhs"
+ },
+ {
+ "setType": "rs"
+ },
+ {
+ "setType": "rc"
+ },
+ {
+ "setType": "ri"
+ },
+ {
+ "setType": "ey"
+ },
+ {
+ "setType": "fc"
+ },
+ {
+ "setType": "hd"
+ }
+ ]
+ },
+ {
+ "id": "handLeft",
+ "activeParts": [
+ {
+ "setType": "lh"
+ },
+ {
+ "setType": "lhs"
+ },
+ {
+ "setType": "ls"
+ },
+ {
+ "setType": "lc"
+ },
+ {
+ "setType": "li"
+ }
+ ]
+ },
+ {
+ "id": "walk",
+ "activeParts": [
+ {
+ "setType": "bd"
+ },
+ {
+ "setType": "bds"
+ },
+ {
+ "setType": "ss"
+ },
+ {
+ "setType": "lg"
+ },
+ {
+ "setType": "lh"
+ },
+ {
+ "setType": "lhs"
+ },
+ {
+ "setType": "rh"
+ },
+ {
+ "setType": "rhs"
+ },
+ {
+ "setType": "ls"
+ },
+ {
+ "setType": "lc"
+ },
+ {
+ "setType": "rs"
+ },
+ {
+ "setType": "rc"
+ },
+ {
+ "setType": "sh"
+ }
+ ]
+ },
+ {
+ "id": "sit",
+ "activeParts": [
+ {
+ "setType": "bd"
+ },
+ {
+ "setType": "bds"
+ },
+ {
+ "setType": "ss"
+ },
+ {
+ "setType": "lg"
+ },
+ {
+ "setType": "sh"
+ },
+ {
+ "setType": "cc"
+ }
+ ]
+ },
+ {
+ "id": "itemRight",
+ "activeParts": [
+ {
+ "setType": "ri"
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/enum/AvatarAction.ts b/src/nitro/avatar/enum/AvatarAction.ts
new file mode 100644
index 00000000..b53c2a0b
--- /dev/null
+++ b/src/nitro/avatar/enum/AvatarAction.ts
@@ -0,0 +1,127 @@
+export class AvatarAction
+{
+ public static CARRY_OBJECT = 'cri';
+ public static DANCE = 'dance';
+ public static EFFECT = 'fx';
+ public static EXPRESSION = 'expression';
+ public static EXPRESSION_BLOW_A_KISS = 'blow';
+ public static EXPRESSION_CRY = 'cry';
+ public static EXPRESSION_IDLE = 'idle';
+ public static EXPRESSION_LAUGH = 'laugh';
+ public static EXPRESSION_RESPECT = 'respect';
+ public static EXPRESSION_RIDE_JUMP = 'ridejump';
+ public static EXPRESSION_SNOWBOARD_OLLIE = 'sbollie';
+ public static EXPRESSION_SNOWBORD_360 = 'sb360';
+ public static EXPRESSION_WAVE = 'wave';
+ public static GESTURE = 'gest';
+ public static GESTURE_AGGRAVATED = 'agr';
+ public static GESTURE_SAD = 'sad';
+ public static GESTURE_SMILE = 'sml';
+ public static GESTURE_SURPRISED = 'srp';
+ public static GUIDE_STATUS = 'guide';
+ public static MUTED = 'muted';
+ public static PET_GESTURE_BLINK = 'eyb';
+ public static PET_GESTURE_CRAZY = 'crz';
+ public static PET_GESTURE_JOY = 'joy';
+ public static PET_GESTURE_MISERABLE = 'mis';
+ public static PET_GESTURE_PUZZLED = 'puz';
+ public static PET_GESTURE_TONGUE = 'tng';
+ public static PLAYING_GAME = 'playing_game';
+ public static POSTURE = 'posture';
+ public static POSTURE_FLOAT = 'float';
+ public static POSTURE_LAY = 'lay';
+ public static POSTURE_SIT = 'sit';
+ public static POSTURE_STAND = 'std';
+ public static POSTURE_SWIM = 'swim';
+ public static POSTURE_WALK = 'mv';
+ public static SIGN = 'sign';
+ public static SLEEP = 'sleep';
+ public static SNOWWAR_DIE_BACK = 'swdieback';
+ public static SNOWWAR_DIE_FRONT = 'swdiefront';
+ public static SNOWWAR_PICK = 'swpick';
+ public static SNOWWAR_RUN = 'swrun';
+ public static SNOWWAR_THROW = 'swthrow';
+ public static TALK = 'talk';
+ public static BLINK = 'blink';
+ public static TYPING = 'typing';
+ public static USE_OBJECT = 'usei';
+ public static VOTE = 'vote';
+
+ public static GESTURE_MAP = [ '', AvatarAction.GESTURE_SMILE, AvatarAction.GESTURE_AGGRAVATED, AvatarAction.GESTURE_SURPRISED, AvatarAction.GESTURE_SAD, AvatarAction.PET_GESTURE_JOY, AvatarAction.PET_GESTURE_CRAZY, AvatarAction.PET_GESTURE_TONGUE, AvatarAction.PET_GESTURE_BLINK, AvatarAction.PET_GESTURE_MISERABLE, AvatarAction.PET_GESTURE_PUZZLED ];
+
+ public static EXPRESSION_MAP = [ '', AvatarAction.EXPRESSION_WAVE, AvatarAction.EXPRESSION_BLOW_A_KISS, AvatarAction.EXPRESSION_LAUGH, AvatarAction.EXPRESSION_CRY, AvatarAction.EXPRESSION_IDLE, AvatarAction.DANCE, AvatarAction.EXPRESSION_RESPECT, AvatarAction.EXPRESSION_SNOWBOARD_OLLIE, AvatarAction.EXPRESSION_SNOWBORD_360, AvatarAction.EXPRESSION_RIDE_JUMP ];
+
+ public static getExpressionTimeout(expressionId: number): number
+ {
+ expressionId = parseInt(expressionId as any);
+
+ switch(expressionId)
+ {
+ case 1:
+ return 5000;
+ case 2:
+ return 1400;
+ case 3:
+ return 2000;
+ case 4:
+ return 2000;
+ case 5:
+ return 0;
+ case 6:
+ return 700;
+ case 7:
+ return 2000;
+ case 8:
+ return 1500;
+ case 9:
+ return 1500;
+ case 10:
+ return 1500;
+ default:
+ return 0;
+ }
+ }
+
+ public static getExpressionId(expression: string): number
+ {
+ return AvatarAction.EXPRESSION_MAP.indexOf(expression);
+ }
+
+ public static getExpression(expressionId: number): string
+ {
+ if(expressionId > AvatarAction.EXPRESSION_MAP.length) return null;
+
+ return AvatarAction.EXPRESSION_MAP[expressionId];
+ }
+
+ public static getGestureId(gesture: string): number
+ {
+ return AvatarAction.GESTURE_MAP.indexOf(gesture);
+ }
+
+ public static getGesture(gestureId: number): string
+ {
+ if(gestureId > AvatarAction.GESTURE_MAP.length) return null;
+
+ return AvatarAction.GESTURE_MAP[gestureId];
+ }
+
+ public static idToAvatarActionState(id: string): string
+ {
+ if(id === 'Lay') return 'lay';
+ if(id === 'Float') return 'float';
+ if(id === 'Swim') return 'swim';
+ if(id === 'Sit') return 'sit';
+ if(id === 'Respect') return 'respect';
+ if(id === 'Wave') return 'wave';
+ if(id === 'Idle') return 'idle';
+ if(id === 'Dance') return 'dance';
+ if(id === 'UseItem') return 'usei';
+ if(id === 'CarryItem') return 'cri';
+ if(id === 'Talk') return 'talk';
+ if(id === 'Sleep') return 'Sleep';
+ if(id === 'Move') return 'mv';
+
+ return 'std';
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/enum/AvatarDirectionAngle.ts b/src/nitro/avatar/enum/AvatarDirectionAngle.ts
new file mode 100644
index 00000000..cb383d9b
--- /dev/null
+++ b/src/nitro/avatar/enum/AvatarDirectionAngle.ts
@@ -0,0 +1,7 @@
+export class AvatarDirectionAngle
+{
+ public static DIRECTION_TO_ANGLE: number[] = [45, 90, 135, 180, 225, 270, 315, 0]; //_Str_2204
+ public static DIRECTION_IS_FLIPPED: boolean[] = [false, false, false, false, true, true, true, false]; //_Str_1859
+ public static MIN_DIRECTION: number = 0; //_Str_1562
+ public static MAX_DIRECTION: number = 7; //_Str_1257
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/enum/AvatarEditorFigureCategory.ts b/src/nitro/avatar/enum/AvatarEditorFigureCategory.ts
new file mode 100644
index 00000000..4c53f891
--- /dev/null
+++ b/src/nitro/avatar/enum/AvatarEditorFigureCategory.ts
@@ -0,0 +1,10 @@
+export class AvatarEditorFigureCategory
+{
+ public static GENERIC: string = 'hd';
+ public static HEAD: string = 'head';
+ public static TORSO: string = 'torso';
+ public static LEGS: string = 'legs';
+ public static HOTLOOKS: string = 'hotlooks';
+ public static WARDROBE: string = 'wardrobe';
+ public static EFFECTS: string = 'effects';
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/enum/AvatarEditorInstanceId.ts b/src/nitro/avatar/enum/AvatarEditorInstanceId.ts
new file mode 100644
index 00000000..d4c8ace3
--- /dev/null
+++ b/src/nitro/avatar/enum/AvatarEditorInstanceId.ts
@@ -0,0 +1,7 @@
+export class AvatarEditorInstanceId
+{
+ public static _Str_3350: number = 0;
+ public static _Str_7195: number = 1;
+ public static _Str_17909: number = 2;
+ public static _Str_16370: number = 3;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/enum/AvatarEditorSideCategory.ts b/src/nitro/avatar/enum/AvatarEditorSideCategory.ts
new file mode 100644
index 00000000..13e3304d
--- /dev/null
+++ b/src/nitro/avatar/enum/AvatarEditorSideCategory.ts
@@ -0,0 +1,5 @@
+export class AvatarEditorSideCategory
+{
+ public static NOTHING: string = 'nothing';
+ public static WARDROBE: string = 'wardrobe';
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/enum/AvatarFigurePartType.ts b/src/nitro/avatar/enum/AvatarFigurePartType.ts
new file mode 100644
index 00000000..9ac466ed
--- /dev/null
+++ b/src/nitro/avatar/enum/AvatarFigurePartType.ts
@@ -0,0 +1,29 @@
+export class AvatarFigurePartType
+{
+ public static BODY: string = 'bd';
+ public static SHOES: string = 'sh';
+ public static LEGS: string = 'lg';
+ public static CHEST: string = 'ch';
+ public static WAIST_ACCESSORY: string = 'wa';
+ public static CHEST_ACCESSORY: string = 'ca';
+ public static HEAD: string = 'hd';
+ public static HAIR: string = 'hr';
+ public static FACE_ACCESSORY: string = 'fa';
+ public static EYE_ACCESSORY: string = 'ea';
+ public static HEAD_ACCESSORY: string = 'ha';
+ public static HEAD_ACCESSORY_EXTRA: string = 'he';
+ public static COAT_CHEST: string = 'cc';
+ public static CHEST_PRINT: string = 'cp';
+ public static LEFT_HAND_ITEM: string = 'li';
+ public static LEFT_HAND: string = 'lh';
+ public static LEFT_SLEEVE: string = 'ls';
+ public static RIGHT_HAND: string = 'rh';
+ public static RIGHT_SLEEVE: string = 'rs';
+ public static FACE: string = 'fc';
+ public static EYES: string = 'ey';
+ public static HAIR_BIG: string = 'hrb';
+ public static RIGHT_HAND_ITEM: string = 'ri';
+ public static LEFT_COAT_SLEEVE: string = 'lc';
+ public static RIGHT_COAT_SLEEVE: string = 'rc';
+ public static _Str_1286: string[] = [ AvatarFigurePartType.SHOES, AvatarFigurePartType.LEGS, AvatarFigurePartType.CHEST, AvatarFigurePartType.WAIST_ACCESSORY, AvatarFigurePartType.CHEST_ACCESSORY, AvatarFigurePartType.HEAD, AvatarFigurePartType.HAIR, AvatarFigurePartType.FACE_ACCESSORY, AvatarFigurePartType.EYE_ACCESSORY, AvatarFigurePartType.HEAD_ACCESSORY, AvatarFigurePartType.HEAD_ACCESSORY_EXTRA, AvatarFigurePartType.COAT_CHEST, AvatarFigurePartType.CHEST_PRINT ];
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/enum/AvatarGuideStatus.ts b/src/nitro/avatar/enum/AvatarGuideStatus.ts
new file mode 100644
index 00000000..35004c28
--- /dev/null
+++ b/src/nitro/avatar/enum/AvatarGuideStatus.ts
@@ -0,0 +1,6 @@
+export class AvatarGuideStatus
+{
+ public static NONE: number = 0;
+ public static GUIDE: number = 1;
+ public static REQUESTER: number = 2;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/enum/AvatarScaleType.ts b/src/nitro/avatar/enum/AvatarScaleType.ts
new file mode 100644
index 00000000..59334952
--- /dev/null
+++ b/src/nitro/avatar/enum/AvatarScaleType.ts
@@ -0,0 +1,5 @@
+export class AvatarScaleType
+{
+ public static LARGE: string = 'h';
+ public static SMALL: string = 'sh';
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/enum/AvatarSetType.ts b/src/nitro/avatar/enum/AvatarSetType.ts
new file mode 100644
index 00000000..38df0af9
--- /dev/null
+++ b/src/nitro/avatar/enum/AvatarSetType.ts
@@ -0,0 +1,6 @@
+export class AvatarSetType
+{
+ public static FULL: string = 'full';
+ public static HEAD: string = 'head';
+ public static BODY: string = 'body';
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/enum/GeometryType.ts b/src/nitro/avatar/enum/GeometryType.ts
new file mode 100644
index 00000000..30607459
--- /dev/null
+++ b/src/nitro/avatar/enum/GeometryType.ts
@@ -0,0 +1,8 @@
+export class GeometryType
+{
+ public static VERTICAL: string = 'vertical';
+ public static SITTING: string = 'sitting';
+ public static HORIZONTAL: string = 'horizontal';
+ public static SWIM: string = 'swim';
+ public static SNOWWARS_HORIZONTAL: string = 'swhorizontal';
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/enum/RenderMode.ts b/src/nitro/avatar/enum/RenderMode.ts
new file mode 100644
index 00000000..48147d30
--- /dev/null
+++ b/src/nitro/avatar/enum/RenderMode.ts
@@ -0,0 +1,7 @@
+export class RenderMode
+{
+ public static TOOL: string = 'tool';
+ public static COMPONENT: string = 'component';
+ public static ONLINE_TOOL: string = 'online_tool';
+ public static LOCAL_ONLY: string = 'local_only';
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/events/AvatarRenderEffectLibraryEvent.ts b/src/nitro/avatar/events/AvatarRenderEffectLibraryEvent.ts
new file mode 100644
index 00000000..68041bd9
--- /dev/null
+++ b/src/nitro/avatar/events/AvatarRenderEffectLibraryEvent.ts
@@ -0,0 +1,21 @@
+import { NitroEvent } from '../../../core/events/NitroEvent';
+import { EffectAssetDownloadLibrary } from '../EffectAssetDownloadLibrary';
+
+export class AvatarRenderEffectLibraryEvent extends NitroEvent
+{
+ public static DOWNLOAD_COMPLETE: string = 'ARELE_DOWNLOAD_COMPLETE';
+
+ private _library: EffectAssetDownloadLibrary;
+
+ constructor(type: string, library: EffectAssetDownloadLibrary)
+ {
+ super(type);
+
+ this._library = library;
+ }
+
+ public get library(): EffectAssetDownloadLibrary
+ {
+ return this._library;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/events/AvatarRenderEvent.ts b/src/nitro/avatar/events/AvatarRenderEvent.ts
new file mode 100644
index 00000000..d3292e68
--- /dev/null
+++ b/src/nitro/avatar/events/AvatarRenderEvent.ts
@@ -0,0 +1,4 @@
+export class AvatarRenderEvent
+{
+ public static AVATAR_RENDER_READY: string = 'AVATAR_RENDER_READY';
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/events/AvatarRenderLibraryEvent.ts b/src/nitro/avatar/events/AvatarRenderLibraryEvent.ts
new file mode 100644
index 00000000..caa80d5c
--- /dev/null
+++ b/src/nitro/avatar/events/AvatarRenderLibraryEvent.ts
@@ -0,0 +1,21 @@
+import { NitroEvent } from '../../../core/events/NitroEvent';
+import { AvatarAssetDownloadLibrary } from '../AvatarAssetDownloadLibrary';
+
+export class AvatarRenderLibraryEvent extends NitroEvent
+{
+ public static DOWNLOAD_COMPLETE: string = 'ARLE_DOWNLOAD_COMPLETE';
+
+ private _library: AvatarAssetDownloadLibrary;
+
+ constructor(type: string, library: AvatarAssetDownloadLibrary)
+ {
+ super(type);
+
+ this._library = library;
+ }
+
+ public get library(): AvatarAssetDownloadLibrary
+ {
+ return this._library;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/figuredata/FigureData.ts b/src/nitro/avatar/figuredata/FigureData.ts
new file mode 100644
index 00000000..4586660e
--- /dev/null
+++ b/src/nitro/avatar/figuredata/FigureData.ts
@@ -0,0 +1,311 @@
+import { IAvatarImageListener } from '../IAvatarImageListener';
+import { FigureDataView } from './FigureDataView';
+
+export class FigureData implements IAvatarImageListener
+{
+ public static M: string = 'M';
+ public static F: string = 'F';
+ public static U: string = 'U';
+ public static H: string = 'h';
+ public static STD: string = 'std';
+ public static _Str_2028: string = '0';
+ public static FACE: string = 'hd';
+ public static HR: string = 'hr';
+ public static HA: string = 'ha';
+ public static HE: string = 'he';
+ public static EA: string = 'ea';
+ public static FA: string = 'fa';
+ public static CC: string = 'cc';
+ public static CH: string = 'ch';
+ public static CHEST_ACCESSORIES: string = 'ca';
+ public static CHEST_PRINTS: string = 'cp';
+ public static LG: string = 'lg';
+ public static SH: string = 'sh';
+ public static WA: string = 'wa';
+
+ private _view: FigureDataView;
+ private _data: Map;
+ private _colors: Map;
+ private _gender: string = 'M';
+ private _isDisposed: boolean;
+ private _direction: number = 4;
+ private _avatarEffectType: number = -1;
+
+ constructor()
+ {
+ this._direction = FigureDataView._Str_9887;
+ this._view = new FigureDataView(this);
+ }
+
+ public loadAvatarData(figureString: string, gender: string): void
+ {
+ this._data = new Map();
+ this._colors = new Map();
+ this._gender = gender;
+
+ this.parseFigureString(figureString);
+ this.updateView();
+ }
+
+ public dispose(): void
+ {
+ this._data = null;
+ this._colors = null;
+ this._isDisposed = true;
+
+ if(this._view)
+ {
+ this._view.dispose();
+
+ this._view = null;
+ }
+ }
+
+ public get disposed(): boolean
+ {
+ return this._isDisposed;
+ }
+
+ private parseFigureString(figure: string): void
+ {
+ if(!figure) return;
+
+ const sets = figure.split('.');
+
+ if(!sets || !sets.length) return;
+
+ for(const set of sets)
+ {
+ const parts = set.split('-');
+
+ if(!parts.length) continue;
+
+ const setType = parts[0];
+ const setId = parseInt(parts[1]);
+ const colorIds: number[] = [];
+
+ let offset = 2;
+
+ while(offset < parts.length)
+ {
+ colorIds.push(parseInt(parts[offset]));
+
+ offset++;
+ }
+
+ if(!colorIds.length) colorIds.push(0);
+
+ this.savePartSetId(setType, setId, false);
+ this.savePartSetColourId(setType, colorIds, false);
+ }
+ }
+
+ public getPartSetId(k: string): number
+ {
+ const existing = this._data.get(k);
+
+ if(existing !== undefined) return existing;
+
+ return -1;
+ }
+
+ public getColourIds(k: string): number[]
+ {
+ const existing = this._colors.get(k);
+
+ if(existing !== undefined) return existing;
+
+ return [];
+ // return [this._avatarEditor._Str_24919(k)];
+ }
+
+ public getFigureString(): string
+ {
+ let figureString = '';
+ const setParts: string[] = [];
+
+ for(const [ setType, setId ] of this._data.entries())
+ {
+ const colorIds = this._colors.get(setType);
+
+ let setPart = ((setType + '-') + setId);
+
+ if(colorIds && colorIds.length)
+ {
+ let i = 0;
+
+ while(i < colorIds.length)
+ {
+ setPart = (setPart + ('-' + colorIds[i]));
+
+ i++;
+ }
+ }
+
+ setParts.push(setPart);
+ }
+
+ let i = 0;
+
+ while(i < setParts.length)
+ {
+ figureString = (figureString + setParts[i]);
+
+ if(i < (setParts.length - 1)) figureString = (figureString + '.');
+
+ i++;
+ }
+
+ return figureString;
+ }
+
+ public savePartData(k: string, _arg_2: number, _arg_3: number[], _arg_4: boolean = false): void
+ {
+ this.savePartSetId(k, _arg_2, _arg_4);
+ this.savePartSetColourId(k, _arg_3, _arg_4);
+ }
+
+ private savePartSetId(k: string, _arg_2: number, _arg_3: boolean = true): void
+ {
+ switch(k)
+ {
+ case FigureData.FACE:
+ case FigureData.HR:
+ case FigureData.HA:
+ case FigureData.HE:
+ case FigureData.EA:
+ case FigureData.FA:
+ case FigureData.CH:
+ case FigureData.CC:
+ case FigureData.CHEST_ACCESSORIES:
+ case FigureData.CHEST_PRINTS:
+ case FigureData.LG:
+ case FigureData.SH:
+ case FigureData.WA:
+ if(_arg_2 >= 0)
+ {
+ this._data.set(k, _arg_2);
+ }
+ else
+ {
+ this._data.delete(k);
+ }
+ break;
+ }
+
+ if(_arg_3) this.updateView();
+ }
+
+ public savePartSetColourId(k: string, _arg_2: number[], _arg_3: boolean = true): void
+ {
+ switch(k)
+ {
+ case FigureData.FACE:
+ case FigureData.HR:
+ case FigureData.HA:
+ case FigureData.HE:
+ case FigureData.EA:
+ case FigureData.FA:
+ case FigureData.CH:
+ case FigureData.CC:
+ case FigureData.CHEST_ACCESSORIES:
+ case FigureData.CHEST_PRINTS:
+ case FigureData.LG:
+ case FigureData.SH:
+ case FigureData.WA:
+ this._colors.set(k, _arg_2);
+ break;
+ }
+
+ if(_arg_3) this.updateView();
+ }
+
+ public getFigureStringWithFace(k: number, override = true): string
+ {
+ let figureString = '';
+
+ const setTypes: string[] = [ FigureData.FACE ];
+ const figureSets: string[] = [];
+
+ for(const setType of setTypes)
+ {
+ const colors = this._colors.get(setType);
+
+ if(colors === undefined) continue;
+
+ let setId = this._data.get(setType);
+
+ if((setType === FigureData.FACE) && override) setId = k;
+
+ let figureSet = ((setType + '-') + setId);
+
+ if(setId >= 0)
+ {
+ let i = 0;
+
+ while(i < colors.length)
+ {
+ figureSet = (figureSet + ('-' + colors[i]));
+
+ i++;
+ }
+ }
+
+ figureSets.push(figureSet);
+ }
+
+ let i = 0;
+
+ while(i < figureSets.length)
+ {
+ figureString = (figureString + figureSets[i]);
+
+ if(i < (figureSets.length - 1)) figureString = (figureString + '.');
+
+ i++;
+ }
+
+ return figureString;
+ }
+
+ public updateView(): void
+ {
+ this._view.update(this.getFigureString(), this._avatarEffectType, this._direction);
+ }
+
+ public get view(): FigureDataView
+ {
+ return this._view;
+ }
+
+ public get gender(): string
+ {
+ return this._gender;
+ }
+
+ public resetFigure(k: string): void
+ {
+ this.updateView();
+ }
+
+ public set avatarEffectType(k: number)
+ {
+ this._avatarEffectType = k;
+ }
+
+ public get avatarEffectType(): number
+ {
+ return this._avatarEffectType;
+ }
+
+ public get direction(): number
+ {
+ return this._direction;
+ }
+
+ public set direction(k: number)
+ {
+ this._direction = k;
+ this.updateView();
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/figuredata/FigureDataView.ts b/src/nitro/avatar/figuredata/FigureDataView.ts
new file mode 100644
index 00000000..6d794f65
--- /dev/null
+++ b/src/nitro/avatar/figuredata/FigureDataView.ts
@@ -0,0 +1,43 @@
+import { IAvatarImageListener } from '../IAvatarImageListener';
+import { FigureData } from './FigureData';
+
+export class FigureDataView implements IAvatarImageListener
+{
+ public static _Str_9887: number = 4;
+
+ private _model: FigureData;
+ private _figureString: string;
+ private _isDisposed: boolean;
+
+ constructor(k: FigureData)
+ {
+ this._model = k;
+ this._figureString = null;
+ this._isDisposed = false;
+ }
+
+ public dispose(): void
+ {
+ this._isDisposed = true;
+ }
+
+ public update(k: string, effectId: number = 0, direction: number = 4): void
+ {
+ this._figureString = k;
+ }
+
+ public resetFigure(k: string): void
+ {
+ if(k !== this._figureString) return;
+ }
+
+ public get disposed(): boolean
+ {
+ return this._isDisposed;
+ }
+
+ public get figureString(): string
+ {
+ return this._figureString;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/geometry/AvatarModelGeometry.ts b/src/nitro/avatar/geometry/AvatarModelGeometry.ts
new file mode 100644
index 00000000..621209c5
--- /dev/null
+++ b/src/nitro/avatar/geometry/AvatarModelGeometry.ts
@@ -0,0 +1,287 @@
+import { IAvatarImage } from '../IAvatarImage';
+import { AvatarCanvas } from '../structure/AvatarCanvas';
+import { AvatarSet } from './AvatarSet';
+import { GeometryBodyPart } from './GeometryBodyPart';
+import { Matrix4x4 } from './Matrix4x4';
+import { Vector3D } from './Vector3D';
+
+export class AvatarModelGeometry
+{
+ private _camera: Vector3D;
+ private _avatarSet: AvatarSet;
+ private _geometryTypes: Map>;
+ private _itemIdToBodyPartMap: Map>;
+ private _transformation: Matrix4x4;
+ private _canvases: Map>;
+
+ constructor(k: any)
+ {
+ this._camera = new Vector3D(0, 0, 10);
+ this._avatarSet = new AvatarSet(k.avatarSets[0]);
+ this._geometryTypes = new Map();
+ this._itemIdToBodyPartMap = new Map();
+ this._transformation = new Matrix4x4();
+ this._canvases = new Map();
+
+ const camera = k.camera;
+
+ if(camera)
+ {
+ this._camera.x = parseFloat(camera.x);
+ this._camera.y = parseFloat(camera.y);
+ this._camera.z = parseFloat(camera.z);
+ }
+
+ if(k.canvases && (k.canvases.length > 0))
+ {
+ for(const canvas of k.canvases)
+ {
+ if(!canvas) continue;
+
+ const scale = canvas.scale;
+ const geometries = new Map();
+
+ if(canvas.geometries && (canvas.geometries.length > 0))
+ {
+ for(const geometry of canvas.geometries)
+ {
+ if(!geometry) continue;
+
+ const avatarCanvas = new AvatarCanvas(geometry, scale);
+
+ geometries.set(avatarCanvas.id, avatarCanvas);
+ }
+ }
+
+ this._canvases.set(scale, geometries);
+ }
+ }
+
+ if(k.types && (k.types.length > 0))
+ {
+ for(const type of k.types)
+ {
+ if(!type) continue;
+
+ const bodyParts: Map = new Map();
+ const itemIds: Map = new Map();
+
+ if(type.bodyParts && (type.bodyParts.length > 0))
+ {
+ for(const bodyPart of type.bodyParts)
+ {
+ if(!bodyPart) continue;
+
+ const geometryBodyPart = new GeometryBodyPart(bodyPart);
+
+ bodyParts.set(geometryBodyPart.id, geometryBodyPart);
+
+ for(const part of geometryBodyPart._Str_1456(null))
+ {
+ itemIds.set(part, geometryBodyPart);
+ }
+ }
+ }
+
+ this._geometryTypes.set(type.id, bodyParts);
+ this._itemIdToBodyPartMap.set(type.id, itemIds);
+ }
+ }
+ }
+
+ public _Str_2101(k: IAvatarImage): void
+ {
+ for(const geometry of this._geometryTypes.values())
+ {
+ if(!geometry) continue;
+
+ for(const part of geometry.values())
+ {
+ if(!part) continue;
+
+ part._Str_2004(k);
+ }
+ }
+ }
+
+ public _Str_1307(k: string): string[]
+ {
+ const avatarSet = this._avatarSet._Str_1498(k);
+
+ if(!avatarSet) return [];
+
+ return avatarSet._Str_755();
+ }
+
+ public _Str_1939(k: string): boolean
+ {
+ const avatarSet = this._avatarSet._Str_1498(k);
+
+ if(!avatarSet) return false;
+
+ return avatarSet._Str_779;
+ }
+
+ public _Str_1664(k: string, _arg_2: string): AvatarCanvas
+ {
+ const canvas = this._canvases.get(k);
+
+ if(!canvas) return null;
+
+ return (canvas.get(_arg_2) || null);
+ }
+
+ private _Str_1342(k: string): boolean
+ {
+ const existing = this._geometryTypes.get(k);
+
+ if(existing) return true;
+
+ return false;
+ }
+
+ private _Str_1332(k: string, _arg_2: string): boolean
+ {
+ if(this._Str_1342(k))
+ {
+ const existing = this._geometryTypes.get(k);
+
+ if(existing && existing.get(_arg_2)) return true;
+ }
+
+ return false;
+ }
+
+ private _Str_2072(k: string): string[]
+ {
+ const parts = this._Str_1280(k);
+
+ const types = [];
+
+ if(parts)
+ {
+ for(const part of parts.values())
+ {
+ if(!part) continue;
+
+ types.push(part.id);
+ }
+ }
+
+ return types;
+ }
+
+ private _Str_1280(k: string): Map
+ {
+ if(this._Str_1342(k)) return this._geometryTypes.get(k);
+
+ return new Map();
+ }
+
+ public _Str_1919(k: string, _arg_2: string): GeometryBodyPart
+ {
+ return (this._Str_1280(k).get(_arg_2) || null);
+ }
+
+ public _Str_1701(k: string, _arg_2: string, _arg_3:IAvatarImage): GeometryBodyPart
+ {
+ const itemIds = this._itemIdToBodyPartMap.get(k);
+
+ if(itemIds)
+ {
+ const part = itemIds.get(_arg_2);
+
+ if(part) return part;
+
+ const parts = this._Str_1280(k);
+
+ if(parts)
+ {
+ for(const part of parts.values())
+ {
+ if(!part) continue;
+
+ if(part._Str_2030(_arg_2, _arg_3)) return part;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private _Str_1787(k: Map, _arg_2: string): GeometryBodyPart[]
+ {
+ const parts = this._Str_1307(_arg_2);
+ const geometryParts = [];
+
+ for(const part of parts)
+ {
+ if(!part) continue;
+
+ const bodyPart = k.get(part);
+
+ if(bodyPart)
+ {
+ geometryParts.push(bodyPart);
+ }
+ }
+
+ return geometryParts;
+ }
+
+ public _Str_2250(k: string, _arg_2: number, _arg_3: string): string[]
+ {
+ if(!_arg_3) return [];
+
+ const geometryParts = this._Str_1280(_arg_3);
+ const parts = this._Str_1787(geometryParts, k);
+ const sets: [ number, GeometryBodyPart ][] = [];
+ const ids: string[] = [];
+
+ this._transformation = Matrix4x4._Str_1560(_arg_2);
+
+ for(const part of parts.values())
+ {
+ if(!part) continue;
+
+ part._Str_1101(this._transformation);
+
+ sets.push([ part._Str_1522(this._camera), part ]);
+ }
+
+ sets.sort((a, b) =>
+ {
+ const partA = a[0];
+ const partB = b[0];
+
+ if(partA < partB) return -1;
+
+ if(partA > partB) return 1;
+
+ return 0;
+ });
+
+ for(const set of sets)
+ {
+ if(!set) continue;
+
+ ids.push(set[1].id);
+ }
+
+ return ids;
+ }
+
+ public _Str_713(k: string, _arg_2: string, _arg_3: number, _arg_4: any[], _arg_5:IAvatarImage): string[]
+ {
+ if(this._Str_1332(k, _arg_2))
+ {
+ const part = this._Str_1280(k).get(_arg_2);
+
+ this._transformation = Matrix4x4._Str_1560(_arg_3);
+
+ return part._Str_713(this._transformation, this._camera, _arg_4, _arg_5);
+ }
+
+ return [];
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/geometry/AvatarSet.ts b/src/nitro/avatar/geometry/AvatarSet.ts
new file mode 100644
index 00000000..f22c2702
--- /dev/null
+++ b/src/nitro/avatar/geometry/AvatarSet.ts
@@ -0,0 +1,92 @@
+export class AvatarSet
+{
+ private _id: string;
+ private _isMain: boolean;
+ private _avatarSets: Map;
+ private _bodyParts: string[];
+ private _allBodyParts: string[];
+
+ constructor(k: any)
+ {
+ this._id = k.id;
+ this._isMain = k.main || false;
+ this._avatarSets = new Map();
+ this._bodyParts = [];
+ this._allBodyParts = [];
+
+ if(k.avatarSets && (k.avatarSets.length > 0))
+ {
+ for(const avatarSet of k.avatarSets)
+ {
+ if(!avatarSet) continue;
+
+ const set = new AvatarSet(avatarSet);
+
+ this._avatarSets.set(set.id, set);
+ }
+ }
+
+ if(k.bodyParts && (k.bodyParts.length > 0))
+ {
+ for(const bodyPart of k.bodyParts)
+ {
+ if(!bodyPart) continue;
+
+ this._bodyParts.push(bodyPart.id);
+ }
+ }
+
+ let bodyParts = this._bodyParts.concat();
+
+ for(const avatarSet of this._avatarSets.values())
+ {
+ if(!avatarSet) continue;
+
+ bodyParts = bodyParts.concat(avatarSet._Str_755());
+ }
+
+ this._allBodyParts = bodyParts;
+ }
+
+ public _Str_1498(k: string): AvatarSet
+ {
+ if(k === this._id) return this;
+
+ for(const avatarSet of this._avatarSets.values())
+ {
+ if(!avatarSet) continue;
+
+ if(!avatarSet._Str_1498(k)) continue;
+
+ return avatarSet;
+ }
+
+ return null;
+ }
+
+ public _Str_755(): string[]
+ {
+ return this._allBodyParts.concat();
+ }
+
+ public get id(): string
+ {
+ return this._id;
+ }
+
+ public get _Str_779(): boolean
+ {
+ if(this._isMain) return true;
+
+ for(const avatarSet of this._avatarSets.values())
+ {
+ if(!avatarSet) continue;
+
+ if(!avatarSet._Str_779) continue;
+
+ return true;
+ }
+
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/geometry/GeometryBodyPart.ts b/src/nitro/avatar/geometry/GeometryBodyPart.ts
new file mode 100644
index 00000000..ef82d5d2
--- /dev/null
+++ b/src/nitro/avatar/geometry/GeometryBodyPart.ts
@@ -0,0 +1,194 @@
+import { IAvatarImage } from '../IAvatarImage';
+import { GeometryItem } from './GeometryItem';
+import { Matrix4x4 } from './Matrix4x4';
+import { Node3D } from './Node3D';
+import { Vector3D } from './Vector3D';
+
+export class GeometryBodyPart extends Node3D
+{
+ private _id: string;
+ private _radius: number;
+ private _parts: Map;
+ private _dynamicParts: Map;
+
+ constructor(k: any)
+ {
+ super(parseFloat(k.x), parseFloat(k.y), parseFloat(k.z));
+
+ this._id = k.id;
+ this._radius = parseFloat(k.radius);
+ this._parts = new Map();
+ this._dynamicParts = new Map();
+
+ if(k.items && (k.items.length > 0))
+ {
+ for(const item of k.items)
+ {
+ if(!item) continue;
+
+ const geometryItem = new GeometryItem(item);
+
+ this._parts.set(geometryItem.id, geometryItem);
+ }
+ }
+ }
+
+ public _Str_1883(k: IAvatarImage): GeometryItem[]
+ {
+ const existing = this._dynamicParts.get(k);
+ const parts: GeometryItem[] = [];
+
+ if(existing)
+ {
+ for(const index in existing)
+ {
+ const item = existing[index];
+
+ if(!item) continue;
+
+ parts.push(item);
+ }
+ }
+
+ return parts;
+ }
+
+ public _Str_1456(k: IAvatarImage): string[]
+ {
+ const ids: string[] = [];
+
+ for(const part of this._parts.values())
+ {
+ if(!part) continue;
+
+ ids.push(part.id);
+ }
+
+ if(k)
+ {
+ const existing = this._dynamicParts.get(k);
+
+ if(existing)
+ {
+ for(const index in existing)
+ {
+ const part = existing[index];
+
+ if(!part) continue;
+
+ ids.push(part.id);
+ }
+ }
+ }
+
+ return ids;
+ }
+
+ public _Str_2004(k: IAvatarImage): boolean
+ {
+ this._dynamicParts.delete(k);
+
+ return true;
+ }
+
+ public _Str_2020(k: any, _arg_2: IAvatarImage): boolean
+ {
+ if(this._Str_2030(k.id, _arg_2)) return false;
+
+ let existing = this._dynamicParts.get(_arg_2);
+
+ if(!existing)
+ {
+ existing = {};
+
+ this._dynamicParts.set(_arg_2, existing);
+ }
+
+ existing[k.id] = new GeometryItem(k, true);
+
+ return true;
+ }
+
+ public _Str_2030(k: string, _arg_2: IAvatarImage): boolean
+ {
+ let existingPart = (this._parts.get(k) || null);
+
+ if(!existingPart && (this._dynamicParts.get(_arg_2) !== undefined))
+ {
+ existingPart = (this._dynamicParts.get(_arg_2)[k] || null);
+ }
+
+ return (existingPart !== null);
+ }
+
+ public _Str_713(k: Matrix4x4, _arg_2: Vector3D, _arg_3: any[], _arg_4: IAvatarImage): string[]
+ {
+ const parts: [ number, GeometryItem ][] = [];
+
+ for(const part of this._parts.values())
+ {
+ if(!part) continue;
+
+ part._Str_1101(k);
+
+ parts.push([ part._Str_1522(_arg_2), part ]);
+ }
+
+ const existingDynamic = this._dynamicParts.get(_arg_4);
+
+ if(existingDynamic)
+ {
+ for(const index in existingDynamic)
+ {
+ const part = existingDynamic[index];
+
+ if(!part) continue;
+
+ part._Str_1101(k);
+
+ parts.push([ part._Str_1522(_arg_2), part ]);
+ }
+ }
+
+ parts.sort((a, b) =>
+ {
+ const partA = a[0];
+ const partB = b[0];
+
+ if(partA < partB) return -1;
+
+ if(partA > partB) return 1;
+
+ return 0;
+ });
+
+ const partIds: string[] = [];
+
+ for(const part of parts)
+ {
+ if(!part) continue;
+
+ partIds.push(part[1].id);
+ }
+
+ return partIds;
+ }
+
+ public _Str_1522(k: Vector3D): number
+ {
+ const _local_2 = Math.abs(((k.z - this._Str_1604.z) - this._radius));
+ const _local_3 = Math.abs(((k.z - this._Str_1604.z) + this._radius));
+
+ return Math.min(_local_2, _local_3);
+ }
+
+ public get id(): string
+ {
+ return this._id;
+ }
+
+ public get radius(): number
+ {
+ return this._radius;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/geometry/GeometryItem.ts b/src/nitro/avatar/geometry/GeometryItem.ts
new file mode 100644
index 00000000..ee2b6e54
--- /dev/null
+++ b/src/nitro/avatar/geometry/GeometryItem.ts
@@ -0,0 +1,55 @@
+import { Node3D } from './Node3D';
+import { Vector3D } from './Vector3D';
+
+export class GeometryItem extends Node3D
+{
+ private _id: string;
+ private _radius: number;
+ private _normal: Vector3D;
+ private _isDoubleSided: boolean;
+ private _isDynamic: boolean;
+
+ constructor(k: any, _arg_2: boolean = false)
+ {
+ super(parseFloat(k.x), parseFloat(k.y), parseFloat(k.z));
+
+ this._id = k.id;
+ this._radius = parseFloat(k.radius);
+ this._normal = new Vector3D(parseFloat(k.nx), parseFloat(k.ny), parseFloat(k.nz));
+ this._isDoubleSided = k.double || false;
+ this._isDynamic = _arg_2;
+ }
+
+ public _Str_1522(k: Vector3D): number
+ {
+ const _local_2 = Math.abs(((k.z - this._Str_1604.z) - this._radius));
+ const _local_3 = Math.abs(((k.z - this._Str_1604.z) + this._radius));
+
+ return Math.min(_local_2, _local_3);
+ }
+
+ public get id(): string
+ {
+ return this._id;
+ }
+
+ public get normal(): Vector3D
+ {
+ return this._normal;
+ }
+
+ public get _Str_2207(): boolean
+ {
+ return this._isDoubleSided;
+ }
+
+ public toString(): string
+ {
+ return ((((this._id + ': ') + this.location) + ' - ') + this._Str_1604);
+ }
+
+ public get _Str_1457(): boolean
+ {
+ return this._isDynamic;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/geometry/Matrix4x4.ts b/src/nitro/avatar/geometry/Matrix4x4.ts
new file mode 100644
index 00000000..c248ea5d
--- /dev/null
+++ b/src/nitro/avatar/geometry/Matrix4x4.ts
@@ -0,0 +1,133 @@
+import { Vector3D } from './Vector3D';
+
+export class Matrix4x4
+{
+ public static IDENTITY:Matrix4x4 = new Matrix4x4(1, 0, 0, 0, 1, 0, 0, 0, 1);
+ private static TOLERANS: number = 1E-18;
+
+ private _data: number[];
+
+ constructor(k: number = 0, _arg_2: number = 0, _arg_3: number = 0, _arg_4: number = 0, _arg_5: number = 0, _arg_6: number = 0, _arg_7: number = 0, _arg_8: number = 0, _arg_9: number = 0)
+ {
+ this._data = [k, _arg_2, _arg_3, _arg_4, _arg_5, _arg_6, _arg_7, _arg_8, _arg_9];
+ }
+
+ public static _Str_1869(k: number): Matrix4x4
+ {
+ const _local_2 = ((k * Math.PI) / 180);
+ const _local_3 = Math.cos(_local_2);
+ const _local_4 = Math.sin(_local_2);
+
+ return new Matrix4x4(1, 0, 0, 0, _local_3, -(_local_4), 0, _local_4, _local_3);
+ }
+
+ public static _Str_1560(k: number): Matrix4x4
+ {
+ const _local_2 = ((k * Math.PI) / 180);
+ const _local_3 = Math.cos(_local_2);
+ const _local_4 = Math.sin(_local_2);
+
+ return new Matrix4x4(_local_3, 0, _local_4, 0, 1, 0, -(_local_4), 0, _local_3);
+ }
+
+ public static _Str_1368(k: number): Matrix4x4
+ {
+ const _local_2 = ((k * Math.PI) / 180);
+ const _local_3 = Math.cos(_local_2);
+ const _local_4 = Math.sin(_local_2);
+
+ return new Matrix4x4(_local_3, -(_local_4), 0, _local_4, _local_3, 0, 0, 0, 1);
+ }
+
+ public identity(): Matrix4x4
+ {
+ this._data = [1, 0, 0, 0, 1, 0, 0, 0, 1];
+
+ return this;
+ }
+
+ public _Str_2186(k: Vector3D): Vector3D
+ {
+ const _local_2 = (((k.x * this._data[0]) + (k.y * this._data[3])) + (k.z * this._data[6]));
+ const _local_3 = (((k.x * this._data[1]) + (k.y * this._data[4])) + (k.z * this._data[7]));
+ const _local_4 = (((k.x * this._data[2]) + (k.y * this._data[5])) + (k.z * this._data[8]));
+
+ return new Vector3D(_local_2, _local_3, _local_4);
+ }
+
+ public _Str_1186(k:Matrix4x4): Matrix4x4
+ {
+ const _local_2 = (((this._data[0] * k.data[0]) + (this._data[1] * k.data[3])) + (this._data[2] * k.data[6]));
+ const _local_3 = (((this._data[0] * k.data[1]) + (this._data[1] * k.data[4])) + (this._data[2] * k.data[7]));
+ const _local_4 = (((this._data[0] * k.data[2]) + (this._data[1] * k.data[5])) + (this._data[2] * k.data[8]));
+ const _local_5 = (((this._data[3] * k.data[0]) + (this._data[4] * k.data[3])) + (this._data[5] * k.data[6]));
+ const _local_6 = (((this._data[3] * k.data[1]) + (this._data[4] * k.data[4])) + (this._data[5] * k.data[7]));
+ const _local_7 = (((this._data[3] * k.data[2]) + (this._data[4] * k.data[5])) + (this._data[5] * k.data[8]));
+ const _local_8 = (((this._data[6] * k.data[0]) + (this._data[7] * k.data[3])) + (this._data[8] * k.data[6]));
+ const _local_9 = (((this._data[6] * k.data[1]) + (this._data[7] * k.data[4])) + (this._data[8] * k.data[7]));
+ const _local_10 = (((this._data[6] * k.data[2]) + (this._data[7] * k.data[5])) + (this._data[8] * k.data[8]));
+
+ return new Matrix4x4(_local_2, _local_3, _local_4, _local_5, _local_6, _local_7, _local_8, _local_9, _local_10);
+ }
+
+ public _Str_1157(k: number): void
+ {
+ let index = 0;
+
+ while(index < this._data.length)
+ {
+ this._data[index] = (this._data[index] * k);
+
+ index++;
+ }
+ }
+
+ public _Str_1089(k: number): Matrix4x4
+ {
+ const _local_2 = ((k * Math.PI) / 180);
+ const _local_3 = Math.cos(_local_2);
+ const _local_4 = Math.sin(_local_2);
+ const _local_5 = new Matrix4x4(1, 0, 0, 0, _local_3, -(_local_4), 0, _local_4, _local_3);
+
+ return _local_5._Str_1186(this);
+ }
+
+ public _Str_2123(k: number): Matrix4x4
+ {
+ const _local_2 = ((k * Math.PI) / 180);
+ const _local_3 = Math.cos(_local_2);
+ const _local_4 = Math.sin(_local_2);
+ const _local_5 = new Matrix4x4(_local_3, 0, _local_4, 0, 1, 0, -(_local_4), 0, _local_3);
+
+ return _local_5._Str_1186(this);
+ }
+
+ public _Str_2232(k: number): Matrix4x4
+ {
+ const _local_2 = ((k * Math.PI) / 180);
+ const _local_3 = Math.cos(_local_2);
+ const _local_4 = Math.sin(_local_2);
+ const _local_5 = new Matrix4x4(_local_3, -(_local_4), 0, _local_4, _local_3, 0, 0, 0, 1);
+
+ return _local_5._Str_1186(this);
+ }
+
+ public skew(): void
+ {
+ }
+
+ public _Str_1779(): Matrix4x4
+ {
+ return new Matrix4x4(this._data[0], this._data[3], this._data[6], this._data[1], this._data[4], this._data[7], this._data[2], this._data[5], this._data[8]);
+ }
+
+ public _Str_1451(k: Matrix4x4): boolean
+ {
+ return false;
+ }
+
+ public get data(): number[]
+ {
+ return this._data;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/geometry/Node3D.ts b/src/nitro/avatar/geometry/Node3D.ts
new file mode 100644
index 00000000..1f52e5ac
--- /dev/null
+++ b/src/nitro/avatar/geometry/Node3D.ts
@@ -0,0 +1,33 @@
+import { Matrix4x4 } from './Matrix4x4';
+import { Vector3D } from './Vector3D';
+
+export class Node3D
+{
+ private _location: Vector3D;
+ private _transformedLocation: Vector3D;
+ private _needsTransformation: boolean;
+
+ constructor(k: number, _arg_2: number, _arg_3: number)
+ {
+ this._location = new Vector3D(k, _arg_2, _arg_3);
+ this._transformedLocation = new Vector3D();
+ this._needsTransformation = false;
+
+ if(((!(k == 0)) || (!(_arg_2 == 0))) || (!(_arg_3 == 0))) this._needsTransformation = true;
+ }
+
+ public get location(): Vector3D
+ {
+ return this._location;
+ }
+
+ public get _Str_1604(): Vector3D
+ {
+ return this._transformedLocation;
+ }
+
+ public _Str_1101(k: Matrix4x4): void
+ {
+ if(this._needsTransformation) this._transformedLocation = k._Str_2186(this._location);
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/geometry/Vector3D.ts b/src/nitro/avatar/geometry/Vector3D.ts
new file mode 100644
index 00000000..1f9cfb39
--- /dev/null
+++ b/src/nitro/avatar/geometry/Vector3D.ts
@@ -0,0 +1,113 @@
+export class Vector3D
+{
+ private _x: number;
+ private _y: number;
+ private _z: number;
+
+ constructor(k: number = 0, _arg_2: number = 0, _arg_3: number = 0)
+ {
+ this._x = k;
+ this._y = _arg_2;
+ this._z = _arg_3;
+ }
+
+ public static _Str_2224(k: Vector3D, _arg_2: Vector3D): number
+ {
+ return ((k.x * _arg_2.x) + (k.y * _arg_2.y)) + (k.z * _arg_2.z);
+ }
+
+ public static _Str_1645(k: Vector3D, _arg_2: Vector3D): Vector3D
+ {
+ const _local_3 = new Vector3D();
+
+ _local_3.x = ((k.y * _arg_2.z) - (k.z * _arg_2.y));
+ _local_3.y = ((k.z * _arg_2.x) - (k.x * _arg_2.z));
+ _local_3.z = ((k.x * _arg_2.y) - (k.y * _arg_2.x));
+
+ return _local_3;
+ }
+
+ public static subtract(k: Vector3D, _arg_2: Vector3D): Vector3D
+ {
+ return new Vector3D((k.x - _arg_2.x), (k.y - _arg_2.y), (k.z - _arg_2.z));
+ }
+
+ public _Str_2224(k: Vector3D): number
+ {
+ return ((this._x * k.x) + (this._y * k.y)) + (this._z * k.z);
+ }
+
+ public _Str_1645(k: Vector3D): Vector3D
+ {
+ const _local_2 = new Vector3D();
+
+ _local_2.x = ((this._y * k.z) - (this._z * k.y));
+ _local_2.y = ((this._z * k.x) - (this._x * k.z));
+ _local_2.z = ((this._x * k.y) - (this._y * k.x));
+
+ return _local_2;
+ }
+
+ public subtract(k: Vector3D): void
+ {
+ this._x = (this._x - k.x);
+ this._y = (this._y - k.y);
+ this._z = (this._z - k.z);
+ }
+
+ public add(k: Vector3D): void
+ {
+ this._x = (this._x + k.x);
+ this._y = (this._y + k.y);
+ this._z = (this._z + k.z);
+ }
+
+ public normalize(): void
+ {
+ const k = (1 / this.length());
+
+ this._x = (this._x * k);
+ this._y = (this._y * k);
+ this._z = (this._z * k);
+ }
+
+ public length(): number
+ {
+ return Math.sqrt((((this._x * this._x) + (this._y * this._y)) + (this._z * this._z)));
+ }
+
+ public toString(): string
+ {
+ return (((((('Vector3D: (' + this._x) + ',') + this._y) + ',') + this._z) + ')');
+ }
+
+ public get x(): number
+ {
+ return this._x;
+ }
+
+ public set x(k: number)
+ {
+ this._x = k;
+ }
+
+ public get y(): number
+ {
+ return this._y;
+ }
+
+ public set y(k: number)
+ {
+ this._y = k;
+ }
+
+ public get z(): number
+ {
+ return this._z;
+ }
+
+ public set z(k: number)
+ {
+ this._z = k;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/pets/PetCustomPart.ts b/src/nitro/avatar/pets/PetCustomPart.ts
new file mode 100644
index 00000000..0c374016
--- /dev/null
+++ b/src/nitro/avatar/pets/PetCustomPart.ts
@@ -0,0 +1,43 @@
+export class PetCustomPart
+{
+ private _layerId: number;
+ private _partId: number;
+ private _paletteId: number;
+
+ constructor(layerId: number, partId: number, paletteId: number)
+ {
+ this._layerId = layerId;
+ this._partId = partId;
+ this._paletteId = paletteId;
+ }
+
+ public get layerId(): number
+ {
+ return this._layerId;
+ }
+
+ public set layerId(layerId: number)
+ {
+ this._layerId = layerId;
+ }
+
+ public get partId(): number
+ {
+ return this._partId;
+ }
+
+ public set partId(partId: number)
+ {
+ this._partId = partId;
+ }
+
+ public get paletteId(): number
+ {
+ return this._paletteId;
+ }
+
+ public set paletteId(paletteId: number)
+ {
+ this._paletteId = paletteId;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/pets/PetFigureData.ts b/src/nitro/avatar/pets/PetFigureData.ts
new file mode 100644
index 00000000..57a0f102
--- /dev/null
+++ b/src/nitro/avatar/pets/PetFigureData.ts
@@ -0,0 +1,228 @@
+import { PetCustomPart } from './PetCustomPart';
+
+export class PetFigureData
+{
+ private _typeId: number;
+ private _paletteId: number;
+ private _color: number;
+ private _headOnly: boolean;
+
+ private _customParts: PetCustomPart[];
+ private _customLayerIds: number[];
+ private _customPartIds: number[];
+ private _customPaletteIds: number[];
+
+ constructor(k: string)
+ {
+ this._typeId = this.getTypeId(k);
+ this._paletteId = this.getPaletteId(k);
+ this._color = this.getColor(k);
+ this._headOnly = this.getHeadOnly(k);
+
+ const _local_2 = this.getCustomData(k);
+
+ this._customLayerIds = this.getCustomLayerIds(_local_2);
+ this._customPartIds = this.getCustomPartIds(_local_2);
+ this._customPaletteIds = this.getCustomPaletteIds(_local_2);
+ this._customParts = [];
+
+ let i = 0;
+
+ while(i < this._customLayerIds.length)
+ {
+ this._customParts.push(new PetCustomPart(this._customLayerIds[i], this._customPartIds[i], this._customPaletteIds[i]));
+
+ i++;
+ }
+ }
+
+ public get typeId(): number
+ {
+ return this._typeId;
+ }
+
+ public get paletteId(): number
+ {
+ return this._paletteId;
+ }
+
+ public get color(): number
+ {
+ return this._color;
+ }
+
+ public get customLayerIds(): number[]
+ {
+ return this._customLayerIds;
+ }
+
+ public get customPartIds(): number[]
+ {
+ return this._customPartIds;
+ }
+
+ public get customPaletteIds(): number[]
+ {
+ return this._customPaletteIds;
+ }
+
+ public get customParts(): PetCustomPart[]
+ {
+ return this._customParts;
+ }
+
+ public getCustomPart(k: number): PetCustomPart
+ {
+ if(this._customParts)
+ {
+ for(const _local_2 of this._customParts)
+ {
+ if(_local_2.layerId === k) return _local_2;
+ }
+ }
+
+ return null;
+ }
+
+ public get hasCustomParts(): boolean
+ {
+ return (!(this._customLayerIds == null)) && (this._customLayerIds.length > 0);
+ }
+
+ public get headOnly(): boolean
+ {
+ return this._headOnly;
+ }
+
+ public get figureString(): string
+ {
+ let figure = ((((this.typeId + ' ') + this.paletteId) + ' ') + this.color.toString(16));
+
+ figure = (figure + (' ' + this.customParts.length));
+
+ for(const _local_2 of this.customParts)
+ {
+ figure = (figure + (((((' ' + _local_2.layerId) + ' ') + _local_2.partId) + ' ') + _local_2.paletteId));
+ }
+
+ return figure;
+ }
+
+ private getCustomData(k: string): string[]
+ {
+ let _local_2: string[] = [];
+
+ if(k)
+ {
+ const _local_3 = k.split(' ');
+ const _local_4 = ((this._headOnly) ? 1 : 0);
+ const _local_5 = (4 + _local_4);
+
+ if(_local_3.length > _local_5)
+ {
+ const _local_6 = (3 + _local_4);
+ const _local_7 = parseInt(_local_3[_local_6]);
+
+ _local_2 = _local_3.slice(_local_5, (_local_5 + (_local_7 * 3)));
+ }
+ }
+
+ return _local_2;
+ }
+
+ private getCustomLayerIds(data: string[]): number[]
+ {
+ const layerIds: number[] = [];
+
+ let i = 0;
+
+ while(i < data.length)
+ {
+ layerIds.push(parseInt(data[(i + 0)]));
+
+ i = (i + 3);
+ }
+
+ return layerIds;
+ }
+
+ private getCustomPartIds(data: string[]): number[]
+ {
+ const partIds: number[] = [];
+
+ let i = 0;
+
+ while(i < data.length)
+ {
+ partIds.push(parseInt(data[(i + 1)]));
+
+ i = (i + 3);
+ }
+
+ return partIds;
+ }
+
+ private getCustomPaletteIds(data: string[]): number[]
+ {
+ const paletteIds: number[] = [];
+
+ let i = 0;
+
+ while(i < data.length)
+ {
+ paletteIds.push(parseInt(data[(i + 2)]));
+
+ i = (i + 3);
+ }
+
+ return paletteIds;
+ }
+
+ private getTypeId(data: string): number
+ {
+ if(data)
+ {
+ const parts = data.split(' ');
+
+ if(parts.length >= 1) return parseInt(parts[0]);
+ }
+
+ return 0;
+ }
+
+ private getPaletteId(data: string): number
+ {
+ if(data)
+ {
+ const parts = data.split(' ');
+
+ if(parts.length >= 2) return parseInt(parts[1]);
+ }
+
+ return 0;
+ }
+
+ private getColor(data: string): number
+ {
+ if(data)
+ {
+ const parts = data.split(' ');
+
+ if(parts.length >= 3) return parseInt(parts[2], 16);
+ }
+
+ return 0xFFFFFF;
+ }
+
+ private getHeadOnly(data: string): boolean
+ {
+ if(data)
+ {
+ const parts = data.split(' ');
+
+ if(parts.length >= 4) return parts[3] === 'head';
+ }
+
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/pets/PetType.ts b/src/nitro/avatar/pets/PetType.ts
new file mode 100644
index 00000000..cca7168d
--- /dev/null
+++ b/src/nitro/avatar/pets/PetType.ts
@@ -0,0 +1,38 @@
+export class PetType
+{
+ public static DOG: number = 0;
+ public static CAT: number = 1;
+ public static CROCODILE: number = 2;
+ public static TERRIER: number = 3;
+ public static BEAR: number = 4;
+ public static PIG: number = 5;
+ public static LION: number = 6;
+ public static RHINO: number = 7;
+ public static SPIDER: number = 8;
+ public static TURTLE: number = 9;
+ public static CHICKEN: number = 10;
+ public static FROG: number = 11;
+ public static DRAGON: number = 12;
+ public static MONSTER: number = 13;
+ public static MONKEY: number = 14;
+ public static HORSE: number = 15;
+ public static MONSTERPLANT: number = 16;
+ public static BUNNY: number = 17;
+ public static BUNNYEVIL: number = 18;
+ public static BUNNYDEPRESSED: number = 19;
+ public static BUNNYLOVE: number = 20;
+ public static PIGEONGOOD: number = 21;
+ public static PIGEONEVIL: number = 22;
+ public static DEMONMONKEY: number = 23;
+ public static BABYBEAR: number = 24;
+ public static BABYTERRIER: number = 25;
+ public static GNOME: number = 26;
+ public static LEPRECHAUN: number = 27;
+ public static KITTENBABY: number = 28;
+ public static PUPPYBABY: number = 29;
+ public static PIGLETNBABY: number = 30;
+ public static HALOOMPA: number = 31;
+ public static FOOLS: number = 32;
+ public static PTEROSAUR: number = 33;
+ public static VELOCIRAPTOR: number = 34;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/AnimationData.ts b/src/nitro/avatar/structure/AnimationData.ts
new file mode 100644
index 00000000..7e714b34
--- /dev/null
+++ b/src/nitro/avatar/structure/AnimationData.ts
@@ -0,0 +1,58 @@
+import { IActionDefinition } from '../actions/IActionDefinition';
+import { AnimationAction } from './animation/AnimationAction';
+import { IFigureSetData } from './IFigureSetData';
+
+export class AnimationData implements IFigureSetData
+{
+ private _actions: Map;
+
+ constructor()
+ {
+ this._actions = new Map();
+ }
+
+ public parse(data: any): boolean
+ {
+ if(data && (data.length > 0))
+ {
+ for(const animation of data)
+ {
+ if(!animation) continue;
+
+ const newAnimation = new AnimationAction(animation);
+
+ this._actions.set(newAnimation.id, newAnimation);
+ }
+ }
+
+ return true;
+ }
+
+ public _Str_1017(k: any): boolean
+ {
+ for(const _local_2 of k.action)
+ {
+ this._actions.set(_local_2.id, new AnimationAction(_local_2));
+ }
+
+ return true;
+ }
+
+ public _Str_2244(action: IActionDefinition): AnimationAction
+ {
+ const existing = this._actions.get(action.id);
+
+ if(!existing) return null;
+
+ return existing;
+ }
+
+ public _Str_1408(k: IActionDefinition): number
+ {
+ const animationAction = this._Str_2244(k);
+
+ if(!animationAction) return 0;
+
+ return animationAction._Str_2185;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/AvatarCanvas.ts b/src/nitro/avatar/structure/AvatarCanvas.ts
new file mode 100644
index 00000000..b47a79e9
--- /dev/null
+++ b/src/nitro/avatar/structure/AvatarCanvas.ts
@@ -0,0 +1,47 @@
+import { Point } from 'pixi.js';
+import { AvatarScaleType } from '../enum/AvatarScaleType';
+
+export class AvatarCanvas
+{
+ private _id: string;
+ private _width: number;
+ private _height: number;
+ private _offset: Point;
+ private _regPoint: Point;
+
+ constructor(k: any, _arg_2: string)
+ {
+ this._id = k.id;
+ this._width = k.width;
+ this._height = k.height;
+ this._offset = new Point(k.dx, k.dy);
+
+ if(_arg_2 == AvatarScaleType.LARGE) this._regPoint = new Point(((this._width - 64) / 2), 0);
+ else this._regPoint = new Point(((this._width - 32) / 2), 0);
+ }
+
+ public get width(): number
+ {
+ return this._width;
+ }
+
+ public get height(): number
+ {
+ return this._height;
+ }
+
+ public get offset(): Point
+ {
+ return this._offset;
+ }
+
+ public get id(): string
+ {
+ return this._id;
+ }
+
+ public get _Str_1076(): Point
+ {
+ return this._regPoint;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/AvatarStructureDownload.ts b/src/nitro/avatar/structure/AvatarStructureDownload.ts
new file mode 100644
index 00000000..215c0597
--- /dev/null
+++ b/src/nitro/avatar/structure/AvatarStructureDownload.ts
@@ -0,0 +1,57 @@
+import { Parser } from 'xml2js';
+import { NitroLogger } from '../../../core/common/logger/NitroLogger';
+import { EventDispatcher } from '../../../core/events/EventDispatcher';
+import { NitroEvent } from '../../../core/events/NitroEvent';
+import { IFigureSetData } from './IFigureSetData';
+
+export class AvatarStructureDownload extends EventDispatcher
+{
+ public static AVATAR_STRUCTURE_DONE: string = 'AVATAR_STRUCTURE_DONE';
+
+ private _dataReceiver: IFigureSetData;
+
+ constructor(downloadUrl: string, dataReceiver: IFigureSetData)
+ {
+ super();
+
+ this._dataReceiver = dataReceiver;
+
+ this.download(downloadUrl);
+ }
+
+ private download(url: string): void
+ {
+ const request = new XMLHttpRequest();
+
+ try
+ {
+ request.open('GET', url);
+
+ request.send();
+
+ request.onloadend = e =>
+ {
+ const parser = new Parser();
+
+ parser.parseString(request.responseText, (err: Error, results: any) =>
+ {
+ if(err || !results || !results.figuredata) throw new Error('invalid_figure_data');
+
+ if(this._dataReceiver) this._dataReceiver._Str_1017(results.figuredata);
+
+ this.dispatchEvent(new NitroEvent(AvatarStructureDownload.AVATAR_STRUCTURE_DONE));
+ });
+ };
+
+ request.onerror = e =>
+ {
+ throw new Error('invalid_avatar_figure_data');
+ };
+ }
+
+ catch (e)
+ {
+ NitroLogger.log(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/FigureSetData.ts b/src/nitro/avatar/structure/FigureSetData.ts
new file mode 100644
index 00000000..6a40a993
--- /dev/null
+++ b/src/nitro/avatar/structure/FigureSetData.ts
@@ -0,0 +1,152 @@
+import { IFigurePartSet } from './figure/IFigurePartSet';
+import { IPalette } from './figure/IPalette';
+import { ISetType } from './figure/ISetType';
+import { Palette } from './figure/Palette';
+import { SetType } from './figure/SetType';
+import { IFigureSetData } from './IFigureSetData';
+import { IStructureData } from './IStructureData';
+
+export class FigureSetData implements IFigureSetData, IStructureData
+{
+ private _palettes: Map;
+ private _setTypes: Map;
+
+ constructor()
+ {
+ this._palettes = new Map();
+ this._setTypes = new Map();
+ }
+
+ public dispose(): void
+ {
+
+ }
+
+ public parse(data: any): boolean
+ {
+ if(!data) return false;
+
+ for(const palette of data.colors[0].palette)
+ {
+ const newPalette = new Palette(palette);
+
+ if(!newPalette) continue;
+
+ this._palettes.set(newPalette.id.toString(), newPalette);
+ }
+
+ for(const set of data.sets[0].settype)
+ {
+ const newSet = new SetType(set);
+
+ if(!newSet) continue;
+
+ this._setTypes.set(newSet.type, newSet);
+ }
+
+ return true;
+ }
+
+ public _Str_1133(k: any): void
+ {
+ for(const _local_2 of k.sets[0].settype)
+ {
+ const setType = this._setTypes.get(_local_2['$'].type);
+
+ if(setType)
+ {
+ setType._Str_1874(_local_2);
+ }
+ else
+ {
+ this._setTypes.set(_local_2['$'].type, new SetType(_local_2));
+ }
+ }
+
+ this._Str_1017(k);
+ }
+
+ public _Str_1017(k: any): boolean
+ {
+ if(!k) return false;
+
+ for(const _local_2 of k.colors[0].palette)
+ {
+ const id = _local_2['$'].id.toString();
+ const _local_4 = this._palettes.get(id);
+
+ if(!_local_4)
+ {
+ this._palettes.set(id, new Palette(_local_2));
+ }
+ else
+ {
+ _local_4._Str_2015(_local_2);
+ }
+ }
+
+ for(const _local_3 of k.sets[0].settype)
+ {
+ const type = _local_3['$'].type;
+ const _local_5 = this._setTypes.get(type);
+
+ if(!_local_5)
+ {
+ this._setTypes.set(type, new SetType(_local_3));
+ }
+ else
+ {
+ _local_5._Str_2015(_local_3);
+ }
+ }
+
+ return false;
+ }
+
+ public _Str_1733(k: string, _arg_2: number): string[]
+ {
+ const types: string[] = [];
+
+ for(const set of this._setTypes.values())
+ {
+ if(!set || !set._Str_895(k, _arg_2)) continue;
+
+ types.push(set.type);
+ }
+
+ return types;
+ }
+
+ public _Str_2264(k: string, _arg_2: string): IFigurePartSet
+ {
+ const setType = this._setTypes.get(k);
+
+ if(!setType) return null;
+
+ return setType._Str_2264(_arg_2);
+ }
+
+ public _Str_740(k: string): ISetType
+ {
+ return (this._setTypes.get(k) || null);
+ }
+
+ public _Str_783(k: number): IPalette
+ {
+ return (this._palettes.get(k.toString()) || null);
+ }
+
+ public _Str_938(k: number): IFigurePartSet
+ {
+ for(const set of this._setTypes.values())
+ {
+ const partSet = set._Str_1020(k);
+
+ if(!partSet) continue;
+
+ return partSet;
+ }
+
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/IFigureSetData.ts b/src/nitro/avatar/structure/IFigureSetData.ts
new file mode 100644
index 00000000..444911f3
--- /dev/null
+++ b/src/nitro/avatar/structure/IFigureSetData.ts
@@ -0,0 +1,5 @@
+export interface IFigureSetData
+{
+ parse(data: any): boolean;
+ _Str_1017(data: any): boolean;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/IStructureData.ts b/src/nitro/avatar/structure/IStructureData.ts
new file mode 100644
index 00000000..05dac860
--- /dev/null
+++ b/src/nitro/avatar/structure/IStructureData.ts
@@ -0,0 +1,12 @@
+import { IFigurePartSet } from './figure/IFigurePartSet';
+import { IPalette } from './figure/IPalette';
+import { ISetType } from './figure/ISetType';
+
+export interface IStructureData
+{
+ parse(data: any): boolean;
+ _Str_1017(k: any): boolean;
+ _Str_740(_arg_1: string): ISetType;
+ _Str_783(_arg_1: number): IPalette;
+ _Str_938(_arg_1: number): IFigurePartSet;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/PartSetsData.ts b/src/nitro/avatar/structure/PartSetsData.ts
new file mode 100644
index 00000000..99236c7a
--- /dev/null
+++ b/src/nitro/avatar/structure/PartSetsData.ts
@@ -0,0 +1,120 @@
+import { ActionDefinition } from '../actions/ActionDefinition';
+import { IActionDefinition } from '../actions/IActionDefinition';
+import { IFigureSetData } from './IFigureSetData';
+import { ActivePartSet } from './parts/ActivePartSet';
+import { PartDefinition } from './parts/PartDefinition';
+
+export class PartSetsData implements IFigureSetData
+{
+ private _parts: Map;
+ private _activePartSets: Map;
+
+ constructor()
+ {
+ this._parts = new Map();
+ this._activePartSets = new Map();
+ }
+
+ public parse(data: any): boolean
+ {
+ if(data.partSet && (data.partSet.length > 0))
+ {
+ for(const part of data.partSet)
+ {
+ if(!part) continue;
+
+ this._parts.set(part.setType, new PartDefinition(part));
+ }
+ }
+
+ if(data.activePartSets && (data.activePartSets.length > 0))
+ {
+ for(const activePart of data.activePartSets)
+ {
+ if(!activePart) continue;
+
+ this._activePartSets.set(activePart.id, new ActivePartSet(activePart));
+ }
+ }
+
+ return true;
+ }
+
+ public _Str_1017(data: any): boolean
+ {
+ if(data.partSet && (data.partSet.length > 0))
+ {
+ for(const part of data.partSet)
+ {
+ if(!part) continue;
+
+ this._parts.set(part.setType, new PartDefinition(part));
+ }
+ }
+
+ if(data.activePartSets && (data.activePartSets.length > 0))
+ {
+ for(const activePart of data.activePartSets)
+ {
+ if(!activePart) continue;
+
+ this._activePartSets.set(activePart.id, new ActivePartSet(activePart));
+ }
+ }
+
+ return false;
+ }
+
+ public _Str_1795(k:IActionDefinition): string[]
+ {
+ const activePartSet = this._activePartSets.get(k.activePartSet);
+
+ if(!activePartSet) return [];
+
+ return activePartSet._Str_806;
+ }
+
+ public _Str_1102(part: string): PartDefinition
+ {
+ const existing = this._parts.get(part);
+
+ if(!existing) return null;
+
+ return existing;
+ }
+
+ public _Str_1520(k: any): PartDefinition
+ {
+ const _local_2 = k.setType as string;
+
+ let existing = this._parts.get(_local_2);
+
+ if(!existing)
+ {
+ existing = new PartDefinition(k);
+
+ this._parts.set(_local_2, existing);
+ }
+
+ return existing;
+ }
+
+ public _Str_1113(k: ActionDefinition): ActivePartSet
+ {
+ const existing = this._activePartSets.get(k.activePartSet);
+
+ if(!existing) return null;
+
+ return existing;
+ }
+
+ public get _Str_806(): Map
+ {
+ return this._parts;
+ }
+
+ public get _Str_1979(): Map
+ {
+ return this._activePartSets;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/animation/AnimationAction.ts b/src/nitro/avatar/structure/animation/AnimationAction.ts
new file mode 100644
index 00000000..462d54a2
--- /dev/null
+++ b/src/nitro/avatar/structure/animation/AnimationAction.ts
@@ -0,0 +1,138 @@
+import { Point } from 'pixi.js';
+import { AnimationActionPart } from './AnimationActionPart';
+
+export class AnimationAction
+{
+ public static _Str_1934: Point = new Point(0, 0);
+
+ private _id: string;
+ private _actionParts: Map;
+ private _bodyPartOffsets: Map>>;
+ private _frameCount: number;
+ private _frameIndexes: number[];
+
+ constructor(data: any)
+ {
+ this._id = data.id;
+ this._actionParts = new Map();
+ this._bodyPartOffsets = new Map();
+ this._frameCount = 0;
+ this._frameIndexes = [];
+
+ if(data.parts && (data.parts.length > 0))
+ {
+ for(const part of data.parts)
+ {
+ if(!part) continue;
+
+ const newPart = new AnimationActionPart(part);
+
+ this._actionParts.set(part.setType, newPart);
+
+ this._frameCount = Math.max(this._frameCount, newPart.frames.length);
+ }
+ }
+
+ if(data.offsets && data.offsets.frames && (data.offsets.frames.length > 0))
+ {
+ for(const frame of data.offsets.frames)
+ {
+ if(!frame) continue;
+
+ const frameId = frame.id;
+
+ this._frameCount = Math.max(this._frameCount, frameId);
+
+ const directions: Map> = new Map();
+
+ this._bodyPartOffsets.set(frameId, directions);
+
+ if(frame.directions && (frame.directions.length > 0))
+ {
+ for(const direction of frame.directions)
+ {
+ if(!direction) continue;
+
+ const directionId = direction.id;
+
+ const offsets: Map = new Map();
+
+ directions.set(directionId, offsets);
+
+ if(direction.bodyParts && (direction.bodyParts.length > 0))
+ {
+ for(const part of direction.bodyParts)
+ {
+ if(!part) continue;
+
+ const partId = part.id;
+
+ let dx = 0;
+ let dy = 0;
+
+ if(part.dx !== undefined) dx = part.dx;
+ if(part.dy !== undefined) dy = part.dy;
+
+ offsets.set(partId, new Point(dx, dy));
+ }
+ }
+ }
+ }
+
+ this._frameIndexes.push(frameId);
+
+ if(frame.repeats !== undefined)
+ {
+ let repeats = frame.repeats || 0;
+
+ if(repeats > 1) while(--repeats > 0) this._frameIndexes.push(frameId);
+ }
+ }
+ }
+ }
+
+ public _Str_989(type: string): AnimationActionPart
+ {
+ if(!type) return null;
+
+ const existing = this._actionParts.get(type);
+
+ if(!existing) return null;
+
+ return existing;
+ }
+
+ public _Str_1888(frameId: number, frameCount: number, partId: string): Point
+ {
+ const frameIndex = (frameCount % this._frameIndexes.length);
+ const frameNumber = this._frameIndexes[frameIndex];
+ const offsets = this._bodyPartOffsets.get(frameNumber);
+
+ if(!offsets) return AnimationAction._Str_1934;
+
+ const frameOffset = offsets.get(frameId);
+
+ if(!frameOffset) return AnimationAction._Str_1934;
+
+ const offset = frameOffset.get(partId);
+
+ if(!offset) return AnimationAction._Str_1934;
+
+ return offset;
+ }
+
+ public get id(): string
+ {
+ return this._id;
+ }
+
+ public get _Str_806(): Map
+ {
+ return this._actionParts;
+ }
+
+ public get _Str_2185(): number
+ {
+ return this._frameCount;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/animation/AnimationActionPart.ts b/src/nitro/avatar/structure/animation/AnimationActionPart.ts
new file mode 100644
index 00000000..6df6b5db
--- /dev/null
+++ b/src/nitro/avatar/structure/animation/AnimationActionPart.ts
@@ -0,0 +1,30 @@
+import { AnimationFrame } from './AnimationFrame';
+
+export class AnimationActionPart
+{
+ private _frames: AnimationFrame[];
+
+ constructor(data: any)
+ {
+ this._frames = [];
+
+ if(data.frames && (data.frames.length > 0))
+ {
+ for(const frame of data.frames)
+ {
+ if(!frame) continue;
+
+ this._frames.push(new AnimationFrame(frame));
+
+ let repeats = frame.repeats || 0;
+
+ if(repeats > 1) while(--repeats > 0) this._frames.push(this._frames[(this._frames.length - 1)]);
+ }
+ }
+ }
+
+ public get frames(): AnimationFrame[]
+ {
+ return this._frames;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/animation/AnimationFrame.ts b/src/nitro/avatar/structure/animation/AnimationFrame.ts
new file mode 100644
index 00000000..74899f9c
--- /dev/null
+++ b/src/nitro/avatar/structure/animation/AnimationFrame.ts
@@ -0,0 +1,21 @@
+export class AnimationFrame
+{
+ private _number: number;
+ private _assetPartDefinition: string;
+
+ constructor(data: any)
+ {
+ this._number = data.number;
+ this._assetPartDefinition = data.assetPartDefinition || null;
+ }
+
+ public get number(): number
+ {
+ return this._number;
+ }
+
+ public get _Str_778(): string
+ {
+ return this._assetPartDefinition;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/figure/FigurePart.ts b/src/nitro/avatar/structure/figure/FigurePart.ts
new file mode 100644
index 00000000..93455739
--- /dev/null
+++ b/src/nitro/avatar/structure/figure/FigurePart.ts
@@ -0,0 +1,66 @@
+import { IFigurePart } from './IFigurePart';
+
+export class FigurePart implements IFigurePart
+{
+ private _id: number;
+ private _type: string;
+ private _breed: number;
+ private _index: number;
+ private _colorLayerIndex: number;
+ private _paletteMapId: number;
+
+ constructor(data: any)
+ {
+ if(!data) throw new Error('invalid_data');
+
+ this._id = parseInt(data['$'].id);
+ this._type = data['$'].type;
+ this._index = parseInt(data['$'].index);
+ this._colorLayerIndex = parseInt(data['$'].colorindex);
+
+ const paletteMapId = data['$'].palettemapid;
+
+ if(!isNaN(paletteMapId)) this._paletteMapId = parseInt(paletteMapId);
+ else this._paletteMapId = -1;
+
+ const breed = data['$'].palettemapid;
+
+ if(!isNaN(breed)) this._breed = parseInt(breed);
+ else this._breed = -1;
+ }
+
+ public dispose(): void
+ {
+
+ }
+
+ public get id(): number
+ {
+ return this._id;
+ }
+
+ public get type(): string
+ {
+ return this._type;
+ }
+
+ public get breed(): number
+ {
+ return this._breed;
+ }
+
+ public get index(): number
+ {
+ return this._index;
+ }
+
+ public get _Str_827(): number
+ {
+ return this._colorLayerIndex;
+ }
+
+ public get paletteMap(): number
+ {
+ return this._paletteMapId;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/figure/FigurePartSet.ts b/src/nitro/avatar/structure/figure/FigurePartSet.ts
new file mode 100644
index 00000000..6d9163e8
--- /dev/null
+++ b/src/nitro/avatar/structure/figure/FigurePartSet.ts
@@ -0,0 +1,144 @@
+import { FigurePart } from './FigurePart';
+import { IFigurePart } from './IFigurePart';
+import { IFigurePartSet } from './IFigurePartSet';
+
+export class FigurePartSet implements IFigurePartSet
+{
+ private _id: number;
+ private _type: string;
+ private _gender: string;
+ private _clubLevel: number;
+ private _isColorable: boolean;
+ private _isSelectable: boolean;
+ private _parts: IFigurePart[];
+ private _hiddenLayers: string[];
+ private _isPreSelectable: boolean;
+ private _isSellable: boolean;
+
+ constructor(type: string, data: any)
+ {
+ if(!type || !data) throw new Error('invalid_data');
+
+ this._id = parseInt(data['$'].id);
+ this._type = type;
+ this._gender = data['$'].gender;
+ this._clubLevel = parseInt(data['$'].club);
+ this._isColorable = parseInt(data['$'].colorable) === 1;
+ this._isSelectable = parseInt(data['$'].selectable) === 1;
+ this._parts = [];
+ this._hiddenLayers = [];
+ this._isPreSelectable = parseInt(data['$'].preselectable) === 1;
+ this._isSellable = parseInt(data['$'].sellable) === 1;
+
+ for(const part of data.part)
+ {
+ const newPart = new FigurePart(part);
+ const partIndex = this.getPartIndex(newPart);
+
+ if(partIndex !== -1) this._parts.splice(partIndex, 0, newPart);
+ else this._parts.push(newPart);
+ }
+
+ if(data.hiddenlayers)
+ {
+ const hiddenLayers = data.hiddenlayers[0];
+
+ for(const layer of hiddenLayers.layer) this._hiddenLayers.push(layer['$'].parttype);
+ }
+ }
+
+ public dispose(): void
+ {
+ for(const part of this._parts)
+ {
+ const figurePart = part as FigurePart;
+
+ figurePart.dispose();
+ }
+
+ this._parts = null;
+ this._hiddenLayers = null;
+ }
+
+ private getPartIndex(part: FigurePart): number
+ {
+ const totalParts = this._parts.length;
+
+ if(!totalParts) return -1;
+
+ for(let i = 0; i < totalParts; i++)
+ {
+ const existingPart = this._parts[i];
+
+ if(!existingPart) continue;
+
+ if(existingPart.type !== part.type || existingPart.index > part.index) continue;
+
+ return i;
+ }
+
+ return -1;
+ }
+
+ public _Str_989(k: string, _arg_2: number): IFigurePart
+ {
+ for(const part of this._parts)
+ {
+ if((part.type !== k) || (part.id !== _arg_2)) continue;
+
+ return part;
+ }
+
+ return null;
+ }
+
+ public get id(): number
+ {
+ return this._id;
+ }
+
+ public get type(): string
+ {
+ return this._type;
+ }
+
+ public get gender(): string
+ {
+ return this._gender;
+ }
+
+ public get clubLevel(): number
+ {
+ return this._clubLevel;
+ }
+
+ public get isColorable(): boolean
+ {
+ return this._isColorable;
+ }
+
+ public get _Str_608(): boolean
+ {
+ return this._isSelectable;
+ }
+
+ public get _Str_806(): IFigurePart[]
+ {
+ return this._parts;
+ }
+
+ public get _Str_790(): string[]
+ {
+ return this._hiddenLayers;
+ }
+
+ public get _Str_653(): boolean
+ {
+ return this._isPreSelectable;
+ }
+
+ public get _Str_651(): boolean
+ {
+ return this._isSellable;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/figure/IFigurePart.ts b/src/nitro/avatar/structure/figure/IFigurePart.ts
new file mode 100644
index 00000000..882e178f
--- /dev/null
+++ b/src/nitro/avatar/structure/figure/IFigurePart.ts
@@ -0,0 +1,9 @@
+export interface IFigurePart
+{
+ id: number;
+ type: string;
+ breed: number;
+ index: number;
+ _Str_827: number;
+ paletteMap: number;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/figure/IFigurePartSet.ts b/src/nitro/avatar/structure/figure/IFigurePartSet.ts
new file mode 100644
index 00000000..1b08de5d
--- /dev/null
+++ b/src/nitro/avatar/structure/figure/IFigurePartSet.ts
@@ -0,0 +1,16 @@
+import { IFigurePart } from './IFigurePart';
+
+export interface IFigurePartSet
+{
+ _Str_989(_arg_1: string, _arg_2: number): IFigurePart;
+ id: number;
+ type: string;
+ gender: string;
+ clubLevel: number;
+ isColorable: boolean;
+ _Str_608: boolean;
+ _Str_806: IFigurePart[];
+ _Str_790: string[];
+ _Str_653: boolean;
+ _Str_651: boolean;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/figure/IPalette.ts b/src/nitro/avatar/structure/figure/IPalette.ts
new file mode 100644
index 00000000..dd5233e7
--- /dev/null
+++ b/src/nitro/avatar/structure/figure/IPalette.ts
@@ -0,0 +1,8 @@
+import { IPartColor } from './IPartColor';
+
+export interface IPalette
+{
+ _Str_751(id: number): IPartColor;
+ id: number;
+ colors: Map;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/figure/IPartColor.ts b/src/nitro/avatar/structure/figure/IPartColor.ts
new file mode 100644
index 00000000..2630b71f
--- /dev/null
+++ b/src/nitro/avatar/structure/figure/IPartColor.ts
@@ -0,0 +1,8 @@
+export interface IPartColor
+{
+ id: number;
+ index: number;
+ clubLevel: number;
+ isSelectable: boolean;
+ _Str_915: number;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/figure/ISetType.ts b/src/nitro/avatar/structure/figure/ISetType.ts
new file mode 100644
index 00000000..29f2c5dd
--- /dev/null
+++ b/src/nitro/avatar/structure/figure/ISetType.ts
@@ -0,0 +1,12 @@
+import { AdvancedMap } from '../../../../core/utils/AdvancedMap';
+import { IFigurePartSet } from './IFigurePartSet';
+
+export interface ISetType
+{
+ _Str_1020(_arg_1: number): IFigurePartSet;
+ _Str_895(_arg_1: string, _arg_2: number): boolean;
+ _Str_1002(_arg_1: string): number;
+ type: string;
+ _Str_734: number;
+ _Str_710: AdvancedMap;
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/figure/Palette.ts b/src/nitro/avatar/structure/figure/Palette.ts
new file mode 100644
index 00000000..5e15d1f2
--- /dev/null
+++ b/src/nitro/avatar/structure/figure/Palette.ts
@@ -0,0 +1,46 @@
+import { IPalette } from './IPalette';
+import { IPartColor } from './IPartColor';
+import { PartColor } from './PartColor';
+
+export class Palette implements IPalette
+{
+ private _id: number;
+ private _colors: Map;
+
+ constructor(data: any)
+ {
+ if(!data) throw new Error('invalid_data');
+
+ this._id = parseInt(data['$'].id);
+ this._colors = new Map();
+
+ this._Str_2015(data);
+ }
+
+ public _Str_2015(data: any): void
+ {
+ for(const color of data.color)
+ {
+ const newColor = new PartColor(color);
+
+ this._colors.set(color['$'].id.toString(), newColor);
+ }
+ }
+
+ public _Str_751(id: number): IPartColor
+ {
+ if((id === undefined) || id < 0) return null;
+
+ return (this._colors.get(id.toString()) || null);
+ }
+
+ public get id(): number
+ {
+ return this._id;
+ }
+
+ public get colors(): Map
+ {
+ return this._colors;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/figure/PartColor.ts b/src/nitro/avatar/structure/figure/PartColor.ts
new file mode 100644
index 00000000..24c34367
--- /dev/null
+++ b/src/nitro/avatar/structure/figure/PartColor.ts
@@ -0,0 +1,46 @@
+import { IPartColor } from './IPartColor';
+
+export class PartColor implements IPartColor
+{
+ private _id: number;
+ private _index: number;
+ private _clubLevel: number;
+ private _isSelectable: boolean;
+ private _rgb: number;
+
+ constructor(data: any)
+ {
+ if(!data) throw new Error('invalid_data');
+
+ this._id = parseInt(data['$'].id);
+ this._index = parseInt(data['$'].index);
+ this._clubLevel = parseInt(data['$'].club);
+ this._isSelectable = parseInt(data['$'].selectable) === 1;
+ this._rgb = parseInt('0x' + data['_'], 16);
+ }
+
+ public get id(): number
+ {
+ return this._id;
+ }
+
+ public get index(): number
+ {
+ return this._index;
+ }
+
+ public get clubLevel(): number
+ {
+ return this._clubLevel;
+ }
+
+ public get isSelectable(): boolean
+ {
+ return this._isSelectable;
+ }
+
+ public get _Str_915(): number
+ {
+ return this._rgb;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/figure/SetType.ts b/src/nitro/avatar/structure/figure/SetType.ts
new file mode 100644
index 00000000..618cb143
--- /dev/null
+++ b/src/nitro/avatar/structure/figure/SetType.ts
@@ -0,0 +1,105 @@
+import { AdvancedMap } from '../../../../core/utils/AdvancedMap';
+import { FigurePartSet } from './FigurePartSet';
+import { IFigurePartSet } from './IFigurePartSet';
+import { ISetType } from './ISetType';
+
+export class SetType implements ISetType
+{
+ private _type: string;
+ private _paletteId: number;
+ private _isMandatory: { [index: string]: boolean[] };
+ private _partSets: AdvancedMap;
+
+ constructor(data: any)
+ {
+ if(!data) throw new Error('invalid_data');
+
+ this._type = data['$'].type;
+ this._paletteId = parseInt(data['$'].paletteid);
+ this._isMandatory = {};
+ this._isMandatory['F'] = [ parseInt(data['$'].mand_f_0) === 1, parseInt(data['$'].mand_f_1) === 1 ];
+ this._isMandatory['M'] = [ (parseInt(data['$'].mand_m_0) === 1), (parseInt(data['$'].mand_m_1) === 1) ];
+ this._partSets = new AdvancedMap();
+
+ this._Str_2015(data);
+ }
+
+ public dispose(): void
+ {
+ for(const set of this._partSets.getValues())
+ {
+ const partSet = set as FigurePartSet;
+
+ partSet.dispose();
+ }
+
+ this._partSets = null;
+ }
+
+ public _Str_1874(k: any): void
+ {
+ for(const _local_2 of k)
+ {
+ const _local_3 = (_local_2.id as string);
+ const _local_4 = (this._partSets.getValue(_local_3) as FigurePartSet);
+
+ if(_local_4)
+ {
+ _local_4.dispose();
+
+ this._partSets.remove(_local_3);
+ }
+ }
+ }
+
+ public _Str_2015(k: any): void
+ {
+ if(!k || !k.set) return;
+
+ for(const set of k.set) this._partSets.add(set['$'].id, new FigurePartSet(this._type, set));
+ }
+
+ public _Str_2264(k: string): IFigurePartSet
+ {
+ for(const set of this._partSets.getValues())
+ {
+ if(!set) continue;
+
+ if((set.clubLevel === 0) && ((set.gender === k) || (set.gender === 'U'))) return set;
+ }
+
+ return null;
+ }
+
+ public _Str_1020(k: number): IFigurePartSet
+ {
+ return this._partSets.getValue(k.toString());
+ }
+
+ public get type(): string
+ {
+ return this._type;
+ }
+
+ public get _Str_734(): number
+ {
+ return this._paletteId;
+ }
+
+ public _Str_895(k: string, _arg_2: number): boolean
+ {
+ return this._isMandatory[k.toUpperCase()][Math.min(_arg_2, 1)];
+ }
+
+ public _Str_1002(k: string): number
+ {
+ const _local_2 = this._isMandatory[k.toUpperCase()];
+
+ return _local_2.indexOf(false);
+ }
+
+ public get _Str_710(): AdvancedMap
+ {
+ return this._partSets;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/parts/ActivePartSet.ts b/src/nitro/avatar/structure/parts/ActivePartSet.ts
new file mode 100644
index 00000000..9e3ac69d
--- /dev/null
+++ b/src/nitro/avatar/structure/parts/ActivePartSet.ts
@@ -0,0 +1,26 @@
+export class ActivePartSet
+{
+ private _id: string;
+ private _parts: string[];
+
+ constructor(data: any)
+ {
+ this._id = data.id;
+ this._parts = [];
+
+ if(data.activeParts && (data.activeParts.length > 0))
+ {
+ for(const part of data.activeParts)
+ {
+ if(!part) continue;
+
+ this._parts.push(part.setType);
+ }
+ }
+ }
+
+ public get _Str_806(): string[]
+ {
+ return this._parts;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/avatar/structure/parts/PartDefinition.ts b/src/nitro/avatar/structure/parts/PartDefinition.ts
new file mode 100644
index 00000000..305ce47b
--- /dev/null
+++ b/src/nitro/avatar/structure/parts/PartDefinition.ts
@@ -0,0 +1,64 @@
+export class PartDefinition
+{
+ private _setType: string;
+ private _flippedSetType: string;
+ private _removeSetType: string;
+ private _appendToFigure: boolean;
+ private _staticId: number;
+
+ constructor(data: any)
+ {
+ if(!data) throw new Error('invalid_data');
+
+ this._setType = data.setType;
+ this._flippedSetType = data.flippedSetType || null;
+ this._removeSetType = data.removeSetType || null;
+ this._appendToFigure = false;
+ this._staticId = -1;
+ }
+
+ public _Str_2234(): boolean
+ {
+ return this._staticId >= 0;
+ }
+
+ public get _Str_1734(): number
+ {
+ return this._staticId;
+ }
+
+ public set _Str_1734(k: number)
+ {
+ this._staticId = k;
+ }
+
+ public get _Str_2174(): string
+ {
+ return this._setType;
+ }
+
+ public get _Str_1693(): string
+ {
+ return this._flippedSetType;
+ }
+
+ public set _Str_1693(type: string)
+ {
+ this._flippedSetType = type;
+ }
+
+ public get _Str_1209(): string
+ {
+ return this._removeSetType;
+ }
+
+ public get _Str_1583(): boolean
+ {
+ return this._appendToFigure;
+ }
+
+ public set _Str_1583(flag: boolean)
+ {
+ this._appendToFigure = flag;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/INitroCommunicationManager.ts b/src/nitro/communication/INitroCommunicationManager.ts
new file mode 100644
index 00000000..39041234
--- /dev/null
+++ b/src/nitro/communication/INitroCommunicationManager.ts
@@ -0,0 +1,12 @@
+import { INitroManager } from '../../core/common/INitroManager';
+import { IConnection } from '../../core/communication/connections/IConnection';
+import { IMessageEvent } from '../../core/communication/messages/IMessageEvent';
+import { NitroCommunicationDemo } from './demo/NitroCommunicationDemo';
+
+export interface INitroCommunicationManager extends INitroManager
+{
+ registerMessageEvent(event: IMessageEvent): IMessageEvent;
+ removeMessageEvent(event: IMessageEvent): void;
+ demo: NitroCommunicationDemo;
+ connection: IConnection;
+}
\ No newline at end of file
diff --git a/src/nitro/communication/NitroCommunicationManager.ts b/src/nitro/communication/NitroCommunicationManager.ts
new file mode 100644
index 00000000..cccae233
--- /dev/null
+++ b/src/nitro/communication/NitroCommunicationManager.ts
@@ -0,0 +1,124 @@
+import { NitroManager } from '../../core/common/NitroManager';
+import { IConnection } from '../../core/communication/connections/IConnection';
+import { IConnectionStateListener } from '../../core/communication/connections/IConnectionStateListener';
+import { SocketConnectionEvent } from '../../core/communication/events/SocketConnectionEvent';
+import { ICommunicationManager } from '../../core/communication/ICommunicationManager';
+import { IMessageConfiguration } from '../../core/communication/messages/IMessageConfiguration';
+import { IMessageEvent } from '../../core/communication/messages/IMessageEvent';
+import { NitroEvent } from '../../core/events/NitroEvent';
+import { Nitro } from '../Nitro';
+import { NitroCommunicationDemo } from './demo/NitroCommunicationDemo';
+import { NitroCommunicationDemoEvent } from './demo/NitroCommunicationDemoEvent';
+import { INitroCommunicationManager } from './INitroCommunicationManager';
+import { NitroMessages } from './NitroMessages';
+
+export class NitroCommunicationManager extends NitroManager implements INitroCommunicationManager, IConnectionStateListener
+{
+ private _communication: ICommunicationManager;
+ private _connection: IConnection;
+ private _messages: IMessageConfiguration;
+
+ private _demo: NitroCommunicationDemo;
+
+ constructor(communication: ICommunicationManager)
+ {
+ super();
+
+ this._communication = communication;
+ this._connection = null;
+ this._messages = new NitroMessages();
+
+ this._demo = new NitroCommunicationDemo(this);
+
+ this.onConnectionOpenedEvent = this.onConnectionOpenedEvent.bind(this);
+ this.onConnectionClosedEvent = this.onConnectionClosedEvent.bind(this);
+ this.onConnectionErrorEvent = this.onConnectionErrorEvent.bind(this);
+ this.onConnectionAuthenticatedEvent = this.onConnectionAuthenticatedEvent.bind(this);
+ }
+
+ protected onInit(): void
+ {
+ if(this._connection) return;
+
+ Nitro.instance.events.addEventListener(NitroCommunicationDemoEvent.CONNECTION_AUTHENTICATED, this.onConnectionAuthenticatedEvent);
+
+ this._connection = this._communication.createConnection(this);
+
+ this._connection.registerMessages(this._messages);
+
+ this._connection.addEventListener(SocketConnectionEvent.CONNECTION_OPENED, this.onConnectionOpenedEvent);
+ this._connection.addEventListener(SocketConnectionEvent.CONNECTION_CLOSED, this.onConnectionClosedEvent);
+ this._connection.addEventListener(SocketConnectionEvent.CONNECTION_ERROR, this.onConnectionErrorEvent);
+
+ if(this._demo) this._demo.init();
+
+ this._connection.init(Nitro.instance.getConfiguration('socket.url'));
+ }
+
+ protected onDispose(): void
+ {
+ if(this._demo) this._demo.dispose();
+
+ if(this._connection)
+ {
+ this._connection.removeEventListener(SocketConnectionEvent.CONNECTION_OPENED, this.onConnectionOpenedEvent);
+ this._connection.removeEventListener(SocketConnectionEvent.CONNECTION_CLOSED, this.onConnectionClosedEvent);
+ this._connection.removeEventListener(SocketConnectionEvent.CONNECTION_ERROR, this.onConnectionErrorEvent);
+ }
+
+ Nitro.instance.events.removeEventListener(NitroCommunicationDemoEvent.CONNECTION_AUTHENTICATED, this.onConnectionAuthenticatedEvent);
+
+ super.onDispose();
+ }
+
+ private onConnectionOpenedEvent(event: Event): void
+ {
+ this.logger.log('Connection Initialized');
+ }
+
+ private onConnectionClosedEvent(event: CloseEvent): void
+ {
+ this.logger.log('Connection Closed');
+ }
+
+ private onConnectionErrorEvent(event: Event): void
+ {
+ this.logger.log('Connection Error');
+ }
+
+ private onConnectionAuthenticatedEvent(event: NitroEvent): void
+ {
+ this.logger.log('Connection Authenticated');
+
+ if(this._connection) this._connection.authenticated();
+ }
+
+ public connectionInit(socketUrl: string): void
+ {
+ this.logger.log(`Initializing Connection: ${ socketUrl }`);
+ }
+
+ public registerMessageEvent(event: IMessageEvent): IMessageEvent
+ {
+ if(this._connection) this._connection.addMessageEvent(event);
+
+ return event;
+ }
+
+ public removeMessageEvent(event: IMessageEvent): void
+ {
+ if(!this._connection) return;
+
+ this._connection.removeMessageEvent(event);
+ }
+
+ public get demo(): NitroCommunicationDemo
+ {
+ return this._demo;
+ }
+
+ public get connection(): IConnection
+ {
+ return this._connection;
+ }
+}
diff --git a/src/nitro/communication/NitroMessages.ts b/src/nitro/communication/NitroMessages.ts
new file mode 100644
index 00000000..744024b9
--- /dev/null
+++ b/src/nitro/communication/NitroMessages.ts
@@ -0,0 +1,971 @@
+import { IMessageConfiguration } from '../../core/communication/messages/IMessageConfiguration';
+import { AvailabilityStatusMessageEvent } from './messages/incoming/availability/AvailabilityStatusMessageEvent';
+import { ChangeNameUpdateEvent } from './messages/incoming/avatar/ChangeNameUpdateEvent';
+import { CatalogClubEvent } from './messages/incoming/catalog/CatalogClubEvent';
+import { CatalogClubGiftsEvent } from './messages/incoming/catalog/CatalogClubGiftsEvent';
+import { CatalogGiftConfigurationEvent } from './messages/incoming/catalog/CatalogGiftConfigurationEvent';
+import { CatalogGiftUsernameUnavailableEvent } from './messages/incoming/catalog/CatalogGiftUsernameUnavailableEvent';
+import { CatalogGroupsEvent } from './messages/incoming/catalog/CatalogGroupsEvent';
+import { CatalogModeEvent } from './messages/incoming/catalog/CatalogModeEvent';
+import { CatalogPageEvent } from './messages/incoming/catalog/CatalogPageEvent';
+import { CatalogPagesEvent } from './messages/incoming/catalog/CatalogPagesEvent';
+import { CatalogPurchaseEvent } from './messages/incoming/catalog/CatalogPurchaseEvent';
+import { CatalogPurchaseFailedEvent } from './messages/incoming/catalog/CatalogPurchaseFailedEvent';
+import { CatalogPurchaseUnavailableEvent } from './messages/incoming/catalog/CatalogPurchaseUnavailableEvent';
+import { CatalogRedeemVoucherErrorEvent } from './messages/incoming/catalog/CatalogRedeemVoucherErrorEvent';
+import { CatalogRedeemVoucherOkEvent } from './messages/incoming/catalog/CatalogRedeemVoucherOkEvent';
+import { CatalogSearchEvent } from './messages/incoming/catalog/CatalogSearchEvent';
+import { CatalogSoldOutEvent } from './messages/incoming/catalog/CatalogSoldOutEvent';
+import { CatalogUpdatedEvent } from './messages/incoming/catalog/CatalogUpdatedEvent';
+import { ClientPingEvent } from './messages/incoming/client/ClientPingEvent';
+import { DesktopViewEvent } from './messages/incoming/desktop/DesktopViewEvent';
+import { AcceptFriendResultEvent } from './messages/incoming/friendlist/AcceptFriendResultEvent';
+import { FindFriendsProcessResultEvent } from './messages/incoming/friendlist/FindFriendsProcessResultEvent';
+import { FollowFriendFailedEvent } from './messages/incoming/friendlist/FollowFriendFailedEvent';
+import { FriendListFragmentEvent } from './messages/incoming/friendlist/FriendListFragmentEvent';
+import { FriendListUpdateEvent } from './messages/incoming/friendlist/FriendListUpdateEvent';
+import { FriendNotificationEvent } from './messages/incoming/friendlist/FriendNotificationEvent';
+import { FriendRequestsEvent } from './messages/incoming/friendlist/FriendRequestsEvent';
+import { HabboSearchResultEvent } from './messages/incoming/friendlist/HabboSearchResultEvent';
+import { InstantMessageErrorEvent } from './messages/incoming/friendlist/InstantMessageErrorEvent';
+import { MessageErrorEvent } from './messages/incoming/friendlist/MessageErrorEvent';
+import { MessengerInitEvent } from './messages/incoming/friendlist/MessengerInitEvent';
+import { MiniMailNewMessageEvent } from './messages/incoming/friendlist/MiniMailNewMessageEvent';
+import { NewConsoleMessageEvent } from './messages/incoming/friendlist/NewConsoleMessageEvent';
+import { NewFriendRequestEvent } from './messages/incoming/friendlist/NewFriendRequestEvent';
+import { RoomInviteErrorEvent } from './messages/incoming/friendlist/RoomInviteErrorEvent';
+import { RoomInviteEvent } from './messages/incoming/friendlist/RoomInviteEvent';
+import { LoadGameUrlEvent } from './messages/incoming/game/LoadGameUrlEvent';
+import { GenericErrorEvent } from './messages/incoming/generic/GenericErrorEvent';
+import { GroupBadgePartsEvent } from './messages/incoming/group/GroupBadgePartsEvent';
+import { GroupBuyDataEvent } from './messages/incoming/group/GroupBuyDataEvent';
+import { GroupConfirmMemberRemoveEvent } from './messages/incoming/group/GroupConfirmMemberRemoveEvent';
+import { GroupInformationEvent } from './messages/incoming/group/GroupInformationEvent';
+import { GroupMembersEvent } from './messages/incoming/group/GroupMembersEvent';
+import { GroupSettingsEvent } from './messages/incoming/group/GroupSettingsEvent';
+import { CallForHelpResultMessageEvent } from './messages/incoming/help/CallForHelpResultMessageEvent';
+import { IncomingHeader } from './messages/incoming/IncomingHeader';
+import { AchievementEvent } from './messages/incoming/inventory/achievements/AchievementEvent';
+import { AchievementsEvent } from './messages/incoming/inventory/achievements/AchievementsEvent';
+import { AchievementsScoreEvent } from './messages/incoming/inventory/achievements/AchievementsScoreEvent';
+import { AvatarEffectActivatedEvent } from './messages/incoming/inventory/avatareffect/AvatarEffectActivatedEvent';
+import { AvatarEffectAddedEvent } from './messages/incoming/inventory/avatareffect/AvatarEffectAddedEvent';
+import { AvatarEffectExpiredEvent } from './messages/incoming/inventory/avatareffect/AvatarEffectExpiredEvent';
+import { AvatarEffectsEvent } from './messages/incoming/inventory/avatareffect/AvatarEffectsEvent';
+import { BadgesEvent } from './messages/incoming/inventory/badges/BadgesEvent';
+import { BotAddedToInventoryEvent } from './messages/incoming/inventory/bots/BotAddedToInventoryEvent';
+import { BotInventoryMessageEvent } from './messages/incoming/inventory/bots/BotInventoryMessageEvent';
+import { BotRemovedFromInventoryEvent } from './messages/incoming/inventory/bots/BotRemovedFromInventoryEvent';
+import { FigureSetIdsMessageEvent } from './messages/incoming/inventory/clothes/FigureSetIdsMessageEvent';
+import { FurnitureListAddOrUpdateEvent } from './messages/incoming/inventory/furni/FurnitureListAddOrUpdateEvent';
+import { FurnitureListEvent } from './messages/incoming/inventory/furni/FurnitureListEvent';
+import { FurnitureListInvalidateEvent } from './messages/incoming/inventory/furni/FurnitureListInvalidateEvent';
+import { FurnitureListRemovedEvent } from './messages/incoming/inventory/furni/FurnitureListRemovedEvent';
+import { FurniturePostItPlacedEvent } from './messages/incoming/inventory/furni/FurniturePostItPlacedEvent';
+import { FurnitureGiftOpenedEvent } from './messages/incoming/inventory/furni/gifts/FurnitureGiftOpenedEvent';
+import { PetAddedToInventoryEvent } from './messages/incoming/inventory/pets/PetAddedToInventoryEvent';
+import { PetInventoryEvent } from './messages/incoming/inventory/pets/PetInventoryEvent';
+import { PetRemovedFromInventory } from './messages/incoming/inventory/pets/PetRemovedFromInventoryEvent';
+import { TradingAcceptEvent } from './messages/incoming/inventory/trading/TradingAcceptEvent';
+import { TradingCloseEvent } from './messages/incoming/inventory/trading/TradingCloseEvent';
+import { TradingCompletedEvent } from './messages/incoming/inventory/trading/TradingCompletedEvent';
+import { TradingConfirmationEvent } from './messages/incoming/inventory/trading/TradingConfirmationEvent';
+import { TradingListItemEvent } from './messages/incoming/inventory/trading/TradingListItemEvent';
+import { TradingNotOpenEvent } from './messages/incoming/inventory/trading/TradingNotOpenEvent';
+import { TradingOpenEvent } from './messages/incoming/inventory/trading/TradingOpenEvent';
+import { TradingOpenFailedEvent } from './messages/incoming/inventory/trading/TradingOpenFailedEvent';
+import { TradingOtherNotAllowedEvent } from './messages/incoming/inventory/trading/TradingOtherNotAllowedEvent';
+import { TradingYouAreNotAllowedEvent } from './messages/incoming/inventory/trading/TradingYouAreNotAllowedEvent';
+import { ModeratorMessageEvent } from './messages/incoming/moderation/ModeratorMessageEvent';
+import { ModtoolCallForHelpTopicsEvent } from './messages/incoming/modtool/ModtoolCallForHelpTopicsEvent';
+import { ModtoolMainEvent } from './messages/incoming/modtool/ModtoolMainEvent';
+import { ModtoolReceivedRoomsUserEvent } from './messages/incoming/modtool/ModtoolReceivedRoomsUserEvent';
+import { ModtoolRoomChatlogEvent } from './messages/incoming/modtool/ModtoolRoomChatlogEvent';
+import { ModtoolRoomInfoEvent } from './messages/incoming/modtool/ModtoolRoomInfoEvent';
+import { ModtoolUserChatlogEvent } from './messages/incoming/modtool/ModtoolUserChatlogEvent';
+import { ModtoolUserInfoEvent } from './messages/incoming/modtool/ModtoolUserInfoEvent';
+import { NavigatorCategoriesEvent } from './messages/incoming/navigator/NavigatorCategoriesEvent';
+import { NavigatorCollapsedEvent } from './messages/incoming/navigator/NavigatorCollapsedEvent';
+import { NavigatorEventCategoriesEvent } from './messages/incoming/navigator/NavigatorEventCategoriesEvent';
+import { NavigatorHomeRoomEvent } from './messages/incoming/navigator/NavigatorHomeRoomEvent';
+import { NavigatorLiftedEvent } from './messages/incoming/navigator/NavigatorLiftedEvent';
+import { NavigatorMetadataEvent } from './messages/incoming/navigator/NavigatorMetadataEvent';
+import { NavigatorOpenRoomCreatorEvent } from './messages/incoming/navigator/NavigatorOpenRoomCreatorEvent';
+import { NavigatorSearchesEvent } from './messages/incoming/navigator/NavigatorSearchesEvent';
+import { NavigatorSearchEvent } from './messages/incoming/navigator/NavigatorSearchEvent';
+import { NavigatorSettingsEvent } from './messages/incoming/navigator/NavigatorSettingsEvent';
+import { BotErrorEvent } from './messages/incoming/notifications/BotErrorEvent';
+import { HabboBroadcastMessageEvent } from './messages/incoming/notifications/HabboBroadcastMessageEvent';
+import { HotelWillShutdownEvent } from './messages/incoming/notifications/HotelWillShutdownEvent';
+import { MOTDNotificationEvent } from './messages/incoming/notifications/MOTDNotificationEvent';
+import { NotificationDialogMessageEvent } from './messages/incoming/notifications/NotificationDialogMessageEvent';
+import { PetPlacingErrorEvent } from './messages/incoming/notifications/PetPlacingErrorEvent';
+import { RespectReceivedEvent } from './messages/incoming/notifications/RespectReceivedEvent';
+import { UnseenItemsEvent } from './messages/incoming/notifications/UnseenItemsEvent';
+import { RoomDoorbellAcceptedEvent } from './messages/incoming/room/access/doorbell/RoomDoorbellAcceptedEvent';
+import { RoomDoorbellEvent } from './messages/incoming/room/access/doorbell/RoomDoorbellEvent';
+import { RoomDoorbellRejectedEvent } from './messages/incoming/room/access/doorbell/RoomDoorbellRejectedEvent';
+import { RoomRightsClearEvent } from './messages/incoming/room/access/rights/RoomRightsClearEvent';
+import { RoomRightsEvent } from './messages/incoming/room/access/rights/RoomRightsEvent';
+import { RoomRightsOwnerEvent } from './messages/incoming/room/access/rights/RoomRightsOwnerEvent';
+import { RoomEnterErrorEvent } from './messages/incoming/room/access/RoomEnterErrorEvent';
+import { RoomEnterEvent } from './messages/incoming/room/access/RoomEnterEvent';
+import { RoomForwardEvent } from './messages/incoming/room/access/RoomForwardEvent';
+import { BotCommandConfigurationEvent } from './messages/incoming/room/bots/BotCommandConfigurationEvent';
+import { RoomBannedUsersEvent } from './messages/incoming/room/data/RoomBannedUsersEvent';
+import { RoomChatSettingsEvent } from './messages/incoming/room/data/RoomChatSettingsEvent';
+import { RoomInfoEvent } from './messages/incoming/room/data/RoomInfoEvent';
+import { RoomInfoOwnerEvent } from './messages/incoming/room/data/RoomInfoOwnerEvent';
+import { RoomScoreEvent } from './messages/incoming/room/data/RoomScoreEvent';
+import { RoomSettingsErrorEvent } from './messages/incoming/room/data/RoomSettingsErrorEvent';
+import { RoomSettingsEvent } from './messages/incoming/room/data/RoomSettingsEvent';
+import { RoomSettingsSavedEvent } from './messages/incoming/room/data/RoomSettingsSavedEvent';
+import { RoomSettingsUpdatedEvent } from './messages/incoming/room/data/RoomSettingsUpdatedEvent';
+import { RoomUsersWithRightsEvent } from './messages/incoming/room/data/RoomUsersWithRightsEvent';
+import { ObjectsRollingEvent } from './messages/incoming/room/engine/ObjectsRollingEvent';
+import { RoomCreatedEvent } from './messages/incoming/room/engine/RoomCreatedEvent';
+import { FurnitureFloorAddEvent } from './messages/incoming/room/furniture/floor/FurnitureFloorAddEvent';
+import { FurnitureFloorEvent } from './messages/incoming/room/furniture/floor/FurnitureFloorEvent';
+import { FurnitureFloorRemoveEvent } from './messages/incoming/room/furniture/floor/FurnitureFloorRemoveEvent';
+import { FurnitureFloorUpdateEvent } from './messages/incoming/room/furniture/floor/FurnitureFloorUpdateEvent';
+import { FurnitureAliasesEvent } from './messages/incoming/room/furniture/FurnitureAliasesEvent';
+import { FurnitureDataEvent } from './messages/incoming/room/furniture/FurnitureDataEvent';
+import { FurnitureItemDataEvent } from './messages/incoming/room/furniture/FurnitureItemDataEvent';
+import { FurnitureStackHeightEvent } from './messages/incoming/room/furniture/FurnitureStackHeightEvent';
+import { FurnitureState2Event } from './messages/incoming/room/furniture/FurnitureState2Event';
+import { FurnitureStateEvent } from './messages/incoming/room/furniture/FurnitureStateEvent';
+import { LoveLockFurniFinishedEvent } from './messages/incoming/room/furniture/LoveLockFurniFinishedEvent';
+import { LoveLockFurniFriendConfirmedEvent } from './messages/incoming/room/furniture/LoveLockFurniFriendConfirmedEvent';
+import { LoveLockFurniStartEvent } from './messages/incoming/room/furniture/LoveLockFurniStartEvent';
+import { RoomDimmerPresetsEvent } from './messages/incoming/room/furniture/RoomDimmerPresetsMessageEvent';
+import { FurnitureWallAddEvent } from './messages/incoming/room/furniture/wall/FurnitureWallAddEvent';
+import { FurnitureWallEvent } from './messages/incoming/room/furniture/wall/FurnitureWallEvent';
+import { FurnitureWallRemoveEvent } from './messages/incoming/room/furniture/wall/FurnitureWallRemoveEvent';
+import { FurnitureWallUpdateEvent } from './messages/incoming/room/furniture/wall/FurnitureWallUpdateEvent';
+import { RoomDoorEvent } from './messages/incoming/room/mapping/RoomDoorEvent';
+import { RoomHeightMapEvent } from './messages/incoming/room/mapping/RoomHeightMapEvent';
+import { RoomHeightMapUpdateEvent } from './messages/incoming/room/mapping/RoomHeightMapUpdateEvent';
+import { RoomModelEvent } from './messages/incoming/room/mapping/RoomModelEvent';
+import { RoomModelNameEvent } from './messages/incoming/room/mapping/RoomModelNameEvent';
+import { RoomPaintEvent } from './messages/incoming/room/mapping/RoomPaintEvent';
+import { RoomThicknessEvent } from './messages/incoming/room/mapping/RoomThicknessEvent';
+import { PetFigureUpdateEvent } from './messages/incoming/room/pet/PetFigureUpdateEvent';
+import { PetInfoEvent } from './messages/incoming/room/pet/PetInfoEvent';
+import { YouArePlayingGameEvent } from './messages/incoming/room/session/YouArePlayingGameEvent';
+import { FloodControlEvent } from './messages/incoming/room/unit/chat/FloodControlEvent';
+import { RemainingMuteEvent } from './messages/incoming/room/unit/chat/RemainingMuteEvent';
+import { RoomUnitChatEvent } from './messages/incoming/room/unit/chat/RoomUnitChatEvent';
+import { RoomUnitChatShoutEvent } from './messages/incoming/room/unit/chat/RoomUnitChatShoutEvent';
+import { RoomUnitChatWhisperEvent } from './messages/incoming/room/unit/chat/RoomUnitChatWhisperEvent';
+import { RoomUnitTypingEvent } from './messages/incoming/room/unit/chat/RoomUnitTypingEvent';
+import { RoomUnitDanceEvent } from './messages/incoming/room/unit/RoomUnitDanceEvent';
+import { RoomUnitEffectEvent } from './messages/incoming/room/unit/RoomUnitEffectEvent';
+import { RoomUnitEvent } from './messages/incoming/room/unit/RoomUnitEvent';
+import { RoomUnitExpressionEvent } from './messages/incoming/room/unit/RoomUnitExpressionEvent';
+import { RoomUnitHandItemEvent } from './messages/incoming/room/unit/RoomUnitHandItemEvent';
+import { RoomUnitHandItemReceivedEvent } from './messages/incoming/room/unit/RoomUnitHandItemReceivedEvent';
+import { RoomUnitIdleEvent } from './messages/incoming/room/unit/RoomUnitIdleEvent';
+import { RoomUnitInfoEvent } from './messages/incoming/room/unit/RoomUnitInfoEvent';
+import { RoomUnitNumberEvent } from './messages/incoming/room/unit/RoomUnitNumberEvent';
+import { RoomUnitRemoveEvent } from './messages/incoming/room/unit/RoomUnitRemoveEvent';
+import { RoomUnitStatusEvent } from './messages/incoming/room/unit/RoomUnitStatusEvent';
+import { RoomMutedEvent } from './messages/incoming/roomevents/RoomMutedEvent';
+import { WiredFurniActionEvent } from './messages/incoming/roomevents/WiredFurniActionEvent';
+import { WiredFurniConditionEvent } from './messages/incoming/roomevents/WiredFurniConditionEvent';
+import { WiredFurniTriggerEvent } from './messages/incoming/roomevents/WiredFurniTriggerEvent';
+import { WiredOpenEvent } from './messages/incoming/roomevents/WiredOpenEvent';
+import { WiredRewardResultMessageEvent } from './messages/incoming/roomevents/WiredRewardResultMessageEvent';
+import { WiredSaveSuccessEvent } from './messages/incoming/roomevents/WiredSaveSuccessEvent';
+import { WiredValidationErrorEvent } from './messages/incoming/roomevents/WiredValidationErrorEvent';
+import { AuthenticatedEvent } from './messages/incoming/security/AuthenticatedEvent';
+import { UserPerksEvent } from './messages/incoming/user/access/UserPerksEvent';
+import { UserPermissionsEvent } from './messages/incoming/user/access/UserPermissionsEvent';
+import { UserCurrentBadgesEvent } from './messages/incoming/user/data/UserCurrentBadgesEvent';
+import { UserFigureEvent } from './messages/incoming/user/data/UserFigureEvent';
+import { UserInfoEvent } from './messages/incoming/user/data/UserInfoEvent';
+import { UserNameChangeMessageEvent } from './messages/incoming/user/data/UserNameChangeMessageEvent';
+import { UserProfileEvent } from './messages/incoming/user/data/UserProfileEvent';
+import { UserRelationshipsEvent } from './messages/incoming/user/data/UserRelationshipsEvent';
+import { UserSettingsEvent } from './messages/incoming/user/data/UserSettingsEvent';
+import { IgnoredUsersEvent } from './messages/incoming/user/IgnoredUsersEvent';
+import { IgnoreResultEvent } from './messages/incoming/user/IgnoreResultEvent';
+import { InClientLinkEvent } from './messages/incoming/user/InClientLinkEvent';
+import { UserCreditsEvent } from './messages/incoming/user/inventory/currency/UserCreditsEvent';
+import { UserCurrencyEvent } from './messages/incoming/user/inventory/currency/UserCurrencyEvent';
+import { UserCurrencyUpdateEvent } from './messages/incoming/user/inventory/currency/UserCurrencyUpdateEvent';
+import { UserSubscriptionEvent } from './messages/incoming/user/inventory/subscription/UserSubscriptionEvent';
+import { UserWardrobePageEvent } from './messages/incoming/user/wardrobe/UserWardrobePageEvent';
+import { RequestAchievementsMessageComposer } from './messages/outgoing/achievements/RequestAchievementsMessageComposer';
+import { CatalogGroupsComposer } from './messages/outgoing/catalog/CatalogGroupsComposer';
+import { CatalogModeComposer } from './messages/outgoing/catalog/CatalogModeComposer';
+import { CatalogPageComposer } from './messages/outgoing/catalog/CatalogPageComposer';
+import { CatalogPurchaseComposer } from './messages/outgoing/catalog/CatalogPurchaseComposer';
+import { CatalogPurchaseGiftComposer } from './messages/outgoing/catalog/CatalogPurchaseGiftComposer';
+import { CatalogRequestGiftConfigurationComposer } from './messages/outgoing/catalog/CatalogRequestGiftConfigurationComposer';
+import { CatalogRequestVipGiftsComposer } from './messages/outgoing/catalog/CatalogRequestVipGiftsComposer';
+import { CatalogRequestVipOffersComposer } from './messages/outgoing/catalog/CatalogRequestVipOffersComposer';
+import { CatalogSearchComposer } from './messages/outgoing/catalog/CatalogSearchComposer';
+import { CatalogSelectClubGiftComposer } from './messages/outgoing/catalog/CatalogSelectClubGiftComposer';
+import { RedeemItemClothingComposer } from './messages/outgoing/catalog/RedeemItemClothingComposer';
+import { CatalogRedeemVoucherComposer } from './messages/outgoing/catalog/RedeemVoucherComposer';
+import { ClientPongComposer } from './messages/outgoing/client/ClientPongComposer';
+import { ClientReleaseVersionComposer } from './messages/outgoing/client/ClientReleaseVersionComposer';
+import { DesktopViewComposer } from './messages/outgoing/desktop/DesktopViewComposer';
+import { AcceptFriendComposer } from './messages/outgoing/friendlist/AcceptFriendComposer';
+import { DeclineFriendComposer } from './messages/outgoing/friendlist/DeclineFriendComposer';
+import { FindNewFriendsComposer } from './messages/outgoing/friendlist/FindNewFriendsComposer';
+import { FollowFriendComposer } from './messages/outgoing/friendlist/FollowFriendComposer';
+import { FriendListUpdateComposer } from './messages/outgoing/friendlist/FriendListUpdateComposer';
+import { GetFriendRequestsComposer } from './messages/outgoing/friendlist/GetFriendRequestsComposer';
+import { HabboSearchComposer } from './messages/outgoing/friendlist/HabboSearchComposer';
+import { MessengerInitComposer } from './messages/outgoing/friendlist/MessengerInitComposer';
+import { RemoveFriendComposer } from './messages/outgoing/friendlist/RemoveFriendComposer';
+import { RequestFriendComposer } from './messages/outgoing/friendlist/RequestFriendComposer';
+import { SendMessageComposer } from './messages/outgoing/friendlist/SendMessageComposer';
+import { SendRoomInviteComposer } from './messages/outgoing/friendlist/SendRoomInviteComposer';
+import { SetRelationshipStatusComposer } from './messages/outgoing/friendlist/SetRelationshipStatusComposer';
+import { VisitUserComposer } from './messages/outgoing/friendlist/VisitUserComposer';
+import { GroupAdminGiveComposer } from './messages/outgoing/group/GroupAdminGiveComposer';
+import { GroupAdminTakeComposer } from './messages/outgoing/group/GroupAdminTakeComposer';
+import { GroupBadgePartsComposer } from './messages/outgoing/group/GroupBadgePartsComposer';
+import { GroupBuyComposer } from './messages/outgoing/group/GroupBuyComposer';
+import { GroupBuyDataComposer } from './messages/outgoing/group/GroupBuyDataComposer';
+import { GroupConfirmRemoveMemberComposer } from './messages/outgoing/group/GroupConfirmRemoveMemberComposer';
+import { GroupDeleteComposer } from './messages/outgoing/group/GroupDeleteComposer';
+import { GroupInformationComposer } from './messages/outgoing/group/GroupInformationComposer';
+import { GroupJoinComposer } from './messages/outgoing/group/GroupJoinComposer';
+import { GroupMembersComposer } from './messages/outgoing/group/GroupMembersComposer';
+import { GroupMembershipAcceptComposer } from './messages/outgoing/group/GroupMembershipAcceptComposer';
+import { GroupMembershipDeclineComposer } from './messages/outgoing/group/GroupMembershipDeclineComposer';
+import { GroupRemoveMemberComposer } from './messages/outgoing/group/GroupRemoveMemberComposer';
+import { GroupSaveBadgeComposer } from './messages/outgoing/group/GroupSaveBadgeComposer';
+import { GroupSaveColorsComposer } from './messages/outgoing/group/GroupSaveColorsComposer';
+import { GroupSaveInformationComposer } from './messages/outgoing/group/GroupSaveInformationComposer';
+import { GroupSavePreferencesComposer } from './messages/outgoing/group/GroupSavePreferencesComposer';
+import { GroupSettingsComposer } from './messages/outgoing/group/GroupSettingsComposer';
+import { InfoRetrieveBaseMessageComposer } from './messages/outgoing/handshake/InfoRetrieveBaseMessageComposer';
+import { SecurityTicketComposer } from './messages/outgoing/handshake/SecurityTicketComposer';
+import { RequestBadgesComposer } from './messages/outgoing/inventory/badges/RequestBadgesComposer';
+import { SetActivatedBadgesComposer } from './messages/outgoing/inventory/badges/SetActivatedBadgesComposer';
+import { GetBotInventoryComposer } from './messages/outgoing/inventory/bots/GetBotInventoryComposer';
+import { FurnitureList2Composer } from './messages/outgoing/inventory/furni/FurnitureList2Composer';
+import { FurnitureListComposer } from './messages/outgoing/inventory/furni/FurnitureListComposer';
+import { RequestPetsComposer } from './messages/outgoing/inventory/pets/RequestPetsComposer';
+import { TradingAcceptComposer } from './messages/outgoing/inventory/trading/TradingAcceptComposer';
+import { TradingCancelComposer } from './messages/outgoing/inventory/trading/TradingCancelComposer';
+import { TradingCloseComposer } from './messages/outgoing/inventory/trading/TradingCloseComposer';
+import { TradingConfirmationComposer } from './messages/outgoing/inventory/trading/TradingConfirmationComposer';
+import { TradingListAddItemComposer } from './messages/outgoing/inventory/trading/TradingListAddItemComposer';
+import { TradingListAddItemsComposer } from './messages/outgoing/inventory/trading/TradingListAddItemsComposer';
+import { TradingListItemRemoveComposer } from './messages/outgoing/inventory/trading/TradingListRemoveItemComposer';
+import { TradingOpenComposer } from './messages/outgoing/inventory/trading/TradingOpenComposer';
+import { TradingUnacceptComposer } from './messages/outgoing/inventory/trading/TradingUnacceptComposer';
+import { ModtoolChangeRoomSettingsComposer } from './messages/outgoing/modtool/ModtoolChangeRoomSettingsComposer';
+import { ModtoolEventAlertComposer } from './messages/outgoing/modtool/ModtoolEventAlertComposer';
+import { ModtoolRequestRoomChatlogComposer } from './messages/outgoing/modtool/ModtoolRequestRoomChatlogComposer';
+import { ModtoolRequestRoomInfoComposer } from './messages/outgoing/modtool/ModtoolRequestRoomInfoComposer';
+import { ModtoolRequestUserChatlogComposer } from './messages/outgoing/modtool/ModtoolRequestUserChatlogComposer';
+import { ModtoolRequestUserInfoComposer } from './messages/outgoing/modtool/ModtoolRequestUserInfoComposer';
+import { ModtoolRequestUserRoomsComposer } from './messages/outgoing/modtool/ModtoolRequestUserRoomsComposer';
+import { ModtoolRoomAlertComposer } from './messages/outgoing/modtool/ModtoolRoomAlertComposer';
+import { ModtoolSanctionAlertComposer } from './messages/outgoing/modtool/ModtoolSanctionAlertComposer';
+import { ModtoolSanctionBanComposer } from './messages/outgoing/modtool/ModtoolSanctionBanComposer';
+import { ModtoolSanctionKickComposer } from './messages/outgoing/modtool/ModtoolSanctionKickComposer';
+import { ModtoolSanctionMuteComposer } from './messages/outgoing/modtool/ModtoolSanctionMuteComposer';
+import { ModtoolSanctionTradelockComposer } from './messages/outgoing/modtool/ModtoolSanctionTradelockComposer';
+import { ConvertGlobalRoomIdMessageComposer } from './messages/outgoing/navigator/ConvertGlobalRoomIdComposer';
+import { NavigatorCategoriesComposer } from './messages/outgoing/navigator/NavigatorCategoriesComposer';
+import { NavigatorCategoryListModeComposer } from './messages/outgoing/navigator/NavigatorCategoryListModeComposer';
+import { NavigatorInitComposer } from './messages/outgoing/navigator/NavigatorInitComposer';
+import { NavigatorSearchCloseComposer } from './messages/outgoing/navigator/NavigatorSearchCloseComposer';
+import { NavigatorSearchComposer } from './messages/outgoing/navigator/NavigatorSearchComposer';
+import { NavigatorSearchOpenComposer } from './messages/outgoing/navigator/NavigatorSearchOpenComposer';
+import { NavigatorSearchSaveComposer } from './messages/outgoing/navigator/NavigatorSearchSaveComposer';
+import { NavigatorSettingsComposer } from './messages/outgoing/navigator/NavigatorSettingsComposer';
+import { NavigatorSettingsSaveComposer } from './messages/outgoing/navigator/NavigatorSettingsSaveComposer';
+import { OutgoingHeader } from './messages/outgoing/OutgoingHeader';
+import { PetRespectComposer } from './messages/outgoing/pet/PetRespectComposer';
+import { RequestPetInfoComposer } from './messages/outgoing/pet/RequestPetInfoComposer';
+import { RoomDoorbellAccessComposer } from './messages/outgoing/room/access/RoomDoorbellAccessComposer';
+import { RoomEnterComposer } from './messages/outgoing/room/access/RoomEnterComposer';
+import { RoomAmbassadorAlertComposer } from './messages/outgoing/room/action/RoomAmbassadorAlertComposer';
+import { RoomBanUserComposer } from './messages/outgoing/room/action/RoomBanUserComposer';
+import { RoomDeleteComposer } from './messages/outgoing/room/action/RoomDeleteComposer';
+import { RoomGiveRightsComposer } from './messages/outgoing/room/action/RoomGiveRightsComposer';
+import { RoomKickUserComposer } from './messages/outgoing/room/action/RoomKickUserComposer';
+import { RoomLikeRoomComposer } from './messages/outgoing/room/action/RoomLikeRoomComposer';
+import { RoomMuteUserComposer } from './messages/outgoing/room/action/RoomMuteUserComposer';
+import { RoomStaffPickComposer } from './messages/outgoing/room/action/RoomStaffPickComposer';
+import { RoomTakeRightsComposer } from './messages/outgoing/room/action/RoomTakeRightsComposer';
+import { RoomUnbanUserComposer } from './messages/outgoing/room/action/RoomUnbanUserComposer';
+import { RequestBotCommandConfigurationComposer } from './messages/outgoing/room/bots/RequestBotConfigurationComposer';
+import { RoomBannedUsersComposer } from './messages/outgoing/room/data/RoomBannedUsersComposer';
+import { RoomInfoComposer } from './messages/outgoing/room/data/RoomInfoComposer';
+import { RoomSettingsComposer } from './messages/outgoing/room/data/RoomSettingsComposer';
+import { RoomUsersWithRightsComposer } from './messages/outgoing/room/data/RoomUsersWithRightsComposer';
+import { SaveRoomSettingsComposer } from './messages/outgoing/room/data/SaveRoomSettingsComposer';
+import { BotPlaceComposer } from './messages/outgoing/room/engine/BotPlaceComposer';
+import { BotRemoveComposer } from './messages/outgoing/room/engine/BotRemoveComposer';
+import { BotSkillSaveComposer } from './messages/outgoing/room/engine/BotSkillSaveComposer';
+import { GetItemDataComposer } from './messages/outgoing/room/engine/GetItemDataComposer';
+import { ModifyWallItemDataComposer } from './messages/outgoing/room/engine/ModifyWallItemDataComposer';
+import { PetMoveComposer } from './messages/outgoing/room/engine/PetMoveComposer';
+import { PetPlaceComposer } from './messages/outgoing/room/engine/PetPlaceComposer';
+import { PetRemoveComposer } from './messages/outgoing/room/engine/PetRemoveComposer';
+import { RemoveWallItemComposer } from './messages/outgoing/room/engine/RemoveWallItemComposer';
+import { RoomAdsUpdateComposer } from './messages/outgoing/room/furniture/ads/RoomAdsUpdateComposer';
+import { MoodlightSettingsComposer } from './messages/outgoing/room/furniture/dimmer/MoodlightSettingsComposer';
+import { MoodlightSettingsSaveComposer } from './messages/outgoing/room/furniture/dimmer/MoodlightSettingsSaveComposer';
+import { MoodlightTogggleStateComposer } from './messages/outgoing/room/furniture/dimmer/MoodlightTogggleStateComposer';
+import { FurnitureFloorUpdateComposer } from './messages/outgoing/room/furniture/floor/FurnitureFloorUpdateComposer';
+import { FurnitureAliasesComposer } from './messages/outgoing/room/furniture/FurnitureAliasesComposer';
+import { FurniturePickupComposer } from './messages/outgoing/room/furniture/FurniturePickupComposer';
+import { FurniturePlaceComposer } from './messages/outgoing/room/furniture/FurniturePlaceComposer';
+import { FurniturePlacePaintComposer } from './messages/outgoing/room/furniture/FurniturePlacePaintComposer';
+import { FurniturePostItPlaceComposer } from './messages/outgoing/room/furniture/FurniturePostItPlaceComposer';
+import { FurnitureColorWheelComposer } from './messages/outgoing/room/furniture/logic/FurnitureColorWheelComposer';
+import { FurnitureDiceActivateComposer } from './messages/outgoing/room/furniture/logic/FurnitureDiceActivateComposer';
+import { FurnitureDiceDeactivateComposer } from './messages/outgoing/room/furniture/logic/FurnitureDiceDeactivateComposer';
+import { FurnitureExchangeComposer } from './messages/outgoing/room/furniture/logic/FurnitureExchangeComposer';
+import { FurnitureMultiStateComposer } from './messages/outgoing/room/furniture/logic/FurnitureMultiStateComposer';
+import { FurnitureOneWayDoorComposer } from './messages/outgoing/room/furniture/logic/FurnitureOneWayDoorComposer';
+import { FurnitureRandomStateComposer } from './messages/outgoing/room/furniture/logic/FurnitureRandomStateComposer';
+import { FurnitureStackHeightComposer } from './messages/outgoing/room/furniture/logic/FurnitureStackHeightComposer';
+import { FurnitureWallMultiStateComposer } from './messages/outgoing/room/furniture/logic/FurnitureWallMultiStateComposer';
+import { LoveLockStartConfirmComposer } from './messages/outgoing/room/furniture/logic/LoveLockStartConfirmComposer';
+import { FurnitureMannequinSaveLookComposer } from './messages/outgoing/room/furniture/mannequin/FurnitureMannequinSaveLookComposer';
+import { FurnitureMannequinSaveNameComposer } from './messages/outgoing/room/furniture/mannequin/FurnitureMannequinSaveNameComposer';
+import { OpenPresentComposer } from './messages/outgoing/room/furniture/presents/OpenPresentComposer';
+import { ApplyTonerComposer } from './messages/outgoing/room/furniture/toner/ApplyTonerComposer';
+import { FurnitureWallUpdateComposer } from './messages/outgoing/room/furniture/wall/FurnitureWallUpdateComposer';
+import { RoomModelComposer } from './messages/outgoing/room/mapping/RoomModelComposer';
+import { RoomCreateComposer } from './messages/outgoing/room/RoomCreateComposer';
+import { RoomUnitChatComposer } from './messages/outgoing/room/unit/chat/RoomUnitChatComposer';
+import { RoomUnitChatShoutComposer } from './messages/outgoing/room/unit/chat/RoomUnitChatShoutComposer';
+import { RoomUnitChatStyleComposer } from './messages/outgoing/room/unit/chat/RoomUnitChatStyleComposer';
+import { RoomUnitChatWhisperComposer } from './messages/outgoing/room/unit/chat/RoomUnitChatWhisperComposer';
+import { RoomUnitTypingStartComposer } from './messages/outgoing/room/unit/chat/RoomUnitTypingStartComposer';
+import { RoomUnitTypingStopComposer } from './messages/outgoing/room/unit/chat/RoomUnitTypingStopComposer';
+import { RoomUnitActionComposer } from './messages/outgoing/room/unit/RoomUnitActionComposer';
+import { RoomUnitDanceComposer } from './messages/outgoing/room/unit/RoomUnitDanceComposer';
+import { RoomUnitDropHandItemComposer } from './messages/outgoing/room/unit/RoomUnitDropHandItemComposer';
+import { RoomUnitGiveHandItemComposer } from './messages/outgoing/room/unit/RoomUnitGiveHandItemComposer';
+import { RoomUnitLookComposer } from './messages/outgoing/room/unit/RoomUnitLookComposer';
+import { RoomUnitPostureComposer } from './messages/outgoing/room/unit/RoomUnitPostureComposer';
+import { RoomUnitSignComposer } from './messages/outgoing/room/unit/RoomUnitSignComposer';
+import { RoomUnitWalkComposer } from './messages/outgoing/room/unit/RoomUnitWalkComposer';
+import { ApplySnapshotMessageComposer } from './messages/outgoing/roomevents/ApplySnapshotMessageComposer';
+import { OpenMessageComposer } from './messages/outgoing/roomevents/OpenMessageComposer';
+import { RoomMuteComposer } from './messages/outgoing/roomevents/RoomMuteComposer';
+import { UpdateActionMessageComposer } from './messages/outgoing/roomevents/UpdateActionMessageComposer';
+import { UpdateConditionMessageComposer } from './messages/outgoing/roomevents/UpdateConditionMessageComposer';
+import { UpdateTriggerMessageComposer } from './messages/outgoing/roomevents/UpdateTriggerMessageComposer';
+import { GetIgnoredUsersComposer } from './messages/outgoing/user/data/GetIgnoredUsersComposer';
+import { IgnoreUserComposer } from './messages/outgoing/user/data/IgnoreUserComposer';
+import { IgnoreUserIdComposer } from './messages/outgoing/user/data/IgnoreUserIdComposer';
+import { UnignoreUserComposer } from './messages/outgoing/user/data/UnignoreUserComposer';
+import { UserCurrentBadgesComposer } from './messages/outgoing/user/data/UserCurrentBadgesComposer';
+import { UserFigureComposer } from './messages/outgoing/user/data/UserFigureComposer';
+import { UserHomeRoomComposer } from './messages/outgoing/user/data/UserHomeRoomComposer';
+import { UserMottoComposer } from './messages/outgoing/user/data/UserMottoComposer';
+import { UserProfileComposer } from './messages/outgoing/user/data/UserProfileComposer';
+import { UserRelationshipsComposer } from './messages/outgoing/user/data/UserRelationshipsComposer';
+import { UserCurrencyComposer } from './messages/outgoing/user/inventory/currency/UserCurrencyComposer';
+import { UserSubscriptionComposer } from './messages/outgoing/user/inventory/subscription/UserSubscriptionComposer';
+import { UserSettingsCameraFollowComposer } from './messages/outgoing/user/settings/UserSettingsCameraFollowComposer';
+import { UserSettingsOldChatComposer } from './messages/outgoing/user/settings/UserSettingsOldChatComposer';
+import { UserSettingsRoomInvitesComposer } from './messages/outgoing/user/settings/UserSettingsRoomInvitesComposer';
+import { UserSettingsSoundComposer } from './messages/outgoing/user/settings/UserSettingsSoundComposer';
+import { UserRespectComposer } from './messages/outgoing/user/UserRespectComposer';
+import { UserWardrobePageComposer } from './messages/outgoing/user/wardrobe/UserWardrobePageComposer';
+import { UserWardrobeSaveComposer } from './messages/outgoing/user/wardrobe/UserWardrobeSaveComposer';
+import { MiniMailUnreadCountParser } from './messages/parser/friendlist/MiniMailUnreadCountParser';
+
+export class NitroMessages implements IMessageConfiguration
+{
+ private _events: Map;
+ private _composers: Map;
+
+ constructor()
+ {
+ this._events = new Map();
+ this._composers = new Map();
+
+ this.registerEvents();
+ this.registerComposers();
+ }
+
+ private registerEvents(): void
+ {
+ // AVAILABILITY
+ this._events.set(IncomingHeader.AVAILABILITY_STATUS, AvailabilityStatusMessageEvent);
+ this._events.set(IncomingHeader.GENERIC_ERROR, GenericErrorEvent);
+
+ // AVATAR
+ this._events.set(IncomingHeader.USER_CHANGE_NAME, ChangeNameUpdateEvent);
+
+ // CATALOG
+ this._events.set(IncomingHeader.CATALOG_CLUB, CatalogClubEvent);
+ this._events.set(IncomingHeader.CATALOG_MODE, CatalogModeEvent);
+ this._events.set(IncomingHeader.CATALOG_PAGE, CatalogPageEvent);
+ this._events.set(IncomingHeader.CATALOG_PAGES, CatalogPagesEvent);
+ this._events.set(IncomingHeader.CATALOG_PURCHASE, CatalogPurchaseEvent);
+ this._events.set(IncomingHeader.CATALOG_PURCHASE_FAILED, CatalogPurchaseFailedEvent);
+ this._events.set(IncomingHeader.CATALOG_PURCHASE_UNAVAILABLE, CatalogPurchaseUnavailableEvent);
+ this._events.set(IncomingHeader.CATALOG_SEARCH, CatalogSearchEvent);
+ this._events.set(IncomingHeader.CATALOG_SOLD_OUT, CatalogSoldOutEvent);
+ this._events.set(IncomingHeader.CATALOG_UPDATED, CatalogUpdatedEvent);
+ this._events.set(IncomingHeader.CATALOG_CLUB_GIFTS, CatalogClubGiftsEvent);
+ this._events.set(IncomingHeader.GROUP_LIST, CatalogGroupsEvent);
+ this._events.set(IncomingHeader.GIFT_CONFIG, CatalogGiftConfigurationEvent);
+ this._events.set(IncomingHeader.REDEEM_VOUCHER_ERROR, CatalogRedeemVoucherErrorEvent);
+ this._events.set(IncomingHeader.REDEEM_VOUCHER_OK, CatalogRedeemVoucherOkEvent);
+
+ // CLIENT
+ this._events.set(IncomingHeader.CLIENT_PING, ClientPingEvent);
+
+ // DESKTOP
+ this._events.set(IncomingHeader.DESKTOP_VIEW, DesktopViewEvent);
+
+ // FRIENDLIST
+ this._events.set(IncomingHeader.MESSENGER_ACCEPT_FRIENDS, AcceptFriendResultEvent);
+ this._events.set(IncomingHeader.MESSENGER_FIND_FRIENDS, FindFriendsProcessResultEvent);
+ this._events.set(IncomingHeader.MESSENGER_FOLLOW_FAILED, FollowFriendFailedEvent);
+ this._events.set(IncomingHeader.MESSENGER_FRIENDS, FriendListFragmentEvent);
+ this._events.set(IncomingHeader.MESSENGER_UPDATE, FriendListUpdateEvent);
+ this._events.set(IncomingHeader.MESSENGER_FRIEND_NOTIFICATION, FriendNotificationEvent);
+ this._events.set(IncomingHeader.MESSENGER_REQUESTS, FriendRequestsEvent);
+ this._events.set(IncomingHeader.MESSENGER_SEARCH, HabboSearchResultEvent);
+ this._events.set(IncomingHeader.MESSENGER_INSTANCE_MESSAGE_ERROR, InstantMessageErrorEvent);
+ this._events.set(IncomingHeader.MESSENGER_MESSAGE_ERROR, MessageErrorEvent);
+ this._events.set(IncomingHeader.MESSENGER_INIT, MessengerInitEvent);
+ this._events.set(IncomingHeader.MESSENGER_MINIMAIL_NEW, MiniMailNewMessageEvent);
+ this._events.set(IncomingHeader.MESSENGER_MINIMAIL_COUNT, MiniMailUnreadCountParser);
+ this._events.set(IncomingHeader.MESSENGER_CHAT, NewConsoleMessageEvent);
+ this._events.set(IncomingHeader.MESSENGER_REQUEST, NewFriendRequestEvent);
+ this._events.set(IncomingHeader.MESSENGER_INVITE_ERROR, RoomInviteErrorEvent);
+ this._events.set(IncomingHeader.MESSENGER_INVITE, RoomInviteEvent);
+
+ // GROUP
+ this._events.set(IncomingHeader.GROUP_INFO, GroupInformationEvent);
+ this._events.set(IncomingHeader.GROUP_MEMBER_REMOVE_CONFIRM, GroupConfirmMemberRemoveEvent);
+ this._events.set(IncomingHeader.GROUP_MEMBERS, GroupMembersEvent);
+ this._events.set(IncomingHeader.GROUP_CREATE_OPTIONS, GroupBuyDataEvent);
+ this._events.set(IncomingHeader.GROUP_BADGE_PARTS, GroupBadgePartsEvent);
+ this._events.set(IncomingHeader.GROUP_SETTINGS, GroupSettingsEvent);
+
+ // HELP
+ this._events.set(IncomingHeader.CFH_RESULT_MESSAGE, CallForHelpResultMessageEvent);
+
+ // INVENTORY
+
+ // ACHIEVEMENTS
+ this._events.set(IncomingHeader.ACHIEVEMENT_PROGRESSED, AchievementEvent);
+ this._events.set(IncomingHeader.ACHIEVEMENT_LIST, AchievementsEvent);
+ this._events.set(IncomingHeader.USER_ACHIEVEMENT_SCORE,AchievementsScoreEvent);
+
+ // EFFECTS
+ this._events.set(IncomingHeader.USER_EFFECT_ACTIVATE, AvatarEffectActivatedEvent);
+ this._events.set(IncomingHeader.USER_EFFECT_LIST_ADD, AvatarEffectAddedEvent);
+ this._events.set(IncomingHeader.USER_EFFECT_LIST_REMOVE, AvatarEffectExpiredEvent);
+ this._events.set(IncomingHeader.USER_EFFECT_LIST, AvatarEffectsEvent);
+
+ // CLOTHES
+ this._events.set(IncomingHeader.USER_CLOTHING, FigureSetIdsMessageEvent);
+
+ // FURNITURE
+ this._events.set(IncomingHeader.USER_FURNITURE_ADD, FurnitureListAddOrUpdateEvent);
+ this._events.set(IncomingHeader.USER_FURNITURE, FurnitureListEvent);
+ this._events.set(IncomingHeader.USER_FURNITURE_REFRESH, FurnitureListInvalidateEvent);
+ this._events.set(IncomingHeader.USER_FURNITURE_REMOVE, FurnitureListRemovedEvent);
+ this._events.set(IncomingHeader.USER_FURNITURE_POSTIT_PLACED, FurniturePostItPlacedEvent);
+
+ // TRADING
+ this._events.set(IncomingHeader.TRADE_ACCEPTED, TradingAcceptEvent);
+ this._events.set(IncomingHeader.TRADE_CLOSED, TradingCloseEvent);
+ this._events.set(IncomingHeader.TRADE_COMPLETED, TradingCompletedEvent);
+ this._events.set(IncomingHeader.TRADE_CONFIRMATION, TradingConfirmationEvent);
+ this._events.set(IncomingHeader.TRADE_LIST_ITEM, TradingListItemEvent);
+ this._events.set(IncomingHeader.TRADE_NOT_OPEN, TradingNotOpenEvent);
+ this._events.set(IncomingHeader.TRADE_OPEN_FAILED, TradingOpenFailedEvent);
+ this._events.set(IncomingHeader.TRADE_OPEN, TradingOpenEvent);
+ this._events.set(IncomingHeader.TRADE_OTHER_NOT_ALLOWED, TradingOtherNotAllowedEvent);
+ this._events.set(IncomingHeader.TRADE_YOU_NOT_ALLOWED, TradingYouAreNotAllowedEvent);
+
+ // MODERATION
+ this._events.set(IncomingHeader.GENERIC_ALERT_LINK, ModeratorMessageEvent);
+
+ // MODTOOL
+ this._events.set(IncomingHeader.MODTOOL_ROOM_INFO, ModtoolRoomInfoEvent);
+ this._events.set(IncomingHeader.MODTOOL_USER_CHATLOG, ModtoolUserChatlogEvent);
+ this._events.set(IncomingHeader.MODTOOL_ROOM_CHATLOG, ModtoolRoomChatlogEvent);
+
+ // NAVIGATOR
+ this._events.set(IncomingHeader.NAVIGATOR_CATEGORIES, NavigatorCategoriesEvent);
+ this._events.set(IncomingHeader.NAVIGATOR_COLLAPSED, NavigatorCollapsedEvent);
+ this._events.set(IncomingHeader.NAVIGATOR_EVENT_CATEGORIES, NavigatorEventCategoriesEvent);
+ this._events.set(IncomingHeader.USER_HOME_ROOM, NavigatorHomeRoomEvent);
+ this._events.set(IncomingHeader.NAVIGATOR_LIFTED, NavigatorLiftedEvent);
+ this._events.set(IncomingHeader.NAVIGATOR_METADATA, NavigatorMetadataEvent);
+ this._events.set(IncomingHeader.NAVIGATOR_OPEN_ROOM_CREATOR, NavigatorOpenRoomCreatorEvent);
+ this._events.set(IncomingHeader.NAVIGATOR_SEARCHES, NavigatorSearchesEvent);
+ this._events.set(IncomingHeader.NAVIGATOR_SEARCH, NavigatorSearchEvent);
+ this._events.set(IncomingHeader.NAVIGATOR_SETTINGS, NavigatorSettingsEvent);
+
+ // NOTIFICATIONS
+ this._events.set(IncomingHeader.GENERIC_ALERT, HabboBroadcastMessageEvent);
+ this._events.set(IncomingHeader.MOTD_MESSAGES, MOTDNotificationEvent);
+ this._events.set(IncomingHeader.NOTIFICATION_LIST, NotificationDialogMessageEvent);
+ this._events.set(IncomingHeader.USER_RESPECT, RespectReceivedEvent);
+ this._events.set(IncomingHeader.UNSEEN_ITEMS, UnseenItemsEvent);
+ this._events.set(IncomingHeader.HOTEL_WILL_SHUTDOWN, HotelWillShutdownEvent);
+
+ // ROOM
+
+ // ACCESS
+ this._events.set(IncomingHeader.ROOM_ENTER_ERROR, RoomEnterErrorEvent);
+ this._events.set(IncomingHeader.ROOM_ENTER, RoomEnterEvent);
+ this._events.set(IncomingHeader.ROOM_FORWARD, RoomForwardEvent);
+
+ // DOORBELL
+ this._events.set(IncomingHeader.ROOM_DOORBELL, RoomDoorbellEvent);
+ this._events.set(IncomingHeader.ROOM_DOORBELL_ACCEPTED, RoomDoorbellAcceptedEvent);
+ this._events.set(IncomingHeader.ROOM_DOORBELL_REJECTED, RoomDoorbellRejectedEvent);
+
+ // RIGHTS
+ this._events.set(IncomingHeader.ROOM_RIGHTS_CLEAR, RoomRightsClearEvent);
+ this._events.set(IncomingHeader.ROOM_RIGHTS_OWNER, RoomRightsOwnerEvent);
+ this._events.set(IncomingHeader.ROOM_RIGHTS, RoomRightsEvent);
+
+ // DATA
+ this._events.set(IncomingHeader.ROOM_SETTINGS_CHAT, RoomChatSettingsEvent);
+ this._events.set(IncomingHeader.ROOM_INFO, RoomInfoEvent);
+ this._events.set(IncomingHeader.ROOM_INFO_OWNER, RoomInfoOwnerEvent);
+ this._events.set(IncomingHeader.ROOM_SCORE, RoomScoreEvent);
+ this._events.set(IncomingHeader.ROOM_SETTINGS_SAVE_ERROR, RoomSettingsErrorEvent);
+ this._events.set(IncomingHeader.ROOM_SETTINGS, RoomSettingsEvent);
+ this._events.set(IncomingHeader.ROOM_SETTINGS_SAVE, RoomSettingsSavedEvent);
+ this._events.set(IncomingHeader.ROOM_SETTINGS_UPDATED, RoomSettingsUpdatedEvent);
+ this._events.set(IncomingHeader.ROOM_RIGHTS_LIST, RoomUsersWithRightsEvent);
+ this._events.set(IncomingHeader.ROOM_BAN_LIST, RoomBannedUsersEvent);
+
+ // ENGINE
+ this._events.set(IncomingHeader.ROOM_ROLLING, ObjectsRollingEvent);
+ this._events.set(IncomingHeader.ROOM_CREATED, RoomCreatedEvent);
+
+ // BOTS
+ this._events.set(IncomingHeader.BOT_COMMAND_CONFIGURATION, BotCommandConfigurationEvent);
+ this._events.set(IncomingHeader.BOT_ERROR, BotErrorEvent);
+
+ // FURNITURE
+ this._events.set(IncomingHeader.FURNITURE_ALIASES, FurnitureAliasesEvent);
+ this._events.set(IncomingHeader.FURNITURE_DATA, FurnitureDataEvent);
+ this._events.set(IncomingHeader.FURNITURE_ITEMDATA, FurnitureItemDataEvent);
+ this._events.set(IncomingHeader.ITEM_STACK_HELPER, FurnitureStackHeightEvent);
+ this._events.set(IncomingHeader.FURNITURE_STATE, FurnitureStateEvent);
+ this._events.set(IncomingHeader.ITEM_DIMMER_SETTINGS, RoomDimmerPresetsEvent);
+ this._events.set(IncomingHeader.FURNITURE_STATE_2, FurnitureState2Event);
+ this._events.set(IncomingHeader.LOVELOCK_FURNI_FINISHED, LoveLockFurniFinishedEvent);
+ this._events.set(IncomingHeader.LOVELOCK_FURNI_FRIEND_COMFIRMED, LoveLockFurniFriendConfirmedEvent);
+ this._events.set(IncomingHeader.LOVELOCK_FURNI_START, LoveLockFurniStartEvent);
+
+ // FLOOR
+ this._events.set(IncomingHeader.FURNITURE_FLOOR_ADD, FurnitureFloorAddEvent);
+ this._events.set(IncomingHeader.FURNITURE_FLOOR, FurnitureFloorEvent);
+ this._events.set(IncomingHeader.FURNITURE_FLOOR_REMOVE, FurnitureFloorRemoveEvent);
+ this._events.set(IncomingHeader.FURNITURE_FLOOR_UPDATE, FurnitureFloorUpdateEvent);
+
+ // WALL
+ this._events.set(IncomingHeader.ITEM_WALL_ADD, FurnitureWallAddEvent);
+ this._events.set(IncomingHeader.ITEM_WALL, FurnitureWallEvent);
+ this._events.set(IncomingHeader.ITEM_WALL_REMOVE, FurnitureWallRemoveEvent);
+ this._events.set(IncomingHeader.ITEM_WALL_UPDATE, FurnitureWallUpdateEvent);
+
+ // MAPPING
+ this._events.set(IncomingHeader.ROOM_MODEL_DOOR, RoomDoorEvent);
+ this._events.set(IncomingHeader.ROOM_HEIGHT_MAP, RoomHeightMapEvent);
+ this._events.set(IncomingHeader.ROOM_HEIGHT_MAP_UPDATE, RoomHeightMapUpdateEvent);
+ this._events.set(IncomingHeader.ROOM_MODEL, RoomModelEvent);
+ this._events.set(IncomingHeader.ROOM_MODEL_NAME, RoomModelNameEvent);
+ this._events.set(IncomingHeader.ROOM_PAINT, RoomPaintEvent);
+ this._events.set(IncomingHeader.ROOM_THICKNESS, RoomThicknessEvent);
+
+ // PET
+ this._events.set(IncomingHeader.PET_FIGURE_UPDATE, PetFigureUpdateEvent);
+ this._events.set(IncomingHeader.PET_INFO, PetInfoEvent);
+
+ // SESSION
+ this._events.set(IncomingHeader.PLAYING_GAME, YouArePlayingGameEvent);
+
+ // UNIT
+ this._events.set(IncomingHeader.UNIT_DANCE, RoomUnitDanceEvent);
+ this._events.set(IncomingHeader.UNIT_EFFECT, RoomUnitEffectEvent);
+ this._events.set(IncomingHeader.UNIT, RoomUnitEvent);
+ this._events.set(IncomingHeader.UNIT_EXPRESSION, RoomUnitExpressionEvent);
+ this._events.set(IncomingHeader.UNIT_HAND_ITEM, RoomUnitHandItemEvent);
+ this._events.set(IncomingHeader.UNIT_IDLE, RoomUnitIdleEvent);
+ this._events.set(IncomingHeader.UNIT_INFO, RoomUnitInfoEvent);
+ this._events.set(IncomingHeader.UNIT_NUMBER, RoomUnitNumberEvent);
+ this._events.set(IncomingHeader.UNIT_REMOVE, RoomUnitRemoveEvent);
+ this._events.set(IncomingHeader.UNIT_STATUS, RoomUnitStatusEvent);
+ this._events.set(IncomingHeader.HAND_ITEM_RECEIVED, RoomUnitHandItemReceivedEvent);
+
+ // CHAT
+ this._events.set(IncomingHeader.FLOOD_CONTROL, FloodControlEvent);
+ this._events.set(IncomingHeader.REMAINING_MUTE, RemainingMuteEvent);
+ this._events.set(IncomingHeader.UNIT_CHAT, RoomUnitChatEvent);
+ this._events.set(IncomingHeader.UNIT_CHAT_SHOUT, RoomUnitChatShoutEvent);
+ this._events.set(IncomingHeader.UNIT_CHAT_WHISPER, RoomUnitChatWhisperEvent);
+ this._events.set(IncomingHeader.UNIT_TYPING, RoomUnitTypingEvent);
+
+ // ROOM EVENTS
+ this._events.set(IncomingHeader.WIRED_ACTION, WiredFurniActionEvent);
+ this._events.set(IncomingHeader.WIRED_CONDITION, WiredFurniConditionEvent);
+ this._events.set(IncomingHeader.WIRED_TRIGGER, WiredFurniTriggerEvent);
+ this._events.set(IncomingHeader.WIRED_OPEN, WiredOpenEvent);
+ this._events.set(IncomingHeader.WIRED_REWARD, WiredRewardResultMessageEvent);
+ this._events.set(IncomingHeader.WIRED_SAVE, WiredSaveSuccessEvent);
+ this._events.set(IncomingHeader.WIRED_ERROR, WiredValidationErrorEvent);
+ this._events.set(IncomingHeader.ROOM_MUTED, RoomMutedEvent);
+
+ // SECURITY
+ this._events.set(IncomingHeader.AUTHENTICATED, AuthenticatedEvent);
+
+ // USER
+ this._events.set(IncomingHeader.IN_CLIENT_LINK, InClientLinkEvent);
+ this._events.set(IncomingHeader.USER_IGNORED, IgnoredUsersEvent);
+ this._events.set(IncomingHeader.USER_IGNORED_RESULT, IgnoreResultEvent);
+
+ // BADGES
+ this._events.set(IncomingHeader.USER_BADGES, BadgesEvent);
+
+ // ACCESS
+ this._events.set(IncomingHeader.USER_PERKS, UserPerksEvent);
+ this._events.set(IncomingHeader.USER_PERMISSIONS, UserPermissionsEvent);
+
+ // DATA
+ this._events.set(IncomingHeader.USER_BADGES_CURRENT, UserCurrentBadgesEvent);
+ this._events.set(IncomingHeader.USER_FIGURE, UserFigureEvent);
+ this._events.set(IncomingHeader.USER_INFO, UserInfoEvent);
+ this._events.set(IncomingHeader.UNIT_CHANGE_NAME, UserNameChangeMessageEvent);
+ this._events.set(IncomingHeader.USER_SETTINGS, UserSettingsEvent);
+ this._events.set(IncomingHeader.USER_PROFILE, UserProfileEvent);
+ this._events.set(IncomingHeader.MESSENGER_RELATIONSHIPS, UserRelationshipsEvent);
+
+ // GIFTS
+ this._events.set(IncomingHeader.GIFT_OPENED, FurnitureGiftOpenedEvent);
+
+ // INVENTORY
+ this._events.set(IncomingHeader.GIFT_RECEIVER_NOT_FOUND, CatalogGiftUsernameUnavailableEvent);
+
+ // BOTS
+ this._events.set(IncomingHeader.USER_BOTS, BotInventoryMessageEvent);
+ this._events.set(IncomingHeader.REMOVE_BOT_FROM_INVENTORY, BotRemovedFromInventoryEvent);
+ this._events.set(IncomingHeader.ADD_BOT_TO_INVENTORY, BotAddedToInventoryEvent);
+
+ // CURRENCY
+ this._events.set(IncomingHeader.USER_CREDITS, UserCreditsEvent);
+ this._events.set(IncomingHeader.USER_CURRENCY, UserCurrencyEvent);
+ this._events.set(IncomingHeader.USER_CURRENCY_UPDATE, UserCurrencyUpdateEvent);
+
+ // SUBSCRIPTION
+ this._events.set(IncomingHeader.USER_SUBSCRIPTION, UserSubscriptionEvent);
+
+ // GAMES
+ this._events.set(IncomingHeader.LOAD_GAME_URL, LoadGameUrlEvent);
+
+ // WARDROBE
+ this._events.set(IncomingHeader.USER_WARDROBE_PAGE, UserWardrobePageEvent);
+
+ // PETS
+ this._events.set(IncomingHeader.USER_PETS, PetInventoryEvent);
+ this._events.set(IncomingHeader.USER_PET_REMOVE, PetRemovedFromInventory);
+ this._events.set(IncomingHeader.USER_PET_ADD, PetAddedToInventoryEvent);
+ this._events.set(IncomingHeader.PET_PLACING_ERROR, PetPlacingErrorEvent);
+
+ // MOD TOOL
+ this._events.set(IncomingHeader.MODERATION_USER_INFO, ModtoolUserInfoEvent);
+ this._events.set(IncomingHeader.MODERATION_TOPICS, ModtoolCallForHelpTopicsEvent);
+ this._events.set(IncomingHeader.MODERATION_TOOL, ModtoolMainEvent);
+ this._events.set(IncomingHeader.MODTOOL_VISITED_ROOMS_USER, ModtoolReceivedRoomsUserEvent);
+ }
+
+ private registerComposers(): void
+ {
+ // CATALOG
+ this._composers.set(OutgoingHeader.CATALOG_MODE, CatalogModeComposer);
+ this._composers.set(OutgoingHeader.CATALOG_PAGE, CatalogPageComposer);
+ this._composers.set(OutgoingHeader.CATALOG_PURCHASE, CatalogPurchaseComposer);
+ this._composers.set(OutgoingHeader.CATALOG_PURCHASE_GIFT, CatalogPurchaseGiftComposer);
+ this._composers.set(OutgoingHeader.CATALOG_SEARCH, CatalogSearchComposer);
+ this._composers.set(OutgoingHeader.CATALOG_CLUB, CatalogRequestVipOffersComposer);
+ this._composers.set(OutgoingHeader.CATALOG_CLUB_GIFTS, CatalogRequestVipGiftsComposer);
+ this._composers.set(OutgoingHeader.CATALOG_REDEEM_VOUCHER, CatalogRedeemVoucherComposer);
+ this._composers.set(OutgoingHeader.LOVELOCK_START_CONFIRM, LoveLockStartConfirmComposer);
+ this._composers.set(OutgoingHeader.GROUP_MEMBERSHIPS, CatalogGroupsComposer);
+ this._composers.set(OutgoingHeader.GIFT_CONFIG, CatalogRequestGiftConfigurationComposer);
+ this._composers.set(OutgoingHeader.CATALOG_SELECT_VIP_GIFT, CatalogSelectClubGiftComposer);
+
+ // CLIENT
+ this._composers.set(OutgoingHeader.CLIENT_PONG, ClientPongComposer);
+ this._composers.set(OutgoingHeader.RELEASE_VERSION, ClientReleaseVersionComposer);
+
+ // DESKTOP
+ this._composers.set(OutgoingHeader.DESKTOP_VIEW, DesktopViewComposer);
+
+ // FRIENDLIST
+ this._composers.set(OutgoingHeader.MESSENGER_ACCEPT, AcceptFriendComposer);
+ this._composers.set(OutgoingHeader.MESSENGER_DECLINE, DeclineFriendComposer);
+ this._composers.set(OutgoingHeader.FIND_FRIENDS, FindNewFriendsComposer);
+ this._composers.set(OutgoingHeader.MESSENGER_FOLLOW, FollowFriendComposer);
+ this._composers.set(OutgoingHeader.MESSENGER_UPDATES, FriendListUpdateComposer);
+ this._composers.set(OutgoingHeader.MESSENGER_REQUESTS, GetFriendRequestsComposer);
+ this._composers.set(OutgoingHeader.MESSENGER_SEARCH, HabboSearchComposer);
+ this._composers.set(OutgoingHeader.MESSENGER_INIT, MessengerInitComposer);
+ this._composers.set(OutgoingHeader.MESSENGER_REMOVE, RemoveFriendComposer);
+ this._composers.set(OutgoingHeader.MESSENGER_REQUEST, RequestFriendComposer);
+ this._composers.set(OutgoingHeader.MESSENGER_CHAT, SendMessageComposer);
+ this._composers.set(OutgoingHeader.MESSENGER_ROOM_INVITE, SendRoomInviteComposer);
+ this._composers.set(OutgoingHeader.MESSENGER_RELATIONSHIPS_UPDATE, SetRelationshipStatusComposer);
+ this._composers.set(OutgoingHeader.USER_VISIT, VisitUserComposer);
+
+ // GROUP
+ this._composers.set(OutgoingHeader.GROUP_INFO, GroupInformationComposer);
+ this._composers.set(OutgoingHeader.GROUP_REQUEST, GroupJoinComposer);
+ this._composers.set(OutgoingHeader.GROUP_MEMBER_REMOVE_CONFIRM, GroupConfirmRemoveMemberComposer);
+ this._composers.set(OutgoingHeader.GROUP_MEMBER_REMOVE, GroupRemoveMemberComposer);
+ this._composers.set(OutgoingHeader.GROUP_MEMBERS, GroupMembersComposer);
+ this._composers.set(OutgoingHeader.GROUP_ADMIN_ADD, GroupAdminGiveComposer);
+ this._composers.set(OutgoingHeader.GROUP_ADMIN_REMOVE, GroupAdminTakeComposer);
+ this._composers.set(OutgoingHeader.GROUP_REQUEST_ACCEPT, GroupMembershipAcceptComposer);
+ this._composers.set(OutgoingHeader.GROUP_REQUEST_DECLINE, GroupMembershipDeclineComposer);
+ this._composers.set(OutgoingHeader.GROUP_DELETE, GroupDeleteComposer);
+ this._composers.set(OutgoingHeader.GROUP_CREATE_OPTIONS, GroupBuyDataComposer);
+ this._composers.set(OutgoingHeader.GROUP_PARTS, GroupBadgePartsComposer);
+ this._composers.set(OutgoingHeader.GROUP_BUY, GroupBuyComposer);
+ this._composers.set(OutgoingHeader.GROUP_SETTINGS, GroupSettingsComposer);
+ this._composers.set(OutgoingHeader.GROUP_SAVE_BADGE, GroupSaveBadgeComposer);
+ this._composers.set(OutgoingHeader.GROUP_SAVE_COLORS, GroupSaveColorsComposer);
+ this._composers.set(OutgoingHeader.GROUP_SAVE_INFORMATION, GroupSaveInformationComposer);
+ this._composers.set(OutgoingHeader.GROUP_SAVE_PREFERENCES, GroupSavePreferencesComposer);
+
+ // SECURITY
+ this._composers.set(OutgoingHeader.SECURITY_TICKET, SecurityTicketComposer);
+ this._composers.set(OutgoingHeader.USER_INFO, InfoRetrieveBaseMessageComposer);
+
+ // NAVIGATOR
+ this._composers.set(OutgoingHeader.NAVIGATOR_CATEGORIES, NavigatorCategoriesComposer);
+ this._composers.set(OutgoingHeader.NAVIGATOR_INIT, NavigatorInitComposer);
+ this._composers.set(OutgoingHeader.NAVIGATOR_SEARCH_CLOSE, NavigatorSearchCloseComposer);
+ this._composers.set(OutgoingHeader.NAVIGATOR_SEARCH, NavigatorSearchComposer);
+ this._composers.set(OutgoingHeader.NAVIGATOR_SEARCH_OPEN, NavigatorSearchOpenComposer);
+ this._composers.set(OutgoingHeader.NAVIGATOR_SEARCH_SAVE, NavigatorSearchSaveComposer);
+ this._composers.set(OutgoingHeader.NAVIGATOR_SETTINGS, NavigatorSettingsComposer);
+ this._composers.set(OutgoingHeader.NAVIGATOR_SETTINGS_SAVE, NavigatorSettingsSaveComposer);
+ this._composers.set(OutgoingHeader.NAVIGATOR_CATEGORY_LIST_MODE, NavigatorCategoryListModeComposer);
+ this._composers.set(OutgoingHeader.CONVERT_GLOBAL_ROOM_ID, ConvertGlobalRoomIdMessageComposer);
+
+ // INVENTORY
+
+ // FURNI
+ this._composers.set(OutgoingHeader.USER_FURNITURE, FurnitureListComposer);
+ this._composers.set(OutgoingHeader.USER_FURNITURE2, FurnitureList2Composer);
+ this._composers.set(OutgoingHeader.ITEM_SAVE_BACKGROUND, RoomAdsUpdateComposer);
+
+ // TRADING
+ this._composers.set(OutgoingHeader.TRADE_ACCEPT, TradingAcceptComposer);
+ this._composers.set(OutgoingHeader.TRADE_CANCEL, TradingCancelComposer);
+ this._composers.set(OutgoingHeader.TRADE_CLOSE, TradingCloseComposer);
+ this._composers.set(OutgoingHeader.TRADE_CONFIRM, TradingConfirmationComposer);
+ this._composers.set(OutgoingHeader.TRADE_ITEM, TradingListAddItemComposer);
+ this._composers.set(OutgoingHeader.TRADE_ITEMS, TradingListAddItemsComposer);
+ this._composers.set(OutgoingHeader.TRADE_ITEM_REMOVE, TradingListItemRemoveComposer);
+ this._composers.set(OutgoingHeader.TRADE, TradingOpenComposer);
+ this._composers.set(OutgoingHeader.TRADE_UNACCEPT, TradingUnacceptComposer);
+
+ // ACHIVEMENTS
+ this._composers.set(OutgoingHeader.ACHIEVEMENT_LIST, RequestAchievementsMessageComposer);
+
+ // PET
+ this._composers.set(OutgoingHeader.PET_RESPECT, PetRespectComposer);
+ this._composers.set(OutgoingHeader.PET_INFO, RequestPetInfoComposer);
+
+ // ROOM
+ this._composers.set(OutgoingHeader.ROOM_CREATE, RoomCreateComposer);
+
+ // ACCESS
+ this._composers.set(OutgoingHeader.ROOM_ENTER, RoomEnterComposer);
+ this._composers.set(OutgoingHeader.ROOM_DOORBELL, RoomDoorbellAccessComposer);
+
+ // ACTION
+ this._composers.set(OutgoingHeader.ROOM_AMBASSADOR_ALERT, RoomAmbassadorAlertComposer);
+ this._composers.set(OutgoingHeader.ROOM_BAN_GIVE, RoomBanUserComposer);
+ this._composers.set(OutgoingHeader.ROOM_BAN_REMOVE, RoomUnbanUserComposer);
+ this._composers.set(OutgoingHeader.ROOM_RIGHTS_GIVE, RoomGiveRightsComposer);
+ this._composers.set(OutgoingHeader.ROOM_KICK, RoomKickUserComposer);
+ this._composers.set(OutgoingHeader.ROOM_MUTE_USER, RoomMuteUserComposer);
+ this._composers.set(OutgoingHeader.ROOM_RIGHTS_REMOVE, RoomTakeRightsComposer);
+
+ this._composers.set(OutgoingHeader.ROOM_LIKE, RoomLikeRoomComposer);
+ this._composers.set(OutgoingHeader.ROOM_DELETE, RoomDeleteComposer);
+ this._composers.set(OutgoingHeader.ROOM_STAFF_PICK, RoomStaffPickComposer);
+
+ // DATA
+ this._composers.set(OutgoingHeader.ROOM_INFO, RoomInfoComposer);
+ this._composers.set(OutgoingHeader.ROOM_SETTINGS, RoomSettingsComposer);
+ this._composers.set(OutgoingHeader.ROOM_SETTINGS_SAVE, SaveRoomSettingsComposer);
+ this._composers.set(OutgoingHeader.ROOM_RIGHTS_LIST, RoomUsersWithRightsComposer);
+ this._composers.set(OutgoingHeader.ROOM_BAN_LIST, RoomBannedUsersComposer);
+
+ // BOTS
+ this._composers.set(OutgoingHeader.BOT_CONFIGURATION, RequestBotCommandConfigurationComposer);
+
+ // ENGINE
+ this._composers.set(OutgoingHeader.GET_ITEM_DATA, GetItemDataComposer);
+ this._composers.set(OutgoingHeader.REMOVE_WALL_ITEM, RemoveWallItemComposer);
+ this._composers.set(OutgoingHeader.MODIFY_WALL_ITEM_DATA, ModifyWallItemDataComposer);
+ this._composers.set(OutgoingHeader.BOT_PLACE, BotPlaceComposer);
+ this._composers.set(OutgoingHeader.BOT_PICKUP, BotRemoveComposer);
+ this._composers.set(OutgoingHeader.BOT_SKILL_SAVE, BotSkillSaveComposer);
+ this._composers.set(OutgoingHeader.PET_PLACE, PetPlaceComposer);
+ this._composers.set(OutgoingHeader.PET_MOVE, PetMoveComposer);
+ this._composers.set(OutgoingHeader.PET_PICKUP, PetRemoveComposer);
+
+ // FURNITURE
+ this._composers.set(OutgoingHeader.FURNITURE_ALIASES, FurnitureAliasesComposer);
+ this._composers.set(OutgoingHeader.FURNITURE_PICKUP, FurniturePickupComposer);
+ this._composers.set(OutgoingHeader.FURNITURE_PLACE, FurniturePlaceComposer);
+ this._composers.set(OutgoingHeader.ITEM_PAINT, FurniturePlacePaintComposer);
+ this._composers.set(OutgoingHeader.FURNITURE_POSTIT_PLACE, FurniturePostItPlaceComposer);
+
+ // FLOOR
+ this._composers.set(OutgoingHeader.FURNITURE_FLOOR_UPDATE, FurnitureFloorUpdateComposer);
+
+ // WALL
+ this._composers.set(OutgoingHeader.FURNITURE_WALL_UPDATE, FurnitureWallUpdateComposer);
+
+ // Dimmers
+ this._composers.set(OutgoingHeader.ITEM_DIMMER_SETTINGS, MoodlightSettingsComposer);
+ this._composers.set(OutgoingHeader.ITEM_DIMMER_SAVE, MoodlightSettingsSaveComposer);
+ this._composers.set(OutgoingHeader.ITEM_DIMMER_TOGGLE, MoodlightTogggleStateComposer);
+
+ // Toners
+ this._composers.set(OutgoingHeader.ROOM_TONER_APPLY, ApplyTonerComposer);
+
+ // LOGIC
+ this._composers.set(OutgoingHeader.ITEM_COLOR_WHEEL_CLICK, FurnitureColorWheelComposer);
+ this._composers.set(OutgoingHeader.ITEM_DICE_CLICK, FurnitureDiceActivateComposer);
+ this._composers.set(OutgoingHeader.ITEM_DICE_CLOSE, FurnitureDiceDeactivateComposer);
+ this._composers.set(OutgoingHeader.FURNITURE_MULTISTATE, FurnitureMultiStateComposer);
+ this._composers.set(OutgoingHeader.FURNITURE_RANDOMSTATE, FurnitureRandomStateComposer);
+ this._composers.set(OutgoingHeader.ITEM_STACK_HELPER, FurnitureStackHeightComposer);
+ this._composers.set(OutgoingHeader.FURNITURE_WALL_MULTISTATE, FurnitureWallMultiStateComposer);
+ this._composers.set(OutgoingHeader.ONE_WAY_DOOR_CLICK, FurnitureOneWayDoorComposer);
+ this._composers.set(OutgoingHeader.ITEM_EXCHANGE_REDEEM, FurnitureExchangeComposer);
+ this._composers.set(OutgoingHeader.ITEM_CLOTHING_REDEEM, RedeemItemClothingComposer);
+
+ // MAPPING
+ this._composers.set(OutgoingHeader.ROOM_MODEL, RoomModelComposer);
+
+ // UNIT
+ this._composers.set(OutgoingHeader.UNIT_ACTION, RoomUnitActionComposer);
+ this._composers.set(OutgoingHeader.UNIT_DANCE, RoomUnitDanceComposer);
+ this._composers.set(OutgoingHeader.UNIT_DROP_HAND_ITEM, RoomUnitDropHandItemComposer);
+ this._composers.set(OutgoingHeader.UNIT_GIVE_HANDITEM, RoomUnitGiveHandItemComposer);
+ this._composers.set(OutgoingHeader.UNIT_LOOK, RoomUnitLookComposer);
+ this._composers.set(OutgoingHeader.UNIT_SIGN, RoomUnitSignComposer);
+ this._composers.set(OutgoingHeader.UNIT_POSTURE, RoomUnitPostureComposer);
+ this._composers.set(OutgoingHeader.UNIT_WALK, RoomUnitWalkComposer);
+
+ // CHAT
+ this._composers.set(OutgoingHeader.UNIT_CHAT, RoomUnitChatComposer);
+ this._composers.set(OutgoingHeader.UNIT_CHAT_SHOUT, RoomUnitChatShoutComposer);
+ this._composers.set(OutgoingHeader.USER_SETTINGS_CHAT_STYLE, RoomUnitChatStyleComposer);
+ this._composers.set(OutgoingHeader.UNIT_CHAT_WHISPER, RoomUnitChatWhisperComposer);
+ this._composers.set(OutgoingHeader.UNIT_TYPING, RoomUnitTypingStartComposer);
+ this._composers.set(OutgoingHeader.UNIT_TYPING_STOP, RoomUnitTypingStopComposer);
+
+ // ROOM EVENTS
+ this._composers.set(OutgoingHeader.WIRED_APPLY_SNAPSHOT, ApplySnapshotMessageComposer);
+ this._composers.set(OutgoingHeader.WIRED_OPEN, OpenMessageComposer);
+ this._composers.set(OutgoingHeader.WIRED_ACTION_SAVE, UpdateActionMessageComposer);
+ this._composers.set(OutgoingHeader.WIRED_CONDITION_SAVE, UpdateConditionMessageComposer);
+ this._composers.set(OutgoingHeader.WIRED_TRIGGER_SAVE, UpdateTriggerMessageComposer);
+ this._composers.set(OutgoingHeader.ROOM_MUTE, RoomMuteComposer);
+
+ // USER
+ this._composers.set(OutgoingHeader.USER_RESPECT, UserRespectComposer);
+
+ // DATA
+ this._composers.set(OutgoingHeader.USER_IGNORED, GetIgnoredUsersComposer);
+ this._composers.set(OutgoingHeader.USER_IGNORE, IgnoreUserComposer);
+ this._composers.set(OutgoingHeader.USER_IGNORE_ID, IgnoreUserIdComposer);
+ this._composers.set(OutgoingHeader.USER_UNIGNORE, UnignoreUserComposer);
+ this._composers.set(OutgoingHeader.USER_BADGES_CURRENT, UserCurrentBadgesComposer);
+ this._composers.set(OutgoingHeader.USER_FIGURE, UserFigureComposer);
+ this._composers.set(OutgoingHeader.USER_HOME_ROOM, UserHomeRoomComposer);
+ this._composers.set(OutgoingHeader.USER_MOTTO, UserMottoComposer);
+ this._composers.set(OutgoingHeader.USER_PROFILE, UserProfileComposer);
+ this._composers.set(OutgoingHeader.MESSENGER_RELATIONSHIPS, UserRelationshipsComposer);
+
+ // MANNEQUIN
+ this._composers.set(OutgoingHeader.MANNEQUIN_SAVE_NAME, FurnitureMannequinSaveNameComposer);
+ this._composers.set(OutgoingHeader.MANNEQUIN_SAVE_LOOK, FurnitureMannequinSaveLookComposer);
+
+ // GIFTS
+ this._composers.set(OutgoingHeader.PRESENT_OPEN_PRESENT, OpenPresentComposer);
+
+ // INVENTORY
+
+ // BOTS
+ this._composers.set(OutgoingHeader.USER_BOTS, GetBotInventoryComposer);
+
+ // BADGES
+ this._composers.set(OutgoingHeader.USER_BADGES, RequestBadgesComposer);
+ this._composers.set(OutgoingHeader.USER_BADGES_CURRENT_UPDATE, SetActivatedBadgesComposer);
+
+ // PETS
+ this._composers.set(OutgoingHeader.USER_PETS, RequestPetsComposer);
+
+ // CURRENCY
+ this._composers.set(OutgoingHeader.USER_CURRENCY, UserCurrencyComposer);
+
+ // SUBSCRIPTION
+ this._composers.set(OutgoingHeader.USER_SUBSCRIPTION, UserSubscriptionComposer);
+
+ // MODTOOL
+ this._composers.set(OutgoingHeader.MODTOOL_REQUEST_ROOM_INFO, ModtoolRequestRoomInfoComposer);
+ this._composers.set(OutgoingHeader.MODTOOL_CHANGE_ROOM_SETTINGS, ModtoolChangeRoomSettingsComposer);
+ this._composers.set(OutgoingHeader.MODTOOL_REQUEST_USER_CHATLOG, ModtoolRequestUserChatlogComposer);
+ this._composers.set(OutgoingHeader.MODTOOL_REQUEST_ROOM_CHATLOG, ModtoolRequestRoomChatlogComposer);
+ this._composers.set(OutgoingHeader.MOD_TOOL_USER_INFO, ModtoolRequestUserInfoComposer);
+ this._composers.set(OutgoingHeader.MODTOOL_SANCTION_ALERT, ModtoolSanctionAlertComposer);
+ this._composers.set(OutgoingHeader.MODTOOL_SANCTION_BAN, ModtoolSanctionBanComposer);
+ this._composers.set(OutgoingHeader.MODTOOL_SANCTION_KICK, ModtoolSanctionKickComposer);
+ this._composers.set(OutgoingHeader.MODTOOL_SANCTION_TRADELOCK, ModtoolSanctionTradelockComposer);
+ this._composers.set(OutgoingHeader.MODTOOL_ALERTEVENT, ModtoolEventAlertComposer);
+ this._composers.set(OutgoingHeader.MODTOOL_SANCTION_MUTE, ModtoolSanctionMuteComposer);
+ this._composers.set(OutgoingHeader.MODTOOL_REQUEST_USER_ROOMS, ModtoolRequestUserRoomsComposer);
+ this._composers.set(OutgoingHeader.MODTOOL_ROOM_ALERT, ModtoolRoomAlertComposer);
+
+ // WARDROBE
+ this._composers.set(OutgoingHeader.USER_WARDROBE_PAGE, UserWardrobePageComposer);
+ this._composers.set(OutgoingHeader.USER_WARDROBE_SAVE, UserWardrobeSaveComposer);
+
+ // SETTINGS
+ this._composers.set(OutgoingHeader.USER_SETTINGS_CAMERA, UserSettingsCameraFollowComposer);
+ this._composers.set(OutgoingHeader.USER_SETTINGS_OLD_CHAT, UserSettingsOldChatComposer);
+ this._composers.set(OutgoingHeader.USER_SETTINGS_INVITES, UserSettingsRoomInvitesComposer);
+ this._composers.set(OutgoingHeader.USER_SETTINGS_VOLUME, UserSettingsSoundComposer);
+ }
+
+ public get events(): Map
+ {
+ return this._events;
+ }
+
+ public get composers(): Map
+ {
+ return this._composers;
+ }
+}
diff --git a/src/nitro/communication/demo/NitroCommunicationDemo.ts b/src/nitro/communication/demo/NitroCommunicationDemo.ts
new file mode 100644
index 00000000..d4cec0a6
--- /dev/null
+++ b/src/nitro/communication/demo/NitroCommunicationDemo.ts
@@ -0,0 +1,205 @@
+import { NitroLogger } from '../../../core/common/logger/NitroLogger';
+import { NitroManager } from '../../../core/common/NitroManager';
+import { IConnection } from '../../../core/communication/connections/IConnection';
+import { SocketConnectionEvent } from '../../../core/communication/events/SocketConnectionEvent';
+import { Nitro } from '../../Nitro';
+import { INitroCommunicationManager } from '../INitroCommunicationManager';
+import { ClientPingEvent } from '../messages/incoming/client/ClientPingEvent';
+import { AuthenticatedEvent } from '../messages/incoming/security/AuthenticatedEvent';
+import { ClientPongComposer } from '../messages/outgoing/client/ClientPongComposer';
+import { ClientReleaseVersionComposer } from '../messages/outgoing/client/ClientReleaseVersionComposer';
+import { InfoRetrieveBaseMessageComposer } from '../messages/outgoing/handshake/InfoRetrieveBaseMessageComposer';
+import { SecurityTicketComposer } from '../messages/outgoing/handshake/SecurityTicketComposer';
+import { NitroCommunicationDemoEvent } from './NitroCommunicationDemoEvent';
+
+export class NitroCommunicationDemo extends NitroManager
+{
+ private _communication: INitroCommunicationManager;
+
+ private _sso: string;
+ private _handShaking: boolean;
+ private _didConnect: boolean;
+
+ private _pongInterval: any;
+
+ constructor(communication: INitroCommunicationManager)
+ {
+ super();
+
+ this._communication = communication;
+
+ this._sso = null;
+ this._handShaking = false;
+ this._didConnect = false;
+
+ this._pongInterval = null;
+
+ this.onConnectionOpenedEvent = this.onConnectionOpenedEvent.bind(this);
+ this.onConnectionClosedEvent = this.onConnectionClosedEvent.bind(this);
+ this.onConnectionErrorEvent = this.onConnectionErrorEvent.bind(this);
+ this.sendPong = this.sendPong.bind(this);
+ }
+
+ protected onInit(): void
+ {
+ const connection = this._communication.connection;
+
+ if(connection)
+ {
+ connection.addEventListener(SocketConnectionEvent.CONNECTION_OPENED, this.onConnectionOpenedEvent);
+ connection.addEventListener(SocketConnectionEvent.CONNECTION_CLOSED, this.onConnectionClosedEvent);
+ connection.addEventListener(SocketConnectionEvent.CONNECTION_ERROR, this.onConnectionErrorEvent);
+ }
+
+ this._communication.registerMessageEvent(new ClientPingEvent(this.onClientPingEvent.bind(this)));
+ this._communication.registerMessageEvent(new AuthenticatedEvent(this.onAuthenticatedEvent.bind(this)));
+ }
+
+ protected onDispose(): void
+ {
+ const connection = this._communication.connection;
+
+ if(connection)
+ {
+ connection.removeEventListener(SocketConnectionEvent.CONNECTION_OPENED, this.onConnectionOpenedEvent);
+ connection.removeEventListener(SocketConnectionEvent.CONNECTION_CLOSED, this.onConnectionClosedEvent);
+ connection.removeEventListener(SocketConnectionEvent.CONNECTION_ERROR, this.onConnectionErrorEvent);
+ }
+
+ this._sso = null;
+ this._handShaking = false;
+
+ this.stopPonging();
+
+ super.onDispose();
+ }
+
+ private onConnectionOpenedEvent(event: Event): void
+ {
+ const connection = this._communication.connection;
+
+ if(!connection) return;
+
+ this._didConnect = true;
+
+ this.dispatchCommunicationDemoEvent(NitroCommunicationDemoEvent.CONNECTION_ESTABLISHED, connection);
+
+ if(Nitro.instance.getConfiguration('communication.pong.manually', false)) this.startPonging();
+
+ this.startHandshake(connection);
+
+ connection.send(new ClientReleaseVersionComposer(null, null, null, null));
+
+ this.tryAuthentication(connection);
+ }
+
+ private onConnectionClosedEvent(event: CloseEvent): void
+ {
+ const connection = this._communication.connection;
+
+ if(!connection) return;
+
+ this.stopPonging();
+
+ if(this._didConnect) this.dispatchCommunicationDemoEvent(NitroCommunicationDemoEvent.CONNECTION_CLOSED, connection);
+ }
+
+ private onConnectionErrorEvent(event: CloseEvent): void
+ {
+ const connection = this._communication.connection;
+
+ if(!connection) return;
+
+ this.stopPonging();
+
+ this.dispatchCommunicationDemoEvent(NitroCommunicationDemoEvent.CONNECTION_ERROR, connection);
+ }
+
+ private tryAuthentication(connection: IConnection): void
+ {
+ if(!connection || !this._sso)
+ {
+ if(!this._sso)
+ {
+ NitroLogger.log('Login without an SSO ticket is not supported');
+ }
+
+ this.dispatchCommunicationDemoEvent(NitroCommunicationDemoEvent.CONNECTION_HANDSHAKE_FAILED, connection);
+
+ return;
+ }
+
+ connection.send(new SecurityTicketComposer(this._sso, Nitro.instance.time));
+ }
+
+ private onClientPingEvent(event: ClientPingEvent): void
+ {
+ if(!event || !event.connection) return;
+
+ this.sendPong(event.connection);
+ }
+
+ private onAuthenticatedEvent(event: AuthenticatedEvent): void
+ {
+ if(!event || !event.connection) return;
+
+ this.completeHandshake(event.connection);
+
+ this.dispatchCommunicationDemoEvent(NitroCommunicationDemoEvent.CONNECTION_AUTHENTICATED, event.connection);
+
+ //event.connection.send(new UserHomeRoomComposer(555));
+
+ event.connection.send(new InfoRetrieveBaseMessageComposer());
+ }
+
+ public setSSO(sso: string): void
+ {
+ if(!sso || (sso === '') || this._sso) return;
+
+ this._sso = sso;
+ }
+
+ private startHandshake(connection: IConnection): void
+ {
+ this.dispatchCommunicationDemoEvent(NitroCommunicationDemoEvent.CONNECTION_HANDSHAKING, connection);
+
+ this._handShaking = true;
+ }
+
+ private completeHandshake(connection: IConnection): void
+ {
+ this.dispatchCommunicationDemoEvent(NitroCommunicationDemoEvent.CONNECTION_HANDSHAKED, connection);
+
+ this._handShaking = false;
+ }
+
+ private startPonging(): void
+ {
+ this.stopPonging();
+
+ this._pongInterval = setInterval(this.sendPong, Nitro.instance.getConfiguration('communication.pong.interval.ms', 20000));
+ }
+
+ private stopPonging(): void
+ {
+ if(!this._pongInterval) return;
+
+ clearInterval(this._pongInterval);
+
+ this._pongInterval = null;
+ }
+
+ private sendPong(connection: IConnection = null): void
+ {
+ connection = ((connection || this._communication.connection) || null);
+
+ if(!connection) return;
+
+ connection.send(new ClientPongComposer());
+ }
+
+ private dispatchCommunicationDemoEvent(type: string, connection: IConnection): void
+ {
+ Nitro.instance.events.dispatchEvent(new NitroCommunicationDemoEvent(type, connection));
+ }
+}
diff --git a/src/nitro/communication/demo/NitroCommunicationDemoEvent.ts b/src/nitro/communication/demo/NitroCommunicationDemoEvent.ts
new file mode 100644
index 00000000..43ff9df1
--- /dev/null
+++ b/src/nitro/communication/demo/NitroCommunicationDemoEvent.ts
@@ -0,0 +1,27 @@
+import { IConnection } from '../../../core/communication/connections/IConnection';
+import { NitroEvent } from '../../../core/events/NitroEvent';
+
+export class NitroCommunicationDemoEvent extends NitroEvent
+{
+ public static CONNECTION_ESTABLISHED = 'NCE_ESTABLISHED';
+ public static CONNECTION_CLOSED = 'NCE_CLOSED';
+ public static CONNECTION_ERROR = 'NCE_ERROR';
+ public static CONNECTION_HANDSHAKING = 'NCE_HANDSHAKING';
+ public static CONNECTION_HANDSHAKED = 'NCE_HANDSHAKED';
+ public static CONNECTION_HANDSHAKE_FAILED = 'NCE_HANDSHAKE_FAILED';
+ public static CONNECTION_AUTHENTICATED = 'NCE_AUTHENTICATED';
+
+ private _connection: IConnection;
+
+ constructor(type: string, connection: IConnection)
+ {
+ super(type);
+
+ this._connection = connection;
+ }
+
+ public get connection(): IConnection
+ {
+ return this._connection;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/IncomingHeader.ts b/src/nitro/communication/messages/incoming/IncomingHeader.ts
new file mode 100644
index 00000000..4b16db9b
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/IncomingHeader.ts
@@ -0,0 +1,241 @@
+export class IncomingHeader
+{
+ public static ACHIEVEMENT_LIST = 305;
+ public static AUTHENTICATED = 2491;
+ public static AVAILABILITY_STATUS = 2033;
+ public static BUILDERS_CLUB_EXPIRED = 1452;
+ public static CAMERA_PRICE = 3878;
+ public static CAMERA_THUMBNAIL_SAVED = 3595;
+ public static CAMERA_URL = 3696;
+ public static CATALOG_CLUB = 2405;
+ public static CATALOG_MODE = 3828;
+ public static CATALOG_PAGE = 804;
+ public static CATALOG_PAGES = 1032;
+ public static CATALOG_PURCHASE = 869;
+ public static CATALOG_PURCHASE_FAILED = 1404;
+ public static CATALOG_PURCHASE_UNAVAILABLE = 3770;
+ public static CATALOG_SEARCH = 3388;
+ public static CATALOG_SOLD_OUT = 377;
+ public static CATALOG_UPDATED = 1866;
+ public static CFH_RESULT_MESSAGE = 934;
+ public static CLIENT_LATENCY = 10;
+ public static CLIENT_PING = 3928;
+ public static DESKTOP_CAMPAIGN = 1745;
+ public static DESKTOP_NEWS = 286;
+ public static DESKTOP_VIEW = 122;
+ public static DISCOUNT_CONFIG = 2347;
+ public static FIRST_LOGIN_OF_DAY = 793;
+ public static FURNITURE_ALIASES = 1723;
+ public static FURNITURE_DATA = 2547;
+ public static FURNITURE_FLOOR = 1778;
+ public static FURNITURE_FLOOR_ADD = 1534;
+ public static FURNITURE_FLOOR_REMOVE = 2703;
+ public static FURNITURE_FLOOR_UPDATE = 3776;
+ public static FURNITURE_ITEMDATA = 2202;
+ public static FURNITURE_STATE = 2376;
+ public static GAME_CENTER_ACHIEVEMENTS = 2265;
+ public static GAME_CENTER_GAME_LIST = 222;
+ public static GAME_CENTER_STATUS = 2893;
+ public static GENERIC_ALERT = 3801;
+ public static GENERIC_ALERT_LINK = 2030;
+ public static GENERIC_ERROR = 1600;
+ public static GIFT_CONFIG = 2234;
+ public static GROUP_BADGES = 2402;
+ public static GROUP_CREATE_OPTIONS = 2159;
+ public static GROUP_FORUM_INFO = 3011;
+ public static GROUP_FORUM_LIST = 3001;
+ public static GROUP_FORUM_THREADS = 1073;
+ public static GROUP_INFO = 1702;
+ public static GROUP_LIST = 420;
+ public static GROUP_MEMBER = 265;
+ public static GROUP_MEMBERS = 1200;
+ public static GROUP_MEMBERS_REFRESH = 2445;
+ public static GROUP_MEMBER_REMOVE_CONFIRM = 1876;
+ public static GROUP_SETTINGS = 3965;
+ public static GROUP_BADGE_PARTS = 2238;
+ public static ITEM_DIMMER_SETTINGS = 2710;
+ public static ITEM_STACK_HELPER = 2816;
+ public static ITEM_WALL = 1369;
+ public static ITEM_WALL_ADD = 2187;
+ public static ITEM_WALL_REMOVE = 3208;
+ public static ITEM_WALL_UPDATE = 2009;
+ public static LOAD_GAME_URL = 2624;
+ public static MARKETPLACE_CONFIG = 1823;
+ public static MESSENGER_ACCEPT_FRIENDS = 896;
+ public static MESSENGER_CHAT = 1587;
+ public static MESSENGER_FIND_FRIENDS = 1210;
+ public static MESSENGER_FOLLOW_FAILED = 3048;
+ public static MESSENGER_FRIEND_NOTIFICATION = 3082;
+ public static MESSENGER_FRIENDS = 3130;
+ public static MESSENGER_INIT = 1605;
+ public static MESSENGER_INSTANCE_MESSAGE_ERROR = 3359;
+ public static MESSENGER_INVITE = 3870;
+ public static MESSENGER_INVITE_ERROR = 462;
+ public static MESSENGER_MESSAGE_ERROR = 892;
+ public static MESSENGER_MINIMAIL_COUNT = 2803;
+ public static MESSENGER_MINIMAIL_NEW = 1911;
+ public static MESSENGER_RELATIONSHIPS = 2016;
+ public static MESSENGER_REQUEST = 2219;
+ public static MESSENGER_REQUEST_ERROR = 892;
+ public static MESSENGER_REQUESTS = 280;
+ public static MESSENGER_ROOM_INVITE = 3870;
+ public static MESSENGER_SEARCH = 973;
+ public static MESSENGER_UPDATE = 2800;
+ public static MODERATION_REPORT_DISABLED = 1651;
+ public static MODERATION_TOOL = 2696;
+ public static MODERATION_TOPICS = 325;
+ public static MODERATION_USER_INFO = 2866;
+ public static MOTD_MESSAGES = 2035;
+ public static NAVIGATOR_CATEGORIES = 1562;
+ public static NAVIGATOR_COLLAPSED = 1543;
+ public static NAVIGATOR_EVENT_CATEGORIES = 3244;
+ public static NAVIGATOR_LIFTED = 3104;
+ public static NAVIGATOR_METADATA = 3052;
+ public static NAVIGATOR_OPEN_ROOM_CREATOR = 2064;
+ public static NAVIGATOR_SEARCH = 2690;
+ public static NAVIGATOR_SEARCHES = 3984;
+ public static NAVIGATOR_SETTINGS = 518;
+ public static NOTIFICATION_LIST = 1992;
+ public static PET_FIGURE_UPDATE = 1924;
+ public static PET_INFO = 2901;
+ public static RECYCLER_PRIZES = 3164;
+ public static ROOM_BAN_LIST = 1869;
+ public static ROOM_BAN_REMOVE = 3429;
+ public static ROOM_CREATED = 1304;
+ public static ROOM_DOORBELL = 2309;
+ public static ROOM_DOORBELL_ACCEPTED = 3783;
+ public static ROOM_DOORBELL_REJECTED = 878;
+ public static ROOM_ENTER = 758;
+ public static ROOM_ENTER_ERROR = 899;
+ public static ROOM_FORWARD = 160;
+ public static ROOM_HEIGHT_MAP = 2753;
+ public static ROOM_HEIGHT_MAP_UPDATE = 558;
+ public static ROOM_INFO = 687;
+ public static ROOM_INFO_OWNER = 749;
+ public static ROOM_MODEL = 1301;
+ public static ROOM_MODEL_BLOCKED_TILES = 3990;
+ public static ROOM_MODEL_DOOR = 1664;
+ public static ROOM_MODEL_NAME = 2031;
+ public static ROOM_MUTED = 2533;
+ public static ROOM_MUTE_USER = 826;
+ public static ROOM_PAINT = 2454;
+ public static ROOM_PROMOTION = 2274;
+ public static ROOM_QUEUE_STATUS = 2208;
+ public static ROOM_RIGHTS = 780;
+ public static ROOM_RIGHTS_CLEAR = 2392;
+ public static ROOM_RIGHTS_LIST = 1284;
+ public static ROOM_RIGHTS_LIST_ADD = 2088;
+ public static ROOM_RIGHTS_LIST_REMOVE = 1327;
+ public static ROOM_RIGHTS_OWNER = 339;
+ public static ROOM_ROLLING = 3207;
+ public static ROOM_SCORE = 482;
+ public static ROOM_SETTINGS = 1498;
+ public static ROOM_SETTINGS_CHAT = 1191;
+ public static ROOM_SETTINGS_SAVE = 948;
+ public static ROOM_SETTINGS_SAVE_ERROR = 1555;
+ public static ROOM_SETTINGS_UPDATED = 3297;
+ public static ROOM_SPECTATOR = 1033;
+ public static ROOM_THICKNESS = 3547;
+ public static SECURITY_DEBUG = 3284;
+ public static SECURITY_MACHINE = 1488;
+ public static SECURITY_UNKNOWN2 = 2833;
+ public static TRADE_ACCEPTED = 2568;
+ public static TRADE_CLOSED = 1373;
+ public static TRADE_COMPLETED = 1001;
+ public static TRADE_CONFIRMATION = 2720;
+ public static TRADE_LIST_ITEM = 2024;
+ public static TRADE_NOT_OPEN = 3128;
+ public static TRADE_OPEN = 2505;
+ public static TRADE_OPEN_FAILED = 217;
+ public static TRADE_OTHER_NOT_ALLOWED = 2154;
+ public static TRADE_YOU_NOT_ALLOWED = 3058;
+ public static UNIT = 374;
+ public static UNIT_CHANGE_NAME = 2182;
+ public static UNIT_CHAT = 1446;
+ public static UNIT_CHAT_SHOUT = 1036;
+ public static UNIT_CHAT_WHISPER = 2704;
+ public static UNIT_DANCE = 2233;
+ public static UNIT_EFFECT = 1167;
+ public static UNIT_EXPRESSION = 1631;
+ public static UNIT_HAND_ITEM = 1474;
+ public static UNIT_IDLE = 1797;
+ public static UNIT_INFO = 3920;
+ public static UNIT_NUMBER = 2324;
+ public static UNIT_REMOVE = 2661;
+ public static UNIT_STATUS = 1640;
+ public static UNIT_TYPING = 1717;
+ public static UNSEEN_ITEMS = 2103;
+ public static USER_ACHIEVEMENT_SCORE = 1968;
+ public static USER_BADGES = 717;
+ public static USER_BADGES_ADD = 2493;
+ public static USER_BADGES_CURRENT = 1087;
+ public static USER_BOT_ADD = 1352;
+ public static USER_BOT_REMOVE = 233;
+ public static USER_BOTS = 3086;
+ public static USER_CHANGE_NAME = 118;
+ public static USER_CLOTHING = 1450;
+ public static USER_CREDITS = 3475;
+ public static USER_CURRENCY = 2018;
+ public static USER_CURRENCY_UPDATE = 2275;
+ public static USER_EFFECTS = 340;
+ public static USER_FAVORITE_ROOM = 2524;
+ public static USER_FAVORITE_ROOM_COUNT = 151;
+ public static USER_FIGURE = 2429;
+ public static USER_FURNITURE = 994;
+ public static USER_FURNITURE_ADD = 104;
+ public static USER_FURNITURE_POSTIT_PLACED = 1501;
+ public static USER_FURNITURE_REFRESH = 3151;
+ public static USER_FURNITURE_REMOVE = 159;
+ public static USER_HOME_ROOM = 2875;
+ public static USER_IGNORED = 126;
+ public static USER_IGNORED_RESULT = 207;
+ public static USER_INFO = 2725;
+ public static USER_OUTFITS = 3315;
+ public static USER_PERKS = 2586;
+ public static USER_PERMISSIONS = 411;
+ public static USER_PET_ADD = 2101;
+ public static USER_PET_REMOVE = 3253;
+ public static USER_PETS = 3522;
+ public static USER_PROFILE = 3898;
+ public static USER_RESPECT = 2815;
+ public static USER_SANCTION_STATUS = 3679;
+ public static USER_SETTINGS = 513;
+ public static USER_SUBSCRIPTION = 954;
+ public static USER_WARDROBE_PAGE = 3315;
+ public static WIRED_ACTION = 1434;
+ public static WIRED_CONDITION = 1108;
+ public static WIRED_ERROR = 156;
+ public static WIRED_OPEN = 1830;
+ public static WIRED_REWARD = 178;
+ public static WIRED_SAVE = 1155;
+ public static WIRED_TRIGGER = 383;
+ public static PLAYING_GAME = 448;
+ public static FURNITURE_STATE_2 = 3431;
+ public static REMOVE_BOT_FROM_INVENTORY = 233;
+ public static ADD_BOT_TO_INVENTORY = 1352;
+ public static ACHIEVEMENT_PROGRESSED = 2107;
+ public static MODTOOL_ROOM_INFO = 1333;
+ public static MODTOOL_USER_CHATLOG = 3377;
+ public static MODTOOL_ROOM_CHATLOG = 3434;
+ public static LOVELOCK_FURNI_START = 3753;
+ public static LOVELOCK_FURNI_FRIEND_COMFIRMED = 382;
+ public static LOVELOCK_FURNI_FINISHED = 770;
+ public static GIFT_RECEIVER_NOT_FOUND = 1517;
+ public static GIFT_OPENED = 56;
+ public static HOTEL_WILL_SHUTDOWN = 1050;
+ public static FLOOD_CONTROL = 566;
+ public static REMAINING_MUTE = 826;
+ public static USER_EFFECT_LIST = 340;
+ public static USER_EFFECT_LIST_ADD = 2867;
+ public static USER_EFFECT_LIST_REMOVE = 2228;
+ public static USER_EFFECT_ACTIVATE = 1959;
+ public static CATALOG_CLUB_GIFTS = 619;
+ public static REDEEM_VOUCHER_ERROR = 714;
+ public static REDEEM_VOUCHER_OK = 3336;
+ public static MODTOOL_VISITED_ROOMS_USER = 1752;
+ public static IN_CLIENT_LINK = 2023;
+ public static BOT_COMMAND_CONFIGURATION = 1618;
+ public static HAND_ITEM_RECEIVED = 354;
+ public static PET_PLACING_ERROR = 2913;
+ public static BOT_ERROR = 639;
+}
diff --git a/src/nitro/communication/messages/incoming/availability/AvailabilityStatusMessageEvent.ts b/src/nitro/communication/messages/incoming/availability/AvailabilityStatusMessageEvent.ts
new file mode 100644
index 00000000..8d1cfa30
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/availability/AvailabilityStatusMessageEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { AvailabilityStatusMessageParser } from '../../parser/availability/AvailabilityStatusMessageParser';
+
+export class AvailabilityStatusMessageEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, AvailabilityStatusMessageParser);
+ }
+
+ public getParser(): AvailabilityStatusMessageParser
+ {
+ return this.parser as AvailabilityStatusMessageParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/avatar/ChangeNameUpdateEvent.ts b/src/nitro/communication/messages/incoming/avatar/ChangeNameUpdateEvent.ts
new file mode 100644
index 00000000..e31aaa32
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/avatar/ChangeNameUpdateEvent.ts
@@ -0,0 +1,25 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { ChangeNameUpdateParser } from '../../parser/avatar/ChangeNameUpdateParser';
+
+export class ChangeNameUpdateEvent extends MessageEvent implements IMessageEvent
+{
+ public static _Str_5797: number = 0;
+ public static _Str_7005: number = 1;
+ public static _Str_7389: number = 2;
+ public static _Str_7137: number = 3;
+ public static _Str_7836: number = 4;
+ public static _Str_7721: number = 5;
+ public static _Str_8620: number = 6;
+ public static _Str_9429: number = 7;
+
+ constructor(callBack: Function)
+ {
+ super(callBack, ChangeNameUpdateParser);
+ }
+
+ public getParser(): ChangeNameUpdateParser
+ {
+ return this.parser as ChangeNameUpdateParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogClubEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogClubEvent.ts
new file mode 100644
index 00000000..ec0ddb82
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogClubEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogClubParser } from '../../parser/catalog/CatalogClubParser';
+
+export class CatalogClubEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogClubParser);
+ }
+
+ public getParser(): CatalogClubParser
+ {
+ return this.parser as CatalogClubParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogClubGiftsEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogClubGiftsEvent.ts
new file mode 100644
index 00000000..29ae3bf7
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogClubGiftsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogClubGiftsParser } from '../../parser/catalog/CatalogClubGiftsParser';
+
+export class CatalogClubGiftsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogClubGiftsParser);
+ }
+
+ public getParser(): CatalogClubGiftsParser
+ {
+ return this.parser as CatalogClubGiftsParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogGiftConfigurationEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogGiftConfigurationEvent.ts
new file mode 100644
index 00000000..a7a9f47c
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogGiftConfigurationEvent.ts
@@ -0,0 +1,17 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogPagesParser } from '../../parser/catalog/CatalogPagesParser';
+import { CatalogGiftConfigurationParser } from '../../parser/catalog/CatalogGiftConfigurationParser';
+
+export class CatalogGiftConfigurationEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogGiftConfigurationParser);
+ }
+
+ public getParser(): CatalogGiftConfigurationParser
+ {
+ return this.parser as CatalogGiftConfigurationParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogGiftUsernameUnavailableEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogGiftUsernameUnavailableEvent.ts
new file mode 100644
index 00000000..f6b565e8
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogGiftUsernameUnavailableEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogGiftUsernameUnavailableParser } from '../../parser/catalog/CatalogGiftUsernameUnavailableParser';
+
+export class CatalogGiftUsernameUnavailableEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogGiftUsernameUnavailableParser);
+ }
+
+ public getParser(): CatalogGiftUsernameUnavailableParser
+ {
+ return this.parser as CatalogGiftUsernameUnavailableParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogGroupsEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogGroupsEvent.ts
new file mode 100644
index 00000000..aa0234d7
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogGroupsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogGroupsParser } from '../../parser/catalog/CatalogGroupsParser';
+
+export class CatalogGroupsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogGroupsParser);
+ }
+
+ public getParser(): CatalogGroupsParser
+ {
+ return this.parser as CatalogGroupsParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogModeEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogModeEvent.ts
new file mode 100644
index 00000000..fb76a8a8
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogModeEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogModeParser } from '../../parser/catalog/CatalogModeParser';
+
+export class CatalogModeEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogModeParser);
+ }
+
+ public getParser(): CatalogModeParser
+ {
+ return this.parser as CatalogModeParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogPageEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogPageEvent.ts
new file mode 100644
index 00000000..85589423
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogPageEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogPageParser } from '../../parser/catalog/CatalogPageParser';
+
+export class CatalogPageEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogPageParser);
+ }
+
+ public getParser(): CatalogPageParser
+ {
+ return this.parser as CatalogPageParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogPagesEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogPagesEvent.ts
new file mode 100644
index 00000000..a9224d50
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogPagesEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogPagesParser } from '../../parser/catalog/CatalogPagesParser';
+
+export class CatalogPagesEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogPagesParser);
+ }
+
+ public getParser(): CatalogPagesParser
+ {
+ return this.parser as CatalogPagesParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogPurchaseEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogPurchaseEvent.ts
new file mode 100644
index 00000000..13711625
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogPurchaseEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogPurchaseParser } from '../../parser/catalog/CatalogPurchaseParser';
+
+export class CatalogPurchaseEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogPurchaseParser);
+ }
+
+ public getParser(): CatalogPurchaseParser
+ {
+ return this.parser as CatalogPurchaseParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogPurchaseFailedEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogPurchaseFailedEvent.ts
new file mode 100644
index 00000000..37ae8047
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogPurchaseFailedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogPurchaseFailedParser } from '../../parser/catalog/CatalogPurchaseFailedParser';
+
+export class CatalogPurchaseFailedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogPurchaseFailedParser);
+ }
+
+ public getParser(): CatalogPurchaseFailedParser
+ {
+ return this.parser as CatalogPurchaseFailedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogPurchaseUnavailableEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogPurchaseUnavailableEvent.ts
new file mode 100644
index 00000000..5e5555e3
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogPurchaseUnavailableEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogPurchaseUnavailableParser } from '../../parser/catalog/CatalogPurchaseUnavailableParser';
+
+export class CatalogPurchaseUnavailableEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogPurchaseUnavailableParser);
+ }
+
+ public getParser(): CatalogPurchaseUnavailableParser
+ {
+ return this.parser as CatalogPurchaseUnavailableParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogRedeemVoucherErrorEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogRedeemVoucherErrorEvent.ts
new file mode 100644
index 00000000..953d9ff9
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogRedeemVoucherErrorEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogRedeemVoucherErrorParser } from '../../parser/catalog/CatalogRedeemVoucherErrorParser';
+
+export class CatalogRedeemVoucherErrorEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogRedeemVoucherErrorParser);
+ }
+
+ public getParser(): CatalogRedeemVoucherErrorParser
+ {
+ return this.parser as CatalogRedeemVoucherErrorParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogRedeemVoucherOkEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogRedeemVoucherOkEvent.ts
new file mode 100644
index 00000000..b97bc8a0
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogRedeemVoucherOkEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogRedeemVoucherOkParser } from '../../parser/catalog/CatalogRedeemVoucherOkParser';
+
+export class CatalogRedeemVoucherOkEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogRedeemVoucherOkParser);
+ }
+
+ public getParser(): CatalogRedeemVoucherOkParser
+ {
+ return this.parser as CatalogRedeemVoucherOkParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogSearchEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogSearchEvent.ts
new file mode 100644
index 00000000..0e230478
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogSearchEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogSearchParser } from '../../parser/catalog/CatalogSearchParser';
+
+export class CatalogSearchEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogSearchParser);
+ }
+
+ public getParser(): CatalogSearchParser
+ {
+ return this.parser as CatalogSearchParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogSoldOutEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogSoldOutEvent.ts
new file mode 100644
index 00000000..96ea0457
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogSoldOutEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogSoldOutParser } from '../../parser/catalog/CatalogSoldOutParser';
+
+export class CatalogSoldOutEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogSoldOutParser);
+ }
+
+ public getParser(): CatalogSoldOutParser
+ {
+ return this.parser as CatalogSoldOutParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/catalog/CatalogUpdatedEvent.ts b/src/nitro/communication/messages/incoming/catalog/CatalogUpdatedEvent.ts
new file mode 100644
index 00000000..3ee3503b
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/catalog/CatalogUpdatedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CatalogUpdatedParser } from '../../parser/catalog/CatalogUpdatedParser';
+
+export class CatalogUpdatedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CatalogUpdatedParser);
+ }
+
+ public getParser(): CatalogUpdatedParser
+ {
+ return this.parser as CatalogUpdatedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/client/ClientPingEvent.ts b/src/nitro/communication/messages/incoming/client/ClientPingEvent.ts
new file mode 100644
index 00000000..be283ebd
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/client/ClientPingEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { ClientPingParser } from '../../parser/client/ClientPingParser';
+
+export class ClientPingEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, ClientPingParser);
+ }
+
+ public getParser(): ClientPingParser
+ {
+ return this.parser as ClientPingParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/desktop/DesktopViewEvent.ts b/src/nitro/communication/messages/incoming/desktop/DesktopViewEvent.ts
new file mode 100644
index 00000000..869ee120
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/desktop/DesktopViewEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { DesktopViewParser } from '../../parser/desktop/DesktopViewParser';
+
+export class DesktopViewEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, DesktopViewParser);
+ }
+
+ public getParser(): DesktopViewParser
+ {
+ return this.parser as DesktopViewParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/AcceptFriendFailureData.ts b/src/nitro/communication/messages/incoming/friendlist/AcceptFriendFailureData.ts
new file mode 100644
index 00000000..c83053e1
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/AcceptFriendFailureData.ts
@@ -0,0 +1,25 @@
+import { IMessageDataWrapper } from '../../../../../core/communication/messages/IMessageDataWrapper';
+
+export class AcceptFriendFailerData
+{
+ private _senderId: number;
+ private _errorCode: number;
+
+ constructor(wrapper: IMessageDataWrapper)
+ {
+ if(!wrapper) throw new Error('invalid_wrapper');
+
+ this._senderId = wrapper.readInt();
+ this._errorCode = wrapper.readInt();
+ }
+
+ public get senderId(): number
+ {
+ return this._senderId;
+ }
+
+ public get errorCode(): number
+ {
+ return this._errorCode;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/AcceptFriendResultEvent.ts b/src/nitro/communication/messages/incoming/friendlist/AcceptFriendResultEvent.ts
new file mode 100644
index 00000000..e9e28715
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/AcceptFriendResultEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { AcceptFriendResultParser } from '../../parser/friendlist/AcceptFriendResultParser';
+
+export class AcceptFriendResultEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, AcceptFriendResultParser);
+ }
+
+ public getParser(): AcceptFriendResultParser
+ {
+ return this.parser as AcceptFriendResultParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/FindFriendsProcessResultEvent.ts b/src/nitro/communication/messages/incoming/friendlist/FindFriendsProcessResultEvent.ts
new file mode 100644
index 00000000..c326b76d
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/FindFriendsProcessResultEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { FindFriendsProcessResultParser } from '../../parser/friendlist/FindFriendsProcessResultParser';
+
+export class FindFriendsProcessResultEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FindFriendsProcessResultParser);
+ }
+
+ public getParser(): FindFriendsProcessResultParser
+ {
+ return this.parser as FindFriendsProcessResultParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/FollowFriendFailedEvent.ts b/src/nitro/communication/messages/incoming/friendlist/FollowFriendFailedEvent.ts
new file mode 100644
index 00000000..0cf9733a
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/FollowFriendFailedEvent.ts
@@ -0,0 +1,17 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { DesktopViewParser } from '../../parser/desktop/DesktopViewParser';
+import { FollowFriendFailedParser } from '../../parser/friendlist/FollowFriendFailedParser';
+
+export class FollowFriendFailedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FollowFriendFailedParser);
+ }
+
+ public getParser(): DesktopViewParser
+ {
+ return this.parser as FollowFriendFailedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/FriendCategoryData.ts b/src/nitro/communication/messages/incoming/friendlist/FriendCategoryData.ts
new file mode 100644
index 00000000..acd36270
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/FriendCategoryData.ts
@@ -0,0 +1,25 @@
+import { IMessageDataWrapper } from '../../../../../core/communication/messages/IMessageDataWrapper';
+
+export class FriendCategoryData
+{
+ private _id: number;
+ private _name: string;
+
+ constructor(wrapper: IMessageDataWrapper)
+ {
+ if(!wrapper) throw new Error('invalid_wrapper');
+
+ this._id = wrapper.readInt();
+ this._name = wrapper.readString();
+ }
+
+ public get id(): number
+ {
+ return this._id;
+ }
+
+ public get name(): string
+ {
+ return this._name;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/FriendListFragmentEvent.ts b/src/nitro/communication/messages/incoming/friendlist/FriendListFragmentEvent.ts
new file mode 100644
index 00000000..3889078c
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/FriendListFragmentEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { FriendListFragmentParser } from '../../parser/friendlist/FriendListFragmentMessageParser';
+
+export class FriendListFragmentEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FriendListFragmentParser);
+ }
+
+ public getParser(): FriendListFragmentParser
+ {
+ return this.parser as FriendListFragmentParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/FriendListUpdateEvent.ts b/src/nitro/communication/messages/incoming/friendlist/FriendListUpdateEvent.ts
new file mode 100644
index 00000000..74caa2ff
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/FriendListUpdateEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { FriendListUpdateParser } from '../../parser/friendlist/FriendListUpdateParser';
+
+export class FriendListUpdateEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FriendListUpdateParser);
+ }
+
+ public getParser(): FriendListUpdateParser
+ {
+ return this.parser as FriendListUpdateParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/FriendNotificationEvent.ts b/src/nitro/communication/messages/incoming/friendlist/FriendNotificationEvent.ts
new file mode 100644
index 00000000..8fd10195
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/FriendNotificationEvent.ts
@@ -0,0 +1,17 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { DesktopViewParser } from '../../parser/desktop/DesktopViewParser';
+import { FriendNotificationParser } from '../../parser/friendlist/FriendNotificationParser';
+
+export class FriendNotificationEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FriendNotificationParser);
+ }
+
+ public getParser(): DesktopViewParser
+ {
+ return this.parser as FriendNotificationParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/FriendParser.ts b/src/nitro/communication/messages/incoming/friendlist/FriendParser.ts
new file mode 100644
index 00000000..11fb9bcd
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/FriendParser.ts
@@ -0,0 +1,109 @@
+import { IMessageDataWrapper } from '../../../../../core/communication/messages/IMessageDataWrapper';
+
+export class FriendParser
+{
+ private _id: number;
+ private _name: string;
+ private _gender: number;
+ private _online: boolean;
+ private _followingAllowed: boolean;
+ private _figure: string;
+ private _categoryId: number;
+ private _motto: string;
+ private _realName: string;
+ private _lastAccess: string;
+ private _persistedMessageUser: boolean;
+ private _vipMember: boolean;
+ private _pocketHabboUser: boolean;
+ private _relationshipStatus: number;
+
+ constructor(wrapper: IMessageDataWrapper)
+ {
+ if(!wrapper) throw new Error('invalid_wrapper');
+
+ this._id = wrapper.readInt();
+ this._name = wrapper.readString();
+ this._gender = wrapper.readInt();
+ this._online = wrapper.readBoolean();
+ this._followingAllowed = wrapper.readBoolean();
+ this._figure = wrapper.readString();
+ this._categoryId = wrapper.readInt();
+ this._motto = wrapper.readString();
+ this._realName = wrapper.readString();
+ this._lastAccess = wrapper.readString();
+ this._persistedMessageUser = wrapper.readBoolean();
+ this._vipMember = wrapper.readBoolean();
+ this._pocketHabboUser = wrapper.readBoolean();
+ this._relationshipStatus = wrapper.readShort();
+ }
+
+ public get id(): number
+ {
+ return this._id;
+ }
+
+ public get name(): string
+ {
+ return this._name;
+ }
+
+ public get gender(): number
+ {
+ return this._gender;
+ }
+
+ public get online(): boolean
+ {
+ return this._online;
+ }
+
+ public get followingAllowed(): boolean
+ {
+ return this._followingAllowed;
+ }
+
+ public get figure(): string
+ {
+ return this._figure;
+ }
+
+ public get categoryId(): number
+ {
+ return this._categoryId;
+ }
+
+ public get motto(): string
+ {
+ return this._motto;
+ }
+
+ public get lastAccess(): string
+ {
+ return this._lastAccess;
+ }
+
+ public get realName(): string
+ {
+ return this._realName;
+ }
+
+ public get persistedMessageUser(): boolean
+ {
+ return this._persistedMessageUser;
+ }
+
+ public get vipMember(): boolean
+ {
+ return this._vipMember;
+ }
+
+ public get pocketHabboUser(): boolean
+ {
+ return this._pocketHabboUser;
+ }
+
+ public get relationshipStatus(): number
+ {
+ return this._relationshipStatus;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/FriendRequestData.ts b/src/nitro/communication/messages/incoming/friendlist/FriendRequestData.ts
new file mode 100644
index 00000000..96d5a734
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/FriendRequestData.ts
@@ -0,0 +1,39 @@
+import { IMessageDataWrapper } from '../../../../../core/communication/messages/IMessageDataWrapper';
+
+export class FriendRequestData
+{
+ private _requestId: number;
+ private _requesterName: string;
+ private _requesterUserId: number;
+ private _figureString: string;
+
+ constructor(wrapper: IMessageDataWrapper)
+ {
+ if(!wrapper) throw new Error('invalid_wrapper');
+
+ this._requestId = wrapper.readInt();
+ this._requesterName = wrapper.readString();
+ this._figureString = wrapper.readString();
+ this._requesterUserId = this._requestId;
+ }
+
+ public get requestId(): number
+ {
+ return this._requestId;
+ }
+
+ public get requesterName(): string
+ {
+ return this._requesterName;
+ }
+
+ public get requesterUserId(): number
+ {
+ return this._requesterUserId;
+ }
+
+ public get figureString(): string
+ {
+ return this._figureString;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/FriendRequestsEvent.ts b/src/nitro/communication/messages/incoming/friendlist/FriendRequestsEvent.ts
new file mode 100644
index 00000000..cdd1349a
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/FriendRequestsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { FriendRequestsParser } from '../../parser/friendlist/FriendRequestsParser';
+
+export class FriendRequestsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FriendRequestsParser);
+ }
+
+ public getParser(): FriendRequestsParser
+ {
+ return this.parser as FriendRequestsParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/HabboSearchResultData.ts b/src/nitro/communication/messages/incoming/friendlist/HabboSearchResultData.ts
new file mode 100644
index 00000000..11b8bc3f
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/HabboSearchResultData.ts
@@ -0,0 +1,74 @@
+import { IMessageDataWrapper } from '../../../../../core/communication/messages/IMessageDataWrapper';
+
+export class HabboSearchResultData
+{
+ private _avatarId: number;
+ private _avatarName: string;
+ private _avatarMotto: string;
+ private _isAvatarOnline: boolean;
+ private _canFollow: boolean;
+ private _avatarGender: number;
+ private _avatarFigure: string;
+ private _lastOnlineData: string;
+ private _realName: string;
+
+ constructor(wrapper: IMessageDataWrapper)
+ {
+ if(!wrapper) throw new Error('invalid_wrapper');
+
+ this._avatarId = wrapper.readInt();
+ this._avatarName = wrapper.readString();
+ this._avatarMotto = wrapper.readString();
+ this._isAvatarOnline = wrapper.readBoolean();
+ this._canFollow = wrapper.readBoolean();
+ this._avatarGender = wrapper.readInt();
+ this._avatarFigure = wrapper.readString();
+ this._lastOnlineData = wrapper.readString();
+ this._realName = wrapper.readString();
+ }
+
+ public get avatarId(): number
+ {
+ return this._avatarId;
+ }
+
+ public get avatarName(): string
+ {
+ return this._avatarName;
+ }
+
+ public get avatarMotto(): string
+ {
+ return this._avatarMotto;
+ }
+
+ public get isAvatarOnline(): boolean
+ {
+ return this._isAvatarOnline;
+ }
+
+ public get canFollow(): boolean
+ {
+ return this._canFollow;
+ }
+
+ public get avatarGender(): number
+ {
+ return this._avatarGender;
+ }
+
+ public get avatarFigure(): string
+ {
+ return this._avatarFigure;
+ }
+
+ public get lastOnlineData(): string
+ {
+ return this._lastOnlineData;
+ }
+
+ public get realName(): string
+ {
+ return this._realName;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/HabboSearchResultEvent.ts b/src/nitro/communication/messages/incoming/friendlist/HabboSearchResultEvent.ts
new file mode 100644
index 00000000..41c1b840
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/HabboSearchResultEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { HabboSearchResultParser } from '../../parser/friendlist/HabboSearchResultParser';
+
+export class HabboSearchResultEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, HabboSearchResultParser);
+ }
+
+ public getParser(): HabboSearchResultParser
+ {
+ return this.parser as HabboSearchResultParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/InstantMessageErrorEvent.ts b/src/nitro/communication/messages/incoming/friendlist/InstantMessageErrorEvent.ts
new file mode 100644
index 00000000..54991a69
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/InstantMessageErrorEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { InstantMessageErrorParser } from '../../parser/friendlist/InstantMessageErrorParser';
+
+export class InstantMessageErrorEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, InstantMessageErrorParser);
+ }
+
+ public getParser(): InstantMessageErrorParser
+ {
+ return this.parser as InstantMessageErrorParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/MessageErrorEvent.ts b/src/nitro/communication/messages/incoming/friendlist/MessageErrorEvent.ts
new file mode 100644
index 00000000..2a2eb4db
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/MessageErrorEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { MessageErrorParser } from '../../parser/friendlist/MessageErrorParser';
+
+export class MessageErrorEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, MessageErrorParser);
+ }
+
+ public getParser(): MessageErrorParser
+ {
+ return this.parser as MessageErrorParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/MessengerInitEvent.ts b/src/nitro/communication/messages/incoming/friendlist/MessengerInitEvent.ts
new file mode 100644
index 00000000..3b03026b
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/MessengerInitEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { MessengerInitParser } from '../../parser/friendlist/MessengerInitParser';
+
+export class MessengerInitEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, MessengerInitParser);
+ }
+
+ public getParser(): MessengerInitParser
+ {
+ return this.parser as MessengerInitParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/MiniMailNewMessageEvent.ts b/src/nitro/communication/messages/incoming/friendlist/MiniMailNewMessageEvent.ts
new file mode 100644
index 00000000..64d40aa2
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/MiniMailNewMessageEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { MiniMailNewMessageParser } from '../../parser/friendlist/MiniMailNewMessageParser';
+
+export class MiniMailNewMessageEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, MiniMailNewMessageParser);
+ }
+
+ public getParser(): MiniMailNewMessageParser
+ {
+ return this.parser as MiniMailNewMessageParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/MiniMailUnreadCountEvent.ts b/src/nitro/communication/messages/incoming/friendlist/MiniMailUnreadCountEvent.ts
new file mode 100644
index 00000000..36d1fcf6
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/MiniMailUnreadCountEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { MiniMailUnreadCountParser } from '../../parser/friendlist/MiniMailUnreadCountParser';
+
+export class MiniMailUnreadCountEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, MiniMailUnreadCountParser);
+ }
+
+ public getParser(): MiniMailUnreadCountParser
+ {
+ return this.parser as MiniMailUnreadCountParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/NewConsoleMessageEvent.ts b/src/nitro/communication/messages/incoming/friendlist/NewConsoleMessageEvent.ts
new file mode 100644
index 00000000..5878bc65
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/NewConsoleMessageEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { NewConsoleMessageParser } from '../../parser/friendlist/NewConsoleMessageParser';
+
+export class NewConsoleMessageEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, NewConsoleMessageParser);
+ }
+
+ public getParser(): NewConsoleMessageParser
+ {
+ return this.parser as NewConsoleMessageParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/NewFriendRequestEvent.ts b/src/nitro/communication/messages/incoming/friendlist/NewFriendRequestEvent.ts
new file mode 100644
index 00000000..9cb46a60
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/NewFriendRequestEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { NewFriendRequestParser } from '../../parser/friendlist/NewFriendRequestMessageParser';
+
+export class NewFriendRequestEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, NewFriendRequestParser);
+ }
+
+ public getParser(): NewFriendRequestParser
+ {
+ return this.parser as NewFriendRequestParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/RoomInviteErrorEvent.ts b/src/nitro/communication/messages/incoming/friendlist/RoomInviteErrorEvent.ts
new file mode 100644
index 00000000..d3d9dde5
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/RoomInviteErrorEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { RoomInviteErrorParser } from '../../parser/friendlist/RoomInviteErrorParser';
+
+export class RoomInviteErrorEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomInviteErrorParser);
+ }
+
+ public getParser(): RoomInviteErrorParser
+ {
+ return this.parser as RoomInviteErrorParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/friendlist/RoomInviteEvent.ts b/src/nitro/communication/messages/incoming/friendlist/RoomInviteEvent.ts
new file mode 100644
index 00000000..859842fe
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/friendlist/RoomInviteEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { RoomInviteParser } from '../../parser/friendlist/RoomInviteMessageParser';
+
+export class RoomInviteEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomInviteParser);
+ }
+
+ public getParser(): RoomInviteParser
+ {
+ return this.parser as RoomInviteParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/game/LoadGameUrlEvent.ts b/src/nitro/communication/messages/incoming/game/LoadGameUrlEvent.ts
new file mode 100644
index 00000000..85226e21
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/game/LoadGameUrlEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { LoadGameUrlParser } from '../../parser/game/LoadGameUrlParser';
+
+export class LoadGameUrlEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, LoadGameUrlParser);
+ }
+
+ public getParser(): LoadGameUrlParser
+ {
+ return this.parser as LoadGameUrlParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/generic/GenericErrorEvent.ts b/src/nitro/communication/messages/incoming/generic/GenericErrorEvent.ts
new file mode 100644
index 00000000..7e13fc1e
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/generic/GenericErrorEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { GenericErrorParser } from '../../parser/generic/GenericErrorParser';
+
+export class GenericErrorEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, GenericErrorParser);
+ }
+
+ public getParser(): GenericErrorParser
+ {
+ return this.parser as GenericErrorParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/group/GroupBadgePartsEvent.ts b/src/nitro/communication/messages/incoming/group/GroupBadgePartsEvent.ts
new file mode 100644
index 00000000..d9c6ca97
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/group/GroupBadgePartsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { GroupBadgePartsParser } from '../../parser/group/GroupBadgePartsParser';
+
+export class GroupBadgePartsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, GroupBadgePartsParser);
+ }
+
+ public getParser(): GroupBadgePartsParser
+ {
+ return this.parser as GroupBadgePartsParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/group/GroupBuyDataEvent.ts b/src/nitro/communication/messages/incoming/group/GroupBuyDataEvent.ts
new file mode 100644
index 00000000..23a8e187
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/group/GroupBuyDataEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { GroupBuyDataParser } from '../../parser/group/GroupBuyDataParser';
+
+export class GroupBuyDataEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, GroupBuyDataParser);
+ }
+
+ public getParser(): GroupBuyDataParser
+ {
+ return this.parser as GroupBuyDataParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/group/GroupConfirmMemberRemoveEvent.ts b/src/nitro/communication/messages/incoming/group/GroupConfirmMemberRemoveEvent.ts
new file mode 100644
index 00000000..3550173c
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/group/GroupConfirmMemberRemoveEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { GroupConfirmMemberRemoveParser } from '../../parser/group/GroupConfirmMemberRemoveParser';
+
+export class GroupConfirmMemberRemoveEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, GroupConfirmMemberRemoveParser);
+ }
+
+ public getParser(): GroupConfirmMemberRemoveParser
+ {
+ return this.parser as GroupConfirmMemberRemoveParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/group/GroupInformationEvent.ts b/src/nitro/communication/messages/incoming/group/GroupInformationEvent.ts
new file mode 100644
index 00000000..aa3d9afb
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/group/GroupInformationEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { GroupInformationParser } from '../../parser/group/GroupInformationParser';
+
+export class GroupInformationEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, GroupInformationParser);
+ }
+
+ public getParser(): GroupInformationParser
+ {
+ return this.parser as GroupInformationParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/group/GroupMembersEvent.ts b/src/nitro/communication/messages/incoming/group/GroupMembersEvent.ts
new file mode 100644
index 00000000..34e11f6a
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/group/GroupMembersEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { GroupMembersParser } from '../../parser/group/GroupMembersParser';
+
+export class GroupMembersEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, GroupMembersParser);
+ }
+
+ public getParser(): GroupMembersParser
+ {
+ return this.parser as GroupMembersParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/group/GroupSettingsEvent.ts b/src/nitro/communication/messages/incoming/group/GroupSettingsEvent.ts
new file mode 100644
index 00000000..6cb4c775
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/group/GroupSettingsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { GroupSettingsParser } from '../../parser/group/GroupSettingsParser';
+
+export class GroupSettingsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, GroupSettingsParser);
+ }
+
+ public getParser(): GroupSettingsParser
+ {
+ return this.parser as GroupSettingsParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/help/CallForHelpResultMessageEvent.ts b/src/nitro/communication/messages/incoming/help/CallForHelpResultMessageEvent.ts
new file mode 100644
index 00000000..277a3166
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/help/CallForHelpResultMessageEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { CallForHelpResultMessageParser } from '../../parser/help/CallForHelpResultMessageParser';
+
+export class CallForHelpResultMessageEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, CallForHelpResultMessageParser);
+ }
+
+ public getParser(): CallForHelpResultMessageParser
+ {
+ return this.parser as CallForHelpResultMessageParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/achievements/Achievement.ts b/src/nitro/communication/messages/incoming/inventory/achievements/Achievement.ts
new file mode 100644
index 00000000..fc7efce0
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/achievements/Achievement.ts
@@ -0,0 +1,156 @@
+import { IMessageDataWrapper } from '../../../../../../core/communication/messages/IMessageDataWrapper';
+
+export class Achievement
+{
+ public static _Str_21736: number = -1;
+ public static _Str_21318: number = 0;
+ public static _Str_15908: number = 1;
+ public static _Str_20384: number = 2;
+
+ private _achievementId: number;
+ private _level: number;
+ private _badgeId: string;
+ private _Str_6791: number;
+ private _Str_18274: number;
+ private _Str_10280: number;
+ private _Str_12282: number;
+ private _Str_19007: number;
+ private _Str_16081: boolean;
+ private _category: string;
+ private _Str_21707: string;
+ private _Str_20339: number;
+ private _Str_19099: number;
+
+ private _unseen: number = 0;
+
+ constructor(wrapper: IMessageDataWrapper)
+ {
+ if(!wrapper) throw new Error('invalid_parser');
+
+ this._achievementId = wrapper.readInt();
+ this._level = wrapper.readInt();
+ this._badgeId = wrapper.readString();
+ this._Str_6791 = wrapper.readInt();
+ this._Str_18274 = Math.max(1, wrapper.readInt());
+ this._Str_10280 = wrapper.readInt();
+ this._Str_12282 = wrapper.readInt();
+ this._Str_19007 = wrapper.readInt();
+ this._Str_16081 = wrapper.readBoolean();
+ this._category = wrapper.readString();
+ this._Str_21707 = wrapper.readString();
+ this._Str_20339 = wrapper.readInt();
+ this._Str_19099 = wrapper.readInt();
+ }
+
+ public get achievementId(): number
+ {
+ return this._achievementId;
+ }
+
+ public get badgeId(): string
+ {
+ return this._badgeId;
+ }
+
+ public get level(): number
+ {
+ return this._level;
+ }
+
+ public get _Str_25209(): number
+ {
+ return this._Str_6791;
+ }
+
+ public get _Str_24142(): number
+ {
+ return (this._Str_18274 - this._Str_6791);
+ }
+
+ public get rewardAmount(): number
+ {
+ return this._Str_10280;
+ }
+
+ public get rewardType(): number
+ {
+ return this._Str_12282;
+ }
+
+ public get _Str_22939(): number
+ {
+ return (this._Str_19007 - this._Str_6791);
+ }
+
+ public get _Str_7518(): boolean
+ {
+ return this._Str_16081;
+ }
+
+ public get category(): string
+ {
+ return this._category;
+ }
+
+ public get _Str_25896(): string
+ {
+ return this._Str_21707;
+ }
+
+ public get totalLevels(): number
+ {
+ return this._Str_20339;
+ }
+
+ public get _Str_10438(): boolean
+ {
+ return (this._level > 1) || (this._Str_16081);
+ }
+
+ public _Str_24410(): void
+ {
+ this._Str_19007 = this._Str_18274;
+ }
+
+ public get _Str_24874(): number
+ {
+ return this._Str_19099;
+ }
+
+ public get progress(): number
+ {
+ return this._Str_19007;
+ }
+
+ public get toNextProgress(): number
+ {
+ return this._Str_18274;
+ }
+
+ public set unseen(unseen: number)
+ {
+ this._unseen = unseen;
+ }
+
+ public get unseen(): number
+ {
+ return this._unseen;
+ }
+
+ public reset(badge: Achievement)
+ {
+ this._achievementId = badge._achievementId;
+ this._level = badge._level;
+ this._badgeId = badge._badgeId;
+ this._Str_6791 = badge._Str_6791;
+ this._Str_18274 = badge._Str_18274;
+ this._Str_10280 = badge._Str_10280;
+ this._Str_12282 = badge._Str_12282;
+ this._Str_19007 = badge._Str_19007;
+ this._Str_16081 = badge._Str_16081;
+ this._category = badge.category;
+ this._Str_21707 = badge._Str_21707;
+ this._Str_20339 = badge._Str_20339;
+ this._Str_19099 = badge._Str_19099;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/achievements/AchievementEvent.ts b/src/nitro/communication/messages/incoming/inventory/achievements/AchievementEvent.ts
new file mode 100644
index 00000000..3d6a1bf5
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/achievements/AchievementEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { AchievementParser } from '../../../parser/inventory/achievements/AchievementParser';
+
+export class AchievementEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, AchievementParser);
+ }
+
+ public getParser(): AchievementParser
+ {
+ return this.parser as AchievementParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/achievements/AchievementResolution.ts b/src/nitro/communication/messages/incoming/inventory/achievements/AchievementResolution.ts
new file mode 100644
index 00000000..39f2577c
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/achievements/AchievementResolution.ts
@@ -0,0 +1,59 @@
+import { IMessageDataWrapper } from '../../../../../../core/communication/messages/IMessageDataWrapper';
+
+export class AchievementResolution
+{
+ public static _Str_16945: number = 0;
+
+ private _achievementId: number;
+ private _level: number;
+ private _badgeId: string;
+ private _Str_8741: number;
+ private _state: number;
+
+ constructor(wrapper: IMessageDataWrapper)
+ {
+ this._achievementId = wrapper.readInt();
+ this._level = wrapper.readInt();
+ this._badgeId = wrapper.readString();
+ this._Str_8741 = wrapper.readInt();
+ this._state = wrapper.readInt();
+ }
+
+ public dispose(): void
+ {
+ this._achievementId = 0;
+ this._level = 0;
+ this._badgeId = '';
+ this._Str_8741 = 0;
+ }
+
+ public get achievementId(): number
+ {
+ return this._achievementId;
+ }
+
+ public get level(): number
+ {
+ return this._level;
+ }
+
+ public get badgeId(): string
+ {
+ return this._badgeId;
+ }
+
+ public get _Str_20240(): number
+ {
+ return this._Str_8741;
+ }
+
+ public get enabled(): boolean
+ {
+ return (this._state === AchievementResolution._Str_16945);
+ }
+
+ public get state(): number
+ {
+ return this._state;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/achievements/AchievementsEvent.ts b/src/nitro/communication/messages/incoming/inventory/achievements/AchievementsEvent.ts
new file mode 100644
index 00000000..f5698094
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/achievements/AchievementsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { AchievementsParser } from '../../../parser/inventory/achievements/AchievementsParser';
+
+export class AchievementsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, AchievementsParser);
+ }
+
+ public getParser(): AchievementsParser
+ {
+ return this.parser as AchievementsParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/achievements/AchievementsScoreEvent.ts b/src/nitro/communication/messages/incoming/inventory/achievements/AchievementsScoreEvent.ts
new file mode 100644
index 00000000..92735e26
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/achievements/AchievementsScoreEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { AchievementsScoreParser } from '../../../parser/inventory/achievements/AchievementsScoreParser';
+
+export class AchievementsScoreEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, AchievementsScoreParser);
+ }
+
+ public getParser(): AchievementsScoreParser
+ {
+ return this.parser as AchievementsScoreParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffect.ts b/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffect.ts
new file mode 100644
index 00000000..01c08256
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffect.ts
@@ -0,0 +1,69 @@
+export class AvatarEffect
+{
+ private _type: number;
+ private _subType: number;
+ private _duration: number;
+ private _inactiveEffectsInInventory: number;
+ private _secondsLeftIfActive: number;
+ private _permanent: boolean;
+
+ public get type(): number
+ {
+ return this._type;
+ }
+
+ public set type(k: number)
+ {
+ this._type = k;
+ }
+
+ public get _Str_3882(): number
+ {
+ return this._subType;
+ }
+
+ public set _Str_3882(k: number)
+ {
+ this._subType = k;
+ }
+
+ public get duration(): number
+ {
+ return this._duration;
+ }
+
+ public set duration(k: number)
+ {
+ this._duration = k;
+ }
+
+ public get _Str_18572(): number
+ {
+ return this._inactiveEffectsInInventory;
+ }
+
+ public set _Str_18572(k: number)
+ {
+ this._inactiveEffectsInInventory = k;
+ }
+
+ public get _Str_12185(): number
+ {
+ return this._secondsLeftIfActive;
+ }
+
+ public set _Str_12185(k: number)
+ {
+ this._secondsLeftIfActive = k;
+ }
+
+ public get _Str_4010(): boolean
+ {
+ return this._permanent;
+ }
+
+ public set _Str_4010(k: boolean)
+ {
+ this._permanent = k;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectActivatedEvent.ts b/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectActivatedEvent.ts
new file mode 100644
index 00000000..47ff020b
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectActivatedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { AvatarEffectActivatedParser } from '../../../parser/inventory/avatareffect/AvatarEffectActivatedParser';
+
+export class AvatarEffectActivatedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, AvatarEffectActivatedParser);
+ }
+
+ public getParser(): AvatarEffectActivatedParser
+ {
+ return this.parser as AvatarEffectActivatedParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectAddedEvent.ts b/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectAddedEvent.ts
new file mode 100644
index 00000000..78d17fa0
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectAddedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { AvatarEffectAddedParser } from '../../../parser/inventory/avatareffect/AvatarEffectAddedParser';
+
+export class AvatarEffectAddedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, AvatarEffectAddedParser);
+ }
+
+ public getParser(): AvatarEffectAddedParser
+ {
+ return this.parser as AvatarEffectAddedParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectExpiredEvent.ts b/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectExpiredEvent.ts
new file mode 100644
index 00000000..e2f6cd25
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectExpiredEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { AvatarEffectExpiredParser } from '../../../parser/inventory/avatareffect/AvatarEffectExpiredParser';
+
+export class AvatarEffectExpiredEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, AvatarEffectExpiredParser);
+ }
+
+ public getParser(): AvatarEffectExpiredParser
+ {
+ return this.parser as AvatarEffectExpiredParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectSelectedEvent.ts b/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectSelectedEvent.ts
new file mode 100644
index 00000000..88b7bbc0
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectSelectedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { AvatarEffectSelectedParser } from '../../../parser/inventory/avatareffect/AvatarEffectSelectedParser';
+
+export class AvatarEffectSelectedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, AvatarEffectSelectedParser);
+ }
+
+ public getParser(): AvatarEffectSelectedParser
+ {
+ return this.parser as AvatarEffectSelectedParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectsEvent.ts b/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectsEvent.ts
new file mode 100644
index 00000000..2041f9d1
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/avatareffect/AvatarEffectsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { AvatarEffectsParser } from '../../../parser/inventory/avatareffect/AvatarEffectsParser';
+
+export class AvatarEffectsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, AvatarEffectsParser);
+ }
+
+ public getParser(): AvatarEffectsParser
+ {
+ return this.parser as AvatarEffectsParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/inventory/badges/BadgesEvent.ts b/src/nitro/communication/messages/incoming/inventory/badges/BadgesEvent.ts
new file mode 100644
index 00000000..bae0c33d
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/badges/BadgesEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { BadgesParser } from '../../../parser/inventory/badges/BadgesParser';
+
+export class BadgesEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, BadgesParser);
+ }
+
+ public getParser(): BadgesParser
+ {
+ return this.parser as BadgesParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/inventory/badges/_Str_8120.ts b/src/nitro/communication/messages/incoming/inventory/badges/_Str_8120.ts
new file mode 100644
index 00000000..f3413334
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/badges/_Str_8120.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { _Str_7491 } from '../../../parser/inventory/badges/_Str_7491';
+
+export class _Str_8120 extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, _Str_7491);
+ }
+
+ public getParser(): _Str_7491
+ {
+ return this.parser as _Str_7491;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/badges/_Str_8179.ts b/src/nitro/communication/messages/incoming/inventory/badges/_Str_8179.ts
new file mode 100644
index 00000000..15feb804
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/badges/_Str_8179.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { _Str_9135 } from '../../../parser/inventory/badges/_Str_9135';
+
+export class _Str_8179 extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, _Str_9135);
+ }
+
+ public getParser(): _Str_9135
+ {
+ return this.parser as _Str_9135;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/badges/_Str_8980.ts b/src/nitro/communication/messages/incoming/inventory/badges/_Str_8980.ts
new file mode 100644
index 00000000..75597335
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/badges/_Str_8980.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { _Str_7305 } from '../../../parser/inventory/badges/_Str_7305';
+
+export class _Str_8980 extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, _Str_7305);
+ }
+
+ public getParser(): _Str_7305
+ {
+ return this.parser as _Str_7305;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/bots/BotAddedToInventoryEvent.ts b/src/nitro/communication/messages/incoming/inventory/bots/BotAddedToInventoryEvent.ts
new file mode 100644
index 00000000..fe55b447
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/bots/BotAddedToInventoryEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { BotAddedToInventoryParser } from '../../../parser/inventory/bots/BotAddedToInventoryParser';
+
+export class BotAddedToInventoryEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, BotAddedToInventoryParser);
+ }
+
+ public getParser(): BotAddedToInventoryParser
+ {
+ return this.parser as BotAddedToInventoryParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/bots/BotInventoryEvent.ts b/src/nitro/communication/messages/incoming/inventory/bots/BotInventoryEvent.ts
new file mode 100644
index 00000000..e5452974
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/bots/BotInventoryEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { BotInventoryParser } from '../../../parser/inventory/bots/BotReceivedMessageParser';
+
+export class BotInventoryEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, BotInventoryParser);
+ }
+
+ public getParser(): BotInventoryParser
+ {
+ return this.parser as BotInventoryParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/inventory/bots/BotInventoryMessageEvent.ts b/src/nitro/communication/messages/incoming/inventory/bots/BotInventoryMessageEvent.ts
new file mode 100644
index 00000000..421e35a7
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/bots/BotInventoryMessageEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { BotInventoryMessageParser } from '../../../parser/inventory/bots/BotInventoryMessageParser';
+
+export class BotInventoryMessageEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, BotInventoryMessageParser);
+ }
+
+ public getParser(): BotInventoryMessageParser
+ {
+ return this.parser as BotInventoryMessageParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/bots/BotRemovedFromInventoryEvent.ts b/src/nitro/communication/messages/incoming/inventory/bots/BotRemovedFromInventoryEvent.ts
new file mode 100644
index 00000000..e2400316
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/bots/BotRemovedFromInventoryEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { BotRemovedFromInventoryParser } from '../../../parser/inventory/bots/BotRemovedFromInventoryParser';
+
+export class BotRemovedFromInventoryEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, BotRemovedFromInventoryParser);
+ }
+
+ public getParser(): BotRemovedFromInventoryParser
+ {
+ return this.parser as BotRemovedFromInventoryParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/clothes/FigureSetIdsMessageEvent.ts b/src/nitro/communication/messages/incoming/inventory/clothes/FigureSetIdsMessageEvent.ts
new file mode 100644
index 00000000..1b68df23
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/clothes/FigureSetIdsMessageEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { FigureSetIdsMessageParser } from '../../../parser/inventory/clothing/FigureSetIdsMessageParser';
+
+export class FigureSetIdsMessageEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FigureSetIdsMessageParser);
+ }
+
+ public getParser(): FigureSetIdsMessageParser
+ {
+ return this.parser as FigureSetIdsMessageParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/clothes/_Str_16135.ts b/src/nitro/communication/messages/incoming/inventory/clothes/_Str_16135.ts
new file mode 100644
index 00000000..073b3397
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/clothes/_Str_16135.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { _Str_8728 } from '../../../parser/inventory/clothing/_Str_8728';
+
+export class _Str_16135 extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, _Str_8728);
+ }
+
+ public getParser(): _Str_8728
+ {
+ return this.parser as _Str_8728;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/clothes/_Str_17532.ts b/src/nitro/communication/messages/incoming/inventory/clothes/_Str_17532.ts
new file mode 100644
index 00000000..ecfb0e5f
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/clothes/_Str_17532.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { _Str_9021 } from '../../../parser/inventory/clothing/_Str_9021';
+
+export class _Str_17532 extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, _Str_9021);
+ }
+
+ public getParser(): _Str_9021
+ {
+ return this.parser as _Str_9021;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/furni/FurnitureListAddOrUpdateEvent.ts b/src/nitro/communication/messages/incoming/inventory/furni/FurnitureListAddOrUpdateEvent.ts
new file mode 100644
index 00000000..91ccaffe
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/furni/FurnitureListAddOrUpdateEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureListAddOrUpdateParser } from '../../../parser/inventory/furniture/FurnitureListAddOrUpdateParser';
+
+export class FurnitureListAddOrUpdateEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureListAddOrUpdateParser);
+ }
+
+ public getParser(): FurnitureListAddOrUpdateParser
+ {
+ return this.parser as FurnitureListAddOrUpdateParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/furni/FurnitureListEvent.ts b/src/nitro/communication/messages/incoming/inventory/furni/FurnitureListEvent.ts
new file mode 100644
index 00000000..b0a9384c
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/furni/FurnitureListEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureListParser } from '../../../parser/inventory/furniture/FurnitureListParser';
+
+export class FurnitureListEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureListParser);
+ }
+
+ public getParser(): FurnitureListParser
+ {
+ return this.parser as FurnitureListParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/furni/FurnitureListInvalidateEvent.ts b/src/nitro/communication/messages/incoming/inventory/furni/FurnitureListInvalidateEvent.ts
new file mode 100644
index 00000000..b66972d6
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/furni/FurnitureListInvalidateEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureListInvalidateParser } from '../../../parser/inventory/furniture/FurnitureListInvalidateParser';
+
+export class FurnitureListInvalidateEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureListInvalidateParser);
+ }
+
+ public getParser(): FurnitureListInvalidateParser
+ {
+ return this.parser as FurnitureListInvalidateParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/furni/FurnitureListRemovedEvent.ts b/src/nitro/communication/messages/incoming/inventory/furni/FurnitureListRemovedEvent.ts
new file mode 100644
index 00000000..185706f1
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/furni/FurnitureListRemovedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureListRemovedParser } from '../../../parser/inventory/furniture/FurnitureListRemovedParser';
+
+export class FurnitureListRemovedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureListRemovedParser);
+ }
+
+ public getParser(): FurnitureListRemovedParser
+ {
+ return this.parser as FurnitureListRemovedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/furni/FurniturePostItPlacedEvent.ts b/src/nitro/communication/messages/incoming/inventory/furni/FurniturePostItPlacedEvent.ts
new file mode 100644
index 00000000..af96c5f3
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/furni/FurniturePostItPlacedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { FurniturePostItPlacedParser } from '../../../parser/inventory/furniture/FurniturePostItPlacedParser';
+
+export class FurniturePostItPlacedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurniturePostItPlacedParser);
+ }
+
+ public getParser(): FurniturePostItPlacedParser
+ {
+ return this.parser as FurniturePostItPlacedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/furni/IFurnitureItemData.ts b/src/nitro/communication/messages/incoming/inventory/furni/IFurnitureItemData.ts
new file mode 100644
index 00000000..813d08b2
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/furni/IFurnitureItemData.ts
@@ -0,0 +1,28 @@
+import { IObjectData } from '../../../../../room/object/data/IObjectData';
+
+export interface IFurnitureItemData
+{
+ itemId: number;
+ furniType: string;
+ ref: number;
+ spriteId: number;
+ category: number;
+ stuffData: IObjectData;
+ isGroupable: boolean;
+ isRecycleable: boolean;
+ tradable: boolean;
+ sellable: boolean;
+ secondsToExpiration: number;
+ flatId: number;
+ slotId: string;
+ _Str_3951: number;
+ _Str_2794: number;
+ rentable: boolean;
+ isWallItem: boolean;
+ hasRentPeriodStarted: boolean;
+ _Str_10616: number;
+ _Str_8932: number;
+ _Str_9050: number;
+ _Str_9408: number;
+ _Str_19297: boolean;
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/furni/gifts/FurnitureGiftOpenedEvent.ts b/src/nitro/communication/messages/incoming/inventory/furni/gifts/FurnitureGiftOpenedEvent.ts
new file mode 100644
index 00000000..b95a8467
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/furni/gifts/FurnitureGiftOpenedEvent.ts
@@ -0,0 +1,17 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureGiftOpenedParser } from '../../../../parser/inventory/furniture/FurnitureGiftOpenedParser';
+
+// see _Str_9591
+export class FurnitureGiftOpenedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureGiftOpenedParser);
+ }
+
+ public getParser(): FurnitureGiftOpenedParser
+ {
+ return this.parser as FurnitureGiftOpenedParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/inventory/pets/PetAddedToInventoryEvent.ts b/src/nitro/communication/messages/incoming/inventory/pets/PetAddedToInventoryEvent.ts
new file mode 100644
index 00000000..31eb0db6
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/pets/PetAddedToInventoryEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { PetAddedToInventoryParser } from '../../../parser/inventory/pets/PetAddedToInventoryParser';
+
+export class PetAddedToInventoryEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, PetAddedToInventoryParser);
+ }
+
+ public getParser(): PetAddedToInventoryParser
+ {
+ return this.parser as PetAddedToInventoryParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/inventory/pets/PetInventoryEvent.ts b/src/nitro/communication/messages/incoming/inventory/pets/PetInventoryEvent.ts
new file mode 100644
index 00000000..cbf1cc23
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/pets/PetInventoryEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { PetInventoryParser } from '../../../parser/inventory/pets/PetInventoryParser';
+
+export class PetInventoryEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, PetInventoryParser);
+ }
+
+ public getParser(): PetInventoryParser
+ {
+ return this.parser as PetInventoryParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/inventory/pets/PetRemovedFromInventoryEvent.ts b/src/nitro/communication/messages/incoming/inventory/pets/PetRemovedFromInventoryEvent.ts
new file mode 100644
index 00000000..0e7c833c
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/pets/PetRemovedFromInventoryEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { PetRemovedFromInventoryParser } from '../../../parser/inventory/pets/PetRemovedFromInventoryParser';
+
+export class PetRemovedFromInventory extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, PetRemovedFromInventoryParser);
+ }
+
+ public getParser(): PetRemovedFromInventoryParser
+ {
+ return this.parser as PetRemovedFromInventoryParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/inventory/trading/TradingAcceptEvent.ts b/src/nitro/communication/messages/incoming/inventory/trading/TradingAcceptEvent.ts
new file mode 100644
index 00000000..bc9e636a
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/trading/TradingAcceptEvent.ts
@@ -0,0 +1,26 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { TradingAcceptParser } from '../../../parser/inventory/trading/TradingAcceptParser';
+
+export class TradingAcceptEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, TradingAcceptParser);
+ }
+
+ public get _Str_4963(): number
+ {
+ return this.getParser()._Str_4963;
+ }
+
+ public get _Str_15794(): boolean
+ {
+ return this.getParser()._Str_15794;
+ }
+
+ public getParser(): TradingAcceptParser
+ {
+ return this.parser as TradingAcceptParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/trading/TradingCloseEvent.ts b/src/nitro/communication/messages/incoming/inventory/trading/TradingCloseEvent.ts
new file mode 100644
index 00000000..e0957081
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/trading/TradingCloseEvent.ts
@@ -0,0 +1,21 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { TradingCloseParser } from '../../../parser/inventory/trading/TradingCloseParser';
+
+export class TradingCloseEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, TradingCloseParser);
+ }
+
+ public get _Str_4963(): number
+ {
+ return this.getParser()._Str_4963;
+ }
+
+ public getParser(): TradingCloseParser
+ {
+ return this.parser as TradingCloseParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/trading/TradingCompletedEvent.ts b/src/nitro/communication/messages/incoming/inventory/trading/TradingCompletedEvent.ts
new file mode 100644
index 00000000..b1a1b462
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/trading/TradingCompletedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { TradingCompletedParser } from '../../../parser/inventory/trading/TradingCompletedParser';
+
+export class TradingCompletedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, TradingCompletedParser);
+ }
+
+ public getParser(): TradingCompletedParser
+ {
+ return this.parser as TradingCompletedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/trading/TradingConfirmationEvent.ts b/src/nitro/communication/messages/incoming/inventory/trading/TradingConfirmationEvent.ts
new file mode 100644
index 00000000..08b81fcf
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/trading/TradingConfirmationEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { TradingConfirmationParser } from '../../../parser/inventory/trading/TradingConfirmationParser';
+
+export class TradingConfirmationEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, TradingConfirmationParser);
+ }
+
+ public getParser(): TradingConfirmationParser
+ {
+ return this.parser as TradingConfirmationParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/trading/TradingListItem.ts b/src/nitro/communication/messages/incoming/inventory/trading/TradingListItem.ts
new file mode 100644
index 00000000..15b08418
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/trading/TradingListItem.ts
@@ -0,0 +1,163 @@
+import { IMessageDataWrapper } from '../../../../../../core/communication/messages/IMessageDataWrapper';
+import { Nitro } from '../../../../../Nitro';
+import { IObjectData } from '../../../../../room/object/data/IObjectData';
+import { FurnitureDataParser } from '../../../parser/room/furniture/FurnitureDataParser';
+import { IFurnitureItemData } from '../furni/IFurnitureItemData';
+
+export class TradingListItem implements IFurnitureItemData
+{
+ private _Str_5390: number;
+ private _isWallItem: boolean;
+ private _itemId: number;
+ private _furniType: string;
+ private _ref: number;
+ private _spriteId: number;
+ private _category: number;
+ private _stuffData: IObjectData;
+ private _Str_3182: number;
+ private _secondsToExpiration: number;
+ private _Str_9291: number;
+ private _Str_8744: number;
+ private _Str_9700: number;
+ private _isGroupable: boolean;
+ private _Str_2808: number;
+ private _flatId: number;
+ private _rentable: boolean;
+ private _hasRentPeriodStarted: boolean;
+
+ constructor(wrapper: IMessageDataWrapper)
+ {
+ this._itemId = wrapper.readInt();
+ this._furniType = wrapper.readString().toUpperCase();
+ this._ref = wrapper.readInt();
+ this._spriteId = wrapper.readInt();
+ this._category = wrapper.readInt();
+ this._isGroupable = wrapper.readBoolean();
+ this._stuffData = FurnitureDataParser.parseObjectData(wrapper);
+ this._secondsToExpiration = -1;
+ this._Str_5390 = Nitro.instance.time;
+ this._hasRentPeriodStarted = false;
+ this._Str_9291 = wrapper.readInt();
+ this._Str_8744 = wrapper.readInt();
+ this._Str_9700 = wrapper.readInt();
+ this._Str_3182 = ((this.furniType === 'S') ? wrapper.readInt() : -1);
+ this._flatId = -1;
+ this._rentable = false;
+ this._isWallItem = (this._furniType === 'I');
+ }
+
+ public get itemId(): number
+ {
+ return this._itemId;
+ }
+
+ public get furniType(): string
+ {
+ return this._furniType;
+ }
+
+ public get ref(): number
+ {
+ return this._ref;
+ }
+
+ public get spriteId(): number
+ {
+ return this._spriteId;
+ }
+
+ public get category(): number
+ {
+ return this._category;
+ }
+
+ public get stuffData(): IObjectData
+ {
+ return this._stuffData;
+ }
+
+ public get _Str_2794(): number
+ {
+ return this._Str_3182;
+ }
+
+ public get secondsToExpiration(): number
+ {
+ return this._secondsToExpiration;
+ }
+
+ public get _Str_8932(): number
+ {
+ return this._Str_9291;
+ }
+
+ public get _Str_9050(): number
+ {
+ return this._Str_8744;
+ }
+
+ public get _Str_9408(): number
+ {
+ return this._Str_9700;
+ }
+
+ public get isGroupable(): boolean
+ {
+ return this._isGroupable;
+ }
+
+ public get _Str_3951(): number
+ {
+ return this._Str_3182;
+ }
+
+ public get flatId(): number
+ {
+ return this._flatId;
+ }
+
+ public get rentable(): boolean
+ {
+ return this._rentable;
+ }
+
+ public get isWallItem(): boolean
+ {
+ return this._isWallItem;
+ }
+
+ public get hasRentPeriodStarted(): boolean
+ {
+ return this._hasRentPeriodStarted;
+ }
+
+ public get _Str_10616(): number
+ {
+ return this._Str_5390;
+ }
+
+ public get isRecycleable(): boolean
+ {
+ return true;
+ }
+
+ public get tradable(): boolean
+ {
+ return true;
+ }
+
+ public get sellable(): boolean
+ {
+ return true;
+ }
+
+ public get slotId(): string
+ {
+ return null;
+ }
+
+ public get _Str_19297(): boolean
+ {
+ return (this._furniType.indexOf('external_image') !== -1);
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/inventory/trading/TradingListItemEvent.ts b/src/nitro/communication/messages/incoming/inventory/trading/TradingListItemEvent.ts
new file mode 100644
index 00000000..8d91fd827
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/trading/TradingListItemEvent.ts
@@ -0,0 +1,57 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { TradingListItemParser } from '../../../parser/inventory/trading/TradingListItemParser';
+import { TradingListItem } from './TradingListItem';
+
+export class TradingListItemEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, TradingListItemParser);
+ }
+
+ public get _Str_15162(): number
+ {
+ return this.getParser()._Str_15162;
+ }
+
+ public get _Str_18215(): number
+ {
+ return this.getParser()._Str_18215;
+ }
+
+ public get _Str_14946(): number
+ {
+ return this.getParser()._Str_14946;
+ }
+
+ public get _Str_13801(): number
+ {
+ return this.getParser()._Str_13801;
+ }
+
+ public get _Str_15709(): number
+ {
+ return this.getParser()._Str_15709;
+ }
+
+ public get _Str_9138(): number
+ {
+ return this.getParser()._Str_9138;
+ }
+
+ public get _Str_17841(): TradingListItem[]
+ {
+ return this.getParser()._Str_17841;
+ }
+
+ public get _Str_17465(): TradingListItem[]
+ {
+ return this.getParser()._Str_17465;
+ }
+
+ public getParser(): TradingListItemParser
+ {
+ return this.parser as TradingListItemParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/trading/TradingNotOpenEvent.ts b/src/nitro/communication/messages/incoming/inventory/trading/TradingNotOpenEvent.ts
new file mode 100644
index 00000000..cb76ddfd
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/trading/TradingNotOpenEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { TradingNotOpenParser } from '../../../parser/inventory/trading/TradingNotOpenParser';
+
+export class TradingNotOpenEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, TradingNotOpenParser);
+ }
+
+ public getParser(): TradingNotOpenParser
+ {
+ return this.parser as TradingNotOpenParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/trading/TradingOpenEvent.ts b/src/nitro/communication/messages/incoming/inventory/trading/TradingOpenEvent.ts
new file mode 100644
index 00000000..2ed9243c
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/trading/TradingOpenEvent.ts
@@ -0,0 +1,36 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { TradingOpenParser } from '../../../parser/inventory/trading/TradingOpenParser';
+
+export class TradingOpenEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, TradingOpenParser);
+ }
+
+ public get _Str_4963(): number
+ {
+ return this.getParser()._Str_4963;
+ }
+
+ public get _Str_16764(): boolean
+ {
+ return this.getParser()._Str_16764;
+ }
+
+ public get _Str_17613(): number
+ {
+ return this.getParser()._Str_17613;
+ }
+
+ public get _Str_13374(): boolean
+ {
+ return this.getParser()._Str_13374;
+ }
+
+ public getParser(): TradingOpenParser
+ {
+ return this.parser as TradingOpenParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/trading/TradingOpenFailedEvent.ts b/src/nitro/communication/messages/incoming/inventory/trading/TradingOpenFailedEvent.ts
new file mode 100644
index 00000000..0bbafe5c
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/trading/TradingOpenFailedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { TradingOpenFailedParser } from '../../../parser/inventory/trading/TradingOpenFailedParser';
+
+export class TradingOpenFailedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, TradingOpenFailedParser);
+ }
+
+ public getParser(): TradingOpenFailedParser
+ {
+ return this.parser as TradingOpenFailedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/trading/TradingOtherNotAllowedEvent.ts b/src/nitro/communication/messages/incoming/inventory/trading/TradingOtherNotAllowedEvent.ts
new file mode 100644
index 00000000..3b0eb484
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/trading/TradingOtherNotAllowedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { TradingOtherNotAllowedParser } from '../../../parser/inventory/trading/TradingOtherNotAllowedParser';
+
+export class TradingOtherNotAllowedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, TradingOtherNotAllowedParser);
+ }
+
+ public getParser(): TradingOtherNotAllowedParser
+ {
+ return this.parser as TradingOtherNotAllowedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/inventory/trading/TradingYouAreNotAllowedEvent.ts b/src/nitro/communication/messages/incoming/inventory/trading/TradingYouAreNotAllowedEvent.ts
new file mode 100644
index 00000000..c77563a0
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/inventory/trading/TradingYouAreNotAllowedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { TradingYouAreNotAllowedParser } from '../../../parser/inventory/trading/TradingYouAreNotAllowedParser';
+
+export class TradingYouAreNotAllowedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, TradingYouAreNotAllowedParser);
+ }
+
+ public getParser(): TradingYouAreNotAllowedParser
+ {
+ return this.parser as TradingYouAreNotAllowedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/moderation/ModeratorMessageEvent.ts b/src/nitro/communication/messages/incoming/moderation/ModeratorMessageEvent.ts
new file mode 100644
index 00000000..d63d55ac
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/moderation/ModeratorMessageEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { ModeratorMessageParser } from '../../parser/moderation/ModeratorMessageParser';
+
+export class ModeratorMessageEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, ModeratorMessageParser);
+ }
+
+ public getParser(): ModeratorMessageParser
+ {
+ return this.parser as ModeratorMessageParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/modtool/ModtoolCallForHelpTopicsEvent.ts b/src/nitro/communication/messages/incoming/modtool/ModtoolCallForHelpTopicsEvent.ts
new file mode 100644
index 00000000..76d9094b
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/modtool/ModtoolCallForHelpTopicsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { ModtoolCFHTopicsParser } from '../../parser/modtool/ModtoolCFHTopicsParser';
+
+export class ModtoolCallForHelpTopicsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, ModtoolCFHTopicsParser);
+ }
+
+ public getParser(): ModtoolCFHTopicsParser
+ {
+ return this.parser as ModtoolCFHTopicsParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/modtool/ModtoolMainEvent.ts b/src/nitro/communication/messages/incoming/modtool/ModtoolMainEvent.ts
new file mode 100644
index 00000000..63814725
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/modtool/ModtoolMainEvent.ts
@@ -0,0 +1,17 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { ModtoolRoomChatlogParser } from '../../parser/modtool/ModtoolRoomChatlogParser';
+import { ModtoolMainParser } from '../../parser/modtool/ModtoolMainParser';
+
+export class ModtoolMainEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, ModtoolMainParser);
+ }
+
+ public getParser(): ModtoolMainParser
+ {
+ return this.parser as ModtoolMainParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/modtool/ModtoolReceivedRoomsUserEvent.ts b/src/nitro/communication/messages/incoming/modtool/ModtoolReceivedRoomsUserEvent.ts
new file mode 100644
index 00000000..3122afbb
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/modtool/ModtoolReceivedRoomsUserEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { ModtoolRoomUsersParser } from '../../parser/modtool/ModtoolRoomUsersParser';
+
+export class ModtoolReceivedRoomsUserEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, ModtoolRoomUsersParser);
+ }
+
+ public getParser(): ModtoolRoomUsersParser
+ {
+ return this.parser as ModtoolRoomUsersParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/modtool/ModtoolRoomChatlogEvent.ts b/src/nitro/communication/messages/incoming/modtool/ModtoolRoomChatlogEvent.ts
new file mode 100644
index 00000000..1747c21c
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/modtool/ModtoolRoomChatlogEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { ModtoolRoomChatlogParser } from '../../parser/modtool/ModtoolRoomChatlogParser';
+
+export class ModtoolRoomChatlogEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, ModtoolRoomChatlogParser);
+ }
+
+ public getParser(): ModtoolRoomChatlogParser
+ {
+ return this.parser as ModtoolRoomChatlogParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/modtool/ModtoolRoomInfoEvent.ts b/src/nitro/communication/messages/incoming/modtool/ModtoolRoomInfoEvent.ts
new file mode 100644
index 00000000..5e451978
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/modtool/ModtoolRoomInfoEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { ModtoolRoomInfoParser } from '../../parser/modtool/ModtoolRoomInfoParser';
+
+export class ModtoolRoomInfoEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, ModtoolRoomInfoParser);
+ }
+
+ public getParser(): ModtoolRoomInfoParser
+ {
+ return this.parser as ModtoolRoomInfoParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/modtool/ModtoolUserChatlogEvent.ts b/src/nitro/communication/messages/incoming/modtool/ModtoolUserChatlogEvent.ts
new file mode 100644
index 00000000..97553c7c
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/modtool/ModtoolUserChatlogEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { ModtoolUserChatlogParser } from '../../parser/modtool/ModtoolUserChatlogParser';
+
+export class ModtoolUserChatlogEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, ModtoolUserChatlogParser);
+ }
+
+ public getParser(): ModtoolUserChatlogParser
+ {
+ return this.parser as ModtoolUserChatlogParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/modtool/ModtoolUserInfoEvent.ts b/src/nitro/communication/messages/incoming/modtool/ModtoolUserInfoEvent.ts
new file mode 100644
index 00000000..cd1eaa75
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/modtool/ModtoolUserInfoEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { ModtoolUserInfoParser } from '../../parser/modtool/ModtoolUserInfoParser';
+
+export class ModtoolUserInfoEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, ModtoolUserInfoParser);
+ }
+
+ public getParser(): ModtoolUserInfoParser
+ {
+ return this.parser as ModtoolUserInfoParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/navigator/NavigatorCategoriesEvent.ts b/src/nitro/communication/messages/incoming/navigator/NavigatorCategoriesEvent.ts
new file mode 100644
index 00000000..789352dd
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/navigator/NavigatorCategoriesEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { NavigatorCategoriesParser } from '../../parser/navigator/NavigatorCategoriesParser';
+
+export class NavigatorCategoriesEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, NavigatorCategoriesParser);
+ }
+
+ public getParser(): NavigatorCategoriesParser
+ {
+ return this.parser as NavigatorCategoriesParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/navigator/NavigatorCollapsedEvent.ts b/src/nitro/communication/messages/incoming/navigator/NavigatorCollapsedEvent.ts
new file mode 100644
index 00000000..eee2e601
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/navigator/NavigatorCollapsedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { NavigatorCollapsedParser } from '../../parser/navigator/NavigatorCollapsedParser';
+
+export class NavigatorCollapsedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, NavigatorCollapsedParser);
+ }
+
+ public getParser(): NavigatorCollapsedParser
+ {
+ return this.parser as NavigatorCollapsedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/navigator/NavigatorEventCategoriesEvent.ts b/src/nitro/communication/messages/incoming/navigator/NavigatorEventCategoriesEvent.ts
new file mode 100644
index 00000000..e83361a0
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/navigator/NavigatorEventCategoriesEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { NavigatorEventCategoriesParser } from '../../parser/navigator/NavigatorEventCategoriesParser';
+
+export class NavigatorEventCategoriesEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, NavigatorEventCategoriesParser);
+ }
+
+ public getParser(): NavigatorEventCategoriesParser
+ {
+ return this.parser as NavigatorEventCategoriesParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/navigator/NavigatorHomeRoomEvent.ts b/src/nitro/communication/messages/incoming/navigator/NavigatorHomeRoomEvent.ts
new file mode 100644
index 00000000..d5a444bd
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/navigator/NavigatorHomeRoomEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { NavigatorHomeRoomParser } from '../../parser/navigator/NavigatorHomeRoomParser';
+
+export class NavigatorHomeRoomEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, NavigatorHomeRoomParser);
+ }
+
+ public getParser(): NavigatorHomeRoomParser
+ {
+ return this.parser as NavigatorHomeRoomParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/navigator/NavigatorLiftedEvent.ts b/src/nitro/communication/messages/incoming/navigator/NavigatorLiftedEvent.ts
new file mode 100644
index 00000000..2624106e
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/navigator/NavigatorLiftedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { NavigatorLiftedParser } from '../../parser/navigator/NavigatorLiftedParser';
+
+export class NavigatorLiftedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, NavigatorLiftedParser);
+ }
+
+ public getParser(): NavigatorLiftedParser
+ {
+ return this.parser as NavigatorLiftedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/navigator/NavigatorMetadataEvent.ts b/src/nitro/communication/messages/incoming/navigator/NavigatorMetadataEvent.ts
new file mode 100644
index 00000000..44e7224f
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/navigator/NavigatorMetadataEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { NavigatorMetadataParser } from '../../parser/navigator/NavigatorMetadataParser';
+
+export class NavigatorMetadataEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, NavigatorMetadataParser);
+ }
+
+ public getParser(): NavigatorMetadataParser
+ {
+ return this.parser as NavigatorMetadataParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/navigator/NavigatorOpenRoomCreatorEvent.ts b/src/nitro/communication/messages/incoming/navigator/NavigatorOpenRoomCreatorEvent.ts
new file mode 100644
index 00000000..0979b5f1
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/navigator/NavigatorOpenRoomCreatorEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { NavigatorOpenRoomCreatorParser } from '../../parser/navigator/NavigatorOpenRoomCreatorParser';
+
+export class NavigatorOpenRoomCreatorEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, NavigatorOpenRoomCreatorParser);
+ }
+
+ public getParser(): NavigatorOpenRoomCreatorParser
+ {
+ return this.parser as NavigatorOpenRoomCreatorParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/navigator/NavigatorSearchEvent.ts b/src/nitro/communication/messages/incoming/navigator/NavigatorSearchEvent.ts
new file mode 100644
index 00000000..5ba3d204
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/navigator/NavigatorSearchEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { NavigatorSearchParser } from '../../parser/navigator/NavigatorSearchParser';
+
+export class NavigatorSearchEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, NavigatorSearchParser);
+ }
+
+ public getParser(): NavigatorSearchParser
+ {
+ return this.parser as NavigatorSearchParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/navigator/NavigatorSearchesEvent.ts b/src/nitro/communication/messages/incoming/navigator/NavigatorSearchesEvent.ts
new file mode 100644
index 00000000..06e8bdad
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/navigator/NavigatorSearchesEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { NavigatorSearchesParser } from '../../parser/navigator/NavigatorSearchesParser';
+
+export class NavigatorSearchesEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, NavigatorSearchesParser);
+ }
+
+ public getParser(): NavigatorSearchesParser
+ {
+ return this.parser as NavigatorSearchesParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/navigator/NavigatorSettingsEvent.ts b/src/nitro/communication/messages/incoming/navigator/NavigatorSettingsEvent.ts
new file mode 100644
index 00000000..1e80d52d
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/navigator/NavigatorSettingsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { NavigatorSettingsParser } from '../../parser/navigator/NavigatorSettingsParser';
+
+export class NavigatorSettingsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, NavigatorSettingsParser);
+ }
+
+ public getParser(): NavigatorSettingsParser
+ {
+ return this.parser as NavigatorSettingsParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/notifications/BotErrorEvent.ts b/src/nitro/communication/messages/incoming/notifications/BotErrorEvent.ts
new file mode 100644
index 00000000..579c71f2
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/notifications/BotErrorEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { BotErrorEventParser } from '../../parser/notifications/BotErrorEventParser';
+
+export class BotErrorEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, BotErrorEventParser);
+ }
+
+ public getParser(): BotErrorEventParser
+ {
+ return this.parser as BotErrorEventParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/notifications/HabboBroadcastMessageEvent.ts b/src/nitro/communication/messages/incoming/notifications/HabboBroadcastMessageEvent.ts
new file mode 100644
index 00000000..616c4653
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/notifications/HabboBroadcastMessageEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { HabboBroadcastMessageParser } from '../../parser/notifications/HabboBroadcastMessageParser';
+
+export class HabboBroadcastMessageEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, HabboBroadcastMessageParser);
+ }
+
+ public getParser(): HabboBroadcastMessageParser
+ {
+ return this.parser as HabboBroadcastMessageParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/notifications/HotelWillShutdownEvent.ts b/src/nitro/communication/messages/incoming/notifications/HotelWillShutdownEvent.ts
new file mode 100644
index 00000000..6cc44385
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/notifications/HotelWillShutdownEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { HotelWillShutdownParser } from '../../parser/notifications/HotelWillShutdownParser';
+
+export class HotelWillShutdownEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, HotelWillShutdownParser);
+ }
+
+ public getParser(): HotelWillShutdownParser
+ {
+ return this.parser as HotelWillShutdownParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/notifications/MOTDNotificationEvent.ts b/src/nitro/communication/messages/incoming/notifications/MOTDNotificationEvent.ts
new file mode 100644
index 00000000..1bbdca07
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/notifications/MOTDNotificationEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { MOTDNotificationParser } from '../../parser/notifications/MOTDNotificationParser';
+
+export class MOTDNotificationEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, MOTDNotificationParser);
+ }
+
+ public getParser(): MOTDNotificationParser
+ {
+ return this.parser as MOTDNotificationParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/notifications/NotificationDialogMessageEvent.ts b/src/nitro/communication/messages/incoming/notifications/NotificationDialogMessageEvent.ts
new file mode 100644
index 00000000..33b909ea
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/notifications/NotificationDialogMessageEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { NotificationDialogMessageParser } from '../../parser/notifications/NotificationDialogMessageParser';
+
+export class NotificationDialogMessageEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, NotificationDialogMessageParser);
+ }
+
+ public getParser(): NotificationDialogMessageParser
+ {
+ return this.parser as NotificationDialogMessageParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/notifications/PetPlacingErrorEvent.ts b/src/nitro/communication/messages/incoming/notifications/PetPlacingErrorEvent.ts
new file mode 100644
index 00000000..a9291352
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/notifications/PetPlacingErrorEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { PetPlacingErrorEventParser } from '../../parser/notifications/PetPlacingErrorEventParser';
+
+export class PetPlacingErrorEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, PetPlacingErrorEventParser);
+ }
+
+ public getParser(): PetPlacingErrorEventParser
+ {
+ return this.parser as PetPlacingErrorEventParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/notifications/RespectReceivedEvent.ts b/src/nitro/communication/messages/incoming/notifications/RespectReceivedEvent.ts
new file mode 100644
index 00000000..e67a7f2d
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/notifications/RespectReceivedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { RespectReceivedParser } from '../../parser/notifications/RespectReceivedParser';
+
+export class RespectReceivedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RespectReceivedParser);
+ }
+
+ public getParser(): RespectReceivedParser
+ {
+ return this.parser as RespectReceivedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/notifications/UnseenItemsEvent.ts b/src/nitro/communication/messages/incoming/notifications/UnseenItemsEvent.ts
new file mode 100644
index 00000000..0d347fdd
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/notifications/UnseenItemsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { UnseenItemsParser } from '../../parser/notifications/UnseenItemsParser';
+
+export class UnseenItemsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UnseenItemsParser);
+ }
+
+ public getParser(): UnseenItemsParser
+ {
+ return this.parser as UnseenItemsParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/access/RoomEnterErrorEvent.ts b/src/nitro/communication/messages/incoming/room/access/RoomEnterErrorEvent.ts
new file mode 100644
index 00000000..d959a351
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/access/RoomEnterErrorEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomEnterErrorParser } from '../../../parser/room/access/RoomEnterErrorParser';
+
+export class RoomEnterErrorEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomEnterErrorParser);
+ }
+
+ public getParser(): RoomEnterErrorParser
+ {
+ return this.parser as RoomEnterErrorParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/access/RoomEnterEvent.ts b/src/nitro/communication/messages/incoming/room/access/RoomEnterEvent.ts
new file mode 100644
index 00000000..c46ee72a
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/access/RoomEnterEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomEnterParser } from '../../../parser/room/access/RoomEnterParser';
+
+export class RoomEnterEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomEnterParser);
+ }
+
+ public getParser(): RoomEnterParser
+ {
+ return this.parser as RoomEnterParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/access/RoomForwardEvent.ts b/src/nitro/communication/messages/incoming/room/access/RoomForwardEvent.ts
new file mode 100644
index 00000000..6d5ac9b3
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/access/RoomForwardEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomFowardParser as RoomForwardParser } from '../../../parser/room/access/RoomFowardParser';
+
+export class RoomForwardEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomForwardParser);
+ }
+
+ public getParser(): RoomForwardParser
+ {
+ return this.parser as RoomForwardParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/access/doorbell/RoomDoorbellAcceptedEvent.ts b/src/nitro/communication/messages/incoming/room/access/doorbell/RoomDoorbellAcceptedEvent.ts
new file mode 100644
index 00000000..1526dc6b
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/access/doorbell/RoomDoorbellAcceptedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { RoomDoorbellAcceptedParser } from '../../../../parser/room/access/doorbell/RoomDoorbellAcceptedParser';
+
+export class RoomDoorbellAcceptedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomDoorbellAcceptedParser);
+ }
+
+ public getParser(): RoomDoorbellAcceptedParser
+ {
+ return this.parser as RoomDoorbellAcceptedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/access/doorbell/RoomDoorbellEvent.ts b/src/nitro/communication/messages/incoming/room/access/doorbell/RoomDoorbellEvent.ts
new file mode 100644
index 00000000..70e698fb
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/access/doorbell/RoomDoorbellEvent.ts
@@ -0,0 +1,21 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { RoomDoorbellParser } from '../../../../parser/room/access/doorbell/RoomDoorbellParser';
+
+export class RoomDoorbellEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomDoorbellParser);
+ }
+
+ public getParser(): RoomDoorbellParser
+ {
+ return this.parser as RoomDoorbellParser;
+ }
+
+ public get userName(): string
+ {
+ return this.getParser().userName;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/room/access/doorbell/RoomDoorbellRejectedEvent.ts b/src/nitro/communication/messages/incoming/room/access/doorbell/RoomDoorbellRejectedEvent.ts
new file mode 100644
index 00000000..7547ad44
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/access/doorbell/RoomDoorbellRejectedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { RoomDoorbellRejectedParser } from '../../../../parser/room/access/doorbell/RoomDoorbellRejectedParser';
+
+export class RoomDoorbellRejectedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomDoorbellRejectedParser);
+ }
+
+ public getParser(): RoomDoorbellRejectedParser
+ {
+ return this.parser as RoomDoorbellRejectedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/access/rights/RoomRightsClearEvent.ts b/src/nitro/communication/messages/incoming/room/access/rights/RoomRightsClearEvent.ts
new file mode 100644
index 00000000..0aed6433
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/access/rights/RoomRightsClearEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { RoomRightsClearParser } from '../../../../parser/room/access/rights/RoomRightsClearParser';
+
+export class RoomRightsClearEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomRightsClearParser);
+ }
+
+ public getParser(): RoomRightsClearParser
+ {
+ return this.parser as RoomRightsClearParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/access/rights/RoomRightsEvent.ts b/src/nitro/communication/messages/incoming/room/access/rights/RoomRightsEvent.ts
new file mode 100644
index 00000000..399bcf73
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/access/rights/RoomRightsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { RoomRightsParser } from '../../../../parser/room/access/rights/RoomRightsParser';
+
+export class RoomRightsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomRightsParser);
+ }
+
+ public getParser(): RoomRightsParser
+ {
+ return this.parser as RoomRightsParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/access/rights/RoomRightsOwnerEvent.ts b/src/nitro/communication/messages/incoming/room/access/rights/RoomRightsOwnerEvent.ts
new file mode 100644
index 00000000..e846cdc4
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/access/rights/RoomRightsOwnerEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { RoomRightsOwnerParser } from '../../../../parser/room/access/rights/RoomRightsOwnerParser';
+
+export class RoomRightsOwnerEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomRightsOwnerParser);
+ }
+
+ public getParser(): RoomRightsOwnerParser
+ {
+ return this.parser as RoomRightsOwnerParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/bots/BotCommandConfigurationEvent.ts b/src/nitro/communication/messages/incoming/room/bots/BotCommandConfigurationEvent.ts
new file mode 100644
index 00000000..2dfdee94
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/bots/BotCommandConfigurationEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { BotCommandConfigurationParser } from '../../../parser/room/bots/BotCommandConfigurationParser';
+
+export class BotCommandConfigurationEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, BotCommandConfigurationParser);
+ }
+
+ public getParser(): BotCommandConfigurationParser
+ {
+ return this.parser as BotCommandConfigurationParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/room/data/RoomBannedUsersEvent.ts b/src/nitro/communication/messages/incoming/room/data/RoomBannedUsersEvent.ts
new file mode 100644
index 00000000..f4d56579
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/data/RoomBannedUsersEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomSettingsUsersListParser } from '../../../parser/room/data/RoomSettingsUsersListParser';
+
+export class RoomBannedUsersEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomSettingsUsersListParser);
+ }
+
+ public getParser(): RoomSettingsUsersListParser
+ {
+ return this.parser as RoomSettingsUsersListParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/data/RoomChatSettingsEvent.ts b/src/nitro/communication/messages/incoming/room/data/RoomChatSettingsEvent.ts
new file mode 100644
index 00000000..407d3224
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/data/RoomChatSettingsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomChatSettingsParser } from '../../../parser/room/data/RoomChatSettingsParser';
+
+export class RoomChatSettingsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomChatSettingsParser);
+ }
+
+ public getParser(): RoomChatSettingsParser
+ {
+ return this.parser as RoomChatSettingsParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/data/RoomInfoEvent.ts b/src/nitro/communication/messages/incoming/room/data/RoomInfoEvent.ts
new file mode 100644
index 00000000..bc84fd70
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/data/RoomInfoEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomInfoParser } from '../../../parser/room/data/RoomInfoParser';
+
+export class RoomInfoEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomInfoParser);
+ }
+
+ public getParser(): RoomInfoParser
+ {
+ return this.parser as RoomInfoParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/data/RoomInfoOwnerEvent.ts b/src/nitro/communication/messages/incoming/room/data/RoomInfoOwnerEvent.ts
new file mode 100644
index 00000000..bfbfb969
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/data/RoomInfoOwnerEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomInfoOwnerParser } from '../../../parser/room/data/RoomInfoOwnerParser';
+
+export class RoomInfoOwnerEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomInfoOwnerParser);
+ }
+
+ public getParser(): RoomInfoOwnerParser
+ {
+ return this.parser as RoomInfoOwnerParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/data/RoomScoreEvent.ts b/src/nitro/communication/messages/incoming/room/data/RoomScoreEvent.ts
new file mode 100644
index 00000000..040c408a
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/data/RoomScoreEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomScoreParser } from '../../../parser/room/data/RoomScoreParser';
+
+export class RoomScoreEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomScoreParser);
+ }
+
+ public getParser(): RoomScoreParser
+ {
+ return this.parser as RoomScoreParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/data/RoomSettingsErrorEvent.ts b/src/nitro/communication/messages/incoming/room/data/RoomSettingsErrorEvent.ts
new file mode 100644
index 00000000..589d8db0
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/data/RoomSettingsErrorEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomSettingsErrorParser } from '../../../parser/room/data/RoomSettingsErrorParser';
+
+export class RoomSettingsErrorEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomSettingsErrorParser);
+ }
+
+ public getParser(): RoomSettingsErrorParser
+ {
+ return this.parser as RoomSettingsErrorParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/data/RoomSettingsEvent.ts b/src/nitro/communication/messages/incoming/room/data/RoomSettingsEvent.ts
new file mode 100644
index 00000000..27deb0e6
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/data/RoomSettingsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomSettingsParser } from '../../../parser/room/data/RoomSettingsParser';
+
+export class RoomSettingsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomSettingsParser);
+ }
+
+ public getParser(): RoomSettingsParser
+ {
+ return this.parser as RoomSettingsParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/data/RoomSettingsSavedEvent.ts b/src/nitro/communication/messages/incoming/room/data/RoomSettingsSavedEvent.ts
new file mode 100644
index 00000000..7b3dbd4c
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/data/RoomSettingsSavedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomSettingsSavedParser } from '../../../parser/room/data/RoomSettingsSavedParser';
+
+export class RoomSettingsSavedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomSettingsSavedParser);
+ }
+
+ public getParser(): RoomSettingsSavedParser
+ {
+ return this.parser as RoomSettingsSavedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/data/RoomSettingsUpdatedEvent.ts b/src/nitro/communication/messages/incoming/room/data/RoomSettingsUpdatedEvent.ts
new file mode 100644
index 00000000..314e7946
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/data/RoomSettingsUpdatedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomSettingsUpdatedParser } from '../../../parser/room/data/RoomSettingsUpdatedParser';
+
+export class RoomSettingsUpdatedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomSettingsUpdatedParser);
+ }
+
+ public getParser(): RoomSettingsUpdatedParser
+ {
+ return this.parser as RoomSettingsUpdatedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/data/RoomUsersWithRightsEvent.ts b/src/nitro/communication/messages/incoming/room/data/RoomUsersWithRightsEvent.ts
new file mode 100644
index 00000000..b32b8c8a
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/data/RoomUsersWithRightsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomSettingsUsersListParser } from '../../../parser/room/data/RoomSettingsUsersListParser';
+
+export class RoomUsersWithRightsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomSettingsUsersListParser);
+ }
+
+ public getParser(): RoomSettingsUsersListParser
+ {
+ return this.parser as RoomSettingsUsersListParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/engine/ObjectsRollingEvent.ts b/src/nitro/communication/messages/incoming/room/engine/ObjectsRollingEvent.ts
new file mode 100644
index 00000000..3576dcff
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/engine/ObjectsRollingEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { ObjectsRollingParser } from '../../../parser/room/engine/ObjectsRollingParser';
+
+export class ObjectsRollingEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, ObjectsRollingParser);
+ }
+
+ public getParser(): ObjectsRollingParser
+ {
+ return this.parser as ObjectsRollingParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/engine/RoomCreatedEvent.ts b/src/nitro/communication/messages/incoming/room/engine/RoomCreatedEvent.ts
new file mode 100644
index 00000000..cfa37558
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/engine/RoomCreatedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomCreatedParser } from '../../../parser/room/engine/RoomCreatedParser';
+
+export class RoomCreatedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomCreatedParser);
+ }
+
+ public getParser(): RoomCreatedParser
+ {
+ return this.parser as RoomCreatedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/FurnitureAliasesEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/FurnitureAliasesEvent.ts
new file mode 100644
index 00000000..e36c34ca
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/FurnitureAliasesEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureAliasesParser } from '../../../parser/room/furniture/FurnitureAliasesParser';
+
+export class FurnitureAliasesEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureAliasesParser);
+ }
+
+ public getParser(): FurnitureAliasesParser
+ {
+ return this.parser as FurnitureAliasesParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/FurnitureDataEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/FurnitureDataEvent.ts
new file mode 100644
index 00000000..3e7808e6
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/FurnitureDataEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureDataParser } from '../../../parser/room/furniture/FurnitureDataParser';
+
+export class FurnitureDataEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureDataParser);
+ }
+
+ public getParser(): FurnitureDataParser
+ {
+ return this.parser as FurnitureDataParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/FurnitureItemDataEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/FurnitureItemDataEvent.ts
new file mode 100644
index 00000000..a54e8daf
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/FurnitureItemDataEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureItemDataParser } from '../../../parser/room/furniture/FurnitureItemDataParser';
+
+export class FurnitureItemDataEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureItemDataParser);
+ }
+
+ public getParser(): FurnitureItemDataParser
+ {
+ return this.parser as FurnitureItemDataParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/FurnitureStackHeightEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/FurnitureStackHeightEvent.ts
new file mode 100644
index 00000000..90a9baa6
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/FurnitureStackHeightEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureStackHeightParser } from '../../../parser/room/furniture/FurnitureStackHeightParser';
+
+export class FurnitureStackHeightEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureStackHeightParser);
+ }
+
+ public getParser(): FurnitureStackHeightParser
+ {
+ return this.parser as FurnitureStackHeightParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/FurnitureState2Event.ts b/src/nitro/communication/messages/incoming/room/furniture/FurnitureState2Event.ts
new file mode 100644
index 00000000..7cc24502
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/FurnitureState2Event.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureState2Parser } from '../../../parser/room/furniture/FurnitureState2Parser';
+
+export class FurnitureState2Event extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureState2Parser);
+ }
+
+ public getParser(): FurnitureState2Parser
+ {
+ return this.parser as FurnitureState2Parser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/FurnitureStateEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/FurnitureStateEvent.ts
new file mode 100644
index 00000000..07b53842
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/FurnitureStateEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureStateParser } from '../../../parser/room/furniture/FurnitureStateParser';
+
+export class FurnitureStateEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureStateParser);
+ }
+
+ public getParser(): FurnitureStateParser
+ {
+ return this.parser as FurnitureStateParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/LoveLockFurniFinishedEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/LoveLockFurniFinishedEvent.ts
new file mode 100644
index 00000000..a8bdf2a7
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/LoveLockFurniFinishedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { LoveLockFurniFinishedParser } from '../../../parser/room/furniture/LoveLockFurniFinishedParser';
+
+export class LoveLockFurniFinishedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, LoveLockFurniFinishedParser);
+ }
+
+ public getParser(): LoveLockFurniFinishedParser
+ {
+ return this.parser as LoveLockFurniFinishedParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/room/furniture/LoveLockFurniFriendConfirmedEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/LoveLockFurniFriendConfirmedEvent.ts
new file mode 100644
index 00000000..3e279a31
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/LoveLockFurniFriendConfirmedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { LoveLockFurniFriendConfirmedParser } from '../../../parser/room/furniture/LoveLockFurniFriendConfirmedParser';
+
+export class LoveLockFurniFriendConfirmedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, LoveLockFurniFriendConfirmedParser);
+ }
+
+ public getParser(): LoveLockFurniFriendConfirmedParser
+ {
+ return this.parser as LoveLockFurniFriendConfirmedParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/room/furniture/LoveLockFurniStartEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/LoveLockFurniStartEvent.ts
new file mode 100644
index 00000000..2c6ce083
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/LoveLockFurniStartEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { LoveLockFurniStartParser } from '../../../parser/room/furniture/LoveLockFurniStartParser';
+
+export class LoveLockFurniStartEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, LoveLockFurniStartParser);
+ }
+
+ public getParser(): LoveLockFurniStartParser
+ {
+ return this.parser as LoveLockFurniStartParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/room/furniture/RoomDimmerPresetsMessageEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/RoomDimmerPresetsMessageEvent.ts
new file mode 100644
index 00000000..049823d0
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/RoomDimmerPresetsMessageEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomDimmerPresetsMessageParser } from '../../../parser/room/furniture/RoomDimmerPresetsMessageParser';
+
+export class RoomDimmerPresetsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomDimmerPresetsMessageParser);
+ }
+
+ public getParser(): RoomDimmerPresetsMessageParser
+ {
+ return this.parser as RoomDimmerPresetsMessageParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/floor/FurnitureFloorAddEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/floor/FurnitureFloorAddEvent.ts
new file mode 100644
index 00000000..e4418384
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/floor/FurnitureFloorAddEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureFloorAddParser } from '../../../../parser/room/furniture/floor/FurnitureFloorAddParser';
+
+export class FurnitureFloorAddEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureFloorAddParser);
+ }
+
+ public getParser(): FurnitureFloorAddParser
+ {
+ return this.parser as FurnitureFloorAddParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/floor/FurnitureFloorEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/floor/FurnitureFloorEvent.ts
new file mode 100644
index 00000000..64aa7314
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/floor/FurnitureFloorEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureFloorParser } from '../../../../parser/room/furniture/floor/FurnitureFloorParser';
+
+export class FurnitureFloorEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureFloorParser);
+ }
+
+ public getParser(): FurnitureFloorParser
+ {
+ return this.parser as FurnitureFloorParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/floor/FurnitureFloorRemoveEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/floor/FurnitureFloorRemoveEvent.ts
new file mode 100644
index 00000000..727a165e
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/floor/FurnitureFloorRemoveEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureFloorRemoveParser } from '../../../../parser/room/furniture/floor/FurnitureFloorRemoveParser';
+
+export class FurnitureFloorRemoveEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureFloorRemoveParser);
+ }
+
+ public getParser(): FurnitureFloorRemoveParser
+ {
+ return this.parser as FurnitureFloorRemoveParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/floor/FurnitureFloorUpdateEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/floor/FurnitureFloorUpdateEvent.ts
new file mode 100644
index 00000000..245e6aba
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/floor/FurnitureFloorUpdateEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureFloorUpdateParser } from '../../../../parser/room/furniture/floor/FurnitureFloorUpdateParser';
+
+export class FurnitureFloorUpdateEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureFloorUpdateParser);
+ }
+
+ public getParser(): FurnitureFloorUpdateParser
+ {
+ return this.parser as FurnitureFloorUpdateParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/moodlightFromServer.ts b/src/nitro/communication/messages/incoming/room/furniture/moodlightFromServer.ts
new file mode 100644
index 00000000..0aedc1f9
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/moodlightFromServer.ts
@@ -0,0 +1,64 @@
+export class MoodlightFromServer
+{
+ private readonly _id: number = 0;
+ private _type: number = 0;
+ private _color: number = 0;
+ private _intensity: number = 0;
+ private _isParsed: boolean = false;
+ private _htmlColor: string = null;
+
+ constructor(k: number)
+ {
+ this._id = k;
+ }
+
+ public parsed(): void
+ {
+ this._isParsed = true;
+ }
+
+ public get id(): number
+ {
+ return this._id;
+ }
+
+ public get type(): number
+ {
+ return this._type;
+ }
+
+ public set type(k: number)
+ {
+ if(!this._isParsed) this._type = k;
+ }
+
+ public get color(): number
+ {
+ return this._color;
+ }
+
+ public set color(k: number)
+ {
+ if(!this._isParsed) this._color = k;
+ }
+
+ public get intensity(): number
+ {
+ return this._intensity;
+ }
+
+ public set intensity(k: number)
+ {
+ if(!this._isParsed) this._intensity = k;
+ }
+
+ public set htmlColor(color: string)
+ {
+ this._htmlColor = color;
+ }
+
+ public get htmlColor(): string
+ {
+ return this._htmlColor;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/room/furniture/wall/FurnitureWallAddEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/wall/FurnitureWallAddEvent.ts
new file mode 100644
index 00000000..10f6f585
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/wall/FurnitureWallAddEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureWallAddParser } from '../../../../parser/room/furniture/wall/FurnitureWallAddParser';
+
+export class FurnitureWallAddEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureWallAddParser);
+ }
+
+ public getParser(): FurnitureWallAddParser
+ {
+ return this.parser as FurnitureWallAddParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/wall/FurnitureWallEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/wall/FurnitureWallEvent.ts
new file mode 100644
index 00000000..46d06b2e
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/wall/FurnitureWallEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureWallParser } from '../../../../parser/room/furniture/wall/FurnitureWallParser';
+
+export class FurnitureWallEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureWallParser);
+ }
+
+ public getParser(): FurnitureWallParser
+ {
+ return this.parser as FurnitureWallParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/wall/FurnitureWallRemoveEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/wall/FurnitureWallRemoveEvent.ts
new file mode 100644
index 00000000..92840164
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/wall/FurnitureWallRemoveEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureWallRemoveParser } from '../../../../parser/room/furniture/wall/FurnitureWallRemoveParser';
+
+export class FurnitureWallRemoveEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureWallRemoveParser);
+ }
+
+ public getParser(): FurnitureWallRemoveParser
+ {
+ return this.parser as FurnitureWallRemoveParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/furniture/wall/FurnitureWallUpdateEvent.ts b/src/nitro/communication/messages/incoming/room/furniture/wall/FurnitureWallUpdateEvent.ts
new file mode 100644
index 00000000..86e8f3b9
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/furniture/wall/FurnitureWallUpdateEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { FurnitureWallUpdateParser } from '../../../../parser/room/furniture/wall/FurnitureWallUpdateParser';
+
+export class FurnitureWallUpdateEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FurnitureWallUpdateParser);
+ }
+
+ public getParser(): FurnitureWallUpdateParser
+ {
+ return this.parser as FurnitureWallUpdateParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/mapping/RoomDoorEvent.ts b/src/nitro/communication/messages/incoming/room/mapping/RoomDoorEvent.ts
new file mode 100644
index 00000000..12051a65
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/mapping/RoomDoorEvent.ts
@@ -0,0 +1,16 @@
+import { RoomDoorParser } from '../../../parser/room/mapping/RoomDoorParser';
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+
+export class RoomDoorEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomDoorParser);
+ }
+
+ public getParser(): RoomDoorParser
+ {
+ return this.parser as RoomDoorParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/mapping/RoomHeightMapEvent.ts b/src/nitro/communication/messages/incoming/room/mapping/RoomHeightMapEvent.ts
new file mode 100644
index 00000000..48b1cbdf
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/mapping/RoomHeightMapEvent.ts
@@ -0,0 +1,16 @@
+import { RoomHeightMapParser } from '../../../parser/room/mapping/RoomHeightMapParser';
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+
+export class RoomHeightMapEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomHeightMapParser);
+ }
+
+ public getParser(): RoomHeightMapParser
+ {
+ return this.parser as RoomHeightMapParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/mapping/RoomHeightMapUpdateEvent.ts b/src/nitro/communication/messages/incoming/room/mapping/RoomHeightMapUpdateEvent.ts
new file mode 100644
index 00000000..02cd7c01
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/mapping/RoomHeightMapUpdateEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomHeightMapUpdateParser } from '../../../parser/room/mapping/RoomHeightMapUpdateParser';
+
+export class RoomHeightMapUpdateEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomHeightMapUpdateParser);
+ }
+
+ public getParser(): RoomHeightMapUpdateParser
+ {
+ return this.parser as RoomHeightMapUpdateParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/mapping/RoomModelEvent.ts b/src/nitro/communication/messages/incoming/room/mapping/RoomModelEvent.ts
new file mode 100644
index 00000000..17ac3cbc
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/mapping/RoomModelEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomModelParser } from '../../../parser/room/mapping/RoomModelParser';
+
+export class RoomModelEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomModelParser);
+ }
+
+ public getParser(): RoomModelParser
+ {
+ return this.parser as RoomModelParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/mapping/RoomModelNameEvent.ts b/src/nitro/communication/messages/incoming/room/mapping/RoomModelNameEvent.ts
new file mode 100644
index 00000000..575ec56a
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/mapping/RoomModelNameEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomModelNameParser } from '../../../parser/room/mapping/RoomModelNameParser';
+
+export class RoomModelNameEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomModelNameParser);
+ }
+
+ public getParser(): RoomModelNameParser
+ {
+ return this.parser as RoomModelNameParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/mapping/RoomPaintEvent.ts b/src/nitro/communication/messages/incoming/room/mapping/RoomPaintEvent.ts
new file mode 100644
index 00000000..9e1597af
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/mapping/RoomPaintEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomPaintParser } from '../../../parser/room/mapping/RoomPaintParser';
+
+export class RoomPaintEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomPaintParser);
+ }
+
+ public getParser(): RoomPaintParser
+ {
+ return this.parser as RoomPaintParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/mapping/RoomThicknessEvent.ts b/src/nitro/communication/messages/incoming/room/mapping/RoomThicknessEvent.ts
new file mode 100644
index 00000000..3ea31011
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/mapping/RoomThicknessEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomThicknessParser } from '../../../parser/room/mapping/RoomThicknessParser';
+
+export class RoomThicknessEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomThicknessParser);
+ }
+
+ public getParser(): RoomThicknessParser
+ {
+ return this.parser as RoomThicknessParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/pet/PetFigureUpdateEvent.ts b/src/nitro/communication/messages/incoming/room/pet/PetFigureUpdateEvent.ts
new file mode 100644
index 00000000..00a56355
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/pet/PetFigureUpdateEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { PetFigureUpdateParser } from '../../../parser/room/pet/PetFigureUpdateParser';
+
+export class PetFigureUpdateEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, PetFigureUpdateParser);
+ }
+
+ public getParser(): PetFigureUpdateParser
+ {
+ return this.parser as PetFigureUpdateParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/pet/PetInfoEvent.ts b/src/nitro/communication/messages/incoming/room/pet/PetInfoEvent.ts
new file mode 100644
index 00000000..3372412a
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/pet/PetInfoEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { PetInfoParser } from '../../../parser/room/pet/PetInfoParser';
+
+export class PetInfoEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, PetInfoParser);
+ }
+
+ public getParser(): PetInfoParser
+ {
+ return this.parser as PetInfoParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/room/pet/_Str_3763.ts b/src/nitro/communication/messages/incoming/room/pet/_Str_3763.ts
new file mode 100644
index 00000000..ca1d0f8d
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/pet/_Str_3763.ts
@@ -0,0 +1,55 @@
+import { IMessageDataWrapper } from '../../../../../../core/communication/messages/IMessageDataWrapper';
+
+export class _Str_3763
+{
+ private _Str_7992: number;
+ private _name: string;
+ private _level: number;
+ private _figure: string;
+ private _owner: string;
+
+ constructor(wrapper: IMessageDataWrapper)
+ {
+ if(!wrapper) throw new Error('invalid_wrapper');
+
+ this._Str_7992 = wrapper.readInt();
+ this._name = wrapper.readString();
+ this._level = wrapper.readInt();
+ this._figure = wrapper.readString();
+ this._owner = wrapper.readString();
+ }
+
+ public dispose():void
+ {
+ this._Str_7992 = 0;
+ this._name = '';
+ this._level = 0;
+ this._figure = '';
+ this._owner = '';
+ }
+
+ public get _Str_5277(): number
+ {
+ return this._Str_7992;
+ }
+
+ public get name(): string
+ {
+ return this._name;
+ }
+
+ public get level(): number
+ {
+ return this._level;
+ }
+
+ public get figure(): string
+ {
+ return this._figure;
+ }
+
+ public get owner(): string
+ {
+ return this._owner;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/pet/_Str_5753.ts b/src/nitro/communication/messages/incoming/room/pet/_Str_5753.ts
new file mode 100644
index 00000000..a9163d8f
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/pet/_Str_5753.ts
@@ -0,0 +1,40 @@
+import { IMessageDataWrapper } from '../../../../../../core/communication/messages/IMessageDataWrapper';
+
+export class _Str_5753
+{
+ private _Str_16211: number;
+ private _breeds: number[];
+
+ constructor(wrapper: IMessageDataWrapper)
+ {
+ if(!wrapper) throw new Error('invalid_wrapper');
+
+ this._Str_16211 = wrapper.readInt();
+ this._breeds = [];
+
+ let totalCount = wrapper.readInt();
+
+ while(totalCount > 0)
+ {
+ this._breeds.push(wrapper.readInt());
+
+ totalCount--;
+ }
+ }
+
+ public dispose():void
+ {
+ this._Str_16211 = -1;
+ this._breeds = [];
+ }
+
+ public get _Str_12554(): number
+ {
+ return this._Str_16211;
+ }
+
+ public get breeds(): number[]
+ {
+ return this._breeds;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/session/YouArePlayingGameEvent.ts b/src/nitro/communication/messages/incoming/room/session/YouArePlayingGameEvent.ts
new file mode 100644
index 00000000..a8471056
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/session/YouArePlayingGameEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { YouArePlayingGameParser } from '../../../parser/room/session/YouArePlayingGameParser';
+
+export class YouArePlayingGameEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, YouArePlayingGameParser);
+ }
+
+ public getParser(): YouArePlayingGameParser
+ {
+ return this.parser as YouArePlayingGameParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/unit/RoomUnitDanceEvent.ts b/src/nitro/communication/messages/incoming/room/unit/RoomUnitDanceEvent.ts
new file mode 100644
index 00000000..0b2ab9d3
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/RoomUnitDanceEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitDanceParser } from '../../../parser/room/unit/RoomUnitDanceParser';
+
+export class RoomUnitDanceEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitDanceParser);
+ }
+
+ public getParser(): RoomUnitDanceParser
+ {
+ return this.parser as RoomUnitDanceParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/unit/RoomUnitEffectEvent.ts b/src/nitro/communication/messages/incoming/room/unit/RoomUnitEffectEvent.ts
new file mode 100644
index 00000000..213ec52c
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/RoomUnitEffectEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitEffectParser } from '../../../parser/room/unit/RoomUnitEffectParser';
+
+export class RoomUnitEffectEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitEffectParser);
+ }
+
+ public getParser(): RoomUnitEffectParser
+ {
+ return this.parser as RoomUnitEffectParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/unit/RoomUnitEvent.ts b/src/nitro/communication/messages/incoming/room/unit/RoomUnitEvent.ts
new file mode 100644
index 00000000..643afb5f
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/RoomUnitEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitParser } from '../../../parser/room/unit/RoomUnitParser';
+
+export class RoomUnitEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitParser);
+ }
+
+ public getParser(): RoomUnitParser
+ {
+ return this.parser as RoomUnitParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/unit/RoomUnitExpressionEvent.ts b/src/nitro/communication/messages/incoming/room/unit/RoomUnitExpressionEvent.ts
new file mode 100644
index 00000000..36bc3478
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/RoomUnitExpressionEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitExpressionParser } from '../../../parser/room/unit/RoomUnitExpressionParser';
+
+export class RoomUnitExpressionEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitExpressionParser);
+ }
+
+ public getParser(): RoomUnitExpressionParser
+ {
+ return this.parser as RoomUnitExpressionParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/unit/RoomUnitHandItemEvent.ts b/src/nitro/communication/messages/incoming/room/unit/RoomUnitHandItemEvent.ts
new file mode 100644
index 00000000..e9ad8b58
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/RoomUnitHandItemEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitHandItemParser } from '../../../parser/room/unit/RoomUnitHandItemParser';
+
+export class RoomUnitHandItemEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitHandItemParser);
+ }
+
+ public getParser(): RoomUnitHandItemParser
+ {
+ return this.parser as RoomUnitHandItemParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/unit/RoomUnitHandItemReceivedEvent.ts b/src/nitro/communication/messages/incoming/room/unit/RoomUnitHandItemReceivedEvent.ts
new file mode 100644
index 00000000..3a0e88a8
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/RoomUnitHandItemReceivedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitHandItemReceivedParser } from '../../../parser/room/unit/RoomUnitHandItemReceivedParser';
+
+export class RoomUnitHandItemReceivedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitHandItemReceivedParser);
+ }
+
+ public getParser(): RoomUnitHandItemReceivedParser
+ {
+ return this.parser as RoomUnitHandItemReceivedParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/room/unit/RoomUnitIdleEvent.ts b/src/nitro/communication/messages/incoming/room/unit/RoomUnitIdleEvent.ts
new file mode 100644
index 00000000..ef7089ff
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/RoomUnitIdleEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitIdleParser } from '../../../parser/room/unit/RoomUnitIdleParser';
+
+export class RoomUnitIdleEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitIdleParser);
+ }
+
+ public getParser(): RoomUnitIdleParser
+ {
+ return this.parser as RoomUnitIdleParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/unit/RoomUnitInfoEvent.ts b/src/nitro/communication/messages/incoming/room/unit/RoomUnitInfoEvent.ts
new file mode 100644
index 00000000..f3dee198
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/RoomUnitInfoEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitInfoParser } from '../../../parser/room/unit/RoomUnitInfoParser';
+
+export class RoomUnitInfoEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitInfoParser);
+ }
+
+ public getParser(): RoomUnitInfoParser
+ {
+ return this.parser as RoomUnitInfoParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/unit/RoomUnitNumberEvent.ts b/src/nitro/communication/messages/incoming/room/unit/RoomUnitNumberEvent.ts
new file mode 100644
index 00000000..316a82e6
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/RoomUnitNumberEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitNumberParser } from '../../../parser/room/unit/RoomUnitNumberParser';
+
+export class RoomUnitNumberEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitNumberParser);
+ }
+
+ public getParser(): RoomUnitNumberParser
+ {
+ return this.parser as RoomUnitNumberParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/unit/RoomUnitRemoveEvent.ts b/src/nitro/communication/messages/incoming/room/unit/RoomUnitRemoveEvent.ts
new file mode 100644
index 00000000..3f410a2d
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/RoomUnitRemoveEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitRemoveParser } from '../../../parser/room/unit/RoomUnitRemoveParser';
+
+export class RoomUnitRemoveEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitRemoveParser);
+ }
+
+ public getParser(): RoomUnitRemoveParser
+ {
+ return this.parser as RoomUnitRemoveParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/unit/RoomUnitStatusEvent.ts b/src/nitro/communication/messages/incoming/room/unit/RoomUnitStatusEvent.ts
new file mode 100644
index 00000000..808b184f
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/RoomUnitStatusEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitStatusParser } from '../../../parser/room/unit/RoomUnitStatusParser';
+
+export class RoomUnitStatusEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitStatusParser);
+ }
+
+ public getParser(): RoomUnitStatusParser
+ {
+ return this.parser as RoomUnitStatusParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/unit/chat/FloodControlEvent.ts b/src/nitro/communication/messages/incoming/room/unit/chat/FloodControlEvent.ts
new file mode 100644
index 00000000..54d61dd7
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/chat/FloodControlEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { FloodControlParser } from '../../../../parser/room/unit/chat/FloodControlParser';
+
+export class FloodControlEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, FloodControlParser);
+ }
+
+ public getParser(): FloodControlParser
+ {
+ return this.parser as FloodControlParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/room/unit/chat/RemainingMuteEvent.ts b/src/nitro/communication/messages/incoming/room/unit/chat/RemainingMuteEvent.ts
new file mode 100644
index 00000000..94eb5106
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/chat/RemainingMuteEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { RemainingMuteParser } from '../../../../parser/room/unit/chat/RemainingMuteParser';
+
+export class RemainingMuteEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RemainingMuteParser);
+ }
+
+ public getParser(): RemainingMuteParser
+ {
+ return this.parser as RemainingMuteParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/room/unit/chat/RoomUnitChatEvent.ts b/src/nitro/communication/messages/incoming/room/unit/chat/RoomUnitChatEvent.ts
new file mode 100644
index 00000000..bc5514d7
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/chat/RoomUnitChatEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitChatParser } from '../../../../parser/room/unit/chat/RoomUnitChatParser';
+
+export class RoomUnitChatEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitChatParser);
+ }
+
+ public getParser(): RoomUnitChatParser
+ {
+ return this.parser as RoomUnitChatParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/unit/chat/RoomUnitChatShoutEvent.ts b/src/nitro/communication/messages/incoming/room/unit/chat/RoomUnitChatShoutEvent.ts
new file mode 100644
index 00000000..d6096b4d
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/chat/RoomUnitChatShoutEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitChatParser } from '../../../../parser/room/unit/chat/RoomUnitChatParser';
+
+export class RoomUnitChatShoutEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitChatParser);
+ }
+
+ public getParser(): RoomUnitChatParser
+ {
+ return this.parser as RoomUnitChatParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/unit/chat/RoomUnitChatWhisperEvent.ts b/src/nitro/communication/messages/incoming/room/unit/chat/RoomUnitChatWhisperEvent.ts
new file mode 100644
index 00000000..2f2944d0
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/chat/RoomUnitChatWhisperEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitChatParser } from '../../../../parser/room/unit/chat/RoomUnitChatParser';
+
+export class RoomUnitChatWhisperEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitChatParser);
+ }
+
+ public getParser(): RoomUnitChatParser
+ {
+ return this.parser as RoomUnitChatParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/room/unit/chat/RoomUnitTypingEvent.ts b/src/nitro/communication/messages/incoming/room/unit/chat/RoomUnitTypingEvent.ts
new file mode 100644
index 00000000..159bd502
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/room/unit/chat/RoomUnitTypingEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { RoomUnitTypingParser } from '../../../../parser/room/unit/chat/RoomUnitTypingParser';
+
+export class RoomUnitTypingEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomUnitTypingParser);
+ }
+
+ public getParser(): RoomUnitTypingParser
+ {
+ return this.parser as RoomUnitTypingParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/roomevents/ActionDefinition.ts b/src/nitro/communication/messages/incoming/roomevents/ActionDefinition.ts
new file mode 100644
index 00000000..666d6160
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/roomevents/ActionDefinition.ts
@@ -0,0 +1,47 @@
+import { IMessageDataWrapper } from '../../../../../core/communication/messages/IMessageDataWrapper';
+import { Triggerable } from './Triggerable';
+
+export class ActionDefinition extends Triggerable
+{
+ private _type: number;
+ private _delayInPulses: number;
+ private _conflictingTriggers: number[];
+
+ constructor(wrapper: IMessageDataWrapper)
+ {
+ super(wrapper);
+
+ this._conflictingTriggers = [];
+ this._type = wrapper.readInt();
+ this._delayInPulses = wrapper.readInt();
+
+ let count = wrapper.readInt();
+
+ while(count > 0)
+ {
+ this._conflictingTriggers.push(wrapper.readInt());
+
+ count--;
+ }
+ }
+
+ public get type(): number
+ {
+ return this._type;
+ }
+
+ public get code(): number
+ {
+ return this._type;
+ }
+
+ public get delayInPulses(): number
+ {
+ return this._delayInPulses;
+ }
+
+ public get conflictingTriggers(): number[]
+ {
+ return this._conflictingTriggers;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/roomevents/ConditionDefinition.ts b/src/nitro/communication/messages/incoming/roomevents/ConditionDefinition.ts
new file mode 100644
index 00000000..2671f6ae
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/roomevents/ConditionDefinition.ts
@@ -0,0 +1,24 @@
+import { IMessageDataWrapper } from '../../../../../core/communication/messages/IMessageDataWrapper';
+import { Triggerable } from './Triggerable';
+
+export class ConditionDefinition extends Triggerable
+{
+ private _type: number;
+
+ constructor(wrapper: IMessageDataWrapper)
+ {
+ super(wrapper);
+
+ this._type = wrapper.readInt();
+ }
+
+ public get type(): number
+ {
+ return this._type;
+ }
+
+ public get code(): number
+ {
+ return this._type;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/roomevents/RoomMutedEvent.ts b/src/nitro/communication/messages/incoming/roomevents/RoomMutedEvent.ts
new file mode 100644
index 00000000..bbe27abe
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/roomevents/RoomMutedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { RoomMutedParser } from '../../parser/roomevents/RoomMutedParser';
+
+export class RoomMutedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, RoomMutedParser);
+ }
+
+ public getParser(): RoomMutedParser
+ {
+ return this.parser as RoomMutedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/roomevents/TriggerDefinition.ts b/src/nitro/communication/messages/incoming/roomevents/TriggerDefinition.ts
new file mode 100644
index 00000000..5d159426
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/roomevents/TriggerDefinition.ts
@@ -0,0 +1,40 @@
+import { IMessageDataWrapper } from '../../../../../core/communication/messages/IMessageDataWrapper';
+import { Triggerable } from './Triggerable';
+
+export class TriggerDefinition extends Triggerable
+{
+ private _triggerConf: number;
+ private _conflictingActions: number[];
+
+ constructor(wrapper: IMessageDataWrapper)
+ {
+ super(wrapper);
+
+ this._conflictingActions = [];
+ this._triggerConf = wrapper.readInt();
+
+ let count = wrapper.readInt();
+
+ while(count > 0)
+ {
+ this._conflictingActions.push(wrapper.readInt());
+
+ count--;
+ }
+ }
+
+ public get type(): number
+ {
+ return this._triggerConf;
+ }
+
+ public get code(): number
+ {
+ return this._triggerConf;
+ }
+
+ public get _Str_21837(): number[]
+ {
+ return this._conflictingActions;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/roomevents/Triggerable.ts b/src/nitro/communication/messages/incoming/roomevents/Triggerable.ts
new file mode 100644
index 00000000..e51a254a
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/roomevents/Triggerable.ts
@@ -0,0 +1,100 @@
+import { IMessageDataWrapper } from '../../../../../core/communication/messages/IMessageDataWrapper';
+
+export class Triggerable
+{
+ private _stuffTypeSelectionEnabled: boolean;
+ private _furniLimit: number;
+ private _stuffIds: number[];
+ private _id: number;
+ private _stringParam: string;
+ private _intParams: number[];
+ private _stuffTypeId: number;
+ private _stuffTypeSelectionCode: number;
+
+ constructor(wrapper: IMessageDataWrapper)
+ {
+ this._stuffIds = [];
+ this._intParams = [];
+ this._stuffTypeSelectionEnabled = wrapper.readBoolean();
+ this._furniLimit = wrapper.readInt();
+
+ let count = wrapper.readInt();
+
+ while(count > 0)
+ {
+ this._stuffIds.push(wrapper.readInt());
+
+ count--;
+ }
+
+ this._stuffTypeId = wrapper.readInt();
+ this._id = wrapper.readInt();
+ this._stringParam = wrapper.readString();
+
+ count = wrapper.readInt();
+
+ while(count > 0)
+ {
+ this._intParams.push(wrapper.readInt());
+
+ count--;
+ }
+
+ this._stuffTypeSelectionCode = wrapper.readInt();
+ }
+
+ public getBoolean(index: number): boolean
+ {
+ return (this._intParams[index] === 1);
+ }
+
+ public get _Str_21824(): boolean
+ {
+ return this._stuffTypeSelectionEnabled;
+ }
+
+ public get _Str_6040(): number
+ {
+ return this._stuffTypeSelectionCode;
+ }
+
+ public set _Str_6040(k: number)
+ {
+ this._stuffTypeSelectionCode = k;
+ }
+
+ public get maximumItemSelectionCount(): number
+ {
+ return this._furniLimit;
+ }
+
+ public get selectedItems(): number[]
+ {
+ return this._stuffIds;
+ }
+
+ public get id(): number
+ {
+ return this._id;
+ }
+
+ public get stringData(): string
+ {
+ return this._stringParam;
+ }
+
+ public get intData(): number[]
+ {
+ return this._intParams;
+ }
+
+ public get code(): number
+ {
+ return 0;
+ }
+
+ public get spriteId(): number
+ {
+ return this._stuffTypeId;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/roomevents/WiredFurniActionEvent.ts b/src/nitro/communication/messages/incoming/roomevents/WiredFurniActionEvent.ts
new file mode 100644
index 00000000..e20ca83a
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/roomevents/WiredFurniActionEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { WiredFurniActionParser } from '../../parser/roomevents/WiredFurniActionParser';
+
+export class WiredFurniActionEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, WiredFurniActionParser);
+ }
+
+ public getParser(): WiredFurniActionParser
+ {
+ return this.parser as WiredFurniActionParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/roomevents/WiredFurniConditionEvent.ts b/src/nitro/communication/messages/incoming/roomevents/WiredFurniConditionEvent.ts
new file mode 100644
index 00000000..4d9a729e
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/roomevents/WiredFurniConditionEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { WiredFurniConditionParser } from '../../parser/roomevents/WiredFurniConditionParser';
+
+export class WiredFurniConditionEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, WiredFurniConditionParser);
+ }
+
+ public getParser(): WiredFurniConditionParser
+ {
+ return this.parser as WiredFurniConditionParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/roomevents/WiredFurniTriggerEvent.ts b/src/nitro/communication/messages/incoming/roomevents/WiredFurniTriggerEvent.ts
new file mode 100644
index 00000000..4b4ff095
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/roomevents/WiredFurniTriggerEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { WiredFurniTriggerParser } from '../../parser/roomevents/WiredFurniTriggerParser';
+
+export class WiredFurniTriggerEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, WiredFurniTriggerParser);
+ }
+
+ public getParser(): WiredFurniTriggerParser
+ {
+ return this.parser as WiredFurniTriggerParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/roomevents/WiredOpenEvent.ts b/src/nitro/communication/messages/incoming/roomevents/WiredOpenEvent.ts
new file mode 100644
index 00000000..0824e49d
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/roomevents/WiredOpenEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { WiredOpenParser } from '../../parser/roomevents/WiredOpenParser';
+
+export class WiredOpenEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, WiredOpenParser);
+ }
+
+ public getParser(): WiredOpenParser
+ {
+ return this.parser as WiredOpenParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/roomevents/WiredRewardResultMessageEvent.ts b/src/nitro/communication/messages/incoming/roomevents/WiredRewardResultMessageEvent.ts
new file mode 100644
index 00000000..d803f69f
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/roomevents/WiredRewardResultMessageEvent.ts
@@ -0,0 +1,19 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { WiredRewardResultMessageParser } from '../../parser/roomevents/WiredRewardResultMessageParser';
+
+export class WiredRewardResultMessageEvent extends MessageEvent implements IMessageEvent
+{
+ public static _Str_18436: number = 6;
+ public static _Str_17787: number = 7;
+
+ constructor(callBack: Function)
+ {
+ super(callBack, WiredRewardResultMessageParser);
+ }
+
+ public getParser(): WiredRewardResultMessageParser
+ {
+ return this.parser as WiredRewardResultMessageParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/roomevents/WiredSaveSuccessEvent.ts b/src/nitro/communication/messages/incoming/roomevents/WiredSaveSuccessEvent.ts
new file mode 100644
index 00000000..02534465
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/roomevents/WiredSaveSuccessEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { WiredSaveSuccessParser } from '../../parser/roomevents/WiredSaveSuccessParser';
+
+export class WiredSaveSuccessEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, WiredSaveSuccessParser);
+ }
+
+ public getParser(): WiredSaveSuccessParser
+ {
+ return this.parser as WiredSaveSuccessParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/roomevents/WiredValidationErrorEvent.ts b/src/nitro/communication/messages/incoming/roomevents/WiredValidationErrorEvent.ts
new file mode 100644
index 00000000..14d09754
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/roomevents/WiredValidationErrorEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { WiredValidationErrorParser } from '../../parser/roomevents/WiredValidationErrorParser';
+
+export class WiredValidationErrorEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, WiredValidationErrorParser);
+ }
+
+ public getParser(): WiredValidationErrorParser
+ {
+ return this.parser as WiredValidationErrorParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/security/AuthenticatedEvent.ts b/src/nitro/communication/messages/incoming/security/AuthenticatedEvent.ts
new file mode 100644
index 00000000..8c01ea30
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/security/AuthenticatedEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { AuthenticatedParser } from '../../parser/security/AuthenticatedParser';
+
+export class AuthenticatedEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, AuthenticatedParser);
+ }
+
+ public getParser(): AuthenticatedParser
+ {
+ return this.parser as AuthenticatedParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/IgnoreResultEvent.ts b/src/nitro/communication/messages/incoming/user/IgnoreResultEvent.ts
new file mode 100644
index 00000000..2b700fdd
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/IgnoreResultEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { IgnoreResultParser } from '../../parser/user/IgnoreResultParser';
+
+export class IgnoreResultEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, IgnoreResultParser);
+ }
+
+ public getParser(): IgnoreResultParser
+ {
+ return this.parser as IgnoreResultParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/user/IgnoredUsersEvent.ts b/src/nitro/communication/messages/incoming/user/IgnoredUsersEvent.ts
new file mode 100644
index 00000000..d8ade5c9
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/IgnoredUsersEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+import { IgnoredUsersParser } from '../../parser/user/IgnoredUsersParser';
+
+export class IgnoredUsersEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, IgnoredUsersParser);
+ }
+
+ public getParser(): IgnoredUsersParser
+ {
+ return this.parser as IgnoredUsersParser;
+ }
+}
diff --git a/src/nitro/communication/messages/incoming/user/InClientLinkEvent.ts b/src/nitro/communication/messages/incoming/user/InClientLinkEvent.ts
new file mode 100644
index 00000000..76d0bc15
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/InClientLinkEvent.ts
@@ -0,0 +1,16 @@
+import { InClientLinkParser } from '../../parser/user/InClientLinkParser';
+import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
+
+export class InClientLinkEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, InClientLinkParser);
+ }
+
+ public getParser(): InClientLinkParser
+ {
+ return this.parser as InClientLinkParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/access/UserPerksEvent.ts b/src/nitro/communication/messages/incoming/user/access/UserPerksEvent.ts
new file mode 100644
index 00000000..e921e8d6
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/access/UserPerksEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { UserPerksParser } from '../../../parser/user/access/UserPerksParser';
+
+export class UserPerksEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UserPerksParser);
+ }
+
+ public getParser(): UserPerksParser
+ {
+ return this.parser as UserPerksParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/access/UserPermissionsEvent.ts b/src/nitro/communication/messages/incoming/user/access/UserPermissionsEvent.ts
new file mode 100644
index 00000000..73ffd528
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/access/UserPermissionsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { UserPermissionsParser } from '../../../parser/user/access/UserPermissionsParser';
+
+export class UserPermissionsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UserPermissionsParser);
+ }
+
+ public getParser(): UserPermissionsParser
+ {
+ return this.parser as UserPermissionsParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/data/UserCurrentBadgesEvent.ts b/src/nitro/communication/messages/incoming/user/data/UserCurrentBadgesEvent.ts
new file mode 100644
index 00000000..c9936402
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/data/UserCurrentBadgesEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { UserCurrentBadgesParser } from '../../../parser/user/data/UserCurrentBadgesParser';
+
+export class UserCurrentBadgesEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UserCurrentBadgesParser);
+ }
+
+ public getParser(): UserCurrentBadgesParser
+ {
+ return this.parser as UserCurrentBadgesParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/data/UserFigureEvent.ts b/src/nitro/communication/messages/incoming/user/data/UserFigureEvent.ts
new file mode 100644
index 00000000..1bfbd732
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/data/UserFigureEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { UserFigureParser } from '../../../parser/user/data/UserFigureParser';
+
+export class UserFigureEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UserFigureParser);
+ }
+
+ public getParser(): UserFigureParser
+ {
+ return this.parser as UserFigureParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/data/UserInfoEvent.ts b/src/nitro/communication/messages/incoming/user/data/UserInfoEvent.ts
new file mode 100644
index 00000000..ffc071e7
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/data/UserInfoEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { UserInfoParser } from '../../../parser/user/data/UserInfoParser';
+
+export class UserInfoEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UserInfoParser);
+ }
+
+ public getParser(): UserInfoParser
+ {
+ return this.parser as UserInfoParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/data/UserNameChangeMessageEvent.ts b/src/nitro/communication/messages/incoming/user/data/UserNameChangeMessageEvent.ts
new file mode 100644
index 00000000..2b0d19a8
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/data/UserNameChangeMessageEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { UserNameChangeMessageParser } from '../../../parser/user/data/UserNameChangeMessageParser';
+
+export class UserNameChangeMessageEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UserNameChangeMessageParser);
+ }
+
+ public getParser(): UserNameChangeMessageParser
+ {
+ return this.parser as UserNameChangeMessageParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/data/UserProfileEvent.ts b/src/nitro/communication/messages/incoming/user/data/UserProfileEvent.ts
new file mode 100644
index 00000000..82491aed
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/data/UserProfileEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { UserProfileParser } from '../../../parser/user/data/UserProfileParser';
+
+export class UserProfileEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UserProfileParser);
+ }
+
+ public getParser(): UserProfileParser
+ {
+ return this.parser as UserProfileParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/data/UserRelationshipsEvent.ts b/src/nitro/communication/messages/incoming/user/data/UserRelationshipsEvent.ts
new file mode 100644
index 00000000..f44e2936
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/data/UserRelationshipsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { UserRelationshipsParser } from '../../../parser/user/data/UserRelationshipsParser';
+
+export class UserRelationshipsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UserRelationshipsParser);
+ }
+
+ public getParser(): UserRelationshipsParser
+ {
+ return this.parser as UserRelationshipsParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/data/UserSettingsEvent.ts b/src/nitro/communication/messages/incoming/user/data/UserSettingsEvent.ts
new file mode 100644
index 00000000..7add18ac
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/data/UserSettingsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { UserSettingsParser } from '../../../parser/user/data/UserSettingsParser';
+
+export class UserSettingsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UserSettingsParser);
+ }
+
+ public getParser(): UserSettingsParser
+ {
+ return this.parser as UserSettingsParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/inventory/currency/UserCreditsEvent.ts b/src/nitro/communication/messages/incoming/user/inventory/currency/UserCreditsEvent.ts
new file mode 100644
index 00000000..bc2b65c5
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/inventory/currency/UserCreditsEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { UserCreditsParser } from '../../../../parser/user/inventory/currency/UserCreditsParser';
+
+export class UserCreditsEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UserCreditsParser);
+ }
+
+ public getParser(): UserCreditsParser
+ {
+ return this.parser as UserCreditsParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/inventory/currency/UserCurrencyEvent.ts b/src/nitro/communication/messages/incoming/user/inventory/currency/UserCurrencyEvent.ts
new file mode 100644
index 00000000..6175e1bb
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/inventory/currency/UserCurrencyEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { UserCurrencyParser } from '../../../../parser/user/inventory/currency/UserCurrencyParser';
+
+export class UserCurrencyEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UserCurrencyParser);
+ }
+
+ public getParser(): UserCurrencyParser
+ {
+ return this.parser as UserCurrencyParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/inventory/currency/UserCurrencyUpdateEvent.ts b/src/nitro/communication/messages/incoming/user/inventory/currency/UserCurrencyUpdateEvent.ts
new file mode 100644
index 00000000..a2c4db74
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/inventory/currency/UserCurrencyUpdateEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { UserCurrencyUpdateParser } from '../../../../parser/user/inventory/currency/UserCurrencyUpdateParser';
+
+export class UserCurrencyUpdateEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UserCurrencyUpdateParser);
+ }
+
+ public getParser(): UserCurrencyUpdateParser
+ {
+ return this.parser as UserCurrencyUpdateParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/inventory/subscription/UserSubscriptionEvent.ts b/src/nitro/communication/messages/incoming/user/inventory/subscription/UserSubscriptionEvent.ts
new file mode 100644
index 00000000..2f370f24
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/inventory/subscription/UserSubscriptionEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../../core/communication/messages/MessageEvent';
+import { UserSubscriptionParser } from '../../../../parser/user/inventory/subscription/UserSubscriptionParser';
+
+export class UserSubscriptionEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UserSubscriptionParser);
+ }
+
+ public getParser(): UserSubscriptionParser
+ {
+ return this.parser as UserSubscriptionParser;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/incoming/user/wardrobe/UserWardrobePageEvent.ts b/src/nitro/communication/messages/incoming/user/wardrobe/UserWardrobePageEvent.ts
new file mode 100644
index 00000000..d0d87747
--- /dev/null
+++ b/src/nitro/communication/messages/incoming/user/wardrobe/UserWardrobePageEvent.ts
@@ -0,0 +1,16 @@
+import { IMessageEvent } from '../../../../../../core/communication/messages/IMessageEvent';
+import { MessageEvent } from '../../../../../../core/communication/messages/MessageEvent';
+import { UserWardrobePageParser } from '../../../parser/user/wardrobe/UserWardrobePageParser';
+
+export class UserWardrobePageEvent extends MessageEvent implements IMessageEvent
+{
+ constructor(callBack: Function)
+ {
+ super(callBack, UserWardrobePageParser);
+ }
+
+ public getParser(): UserWardrobePageParser
+ {
+ return this.parser as UserWardrobePageParser;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/OutgoingHeader.ts b/src/nitro/communication/messages/outgoing/OutgoingHeader.ts
new file mode 100644
index 00000000..e7ec4cc1
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/OutgoingHeader.ts
@@ -0,0 +1,225 @@
+export class OutgoingHeader
+{
+ public static ACHIEVEMENT_LIST = 219;
+ public static BOT_CONFIGURATION = 1986;
+ public static BOT_PICKUP = 3323;
+ public static BOT_PLACE = 1592;
+ public static BOT_SKILL_SAVE = 2624;
+ public static CAMERA_PRICE = 796;
+ public static CAMERA_SAVE = 3226;
+ public static CAMERA_THUMBNAIL = 1982;
+ public static CATALOG_CLUB = 3285;
+ public static CATALOG_CLUB_GIFTS = 487;
+ public static CATALOG_MODE = 1195;
+ public static CATALOG_PAGE = 412;
+ public static CATALOG_PURCHASE = 3492;
+ public static CATALOG_PURCHASE_GIFT = 1411;
+ public static CATALOG_SEARCH = 2594;
+ public static CLIENT_LATENCY = 295;
+ public static CLIENT_LATENCY_MEASURE = 96;
+ public static CLIENT_POLICY = 26979;
+ public static CLIENT_PONG = 2596;
+ public static CLIENT_TOOLBAR_TOGGLE = 2313;
+ public static CLIENT_VARIABLES = 1053;
+ public static DESKTOP_CAMPAIGNS = 2912;
+ public static DESKTOP_NEWS = 1827;
+ public static DESKTOP_VIEW = 105;
+ public static DISCOUNT_CONFIG = 223;
+ public static EVENT_TRACKER = 3457;
+ public static FIND_FRIENDS = 516;
+ public static FURNITURE_ALIASES = 3898;
+ public static FURNITURE_FLOOR_UPDATE = 248;
+ public static FURNITURE_MULTISTATE = 99;
+ public static FURNITURE_PICKUP = 3456;
+ public static FURNITURE_PLACE = 1258;
+ public static FURNITURE_POSTIT_PLACE = 2248;
+ public static FURNITURE_RANDOMSTATE = 3617;
+ public static FURNITURE_WALL_MULTISTATE = 210;
+ public static FURNITURE_WALL_UPDATE = 168;
+ public static GAMES_INIT = 2914;
+ public static GAMES_LIST = 741;
+ public static GIFT_CONFIG = 418;
+ public static GROUP_ADMIN_ADD = 2894;
+ public static GROUP_ADMIN_REMOVE = 722;
+ public static GROUP_CREATE_OPTIONS = 798;
+ public static GROUP_FORUM_INFO = 3149;
+ public static GROUP_FORUM_LIST = 873;
+ public static GROUP_FORUM_THREADS = 436;
+ public static GROUP_INFO = 2991;
+ public static GROUP_DELETE = 1134;
+ public static GROUP_MEMBER_REMOVE_CONFIRM = 3593;
+ public static GROUP_MEMBER_REMOVE = 593;
+ public static GROUP_MEMBERS = 312;
+ public static GROUP_MEMBERSHIPS = 367;
+ public static GROUP_REQUEST = 998;
+ public static GROUP_REQUEST_ACCEPT = 3386;
+ public static GROUP_REQUEST_DECLINE = 1894;
+ public static GROUP_SETTINGS = 1004;
+ public static GROUP_PARTS = 813;
+ public static GROUP_BUY = 230;
+ public static GROUP_SAVE_INFORMATION = 3137;
+ public static GROUP_SAVE_BADGE = 1991;
+ public static GROUP_SAVE_COLORS = 1764;
+ public static GROUP_SAVE_PREFERENCES = 3435;
+ public static INVENTORY_UNKNOWN = 1371;
+ public static ITEM_CLOTHING_REDEEM = 3374;
+ public static ITEM_COLOR_WHEEL_CLICK = 2144;
+ public static ITEM_DICE_CLICK = 1990;
+ public static ITEM_DICE_CLOSE = 1533;
+ public static ITEM_DIMMER_SAVE = 1648;
+ public static ITEM_DIMMER_SETTINGS = 2813;
+ public static ITEM_DIMMER_TOGGLE = 2296;
+ public static ITEM_EXCHANGE_REDEEM = 3115;
+ public static ITEM_PAINT = 711;
+ public static ITEM_SAVE_BACKGROUND = 3608;
+ public static ITEM_STACK_HELPER = 3839;
+ public static ITEM_WALL_CLICK = 210;
+ public static ITEM_WALL_UPDATE = 168;
+ public static MARKETPLACE_CONFIG = 2597;
+ public static MESSENGER_ACCEPT = 137;
+ public static MESSENGER_CHAT = 3567;
+ public static MESSENGER_DECLINE = 2890;
+ public static MESSENGER_FOLLOW = 3997;
+ public static MESSENGER_FRIENDS = 1523;
+ public static MESSENGER_INIT = 2781;
+ public static MESSENGER_RELATIONSHIPS = 2138;
+ public static MESSENGER_RELATIONSHIPS_UPDATE = 3768;
+ public static MESSENGER_REMOVE = 1689;
+ public static MESSENGER_REQUEST = 3157;
+ public static MESSENGER_REQUESTS = 2448;
+ public static MESSENGER_ROOM_INVITE = 1276;
+ public static MESSENGER_SEARCH = 1210;
+ public static MESSENGER_UPDATES = 1419;
+ public static MOD_TOOL_USER_INFO = 3295;
+ public static NAVIGATOR_CATEGORIES = 3027;
+ public static NAVIGATOR_INIT = 2110;
+ public static NAVIGATOR_SEARCH = 249;
+ public static NAVIGATOR_SEARCH_CLOSE = 1834;
+ public static NAVIGATOR_SEARCH_OPEN = 637;
+ public static NAVIGATOR_SEARCH_SAVE = 2226;
+ public static NAVIGATOR_SETTINGS = 1782;
+ public static NAVIGATOR_SETTINGS_SAVE = 3159;
+ public static NAVIGATOR_CATEGORY_LIST_MODE = 1202;
+ public static PET_INFO = 2934;
+ public static PET_PICKUP = 1581;
+ public static PET_PLACE = 2647;
+ public static PET_RESPECT = 3202;
+ public static PET_RIDE = 1036;
+ public static PET_MOVE = 3449;
+ public static RECYCLER_PRIZES = 398;
+ public static RELEASE_VERSION = 4000;
+ public static REPORT = 1691;
+ public static ROOM_AMBASSADOR_ALERT = 2996;
+ public static ROOM_BAN_GIVE = 1477;
+ public static ROOM_BAN_LIST = 2267;
+ public static ROOM_BAN_REMOVE = 992;
+ public static ROOM_CREATE = 2752;
+ public static ROOM_DELETE = 532;
+ public static ROOM_DOORBELL = 1644;
+ public static ROOM_ENTER = 2312;
+ public static ROOM_FAVORITE = 3817;
+ public static ROOM_FAVORITE_REMOVE = 309;
+ public static ROOM_INFO = 2230;
+ public static ROOM_KICK = 1320;
+ public static ROOM_LIKE = 3582;
+ public static ROOM_MODEL = 2300;
+ public static ROOM_MODEL_BLOCKED_TILES = 1687;
+ public static ROOM_MODEL_DOOR = 3559;
+ public static ROOM_MODEL_SAVE = 875;
+ public static ROOM_MUTE = 3637;
+ public static ROOM_MUTE_USER = 3485;
+ public static ROOM_RIGHTS_GIVE = 808;
+ public static ROOM_RIGHTS_LIST = 3385;
+ public static ROOM_RIGHTS_REMOVE = 2064;
+ public static ROOM_RIGHTS_REMOVE_ALL = 2683;
+ public static ROOM_RIGHTS_REMOVE_OWN = 3182;
+ public static ROOM_SETTINGS = 3129;
+ public static ROOM_SETTINGS_SAVE = 1969;
+ public static ROOM_STAFF_PICK = 1918;
+ public static SECURITY_MACHINE = 2490;
+ public static SECURITY_TICKET = 2419;
+ public static TRADE = 1481;
+ public static TRADE_ACCEPT = 3863;
+ public static TRADE_CANCEL = 2341;
+ public static TRADE_CLOSE = 2551;
+ public static TRADE_CONFIRM = 2760;
+ public static TRADE_ITEM = 3107;
+ public static TRADE_ITEM_REMOVE = 3845;
+ public static TRADE_ITEMS = 1263;
+ public static TRADE_UNACCEPT = 1444;
+ public static UNIT_ACTION = 2456;
+ public static UNIT_CHAT = 1314;
+ public static UNIT_CHAT_SHOUT = 2085;
+ public static UNIT_CHAT_WHISPER = 1543;
+ public static UNIT_DANCE = 2080;
+ public static UNIT_DROP_HAND_ITEM = 2814;
+ public static UNIT_GIVE_HANDITEM = 2941;
+ public static UNIT_LOOK = 3301;
+ public static UNIT_POSTURE = 2235;
+ public static UNIT_SIGN = 1975;
+ public static UNIT_TYPING = 1597;
+ public static UNIT_TYPING_STOP = 1474;
+ public static UNIT_WALK = 3320;
+ public static USER_BADGES = 2769;
+ public static USER_BADGES_CURRENT = 2091;
+ public static USER_BADGES_CURRENT_UPDATE = 644;
+ public static USER_BOTS = 3848;
+ public static USER_CURRENCY = 273;
+ public static USER_EFFECT_ACTIVATE = 2959;
+ public static USER_EFFECT_ENABLE = 1752;
+ public static USER_FIGURE = 2730;
+ public static USER_FURNITURE = 3150; // sent when in room
+ public static USER_FURNITURE2 = 3500; // sent when not in room
+ public static USER_HOME_ROOM = 1740;
+ public static USER_INFO = 357;
+ public static USER_MOTTO = 2228;
+ public static USER_IGNORED = 3878;
+ public static USER_OUTFIT_SAVE = 800;
+ public static USER_OUTFITS = 2742;
+ public static USER_PETS = 3095;
+ public static USER_PROFILE = 3265;
+ public static USER_RESPECT = 2694;
+ public static USER_SETTINGS = 2388;
+ public static USER_SETTINGS_CAMERA = 1461;
+ public static USER_SETTINGS_CHAT_STYLE = 1030;
+ public static USER_SETTINGS_INVITES = 1086;
+ public static USER_SETTINGS_OLD_CHAT = 1262;
+ public static USER_SETTINGS_VOLUME = 1367;
+ public static USER_SUBSCRIPTION = 3166;
+ public static USER_WARDROBE_PAGE = 2742;
+ public static USER_WARDROBE_SAVE = 800;
+ public static USER_TAGS = 17;
+ public static USER_VISIT = 2970;
+ public static WIRED_ACTION_SAVE = 2281;
+ public static WIRED_APPLY_SNAPSHOT = 3373;
+ public static WIRED_CONDITION_SAVE = 3203;
+ public static WIRED_OPEN = 768;
+ public static WIRED_TRIGGER_SAVE = 1520;
+ public static GET_ITEM_DATA = 3964;
+ public static ONE_WAY_DOOR_CLICK = 2765;
+ public static REMOVE_WALL_ITEM = 3336;
+ public static MODIFY_WALL_ITEM_DATA = 3666;
+ public static CATALOG_REDEEM_VOUCHER = 339;
+ public static ROOM_TONER_APPLY = 2880;
+ public static LOVELOCK_START_CONFIRM = 3775;
+ public static MANNEQUIN_SAVE_NAME = 2850;
+ public static MANNEQUIN_SAVE_LOOK = 2209;
+ public static PRESENT_OPEN_PRESENT = 3558;
+ public static CATALOG_SELECT_VIP_GIFT = 2276;
+ public static USER_IGNORE_ID = 3314;
+ public static USER_IGNORE = 1117;
+ public static USER_UNIGNORE = 2061;
+ public static MODTOOL_REQUEST_ROOM_INFO = 707;
+ public static MODTOOL_CHANGE_ROOM_SETTINGS = 3260;
+ public static MODTOOL_REQUEST_USER_CHATLOG = 1391;
+ public static MODTOOL_REQUEST_ROOM_CHATLOG = 2587;
+ public static MODTOOL_SANCTION_ALERT = 229;
+ public static MODTOOL_SANCTION_BAN = 2766;
+ public static MODTOOL_SANCTION_KICK = 2582;
+ public static MODTOOL_SANCTION_TRADELOCK = 3742;
+ public static MODTOOL_ALERTEVENT = 1840;
+ public static MODTOOL_SANCTION_MUTE = 1945;
+ public static MODTOOL_REQUEST_USER_ROOMS = 3526;
+ public static MODTOOL_ROOM_ALERT = 3842;
+ public static CONVERT_GLOBAL_ROOM_ID = 314;
+}
diff --git a/src/nitro/communication/messages/outgoing/achievements/RequestAchievementsMessageComposer.ts b/src/nitro/communication/messages/outgoing/achievements/RequestAchievementsMessageComposer.ts
new file mode 100644
index 00000000..a3f6403a
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/achievements/RequestAchievementsMessageComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class RequestAchievementsMessageComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/catalog/CatalogGroupsComposer.ts b/src/nitro/communication/messages/outgoing/catalog/CatalogGroupsComposer.ts
new file mode 100644
index 00000000..171a6e1a
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/catalog/CatalogGroupsComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class CatalogGroupsComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/catalog/CatalogModeComposer.ts b/src/nitro/communication/messages/outgoing/catalog/CatalogModeComposer.ts
new file mode 100644
index 00000000..dd37048c
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/catalog/CatalogModeComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class CatalogModeComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(mode: string)
+ {
+ this._data = [ mode ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/catalog/CatalogPageComposer.ts b/src/nitro/communication/messages/outgoing/catalog/CatalogPageComposer.ts
new file mode 100644
index 00000000..9e55bd0e
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/catalog/CatalogPageComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class CatalogPageComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(pageId: number, offerId: number, catalogType: string)
+ {
+ this._data = [ pageId, offerId, catalogType ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/catalog/CatalogPurchaseComposer.ts b/src/nitro/communication/messages/outgoing/catalog/CatalogPurchaseComposer.ts
new file mode 100644
index 00000000..413b255a
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/catalog/CatalogPurchaseComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class CatalogPurchaseComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(pageId: number, offerId: number, extraData: string, amount: number)
+ {
+ this._data = [ pageId, offerId, extraData, amount ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/catalog/CatalogPurchaseGiftComposer.ts b/src/nitro/communication/messages/outgoing/catalog/CatalogPurchaseGiftComposer.ts
new file mode 100644
index 00000000..5e3197c4
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/catalog/CatalogPurchaseGiftComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class CatalogPurchaseGiftComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(pageId: number, itemId: number, extraData: string, receivingName: string, giftMessage: string, spriteId: number, color: number, ribbonId: number, anonymousGift: boolean)
+ {
+ this._data = [pageId, itemId, extraData, receivingName, giftMessage, spriteId, color, ribbonId, anonymousGift];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/catalog/CatalogRequestGiftConfigurationComposer.ts b/src/nitro/communication/messages/outgoing/catalog/CatalogRequestGiftConfigurationComposer.ts
new file mode 100644
index 00000000..e9cf6cf4
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/catalog/CatalogRequestGiftConfigurationComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class CatalogRequestGiftConfigurationComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/catalog/CatalogRequestVipGiftsComposer.ts b/src/nitro/communication/messages/outgoing/catalog/CatalogRequestVipGiftsComposer.ts
new file mode 100644
index 00000000..7d50cca9
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/catalog/CatalogRequestVipGiftsComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class CatalogRequestVipGiftsComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [ ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ this._data = null;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/catalog/CatalogRequestVipOffersComposer.ts b/src/nitro/communication/messages/outgoing/catalog/CatalogRequestVipOffersComposer.ts
new file mode 100644
index 00000000..29c405a5
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/catalog/CatalogRequestVipOffersComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class CatalogRequestVipOffersComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(offerId: number)
+ {
+ this._data = [ offerId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ this._data = null;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/catalog/CatalogSearchComposer.ts b/src/nitro/communication/messages/outgoing/catalog/CatalogSearchComposer.ts
new file mode 100644
index 00000000..9f15bdf7
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/catalog/CatalogSearchComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class CatalogSearchComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(offerId: number)
+ {
+ this._data = [ offerId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/catalog/CatalogSelectClubGiftComposer.ts b/src/nitro/communication/messages/outgoing/catalog/CatalogSelectClubGiftComposer.ts
new file mode 100644
index 00000000..58d09a5d
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/catalog/CatalogSelectClubGiftComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class CatalogSelectClubGiftComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(itemName: string)
+ {
+ this._data = [ itemName ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/catalog/RedeemItemClothingComposer.ts b/src/nitro/communication/messages/outgoing/catalog/RedeemItemClothingComposer.ts
new file mode 100644
index 00000000..2aa3f80c
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/catalog/RedeemItemClothingComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class RedeemItemClothingComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(setId: number)
+ {
+ this._data = [ setId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/catalog/RedeemVoucherComposer.ts b/src/nitro/communication/messages/outgoing/catalog/RedeemVoucherComposer.ts
new file mode 100644
index 00000000..870910ec
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/catalog/RedeemVoucherComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class CatalogRedeemVoucherComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(voucherCode: string)
+ {
+ this._data = [ voucherCode ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/client/ClientPongComposer.ts b/src/nitro/communication/messages/outgoing/client/ClientPongComposer.ts
new file mode 100644
index 00000000..10a68f84
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/client/ClientPongComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class ClientPongComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/client/ClientReleaseVersionComposer.ts b/src/nitro/communication/messages/outgoing/client/ClientReleaseVersionComposer.ts
new file mode 100644
index 00000000..876b9788
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/client/ClientReleaseVersionComposer.ts
@@ -0,0 +1,24 @@
+import { ClientDeviceCategoryEnum } from '../../../../../core/communication/connections/enums/ClientDeviceCategoryEnum';
+import { ClientPlatformEnum } from '../../../../../core/communication/connections/enums/ClientPlatformEnum';
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+import { Nitro } from '../../../../Nitro';
+
+export class ClientReleaseVersionComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(releaseVersion: string, type: string, platform: number, category: number)
+ {
+ this._data = [ Nitro.RELEASE_VERSION, 'HTML5', ClientPlatformEnum.HTML5, ClientDeviceCategoryEnum.BROWSER ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/desktop/DesktopViewComposer.ts b/src/nitro/communication/messages/outgoing/desktop/DesktopViewComposer.ts
new file mode 100644
index 00000000..77998d48
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/desktop/DesktopViewComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class DesktopViewComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/friendlist/AcceptFriendComposer.ts b/src/nitro/communication/messages/outgoing/friendlist/AcceptFriendComposer.ts
new file mode 100644
index 00000000..dee8bd7a
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/friendlist/AcceptFriendComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class AcceptFriendComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(...userIds: number[])
+ {
+ this._data = [ userIds.length, ...userIds ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/friendlist/DeclineFriendComposer.ts b/src/nitro/communication/messages/outgoing/friendlist/DeclineFriendComposer.ts
new file mode 100644
index 00000000..4ecd6dad
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/friendlist/DeclineFriendComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class DeclineFriendComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(removeAll: boolean, ...userIds: number[])
+ {
+ this._data = [ removeAll, userIds.length, ...userIds ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/friendlist/FindNewFriendsComposer.ts b/src/nitro/communication/messages/outgoing/friendlist/FindNewFriendsComposer.ts
new file mode 100644
index 00000000..936ce7b5
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/friendlist/FindNewFriendsComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class FindNewFriendsComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/friendlist/FollowFriendComposer.ts b/src/nitro/communication/messages/outgoing/friendlist/FollowFriendComposer.ts
new file mode 100644
index 00000000..f4e96cda
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/friendlist/FollowFriendComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class FollowFriendComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(userId: number)
+ {
+ this._data = [ userId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/friendlist/FriendListUpdateComposer.ts b/src/nitro/communication/messages/outgoing/friendlist/FriendListUpdateComposer.ts
new file mode 100644
index 00000000..dcc4d856
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/friendlist/FriendListUpdateComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class FriendListUpdateComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/friendlist/GetFriendRequestsComposer.ts b/src/nitro/communication/messages/outgoing/friendlist/GetFriendRequestsComposer.ts
new file mode 100644
index 00000000..193c55f6
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/friendlist/GetFriendRequestsComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GetFriendRequestsComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/friendlist/HabboSearchComposer.ts b/src/nitro/communication/messages/outgoing/friendlist/HabboSearchComposer.ts
new file mode 100644
index 00000000..0452c199
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/friendlist/HabboSearchComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class HabboSearchComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(search: string)
+ {
+ this._data = [ search ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/friendlist/MessengerInitComposer.ts b/src/nitro/communication/messages/outgoing/friendlist/MessengerInitComposer.ts
new file mode 100644
index 00000000..c2eb5df6
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/friendlist/MessengerInitComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class MessengerInitComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/friendlist/RemoveFriendComposer.ts b/src/nitro/communication/messages/outgoing/friendlist/RemoveFriendComposer.ts
new file mode 100644
index 00000000..b1b09cf9
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/friendlist/RemoveFriendComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class RemoveFriendComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(...userIds: number[])
+ {
+ this._data = [ userIds.length, ...userIds ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/friendlist/RequestFriendComposer.ts b/src/nitro/communication/messages/outgoing/friendlist/RequestFriendComposer.ts
new file mode 100644
index 00000000..4dc10701
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/friendlist/RequestFriendComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class RequestFriendComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(username: string)
+ {
+ this._data = [ username ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/friendlist/SendMessageComposer.ts b/src/nitro/communication/messages/outgoing/friendlist/SendMessageComposer.ts
new file mode 100644
index 00000000..c05ff153
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/friendlist/SendMessageComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class SendMessageComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(userId: number, message: string)
+ {
+ this._data = [ userId, message ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/friendlist/SendRoomInviteComposer.ts b/src/nitro/communication/messages/outgoing/friendlist/SendRoomInviteComposer.ts
new file mode 100644
index 00000000..10958e78
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/friendlist/SendRoomInviteComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class SendRoomInviteComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(message: string, ...userIds: number[])
+ {
+ this._data = [ message, userIds.length, ...userIds ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/friendlist/SetRelationshipStatusComposer.ts b/src/nitro/communication/messages/outgoing/friendlist/SetRelationshipStatusComposer.ts
new file mode 100644
index 00000000..14e83b95
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/friendlist/SetRelationshipStatusComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class SetRelationshipStatusComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(userId: number, relationship: number)
+ {
+ this._data = [ userId, relationship ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/friendlist/VisitUserComposer.ts b/src/nitro/communication/messages/outgoing/friendlist/VisitUserComposer.ts
new file mode 100644
index 00000000..46da4924
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/friendlist/VisitUserComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class VisitUserComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(username: string)
+ {
+ this._data = [ username ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/group/GroupAdminGiveComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupAdminGiveComposer.ts
new file mode 100644
index 00000000..e69bb8a1
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupAdminGiveComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupAdminGiveComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(groupId: number, memberId: number)
+ {
+ this._data = [ groupId, memberId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/group/GroupAdminTakeComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupAdminTakeComposer.ts
new file mode 100644
index 00000000..7af6ccca
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupAdminTakeComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupAdminTakeComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(groupId: number, memberId: number)
+ {
+ this._data = [ groupId, memberId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/group/GroupBadgePartsComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupBadgePartsComposer.ts
new file mode 100644
index 00000000..5fdb39b2
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupBadgePartsComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupBadgePartsComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/group/GroupBuyComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupBuyComposer.ts
new file mode 100644
index 00000000..38e1662a
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupBuyComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupBuyComposer implements IMessageComposer
+{
+ private _data: any[];
+
+ constructor(name: string, description: string, roomId: number, colorA: number, colorB: number, badge: number[])
+ {
+ this._data = [ name, description, roomId, colorA, colorB, badge.length, badge ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/group/GroupBuyDataComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupBuyDataComposer.ts
new file mode 100644
index 00000000..99db1c84
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupBuyDataComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupBuyDataComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/group/GroupConfirmRemoveMemberComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupConfirmRemoveMemberComposer.ts
new file mode 100644
index 00000000..6cacfa10
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupConfirmRemoveMemberComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupConfirmRemoveMemberComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(groupId: number, memberId: number)
+ {
+ this._data = [ groupId, memberId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/group/GroupDeleteComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupDeleteComposer.ts
new file mode 100644
index 00000000..74c55e0b
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupDeleteComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupDeleteComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(groupId: number)
+ {
+ this._data = [ groupId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/group/GroupInformationComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupInformationComposer.ts
new file mode 100644
index 00000000..0f67c5ac
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupInformationComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupInformationComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(groupId: number, flag: boolean)
+ {
+ this._data = [ groupId, flag ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/group/GroupJoinComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupJoinComposer.ts
new file mode 100644
index 00000000..e5be889c
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupJoinComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupJoinComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(groupId: number)
+ {
+ this._data = [ groupId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/group/GroupMembersComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupMembersComposer.ts
new file mode 100644
index 00000000..d7cd91dc
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupMembersComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupMembersComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(groupId: number, pageId: number, query: string, levelId: number)
+ {
+ this._data = [ groupId, pageId, query, levelId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/group/GroupMembershipAcceptComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupMembershipAcceptComposer.ts
new file mode 100644
index 00000000..b56affb0
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupMembershipAcceptComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupMembershipAcceptComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(groupId: number, memberId: number)
+ {
+ this._data = [ groupId, memberId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/group/GroupMembershipDeclineComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupMembershipDeclineComposer.ts
new file mode 100644
index 00000000..fff18378
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupMembershipDeclineComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupMembershipDeclineComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(groupId: number, memberId: number)
+ {
+ this._data = [ groupId, memberId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/group/GroupRemoveMemberComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupRemoveMemberComposer.ts
new file mode 100644
index 00000000..8c656c75
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupRemoveMemberComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupRemoveMemberComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(groupId: number, memberId: number)
+ {
+ this._data = [ groupId, memberId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/group/GroupSaveBadgeComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupSaveBadgeComposer.ts
new file mode 100644
index 00000000..ab04369e
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupSaveBadgeComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupSaveBadgeComposer implements IMessageComposer
+{
+ private _data: any[];
+
+ constructor(groupId: number, badge: number[])
+ {
+ this._data = [ groupId, badge.length, ...badge ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/group/GroupSaveColorsComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupSaveColorsComposer.ts
new file mode 100644
index 00000000..45879c81
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupSaveColorsComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupSaveColorsComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(groupId: number, colorA: number, colorB: number)
+ {
+ this._data = [ groupId, colorA, colorB ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/group/GroupSaveInformationComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupSaveInformationComposer.ts
new file mode 100644
index 00000000..b45ce938
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupSaveInformationComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupSaveInformationComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(groupId: number, title: string, description: string)
+ {
+ this._data = [ groupId, title, description ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/group/GroupSavePreferencesComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupSavePreferencesComposer.ts
new file mode 100644
index 00000000..8a018a52
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupSavePreferencesComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupSavePreferencesComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(groupId: number, state: number, onlyAdminCanDecorate: number)
+ {
+ this._data = [ groupId, state, onlyAdminCanDecorate ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/group/GroupSettingsComposer.ts b/src/nitro/communication/messages/outgoing/group/GroupSettingsComposer.ts
new file mode 100644
index 00000000..24564726
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/group/GroupSettingsComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class GroupSettingsComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(groupId: number)
+ {
+ this._data = [ groupId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/handshake/InfoRetrieveBaseMessageComposer.ts b/src/nitro/communication/messages/outgoing/handshake/InfoRetrieveBaseMessageComposer.ts
new file mode 100644
index 00000000..1a133511
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/handshake/InfoRetrieveBaseMessageComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class InfoRetrieveBaseMessageComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/handshake/SecurityTicketComposer.ts b/src/nitro/communication/messages/outgoing/handshake/SecurityTicketComposer.ts
new file mode 100644
index 00000000..f041840d
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/handshake/SecurityTicketComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class SecurityTicketComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(ticket: string, time: number)
+ {
+ this._data = [ ticket, time ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/inventory/badges/RequestBadgesComposer.ts b/src/nitro/communication/messages/outgoing/inventory/badges/RequestBadgesComposer.ts
new file mode 100644
index 00000000..8dc95eb3
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/badges/RequestBadgesComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class RequestBadgesComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/inventory/badges/SetActivatedBadgesComposer.ts b/src/nitro/communication/messages/outgoing/inventory/badges/SetActivatedBadgesComposer.ts
new file mode 100644
index 00000000..4524b6e3
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/badges/SetActivatedBadgesComposer.ts
@@ -0,0 +1,40 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class SetActivatedBadgesComposer implements IMessageComposer
+{
+ private _badges: string[] = [];
+
+ public getMessageArray()
+ {
+ const data = [];
+ let local2 = 1;
+ while(local2 <= 5)
+ {
+ if(local2 <= this._badges.length)
+ {
+ data.push(local2);
+ data.push(this._badges[(local2 - 1)]);
+ }
+ else
+ {
+ data.push(local2);
+ data.push('');
+ }
+
+ local2++;
+ }
+ return data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+
+ public addActivatedBadge(badge: string): void
+ {
+ if(this._badges.length >= 5) return;
+
+ this._badges.push(badge);
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/inventory/bots/GetBotInventoryComposer.ts b/src/nitro/communication/messages/outgoing/inventory/bots/GetBotInventoryComposer.ts
new file mode 100644
index 00000000..48a6767f
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/bots/GetBotInventoryComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class GetBotInventoryComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/inventory/furni/FurnitureList2Composer.ts b/src/nitro/communication/messages/outgoing/inventory/furni/FurnitureList2Composer.ts
new file mode 100644
index 00000000..8d2b2290
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/furni/FurnitureList2Composer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class FurnitureList2Composer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/inventory/furni/FurnitureListComposer.ts b/src/nitro/communication/messages/outgoing/inventory/furni/FurnitureListComposer.ts
new file mode 100644
index 00000000..d7e2d5e5
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/furni/FurnitureListComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class FurnitureListComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/inventory/pets/RequestPetsComposer.ts b/src/nitro/communication/messages/outgoing/inventory/pets/RequestPetsComposer.ts
new file mode 100644
index 00000000..885d75bf
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/pets/RequestPetsComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class RequestPetsComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/inventory/trading/TradingAcceptComposer.ts b/src/nitro/communication/messages/outgoing/inventory/trading/TradingAcceptComposer.ts
new file mode 100644
index 00000000..0dfbe6b5
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/trading/TradingAcceptComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class TradingAcceptComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/inventory/trading/TradingCancelComposer.ts b/src/nitro/communication/messages/outgoing/inventory/trading/TradingCancelComposer.ts
new file mode 100644
index 00000000..d7382448
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/trading/TradingCancelComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class TradingCancelComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/inventory/trading/TradingCloseComposer.ts b/src/nitro/communication/messages/outgoing/inventory/trading/TradingCloseComposer.ts
new file mode 100644
index 00000000..519c6632
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/trading/TradingCloseComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class TradingCloseComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/inventory/trading/TradingConfirmationComposer.ts b/src/nitro/communication/messages/outgoing/inventory/trading/TradingConfirmationComposer.ts
new file mode 100644
index 00000000..d6152aa3
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/trading/TradingConfirmationComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class TradingConfirmationComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/inventory/trading/TradingListAddItemComposer.ts b/src/nitro/communication/messages/outgoing/inventory/trading/TradingListAddItemComposer.ts
new file mode 100644
index 00000000..cf6bdccf
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/trading/TradingListAddItemComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class TradingListAddItemComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(itemId: number)
+ {
+ this._data = [ itemId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/inventory/trading/TradingListAddItemsComposer.ts b/src/nitro/communication/messages/outgoing/inventory/trading/TradingListAddItemsComposer.ts
new file mode 100644
index 00000000..575a30e1
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/trading/TradingListAddItemsComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class TradingListAddItemsComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(...itemIds: number[])
+ {
+ this._data = [ itemIds.length, ...itemIds ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/inventory/trading/TradingListRemoveItemComposer.ts b/src/nitro/communication/messages/outgoing/inventory/trading/TradingListRemoveItemComposer.ts
new file mode 100644
index 00000000..148109d9
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/trading/TradingListRemoveItemComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class TradingListItemRemoveComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(itemId: number)
+ {
+ this._data = [ itemId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/inventory/trading/TradingOpenComposer.ts b/src/nitro/communication/messages/outgoing/inventory/trading/TradingOpenComposer.ts
new file mode 100644
index 00000000..406c3b9e
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/trading/TradingOpenComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class TradingOpenComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(userId: number)
+ {
+ this._data = [ userId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/inventory/trading/TradingUnacceptComposer.ts b/src/nitro/communication/messages/outgoing/inventory/trading/TradingUnacceptComposer.ts
new file mode 100644
index 00000000..7f02bf22
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/inventory/trading/TradingUnacceptComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../../core/communication/messages/IMessageComposer';
+
+export class TradingUnacceptComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor()
+ {
+ this._data = [];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/nitro/communication/messages/outgoing/modtool/ModtoolChangeRoomSettingsComposer.ts b/src/nitro/communication/messages/outgoing/modtool/ModtoolChangeRoomSettingsComposer.ts
new file mode 100644
index 00000000..168ff4eb
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/modtool/ModtoolChangeRoomSettingsComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class ModtoolChangeRoomSettingsComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(roomId: number, lockDoor: number, changeTitle: number, kickUsers: number)
+ {
+ this._data = [ roomId, lockDoor, changeTitle, kickUsers ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/modtool/ModtoolEventAlertComposer.ts b/src/nitro/communication/messages/outgoing/modtool/ModtoolEventAlertComposer.ts
new file mode 100644
index 00000000..59d71974
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/modtool/ModtoolEventAlertComposer.ts
@@ -0,0 +1,27 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class ModtoolEventAlertComposer implements IMessageComposer
+{
+ private _data: any[] = [];
+
+ constructor(k: number, arg2: string, arg3: number, arg4: number = -1)
+ {
+ this._data.push(k);
+ this._data.push(arg2);
+ this._data.push(arg3);
+ if(arg4 != -1)
+ {
+ this._data.push(arg4);
+ }
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/modtool/ModtoolRequestRoomChatlogComposer.ts b/src/nitro/communication/messages/outgoing/modtool/ModtoolRequestRoomChatlogComposer.ts
new file mode 100644
index 00000000..3a87a54e
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/modtool/ModtoolRequestRoomChatlogComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class ModtoolRequestRoomChatlogComposer implements IMessageComposer>
+{
+ private _data: ConstructorParameters;
+
+ constructor(roomId: number, useless: number = 0)
+ {
+ this._data = [ useless, roomId ];
+ }
+
+ public getMessageArray()
+ {
+ return this._data;
+ }
+
+ public dispose(): void
+ {
+ return;
+ }
+}
diff --git a/src/nitro/communication/messages/outgoing/modtool/ModtoolRequestRoomInfoComposer.ts b/src/nitro/communication/messages/outgoing/modtool/ModtoolRequestRoomInfoComposer.ts
new file mode 100644
index 00000000..1dbd40d0
--- /dev/null
+++ b/src/nitro/communication/messages/outgoing/modtool/ModtoolRequestRoomInfoComposer.ts
@@ -0,0 +1,21 @@
+import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
+
+export class ModtoolRequestRoomInfoComposer implements IMessageComposer