diff --git a/server-data/resources/[esx]/EasyAdmin/.eslintrc.json b/server-data/resources/[esx]/EasyAdmin/.eslintrc.json deleted file mode 100644 index 2eae331a3..000000000 --- a/server-data/resources/[esx]/EasyAdmin/.eslintrc.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "env": { - "browser": true, - "commonjs": true, - "es2021": true - }, - "extends": "eslint:recommended", - "overrides": [], - "parserOptions": { - "ecmaVersion": "latest" - }, - "rules": { - "indent": [ - "error", - "tab" - ], - "linebreak-style": [ - "error", - "unix" - ], - "quotes": [ - "error", - "single" - ], - "semi": [ - "error", - "never" - ], - "no-undef": "off", - "no-else-return": [ - "warn" - ], - "no-empty-function": [ - "error", - {"allow": ["arrowFunctions"]} - ], - "no-implicit-coercion": [ - "warn" - ], - "no-useless-return": [ - "warn" - ], - "no-undef-init": [ - "warn" - ] - } -} \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/LICENSE.md b/server-data/resources/[esx]/EasyAdmin/LICENSE.md deleted file mode 100644 index 4ef32f083..000000000 --- a/server-data/resources/[esx]/EasyAdmin/LICENSE.md +++ /dev/null @@ -1,651 +0,0 @@ -GNU Affero General Public License -================================= - -_Version 3, 19 November 2007_ -_Copyright © 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 Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - -The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are 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. - -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. - -Developers that use our General Public Licenses protect your rights -with two steps: **(1)** assert copyright on the software, and **(2)** offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - -A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - -The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - -An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - -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 Affero 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. Remote Network Interaction; Use with the GNU General Public License - -Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - -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 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 work with which it is combined will remain governed by version -3 of the GNU General Public License. - -### 14. Revised Versions of this License - -The Free Software Foundation may publish revised and/or new versions of -the GNU Affero 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 Affero 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 Affero 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 Affero 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 Affero 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - -If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a “Source” link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - -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 AGPL, see -<>. diff --git a/server-data/resources/[esx]/EasyAdmin/README.md b/server-data/resources/[esx]/EasyAdmin/README.md deleted file mode 100644 index 736afe8f1..000000000 --- a/server-data/resources/[esx]/EasyAdmin/README.md +++ /dev/null @@ -1,48 +0,0 @@ -![image](https://user-images.githubusercontent.com/13604413/129143671-3ab6a643-faf0-479d-8b97-af71ffb5193c.png) - - -EasyAdmin is an Administration Suite for FiveM Servers, EasyAdmin is feature-rich and highly customisable, it includes features such as - -- Basic Administration (Kicking,Temp/PermaBanning,Mute,Teleport To/From,Slapping,Freeze Player,Warnings) -- Ability to Screenshot other Players' Game (requires screenshot-basic) -- Extensive Banlist System which is highly resilient to ban evasion -- Basic Ability to modify Server Settings from a GUI. -- Report / Admin Call System with GUI to view and handle them -- Extensive Permission system utilising FiveM's inbuilt ACE System. -- A Permission Editor allowing for realtime modification of Server Permissions, saves to a config! -- Various Server Admin Tools such as Cleaning up spawned Cars/Peds/Props -- API to allow Developers to Communicate with EasyAdmin -- Translation in 7 Languages (Community Driven) -- Actively Supported & Updated since 2017 -- Plugin Support -- Fully integrated Discord Bot, including Discord ACE Permissions, Chat Bridge, Commands and Logs - -![image](https://user-images.githubusercontent.com/13604413/126916981-1680e5ac-e024-467b-aad3-a5a9658449e0.png) - -![image](https://user-images.githubusercontent.com/13604413/126916983-0e62e13f-aa66-49ea-b7ef-4f8449601c53.png) - -![image](https://user-images.githubusercontent.com/13604413/126916995-213fca15-d356-47b6-8b80-8745b4a37eb9.png) - -![image](https://user-images.githubusercontent.com/13604413/126916989-f78d7b16-d20a-49ba-a559-6c3b56e98de5.png) - -### Dependencies - -EasyAdmin requires FiveM's default `yarn` resource, this is included in [cfx-server-data](https://github.com/citizenfx/cfx-server-data) when installing the server. - - -### Installation - -Take a look at our Documentation [here](https://easyadmin.readthedocs.io/), we Explain how to Install and Configure EasyAdmin on the Wiki. - -## [Support Discord](https://discord.gg/GugyRU8) - - - -Graphic Design by [Team Snaily](https://teamsnaily.com) - - - -Supported by: - -ZAP-Hosting Gameserver and Webhosting -10% Discount Code: blumlaut-a-1757 diff --git a/server-data/resources/[esx]/EasyAdmin/backups/.gitkeep b/server-data/resources/[esx]/EasyAdmin/backups/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/server-data/resources/[esx]/EasyAdmin/client/admin_client.lua b/server-data/resources/[esx]/EasyAdmin/client/admin_client.lua deleted file mode 100644 index d6dc827ba..000000000 --- a/server-data/resources/[esx]/EasyAdmin/client/admin_client.lua +++ /dev/null @@ -1,420 +0,0 @@ ------------------------------------- ------------------------------------- ----- DONT TOUCH ANY OF THIS IF YOU DON'T KNOW WHAT YOU ARE DOING ----- THESE ARE **NOT** CONFIG VALUES, USE THE CONVARS IF YOU WANT TO CHANGE SOMETHING ----- ----- ----- If you are a developer and want to change something, consider writing a plugin instead: ----- https://easyadmin.readthedocs.io/en/latest/plugins/ ----- ------------------------------------- ------------------------------------- - -players = {} -banlist = {} -cachedplayers = {} -reports = {} -add_aces, add_principals = {}, {} -MessageShortcuts = {} -FrozenPlayers = {} -MutedPlayers = {} - -local vehicleInfo = { - netId = nil, - seat = nil, -} - -RegisterNetEvent("EasyAdmin:adminresponse", function(perms) - permissions = perms - - for _, val in pairs(perms) do - if val == true then - isAdmin = true - end - end -end) - -RegisterNetEvent("EasyAdmin:SetSetting", function(setting,state) - settings[setting] = state -end) - -AddEventHandler('EasyAdmin:SetLanguage', function(newstrings) - strings = newstrings -end) - -RegisterNetEvent("EasyAdmin:fillBanlist", function(thebanlist) - banlist = thebanlist -end) - -RegisterNetEvent("EasyAdmin:fillCachedPlayers", function(thecached) - if permissions["player.ban.temporary"] or permissions["player.ban.permanent"] then - cachedplayers = thecached - end -end) - - -RegisterNetEvent("EasyAdmin:GetInfinityPlayerList", function(players) - playerlist = players -end) - -RegisterNetEvent("EasyAdmin:getServerAces", function(aces,principals) - add_aces = aces - add_principals = principals - PrintDebugMessage("Recieved ACE Permissions list", 4) -end) - -RegisterNetEvent("EasyAdmin:SetLanguage", function() - if permissions["server.permissions.read"] then - TriggerServerEvent("EasyAdmin:getServerAces") - end -end) - -RegisterNetEvent("EasyAdmin:NewReport", function(reportData) - reports[reportData.id] = reportData -end) - -RegisterNetEvent("EasyAdmin:ClaimedReport", function(reportData) - reports[reportData.id] = reportData - if _menuPool and _menuPool:IsAnyMenuOpen() then - for _, menu in pairs(reportMenus) do - for _,item in pairs(menu.Items) do - if getMenuItemTitle(item) == GetLocalisedText("claimreport") then - setMenuItemTitle(item, GetLocalisedText("claimedby")) - item:RightLabel(reportData.claimedName) - end - end - end - end -end) - -RegisterNetEvent("EasyAdmin:RemoveReport", function(reportData) - reports[reportData.id] = nil -end) - -RegisterNetEvent("EasyAdmin:fillShortcuts", function (shortcuts) - MessageShortcuts = shortcuts -end) - -RegisterNetEvent('EasyAdmin:SetPlayerFrozen', function(player,state) - FrozenPlayers[player] = state - if _menuPool and _menuPool:IsAnyMenuOpen() then - if playerMenus[tostring(player)].menu then - for _,item in pairs(playerMenus[tostring(player)].menu.Items) do - if getMenuItemTitle(item) == GetLocalisedText("setplayerfrozen") then - item.Checked = state - end - end - end - end -end) - -RegisterNetEvent('EasyAdmin:SetPlayerMuted', function(player,state) - MutedPlayers[player] = state - if _menuPool and _menuPool:IsAnyMenuOpen() then - if playerMenus[tostring(player)].menu then - for _,item in pairs(playerMenus[tostring(player)].menu.Items) do - if getMenuItemTitle(item) == GetLocalisedText("mute") then - item.Checked = state - end - end - end - end -end) - -Citizen.CreateThread( function() - while true do - Citizen.Wait(0) - if frozen then - local localPlayerPedId = PlayerPedId() - FreezeEntityPosition(localPlayerPedId, frozen) - if IsPedInAnyVehicle(localPlayerPedId, true) then - FreezeEntityPosition(GetVehiclePedIsIn(localPlayerPedId, false), frozen) - end - else - Citizen.Wait(200) - end - end -end) - -RegisterNetEvent("EasyAdmin:requestSpectate", function(playerServerId, tgtCoords) - local localPlayerPed = PlayerPedId() - - if IsPedInAnyVehicle(localPlayerPed) then - local vehicle = GetVehiclePedIsIn(localPlayerPed, false) - local numVehSeats = GetVehicleModelNumberOfSeats(GetEntityModel(vehicle)) - vehicleInfo.netId = VehToNet(vehicle) - for i = -1, numVehSeats do - if GetPedInVehicleSeat(vehicle, i) == localPlayerPed then - vehicleInfo.seat = i - break - end - end - end - - if ((not tgtCoords) or (tgtCoords.z == 0.0)) then tgtCoords = GetEntityCoords(GetPlayerPed(GetPlayerFromServerId(playerServerId))) end - if playerServerId == GetPlayerServerId(PlayerId()) then - local oldCoords - if oldCoords then - RequestCollisionAtCoord(oldCoords.x, oldCoords.y, oldCoords.z) - Wait(500) - SetEntityCoords(playerPed, oldCoords.x, oldCoords.y, oldCoords.z, 0, 0, 0, false) - oldCoords=nil - end - spectatePlayer(localPlayerPed,GetPlayerFromServerId(PlayerId()),GetPlayerName(PlayerId())) - frozen = false - return - else - if not oldCoords then - oldCoords = GetEntityCoords(localPlayerPed) - end - end - SetEntityCoords(localPlayerPed, tgtCoords.x, tgtCoords.y, tgtCoords.z - 10.0, 0, 0, 0, false) - frozen = true - stopSpectateUpdate = true - - local playerId = GetPlayerFromServerId(playerServerId) - repeat - Wait(200) - playerId = GetPlayerFromServerId(playerServerId) - until ((GetPlayerPed(playerId) > 0) and (playerId ~= -1)) - spectatePlayer(GetPlayerPed(playerId),playerId,GetPlayerName(playerId)) - stopSpectateUpdate = false -end) - -Citizen.CreateThread(function() - RegisterNetEvent("EasyAdmin:requestCleanup", function(type, radius) - - local toDelete = {} - local deletionText = "" - if type == "cars" then - toDelete = GetGamePool("CVehicle") - deletionText = GetLocalisedText("cleaningcar") - elseif type == "peds" then - toDelete = GetGamePool("CPed") - deletionText = GetLocalisedText("cleaningped") - elseif type == "props" then - toDelete = mergeTables(GetGamePool("CObject"), GetGamePool("CPickup")) - deletionText = GetLocalisedText("cleaningprop") - end - - for _,entity in pairs(toDelete) do - PrintDebugMessage("starting deletion for entity "..entity, 4) - if DoesEntityExist(entity) then - if (type == "cars" and not IsPedAPlayer(GetPedInVehicleSeat(entity, -1))) then - if not NetworkHasControlOfEntity(entity) then - local i=0 - repeat - NetworkRequestControlOfEntity(entity) - i=i+1 - Wait(150) - until (NetworkHasControlOfEntity(entity) or i==500) - end - - -- draw text - SetTextFont(2) - SetTextColour(255, 255, 255, 200) - SetTextProportional(1) - SetTextScale(0.0, 0.6) - SetTextDropshadow(0, 0, 0, 0, 255) - SetTextEdge(1, 0, 0, 0, 255) - SetTextDropShadow() - SetTextOutline() - SetTextEntry("STRING") - AddTextComponentString(string.format(deletionText, entity)) - EndTextCommandDisplayText(0.45, 0.95) - - -- delete entity - if radius == "global" then - PrintDebugMessage("deleting entity "..entity, 3) - SetEntityAsNoLongerNeeded(entity) - DeleteEntity(entity) - else - local entityCoords = GetEntityCoords(entity) - local playerCoords = GetEntityCoords(PlayerPedId()) - if #(playerCoords - entityCoords) < radius then - PrintDebugMessage("deleting entity "..entity, 3) - SetEntityAsNoLongerNeeded(entity) - DeleteEntity(entity) - end - end - Wait(1) - end - toDelete[i] = nil - end - end - end) -end) - -Citizen.CreateThread( function() - while true do - Citizen.Wait(500) - if drawInfo and not stopSpectateUpdate then - local localPlayerPed = PlayerPedId() - local targetPed = GetPlayerPed(drawTarget) - - local tgtCoords = GetEntityCoords(targetPed) - if tgtCoords and tgtCoords.x ~= 0 then - SetEntityCoords(localPlayerPed, tgtCoords.x, tgtCoords.y, tgtCoords.z - 10.0, 0, 0, 0, false) - end - else - Citizen.Wait(1000) - end - end -end) - - -RegisterNetEvent("EasyAdmin:TeleportPlayerBack", function() - if lastLocation then - SetEntityCoords(PlayerPedId(), lastLocation,0,0,0, false) - lastLocation=nil - end -end) - -RegisterNetEvent("EasyAdmin:TeleportRequest", function(id, tgtCoords) - if id then - if (tgtCoords.x == 0.0 and tgtCoords.y == 0.0 and tgtCoords.z == 0.0) then - local tgtPed = GetPlayerPed(GetPlayerFromServerId(id)) - tgtCoords = GetEntityCoords(tgtPed) - end - lastLocation = tgtCoords - SetEntityCoords(PlayerPedId(), tgtCoords,0,0,0, false) - else - lastLocation = tgtCoords - SetEntityCoords(PlayerPedId(), tgtCoords,0,0,0, false) - end -end) - -RegisterNetEvent("EasyAdmin:SlapPlayer", function(slapAmount) - local ped = PlayerPedId() - if slapAmount > GetEntityHealth(ped) then - ApplyDamageToPed(ped, 5000, false, true,true) - else - ApplyDamageToPed(ped, slapAmount, false, true,true) - end -end) - - -RegisterCommand("kick", function(_, args) - local reason = "" - for i,theArg in pairs(args) do - if i ~= 1 then -- make sure we are not adding the kicked player as a reason - reason = reason.." "..theArg - end - end - if args[1] and tonumber(args[1]) then - TriggerServerEvent("EasyAdmin:kickPlayer", tonumber(args[1]), reason) - end -end, false) - -RegisterCommand("ban", function(_, args) - if args[1] and tonumber(args[1]) then - local reason = "" - for i,theArg in pairs(args) do - if i ~= 1 then - reason = reason.." "..theArg - end - end - if args[1] and tonumber(args[1]) then - TriggerServerEvent("EasyAdmin:banPlayer", tonumber(args[1]), reason, false, GetPlayerName(args[1])) - end - end -end, false) - -RegisterNetEvent("EasyAdmin:FreezePlayer", function(toggle) - frozen = toggle - local playerPed = PlayerPedId() - FreezeEntityPosition(playerPed, frozen) - if IsPedInAnyVehicle(playerPed, false) then - FreezeEntityPosition(GetVehiclePedIsIn(playerPed, false), frozen) - end -end) - - -RegisterNetEvent("EasyAdmin:CaptureScreenshot", function() - exports['screenshot-basic']:requestScreenshotUpload(GetConvar("ea_screenshoturl", 'https://wew.wtf/upload.php'), GetConvar("ea_screenshotfield", 'files[]'), function(data) - TriggerLatentServerEvent("EasyAdmin:TookScreenshot", 100000, data) - end) -end) - -function spectatePlayer(targetPed, target, name) - local playerPed = PlayerPedId() -- yourself - enable = true - if (target == PlayerId() or target == -1) then - enable = false - end - - if(enable)then - SetEntityVisible(playerPed, false, 0) - SetEntityCollision(playerPed, false, false) - SetEntityInvincible(playerPed, true) - NetworkSetEntityInvisibleToNetwork(playerPed, true) - Citizen.Wait(200) -- to prevent target player seeing you - if targetPed == playerPed then - Wait(500) - targetPed = GetPlayerPed(target) - end - local targetx, targety, targetz = table.unpack(GetEntityCoords(targetPed, false)) - RequestCollisionAtCoord(targetx,targety,targetz) - NetworkSetInSpectatorMode(true, targetPed) - - DrawPlayerInfo(target) - TriggerEvent("EasyAdmin:showNotification", string.format(GetLocalisedText("spectatingUser"), name)) - else - local oldCoords - if oldCoords then - RequestCollisionAtCoord(oldCoords.x, oldCoords.y, oldCoords.z) - Wait(500) - SetEntityCoords(playerPed, oldCoords.x, oldCoords.y, oldCoords.z, 0, 0, 0, false) - end - NetworkSetInSpectatorMode(false, targetPed) - StopDrawPlayerInfo() - TriggerEvent("EasyAdmin:showNotification", GetLocalisedText("stoppedSpectating")) - frozen = false - Citizen.Wait(200) -- to prevent staying invisible - SetEntityVisible(playerPed, true, 0) - SetEntityCollision(playerPed, true, true) - SetEntityInvincible(playerPed, false) - NetworkSetEntityInvisibleToNetwork(playerPed, false) - if vehicleInfo.netId and vehicleInfo.seat then - local vehicle = NetToVeh(vehicleInfo.netId) - if DoesEntityExist(vehicle) then - if IsVehicleSeatFree(vehicle, vehicleInfo.seat) then - SetPedIntoVehicle(playerPed, vehicle, vehicleInfo.seat) - else - TriggerEvent("EasyAdmin:showNotification", GetLocalisedText("spectatevehicleseatoccupied")) - end - else - TriggerEvent("EasyAdmin:showNotification", GetLocalisedText("spectatenovehiclefound")) - end - - vehicleInfo.netId = nil - vehicleInfo.seat = nil - end - end -end - -function ShowNotification(text) - if not RedM then - local notificationTxd = CreateRuntimeTxd("easyadmin_notification") - CreateRuntimeTextureFromImage(notificationTxd, 'small_logo', 'dependencies/images/small-logo-bg.png') - BeginTextCommandThefeedPost("STRING") - AddTextComponentSubstringPlayerName(text) - - local title = "~bold~EasyAdmin" - local subtitle = GetLocalisedText("notification") - local iconType = 0 - local flash = false - - EndTextCommandThefeedPostMessagetext("easyadmin_notification", "small_logo", flash, iconType, title, subtitle) - local showInBrief = false - local blink = false - EndTextCommandThefeedPostTicker(blink, showInBrief) - end -end - -RegisterNetEvent("EasyAdmin:showNotification", function(text) - TriggerEvent("EasyAdmin:receivedNotification") - if not WasEventCanceled() then - ShowNotification(text) - end -end) \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/client/gui_c.lua b/server-data/resources/[esx]/EasyAdmin/client/gui_c.lua deleted file mode 100644 index b057a0e73..000000000 --- a/server-data/resources/[esx]/EasyAdmin/client/gui_c.lua +++ /dev/null @@ -1,1932 +0,0 @@ ------------------------------------- ------------------------------------- ------------------------------------- ----- DONT TOUCH ANY OF THIS IF YOU DON'T KNOW WHAT YOU ARE DOING ----- THESE ARE **NOT** CONFIG VALUES, USE THE CONVARS IF YOU WANT TO CHANGE SOMETHING ----- ----- ----- If you are a developer and want to change something, consider writing a plugin instead: ----- https://easyadmin.readthedocs.io/en/latest/plugins/ ----- ------------------------------------- ------------------------------------- - -isAdmin = false -showLicenses = false -RedM = false - -settings = { - button = "none", - forceShowGUIButtons = false, -} - - --- generate "slap" table once -local SlapAmount = {} -for i=1,20 do - table.insert(SlapAmount,i) -end - -function handleOrientation(orientation) - if orientation == "right" then - return 1300-menuWidth - elseif orientation == "middle" then - return 730 - elseif orientation == "left" then - return 0 - end -end - -playlist = nil - - -RegisterCommand('easyadmin', function(source, args) - CreateThread(function() - if not isAdmin == true then - TriggerServerEvent("EasyAdmin:amiadmin") - local waitTime = 0 - - repeat - Wait(10) - waitTime=waitTime+1 - until (isAdmin or waitTime==1000) - if not isAdmin then - return - end - end - - if not mainMenu or not mainMenu:Visible() then - if ((RedM and settings.infinity) or not RedM) and isAdmin then - playerlist = nil - if DoesPlayerHavePermissionForCategory(-1, "player") then - TriggerServerEvent("EasyAdmin:GetInfinityPlayerList") - repeat - Wait(10) - until playerlist - else - playerlist = {} - end - end - - if strings and isAdmin then - banLength = {} - - if permissions["player.ban.permanent"] then - table.insert(banLength, {label = GetLocalisedText("permanent"), time = 10444633200}) - end - - if permissions["player.ban.temporary"] then - table.insert(banLength, {label = "6 "..GetLocalisedText("hours"), time = 21600}) - table.insert(banLength, {label = "12 "..GetLocalisedText("hours"), time = 43200}) - table.insert(banLength, {label = "1 "..GetLocalisedText("day"), time = 86400}) - table.insert(banLength, {label = "3 "..GetLocalisedText("days"), time = 259200}) - table.insert(banLength, {label = "1 "..GetLocalisedText("week"), time = 518400}) - table.insert(banLength, {label = "2 "..GetLocalisedText("weeks"), time = 1123200}) - table.insert(banLength, {label = "1 "..GetLocalisedText("month"), time = 2678400}) - table.insert(banLength, {label = "1 "..GetLocalisedText("year"), time = 31536000}) - table.insert(banLength, {label = GetLocalisedText("customtime"), time = -1}) - end - GenerateMenu() - - if (args[1]) then - local id = tonumber(args[1]) - if (reportMenus[id]) then - reportMenus[id]:Visible(true) - return - elseif playerMenus[args[1]] then - local menu = playerMenus[args[1]] - menu.generate(menu.menu) - menu.menu:Visible(true) - return - end - end - SendNUIMessage({action= "speak", text="EasyAdmin"}) - mainMenu:Visible(true) - else - TriggerServerEvent("EasyAdmin:amiadmin") - end - else - mainMenu:Visible(false) - _menuPool:Remove() - TriggerEvent("EasyAdmin:MenuRemoved") - collectgarbage() - end - end) -end) - - -RegisterCommand('ea', function(source,args) - ExecuteCommand('easyadmin '..table.concat(args, " ")) -end) - -Citizen.CreateThread(function() - if CompendiumHorseObserved then -- https://www.youtube.com/watch?v=r7qovpFAGrQ - RedM = true - settings.button = "PhotoModePc" - end - repeat - Wait(100) - until NativeUI - - TriggerServerEvent("EasyAdmin:amiadmin") - TriggerServerEvent("EasyAdmin:requestBanlist") - TriggerServerEvent("EasyAdmin:requestCachedPlayers") - - if not GetResourceKvpString("ea_menuorientation") then - SetResourceKvp("ea_menuorientation", "middle") - SetResourceKvpInt("ea_menuwidth", 0) - menuWidth = 0 - menuOrientation = handleOrientation("middle") - else - menuWidth = GetResourceKvpInt("ea_menuwidth") - menuOrientation = handleOrientation(GetResourceKvpString("ea_menuorientation")) - end - if not GetResourceKvpInt("ea_tts") then - SetResourceKvpInt("ea_tts", 0) - else - if GetResourceKvpInt("ea_tts") == 1 then - SendNUIMessage({ - action = "toggle_speak", - enabled = true - }) - end - end - - local subtitle = "~b~Admin Menu" - if settings.updateAvailable then - subtitle = "~g~UPDATE "..settings.updateAvailable.." AVAILABLE!" - elseif settings.alternativeTitle then - -- if you remove this code then you're a killjoy, can't we have nice things? just once? it's not like this changes the whole admin menu or how it behaves, its a single subtitle. - subtitle = settings.alternativeTitle - end - - while true do - if _menuPool then - if not _menuPool:IsAnyMenuOpen() then - _menuPool:Remove() - TriggerEvent("EasyAdmin:MenuRemoved") - _menuPool = nil - collectgarbage() - elseif _menuPool:IsAnyMenuOpen() then - _menuPool:ProcessMenus() - end - end - - if RedM then -- since RedM doesn't have the new key bindings yet, watch for button press actively. - if (RedM and IsControlJustReleased(0, Controls[settings.button]) ) then - ExecuteCommand("easyadmin") - end - end - - Citizen.Wait(1) - end -end) - -function DrawPlayerInfo(target) - drawTarget = target - drawInfo = true -end - -function StopDrawPlayerInfo() - drawInfo = false - drawTarget = 0 -end - -local banlistPage = 1 -playerMenus = {} -cachedMenus = {} -reportMenus = {} -local easterChance = math.random(0,101) -local overrideEgg, currentEgg - - - --- note: we dont support dui banner and dui logo at the same time yet. -local eastereggs = { - pipes = { - duibanner = "http://legacy.furfag.de/eggs/pipes", - banner = false, - logo = "dependencies/images/banner-logo.png", - }, - nom = { - duilogo = "http://legacy.furfag.de/eggs/nom", - banner = "dependencies/images/banner-gradient.png", - logo = false, - }, - pride = { - banner = "dependencies/images/banner-gradient.png", - logo = "dependencies/images/pride.png", - }, - ukraine = { - banner = "dependencies/images/banner-gradient.png", - logo = "dependencies/images/ukraine.png" - }, - EOA = { - banner = "dependencies/images/banner-eoa.png", - logo = "dependencies/images/logo-eoa.png" - }, - HardAdmin = { - banner = "dependencies/images/banner-hardadmin.png", - logo = "dependencies/images/logo-hardadmin.png" - } -} - -function generateTextures() - if not RedM and not txd or (overrideEgg ~= currentEgg) then - if dui then - DestroyDui(dui) - dui = nil - end - txd = CreateRuntimeTxd("easyadmin") - CreateRuntimeTextureFromImage(txd, 'badge_dev', 'dependencies/images/pl_badge_dev.png') - CreateRuntimeTextureFromImage(txd, 'badge_contrib', 'dependencies/images/pl_badge_contr.png') - - if ((overrideEgg == nil) and easterChance == 100) or (overrideEgg or overrideEgg == false) then - local chance = overrideEgg - if ((overrideEgg == nil) and easterChance == 100) then - -- dirty function to select random easter egg - local tbl = {} - for k,v in pairs(eastereggs) do - table.insert(tbl, k) - end - - chance = tbl[math.random( #tbl )] - end - - local egg = eastereggs[chance] - if egg then - if egg.duibanner then - dui = CreateDui(egg.duibanner, 512,128) - local duihandle = GetDuiHandle(dui) - CreateRuntimeTextureFromDuiHandle(txd, 'banner-gradient', duihandle) - Wait(800) - elseif egg.duilogo then - dui = CreateDui(egg.duilogo, 512,128) - local duihandle = GetDuiHandle(dui) - CreateRuntimeTextureFromDuiHandle(txd, 'logo', duihandle) - Wait(800) - end - if egg.logo then - CreateRuntimeTextureFromImage(txd, 'logo', egg.logo) - end - if egg.banner then - CreateRuntimeTextureFromImage(txd, 'banner-gradient', egg.banner) - end - currentEgg = chance - else - CreateRuntimeTextureFromImage(txd, 'logo', 'dependencies/images/banner-logo.png') - CreateRuntimeTextureFromImage(txd, 'banner-gradient', 'dependencies/images/banner-gradient.png') - currentEgg = false - end - else - if settings.alternativeLogo then - CreateRuntimeTextureFromImage(txd, 'logo', 'dependencies/images/'..settings.alternativeLogo..'.png') - else - CreateRuntimeTextureFromImage(txd, 'logo', 'dependencies/images/banner-logo.png') - end - if settings.alternativeBanner then - CreateRuntimeTextureFromImage(txd, 'banner-gradient', 'dependencies/images/'..settings.alternativeBanner..'.png') - else - CreateRuntimeTextureFromImage(txd, 'banner-gradient', 'dependencies/images/banner-gradient.png') - end - currentEgg=nil - end - end -end - -function GenerateMenu() -- this is a big ass function - - generateTextures() - TriggerServerEvent("EasyAdmin:requestCachedPlayers") - if _menuPool then - _menuPool:Remove() - TriggerEvent("EasyAdmin:MenuRemoved") - collectgarbage() - end - _menuPool = NativeUI.CreatePool() - collectgarbage() - if not GetResourceKvpString("ea_menuorientation") then - SetResourceKvp("ea_menuorientation", "middle") - SetResourceKvpInt("ea_menuwidth", 0) - menuWidth = 0 - menuOrientation = handleOrientation("middle") - else - menuWidth = GetResourceKvpInt("ea_menuwidth") - menuOrientation = handleOrientation(GetResourceKvpString("ea_menuorientation")) - end - maxRightTextWidth = math.floor((24+(menuWidth*0.12))) - local subtitle = "Admin Menu" - if settings.updateAvailable then - subtitle = "~g~UPDATE "..settings.updateAvailable.." AVAILABLE!" elseif settings.alternativeTitle then subtitle = settings.alternativeTitle - end - mainMenu = NativeUI.CreateMenu(RedM and "EasyAdmin" or "", subtitle, menuOrientation, 0, "easyadmin", "banner-gradient", "logo") - _menuPool:Add(mainMenu) - - _menuPool:ControlDisablingEnabled(false) - _menuPool:MouseControlsEnabled(false) - - if DoesPlayerHavePermissionForCategory(-1, "player") then - playermanagement = _menuPool:AddSubMenu(mainMenu, GetLocalisedText("playermanagement"),"",true, true) - playermanagement:SetMenuWidthOffset(menuWidth) - end - - if DoesPlayerHavePermissionForCategory(-1, "server") or permissions["player.ban.view"] then - servermanagement = _menuPool:AddSubMenu(mainMenu, GetLocalisedText("servermanagement"),"",true, true) - servermanagement:SetMenuWidthOffset(menuWidth) - end - - settingsMenu = _menuPool:AddSubMenu(mainMenu, GetLocalisedText("settings"),"",true, true) - - mainMenu:SetMenuWidthOffset(menuWidth) - settingsMenu:SetMenuWidthOffset(menuWidth) - - -- util stuff - players = {} - local localplayers = {} - - if (RedM and settings.infinity) or not RedM then - local localplayers = playerlist - local temp = {} - --table.sort(localplayers) - for i,thePlayer in pairs(localplayers) do - table.insert(temp, thePlayer.id) - end - table.sort(temp) - for i, thePlayerId in pairs(temp) do - for _, thePlayer in pairs(localplayers) do - if thePlayerId == thePlayer.id then - players[i] = thePlayer - end - end - end - temp=nil - else - for i = 0, 128 do - if NetworkIsPlayerActive( i ) then - table.insert( localplayers, GetPlayerServerId(i) ) - end - end - table.sort(localplayers) - for i,thePlayer in ipairs(localplayers) do - table.insert(players,GetPlayerFromServerId(thePlayer)) - end - end - - TriggerEvent("EasyAdmin:BuildMainMenuOptions") - for i, plugin in pairs(plugins) do - if plugin.functions.mainMenu then - PrintDebugMessage("Processing Plugin: "..plugin.name, 4) - local ran, errorMsg = pcall(plugin.functions.mainMenu) - if not ran then - PrintDebugMessage("Error in plugin "..plugin.name..": \n"..errorMsg, 1) - end - end - end - - if DoesPlayerHavePermissionForCategory(-1, "player") then - - local userSearch = NativeUI.CreateItem(GetLocalisedText("searchuser"), GetLocalisedText("searchuserguide")) - playermanagement:AddItem(userSearch) - userSearch.Activated = function(ParentMenu, SelectedItem) - - local result = displayKeyboardInput("FMMC_KEY_TIP8", "", 60) - - if result and result ~= "" then - local found = false - local foundbyid = playerMenus[result] or false - local temp = {} - if foundbyid then - found = true - table.insert(temp, {id = foundbyid.id, name = foundbyid.name, menu = foundbyid.menu}) - end - for k,v in pairs(playerMenus) do - if string.find(string.lower(v.name), string.lower(result)) then - found = true - table.insert(temp, {id = v.id, name = v.name, menu = v.menu}) - end - end - for k,v in pairs(cachedMenus) do - if string.find(string.lower(v.name), string.lower(result)) then - found = true - table.insert(temp, {id = v.id, name = v.name, menu = v.menu, cached = true}) - end - end - - if found and (#temp > 1) then - local searchsubtitle = "Found "..tostring(#temp).." results!" - ttsSpeechText(searchsubtitle) - local resultMenu = NativeUI.CreateMenu("Search Results", searchsubtitle, menuOrientation, 0, "easyadmin", "banner-gradient", "logo") - _menuPool:Add(resultMenu) - _menuPool:ControlDisablingEnabled(false) - _menuPool:MouseControlsEnabled(false) - - for i,thePlayer in ipairs(temp) do - local title = "["..thePlayer.id.."] "..thePlayer.name, "" - if thePlayer.cached then - title = thePlayer.name - end - local thisItem = NativeUI.CreateItem(title) - resultMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu, SelectedItem) - _menuPool:CloseAllMenus() - Citizen.Wait(300) - local thisMenu = thePlayer.menu - playerMenus[tostring(thePlayer.id)].generate(thisMenu) - thisMenu:Visible(true) - end - end - _menuPool:CloseAllMenus() - Citizen.Wait(300) - resultMenu:Visible(true) - return - end - if found and (#temp == 1) then - local thisMenu = temp[1].menu - _menuPool:CloseAllMenus() - Citizen.Wait(300) - ttsSpeechText("Found User.") - playerMenus[tostring(temp[1].id)].generate(thisMenu) - thisMenu:Visible(true) - return - end - TriggerEvent("EasyAdmin:showNotification", "~r~No results found!") - end - end - - playerMenus = {} - cachedMenus = {} - reportMenus = {} - for i,thePlayer in pairs(players) do - if RedM and not settings.infinity then - thePlayer = { - id = GetPlayerServerId(thePlayer), - name = GetPlayerName(thePlayer) - } - end - local thisPlayerMenu = _menuPool:AddSubMenu(playermanagement,"["..thePlayer.id.."] "..thePlayer.name,"",true) - if not RedM and thePlayer.developer then - thisPlayerMenu.ParentItem:SetRightBadge(23) - elseif not RedM and thePlayer.contributor then - thisPlayerMenu.ParentItem:SetRightBadge(24) - end - playerMenus[tostring(thePlayer.id)] = {menu = thisPlayerMenu, name = thePlayer.name, id = thePlayer.id } - - thisPlayerMenu:SetMenuWidthOffset(menuWidth) - - playerMenus[tostring(thePlayer.id)].generate = function(menu) - thisPlayer = menu - - - if not playerMenus[tostring(thePlayer.id)].generated then - - if permissions["player.kick"] then - local thisKickMenu = _menuPool:AddSubMenu(thisPlayer,GetLocalisedText("kickplayer"),"",true) - thisKickMenu:SetMenuWidthOffset(menuWidth) - - local thisItem = NativeUI.CreateItem(GetLocalisedText("reason"),GetLocalisedText("kickreasonguide")) - thisKickMenu:AddItem(thisItem) - KickReason = GetLocalisedText("noreason") - thisItem:RightLabel(KickReason) - thisItem.Activated = function(ParentMenu,SelectedItem) - local result = displayKeyboardInput("FMMC_KEY_TIP8", "", 128) - local formattedResult = formatRightString(formatShortcuts(result)) - - if result and result ~= "" then - KickReason = result - thisItem:RightLabel(formattedResult) - else - KickReason = GetLocalisedText("noreason") - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("confirmkick"),GetLocalisedText("confirmkickguide")) - thisKickMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - if KickReason == "" then - KickReason = GetLocalisedText("noreason") - end - TriggerServerEvent("EasyAdmin:kickPlayer", thePlayer.id, KickReason) - _menuPool:CloseAllMenus() - Citizen.Wait(800) - GenerateMenu() - playermanagement:Visible(true) - end - end - - if permissions["player.ban.temporary"] or permissions["player.ban.permanent"] then - local thisBanMenu = _menuPool:AddSubMenu(thisPlayer,GetLocalisedText("banplayer"),"",true) - thisBanMenu:SetMenuWidthOffset(menuWidth) - - local thisItem = NativeUI.CreateItem(GetLocalisedText("reason"),GetLocalisedText("banreasonguide")) - thisBanMenu:AddItem(thisItem) - BanReason = GetLocalisedText("noreason") - thisItem:RightLabel(BanReason) - thisItem.Activated = function(ParentMenu,SelectedItem) - local result = displayKeyboardInput("FMMC_KEY_TIP8", "", 128) - local formattedResult = formatRightString(formatShortcuts(result)) - - if result and result ~= "" then - BanReason = result - thisItem:RightLabel(formattedResult) - else - BanReason = GetLocalisedText("noreason") - end - end - local bt = {} - for i,a in ipairs(banLength) do - table.insert(bt, a.label) - end - - local thisItem = NativeUI.CreateListItem(GetLocalisedText("banlength"),bt, 1,GetLocalisedText("banlengthguide") ) - thisBanMenu:AddItem(thisItem) - local BanTime = banLength[1].time - thisItem.OnListChanged = function(sender,item,index) - BanTime = banLength[index].time - end - - thisItem.OnListSelected = function (sender,item,index) - if banLength[index].time == -1 then - - local thisBanTimeMenu = _menuPool:AddSubMenu(thisBanMenu, GetLocalisedText("banlength"), "",true) - thisBanTimeMenu:SetMenuWidthOffset(menuWidth) - - local hours, days, weeks, months = 0, 0, 0, 0 - -- generate our ban lengths - local hourArray = {} - for i=0, 24 do - table.insert(hourArray,i) - end - - local dayArray = {} - for i=0, 31 do - table.insert(dayArray,i) - end - - local weekArray = {} - for i=0, 4 do - table.insert(weekArray,i) - end - - local monthArray = {} - for i=0, 12 do - table.insert(monthArray,i) - end - - local thisItem = NativeUI.CreateListItem(GetLocalisedText("hours"),hourArray, 1,"") - thisBanTimeMenu:AddItem(thisItem) - thisItem.OnListChanged = function(sender,item,index) - hours = item:IndexToItem(index) - end - - local thisItem = NativeUI.CreateListItem(GetLocalisedText("days"),dayArray, 1,"") - thisBanTimeMenu:AddItem(thisItem) - thisItem.OnListChanged = function(sender,item,index) - days = item:IndexToItem(index) - end - - local thisItem = NativeUI.CreateListItem(GetLocalisedText("weeks"),weekArray, 1,"") - thisBanTimeMenu:AddItem(thisItem) - thisItem.OnListChanged = function(sender,item,index) - weeks = item:IndexToItem(index) - end - - local thisItem = NativeUI.CreateListItem(GetLocalisedText("months"),monthArray, 1,"") - thisBanTimeMenu:AddItem(thisItem) - thisItem.OnListChanged = function(sender,item,index) - months = item:IndexToItem(index) - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("confirm"),"") - thisBanTimeMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - hours=hours*3600 - days=days*86400 - weeks=weeks*518400 - months=months*2678400 - BanTime = hours+days+weeks+months - thisBanMenu:Visible(true) - end - - thisBanTimeMenu:RefreshIndexRecursively() - -- evil NativeUI hack to force it to select and open our submenu - thisBanMenu:CurrentSelection(#thisBanMenu.Items-1) - for i, item in pairs(thisBanMenu.Items) do - item:Selected(false) - end - - thisBanMenu:SelectItem() - -- woosh - thisBanMenu:RemoveItemAt(#thisBanMenu.Items) - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("confirmban"),GetLocalisedText("confirmbanguide")) - thisBanMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - if BanTime == -1 then - TriggerEvent("EasyAdmin:showNotification", GetLocalisedText("nocustombantime")) - return - end - if BanReason == "" then - BanReason = GetLocalisedText("noreason") - end - TriggerServerEvent("EasyAdmin:banPlayer", thePlayer.id, BanReason, BanTime, thePlayer.name ) - BanTime = 1 - BanReason = "" - _menuPool:CloseAllMenus() - Citizen.Wait(800) - GenerateMenu() - playermanagement:Visible(true) - end - - end - - if permissions["player.mute"] then - local thisItem = NativeUI.CreateCheckboxItem(GetLocalisedText("mute"), MutedPlayers[thePlayer.id], GetLocalisedText("muteguide")) - thisPlayer:AddItem(thisItem) - thisItem.CheckboxEvent = function(sender, item, checked_) - TriggerServerEvent("EasyAdmin:mutePlayer", thePlayer.id) - end - end - - if permissions["player.spectate"] then - local thisItem = NativeUI.CreateItem(GetLocalisedText("spectateplayer"), "") - thisPlayer:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - TriggerServerEvent("EasyAdmin:requestSpectate",thePlayer.id) - end - end - - if permissions["player.teleport.single"] then - local sl = {GetLocalisedText("teleporttoplayer"), GetLocalisedText("teleportplayertome"), GetLocalisedText("teleportmeback"), GetLocalisedText("teleportplayerback"), GetLocalisedText("teleportintoclosestvehicle")} - local thisItem = NativeUI.CreateListItem(GetLocalisedText("teleportplayer"), sl, 1, "") - thisPlayer:AddItem(thisItem) - thisItem.OnListSelected = function(sender, item, index) - if item == thisItem then - i = item:IndexToItem(index) - local playerPed = PlayerPedId() - if i == GetLocalisedText("teleporttoplayer") then - if settings.infinity then - TriggerServerEvent('EasyAdmin:TeleportAdminToPlayer', thePlayer.id) - else - lastLocation = GetEntityCoords(playerPed) - local x,y,z = table.unpack(GetEntityCoords(GetPlayerPed(GetPlayerFromServerId(thePlayer.id)),true)) - local heading = GetEntityHeading(GetPlayerPed(player)) - SetEntityCoords(playerPed, x,y,z,0,0,heading, false) - end - elseif i == GetLocalisedText("teleportplayertome") then - local coords = GetEntityCoords(playerPed,true) - TriggerServerEvent("EasyAdmin:TeleportPlayerToCoords", thePlayer.id, coords) - elseif i == GetLocalisedText("teleportmeback") and lastLocation then - local heading = GetEntityHeading(playerPed) - SetEntityCoords(playerPed, lastLocation,0,0,heading, false) - lastLocation = nil - elseif i == GetLocalisedText("teleportplayerback") then - TriggerServerEvent("EasyAdmin:TeleportPlayerBack", thePlayer.id) - elseif i == GetLocalisedText("teleportintoclosestvehicle") then - local coords = GetEntityCoords(playerPed,true) - local vehicles = GetGamePool("CVehicle") - local closestDistance = -1 - local closestVehicle = -1 - for _,vehicle in pairs(vehicles) do - local vehcoords = GetEntityCoords(vehicle,true) - local distance = #(coords - vehcoords) - if closestDistance == -1 or closestDistance > distance then - closestDistance = distance - closestVehicle = vehicle - end - end - if closestVehicle ~= -1 then - for i=-1, GetVehicleMaxNumberOfPassengers(closestVehicle) do - if IsVehicleSeatFree(closestVehicle, i) then - SetPedIntoVehicle(playerPed, closestVehicle, i) - break - end - end - else - TriggerEvent("EasyAdmin:showNotification", "No Vehicles found nearby.") - end - end - end - end - end - - if permissions["player.slap"] then - local thisItem = NativeUI.CreateSliderItem(GetLocalisedText("slapplayer"), SlapAmount, 20, false, false) - thisPlayer:AddItem(thisItem) - thisItem.OnSliderSelected = function(index) - TriggerServerEvent("EasyAdmin:SlapPlayer", thePlayer.id, index*10) - end - end - - if permissions["player.freeze"] and not RedM then - local thisItem = NativeUI.CreateCheckboxItem(GetLocalisedText("setplayerfrozen"), FrozenPlayers[thePlayer.id]) - thisPlayer:AddItem(thisItem) - thisItem.CheckboxEvent = function(sender, item, checked_) - TriggerServerEvent("EasyAdmin:FreezePlayer", thePlayer.id, checked_) - end - end - - if permissions["player.screenshot"] then - local thisItem = NativeUI.CreateItem(GetLocalisedText("takescreenshot"),"") - thisPlayer:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - TriggerServerEvent("EasyAdmin:TakeScreenshot", thePlayer.id) - end - end - - if permissions["player.warn"] then - local thisWarnMenu = _menuPool:AddSubMenu(thisPlayer,GetLocalisedText("warnplayer"),"",true) - thisWarnMenu:SetMenuWidthOffset(menuWidth) - - local thisItem = NativeUI.CreateItem(GetLocalisedText("reason"),GetLocalisedText("warnreasonguide")) - thisWarnMenu:AddItem(thisItem) - WarnReason = GetLocalisedText("noreason") - thisItem:RightLabel(WarnReason) - thisItem.Activated = function(ParentMenu,SelectedItem) - local result = displayKeyboardInput("FMMC_KEY_TIP8", "", 128) - local formattedResult = formatRightString(formatShortcuts(result)) - - if result and result ~= "" then - WarnReason = result - thisItem:RightLabel(formattedResult) - else - WarnReason = GetLocalisedText("noreason") - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("confirmwarn"),GetLocalisedText("confirmwarnguide")) - thisWarnMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - if WarnReason == "" then - WarnReason = GetLocalisedText("noreason") - end - TriggerServerEvent("EasyAdmin:warnPlayer", thePlayer.id, WarnReason) - BanTime = 1 - BanReason = "" - _menuPool:CloseAllMenus() - Citizen.Wait(800) - GenerateMenu() - playermanagement:Visible(true) - end - end - - TriggerEvent("EasyAdmin:BuildPlayerOptions", thePlayer.id) - for i, plugin in pairs(plugins) do - if plugin.functions.playerMenu then - PrintDebugMessage("Processing Plugin: "..plugin.name, 4) - local ran, errorMsg = pcall(plugin.functions.playerMenu, thePlayer.id ) - if not ran then - PrintDebugMessage("Error in plugin "..plugin.name..": \n"..errorMsg, 1) - end - end - end - - if GetResourceState("es_extended") == "started" and not ESX then - local thisItem = NativeUI.CreateItem("~y~[ESX]~s~ Options","You can buy the ESX Plugin from https://blumlaut.tebex.io to use this Feature.") - thisPlayer:AddItem(thisItem) - thisItem.Activated = function(ParentMenu, SelectedItem) - copyToClipboard("https://blumlaut.tebex.io/package/4455820") - end - end - if GetResourceState("qb-core") == "started" and not QBCore then - local thisItem = NativeUI.CreateItem("~b~[QBCore]~s~ Options","You can buy the QBCore Plugin from https://blumlaut.tebex.io to use this Feature.") - thisPlayer:AddItem(thisItem) - thisItem.Activated = function(ParentMenu, SelectedItem) - copyToClipboard("https://blumlaut.tebex.io/package/4842353") - end - end - - _menuPool:ControlDisablingEnabled(false) - _menuPool:MouseControlsEnabled(false) - - thisPlayer:RefreshIndexRecursively() - playerMenus[tostring(thePlayer.id)].generated = true - end - end - - thisPlayerMenu.ParentItem.Activated = function(ParentMenu, SelectedItem) - thisPlayer = thisPlayerMenu - playerMenus[tostring(thePlayer.id)].generate(thisPlayer) - - for i, menu in pairs(playerMenus) do - menu.menu.ParentMenu = playermanagement - end - end - - end - - playermanagement.ParentItem.Activated = function(ParentMenu, SelectedItem) - for i, menu in pairs(playerMenus) do - menu.menu.ParentMenu = playermanagement - end - end - - if permissions["player.reports.view"] then - reportViewer = _menuPool:AddSubMenu(playermanagement, GetLocalisedText("reportviewer"),"",true) - local thisMenuWidth = menuWidth - if menuWidth < 150 then - thisMenuWidth = 150 - else - thisMenuWidth = menuWidth - end - reportViewer:SetMenuWidthOffset(thisMenuWidth) - reportViewer.ParentItem:RightLabel(tostring(#reports).." "..GetLocalisedText("open")) - - for i, report in pairs(reports) do - local reportColour = (report.type == 0 and "~y~" or "~r~") - if report.claimed then - reportColour = "~g~" - end - local thisMenu = _menuPool:AddSubMenu(reportViewer, reportColour.. "#"..report.id.." "..string.sub((report.reportedName or report.reporterName), 1, 12).."~w~", "", true) - thisMenu:SetMenuWidthOffset(thisMenuWidth) - thisMenu.ParentItem:RightLabel(formatRightString(report.reason, 32)) - reportMenus[report.id] = thisMenu - - if permissions["player.reports.claim"] then - local claimText = GetLocalisedText("claimreport") - local rightLabel = "" - if report.claimed then - claimText = GetLocalisedText("claimedby") - rightLabel = formatRightString(report.claimedName) - end - - local thisItem = NativeUI.CreateItem(claimText, "") - thisItem:RightLabel(rightLabel) - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - if not report.claimed then - TriggerServerEvent("EasyAdmin:ClaimReport", i) - else - TriggerEvent("EasyAdmin:showNotification", GetLocalisedText("reportalreadyclaimed")) - end - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("reporter"), GetLocalisedText("entertoopen")) - thisItem:RightLabel(formatRightString(report.reporterName)) - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - _menuPool:CloseAllMenus() - Citizen.Wait(50) - GenerateMenu() - Wait(100) - if not playerMenus[tostring(report.reporter)] then - TriggerEvent("EasyAdmin:showNotification", "~r~Reporting player not found.") - reportViewer:Visible(true) - else - local ourMenu = playerMenus[tostring(report.reporter)].menu - playerMenus[tostring(report.reporter)].generate(ourMenu) - ourMenu.ParentMenu=reportMenus[report.id] - ourMenu:Visible(true) - end - end - - if report.type == 1 then - local thisItem = NativeUI.CreateItem(GetLocalisedText("reported"), GetLocalisedText("entertoopen")) - thisItem:RightLabel(formatRightString(report.reportedName)) - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - _menuPool:CloseAllMenus() - Citizen.Wait(50) - GenerateMenu() - Wait(100) - if not playerMenus[tostring(report.reported)] then - TriggerEvent("EasyAdmin:showNotification", "~r~Reported player not found.") - reportViewer:Visible(true) - else - local ourMenu = playerMenus[tostring(report.reported)].menu - playerMenus[tostring(report.reported)].generate(ourMenu) - ourMenu.ParentMenu=reportMenus[report.id] - ourMenu:Visible(true) - end - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("reason"), "") - thisItem:RightLabel(formatRightString(report.reason, 48)) - thisMenu:AddItem(thisItem) - - if permissions["player.reports.process"] then - local thisItem = NativeUI.CreateItem(GetLocalisedText("closereport"), "") - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - TriggerServerEvent("EasyAdmin:RemoveReport", report) - _menuPool:CloseAllMenus() - Citizen.Wait(800) - GenerateMenu() - reportViewer:Visible(true) - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("closesimilarreports"), GetLocalisedText("closesimilarreportsguide")) - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - TriggerServerEvent("EasyAdmin:RemoveSimilarReports", report) - _menuPool:CloseAllMenus() - Citizen.Wait(800) - GenerateMenu() - reportViewer:Visible(true) - end - end - end - local thisItem = NativeUI.CreateItem(GetLocalisedText("refreshreports"), GetLocalisedText("refreshreportsguide")) - reportViewer:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - _menuPool:CloseAllMenus() - repeat - Wait(100) - until reportViewer - GenerateMenu() - reportViewer:Visible(true) - end - end - - allPlayers = _menuPool:AddSubMenu(playermanagement,GetLocalisedText("allplayers"),"",true) - allPlayers:SetMenuWidthOffset(menuWidth) - if permissions["player.teleport.everyone"] then - -- "all players" function - local thisItem = NativeUI.CreateItem(GetLocalisedText("teleporttome"), GetLocalisedText("teleporttomeguide")) - allPlayers:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - local pCoords = GetEntityCoords(PlayerPedId(),true) - TriggerServerEvent("EasyAdmin:TeleportPlayerToCoords", -1, pCoords) - end - end - - - cachedListGenerated = false - - CachedList = _menuPool:AddSubMenu(playermanagement,GetLocalisedText("cachedplayers"),"",true) - CachedList:SetMenuWidthOffset(menuWidth) - - CachedList.ParentItem.Activated = function(ParentMenu, SelectedItem) - if not cachedListGenerated then - if permissions["player.ban.temporary"] or permissions["player.ban.permanent"] then - for i, cachedplayer in pairs(cachedplayers) do - if cachedplayer.droppedTime and not cachedplayer.immune then - local thisCachedPlayerMenu = _menuPool:AddSubMenu(CachedList,"["..cachedplayer.id.."] "..cachedplayer.name,"",true) - cachedMenus[tostring(cachedplayer.id)] = {menu = thisCachedPlayerMenu, name = cachedplayer.name, id = cachedplayer.id } - thisCachedPlayerMenu:SetMenuWidthOffset(menuWidth) - - thisCachedPlayerMenu.ParentItem.Activated = function(ParentMenu, SelectedItem) - thisPlayer = thisCachedPlayerMenu - if not cachedMenus[tostring(cachedplayer.id)].generated then - local thisBanMenu = _menuPool:AddSubMenu(thisPlayer,GetLocalisedText("banplayer"),"",true) - thisBanMenu:SetMenuWidthOffset(menuWidth) - - local thisItem = NativeUI.CreateItem(GetLocalisedText("reason"),GetLocalisedText("banreasonguide")) - thisBanMenu:AddItem(thisItem) - BanReason = GetLocalisedText("noreason") - thisItem:RightLabel(BanReason) - thisItem.Activated = function(ParentMenu,SelectedItem) - local result = displayKeyboardInput("FMMC_KEY_TIP8", "", 128) - local formattedResult = formatRightString(formatShortcuts(result)) - - if result and result ~= "" then - BanReason = result - thisItem:RightLabel(formattedResult) - else - BanReason = GetLocalisedText("noreason") - end - end - local bt = {} - for i,a in ipairs(banLength) do - table.insert(bt, a.label) - end - - local thisItem = NativeUI.CreateListItem(GetLocalisedText("banlength"),bt, 1,GetLocalisedText("banlengthguide") ) - thisBanMenu:AddItem(thisItem) - local BanTime = 1 - thisItem.OnListChanged = function(sender,item,index) - BanTime = index - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("confirmban"),GetLocalisedText("confirmbanguide")) - thisBanMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - if BanReason == "" then - BanReason = GetLocalisedText("noreason") - end - TriggerServerEvent("EasyAdmin:offlinebanPlayer", cachedplayer.id, BanReason, banLength[BanTime].time, cachedplayer.name) - BanTime = 1 - BanReason = "" - _menuPool:CloseAllMenus() - Citizen.Wait(800) - GenerateMenu() - playermanagement:Visible(true) - end - TriggerEvent("EasyAdmin:BuildCachedOptions", cachedplayer.id) - for i, plugin in pairs(plugins) do - if plugin.functions.cachedMenu then - PrintDebugMessage("Processing Plugin: "..plugin.name, 4) - local ran, errorMsg = pcall(plugin.functions.cachedMenu, cachedplayer.id ) - if not ran then - PrintDebugMessage("Error in plugin "..plugin.name..": \n"..errorMsg, 1) - end - end - end - thisPlayer:RefreshIndexRecursively() - end - end - - end - end - end - cachedListGenerated=true - CachedList:RefreshIndexRecursively() - end - end - - end - - - if DoesPlayerHavePermissionForCategory(-1, "server") then - if permissions["server.announce"] then - local thisItem = NativeUI.CreateItem(GetLocalisedText("announcement"), GetLocalisedText("announcementguide")) - servermanagement:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - local result = displayKeyboardInput("FMMC_KEY_TIP8", "", 128) - - if result then - TriggerServerEvent("EasyAdmin:Announce", result) - end - end - end - - if permissions["server.convars"] then - local thisItem = NativeUI.CreateItem(GetLocalisedText("setgametype"), GetLocalisedText("setgametypeguide")) - servermanagement:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - - local result = displayKeyboardInput("FMMC_KEY_TIP8", "", 32) - - if result then - TriggerServerEvent("EasyAdmin:SetGameType", result) - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("setmapname"), GetLocalisedText("setmapnameguide")) - servermanagement:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - local result = displayKeyboardInput("FMMC_KEY_TIP8", "", 32) - - if result then - TriggerServerEvent("EasyAdmin:SetMapName", result) - end - end - end - - if permissions["server.resources.start"] then - local thisItem = NativeUI.CreateItem(GetLocalisedText("startresourcebyname"), GetLocalisedText("startresourcebynameguide")) - servermanagement:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - local result = displayKeyboardInput("FMMC_KEY_TIP8", "", 32) - - if result then - TriggerServerEvent("EasyAdmin:StartResource", result) - end - end - end - - if permissions["server.resources.stop"] then - local thisItem = NativeUI.CreateItem(GetLocalisedText("stopresourcebyname"), GetLocalisedText("stopresourcebynameguide")) - servermanagement:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - local result = displayKeyboardInput("FMMC_KEY_TIP8", "", 32) - - if result then - if result ~= GetCurrentResourceName() then - TriggerServerEvent("EasyAdmin:StopResource", result) - else - TriggerEvent("EasyAdmin:showNotification", GetLocalisedText("badidea")) - end - end - end - end - - if permissions["server.convars"] then - local thisItem = NativeUI.CreateItem(GetLocalisedText("setconvar"), GetLocalisedText("setconvarguide")) - servermanagement:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - AddTextEntry("EA_SETCONVAR_1", GetLocalisedText("convarname")) - AddTextEntry("EA_SETCONVAR_2", GetLocalisedText("convarvalue")) - local result = displayKeyboardInput("EA_SETCONVAR_1", "", 64) - - if result then - local result2 = displayKeyboardInput("EA_SETCONVAR_2", "", 64) - - if result2 then - TriggerServerEvent("EasyAdmin:SetConvar", result, result2) - end - end - end - end - end - - if permissions["player.ban.view"] then - unbanPlayer = _menuPool:AddSubMenu(servermanagement,GetLocalisedText("viewbanlist"),"",true) - local thisMenuWidth = menuWidth - if menuWidth < 150 then - thisMenuWidth = 150 - else - thisMenuWidth = menuWidth - end - unbanPlayer:SetMenuWidthOffset(thisMenuWidth) - local reason = "" - local identifier = "" - - local function generateBanOverview(banId) - _menuPool:Remove() - TriggerEvent("EasyAdmin:MenuRemoved") - _menuPool = NativeUI.CreatePool() - collectgarbage() - if not GetResourceKvpString("ea_menuorientation") then - SetResourceKvp("ea_menuorientation", "middle") - SetResourceKvpInt("ea_menuwidth", 0) - menuWidth = 0 - menuOrientation = handleOrientation("middle") - else - menuWidth = GetResourceKvpInt("ea_menuwidth") - menuOrientation = handleOrientation(GetResourceKvpString("ea_menuorientation")) - end - - local mainMenu = NativeUI.CreateMenu("", "Ban Infos", menuOrientation, 0, "easyadmin", "banner-gradient", "logo") - _menuPool:Add(mainMenu) - - local thisMenuWidth = menuWidth - if menuWidth < 150 then - thisMenuWidth = 150 - else - thisMenuWidth = menuWidth - end - mainMenu:SetMenuWidthOffset(thisMenuWidth) - _menuPool:ControlDisablingEnabled(false) - _menuPool:MouseControlsEnabled(false) - - if banlist[banId].banid then - local thisItem = NativeUI.CreateItem("Ban ID: "..banlist[banId].banid, "") - mainMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - copyToClipboard(banlist[banId].banid) - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("reason"),banlist[banId].reason) - mainMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - --nothing - end - - - if banlist[banId].name then - local thisItem = NativeUI.CreateItem("Name: "..banlist[banId].name, "") - mainMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - if permissions["player.ban.edit"] then - local result = displayKeyboardInput("", banlist[banId].name, 64) - - if result then - banlist[banId].name = result - end - end - end - end - - if banlist[banId].banner then - local thisItem = NativeUI.CreateItem("Banner: "..banlist[banId].banner, "") - mainMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - if permissions["player.ban.edit"] then - local result = displayKeyboardInput("", banlist[banId].banner, 64) - - if result then - banlist[banId].banner = result - end - end - end - end - - - if banlist[banId].expireString then - local thisItem = NativeUI.CreateItem("Expires: "..banlist[banId].expireString, "") - mainMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - if permissions["player.ban.edit"] then - AddTextEntry("EA_ENTERTIME", "Enter Unix Timestamp") - local result = displayKeyboardInput("EA_ENTERTIME", banlist[banId].expire, 64) - - if result then - banlist[banId].expire = tonumber(result) - end - end - end - end - - for _, identifier in pairs(banlist[banId].identifiers) do - if not (GetConvar("ea_IpPrivacy", "true") == "true" and string.split(identifier, ":")[1] == "ip") then - local thisItem = NativeUI.CreateItem(string.format(GetLocalisedText("identifier"), string.split(identifier, ":")[1]),identifier) - mainMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - copyToClipboard(identifier) - end - end - end - - if permissions["player.ban.edit"] then - local thisItem = NativeUI.CreateItem(GetLocalisedText("savebanchanges"),GetLocalisedText("savebanguide")) - mainMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - TriggerServerEvent("EasyAdmin:editBan", banlist[banId]) - end - end - - if permissions["player.ban.remove"] then - local thisItem = NativeUI.CreateItem(GetLocalisedText("unbanplayer"), GetLocalisedText("unbanplayerguide")) - mainMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - TriggerServerEvent("EasyAdmin:unbanPlayer", banlist[banId].banid) - TriggerServerEvent("EasyAdmin:requestBanlist") - _menuPool:CloseAllMenus() - Citizen.Wait(800) - GenerateMenu() - unbanPlayer:Visible(true) - end - mainMenu:Visible(true) - end - end - - - local thisItem = NativeUI.CreateItem(GetLocalisedText("searchbans"), "") - unbanPlayer:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - local result = displayKeyboardInput("FMMC_KEY_TIP8", "", 128) - - local foundBan = false - if result then - for i,theBanned in ipairs(banlist) do - if foundBan then - break - end - if tostring(theBanned.banid) == result then - foundBan=true - foundBanid=i - break - end - end - if not foundBan then - for i,theBanned in ipairs(banlist) do - if theBanned.name then - if string.find(string.lower(theBanned.name), string.lower(result)) then - foundBan=true - foundBanid=i - break - end - end - if string.find((string.lower(theBanned.reason) or "No Reason"), string.lower(result)) then - foundBan=true - foundBanid=i - break - end - for _, identifier in pairs(theBanned.identifiers) do - if string.find(identifier, result) then - foundBan=true - foundBanid=i - break - end - end - end - end - end - _menuPool:CloseAllMenus() - Citizen.Wait(300) - if foundBan then - generateBanOverview(foundBanid) - else - TriggerEvent("EasyAdmin:showNotification", GetLocalisedText("searchbansfail")) - GenerateMenu() - unbanPlayer:Visible(true) - end - - end - - for i,theBanned in ipairs(banlist) do - if i<(banlistPage*10)+1 and i>(banlistPage*10)-10 then - if theBanned then - reason = theBanned.reason or "No Reason" - local thisItem = NativeUI.CreateItem(string.sub(reason, 1,50), "") - unbanPlayer:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - generateBanOverview(i) - end - end - end - end - - - if #banlist > (banlistPage*10) then - local thisItem = NativeUI.CreateItem(GetLocalisedText("lastpage"), "") - unbanPlayer:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - banlistPage = math.ceil(#banlist/10) - _menuPool:CloseAllMenus() - Citizen.Wait(300) - GenerateMenu() - unbanPlayer:Visible(true) - end - end - - if banlistPage>1 then - local thisItem = NativeUI.CreateItem(GetLocalisedText("firstpage"), "") - unbanPlayer:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - banlistPage = 1 - _menuPool:CloseAllMenus() - Citizen.Wait(300) - GenerateMenu() - unbanPlayer:Visible(true) - end - local thisItem = NativeUI.CreateItem(GetLocalisedText("previouspage"), "") - unbanPlayer:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - banlistPage=banlistPage-1 - _menuPool:CloseAllMenus() - Citizen.Wait(300) - GenerateMenu() - unbanPlayer:Visible(true) - end - end - if #banlist > (banlistPage*10) then - local thisItem = NativeUI.CreateItem(GetLocalisedText("nextpage"), "") - unbanPlayer:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - banlistPage=banlistPage+1 - _menuPool:CloseAllMenus() - Citizen.Wait(300) - GenerateMenu() - unbanPlayer:Visible(true) - end - end - end - - if DoesPlayerHavePermissionForCategory(-1, "server") then - - local sl = {} - if permissions["server.cleanup.cars"] then - table.insert(sl, GetLocalisedText('cars')) - end - if permissions["server.cleanup.peds"] then - table.insert(sl, GetLocalisedText('peds')) - end - if permissions["server.cleanup.props"] then - table.insert(sl, GetLocalisedText('props')) - end - - local radi = {10,20,50,100,"global"} - - if #sl > 0 and not RedM then - cleanType = sl[1] - cleanRadius = radi[1] - deepClean = true - - cleanupMenu = _menuPool:AddSubMenu(servermanagement, GetLocalisedText("cleanarea"), GetLocalisedText("cleanareaguide"),true) - - local thisItem = NativeUI.CreateListItem(GetLocalisedText("type"), sl, 1, GetLocalisedText("cleanareaguide")) - cleanupMenu:AddItem(thisItem) - thisItem.OnListChanged = function(sender, item, index) - if item == thisItem then - i = item:IndexToItem(index) - cleanType = i - end - end - - local thisItem = NativeUI.CreateListItem(GetLocalisedText("radius"), radi, 1, "") - cleanupMenu:AddItem(thisItem) - thisItem.OnListChanged = function(sender, item, index) - if item == thisItem then - i = item:IndexToItem(index) - cleanRadius = i - end - end - - local thisItem = NativeUI.CreateCheckboxItem(GetLocalisedText("deepclean"), deepClean, GetLocalisedText("deepcleanguide")) - cleanupMenu:AddItem(thisItem) - thisItem.CheckboxEvent = function(sender, item, checked_) - deepClean = checked_ - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("cleanarea"), GetLocalisedText("cleanareaguide")) - cleanupMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - if cleanType == GetLocalisedText('cars') then - cleanType = "cars" - elseif cleanType == GetLocalisedText('peds') then - cleanType = "peds" - elseif cleanType == GetLocalisedText('props') then - cleanType = "props" - end - TriggerServerEvent("EasyAdmin:requestCleanup", cleanType, cleanRadius, deepClean) - end - end - - if permissions["server.permissions.read"] then - permissionEditor = _menuPool:AddSubMenu(servermanagement, GetLocalisedText("permissioneditor"),GetLocalisedText("permissioneditorguide"),true) - local thisMenuWidth = menuWidth - if menuWidth < 150 then - thisMenuWidth = 150 - else - thisMenuWidth = menuWidth - end - permissionEditor:SetMenuWidthOffset(thisMenuWidth) - - editAces = _menuPool:AddSubMenu(permissionEditor, GetLocalisedText("aces"),"",true) - editAces:SetMenuWidthOffset(thisMenuWidth) - - - if permissions["server.permissions.read"] and permissions["server.permissions.write"] then - local thisMenu = _menuPool:AddSubMenu(editAces, GetLocalisedText("addace"), "", true) - thisMenu:SetMenuWidthOffset(thisMenuWidth) - local tempAce = {} - local thisItem = NativeUI.CreateItem(GetLocalisedText("group"), "") - thisItem:RightLabel(tempAce[1] or "") - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - AddTextEntry("ENTERGROUP", GetLocalisedText("entergroup")) - local result = displayKeyboardInput("ENTERGROUP", "group.", 64) - - if result and result ~= "" then - tempAce[1] = result - thisItem:RightLabel(formatRightString(result)) - thisMenu.ParentItem.Text._Text = result - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("permission"), "") - thisItem:RightLabel(formatRightString(tempAce[2])) - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - AddTextEntry("ENTERPERM", GetLocalisedText("enterperm")) - local result = displayKeyboardInput("ENTERPERM", "", 64) - - if result and result ~= "" then - tempAce[2] = result - thisItem:RightLabel(formatRightString(result)) - thisMenu.ParentItem:RightLabel(formatRightString(result)) - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("state"), GetLocalisedText("stateguide")) - thisItem:RightLabel("allow") - tempAce[3] = "allow" - thisMenu:AddItem(thisItem) - thisItem:Enabled(false) - - local thisItem = NativeUI.CreateItem(GetLocalisedText("addace"), GetLocalisedText("addaceguide")) - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - table.insert(add_aces, tempAce) - _menuPool:CloseAllMenus() - Citizen.Wait(800) - GenerateMenu() - editAces:Visible(true) - collectgarbage() - end - end - - for i, ace in pairs(add_aces) do - local thisMenu = _menuPool:AddSubMenu(editAces, ace[1].." "..ace[2], "", true) - thisMenu:SetMenuWidthOffset(thisMenuWidth) - thisMenu.ParentItem:RightLabel(ace[3]) - - local thisItem = NativeUI.CreateItem(GetLocalisedText("group"), "") - thisItem:RightLabel(formatRightString(ace[1])) - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - AddTextEntry("ENTERGROUP", GetLocalisedText("entergroup")) - local result = displayKeyboardInput("ENTERGROUP", ace[1], 64) - - if result and result ~= "" then - add_aces[i][1] = result - thisItem:RightLabel(formatRightString(result)) - thisMenu.ParentItem.Text._Text = add_aces[i][1].." "..add_aces[i][2] - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("permission"), "") - thisItem:RightLabel(formatRightString(ace[2])) - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - AddTextEntry("ENTERPERM", GetLocalisedText("enterperm")) - local result = displayKeyboardInput("ENTERPERM", ace[2], 64) - - if result and result ~= "" then - add_aces[i][2] = result - thisItem:RightLabel(formatRightString(result)) - thisMenu.ParentItem.Text._Text = add_aces[i][1].." "..add_aces[i][2] - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("state"), GetLocalisedText("stateguide")) - thisItem:RightLabel(formatRightString(ace[3])) - thisMenu:AddItem(thisItem) - thisItem:Enabled(false) - - if (ace.file) then - local thisItem = NativeUI.CreateItem(GetLocalisedText("location"), GetLocalisedText("locationguide")) - thisItem:RightLabel(formatRightString(ace.file)) - thisMenu:AddItem(thisItem) - thisItem:Enabled(false) - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("deletepermission"), GetLocalisedText("deletepermissionguide")) - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - thisMenu.ParentItem:Enabled(false) - thisMenu.ParentItem._Description = GetLocalisedText("itemdeleted") - add_aces[i] = nil - thisMenu:GoBack() - end - end - - - editPrincipals = _menuPool:AddSubMenu(permissionEditor, GetLocalisedText("principals"),"",true) - editPrincipals:SetMenuWidthOffset(thisMenuWidth) - - if permissions["server.permissions.read"] and permissions["server.permissions.write"] then - local thisMenu = _menuPool:AddSubMenu(editPrincipals, GetLocalisedText("addprincipal"), "", true) - thisMenu:SetMenuWidthOffset(thisMenuWidth) - local tempPrincipal = {} - local thisItem = NativeUI.CreateItem(GetLocalisedText("principal"), "") - thisItem:RightLabel(tempPrincipal[1] or "") - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - AddTextEntry("ENTERPRINCIPAL", GetLocalisedText("enterprincipal")) - local result = displayKeyboardInput("ENTERPRINCIPAL", "identifier.", 64) - - if result and result ~= "" then - tempPrincipal[1] = result - thisItem:RightLabel(formatRightString(result)) - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("group"), "") - thisItem:RightLabel(tempPrincipal[2] or "") - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - AddTextEntry("ENTERGROUP", GetLocalisedText("entergroup")) - local result = displayKeyboardInput("ENTERGROUP", "group.", 64) - - if result and result ~= "" then - tempPrincipal[2] = result - thisItem:RightLabel(formatRightString(result)) - thisMenu.ParentItem:RightLabel(formatRightString(result)) - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("addprincipal"), GetLocalisedText("addaceguide")) -- the use of addaceguide is intentional. - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - table.insert(add_principals, tempPrincipal) - _menuPool:CloseAllMenus() - Citizen.Wait(800) - GenerateMenu() - editPrincipals:Visible(true) - collectgarbage() - end - end - - for i, principal in pairs(add_principals) do - - local thisMenu = _menuPool:AddSubMenu(editPrincipals, principal[1], "", true) - thisMenu:SetMenuWidthOffset(thisMenuWidth) - thisMenu.ParentItem:RightLabel(principal[2]) - - local thisItem = NativeUI.CreateItem(GetLocalisedText("principal"), "") - thisItem:RightLabel(formatRightString(principal[1])) - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - AddTextEntry("ENTERPRINCIPAL", GetLocalisedText("enterprincipal")) - local result = displayKeyboardInput("ENTERPRINCIPAL", principal[1], 64) - - if result and result ~= "" then - add_principals[i][1] = result - thisItem:RightLabel(formatRightString(result)) - thisMenu.ParentItem.Text._Text = add_principals[i][1] - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("group"), "") - thisItem:RightLabel(formatRightString(principal[2])) - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - AddTextEntry("ENTERGROUP", GetLocalisedText("entergroup")) - local result = displayKeyboardInput("ENTERGROUP", principal[2], 64) - - if result and result ~= "" then - add_principals[i][2] = result - thisItem:RightLabel(formatRightString(result)) - thisMenu.ParentItem:RightLabel(formatRightString(result)) - end - end - - if (principal.file) then - local thisItem = NativeUI.CreateItem(GetLocalisedText("location"), GetLocalisedText("locationguide")) - thisItem:RightLabel(formatRightString(principal.file)) - thisMenu:AddItem(thisItem) - thisItem:Enabled(false) - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("deleteprincipal"), GetLocalisedText("deleteprincipalguide")) - thisMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - thisMenu.ParentItem:Enabled(false) - thisMenu.ParentItem._Description = GetLocalisedText("itemdeleted") - add_principals[i] = nil - thisMenu:GoBack() - end - - end - end - if permissions["server.permissions.read"] then - local thisItem = NativeUI.CreateItem(GetLocalisedText("refreshpermissions"), "") - permissionEditor:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - add_aces, add_principals = nil, nil - TriggerServerEvent("EasyAdmin:getServerAces") - _menuPool:CloseAllMenus() - repeat - Wait(500) - until add_aces - GenerateMenu() - permissionEditor:Visible(true) - collectgarbage() - end - end - - if permissions["server.permissions.read"] and permissions["server.permissions.write"] then - local thisItem = NativeUI.CreateItem(GetLocalisedText("savechanges"), GetLocalisedText("savechangesguide")) - permissionEditor:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - TriggerLatentServerEvent("EasyAdmin:setServerAces", 200000, add_aces, add_principals) - _menuPool:CloseAllMenus() - Citizen.Wait(800) - GenerateMenu() - permissionEditor:Visible(true) - collectgarbage() - end - end - - - TriggerEvent("EasyAdmin:BuildServerManagementOptions") - for i, plugin in pairs(plugins) do - if plugin.functions.serverMenu then - PrintDebugMessage("Processing Plugin: "..plugin.name, 4) - local ran, errorMsg = pcall(plugin.functions.serverMenu) - if not ran then - PrintDebugMessage("Error in plugin "..plugin.name..": \n"..errorMsg, 1) - end - end - end - end - - if permissions["player.ban.view"] then - local sl = {GetLocalisedText("unbanreasons"), GetLocalisedText("unbanlicenses")} - local thisItem = NativeUI.CreateListItem(GetLocalisedText("banlistshowtype"), sl, 1,GetLocalisedText("banlistshowtypeguide")) - settingsMenu:AddItem(thisItem) - thisItem.OnListSelected = function(sender, item, index) - if item == thisItem then - i = item:IndexToItem(index) - if i == GetLocalisedText(unbanreasons) then - showLicenses = false - else - showLicenses = true - end - end - end - end - - if permissions["player.ban.view"] then - local thisItem = NativeUI.CreateItem(GetLocalisedText("refreshbanlist"), GetLocalisedText("refreshbanlistguide")) - settingsMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - banlist=nil - TriggerServerEvent("EasyAdmin:updateBanlist") - repeat - Wait(500) - until banlist - GenerateMenu() - settingsMenu:Visible(true) - collectgarbage() - end - end - - if permissions["player.ban.temporary"] or permissions["player.ban.permanent"] then - local thisItem = NativeUI.CreateItem(GetLocalisedText("refreshcachedplayers"), GetLocalisedText("refreshcachedplayersguide")) - settingsMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - cachedplayers=nil - TriggerServerEvent("EasyAdmin:requestCachedPlayers") - repeat - Wait(500) - until cachedplayers - GenerateMenu() - settingsMenu:Visible(true) - collectgarbage() - end - end - - local thisItem = NativeUI.CreateItem(GetLocalisedText("refreshpermissions"), GetLocalisedText("refreshpermissionsguide")) - settingsMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - TriggerServerEvent("EasyAdmin:amiadmin") - end - - local orientationIndex = 1 - if GetResourceKvpString("ea_menuorientation") == "middle" then - orientationIndex = 2 - elseif GetResourceKvpString("ea_menuorientation") == "right" then - orientationIndex = 3 - end - - local sl = {GetLocalisedText("left"), GetLocalisedText("middle"), GetLocalisedText("right")} - local thisItem = NativeUI.CreateListItem(GetLocalisedText("menuOrientation"), sl, orientationIndex, GetLocalisedText("menuOrientationguide")) - settingsMenu:AddItem(thisItem) - thisItem.OnListSelected = function(sender, item, index) - if item == thisItem then - i = item:IndexToItem(index) - if i == GetLocalisedText("left") then - SetResourceKvp("ea_menuorientation", "left") - elseif i == GetLocalisedText("middle") then - SetResourceKvp("ea_menuorientation", "middle") - else - SetResourceKvp("ea_menuorientation", "right") - end - end - end - - local sl = {} - for i=0,250,10 do - table.insert(sl,i) - end - local thisi = 0 - for i,a in ipairs(sl) do - if menuWidth == a then - thisi = i - end - end - local thisItem = NativeUI.CreateSliderItem(GetLocalisedText("menuOffset"), sl, thisi, GetLocalisedText("menuOffsetguide"), false) - settingsMenu:AddItem(thisItem) - thisItem.OnSliderSelected = function(index) - i = thisItem:IndexToItem(index) - SetResourceKvpInt("ea_menuwidth", i) - menuWidth = i - end - thisi = nil - sl = nil - - local thisItem = NativeUI.CreateItem(GetLocalisedText("resetmenuOffset"), "") - settingsMenu:AddItem(thisItem) - thisItem.Activated = function(ParentMenu,SelectedItem) - SetResourceKvpInt("ea_menuwidth", 0) - menuWidth = 0 - end - - if permissions["anon"] then - local thisItem = NativeUI.CreateCheckboxItem(GetLocalisedText("anonymous"), anonymous or false, GetLocalisedText("anonymousguide")) - settingsMenu:AddItem(thisItem) - thisItem.CheckboxEvent = function(sender, item, checked_) - anonymous = checked_ - TriggerServerEvent("EasyAdmin:SetAnonymous", checked_) - end - end - - local thisItem = NativeUI.CreateCheckboxItem(GetLocalisedText("screenreader"), GetResourceKvpInt('ea_tts') == 1 and true or false, GetLocalisedText("screenreaderguide")) - settingsMenu:AddItem(thisItem) - thisItem.CheckboxEvent = function(sender, item, checked_) - SendNUIMessage({ - action = "toggle_speak", - enabled = checked_ - }) - SetResourceKvpInt("ea_tts", checked_ and 1 or 0) - SendNUIMessage({action= "speak", text="Text to Speech"}) - end - - if not RedM then - local sl = {"none"} - local currentEggIndex = 1 - for k,v in pairs(eastereggs) do - table.insert(sl, k) - end - for k,v in pairs(sl) do - if v == overrideEgg or v == currentEgg then - currentEggIndex = k - end - end - - local thisItem = NativeUI.CreateListItem(GetLocalisedText("forceeasteregg"), sl, currentEggIndex, "") - settingsMenu:AddItem(thisItem) - thisItem.OnListSelected = function(sender, item, index) - if item == thisItem then - i = item:IndexToItem(index) - if i == "none" then - overrideEgg = false - else - overrideEgg = i - end - end - end - end - - TriggerEvent("EasyAdmin:BuildSettingsOptions") - for i, plugin in pairs(plugins) do - if plugin.functions.settingsMenu then - PrintDebugMessage("Processing Plugin: "..plugin.name, 4) - local ran, errorMsg = pcall(plugin.functions.settingsMenu) - if not ran then - PrintDebugMessage("Error in plugin "..plugin.name..": \n"..errorMsg, 1) - end - end - end - _menuPool:ControlDisablingEnabled(false) - _menuPool:MouseControlsEnabled(false) - _menuPool:RefreshIndex() -- refresh indexes -end - - -Citizen.CreateThread( function() - while true do - Citizen.Wait(0) - if drawInfo then - local text = {} - -- cheat checks - local targetPed = GetPlayerPed(drawTarget) - if (not RedM) then - local targetGod = GetPlayerInvincible(drawTarget) - if targetGod then - table.insert(text,GetLocalisedText("godmodedetected")) - else - table.insert(text,GetLocalisedText("godmodenotdetected")) - end - if not CanPedRagdoll(targetPed) and not IsPedInAnyVehicle(targetPed, false) and (GetPedParachuteState(targetPed) == -1 or GetPedParachuteState(targetPed) == 0) and not IsPedInParachuteFreeFall(targetPed) then - table.insert(text,GetLocalisedText("antiragdoll")) - end - -- health info - table.insert(text,GetLocalisedText("health")..": "..GetEntityHealth(targetPed).."/"..GetEntityMaxHealth(targetPed)) - - table.insert(text,GetLocalisedText("armor")..": "..GetPedArmour(targetPed)) - - -- misc info - table.insert(text,GetLocalisedText("wantedlevel")..": "..GetPlayerWantedLevel(drawTarget)) - table.insert(text,GetLocalisedText("exitspectator")) - - for i,theText in pairs(text) do - SetTextFont(0) - SetTextProportional(1) - SetTextScale(0.0, 0.30) - SetTextDropshadow(0, 0, 0, 0, 255) - SetTextEdge(1, 0, 0, 0, 255) - SetTextDropShadow() - SetTextOutline() - SetTextEntry("STRING") - AddTextComponentString(theText) - EndTextCommandDisplayText(0.3, 0.7+(i/30)) - end - elseif (RedM) then - local targetGod = GetPlayerInvincible(drawTarget) - if targetGod then - table.insert(text,GetLocalisedText("godmodedetected")) - else - table.insert(text,GetLocalisedText("godmodenotdetected")) - end - - table.insert(text,GetLocalisedText("health")..": "..GetEntityHealth(targetPed).."/"..GetEntityMaxHealth(targetPed)) - table.insert(text,GetLocalisedText("exitspectator")) - - for i,theText in pairs(text) do - Citizen.InvokeNative(0xADA9255D,0) - SetTextScale(0.0, 0.30) - SetTextDropshadow(0, 0, 0, 0, 255) - - local str = CreateVarString(10, "LITERAL_STRING",Text) - DisplayText(theText, 0.3, 0.7+(i/30)) - end - end - - if (not RedM and IsControlJustPressed(0,103) or (RedM and IsControlJustReleased(0, Controls["Enter"]))) then - local targetPed = PlayerPedId() - local targetPlayer = -1 - local targetx,targety,targetz = table.unpack(GetEntityCoords(targetPed, false)) - spectatePlayer(targetPed,targetPlayer,GetPlayerName(targetPlayer)) - TriggerEvent('EasyAdmin:FreezePlayer', false) - --SetEntityCoords(PlayerPedId(), oldCoords.x, oldCoords.y, oldCoords.z, 0, 0, 0, false) - if not RedM then - TriggerEvent('EasyAdmin:FreezePlayer', false) - end - - StopDrawPlayerInfo() - TriggerEvent("EasyAdmin:showNotification", GetLocalisedText("stoppedSpectating")) - end - else - Citizen.Wait(1000) - end - end -end) diff --git a/server-data/resources/[esx]/EasyAdmin/client/plugins.lua b/server-data/resources/[esx]/EasyAdmin/client/plugins.lua deleted file mode 100644 index 35837315c..000000000 --- a/server-data/resources/[esx]/EasyAdmin/client/plugins.lua +++ /dev/null @@ -1,10 +0,0 @@ -plugins = {} - -function addPlugin(data) - table.insert(plugins, data) - -- sort plugins table by name (alphabetically) - table.sort(plugins, function(a, b) return a.name < b.name end) - - TriggerEvent('EasyAdmin:pluginAdded', data.name) - PrintDebugMessage("Added Plugin "..data.name, 4) -end \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/Controls.lua b/server-data/resources/[esx]/EasyAdmin/dependencies/Controls.lua deleted file mode 100644 index 4505864ae..000000000 --- a/server-data/resources/[esx]/EasyAdmin/dependencies/Controls.lua +++ /dev/null @@ -1,776 +0,0 @@ --- RedM Only - -Controls = {} -Controls["NextCamera"] = 0x7F8D09B8 -Controls["LookLr"] = 0xA987235F -Controls["LookUd"] = 0xD2047988 -Controls["LookUpOnly"] = 0xC0651D40 -Controls["LookDownOnly"] = 0x8ED92E16 -Controls["LookLeftOnly"] = 0x08F8BC6D -Controls["LookRightOnly"] = 0xA1EB1353 -Controls["CinematicSlowmo"] = 0x7A9093DE -Controls["RadialMenuNavUd"] = 0xBA60039F -Controls["RadialMenuNavLr"] = 0x390948DC -Controls["RadialMenuSlotNavNext"] = 0xE71F89B8 -Controls["RadialMenuSlotNavPrev"] = 0x93D6723F -Controls["SelectNextWheel"] = 0x77E56FB3 -Controls["SelectItemWheel"] = 0x1F6D95E5 -Controls["QuickSelectInspect"] = 0xF09866F3 -Controls["QuickSelectSetForSwap"] = 0xD45EC04F -Controls["QuickShortcutAbilitiesMenu"] = 0x9CC7A1A4 -Controls["QuickSelectSecondaryNavNext"] = 0xF1421CF5 -Controls["QuickSelectSecondaryNavPrev"] = 0xD9F9F017 -Controls["QuickSelectToggleShortcutItem"] = 0xFA0B29CD -Controls["QuickSelectPutAwayRod"] = 0x253FEC09 -Controls["EmotesFavorite"] = 0xA835261B -Controls["EmotesManage"] = 0x7E75F4DC -Controls["EmotesSlotNavNext"] = 0xCBB12F87 -Controls["SelectNextWeapon"] = 0xD0842EDF -Controls["SelectPrevWeapon"] = 0xF78D7337 -Controls["SkipCutscene"] = 0xCDC4E4E9 -Controls["CharacterWheel"] = 0x972F8D1E -Controls["MultiplayerInfo"] = 0xE8342FF2 -Controls["Sprint"] = 0x8FFC75D6 -Controls["Jump"] = 0xD9D0E1C0 -Controls["Enter"] = 0xCEFD9220 -Controls["Attack"] = 0x07CE1E61 -Controls["Aim"] = 0xF84FA74F -Controls["LookBehind"] = 0x9959A6F0 -Controls["Phone"] = 0x4CF871D0 -Controls["SpecialAbility"] = 0xCEE12B50 -Controls["SpecialAbilitySecondary"] = 0x6328239B -Controls["SecondarySpecialAbilitySecondary"] = 0x811F4A1A -Controls["SpecialAbilityAction"] = 0x1ECA87D4 -Controls["MoveLr"] = 0x4D8FB4C1 -Controls["MoveUd"] = 0xFDA83190 -Controls["MoveUpOnly"] = 0x8FD015D8 -Controls["MoveDownOnly"] = 0xD27782E3 -Controls["MoveLeftOnly"] = 0x7065027D -Controls["MoveRightOnly"] = 0xB4E465B4 -Controls["Duck"] = 0xDB096B85 -Controls["TwirlPistol"] = 0x938D4071 -Controls["ToggleHolster"] = 0xB238FE0B -Controls["OpenWheelMenu"] = 0xAC4BD4F1 -Controls["OpenSatchelMenu"] = 0x4CC0E2FE -Controls["OpenSatchelHorseMenu"] = 0x5966D52A -Controls["OpenCraftingMenu"] = 0x734C6E39 -Controls["OpenJournal"] = 0xF3830D8E -Controls["Pickup"] = 0xE6360A8E -Controls["Ignite"] = 0xC75C27B0 -Controls["SniperZoom"] = 0x7ABC6A66 -Controls["SniperZoomInOnly"] = 0xA5BDCD3C -Controls["SniperZoomOutOnly"] = 0x430593AA -Controls["SniperZoomInSecondary"] = 0x6BE9C207 -Controls["SniperZoomOutSecondary"] = 0x8A7B8833 -Controls["ToggleWeaponScope"] = 0x3076E97C -Controls["Cover"] = 0xDE794E3E -Controls["CoverTransition"] = 0x750C8010 -Controls["Reload"] = 0xE30CD707 -Controls["Talk"] = 0x7DCA9C75 -Controls["Detonate"] = 0x73846677 -Controls["HudSpecial"] = 0x580C4473 -Controls["Arrest"] = 0xA4F1006B -Controls["AccurateAim"] = 0x406ADFAE -Controls["SwitchShoulder"] = 0x827E9EE8 -Controls["IronSight"] = 0x841240A9 -Controls["AimInAir"] = 0xD8F73058 -Controls["SwitchFiringMode"] = 0xEED15F18 -Controls["Context"] = 0xB73BCA77 -Controls["ContextSecondary"] = 0xF19BE385 -Controls["WeaponSpecial"] = 0x733901F3 -Controls["WeaponSpecialTwo"] = 0x50BA1A77 -Controls["Dive"] = 0x06052D11 -Controls["DropWeapon"] = 0x7DBCD016 -Controls["DropAmmo"] = 0x4E42696E -Controls["ThrowGrenade"] = 0x0AF99998 -Controls["FocusCam"] = 0xE72B43F4 -Controls["Inspect"] = 0xA61DC630 -Controls["InspectZoom"] = 0x53296B75 -Controls["InspectLr"] = 0x1788C283 -Controls["InspectUd"] = 0xF9781997 -Controls["InspectOpenSatchel"] = 0x9B1CA8DA -Controls["DynamicScenario"] = 0x2EAB0795 -Controls["PlayerMenu"] = 0x80F28E95 -Controls["OpenEmoteWheel"] = 0xE2B557A3 -Controls["OpenEmoteWheelHorse"] = 0x8B3FA65E -Controls["EmoteGroupLink"] = 0x1C826362 -Controls["EmoteGroupLinkHorse"] = 0x4FD1C57B -Controls["RevealHud"] = 0xCF8A4ECA -Controls["SelectRadarMode"] = 0x0F39B3D4 -Controls["SimpleRadar"] = 0x5FEF1B6D -Controls["ExpandRadar"] = 0xCF0B11DE -Controls["RegularRadar"] = 0x51AA7A35 -Controls["DisableRadar"] = 0x70CBD78D -Controls["Surrender"] = 0xDB8D69B8 -Controls["Whistle"] = 0x24978A28 -Controls["WhistleHorseback"] = 0xE7EB9185 -Controls["StopLeadingAnimal"] = 0x7914A3DD -Controls["CinematicCam"] = 0x620A6C5E -Controls["CinematicCamHold"] = 0xD7E7B375 -Controls["CinematicCamChangeShot"] = 0xA6C67243 -Controls["CinematicCamUd"] = 0x84574AE8 -Controls["CinematicCamUpOnly"] = 0xEFCFE6B7 -Controls["CinematicCamDownOnly"] = 0x23AE34A2 -Controls["CinematicCamLr"] = 0x6BC904FC -Controls["ContextA"] = 0x5181713D -Controls["ContextB"] = 0x3B24C470 -Controls["ContextX"] = 0xE3BF959B -Controls["ContextY"] = 0xD51B784F -Controls["ContextLt"] = 0xC13A6564 -Controls["ContextRt"] = 0x07B8BEAF -Controls["ContextAction"] = 0xB28318C0 -Controls["VehMoveLr"] = 0xF1E2852C -Controls["VehMoveUd"] = 0x8A81C00C -Controls["VehMoveUpOnly"] = 0xDEBD7EF6 -Controls["VehMoveDownOnly"] = 0x16D73E1D -Controls["VehMoveLeftOnly"] = 0x9DF54706 -Controls["VehMoveRightOnly"] = 0x97A8FD98 -Controls["VehSpecial"] = 0x493919DB -Controls["VehGunLr"] = 0xB6F3E4FE -Controls["VehGunUd"] = 0x482560EE -Controls["VehAim"] = 0xD7CAFCEF -Controls["VehAttack"] = 0xF4330038 -Controls["VehAttack2"] = 0xF1C341BA -Controls["VehAccelerate"] = 0x5B9FD4E2 -Controls["VehBrake"] = 0x6E1F639B -Controls["VehDuck"] = 0x5B3690F2 -Controls["VehHeadlight"] = 0xF1301666 -Controls["VehExit"] = 0xFEFAB9B4 -Controls["VehHandbrake"] = 0x65D24C98 -Controls["VehLookBehind"] = 0xCAE9B017 -Controls["VehNextRadio"] = 0x22E0F7E7 -Controls["VehPrevRadio"] = 0x9785CE13 -Controls["VehNextRadioTrack"] = 0xF7FA2DDC -Controls["VehPrevRadioTrack"] = 0x0A94C4FF -Controls["VehRadioWheel"] = 0x4915AC0A -Controls["VehHorn"] = 0x63A0D258 -Controls["VehFlyThrottleUp"] = 0x7232BAB3 -Controls["VehFlyThrottleDown"] = 0x084DFF95 -Controls["VehFlyYawLeft"] = 0x31589AD1 -Controls["VehFlyYawRight"] = 0xBD143FC6 -Controls["VehPassengerAim"] = 0xEE2804D0 -Controls["VehPassengerAttack"] = 0x27AD4433 -Controls["VehSpecialAbilityFranklin"] = 0x5EC33578 -Controls["VehStuntUd"] = 0x4AA1560E -Controls["VehSelectNextWeapon"] = 0x889A626F -Controls["VehSelectPrevWeapon"] = 0x0C97BAC7 -Controls["VehRoof"] = 0x3E7CF9A4 -Controls["VehJump"] = 0xAA56B926 -Controls["VehGrapplingHook"] = 0xB985AA5E -Controls["VehShuffle"] = 0xC7083798 -Controls["VehTraversal"] = 0x739D6261 -Controls["VehDropProjectile"] = 0xC61611E6 -Controls["VehMouseControlOverride"] = 0x39CCABD5 -Controls["VehFlyRollLr"] = 0x3C8AB570 -Controls["VehFlyRollLeftOnly"] = 0x56F84EA0 -Controls["VehFlyRollRightOnly"] = 0x876B3361 -Controls["VehFlyPitchUd"] = 0xE67E1E57 -Controls["VehFlyPitchUpOnly"] = 0x6280BA1A -Controls["VehFlyPitchDownOnly"] = 0x0F4E369F -Controls["VehFlyUndercarriage"] = 0xFE0FE518 -Controls["VehFlyAttack"] = 0x1D71D7AA -Controls["VehFlySelectNextWeapon"] = 0x24E94299 -Controls["VehFlySelectPrevWeapon"] = 0xC0D874E5 -Controls["VehFlySelectTargetLeft"] = 0x307FC4C1 -Controls["VehFlySelectTargetRight"] = 0x52F25C96 -Controls["VehFlyVerticalFlightMode"] = 0xE3238029 -Controls["VehFlyDuck"] = 0x378A10F7 -Controls["VehFlyAttackCamera"] = 0x2FBA3F0B -Controls["VehFlyMouseControlOverride"] = 0x6C9810A5 -Controls["VehSubMouseControlOverride"] = 0x2CAF327E -Controls["VehSubTurnLr"] = 0x627C4619 -Controls["VehSubTurnLeftOnly"] = 0x44E7E093 -Controls["VehSubTurnRightOnly"] = 0xE78A5A3C -Controls["VehSubPitchUd"] = 0x469CE271 -Controls["VehSubPitchUpOnly"] = 0xF9EF072A -Controls["VehSubPitchDownOnly"] = 0xBA2D22AA -Controls["VehSubThrottleUp"] = 0xD28C446F -Controls["VehSubThrottleDown"] = 0xF5B2CEFB -Controls["VehSubAscend"] = 0xD7991F74 -Controls["VehSubDescend"] = 0x7D51DE24 -Controls["VehSubTurnHardLeft"] = 0x64214D49 -Controls["VehSubTurnHardRight"] = 0xA44C0F83 -Controls["VehPushbikePedal"] = 0xFD8D64A7 -Controls["VehPushbikeSprint"] = 0xF03EE151 -Controls["VehPushbikeFrontBrake"] = 0x585E942D -Controls["VehPushbikeRearBrake"] = 0xF8CBAFB5 -Controls["VehDraftMoveUd"] = 0x23595CEA -Controls["VehDraftTurnLr"] = 0xA7DFAE8A -Controls["VehDraftMoveUpOnly"] = 0x29A5E51E -Controls["VehDraftMoveDownOnly"] = 0x25493EB3 -Controls["VehDraftTurnLeftOnly"] = 0x198AFC64 -Controls["VehDraftTurnRightOnly"] = 0x5E371EA7 -Controls["VehDraftAccelerate"] = 0xE99D2B05 -Controls["VehDraftBrake"] = 0xD648E48D -Controls["VehDraftAim"] = 0xBDD5830D -Controls["VehDraftAttack"] = 0xF40AB198 -Controls["VehDraftAttack2"] = 0x886F12DD -Controls["VehDraftSwitchDrivers"] = 0x70B87844 -Controls["VehBoatTurnLr"] = 0xD8DFCAB3 -Controls["VehBoatTurnLeftOnly"] = 0x5BED7C91 -Controls["VehBoatTurnRightOnly"] = 0xF9780DFB -Controls["VehBoatAccelerate"] = 0xB341E812 -Controls["VehBoatBrake"] = 0x428D5F39 -Controls["VehBoatAim"] = 0x92F5F01E -Controls["VehBoatAttack"] = 0x6866FA3A -Controls["VehBoatAttack2"] = 0x876096E9 -Controls["VehCarTurnLr"] = 0x3BD38D43 -Controls["VehCarTurnLeftOnly"] = 0x07D1654C -Controls["VehCarTurnRightOnly"] = 0x6E3C3649 -Controls["VehCarAccelerate"] = 0xB9F544B0 -Controls["VehCarBrake"] = 0xD1887B3F -Controls["VehCarAim"] = 0x6777B840 -Controls["VehCarAttack"] = 0x5572F386 -Controls["VehCarAttack2"] = 0x5B763AD7 -Controls["VehHandcartAccelerate"] = 0xFF3626FC -Controls["VehHandcartBrake"] = 0x2D79D80A -Controls["HorseMoveLr"] = 0x126796EB -Controls["HorseMoveUd"] = 0x3BBDEFEF -Controls["HorseMoveUpOnly"] = 0x699487BB -Controls["HorseMoveDownOnly"] = 0x56F82045 -Controls["HorseMoveLeftOnly"] = 0x86D773F6 -Controls["HorseMoveRightOnly"] = 0x7E6B8612 -Controls["HorseSpecial"] = 0x70089459 -Controls["HorseGunLr"] = 0x3D99EEC6 -Controls["HorseGunUd"] = 0xBFF476F9 -Controls["HorseAttack"] = 0x60C81CDE -Controls["HorseAttack2"] = 0xC904196D -Controls["HorseSprint"] = 0x5AA007D7 -Controls["HorseStop"] = 0xE16B9AAD -Controls["HorseExit"] = 0xCBDB82A8 -Controls["HorseLookBehind"] = 0x81280569 -Controls["HorseJump"] = 0xE4D2CE1D -Controls["HorseAim"] = 0x61470051 -Controls["HorseCollect"] = 0x7D5B3717 -Controls["HitchAnimal"] = 0xA95E1468 -Controls["HorseCommandFlee"] = 0x4216AF06 -Controls["HorseCommandStay"] = 0xAE5DFDED -Controls["HorseCommandFollow"] = 0x763E4D27 -Controls["HorseMelee"] = 0x1A3EABBB -Controls["MeleeHorseAttackPrimary"] = 0x78ED2132 -Controls["MeleeHorseAttackSecondary"] = 0x162AFEB8 -Controls["HorseCoverTransition"] = 0x2996DD15 -Controls["MeleeAttack"] = 0xB2F377E8 -Controls["MeleeModifier"] = 0x1E7D7275 -Controls["MeleeBlock"] = 0xB5EEEFB7 -Controls["MeleeGrapple"] = 0x2277FAE9 -Controls["MeleeGrappleAttack"] = 0xADEAF48C -Controls["MeleeGrappleChoke"] = 0x018C47CF -Controls["MeleeGrappleReversal"] = 0x91C9A817 -Controls["MeleeGrappleBreakout"] = 0xD0C1FEFF -Controls["MeleeGrappleStandSwitch"] = 0xBE1F4699 -Controls["MeleeGrappleMountSwitch"] = 0x67ED272E -Controls["ParachuteDeploy"] = 0xEBF53058 -Controls["ParachuteDetach"] = 0xFFBFF139 -Controls["ParachuteTurnLr"] = 0x8EC920BF -Controls["ParachuteTurnLeftOnly"] = 0xC4CF3322 -Controls["ParachuteTurnRightOnly"] = 0x2BDBA378 -Controls["ParachutePitchUd"] = 0xF0526228 -Controls["ParachutePitchUpOnly"] = 0x08BFEA69 -Controls["ParachutePitchDownOnly"] = 0x7C3A4352 -Controls["ParachuteBrakeLeft"] = 0x272BD8BA -Controls["ParachuteBrakeRight"] = 0x948B3EA7 -Controls["ParachuteSmoke"] = 0x2574FAB0 -Controls["ParachutePrecisionLanding"] = 0xC675B8BD -Controls["Map"] = 0xE31C6A41 -Controls["SelectWeaponUnarmed"] = 0x1F6EEB0F -Controls["SelectWeaponMelee"] = 0x109E6852 -Controls["SelectWeaponHandgun"] = 0x184960E3 -Controls["SelectWeaponShotgun"] = 0x76D3EA05 -Controls["SelectWeaponSmg"] = 0xCEF1BB48 -Controls["SelectWeaponAutoRifle"] = 0x05EEA9D0 -Controls["SelectWeaponSniper"] = 0x96C61FDF -Controls["SelectWeaponHeavy"] = 0x3D1675C3 -Controls["SelectWeaponSpecial"] = 0xC41ECEF8 -Controls["SelectCharacterMichael"] = 0xEA9256B8 -Controls["SelectCharacterFranklin"] = 0x8E8B08CB -Controls["SelectCharacterTrevor"] = 0xB00CC093 -Controls["SelectCharacterMultiplayer"] = 0xDFB2B3B8 -Controls["SaveReplayClip"] = 0x5B3AF9E3 -Controls["SpecialAbilityPc"] = 0x52E60A8B -Controls["SelectQuickselectSidearmsLeft"] = 0xE6F612E4 -Controls["SelectQuickselectDualwield"] = 0x1CE6D9EB -Controls["SelectQuickselectSidearmsRight"] = 0x4F49CC4C -Controls["SelectQuickselectUnarmed"] = 0x8F9F9E58 -Controls["SelectQuickselectMeleeNoUnarmed"] = 0xAB62E997 -Controls["SelectQuickselectSecondaryLongarm"] = 0xA1FDE2A6 -Controls["SelectQuickselectThrown"] = 0xB03A913B -Controls["SelectQuickselectPrimaryLongarm"] = 0x42385422 -Controls["CellphoneUp"] = 0xD2EE3B1E -Controls["CellphoneDown"] = 0x82196002 -Controls["CellphoneLeft"] = 0x3ABBE990 -Controls["CellphoneRight"] = 0xD25EFDCD -Controls["CellphoneSelect"] = 0xDC264018 -Controls["CellphoneCancel"] = 0xDD833287 -Controls["CellphoneOption"] = 0xD2C28BB4 -Controls["CellphoneExtraOption"] = 0xBE354011 -Controls["CellphoneScrollForward"] = 0xCB4E1798 -Controls["CellphoneScrollBackward"] = 0x47CD0F3B -Controls["CellphoneCameraFocusLock"] = 0x5AC1805E -Controls["CellphoneCameraGrid"] = 0xE18CC57A -Controls["CellphoneCameraSelfie"] = 0x6A440BFE -Controls["CellphoneCameraDof"] = 0x593DB489 -Controls["CellphoneCameraExpression"] = 0xD7E274E7 -Controls["FrontendDown"] = 0x05CA7C52 -Controls["FrontendUp"] = 0x6319DB71 -Controls["FrontendLeft"] = 0xA65EBAB4 -Controls["FrontendRight"] = 0xDEB34313 -Controls["FrontendRdown"] = 0x5734A944 -Controls["FrontendRup"] = 0xD7DE6B1E -Controls["FrontendRleft"] = 0x39336A4F -Controls["FrontendRright"] = 0x5B48F938 -Controls["FrontendAxisX"] = 0xFB56DD5B -Controls["FrontendAxisY"] = 0x091178D0 -Controls["FrontendScrollAxisX"] = 0x3224BC55 -Controls["FrontendScrollAxisY"] = 0x21651AD6 -Controls["FrontendRightAxisX"] = 0x3D23549A -Controls["FrontendRightAxisY"] = 0xEB4130DF -Controls["FrontendPause"] = 0xD82E0BD2 -Controls["FrontendPauseAlternate"] = 0x4A903C11 -Controls["FrontendAccept"] = 0xC7B5340A -Controls["FrontendCancel"] = 0x156F7119 -Controls["FrontendX"] = 0x6DB8C62F -Controls["FrontendY"] = 0x7C0162C0 -Controls["FrontendLb"] = 0xE885EF16 -Controls["FrontendRb"] = 0x17BEC168 -Controls["FrontendLt"] = 0x51104035 -Controls["FrontendRt"] = 0x6FED71BC -Controls["FrontendLs"] = 0x43CDA5B0 -Controls["FrontendRs"] = 0x7DA48D2A -Controls["FrontendLeaderboard"] = 0x9EDC8D65 -Controls["FrontendSocialClub"] = 0x064D1698 -Controls["FrontendSocialClubSecondary"] = 0xBDB8D6F3 -Controls["FrontendDelete"] = 0x4AF4D473 -Controls["FrontendEndscreenAccept"] = 0x3E32FCEE -Controls["FrontendEndscreenExpand"] = 0xC79BDE9F -Controls["FrontendSelect"] = 0x171910DC -Controls["FrontendPhotoMode"] = 0x44CD301B -Controls["FrontendNavUp"] = 0x8CFFE0A1 -Controls["FrontendNavDown"] = 0x78114AB3 -Controls["FrontendNavLeft"] = 0x877F1027 -Controls["FrontendNavRight"] = 0x08BD758C -Controls["FrontendMapNavUp"] = 0x125A70E5 -Controls["FrontendMapNavDown"] = 0xF8480EED -Controls["FrontendMapNavLeft"] = 0xE0D75B00 -Controls["FrontendMapNavRight"] = 0x28725E5D -Controls["FrontendMapZoom"] = 0x6B359A27 -Controls["GameMenuAccept"] = 0x43DBF61F -Controls["GameMenuCancel"] = 0x308588E6 -Controls["GameMenuOption"] = 0xFBD7B3E6 -Controls["GameMenuExtraOption"] = 0xD596CFB0 -Controls["GameMenuUp"] = 0x911CB09E -Controls["GameMenuDown"] = 0x4403F97F -Controls["GameMenuLeft"] = 0xAD7FCC5B -Controls["GameMenuRight"] = 0x65F9EC5B -Controls["GameMenuTabLeft"] = 0xCBD5B26E -Controls["GameMenuTabRight"] = 0x110AD1D2 -Controls["GameMenuTabLeftSecondary"] = 0x26E9DC00 -Controls["GameMenuTabRightSecondary"] = 0x8CC9CD42 -Controls["GameMenuScrollForward"] = 0x81457A1A -Controls["GameMenuScrollBackward"] = 0x9DA42644 -Controls["GameMenuStickUp"] = 0x9CA97399 -Controls["GameMenuStickDown"] = 0x63898D36 -Controls["GameMenuStickLeft"] = 0x06C089D4 -Controls["GameMenuStickRight"] = 0x5BDBE841 -Controls["GameMenuRightStickUp"] = 0xF0232A03 -Controls["GameMenuRightStickDown"] = 0xADB78673 -Controls["GameMenuRightStickLeft"] = 0x71E38966 -Controls["GameMenuRightStickRight"] = 0xE1CECE4B -Controls["GameMenuLs"] = 0xA8F6DE66 -Controls["GameMenuRs"] = 0x89EA3FA5 -Controls["GameMenuRightAxisX"] = 0x4685AA33 -Controls["GameMenuRightAxisY"] = 0x60C65EB4 -Controls["GameMenuLeftAxisX"] = 0xF431D57A -Controls["GameMenuLeftAxisY"] = 0x226EB1EF -Controls["Quit"] = 0x8E90C7BB -Controls["DocumentPageNext"] = 0xC97792B7 -Controls["DocumentPagePrev"] = 0x20190AB4 -Controls["DocumentScroll"] = 0xAC70F311 -Controls["DocumentScrollUpOnly"] = 0x3D0C19EC -Controls["DocumentScrollDownOnly"] = 0xD72F3E29 -Controls["Attack2"] = 0x0283C582 -Controls["PrevWeapon"] = 0xCC1075A7 -Controls["NextWeapon"] = 0xFD0F0C2C -Controls["SniperZoomIn"] = 0xE4568AA1 -Controls["SniperZoomOut"] = 0xE40CE39E -Controls["SniperZoomInAlternate"] = 0x3A9897C1 -Controls["SniperZoomOutAlternate"] = 0xBC820489 -Controls["ReplayStartStopRecording"] = 0xDCA6978E -Controls["ReplayStartStopRecordingSecondary"] = 0x8991A70B -Controls["ReplayMarkerDelete"] = 0xC7D2C51B -Controls["ReplayClipDelete"] = 0xF6734E42 -Controls["ReplayPause"] = 0x083137B2 -Controls["ReplayRewind"] = 0xC1339A31 -Controls["ReplayFfwd"] = 0x609A27E8 -Controls["ReplayNewmarker"] = 0xF7C6DA28 -Controls["ReplayRecord"] = 0xAD9A9C7C -Controls["ReplayScreenshot"] = 0x567FAF34 -Controls["ReplayHidehud"] = 0x7E479C7B -Controls["ReplayStartpoint"] = 0x5DAFACCF -Controls["ReplayEndpoint"] = 0x4EF75BBD -Controls["ReplayAdvance"] = 0x323AA450 -Controls["ReplayBack"] = 0x088C7CD4 -Controls["ReplayTools"] = 0x561A3387 -Controls["ReplayRestart"] = 0x81B8BC9D -Controls["ReplayShowhotkey"] = 0xEBA2A41E -Controls["ReplayCyclemarkerleft"] = 0x5C220959 -Controls["ReplayCyclemarkerright"] = 0xC69AE799 -Controls["ReplayFovincrease"] = 0x5925A10D -Controls["ReplayFovdecrease"] = 0x2B88D701 -Controls["ReplayCameraup"] = 0x749EFF0C -Controls["ReplayCameradown"] = 0xA1FE9E2A -Controls["ReplaySave"] = 0xEBC60685 -Controls["ReplayToggletime"] = 0xE3FB91B3 -Controls["ReplayToggletips"] = 0xC8A1DE20 -Controls["ReplayPreview"] = 0x58AC1355 -Controls["ReplayToggleTimeline"] = 0xF8629909 -Controls["ReplayTimelinePickupClip"] = 0xD2454F90 -Controls["ReplayTimelineDuplicateClip"] = 0x4146A033 -Controls["ReplayTimelinePlaceClip"] = 0x60726F50 -Controls["ReplayCtrl"] = 0xD88B47E7 -Controls["ReplayTimelineSave"] = 0x65D70E9D -Controls["ReplayPreviewAudio"] = 0x79022218 -Controls["ReplayActionReplayStart"] = 0xD9961107 -Controls["ReplayActionReplayCancel"] = 0x93776CAE -Controls["ReplayRecordingStart"] = 0xFD28D0F4 -Controls["ReplayRecordingStop"] = 0xDB16E702 -Controls["ReplaySaveSnapshot"] = 0xEFEC8FDE -Controls["VehDriveLook"] = 0xA2117C9A -Controls["VehDriveLook2"] = 0x55AC04E5 -Controls["VehFlyAttack2"] = 0x4D83147C -Controls["RadioWheelUd"] = 0x14C7291D -Controls["RadioWheelLr"] = 0xF9FA6BC8 -Controls["VehSlowmoUd"] = 0xF1F9CD26 -Controls["VehSlowmoUpOnly"] = 0x2B981F4F -Controls["VehSlowmoDownOnly"] = 0x642DE054 -Controls["MapPoi"] = 0x9BEE9213 -Controls["InteractLockon"] = 0xF8982F00 -Controls["InteractLockonNeg"] = 0x26A18F47 -Controls["InteractLockonPos"] = 0xF63A17F9 -Controls["InteractLockonRob"] = 0x9FA5AD07 -Controls["InteractLockonY"] = 0x09A92B8B -Controls["InteractLockonA"] = 0xD10A3A36 -Controls["InteractNeg"] = 0x424BD2D2 -Controls["InteractPos"] = 0xF6BB7378 -Controls["InteractOption1"] = 0x760A9C6F -Controls["InteractOption2"] = 0x84543902 -Controls["InteractAnimal"] = 0xA1ABB953 -Controls["InteractLockonAnimal"] = 0x5415BE48 -Controls["InteractLeadAnimal"] = 0x17D3BFF5 -Controls["InteractLockonDetachHorse"] = 0xF5C4701B -Controls["InteractHorseCare"] = 0xB0BCE5D6 -Controls["InteractLockonCallAnimal"] = 0x71F89BBC -Controls["InteractLockonTrackAnimal"] = 0xE2473BF0 -Controls["InteractLockonTargetInfo"] = 0x31219490 -Controls["InteractLockonStudyBinoculars"] = 0xB3F388BC -Controls["InteractWildAnimal"] = 0x89F3D2E0 -Controls["InteractHorseFeed"] = 0x0D55A0F0 -Controls["InteractHorseBrush"] = 0x63A38F2C -Controls["EmoteAction"] = 0x13C42BB2 -Controls["EmoteTaunt"] = 0x470DC190 -Controls["EmoteGreet"] = 0x72BAD5AA -Controls["EmoteComm"] = 0x661857B3 -Controls["EmoteDance"] = 0xF311100C -Controls["EmoteTwirlGunHold"] = 0x04FB8191 -Controls["EmoteTwirlGunVarA"] = 0x6990BDDF -Controls["EmoteTwirlGunVarB"] = 0x52D29063 -Controls["EmoteTwirlGunVarC"] = 0xBC2AE312 -Controls["EmoteTwirlGunVarD"] = 0xAE69478F -Controls["QuickEquipItem"] = 0x6070D032 -Controls["MinigameBuildingCameraNext"] = 0x16B0EEF8 -Controls["MinigameBuildingCameraPrev"] = 0x5F97B231 -Controls["MinigameBuildingHammer"] = 0xFA91AECD -Controls["CursorAcceptDoubleClick"] = 0x1C559F2E -Controls["CursorAcceptHold"] = 0xE474F150 -Controls["CursorAccept"] = 0x9D2AEA88 -Controls["CursorCancel"] = 0x27568539 -Controls["CursorCancelDoubleClick"] = 0x9CB4ECCE -Controls["CursorCancelHold"] = 0xD7F70F36 -Controls["CursorX"] = 0xD6C4ECDC -Controls["CursorY"] = 0xE4130778 -Controls["CursorScrollUp"] = 0x62800C92 -Controls["CursorScrollDown"] = 0x8BDE7443 -Controls["CursorScrollClick"] = 0x6AA8A71B -Controls["CursorScrollDoubleClick"] = 0xE1B6ED6D -Controls["CursorScrollHold"] = 0x5484DBDD -Controls["CursorForwardClick"] = 0x11DBBAB9 -Controls["CursorForwardDoubleClick"] = 0x9805D715 -Controls["CursorForwardHold"] = 0x7630C9A1 -Controls["CursorBackwardClick"] = 0x9AF38793 -Controls["CursorBackwardDoubleClick"] = 0xA14BA1FC -Controls["CursorBackwardHold"] = 0x01AA9FA1 -Controls["EnterCheatCode"] = 0x7BF65AC8 -Controls["InteractionMenu"] = 0xCC510E59 -Controls["MpTextChatAll"] = 0x9720FCEE -Controls["MpTextChatTeam"] = 0x9098AD9D -Controls["MpTextChatFriends"] = 0x7098AC73 -Controls["MpTextChatCrew"] = 0x8142FA92 -Controls["PushToTalk"] = 0x4BC9DABB -Controls["CreatorLs"] = 0x339F3730 -Controls["CreatorRs"] = 0xD8CF0C95 -Controls["CreatorLt"] = 0x446258B6 -Controls["CreatorRt"] = 0x3C3DD371 -Controls["CreatorMenuToggle"] = 0x85D24405 -Controls["CreatorAccept"] = 0x2CD5343E -Controls["CreatorMenuUp"] = 0xBCD1444B -Controls["CreatorMenuDown"] = 0x97410755 -Controls["CreatorMenuLeft"] = 0xEC6A30AA -Controls["CreatorMenuRight"] = 0x19D8334C -Controls["CreatorMenuAccept"] = 0xFB9C3231 -Controls["CreatorMenuCancel"] = 0xBB3FC460 -Controls["CreatorMenuFunction"] = 0x5A03B3F3 -Controls["CreatorMenuExtraFunction"] = 0xE6B8F103 -Controls["CreatorMenuSelect"] = 0x0984E40A -Controls["CreatorPlace"] = 0xD74CACAD -Controls["CreatorDelete"] = 0x3F4DC0EF -Controls["CreatorDrop"] = 0x414034D5 -Controls["CreatorFunction"] = 0xB05FDA25 -Controls["CreatorRotateRight"] = 0x9D75674E -Controls["CreatorRotateLeft"] = 0xD41E9C2A -Controls["CreatorGrab"] = 0x338A0D45 -Controls["CreatorSwitchCam"] = 0x16CCFEC6 -Controls["CreatorZoomIn"] = 0x335D8D76 -Controls["CreatorZoomOut"] = 0x24A42F93 -Controls["CreatorRaise"] = 0x0D0FB9B1 -Controls["CreatorLower"] = 0x1BDE2EB3 -Controls["CreatorSearch"] = 0xF55864CD -Controls["CreatorMoveUd"] = 0x82428676 -Controls["CreatorMoveLr"] = 0x59753EDC -Controls["CreatorLookUd"] = 0x55EA24F3 -Controls["CreatorLookLr"] = 0xAEB2A9C7 -Controls["CutFree"] = 0xD2CC4644 -Controls["Drop"] = 0xD2928083 -Controls["PickupCarriable"] = 0xEB2AC491 -Controls["PickupCarriable2"] = 0xBE8593AF -Controls["PlaceCarriableOntoParent"] = 0x7D326951 -Controls["PickupCarriableFromParent"] = 0xA1202C7B -Controls["MercyKill"] = 0x956C2A0E -Controls["Revive"] = 0x43F2959C -Controls["Hogtie"] = 0xD9C50532 -Controls["CarriableSuicide"] = 0x6E9734E8 -Controls["CarriableBreakFree"] = 0x295175BF -Controls["InteractHitCarriable"] = 0x0522B243 -Controls["Loot"] = 0x41AC83D1 -Controls["Loot2"] = 0x399C6619 -Controls["Loot3"] = 0x27D1C284 -Controls["LootVehicle"] = 0x14DB6C5E -Controls["LootAmmo"] = 0xC23D7B9E -Controls["BreakVehicleLock"] = 0x97C71B28 -Controls["LootAliveComponent"] = 0xFF8109D8 -Controls["FeedInteract"] = 0xA8E3F467 -Controls["SaddleTransfer"] = 0x73A8FD83 -Controls["ShopBuy"] = 0xDFF812F9 -Controls["ShopSell"] = 0x6D1319BE -Controls["ShopSpecial"] = 0xEA150E72 -Controls["ShopBounty"] = 0xD3ECF82F -Controls["ShopInspect"] = 0x5E723D8C -Controls["ShopChangeCurrency"] = 0x90FA19AB -Controls["QuickUseItem"] = 0xC1989F95 -Controls["PromptPageNext"] = 0x8CF90A9D -Controls["FrontendTouchZoomFactor"] = 0xE7F89C38 -Controls["FrontendTouchZoomX"] = 0x16661AD0 -Controls["FrontendTouchZoomY"] = 0x253DB87F -Controls["FrontendTouchDragX"] = 0xEC93548E -Controls["FrontendTouchDragY"] = 0x9AC130EB -Controls["FrontendTouchTapX"] = 0xC10E180A -Controls["FrontendTouchTapY"] = 0xCF4B3484 -Controls["FrontendTouchDoubleTapX"] = 0x1661FAB0 -Controls["FrontendTouchDoubleTapY"] = 0x96E87BBF -Controls["FrontendTouchHoldX"] = 0x0FF17F1D -Controls["FrontendTouchHoldY"] = 0x398ED257 -Controls["FrontendTouchSwipeUpX"] = 0x0B71D439 -Controls["FrontendTouchSwipeUpY"] = 0x19CA70EA -Controls["FrontendTouchSwipeDownX"] = 0xE3B30955 -Controls["FrontendTouchSwipeDownY"] = 0xBDFF3DEA -Controls["FrontendTouchSwipeLeftX"] = 0x2545B0DE -Controls["FrontendTouchSwipeLeftY"] = 0xD43D0ECE -Controls["FrontendTouchSwipeRightX"] = 0xEAB68397 -Controls["FrontendTouchSwipeRightY"] = 0x675B7CE3 -Controls["MultiplayerInfoPlayers"] = 0x9C68CE34 -Controls["MultiplayerDeadSwitchRespawn"] = 0xB4F298BA -Controls["MultiplayerDeadInformLaw"] = 0x6816A38E -Controls["MultiplayerDeadRespawn"] = 0x18987353 -Controls["MultiplayerDeadDuel"] = 0xF875FC78 -Controls["MultiplayerDeadParley"] = 0x4D11FE01 -Controls["MultiplayerDeadFeud"] = 0xB4A11066 -Controls["MultiplayerDeadLeaderFeud"] = 0xCC18F960 -Controls["MultiplayerDeadPressCharges"] = 0xE50DCA13 -Controls["MultiplayerRaceRespawn"] = 0x014CA044 -Controls["MultiplayerPredatorAbility"] = 0xC5CF41B2 -Controls["MultiplayerSpectatePlayerNext"] = 0xBA065692 -Controls["MultiplayerSpectatePlayerPrev"] = 0x5092BF47 -Controls["MultiplayerSpectateHideHud"] = 0x7DBA5D49 -Controls["MultiplayerSpectatePlayerOptions"] = 0x4E074EE6 -Controls["MultiplayerLeaderboardScrollUd"] = 0xA917D24B -Controls["MinigameQuit"] = 0xE9094BA0 -Controls["MinigameIncreaseBet"] = 0xC7CB8D5F -Controls["MinigameDecreaseBet"] = 0xD3EBF425 -Controls["MinigameChangeBetAxisY"] = 0xBDC733EE -Controls["MinigamePlaceBet"] = 0x410B0B2E -Controls["MinigameClearBet"] = 0x4A21C66B -Controls["MinigameHelp"] = 0x9384E0A8 -Controls["MinigameHelpPrev"] = 0xC5F53156 -Controls["MinigameHelpNext"] = 0x83608AC0 -Controls["MinigameReplay"] = 0x985243B7 -Controls["MinigameNewGame"] = 0x5D1788FF -Controls["MinigamePokerSkip"] = 0x646A7792 -Controls["MinigamePokerCall"] = 0xDAB9EE72 -Controls["MinigamePokerFold"] = 0x49B4AD1E -Controls["MinigamePokerCheck"] = 0x206B2087 -Controls["MinigamePokerCheckFold"] = 0x72A9D1F7 -Controls["MinigamePokerBet"] = 0xA9883369 -Controls["MinigamePokerHoleCards"] = 0xC2B1193A -Controls["MinigamePokerBoardCards"] = 0x03753498 -Controls["MinigamePokerSkipTutorial"] = 0xB568BCD0 -Controls["MinigamePokerShowPossibleHands"] = 0x7765B9D4 -Controls["MinigamePokerYourCards"] = 0xF923B337 -Controls["MinigamePokerCommunityCards"] = 0xE402B898 -Controls["MinigamePokerCheatLr"] = 0x2330F517 -Controls["MinigameFishingResetCast"] = 0xB40A9BDB -Controls["MinigameFishingReleaseFish"] = 0xF14FD435 -Controls["MinigameFishingKeepFish"] = 0x52C5C34A -Controls["MinigameFishingHook"] = 0xA1CD103A -Controls["MinigameFishingLeftAxisX"] = 0x69B10623 -Controls["MinigameFishingLeftAxisY"] = 0x09BF4645 -Controls["MinigameFishingRightAxisX"] = 0x4FD4E558 -Controls["MinigameFishingRightAxisY"] = 0x95F2F193 -Controls["MinigameFishingLeanLeft"] = 0x0D4C3ABA -Controls["MinigameFishingLeanRight"] = 0x05074A9B -Controls["MinigameFishingQuickEquip"] = 0x25F525CD -Controls["MinigameFishingReelSpeedUp"] = 0x2FA915F5 -Controls["MinigameFishingReelSpeedDown"] = 0xD7AF56A0 -Controls["MinigameFishingReelSpeedAxis"] = 0x49C73CB2 -Controls["MinigameFishingManualReelIn"] = 0xA303F462 -Controls["MinigameFishingManualReelOutModifier"] = 0x4556642C -Controls["MinigameCrackpotBoatShowControls"] = 0x524C3787 -Controls["MinigameDominoesViewDominoes"] = 0x88F8B6B1 -Controls["MinigameDominoesViewMoves"] = 0x7733CF2C -Controls["MinigameDominoesPlayTile"] = 0x95F5BB7C -Controls["MinigameDominoesSkipDeal"] = 0xC5E622D7 -Controls["MinigameDominoesMoveLeftOnly"] = 0xFDDD89D4 -Controls["MinigameDominoesMoveRightOnly"] = 0x7D5187C9 -Controls["MinigameDominoesMoveUpOnly"] = 0xC6AB8CB3 -Controls["MinigameDominoesMoveDownOnly"] = 0xFD9FC86D -Controls["MinigameBlackjackHandView"] = 0x03F1E7CB -Controls["MinigameBlackjackTableView"] = 0xADE09435 -Controls["MinigameBlackjackBetAxisY"] = 0x3D2EA092 -Controls["MinigameBlackjackBet"] = 0x661D8A31 -Controls["MinigameBlackjackDecline"] = 0xCD7DDF9B -Controls["MinigameBlackjackStand"] = 0x31260507 -Controls["MinigameBlackjackHit"] = 0xA8142713 -Controls["MinigameBlackjackDouble"] = 0x74486CA4 -Controls["MinigameBlackjackSplit"] = 0x432B111F -Controls["MinigameFffA"] = 0x0E717DC6 -Controls["MinigameFffB"] = 0x1BC81873 -Controls["MinigameFffX"] = 0x65F0ACDF -Controls["MinigameFffY"] = 0x73AD4858 -Controls["MinigameFffZoom"] = 0x61E4CACC -Controls["MinigameFffSkipTurn"] = 0x3073681B -Controls["MinigameFffCycleSequenceLeft"] = 0x29A3550E -Controls["MinigameFffCycleSequenceRight"] = 0x7B5B896D -Controls["MinigameFffFlourishContinue"] = 0x6FC9DE68 -Controls["MinigameFffFlourishEnd"] = 0xF7750B25 -Controls["MinigameFffPractice"] = 0xCA379F82 -Controls["MinigameMilkingLeftAction"] = 0xFF4B2ADA -Controls["MinigameMilkingRightAction"] = 0x30BE7CF2 -Controls["MinigameLeftTrigger"] = 0x7EC33553 -Controls["MinigameRightTrigger"] = 0xBE78B715 -Controls["MinigameActionLeft"] = 0x0A1EFC09 -Controls["MinigameActionRight"] = 0x16D70379 -Controls["MinigameActionUp"] = 0xF5A13A0D -Controls["MinigameActionDown"] = 0xF601BCFC -Controls["StickyFeedAccept"] = 0xF4DD4C67 -Controls["StickyFeedCancel"] = 0x0CFB963F -Controls["StickyFeedX"] = 0xBD1D94A1 -Controls["StickyFeedY"] = 0xC85BAB1D -Controls["CameraPutAway"] = 0x5FC770EA -Controls["CameraBack"] = 0xA4BD74A5 -Controls["CameraTakePhoto"] = 0x44FA14C2 -Controls["CameraContextGallery"] = 0xE8337356 -Controls["CameraHandheldUse"] = 0x776F65E9 -Controls["CameraDof"] = 0x3003F9DC -Controls["CameraSelfie"] = 0xAC5922EA -Controls["CameraZoom"] = 0x47EC4C22 -Controls["CameraPoseNext"] = 0xF810FB35 -Controls["CameraPosePrev"] = 0x8D5BE9D1 -Controls["CameraExpressionNext"] = 0xCFA703D3 -Controls["CameraExpressionPrev"] = 0x07B6435D -Controls["TithingIncreaseAmount"] = 0x24F37AB5 -Controls["TithingDecreaseAmount"] = 0xCEFF5C13 -Controls["BreakDoorLock"] = 0x77110B0A -Controls["InterrogateQuestion"] = 0xA1AA2D8D -Controls["InterrogateBeat"] = 0x6E1E0D62 -Controls["InterrogateKill"] = 0x81B2E311 -Controls["InterrogateRelease"] = 0x3C22EF0E -Controls["CampBedInspect"] = 0xC67E13BB -Controls["PcFreeLook"] = 0x8AAA0AD4 -Controls["MinigameBartenderRaiseGlass"] = 0xA13460F5 -Controls["MinigameBartenderRaiseBottle"] = 0xF0A25112 -Controls["MinigameBartenderPour"] = 0xCABC2460 -Controls["MinigameBartenderServe"] = 0xDC03B043 -Controls["PhotoMode"] = 0x3C0A40F2 -Controls["PhotoModePc"] = 0x35957F6C -Controls["PhotoModeChangeCamera"] = 0x9F06B29C -Controls["PhotoModeMoveLr"] = 0x4F136512 -Controls["PhotoModeMoveLeftOnly"] = 0x311353EB -Controls["PhotoModeMoveRightOnly"] = 0x5357A7F5 -Controls["PhotoModeMoveUd"] = 0xEC001315 -Controls["PhotoModeMoveUpOnly"] = 0x315D57E6 -Controls["PhotoModeMoveDownOnly"] = 0x4EBCC409 -Controls["PhotoModeReset"] = 0xA209BD57 -Controls["PhotoModeLenseNext"] = 0xB138D899 -Controls["PhotoModeLensePrev"] = 0x06A057F8 -Controls["PhotoModeRotateLeft"] = 0x2EEA1D2A -Controls["PhotoModeRotateRight"] = 0x96E70854 -Controls["PhotoModeToggleHud"] = 0x7F9055F5 -Controls["PhotoModeViewPhotos"] = 0xDCE96D67 -Controls["PhotoModeTakePhoto"] = 0xA190AAC7 -Controls["PhotoModeBack"] = 0x2F13EC9A -Controls["PhotoModeSwitchMode"] = 0x8F32E2EB -Controls["PhotoModeFilterIntensity"] = 0xFE6DD360 -Controls["PhotoModeFilterIntensityUp"] = 0x2286D46B -Controls["PhotoModeFilterIntensityDown"] = 0xB341F407 -Controls["PhotoModeFocalLength"] = 0x886ABA4E -Controls["PhotoModeFocalLengthUpOnly"] = 0xFAFBD66A -Controls["PhotoModeFocalLengthDownOnly"] = 0x01EBFABD -Controls["PhotoModeFilterNext"] = 0x699F8D08 -Controls["PhotoModeFilterPrev"] = 0x4F640885 -Controls["PhotoModeZoomIn"] = 0x5B843BC9 -Controls["PhotoModeZoomOut"] = 0x2354D2E6 -Controls["PhotoModeDof"] = 0x26B9AE6A -Controls["PhotoModeDofUpOnly"] = 0x87B07940 -Controls["PhotoModeDofDownOnly"] = 0x047099F1 -Controls["PhotoModeExposureUp"] = 0xC64E2284 -Controls["PhotoModeExposureDown"] = 0xAD07A5A5 -Controls["PhotoModeExposureLock"] = 0x9DE08D71 -Controls["PhotoModeContrast"] = 0x483F707F -Controls["PhotoModeContrastUpOnly"] = 0x5D2DD717 -Controls["PhotoModeContrastDownOnly"] = 0x30811620 -Controls["CraftingEat"] = 0xB99A9CAD -Controls["CampSetupTent"] = 0x0B1BE2E8 -Controls["MinigameActionX"] = 0x1D927DF2 -Controls["DeprecatedAbove"] = 0xC1D24F92 -Controls["ScriptLeftAxisX"] = 0x1F8EEF84 -Controls["ScriptLeftAxisY"] = 0x5418D8AB -Controls["ScriptRightAxisX"] = 0xA6B769E9 -Controls["ScriptRightAxisY"] = 0x27A5EBC0 -Controls["ScriptRup"] = 0x771D6E13 -Controls["ScriptRdown"] = 0x37933367 -Controls["ScriptRleft"] = 0xA4DB0458 -Controls["ScriptRright"] = 0x22A3B800 -Controls["ScriptLb"] = 0xE624C062 -Controls["ScriptRb"] = 0x91E9231C -Controls["ScriptLt"] = 0x2B314A1E -Controls["ScriptRt"] = 0x26E9CD17 -Controls["ScriptLs"] = 0xAADDC975 -Controls["ScriptRs"] = 0xD04E9FE2 -Controls["ScriptPadUp"] = 0x0DC15ADD -Controls["ScriptPadDown"] = 0xB1DA5574 -Controls["ScriptPadLeft"] = 0x1AF81D9E -Controls["ScriptPadRight"] = 0x82A9B758 -Controls["ScriptSelect"] = 0xC8722109 -Controls["ScriptedFlyUd"] = 0xAEB4B1DE -Controls["ScriptedFlyLr"] = 0xF1111E4A -Controls["ScriptedFlyZup"] = 0x639B9FC9 -Controls["ScriptedFlyZdown"] = 0x9C5E030C -Controls["Count"] = 0x8EDFFB30 \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/NativeUI.lua b/server-data/resources/[esx]/EasyAdmin/dependencies/NativeUI.lua deleted file mode 100644 index e5f203af9..000000000 --- a/server-data/resources/[esx]/EasyAdmin/dependencies/NativeUI.lua +++ /dev/null @@ -1,3938 +0,0 @@ -Citizen.CreateThread(function() - - if CompendiumHorseObserved then - return - end - - -UIResRectangle = setmetatable({}, UIResRectangle) -UIResRectangle.__index = UIResRectangle -UIResRectangle.__call = function() return "Rectangle" end - -UIResText = setmetatable({}, UIResText) -UIResText.__index = UIResText -UIResText.__call = function() return "Text" end - -Sprite = setmetatable({}, Sprite) -Sprite.__index = Sprite -Sprite.__call = function() return "Sprite" end - -UIMenuItem = setmetatable({}, UIMenuItem) -UIMenuItem.__index = UIMenuItem -UIMenuItem.__call = function() return "UIMenuItem", "UIMenuItem" end - -UIMenuCheckboxItem = setmetatable({}, UIMenuCheckboxItem) -UIMenuCheckboxItem.__index = UIMenuCheckboxItem -UIMenuCheckboxItem.__call = function() return "UIMenuItem", "UIMenuCheckboxItem" end - -UIMenuListItem = setmetatable({}, UIMenuListItem) -UIMenuListItem.__index = UIMenuListItem -UIMenuListItem.__call = function() return "UIMenuItem", "UIMenuListItem" end - -UIMenuSliderItem = setmetatable({}, UIMenuSliderItem) -UIMenuSliderItem.__index = UIMenuSliderItem -UIMenuSliderItem.__call = function() return "UIMenuItem", "UIMenuSliderItem" end - -UIMenuColouredItem = setmetatable({}, UIMenuColouredItem) -UIMenuColouredItem.__index = UIMenuColouredItem -UIMenuColouredItem.__call = function() return "UIMenuItem", "UIMenuColouredItem" end - -UIMenuProgressItem = setmetatable({}, UIMenuProgressItem) -UIMenuProgressItem.__index = UIMenuProgressItem -UIMenuProgressItem.__call = function() return "UIMenuItem", "UIMenuProgressItem" end - -UIMenuHeritageWindow = setmetatable({}, UIMenuHeritageWindow) -UIMenuHeritageWindow.__index = UIMenuHeritageWindow -UIMenuHeritageWindow.__call = function() return "UIMenuWindow", "UIMenuHeritageWindow" end - -UIMenuGridPanel = setmetatable({}, UIMenuGridPanel) -UIMenuGridPanel.__index = UIMenuGridPanel -UIMenuGridPanel.__call = function() return "UIMenuPanel", "UIMenuGridPanel" end - -UIMenuColourPanel = setmetatable({}, UIMenuColourPanel) -UIMenuColourPanel.__index = UIMenuColourPanel -UIMenuColourPanel.__call = function() return "UIMenuPanel", "UIMenuColourPanel" end - -UIMenuPercentagePanel = setmetatable({}, UIMenuPercentagePanel) -UIMenuPercentagePanel.__index = UIMenuPercentagePanel -UIMenuPercentagePanel.__call = function() return "UIMenuPanel", "UIMenuPercentagePanel" end - -UIMenu = setmetatable({}, UIMenu) -UIMenu.__index = UIMenu -UIMenu.__call = function() return "UIMenu" end - -MenuPool = setmetatable({}, MenuPool) -MenuPool.__index = MenuPool - -NativeUI = {} - -CharacterMap = { [' '] = 6, ['!'] = 6, ['"'] = 6, ['#'] = 11,['$'] = 10, ['%'] = 17,['&'] = 13, ['\\'] = 4,['('] = 6, [')'] = 6,['*'] = 7, ['+'] = 10, [','] = 4, ['-'] = 6, ['.'] = 4, ['/'] = 7, ['0'] = 12, ['1'] = 7, ['2'] = 11, ['3'] = 11, ['4'] = 11, ['5'] = 11, ['6'] = 12, ['7'] = 10, ['8'] = 11, ['9'] = 11, [':'] = 5, [';'] = 4, ['<'] = 9, ['='] = 9, ['>'] = 9, ['?'] = 10, ['@'] = 15, ['A'] = 12, ['B'] = 13, ['C'] = 14, ['D'] = 14, ['E'] = 12, ['F'] = 12, ['G'] = 15, ['H'] = 14, ['I'] = 5, ['J'] = 11, ['K'] = 13, ['L'] = 11, ['M'] = 16, ['N'] = 14, ['O'] = 16, ['P'] = 12, ['Q'] = 15, ['R'] = 13, ['S'] = 12, ['T'] = 11, ['U'] = 13, ['V'] = 12, ['W'] = 18, ['X'] = 11, ['Y'] = 11, ['Z'] = 12, ['['] = 6, [']'] = 6, ['^'] = 9, ['_'] = 18, ['`'] = 8, ['a'] = 11, ['b'] = 12, ['c'] = 11, ['d'] = 12, ['e'] = 12, ['f'] = 5, ['g'] = 13, ['h'] = 11, ['i'] = 4, ['j'] = 4, ['k'] = 10, ['l'] = 4, ['m'] = 18, ['n'] = 11, ['o'] = 12, ['p'] = 12, ['q'] = 12, ['r'] = 7, ['s'] = 9, ['t'] = 5, ['u'] = 11, ['v'] = 10, ['w'] = 14, ['x'] = 9, ['y'] = 10, ['z'] = 9, ['{'] = 6, ['|'] = 3, ['}'] = 6 } - -BadgeStyle = { None = 0, BronzeMedal = 1, GoldMedal = 2, SilverMedal = 3, Alert = 4, Crown = 5, Ammo = 6, Armour = 7, Barber = 8, Clothes = 9, Franklin = 10, Bike = 11, Car = 12, Gun = 13, Heart = 14, Makeup = 15, Mask = 16, Michael = 17, Star = 18, Tattoo = 19, Trevor = 20, Lock = 21, Tick = 22 } - -BadgeTexture = { - [0] = function() return "" end, - [1] = function() return "mp_medal_bronze" end, - [2] = function() return "mp_medal_gold" end, - [3] = function() return "medal_silver" end, - [4] = function() return "mp_alerttriangle" end, - [5] = function() return "mp_hostcrown" end, - [6] = function(Selected) if Selected then return "shop_ammo_icon_b" else return "shop_ammo_icon_a" end end, - [7] = function(Selected) if Selected then return "shop_armour_icon_b" else return "shop_armour_icon_a" end end, - [8] = function(Selected) if Selected then return "shop_barber_icon_b" else return "shop_barber_icon_a" end end, - [9] = function(Selected) if Selected then return "shop_clothing_icon_b" else return "shop_clothing_icon_a" end end, - [10] = function(Selected) if Selected then return "shop_franklin_icon_b" else return "shop_franklin_icon_a" end end, - [11] = function(Selected) if Selected then return "shop_garage_bike_icon_b" else return "shop_garage_bike_icon_a" end end, - [12] = function(Selected) if Selected then return "shop_garage_icon_b" else return "shop_garage_icon_a" end end, - [13] = function(Selected) if Selected then return "shop_gunclub_icon_b" else return "shop_gunclub_icon_a" end end, - [14] = function(Selected) if Selected then return "shop_health_icon_b" else return "shop_health_icon_a" end end, - [15] = function(Selected) if Selected then return "shop_makeup_icon_b" else return "shop_makeup_icon_a" end end, - [16] = function(Selected) if Selected then return "shop_mask_icon_b" else return "shop_mask_icon_a" end end, - [17] = function(Selected) if Selected then return "shop_michael_icon_b" else return "shop_michael_icon_a" end end, - [18] = function() return "shop_new_star" end, - [19] = function(Selected) if Selected then return "shop_tattoos_icon_b" else return "shop_tattoos_icon_a" end end, - [20] = function(Selected) if Selected then return "shop_trevor_icon_b" else return "shop_trevor_icon_a" end end, - [21] = function() return "shop_lock" end, - [22] = function() return "shop_tick_icon" end, - [23] = function() return "badge_dev" end, - [24] = function() return "badge_contrib" end, -} - -BadgeDictionary = { - [0] = function(Selected) - if Selected then - return "commonmenu" - else - return "commonmenu" - end - end, - [23] = function(Selected) - return "easyadmin" - end, - [24] = function(Selected) - return "easyadmin" - end, -} - -BadgeColour = { - [5] = function(Selected) if Selected then return 0, 0, 0, 255 else return 255, 255, 255, 255 end end, - [21] = function(Selected) if Selected then return 0, 0, 0, 255 else return 255, 255, 255, 255 end end, - [22] = function(Selected) if Selected then return 0, 0, 0, 255 else return 255, 255, 255, 255 end end, - [23] = function(Selected) if Selected then return 0,0,0, 255 else return 255,255,255,255 end end, - [24] = function(Selected) if Selected then return 0,0,0, 255 else return 255,255,255,255 end end -} - -Colours = { - PureWhite = {255, 255, 255, 255}, - White = {240, 240, 240, 255}, - Black = {0, 0, 0, 255}, - Grey = {155, 155, 155, 255}, - GreyLight = {205, 205, 205, 255}, - GreyDark = {77, 77, 77, 255}, - Red = {224, 50, 50, 255}, - RedLight = {240, 153, 153, 255}, - RedDark = {112, 25, 25, 255}, - Blue = {93, 182, 229, 255}, - BlueLight = {174, 219, 242, 255}, - BlueDark = {47, 92, 115, 255}, - Yellow = {240, 200, 80, 255}, - YellowLight = {254, 235, 169, 255}, - YellowDark = {126, 107, 41, 255}, - Orange = {255, 133, 85, 255}, - OrangeLight = {255, 194, 170, 255}, - OrangeDark = {127, 66, 42, 255}, - Green = {114, 204, 114, 255}, - GreenLight = {185, 230, 185, 255}, - GreenDark = {57, 102, 57, 255}, - Purple = {132, 102, 226, 255}, - PurpleLight = {192, 179, 239, 255}, - PurpleDark = {67, 57, 111, 255}, - Pink = {203, 54, 148, 255}, - RadarHealth = {53, 154, 71, 255}, - RadarArmour = {93, 182, 229, 255}, - RadarDamage = {235, 36, 39, 255}, - NetPlayer1 = {194, 80, 80, 255}, - NetPlayer2 = {156, 110, 175, 255}, - NetPlayer3 = {255, 123, 196, 255}, - NetPlayer4 = {247, 159, 123, 255}, - NetPlayer5 = {178, 144, 132, 255}, - NetPlayer6 = {141, 206, 167, 255}, - NetPlayer7 = {113, 169, 175, 255}, - NetPlayer8 = {211, 209, 231, 255}, - NetPlayer9 = {144, 127, 153, 255}, - NetPlayer10 = {106, 196, 191, 255}, - NetPlayer11 = {214, 196, 153, 255}, - NetPlayer12 = {234, 142, 80, 255}, - NetPlayer13 = {152, 203, 234, 255}, - NetPlayer14 = {178, 98, 135, 255}, - NetPlayer15 = {144, 142, 122, 255}, - NetPlayer16 = {166, 117, 94, 255}, - NetPlayer17 = {175, 168, 168, 255}, - NetPlayer18 = {232, 142, 155, 255}, - NetPlayer19 = {187, 214, 91, 255}, - NetPlayer20 = {12, 123, 86, 255}, - NetPlayer21 = {123, 196, 255, 255}, - NetPlayer22 = {171, 60, 230, 255}, - NetPlayer23 = {206, 169, 13, 255}, - NetPlayer24 = {71, 99, 173, 255}, - NetPlayer25 = {42, 166, 185, 255}, - NetPlayer26 = {186, 157, 125, 255}, - NetPlayer27 = {201, 225, 255, 255}, - NetPlayer28 = {240, 240, 150, 255}, - NetPlayer29 = {237, 140, 161, 255}, - NetPlayer30 = {249, 138, 138, 255}, - NetPlayer31 = {252, 239, 166, 255}, - NetPlayer32 = {240, 240, 240, 255}, - SimpleBlipDefault = {159, 201, 166, 255}, - MenuBlue = {140, 140, 140, 255}, - MenuGreyLight = {140, 140, 140, 255}, - MenuBlueExtraDark = {40, 40, 40, 255}, - MenuYellow = {240, 160, 0, 255}, - MenuYellowDark = {240, 160, 0, 255}, - MenuGreen = {240, 160, 0, 255}, - MenuGrey = {140, 140, 140, 255}, - MenuGreyDark = {60, 60, 60, 255}, - MenuHighlight = {30, 30, 30, 255}, - MenuStandard = {140, 140, 140, 255}, - MenuDimmed = {75, 75, 75, 255}, - MenuExtraDimmed = {50, 50, 50, 255}, - BriefTitle = {95, 95, 95, 255}, - MidGreyMp = {100, 100, 100, 255}, - NetPlayer1Dark = {93, 39, 39, 255}, - NetPlayer2Dark = {77, 55, 89, 255}, - NetPlayer3Dark = {124, 62, 99, 255}, - NetPlayer4Dark = {120, 80, 80, 255}, - NetPlayer5Dark = {87, 72, 66, 255}, - NetPlayer6Dark = {74, 103, 83, 255}, - NetPlayer7Dark = {60, 85, 88, 255}, - NetPlayer8Dark = {105, 105, 64, 255}, - NetPlayer9Dark = {72, 63, 76, 255}, - NetPlayer10Dark = {53, 98, 95, 255}, - NetPlayer11Dark = {107, 98, 76, 255}, - NetPlayer12Dark = {117, 71, 40, 255}, - NetPlayer13Dark = {76, 101, 117, 255}, - NetPlayer14Dark = {65, 35, 47, 255}, - NetPlayer15Dark = {72, 71, 61, 255}, - NetPlayer16Dark = {85, 58, 47, 255}, - NetPlayer17Dark = {87, 84, 84, 255}, - NetPlayer18Dark = {116, 71, 77, 255}, - NetPlayer19Dark = {93, 107, 45, 255}, - NetPlayer20Dark = {6, 61, 43, 255}, - NetPlayer21Dark = {61, 98, 127, 255}, - NetPlayer22Dark = {85, 30, 115, 255}, - NetPlayer23Dark = {103, 84, 6, 255}, - NetPlayer24Dark = {35, 49, 86, 255}, - NetPlayer25Dark = {21, 83, 92, 255}, - NetPlayer26Dark = {93, 98, 62, 255}, - NetPlayer27Dark = {100, 112, 127, 255}, - NetPlayer28Dark = {120, 120, 75, 255}, - NetPlayer29Dark = {152, 76, 93, 255}, - NetPlayer30Dark = {124, 69, 69, 255}, - NetPlayer31Dark = {10, 43, 50, 255}, - NetPlayer32Dark = {95, 95, 10, 255}, - Bronze = {180, 130, 97, 255}, - Silver = {150, 153, 161, 255}, - Gold = {214, 181, 99, 255}, - Platinum = {166, 221, 190, 255}, - Gang1 = {29, 100, 153, 255}, - Gang2 = {214, 116, 15, 255}, - Gang3 = {135, 125, 142, 255}, - Gang4 = {229, 119, 185, 255}, - SameCrew = {252, 239, 166, 255}, - Freemode = {45, 110, 185, 255}, - PauseBg = {0, 0, 0, 255}, - Friendly = {93, 182, 229, 255}, - Enemy = {194, 80, 80, 255}, - Location = {240, 200, 80, 255}, - Pickup = {114, 204, 114, 255}, - PauseSingleplayer = {114, 204, 114, 255}, - FreemodeDark = {22, 55, 92, 255}, - InactiveMission = {154, 154, 154, 255}, - Damage = {194, 80, 80, 255}, - PinkLight = {252, 115, 201, 255}, - PmMitemHighlight = {252, 177, 49, 255}, - ScriptVariable = {0, 0, 0, 255}, - Yoga = {109, 247, 204, 255}, - Tennis = {241, 101, 34, 255}, - Golf = {214, 189, 97, 255}, - ShootingRange = {112, 25, 25, 255}, - FlightSchool = {47, 92, 115, 255}, - NorthBlue = {93, 182, 229, 255}, - SocialClub = {234, 153, 28, 255}, - PlatformBlue = {11, 55, 123, 255}, - PlatformGreen = {146, 200, 62, 255}, - PlatformGrey = {234, 153, 28, 255}, - FacebookBlue = {66, 89, 148, 255}, - IngameBg = {0, 0, 0, 255}, - Darts = {114, 204, 114, 255}, - Waypoint = {164, 76, 242, 255}, - Michael = {101, 180, 212, 255}, - Franklin = {171, 237, 171, 255}, - Trevor = {255, 163, 87, 255}, - GolfP1 = {240, 240, 240, 255}, - GolfP2 = {235, 239, 30, 255}, - GolfP3 = {255, 149, 14, 255}, - GolfP4 = {246, 60, 161, 255}, - WaypointLight = {210, 166, 249, 255}, - WaypointDark = {82, 38, 121, 255}, - PanelLight = {0, 0, 0, 255}, - MichaelDark = {72, 103, 116, 255}, - FranklinDark = {85, 118, 85, 255}, - TrevorDark = {127, 81, 43, 255}, - ObjectiveRoute = {240, 200, 80, 255}, - PausemapTint = {0, 0, 0, 255}, - PauseDeselect = {100, 100, 100, 255}, - PmWeaponsPurchasable = {45, 110, 185, 255}, - PmWeaponsLocked = {240, 240, 240, 255}, - ScreenBg = {0, 0, 0, 255}, - Chop = {224, 50, 50, 255}, - PausemapTintHalf = {0, 0, 0, 255}, - NorthBlueOfficial = {0, 71, 133, 255}, - ScriptVariable2 = {0, 0, 0, 255}, - H = {33, 118, 37, 255}, - HDark = {37, 102, 40, 255}, - T = {234, 153, 28, 255}, - TDark = {225, 140, 8, 255}, - HShard = {20, 40, 0, 255}, - ControllerMichael = {48, 255, 255, 255}, - ControllerFranklin = {48, 255, 0, 255}, - ControllerTrevor = {176, 80, 0, 255}, - ControllerChop = {127, 0, 0, 255}, - VideoEditorVideo = {53, 166, 224, 255}, - VideoEditorAudio = {162, 79, 157, 255}, - VideoEditorText = {104, 192, 141, 255}, - HbBlue = {29, 100, 153, 255}, - HbYellow = {234, 153, 28, 255}, - VideoEditorScore = {240, 160, 1, 255}, - VideoEditorAudioFadeout = {59, 34, 57, 255}, - VideoEditorTextFadeout = {41, 68, 53, 255}, - VideoEditorScoreFadeout = {82, 58, 10, 255}, - HeistBackground = {37, 102, 40, 255}, - VideoEditorAmbient = {240, 200, 80, 255}, - VideoEditorAmbientFadeout = {80, 70, 34, 255}, - Gb = {255, 133, 85, 255}, - G = {255, 194, 170, 255}, - B = {255, 133, 85, 255}, - LowFlow = {240, 200, 80, 255}, - LowFlowDark = {126, 107, 41, 255}, - G1 = {247, 159, 123, 255}, - G2 = {226, 134, 187, 255}, - G3 = {239, 238, 151, 255}, - G4 = {113, 169, 175, 255}, - G5 = {160, 140, 193, 255}, - G6 = {141, 206, 167, 255}, - G7 = {181, 214, 234, 255}, - G8 = {178, 144, 132, 255}, - G9 = {0, 132, 114, 255}, - G10 = {216, 85, 117, 255}, - G11 = {30, 100, 152, 255}, - G12 = {43, 181, 117, 255}, - G13 = {233, 141, 79, 255}, - G14 = {137, 210, 215, 255}, - G15 = {134, 125, 141, 255}, - Adversary = {109, 34, 33, 255}, - DegenRed = {255, 0, 0, 255}, - DegenYellow = {255, 255, 0, 255}, - DegenGreen = {0, 255, 0, 255}, - DegenCyan = {0, 255, 255, 255}, - DegenBlue = {0, 0, 255, 255}, - DegenMagenta = {255, 0, 255, 255}, - Stunt1 = {38, 136, 234, 255}, - Stunt2 = {224, 50, 50, 255}, -} - ---[[ - Utils.lua - Utilities ---]] - -function GetResolution() - local W, H = GetActiveScreenResolution() - if (W/H) > 3.5 then - return GetScreenResolution() - else - return W, H - end -end - -function FormatXWYH(Value, Value2) - return Value/1920, Value2/1080 -end - -function math.round(num, numDecimalPlaces) - return tonumber(string.format("%." .. (numDecimalPlaces or 0) .. "f", num)) -end - -function tobool(input) - if input == "true" or tonumber(input) == 1 or input == true then - return true - else - return false - end -end - -function string.split(inputstr, sep) - if sep == nil then - sep = "%s" - end - local t={} ; i=1 - for str in string.gmatch(inputstr, "([^"..sep.."]+)") do - t[i] = str - i = i + 1 - end - - return t -end - -function string.starts(String, Start) - return string.sub(String, 1, string.len(Start)) == Start -end - -function IsMouseInBounds(X, Y, Width, Height) - local MX, MY = math.round(GetControlNormal(0, 239) * 1920), math.round(GetControlNormal(0, 240) * 1080) - MX, MY = FormatXWYH(MX, MY) - local X, Y = FormatXWYH(X, Y) - local Width, Height = FormatXWYH(Width, Height) - return (MX >= X and MX <= X + Width) and (MY > Y and MY < Y + Height) -end - -function GetSafeZoneBounds() - local SafeSize = GetSafeZoneSize() - SafeSize = math.round(SafeSize, 2) - SafeSize = (SafeSize * 100) - 90 - SafeSize = 10 - SafeSize - - local W, H = 1920, 1080 - - return {X = math.round(SafeSize * ((W/H) * 5.4)), Y = math.round(SafeSize * 5.4)} -end - -function Controller() - return not IsInputDisabled(2) -end - ---[[ - UIResRectangle.lua - Elements ---]] - -function UIResRectangle.New(X, Y, Width, Height, R, G, B, A) - local _UIResRectangle = { - X = tonumber(X) or 0, - Y = tonumber(Y) or 0, - Width = tonumber(Width) or 0, - Height = tonumber(Height) or 0, - _Colour = {R = tonumber(R) or 255, G = tonumber(G) or 255, B = tonumber(B) or 255, A = tonumber(A) or 255}, - } - return setmetatable(_UIResRectangle, UIResRectangle) -end - -function UIResRectangle:Position(X, Y) - if tonumber(X) and tonumber(Y) then - self.X = tonumber(X) - self.Y = tonumber(Y) - else - return {X = self.X, Y = self.Y} - end -end - -function UIResRectangle:Size(Width, Height) - if tonumber(Width) and tonumber(Height) then - self.Width = tonumber(Width) - self.Height = tonumber(Height) - else - return {Width = self.Width, Height = self.Height} - end -end - -function UIResRectangle:Colour(R, G, B, A) - if tonumber(R) or tonumber(G) or tonumber(B) or tonumber(A) then - self._Colour.R = tonumber(R) or 255 - self._Colour.B = tonumber(B) or 255 - self._Colour.G = tonumber(G) or 255 - self._Colour.A = tonumber(A) or 255 - else - return self._Colour - end -end - -function UIResRectangle:Draw() - local Position = self:Position() - local Size = self:Size() - Size.Width, Size.Height = FormatXWYH(Size.Width, Size.Height) - Position.X, Position.Y = FormatXWYH(Position.X, Position.Y) - DrawRect(Position.X + Size.Width * 0.5, Position.Y + Size.Height * 0.5, Size.Width, Size.Height, self._Colour.R, self._Colour.G, self._Colour.B, self._Colour.A) -end - -function DrawRectangle(X, Y, Width, Height, R, G, B, A) - local X, Y, Width, Height = X or 0, Y or 0, Width or 0, Height or 0 - X, Y = FormatXWYH(X, Y) - Width, Height = FormatXWYH(Width, Height) - DrawRect(X + Width * 0.5, Y + Height * 0.5, Width, Height, tonumber(R) or 255, tonumber(G) or 255, tonumber(B) or 255, tonumber(A) or 255) -end - ---[[ - UIResText.lua - Elements ---]] - -function GetCharacterCount(str) - local characters = 0 - for c in str:gmatch("[%z\1-\127\194-\244][\128-\191]*") do - local a = c:byte(1, -1) - if a ~= nil then - characters = characters + 1 - end - end - return characters -end - -function GetByteCount(str) - local bytes = 0 - - for c in str:gmatch("[%z\1-\127\194-\244][\128-\191]*") do - local a,b,c,d = c:byte(1, -1) - if a ~= nil then - bytes = bytes + 1 - end - if b ~= nil then - bytes = bytes + 1 - end - if c ~= nil then - bytes = bytes + 1 - end - if d ~= nil then - bytes = bytes + 1 - end - end - return bytes -end - -function AddLongStringForAscii(str) - local maxbytelength = 99 - for i = 0, GetCharacterCount(str), 99 do - AddTextComponentSubstringPlayerName(string.sub(str, i, math.min(maxbytelength, GetCharacterCount(str) - i))) --needs changed - end -end - -function AddLongStringForUtf8(str) - local maxbytelength = 99 - local bytecount = GetByteCount(str) - - if bytecount < maxbytelength then - AddTextComponentSubstringPlayerName(str) - return - end - - local startIndex = 0 - - for i = 0, GetCharacterCount(str), 1 do - local length = i - startIndex - if GetByteCount(string.sub(str, startIndex, length)) > maxbytelength then - AddTextComponentSubstringPlayerName(string.sub(str, startIndex, length - 1)) - i = i - 1 - startIndex = startIndex + (length - 1) - end - end - AddTextComponentSubstringPlayerName(string.sub(str, startIndex, GetCharacterCount(str) - startIndex)) -end - -function AddLongString(str) - local bytecount = GetByteCount(str) - if bytecount == GetCharacterCount(str) then - AddLongStringForAscii(str) - else - AddLongStringForUtf8(str) - end -end - -function MeasureStringWidthNoConvert(str, font, scale) - BeginTextCommandWidth("STRING") - AddLongString(str) - SetTextFont(font or 0) - SetTextScale(1.0, scale or 0) - return EndTextCommandGetWidth(true) -end - -function MeasureStringWidth(str, font, scale) - return MeasureStringWidthNoConvert(str, font, scale) * 1920 -end - -function UIResText.New(Text, X, Y, Scale, R, G, B, A, Font, Alignment, DropShadow, Outline, WordWrap) - local _UIResText = { - _Text = tostring(Text) or "", - X = tonumber(X) or 0, - Y = tonumber(Y) or 0, - Scale = tonumber(Scale) or 0, - _Colour = {R = tonumber(R) or 255, G = tonumber(G) or 255, B = tonumber(B) or 255, A = tonumber(A) or 255}, - Font = tonumber(Font) or 0, - Alignment = Alignment or nil, - DropShadow = Dropshadow or nil, - Outline = Outline or nil, - WordWrap = tonumber(WordWrap) or 0, - } - return setmetatable(_UIResText, UIResText) -end - -function UIResText:Position(X, Y) - if tonumber(X) and tonumber(Y) then - self.X = tonumber(X) - self.Y = tonumber(Y) - else - return {X = self.X, Y = self.Y} - end -end - -function UIResText:Colour(R, G, B, A) - if tonumber(R) and tonumber(G) and tonumber(B) and tonumber(A) then - self._Colour.R = tonumber(R) - self._Colour.B = tonumber(B) - self._Colour.G = tonumber(G) - self._Colour.A = tonumber(A) - else - return self._Colour - end -end - -function UIResText:Text(Text) - if tostring(Text) and Text ~= nil then - self._Text = tostring(Text) - else - return self._Text - end -end - -function UIResText:Draw() - local Position = self:Position() - Position.X, Position.Y = FormatXWYH(Position.X, Position.Y) - - SetTextFont(self.Font) - SetTextScale(1.0, self.Scale) - SetTextColour(self._Colour.R, self._Colour.G, self._Colour.B, self._Colour.A) - - if self.DropShadow then - SetTextDropShadow() - end - if self.Outline then - SetTextOutline() - end - - if self.Alignment ~= nil then - if self.Alignment == 1 or self.Alignment == "Center" or self.Alignment == "Centre" then - SetTextCentre(true) - elseif self.Alignment == 2 or self.Alignment == "Right" then - SetTextRightJustify(true) - SetTextWrap(0, Position.X) - end - end - - if tonumber(self.WordWrap) then - if tonumber(self.WordWrap) ~= 0 then - SetTextWrap(Position.X, Position.X + (tonumber(self.WordWrap) / Resolution.Width)) - end - end - - BeginTextCommandDisplayText("STRING") - AddLongString(self._Text) - EndTextCommandDisplayText(Position.X, Position.Y) -end - -function RenderText(Text, X, Y, Font, Scale, R, G, B, A, Alignment, DropShadow, Outline, WordWrap) - local Text = tostring(Text) - local X, Y = FormatXWYH(X, Y) - SetTextFont(Font or 0) - SetTextScale(1.0, Scale or 0) - SetTextColour(R or 255, G or 255, B or 255, A or 255) - - if DropShadow then - SetTextDropShadow() - end - if Outline then - SetTextOutline() - end - - if Alignment ~= nil then - if Alignment == 1 or Alignment == "Center" or Alignment == "Centre" then - SetTextCentre(true) - elseif Alignment == 2 or Alignment == "Right" then - SetTextRightJustify(true) - SetTextWrap(0, X) - end - end - - if tonumber(WordWrap) then - if tonumber(WordWrap) ~= 0 then - WordWrap, _ = FormatXWYH(WordWrap, 0) - SetTextWrap(WordWrap, X - WordWrap) - end - end - - BeginTextCommandDisplayText("STRING") - AddLongString(Text) - EndTextCommandDisplayText(X, Y) -end - ---[[ - Sprite.lua - Elements ---]] - -function Sprite.New(TxtDictionary, TxtName, X, Y, Width, Height, Heading, R, G, B, A) - local _Sprite = { - TxtDictionary = tostring(TxtDictionary), - TxtName = tostring(TxtName), - X = tonumber(X) or 0, - Y = tonumber(Y) or 0, - Width = tonumber(Width) or 0, - Height = tonumber(Height) or 0, - Heading = tonumber(Heading) or 0, - _Colour = {R = tonumber(R) or 255, G = tonumber(G) or 255, B = tonumber(B) or 255, A = tonumber(A) or 255}, - } - return setmetatable(_Sprite, Sprite) -end - -function Sprite:Position(X, Y) - if tonumber(X) and tonumber(Y) then - self.X = tonumber(X) - self.Y = tonumber(Y) - else - return {X = self.X, Y = self.Y} - end -end - -function Sprite:Size(Width, Height) - if tonumber(Width) and tonumber(Width) then - self.Width = tonumber(Width) - self.Height = tonumber(Height) - else - return {Width = self.Width, Height = self.Height} - end -end - -function Sprite:Colour(R, G, B, A) - if tonumber(R) or tonumber(G) or tonumber(B) or tonumber(A) then - self._Colour.R = tonumber(R) or 255 - self._Colour.B = tonumber(B) or 255 - self._Colour.G = tonumber(G) or 255 - self._Colour.A = tonumber(A) or 255 - else - return self._Colour - end -end - -function Sprite:Draw() - if not HasStreamedTextureDictLoaded(self.TxtDictionary) then - RequestStreamedTextureDict(self.TxtDictionary, true) - end - local Position = self:Position() - local Size = self:Size() - Size.Width, Size.Height = FormatXWYH(Size.Width, Size.Height) - Position.X, Position.Y = FormatXWYH(Position.X, Position.Y) - DrawSprite(self.TxtDictionary, self.TxtName, Position.X + Size.Width * 0.5, Position.Y + Size.Height * 0.5, Size.Width, Size.Height, self.Heading, self._Colour.R, self._Colour.G, self._Colour.B, self._Colour.A) -end - -function DrawTexture(TxtDictionary, TxtName, X, Y, Width, Height, Heading, R, G, B, A) - if not HasStreamedTextureDictLoaded(tostring(TxtDictionary) or "") then - RequestStreamedTextureDict(tostring(TxtDictionary) or "", true) - end - local X, Y, Width, Height = X or 0, Y or 0, Width or 0, Height or 0 - X, Y = FormatXWYH(X, Y) - Width, Height = FormatXWYH(Width, Height) - DrawSprite(tostring(TxtDictionary) or "", tostring(TxtName) or "", X + Width * 0.5, Y + Height * 0.5, Width, Height, tonumber(Heading) or 0, tonumber(R) or 255, tonumber(G) or 255, tonumber(B) or 255, tonumber(A) or 255) -end - ---[[ - StringMeasurer.lua - Elements ---]] - -function MeasureString(str) - local output = 0 - for i = 1, GetCharacterCount(str), 1 do - if CharacterMap[string.sub(str, i, i)] then - output = output + CharacterMap[string.sub(str, i, i)] + 1 - end - end - return output -end - ---[[ - Badge.lua - Elements ---]] - -function GetBadgeTexture(Badge, Selected) - if BadgeTexture[Badge] then - return BadgeTexture[Badge](Selected) - else - return "" - end -end - -function GetBadgeDictionary(Badge, Selected) - if BadgeDictionary[Badge] then - return BadgeDictionary[Badge](Selected) - else - return "commonmenu" - end -end - -function GetBadgeColour(Badge, Selected) - if BadgeColour[Badge] then - return BadgeColour[Badge](Selected) - else - return 255, 255, 255, 255 - end -end - ---[[ - Colours.lua - Elements ---]] - ---[[ - UIMenuItem.lua - Items ---]] - -function UIMenuItem.New(Text, Description) - _UIMenuItem = { - Rectangle = UIResRectangle.New(0, 0, 431, 38, 255, 255, 255, 20), - Text = UIResText.New(tostring(Text) or "", 8, 0, 0.33, 245, 245, 245, 255, 0), - _Description = tostring(Description) or ""; - SelectedSprite = Sprite.New("commonmenu", "gradient_nav", 0, 0, 431, 38), - LeftBadge = { Sprite = Sprite.New("commonmenu", "", 0, 0, 40, 40), Badge = 0}, - RightBadge = { Sprite = Sprite.New("commonmenu", "", 0, 0, 40, 40), Badge = 0}, - Label = { - Text = UIResText.New("", 0, 0, 0.35, 245, 245, 245, 255, 0, "Right"), - MainColour = {R = 255, G = 255, B = 255, A = 255}, - HighlightColour = {R = 0, G = 0, B = 0, A = 255}, - }, - _Selected = false, - _Hovered = false, - _Enabled = true, - _Offset = {X = 0, Y = 0}, - ParentMenu = nil, - Panels = {}, - Activated = function(menu, item, panels) end, - ActivatedPanel = function(menu, item, panel, panelvalue) end, - } - return setmetatable(_UIMenuItem, UIMenuItem) -end - -function UIMenuItem:SetParentMenu(Menu) - if Menu ~= nil and Menu() == "UIMenu" then - self.ParentMenu = Menu - else - return self.ParentMenu - end -end - -function UIMenuItem:Selected(bool) - if bool ~= nil then - self._Selected = tobool(bool) - else - return self._Selected - end -end - -function UIMenuItem:Hovered(bool) - if bool ~= nil then - self._Hovered = tobool(bool) - else - return self._Hovered - end -end - -function UIMenuItem:Enabled(bool) - if bool ~= nil then - self._Enabled = tobool(bool) - else - return self._Enabled - end -end - -function UIMenuItem:Description(str) - if tostring(str) and str ~= nil then - self._Description = tostring(str) - else - return self._Description - end -end - -function UIMenuItem:Offset(X, Y) - if tonumber(X) or tonumber(Y) then - if tonumber(X) then - self._Offset.X = tonumber(X) - end - if tonumber(Y) then - self._Offset.Y = tonumber(Y) - end - else - return self._Offset - end -end - -function UIMenuItem:Position(Y) - if tonumber(Y) then - self.Rectangle:Position(self._Offset.X, Y + 144 + self._Offset.Y) - self.SelectedSprite:Position(0 + self._Offset.X, Y + 144 + self._Offset.Y) - self.Text:Position(8 + self._Offset.X, Y + 147 + self._Offset.Y) - self.LeftBadge.Sprite:Position(0 + self._Offset.X, Y + 142 + self._Offset.Y) - self.RightBadge.Sprite:Position(385 + self._Offset.X, Y + 142 + self._Offset.Y) - self.Label.Text:Position(420 + self._Offset.X, Y + 148 + self._Offset.Y) - end -end - -function UIMenuItem:RightLabel(Text, MainColour, HighlightColour) - if tostring(Text) and Text ~= nil then - if type(MainColour) == "table" then - self.Label.MainColour = MainColour - end - if type(HighlightColour) == "table" then - self.Label.HighlightColour = HighlightColour - end - self.Label.Text:Text(tostring(Text)) - else - return self.Label.Text:Text() - end -end - -function UIMenuItem:SetLeftBadge(Badge) - if tonumber(Badge) then - self.LeftBadge.Badge = tonumber(Badge) - end -end - -function UIMenuItem:SetRightBadge(Badge) - if tonumber(Badge) then - self.RightBadge.Badge = tonumber(Badge) - end -end - -function UIMenuItem:Text(Text) - if tostring(Text) and Text ~= nil then - self.Text:Text(tostring(Text)) - else - return self.Text:Text() - end -end - -function UIMenuItem:AddPanel(Panel) - if Panel() == "UIMenuPanel" then - table.insert(self.Panels, Panel) - Panel:SetParentItem(self) - end -end - -function UIMenuItem:RemovePanelAt(Index) - if tonumber(Index) then - if self.Panels[Index] then - table.remove(self.Panels, tonumber(Index)) - end - end -end - -function UIMenuItem:FindPanelIndex(Panel) - if Panel() == "UIMenuPanel" then - for Index = 1, #self.Panels do - if self.Panels[Index] == Panel then - return Index - end - end - end - return nil -end - -function UIMenuItem:FindPanelItem() - for Index = #self.Items, 1, -1 do - if self.Items[Index].Panel then - return Index - end - end - return nil -end - -function UIMenuItem:Draw() - self.Rectangle:Size(431 + self.ParentMenu.WidthOffset, self.Rectangle.Height) - self.SelectedSprite:Size(431 + self.ParentMenu.WidthOffset, self.SelectedSprite.Height) - - if self._Hovered and not self._Selected then - self.Rectangle:Draw() - end - - if self._Selected then - self.SelectedSprite:Draw() - end - - if self._Enabled then - if self._Selected then - self.Text:Colour(0, 0, 0, 255) - self.Label.Text:Colour(self.Label.HighlightColour.R, self.Label.HighlightColour.G, self.Label.HighlightColour.B, self.Label.HighlightColour.A) - else - self.Text:Colour(245, 245, 245, 255) - self.Label.Text:Colour(self.Label.MainColour.R, self.Label.MainColour.G, self.Label.MainColour.B, self.Label.MainColour.A) - end - else - self.Text:Colour(163, 159, 148, 255) - self.Label.Text:Colour(163, 159, 148, 255) - end - - if self.LeftBadge.Badge == BadgeStyle.None then - self.Text:Position(8 + self._Offset.X, self.Text.Y) - else - self.Text:Position(35 + self._Offset.X, self.Text.Y) - self.LeftBadge.Sprite.TxtDictionary = GetBadgeDictionary(self.LeftBadge.Badge, self._Selected) - self.LeftBadge.Sprite.TxtName = GetBadgeTexture(self.LeftBadge.Badge, self._Selected) - self.LeftBadge.Sprite:Colour(GetBadgeColour(self.LeftBadge.Badge, self._Selected)) - self.LeftBadge.Sprite:Draw() - end - - if self.RightBadge.Badge ~= BadgeStyle.None then - self.RightBadge.Sprite:Position(385 + self._Offset.X + self.ParentMenu.WidthOffset, self.RightBadge.Sprite.Y) - self.RightBadge.Sprite.TxtDictionary = GetBadgeDictionary(self.RightBadge.Badge, self._Selected) - self.RightBadge.Sprite.TxtName = GetBadgeTexture(self.RightBadge.Badge, self._Selected) - self.RightBadge.Sprite:Colour(GetBadgeColour(self.RightBadge.Badge, self._Selected)) - self.RightBadge.Sprite:Draw() - end - - if self.Label.Text:Text() ~= "" and string.len(self.Label.Text:Text()) > 0 then - self.Label.Text:Position(420 + self._Offset.X + self.ParentMenu.WidthOffset, self.Label.Text.Y) - self.Label.Text:Draw() - end - - self.Text:Draw() -end - ---[[ - UIMenuCheckboxItem.lua - Items ---]] - -function UIMenuCheckboxItem.New(Text, Check, Description) - local _UIMenuCheckboxItem = { - Base = UIMenuItem.New(Text or "", Description or ""), - CheckedSprite = Sprite.New("commonmenu", "shop_box_blank", 410, 95, 50, 50), - Checked = tobool(Check), - CheckboxEvent = function(menu, item, checked) end, - } - return setmetatable(_UIMenuCheckboxItem, UIMenuCheckboxItem) -end - -function UIMenuCheckboxItem:SetParentMenu(Menu) - if Menu() == "UIMenu" then - self.Base.ParentMenu = Menu - else - return self.Base.ParentMenu - end -end - -function UIMenuCheckboxItem:Position(Y) - if tonumber(Y) then - self.Base:Position(Y) - self.CheckedSprite:Position(380 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 138 + self.Base._Offset.Y) - end -end - -function UIMenuCheckboxItem:Selected(bool) - if bool ~= nil then - self.Base._Selected = tobool(bool) - else - return self.Base._Selected - end -end - -function UIMenuCheckboxItem:Hovered(bool) - if bool ~= nil then - self.Base._Hovered = tobool(bool) - else - return self.Base._Hovered - end -end - -function UIMenuCheckboxItem:Enabled(bool) - if bool ~= nil then - self.Base._Enabled = tobool(bool) - else - return self.Base._Enabled - end -end - -function UIMenuCheckboxItem:Description(str) - if tostring(str) and str ~= nil then - self.Base._Description = tostring(str) - else - return self.Base._Description - end -end - -function UIMenuCheckboxItem:Offset(X, Y) - if tonumber(X) or tonumber(Y) then - if tonumber(X) then - self.Base._Offset.X = tonumber(X) - end - if tonumber(Y) then - self.Base._Offset.Y = tonumber(Y) - end - else - return self.Base._Offset - end -end - -function UIMenuCheckboxItem:Text(Text) - if tostring(Text) and Text ~= nil then - self.Base.Text:Text(tostring(Text)) - else - return self.Base.Text:Text() - end -end - -function UIMenuCheckboxItem:SetLeftBadge() - error("This item does not support badges") -end - -function UIMenuCheckboxItem:SetRightBadge() - error("This item does not support badges") -end - -function UIMenuCheckboxItem:RightLabel() - error("This item does not support a right label") -end - -function UIMenuCheckboxItem:Draw() - self.Base:Draw() - self.CheckedSprite:Position(380 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.CheckedSprite.Y) - if self.Base:Selected() then - if self.Checked then - self.CheckedSprite.TxtName = "shop_box_tickb" - else - self.CheckedSprite.TxtName = "shop_box_blankb" - end - else - if self.Checked then - self.CheckedSprite.TxtName = "shop_box_tick" - else - self.CheckedSprite.TxtName = "shop_box_blank" - end - end - self.CheckedSprite:Draw() -end - ---[[ - UIMenuListItem.lua - Items ---]] - -function UIMenuListItem.New(Text, Items, Index, Description) - if type(Items) ~= "table" then Items = {} end - if Index == 0 then Index = 1 end - local _UIMenuListItem = { - Base = UIMenuItem.New(Text or "", Description or ""), - Items = Items, - LeftArrow = Sprite.New("commonmenu", "arrowleft", 110, 105, 30, 30), - RightArrow = Sprite.New("commonmenu", "arrowright", 280, 105, 30, 30), - ItemText = UIResText.New("", 290, 104, 0.35, 255, 255, 255, 255, 0, "Right"), - _Index = tonumber(Index) or 1, - Panels = {}, - OnListChanged = function(menu, item, newindex) end, - OnListSelected = function(menu, item, newindex) end, - } - return setmetatable(_UIMenuListItem, UIMenuListItem) -end - -function UIMenuListItem:SetParentMenu(Menu) - if Menu ~= nil and Menu() == "UIMenu" then - self.Base.ParentMenu = Menu - else - return self.Base.ParentMenu - end -end - -function UIMenuListItem:Position(Y) - if tonumber(Y) then - self.LeftArrow:Position(300 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 147 + Y + self.Base._Offset.Y) - self.RightArrow:Position(400 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 147 + Y + self.Base._Offset.Y) - self.ItemText:Position(300 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 147 + Y + self.Base._Offset.Y) - self.Base:Position(Y) - end -end - -function UIMenuListItem:Selected(bool) - if bool ~= nil then - self.Base._Selected = tobool(bool) - else - return self.Base._Selected - end -end - -function UIMenuListItem:Hovered(bool) - if bool ~= nil then - self.Base._Hovered = tobool(bool) - else - return self.Base._Hovered - end -end - -function UIMenuListItem:Enabled(bool) - if bool ~= nil then - self.Base._Enabled = tobool(bool) - else - return self.Base._Enabled - end -end - -function UIMenuListItem:Description(str) - if tostring(str) and str ~= nil then - self.Base._Description = tostring(str) - else - return self.Base._Description - end -end - -function UIMenuListItem:Offset(X, Y) - if tonumber(X) or tonumber(Y) then - if tonumber(X) then - self.Base._Offset.X = tonumber(X) - end - if tonumber(Y) then - self.Base._Offset.Y = tonumber(Y) - end - else - return self.Base._Offset - end -end - -function UIMenuListItem:Text(Text) - if tostring(Text) and Text ~= nil then - self.Base.Text:Text(tostring(Text)) - else - return self.Base.Text:Text() - end -end - -function UIMenuListItem:Index(Index) - if tonumber(Index) then - if tonumber(Index) > #self.Items then - self._Index = 1 - elseif tonumber(Index) < 1 then - self._Index = #self.Items - else - self._Index = tonumber(Index) - end - else - return self._Index - end -end - -function UIMenuListItem:ItemToIndex(Item) - for i = 1, #self.Items do - if type(Item) == type(self.Items[i]) and Item == self.Items[i] then - return i - elseif type(self.Items[i]) == "table" and (type(Item) == type(self.Items[i].Name) or type(Item) == type(self.Items[i].Value)) and (Item == self.Items[i].Name or Item == self.Items[i].Value) then - return i - end - end -end - -function UIMenuListItem:IndexToItem(Index) - if tonumber(Index) then - if tonumber(Index) == 0 then Index = 1 end - if self.Items[tonumber(Index)] then - return self.Items[tonumber(Index)] - end - end -end - -function UIMenuListItem:SetLeftBadge() - error("This item does not support badges") -end - -function UIMenuListItem:SetRightBadge() - error("This item does not support badges") -end - -function UIMenuListItem:RightLabel() - error("This item does not support a right label") -end - -function UIMenuListItem:AddPanel(Panel) - if Panel() == "UIMenuPanel" then - table.insert(self.Panels, Panel) - Panel:SetParentItem(self) - end -end - -function UIMenuListItem:RemovePanelAt(Index) - if tonumber(Index) then - if self.Panels[Index] then - table.remove(self.Panels, tonumber(Index)) - end - end -end - -function UIMenuListItem:FindPanelIndex(Panel) - if Panel() == "UIMenuPanel" then - for Index = 1, #self.Panels do - if self.Panels[Index] == Panel then - return Index - end - end - end - return nil -end - -function UIMenuListItem:FindPanelItem() - for Index = #self.Items, 1, -1 do - if self.Items[Index].Panel then - return Index - end - end - return nil -end - -function UIMenuListItem:Draw() - self.Base:Draw() - - if self:Enabled() then - if self:Selected() then - self.ItemText:Colour(0, 0, 0, 255) - self.LeftArrow:Colour(0, 0, 0, 255) - self.RightArrow:Colour(0, 0, 0, 255) - else - self.ItemText:Colour(245, 245, 245, 255) - self.LeftArrow:Colour(245, 245, 245, 255) - self.RightArrow:Colour(245, 245, 245, 255) - end - else - self.ItemText:Colour(163, 159, 148, 255) - self.LeftArrow:Colour(163, 159, 148, 255) - self.RightArrow:Colour(163, 159, 148, 255) - end - - local Text = (type(self.Items[self._Index]) == "table") and tostring(self.Items[self._Index].Name) or tostring(self.Items[self._Index]) - local Offset = MeasureStringWidth(Text, 0, 0.35) - - self.ItemText:Text(Text) - self.LeftArrow:Position(378 - Offset + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.LeftArrow.Y) - - if self:Selected() then - self.LeftArrow:Draw() - self.RightArrow:Draw() - self.ItemText:Position(403 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.ItemText.Y) - else - self.ItemText:Position(418 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.ItemText.Y) - end - - self.ItemText:Draw() -end - ---[[ - UIMenuSliderItem.lua - Items ---]] - -function UIMenuSliderItem.New(Text, Items, Index, Description, Divider) - if type(Items) ~= "table" then Items = {} end - if Index == 0 then Index = 1 end - local _UIMenuSliderItem = { - Base = UIMenuItem.New(Text or "", Description or ""), - Items = Items, - ShowDivider = tobool(Divider), - LeftArrow = Sprite.New("commonmenutu", "arrowleft", 0, 105, 15, 15), - RightArrow = Sprite.New("commonmenutu", "arrowright", 0, 105, 15, 15), - Background = UIResRectangle.New(0, 0, 150, 9, 15, 24, 33, 255), - Slider = UIResRectangle.New(0, 0, 75, 9, 72,109,149, 255), - Divider = UIResRectangle.New(0, 0, 2.5, 20, 245, 245, 245, 255), - _Index = tonumber(Index) or 1, - OnSliderChanged = function(menu, item, newindex) end, - OnSliderSelected = function(menu, item, newindex) end, - } - return setmetatable(_UIMenuSliderItem, UIMenuSliderItem) -end - -function UIMenuSliderItem:SetParentMenu(Menu) - if Menu() == "UIMenu" then - self.Base.ParentMenu = Menu - else - return self.Base.ParentMenu - end -end - -function UIMenuSliderItem:Position(Y) - if tonumber(Y) then - self.Background:Position(250 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 158.5 + self.Base._Offset.Y) - self.Slider:Position(250 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 158.5 + self.Base._Offset.Y) - self.Divider:Position(323.5 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 153 + self.Base._Offset.Y) - self.LeftArrow:Position(235 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 155.5 + Y + self.Base._Offset.Y) - self.RightArrow:Position(400 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 155.5 + Y + self.Base._Offset.Y) - self.Base:Position(Y) - end -end - -function UIMenuSliderItem:Selected(bool) - if bool ~= nil then - self.Base._Selected = tobool(bool) - else - return self.Base._Selected - end -end - -function UIMenuSliderItem:Hovered(bool) - if bool ~= nil then - self.Base._Hovered = tobool(bool) - else - return self.Base._Hovered - end -end - -function UIMenuSliderItem:Enabled(bool) - if bool ~= nil then - self.Base._Enabled = tobool(bool) - else - return self.Base._Enabled - end -end - -function UIMenuSliderItem:Description(str) - if tostring(str) and str ~= nil then - self.Base._Description = tostring(str) - else - return self.Base._Description - end -end - -function UIMenuSliderItem:Offset(X, Y) - if tonumber(X) or tonumber(Y) then - if tonumber(X) then - self.Base._Offset.X = tonumber(X) - end - if tonumber(Y) then - self.Base._Offset.Y = tonumber(Y) - end - else - return self.Base._Offset - end -end - -function UIMenuSliderItem:Text(Text) - if tostring(Text) and Text ~= nil then - self.Base.Text:Text(tostring(Text)) - else - return self.Base.Text:Text() - end -end - -function UIMenuSliderItem:Index(Index) - if tonumber(Index) then - if tonumber(Index) > #self.Items then - self._Index = 1 - elseif tonumber(Index) < 1 then - self._Index = #self.Items - else - self._Index = tonumber(Index) - end - else - return self._Index - end -end - -function UIMenuSliderItem:ItemToIndex(Item) - for i = 1, #self.Items do - if type(Item) == type(self.Items[i]) and Item == self.Items[i] then - return i - end - end -end - -function UIMenuSliderItem:IndexToItem(Index) - if tonumber(Index) then - if tonumber(Index) == 0 then Index = 1 end - if self.Items[tonumber(Index)] then - return self.Items[tonumber(Index)] - end - end -end - -function UIMenuSliderItem:SetLeftBadge() - error("This item does not support badges") -end - -function UIMenuSliderItem:SetRightBadge() - error("This item does not support badges") -end - -function UIMenuSliderItem:RightLabel() - error("This item does not support a right label") -end - -function UIMenuSliderItem:Draw() - self.Base:Draw() - - if self:Enabled() then - if self:Selected() then - self.LeftArrow:Colour(0, 0, 0, 255) - self.RightArrow:Colour(0, 0, 0, 255) - else - self.LeftArrow:Colour(245, 245, 245, 255) - self.RightArrow:Colour(245, 245, 245, 255) - end - else - self.LeftArrow:Colour(163, 159, 148, 255) - self.RightArrow:Colour(163, 159, 148, 255) - end - - local Offset = ((self.Background.Width - self.Slider.Width)/(#self.Items - 1)) * (self._Index-1) - - self.Slider:Position(250 + self.Base._Offset.X + Offset + self.Base.ParentMenu.WidthOffset, self.Slider.Y) - - if self:Selected() then - self.LeftArrow:Draw() - self.RightArrow:Draw() - end - - self.Background:Draw() - self.Slider:Draw() - if self.ShowDivider then - self.Divider:Draw() - end -end - ---[[ - UIMenuColouredItem.lua - Items ---]] - -function UIMenuColouredItem.New(Text, Description, MainColour, HighlightColour) - if type(Colour) ~= "table" then Colour = {R = 0, G = 0, B = 0, A = 255} end - if type(HighlightColour) ~= "table" then Colour = {R = 255, G = 255, B = 255, A = 255} end - local _UIMenuColouredItem = { - Base = UIMenuItem.New(Text or "", Description or ""), - Rectangle = UIResRectangle.New(0, 0, 431, 38, MainColour.R, MainColour.G, MainColour.B, MainColour.A), - MainColour = MainColour, - HighlightColour = HighlightColour, - Activated = function(menu, item) end, - } - _UIMenuColouredItem.Base.SelectedSprite:Colour(HighlightColour.R, HighlightColour.G, HighlightColour.B, HighlightColour.A) - return setmetatable(_UIMenuColouredItem, UIMenuColouredItem) -end - -function UIMenuColouredItem:SetParentMenu(Menu) - if Menu() == "UIMenu" then - self.Base.ParentMenu = Menu - else - return self.Base.ParentMenu - end -end - -function UIMenuColouredItem:Position(Y) - if tonumber(Y) then - self.Base:Position(Y) - self.Rectangle:Position(self.Base._Offset.X, Y + 144 + self.Base._Offset.Y) - end -end - -function UIMenuColouredItem:Selected(bool) - if bool ~= nil then - self.Base._Selected = tobool(bool) - else - return self.Base._Selected - end -end - -function UIMenuColouredItem:Hovered(bool) - if bool ~= nil then - self.Base._Hovered = tobool(bool) - else - return self.Base._Hovered - end -end - -function UIMenuColouredItem:Enabled(bool) - if bool ~= nil then - self.Base._Enabled = tobool(bool) - else - return self.Base._Enabled - end -end - -function UIMenuColouredItem:Description(str) - if tostring(str) and str ~= nil then - self.Base._Description = tostring(str) - else - return self.Base._Description - end -end - -function UIMenuColouredItem:Offset(X, Y) - if tonumber(X) or tonumber(Y) then - if tonumber(X) then - self.Base._Offset.X = tonumber(X) - end - if tonumber(Y) then - self.Base._Offset.Y = tonumber(Y) - end - else - return self.Base._Offset - end -end - -function UIMenuColouredItem:Text(Text) - if tostring(Text) and Text ~= nil then - self.Base.Text:Text(tostring(Text)) - else - return self.Base.Text:Text() - end -end - -function UIMenuColouredItem:RightLabel(Text, MainColour, HighlightColour) - if tostring(Text) and Text ~= nil then - if type(MainColour) == "table" then - self.Base.Label.MainColour = MainColour - end - if type(HighlightColour) == "table" then - self.Base.Label.HighlightColour = HighlightColour - end - self.Base.Label.Text:Text(tostring(Text)) - else - return self.Base.Label.Text:Text() - end -end - -function UIMenuColouredItem:SetLeftBadge(Badge) - if tonumber(Badge) then - self.Base.LeftBadge.Badge = tonumber(Badge) - end -end - -function UIMenuColouredItem:SetRightBadge(Badge) - if tonumber(Badge) then - self.Base.RightBadge.Badge = tonumber(Badge) - end -end - -function UIMenuColouredItem:Draw() - self.Rectangle:Size(431 + self.ParentMenu.WidthOffset, self.Rectangle.Height) - self.Rectangle:Draw() - self.Base:Draw() -end - ---[[ - UIMenuProgressItem.lua - Items ---]] - -function UIMenuProgressItem.New(Text, Items, Index, Description, Counter) - if type(Items) ~= "table" then Items = {} end - if Index == 0 then Index = 1 end - local _UIMenuProgressItem = { - Base = UIMenuItem.New(Text or "", Description or ""), - Data = { - Items = Items, - Counter = tobool(Counter), - Max = 407.5, - Index = tonumber(Index) or 1, - }, - Background = UIResRectangle.New(0, 0, 415, 20), - Bar = UIResRectangle.New(0, 0, 407.5, 12.5), - OnProgressChanged = function(menu, item, newindex) end, - OnProgressSelected = function(menu, item, newindex) end, - } - - _UIMenuProgressItem.Base.Rectangle.Height = 60 - _UIMenuProgressItem.Base.SelectedSprite.Height = 60 - - if _UIMenuProgressItem.Data.Counter then - _UIMenuProgressItem.Base:RightLabel(_UIMenuProgressItem.Data.Index.."/"..#_UIMenuProgressItem.Data.Items) - else - _UIMenuProgressItem.Base:RightLabel((type(_UIMenuProgressItem.Data.Items[_UIMenuProgressItem.Data.Index]) == "table") and tostring(_UIMenuProgressItem.Data.Items[_UIMenuProgressItem.Data.Index].Name) or tostring(_UIMenuProgressItem.Data.Items[_UIMenuProgressItem.Data.Index])) - end - - _UIMenuProgressItem.Bar.Width = _UIMenuProgressItem.Data.Index/#_UIMenuProgressItem.Data.Items * _UIMenuProgressItem.Data.Max - - return setmetatable(_UIMenuProgressItem, UIMenuProgressItem) -end - -function UIMenuProgressItem:SetParentMenu(Menu) - if Menu() == "UIMenu" then - self.Base.ParentMenu = Menu - else - return self.Base.ParentMenu - end -end - -function UIMenuProgressItem:Position(Y) - if tonumber(Y) then - self.Base:Position(Y) - self.Background:Position(8 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 177 + Y + self.Base._Offset.Y) - self.Bar:Position(11.75 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 180.75 + Y + self.Base._Offset.Y) - end -end - -function UIMenuProgressItem:Selected(bool) - if bool ~= nil then - self.Base._Selected = tobool(bool) - else - return self.Base._Selected - end -end - -function UIMenuProgressItem:Hovered(bool) - if bool ~= nil then - self.Base._Hovered = tobool(bool) - else - return self.Base._Hovered - end -end - -function UIMenuProgressItem:Enabled(bool) - if bool ~= nil then - self.Base._Enabled = tobool(bool) - else - return self.Base._Enabled - end -end - -function UIMenuProgressItem:Description(str) - if tostring(str) and str ~= nil then - self.Base._Description = tostring(str) - else - return self.Base._Description - end -end - -function UIMenuProgressItem:Offset(X, Y) - if tonumber(X) or tonumber(Y) then - if tonumber(X) then - self.Base._Offset.X = tonumber(X) - end - if tonumber(Y) then - self.Base._Offset.Y = tonumber(Y) - end - else - return self.Base._Offset - end -end - -function UIMenuProgressItem:Text(Text) - if tostring(Text) and Text ~= nil then - self.Base.Text:Text(tostring(Text)) - else - return self.Base.Text:Text() - end -end - -function UIMenuProgressItem:Index(Index) - if tonumber(Index) then - if tonumber(Index) > #self.Data.Items then - self.Data.Index = 1 - elseif tonumber(Index) < 1 then - self.Data.Index = #self.Data.Items - else - self.Data.Index = tonumber(Index) - end - - if self.Data.Counter then - self.Base:RightLabel(self.Data.Index.."/"..#self.Data.Items) - else - self.Base:RightLabel((type(self.Data.Items[self.Data.Index]) == "table") and tostring(self.Data.Items[self.Data.Index].Name) or tostring(self.Data.Items[self.Data.Index])) - end - - self.Bar.Width = self.Data.Index/#self.Data.Items * self.Data.Max - else - return self.Data.Index - end -end - -function UIMenuProgressItem:ItemToIndex(Item) - for i = 1, #self.Data.Items do - if type(Item) == type(self.Data.Items[i]) and Item == self.Data.Items[i] then - return i - elseif type(self.Data.Items[i]) == "table" and (type(Item) == type(self.Data.Items[i].Name) or type(Item) == type(self.Data.Items[i].Value)) and (Item == self.Data.Items[i].Name or Item == self.Data.Items[i].Value) then - return i - end - end -end - -function UIMenuProgressItem:IndexToItem(Index) - if tonumber(Index) then - if tonumber(Index) == 0 then Index = 1 end - if self.Data.Items[tonumber(Index)] then - return self.Data.Items[tonumber(Index)] - end - end -end - -function UIMenuProgressItem:SetLeftBadge() - error("This item does not support badges") -end - -function UIMenuProgressItem:SetRightBadge() - error("This item does not support badges") -end - -function UIMenuProgressItem:RightLabel() - error("This item does not support a right label") -end - -function UIMenuProgressItem:CalculateProgress(CursorX) - local Progress = CursorX - self.Bar.X - self:Index(math.round(#self.Data.Items * (((Progress >= 0 and Progress <= self.Data.Max) and Progress or ((Progress < 0) and 0 or self.Data.Max))/self.Data.Max))) -end - -function UIMenuProgressItem:Draw() - self.Base:Draw() - - if self.Base._Selected then - self.Background:Colour(table.unpack(Colours.Black)) - self.Bar:Colour(table.unpack(Colours.White)) - else - self.Background:Colour(table.unpack(Colours.White)) - self.Bar:Colour(table.unpack(Colours.Black)) - end - - self.Background:Draw() - self.Bar:Draw() -end - ---[[ - UIMenuHeritageWindow.lua - Windows ---]] - -function UIMenuHeritageWindow.New(Mum, Dad) - if not tonumber(Mum) then Mum = 0 end - if not (Mum >= 0 and Mum <= 21) then Mum = 0 end - if not tonumber(Dad) then Dad = 0 end - if not (Dad >= 0 and Dad <= 23) then Dad = 0 end - _UIMenuHeritageWindow = { - Background = Sprite.New("pause_menu_pages_char_mom_dad", "mumdadbg", 0, 0, 431, 228), -- Background is required, must be a sprite or a rectangle. - MumSprite = Sprite.New("char_creator_portraits", ((Mum < 21) and "female_"..Mum or "special_female_"..(tonumber(string.sub(Mum, 2, 2)) - 1)), 0, 0, 228, 228), - DadSprite = Sprite.New("char_creator_portraits", ((Dad < 21) and "male_"..Dad or "special_male_"..(tonumber(string.sub(Dad, 2, 2)) - 1)), 0, 0, 228, 228), - Mum = Mum, - Dad = Dad, - _Offset = {X = 0, Y = 0}, -- required - ParentMenu = nil, -- required - } - return setmetatable(_UIMenuHeritageWindow, UIMenuHeritageWindow) -end - -function UIMenuHeritageWindow:SetParentMenu(Menu) -- required - if Menu() == "UIMenu" then - self.ParentMenu = Menu - else - return self.ParentMenu - end -end - -function UIMenuHeritageWindow:Offset(X, Y) -- required - if tonumber(X) or tonumber(Y) then - if tonumber(X) then - self._Offset.X = tonumber(X) - end - if tonumber(Y) then - self._Offset.Y = tonumber(Y) - end - else - return self._Offset - end -end - -function UIMenuHeritageWindow:Position(Y) -- required - if tonumber(Y) then - self.Background:Position(self._Offset.X, 144 + Y + self._Offset.Y) - self.MumSprite:Position(self._Offset.X + (self.ParentMenu.WidthOffset/2) + 25, 144 + Y + self._Offset.Y) - self.DadSprite:Position(self._Offset.X + (self.ParentMenu.WidthOffset/2) + 195, 144 + Y + self._Offset.Y) - end -end - -function UIMenuHeritageWindow:Index(Mum, Dad) - if not tonumber(Mum) then Mum = self.Mum end - if not (Mum >= 0 and Mum <= 21) then Mum = self.Mum end - if not tonumber(Dad) then Dad = self.Dad end - if not (Dad >= 0 and Dad <= 23) then Dad = self.Dad end - - self.Mum = Mum - self.Dad = Dad - - self.MumSprite.TxtName = ((self.Mum < 21) and "female_"..self.Mum or "special_female_"..(tonumber(string.sub(Mum, 2, 2)) - 1)) - self.DadSprite.TxtName = ((self.Dad < 21) and "male_"..self.Dad or "special_male_"..(tonumber(string.sub(Dad, 2, 2)) - 1)) -end - -function UIMenuHeritageWindow:Draw() -- required - self.Background:Size(431 + self.ParentMenu.WidthOffset, 228) - self.Background:Draw() - self.DadSprite:Draw() - self.MumSprite:Draw() -end - ---[[ - UIMenuGridPanel.lua - Panels ---]] - -UIMenuGridPanel = setmetatable({}, UIMenuGridPanel) -UIMenuGridPanel.__index = UIMenuGridPanel -UIMenuGridPanel.__call = function() return "UIMenuPanel", "UIMenuGridPanel" end - -function UIMenuGridPanel.New(TopText, LeftText, RightText, BottomText) - _UIMenuGridPanel = { - Data = { - Enabled = true, - }, - Background = Sprite.New("commonmenu", "gradient_bgd", 0, 0, 431, 275), - Grid = Sprite.New("pause_menu_pages_char_mom_dad", "nose_grid", 0, 0, 200, 200, 0), - Circle = Sprite.New("mpinventory","in_world_circle", 0, 0, 20, 20, 0), - Audio = {Slider = "CONTINUOUS_SLIDER", Library = "HUD_FRONTEND_DEFAULT_SOUNDSET", Id = nil}, - ParentItem = nil, - Text = { - Top = UIResText.New(TopText or "Top", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), - Left = UIResText.New(LeftText or "Left", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), - Right = UIResText.New(RightText or "Right", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), - Bottom = UIResText.New(BottomText or "Bottom", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), - }, - } - return setmetatable(_UIMenuGridPanel, UIMenuGridPanel) -end - -function UIMenuGridPanel:SetParentItem(Item) -- required - if Item() == "UIMenuItem" then - self.ParentItem = Item - else - return self.ParentItem - end -end - -function UIMenuGridPanel:Enabled(Enabled) - if type(Enabled) == "boolean" then - self.Data.Enabled = Enabled - else - return self.Data.Enabled - end -end - -function UIMenuGridPanel:CirclePosition(X, Y) - if tonumber(X) and tonumber(Y) then - self.Circle.X = (self.Grid.X + 20) + ((self.Grid.Width - 40) * ((X >= 0.0 and X <= 1.0) and X or 0.0)) - (self.Circle.Width/2) - self.Circle.Y = (self.Grid.Y + 20) + ((self.Grid.Height - 40) * ((Y >= 0.0 and Y <= 1.0) and Y or 0.0)) - (self.Circle.Height/2) - else - return math.round((self.Circle.X - (self.Grid.X + 20) + (self.Circle.Width/2))/(self.Grid.Width - 40), 2), math.round((self.Circle.Y - (self.Grid.Y + 20) + (self.Circle.Height/2))/(self.Grid.Height - 40), 2) - end -end - -function UIMenuGridPanel:Position(Y) -- required - if tonumber(Y) then - local ParentOffsetX, ParentOffsetWidth = self.ParentItem:Offset().X, self.ParentItem:SetParentMenu().WidthOffset - - self.Background:Position(ParentOffsetX, Y) - self.Grid:Position(ParentOffsetX + 115.5 + (ParentOffsetWidth/2), 37.5 + Y) - self.Text.Top:Position(ParentOffsetX + 215.5 + (ParentOffsetWidth/2), 5 + Y) - self.Text.Left:Position(ParentOffsetX + 57.75 + (ParentOffsetWidth/2), 120 + Y) - self.Text.Right:Position(ParentOffsetX + 373.25 + (ParentOffsetWidth/2), 120 + Y) - self.Text.Bottom:Position(ParentOffsetX + 215.5 + (ParentOffsetWidth/2), 240 + Y) - - if not self.CircleLocked then - self.CircleLocked = true - self:CirclePosition(0.5, 0.5) - end - end -end - -function UIMenuGridPanel:UpdateParent(X, Y) - local _, ParentType = self.ParentItem() - if ParentType == "UIMenuListItem" then - local PanelItemIndex = self.ParentItem:FindPanelItem() - if PanelItemIndex then - self.ParentItem.Items[PanelItemIndex].Value[self.ParentItem:FindPanelIndex(self)] = {X = X, Y = Y} - self.ParentItem:Index(PanelItemIndex) - self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) - self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) - else - local PanelIndex = self.ParentItem:FindPanelIndex(self) - for Index = 1, #self.ParentItem.Items do - if type(self.ParentItem.Items[Index]) == "table" then - if not self.ParentItem.Items[Index].Panels then self.ParentItem.Items[Index].Panels = {} end - self.ParentItem.Items[Index].Panels[PanelIndex] = {X = X, Y = Y} - else - self.ParentItem.Items[Index] = {Name = tostring(self.ParentItem.Items[Index]), Value = self.ParentItem.Items[Index], Panels = {[PanelIndex] = {X = X, Y = Y}}} - end - end - self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) - self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) - end - elseif ParentType == "UIMenuItem" then - self.ParentItem.ActivatedPanel(self.ParentItem.ParentMenu, self.ParentItem, self, {X = X, Y = Y}) - end -end - -function UIMenuGridPanel:Functions() - local SafeZone = {X = 0, Y = 0} - if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then - SafeZone = GetSafeZoneBounds() - end - - if IsMouseInBounds(self.Grid.X + 20 + SafeZone.X, self.Grid.Y + 20 + SafeZone.Y, self.Grid.Width - 40, self.Grid.Height - 40) then - if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then - if not self.Pressed then - self.Pressed = true - Citizen.CreateThread(function() - self.Audio.Id = GetSoundId() - PlaySoundFrontend(self.Audio.Id, self.Audio.Slider, self.Audio.Library, 1) - while IsDisabledControlPressed(0, 24) and IsMouseInBounds(self.Grid.X + 20 + SafeZone.X, self.Grid.Y + 20 + SafeZone.Y, self.Grid.Width - 40, self.Grid.Height - 40) do - Citizen.Wait(0) - local CursorX, CursorY = math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X - (self.Circle.Width/2), math.round(GetControlNormal(0, 240) * 1080) - SafeZone.Y - (self.Circle.Height/2) - - self.Circle:Position(((CursorX > (self.Grid.X + 10 + self.Grid.Width - 40)) and (self.Grid.X + 10 + self.Grid.Width - 40) or ((CursorX < (self.Grid.X + 20 - (self.Circle.Width/2))) and (self.Grid.X + 20 - (self.Circle.Width/2)) or CursorX)), ((CursorY > (self.Grid.Y + 10 + self.Grid.Height - 40)) and (self.Grid.Y + 10 + self.Grid.Height - 40) or ((CursorY < (self.Grid.Y + 20 - (self.Circle.Height/2))) and (self.Grid.Y + 20 - (self.Circle.Height/2)) or CursorY))) - end - StopSound(self.Audio.Id) - ReleaseSoundId(self.Audio.Id) - self.Pressed = false - end) - Citizen.CreateThread(function() - while IsDisabledControlPressed(0, 24) and IsMouseInBounds(self.Grid.X + 20 + SafeZone.X, self.Grid.Y + 20 + SafeZone.Y, self.Grid.Width - 40, self.Grid.Height - 40) do - Citizen.Wait(75) - local ResultX, ResultY = math.round((self.Circle.X - (self.Grid.X + 20) + (self.Circle.Width/2))/(self.Grid.Width - 40), 2), math.round((self.Circle.Y - (self.Grid.Y + 20) + (self.Circle.Height/2))/(self.Grid.Height - 40), 2) - - self:UpdateParent((((ResultX >= 0.0 and ResultX <= 1.0) and ResultX or ((ResultX <= 0) and 0.0) or 1.0) * 2) - 1, (((ResultY >= 0.0 and ResultY <= 1.0) and ResultY or ((ResultY <= 0) and 0.0) or 1.0) * 2) - 1) - end - end) - end - end - end -end - -function UIMenuGridPanel:Draw() -- required - if self.Data.Enabled then - self.Background:Size(431 + self.ParentItem:SetParentMenu().WidthOffset, 275) - - self.Background:Draw() - self.Grid:Draw() - self.Circle:Draw() - self.Text.Top:Draw() - self.Text.Left:Draw() - self.Text.Right:Draw() - self.Text.Bottom:Draw() - self:Functions() - end -end - ---[[ - UIMenuColourPanel.lua - Panels ---]] - -UIMenuColourPanel = setmetatable({}, UIMenuColourPanel) -UIMenuColourPanel.__index = UIMenuColourPanel -UIMenuColourPanel.__call = function() return "UIMenuPanel", "UIMenuColourPanel" end - -function UIMenuColourPanel.New(Title, Colours) - _UIMenuColourPanel = { - Data = { - Pagination = { - Min = 1, - Max = 8, - Total = 8, - }, - Index = 1000, - Items = Colours, - Title = Title or "Title", - Enabled = true, - Value = 1, - }, - Background = Sprite.New("commonmenu", "gradient_bgd", 0, 0, 431, 112), - Bar = {}, - LeftArrow = Sprite.New("commonmenu", "arrowleft", 0, 0, 30, 30), - RightArrow = Sprite.New("commonmenu", "arrowright", 0, 0, 30, 30), - SelectedRectangle = UIResRectangle.New(0, 0, 44.5, 8), - Text = UIResText.New(Title.." (1 of "..#Colours..")" or "Title".." (1 of "..#Colours..")", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), - ParentItem = nil, - } - - for Index = 1, #Colours do - if Index < 10 then - table.insert(_UIMenuColourPanel.Bar, UIResRectangle.New(0, 0, 44.5, 44.5, table.unpack(Colours[Index]))) - else - break - end - end - - if #_UIMenuColourPanel.Data.Items ~= 0 then - _UIMenuColourPanel.Data.Index = 1000 - (1000 % #_UIMenuColourPanel.Data.Items) - _UIMenuColourPanel.Data.Pagination.Max = _UIMenuColourPanel.Data.Pagination.Total + 1 - _UIMenuColourPanel.Data.Pagination.Min = 0 - end - return setmetatable(_UIMenuColourPanel, UIMenuColourPanel) -end - -function UIMenuColourPanel:SetParentItem(Item) -- required - if Item() == "UIMenuItem" then - self.ParentItem = Item - else - return self.ParentItem - end -end - -function UIMenuColourPanel:Enabled(Enabled) - if type(Enabled) == "boolean" then - self.Data.Enabled = Enabled - else - return self.Data.Enabled - end -end - -function UIMenuColourPanel:Position(Y) -- required - if tonumber(Y) then - local ParentOffsetX, ParentOffsetWidth = self.ParentItem:Offset().X, self.ParentItem:SetParentMenu().WidthOffset - - self.Background:Position(ParentOffsetX, Y) - for Index = 1, #self.Bar do - self.Bar[Index]:Position(15 + (44.5 * (Index - 1)) + ParentOffsetX + (ParentOffsetWidth/2), 55 + Y) - end - self.SelectedRectangle:Position(15 + (44.5 * ((self:CurrentSelection() - self.Data.Pagination.Min) - 1)) + ParentOffsetX + (ParentOffsetWidth/2), 47 + Y) - self.LeftArrow:Position(7.5 + ParentOffsetX + (ParentOffsetWidth/2), 15 + Y) - self.RightArrow:Position(393.5 + ParentOffsetX + (ParentOffsetWidth/2), 15 + Y) - self.Text:Position(215.5 + ParentOffsetX + (ParentOffsetWidth/2), 15 + Y) - end -end - -function UIMenuColourPanel:CurrentSelection(value, PreventUpdate) - if tonumber(value) then - if #self.Data.Items == 0 then - self.Data.Index = 0 - end - - self.Data.Index = 1000000 - (1000000 % #self.Data.Items) + tonumber(value) - - if self:CurrentSelection() > self.Data.Pagination.Max then - self.Data.Pagination.Min = self:CurrentSelection() - (self.Data.Pagination.Total + 1) - self.Data.Pagination.Max = self:CurrentSelection() - elseif self:CurrentSelection() < self.Data.Pagination.Min then - self.Data.Pagination.Min = self:CurrentSelection() - 1 - self.Data.Pagination.Max = self:CurrentSelection() + (self.Data.Pagination.Total + 1) - end - - self:UpdateSelection(PreventUpdate) - else - if #self.Data.Items == 0 then - return 1 - else - if self.Data.Index % #self.Data.Items == 0 then - return 1 - else - return self.Data.Index % #self.Data.Items + 1 - end - end - end -end - -function UIMenuColourPanel:UpdateParent(Colour) - local _, ParentType = self.ParentItem() - if ParentType == "UIMenuListItem" then - local PanelItemIndex = self.ParentItem:FindPanelItem() - local PanelIndex = self.ParentItem:FindPanelIndex(self) - if PanelItemIndex then - self.ParentItem.Items[PanelItemIndex].Value[PanelIndex] = Colour - self.ParentItem:Index(PanelItemIndex) - self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) - self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) - else - for Index = 1, #self.ParentItem.Items do - if type(self.ParentItem.Items[Index]) == "table" then - if not self.ParentItem.Items[Index].Panels then self.ParentItem.Items[Index].Panels = {} end - self.ParentItem.Items[Index].Panels[PanelIndex] = Colour - else - self.ParentItem.Items[Index] = {Name = tostring(self.ParentItem.Items[Index]), Value = self.ParentItem.Items[Index], Panels = {[PanelIndex] = Colour}} - end - end - self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) - self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) - end - elseif ParentType == "UIMenuItem" then - self.ParentItem.ActivatedPanel(self.ParentItem.ParentMenu, self.ParentItem, self, Colour) - end -end - -function UIMenuColourPanel:UpdateSelection(PreventUpdate) - local CurrentSelection = self:CurrentSelection() - if not PreventUpdate then - self:UpdateParent(CurrentSelection) - end - self.SelectedRectangle:Position(15 + (44.5 * ((CurrentSelection - self.Data.Pagination.Min) - 1)) + self.ParentItem:Offset().X, self.SelectedRectangle.Y) - for Index = 1, 9 do - self.Bar[Index]:Colour(table.unpack(self.Data.Items[self.Data.Pagination.Min + Index])) - end - self.Text:Text(self.Data.Title.." ("..CurrentSelection.." of "..#self.Data.Items..")") -end - -function UIMenuColourPanel:Functions() - - local SafeZone = {X = 0, Y = 0} - if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then - SafeZone = GetSafeZoneBounds() - end - - - if IsMouseInBounds(self.LeftArrow.X + SafeZone.X, self.LeftArrow.Y + SafeZone.Y, self.LeftArrow.Width, self.LeftArrow.Height) then - if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then - if #self.Data.Items > self.Data.Pagination.Total + 1 then - if self:CurrentSelection() <= self.Data.Pagination.Min + 1 then - if self:CurrentSelection() == 1 then - self.Data.Pagination.Min = #self.Data.Items - (self.Data.Pagination.Total + 1) - self.Data.Pagination.Max = #self.Data.Items - self.Data.Index = 1000 - (1000 % #self.Data.Items) - self.Data.Index = self.Data.Index + (#self.Data.Items - 1) - self:UpdateSelection() - else - self.Data.Pagination.Min = self.Data.Pagination.Min - 1 - self.Data.Pagination.Max = self.Data.Pagination.Max - 1 - self.Data.Index = self.Data.Index - 1 - self:UpdateSelection() - end - else - self.Data.Index = self.Data.Index - 1 - self:UpdateSelection() - end - else - self.Data.Index = self.Data.Index - 1 - self:UpdateSelection() - end - end - end - - if IsMouseInBounds(self.RightArrow.X + SafeZone.X, self.RightArrow.Y + SafeZone.Y, self.RightArrow.Width, self.RightArrow.Height) then - if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then - if #self.Data.Items > self.Data.Pagination.Total + 1 then - if self:CurrentSelection() >= self.Data.Pagination.Max then - if self:CurrentSelection() == #self.Data.Items then - self.Data.Pagination.Min = 0 - self.Data.Pagination.Max = self.Data.Pagination.Total + 1 - self.Data.Index = 1000 - (1000 % #self.Data.Items) - self:UpdateSelection() - else - self.Data.Pagination.Max = self.Data.Pagination.Max + 1 - self.Data.Pagination.Min = self.Data.Pagination.Max - (self.Data.Pagination.Total + 1) - self.Data.Index = self.Data.Index + 1 - self:UpdateSelection() - end - else - self.Data.Index = self.Data.Index + 1 - self:UpdateSelection() - end - else - self.Data.Index = self.Data.Index + 1 - self:UpdateSelection() - end - end - end - - for Index = 1, #self.Bar do - if IsMouseInBounds(self.Bar[Index].X + SafeZone.X, self.Bar[Index].Y + SafeZone.Y, self.Bar[Index].Width, self.Bar[Index].Height) then - if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then - self:CurrentSelection(self.Data.Pagination.Min + Index - 1) - end - end - end -end - -function UIMenuColourPanel:Draw() -- required - if self.Data.Enabled then - self.Background:Size(431 + self.ParentItem:SetParentMenu().WidthOffset, 112) - - self.Background:Draw() - self.LeftArrow:Draw() - self.RightArrow:Draw() - self.Text:Draw() - self.SelectedRectangle:Draw() - for Index = 1, #self.Bar do - self.Bar[Index]:Draw() - end - self:Functions() - end -end - ---[[ - UIMenuPercentagePanel.lua - Panels ---]] - -UIMenuPercentagePanel = setmetatable({}, UIMenuPercentagePanel) -UIMenuPercentagePanel.__index = UIMenuPercentagePanel -UIMenuPercentagePanel.__call = function() return "UIMenuPanel", "UIMenuPercentagePanel" end - -function UIMenuPercentagePanel.New(MinText, MaxText) - _UIMenuPercentagePanel = { - Data = { - Enabled = true, - }, - Background = Sprite.New("commonmenu", "gradient_bgd", 0, 0, 431, 76), - ActiveBar = UIResRectangle.New(0, 0, 413, 10, 245, 245, 245, 255), - BackgroundBar = UIResRectangle.New(0, 0, 413, 10, 87, 87, 87, 255), - Text = { - Min = UIResText.New(MinText or "0%", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), - Max = UIResText.New("100%", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), - Title = UIResText.New(MaxText or "Opacity", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), - }, - Audio = {Slider = "CONTINUOUS_SLIDER", Library = "HUD_FRONTEND_DEFAULT_SOUNDSET", Id = nil}, - ParentItem = nil, - } - - return setmetatable(_UIMenuPercentagePanel, UIMenuPercentagePanel) -end - -function UIMenuPercentagePanel:SetParentItem(Item) -- required - if Item() == "UIMenuItem" then - self.ParentItem = Item - else - return self.ParentItem - end -end - -function UIMenuPercentagePanel:Enabled(Enabled) - if type(Enabled) == "boolean" then - self.Data.Enabled = Enabled - else - return self.Data.Enabled - end -end - -function UIMenuPercentagePanel:Position(Y) -- required - if tonumber(Y) then - local ParentOffsetX, ParentOffsetWidth = self.ParentItem:Offset().X, self.ParentItem:SetParentMenu().WidthOffset - self.Background:Position(ParentOffsetX, Y) - self.ActiveBar:Position(ParentOffsetX + (ParentOffsetWidth/2) + 9, 50 + Y) - self.BackgroundBar:Position(ParentOffsetX + (ParentOffsetWidth/2) + 9, 50 + Y) - self.Text.Min:Position(ParentOffsetX + (ParentOffsetWidth/2) + 25, 15 + Y) - self.Text.Max:Position(ParentOffsetX + (ParentOffsetWidth/2) + 398, 15 + Y) - self.Text.Title:Position(ParentOffsetX + (ParentOffsetWidth/2) + 215.5, 15 + Y) - end -end - -function UIMenuPercentagePanel:Percentage(Value) - if tonumber(Value) then - local Percent = ((Value < 0.0) and 0.0) or ((Value > 1.0) and 1.0 or Value) - self.ActiveBar:Size(self.BackgroundBar.Width * Percent, self.ActiveBar.Height) - else - local SafeZone = {X = 0, Y = 0} - if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then - SafeZone = GetSafeZoneBounds() - end - - local Progress = (math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) - self.ActiveBar.X - return math.round(((Progress >= 0 and Progress <= 413) and Progress or ((Progress < 0) and 0 or 413))/self.BackgroundBar.Width, 2) - end -end - -function UIMenuPercentagePanel:UpdateParent(Percentage) - local _, ParentType = self.ParentItem() - if ParentType == "UIMenuListItem" then - local PanelItemIndex = self.ParentItem:FindPanelItem() - if PanelItemIndex then - self.ParentItem.Items[PanelItemIndex].Value[self.ParentItem:FindPanelIndex(self)] = Percentage - self.ParentItem:Index(PanelItemIndex) - self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) - self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) - else - local PanelIndex = self.ParentItem:FindPanelIndex(self) - for Index = 1, #self.ParentItem.Items do - if type(self.ParentItem.Items[Index]) == "table" then - if not self.ParentItem.Items[Index].Panels then self.ParentItem.Items[Index].Panels = {} end - self.ParentItem.Items[Index].Panels[PanelIndex] = Percentage - else - self.ParentItem.Items[Index] = {Name = tostring(self.ParentItem.Items[Index]), Value = self.ParentItem.Items[Index], Panels = {[PanelIndex] = Percentage}} - end - end - self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) - self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) - end - elseif ParentType == "UIMenuItem" then - self.ParentItem.ActivatedPanel(self.ParentItem.ParentMenu, self.ParentItem, self, Percentage) - end -end - -function UIMenuPercentagePanel:Functions() - - local SafeZone = {X = 0, Y = 0} - if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then - SafeZone = GetSafeZoneBounds() - end - - if IsMouseInBounds(self.BackgroundBar.X + SafeZone.X, self.BackgroundBar.Y - 4 + SafeZone.Y, self.BackgroundBar.Width, self.BackgroundBar.Height + 8) then - if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then - if not self.Pressed then - self.Pressed = true - Citizen.CreateThread(function() - self.Audio.Id = GetSoundId() - PlaySoundFrontend(self.Audio.Id, self.Audio.Slider, self.Audio.Library, 1) - while IsDisabledControlPressed(0, 24) and IsMouseInBounds(self.BackgroundBar.X + SafeZone.X, self.BackgroundBar.Y - 4 + SafeZone.Y, self.BackgroundBar.Width, self.BackgroundBar.Height + 8) do - Citizen.Wait(0) - local Progress = (math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) - self.ActiveBar.X - self.ActiveBar:Size(((Progress >= 0 and Progress <= 413) and Progress or ((Progress < 0) and 0 or 413)), self.ActiveBar.Height) - end - StopSound(self.Audio.Id) - ReleaseSoundId(self.Audio.Id) - self.Pressed = false - end) - Citizen.CreateThread(function() - while IsDisabledControlPressed(0, 24) and IsMouseInBounds(self.BackgroundBar.X + SafeZone.X, self.BackgroundBar.Y - 4 + SafeZone.Y, self.BackgroundBar.Width, self.BackgroundBar.Height + 8) do - Citizen.Wait(75) - local Progress = (math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) - self.ActiveBar.X - self:UpdateParent(math.round(((Progress >= 0 and Progress <= 413) and Progress or ((Progress < 0) and 0 or 413))/self.BackgroundBar.Width, 2)) - end - end) - end - end - end -end - -function UIMenuPercentagePanel:Draw() -- required - if self.Data.Enabled then - self.Background:Size(431 + self.ParentItem:SetParentMenu().WidthOffset, 76) - self.Background:Draw() - self.BackgroundBar:Draw() - self.ActiveBar:Draw() - self.Text.Min:Draw() - self.Text.Max:Draw() - self.Text.Title:Draw() - self:Functions() - end -end - ---[[ - UIMenu.lua - Menus ---]] - -function UIMenu.New(Title, Subtitle, X, Y, TxtDictionary, TxtName, titleTxt) - local X, Y = tonumber(X) or 0, tonumber(Y) or 0 - if Title ~= nil then Title = tostring(Title) or "" else Title = "" end - if Subtitle ~= nil then Subtitle = tostring(Subtitle) or "" else Subtitle = "" end - if TxtDictionary ~= nil then TxtDictionary = tostring(TxtDictionary) or "commonmenu" else TxtDictionary = "commonmenu" end - if TxtName ~= nil then TxtName = tostring(TxtName) or "interaction_bgd" else TxtName = "interaction_bgd" end - local thisTitle - if titleTxt then - thisTitle = Sprite.New(TxtDictionary, titleTxt, 0 + X, 0 + Y, 431, 107) - else - thisTitle = UIResText.New(Title, 215 + X, 20 + Y, 1.15, 255, 255, 255, 255, 1, 1) - end - local _UIMenu = { - Logo = Sprite.New(TxtDictionary, TxtName, 0 + X, 0 + Y, 431, 107), - Banner = nil, - Title = thisTitle, - Subtitle = {ExtraY = 0}, - WidthOffset = 0, - Position = {X = X, Y = Y}, - Pagination = {Min = 0, Max = 9, Total = 9}, - PageCounter = {PreText = ""}, - Extra = {}, - Description = {}, - Items = {}, - Windows = {}, - Children = {}, - TxtDictionary = TxtDictionary, - TxtName = TxtName, - titleTxt = titleTxt, - Controls = { - Back = { - Enabled = true, - }, - Select = { - Enabled = true, - }, - Left = { - Enabled = true, - }, - Right = { - Enabled = true, - }, - Up = { - Enabled = true, - }, - Down = { - Enabled = true, - }, - }, - ParentMenu = nil, - ParentItem = nil, - _Visible = false, - ActiveItem = 1000, - Dirty = false; - ReDraw = true, - InstructionalScaleform = RequestScaleformMovie("INSTRUCTIONAL_BUTTONS"), - InstructionalButtons = {}, - OnIndexChange = function(menu, newindex) end, - OnListChange = function(menu, list, newindex) end, - OnSliderChange = function(menu, slider, newindex) end, - OnProgressChange = function(menu, progress, newindex) end, - OnCheckboxChange = function(menu, item, checked) end, - OnListSelect = function(menu, list, index) end, - OnSliderSelect = function(menu, slider, index) end, - OnProgressSelect = function(menu, progress, index) end, - OnItemSelect = function(menu, item, index) end, - OnMenuChanged = function(menu, newmenu, forward) end, - OnMenuClosed = function(menu) end, - Settings = { - InstructionalButtons = true, - MultilineFormats = true, - ScaleWithSafezone = true, - ResetCursorOnOpen = true, - MouseControlsEnabled = true, - MouseEdgeEnabled = true, - ControlDisablingEnabled = true, - Audio = { - Library = "HUD_FRONTEND_DEFAULT_SOUNDSET", - UpDown = "NAV_UP_DOWN", - LeftRight = "NAV_LEFT_RIGHT", - Select = "SELECT", - Back = "BACK", - Error = "ERROR", - }, - EnabledControls = { - Controller = { - {0, 2}, -- Look Up and Down - {0, 1}, -- Look Left and Right - {0, 25}, -- Aim - {0, 24}, -- Attack - }, - Keyboard = { - {0, 201}, -- Select - {0, 195}, -- X axis - {0, 196}, -- Y axis - {0, 187}, -- Down - {0, 188}, -- Up - {0, 189}, -- Left - {0, 190}, -- Right - {0, 202}, -- Back - {0, 217}, -- Select - {0, 242}, -- Scroll down - {0, 241}, -- Scroll up - {0, 239}, -- Cursor X - {0, 240}, -- Cursor Y - {0, 31}, -- Move Up and Down - {0, 30}, -- Move Left and Right - {0, 21}, -- Sprint - {0, 22}, -- Jump - {0, 23}, -- Enter - {0, 75}, -- Exit Vehicle - {0, 71}, -- Accelerate Vehicle - {0, 72}, -- Vehicle Brake - {0, 59}, -- Move Vehicle Left and Right - {0, 89}, -- Fly Yaw Left - {0, 9}, -- Fly Left and Right - {0, 8}, -- Fly Up and Down - {0, 90}, -- Fly Yaw Right - {0, 76}, -- Vehicle Handbrake - }, - } - } - } - - if Subtitle ~= "" and Subtitle ~= nil then - _UIMenu.Subtitle.Rectangle = UIResRectangle.New(0 + _UIMenu.Position.X, 107 + _UIMenu.Position.Y, 431, 37, 0, 0, 0, 255) - _UIMenu.Subtitle.Text = UIResText.New(Subtitle, 8 + _UIMenu.Position.X, 110 + _UIMenu.Position.Y, 0.35, 245, 245, 245, 255, 0) - _UIMenu.Subtitle.BackupText = Subtitle - _UIMenu.Subtitle.Formatted = false - if string.starts(Subtitle, "~") then - _UIMenu.PageCounter.PreText = string.sub(Subtitle, 1, 3) - end - _UIMenu.PageCounter.Text = UIResText.New("", 425 + _UIMenu.Position.X, 110 + _UIMenu.Position.Y, 0.35, 245, 245, 245, 255, 0, "Right") - _UIMenu.Subtitle.ExtraY = 37 - end - - _UIMenu.ArrowSprite = Sprite.New("commonmenu", "shop_arrows_upanddown", 190 + _UIMenu.Position.X, 147 + 37 * (_UIMenu.Pagination.Total + 1) + _UIMenu.Position.Y - 37 + _UIMenu.Subtitle.ExtraY, 50, 50) - _UIMenu.Extra.Up = UIResRectangle.New(0 + _UIMenu.Position.X, 144 + 38 * (_UIMenu.Pagination.Total + 1) + _UIMenu.Position.Y - 37 + _UIMenu.Subtitle.ExtraY, 431, 18, 0, 0, 0, 200) - _UIMenu.Extra.Down = UIResRectangle.New(0 + _UIMenu.Position.X, 144 + 18 + 38 * (_UIMenu.Pagination.Total + 1) + _UIMenu.Position.Y - 37 + _UIMenu.Subtitle.ExtraY, 431, 18, 0, 0, 0, 200) - - _UIMenu.Description.Bar = UIResRectangle.New(_UIMenu.Position.X, 123, 431, 4, 0, 0, 0, 255) - _UIMenu.Description.Rectangle = Sprite.New("commonmenu", "gradient_bgd", _UIMenu.Position.X, 127, 431, 30) - _UIMenu.Description.Text = UIResText.New("Description", _UIMenu.Position.X + 5, 125, 0.35) - - _UIMenu.Background = Sprite.New("commonmenu", "gradient_bgd", _UIMenu.Position.X, 144 + _UIMenu.Position.Y - 37 + _UIMenu.Subtitle.ExtraY, 290, 25) - - Citizen.CreateThread(function() - if not HasScaleformMovieLoaded(_UIMenu.InstructionalScaleform) then - _UIMenu.InstructionalScaleform = RequestScaleformMovie("INSTRUCTIONAL_BUTTONS") - while not HasScaleformMovieLoaded(_UIMenu.InstructionalScaleform) do - Citizen.Wait(0) - end - end - end) - return setmetatable(_UIMenu, UIMenu) -end - -function UIMenu:SetMenuWidthOffset(Offset) - if tonumber(Offset) then - self.WidthOffset = math.floor(tonumber(Offset)) - self.Logo:Size(431 + self.WidthOffset, 107) - if self.Title.TxtName then - self.Title:Position(((self.WidthOffset + 0)/2) + self.Position.X, 0 + self.Position.Y) - else - self.Title:Position(((self.WidthOffset + 431)/2) + self.Position.X, 20 + self.Position.Y) - end - if self.Subtitle.Rectangle ~= nil then - self.Subtitle.Rectangle:Size(431 + self.WidthOffset + 100, 37) - self.PageCounter.Text:Position(425 + self.Position.X + self.WidthOffset, 110 + self.Position.Y) - end - if self.Banner ~= nil then - self.Banner:Size(431 + self.WidthOffset, 107) - end - end -end - -function UIMenu:DisEnableControls(bool) - if bool then - EnableAllControlActions(2) - else - DisableAllControlActions(2) - end - - if bool then - return - else - if Controller() then - for Index = 1, #self.Settings.EnabledControls.Controller do - EnableControlAction(self.Settings.EnabledControls.Controller[Index][1], self.Settings.EnabledControls.Controller[Index][2], true) - end - else - for Index = 1, #self.Settings.EnabledControls.Keyboard do - EnableControlAction(self.Settings.EnabledControls.Keyboard[Index][1], self.Settings.EnabledControls.Keyboard[Index][2], true) - end - end - end -end - -function UIMenu:InstructionalButtons(bool) - if bool ~= nil then - self.Settings.InstrucitonalButtons = tobool(bool) - end -end - -function UIMenu:SetBannerSprite(Sprite, IncludeChildren) - if Sprite() == "Sprite" then - self.Logo = Sprite - self.Logo:Size(431 + self.WidthOffset, 107) - self.Logo:Position(self.Position.X, self.Position.Y) - self.Banner = nil - if IncludeChildren then - for Item, Menu in pairs(self.Children) do - Menu.Logo = Sprite - Menu.Logo:Size(431 + self.WidthOffset, 107) - Menu.Logo:Position(self.Position.X, self.Position.Y) - Menu.Banner = nil - end - end - end -end - -function UIMenu:SetBannerRectangle(Rectangle, IncludeChildren) - if Rectangle() == "Rectangle" then - self.Banner = Rectangle - self.Banner:Size(431 + self.WidthOffset, 107) - self.Banner:Position(self.Position.X, self.Position.Y) - self.Logo = nil - if IncludeChildren then - for Item, Menu in pairs(self.Children) do - Menu.Banner = Rectangle - Menu.Banner:Size(431 + self.WidthOffset, 107) - Menu:Position(self.Position.X, self.Position.Y) - Menu.Logo = nil - end - end - end -end - -function UIMenu:CurrentSelection(value) - if tonumber(value) then - if #self.Items == 0 then - self.ActiveItem = 0 - end - - self.Items[self:CurrentSelection()]:Selected(false) - self.ActiveItem = 1000000 - (1000000 % #self.Items) + tonumber(value) - - if self:CurrentSelection() > self.Pagination.Max then - self.Pagination.Min = self:CurrentSelection() - self.Pagination.Total - self.Pagination.Max = self:CurrentSelection() - elseif self:CurrentSelection() < self.Pagination.Min then - self.Pagination.Min = self:CurrentSelection() - self.Pagination.Max = self:CurrentSelection() + self.Pagination.Total - end - else - if #self.Items == 0 then - return 1 - else - if self.ActiveItem % #self.Items == 0 then - return 1 - else - return self.ActiveItem % #self.Items + 1 - end - end - end -end - -function UIMenu:CalculateWindowHeight() - local Height = 0 - for i = 1, #self.Windows do - Height = Height + self.Windows[i].Background:Size().Height - end - return Height -end - -function UIMenu:CalculateItemHeightOffset(Item) - if Item.Base then - return Item.Base.Rectangle.Height - else - return Item.Rectangle.Height - end -end - -function UIMenu:CalculateItemHeight() - local ItemOffset = 0 + self.Subtitle.ExtraY - 37 - for i = self.Pagination.Min + 1, self.Pagination.Max do - local Item = self.Items[i] - if Item ~= nil then - ItemOffset = ItemOffset + self:CalculateItemHeightOffset(Item) - end - end - return ItemOffset -end - -function UIMenu:RecalculateDescriptionPosition() - local WindowHeight = self:CalculateWindowHeight() - self.Description.Bar:Position(self.Position.X, 149 + self.Position.Y + WindowHeight) - self.Description.Rectangle:Position(self.Position.X, 149 + self.Position.Y + WindowHeight) - self.Description.Text:Position(self.Position.X + 8, 155 + self.Position.Y + WindowHeight) - - self.Description.Bar:Size(431 + self.WidthOffset, 4) - self.Description.Rectangle:Size(431 + self.WidthOffset, 30) - - self.Description.Bar:Position(self.Position.X, self:CalculateItemHeight() + ((#self.Items > (self.Pagination.Total + 1)) and 37 or 0) + self.Description.Bar:Position().Y) - self.Description.Rectangle:Position(self.Position.X, self:CalculateItemHeight() + ((#self.Items > (self.Pagination.Total + 1)) and 37 or 0) + self.Description.Rectangle:Position().Y) - self.Description.Text:Position(self.Position.X + 8, self:CalculateItemHeight() + ((#self.Items > (self.Pagination.Total + 1)) and 37 or 0) + self.Description.Text:Position().Y) -end - -function UIMenu:CaclulatePanelPosition(HasDescription) - local Height = self:CalculateWindowHeight() + 149 + self.Position.Y - - if HasDescription then - Height = Height + self.Description.Rectangle:Size().Height + 5 - end - - return self:CalculateItemHeight() + ((#self.Items > (self.Pagination.Total + 1)) and 37 or 0) + Height -end - -function UIMenu:AddWindow(Window) - if Window() == "UIMenuWindow" then - Window:SetParentMenu(self) - Window:Offset(self.Position.X, self.Position.Y) - table.insert(self.Windows, Window) - self.ReDraw = true - self:RecalculateDescriptionPosition() - end -end - -function UIMenu:RemoveWindowAt(Index) - if tonumber(Index) then - if self.Windows[Index] then - table.remove(self.Windows, Index) - self.ReDraw = true - self:RecalculateDescriptionPosition() - end - end -end - -function UIMenu:AddItem(Item) - if Item() == "UIMenuItem" then - local SelectedItem = self:CurrentSelection() - Item:SetParentMenu(self) - Item:Offset(self.Position.X, self.Position.Y) - Item:Position((#self.Items * 25) - 37 + self.Subtitle.ExtraY) - table.insert(self.Items, Item) - self:RecalculateDescriptionPosition() - self:CurrentSelection(SelectedItem) - end -end - -function UIMenu:RemoveItemAt(Index) - if tonumber(Index) then - if self.Items[Index] then - local SelectedItem = self:CurrentSelection() - if #self.Items > self.Pagination.Total and self.Pagination.Max == #self.Items - 1 then - self.Pagination.Min = self.Pagination.Min - 1 - self.Pagination.Max = self.Pagination.Max + 1 - end - table.remove(self.Items, tonumber(Index)) - self:RecalculateDescriptionPosition() - self:CurrentSelection(SelectedItem) - end - end -end - -function UIMenu:RefreshIndex() - if #self.Items == 0 then - self.ActiveItem = 1000 - self.Pagination.Max = self.Pagination.Total + 1 - self.Pagination.Min = 0 - return - end - self.Items[self:CurrentSelection()]:Selected(false) - self.ActiveItem = 1000 - (1000 % #self.Items) - self.Pagination.Max = self.Pagination.Total + 1 - self.Pagination.Min = 0 - self.ReDraw = true -end - -function UIMenu:RefreshIndexRecursively() - self:RefreshIndex() - - for _, Item in pairs(self.Children) do - if Item.RefreshIndexRecursively then - Item:RefreshIndexRecursively() - end - end -end - -function UIMenu:Clear() - self.Items = {} - self.ReDraw = true - self:RecalculateDescriptionPosition() -end - -function UIMenu:MultilineFormat(str) - if tostring(str) then - - local PixelPerLine = 425 + self.WidthOffset - local AggregatePixels = 0 - local output = "" - local words = string.split(tostring(str), " ") - - for i = 1, #words do - local offset = MeasureStringWidth(words[i], 0, 0.35) - AggregatePixels = AggregatePixels + offset - if AggregatePixels > PixelPerLine then - output = output .. "\n" .. words[i] .. " " - AggregatePixels = offset + MeasureString(" ") - else - output = output .. words[i] .. " " - AggregatePixels = AggregatePixels + MeasureString(" ") - end - end - return output - end -end - -function UIMenu:DrawCalculations() - local WindowHeight = self:CalculateWindowHeight() - - if self.Settings.MultilineFormats then - if self.Subtitle.Rectangle and not self.Subtitle.Formatted then - self.Subtitle.Formatted = true - self.Subtitle.Text:Text(self:MultilineFormat(self.Subtitle.Text:Text())) - - local Linecount = #string.split(self.Subtitle.Text:Text(), "\n") - self.Subtitle.ExtraY = ((Linecount == 1) and 37 or ((Linecount + 1) * 22)) - self.Subtitle.Rectangle:Size(431 + self.WidthOffset, self.Subtitle.ExtraY) - end - elseif self.Subtitle.Formatted then - self.Subtitle.Formatted = false - self.Subtitle.ExtraY = 37 - self.Subtitle.Rectangle:Size(431 + self.WidthOffset, self.Subtitle.ExtraY) - self.Subtitle.Text:Text(self.Subtitle.BackupText) - end - - self.Background:Size(431 + self.WidthOffset, self:CalculateItemHeight() + WindowHeight + ((self.Subtitle.ExtraY > 0) and 0 or 37)) - - self.Extra.Up:Size(431 + self.WidthOffset, 18) - self.Extra.Down:Size(431 + self.WidthOffset, 18) - - self.Extra.Up:Position(self.Position.X, 144 + self:CalculateItemHeight() + self.Position.Y + WindowHeight) - self.Extra.Down:Position(self.Position.X, 144 + 18 + self:CalculateItemHeight() + self.Position.Y + WindowHeight) - - if self.WidthOffset > 0 then - self.ArrowSprite:Position(190 + self.Position.X + (self.WidthOffset / 2), 137 + self:CalculateItemHeight() + self.Position.Y + WindowHeight) - else - self.ArrowSprite:Position(190 + self.Position.X + self.WidthOffset, 137 + self:CalculateItemHeight() + self.Position.Y + WindowHeight) - end - - self.ReDraw = false - - if #self.Items ~= 0 and self.Items[self:CurrentSelection()]:Description() ~= "" then - self:RecalculateDescriptionPosition() - - local description = self.Items[self:CurrentSelection()]:Description() - if self.Settings.MultilineFormats then - self.Description.Text:Text(self:MultilineFormat(description)) - else - self.Description.Text:Text(description) - end - - local Linecount = #string.split(self.Description.Text:Text(), "\n") - self.Description.Rectangle:Size(431 + self.WidthOffset, ((Linecount == 1) and 37 or ((Linecount + 1) * 22))) - end -end - -function UIMenu:Visible(bool) - if bool ~= nil then - self._Visible = tobool(bool) - self.JustOpened = tobool(bool) - self.Dirty = tobool(bool) - self:UpdateScaleform() - if tobool(bool) == true then - ttsSpeechItem(self.Items[self:CurrentSelection()]) - end - if self.ParentMenu ~= nil or tobool(bool) == false then - return - end - if self.Settings.ResetCursorOnOpen then - local W, H = GetScreenResolution() - SetCursorLocation(W / 2, H / 2) - SetCursorSprite(1) - end - collectgarbage() - else - return self._Visible - end -end - -function UIMenu:ProcessControl() - if not self._Visible then - return - end - - if self.JustOpened then - self.JustOpened = false - return - end - - local isInputZeroDisabled = IsInputDisabled(0) - - if self.Controls.Back.Enabled and (IsDisabledControlJustReleased(2, 177) or IsDisabledControlJustReleased(2, 199) ) and isInputZeroDisabled then - self:GoBack() - - end - - if #self.Items == 0 then - return - end - - if not self.UpPressed then - if self.Controls.Up.Enabled and (IsDisabledControlJustPressed(1, 172) or IsDisabledControlJustPressed(1, 241)) and isInputZeroDisabled then - Citizen.CreateThread(function() - self.UpPressed = true - if #self.Items > self.Pagination.Total + 1 then - self:GoUpOverflow() - else - self:GoUp() - end - self:UpdateScaleform() - Citizen.Wait(175) - while self.Controls.Up.Enabled and (IsDisabledControlPressed(2, 172) or IsDisabledControlPressed(2, 241)) and isInputZeroDisabled do - if #self.Items > self.Pagination.Total + 1 then - self:GoUpOverflow() - else - self:GoUp() - end - self:UpdateScaleform() - Citizen.Wait(125) - end - self.UpPressed = false - end) - end - end - - if not self.DownPressed then - if self.Controls.Down.Enabled and (IsDisabledControlJustPressed(1, 173) or IsDisabledControlJustPressed(1, 242)) and isInputZeroDisabled then - Citizen.CreateThread(function() - self.DownPressed = true - if #self.Items > self.Pagination.Total + 1 then - self:GoDownOverflow() - else - self:GoDown() - end - self:UpdateScaleform() - Citizen.Wait(175) - while self.Controls.Down.Enabled and (IsDisabledControlPressed(2, 173) or IsDisabledControlPressed(2, 242)) and isInputZeroDisabled do - if #self.Items > self.Pagination.Total + 1 then - self:GoDownOverflow() - else - self:GoDown() - end - self:UpdateScaleform() - Citizen.Wait(125) - end - self.DownPressed = false - end) - end - end - - if not self.LeftPressed then - if self.Controls.Left.Enabled and (IsDisabledControlPressed(2, 174)) and isInputZeroDisabled then - Citizen.CreateThread(function() - if not self.LeftPressed then - self.LeftPressed = true - self:GoLeft() - Citizen.Wait(150) - while self.Controls.Left.Enabled and (IsDisabledControlPressed(2, 174)) and isInputZeroDisabled do - self:GoLeft() - Citizen.Wait(200) - end - self.LeftPressed = false - end - end) - end - end - - if not self.RightPressed then - if self.Controls.Right.Enabled and (IsDisabledControlPressed(2, 175)) and isInputZeroDisabled then - Citizen.CreateThread(function() - if not self.RightPressed then - self.RightPressed = true - self:GoRight() - Citizen.Wait(150) - while self.Controls.Right.Enabled and (IsDisabledControlPressed(2, 175)) and isInputZeroDisabled do - self:GoRight() - Citizen.Wait(200) - end - self.RightPressed = false - end - end) - end - end - - if self.Controls.Select.Enabled and (IsDisabledControlJustPressed(1, 201) and isInputZeroDisabled) then - self:SelectItem() - end -end - -function UIMenu:GoUpOverflow() - if #self.Items <= self.Pagination.Total + 1 then - return - end - - if self:CurrentSelection() <= self.Pagination.Min + 1 then - if self:CurrentSelection() == 1 then - self.Pagination.Min = #self.Items - (self.Pagination.Total + 1) - self.Pagination.Max = #self.Items - self.Items[self:CurrentSelection()]:Selected(false) - self.ActiveItem = 1000 - (1000 % #self.Items) - self.ActiveItem = self.ActiveItem + (#self.Items - 1) - self.Items[self:CurrentSelection()]:Selected(true) - else - self.Pagination.Min = self.Pagination.Min - 1 - self.Pagination.Max = self.Pagination.Max - 1 - self.Items[self:CurrentSelection()]:Selected(false) - self.ActiveItem = self.ActiveItem - 1 - self.Items[self:CurrentSelection()]:Selected(true) - end - else - self.Items[self:CurrentSelection()]:Selected(false) - self.ActiveItem = self.ActiveItem - 1 - self.Items[self:CurrentSelection()]:Selected(true) - end - PlaySoundFrontend(-1, self.Settings.Audio.UpDown, self.Settings.Audio.Library, true) - self.OnIndexChange(self, self:CurrentSelection()) - self.ReDraw = true -end - -function UIMenu:GoUp() - if #self.Items > self.Pagination.Total + 1 then - return - end - self.Items[self:CurrentSelection()]:Selected(false) - self.ActiveItem = self.ActiveItem - 1 - self.Items[self:CurrentSelection()]:Selected(true) - PlaySoundFrontend(-1, self.Settings.Audio.UpDown, self.Settings.Audio.Library, true) - - ttsSpeechItem(self.Items[self:CurrentSelection()]) - - self.OnIndexChange(self, self:CurrentSelection()) - self.ReDraw = true -end - -function UIMenu:GoDownOverflow() - if #self.Items <= self.Pagination.Total + 1 then - return - end - - if self:CurrentSelection() >= self.Pagination.Max then - if self:CurrentSelection() == #self.Items then - self.Pagination.Min = 0 - self.Pagination.Max = self.Pagination.Total + 1 - self.Items[self:CurrentSelection()]:Selected(false) - self.ActiveItem = 1000 - (1000 % #self.Items) - self.Items[self:CurrentSelection()]:Selected(true) - else - self.Pagination.Max = self.Pagination.Max + 1 - self.Pagination.Min = self.Pagination.Max - (self.Pagination.Total + 1) - self.Items[self:CurrentSelection()]:Selected(false) - self.ActiveItem = self.ActiveItem + 1 - self.Items[self:CurrentSelection()]:Selected(true) - end - else - self.Items[self:CurrentSelection()]:Selected(false) - self.ActiveItem = self.ActiveItem + 1 - self.Items[self:CurrentSelection()]:Selected(true) - end - PlaySoundFrontend(-1, self.Settings.Audio.UpDown, self.Settings.Audio.Library, true) - self.OnIndexChange(self, self:CurrentSelection()) - self.ReDraw = true -end - -function UIMenu:GoDown() - if #self.Items > self.Pagination.Total + 1 then - return - end - - self.Items[self:CurrentSelection()]:Selected(false) - self.ActiveItem = self.ActiveItem + 1 - self.Items[self:CurrentSelection()]:Selected(true) - PlaySoundFrontend(-1, self.Settings.Audio.UpDown, self.Settings.Audio.Library, true) - - ttsSpeechItem(self.Items[self:CurrentSelection()]) - - self.OnIndexChange(self, self:CurrentSelection()) - self.ReDraw = true -end - -function UIMenu:GoLeft() - local type, subtype = self.Items[self:CurrentSelection()]() - if subtype ~= "UIMenuListItem" and subtype ~= "UIMenuSliderItem" and subtype ~= "UIMenuProgressItem" then - return - end - - if not self.Items[self:CurrentSelection()]:Enabled() then - PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) - return - end - - if subtype == "UIMenuListItem" then - local Item = self.Items[self:CurrentSelection()] - Item:Index(Item._Index - 1) - self.OnListChange(self, Item, Item._Index) - Item.OnListChanged(self, Item, Item._Index) - ttsSpeechText(Item.Items[Item._Index]) - PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true) - elseif subtype == "UIMenuSliderItem" then - local Item = self.Items[self:CurrentSelection()] - Item:Index(Item._Index - 1) - self.OnSliderChange(self, Item, Item:Index()) - Item.OnSliderChanged(self, Item, Item._Index) - PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true) - elseif subtype == "UIMenuProgressItem" then - local Item = self.Items[self:CurrentSelection()] - Item:Index(Item.Data.Index - 1) - self.OnProgressChange(self, Item, Item.Data.Index) - Item.OnProgressChanged(self, Item, Item.Data.Index) - PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true) - end -end - -function UIMenu:GoRight() - local type, subtype = self.Items[self:CurrentSelection()]() - if subtype ~= "UIMenuListItem" and subtype ~= "UIMenuSliderItem" and subtype ~= "UIMenuProgressItem" then - return - end - - if not self.Items[self:CurrentSelection()]:Enabled() then - PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) - return - end - - if subtype == "UIMenuListItem" then - local Item = self.Items[self:CurrentSelection()] - Item:Index(Item._Index + 1) - self.OnListChange(self, Item, Item._Index) - Item.OnListChanged(self, Item, Item._Index) - ttsSpeechText(Item.Items[Item._Index]) - PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true) - elseif subtype == "UIMenuSliderItem" then - local Item = self.Items[self:CurrentSelection()] - Item:Index(Item._Index + 1) - self.OnSliderChange(self, Item, Item:Index()) - Item.OnSliderChanged(self, Item, Item._Index) - PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true) - elseif subtype == "UIMenuProgressItem" then - local Item = self.Items[self:CurrentSelection()] - Item:Index(Item.Data.Index + 1) - self.OnProgressChange(self, Item, Item.Data.Index) - Item.OnProgressChanged(self, Item, Item.Data.Index) - PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true) - end -end - -function UIMenu:SelectItem() - if not self.Items[self:CurrentSelection()]:Enabled() then - PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) - return - end - local Item = self.Items[self:CurrentSelection()] - local type, subtype = Item() - if subtype == "UIMenuCheckboxItem" then - Item.Checked = not Item.Checked - ttsSpeechText(Item.Checked and "Checked" or "Unchecked") - PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true) - self.OnCheckboxChange(self, Item, Item.Checked) - Item.CheckboxEvent(self, Item, Item.Checked) - elseif subtype == "UIMenuListItem" then - PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true) - ttsSpeechText("Selected") - self.OnListSelect(self, Item, Item._Index) - Item.OnListSelected(self, Item, Item._Index) - elseif subtype == "UIMenuSliderItem" then - PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true) - ttsSpeechText("Selected") - self.OnSliderSelect(self, Item, Item._Index) - Item.OnSliderSelected(Item._Index) - elseif subtype == "UIMenuProgressItem" then - PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true) - ttsSpeechText("Selected") - self.OnProgressSelect(self, Item, Item.Data.Index) - Item.OnProgressSelected(Item.Data.Index) - else - PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true) - self.OnItemSelect(self, Item, self:CurrentSelection()) - ttsSpeechItem(Item) - Item.Activated(self, Item) - if not self.Children[Item] then - return - end - self:Visible(false) - self.Children[Item]:Visible(true) - self.OnMenuChanged(self, self.Children[self.Items[self:CurrentSelection()]], true) - - end -end - -function UIMenu:GoBack() - PlaySoundFrontend(-1, self.Settings.Audio.Back, self.Settings.Audio.Library, true) - self:Visible(false) - if self.ParentMenu ~= nil then - self.ParentMenu:Visible(true) - self.OnMenuChanged(self, self.ParentMenu, false) - if self.Settings.ResetCursorOnOpen then - local W, H = GetActiveScreenResolution() - SetCursorLocation(W / 2, H / 2) - end - end - self.OnMenuClosed(self) -end - -function UIMenu:BindMenuToItem(Menu, Item) - if Menu() == "UIMenu" and Item() == "UIMenuItem" then - Menu.ParentMenu = self - Menu.ParentItem = Item - self.Children[Item] = Menu - end -end - -function UIMenu:ReleaseMenuFromItem(Item) - if Item() == "UIMenuItem" then - if not self.Children[Item] then - return false - end - self.Children[Item].ParentMenu = nil - self.Children[Item].ParentItem = nil - self.Children[Item] = nil - return true - end -end - -function UIMenu:Draw() - if not self._Visible then - return - end - - HideHudComponentThisFrame(19) - - if self.Settings.ControlDisablingEnabled then - self:DisEnableControls(false) - end - - if self.Settings.InstructionalButtons then - DrawScaleformMovieFullscreen(self.InstructionalScaleform, 255, 255, 255, 255, 0) - end - - if self.Settings.ScaleWithSafezone then - ScreenDrawPositionBegin(76, 84) - ScreenDrawPositionRatio(0, 0, 0, 0) - end - - if self.ReDraw then - self:DrawCalculations() - end - - if self.Logo then - self.Logo:Draw() - elseif self.Banner then - self.Banner:Draw() - end - - self.Title:Draw() - - if self.Subtitle.Rectangle then - self.Subtitle.Rectangle:Draw() - self.Subtitle.Text:Draw() - end - - if #self.Items ~= 0 or #self.Windows ~= 0 then - self.Background:Draw() - end - - if #self.Windows ~= 0 then - local WindowOffset = 0 - for index = 1, #self.Windows do - if self.Windows[index - 1] then - WindowOffset = WindowOffset + self.Windows[index - 1].Background:Size().Height - end - local Window = self.Windows[index] - Window:Position(WindowOffset + self.Subtitle.ExtraY - 37) - Window:Draw() - end - end - - if #self.Items == 0 then - if self.Settings.ScaleWithSafezone then - ScreenDrawPositionEnd() - end - return - end - - local CurrentSelection = self:CurrentSelection() - self.Items[CurrentSelection]:Selected(true) - - if self.Items[CurrentSelection]:Description() ~= "" then - self.Description.Bar:Draw() - self.Description.Rectangle:Draw() - self.Description.Text:Draw() - end - - if self.Items[CurrentSelection].Panels ~= nil then - if #self.Items[CurrentSelection].Panels ~= 0 then - local PanelOffset = self:CaclulatePanelPosition(self.Items[CurrentSelection]:Description() ~= "") - for index = 1, #self.Items[CurrentSelection].Panels do - if self.Items[CurrentSelection].Panels[index - 1] then - PanelOffset = PanelOffset + self.Items[CurrentSelection].Panels[index - 1].Background:Size().Height + 5 - end - self.Items[CurrentSelection].Panels[index]:Position(PanelOffset) - self.Items[CurrentSelection].Panels[index]:Draw() - end - end - end - - local WindowHeight = self:CalculateWindowHeight() - - if #self.Items <= self.Pagination.Total + 1 then - local ItemOffset = self.Subtitle.ExtraY - 37 + WindowHeight - for index = 1, #self.Items do - local Item = self.Items[index] - Item:Position(ItemOffset) - Item:Draw() - ItemOffset = ItemOffset + self:CalculateItemHeightOffset(Item) - end - else - local ItemOffset = self.Subtitle.ExtraY - 37 + WindowHeight - for index = self.Pagination.Min + 1, self.Pagination.Max, 1 do - if self.Items[index] then - local Item = self.Items[index] - Item:Position(ItemOffset) - Item:Draw() - ItemOffset = ItemOffset + self:CalculateItemHeightOffset(Item) - end - end - - self.Extra.Up:Draw() - self.Extra.Down:Draw() - self.ArrowSprite:Draw() - - if self.PageCounter.Text ~= nil then - local Caption = self.PageCounter.PreText .. CurrentSelection .. " / " .. #self.Items - self.PageCounter.Text:Text(Caption) - self.PageCounter.Text:Draw() - end - end - - if self.Settings.ScaleWithSafezone then - ScreenDrawPositionEnd() - end -end - -function UIMenu:ProcessMouse() - if not self._Visible or self.JustOpened or #self.Items == 0 or tobool(Controller()) or not self.Settings.MouseControlsEnabled then - EnableControlAction(0, 2, true) - EnableControlAction(0, 1, true) - EnableControlAction(0, 25, true) - EnableControlAction(0, 24, true) - if self.Dirty then - for _, Item in pairs(self.Items) do - if Item:Hovered() then - Item:Hovered(false) - end - end - end - return - end - - local SafeZone = {X = 0, Y = 0} - local WindowHeight = self:CalculateWindowHeight() - if self.Settings.ScaleWithSafezone then - SafeZone = GetSafeZoneBounds() - end - - local Limit = #self.Items - local ItemOffset = 0 - - ShowCursorThisFrame() - - if #self.Items > self.Pagination.Total + 1 then - Limit = self.Pagination.Max - end - - if IsMouseInBounds(0, 0, 30, 1080) and self.Settings.MouseEdgeEnabled then - SetGameplayCamRelativeHeading(GetGameplayCamRelativeHeading() + 5) - SetCursorSprite(6) - elseif IsMouseInBounds(1920 - 30, 0, 30, 1080) and self.Settings.MouseEdgeEnabled then - SetGameplayCamRelativeHeading(GetGameplayCamRelativeHeading() - 5) - SetCursorSprite(7) - elseif self.Settings.MouseEdgeEnabled then - SetCursorSprite(1) - end - - for i = self.Pagination.Min + 1, Limit, 1 do - local X, Y = self.Position.X + SafeZone.X, self.Position.Y + 144 - 37 + self.Subtitle.ExtraY + ItemOffset + SafeZone.Y + WindowHeight - local Item = self.Items[i] - local Type, SubType = Item() - local Width, Height = 431 + self.WidthOffset, self:CalculateItemHeightOffset(Item) - - if IsMouseInBounds(X, Y, Width, Height) then - Item:Hovered(true) - if not self.Controls.MousePressed then - if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then - Citizen.CreateThread(function() - local _X, _Y, _Width, _Height = X, Y, Width, Height - self.Controls.MousePressed = true - if Item:Selected() and Item:Enabled() then - if SubType == "UIMenuListItem" then - if IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then - self:GoLeft() - elseif not IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then - self:SelectItem() - end - if IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then - self:GoRight() - elseif not IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then - self:SelectItem() - end - elseif SubType == "UIMenuSliderItem" then - if IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then - self:GoLeft() - elseif not IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then - self:SelectItem() - end - if IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then - self:GoRight() - elseif not IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then - self:SelectItem() - end - elseif SubType == "UIMenuProgressItem" then - if IsMouseInBounds(Item.Bar.X + SafeZone.X, Item.Bar.Y + SafeZone.Y - 12, Item.Data.Max, Item.Bar.Height + 24) then - Item:CalculateProgress(math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) - self.OnProgressChange(self, Item, Item.Data.Index) - Item.OnProgressChanged(self, Item, Item.Data.Index) - else - self:SelectItem() - end - else - self:SelectItem() - end - elseif not Item:Selected() then - self:CurrentSelection(i-1) - PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) - self.OnIndexChange(self, self:CurrentSelection()) - self.ReDraw = true - self:UpdateScaleform() - elseif not Item:Enabled() and Item:Selected() then - PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) - end - Citizen.Wait(175) - while IsDisabledControlPressed(0, 24) and IsMouseInBounds(_X, _Y, _Width, _Height) do - if Item:Selected() and Item:Enabled() then - if SubType == "UIMenuListItem" then - if IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then - self:GoLeft() - end - if IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then - self:GoRight() - end - elseif SubType == "UIMenuSliderItem" then - if IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then - self:GoLeft() - end - if IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then - self:GoRight() - end - elseif SubType == "UIMenuProgressItem" then - if IsMouseInBounds(Item.Bar.X + SafeZone.X, Item.Bar.Y + SafeZone.Y - 12, Item.Data.Max, Item.Bar.Height + 24) then - Item:CalculateProgress(math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) - self.OnProgressChange(self, Item, Item.Data.Index) - Item.OnProgressChanged(self, Item, Item.Data.Index) - else - self:SelectItem() - end - end - elseif not Item:Selected() then - self:CurrentSelection(i-1) - PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) - self.OnIndexChange(self, self:CurrentSelection()) - self.ReDraw = true - self:UpdateScaleform() - elseif not Item:Enabled() and Item:Selected() then - PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) - end - Citizen.Wait(125) - end - self.Controls.MousePressed = false - end) - end - end - else - Item:Hovered(false) - end - ItemOffset = ItemOffset + self:CalculateItemHeightOffset(Item) - end - - local ExtraX, ExtraY = self.Position.X + SafeZone.X, 144 + self:CalculateItemHeight() + self.Position.Y + SafeZone.Y + WindowHeight - - if #self.Items <= self.Pagination.Total + 1 then return end - - if IsMouseInBounds(ExtraX, ExtraY, 431 + self.WidthOffset, 18) then - self.Extra.Up:Colour(30, 30, 30, 255) - if not self.Controls.MousePressed then - if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then - Citizen.CreateThread(function() - local _ExtraX, _ExtraY = ExtraX, ExtraY - self.Controls.MousePressed = true - if #self.Items > self.Pagination.Total + 1 then - self:GoUpOverflow() - else - self:GoUp() - end - Citizen.Wait(175) - while IsDisabledControlPressed(0, 24) and IsMouseInBounds(_ExtraX, _ExtraY, 431 + self.WidthOffset, 18) do - if #self.Items > self.Pagination.Total + 1 then - self:GoUpOverflow() - else - self:GoUp() - end - Citizen.Wait(125) - end - self.Controls.MousePressed = false - end) - end - end - else - self.Extra.Up:Colour(0, 0, 0, 200) - end - - if IsMouseInBounds(ExtraX, ExtraY + 18, 431 + self.WidthOffset, 18) then - self.Extra.Down:Colour(30, 30, 30, 255) - if not self.Controls.MousePressed then - if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then - Citizen.CreateThread(function() - local _ExtraX, _ExtraY = ExtraX, ExtraY - self.Controls.MousePressed = true - if #self.Items > self.Pagination.Total + 1 then - self:GoDownOverflow() - else - self:GoDown() - end - Citizen.Wait(175) - while IsDisabledControlPressed(0, 24) and IsMouseInBounds(_ExtraX, _ExtraY + 18, 431 + self.WidthOffset, 18) do - if #self.Items > self.Pagination.Total + 1 then - self:GoDownOverflow() - else - self:GoDown() - end - Citizen.Wait(125) - end - self.Controls.MousePressed = false - end) - end - end - else - self.Extra.Down:Colour(0, 0, 0, 200) - end -end - -function UIMenu:AddInstructionButton(button) - if type(button) == "table" and #button == 2 then - table.insert(self.InstructionalButtons, button) - end -end - -function UIMenu:RemoveInstructionButton(button) - if type(button) == "table" then - for i = 1, #self.InstructionalButtons do - if button == self.InstructionalButtons[i] then - table.remove(self.InstructionalButtons, i) - break - end - end - else - if tonumber(button) then - if self.InstructionalButtons[tonumber(button)] then - table.remove(self.InstructionalButtons, tonumber(button)) - end - end - end -end - -function UIMenu:AddEnabledControl(Inputgroup, Control, Controller) - if tonumber(Inputgroup) and tonumber(Control) then - table.insert(self.Settings.EnabledControls[(Controller and "Controller" or "Keyboard")], {Inputgroup, Control}) - end -end - -function UIMenu:RemoveEnabledControl(Inputgroup, Control, Controller) - local Type = (Controller and "Controller" or "Keyboard") - for Index = 1, #self.Settings.EnabledControls[Type] do - if Inputgroup == self.Settings.EnabledControls[Type][Index][1] and Control == self.Settings.EnabledControls[Type][Index][2] then - table.remove(self.Settings.EnabledControls[Type], Index) - break - end - end -end - -function UIMenu:UpdateScaleform() - if not self._Visible or not self.Settings.InstructionalButtons then - return - end - - PushScaleformMovieFunction(self.InstructionalScaleform, "CLEAR_ALL") - PopScaleformMovieFunction() - - PushScaleformMovieFunction(self.InstructionalScaleform, "TOGGLE_MOUSE_BUTTONS") - PushScaleformMovieFunctionParameterInt(0) - PopScaleformMovieFunction() - - PushScaleformMovieFunction(self.InstructionalScaleform, "CREATE_CONTAINER") - PopScaleformMovieFunction() - - PushScaleformMovieFunction(self.InstructionalScaleform, "SET_DATA_SLOT") - PushScaleformMovieFunctionParameterInt(0) - PushScaleformMovieFunctionParameterString(GetControlInstructionalButton(2, 176, 0)) - PushScaleformMovieFunctionParameterString("Select") - PopScaleformMovieFunction() - - if self.Controls.Back.Enabled then - PushScaleformMovieFunction(self.InstructionalScaleform, "SET_DATA_SLOT") - PushScaleformMovieFunctionParameterInt(1) - PushScaleformMovieFunctionParameterString(GetControlInstructionalButton(2, 177, 0)) - PushScaleformMovieFunctionParameterString("Back") - PopScaleformMovieFunction() - end - - local count = 2 - - for i = 1, #self.InstructionalButtons do - if self.InstructionalButtons[i] then - if #self.InstructionalButtons[i] == 2 then - PushScaleformMovieFunction(self.InstructionalScaleform, "SET_DATA_SLOT") - PushScaleformMovieFunctionParameterInt(count) - PushScaleformMovieFunctionParameterString(self.InstructionalButtons[i][1]) - PushScaleformMovieFunctionParameterString(self.InstructionalButtons[i][2]) - PopScaleformMovieFunction() - count = count + 1 - end - end - end - - PushScaleformMovieFunction(self.InstructionalScaleform, "DRAW_INSTRUCTIONAL_BUTTONS") - PushScaleformMovieFunctionParameterInt(-1) - PopScaleformMovieFunction() -end - ---[[ - MenuPool.lua - Menus ---]] - -function MenuPool.New() - local _MenuPool = { - Menus = {} - } - return setmetatable(_MenuPool, MenuPool) -end - -function MenuPool:AddSubMenu(Menu, Text, Description, KeepPosition, KeepBanner) - if Menu() == "UIMenu" then - local Item = UIMenuItem.New(tostring(Text), Description or "") - Menu:AddItem(Item) - local SubMenu - - if KeepPosition then - if Menu.Title.TxtName then - SubMenu = UIMenu.New("", Text, Menu.Position.X, Menu.Position.Y, Menu.TxtDictionary, Menu.TxtName, Menu.titleTxt) - else - SubMenu = UIMenu.New(Menu.Title._Text, Text, Menu.Position.X, Menu.Position.Y, Menu.TxtDictionary, Menu.TxtName) - end - else - if Menu.Title.TxtName then - SubMenu = UIMenu.New("", Text, 0, 0, Menu.TxtDictionary, Menu.TxtName, Menu.titleTxt) - else - SubMenu = UIMenu.New(Menu.Title._Text, Text, 0, 0, Menu.TxtDictionary, Menu.TxtName, Menu.titleTxt) - end - end - if KeepBanner then - if Menu.Logo ~= nil then - SubMenu.Logo = Menu.Logo - else - SubMenu.Logo = nil - SubMenu.Banner = Menu.Banner - end - end - self:Add(SubMenu) - Menu:BindMenuToItem(SubMenu, Item) - return SubMenu - end -end - -function MenuPool:Add(Menu) - if Menu() == "UIMenu" then - table.insert(self.Menus, Menu) - end -end - -function MenuPool:Clear() - self = { - Menus = {} - } - collectgarbage() -end - -function MenuPool:Remove() - self = nil - collectgarbage() -end - -function MenuPool:MouseEdgeEnabled(bool) - if bool ~= nil then - for _, Menu in pairs(self.Menus) do - Menu.Settings.MouseEdgeEnabled = tobool(bool) - end - end -end - -function MenuPool:ControlDisablingEnabled(bool) - if bool ~= nil then - for _, Menu in pairs(self.Menus) do - Menu.Settings.ControlDisablingEnabled = tobool(bool) - end - end -end - -function MenuPool:ResetCursorOnOpen(bool) - if bool ~= nil then - for _, Menu in pairs(self.Menus) do - Menu.Settings.ResetCursorOnOpen = tobool(bool) - end - end -end - -function MenuPool:MultilineFormats(bool) - if bool ~= nil then - for _, Menu in pairs(self.Menus) do - Menu.Settings.MultilineFormats = tobool(bool) - end - end -end - -function MenuPool:Audio(Attribute, Setting) - if Attribute ~= nil and Setting ~= nil then - for _, Menu in pairs(self.Menus) do - if Menu.Settings.Audio[Attribute] then - Menu.Settings.Audio[Attribute] = Setting - end - end - end -end - -function MenuPool:WidthOffset(offset) - if tonumber(offset) then - for _, Menu in pairs(self.Menus) do - Menu:SetMenuWidthOffset(tonumber(offset)) - end - end -end - -function MenuPool:CounterPreText(str) - if str ~= nil then - for _, Menu in pairs(self.Menus) do - Menu.PageCounter.PreText = tostring(str) - end - end -end - -function MenuPool:DisableInstructionalButtons(bool) - if bool ~= nil then - for _, Menu in pairs(self.Menus) do - Menu.Settings.InstructionalButtons = tobool(bool) - end - end -end - -function MenuPool:MouseControlsEnabled(bool) - if bool ~= nil then - for _, Menu in pairs(self.Menus) do - Menu.Settings.MouseControlsEnabled = tobool(bool) - end - end -end - -function MenuPool:RefreshIndex() - for _, Menu in pairs(self.Menus) do - Menu:RefreshIndex() - end -end - -function MenuPool:ProcessMenus() - self:ProcessControl() - if false then - self:ProcessMouse() - end - self:Draw() -end - -function MenuPool:ProcessControl() - for _, Menu in pairs(self.Menus) do - if Menu:Visible() then - Menu:ProcessControl() - break - end - end -end - -function MenuPool:ProcessMouse() - for _, Menu in pairs(self.Menus) do - if Menu:Visible() then - Menu:ProcessMouse() - break - end - end -end - -function MenuPool:Draw() - for _, Menu in pairs(self.Menus) do - if Menu:Visible() then - Menu:Draw() - break - end - end -end - -function MenuPool:IsAnyMenuOpen() - local open = false - for _, Menu in pairs(self.Menus) do - if Menu:Visible() then - open = true - break - end - end - return open -end - -function MenuPool:CloseAllMenus() - for _, Menu in pairs(self.Menus) do - if Menu:Visible() then - Menu:Visible(false) - Menu.OnMenuClosed(Menu) - break - end - end -end - -function MenuPool:SetBannerSprite(Sprite) - if Sprite() == "Sprite" then - for _, Menu in pairs(self.Menus) do - Menu:SetBannerSprite(Sprite) - end - end -end - -function MenuPool:SetBannerRectangle(Rectangle) - if Rectangle() == "Rectangle" then - for _, Menu in pairs(self.Menus) do - Menu:SetBannerRectangle(Rectangle) - end - end -end - -function MenuPool:TotalItemsPerPage(Value) - if tonumber(Value) then - for _, Menu in pairs(self.Menus) do - Menu.Pagination.Total = Value - 1 - end - end -end ---[[ - Wrappers ---]] - -function NativeUI.CreatePool() - return MenuPool.New() -end - -function NativeUI.CreateMenu(Title, Subtitle, X, Y, TxtDictionary, TxtName, titleTxt) - return UIMenu.New(Title, Subtitle, X, Y, TxtDictionary, TxtName, titleTxt) -end - -function NativeUI.CreateItem(Text, Description) - return UIMenuItem.New(Text, Description) -end - -function NativeUI.CreateColouredItem(Text, Description, MainColour, HighlightColour) - return UIMenuColouredItem.New(Text, Description, MainColour, HighlightColour) -end - -function NativeUI.CreateCheckboxItem(Text, Check, Description) - return UIMenuCheckboxItem.New(Text, Check, Description) -end - -function NativeUI.CreateListItem(Text, Items, Index, Description) - return UIMenuListItem.New(Text, Items, Index, Description) -end - -function NativeUI.CreateSliderItem(Text, Items, Index, Description, Divider) - return UIMenuSliderItem.New(Text, Items, Index, Description, Divider) -end - -function NativeUI.CreateProgressItem(Text, Items, Index, Description, Counter) - return UIMenuProgressItem.New(Text, Items, Index, Description, Counter) -end - -function NativeUI.CreateHeritageWindow(Mum, Dad) - return UIMenuHeritageWindow.New(Mum, Dad) -end - -function NativeUI.CreateGridPanel(TopText, LeftText, RightText, BottomText) - return UIMenuGridPanel.New(TopText, LeftText, RightText, BottomText) -end - -function NativeUI.CreateColourPanel(Title, Colours) - return UIMenuColourPanel.New(Title, Colours) -end - -function NativeUI.CreatePercentagePanel(MinText, MaxText) - return UIMenuPercentagePanel.New(MinText, MaxText) -end - -function NativeUI.CreateSprite(TxtDictionary, TxtName, X, Y, Width, Height, Heading, R, G, B, A) - return Sprite.New(TxtDictionary, TxtName, X, Y, Width, Height, Heading, R, G, B, A) -end - -function NativeUI.CreateRectangle(X, Y, Width, Height, R, G, B, A) - return UIResRectangle.New(X, Y, Width, Height, R, G, B, A) -end - -function NativeUI.CreateText(Text, X, Y, Scale, R, G, B, A, Font, Alignment, DropShadow, Outline, WordWrap) - return UIResText.New(Text, X, Y, Scale, R, G, B, A, Font, Alignment, DropShadow, Outline, WordWrap) -end - -end) \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/images/banner-eoa.png b/server-data/resources/[esx]/EasyAdmin/dependencies/images/banner-eoa.png deleted file mode 100644 index 6046aa80e..000000000 Binary files a/server-data/resources/[esx]/EasyAdmin/dependencies/images/banner-eoa.png and /dev/null differ diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/images/banner-gradient.png b/server-data/resources/[esx]/EasyAdmin/dependencies/images/banner-gradient.png deleted file mode 100644 index 3ef7346f1..000000000 Binary files a/server-data/resources/[esx]/EasyAdmin/dependencies/images/banner-gradient.png and /dev/null differ diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/images/banner-hardadmin.png b/server-data/resources/[esx]/EasyAdmin/dependencies/images/banner-hardadmin.png deleted file mode 100644 index e2a7de38c..000000000 Binary files a/server-data/resources/[esx]/EasyAdmin/dependencies/images/banner-hardadmin.png and /dev/null differ diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/images/banner-logo.png b/server-data/resources/[esx]/EasyAdmin/dependencies/images/banner-logo.png deleted file mode 100644 index 616920e8a..000000000 Binary files a/server-data/resources/[esx]/EasyAdmin/dependencies/images/banner-logo.png and /dev/null differ diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/images/logo-eoa.png b/server-data/resources/[esx]/EasyAdmin/dependencies/images/logo-eoa.png deleted file mode 100644 index e4bbc1aff..000000000 Binary files a/server-data/resources/[esx]/EasyAdmin/dependencies/images/logo-eoa.png and /dev/null differ diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/images/logo-hardadmin.png b/server-data/resources/[esx]/EasyAdmin/dependencies/images/logo-hardadmin.png deleted file mode 100644 index 0cfae2d3a..000000000 Binary files a/server-data/resources/[esx]/EasyAdmin/dependencies/images/logo-hardadmin.png and /dev/null differ diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/images/pl_badge_contr.png b/server-data/resources/[esx]/EasyAdmin/dependencies/images/pl_badge_contr.png deleted file mode 100644 index f7b9378b0..000000000 Binary files a/server-data/resources/[esx]/EasyAdmin/dependencies/images/pl_badge_contr.png and /dev/null differ diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/images/pl_badge_dev.png b/server-data/resources/[esx]/EasyAdmin/dependencies/images/pl_badge_dev.png deleted file mode 100644 index 79fdbcf4b..000000000 Binary files a/server-data/resources/[esx]/EasyAdmin/dependencies/images/pl_badge_dev.png and /dev/null differ diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/images/pride.png b/server-data/resources/[esx]/EasyAdmin/dependencies/images/pride.png deleted file mode 100644 index c7af26936..000000000 Binary files a/server-data/resources/[esx]/EasyAdmin/dependencies/images/pride.png and /dev/null differ diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/images/small-logo-bg.png b/server-data/resources/[esx]/EasyAdmin/dependencies/images/small-logo-bg.png deleted file mode 100644 index 4321bfd51..000000000 Binary files a/server-data/resources/[esx]/EasyAdmin/dependencies/images/small-logo-bg.png and /dev/null differ diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/images/small-logo.png b/server-data/resources/[esx]/EasyAdmin/dependencies/images/small-logo.png deleted file mode 100644 index 5c2002a26..000000000 Binary files a/server-data/resources/[esx]/EasyAdmin/dependencies/images/small-logo.png and /dev/null differ diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/images/ukraine.png b/server-data/resources/[esx]/EasyAdmin/dependencies/images/ukraine.png deleted file mode 100644 index f544d4ebe..000000000 Binary files a/server-data/resources/[esx]/EasyAdmin/dependencies/images/ukraine.png and /dev/null differ diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/nui/index.html b/server-data/resources/[esx]/EasyAdmin/dependencies/nui/index.html deleted file mode 100644 index 2b2cfedd6..000000000 --- a/server-data/resources/[esx]/EasyAdmin/dependencies/nui/index.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - Keyboard Input - - - - - - - -
- - -
- -
-

- - -
- - -
- -
- \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/nui/input/shadow.js b/server-data/resources/[esx]/EasyAdmin/dependencies/nui/input/shadow.js deleted file mode 100644 index 1801933ce..000000000 --- a/server-data/resources/[esx]/EasyAdmin/dependencies/nui/input/shadow.js +++ /dev/null @@ -1,74 +0,0 @@ -(function() { - var Filters = {} - - var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg') - svg.setAttribute('style', 'display:block;width:0px;height:0px') - var defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs') - - var blurFilter = document.createElementNS('http://www.w3.org/2000/svg', 'filter') - blurFilter.setAttribute('id', 'svgBlurFilter') - var feGaussianFilter = document.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur') - feGaussianFilter.setAttribute('stdDeviation', '0 0') - blurFilter.appendChild(feGaussianFilter) - defs.appendChild(blurFilter) - Filters._svgBlurFilter = feGaussianFilter - - // Drop Shadow Filter - var dropShadowFilter = document.createElementNS('http://www.w3.org/2000/svg', 'filter') - dropShadowFilter.setAttribute('id', 'svgDropShadowFilter') - var feGaussianFilter1 = document.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur') - feGaussianFilter1.setAttribute('in', 'SourceAlpha') - feGaussianFilter1.setAttribute('stdDeviation', '3') - dropShadowFilter.appendChild(feGaussianFilter1) - Filters._svgDropshadowFilterBlur = feGaussianFilter1 - - var feOffset = document.createElementNS('http://www.w3.org/2000/svg', 'feOffset') - feOffset.setAttribute('dx', '0') - feOffset.setAttribute('dy', '0') - feOffset.setAttribute('result', 'offsetblur') - dropShadowFilter.appendChild(feOffset) - Filters._svgDropshadowFilterOffset = feOffset - - var feFlood = document.createElementNS('http://www.w3.org/2000/svg', 'feFlood') - feFlood.setAttribute('flood-color', 'rgba(0,0,0,1)') - dropShadowFilter.appendChild(feFlood) - Filters._svgDropshadowFilterFlood = feFlood - - var feComposite = document.createElementNS('http://www.w3.org/2000/svg', 'feComposite') - feComposite.setAttribute('in2', 'offsetblur') - feComposite.setAttribute('operator', 'in') - dropShadowFilter.appendChild(feComposite) - var feComposite1 = document.createElementNS('http://www.w3.org/2000/svg', 'feComposite') - feComposite1.setAttribute('in2', 'SourceAlpha') - feComposite1.setAttribute('operator', 'out') - feComposite1.setAttribute('result', 'outer') - dropShadowFilter.appendChild(feComposite1) - - var feMerge = document.createElementNS('http://www.w3.org/2000/svg', 'feMerge') - var feMergeNode = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode') - feMerge.appendChild(feMergeNode) - var feMergeNode1 = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode') - feMerge.appendChild(feMergeNode1) - Filters._svgDropshadowMergeNode = feMergeNode1 - dropShadowFilter.appendChild(feMerge) - defs.appendChild(dropShadowFilter) - svg.appendChild(defs) - document.documentElement.appendChild(svg) - - const blurScale = 1 - const scale = (document.body.clientWidth / 1280) - - Filters._svgDropshadowFilterBlur.setAttribute('stdDeviation', - Number(blurScale) + ' ' + - Number(blurScale) - ) - Filters._svgDropshadowFilterOffset.setAttribute('dx', - String(Number(Math.cos(45 * Math.PI / 180)) * scale)) - Filters._svgDropshadowFilterOffset.setAttribute('dy', - String(Number(Math.sin(45 * Math.PI / 180)) * scale)) - Filters._svgDropshadowFilterFlood.setAttribute('flood-color', - 'rgba(0, 0, 0, 1)') - Filters._svgDropshadowMergeNode.setAttribute('in', - 'SourceGraphic') - -})() \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/dependencies/nui/input/style.css b/server-data/resources/[esx]/EasyAdmin/dependencies/nui/input/style.css deleted file mode 100644 index 1396a00fa..000000000 --- a/server-data/resources/[esx]/EasyAdmin/dependencies/nui/input/style.css +++ /dev/null @@ -1,129 +0,0 @@ -/* ==================================================== -Recreating the email field from https://webflow.com/cms. Just an experiment - not as cross-browser friendly as the original. -Changed: -- animated gradient bar to :after element -- flexbox for layout -==================================================== */ -html { - box-sizing: border-box; - font-size: 10px; - } - - *, *:before, *:after { - box-sizing: inherit; - } - - body, ul, li { - margin: 0; - padding: 0; - } - - li { - list-style: none; - } - - p, h1, h2, h3, h4, h5, h6 { - margin-top: 0; - } - - a { - text-decoration: none; - } - - input { - border-style: none; - background: transparent; - outline: none; - } - - button { - padding: 0; - background: none; - border: none; - outline: none; - } - - body { - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - background: transparent; - top: 50%; - left: 50%; - } - - .demo-flex-spacer { - flex-grow: 1; - } - - .container { - display: flex; - flex-direction: column; - height: 100vh; - max-width: 1600px; - padding: 0 15px; - margin: 0 auto; - } - - .webflow-style-input { - position: relative; - display: none; - flex-direction: row; - width: 100%; - max-width: 450px; - margin: 0 auto; - border-radius: 2px; - padding: 1.4rem 2rem 1.6rem; - background: rgba(57, 63, 84, 0.6); - filter: url(#svgDropShadowFilter); - } - - .webflow-style-button { - position: absolute; - right: 5px; - top: 50% - } - - .webflow-style-input:after { - content: ""; - position: absolute; - left: 0px; - right: 0px; - bottom: 0px; - z-index: 999; - height: 2px; - border-bottom-left-radius: 2px; - border-bottom-right-radius: 2px; - background: linear-gradient(to right, #3C4E63, #526B86); - } - - .webflow-style-input input { - flex-grow: 1; - color: #BFD2FF; - font-size: 1.8rem; - line-height: 2.4rem; - vertical-align: middle; - width:100%; - } - - .webflow-style-text { - color: #b5cafc; - font-size: 1.6rem; - margin-bottom: 0.3rem; - vertical-align: middle; - } - - .webflow-style-input input::-webkit-input-placeholder { - color: #8B95B7; - } - - .webflow-style-input button { - color: #8B95B7; - font-size: 2.4rem; - line-height: 2.4rem; - vertical-align: middle; - transition: color 0.25s; - } - .webflow-style-input button:hover { - color: #BFD2FF; - } \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/fxmanifest.lua b/server-data/resources/[esx]/EasyAdmin/fxmanifest.lua deleted file mode 100644 index 34093b4c4..000000000 --- a/server-data/resources/[esx]/EasyAdmin/fxmanifest.lua +++ /dev/null @@ -1,86 +0,0 @@ -fx_version "cerulean" - -games {"gta5"} - -author 'Blumlaut ' -description 'EasyAdmin - Admin Menu for FiveM' -version '7.02' - - -lua54 'yes' - -shared_script 'shared/util_shared.lua' - -server_scripts { - "server/*.lua", - "server/bot/*.js", - "plugins/**/*_shared.lua", - "plugins/**/*_server.lua" -} - -client_scripts { - "dependencies/NativeUI.lua", - "dependencies/Controls.lua", - "client/*.lua", - "plugins/**/*_shared.lua", - "plugins/**/*_client.lua" -} - -ui_page "dependencies/nui/index.html" - -files { - "dependencies/images/*.png", - "dependencies/nui/**/*" -} - -dependencies { - 'yarn' -} - -provide 'EasyAdmin' - - -convar_category 'EasyAdmin' { - "Configuration Options", - { - { "EasyAdmin language", "$ea_LanguageName", "CV_STRING", "en" }, - { "Default key to open the menu", "$ea_defaultKey", "CV_STRING", "none" }, - { "The Minimum Amount of Identifiers", "$ea_minIdentifierMatches", "CV_INT", "2" }, - { "Display banlist checking progress", "$ea_presentDeferral", "CV_BOOL", "true" }, - { "Moderation Actions Webhook", "$ea_moderationNotification", "CV_STRING", "false" }, - { "Report Notifications Webhook", "$ea_reportNotification", "CV_STRING", "false" }, - { "Detail Notifications Webhook", "$ea_detailNotification", "CV_STRING", "false" }, - { "Set a custom DateTime format", "$ea_dateFormat", "CV_STRING", "%d/%m/%Y %H:%M:%S" }, - { "Image Uploader", "$ea_screenshoturl", "CV_STRING", "none" }, - { "Screenshot Field Name", "$ea_screenshotfield", "CV_STRING", "files[]" }, - { "JSON String arguments", "$ea_screenshotOptions", "CV_STRING", "{}" }, - { "Screenshot on Report", "$ea_enableReportScreenshots", "CV_BOOL", "true" }, - { "Webhook Identifier", "$ea_logIdentifier", "CV_STRING", "steam" }, - { "Enable calladmin Command", "$ea_enableCallAdminCommand", "CV_BOOL", "true" }, - { "Enable report Command", "$ea_enableReportCommand", "CV_BOOL", "true" }, - { "calladmin Command Name", "$ea_callAdminCommandName", "CV_STRING", "calladmin" }, - { "report Command Name", "$ea_reportCommandName", "CV_STRING", "report" }, - { "calladmin Cooldown (seconds)", "$ea_callAdminCooldown", "CV_INT", "60" }, - { "Minimum Reports to Ban Someone", "$ea_defaultMinReports", "CV_INT", "3" }, - { "Report Ban Time (unix time)", "$ea_ReportBanTime", "CV_INT", "86400" }, - { "Allow Minimum Report Count", "$ea_MinReportModifierEnabled", "CV_BOOL", "true" }, - { "Minimum Amount of Players to enable Report Modifier", "$ea_MinReportPlayers", "CV_INT", "12" }, - { "Divisor of Player Count to get minimum reports needed count", "$ea_MinReportModifier", "CV_BOOL", "true" }, - { "Amount of Warns before Actions", "$ea_maxWarnings", "CV_INT", "3" }, - { "Maximum Warn Action", "$ea_warnAction", "CV_STRING", "kick" }, - { "Maximum Warn Ban Time (unix time)", "$ea_warningBanTime", "CV_INT", "604800" }, - { "Hide IP in the GUI", "$ea_IpPrivacy", "CV_BOOL", "true" }, - { "Banlist Backup Time (hours)", "$ea_backupFrequency", "CV_INT", "72" }, - { "Maximum Backup Count", "$ea_maxBackupCount", "CV_INT", "10" }, - { "Chat Reminder Time (minutes, disabled if 0)", "$ea_chatReminderTime", "CV_INT", "0" }, - { "Time before Cached Player Expires", "$ea_playerCacheExpiryTime", "CV_INT", "900" }, - { "Set Debug Level", "$ea_logLevel", "CV_INT", "1" }, - { "Enable Custom Banlist", "$ea_custombanlist", "CV_BOOL", "false" }, - { "Use Tokens as Identifiers", "$ea_useTokenIdentifiers", "CV_BOOL", "true" }, - { "Enable Ascii Art on Start", "$ea_enableSplash", "CV_BOOL", "true" }, - { "Token for Discord bot", "$ea_botToken", "CV_STRING", "none" }, - { "Channel for Discord bot to log", "$ea_botLogChannel", "CV_STRING", "none" }, - { "Channel for Discord bot to enable live status", "$ea_botStatusChannel", "CV_STRING", "true" }, - { "Enable Allowlist", "$ea_enableAllowlist", "CV_BOOL", "false" } - } -} diff --git a/server-data/resources/[esx]/EasyAdmin/language/de.json b/server-data/resources/[esx]/EasyAdmin/language/de.json deleted file mode 100644 index 55e78aa11..000000000 --- a/server-data/resources/[esx]/EasyAdmin/language/de.json +++ /dev/null @@ -1,239 +0,0 @@ -[{ - "translator": "EasyAdmin, zRxnx", - "language": "de", - "on": "An", - "off": "Aus", - - "spectatingUser": "Schaue ~b~%s ~w~zu.", - "stoppedSpectating": "Zuschauermodus verlassen.", - "hour": "Stunde", - "hours": "Stunden", - "day": "Tag", - "days": "Tage", - "week": "Woche", - "weeks": "Wochen", - "month": "Monat", - "months": "Monate", - "year": "Jahr", - "years": "Jahre", - "customtime": "Eigener Zeitraum", - "nocustombantime": "Du musst erst einen Zeitraum setzen!", - "permanent": "Permanent", - "confirm": "Bestätigen", - "playermanagement": "Spielermanagement", - "servermanagement": "Servermanagement", - "settings": "Einstellungen", - "kickplayer": "Spieler Kicken", - "banplayer": "Spieler Bannen", - "reason": "Grund", - "kickreasonguide": "Kick Grund angeben.", - "noreason": "Keinen Grund angegeben.", - "confirmkick": "Kick bestätigen", - "confirmkickguide": "~r~~h~ACHTUNG:~h~~w~ Durch das drücken von bestätigen wird der Spieler mit dem angegebenen Grund gekickt.", - "banreasonguide": "Bann Grund angeben.", - "banlength": "Bann Länge", - "banlengthguide": "Wie lange soll der Spieler gebannt werden?", - "confirmban": "Bann bestätigen", - "confirmbanguide": "~r~~h~ACHTUNG:~h~~w~ Durch das drücken von bestätigen wird der Spieler mit dem angegebenen Grund gebannt.", - "mute": "Spieler stummschalten", - "muteguide": "~r~~h~ACHTUNG:~h~~w~ Dadurch wird verhindert, dass der Spieler den Text-Chat verwenden kann.", - "adminmutedplayer": "**%s** hat **%s** gestummt", - "adminunmutedplayer": "**%s** hat **%s** entstummt", - "playermuted": "wurde stummgeschaltet!", - "playerunmuted": "wurde entstummt!", - "playermute": "Du bist stummgeschaltet!", - "spectateplayer": "Spieler zuschauen", - "teleportplayer": "Teleportieren", - "teleporttoplayer": "Zum Spieler", - "teleportplayertome": "Spieler zu mir", - "slapplayer": "Spieler schlagen", - "setplayerfrozen": "Spieler einfrieren", - "allplayers": "Alle Spieler", - "teleporttome": "Zu mir Teleportieren", - "teleporttomeguide": "~r~~h~ACHTUNG:~h~~w~ Das wird ~h~alle~h~ Spieler zu dir Teleportieren.", - "setgametype": "Spiel-Typ setzen", - "setgametypeguide": "~r~~h~ACHTUNG:~h~~w~ Das wird den Spiel-Typ wie er auf der Serverliste angezeigt wird setzen.", - "setmapname": "Karten Namen setzen", - "setmapnameguide": "~r~~h~ACHTUNG:~h~~w~ Das wird den Karten Namen wie er auf der Serverliste angezeigt wird setzen.", - "startresourcebyname": "Ressource mit Namen starten", - "startresourcebynameguide": "~r~~h~ACHTUNG:~h~~w~ Das wird eine Ressource die auf dem server installiert ist starten.", - "stopresourcebyname": "Ressource mit Namen stoppen", - "stopresourcebynameguide": "~r~~h~ACHTUNG:~h~~w~ Das wird eine Ressource die auf dem server installiert ist stoppen.", - "badidea": "Das würde ich lieber nicht tuhen.", - "viewbanlist": "Bannliste ansehen", - "unbanplayer": "Spieler entbannen", - "unbanplayerguide": "~r~~h~ACHTUNG:~h~~w~ Durch das drücken von bestätigen wird der Spieler entbannt.", - "banlistshowtype": "~h~Bannliste:~h~ Typ Anzeigen", - "unbanreasons": "Gründe", - "unbanlicenses": "Lizenzen", - "banlistshowtypeguide": "Zwischen Gründen und Lizenzen wechseln .\nErfordert erneutes öffnen des Adminpanels.", - "refreshbanlist": "Bannliste neu laden", - "refreshbanlistguide": "Das wird die Bannliste neu laden.\nErfordert erneutes öffnen des Adminpanels.", - "refreshpermissions": "Berechtigungen neu Laden", - "refreshpermissionsguide": "Das wird deine jetzigen Berechtigungen neu laden.\nErfordert erneutes öffnen des Adminpanels.", - "godmodedetected": "Godmode: ~r~Erkannt~w~", - "godmodenotdetected": "Godmode: ~g~Nicht Erkannt~w~", - "antiragdoll": "~r~Anti-Ragdoll~w~", - "health": "Leben", - "armor": "Rüstung", - "wantedlevel": "Fahndungslevel", - "exitspectator": "Drücke E um den Zuschauermodus zu verlassen.", - - "allowlist": "Du hast keine Berechtigung diesen Server zu betreten", - "checkingallowlist": "Prüfe Allowlist..", - "bannedjoin": "\nDu wurdest von diesem server gebannt, \nGrund: %s, \nBann Läuft am %s ab\nDeine Bann-ID lautet #%s.", - "kicked": "Gekickt von %s, \nGrund: %s", - "banned": "Du wurdest von diesem server gebannt, \nGrund: %s, \nBann Läuft am %s ab.", - "reasonadd": " ( Spielername: %s ), \nGebannt von: %s", - "nongiven": "Keinen gegeben", - "announcement": "Announcement", - "announcementguide": "Send an announcement to all players", - "adminannouncement": "**%s** sent an announcement: **%s**", - "playernotfound": "Spieler wurde nicht gefunden.", - "done": "Fertig!", - "adminkickedplayer": "**%s** hat **%s** gekickt, Grund: %s", - "adminbannedplayer": "**%s** hat **%s** gebannt, Grund: %s, Bann entfällt: %s, ID: %s", - "adminunbannedplayer": "**%s** hat **%s** entbannt. [ %s ]", - "adminslappedplayer": "**%s** hat **%s** geschlagen **(%s Leben)**.", - - "adminfrozeplayer": "**%s** hat **%s** eingefroren.", - "adminunfrozeplayer": "**%s** hat **%s** entfroren.", - - "left": "Links", - "middle": "Mitte", - "right": "Rechts", - "menuOrientation": "Menüorientation", - "menuOrientationguide": "Menü Orientation setzen ( Links, Rechts oder Mitte ) \nErfordert Spielneustart.", - "menuOffset": "Menüoffset", - "menuOffsetguide": "Menü länger machen.\nErfordert erneutes öffnen des Adminpanels.", - "resetmenuOffset": "Menüoffset Zurücksetzen", - "takescreenshot": "Screenshot erstellen", - "admintookscreenshot": "**%s** hat ein Screenshot von **%s**'s Bildschirm Erstellt: %s", - "screenshotinprogress": "Ein Screenshot wird bereits erstellt, bitte warten!", - "screenshotlink": "Der Screenshot ist hier verfügbar: %s", - "anonymous": "Anonymer Admin", - "anonymousguide": "Blendet dein Namen aus, wenn du die EasyAdmin-Funktionen verwendest.", - "adminofflinebannedplayer": "**%s** hat Offline-Spieler **%s** gebannt, Grund: %s, Bann Läuft am %s ab.", - "cachedplayers": "Frühere Spieler", - "refreshcachedplayers": "Frühere Spielerliste aktualisieren", - "refreshcachedplayersguide": "Aktualisiert die Liste der früheren Spieler. Erfordert erneutes öffnen des Adminpanels.", - "adminrequestedofflineinfo": "**%s** hat die Nutzerdaten des Spielers **%s** angefordert", - "nextpage": "Nächste Seite»", - "firstpage": "««Erste Seite", - "lastpage": "Letzte Seite»»", - "previouspage": "«Vorherige Seite", - "playercalledforadmin": "Spieler %s ruft nach einem Admin!\nGrund: %s\nID: %s\n", - "playerreportedplayer": "Spieler %s hat einen Spieler gemeldet!\n%s, Grund: %s\nReport %s/%s\nID: %s\n", - "successfullyreported": "Spieler erfolgreich gemeldet!", - "reportbantext": "Von %s Spielern in kurzer Zeit gemeldet.", - "alreadyreported": "Du hast diesen Spieler schon gemeldet!", - "reportedusageerror": "Fehler! Nutzung: /report Name Grund", - "admincalled": "Ein Admin wurde erfolgreich gerufen!", - "spectatedplayer": "**%s** hat **%s** zugesehen", - "teleportedtoplayer": "**%s** teleportiert nach **%s**", - "searchbans": "Bann suchen", - "searchbansfail": "Es wurde kein Bann gefunden.", - "identifier": "%s Identifier", - "warnplayer": "Spieler warnen", - "warnreasonguide": "Einen Grund zur Warnung hinzufügen.", - "confirmwarn": "Warnung bestätigen", - "confirmwarnguide": "~r~~h~ACHTUNG:~h~~w~ Durch das drücken von bestätigen wird der Spieler mit dem angegebenen Grund gewarnt.", - "warnedtitle": "Warnung", - "warnedby": "verwarnt durch", - "warndismiss": "Halte die Leertaste für 10 Sekunden gedrückt, um die Warnung zu schließen.", - "warned": "Du wurdest verwarnt, Grund: %s, Warnung %s/%s", - "warnkicked": "Du wurdest gekickt, weil du zu oft verwarnt wurdest.", - "warnbanned": "Du wurdest gebannt, weil du zu oft verwarnt wurdest.", - "adminwarnedplayer": "**%s** hat **%s** gewarnt, Grund: %s, Warnung %s/%s", - - "searchuser": "Spieler suchen", - "searchuserguide": "Spieler mit Spielernamen oder Server ID finden.", - - "setconvar": "Convar Setzen", - "setconvarguide": "~r~~h~ACHTUNG:~h~~w~ Nur mit wissen anfassen!\nÄndert eine Convar.", - "adminchangedconvar": "**%s** hat die Convar **%s** zu **%s** geändert.", - "adminstartedresource": "**%s** hat die Ressource **%s** gestartet", - "adminstoppedresource": "**%s** hat die Ressource **%s** gestoppt", - - "convarname": "Convar Name", - "convarvalue": "Convar Inhalt", - - "cleanarea": "Gebiet aufräumen", - "cleanareaguide": "Entfernt alle Gegenstände in der nähe.", - "cars": "Fahrzeuge", - "peds": "NPC's", - "props": "Objekte", - "cleaningcar": "Loesche Fahrzeug %s", - "cleaningped": "Loesche NPC %s", - "cleaningprop": "Loesche Objekt %s", - "finishedcleaning": "Löschen von %s beendet.", - "admincleanedup": "**%s** hat alle **%s** in einem **%s** radius gelöscht.", - "radius": "Radius", - "type": "Art", - "deepclean":"Tiefe Reinigung", - "deepcleanguide":"Löscht auch clientseitige Gegenstände.", - - "forceeasteregg": "Easter Egg aktivieren", - - "permissioneditor": "Permissions anpassen", - "permissioneditorguide": "Permissions auf dem Server editieren, speichert nach ~g~easyadmin_permissions.cfg~w~.", - - "aces": "ACEs", - "permission": "Permission", - "principals": "Principals", - "addace": "~g~ACE hinzufügen", - "addaceguide": "Du kannst das ganze vor dem abspeichern nochmal editieren.", - "addprincipal": "~g~Principal hinzufügen", - "group": "Gruppe", - "entergroup": "Gruppennamen einfügen (z.b. group.admin)", - "enterperm": "Permissionnamen einfügen (z.b. easyadmin.player.kick)", - "state": "Status", - "stateguide": "Das verweigern von Permissions funktioniert nicht richtig. Erlaube nur die Permissions, die der Spieler haben soll.", - "location": "Ort", - "locationguide": "Dieser Wert kann nicht bearbeitet werden.", - "principal": "Principal", - "enterprincipal": "Principal einfügen (e.g. identifier.steam:aabbccddeefff)", - "deletepermission": "~r~Permission löschen", - "deletepermissionguide": "~r~~h~ACHTUNG:~h~~w~ Dadurch wird die Permission vollständig widerrufen und gelöscht!", - "deleteprincipal": "~r~Principal löschen", - "deleteprincipalguide": "~r~~h~ACHTUNG:~h~~w~ Dadurch wird der Principal vollständig widerrufen und gelöscht!", - - "itemdeleted": "~r~Dieser Eintrag wurde gelöscht.", - "savechanges": "~g~Änderungen speichern", - "savechangesguide": "~r~~h~ACHTUNG:~h~~w~ Das kann nicht rückgängig gemacht werden!", - "admineditedpermissions": "**%s** hat die Berechtigungen des Servers bearbeitet.", - - "reportviewer": "Report Viewer", - "call": "Ruf", - "report": "Report", - "open": "Offen", - "reporter": "Melder", - "reported": "Gemelderter", - "closereport": "Report schließen", - "closesimilarreports": "~r~Ähnliche Reports schließen~w~", - "closesimilarreportsguide": "Versucht ähnliche Reports zu finden und zu löschen.", - "adminclosedreport": "**%s** hat Report #**%s** geschlossen.", - "adminclaimedreport": "**%s** claimed Report #**%s**", - "refreshreports": "Reports aktualisieren", - "refreshreportsguide": "Zeigt neue Reports an, falls es neue gibt seitdem das Menü geöffnet wurde.", - "waitbeforeusingagain": "Du musst warten bevor du das benutzen kannst!", - "invalidreport": "Du musst einen Grund angeben!", - "claimreport": "Report übernehmen", - "claimedby": "Übernommen von", - "reportalreadyclaimed": "Dieser Report wurde bereits übernommen", - "notification": "Benachrichtigung", - "deferral": "Prüfe Bannliste, bitte warten... (%s%%)", - "savebanchanges": "Änderungen speichern", - "savebanguide": "~r~~h~ACHTUNG:~h~~w~ Durch das drücken von bestätigen wird der Bann überschrieben", - "adminimmune": "Dazu hast du keine Rechte, der ausgewählte Spieler ist Immun", - "teleportmeback": "Teleportiere mich zurück", - "teleportplayerback": "Teleportiere Spieler zurück", - "teleportintoclosestvehicle":"zum nächstliegenden Auto", - - "copiedtoclipboard": "Text wurde in die Zwischenablage kopiert!", - - "spectatevehicleseatoccupied": "Der Fahrzeugsitz auf dem du gesessen hast, ist jetzt besetzt", - "spectatenovehiclefound": "Das Fahrzeug in dem du gesessen hast, wurde nicht mehr gefunden", - "screenreader":"Screen Reader (TTS)", - "screenreaderguide":"Aktiviert Text to Speech für die GUI" -}] diff --git a/server-data/resources/[esx]/EasyAdmin/language/en.json b/server-data/resources/[esx]/EasyAdmin/language/en.json deleted file mode 100644 index 91035fcce..000000000 --- a/server-data/resources/[esx]/EasyAdmin/language/en.json +++ /dev/null @@ -1,240 +0,0 @@ -[{ - "translator": "EasyAdmin", - "language": "en", - "on": "On", - "off": "Off", - "spectatingUser": "Spectating ~b~%s.", - "stoppedSpectating": "Stopped Spectating.", - "hour": "Hour", - "hours": "Hours", - "day": "Day", - "days": "Days", - "week": "Week", - "weeks": "Weeks", - "month": "Month", - "months": "Months", - "year": "Year", - "years": "Years", - "customtime": "Custom Time", - "nocustombantime": "You need to set a custom ban length first!", - "permanent": "Permanent", - "confirm": "Confirm", - "playermanagement": "Player Management", - "servermanagement": "Server Management", - "settings": "Settings", - "kickplayer": "Kick Player", - "banplayer": "Ban Player", - "reason": "Reason", - "kickreasonguide": "Add a reason to the kick.", - "noreason": "No Reason Specified", - "confirmkick": "Confirm Kick", - "confirmkickguide": "~r~~h~NOTE:~h~~w~ Pressing Confirm will kick this Player with the specified settings.", - "banreasonguide": "Add a reason to the ban.", - "banlength": "Ban Length", - "banlengthguide": "Until when should the Player be banned?", - "confirmban": "Confirm Ban", - "confirmbanguide": "~r~~h~NOTE:~h~~w~ Pressing Confirm will ban this Player with the specified settings.", - "mute": "Mute Player", - "muteguide": "~r~~h~NOTE:~h~~w~ This will prevent the player from using the text chat.", - "adminmutedplayer": "**%s** muted **%s**", - "adminunmutedplayer": "**%s** unmuted **%s**", - "playermuted": "has been muted!", - "playerunmuted": "has been un-muted!", - "playermute": "You are muted!", - "spectateplayer": "Spectate Player", - "teleportplayer": "Teleport", - "teleporttoplayer": "Me to Player", - "teleportplayertome": "Player to Me", - "slapplayer": "Slap Player", - "setplayerfrozen": "Set Player Frozen", - "allplayers": "All Players", - "teleporttome": "Teleport To Me", - "teleporttomeguide": "~r~~h~NOTE:~h~~w~ This will teleport ~h~all~h~ players to you.", - "setgametype": "Set Game Type", - "setgametypeguide": "~r~~h~NOTE:~h~~w~ This will set the Game Type as listed on the Serverlist.", - "setmapname": "Set Map Name", - "setmapnameguide": "~r~~h~NOTE:~h~~w~ This will set the Map Name as listed on the Serverlist.", - "startresourcebyname": "Start Resource by Name", - "startresourcebynameguide": "~r~~h~NOTE:~h~~w~ This will start a resource installed on the server.", - "stopresourcebyname": "Stop Resource by Name", - "stopresourcebynameguide": "~r~~h~NOTE:~h~~w~ This will stop a resource installed on the server.", - "badidea": "Don't do that, please.", - "viewbanlist": "View Banlist", - "unbanplayer": "Unban Player", - "unbanplayerguide": "~r~~h~NOTE:~h~~w~ Pressing Confirm will unban this Player.", - "banlistshowtype": "~h~Banlist:~h~ Show Type", - "unbanreasons": "Reasons", - "unbanlicenses": "Licenses", - "banlistshowtypeguide": "Toggle Between Ban Reasons or Identifiers in the 'Unban Player' Menu.\nRequires Reopening.", - "refreshbanlist": "Refresh Banlist", - "refreshbanlistguide": "This Refreshes the Banlist in the 'Unban Player' Menu.\nRequires Reopening.", - "refreshpermissions": "Refresh Permissions", - "refreshpermissionsguide": "This Refreshes your current Permissions.\nRequires Reopening.", - "godmodedetected": "Godmode: ~r~Detected~w~", - "godmodenotdetected": "Godmode: ~g~None Detected~w~", - "antiragdoll": "~r~Anti-Ragdoll~w~", - "health": "Health", - "armor": "Armor", - "wantedlevel": "Wanted Level", - "exitspectator": "Press E to exit spectator mode", - - "allowlist": "You are not allowlisted on this server", - "checkingallowlist": "Checking allowlist..", - "bannedjoin": "\nYou have been banned from this Server\n\nReason: %s\n\nBan Expires: %s\nYour Ban ID is #%s.", - "kicked": "Kicked by %s, Reason: %s", - "banned": "You have been banned from this Server, Reason: %s, Ban Expires: %s", - "reasonadd": " ( Nickname: %s ), Banned by: %s", - "nongiven": "None Provided", - "announcement": "Announcement", - "announcementguide": "Send an announcement to all players", - "adminannouncement": "**%s** sent an announcement: **%s**", - "playernotfound": "Player could not be found.", - "done": "Done!", - "adminkickedplayer": "**%s** kicked **%s**, Reason: %s", - "adminbannedplayer": "**%s** banned **%s**, Reason: %s, Ban Expires: %s, ID: %s", - "adminunbannedplayer": "**%s** unbanned **%s** [ %s ]", - "adminslappedplayer": "**%s** slapped **%s** for **%s HP**", - - "adminfrozeplayer": "**%s** froze **%s**.", - "adminunfrozeplayer": "**%s** unfroze **%s**.", - - "left": "Left", - "middle": "Middle", - "right": "Right", - "menuOrientation": "Menu Orientation", - "menuOrientationguide": "Set Menu Orientation ( Left, Right or Center ) \nRequires Game Restart.", - "menuOffset": "Menu Offset", - "menuOffsetguide": "Set Menu Size Offset\nRequires Re-opening of Menu.", - "resetmenuOffset": "Reset Menu Offset", - "takescreenshot": "Take Screenshot", - "admintookscreenshot": "**%s** took a Screenshot of **%s**'s Screen: %s", - "screenshotinprogress": "a Screenshot is already in progress, please wait!", - "screenshotlink": "The Screenshot is available here: %s", - "anonymous": "Anonymous Admin", - "anonymousguide": "Hides your Name when using EasyAdmin Features.", - "adminofflinebannedplayer": "**%s** offline banned **%s**, Reason: %s, Ban Expires: %s", - "cachedplayers": "Cached Players", - "refreshcachedplayers": "Refresh Cached Players", - "refreshcachedplayersguide": "Refreshes List of Cached Players, requires reopening.", - "adminrequestedofflineinfo": "**%s** requested User Data of Offline User **%s**", - "nextpage": "Next Page»", - "firstpage": "««First Page", - "lastpage": "Last Page»»", - "previouspage": "«Previous Page", - "playercalledforadmin": "User %s calls for an admin!\nReason: %s\nID: %s\n", - "playerreportedplayer": "User %s reported a player!\n%s, Reason: %s\nReport %s/%s\nID: %s\n", - "successfullyreported": "Successfully reported the player!", - "reportbantext": "Reported by %s Players in short time.", - "alreadyreported": "You already reported this player!", - "reportedusageerror": "Error! Usage: /report name reason", - "admincalled": "Successfully called an Admin!", - "spectatedplayer": "**%s** has Spectated **%s**", - "teleportedtoplayer": "**%s** has Teleported to **%s**", - "searchbans": "Search Bans", - "searchbansfail": "No Ban with the Search Criteria was found.", - "identifier": "%s Identifier", - "warnplayer": "Warn Player", - "warnreasonguide": "Add a reason to the Warn.", - "confirmwarn": "Confirm Warn", - "confirmwarnguide": "~r~~h~NOTE:~h~~w~ Pressing Confirm will Warn this Player with the specified settings.", - "warnedtitle": "Warning", - "warnedby": "warned by", - "warndismiss": "Hold Spacebar for 10 Seconds to dismiss.", - "warned": "You have been warned, Reason: %s, Warning %s/%s", - "warnkicked": "You have been kicked due to getting Warned too many times.", - "warnbanned": "Warned too many times.", - "adminwarnedplayer": "**%s** warned **%s**, Reason: %s, Warning %s/%s", - - "searchuser": "Search for User", - "searchuserguide": "Find a Player using their Username or ID", - - "setconvar": "Set Convar", - "setconvarguide": "~r~NOTE: If you don't know what you are doing, don't touch this!~w~\nChanges a Convar", - "adminchangedconvar": "**%s** changed convar **%s** to **%s**", - "adminstartedresource": "**%s** started resource **%s**", - "adminstoppedresource": "**%s** stopped resource **%s**", - - "convarname": "Convar Name", - "convarvalue": "Convar Value", - - "cleanarea": "Cleanup Area", - "cleanareaguide": "Cleans up all nearby entities of selected type", - "cars": "Cars", - "peds": "Peds", - "props": "Props", - "cleaningcar": "Deleting Vehicle %s", - "cleaningped": "Deleting Ped %s", - "cleaningprop": "Deleting Object %s", - "finishedcleaning": "Finished cleaning %s", - "admincleanedup": "**%s** Cleaned up all **%s** in a **%s** radius.", - "radius": "Radius", - "type": "Type", - "deepclean":"Deep Clean", - "deepcleanguide":"Also deletes clientside entities.", - - "forceeasteregg": "Force Easter Egg", - - "permissioneditor": "Permission Editor", - "permissioneditorguide": "Edit Permissions on the Server, saves into ~g~easyadmin_permissions.cfg~w~", - - "aces": "ACEs", - "permission": "Permission", - "principals": "Principals", - "addace": "~g~Add ACE", - "addaceguide": "You have the opportunity to edit this before saving.", - "addprincipal": "~g~Add Principal", - "group": "Group", - "entergroup": "Enter group name (e.g. group.admin)", - "enterperm": "Enter Permission name (e.g. easyadmin.player.kick)", - "state": "State", - "stateguide": "Denying permissions does not work properly, only allow permissions you want the player to have.", - "location": "Location", - "locationguide": "This value cannot be edited.", - "principal": "Principal", - "enterprincipal": "Enter principal (e.g. identifier.steam:aabbccddeefff)", - "deletepermission": "~r~Delete Permission", - "deletepermissionguide": "~r~Warning! This will completely revoke and delete the Permission!", - "deleteprincipal": "~r~Delete Principal", - "deleteprincipalguide": "~r~Warning! This will completely revoke and delete the Principal!", - - "itemdeleted": "~r~This Item has been deleted.", - "savechanges": "~g~Save Changes", - "savechangesguide": "~r~Warning! ~w~This cannot be undone!", - "admineditedpermissions": "**%s** edited the server's permissions.", - - "reportviewer": "Report Viewer", - "call": "Call", - "report": "Report", - "open": "Open", - "reporter": "Reporter", - "reported": "Reported", - "closereport": "Close Report", - "closesimilarreports": "~r~Close all similar reports~w~", - "closesimilarreportsguide": "Will attempt to find and delete reports made by the same user.", - "adminclosedreport": "**%s** closed Report #**%s**", - "adminclaimedreport": "**%s** claimed Report #**%s**", - "entertoopen": "Select to display options for this player.", - "refreshreports": "Refresh Reports", - "refreshreportsguide": "Shows new reports in case there are any since last time the menu was opened.", - "waitbeforeusingagain": "You must wait before using this again!", - "invalidreport": "You need to specify a reason!", - "claimreport":"Claim Report", - "claimedby":"Claimed By", - "reportalreadyclaimed": "This report has already been claimed!", - "notification":"Notification", - "deferral":"Checking Banlist, please wait.. (%s%%)", - "savebanchanges":"Save Changes", - "savebanguide":"~r~~h~NOTE:~h~~w~ Pressing Confirm will update this Ban on the Server.", - "adminimmune":"You do not have permission to perform this action, target player is immune.", - "teleportmeback":"Teleport me back", - "teleportplayerback":"Teleport Player back", - "teleportintoclosestvehicle":"into closest vehicle", - - "copiedtoclipboard":"Text copied to Clipboard!", - - "spectatevehicleseatoccupied":"The vehicle seat you were in is now occupied.", - "spectatenovehiclefound":"The vehicle you were in can no longer be found.", - "screenreader":"Screen Reader (TTS)", - "screenreaderguide":"Enables Text to Speech for the GUI" - -}] diff --git a/server-data/resources/[esx]/EasyAdmin/language/es.json b/server-data/resources/[esx]/EasyAdmin/language/es.json deleted file mode 100644 index 6b9891649..000000000 --- a/server-data/resources/[esx]/EasyAdmin/language/es.json +++ /dev/null @@ -1,240 +0,0 @@ -[{ - "translator": "Antho#0707, Javiito32, Jenoxen#2894", - "language": "es", - "on": "Encendido", - "off": "Apagado", - "spectatingUser": "Especteando ~b~%s.", - "stoppedSpectating": "Has parado de Espectear.", - "hour": "Hora", - "hours": "Horas", - "day": "Dia", - "days": "Dias", - "week": "Semana", - "weeks": "Semanas", - "month": "Mes", - "months": "Meses", - "year": "Año", - "years": "Años", - "customtime": "Tiempo personalizado", - "nocustombantime": "Primero tienes que definir un tiempo de Baneo!", - "permanent": "Permanente", - "confirm": "Confirmar", - "playermanagement": "Gestionar Jugadores", - "servermanagement": "Gestionar Servidor", - "settings": "Ajustes", - "kickplayer": "Kickear jugador", - "banplayer": "Banear jugador", - "reason": "Razon", - "kickreasonguide": "Añade una razon.", - "noreason": "No se ha especificado una razón", - "confirmkick": "Confirmar Kickeo", - "confirmkickguide": "~r~~h~NOTA:~h~~w~ Presionando confirmar kickearas a este jugador con la configuración especificada.", - "banreasonguide": "Añadir una razon de baneo.", - "banlength": "Duración de baneo", - "banlengthguide": "¿Cuanto tiempo deseas banear al jugador?", - "confirmban": "Confirmar baneo", - "confirmbanguide": "~r~~h~NOTA:~h~~w~ Presionando confirmar banearas a este jugador con la configuración especificada.", - "mute": "Mutear jugador", - "muteguide": "~r~~h~NOTA:~h~~w~ Le prohibe el uso del chat al jugador.", - "adminmutedplayer": "**%s** ha muteado a **%s**", - "adminunmutedplayer": "**%s** ha desmuteado a **%s**", - "playermuted": "ha sido muteado", - "playerunmuted": "ha sido desmuteado", - "playermute": "Ha sido muteado", - "spectateplayer": "Espectear jugador", - "teleportplayer": "Teletransportar", - "teleporttoplayer": "hacia jugador", - "teleportplayertome": "jugador hacia mi", - "slapplayer": "Pegarle al jugador", - "setplayerfrozen": "Congelar al jugador", - "allplayers": "Todos los jugadores", - "teleporttome": "Teleportar hacia mi", - "teleporttomeguide": "~r~~h~NOTA:~h~~w~ Teletransportaras hacia ti a ~h~TODOS~h~ los jugadores.", - "setgametype": "Cambiar nombre de modo de juego", - "setgametypeguide": "~r~~h~NOTA:~h~~w~ Esto establecera el nombre del modo de juego.", - "setmapname": "Cambia el nombre de mapa", - "setmapnameguide": "~r~~h~NOTA:~h~~w~ Esto ajustara el nombre del mapa.", - "startresourcebyname": "Inicia un recurso o script por nombre", - "startresourcebynameguide": "~r~~h~NOTA:~h~~w~ Esto iniciara un recurso o script instalado en el servidor.", - "stopresourcebyname": "Detiene un recurso o script por nombre", - "stopresourcebynameguide": "~r~~h~NOTA:~h~~w~ Esto detendra a un recurso o script instalado en el servidor.", - "badidea": "NO hagas eso por favor.", - "viewbanlist": "Ver lista de baneos", - "unbanplayer": "Desbanear jugador", - "unbanplayerguide": "~r~~h~NOTA:~h~~w~ Presiona confirmar para desbanear al jugador.", - "banlistshowtype": "~h~Lista de Bans:~h~ Mostrar tipo de ban", - "unbanreasons": "Razones", - "unbanlicenses": "Licencias", - "banlistshowtypeguide": "Alterna entre razones de baneo o identificadores en el menú 'Desbanear jugador'.\nRequiere volver a entrar.", - "refreshbanlist": "Actualizar lista de baneos", - "refreshbanlistguide": "Esto actualiza la lista de baneos en el menú 'Desbanear jugador'.\nRequiere volver a entrar.", - "refreshpermissions": "Actualizar permisos", - "refreshpermissionsguide": "Esto actualiza sus permisos actuales.\nRequiere volver a entrar.", - "godmodedetected": "Godmode: ~r~Detectado~w~", - "godmodenotdetected": "Godmode: ~r~No detectado~w~", - "antiragdoll": "~r~Anti-Ragdoll~w~", - "health": "Vida", - "armor": "Armadura", - "wantedlevel": "Nivel de búsqueda", - "exitspectator": "Presiona E para salir del modo Espectador", - - "allowlist": "You are not allowlisted on this server", - "checkingallowlist": "Checking allowlist..", - "bannedjoin": "Has sido baneado del servidor, \nRazon: %s, Expira: %s, Ban ID: %s", - "kicked": "Has sido kickeado por %s, Razon: %s", - "banned": "Has sido baneado del servidor, Razon: %s, Expira: %s", - "reasonadd": " ( El jugador: %s ), ha sido baneado por: %s", - "nongiven": "No se ha proporcionado", - "announcement": "Anuncio", - "announcementguide": "Send an announcement to all players", - "adminannouncement": "**%s** sent an announcement: **%s**", - "playernotfound": "No se ha encontrado al jugador.", - "done": "Hecho", - "adminkickedplayer": "**%s** a kickeado a **%s**, Razon: %s", - "adminbannedplayer": "**%s** a baneado a **%s**, Razon: %s, Expira: %s, ID: %s", - "adminunbannedplayer": "**%s** a desbaneado a **%s** [ %s ]", - "adminslappedplayer": "**%s** le ha pegado a **%s** por **%s HP**", - - "adminfrozeplayer": "**%s** a congelado a **%s**.", - "adminunfrozeplayer": "**%s** a descongelado a **%s**.", - - "left": "Izquierda", - "middle": "Central", - "right": "Derecha", - "menuOrientation": "Posicion del menu", - "menuOrientationguide": "Ajusta la posición del menu ( Izquierda, Derecha o Central ) \nRequiere reiniciar el juego.", - "menuOffset": "Desplazamiento del menu", - "menuOffsetguide": "Establecer tamaño del menu\nRequiere reabrir el menú.", - "resetmenuOffset": "Reestablecer tamaño del menu", - "takescreenshot": "Sacar una captura", - "admintookscreenshot": "**%s** saco una captura de pantalla de **%s**'s Pantalla: %s", - "screenshotinprogress": "una captura de pantalla ya esta en progreso, por favor espere", - "screenshotlink": "La captura de pantalla estara disponible aqui: %s", - "anonymous": "Admin anonimo", - "anonymousguide": "Oculta su nombre cuando usa las funciones de EasyAdmin.", - "adminofflinebannedplayer": "**%s** baneado desconectado **%s**, Razon: %s, Expira: %s", - "cachedplayers": "Jugadores en cache", - "refreshcachedplayers": "Actualizar jugadores en cache", - "refreshcachedplayersguide": "Refresca la lista de jugadores en cache, Requiere volver a entrar.", - "adminrequestedofflineinfo": "**%s** datos solicitados del usuario sin conexion **%s**", - "nextpage": "Siguiente pagina»", - "firstpage": "««Primera pagina", - "lastpage": "Ultima pagina»»", - "previouspage": "«Pagina anterior", - "playercalledforadmin": "Usuario %s pide un administrador\nRazon: %s\nID: %s\n", - "playerreportedplayer": "Usuario %s reporto a un jugador\n%s, Razon: %s\nReporta %s/%s\nID: %s\n", - "successfullyreported": "Se ha reportado correctamente", - "reportbantext": "Reportado por %s jugadores en poco tiempo.", - "alreadyreported": "Ya has reportado a este jugador", - "reportedusageerror": "Error, Usa: /report nombre razon", - "admincalled": "Se ha llamado a un administrador exitosamente", - "spectatedplayer": "**%s** ha especteado **%s**", - "teleportedtoplayer": "**%s** se ha teletransportado a **%s**", - "searchbans": "Busqueda de baneos", - "searchbansfail": "No se ha encontrado ningun baneo con los criterios de busqueda.", - "identifier": "Identificador %s", - "warnplayer": "Advertir al jugador", - "warnreasonguide": "Añade un motivo a la advertencia.", - "confirmwarn": "Confirmar Advertencia", - "confirmwarnguide": "~r~~h~NOTA:~h~~w~ Al pulsar Confirmar, se advertirá a este usuario con los ajustes especificados.", - "warnedtitle": "Advertencia", - "warnedby": "advertido por", - "warndismiss": "Mantén la Barra Espaciadora durante 10 segundos para cancelar.", - "warned": "Has recibido una advertencia, Razon: %s, Aviso: %s/%s", - "warnkicked": "Has sido kickeado por recibir demasiadas advertencias.", - "warnbanned": "Has sido baneado por recibir demasiadas advertencias.", - "adminwarnedplayer": "**%s** advirtio a **%s**, Razón: %s, Advertencia %s/%s", - - "searchuser": "Buscar usuario", - "searchuserguide": "Encuentra un jugador usando su nombre de usuario o ID", - - "setconvar": "Definir Convar", - "setconvarguide": "~r~NOTA: NO TOQUES ESTO si no sabes lo que haces ~w~\nCambia una Convar", - "adminchangedconvar": "**%s** ha cambiado la convar **%s** a **%s**", - "adminstartedresource": "**%s** ha iniciado el script **%s**", - "adminstoppedresource": "**%s** ha detenido el script **%s**", - - "convarname": "Nombre de Convar", - "convarvalue": "Valor de Convar", - - "cleanarea": "Limpiar Area", - "cleanareaguide": "Limpia el area de las entidades seleccionadas", - "cars": "Vehículos", - "peds": "Peatones", - "props": "Objetos", - "cleaningcar": "Borrando Vehículos %s", - "cleaningped": "Borrando Peatones %s", - "cleaningprop": "Borrando Objetos %s", - "finishedcleaning": "Limpieza completada con exito %s", - "admincleanedup": "**%s** Ha realizado una limpieza de todos los **%s** en un radio de **%s**.", - "radius": "Radio", - "type": "Tipo", - "deepclean":"Limpieza Profunda", - "deepcleanguide":"También borra las entidades del cliente.", - - "forceeasteregg": "Forzar Easter Egg", - - "permissioneditor": "Editor de permisos", - "permissioneditorguide": "Edita los permisos del servidor, se guardan en ~g~easyadmin_permissions.cfg~w~", - - "aces": "ACEs", - "permission": "Permisos", - "principals": "Principal", - "addace": "~g~Añadir ACE", - "addaceguide": "Puedes editar esto antes de guardar.", - "addprincipal": "~g~Añadir Principal", - "group": "Grupo", - "entergroup": "Introduce un nombre de grupo (ej. group.admin)", - "enterperm": "Introduce nombre de permiso (ej. easyadmin.player.kick)", - "state": "Estado", - "stateguide": "La denegacion de permisos no funciona correctamente, Solo dale permisos que quieras que el jugador tenga.", - "location": "Ubicacion", - "locationguide": "Este valor no se puede editar.", - "principal": "Principal", - "enterprincipal": "Añadir principal (ej. identifier.steam:aabbccddeefff)", - "deletepermission": "~r~Borrar Permisos", - "deletepermissionguide": "~r~CUIDADO, Esto le borrara el permiso a este jugador", - "deleteprincipal": "~r~Borrar Principal", - "deleteprincipalguide": "~r~CUIDADO, Esto le borrará el permiso a este jugador", - - "itemdeleted": "~r~Item borrado.", - "savechanges": "~g~Guardar cambios", - "savechangesguide": "~r~CUIDADO ~w~ Esto no se puede restaurar", - "admineditedpermissions": "**%s** ha editado los permisos del servidor.", - - "reportviewer": "Reportes activos", - "call": "Llamada de Admin", - "report": "Reporte de Admin", - "open": "Abrir", - "reporter": "Jugador que Reporta", - "reported": "Jugador Reportado", - "closereport": "Cerrar Reporte", - "closesimilarreports": "~r~Cerrar todos los reportes similares~w~", - "closesimilarreportsguide": "Intentara encontrar y borrar todos los reportes realizados por el mismo usuario.", - "adminclosedreport": "**%s** ha cerrado el reporte #**%s**", - "adminclaimedreport": "**%s** claimed Report #**%s**", - "entertoopen": "Selecciona para revisar las opciones para este jugador.", - "refreshreports": "Refrescar Reportes", - "refreshreportsguide": "Muestra nuevos reportes desde la última vez que se haya abierto el menu.", - "waitbeforeusingagain": "¡Debes esperar antes de poder hacer eso otra vez!", - "invalidreport": "¡Tienes que especificar un motivo!", - "claimreport":"Aceptar reporte", - "claimedby":"Reporte atendido por", - "reportalreadyclaimed": "Este reporte ya ha sido aceptado", - "notification":"Notificacion", - "deferral":"Comprobando lista de baneos, por favor espere... (%s%%)", - "savebanchanges":"Guardar Cambios", - "savebanguide":"~r~~h~NOTA:~h~~w~ Pulsando Confirmar actualizaras este Baneo en el servidor.", - "adminimmune":"No tienes permiso para hacer esto, el jugador que has seleccionado es Administrador.", - "teleportmeback":"Teletransportarme a donde estaba", - "teleportplayerback":"Teletransportar al jugador a donde estaba", - "teleportintoclosestvehicle":"Al vehiculo mas cercano", - - "copiedtoclipboard":"Texto copiado al portapapeles", - - "spectatevehicleseatoccupied":"El asiento en el vehiculo en el que estabas se encuentra ocupado.", - "spectatenovehiclefound":"El vehiculo en el que estabas ya no puede ser encontrado.", - "screenreader":"Texto a Voz (TTS)", - "screenreaderguide":"Activa el Texto a Voz de la interfaz (GUI)" - -}] diff --git a/server-data/resources/[esx]/EasyAdmin/language/fr.json b/server-data/resources/[esx]/EasyAdmin/language/fr.json deleted file mode 100644 index 347054205..000000000 --- a/server-data/resources/[esx]/EasyAdmin/language/fr.json +++ /dev/null @@ -1,243 +0,0 @@ -[{ - "translator": "Feared, Robi321", - "language": "fr", - "on": "Activer", - "off": "Éteins", - - "spectatingUser": "Vous regardez ~b~%s.", - "stoppedSpectating": "Vous avez arrêté de regarder un joueur.", - "hour": "Heure", - "hours": "Les heures", - "day": "Jour", - "days": "Jours", - "week": "La semaine", - "weeks": "Semaines", - "month": "Mois", - "months": "Mois", - "year": "An", - "years": "Ans", - "customtime": "Heure personnalisée", - "nocustombantime": "Vous devez d'abord définir une durée d'interdiction personnalisée !", - "permanent": "Permanent", - "confirm": "Confirmer", - "playermanagement": "Gestion des joueurs", - "servermanagement": "Gestion du serveur", - "settings": "Paramètres", - "kickplayer": "Expulser le joueur", - "banplayer": "Bannir le joueur", - "reason": "Raison", - "kickreasonguide": "Ajouter une raison pour le kick.", - "noreason": "Aucune raison spécifiée", - "confirmkick": "Confirmer le kick", - "confirmkickguide": "~r~~h~NOTE :~h~~w~ Appuyer sur confirmer va ~r~~h~expulser~h~~w~ le joueur avec les paramètres spécifiés.", - "banreasonguide": "Ajouter une raison pour le bannissement.", - "banlength": "Temps du bannissement", - "banlengthguide": "Jusqu'à quand le joueur doit être banni?", - "confirmban": "Confirmer le bannissement", - "mute": "Joueur muet", - "muteguide": "~r~~h~NOTE:~h~~w~ Cela empêchera le joueur d’utiliser le chat textuel.", - "adminmutedplayer": "**%s** muted **%s**", - "adminunmutedplayer": "**%s** unmuted **%s**", - "playermuted": "a été mis en sourdine!", - "playerunmuted": "a été mis en sans sourdine!", - "playermute": "Vous êtes muet!", - "confirmbanguide": "~r~~h~NOTE:~h~~w~ Appuyer sur confirmer va ~r~~h~bannir~h~~w~ le joueur avec les paramètres specifiés.", - "spectateplayer": "Regarder le joueur", - "teleportplayer": "Téléportation", - "teleporttoplayer": "au joueur", - "teleportplayertome": "du joueur à moi", - "slapplayer": "Pousser le joueur", - "setplayerfrozen": "Geler le joueur", - "allplayers": "Tout les joueurs", - "teleporttome": "Téléporter à moi", - "teleporttomeguide": "~r~~h~NOTE :~h~~w~ Cela va téléporter ~r~~h~tout~h~~w~ les joueurs à vous.", - "setgametype": "Changer le type de jeu", - "setgametypeguide": "~r~~h~NOTE:~h~~w~ Cela va changer de type de jeu dans la liste des serveurs.", - "setmapname": "Changer de carte", - "setmapnameguide": "~r~~h~NOTE :~h~~w~ Cela va changer de carte dans la liste des serveurs.", - "startresourcebyname": "Lancer la ressource par son nom", - "startresourcebynameguide": "~r~~h~NOTE :~h~~w~ Cela va lancer une ressource sur votre serveur.", - "stopresourcebyname": "Arrêter la ressource par son nom", - "stopresourcebynameguide": "~r~~h~NOTE :~h~~w~ Cela va arrêter une ressource sur votre serveur.", - "badidea": "Ne faites pas cela, s'il vous plaît.", - "viewbanlist": "Voir la liste d'interdiction", - "unbanplayer": "Débannir un joueur", - "unbanplayerguide": "~r~~h~NOTE :~h~~w~ Confirmer le débannissement du joueur.", - "banlistshowtype": "~h~Liste des bans :~h~ voir le type", - "unbanreasons": "Raison", - "unbanlicenses": "ID", - "banlistshowtypeguide": "Choisir l'affichage dans le menu 'Débannir joueur'.\nRéouverture requise.", - "refreshbanlist": "Rafraîchir la liste des bans", - "refreshbanlistguide": "Rafraîchir votre liste des bans au menu 'Débannir joueur'. Réouverture requise.", - "refreshpermissions": "Rafraîchir les permissions", - "refreshpermissionsguide": "Rafraîchir vos permissions sur le serveur actuel.\nRéouverture requise.", - "godmodedetected": "Invincibilité : ~r~Détecté~w~", - "godmodenotdetected": "Invincibilité : ~g~Non détecté~w~", - "antiragdoll": "~r~Anti-Gamelle~w~", - "health": "Vie", - "armor": "Armure", - "wantedlevel": "Niveau de recherche", - "exitspectator": "Appuyer sur E pour quitter le mode spectateur", - - "allowlist": "You are not allowlisted on this server", - "checkingallowlist": "Checking allowlist..", - "bannedjoin": "Vous avez été banni du serveur, \nRaison : %s, Expiration du bannissement : %s, Ban ID: %s", - "kicked": "Éjecté par %s, Raison : %s", - "banned": "Vous avez été banni du serveur, \nRaison : %s, Expiration du bannissement : %s", - "reasonadd": " ( Pseudo : %s ), banni par : %s", - "nongiven": "Non autorisé", - "announcement": "Announcement", - "announcementguide": "Send an announcement to all players", - "adminannouncement": "**%s** sent an announcement: **%s**", - "playernotfound": "Le joueur n'a pas été trouvé.", - "done": "Fait!", - "adminkickedplayer": "**%s** a expulser **%s**, Raison: %s", - "adminbannedplayer": "**%s** a banni **%s**, Raison: %s, Expire: %s, ID: %s", - "adminunbannedplayer": "**%s** a débanni **%s** [ %s ]", - "adminslappedplayer": "**%s** à pousser **%s** pour **%s HP**", - - "adminfrozeplayer": "**%s** à geler **%s**.", - "adminunfrozeplayer": "**%s** à dégeler **%s**.", - - "left": "Gauche", - "middle": "Milieu", - "right": "Droite", - "menuOrientation": "Orientation du menu", - "menuOrientationguide": "Réglage de l'orientation du menu ( Gauche, milieu ou droite ) \nNécessite un redémarrage du jeu.", - "menuOffset": "Définir la largeur du menu", - "menuOffsetguide": "Définir la taille du menu\nNécessite la réouverture du menu.", - "resetmenuOffset": "Réinitialiser la largeur du menu", - "takescreenshot": "Faire une capture d'écran", - "admintookscreenshot": "**%s** a fait une capture d'écran de l'écran de **%s** : %s", - "screenshotinprogress": "Une capture d'écran est déjà en cours, veuillez patienter !", - "screenshotlink": "La capture d'écran est disponible ici : %s", - "anonymous": "Administration anonyme", - "anonymousguide": "Masque votre nom lorsque vous utilisez les fonctions EasyAdmin.", - "adminofflinebannedplayer": "**%s** offline banned **%s**, Reason: %s, Ban Expires: %s", - "cachedplayers": "Joueurs en cache", - "refreshcachedplayers": "Rafraîchir les joueurs en cache", - "refreshcachedplayersguide": "Refreshes List of Cached Players, requires reopening.", - "adminrequestedofflineinfo": "**%s** Données demandées à l'utilisateur de l'utilisateur hors ligne **%s**", - "nextpage": "Page suivante»", - "firstpage": "««Première page", - "lastpage": "Dernière page»»", - "previouspage": "«Page précédente", - "playercalledforadmin": "Utilisateur %s appelle un administrateur!\nRaison: %s\nID: %s\n", - "playerreportedplayer": "Utilisateur %s a signalé un joueur!\n%s, Raison: %s\nReportage %s/%s\nID: %s\n", - "successfullyreported": "A signalé le joueur avec succès!", - "reportbantext": "Rapporté par %s Joueurs en peu de temps.", - "alreadyreported": "Vous avez déjà signalé ce joueur!", - "reportedusageerror": "Erreur! Usage: /report nom raison", - "admincalled": "Appelé avec succès un administrateur!", - - "spectatedplayer": "**%s** a regardé **%s**", - "teleportedtoplayer": "**%s** téléporté vers **%s**", - "searchbans": "Interdictions de recherche", - "searchbansfail": "Aucune interdiction avec les critères de recherche n'a été trouvée.", - "identifier": "Identifier %s", - "warnplayer": "Avertir le joueur", - "warnreasonguide": "Ajouter une raison à l'avertissement.", - "confirmwarn": "Confirmer Avertir", - "confirmwarnguide": "~r~~h~NOTE:~h~~w~ Appuyer sur Confirmer avertira ce lecteur avec les paramètres spécifiés.", - "warned": "Vous avez été averti, Raison : %s, Avertissement %s/%s", - "warnedtitle": "Avertissement", - "warnedby": "averti par", - "warndismiss": "Maintenez la barre d'espacement pendant 10 secondes pour fermer.", - "warnkicked": "Vous avez reçu un coup de pied parce que vous avez été averti trop souvent.", - "warnbanned": "Averti trop souvent.", - "adminwarnedplayer": "**%s** averti **%s**, Raison : %s, Avertissement %s/%s", - - "searchuser": "Rechercher un utilisateur", - "searchuserguide": "Trouver un joueur à l'aide de son nom d'utilisateur ou de son identifiant", - - "setconvar": "Set Convar", - "setconvarguide": "~r~NOTE: Si vous ne savez pas ce que vous faites, n'y touchez pas!~w~\nModifications apportées à Convar", - "adminchangedconvar": "**%s** changed convar **%s** to **%s**", - "adminstartedresource": "**%s** started resource **%s**", - "adminstoppedresource": "**%s** stopped resource **%s**", - - "convarname": "Convar Nom", - "convarvalue": "Convar Valeur", - - "cleanarea": "Zone de nettoyage", - "cleanareaguide": "Nettoie toutes les entités à proximité du type sélectionné", - "cars": "Voitures", - "peds": "Péd", - "props": "Accessoires", - "cleaningcar": "Suppression d'un véhicule %s", - "cleaningped": "Suppression Ped %s", - "cleaningprop": "Suppression d'un objet %s", - "finishedcleaning": "Nettoyage terminé %s", - "admincleanedup": "**%s** Nettoyé tous les **%s** dans un rayon de **%s**.", - "radius": "Radius", - "type": "Type", - "deepclean":"Deep Clean", - "deepcleanguide":"Also deletes clientside entities.", - - "forceeasteregg": "Forcer Easter Egg", - - "permissioneditor": "Permission Editor", - "permissioneditorguide": "Modifier les autorisations sur le serveur, enregistre dans ~g~easyadmin_permissions.cfg~w~", - - "aces": "ACEs", - "permission": "Autorisation", - "principals": "Principals", - "addace": "~g~Ajouter ACE", - "addaceguide": "Vous avez la possibilité de le modifier avant d'enregistrer.", - "addprincipal": "~g~Ajouter Principal", - "group": "Grouper", - "entergroup": "Entrez le nom du groupe (e.g. group.admin)", - "enterperm": "Entrez le nom de l'autorisation (e.g. easyadmin.player.kick)", - "state": "État", - "stateguide": "Refuser les autorisations ne fonctionne pas correctement, n'autorisez que les autorisations que vous souhaitez que le joueur ait.", - "location": "Emplacement", - "locationguide": "Cette valeur ne peut pas être modifiée.", - "principal": "Principal", - "enterprincipal": "Entrer principal (e.g. identifier.steam:aabbccddeefff)", - "deletepermission": "~r~Supprimer l'autorisation", - "deletepermissionguide": "~r~Avertissement! Cela révoquera et supprimera complètement l'autorisation!", - "deleteprincipal": "~r~Supprimer Principal", - "deleteprincipalguide": "~r~Avertissement! Cela révoquera et supprimera complètement le principal!", - - "itemdeleted": "~r~Cet élément a été supprimé.", - "savechanges": "~g~Sauvegarder les modifications", - "savechangesguide": "~r~Avertissement! ~w~Ça ne peut pas être annulé!", - "admineditedpermissions": "**%s** modifié les autorisations du serveur.", - - "reportviewer": "Visionneuse de rapports", - "call": "Appeler", - "report": "Reportage", - "open": "Ouvert", - "reporter": "Reporter", - "reported": "Signalé", - "closereport": "Fermer le rapport", - "closesimilarreports": "~r~Fermer tous les rapports similaires~w~", - "closesimilarreportsguide": "Tentera de trouver et de supprimer les rapports créés par le même utilisateur.", - "adminclosedreport": "**%s** Rapport fermé #**%s**", - "adminclaimedreport": "**%s** claimed Report #**%s**", - "entertoopen": "Sélectionnez pour afficher les options pour ce lecteur.", - "refreshreports": "Actualiser les rapports", - "refreshreportsguide": "Affiche de nouveaux rapports au cas où il y en aurait depuis la dernière fois que le menu a été ouvert.", - "waitbeforeusingagain": "Vous devez attendre avant de l'utiliser à nouveau!", - "invalidreport": "Vous devez spécifier une raison!", - "claimreport":"Rapport de réclamation", - "claimedby":"Revendiquée par", - "reportalreadyclaimed": "Ce rapport a déjà été réclamé!", - "notification":"Notification", - "deferral":"Vérification de la liste de bannissement, veuillez patienter.. (%s%%)", - "savebanchanges":"Sauvegarder les modifications", - "savebanguide":"~r~~h~NOTE:~h~~w~ Appuyez sur Confirmer pour mettre à jour cette interdiction sur le serveur.", - "adminimmune":"Vous n'avez pas la permission d'effectuer cette action, le joueur ciblé est immunisé.", - "teleportmeback":"Téléporter moi dos", - "teleportplayerback":"Téléporter le joueur dos", - "teleportintoclosestvehicle":"into closest vehicle", - - "copiedtoclipboard":"Texte copié dans le presse-papiers!", - - "spectatevehicleseatoccupied":"Le siège du véhicule dans lequel vous étiez est maintenant occupé.", - "spectatenovehiclefound":"Le véhicule dans lequel vous étiez est introuvable.", - "screenreader":"Screen Reader (TTS)", - "screenreaderguide":"Enables Text to Speech for the GUI" - - -}] diff --git a/server-data/resources/[esx]/EasyAdmin/language/it.json b/server-data/resources/[esx]/EasyAdmin/language/it.json deleted file mode 100644 index ff1426bc1..000000000 --- a/server-data/resources/[esx]/EasyAdmin/language/it.json +++ /dev/null @@ -1,242 +0,0 @@ -[{ - "translator": "IceHax, ITKewai", - "language": "it", - "on": "Attivo", - "off": "Disattivo", - "spectatingUser": "Spectando ~b~%s.", - "stoppedSpectating": "Non Stai Più Spectando.", - "hour": "Hour", - "hours": "Hours", - "day": "Day", - "days": "Days", - "week": "Week", - "weeks": "Weeks", - "month": "Month", - "months": "Months", - "year": "Year", - "years": "Years", - "customtime": "Custom Time", - "nocustombantime": "You need to set a custom ban length first!", - "permanent": "Permanente", - "confirm": "Confirm", - "playermanagement": "Gestione Giocatori", - "servermanagement": "Gestione Server", - "settings": "Impostazioni", - "kickplayer": "Espelli Giocatore", - "banplayer": "Bandisci Giocatore", - "reason": "Ragione", - "kickreasonguide": "Aggiungi una ragione per l'espulsione", - "noreason": "Nessuna Ragione Specificata", - "confirmkick": "Conferma espulsione", - "confirmkickguide": "~r~~h~NOTA:~h~~w~ Premendo Conferma si espellera il giocatore con le impostazioni correnti.", - "banreasonguide": "Aggiugi una ragione per il Ban.", - "banlength": "Durata del Ban", - "banlengthguide": "Fino a quando dovrà essere bandito il giocatore?", - "confirmban": "Conferma il Ban", - "confirmbanguide": "~r~~h~NOTA:~h~~w~ Premendo conferma bandirai il giocatore con le impostazioni correnti.", - "mute": "Muta il Giocatore", - "muteguide": "~r~~h~ATTENZIONE:~h~~w~ Ciò impedirà al giocatore di utilizzare la chat di testo.", - "adminmutedplayer": "**%s** ha mutato **%s**", - "adminunmutedplayer": "**%s** ha smutato **%s**", - "playermuted": "è stato mutato!", - "playerunmuted": "è stato smutato!", - "playermute": "Sei mutato!", - "spectateplayer": "Spetta Giocatore", - "teleportplayer": "Teletrasporta", - "teleporttoplayer": "Te dal Giocatore", - "teleportplayertome": "il Giocatore da Me", - "slapplayer": "Schiaffeggia il Giocatore", - "setplayerfrozen": "Blocca Il Giocatore", - "allplayers": "Tutti i Giocatori", - "teleporttome": "Teletrasporta tutti", - "teleporttomeguide": "~r~~h~NOTA:~h~~w~ Questo Teletrasporterà ~h~TUTTI~h~ i giocatori da te.", - "setgametype": "Imposta Game Type", - "setgametypeguide": "~r~~h~NOTA:~h~~w~ Questo imposterà il Game Type mostrato nella ServerList.", - "setmapname": "Imposta Map Name", - "setmapnameguide": "~r~~h~NOTA:~h~~w~ Questo modificherà La Map Name, mostrata nella ServerList.", - "startresourcebyname": "Esegui Risorsa per nome", - "startresourcebynameguide": "~r~~h~NOTA:~h~~w~ Questo Starterà una Risorsa installata sul server.", - "stopresourcebyname": "Ferma Risorsa per nome", - "stopresourcebynameguide": "~r~~h~NOTA:~h~~w~ Questo Stopperà una Risorsa installata sul server.", - "badidea": "Non farlo, per piacere.", - "viewbanlist": "Visualizza Banlist", - "unbanplayer": "Rimuovi ban per il giocatore", - "unbanplayerguide": "~r~~h~NOTA:~h~~w~ Premendo Conferma Rimuoverai il Ban di questo giocatore.", - "banlistshowtype": "~h~Banlist:~h~ Mostra tipo", - "unbanreasons": "Ragioni", - "unbanlicenses": "Licenze", - "banlistshowtypeguide": "Cambia tra Identificatore e Ragioni per il ban Nel menù 'Rimuovi Ban per il giocatore'.\nRichiede una riapertura del menù.", - "refreshbanlist": "Aggiorna La lista dei ban", - "refreshbanlistguide": "Questo aggiorna la lista dei ban per il menù 'Rimuovi ban per il giocatore'.\nRichiede una riapertura del menù.", - "refreshpermissions": "Aggiorna Permessi", - "refreshpermissionsguide": "Questo aggiorna i tuoi permessi correnti.\nRichiede una riapertura del menù.", - "godmodedetected": "Godmode: ~r~Trovata~w~", - "godmodenotdetected": "Godmode: ~g~Non Trovata~w~", - "antiragdoll": "~r~Anti-Ragdoll~w~", - "health": "Salute", - "armor": "Armatura", - "wantedlevel": "Livello Ricercato", - "exitspectator": "Premi E per uscire dalla modalità spettatore.", - - "allowlist": "You are not allowlisted on this server", - "checkingallowlist": "Checking allowlist..", - "bannedjoin": "Sei stato bandito da questo server, \nMotivo: %s, Il Ban Scade: %s, Ban ID: %s", - "kicked": "Espulso da %s, Motivo: %s", - "banned": "Sei stato bandito da questo server, Motivo: %s, Il Ban Scade: %s", - "reasonadd": " ( Nickname: %s ), Bandito da: %s", - "nongiven": "Non fornito", - "announcement": "Announcement", - "announcementguide": "Send an announcement to all players", - "adminannouncement": "**%s** sent an announcement: **%s**", - "playernotfound": "Giocatore non trovato.", - "done": "Fatto!", - "adminkickedplayer": "**%s** Ha espulso **%s**, Motivo: %s", - "adminbannedplayer": "**%s** Ha bandito **%s**, Motivo: %s, Scadenza: %s, ID: %s", - "adminunbannedplayer": "**%s** ha revocato il ban di **%s** [ %s ]", - "adminslappedplayer": "**%s** ha schiaffeggiato **%s** togliendogli **%s HP**", - - "adminfrozeplayer": "**%s** ha bloccato **%s**.", - "adminunfrozeplayer": "**%s** ha sbloccato **%s**.", - - "left": "Sinistra", - "middle": "Centrale", - "right": "Destra", - "menuOrientation": "Orientamento del menù", - "menuOrientationguide": "Imposta l'orientamento del menù ( Sinistra, Destra o Centro ) \nRichiede la riapertura del menù.", - "menuOffset": "Larghezza del menù", - "menuOffsetguide": "Imposta l'offset della dimensione del menù\nRichiede la riapertura del menù.", - "resetmenuOffset": "Resetta larghezza del menù", - "takescreenshot": "Prendi uno Screenshot", - "admintookscreenshot": "**%s** ha preso uno Screenshot dallo schermo di **%s** : %s", - "screenshotinprogress": "si sta già catturando lo Screenshot, attendi!", - "screenshotlink": "Lo screenshot è disponibile qui: %s", - "anonymous": "Admin anonimo", - "anonymousguide": "Nasconde il tuo nome quando usi le funzioni dell' EasyAdmin.", - "adminofflinebannedplayer": "**%s** ha bannato offline **%s**, Motivo: %s, Scadenza del Ban: %s", - "cachedplayers": "Giocatori nella Cache", - "refreshcachedplayers": "Aggiorna giocatori nella Cache", - "refreshcachedplayersguide": "Aggiornare giocatori nella Cache, Richiede la riapertura del menù.", - "adminrequestedofflineinfo": "**%s** ha richiesto i Dati Offline di **%s**", - "nextpage": "Pagina Sucessiva»", - "firstpage": "««Prima Pagina", - "lastpage": "Ultima Pagina»»", - "previouspage": "«Pagina Precedente", - "playercalledforadmin": "L'utente %s sta chiamando un admin!\nMotivo: %s\nID: %s\n", - "playerreportedplayer": "L'utente %s sta segnalando un giocatore!\n%s, Motivo: %s\nSegnalazione %s/%s\nID: %s\n", - "successfullyreported": "Player segnalato con successo!", - "reportbantext": "Sei stato segnalato da %s giocatori in breve periodo.", - "alreadyreported": "Hai già segnalato questo player!", - "reportedusageerror": "Errore! Esempio di utilizzo : /report nome motivo", - "admincalled": "Admin contattato correttamente!", - - "spectatedplayer": "**%s** sta guardando **%s**", - "teleportedtoplayer": "**%s** teletrasportato a **%s**", - "searchbans": "Cerca Ban", - "searchbansfail": "Non è stato trovato nessun Ban con questo criterio di ricerca.", - "identifier": "Identificatore %s", - "warnplayer": "Warna un giocatore", - "warnreasonguide": "Aggiungi il motivo dell' Warn.", - "confirmwarn": "Conferma Warn", - "confirmwarnguide": "~r~~h~ATTENZIONE:~h~~w~ Premendo conferma si Warnerà questo giocatore con le impostazioni attuali.", - "warnedtitle": "Attenzione", - "warnedby": "warnato da", - "warndismiss": "Tieni premuto spazio per 10 Secondi per chiudere questa schermata.", - "warned": "Sei stato warnato, Motivo: %s, Warn %s di %s", - "warnkicked": "Sei stato espulso per aver preso troppi Warn. Rientra", - "warnbanned": "Warnato troppe volte.", - "adminwarnedplayer": "**%s** ha warnato **%s**, Motivo: %s, Warn %s di %s", - - "searchuser": "Cerca utente ", - "searchuserguide": "Trova un giocatore utilizzando il suo nome utente o ID", - - "setconvar": "Set Convar", - "setconvarguide": "~r~ATTENZIONE: Se non sai cosa stai facendo, non modificare niente!~w~\nChanges a Convar", - "adminchangedconvar": "**%s** changed convar **%s** to **%s**", - "adminstartedresource": "**%s** ha avviato la Risorsa **%s**", - "adminstoppedresource": "**%s** ha fermato la Risorsa **%s**", - - "convarname": "Convar Name", - "convarvalue": "Convar Value", - - "cleanarea": "Pulisci l'Area", - "cleanareaguide": "Cleans up all nearby entities of selected type", - "cars": "Veicoli", - "peds": "Ped", - "props": "Oggetti", - "cleaningcar": "Cancellando Veicoli %s", - "cleaningped": "Cancellando Ped %s", - "cleaningprop": "Cancellando Oggetti %s", - "finishedcleaning": "%s cancellatti correttamente", - "admincleanedup": "**%s** Ripulito tutto **%s** in un raggio **%s**.", - "radius": "Radius", - "type": "Type", - "deepclean":"Deep Clean", - "deepcleanguide":"Also deletes clientside entities.", - - "forceeasteregg": "Force Easter Egg", - - "permissioneditor": "Editor permessi", - "permissioneditorguide": "Modifica i permessi nel server, e li salva in ~g~easyadmin_permissions.cfg~w~", - - "aces": "ACEs", - "permission": "Permission", - "principals": "Principals", - "addace": "~g~Add ACE", - "addaceguide": "Puoi modificare questo file prima di salvarlo.", - "addprincipal": "~g~Add Principal", - "group": "Group", - "entergroup": "Enter group name (e.g. group.admin)", - "enterperm": "Enter Permission name (e.g. easyadmin.player.kick)", - "state": "State", - "stateguide": "Denying permissions does not work properly, only allow permissions you want the player to have.", - "location": "Location", - "locationguide": "This value cannot be edited.", - "principal": "Principal", - "enterprincipal": "Enter principal (e.g. identifier.steam:aabbccddeefff)", - "deletepermission": "~r~Delete Permission", - "deletepermissionguide": "~r~Warning! This will completely revoke and delete the Permission!", - "deleteprincipal": "~r~Delete Principal", - "deleteprincipalguide": "~r~Warning! This will completely revoke and delete the Principal!", - - "itemdeleted": "~r~This Item has been deleted.", - "savechanges": "~g~Salve Modifiche", - "savechangesguide": "~r~Attenzione! ~w~Non può essere fatto!", - "admineditedpermissions": "**%s** ha modificato i permessi del server.", - - "reportviewer": "Lista Segnalazioni", - "call": "Call", - "report": "Segnalazioni", - "open": "Apri", - "reporter": "Utente Segnalatore", - "reported": "Utente Segnalato", - "closereport": "Chiudi segnalazione", - "closesimilarreports": "~r~Chiudi le segnalazioni simili~w~", - "closesimilarreportsguide": "Prova a cercare e cancellare segnalazioni fatte dallo stesso utente.", - "adminclosedreport": "**%s** ha chiuso il report #**%s**", - "adminclaimedreport": "**%s** claimed Report #**%s**", - "entertoopen": "Seleziona per vedere opzioni per questo giocatore.", - "refreshreports": "Aggiorna Segnalazioni", - "refreshreportsguide": "Mostra le nuove segnalazioni rispetto all'ultima volta che hai aperto il menù.", - "waitbeforeusingagain": "You must wait before using this again!", - "invalidreport": "You need to specify a reason!", - "claimreport":"Claim Report", - "claimedby":"Claimed By", - "reportalreadyclaimed": "This report has already been claimed!", - "notification":"Notification", - "deferral":"Checking Banlist, please wait.. (%s%%)", - "savebanchanges":"Save Changes", - "savebanguide":"~r~~h~NOTE:~h~~w~ Pressing Confirm will update this Ban on the Server.", - "adminimmune":"You do not have permission to perform this action, target player is immune.", - "teleportmeback":"Teleport me back", - "teleportplayerback":"Teleport Player back", - "teleportintoclosestvehicle":"into closest vehicle", - - "copiedtoclipboard":"Text copied to Clipboard!", - - "spectatevehicleseatoccupied":"The vehicle seat you were in is now occupied.", - "spectatenovehiclefound":"The vehicle you were in can no longer be found.", - "screenreader":"Screen Reader (TTS)", - "screenreaderguide":"Enables Text to Speech for the GUI" - - -}] diff --git a/server-data/resources/[esx]/EasyAdmin/language/nl.json b/server-data/resources/[esx]/EasyAdmin/language/nl.json deleted file mode 100644 index d187605ff..000000000 --- a/server-data/resources/[esx]/EasyAdmin/language/nl.json +++ /dev/null @@ -1,242 +0,0 @@ -[{ - "translator": "TheIndra, Jaccosf", - "language": "nl", - - "on": "Ingeschakeld", - "off": "Uitgeschakeld", - "spectatingUser": "~b~%s aan het Spectaten.", - "stoppedSpectating": "Gestopt met Spectaten.", - "hour": "Uur", - "hours": "Uren", - "day": "Dag", - "days": "Dagen", - "week": "Week", - "weeks": "Weken", - "month": "Maand", - "months": "Maanden", - "year": "Jaar", - "years": "Jaren", - "customtime": "Custom Tijd", - "nocustombantime": "Je moet eerst de lengte van de ban invullen!", - "permanent": "Permanent", - "confirm": "Bevestig", - "playermanagement": "Speler Beheer", - "servermanagement": "Server Management", - "settings": "Instellingen", - "kickplayer": "Kick Speler", - "banplayer": "Ban Speler", - "reason": "Reden", - "kickreasonguide": "Voeg een reden toe aan de kick.", - "noreason": "Geen reden opgegeven", - "confirmkick": "Bevestig Kick", - "confirmkickguide": "~r~~h~NOTITIE:~h~~w~ Als je op bevestigen drukt wordt deze Speler gekickt.", - "mute": "Demp speler", - "muteguide": "~r~~h~NOTITIE:~h~~w~ Dit voorkomt dat de speler de tekstchat gebruikt.", - "adminmutedplayer": "**%s** muted **%s**", - "adminunmutedplayer": "**%s** unmuted **%s**", - "playermuted": "is gedempt!", - "playerunmuted": "is niet-gedempt!", - "playermute": "Je bent gedempt!", - "banreasonguide": "Voeg een reden toe aan de ban.", - "banlength": "Ban Lengte", - "banlengthguide": "Hoelang moet de Speler verbannen worden?", - "confirmban": "Bevestig Ban", - "confirmbanguide": "~r~~h~NOTITIE:~h~~w~ Als je op bevestigen drukt wordt deze Speler verbannen.", - "spectateplayer": "Spectate Speler", - "teleportplayer": "Teleporteer", - "teleporttoplayer": "naar Speler", - "teleportplayertome": "Speler naar mij", - "slapplayer": "Speler klap geven", - "setplayerfrozen": "Speler vastzetten", - "allplayers": "Alle spelers", - "teleporttome": "Teleporteer naar mij", - "teleporttomeguide": "~r~~h~NOTITIE:~h~~w~ Dit teleporteert ~h~alle~h~ spelers naar jou.", - "setgametype": "Stel Game Type in", - "setgametypeguide": "~r~~h~NOTITIE:~h~~w~ Dit stelt het game type in zoals weergegeven op de Serverlijst.", - "setmapname": "Stel Map Naam in", - "setmapnameguide": "~r~~h~NOTITIE:~h~~w~ Dit stelt de map naam in zoals weergegeven in de Serverlijst.", - "startresourcebyname": "Start Resource met Naam", - "startresourcebynameguide": "~r~~h~NOTITIE:~h~~w~ Dit zal een resource starten geinstalleerd op de server.", - "stopresourcebyname": "Stop Resource met Naam", - "stopresourcebynameguide": "~r~~h~NOTITIE:~h~~w~ Dit zal een resource stoppen geinstalleerd op de server.", - "badidea": "Doe dat alsjeblieft niet.", - "viewbanlist": "Bekijk de Banlijst", - "unbanplayer": "Unban Speler", - "unbanplayerguide": "~r~~h~NOTITIE:~h~~w~ Als je op bevestigen drukt wordt deze Speler zijn ban ongedaan gemaakt.", - "banlistshowtype": "~h~Banlijst:~h~ Show Type", - "unbanreasons": "Redenen", - "unbanlicenses": "Licenses", - "banlistshowtypeguide": "Wissel tussen Ban redenen of Identifiers in het 'Unban Speler' Menu.\nVereist Heropenen.", - "refreshbanlist": "Herlaad Banlijst", - "refreshbanlistguide": "Dit herlaad de Banlijst in het 'Unban Speler' Menu.\nVereist Heropenen.", - "refreshpermissions": "Herlaad Permissies", - "refreshpermissionsguide": "Dit herlaad je huidige permissies.\nVereist Heropenen.", - "godmodedetected": "Godmode: ~r~Gevonden~w~", - "godmodenotdetected": "Godmode: ~g~Niet Gevonden~w~", - "antiragdoll": "~r~Anti-Ragdoll~w~", - "health": "Health", - "armor": "Armor", - "wantedlevel": "Wanted Level", - "exitspectator": "Druk op E om spectator mode te verlaten", - - "allowlist": "Je staat niet op de allowlist voor deze server", - "checkingallowlist": "Checking allowlist..", - "bannedjoin": "Je bent verbannen van deze Server, \nReden: %s, Ban Vervalt: %s, Ban ID: %s", - "kicked": "Gekickt door %s, Reden: %s", - "banned": "Je bent verbannen van deze Server, Reden: %s, Ban Vervalt: %s", - "reasonadd": " ( Gebruikersnaam: %s ), Verbannen door: %s", - "nongiven": "Geen reden opgegeven", - "announcement": "Mededeling", - "announcementguide": "Stuur een mededeling naar alle spelers", - "adminannouncement": "**%s** stuurde een mededeling: **%s**", - "playernotfound": "Speler kan niet gevonden worden.", - "done": "Afgerond!", - - "adminkickedplayer": "**%s** Gekickt **%s**, Reden: %s", - "adminbannedplayer": "**%s** banned **%s**, Reden: %s, Ban Vervalt: %s, ID: %s", - "adminunbannedplayer": "**%s** Ban ongedaan gemaakt **%s** [ %s ]", - "adminslappedplayer": "**%s** sloeg **%s** for **%s HP**", - "adminfrozeplayer": "**%s** bevroor **%s**.", - "adminunfrozeplayer": "**%s** gestopt met bevriezen **%s**.", - - "left": "Links", - "middle": "Midden", - "right": "Rechts", - "menuOrientation": "Menu Orientatie", - "menuOrientationguide": "Stel Menu Orientatie in ( Links, Rechts of Midden ) \nVereist Game restart.", - "menuOffset": "Menu Grootte", - "menuOffsetguide": "Stel Menu Grootte in\nVereist menu Heropenen", - "resetmenuOffset": "Reset Menu Grootte", - "takescreenshot": "Neem Schermafbeelding", - "admintookscreenshot": "**%s** Nam een Schermafbeelding van **%s** zijn Scherm: %s", - "screenshotinprogress": "een Schermafbeelding is is al aan de gang, even geduld aub!", - "screenshotlink": "De schermafbeelding is beschikbaar hier: %s", - "anonymous": "Anonieme Admin", - "anonymousguide": "Verberg je naam bij het gebruik van EasyAdmin.", - "adminofflinebannedplayer": "**%s** offline is gebanned **%s**, Reden: %s, Ban verloopt op: %s", - "cachedplayers": "Opgeslagen Spelers", - "refreshcachedplayers": "Herlaad Opgeslage Spelers", - "refreshcachedplayersguide": "Herlaad de opgeslagen spelers, je moet wel het menu heropenen", - "adminrequestedofflineinfo": "**%s** heeft gebruikersgegevens aangevraagd van een offline speler **%s**", - "nextpage": "Volgende Pagina»", - "firstpage": "««Eerste Pagina", - "lastpage": "Laatste Pagina»»", - "previouspage": "«Vorige Pagina", - "playercalledforadmin": "Speler %s wil hulp van een admin!\nReden: %s\nID: %s\n", - "playerreportedplayer": "Speler %s heeft een speler gerapporteerd!\n%s, Reden: %s\nReport %s/%s\nID: %s\n", - "successfullyreported": "De speler is succesvol gerapporteerd!", - "reportbantext": "Gerapporteerd door %s Spelers in een zeer korte tijd.", - "alreadyreported": "Je hebt deze speler al gerapporteerd!", - "reportedusageerror": "Error! Gebruik: /report naam reden", - "admincalled": "Succesvol hulp gevraagd aan een admin!", - - "spectatedplayer": "**%s** is aan het kijken naar **%s**", - "teleportedtoplayer": "**%s** geteleporteerd naar **%s**", - "searchbans": "Zoek Bans", - "searchbansfail": "Geen vergelijkbare ban gevonden.", - "identifier": "Identifier %s", - "warnplayer": "Waarschuw Speler", - "warnreasonguide": "Geef een reden voor de waarschuwing.", - "confirmwarn": "Bevestig Waarschuwing", - "confirmwarnguide": "~r~~h~NOTITIE:~h~~w~ Als je het bevestigt, krijgt de speler de waarschuwing te zien.", - "warnedtitle": "Waarschuwing", - "warnedby": "gewaarschuwd door", - "warndismiss": "Houd spatiebalk 10 seconden ingedrukt, om de waarschuwing te accepteren.", - "warned": "Je bent gewaarschuwd, Reden: %s, Waarschuwing %s/%s", - "warnkicked": "Je bent gekicked, omdat je teveel waarschuwingen hebt ontvangen.", - "warnbanned": "Te vaak gewaarschuwd.", - "adminwarnedplayer": "**%s** heeft **%s** gewaarschuwd, Reden: %s, Waarschuwing %s/%s", - - "searchuser": "Zoek gebruiker", - "searchuserguide": "Zoek een speler met behulp van zijn gebruikersnaam of ID", - - "setconvar": "Pas de Convar aan", - "setconvarguide": "~r~NOTITIE: Gebruik dit alleen, als je weet wat je aan het doen bent!~w~\nVeranderd de Convar", - "adminchangedconvar": "**%s** veranderde de convar **%s** to **%s**", - "adminstartedresource": "**%s** startte resource **%s**", - "adminstoppedresource": "**%s** stopte resource **%s**", - - "convarname": "Convar Naam", - "convarvalue": "Convar Waarde", - - "cleanarea": "Opruim Gebied", - "cleanareaguide": "Verwijdert alle entities van het geselecteerde type", - "cars": "Voertuigen", - "peds": "Herzenlozen", - "props": "Voorwerpen", - "cleaningcar": "Voertuigen aan het verwijderen %s", - "cleaningped": "Herzenlozen aan het verwijderen %s", - "cleaningprop": "Voorwerpen aan het verwijderen %s", - "finishedcleaning": "Klaar met verwijderen %s", - "admincleanedup": "**%s** Alle **%s** in een **%s** gebied zijn verwijderd.", - "radius": "Radius", - "type": "Type", - "deepclean":"Grondige Schoonmaak", - "deepcleanguide":"Verwijdert ook client entities.", - - "forceeasteregg": "Forceer Easter Egg", - - "permissioneditor": "Permissies Aanpassen", - "permissioneditorguide": "Pas de permissies aan, opgeslagen in ~g~easyadmin_permissions.cfg~w~", - - "aces": "ACEs", - "permission": "Permissies", - "principals": "Principals", - "addace": "~g~ACE toevoegen", - "addaceguide": "Je kan het aanpassen, voordat je het opslaat.", - "addprincipal": "~g~Principal toevoegen", - "group": "Groep", - "entergroup": "Voeg groep naam toe (bijv. group.admin)", - "enterperm": "Vul permissie naam in (bijv. easyadmin.player.kick)", - "state": "Staat", - "stateguide": "Permissies weigeren functioneerd niet, sta alleen permissies toe.", - "location": "Locatie", - "locationguide": "Deze waarde kan niet aangepast worden.", - "principal": "Principal", - "enterprincipal": "Vul een principal in (bijv. identifier.steam:aabbccddeefff)", - "deletepermission": "~r~Verwijder permissies", - "deletepermissionguide": "~r~Waarschuwing! Dit zal de permissie intrekken en verwijderen!", - "deleteprincipal": "~r~Verwijder Principal", - "deleteprincipalguide": "~r~Waarschuwing! Dit zal de Principal intrekken en verwijderen!", - - "itemdeleted": "~r~Het voorwerp is verwijderd.", - "savechanges": "~g~Sla de wijzigingen op.", - "savechangesguide": "~r~Waarschuwing! ~w~Dit kan niet ongedaan worden gemaakt!", - "admineditedpermissions": "**%s** heeft de server permissies aangepast.", - - "reportviewer": "Report Overzicht", - "call": "Oproep", - "report": "Report", - "open": "Open", - "reporter": "Reporter", - "reported": "Gerapporteerd", - "closereport": "Sluit Report", - "closesimilarreports": "~r~Sluit alle soortgelijke reports~w~", - "closesimilarreportsguide": "Zal alle reports van deze gebruiker verwijderen.", - "adminclosedreport": "**%s** sloot Report #**%s**", - "adminclaimedreport": "**%s** claimed Report #**%s**", - "entertoopen": "Selecteer om de opties voor de speler te bekijken.", - "refreshreports": "Vernieuw Reports", - "refreshreportsguide": "Laat nieuwe reports zien, als er nieuwe zijn.", - "waitbeforeusingagain": "Je moet wachten voor je dit opnieuw kan gebruiken!", - "invalidreport": "Je moet een reden specificeren!", - "claimreport":"Claim Report", - "claimedby":"Geclaimed Door", - "reportalreadyclaimed": "Deze report is al geclaimed!", - "notification":"Notificatie", - "deferral":"Banlijst aan het checken, even geduld.. (%s%%)", - "savebanchanges":"Sla aanpassingen op", - "savebanguide":"~r~~h~NOTE:~h~~w~ Als je dit bevestigt zal de ban worden geüpdatet.", - "adminimmune":"Je hebt geen permissie om dit te doen, die speler is immuun.", - "teleportmeback":"Teleport jezelf terug", - "teleportplayerback":"Teleport Speler terug", - "teleportintoclosestvehicle":"in het dichtstbijzijnde voertuig", - - "copiedtoclipboard":"Tekst gekopieerd naar het klembord!", - - "spectatevehicleseatoccupied":"Het voertuig waar je net in zat is nu bezet.", - "spectatenovehiclefound":"Het voertuig waar je net in zat kan niet worden gevonden.", - "screenreader":"Screen Reader (TTS)", - "screenreaderguide":"Schakelt Text to Speech in voor de GUI" - -}] diff --git a/server-data/resources/[esx]/EasyAdmin/language/pl.json b/server-data/resources/[esx]/EasyAdmin/language/pl.json deleted file mode 100644 index 38c9b73bf..000000000 --- a/server-data/resources/[esx]/EasyAdmin/language/pl.json +++ /dev/null @@ -1,241 +0,0 @@ -[{ - "translator": "EasyAdmin, robbybaseplate, Kubamaz", - "language": "pl", - "on": "Włącz", - "off": "Wyłącz", - "spectatingUser": "Obserwowanie ~b~%s.", - "stoppedSpectating": "Przerwano obserwację.", - "hour": "Godzina", - "hours": "Godziny", - "day": "Dzień", - "days": "Dni", - "week": "Tydzień", - "weeks": "Tygodnie", - "month": "Miesiąc", - "months": "Miesiące", - "year": "Rok", - "years": "Lata", - "customtime": "Czas niestandardowy", - "nocustombantime": "Najpierw musisz ustawić niestandardową długość bana!", - "permanent": "Permanentny", - "confirm": "Potwierdź", - "playermanagement": "Zarządzanie Graczami", - "servermanagement": "Zarządzanie Serwerem", - "settings": "Ustawienia", - "kickplayer": "Wyrzuć Gracza", - "banplayer": "Zbanuj Gracza", - "reason": "Powód", - "kickreasonguide": "Dodaj powód wyrzucenia.", - "noreason": "Nie określono przyczyny", - "confirmkick": "Potwierdź wyrzucenie", - "confirmkickguide": "~r~~h~UWAGA:~h~~w~ Naciśnięcie potwierdź spowoduje wyrzucenie tego Gracza z określonymi ustawieniami.", - "banreasonguide": "Dodaj powód blokady.", - "banlength": "Długość bana", - "banlengthguide": "Do kiedy powinien zostać zbanowany Gracz?", - "confirmban": "Potwierdź bana", - "confirmbanguide": "~r~~h~UWAGA:~h~~w~ Naciśnięcie potwierdź spowoduje zablokowanie tego gracza z określonymi ustawieniami.", - "mute": "Niemy Gracz", - "muteguide": "~r~~h~NOTE:~h~~w~ Uniemożliwi to graczowi korzystanie z czatu tekstowego", - "adminmutedplayer": "**%s** wyciszył **%s**", - "adminunmutedplayer": "**%s** odciszył **%s**", - "playermuted": "został wyciszony!", - "playerunmuted": "został bez wyciszenia!", - "playermute": "Jesteś wyciszony!", - "spectateplayer": "Obserwuj gracza", - "teleportplayer": "Teleport", - "teleporttoplayer": "do gracza", - "teleportplayertome": "gracza do mnie", - "slapplayer": "Uderz Gracza", - "setplayerfrozen": "Unieruchom gracza", - "allplayers": "Wszyscy gracze", - "teleporttome": "Teleportuj do mnie", - "teleporttomeguide": "~r~~h~UWAGA:~h~~w~ Spowoduje to teleportację do ciebie ~h~wszystkich ~h~ graczy.", - "setgametype": "Ustaw Tryb Gry", - "setgametypeguide": "~r~~h~UWAGA:~h~~w~ Spowoduje to ustawienie Typu Gry zgodnie z listą serwerów.", - "setmapname": "Ustaw Nazwę Mapy", - "setmapnameguide": "~r~~h~UWAGA:~h~~w~ Spowoduje to ustawienie nazwy mapy zgodnie z listą serwerów.", - "startresourcebyname": "Uruchom zasoby według nazwy", - "startresourcebynameguide": "~r~~h~UWAGA:~h~~w~ Spowoduje to uruchomienie zasobu zainstalowanego na serwerze.", - "stopresourcebyname": "Zatrzymaj zasoby według nazwy", - "stopresourcebynameguide": "~r~~h~UWAGA:~h~~w~ Spowoduje to zatrzymanie zasobu zainstalowanego na serwerze.", - "badidea": "Nie rób tego, proszę.", - "viewbanlist": "Pokaż listę banów", - "unbanplayer": "Odblokuj Gracza", - "unbanplayerguide": "~r~~h~UWAGA:~h~~w~ Naciśnięcie Potwierdź spowoduje odblokowanie tego Gracza.", - "banlistshowtype": "~h~Lista blokad:~h~ pokaż Typ", - "unbanreasons": "Powód", - "unbanlicenses": "Licencje", - "banlistshowtypeguide": "Przełącz między przyczynami lub identyfikatorami banu w menu 'Odblokuj Gracza'.\nWymaga ponownego otwarcia.", - "refreshbanlist": "Odśwież banlistę", - "refreshbanlistguide": "To odświeża banlistę w menu 'Odblokuj Gracza'.\nWymaga ponownego otwarcia.", - "refreshpermissions": "Odśwież uprawnienia", - "refreshpermissionsguide": "To odświeża twoje obecne uprawnienia.\nWymaga ponownego otwarcia.", - "godmodedetected": "Nieśmiertelność: ~r~Wykryta~w~", - "godmodenotdetected": "Nieśmiertelność: ~g~Nie Wykryta~w~", - "antiragdoll": "~r~Anty-Przewracanie~w~", - "health": "Zdrowie", - "armor": "Opancerzenie", - "wantedlevel": "Poziom poszukiwań", - "exitspectator": "Naciśnij E, aby wyjść z trybu obserwatora", - - "allowlist": "Nie ma Cię na białej liście tego serwera", - "checkingallowlist": "Sprawdzanie listy dostępu..", - "bannedjoin": "Zostałeś zbanowany na tym serwerze, \nPowód: %s, Czas trwania: %s, Ban ID: %s", - "kicked": "Wyrzucony przez %s, Powód: %s", - "banned": "Zostałeś zbanowany na tym serwerze, Powód: %s, Czas trwania: %s", - "reasonadd": " ( Gracz: %s ), Zablokowany przez: %s", - "nongiven": "Nie podano", - "announcement": "Ogłoszenie", - "announcementguide": "Wyślij ogłoszenie do wszystkich graczy", - "adminannouncement": "**%s** wysłał ogłoszenie: **%s**", - "playernotfound": "Nie można znaleźć gracza.", - "done": "Zrobione!", - "adminkickedplayer": "**%s** wyrzucił **%s**, Powód: %s", - "adminbannedplayer": "**%s** zbanował **%s**, Powód: %s, Czas trwania: %s, ID: %s", - "adminunbannedplayer": "**%s** odblokował **%s** [ %s ]", - "adminslappedplayer": "**%s** uderzył **%s** za **%s HP**", - - "adminfrozeplayer": "**%s** zamrożony **%s**.", - "adminunfrozeplayer": "**%s** odmrożony **%s**.", - - "left": "Lewa", - "middle": "Środek", - "right": "Prawa", - "menuOrientation": "Orientacja menu", - "menuOrientationguide": "Ustaw orientację menu ( Lewa, Prawa lub Środek ) \nWymaga restartu gry.", - "menuOffset": "Przesunięcie menu", - "menuOffsetguide": "Ustaw Przesunięcie menu\nWymaga Ponownego otwarcie menu.", - "resetmenuOffset": "Resetuj przesunięcie menu ", - "takescreenshot": "Zrzut ekranu", - "admintookscreenshot": "**%s** zrobił zrzut ekranu **%s**'s Zrzut ekranu: %s", - "screenshotinprogress": "Zrzut ekranu jest w trakcie tworzenia, zaczekaj!", - "screenshotlink": "Zrzut ekranu jest dostępny tutaj: %s", - "anonymous": "Anonimowy Admin", - "anonymousguide": "Ukrywa twój nick kiedy wykonujesz akcje Administracyjne.", - "adminofflinebannedplayer": "**%s** zbanowany offline **%s**, Powód: %s, Ban wygaśnie: %s", - "cachedplayers": "Ostatni gracze", - "refreshcachedplayers": "Odśwież ostatnich graczy", - "refreshcachedplayersguide": "Odśwież listę zapisanych graczy, wymaga restartu menu.", - "adminrequestedofflineinfo": "**%s** zarządał informacji gracza Offline **%s**", - "nextpage": "Następna strona»", - "firstpage": "««Pierwsza strona", - "lastpage": "Ostatnia strona»»", - "previouspage": "«Poprzednia strona", - "playercalledforadmin": "Użytkownik %s wzywa Administratora!\nPowód: %s\nID: %s\n", - "playerreportedplayer": "Użytkownik %s zgłosił gracza!\n%s, Powód: %s\nReport %s/%s\nID: %s\n", - "successfullyreported": "Pomyślnie zgłoszono gracza!", - "reportbantext": "Zgłosił %s Graczy w krótkim czasie.", - "alreadyreported": "Już zgłosiłeś tego gracza!", - "reportedusageerror": "Błąd! Użyj: /report nick powód", - "admincalled": "Pomyślnie zawiadomiono Administratora!", - - "spectatedplayer": "**%s** ogląda **%s**", - "teleportedtoplayer": "**%s** teleportowany do **%s**", - "searchbans": "Wyszukaj bana", - "searchbansfail": "Nie znaleziono bana z wprowadzonymi parametrami.", - "identifier": "Identyfikator %s", - "warnplayer": "Ostrzeż gracza", - "warnreasonguide": "Dodaj powód do ostrzeżenia.", - "confirmwarn": "Potwierdź ostrzeżenie", - "confirmwarnguide": "~r~~h~UWAGA:~h~~w~ Naciśnięcie Potwierdź spowoduje ostrzeżenie użytkownika z określonymi ustawieniami.", - "warnedtitle": "Ostrzeżenie", - "warnedby": "ostrzeżony przez", - "warndismiss": "Przytrzymaj spację przez 10 sekund aby odrzucić powiadomienie.", - "warned": "Zostałeś ostrzeżony, Powód: %s, Ostrzeżenie %s/%s", - "warnkicked": "Zostałeś wyrzucony z serwera, z powodu otrzymania zbyt wielu ostrzeżeń..", - "warnbanned": "Ostrzeżono cię zbyt wiele razy.", - "adminwarnedplayer": "**%s** ostrzegł **%s**, Powód: %s, Ostrzeżenie %s/%s", - - "searchuser": "Wyszukaj użytkownika", - "searchuserguide": "Znajdź gracza, używając jego nazwy użytkownika lub identyfikatora", - - "setconvar": "Ustaw convar-a", - "setconvarguide": "~r~UWAGA: Jeżeli nie wiesz co robisz, nie dotykaj tego!~w~\nZmienia convar-a", - "adminchangedconvar": "**%s** zmieniono convar-a **%s** na **%s**", - "adminstartedresource": "**%s** uruchomiono skrypt **%s**", - "adminstoppedresource": "**%s** zatrzymano skrypt **%s**", - - "convarname": "Nazwa Convar-a", - "convarvalue": "Wartość Convar-a", - - "cleanarea": "Wyczyść lokalizację", - "cleanareaguide": "Usuń wszystkie pobliskie obiekty wybranego typu", - "cars": "Pojazdy", - "peds": "Pedy", - "props": "Propy", - "cleaningcar": "Usuwanie pojazdu %s", - "cleaningped": "Usuwanie peda %s", - "cleaningprop": "Usunięto obiekt %s", - "finishedcleaning": "Zakończono czyszczenie %s", - "admincleanedup": "**%s** Wszystkie **%s** w **%s** obszarze zostały usunięte.", - "radius": "Zasięg", - "type": "Rodzaj", - "deepclean":"Głębokie Czyszczenie", - "deepcleanguide":"Usuwa również podmioty po stronie klienta.", - - "forceeasteregg": "Wymuś Easter Egg-a", - - "permissioneditor": "Edytor uprawnień", - "permissioneditorguide": "Edytuje uprawnienia na serwerze, zapisuje do ~g~easyadmin_permissions.cfg~w~", - - "aces": "Uprawnienia ACE", - "permission": "Uprawnienia", - "principals": "Principale", - "addace": "~g~Dodaj uprawnienia ACE", - "addaceguide": "Masz możliwość edytowania tego przed zapisaniem.", - "addprincipal": "~g~Dodaj principala", - "group": "Grupa", - "entergroup": "Wprowadź nazwę grupy (np. group.admin)", - "enterperm": "Wprowadź nazwę uprawnienia (np. easyadmin.player.kick)", - "state": "Stan", - "stateguide": "Odmawianie uprawnień nie działa poprawnie, zezwalaj tylko na uprawnienia, które chcesz, aby gracz posiadał.", - "location": "Lokalizacja", - "locationguide": "Ta wartość nie może być zmieniona.", - "principal": "Principal", - "enterprincipal": "Wprowadź identyfikator (np. identifier.steam:aabbccddeefff)", - "deletepermission": "~r~Usuń uprawnienie", - "deletepermissionguide": "~r~Ostrzeżenie! To całkowicie usunie uprawnienia!", - "deleteprincipal": "~r~Usuń principala", - "deleteprincipalguide": "~r~Ostrzeżenie! Spowoduje to całkowite usunięcie principala!", - - "itemdeleted": "~r~Ten element został usunięty.", - "savechanges": "~g~Zapisz zmiany", - "savechangesguide": "~r~Ostrzeżenie! ~w~To nie może być cofnięte!", - "admineditedpermissions": "**%s** edytował uprawnienia serwera.", - - "reportviewer": "Otwórz zgłoszenia", - "call": "Wezwanie", - "report": "Zgłoszenie", - "open": "Otwarty", - "reporter": "Zgłaszający", - "reported": "Zgłoszony", - "closereport": "Zamknij zgłoszenie", - "closesimilarreports": "~r~Zamknij wszystkie podobne zgłoszenia~w~", - "closesimilarreportsguide": "Spróbuję znaleźć i usunąć raporty wykonane przez tego samego użytkownika.", - "adminclosedreport": "**%s** zamknięte zgłoszenie #**%s**", - "adminclaimedreport": "**%s** claimed Report #**%s**", - "entertoopen": "Wybierz, aby wyświetlić opcje dla tego gracza.", - "refreshreports": "Odśwież zgłoszenia", - "refreshreportsguide": "Pokazuje nowe zgłoszenia, jeśli są jakieś od ostatniego otwarcia menu.", - "waitbeforeusingagain": "Musisz poczekać przed użyciem tego ponownie!", - "invalidreport": "Musisz podać powód!", - "claimreport":"Zajmij zgłoszenie", - "claimedby":"Zajęty przez", - "reportalreadyclaimed": "To zgłoszenie zostało już zajęte!", - "notification":"Powiadomienie", - "deferral":"Sprawdzanie listy banów, proszę czekać.. (%s%%)", - "savebanchanges":"Zapisz zmiany", - "savebanguide":"~r~~h~UWAGA:~h~~w~ Naciśnięcie przycisku Potwierdź zaktualizuje ten ban na serwerze.", - "adminimmune":"Nie masz uprawnień aby wykonać tą akcje, docelowy gracz jest nietykalny.", - "teleportmeback":"Teleportuj mnie z powrotem", - "teleportplayerback":"Teleportuj gracza z powrotem", - "teleportintoclosestvehicle":"do najbliższego pojazdu", - - "copiedtoclipboard":"Tekst skopiowany do schowka!", - - "spectatevehicleseatoccupied":"Miejsce w pojeździe, na którym byłeś, jest teraz zajęte.", - "spectatenovehiclefound":"Nie można już znaleźć pojazdu, w którym byłeś.", - "screenreader":"Narrator (TTS)", - "screenreaderguide":"Włącz narratora dla GUI" - -}] diff --git a/server-data/resources/[esx]/EasyAdmin/package.json b/server-data/resources/[esx]/EasyAdmin/package.json deleted file mode 100644 index 8cf1d3c80..000000000 --- a/server-data/resources/[esx]/EasyAdmin/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "dependencies": { - "@discordjs/rest": "1.6.0", - "@discordjs/core": "0.6.0", - "@discordjs/formatters": "0.3.1", - "@discordjs/collection": "1.5.1", - "@discordjs/builders": "1.6.3", - "@discordjs/util": "0.3.1", - "@discordjs/ws": "0.8.1", - "ascii-table": "0.0.9", - "discord-api-types": "0.37.51", - "discord.js": "14.12.1", - "erlpack": "0.1.4", - "juration": "0.1.1", - "pretty-ms": "7.0.1", - "sprintf-js": "1.1.2", - "zlib-sync": "0.1.8" - }, - "devDependencies": { - "eslint": "8.46.0" - }, - "resolutions": { - "@discordjs/rest": "1.6.0", - "@discordjs/core": "0.6.0", - "@discordjs/formatters": "0.3.1", - "@discordjs/collection": "1.5.1", - "@discordjs/builders": "1.6.3", - "@discordjs/util": "0.3.1", - "@discordjs/ws": "0.8.1" - } -} diff --git a/server-data/resources/[esx]/EasyAdmin/plugins/.gitkeep b/server-data/resources/[esx]/EasyAdmin/plugins/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/server-data/resources/[esx]/EasyAdmin/plugins/eadiag/eadiag_server.lua b/server-data/resources/[esx]/EasyAdmin/plugins/eadiag/eadiag_server.lua deleted file mode 100644 index e79da1f49..000000000 --- a/server-data/resources/[esx]/EasyAdmin/plugins/eadiag/eadiag_server.lua +++ /dev/null @@ -1,155 +0,0 @@ -Citizen.CreateThread(function() - local diagActive = false - RegisterCommand("eaDiag", function(source, args, rawCommand) - if diagActive then - PrintDebugMessage("eaDiag is still running, please wait, or report any errors!", 1) - return false - end - - if DoesPlayerHavePermission(source, "server") then - diagActive = true - - PrintDebugMessage("eaDiag triggered, this may take a while, please do not restart EasyAdmin in the meantime.^7\n", 1) - - local supportData = {} - - PrintDebugMessage("Collecting EasyAdmin Config....^7\n", 1) - - local version,ismaster = GetVersion() - supportData.config = { - gamename = GetConvar("gamename", "not-rdr3"), - version = version, - ismaster = tostring(ismaster), - ea_moderationNotification = GetConvar("ea_moderationNotification", "false"), - ea_screenshoturl = GetConvar("ea_screenshoturl", 'https://wew.wtf/upload.php'), - onesync = GetConvar("onesync", "off"), - steam_webApiKey = GetConvar("steam_webApiKey", ""), - ea_LanguageName = GetConvar("ea_LanguageName", "en"), - ea_enableDebugging = GetConvar("ea_enableDebugging", "false"), - ea_logLevel = GetConvar("ea_logLevel", 1), - ea_minIdentifierMatches = GetConvarInt("ea_minIdentifierMatches", 2), - ea_defaultKey = GetConvar("ea_defaultKey", "none"), - ea_alwaysShowButtons = GetConvar("ea_alwaysShowButtons", "false"), - ea_enableCallAdminCommand = GetConvar("ea_enableCallAdminCommand", "true"), - ea_enableReportCommand = GetConvar("ea_enableReportCommand", "true"), - ea_defaultMinReports = GetConvarInt("ea_defaultMinReports", 3), - ea_MinReportPlayers = GetConvarInt("ea_MinReportPlayers", 12), - ea_MinReportModifierEnabled = GetConvar("ea_MinReportModifierEnabled", "true"), - ea_ReportBanTime = GetConvarInt("ea_ReportBanTime", 86400), - ea_custombanlist = GetConvar("ea_custombanlist", "false"), - ea_maxWarnings = GetConvarInt("ea_maxWarnings", 3), - ea_warnAction = GetConvar("ea_warnAction", "kick"), - ea_warningBanTime = GetConvarInt("ea_warningBanTime", 604800), - ea_enableSplash = GetConvar("ea_enableSplash", "true"), - ea_playerCacheExpiryTime = GetConvarInt("ea_playerCacheExpiryTime", 900), - ea_chatReminderTime = GetConvarInt("ea_chatReminderTime", 0), - ea_backupFrequency = GetConvarInt("ea_backupFrequency", 72), - ea_maxBackupCount = GetConvarInt("ea_maxBackupCount", 10), - ea_useTokenIdentifiers = GetConvar("ea_useTokenIdentifiers", "true"), - } - - for i,v in pairs(supportData.config) do - PrintDebugMessage(i.." = "..v, 4) - end - - Wait(500) - - PrintDebugMessage("Collecting Server Config....^7\n", 1) - - local path = GetResourcePath(GetCurrentResourceName()) - local occurance = string.find(path, "/resources") - local path = string.reverse(string.sub(string.reverse(path), -occurance)) - - local servercfg = io.open(path.."server.cfg") - if servercfg then - supportData.serverconfig = servercfg:read("*a") - servercfg:close() - - else - PrintDebugMessage("Could not find your server.cfg file, it should be called `server.cfg` in the parent folder of `resources`, otherwise EasyAdmin cannot read it, this report may be incomplete.\n", 1) - end - - PrintDebugMessage("Collecting easyadmin_permissions.cfg....^7\n", 1) - local permissions = io.open(path.."easyadmin_permissions.cfg") - if permissions then - supportData.serverconfig = supportData.serverconfig.."\n#### The following are the contents of the easyadmin_permissions.cfg ####\n"..permissions:read("*a") - permissions:close() - else - PrintDebugMessage("Could not find your easyadmin_permissions.cfg file, it should be called `easyadmin_permissions.cfg` in the parent folder of `resources`, otherwise EasyAdmin cannot read it, this report may be incomplete.\n", 1) - end - - PrintDebugMessage("Collecting Players....^7\n", 1) - - local players = {} - for i, player in pairs(GetPlayers()) do - players[player] = GetPlayerIdentifiers(player) - if IsPlayerAdmin(player) then - PrintDebugMessage(GetPlayerName(player).." is an Admin.", 1) - end - end - - local lines = string.split(supportData.serverconfig, "\n") - - for i, line in pairs(lines) do - if string.find(line, "add_ace group.admin easyadmin allow") then - adminAllowed = true - end - - if string.find(line, "add_principal identifier.steam") then - local steamid = string.match(line, "add_principal identifier.steam:(.*) group") - if not string.match(steamid,"%a") then - PrintDebugMessage("Please double check the following line: \n"..line.."\n\nthe steamid might be in decimal format, it should be hexadecimal.\n", 1) - end - end - - if string.find(line, "add_ace group.") then - if string.find(line, "deny") then - PrintDebugMessage("The following line is denying permissions, this WILL cause problems, only allow permissions you want to allow! \n"..line.."\n", 1) - end - end - - end - - - - - if supportData.config.steam_webApiKey == "" then - PrintDebugMessage("POSSIBLE ISSUE: steam_webApiKey is not defined! Steam Identifiers will not work.\n", 1) - end - - if supportData.config.ea_custombanlist == "true" then - PrintDebugMessage("POSSIBLE ISSUE: Custom Banlist is enabled, this is no longer supported.\n", 1) - end - - if supportData.config.ea_minIdentifierMatches <= 1 then - PrintDebugMessage("POSSIBLE ISSUE: ea_minIdentifierMatches should never be less than 1.\n", 1) - end - - if type(supportData.config.ea_defaultKey) == "number" then - PrintDebugMessage("POSSIBLE ISSUE: ea_defaultKey should be a Key, not a Control id.\n", 1) - end - - if supportData.config.ismaster then - PrintDebugMessage("EasyAdmin isn't using the latest stable release, this may or may not be an issue.\n", 1) - end - - if updateAvailable then - PrintDebugMessage("POSSIBLE ISSUE: EasyAdmin is outdated, you should update ASAP.\n", 1) - end - - if not adminAllowed then - PrintDebugMessage("POSSIBLE ISSUE: 'add_ace group.admin easyadmin allow' is missing \n", 1) - end - - PrintDebugMessage("eaDiag Finished.", 1) - diagActive=false - - - - - end - end, false) - - - -end) \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/plugins/example_client.lua b/server-data/resources/[esx]/EasyAdmin/plugins/example_client.lua deleted file mode 100644 index 601b9c01f..000000000 --- a/server-data/resources/[esx]/EasyAdmin/plugins/example_client.lua +++ /dev/null @@ -1,58 +0,0 @@ - --- EasyAdmin Plugin Example, this allows injecting new UI Elements directly into EasyAdmin Menus, see NativeUILua Docs on Guides how to add new Items, below is an example code. - -local somevalue = false - --- functions MUST be prefixed with local! - -local function playerOption(playerId) - local thisItem = NativeUI.CreateItem("Example Item","Player ID is "..playerId) -- create our new item - thisPlayer:AddItem(thisItem) -- thisPlayer is global. - thisItem.Activated = function(ParentMenu,SelectedItem) - -- enter your clientside code here, this will be run once the button has been activated. - somevalue = true -- set some value we want to undo once the menu closes. - - end - - if DoesPlayerHavePermission(-1, "player.kick") then -- you can also check if a user has a specific Permission. - local thisExampleMenu = _menuPool:AddSubMenu(thisPlayer,"Example Submenu","",true) -- Submenus work, too! - thisExampleMenu:SetMenuWidthOffset(menuWidth) - - local thisItem = NativeUI.CreateItem("Example Submenu Item","") - thisExampleMenu:AddItem(thisItem) -- Items dont require a trigger. - - end -end - -local function mainMenu() - error("You have the example plugin enabled, this is only meant to be used as a template for new plugins.") -end - -local function cachedMenu() -end - -local function serverMenu() -end - -local function settingsMenu() -end - -local function menuRemoved() - somevalue = false -- reset our value :) -end - - -local pluginData = { - name = "Demo", - functions = { - mainMenu = mainMenu, - playerMenu = playerOption, - cachedMenu = cachedMenu, - serverMenu = serverMenu, - settingsMenu = settingsMenu, - menuRemoved = menuRemoved, - } -} - --- uncomment to enable plugin --- addPlugin(pluginData) \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/plugins/example_server.lua b/server-data/resources/[esx]/EasyAdmin/plugins/example_server.lua deleted file mode 100644 index f2eacb23d..000000000 --- a/server-data/resources/[esx]/EasyAdmin/plugins/example_server.lua +++ /dev/null @@ -1,8 +0,0 @@ --- EasyAdmin Plugin Example, you can run any server-code here, below is an example that shows this functionality - -if false == false then return end - -function foo(bar) - return bar.." baz" -end -AddEventHandler("EasyAdmin:foo", foo) diff --git a/server-data/resources/[esx]/EasyAdmin/plugins/example_shared.lua b/server-data/resources/[esx]/EasyAdmin/plugins/example_shared.lua deleted file mode 100644 index 230df7fd5..000000000 --- a/server-data/resources/[esx]/EasyAdmin/plugins/example_shared.lua +++ /dev/null @@ -1,8 +0,0 @@ - ---[[ This code is disabled as it's an example. - -Citizen.CreateThread(function() -- needs to be in a thread. - permissions["plugin.exmaple"] = false -- adds "easyadmin.plugin.example" Permission which can be used from both the clientside and server side to check for permissions. -end - -]] diff --git a/server-data/resources/[esx]/EasyAdmin/plugins/notifications/mythic-notify_client.lua b/server-data/resources/[esx]/EasyAdmin/plugins/notifications/mythic-notify_client.lua deleted file mode 100644 index 606cbbfff..000000000 --- a/server-data/resources/[esx]/EasyAdmin/plugins/notifications/mythic-notify_client.lua +++ /dev/null @@ -1,20 +0,0 @@ --- --- This is an example Plugin to pass EasyAdmin's Internal events to an External Resource as a Notification, the reader is expected to form their own functions from this, editing this code is *NOT* recommended, --- as updates will overwrite it, instead, make your own plugin from this example (copying the file and renaming it is enough.) --- the end result will look like this: https://blumlaut.me/s/H9pHGsXgjAFeHDP/preview --- --- Feel free to make Pull Requests to add aditional features for this, this is merely an example of whats possible. --- - --- this bit of code tells EasyAdmin to not draw the V Notification. -AddEventHandler("EasyAdmin:receivedNotification", function() - if GetResourceState("mythic-notify") == "started" then - CancelEvent() - end -end) - -AddEventHandler("EasyAdmin:showNotification", function(text, important) - if GetResourceState("mythic-notify") == "started" then - exports['mythic_notify']:DoHudText('inform', text) - end -end) \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/plugins/notifications/pNotify_client.lua b/server-data/resources/[esx]/EasyAdmin/plugins/notifications/pNotify_client.lua deleted file mode 100644 index d6781b301..000000000 --- a/server-data/resources/[esx]/EasyAdmin/plugins/notifications/pNotify_client.lua +++ /dev/null @@ -1,20 +0,0 @@ --- --- This is an example Plugin to pass EasyAdmin's Internal events to an External Resource as a Notification, the reader is expected to form their own functions from this, editing this code is *NOT* recommended, --- as updates will overwrite it, instead, make your own plugin from this example (copying the file and renaming it is enough.) --- the end result will look like this: https://blumlaut.me/s/H9pHGsXgjAFeHDP/preview --- --- Feel free to make Pull Requests to add aditional features for this, this is merely an example of whats possible. --- - --- this bit of code tells EasyAdmin to not draw the V Notification. -AddEventHandler("EasyAdmin:receivedNotification", function() - if GetResourceState("pNotify") == "started" then - CancelEvent() - end -end) - -AddEventHandler("EasyAdmin:showNotification", function(text, important) - if GetResourceState("pNotify") == "started" then - exports['pNotify']:SendNotification({layout = "centerLeft", type = "alert", text = text}) - end -end) \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/plugins/notifications/t-notify_client.lua b/server-data/resources/[esx]/EasyAdmin/plugins/notifications/t-notify_client.lua deleted file mode 100644 index 370327135..000000000 --- a/server-data/resources/[esx]/EasyAdmin/plugins/notifications/t-notify_client.lua +++ /dev/null @@ -1,20 +0,0 @@ --- --- This is an example Plugin to pass EasyAdmin's Internal events to an External Resource as a Notification, the reader is expected to form their own functions from this, editing this code is *NOT* recommended, --- as updates will overwrite it, instead, make your own plugin from this example (copying the file and renaming it is enough.) --- the end result will look like this: https://blumlaut.me/s/H9pHGsXgjAFeHDP/preview --- --- Feel free to make Pull Requests to add aditional features for this, this is merely an example of whats possible. --- - --- this bit of code tells EasyAdmin to not draw the V Notification. -AddEventHandler("EasyAdmin:receivedNotification", function() - if GetResourceState("t-notify") == "started" then - CancelEvent() - end -end) - -AddEventHandler("EasyAdmin:showNotification", function(text, important) - if GetResourceState("t-notify") == "started" then - exports['t-notify']:Alert({style = "error", message = text}) - end -end) \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/server/admin_server.lua b/server-data/resources/[esx]/EasyAdmin/server/admin_server.lua deleted file mode 100644 index 53a837fe9..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/admin_server.lua +++ /dev/null @@ -1,976 +0,0 @@ ------------------------------------- ------------------------------------- ----- DONT TOUCH ANY OF THIS IF YOU DON'T KNOW WHAT YOU ARE DOING ----- THESE ARE **NOT** CONFIG VALUES, USE THE CONVARS IF YOU WANT TO CHANGE SOMETHING ----- ----- ----- If you are a developer and want to change something, consider writing a plugin instead: ----- https://easyadmin.readthedocs.io/en/latest/plugins/ ----- ------------------------------------- ------------------------------------- - --- Chat Reminder Code -function sendRandomReminder() - reminderTime = GetConvarInt("ea_chatReminderTime", 0) - if reminderTime ~= 0 and #ChatReminders > 0 then - local reminder = ChatReminders[ math.random( #ChatReminders ) ] -- select random reminder from table - local adminNames = "" - local t = {} - for i,_ in pairs(OnlineAdmins) do - table.insert(t, getName(i)) - end - for i,n in ipairs(t) do - if i == 1 then - adminNames = n - elseif i == #t then - adminNames = adminNames.." "..n - else - adminNames = adminNames.." "..n.."," - end - end - t=nil - - if adminNames == "" then adminNames = "@admins" end -- if no admins are online just print @admins - reminder = string.gsub(reminder, "@admins", adminNames) - - reminder = string.gsub(reminder, "@bancount", #blacklist) - - reminder = string.gsub(reminder, "@time", os.date("%X", os.time())) - reminder = string.gsub(reminder, "@date", os.date("%x", os.time())) - TriggerClientEvent("chat:addMessage", -1, { args = { "EasyAdmin", reminder } }) - end -end - -function announce(reason) - if reason then - TriggerClientEvent("EasyAdmin:showNotification", -1, "[" .. GetLocalisedText("announcement") .. "] " .. reason) - return true - else - return false - end -end - -exports('announce', announce) - -Citizen.CreateThread(function() - --Wait(10000) - reminderTime = GetConvarInt("ea_chatReminderTime", 0) - if reminderTime ~= 0 then - while true do - Wait(reminderTime*60000) - sendRandomReminder() - end - else - while true do - Wait(20000) - sendRandomReminder() -- check for changes in the convar - end - end -end) - - -function getAllPlayerIdentifiers(playerId) --Gets all info that could identify a player - local identifiers = GetPlayerIdentifiers(playerId) - local tokens = {} - if GetConvar("ea_useTokenIdentifiers", "true") == "true" then - if not GetNumPlayerTokens or not GetPlayerToken then - PrintDebugMessage("Server Version is below artifact 3335, disabling Token identifiers, please consider updating your FXServer!", 1) - SetConvar("ea_useTokenIdentifiers", "false") - PrintDebugMessage("Set ea_useTokenIdentifiers to false for this session.", 1) - return identifiers - end - for i=0,GetNumPlayerTokens(playerId) do - table.insert(tokens, GetPlayerToken(playerId, i)) - end - end - return mergeTables(identifiers, tokens) -end -exports('getAllPlayerIdentifiers', getAllPlayerIdentifiers) - - -function checkForChangedIdentifiers(playerIds, bannedIds) - local unbannedIds = {} - for _,playerId in pairs(playerIds) do - local thisIdBanned = false - for _,bannedId in pairs(bannedIds) do - if playerId == bannedId then - thisIdBanned = true - end - end - if not thisIdBanned then --They have a new/changed identifier - table.insert(unbannedIds, playerId) - end - end - return unbannedIds -end - - -AddEventHandler('playerDropped', function (reason) - if OnlineAdmins[source] then - OnlineAdmins[source] = nil - end - if FrozenPlayers[source] then - FrozenPlayers[source] = nil - for i,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:SetPlayerFrozen", i, 1000, source, nil) - end - end - if MutedPlayers[source] then - MutedPlayers[source] = nil - for i,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:SetPlayerMuted", i, 1000, source, nil) - end - end - PrintDebugMessage(source.." disconnected.", 4) -end) - - -RegisterServerEvent("EasyAdmin:GetInfinityPlayerList", function() - PrintDebugMessage(getName(source, true).." requested Playerlist.", 4) - if IsPlayerAdmin(source) then - local l = {} - local players = GetPlayers() - - for i, player in pairs(players) do - local player = tonumber(player) - cachePlayer(player) - for i, cached in pairs(CachedPlayers) do - if (cached.id == player) then - local pData = {id = cached.id, name = cached.name, immune = cached.immune} - for i, v in pairs(cached.identifiers) do - if v == "discord:178889658128793600" then - pData.developer = true - elseif v == "discord:736521574383091722" --[[ Jaccosf ]] or v == "discord:1001065851790839828" --[[ robbybaseplate ]] or v == "discord:840695262460641311" --[[ Knight ]] or v == "discord:270731163822325770" --[[ Skypo ]] or v == "discord:186980021850734592" --[[ coleminer0112 ]] then - pData.contributor = true - end - end - table.insert(l, pData) - end - end - end - - -- each player is more or less 2000bytes big. - TriggerLatentClientEvent("EasyAdmin:GetInfinityPlayerList", source, 200000, l) - end -end) - -function GetOnlineAdmins() - return OnlineAdmins -end -exports('GetOnlineAdmins', GetOnlineAdmins) - -function IsPlayerAdmin(pid) - return OnlineAdmins[pid] -end -exports('IsPlayerAdmin', IsPlayerAdmin) - - -Citizen.CreateThread(function() - - if not CachedPlayers or GetVersion() == nil then - print("^7--------------------------------------------------------------") - print("^1EasyAdmin self-test failed! Your EasyAdmin **will not work**, likely you edited some files and broke EasyAdmin in the progress, please reinstall EasyAdmin.") - print("^7--------------------------------------------------------------") - return - end - - if GetConvar("gamename", "gta5") == "rdr3" then - RedM = true - PrintDebugMessage("Starting in rdr3 Mode.", 4) - else - RedM = false - PrintDebugMessage("Starting in gta5 Mode.", 4) - end - - AnonymousAdmins = {} - - loadLanguageStrings() - - moderationNotification = GetConvar("ea_moderationNotification", "false") - reportNotification = GetConvar("ea_reportNotification", "false") - detailNotification = GetConvar("ea_detailNotification", "false") - minimumMatchingIdentifierCount = GetConvarInt("ea_minIdentifierMatches", 2) - - - RegisterServerEvent('EasyAdmin:amiadmin', function() - local source = source - - cachePlayer(source) -- this will do nothing if player is already cached. - - if CachedPlayers[source].lastPermRequest and CachedPlayers[source].lastPermRequest+10 > os.time() then - PrintDebugMessage(getName(source).." hit Permission Check Ratelimit! "..CachedPlayers[source].lastPermRequest+10-os.time().." seconds left.", 3) - return - end - - CachedPlayers[source].lastPermRequest = os.time() - - local identifiers = getAllPlayerIdentifiers(source) - local perms = {} - for perm,val in pairs(permissions) do - local thisPerm = DoesPlayerHavePermission(source, perm) - if perm == "player.screenshot" and not screenshots then - thisPerm = false - end - if string.find(perm, "server.permissions") and disablePermissionEditor then - thisPerm = false - end - --if (perm == "teleport" or perm == "spectate") and infinity then - --if (perm == "spectate") and infinity then - -- thisPerm = false - --end - if thisPerm == true then - OnlineAdmins[source] = true - end - perms[perm] = thisPerm - PrintDebugMessage("Processed Perm "..perm.." for "..getName(source, true)..", result: "..tostring(thisPerm), 3) - end - - TriggerLatentClientEvent("EasyAdmin:adminresponse", source, 10000, perms) - TriggerClientEvent('chat:addSuggestion', source, '/easyadmin', "EasyAdmin Menu", {{name="report or player id", help="[Optional] Report or Player ID"}}) - TriggerClientEvent('chat:addSuggestion', source, '/ea', "EasyAdmin Menu", {{name="report or player id", help="[Optional] Report or Player ID"}}) - - if GetConvar("ea_enableReportCommand", "true") == "true" then - TriggerClientEvent('chat:addSuggestion', source, '/'..GetConvar("ea_reportCommandName", "report"), "Report player", {{name='player', help="player name / id"}, {name='reason', help="Reason"}}) - end - - if GetConvar("ea_enableCallAdminCommand", "true") == "true" then - TriggerClientEvent('chat:addSuggestion', source, '/'..GetConvar("ea_callAdminCommandName", "calladmin"), "Call Admin", {{name='reason', help="Reason"}}) - end - - - - if RedM then - -- give player the right settings to work with - local key = GetConvar("ea_defaultKey", "none") - - TriggerClientEvent("EasyAdmin:SetSetting", source, "button", key) - end - - if GetConvar("ea_alwaysShowButtons", "false") == "true" then - TriggerClientEvent("EasyAdmin:SetSetting", source, "forceShowGUIButtons", true) - else - TriggerClientEvent("EasyAdmin:SetSetting", source, "forceShowGUIButtons", false) - end - if updateAvailable then - TriggerClientEvent("EasyAdmin:SetSetting", source, "updateAvailable", updateAvailable) - end - - -- if you remove this code then you're a killjoy, can't we have nice things? just once? it's not like this changes the whole admin menu or how it behaves, its a single subtitle. - if os.date("%d/%m") == "22/08" then - local age = tonumber(os.date("%Y"))-2017 local ordinal = "th" last_digit = age % 10 if last_digit == 1 and age ~= 11 then ordinal = 'st' elseif last_digit == 2 and age ~= 12 then ordinal = 'nd' elseif last_digit == 3 and age ~= 13 then ordinal = 'rd' end - TriggerClientEvent("EasyAdmin:SetSetting", source, "alternativeTitle", "~b~Today is EasyAdmin's "..age..""..ordinal.." birthday! :)") - elseif os.date("%m") == "06" and (tonumber(os.date("%d")) >= 1 and tonumber(os.date("%d")) <= 14) then - TriggerClientEvent("EasyAdmin:SetSetting", source, "alternativeLogo", "pride") - elseif os.date("%m") == "04" and os.date("%d") == "01" then - TriggerClientEvent("EasyAdmin:SetSetting", source, "alternativeLogo", "logo-hardadmin") - TriggerClientEvent("EasyAdmin:SetSetting", source, "alternativeBanner", "banner-hardadmin") - end - - if (infinity) then - TriggerClientEvent("EasyAdmin:SetSetting", source, "infinity", true) - end - - TriggerLatentClientEvent("EasyAdmin:fillShortcuts", source, 10000, MessageShortcuts) - - TriggerLatentClientEvent("EasyAdmin:SetLanguage", source, 10000, strings) - - end) - - RegisterServerEvent("EasyAdmin:kickPlayer", function(playerId,reason) - if DoesPlayerHavePermission(source, "player.kick") and not CachedPlayers[playerId].immune then - reason = formatShortcuts(reason) - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminkickedplayer"), getName(source, false, true), getName(playerId, true, true), reason), "kick", 16711680) - PrintDebugMessage("Kicking Player "..getName(source, true).." for "..reason, 3) - DropPlayer(playerId, string.format(GetLocalisedText("kicked"), getName(source), reason) ) - elseif CachedPlayers[playerId].immune then - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("adminimmune")) - end - end) - - RegisterServerEvent("EasyAdmin:requestSpectate", function(playerId) - if DoesPlayerHavePermission(source, "player.spectate") then - PrintDebugMessage("Player "..getName(source,true).." Requested Spectate to "..getName(playerId,true), 3) - local tgtCoords = GetEntityCoords(GetPlayerPed(playerId)) - TriggerClientEvent("EasyAdmin:requestSpectate", source, playerId, tgtCoords) - local preferredWebhook = detailNotification ~= "false" and detailNotification or moderationNotification - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText('spectatedplayer'), getName(source, false, true), getName(playerId, true, true)), "spectate", 16777214) - end - end) - - function cleanupArea(type, radius, player) - if not radius then radius = "global" end - if (onesync ~= "off" and onesync ~= "legacy") then - local toDelete = {} - if type == "cars" then - toDelete = GetAllVehicles() - elseif type == "peds" then - toDelete = GetAllPeds() - elseif type == "props" then - toDelete = GetAllObjects() - end - PrintDebugMessage("server-known entities: "..table_to_string(toDelete), 4) - for _,entity in pairs(toDelete) do - PrintDebugMessage("starting deletion for entity "..entity, 4) - if DoesEntityExist(entity) and not (type == "cars" and IsPedAPlayer(GetPedInVehicleSeat(entity, -1))) and not (type == "peds" and IsPedAPlayer(entity)) then - if radius == "global" then - PrintDebugMessage("deleting entity "..entity, 3) - DeleteEntity(entity) - else - local entityCoords = GetEntityCoords(entity) - local playerCoords = GetEntityCoords(GetPlayerPed(player)) - if #(playerCoords - entityCoords) < radius then - PrintDebugMessage("deleting entity "..entity, 3) - DeleteEntity(entity) - end - end - end - end - return true - else - return false - end - end - exports('cleanupArea', cleanupArea) - - RegisterServerEvent("EasyAdmin:requestCleanup", function(type, radius, deep) - local source=source - if DoesPlayerHavePermission(source, "server.cleanup."..type) then - PrintDebugMessage("Player "..getName(source,true).." Requested Cleanup for "..type, 3) - cleanupArea(type, radius, source) - - if deep then - TriggerClientEvent("EasyAdmin:requestCleanup", source, type, radius) - end - TriggerClientEvent("EasyAdmin:showNotification", source, string.format(GetLocalisedText("finishedcleaning"), GetLocalisedText(type))) - local preferredWebhook = detailNotification ~= "false" and detailNotification or moderationNotification - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText('admincleanedup'), getName(source, false, true), type, radius), "cleanup", 16777214) - end - end) - - RegisterServerEvent("EasyAdmin:SetGameType", function(text) - if DoesPlayerHavePermission(source, "server.convars") then - PrintDebugMessage("Player "..getName(source,true).." set Gametype to "..text, 3) - SetGameType(text) - local preferredWebhook = detailNotification ~= "false" and detailNotification or moderationNotification - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText('adminchangedconvar'), getName(source, false, true), "gametype", text), "settings", 16777214) - end - end) - - RegisterServerEvent("EasyAdmin:SetMapName", function(text) - if DoesPlayerHavePermission(source, "server.convars") then - PrintDebugMessage("Player "..getName(source,true).." set Map Name to "..text, 3) - SetMapName(text) - local preferredWebhook = detailNotification ~= "false" and detailNotification or moderationNotification - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText('adminchangedconvar'), getName(source, false, true), "mapname", text), "settings", 16777214) - end - end) - - RegisterServerEvent("EasyAdmin:StartResource", function(text) - if DoesPlayerHavePermission(source, "server.resources.start") then - PrintDebugMessage("Player "..getName(source,true).." started Resource "..text, 3) - StartResource(text) - local preferredWebhook = detailNotification ~= "false" and detailNotification or moderationNotification - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText('adminstartedresource'), getName(source, false, true), text), "settings", 65280) - end - end) - - RegisterServerEvent("EasyAdmin:StopResource", function(text) - if DoesPlayerHavePermission(source, "server.resources.stop") then - PrintDebugMessage("Player "..getName(source,true).." stopped Resource "..text, 3) - StopResource(text) - local preferredWebhook = detailNotification ~= "false" and detailNotification or moderationNotification - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText('adminstoppedresource'), getName(source, false, true), text), "settings", 16711680) - end - end) - - RegisterServerEvent("EasyAdmin:SetConvar", function(convarname, convarvalue) - if DoesPlayerHavePermission(source, "server.convars") then - PrintDebugMessage("Player "..getName(source,true).." set convar "..convarname.. " to "..convarvalue, 3) - SetConvar(convarname, convarvalue) - local preferredWebhook = detailNotification ~= "false" and detailNotification or moderationNotification - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText('adminchangedconvar'), getName(source, false, true), convarname, convarvalue), "settings", 16777214) - end - end) - - RegisterServerEvent("EasyAdmin:Announce", function(text) - if DoesPlayerHavePermission(source, "server.announce") then - PrintDebugMessage("Player "..getName(source,true).." sent a announcement: "..text, 3) - announce(text) - local preferredWebhook = detailNotification ~= "false" and detailNotification or moderationNotification - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText('adminannouncement'), getName(source, false, true), text), "settings", 16777214) - end - end) - - RegisterServerEvent("EasyAdmin:TeleportPlayerToCoords", function(playerId,tgtCoords) - if DoesPlayerHavePermission(source, "player.teleport.single") then - PrintDebugMessage("Player "..getName(source,true).." requsted teleport to "..tgtCoords.x..", "..tgtCoords.y..", "..tgtCoords.z, 3) - local preferredWebhook = detailNotification ~= "false" and detailNotification or moderationNotification - local playerName = getName(playerId, true, true) - if playerId == -1 then - playerName = GetLocalisedText("allplayers") - end - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText("teleportedtoplayer"), playerName, getName(source, false, true)), "teleport", 16777214) - TriggerClientEvent("EasyAdmin:TeleportRequest", playerId, false, tgtCoords) - end - end) - - RegisterServerEvent("EasyAdmin:TeleportAdminToPlayer", function(id) - if not CachedPlayers[id].dropped and DoesPlayerHavePermission(source, "player.teleport.single") then - local tgtPed = GetPlayerPed(id) - local tgtCoords = GetEntityCoords(tgtPed) - local preferredWebhook = detailNotification ~= "false" and detailNotification or moderationNotification - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText("teleportedtoplayer"), getName(source, false, true), getName(id, true, true)), "teleport", 16777214) - TriggerClientEvent('EasyAdmin:TeleportRequest', source, id,tgtCoords) - else - PrintDebugMessage('EASYADMIN FAILED TO TELEPORT'..source..' TO ID: '..id, 2) - end - end) - - RegisterServerEvent("EasyAdmin:TeleportPlayerBack", function(id) - if not CachedPlayers[id].dropped and DoesPlayerHavePermission(source, "player.teleport.single") then - TriggerClientEvent('EasyAdmin:TeleportPlayerBack', id) - end - end) - - function slapPlayer(playerId,slapAmount) - if not CachedPlayers[playerId].immune then - TriggerClientEvent("EasyAdmin:SlapPlayer", playerId, slapAmount) - return true - else - return false - end - end - exports('slapPlayer', slapPlayer) - - RegisterServerEvent("EasyAdmin:SlapPlayer", function(playerId,slapAmount) - if DoesPlayerHavePermission(source, "player.slap") and slapPlayer(playerId, slapAmount) then - PrintDebugMessage("Player "..getName(source,true).." slapped "..getName(playerId,true).." for "..slapAmount.." HP", 3) - local preferredWebhook = detailNotification ~= "false" and detailNotification or moderationNotification - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText("adminslappedplayer"), getName(source, false, true), getName(playerId, true, true), slapAmount), "slap", 16777214) - elseif CachedPlayers[playerId].immune then - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("adminimmune")) - end - end) - - function freezePlayer(playerId, toggle) - if not toggle then toggle = not FrozenPlayers[playerId] end - if not CachedPlayers[playerId].immune then - FrozenPlayers[playerId] = (toggle == true or nil) - TriggerClientEvent("EasyAdmin:FreezePlayer", playerId, toggle) - for i,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:SetPlayerFrozen", i, 1000, playerId, (toggle == true or nil)) - end - return true - else - return false - end - end - exports('freezePlayer', freezePlayer) - - RegisterServerEvent("EasyAdmin:FreezePlayer", function(playerId,toggle) - if DoesPlayerHavePermission(source, "player.freeze") and not CachedPlayers[playerId].immune then - local preferredWebhook = detailNotification ~= "false" and detailNotification or moderationNotification - freezePlayer(playerId, toggle) - if toggle then - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText("adminfrozeplayer"), getName(source, false, true), getName(playerId, true, true)), "freeze", 16777214) - PrintDebugMessage("Player "..getName(source,true).." froze "..getName(playerId,true), 3) - else - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText("adminunfrozeplayer"), getName(source, false, true), getName(playerId, true, true)), "freeze", 16777214) - PrintDebugMessage("Player "..getName(source,true).." unfroze "..getName(playerId,true), 3) - end - elseif CachedPlayers[playerId].immune then - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("adminimmune")) - end - end) - - scrinprogress = false - - function isScreenshotInProgress() - return scrinprogress - end - exports('isScreenshotInProgress', isScreenshotInProgress) - - RegisterServerEvent("EasyAdmin:TakeScreenshot", function(playerId) - if scrinprogress then - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("screenshotinprogress")) - return - end - local src=source - local playerId = playerId - local invokingResource - if GetInvokingResource() and GetInvokingResource() ~= GetCurrentResourceName() then - invokingResource = "`"..GetInvokingResource().."`" - end - - if DoesPlayerHavePermission(source, "player.screenshot") then - scrinprogress = true - thistemporaryevent = RegisterServerEvent("EasyAdmin:TookScreenshot", function(result) - if result == "ERROR" then return false end - - res = matchURL(tostring(result)) - - PrintDebugMessage("Screenshot taken, result:\n "..res, 4) - SendWebhookMessage(moderationNotification, string.format(GetLocalisedText("admintookscreenshot"), invokingResource or getName(src), getName(playerId, true, true), res), "screenshot", 16777214, "Screenshot Captured", res) - TriggerClientEvent('chat:addMessage', src, { template = '', args = { res } }) - TriggerClientEvent("chat:addMessage", src, { args = { "EasyAdmin", string.format(GetLocalisedText("screenshotlink"), res) } }) - PrintDebugMessage("Screenshot for Player "..getName(playerId,true).." done, "..res.." requsted by"..getName(src,true), 3) - scrinprogress = false - RemoveEventHandler(thistemporaryevent) - end) - - TriggerClientEvent("EasyAdmin:CaptureScreenshot", playerId) - local timeoutwait = 0 - repeat - timeoutwait=timeoutwait+1 - Wait(5000) - if timeoutwait == 5 then - RemoveEventHandler(thistemporaryevent) - scrinprogress = false -- cancel screenshot, seems like it failed - PrintDebugMessage("Screenshot timed out", 4) - TriggerClientEvent("EasyAdmin:showNotification", src, "Screenshot Failed!") - end - until not scrinprogress - end - end) - - RegisterServerEvent("EasyAdmin:mutePlayer", function(playerId) - local src = source - if DoesPlayerHavePermission(src,"player.mute") and not CachedPlayers[playerId].immune then - local muted = mutePlayer(playerId, not MutedPlayers[playerId]) - - if muted then - if MutedPlayers[playerId] then - TriggerClientEvent("EasyAdmin:showNotification", src, getName(playerId) .. " " .. GetLocalisedText("playermuted")) - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminmutedplayer"), getName(source, false, true), getName(playerId, false, true)), "mute", 16777214) - else - TriggerClientEvent("EasyAdmin:showNotification", src, getName(playerId) .. " " .. GetLocalisedText("playerunmuted")) - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminunmutedplayer"), getName(source, false, false), getName(playerId, false, true)), "mute", 16777214) - end - else - -- todo: handle false retval - end - end - end) - - function mutePlayer(playerId, toggle) - if not CachedPlayers[playerId].immune then - if toggle and not MutedPlayers[playerId] then - MutedPlayers[playerId] = true - if MumbleSetPlayerMuted then -- workaround for outdated servers - MumbleSetPlayerMuted(playerId, true) - end - PrintDebugMessage("muted "..getName(playerId,true), 3) - for i,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:SetPlayerMuted", i, 1000, playerId, (MutedPlayers[playerId] == true or nil)) - end - return true - elseif not toggle and MutedPlayers[playerId] then - MutedPlayers[playerId] = nil - if MumbleSetPlayerMuted then -- workaround for outdated servers - MumbleSetPlayerMuted(playerId, false) - end - PrintDebugMessage("unmuted "..getName(playerId,true), 3) - for i,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:SetPlayerMuted", i, 1000, playerId, (MutedPlayers[playerId] == true or nil)) - end - return true - else - return false - end - else - return false - end - end - exports('mutePlayer', mutePlayer) - - RegisterServerEvent("EasyAdmin:SetAnonymous", function(playerId) - if DoesPlayerHavePermission(source, "anon") then - if AnonymousAdmins[source] then - AnonymousAdmins[source] = nil - PrintDebugMessage("Player "..getName(source,true).." un-anoned themself", 3) - else - AnonymousAdmins[source] = true - PrintDebugMessage("Player "..getName(source,true).." anoned themself", 3) - end - end - end) - - -- Very basic function that turns "source" into a useable player name. - function getName(src,anonymousdisabled,identifierenabled) - local identifierPref = GetConvar("ea_logIdentifier", "steam,discord,license") - if identifierPref == "false" then identifierenabled = false end; - local identifiers, identifier = {}, "~No Identifier~" - if (src == 0 or src == "") then - return "Console" - else - if AnonymousAdmins[src] and not anonymousdisabled then - return GetLocalisedText("anonymous") - elseif CachedPlayers[src] and CachedPlayers[src].name then - if CachedPlayers[src].identifiers then - if identifierPref then - -- split identifierPref by comma and find first identifier in CachedPlayers[src].identifiers that starts with the split string - -- this code was written by GitHub Copilot, neat, huh? - for i,v in ipairs(identifierPref:split(",")) do - for i2,v2 in ipairs(CachedPlayers[src].identifiers) do - if string.sub(v2, 1, string.len(v)) == v then - identifier = v2 - break - end - end - if identifier ~= "~No Identifier~" then break end - end - end - end - if identifier:find('discord:') then - identifier = string.gsub(identifier, "discord:", "") - identifier = "<@"..identifier..">" - end - if identifierenabled then - return (string.format("%s [ %s ]", CachedPlayers[src].name, identifier)) - else - return CachedPlayers[src].name - end - elseif (GetPlayerName(src)) then - identifiers = getAllPlayerIdentifiers(src) - if identifierPref then - for i,v in ipairs(identifierPref:split(",")) do - for i2,v2 in ipairs(identifiers) do - if string.sub(v2, 1, string.len(v)) == v then - identifier = v2 - break - end - end - if identifier ~= "~No Identifier~" then break end - end - end - if identifier:find('discord:') then - identifier = string.gsub(identifier, "discord:", "") - identifier = "<@"..identifier..">" - end - if identifierenabled then - return (string.format("%s [ %s ]", GetPlayerName(src), identifier)) - else - return GetPlayerName(src) - end - else - return "Unknown - " .. src - end - end - end - exports('getName', getName) - - RegisterServerEvent("EasyAdmin:warnPlayer", function(id, reason) - local src = source - if DoesPlayerHavePermission(src,"player.warn") and not CachedPlayers[id].immune then - reason = formatShortcuts(reason) - local maxWarnings = GetConvarInt("ea_maxWarnings", 3) - if not WarnedPlayers[id] then - WarnedPlayers[id] = {name = getName(id, true), identifiers = getAllPlayerIdentifiers(id), warns = 0} - end - WarnedPlayers[id].warns = WarnedPlayers[id].warns+1 - TriggerClientEvent('chat:addMessage', id, { - template = '
{0}
', - args = { string.format(GetLocalisedText("warned"), reason, WarnedPlayers[id].warns, maxWarnings) }, color = { 255, 255, 255 } - }) - TriggerClientEvent("txAdminClient:warn", id, getName(src), string.format(GetLocalisedText("warned"), reason, WarnedPlayers[id].warns, maxWarnings), GetLocalisedText("warnedtitle"), GetLocalisedText("warnedby"),GetLocalisedText("warndismiss")) - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminwarnedplayer"), getName(src, false, true), getName(id, true, true), reason, WarnedPlayers[id].warns, maxWarnings), "warn", 16711680) - if WarnedPlayers[id].warns >= maxWarnings then - if GetConvar("ea_warnAction", "kick") == "kick" then - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminkickedplayer"), getName(src, false, true), getName(id, true, true), reason), "kick", 16711680) - DropPlayer(id, GetLocalisedText("warnkicked")) - WarnedPlayers[id] = nil - elseif GetConvar("ea_warnAction", "kick") == "ban" then - local bannedIdentifiers = CachedPlayers[id].identifiers or getAllPlayerIdentifiers(id) - local bannedUsername = CachedPlayers[id].name or getName(id, true) - local expires = os.time()+GetConvarInt("ea_warningBanTime", 604800) - - reason = GetLocalisedText("warnbanned").. string.format(GetLocalisedText("reasonadd"), CachedPlayers[id].name, getName(source, true) ) - local ban = {banid = GetFreshBanId(), name = bannedUsername,identifiers = bannedIdentifiers, banner = getName(source, true), reason = reason, expire = expires } - updateBlacklist( ban ) - - PrintDebugMessage("Player "..getName(source,true).." warnbanned player "..CachedPlayers[id].name.." for "..reason, 3) - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminbannedplayer"), getName(source, false, true), bannedUsername, reason, formatDateString( expires ), tostring(ban.banid) ), "ban", 16711680) - DropPlayer(id, string.format(GetLocalisedText("banned"), reason, formatDateString( expires ) ) ) - WarnedPlayers[id] = nil - - end - end - elseif CachedPlayers[id].immune then - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("adminimmune")) - end - end) - - function warnPlayerExport(src, id, reason) - if not CachedPlayers[id].immune then - local maxWarnings = GetConvarInt("ea_maxWarnings", 3) - if not WarnedPlayers[id] then - WarnedPlayers[id] = {name = getName(id, true), identifiers = getAllPlayerIdentifiers(id), warns = 0} - end - WarnedPlayers[id].warns = WarnedPlayers[id].warns+1 - TriggerClientEvent('chat:addMessage', id, { - template = '
{0}
', - args = { string.format(GetLocalisedText("warned"), reason, WarnedPlayers[id].warns, maxWarnings) }, color = { 255, 255, 255 } - }) - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminwarnedplayer"), src, getName(id, true, true), reason, WarnedPlayers[id].warns, maxWarnings), "warn", 16711680) - TriggerClientEvent("txAdminClient:warn", id, src, string.format(GetLocalisedText("warned"), reason, WarnedPlayers[id].warns, maxWarnings), GetLocalisedText("warnedtitle"), GetLocalisedText("warnedby"),GetLocalisedText("warndismiss")) - if WarnedPlayers[id].warns >= maxWarnings then - if GetConvar("ea_warnAction", "kick") == "kick" then - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminkickedplayer"), src, getName(id, true, true), reason), "kick", 16711680) - DropPlayer(id, GetLocalisedText("warnkicked")) - WarnedPlayers[id] = nil - elseif GetConvar("ea_warnAction", "kick") == "ban" then - local expires = os.time()+GetConvarInt("ea_warningBanTime", 604800) - addBanExport(id, reason, formatDateString(expires), src) - WarnedPlayers[id] = nil - end - end - return true - else - return false - end - end - - exports('warnPlayer', warnPlayerExport) - - function getPlayerWarnings(playerId) - if not WarnedPlayers[playerId] then - return 0 - else - return WarnedPlayers[playerId].warns - end - end - exports('getPlayerWarnings', getPlayerWarnings) - - AddEventHandler("EasyAdmin:GetVersion", function(cb) - cb(GetVersion()) - end) - - local chatEventsSupported = false - - pcall(function() -- this will prevent our script from erroring if the exports are missing, also mutes any errors. - if exports.chat.registerMessageHook and exports.chat.registerMode then - chatEventsSupported = true - end - end) - - if chatEventsSupported then - exports.chat:registerMessageHook(function(source, outMessage, hookRef) - if MutedPlayers[source] then - hookRef.cancel() - TriggerClientEvent("EasyAdmin:showNotification", source, getName(source) .. ", " .. GetLocalisedText("playermute")) - end - end) - else - AddEventHandler('chatMessage', function(source, name, msg) - if MutedPlayers[source] then - CancelEvent() - TriggerClientEvent("chat:addMessage", source, { args = { "EasyAdmin", GetLocalisedText("playermute") } }) - TriggerClientEvent("EasyAdmin:showNotification", source, getName(source) .. ", " .. GetLocalisedText("playermute")) - end - end) - end - - if GetConvar("ea_enableChat", "true") == "true" and chatEventsSupported then - exports.chat:registerMode({ - name = "admins", - displayName = "Admin Chat", - color = "#19A2E3", - seObject = "easyadmin.server.chat", - cb = function(source, message, cbs) - cbs.updateMessage({ - template = "^5[ADMIN CHAT]^7" .. ' {}' - }) - - cbs.setSeObject("easyadmin.server.chat") - end - }) - end -end) - -Citizen.CreateThread(function() - function HTTPRequest(url, ...) - local err,response,headers - - PerformHttpRequest(url, function(e,r,h) - err,response,headers = e,r,h - end, ...) - repeat - Wait(10) - until (response) - - return response - end - exports('HTTPRequest', HTTPRequest) -end) - -Citizen.CreateThread(function() - AddEventHandler('playerConnecting', function(playerName, setKickReason, deferrals) - local player = source - local numIds = getAllPlayerIdentifiers(player) - local matchingIdentifierCount = 0 - local matchingIdentifiers = {} - local showProgress = GetConvar("ea_presentDeferral", "true") - - deferrals.defer() - Wait(0) - local deferralText = string.format(GetLocalisedText("deferral"), 0) - if showProgress == "false" then - deferralText = deferralText:sub(1, -6) - end - - deferrals.update(deferralText) - PrintDebugMessage(getName(player).."'s Identifiers:\n "..table_to_string(numIds), 3) - if not blacklist then - print("^1-^2-^3-^4-^5-^6-^8-^9-^1-^2-^3-^4-^5-^6-^8-^9-^1-^2-^3-^3!^1FATAL ERROR^3!^3-^2-^1-^9-^8-^6-^5-^4-^3-^2-^1-^9-^8-^6-^5-^4-^3-^2-^7\n") - print("EasyAdmin: ^1Failed^7 to load Banlist!\n") - print("EasyAdmin: Please check this error soon, ^1Bans *will not* work!^7\n") - print("^1-^2-^3-^4-^5-^6-^8-^9-^1-^2-^3-^4-^5-^6-^8-^9-^1-^2-^3-^3!^1FATAL ERROR^3!^3-^2-^1-^9-^8-^6-^5-^4-^3-^2-^1-^9-^8-^6-^5-^4-^3-^2-^7\n") - deferrals.done("\n\nEasyAdmin: A fatal error occured, please contact a Server Administrator to resolve this issue.") - return - end - Wait(0) - - local lastPercentage = 0 - for bi,blacklisted in ipairs(blacklist) do - if showProgress == "true" then - local percentage = math.round(bi/#blacklist*100) - if bi % 12 == 0 and percentage >= lastPercentage+4 then -- only update on every 12th ban - Wait(0) - deferrals.update(string.format(GetLocalisedText("deferral"), percentage)) - lastPercentage = percentage - end - end - for i,theId in ipairs(numIds) do - for ci,identifier in ipairs(blacklisted.identifiers) do - if identifier == theId and matchingIdentifiers[theId] ~= true then - matchingIdentifierCount = matchingIdentifierCount+1 - matchingIdentifiers[theId] = true -- make sure we remember the identifier for later - PrintDebugMessage("IDENTIFIER MATCH! "..identifier.." Required: "..matchingIdentifierCount.."/"..minimumMatchingIdentifierCount, 3) - local notBannedIds = checkForChangedIdentifiers(numIds, blacklisted.identifiers) - if matchingIdentifierCount >= minimumMatchingIdentifierCount then - if #notBannedIds > 0 then - local newBanData = blacklisted - newBanData.identifiers = mergeTables(blacklisted.identifiers, notBannedIds) -- add newly found identifiers to the existing ban - updateBan(blacklisted.banid,newBanData) -- send it off! - end - PrintDebugMessage("Connection of "..getName(player).." Declined, Banned for "..blacklist[bi].reason..", Ban ID: "..blacklist[bi].banid.."\n", 3) - deferrals.done(string.format( GetLocalisedText("bannedjoin"), blacklist[bi].reason, formatDateString(blacklist[bi].expire), blacklist[bi].banid)) - return - end - end - end - end - end - - if GetConvar("ea_enableAllowlist", "false") == "true" then - deferrals.update(GetLocalisedText("checkingallowlist")) - local allowlistAttempts = 0 - local allowlisted = false - repeat - allowlisted = DoesPlayerHavePermission(player, "player.allowlist") - allowlistAttempts = allowlistAttempts+1 - Wait(100) - until (allowlistAttempts >= 15 or allowlisted == true) - - if DoesPlayerHavePermission(player, "player.allowlist") then - deferrals.done() - else - deferrals.done(GetLocalisedText("allowlist")) - return - end - else - deferrals.done() - end - - end) -end) - -curVersion, isMaster = GetVersion() -local resourceName = "EasyAdmin ("..GetCurrentResourceName()..")" -function checkVersion() - local remoteVersion,remoteURL = getLatestVersion() - - if GetResourceKvpString('currentVersion') ~= curVersion then - local legacyFiles = { - '__resource.lua', - 'version.json', - 'admin_server.lua', - 'admin_client.lua', - 'gui_c.lua', - 'util_shared.lua', - 'yarn.lock', - '.yarn.installed', - 'server/bot/notifications.js' - } - - for i,file in pairs(legacyFiles) do - local fileExists = LoadResourceFile(GetCurrentResourceName(), file) - if fileExists then - os.remove(GetResourcePath(GetCurrentResourceName()).."/"..file) - PrintDebugMessage("Found legacy file "..file.." in EasyAdmin Folder and attempted deletion.", 2) - end - end - - PrintDebugMessage('EasyAdmin has been updated, or just been installed for the first time, please restart EasyAdmin to ensure smooth operation.', 1) - - SetResourceKvpNoSync('currentVersion', curVersion) - end - - if isMaster then - PrintDebugMessage("You are using an unstable version of EasyAdmin, if this was not your intention, please download the latest stable version from "..remoteURL, 1) - end - if curVersion ~= remoteVersion and tonumber(curVersion) < tonumber(remoteVersion) then - print("\n--------------------------------------------------------------------------") - print("\n"..resourceName.." is outdated.\nNewest Version: "..remoteVersion.."\nYour Version: "..curVersion.."\nPlease update it from "..remoteURL) - print("\n--------------------------------------------------------------------------") - updateAvailable = remoteVersion - elseif tonumber(curVersion) > tonumber(remoteVersion) then - PrintDebugMessage("Your version of "..resourceName.." seems to be higher than the current stable version.", 2) - end - - if GetResourceState("screenshot-basic") == "missing" then - PrintDebugMessage("screenshot-basic is not installed, screenshots unavailable", 3) - else - StartResource("screenshot-basic") - screenshots = true - end - - local onesync = GetConvar("onesync", "off") - if (onesync ~= "off" and onesync ~= "legacy") then - PrintDebugMessage("Onesync is Infinity", 3) - infinity = true - end - - if GetConvar("ea_defaultKey", "none") == "none" and RedM then - PrintDebugMessage("ea_defaultKey is not defined, EasyAdmin can only be opened using the /easyadmin command, to define a key:\nhttps://easyadmin.readthedocs.io/en/latest", 1) - end - - readAcePermissions() -end - -Citizen.CreateThread(function() - repeat - Wait(1000) - until updateBlacklist - while true do - updateBlacklist() - Wait(300000) - end -end) - --- DO NOT TOUCH THESE --- DO NOT TOUCH THESE --- DO NOT TOUCH THESE --- DO NOT TOUCH THESE -MutedPlayers = {} -- DO NOT TOUCH THIS -OnlineAdmins = {} -- DO NOT TOUCH THIS -ChatReminders = {} -- DO NOT TOUCH THIS -MessageShortcuts = {} -- DO NOT TOUCH THIS -WarnedPlayers = {} -- DO NOT TOUCH THIS -reports = {} -- DO NOT TOUCH THIS -FrozenPlayers = {} -- DO NOT TOUCH THIS --- DO NOT TOUCH THESE --- DO NOT TOUCH THESE --- DO NOT TOUCH THESE --- DO NOT TOUCH THESE \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/server/backups.lua b/server-data/resources/[esx]/EasyAdmin/server/backups.lua deleted file mode 100644 index 0e3ab8695..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/backups.lua +++ /dev/null @@ -1,134 +0,0 @@ ------------------------------------- ------------------------------------- ----- DONT TOUCH ANY OF THIS IF YOU DON'T KNOW WHAT YOU ARE DOING ----- THESE ARE **NOT** CONFIG VALUES, USE THE CONVARS IF YOU WANT TO CHANGE SOMETHING ----- ----- ----- If you are a developer and want to change something, consider writing a plugin instead: ----- https://easyadmin.readthedocs.io/en/latest/plugins/ ----- ------------------------------------- ------------------------------------- - -Citizen.CreateThread(function() - backupInfos = LoadResourceFile(GetCurrentResourceName(), "backups/_backups.json") - - while true do - repeat - Wait(5000) - until blacklist - if backupInfos == nil then - lastBackupTime = 0 - else - backupData = json.decode(backupInfos) - lastBackupTime = backupData.lastBackup - end - if (GetConvarInt("ea_backupFrequency", 72) ~= 0) and (lastBackupTime+(GetConvarInt("ea_backupFrequency", 72)*3600) < os.time()) then - createBackup() - end - Wait(120000) - end -end) - - -function loadBackupName(name) - local backup = LoadResourceFile(GetCurrentResourceName(), "backups/"..name) - if backup then - local backupJson = json.decode(backup) - if backupJson then - PrintDebugMessage("Loading Backup..") - for i,ban in pairs(blacklist) do - UnbanId(ban.banid) - PrintDebugMessage("removing ban "..ban.banid, 4) - Wait(50) - end - - for i,ban in pairs(backupJson) do - addBan(ban) - PrintDebugMessage("adding ban "..ban.banid, 4) - TriggerEvent("ea_data:addBan", ban) - Wait(50) - end - local saved = SaveResourceFile(GetCurrentResourceName(), "banlist.json", json.encode(blacklist, {indent = true}), -1) - if not saved then - PrintDebugMessage("^1Saving banlist.json failed! Please check if EasyAdmin has Permission to write in its own folder!^7", 1) - end - updateBlacklist() - PrintDebugMessage("Backup should be loaded!") - else - PrintDebugMessage("^1EasyAdmin:^7 Backup Could not be loaded, in most cases this comes from there being a formatting error, please use a JSON Validator on the file and fix the errors!") - end - - else - PrintDebugMessage("^1EasyAdmin:^7 Backup Name Invalid or missing from Backups.") - end -end - - -function createBackup() - local backupTime = os.time() - local backupDate = os.date("%H_%M_%d_%m_%Y") - local backupName = "banlist_"..backupDate..".json" - local resourceName = GetCurrentResourceName() - PrintDebugMessage("Creating Banlist Backup to "..backupName, 3) - - local saved = SaveResourceFile(resourceName, "backups/"..backupName, json.encode(blacklist, {indent = true}), -1) - - if not saved then - PrintDebugMessage("^1Saving banlist backup failed! Please check if EasyAdmin has Permission to write in the backups folder!^7", 1) - end - - backupInfos = LoadResourceFile(resourceName, "backups/_backups.json") - if backupInfos then - backupData = json.decode(backupInfos) - table.insert(backupData.backups, {id = getNewBackupid(backupData), backupFile = backupName, backupTimestamp = backupTime, backupDate = backupDate}) - - - if #backupData.backups > GetConvarInt("ea_maxBackupCount", 10) then - deleteBackup(backupData,1) - end - backupData.lastBackup = backupTime - SaveResourceFile(resourceName, "backups/_backups.json", json.encode(backupData, {indent = true})) - - else - local backupData = {lastBackup = backupTime, backups = {}} - table.insert(backupData.backups, {id = getNewBackupid(backupData), backupFile = backupName, backupTimestamp = backupTime, backupDate = backupDate}) - SaveResourceFile(resourceName, "backups/_backups.json", json.encode(backupData, {indent = true})) - end - - return id,timestamp -end - -function deleteBackup(backupData,id) - local expiredBackup = backupData.backups[id] - table.remove(backupData.backups, id) - - local backupFileName = expiredBackup.backupFile - - local fullResourcePath = GetResourcePath(GetCurrentResourceName()) - os.remove(fullResourcePath.."/backups/"..backupFileName) - PrintDebugMessage("Removed Backup "..backupFileName, 3) - -end - -function getNewBackupid(backupData) - if backupData then - local lastBackup = backupData.lastbackup - local backups = backupData.backups - return #backups+1 - else - return 0 - end -end - -RegisterCommand("ea_createBackup", function(source, args, rawCommand) - if DoesPlayerHavePermission(source, "server") then - createBackup() - end -end, false) - -RegisterCommand("ea_loadBackup", function(source,args,rawCommand) - if DoesPlayerHavePermission(source, "server") and args[1] then - loadBackupName(args[1]) - end -end,false) \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/server/banlist.lua b/server-data/resources/[esx]/EasyAdmin/server/banlist.lua deleted file mode 100644 index f8f0df73e..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/banlist.lua +++ /dev/null @@ -1,500 +0,0 @@ ------------------------------------- ------------------------------------- ----- DONT TOUCH ANY OF THIS IF YOU DON'T KNOW WHAT YOU ARE DOING ----- THESE ARE **NOT** CONFIG VALUES, USE THE CONVARS IF YOU WANT TO CHANGE SOMETHING ----- ----- ----- If you are a developer and want to change something, consider writing a plugin instead: ----- https://easyadmin.readthedocs.io/en/latest/plugins/ ----- ------------------------------------- ------------------------------------- - -blacklist = {} - -RegisterServerEvent("EasyAdmin:banPlayer", function(playerId,reason,expires) - if playerId ~= nil then - if (DoesPlayerHavePermission(source, "player.ban.temporary") or DoesPlayerHavePermission(source, "player.ban.permanent")) and CachedPlayers[playerId] and not CachedPlayers[playerId].immune then - local bannedIdentifiers = CachedPlayers[playerId].identifiers or getAllPlayerIdentifiers(playerId) - local username = CachedPlayers[playerId].name or getName(playerId, true) - if expires and expires < os.time() then - expires = os.time()+expires - elseif not expires then - expires = 10444633200 - end - if expires >= 10444633200 and not DoesPlayerHavePermission(source, "player.ban.permanent") then - return false - end - - reason = formatShortcuts(reason).. string.format(GetLocalisedText("reasonadd"), CachedPlayers[playerId].name, getName(source) ) - local ban = {banid = GetFreshBanId(), name = username,identifiers = bannedIdentifiers, banner = getName(source, true), reason = reason, expire = expires, expireString = formatDateString(expires) } - updateBlacklist( ban ) - PrintDebugMessage("Player "..getName(source,true).." banned player "..CachedPlayers[playerId].name.." for "..reason, 3) - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminbannedplayer"), getName(source, false, true), CachedPlayers[playerId].name, reason, formatDateString( expires ), tostring(ban.banid) ), "ban", 16711680) - DropPlayer(playerId, string.format(GetLocalisedText("banned"), reason, formatDateString( expires ) ) ) - elseif CachedPlayers[playerId].immune then - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("adminimmune")) - end - end -end) - -RegisterServerEvent("EasyAdmin:offlinebanPlayer", function(playerId,reason,expires) - if playerId ~= nil and not CachedPlayers[playerId].immune then - if (DoesPlayerHavePermission(source, "player.ban.temporary") or DoesPlayerHavePermission(source, "player.ban.permanent")) and not CachedPlayers[playerId].immune then - local bannedIdentifiers = CachedPlayers[playerId].identifiers or getAllPlayerIdentifiers(playerId) - local username = CachedPlayers[playerId].name or getName(playerId, true) - if expires and expires < os.time() then - expires = os.time()+expires - elseif not expires then - expires = 10444633200 - end - if expires >= 10444633200 and not DoesPlayerHavePermission(source, "player.ban.permanent") then - return false - end - - reason = formatShortcuts(reason).. string.format(GetLocalisedText("reasonadd"), CachedPlayers[playerId].name, getName(source) ) - local ban = {banid = GetFreshBanId(), name = username,identifiers = bannedIdentifiers, banner = getName(source), reason = reason, expire = expires } - updateBlacklist( ban ) - PrintDebugMessage("Player "..getName(source,true).." offline banned player "..CachedPlayers[playerId].name.." for "..reason, 3) - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminofflinebannedplayer"), getName(source, false, true), CachedPlayers[playerId].name, reason, formatDateString( expires ) ), "ban", 16711680) - end - elseif CachedPlayers[playerId].immune then - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("adminimmune")) - end -end) - -AddEventHandler('banCheater', function(playerId,reason) - Citizen.Trace("^1EasyAdmin^7: the banCheater event is ^1deprecated^7 and has been removed! Please adjust your ^3"..GetInvokingResource().."^7 Resource to use EasyAdmin:addBan instead.") -end) - - -function addBanExport(playerId,reason,expires,banner) - local bannedIdentifiers = {} - local bannedUsername = "Unknown" - if type(playerId) == "table" then -- if playerId is a table of identifiers - offline = true - bannedIdentifiers = playerId - elseif CachedPlayers[playerId] then - if CachedPlayers[playerId].dropped then - offline = true - end - if CachedPlayers[playerId].immune then - return false - end - bannedIdentifiers = CachedPlayers[playerId].identifiers - bannedUsername = CachedPlayers[playerId].name or getName(playerId, true) - else - PrintDebugMessage("Couldn't find any Infos about Player "..playerId..", no ban issued.", 1) - return false - end - - - if expires and expires < os.time() then - expires = os.time()+expires - elseif not expires then - expires = 10444633200 - end - reason = formatShortcuts(reason).. string.format(GetLocalisedText("reasonadd"), getName(tostring(playerId) or "?"), banner or "Unknown" ) - local ban = {banid = GetFreshBanId(), name = bannedUsername,identifiers = bannedIdentifiers, banner = banner or "Unknown", reason = reason, expire = expires, expireString = formatDateString(expires) } - updateBlacklist( ban ) - - if source then - PrintDebugMessage("Player "..getName(source,true).." added ban "..reason, 3) - end - - - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminbannedplayer"), banner or "Unknown", getName(tostring(playerId) or "?", false, true), reason, formatDateString( expires ), tostring(ban.banid) ), "ban", 16711680) - if not offline then - DropPlayer(playerId, string.format(GetLocalisedText("banned"), reason, formatDateString( expires ) ) ) - end - return ban -end -exports('addBan', addBanExport) -AddEventHandler("EasyAdmin:addBan", addBanExport) - -RegisterServerEvent("EasyAdmin:updateBanlist", function(playerId) - local src = source - if DoesPlayerHavePermission(source, "player.ban.view") then - updateBlacklist(false,true) - Citizen.Wait(300) - TriggerLatentClientEvent("EasyAdmin:fillBanlist", src, 100000, blacklist) - PrintDebugMessage("Banlist Refreshed by "..getName(src,true), 3) - end -end) - -RegisterServerEvent("EasyAdmin:requestBanlist", function() - local src = source - if DoesPlayerHavePermission(source, "player.ban.view") then - TriggerLatentClientEvent("EasyAdmin:fillBanlist", src, 100000, blacklist) - PrintDebugMessage("Banlist Requested by "..getName(src,true), 3) - end -end) - -RegisterCommand("unban", function(source, args, rawCommand) - if args[1] and DoesPlayerHavePermission(source, "player.ban.remove") then - PrintDebugMessage("Player "..getName(source,true).." Unbanned "..args[1], 3) - if tonumber(args[1]) then - UnbanId(tonumber(args[1])) - else - UnbanIdentifier(args[1]) - end - if (source ~= 0) then - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("done")) - else - Citizen.Trace(GetLocalisedText("done")) - end - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminunbannedplayer"), getName(source, false, true), args[1], "Unbanned via Command"), "ban", 16711680) - end -end, false) - - -RegisterServerEvent("EasyAdmin:editBan", function(ban) - if DoesPlayerHavePermission(source, "player.ban.edit") then - updateBan(ban.banid,ban) - -- TODO Webhook - end -end) - -function unbanPlayer(banId) - local thisBan = nil - for i,ban in ipairs(blacklist) do - if ban.banid == banId then - thisBan = ban - break - end - end - if thisBan == nil then - return false - end - UnbanId(banId) - return true -end -exports('unbanPlayer', unbanPlayer) - - -function fetchBan(banId) - for i,ban in ipairs(blacklist) do - if ban.banid == banId then - return ban - end - end - return false -end -exports('fetchBan', fetchBan) - -RegisterServerEvent("EasyAdmin:unbanPlayer", function(banId) - if DoesPlayerHavePermission(source, "player.ban.remove") then - local thisBan = fetchBan(banId) - local ret = unbanPlayer(banId) - if ret then - PrintDebugMessage("Player "..getName(source,true).." unbanned "..banId, 3) - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminunbannedplayer"), getName(source, false, true), banId, thisBan.reason), "ban", 16711680) - end - end -end) - -function GetFreshBanId() - if blacklist[#blacklist] then - return blacklist[#blacklist].banid+1 - else - return 1 - end -end -exports('GetFreshBanId', GetFreshBanId) - - -RegisterCommand("convertbanlist", function(source, args, rawCommand) - if GetConvar("ea_custombanlist", "false") == "true" then - local content = LoadResourceFile(GetCurrentResourceName(), "banlist.json") - local ob = json.decode(content) - for i,theBan in ipairs(ob) do - TriggerEvent("ea_data:addBan", theBan) - print("processed ban: "..i.."\n") - end - content=nil - else - print("Custom Banlist is not enabled, converting back to json.") - TriggerEvent('ea_data:retrieveBanlist', function(banlist) - blacklist = banlist - for i,theBan in ipairs(blacklist) do - if not theBan.identifiers then theBan.identifiers = {} end - if theBan.steam then - table.insert(theBan.identifiers, theBan.steam) - theBan.steam=nil - end - if theBan.identifier then - table.insert(theBan.identifiers, theBan.identifier) - theBan.identifier=nil - end - if theBan.discord then - table.insert(theBan.identifiers, theBan.discord) - theBan.discord=nil - end - end - local saved = SaveResourceFile(GetCurrentResourceName(), "banlist.json", json.encode(blacklist, {indent = true}), -1) - if not saved then - PrintDebugMessage("^1Saving banlist.json failed! Please check if EasyAdmin has Permission to write in its own folder!^7", 1) - end - end) - end -end, true) - -function updateBan(id,newData) - if id and newData and newData.identifiers and newData.banid and newData.reason and newData.expire then - for i, ban in pairs(blacklist) do - if ban.banid == newData.banid then - blacklist[i] = newData - local saved = SaveResourceFile(GetCurrentResourceName(), "banlist.json", json.encode(blacklist, {indent = true}), -1) - if not saved then - PrintDebugMessage("^1Saving banlist.json failed! Please check if EasyAdmin has Permission to write in its own folder!^7", 1) - end - if GetConvar("ea_custombanlist", "false") == "true" then - TriggerEvent("ea_data:updateBan", newData) - end - break - end - end - end -end - - -function addBan(data) - if data then - table.insert(blacklist, data) - end -end - - - -function updateBlacklist(data,remove, forceChange) - local change = (forceChange or false) --mark if file was changed to save up on disk writes. - if GetConvar("ea_custombanlist", "false") == "true" then - PrintDebugMessage("You are using a Custom Banlist System, this is ^3not currently supported^7 and WILL cause issues! Only use this if you know what you are doing, otherwise, disable ea_custombanlist.", 1) - if data and not remove then - addBan(data) - TriggerEvent("ea_data:addBan", data) - - elseif data and remove then - UnbanId(data.banid) - elseif not data then - TriggerEvent('ea_data:retrieveBanlist', function(banlist) - blacklist = banlist - PrintDebugMessage("updated banlist custom banlist", 4) - for i,theBan in ipairs(blacklist) do - if theBan.expire < os.time() then - table.remove(blacklist,i) - PrintDebugMessage("removing old ban custom banlist", 4) - TriggerEvent("ea_data:removeBan", theBan) - end - end - end) - end - return - end - - local content = LoadResourceFile(GetCurrentResourceName(), "banlist.json") - if not content then - PrintDebugMessage("banlist.json file was missing, we created a new one.", 2) - local saved = SaveResourceFile(GetCurrentResourceName(), "banlist.json", json.encode({}), -1) - if not saved then - PrintDebugMessage("^1Saving banlist.json failed! Please check if EasyAdmin has Permission to write in its own folder!^7", 1) - end - content = json.encode({}) - end - blacklist = json.decode(content) - - if not blacklist then - PrintDebugMessage("^1-^2-^3-^4-^5-^6-^8-^9-^1-^2-^3-^4-^5-^6-^8-^9-^1-^2-^3-^3!^1FATAL ERROR^3!^3-^2-^1-^9-^8-^6-^5-^4-^3-^2-^1-^9-^8-^6-^5-^4-^3-^2-^7\n") - PrintDebugMessage("^1Failed^7 to load Banlist!\n") - PrintDebugMessage("Please check your banlist file for errors, ^1Bans *will not* work!^7\n") - PrintDebugMessage("^1-^2-^3-^4-^5-^6-^8-^9-^1-^2-^3-^4-^5-^6-^8-^9-^1-^2-^3-^3!^1FATAL ERROR^3!^3-^2-^1-^9-^8-^6-^5-^4-^3-^2-^1-^9-^8-^6-^5-^4-^3-^2-^7\n") - return - end - - upgraded = performBanlistUpgrades(blacklist) - if upgraded then change = true end - - if data and not remove then - addBan(data) - PrintDebugMessage("Added the following data to banlist:\n"..table_to_string(data), 4) - change=true - elseif not data then - for i,theBan in ipairs(blacklist) do - theBan.id = nil - if not theBan.banid then - if i==1 then - theBan.banid = 1 - else - theBan.banid = blacklist[i].banid or i - end - PrintDebugMessage("Ban "..theBan.banid.." did not have an ID, assigned one.", 4) - change=true - end - if not theBan.expire then - PrintDebugMessage("Ban "..theBan.banid.." did not have an expiry time, removing..", 4) - table.remove(blacklist,i) - change=true - elseif not theBan.identifiers then -- make sure 1 identifier is given, otherwise its a broken ban - PrintDebugMessage("Ban "..theBan.banid.." did not have any identifiers, removing..", 4) - table.remove(blacklist,i) - change=true - elseif not theBan.identifiers[1] then - PrintDebugMessage("Ban "..theBan.banid.." did not have one identifier, removing..", 4) - table.remove(blacklist,i) - change=true - elseif theBan.expire < os.time() then - PrintDebugMessage("Ban "..theBan.banid.." expired, removing..", 4) - table.remove(blacklist,i) - change=true - elseif theBan.expire == 1924300800 then - PrintDebugMessage("Ban "..theBan.banid.." had legacy expiry time, we fixed it", 4) - blacklist[i].expire = 10444633200 - change=true - end - end - end - if data and remove then - PrintDebugMessage("Removed the following data from banlist:\n"..table_to_string(data), 4) - UnbanId(data.banid) - change = true - end - if change then - PrintDebugMessage("Banlist changed, saving..", 4) - local saved = SaveResourceFile(GetCurrentResourceName(), "banlist.json", json.encode(blacklist, {indent = true}), -1) - if not saved then - PrintDebugMessage("^1Saving banlist.json failed! Please check if EasyAdmin has Permission to write in its own folder!^7", 1) - end - end - PrintDebugMessage("Completed Banlist Update.", 4) -end - -function BanIdentifier(identifier,reason) - updateBlacklist( {identifiers = {identifier} , banner = "Unknown", reason = reason, expire = 10444633200} ) -end - -function BanIdentifiers(identifier,reason) - updateBlacklist( {identifiers = identifier , banner = "Unknown", reason = reason, expire = 10444633200} ) -end - -function UnbanIdentifier(identifier) - if identifier then - for i,ban in pairs(blacklist) do - for index,id in pairs(ban.identifiers) do - if identifier == id then - table.remove(blacklist,i) - local saved = SaveResourceFile(GetCurrentResourceName(), "banlist.json", json.encode(blacklist, {indent = true}), -1) - if not saved then - PrintDebugMessage("^1Saving banlist.json failed! Please check if EasyAdmin has Permission to write in its own folder!^7", 1) - end - - if GetConvar("ea_custombanlist", "false") == "true" then - TriggerEvent("ea_data:removeBan", ban) - end - PrintDebugMessage("removed ban as per unbanidentifier func", 4) - return - end - end - end - end -end - -function UnbanId(id) - for i,ban in pairs(blacklist) do - if ban.banid == id then - table.remove(blacklist,i) - local saved = SaveResourceFile(GetCurrentResourceName(), "banlist.json", json.encode(blacklist, {indent = true}), -1) - if not saved then - PrintDebugMessage("^1Saving banlist.json failed! Please check if EasyAdmin has Permission to write in its own folder!^7", 1) - end - - if GetConvar("ea_custombanlist", "false") == "true" then - TriggerEvent("ea_data:removeBan", ban) - end - end - end -end - -function performBanlistUpgrades() - local upgraded = false - - local takenIds = {} - for i,b in pairs(blacklist) do - if takenIds[b.banid] then - local freshId = GetFreshBanId() - PrintDebugMessage("ID "..b.banid.." was assigned twice, reassigned to "..freshId, 4) - blacklist[i].banid = freshId - upgraded = true - end - takenIds[b.banid] = true - end - takenIds=nil - - for i,ban in pairs(blacklist) do - if type(i) == "string" then - PrintDebugMessage("Ban "..ban.banid.." had a string as indice, fixed it.", 4) - blacklist[i] = nil - table.insert(blacklist,ban) - upgraded = true - end - end - for i,ban in ipairs(blacklist) do - if ban.identifiers then - for k, identifier in pairs(ban.identifiers) do - if identifier == "" then - PrintDebugMessage("Ban "..ban.banid.." had an empty identifier, removed it.", 4) - ban.identifiers[k] = nil - upgraded = true - end - end - end - if not ban.expireString then - upgraded = true - ban.expireString = formatDateString(ban.expire) - end - end - if blacklist[1] and (blacklist[1].identifier or blacklist[1].steam or blacklist[1].discord) then - Citizen.Trace("Upgrading Banlist...\n", 4) - for i,ban in ipairs(blacklist) do - if not ban.identifiers then - ban.identifiers = {} - PrintDebugMessage("Ban "..ban.banid.." had no identifiers, added one.", 4) - upgraded=true - end - if ban.identifier then - table.insert(ban.identifiers, ban.identifier) - PrintDebugMessage("Ban "..ban.banid.." had identifier, converted to identifiers table", 4) - ban.identifier = nil - upgraded=true - end - if ban.steam then - table.insert(ban.identifiers, ban.steam) - PrintDebugMessage("Ban "..ban.banid.." had seperate steam identifier, converted to identifiers table", 4) - ban.steam = nil - upgraded=true - end - if ban.discord and ban.discord ~= "" then - table.insert(ban.identifiers, ban.discord) - PrintDebugMessage("Ban "..ban.banid.." had seperate discord identifier, converted to identifiers table", 4) - ban.discord = nil - upgraded=true - end - end - Citizen.Trace("Banlist Upgraded.\n", 4) - end - return upgraded -end - - - -function IsIdentifierBanned(theIdentifier) - local identifierfound = false - for index,value in ipairs(blacklist) do - for i,identifier in ipairs(value.identifiers) do - if theIdentifier == identifier then - identifierfound = true - end - end - end - return identifierfound -end -exports('IsIdentifierBanned', IsIdentifierBanned) \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/bot.js b/server-data/resources/[esx]/EasyAdmin/server/bot/bot.js deleted file mode 100644 index 918d866a2..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/bot.js +++ /dev/null @@ -1,116 +0,0 @@ -/*eslint no-global-assign: "off", no-unused-vars: "off"*/ -process.on('uncaughtException', function(err) { - console.log('Caught exception: ', err.stack) -}) -process.on('unhandledRejection', function(err) { - console.log('Caught exception: ', err.stack) -}) - -AsciiTable = require('ascii-table') -sprintf = require('sprintf-js').sprintf -juration = require('juration') -const prettyMilliseconds = require('pretty-ms') -const { Client, EmbedBuilder, Collection, Intents, Partials, ButtonStyle, ActionRowBuilder, ButtonBuilder, SelectMenuBuilder, Guild, Util, ModalBuilder, TextInputBuilder, GatewayIntentBits, InteractionType, TextInputStyle } = require('discord.js') - -const { SlashCommandBuilder } = require('@discordjs/builders') - - -client = new Client({ - partials: [Partials.GuildMember, Partials.User, Partials.Message, Partials.Channel, Partials.Reaction], - intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMembers, GatewayIntentBits.MessageContent] -}) -client.commands = new Collection() - - -async function RegisterClientCommands(clientId) { - const { REST } = require('@discordjs/rest') - const { Routes } = require('discord-api-types/v10') - const fs = require('fs') - - const commands = [] - const commandFiles = fs.readdirSync(`${resourcePath}/server/bot/commands`).filter(file => file.endsWith('.js')) - - - for (const file of commandFiles) { - const command = require(`${resourcePath}/server/bot/commands/${file}`) - commands.push(command.data.toJSON()) - client.commands.set(command.data.name, command) - } - - const rest = new REST({ version: '10' }).setToken(GetConvar('ea_botToken', '')) - - // compat: remove existing commands for homeguild - if (guild != '') { - rest.put(Routes.applicationGuildCommands(clientId, guild), { body: {} }) - } - await rest.put( - Routes.applicationCommands(clientId), - { body: commands }, - ) - - client.on('interactionCreate', async interaction => { - if (interaction.type != InteractionType.ApplicationCommand) return - - const command = client.commands.get(interaction.commandName) - - if (!command) return - - if (!(await DoesGuildMemberHavePermission(interaction.member, `bot.${command.data.name}`) == true) && !(command.data.name == 'refreshperms')) { - await refreshRolesForMember(interaction.member) - if (!(await DoesGuildMemberHavePermission(interaction.member, `bot.${command.data.name}`) == true)) { - await interaction.reply({ content: 'You don\'t have permission to run this command!', ephemeral: true }) - return false - } - } - try { - await command.execute(interaction, exports) // we need to pass exports here, otherwise we won't be able to access them inside the command - } catch (error) { - console.error(error) - var errorContent = { content: `There was an error while executing this command, please report the following stack trace here: \`\`\`js\n${error.stack}\`\`\``, ephemeral: true } - if (interaction.replied) { - interaction.followUp(errorContent) - - } else { - interaction.reply(errorContent) - } - } - }) -} - -if (GetConvar('ea_botToken', '') != '') { - - client.on('ready', async () => { - console.log(`Logged in as ${client.user.tag}!`) - client.user.setPresence({ activities: [{ name: `${GetConvar('sv_projectName', GetConvar('sv_hostname', 'default FXServer'))}`, type: 'WATCHING' }], status: 'online' }) - userID = client.user.id - resourcePath = GetResourcePath(GetCurrentResourceName()) // absolute resource path, needed for FS - guild = GetConvar('ea_botGuild', '') - - EasyAdmin = GetCurrentResourceName() // fetch our Resource name and claim we're called EasyAdmin, this just makes exports easier. - - currentVersion = await exports[EasyAdmin].GetVersion()[0] - latestVersionInfo = await exports[EasyAdmin].getLatestVersion() - - - RegisterClientCommands(client.user.id) - var startupMessage = `**EasyAdmin ${currentVersion}** has started.` - if (currentVersion != latestVersionInfo[0]) { - startupMessage+=`\nVersion ${latestVersionInfo[0]} is Available!\n Download it from ${latestVersionInfo[1]}` - } - LogDiscordMessage(startupMessage, 'startup') - }) - - client.on('debug', function(info){ - if (GetConvarInt('ea_logLevel', 1) >= 4 ) { - console.log(`${info}`) - } - }) - on('debug', function(info){ - if (GetConvarInt('ea_logLevel', 1) >= 4 ) { - console.log(`${info}`) - } - }) - - client.login(GetConvar('ea_botToken', '')) -} - diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/chat_bridge.js b/server-data/resources/[esx]/EasyAdmin/server/bot/chat_bridge.js deleted file mode 100644 index acea07b96..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/chat_bridge.js +++ /dev/null @@ -1,84 +0,0 @@ - -try { - - knownAvatars = {} - - - exports['chat'].registerMessageHook(async function(source, outMessage) { - - if (GetConvar('ea_botChatBridge', '') == '') { return } - - const user = await exports[EasyAdmin].getCachedPlayer(source) - - if (!user) { - return // chat message wasnt sent by a user, we don't care. - } - - - var userInfo = {name: outMessage.args[0]} - - if (knownAvatars[source] == undefined) { - var fivemAccount = false - for (let identifier of user.identifiers) { - if (identifier.search('fivem:') != -1) { - fivemAccount = identifier.substring(identifier.indexOf(':') + 1) - } - } - - if (fivemAccount) { - var response = await exports[EasyAdmin].HTTPRequest(`https://policy-live.fivem.net/api/getUserInfo/${fivemAccount}`) - try { - response = JSON.parse(response) - if (response.avatar_template) { - var avatarURL = response.avatar_template.replace('{size}', '96') - if (avatarURL.indexOf('http') == -1) { - avatarURL = `https://forum.cfx.re${avatarURL}` - } - userInfo.iconURL = avatarURL - knownAvatars[source] = avatarURL // we dont need to resolve the avatar every time. - } else { - knownAvatars[source] = false // avatar missing. - } - } catch { - knownAvatars[source] = false // something broke while trying to get discourse avatar, dont try again. - - } - } else { - knownAvatars[source] = false // no fivem identifier - } - } else { - userInfo.iconURL = knownAvatars[source] - } - if (knownAvatars[source] == false) { - userInfo.iconURL = undefined // dont send anything to discord, assume something went wrong - } - - var embed = await prepareGenericEmbed(undefined, undefined, 55555, undefined, undefined, userInfo, outMessage.args[1], false) - client.channels.cache.get(GetConvar('ea_botChatBridge', '')).send({ embeds: [embed] }) - }) - - -} catch(error) { - if (GetConvar('ea_botChatBridge', '') != '') { - console.error('Registering Chat Bridge failed, you will need to update your chat resource from https://github.com/citizenfx/cfx-server-data to use it.') - } -} - -client.on('messageCreate', async msg => { - if (GetConvar('ea_botChatBridge', '') == '') { return } - if (!msg.member || msg.author.bot) { return } // message-sender is a webhook - if(msg.author.id == userID) { - return - } - if(!msg.channel) { return } - if (msg.channel.id == GetConvar('ea_botChatBridge', '')) { - exports['chat'].addMessage(-1, { args: [msg.member.user.tag, msg.cleanContent]}) - } - -}) - -on('playerDropped', () => { - if (GetConvar('ea_botChatBridge', '') == '') { return } - knownAvatars[global.source] = undefined -}) - diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/add_ace.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/add_ace.js deleted file mode 100644 index 93e0c4ad8..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/add_ace.js +++ /dev/null @@ -1,53 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('add_ace') - .setDescription('Adds a permission to a group, saves into easyadmin_permissions.cfg'), - async execute(interaction, exports) { - var timestamp = Date.now() - - const modal = new ModalBuilder() - .setCustomId('addaceModal'+timestamp) - .setTitle('Add ACE') - - const groupName = new TextInputBuilder() - .setCustomId('groupName') - .setLabel('Group Name') - .setStyle(TextInputStyle.Short) - .setRequired(true) - .setMaxLength(120) - .setPlaceholder('group.admin') - - const permission = new TextInputBuilder() - .setCustomId('permission') - // The label is the prompt the user sees for this input - .setLabel('Permission') - // Short means only a single line of text - .setStyle(TextInputStyle.Short) - .setRequired(true) - .setMaxLength(120) - .setPlaceholder('easyadmin.bot.playerlist') - - const firstActionRow = new ActionRowBuilder().addComponents(groupName) - const secondActionRow = new ActionRowBuilder().addComponents(permission) - - modal.addComponents(firstActionRow, secondActionRow) - - interaction.showModal(modal) - - const filter = (interaction) => interaction.customId === 'addaceModal'+timestamp - interaction.awaitModalSubmit({ filter, time: 120000 }) - .then(async (interaction) => { - var group = interaction.fields.getTextInputValue('groupName') - var permission = interaction.fields.getTextInputValue('permission') - var query = `add_ace ${group} ${permission} allow` - exports[EasyAdmin].AddToFile('easyadmin_permissions.cfg', query) - - ExecuteCommand(query) - - interaction.reply(`\`${query}\` has been executed and saved.`) - - }).catch(async () => {}) // silently catch error, happens if the form times out - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/add_group.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/add_group.js deleted file mode 100644 index 7ebbb9631..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/add_group.js +++ /dev/null @@ -1,27 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('add_group') - .setDescription('Adds a group to a User (ACE), saves into easyadmin_permissions.cfg') - .addUserOption(option => - option.setName('user') - .setDescription('The user') - .setRequired(true)) - .addStringOption(option => - option.setName('group') - .setDescription('the group, for example, group.admin') - .setRequired(true)), - async execute(interaction, exports) { - const user = interaction.options.getUser('user').id - const groupName = interaction.options.getString('group') - - - var query = `add_principal identifier.discord:${user} ${groupName}` - exports[EasyAdmin].AddToFile('easyadmin_permissions.cfg', query) - - ExecuteCommand(query) - - interaction.reply(`\`${query}\` has been executed and saved.`) - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/announce.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/announce.js deleted file mode 100644 index da487f414..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/announce.js +++ /dev/null @@ -1,23 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('announce') - .setDescription('send a announcement to the server') - .addStringOption(option => - option.setName('reason') - .setDescription('Reason Text') - .setRequired(true)), - async execute(interaction, exports) { - var reason = exports[EasyAdmin].formatShortcuts(interaction.options.getString('reason')) - - var ret = await exports[EasyAdmin].announce(reason) - if (ret) { - let embed = await prepareGenericEmbed(`Succesfully sent an announcement \nreason: ${reason}`) - await interaction.reply({embeds: [embed]}) - } else { - let embed = await prepareGenericEmbed('Could not send an annoucement.') - await interaction.reply({embeds: [embed]}) - } - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/ban.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/ban.js deleted file mode 100644 index 98a5c0c01..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/ban.js +++ /dev/null @@ -1,66 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('ban') - .setDescription('bans a User') - .addStringOption(option => - option.setName('user') - .setDescription('Username or ID') - .setRequired(true)) - .addStringOption(option => - option.setName('reason') - .setDescription('Reason Text') - .setRequired(true)) - .addStringOption(option => - option.setName('timeframe') - .setDescription('The timeframe in a human readable format (30 mins, 1 hour, 2 weeks, or permanent)') - .setRequired(true)), - async execute(interaction, exports) { - const userOrId = interaction.options.getString('user') - const reason = exports[EasyAdmin].formatShortcuts(interaction.options.getString('reason')) - const timeframe = exports[EasyAdmin].formatShortcuts(interaction.options.getString('timeframe')) - - const user = await findPlayerFromUserInput(userOrId) - - if (!user || user.dropped) { - interaction.reply({ content: 'Sorry, i couldn\'t find any user with the infos you provided.', ephemeral: true}) - return - } - - var banTime - - try { - if (timeframe.toLowerCase() == 'permanent') { - banTime = 10444633200 - } else { - banTime = await juration.parse(timeframe) - if (banTime > 10444633200) { - banTime = 10444633200 - } - } - } catch (error) { - console.error(error) - interaction.reply({ content: 'Sorry, i couldn\'t understand the timeframe you provided.', ephemeral: true }) - return - } - - - if (banTime < 10444633200 && !await DoesGuildMemberHavePermission(interaction.member, 'player.ban.temporary')) { - interaction.reply({ content: 'Insufficient Permissions, you need `easyadmin.player.ban.temporary`.', ephemeral: true }) - return - } else if (banTime > 10444633200 && !await DoesGuildMemberHavePermission(interaction.member, 'player.ban.permanent')) { - interaction.reply({ content: 'Insufficient Permissions, you need `easyadmin.player.ban.permanent`.', ephemeral: true }) - return - } - - var ban = exports[EasyAdmin].addBan(user.id, reason, banTime, interaction.user.tag) - if (ban) { - let embed = await prepareGenericEmbed(`Successfully banned **${user.name}** for **${reason}** until ${ban.expireString} [#${ban.banid}.`) - await interaction.reply({ embeds: [embed]}) - } else { - let embed = await prepareGenericEmbed(`Failed banning **${user.name}**.`) - await interaction.reply({ embeds: [embed]}) - } - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/baninfo.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/baninfo.js deleted file mode 100644 index cadc431eb..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/baninfo.js +++ /dev/null @@ -1,49 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('baninfo') - .setDescription('Shows details of a ban') - .addIntegerOption(option => - option.setName('banid') - .setDescription('Ban ID') - .setRequired(true)), - async execute(interaction, exports) { - const banId = interaction.options.getInteger('banid') - - var ban = await exports[EasyAdmin].fetchBan(banId) - if (ban) { - let embed = new EmbedBuilder() - .setColor(16777214) - .setTimestamp() - - var discordAccount = false - for (let identifier of ban.identifiers) { - if (identifier.search('discord:') != -1) { - discordAccount = await client.users.fetch(identifier.substring(identifier.indexOf(':') + 1)) - } - } - - embed.addFields([ - { name: 'Ban Info', value: `Ban infos for **#${banId}**`}, - { name: 'Username', value: `\`\`\`${ban.name}\`\`\``, inline: true} - ]) - - if (discordAccount) { - embed.addFields([{ name: 'Discord Account', value: `\`\`\`${discordAccount.tag}\`\`\``, inline: true}]) - embed.setThumbnail(discordAccount.avatarURL()) - } - embed.addFields([ - { name: 'Banned by', value: `\`\`\`${ban.banner}\`\`\``, inline: true}, - { name: 'Reason', value: `\`\`\`\n${ban.reason}\`\`\``, inline: false}, - { name: 'Expires', value: `\`\`\`${ban.expireString}\`\`\``, inline: true} - ]) - - - interaction.reply({ embeds: [embed]}) - } else { - let embed = await prepareGenericEmbed('No ban was found with this ID.') - interaction.reply({ embeds: [embed]}) - } - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/cleanup.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/cleanup.js deleted file mode 100644 index afbb4d046..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/cleanup.js +++ /dev/null @@ -1,31 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('cleanup') - .setDescription('Cleans up area of type') - .addStringOption(option => - option.setName('type') - .setDescription('Type of Entity to clean up.') - .setRequired(true) - .addChoices( - {name:'Vehicles', value:'cars'}, - {name:'Peds', value:'peds'}, - {name:'Props', value:'props'})), - - async execute(interaction, exports) { - const type = interaction.options.getString('type') - - var ret = exports[EasyAdmin].cleanupArea(type) - - if (ret) { - let embed = await prepareGenericEmbed(`Cleaned up **${type}**.`) - - await interaction.reply({ embeds: [embed]}) - } else { - let embed = await prepareGenericEmbed(`Could not cleanup **${type}**.`) - - await interaction.reply({ embeds: [embed]}) - } - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/configure.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/configure.js deleted file mode 100644 index 0e37e11ec..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/configure.js +++ /dev/null @@ -1,122 +0,0 @@ - -async function configForward(interaction, exports) { - var embed = await prepareGenericEmbed('Alright! Now please write the type of log to forward (see for examples)') - - - if (!interaction.replied) { - await interaction.reply({ embeds: [embed]}) - } else { - await interaction.followUp({ embeds: [embed]}) - } - - const filter = m => m.author.id == interaction.member.id && m.channel.id == interaction.channel.id - const collector = interaction.channel.createMessageCollector({ filter, time: 10000, max: 1 }) - - collector.on('collect', async m => { - await m.fetch() - let embed = await prepareGenericEmbed(`Great! Now please tag the channel you want me to log this in (like this: <#${interaction.channel.id}>).`) - - - await interaction.followUp({ embeds: [embed]}) - const filter = m => m.author.id == interaction.member.id && m.channel.id == interaction.channel.id - const collector = interaction.channel.createMessageCollector({ filter, time: 10000, max: 1 }) - - collector.on('collect', async message => { - await message.fetch() - let channel = message.mentions.channels.first().id - - exports[EasyAdmin].RemoveFromFile('easyadmin_permissions.cfg', `ea_addBotLogForwarding ${m.cleanContent}`, true) - - exports[EasyAdmin].AddToFile('easyadmin_permissions.cfg', `ea_addBotLogForwarding ${m.cleanContent} ${channel}`) - - - addBotLogForwarding('', [m.cleanContent, channel]) - interaction.followUp('Done! Result has been saved into `easyadmin_permissions.cfg`.') - }) - - }) -} - - -async function configBridge(interaction, exports) { - var embed = await prepareGenericEmbed(`Alright! Please tag the channel you want me to bridge (like this: <#${interaction.channel.id}>).`) - - - if (!interaction.replied) { - await interaction.reply({ embeds: [embed]}) - } else { - await interaction.followUp({ embeds: [embed]}) - } - - const filter = m => m.author.id == interaction.member.id && m.channel.id == interaction.channel.id - const collector = interaction.channel.createMessageCollector({ filter, time: 10000, max: 1 }) - - collector.on('collect', async m => { - await m.fetch() - let channel = m.mentions.channels.first().id - - exports[EasyAdmin].RemoveFromFile('easyadmin_permissions.cfg', 'set ea_botChatBridge', true) - - exports[EasyAdmin].AddToFile('easyadmin_permissions.cfg', `set ea_botChatBridge ${channel}`) - - SetConvar('ea_botChatBridge', `${channel}`) - - interaction.followUp('Done! Result has been saved into `easyadmin_permissions.cfg`.') - - }) -} - -async function configLiveStatus(interaction, exports) { - var embed = await prepareGenericEmbed(`Alright! Please tag the channel you want me to post the live status in, make sure its empty and that normal people can't write there! (like this: <#${interaction.channel.id}>).`) - - - if (!interaction.replied) { - await interaction.reply({ embeds: [embed]}) - } else { - await interaction.followUp({ embeds: [embed]}) - } - - const filter = m => m.author.id == interaction.member.id && m.channel.id == interaction.channel.id - const collector = interaction.channel.createMessageCollector({ filter, time: 10000, max: 1 }) - - collector.on('collect', async m => { - await m.fetch() - let channel = m.mentions.channels.first().id - - exports[EasyAdmin].RemoveFromFile('easyadmin_permissions.cfg', 'set ea_botStatusChannel', true) - - exports[EasyAdmin].AddToFile('easyadmin_permissions.cfg', `set ea_botStatusChannel ${channel}`) - - SetConvar('ea_botStatusChannel', `${channel}`) - - interaction.followUp('Done! Result has been saved into `easyadmin_permissions.cfg`.') - - }) -} - -module.exports = { - data: new SlashCommandBuilder() - .setName('configure') - .setDescription('Configure various easyadmin features') - .addStringOption(option => - option.setName('setting') - .setDescription('The setting to change') - .setRequired(true) - .addChoices( - {name:'Log Forwarding', value: 'logfwd'}, - {name:'Chat Bridge', value: 'chatbridge'}, - {name:'Live Server Status', value: 'serverstatus'} - )), - async execute(interaction, exports) { - const setting = interaction.options.getString('setting') - - - if (setting == 'logfwd') { - configForward(interaction, exports) - } else if (setting == 'chatbridge') { - configBridge(interaction, exports) - } else if (setting == 'serverstatus') { - configLiveStatus(interaction, exports) - } - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/freeze.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/freeze.js deleted file mode 100644 index 8bed3f5b1..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/freeze.js +++ /dev/null @@ -1,33 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('freeze') - .setDescription('Freezes player') - .addStringOption(option => - option.setName('user') - .setDescription('Username or ID') - .setRequired(true)), - async execute(interaction, exports) { - const userOrId = interaction.options.getString('user') - - const user = await findPlayerFromUserInput(userOrId) - - if (!user || user.dropped) { - interaction.reply({ content: 'Sorry, i couldn\'t find any user with the infos you provided.', ephemeral: true}) - return - } - - var ret = await exports[EasyAdmin].freezePlayer(user.id, true) - - if (ret) { - let embed = await prepareGenericEmbed(`Successfully froze **${user.name}**.`) - - await interaction.reply({ embeds: [embed]}) - } else { - let embed = await prepareGenericEmbed(`Could not freeze **${user.name}**.`) - - await interaction.reply({ embeds: [embed]}) - } - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/kick.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/kick.js deleted file mode 100644 index b315d0996..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/kick.js +++ /dev/null @@ -1,34 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('kick') - .setDescription('Kicks a User') - .addStringOption(option => - option.setName('user') - .setDescription('Username or ID') - .setRequired(true)) - .addStringOption(option => - option.setName('reason') - .setDescription('Reason Text') - .setRequired(true)), - async execute(interaction, exports) { - const userOrId = interaction.options.getString('user') - const reason = exports[EasyAdmin].formatShortcuts(interaction.options.getString('reason')) - - - const user = await findPlayerFromUserInput(userOrId) - - if (!user || user.dropped) { - interaction.reply({ content: 'Sorry, i couldn\'t find any user with the infos you provided.', ephemeral: true}) - return - } - - - DropPlayer(user.id, sprintf(exports[EasyAdmin].GetLocalisedText('kicked'), interaction.user.tag, reason )) - - var embed = await prepareGenericEmbed(`Successfully kicked **${user.name}** for **${reason}**`) - - await interaction.reply({ embeds: [embed]}) - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/mute.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/mute.js deleted file mode 100644 index c9d85d3e7..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/mute.js +++ /dev/null @@ -1,33 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('mute') - .setDescription('Mutes a User') - .addStringOption(option => - option.setName('user') - .setDescription('Username or ID') - .setRequired(true)), - async execute(interaction, exports) { - const userOrId = interaction.options.getString('user') - - const user = await findPlayerFromUserInput(userOrId) - - if (!user || user.dropped) { - interaction.reply({ content: 'Sorry, i couldn\'t find any user with the infos you provided.', ephemeral: true}) - return - } - - var ret = await exports[EasyAdmin].mutePlayer(user.id, true) - - if (ret) { - let embed = await prepareGenericEmbed(`Successfully muted **${user.name}**.`) - - await interaction.reply({ embeds: [embed]}) - } else { - let embed = await prepareGenericEmbed(`Could not mute **${user.name}**.`) - - await interaction.reply({ embeds: [embed]}) - } - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/playerinfo.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/playerinfo.js deleted file mode 100644 index 4a6c1a774..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/playerinfo.js +++ /dev/null @@ -1,79 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('playerinfo') - .setDescription('Gives Info about a Player') - .addStringOption(option => - option.setName('user') - .setDescription('Username or ID') - .setRequired(true)), - async execute(interaction, exports) { - const userOrId = interaction.options.getString('user') - - const user = await findPlayerFromUserInput(userOrId) - - if (!user) { - interaction.reply({ content: 'Sorry, i couldn\'t find any user with the infos you provided, if they have recently left, try using their ID instead of username', ephemeral: true}) - return - } - - var displayedIdentifiers = [] - - for (let identifier of user.identifiers) { - if ((isNaN(identifier.charAt(0))) && !(GetConvar('ea_IpPrivacy', 'true') == 'true' && identifier.search('ip:') != -1)) { - displayedIdentifiers.push(identifier) - } - } - - var table = AsciiTable.factory({ - heading: [ 'Identifiers'], - rows: displayedIdentifiers - }) - - var discordAccount = await getDiscordAccountFromPlayer(user) - var discordName = 'N/A' - if (discordAccount) { - discordName = discordAccount.tag - } - - - var embed = new EmbedBuilder() - .setColor(16777214) - .setTimestamp() - - embed.addFields([ - { name: 'Player Info', value: `Player infos for **${user.name}**`}, - { name: 'Discord Account', value: `\`\`\`${discordName}\`\`\``, inline: true} - ]) - - if (discordAccount) { - embed.setThumbnail(discordAccount.avatarURL()) - } - - embed.addFields([ - { name: 'Admin', value: `\`\`\`${exports[EasyAdmin].IsPlayerAdmin(user.id)}\`\`\``, inline: true}, - { name: 'Warnings', value: `\`\`\`${exports[EasyAdmin].getPlayerWarnings(user.id)}\`\`\``, inline: true} - ]) - - - - if (!user.dropped) { - var playerPed = GetPlayerPed(user.id) - embed.addFields([ - { name: 'Health', value: `\`\`\`${GetEntityHealth(playerPed)}\`\`\``, inline: true}, - { name: 'Armour', value: `\`\`\`${GetPedArmour(playerPed)}\`\`\``, inline: true} - ]) - if (GetPlayerInvincible(user.id)) { - embed.addFields([{ name: 'Godmode', value: '```ON```', inline: true}]) - } - } else { - embed.addFields([{ name: 'Status', value: '```Player Disconnected```'}]) - } - - - embed.addFields([{ name: 'Identifiers', value: `\`\`\`${table}\`\`\``}]) - - await interaction.reply({ embeds: [embed]}) - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/playerlist.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/playerlist.js deleted file mode 100644 index a430c1b09..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/playerlist.js +++ /dev/null @@ -1,143 +0,0 @@ - - - -function generatePaginatorRow(idFields, curPage, embedTimestamp) { - const row = new ActionRowBuilder() - - var selector = new SelectMenuBuilder() - - var fieldLength = idFields.length - if (fieldLength == 0) {fieldLength = 1} - selector.setCustomId(`pageSelector${embedTimestamp}`) - selector.setPlaceholder(`Page ${curPage+1}/${fieldLength}`) - - for (var i = 0; i < fieldLength; i++) { - selector.addOptions([ - { - label: `Page ${i+1}/${(fieldLength)}`, - value: `${i}`, - }]) - } - if (!idFields[1]) { - selector.setDisabled(true) - } - row.addComponents([selector]) - return row - -} - - -function generateEmbedFields(embed, idFields,usernameFields,discordnamefields, curPage) { - embed.addFields([{ - name: 'Id', - value: idFields[curPage], - inline: true - }, { - name: 'Name', - value: usernameFields[curPage], - inline: true - }, { - name: 'Discord', - value: discordnamefields[curPage], - inline: true - }]) -} - - -module.exports = { - data: new SlashCommandBuilder() - .setName('playerlist') - .setDescription('Shows a list of all Players'), - async execute(interaction, exports) { - var tempReply = await prepareGenericEmbed('```Processing Playerlist..```') - await interaction.reply({ - embeds: [tempReply] - }) - - var players = await exports[EasyAdmin].getCachedPlayers() - var embedTimestamp = Date.now() - - var embed = new EmbedBuilder() - .setColor(65280) - .setTimestamp() - - var idFields = [] - var usernameFields = [] - var discordnamefields = [] - var ids = '' - var usernames = '' - var discordnames = '' - var curPage = 0 - var row - - if (getPlayers().length != 0) { - for (let player of Object.values(players).entries()) { - if (!player.dropped) { - - if (ids.length >= 500 || usernames.length >= 500 || discordnames.length >= 500) { - idFields.push(ids) - usernameFields.push(usernames) - discordnamefields.push(discordnames) - ids = '' - usernames = '' - discordnames = '' - } - - var discordAccount = await getDiscordAccountFromPlayer(player) - if (discordAccount) { - discordAccount = discordAccount.tag - } else { - discordAccount = 'N/A' - } - - ids += `\n${player.id}` - usernames += `\n${player.name}` - discordnames += `\n${discordAccount}` - } - } - idFields.push(ids) - usernameFields.push(usernames) - discordnamefields.push(discordnames) - - generateEmbedFields(embed,idFields,usernameFields,discordnamefields,0) - - row = generatePaginatorRow(idFields, curPage, embedTimestamp) - if (idFields.length > 1) { - const filter = i => (i.customId === `pageSelector${embedTimestamp}`) - const collector = interaction.channel.createMessageComponentCollector({ - filter, - time: 120000 - }) - - collector.on('collect', async i => { - const embed = new EmbedBuilder() - .setColor(65280) - .setTimestamp() - if (i.customId === `pageSelector${embedTimestamp}`) { - curPage = parseInt(i.values[0]) - } - generateEmbedFields(embed,idFields,usernameFields,discordnamefields,curPage) - - const row = generatePaginatorRow(idFields, curPage, embedTimestamp) - - await interaction.editReply({ - embeds: [embed], - components: [row] - }) - await i.deferUpdate() - }) - } - } else { - embed = new EmbedBuilder() - .setColor(16777214) - .setTimestamp() - .addFields([{name: 'Player List', value: 'There are no players on the server!'}]) - row = generatePaginatorRow(idFields, 0, 0) - } - - await interaction.editReply({ - embeds: [embed], - components: [row] - }) - }, -} \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/refreshperms.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/refreshperms.js deleted file mode 100644 index b30b95e9a..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/refreshperms.js +++ /dev/null @@ -1,30 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('refreshperms') - .setDescription('Refreshes your EasyAdmin permissions') - .addUserOption(option => - option.setName('user') - .setDescription('the user to refresh permissions for, optional.') - .setRequired(false)), - - async execute(interaction) { - var member = interaction.member - let user = interaction.options.getUser('user') - if (user && user.id == member.id) user = null - if(user && !await DoesGuildMemberHavePermission(interaction.member, `bot.${interaction.commandName}`) == true) { - await interaction.reply({ content: 'You don\'t have permission to refresh other users permissions!', ephemeral: true }) - return - } else if (user) { - member = await interaction.guild.members.fetch(user.id) - } - - let username = (user && `${member.displayName}'s`) || 'your' - await refreshRolesForMember(member) - - var embed = await prepareGenericEmbed(`Successfully refreshed ${username} permissions.`) - - await interaction.reply({ embeds: [embed]}) - }, -} \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/remove_ace.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/remove_ace.js deleted file mode 100644 index 526aa7681..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/remove_ace.js +++ /dev/null @@ -1,52 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('remove_ace') - .setDescription('Removes a permission from a group, saves into easyadmin_permissions.cfg'), - async execute(interaction, exports) { - var timestamp = Date.now() - - const modal = new ModalBuilder() - .setCustomId('removeaceModal'+timestamp) - .setTitle('Remove ACE') - - const groupName = new TextInputBuilder() - .setCustomId('groupName') - .setLabel('Group Name') - .setStyle(TextInputStyle.Short) - .setRequired(true) - .setMaxLength(120) - .setPlaceholder('group.admin') - - const permission = new TextInputBuilder() - .setCustomId('permission') - // The label is the prompt the user sees for this input - .setLabel('Permission') - // Short means only a single line of text - .setStyle(TextInputStyle.Short) - .setRequired(true) - .setMaxLength(120) - .setPlaceholder('easyadmin.bot.playerlist') - - const firstActionRow = new ActionRowBuilder().addComponents(groupName) - const secondActionRow = new ActionRowBuilder().addComponents(permission) - - modal.addComponents(firstActionRow, secondActionRow) - - interaction.showModal(modal) - - const filter = (interaction) => interaction.customId === 'removeaceModal'+timestamp - interaction.awaitModalSubmit({ filter, time: 120000 }) - .then(async (interaction) => { - var group = interaction.fields.getTextInputValue('groupName') - var permission = interaction.fields.getTextInputValue('permission') - var query = `remove_ace ${group} ${permission} allow` - exports[EasyAdmin].RemoveFromFile('easyadmin_permissions.cfg', `add_ace ${group} ${permission} allow`) - - ExecuteCommand(query) - - interaction.reply(`\`${query}\` has been executed and saved.`) - }).catch(async () => {}) // silently catch error, happens if the form times out - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/remove_group.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/remove_group.js deleted file mode 100644 index 75fb43963..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/remove_group.js +++ /dev/null @@ -1,27 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('remove_group') - .setDescription('Removes a group from a User (ACE), saves into easyadmin_permissions.cfg') - .addUserOption(option => - option.setName('user') - .setDescription('The user') - .setRequired(true)) - .addStringOption(option => - option.setName('group') - .setDescription('the group, for example, group.admin') - .setRequired(true)), - async execute(interaction, exports) { - const user = interaction.options.getUser('user').id - const groupName = interaction.options.getString('group') - - - var query = `remove_principal identifier.discord:${user} ${groupName}` - exports[EasyAdmin].RemoveFromFile('easyadmin_permissions.cfg', `add_principal identifier.discord:${user} ${groupName}`) - - ExecuteCommand(query) - - interaction.reply(`\`${query}\` has been executed and saved.`) - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/screenshot.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/screenshot.js deleted file mode 100644 index a95d7eff4..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/screenshot.js +++ /dev/null @@ -1,52 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('screenshot') - .setDescription('Takes a screenshot of the player\'s screen') - .addStringOption(option => - option.setName('user') - .setDescription('Username or ID') - .setRequired(true)), - async execute(interaction, exports) { - const userOrId = interaction.options.getString('user') - var embed = await prepareGenericEmbed('Taking Screenshot, please wait.') - await interaction.reply({ embeds: [embed]}) - - - var inProgress = await exports[EasyAdmin].isScreenshotInProgress() - if (inProgress) { - let embed = await prepareGenericEmbed('A screenshot is already in progress! Please try again later.') - interaction.editReply({ embeds: [embed]}) - return - } - - const user = await findPlayerFromUserInput(userOrId) - if (!user || user.dropped) { - interaction.editReply({ content: 'Sorry, i couldn\'t find any user with the infos you provided.', ephemeral: true}) - return - } - - emit('EasyAdmin:TakeScreenshot', user.id) - - const screenshotHandler = async function (result) { - if (result == 'ERROR') { return } - - var screenshotUrl = await exports[EasyAdmin].matchURL(result.toString()) - RemoveEventHandler('EasyAdmin:TookScreenshot', screenshotHandler) - clearTimeout(failedTimeout) - - let embed = await prepareGenericEmbed(`Screenshot of **${user.name}**'s game taken.`,undefined,undefined,undefined,screenshotUrl) - await interaction.editReply({ embeds: [embed]}) - } - - - onNet('EasyAdmin:TookScreenshot', screenshotHandler) - - var failedTimeout = setTimeout(async function () { - RemoveEventHandler('EasyAdmin:TookScreenshot', screenshotHandler) - let embed = await prepareGenericEmbed(`Screenshot of **${user.name}**'s game failed!`, undefined, 16711680) - await interaction.editReply({ embeds: [embed]}) - }, 25000) - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/slap.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/slap.js deleted file mode 100644 index 81c5dfbcf..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/slap.js +++ /dev/null @@ -1,38 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('slap') - .setDescription('Substracts amount of HP from player') - .addStringOption(option => - option.setName('user') - .setDescription('Username or ID') - .setRequired(true)) - .addIntegerOption(option => - option.setName('amount') - .setDescription('Amount of HP to slap the user for.') - .setRequired(true)), - async execute(interaction, exports) { - const userOrId = interaction.options.getString('user') - const slapAmount = interaction.options.getInteger('amount') - - const user = await findPlayerFromUserInput(userOrId) - - if (!user || user.dropped) { - interaction.reply({ content: 'Sorry, i couldn\'t find any user with the infos you provided.', ephemeral: true}) - return - } - - var ret = exports[EasyAdmin].slapPlayer(user.id, slapAmount) - - if (ret) { - let embed = await prepareGenericEmbed(`Successfully slapped **${user.name}** for ${slapAmount} HP.`) - - await interaction.reply({ embeds: [embed]}) - } else { - let embed = await prepareGenericEmbed(`Could not slap **${user.name}**.`) - - await interaction.reply({ embeds: [embed]}) - } - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/unban.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/unban.js deleted file mode 100644 index 88c274b31..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/unban.js +++ /dev/null @@ -1,27 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('unban') - .setDescription('unbans a User') - .addIntegerOption(option => - option.setName('banid') - .setDescription('Ban ID') - .setRequired(true)), - async execute(interaction, exports) { - const banId = interaction.options.getInteger('banid') - - - var ret = await exports[EasyAdmin].unbanPlayer(banId) - - if (ret == true) { - let embed = await prepareGenericEmbed(`Successfully removed Ban **#${banId}**.`) - - await interaction.reply({ embeds: [embed]}) - } else { - let embed = await prepareGenericEmbed(`Failed to remove ban **#${banId}**, make sure the ID is valid.`) - - await interaction.reply({ embeds: [embed]}) - } - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/unfreeze.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/unfreeze.js deleted file mode 100644 index 98542c92b..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/unfreeze.js +++ /dev/null @@ -1,33 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('unfreeze') - .setDescription('Unfreezes player') - .addStringOption(option => - option.setName('user') - .setDescription('Username or ID') - .setRequired(true)), - async execute(interaction, exports) { - const userOrId = interaction.options.getString('user') - - const user = await findPlayerFromUserInput(userOrId) - - if (!user || user.dropped) { - interaction.reply({ content: 'Sorry, i couldn\'t find any user with the infos you provided.', ephemeral: true}) - return - } - - var ret = await exports[EasyAdmin].freezePlayer(user.id, false) - - if (ret) { - let embed = await prepareGenericEmbed(`Successfully unfroze **${user.name}**.`) - - await interaction.reply({ embeds: [embed]}) - } else { - let embed = await prepareGenericEmbed(`Could not unfreeze **${user.name}**.`) - - await interaction.reply({ embeds: [embed]}) - } - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/unmute.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/unmute.js deleted file mode 100644 index e023d5268..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/unmute.js +++ /dev/null @@ -1,33 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('unmute') - .setDescription('Unmutes a User') - .addStringOption(option => - option.setName('user') - .setDescription('Username or ID') - .setRequired(true)), - async execute(interaction, exports) { - const userOrId = interaction.options.getString('user') - - const user = await findPlayerFromUserInput(userOrId) - - if (!user || user.dropped) { - interaction.reply({ content: 'Sorry, i couldn\'t find any user with the infos you provided.', ephemeral: true}) - return - } - - var ret = await exports[EasyAdmin].mutePlayer(user.id, false) - - if (ret) { - let embed = await prepareGenericEmbed(`Successfully unmuted **${user.name}**.`) - - await interaction.reply({ embeds: [embed]}) - } else { - let embed = await prepareGenericEmbed(`Could not unmute **${user.name}**.`) - - await interaction.reply({ embeds: [embed]}) - } - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/warn.js b/server-data/resources/[esx]/EasyAdmin/server/bot/commands/warn.js deleted file mode 100644 index c3749851c..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/commands/warn.js +++ /dev/null @@ -1,37 +0,0 @@ - - -module.exports = { - data: new SlashCommandBuilder() - .setName('warn') - .setDescription('Warn a User') - .addStringOption(option => - option.setName('user') - .setDescription('Username or ID') - .setRequired(true)) - .addStringOption(option => - option.setName('reason') - .setDescription('Reason Text') - .setRequired(true)), - async execute(interaction, exports) { - const userOrId = interaction.options.getString('user') - const reason = exports[EasyAdmin].formatShortcuts(interaction.options.getString('reason')) - - - const user = await findPlayerFromUserInput(userOrId) - - if (!user || user.dropped) { - interaction.reply({ content: 'Sorry, i couldn\'t find any user with the infos you provided.', ephemeral: true}) - return - } - - var src = interaction.member.user.tag - var ret = await exports[EasyAdmin].warnPlayer(src, user.id, reason) - var embed - if (ret) { - embed = await prepareGenericEmbed(`Successfully warned **${user.name}** for **${reason}**`) - } else { - embed = await prepareGenericEmbed('Could not warn this user. (Maybe this user is immune)') - } - await interaction.reply({ embeds: [embed]}) - }, -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/functions.js b/server-data/resources/[esx]/EasyAdmin/server/bot/functions.js deleted file mode 100644 index 037c30594..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/functions.js +++ /dev/null @@ -1,131 +0,0 @@ -/*eslint no-global-assign: "off", no-unused-vars: "off"*/ -// this file contains util functions the bot uses - -async function prepareGenericEmbed(message,feature,colour,title,image,customAuthor,description,timestamp) { - - if (feature && await exports[EasyAdmin].isWebhookFeatureExcluded(feature)) { - return - } - - const embed = new EmbedBuilder() - .setColor(colour || 16777214) - if (timestamp != false) { - embed.setTimestamp() - } - if (message) { - embed.addFields([{name: `**${(title || 'EasyAdmin')}**`, value: message}]) - } - if (description) { - embed.setDescription(description) - } - - if (customAuthor) { - embed.setAuthor(customAuthor) - } - - if (image) { - embed.setImage(image) - } - - return embed -} - -async function findPlayerFromUserInput(input) { - var user - - var players = await exports[EasyAdmin].getCachedPlayers() - - Object.keys(players).forEach(function(key) { - var player = players[key] - var name = player.name - if(!isNaN(input)) { - if (player.id == input) { - user = player - } - } else { - if (name.search(input) != -1) { - user = player - } - } - }) - - return user -} - - -async function DoesGuildMemberHavePermission(member, object) { // wrapper for Discord Permissions, use export for Player Permissions. - if (!member || !object) { return false } - var memberId = member.id - if(!memberId) { - return false - } - if (object.search('easyadmin.') == -1) { - object = `easyadmin.${object}` - } - - if (member.guild.ownerId === memberId) { // guild owner always has permissions, to everything. - return true - } - - - var allowed=IsPrincipalAceAllowed(`identifier.discord:${memberId}`, object) - return allowed -} - - -async function getDiscordAccountFromPlayer(user) { - var discordAccount = false - if (!isNaN(user)) { - user = await exports[EasyAdmin].getCachedPlayer(user) - } - - for (let identifier of user.identifiers) { - if (identifier.search('discord:') != -1) { - discordAccount = await client.users.fetch(identifier.substring(identifier.indexOf(':') + 1)) - } - } - - return discordAccount -} - - -async function getPlayerFromDiscordAccount(user) { - var id = user.id - - var players = await exports[EasyAdmin].getCachedPlayers() - - for (let [index, player] of Object.values(players).entries()) { - for (let identifier of player.identifiers) { - if (identifier == `discord:${id}`) { - return player - } - } - } - - return false -} - -async function refreshRolesForMember(member) { - var roles = await member.roles.cache.keys() - for (var role of roles) { - emit('debug', `role sync for ${member.user.tag} add_principal identifier.discord:${member.id} role:${role}`) - ExecuteCommand(`add_principal identifier.discord:${member.id} role:${role}`) - } - emit('debug', `roles synced for ${member.user.tag}`) -} - -async function refreshRolesForUser(user,roles) { - for (var role of roles) { - emit('debug', `role sync for ${user.tag} add_principal identifier.discord:${user.id} role:${role}`) - ExecuteCommand(`add_principal identifier.discord:${user.id} role:${role}`) - } - emit('debug', `roles synced for ${user.tag}`) -} - -// converts Lua format string to JS format string (e.g. %s -> %s) and replaces %s with arguments -function format(str, ...args) { - let formatted = str.replace(/%s/g, function() { - return args.shift() - }) - return formatted -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/logging.js b/server-data/resources/[esx]/EasyAdmin/server/bot/logging.js deleted file mode 100644 index c7f76a382..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/logging.js +++ /dev/null @@ -1,48 +0,0 @@ - - -botLogForwards = [] -async function addBotLogForwarding(source,args) { - var player=source - - if (await exports[GetCurrentResourceName()].DoesPlayerHavePermission(player, 'server')) { - var feature = args[0] - var channel = args[1] - - if (!feature || !parseInt(channel)) { - console.error('Invalid Usage! ea_addBotLogForwarding feature channelId') - return false - } - - console.log(`Added log fwd ${feature} => ${channel}`) - botLogForwards[feature] = channel - return true - } -} - - -RegisterCommand('ea_addBotLogForwarding', addBotLogForwarding) - - -async function LogDiscordMessage(text, feature, colour) { - if (!EasyAdmin) {return} // bot isnt running - if (GetConvar('ea_botLogChannel', '') == '') {return} - if (feature == 'report' || feature == 'calladmin') {return} // we dont care about reports, these get handled in reports.js - - const embed = await prepareGenericEmbed(text,undefined,colour) - - - var channel = await client.channels.cache.get(botLogForwards[feature] || GetConvar('ea_botLogChannel', '')) - - - if (channel) { - channel.send({ embeds: [embed] }).catch((error) => { - console.error('^7Failed to log message, please make sure you gave the bot permission to write in the log channel!\n\n') - console.error(error) - - }) - } else { - console.error('^7Failed to log message, please make sure you gave the bot permission to write in the log channel!\n\n') - } -} -exports('LogDiscordMessage', LogDiscordMessage) - diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/player_events.js b/server-data/resources/[esx]/EasyAdmin/server/bot/player_events.js deleted file mode 100644 index 56756622c..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/player_events.js +++ /dev/null @@ -1,35 +0,0 @@ -if (GetConvar('ea_botToken', '') != '') { - - on('playerJoining', function () { - const player = global.source - - if (GetConvar('ea_botToken', '') != '' && GetConvar('ea_botLogChannel', '') != '') { - var msg = `Player **${exports[EasyAdmin].getName(player,true,true)}** with id **${player}** joined the Server!` - LogDiscordMessage(msg, 'joinleave') - } - }) - - on('playerConnecting', function () { - if (GetConvar('ea_botToken', '') == '') return - const player = global.source - - exports[EasyAdmin].syncDiscordRoles(player) - }) - - - on('playerDropped', () => { - if (GetConvar('ea_botToken', '') == '') return - var player = global.source - - if (GetConvar('ea_botChatBridge', '') != '') { - knownAvatars[player] = undefined - } - - if (GetConvar('ea_botLogChannel', '') != '') { - var msg = `Player **${exports[EasyAdmin].getName(player,true,true)}** left the server!` - LogDiscordMessage(msg, 'joinleave') - } - }) - -} - diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/reports.js b/server-data/resources/[esx]/EasyAdmin/server/bot/reports.js deleted file mode 100644 index ffe8d6716..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/reports.js +++ /dev/null @@ -1,69 +0,0 @@ - -var reports = [] - -function generateReportEmbed(report, disabled, closed) { - var embed = new EmbedBuilder() - .setTimestamp() - - if (closed) { - embed.setColor(808080) - } else { - embed.setColor(65280) - } - - if (report.type == 1) { - embed.addFields([{name:'Player Report', value: `**${report.reporterName}** reported **${report.reportedName}**!`}]) - } else { - embed.addFields([{name:'Admin Call', value: `**${report.reporterName}** called for an Admin!`}]) - } - - embed.addFields([ - {name:'Reason', value: `\`\`\`\n${report.reason}\`\`\``}, - {name:'Report ID', value: `#${report.id}`, inline: true}, - {name:'Claimed by', value:`${(report.claimedName || 'Noone')}`, inline: true}]) - - return {embeds: [embed]} -} - -async function logNewReport(report) { - if (GetConvar('ea_botToken', '') != '') { - var reportId = report.id - reports[reportId] = report - var reportMessage = generateReportEmbed(report) - var channel = await client.channels.cache.get(GetConvar('ea_botLogChannel', '')) - if (report.type == 1 && botLogForwards['report']) { - channel = await client.channels.cache.get(botLogForwards['report']) - } else if (report.type == 0 && botLogForwards['calladmin']) { - channel = await client.channels.cache.get(botLogForwards['calladmin']) - } - - var msg = await channel.send(reportMessage) - reports[reportId].msg = msg - } else { - return false - } -} - - -on('EasyAdmin:reportAdded', async function(reportdata) { - logNewReport(reportdata) -}) - -on('EasyAdmin:reportClaimed', async function (reportdata) { - var reportId = reportdata.id - if(reports[reportId]) { - reports[reportId].claimed = reportdata.claimed - reports[reportId].claimedName = reportdata.claimedName - let reportMessage = generateReportEmbed(reports[reportId], true) - reports[reportId].msg.edit(reportMessage) - } -}) - -on('EasyAdmin:reportRemoved', async function(reportdata) { - var reportId = reportdata.id - if(reports[reportId]) { - var reportMessage = generateReportEmbed(reports[reportId], true, true) - reports[reportId].msg.edit(reportMessage) - reports[reportId] = undefined - } -}) diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/roles.js b/server-data/resources/[esx]/EasyAdmin/server/bot/roles.js deleted file mode 100644 index 66dd54200..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/roles.js +++ /dev/null @@ -1,48 +0,0 @@ - -async function syncDiscordRoles(player) { - if (!EasyAdmin) {return} // bot is down - var user - - - try { - var identifiers = await exports[EasyAdmin].getAllPlayerIdentifiers(player) - for (let identifier of identifiers) { - if (identifier.search('discord:') != -1) { - user = await client.users.fetch(identifier.substring(identifier.indexOf(':') + 1)) - } - } - if (!user) { - return false - } - } catch (error) { - return - } - - var roles = [] - for (const id of client.guilds.cache.keys()) { - const guild = client.guilds.cache.get(id) - if (guild.members.cache.has(user.id)) { - var guildMember = await guild.members.fetch(user.id) - if (guildMember) { - roles.push(...guildMember.roles.cache.keys()) - } - } - } - refreshRolesForUser(user, roles) -} -exports('syncDiscordRoles', syncDiscordRoles) - -if (GetConvar('ea_botToken', '') != '') { - client.on('guildMemberUpdate', async function(oldMember, newMember){ - oldRoles = await oldMember.roles.cache.keys() - newRoles = await newMember.roles.cache.keys() - - for (let role of oldRoles) { - ExecuteCommand(`remove_principal identifier.discord:${oldMember.id} role:${role}`) - } - - for (let role of newRoles) { - ExecuteCommand(`add_principal identifier.discord:${newMember.id} role:${role}`) - } - }) -} diff --git a/server-data/resources/[esx]/EasyAdmin/server/bot/server_status.js b/server-data/resources/[esx]/EasyAdmin/server/bot/server_status.js deleted file mode 100644 index 6bd1d4e4e..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/bot/server_status.js +++ /dev/null @@ -1,142 +0,0 @@ - -var statusMessage -var startTimestamp = new Date() - - -async function getServerStatus(why) { - var embed = new EmbedBuilder() - .setColor(65280) - .setTimestamp() - - - var joinURL = GetConvar('web_baseUrl', '') - var buttonRow = false - - - if(joinURL != '' && joinURL.indexOf('cfx.re' != -1) && joinURL.match(/^[^A-z0-9]/)==null) { - embed.setURL(`https://${joinURL}`) - buttonRow = new ActionRowBuilder() - var button = new ButtonBuilder() - .setURL(`https://${joinURL}`) - .setLabel('Join Server') - .setStyle(ButtonStyle.Link) - buttonRow.addComponents([button]) - } else { - joinURL = '' - } - var serverName = GetConvar('sv_projectName', GetConvar('sv_hostname', 'default FXServer')) - if (serverName.length > 255) { - serverName = serverName.substring(0,255) - } - serverName = serverName.replace(/\^[0-9]/g, '') - - embed.addFields([{name: 'Server Name', value: `\`\`\`${serverName}\`\`\``}]) - - - var reports = await exports[EasyAdmin].getAllReports() - var activeReports = 0 - var claimedReports = 0 - for (let report of Object.values(reports).entries()) { - activeReports+=1 - if (report.claimed) { - claimedReports+=1 - } - } - - embed.addFields([ - { name: 'Players Online', value: `\`\`\`${getPlayers().length}/${GetConvar('sv_maxClients', '')}\`\`\``, inline: true}, - { name: 'Admins Online', value: `\`\`\`${Object.values(exports[EasyAdmin].GetOnlineAdmins()).length}\`\`\``, inline: true}, - { name: 'Reports', value: `\`\`\`${activeReports} (${claimedReports} claimed)\`\`\``, inline: true}, - { name: 'Active Vehicles', value: `\`\`\`${GetAllVehicles().length}\`\`\``, inline: true}, - { name: 'Active Peds', value: `\`\`\`${GetAllPeds().length}\`\`\``, inline: true}, - { name: 'Active Objects', value: `\`\`\`${GetAllObjects().length}\`\`\``, inline: true} - ]) - - - if (joinURL != '') { - try { - let serverId = joinURL.substring(joinURL.lastIndexOf('-')+1,joinURL.indexOf('.users.cfx.re')) - let response = await exports[EasyAdmin].HTTPRequest(`https://servers-frontend.fivem.net/api/servers/single/${serverId}`) - response = JSON.parse(response).Data - embed.addFields([{ name: 'Upvotes', value: `\`\`\`${response.upvotePower} Upvotes, ${response.burstPower} Bursts\`\`\``, inline: false}]) - - embed.setAuthor({ name: `${serverName}`, iconURL: response.ownerAvatar, url: `https://${joinURL}`}) - - } catch (error) { - console.error(error) - } - } - embed.addFields([{ name: 'Uptime', value: `\`\`\`${prettyMilliseconds(new Date()-startTimestamp, {verbose: true, secondsDecimalDigits: 0})}\`\`\``, inline: false}]) - - - - if (why) { - embed.addFields([{name: 'Last Update', value: why}]) - } - - if (buttonRow) { - return {embeds: [embed], components: [buttonRow] } - } - return {embeds: [embed] } - - - - -} - -async function updateServerStatus(why) { - if (GetConvar('ea_botStatusChannel', '') == '') { return } - var channel = await client.channels.fetch(GetConvar('ea_botStatusChannel', '')) - - if (channel == undefined) { - console.error('Failed to configure bot status channel, please make sure the channel id is correct and the bot has read and write access.') - return - } - - if (!statusMessage) { - var messagesToDelete = [] - var messages = await channel.messages.fetch({ limit: 10 }).catch((error) => { - console.error('^7Failed to configure server status channel, please make sure you gave the bot permission to write in the channel!\n\n') - console.error(error) - - }) - for (var message of messages.values()) { - if (messages.size == 1 && message.author.id == client.user.id) { - statusMessage = message - break - } else { - messagesToDelete.push(message.id) - } - } - try { - if (statusMessage) { - updateServerStatus() - return - } - await channel.bulkDelete(messagesToDelete) - } catch (error) { - console.log('Could not bulk-delete messages in botStatusChannel.') - console.error(error) - } - let embed = await prepareGenericEmbed('Fetching Server Infos..') - statusMessage = await channel.send({ embeds: [embed] }) - } - const embed = await getServerStatus(why) - statusMessage.edit(embed) - -} - -client.on('messageCreate', async msg => { - if (!msg.member || msg.author.bot) { return } // message-sender is a webhook - if(msg.author.id == userID) { - return - } - if(!msg.channel) { return } - if (msg.channel.id == GetConvar('ea_botStatusChannel', '')) { - msg.delete() - updateServerStatus('manual') - } - -}) -setTimeout(updateServerStatus, 10000) -setInterval(updateServerStatus, 180000) diff --git a/server-data/resources/[esx]/EasyAdmin/server/commands.lua b/server-data/resources/[esx]/EasyAdmin/server/commands.lua deleted file mode 100644 index ad6147693..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/commands.lua +++ /dev/null @@ -1,91 +0,0 @@ ------------------------------------- ------------------------------------- ----- DONT TOUCH ANY OF THIS IF YOU DON'T KNOW WHAT YOU ARE DOING ----- THESE ARE **NOT** CONFIG VALUES, USE THE CONVARS IF YOU WANT TO CHANGE SOMETHING ----- ----- ----- If you are a developer and want to change something, consider writing a plugin instead: ----- https://easyadmin.readthedocs.io/en/latest/plugins/ ----- ------------------------------------- ------------------------------------- - -RegisterCommand("ea_addShortcut", function(source, args, rawCommand) - if args[2] and DoesPlayerHavePermission(source, "server.shortcut.add") then - local shortcut = args[1] - local text = table.concat(args, " ", 2) - - PrintDebugMessage("added '"..shortcut.." -> "..text.."' as a shortcut", 3) - MessageShortcuts[shortcut] = text - - for i,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:fillShortcuts", i, 10000, MessageShortcuts) - end - end -end) - -RegisterCommand("ea_addReminder", function(source, args, rawCommand) - if args[1] and DoesPlayerHavePermission(source, "server.reminder.add") then - local text = string.gsub(rawCommand, "ea_addReminder ", "") - local text = string.gsub(text, '"', '') - - PrintDebugMessage("added '"..text.."' as a Chat Reminder", 3) - table.insert(ChatReminders, text) - end -end, false) - -RegisterCommand("ea_printIdentifiers", function(source,args,rawCommand) - if source == 0 and args[1] then -- only let Console run this command - local id = tonumber(args[1]) - print(json.encode(CachedPlayers[id].identifiers)) -- puke all identifiers into console - end -end,false) - -Citizen.CreateThread(function() - RegisterCommand("ea_generateSupportFile", function(source, args, rawCommand) - if DoesPlayerHavePermission(source, "server") then - print("SupportFile is no longer supported, please use eaDiag instead.") - end - end, false) - -end) - -RegisterCommand("spectate", function(source, args, rawCommand) - if(source == 0) then - Citizen.Trace(GetLocalisedText("badidea")) -- Maybe should be it's own string saying something like "only players can do this" or something - end - - PrintDebugMessage("Player "..getName(source,true).." Requested Spectate on "..getName(args[1],true), 3) - - if args[1] and tonumber(args[1]) and DoesPlayerHavePermission(source, "player.spectate") then - if getName(args[1]) then - TriggerClientEvent("EasyAdmin:requestSpectate", source, args[1]) - else - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("playernotfound")) - end - end -end, false) - - -RegisterCommand("setgametype", function(source, args, rawCommand) - if args[1] and DoesPlayerHavePermission(source, "server.convars") then - PrintDebugMessage("Player "..getName(source,true).." set Gametype to "..args[1], 3) - SetGameType(args[1]) - end -end, false) - -RegisterCommand("setmapname", function(source, args, rawCommand) - if args[1] and DoesPlayerHavePermission(source, "server.convars") then - PrintDebugMessage("Player "..getName(source,true).." set Map Name to "..args[1], 3) - SetMapName(args[1]) - end -end, false) - -RegisterCommand("slap", function(source, args, rawCommand) - if args[1] and args[2] and DoesPlayerHavePermission(source, "player.slap") then - local preferredWebhook = detailNotification ~= "false" and detailNotification or moderationNotification - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText("adminslappedplayer"), getName(source, false, true), getName(args[1], true, true), args[2]), "slap", 16711680) - PrintDebugMessage("Player "..getName(source,true).." slapped "..getName(args[1],true).." for "..args[2].." HP", 3) - TriggerClientEvent("EasyAdmin:SlapPlayer", args[1], args[2]) - end -end, false) \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/server/permission_editor.lua b/server-data/resources/[esx]/EasyAdmin/server/permission_editor.lua deleted file mode 100644 index c7576b364..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/permission_editor.lua +++ /dev/null @@ -1,342 +0,0 @@ ------------------------------------- ------------------------------------- ----- DONT TOUCH ANY OF THIS IF YOU DON'T KNOW WHAT YOU ARE DOING ----- THESE ARE **NOT** CONFIG VALUES, USE THE CONVARS IF YOU WANT TO CHANGE SOMETHING ----- ----- ----- If you are a developer and want to change something, consider writing a plugin instead: ----- https://easyadmin.readthedocs.io/en/latest/plugins/ ----- ------------------------------------- ------------------------------------- - -Citizen.CreateThread(function() - local add_aces = {} - local add_principals = {} - function readAcePermissions() - Citizen.CreateThread(function() - add_aces, add_principals, execs = FindInfosinFile("server.cfg") - for i, config in pairs(execs) do - local tempaces, tempprincipals, _ = FindInfosinFile(config) - add_aces = mergeTables(add_aces, tempaces) - add_principals = mergeTables(add_principals, tempprincipals) - end - end) - end - - function FindInfosinFile(filename) - local path = GetResourcePath(GetCurrentResourceName()) - local occurance = string.find(path, "/resources", 1, true) - local path = string.reverse(string.sub(string.reverse(path), -occurance)) - - local filename = filename - - local lines = {} - local needsExec = true - local needsResourcePerms = true - - if filename == "server.cfg" then - needsResourcePerms = false - elseif filename == "easyadmin_permissions.cfg" then - needsExec = false - else - needsResourcePerms, needsExec = false, false - end - local changes = false - local aces, principals, execs = {}, {}, {} - - PrintDebugMessage("reading "..filename, 4) - - local file = io.open(filename, "r") - if file then - line = file:read("*line") - while line do - table.insert(lines,line) - line = file:read("*line") - end - file:close() - - for i, line in pairs(lines) do - if filename == "server.cfg" then - needsResourcePerms = false - if string.find(line, "exec easyadmin_permissions.cfg", 1, true) then - needsExec = false - end - elseif filename == "easyadmin_permissions.cfg" then - needsExec = false - if string.find(line, "add_ace resource."..GetCurrentResourceName().." command.add_ace allow", 1, true) then - needsResourcePerms = false - end - else - local broken = false - -- remove broken lines - if string.find(line, "exec easyadmin_permissions.cfg", 1, true) then - RemoveFromFile(filename, "exec easyadmin_permissions.cfg") - elseif string.find(line, "add_ace resource."..GetCurrentResourceName().." command.", 1, true) then - RemoveFromFile(filename, line) - end - end - - -- filteredLine variable converts tabs to spaces, and multiple spaces to single space - local filteredLine = string.gsub(line, "%s+", " ") - -- remove comments - filteredLine = string.gsub(filteredLine, "%s*#.*$", "") - - - - -- strip the arguments from the "add_ace", "add_principal" and "exec" commands and insert them into their respective tables - if string.find(filteredLine, "add_ace", 1, true) then - local args = string.split(filteredLine, " ") - if args[2] and args[3] and args[4] then - table.insert(aces, {file = filename, oldline = line, args[2], args[3], args[4]}) - end - elseif string.find(filteredLine, "add_principal", 1, true) then - local args = string.split(filteredLine, " ") - if args[2] and args[3] then - table.insert(principals, {file = filename, oldline = line, args[2], args[3]}) - end - elseif string.find(filteredLine, "exec", 1, true) then - local args = string.split(filteredLine, " ") - if args[2] then - table.insert(execs, args[2]) - end - end - end - - if needsExec or needsResourcePerms or changes then - local newLines = {} - if needsExec then - table.insert(newLines, "exec easyadmin_permissions.cfg") - table.insert(execs, "easyadmin_permissions.cfg") - PrintDebugMessage("Did not find `exec easyadmin_permissions.cfg`, added it automatically", 4) - changes=true - end - if needsResourcePerms then - table.insert(newLines, "# This file was generated automatically by EasyAdmin #") - table.insert(newLines, "add_ace resource."..GetCurrentResourceName().." command.add_ace allow") - table.insert(newLines, "add_ace resource."..GetCurrentResourceName().." command.remove_ace allow") - table.insert(newLines, "add_ace resource."..GetCurrentResourceName().." command.add_principal allow") - table.insert(newLines, "add_ace resource."..GetCurrentResourceName().." command.remove_principal allow") - PrintDebugMessage("Did not find `add_ace resource."..GetCurrentResourceName().."` lines, added them automatically", 4) - changes=true - end - local output = "\n" - if changes then - local file = io.open(filename, "a+") -- reopen in write mode - for i, line in pairs(newLines) do - output=output..line.."\n" - end - file:write(output) -- write our lines - file:close() - end - end - - for i,ace in pairs(aces) do - PrintDebugMessage("parsed ace ^1" - ..tostring(ace[1]).." " - ..tostring(ace[2]).." " - ..tostring(ace[3]).."^7 in " - ..filename.."\n", 4) - end - - for i,ace in pairs(principals) do - PrintDebugMessage("parsed principal ^1" - ..tostring(ace[1]).." " - ..tostring(ace[2]).."^7 in " - ..filename.."\n", 4) - end - - for i,ace in pairs(execs) do - PrintDebugMessage("parsed exec ^1" - ..tostring(ace).."^7 in " - ..filename.."\n", 4) - end - - return aces, principals, execs - else - if filename == "easyadmin_permissions.cfg" then - local file = io.open(filename, "w") - local newLines = {} - table.insert(newLines, "add_ace resource."..GetCurrentResourceName().." command.add_ace allow") - table.insert(newLines, "add_ace resource."..GetCurrentResourceName().." command.remove_ace allow") - table.insert(newLines, "add_ace resource."..GetCurrentResourceName().." command.add_principal allow") - table.insert(newLines, "add_ace resource."..GetCurrentResourceName().." command.remove_principal allow") - local output = "" - for i, line in pairs(newLines) do - output=output..line.."\n" - end - file:write(output) -- write our lines - file:close() - end - PrintDebugMessage(filename.." cannot be read, bailing.", 4) - return {}, {}, {} - end - end - - Citizen.CreateThread(function() - lockedFiles = {} - function AddToFile(filename, args) - if not GetInvokingResource() or GetInvokingResource() == GetCurrentResourceName() then -- sorry, but i _really_ dont want other resources hooking into easyadmins file edit functions. - - local path = GetResourcePath(GetCurrentResourceName()) - local occurance = string.find(path, "/resources", 1, true) - local path = string.reverse(string.sub(string.reverse(path), -occurance)) - - - local args = args - local filename = filename - while lockedFiles[filename] do - Wait(100) - end - lockedFiles[filename] = true - - - local file = io.open(filename, "a") - if file then - file:write("\n"..args) -- write our lines - file:close() - else - PrintDebugMessage(filename.." cannot be read, bailing.", 4) - return {}, {}, {} - end - Wait(500) -- without waiting after saving a file it sometimes does not properly save, some OS limitation maybe? - lockedFiles[filename] = false - end - end - exports('AddToFile', AddToFile) - - function RemoveFromFile(filename, args, partial) - if not GetInvokingResource() or GetInvokingResource() == GetCurrentResourceName() then -- sorry, but i _really_ dont want other resources hooking into easyadmins file edit functions. - - local path = GetResourcePath(GetCurrentResourceName()) - local occurance = string.find(path, "/resources", 1, true) - local path = string.reverse(string.sub(string.reverse(path), -occurance)) - - local args = args - local filename = filename - while lockedFiles[filename] do - Wait(100) - end - lockedFiles[filename] = true - - local file = io.open(filename, "r") - local lines = {} - if file then - local line = file:read("*line") - while line do - if (partial and string.find(line, args) or (not partial and line == args)) or (filename == "easyadmin_permissions.cfg" and line == "") then -- skip lines we dont want, incl. empty lines - else - table.insert(lines, line) - end - line = file:read("*line") - end - file:close() - local output = "" - for i, line in pairs(lines) do - output=output..line.."\n" - end - local file = io.open(filename, "w") - file:write(output) -- write our lines - file:close() - else - PrintDebugMessage(filename.." cannot be read, bailing.", 4) - return {}, {}, {} - end - Wait(500) -- without waiting after saving a file it sometimes does not properly save, some OS limitation maybe? - lockedFiles[filename] = false - end - end - exports('RemoveFromFile', RemoveFromFile) - end) - - RegisterServerEvent("EasyAdmin:getServerAces", function() - if DoesPlayerHavePermission(source, "server.permissions.read") then - TriggerLatentClientEvent("EasyAdmin:getServerAces", source, 100000, add_aces, add_principals) - end - end) - - RegisterServerEvent("EasyAdmin:setServerAces", function(aces,principals) - if DoesPlayerHavePermission(source, "server.permissions.write") then - local source=source - local aces=aces - local principals=principals - -- reconfigure aces - for i, ace in pairs(add_aces) do - - if not aces[i] then - if not ace.file then ace.file = "easyadmin_permissions.cfg" end - - ExecuteCommand("remove_ace "..ace[1].." "..ace[2].." "..ace[3]) - RemoveFromFile(ace.file, ace.oldline or "add_ace "..ace[1].." "..ace[2].." "..ace[3]) - - - PrintDebugMessage("Executed remove_ace "..ace[1].." "..ace[2].." "..ace[3], 4) - elseif aces[i][1] ~= ace[1] or aces[i][2] ~= ace[2] or aces[i][3] ~= ace[3] then - if not ace.file then ace.file = "easyadmin_permissions.cfg" end - if not aces[i].file then aces[i].file = "easyadmin_permissions.cfg" end - ExecuteCommand("remove_ace "..ace[1].." "..ace[2].." "..ace[3]) - RemoveFromFile(ace.file, ace.oldline or "add_ace "..ace[1].." "..ace[2].." "..ace[3]) - - ExecuteCommand("add_ace "..aces[i][1].." "..aces[i][2].." "..aces[i][3]) - AddToFile(aces[i].file, "add_ace "..aces[i][1].." "..aces[i][2].." "..aces[i][3]) - - - PrintDebugMessage("Executed remove_ace "..ace[1].." "..ace[2].." "..ace[3], 4) - PrintDebugMessage("Executed add_ace "..aces[i][1].." "..aces[i][2].." "..aces[i][3], 4) - end - end - for i, ace in pairs(aces) do - if not add_aces[i] then - if not ace.file then ace.file = "easyadmin_permissions.cfg" end - - ExecuteCommand("add_ace "..ace[1].." "..ace[2].." "..ace[3]) - AddToFile(ace.file, "add_ace "..ace[1].." "..ace[2].." "..ace[3]) - - PrintDebugMessage("Executed add_ace "..ace[1].." "..ace[2].." "..ace[3], 4) - end - end - -- reconfigure principals - for i, principal in pairs(add_principals) do - - -- set file as our permissions file in case its unset - - if not principals[i] then - if not principal.file then principal.file = "easyadmin_permissions.cfg" end - - ExecuteCommand("remove_principal "..principal[1].." "..principal[2]) - RemoveFromFile(principal.file, principal.oldline or "add_principal "..principal[1].." "..principal[2]) - - PrintDebugMessage("Executed remove_principal "..principal[1].." "..principal[2], 4) - elseif principals[i][1] ~= principal[1] or principals[i][2] ~= principal[2] then - if not principal.file then principal.file = "easyadmin_permissions.cfg" end - if not principals[i].file then principals[i].file = "easyadmin_permissions.cfg" end - - ExecuteCommand("remove_principal "..principal[1].." "..principal[2]) - RemoveFromFile(principal.file, principal.oldline or "add_principal "..principal[1].." "..principal[2]) - - - ExecuteCommand("add_principal "..principals[i][1].." "..principals[i][2]) - AddToFile(principals[i].file, "add_principal "..principals[i][1].." "..principals[i][2]) - - PrintDebugMessage("Executed remove_principal "..principal[1].." "..principal[2], 4) - PrintDebugMessage("Executed add_principal "..principals[i][1].." "..principals[i][2], 4) - end - end - for i, principal in pairs(principals) do - if not add_principals[i] then - if not principal.file then principal.file = "easyadmin_permissions.cfg" end - ExecuteCommand("add_principal "..principal[1].." "..principal[2]) - AddToFile(principal.file, "add_principal "..principal[1].." "..principal[2]) - - PrintDebugMessage("Executed add_principal "..principal[1].." "..principal[2], 4) - end - end - - - add_aces = aces - add_principals = principals - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("admineditedpermissions"), getName(source, false, true)), "permissions", 16777214) - TriggerLatentClientEvent("EasyAdmin:getServerAces", source, 100000, add_aces, add_principals) - end - end) -end) \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/server/playercache.lua b/server-data/resources/[esx]/EasyAdmin/server/playercache.lua deleted file mode 100644 index fd83500f4..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/playercache.lua +++ /dev/null @@ -1,67 +0,0 @@ ------------------------------------- ------------------------------------- ----- DONT TOUCH ANY OF THIS IF YOU DON'T KNOW WHAT YOU ARE DOING ----- THESE ARE **NOT** CONFIG VALUES, USE THE CONVARS IF YOU WANT TO CHANGE SOMETHING ----- ----- ----- If you are a developer and want to change something, consider writing a plugin instead: ----- https://easyadmin.readthedocs.io/en/latest/plugins/ ----- ------------------------------------- ------------------------------------- - -CachedPlayers = {} -- DO NOT TOUCH THIS - -Citizen.CreateThread(function() - while true do - Wait(20000) - local osTime = os.time() - local playerCacheExpiry = GetConvarInt("ea_playerCacheExpiryTime", 1800) - for i, player in pairs(CachedPlayers) do - if player.droppedTime and (osTime > player.droppedTime+playerCacheExpiry) then - PrintDebugMessage("Cache for "..player.id.." expired, removing from cache.", 3) - for i, report in pairs(reports) do - if report.reported == player.id then - reports[i] = nil - end - end - CachedPlayers[i]=nil - end - end - end -end) - -function cachePlayer(playerId) - if not CachedPlayers[playerId] then - CachedPlayers[playerId] = {id = playerId, name = getName(playerId, true), identifiers = getAllPlayerIdentifiers(playerId), immune = DoesPlayerHavePermission(playerId, "immune")} - PrintDebugMessage(getName(playerId).." has been added to cache.", 4) - return true - end - return false -end - -RegisterServerEvent("EasyAdmin:requestCachedPlayers", function() - PrintDebugMessage(getName(source, true).." requested Cache.", 4) - local src = source - if (DoesPlayerHavePermission(source, "player.ban.temporary") or DoesPlayerHavePermission(source, "player.ban.permanent")) then - TriggerLatentClientEvent("EasyAdmin:fillCachedPlayers", src, 200000, CachedPlayers) - end -end) - -function getCachedPlayers() -- this is server-only for security reasons. - return CachedPlayers -end -exports('getCachedPlayers', getCachedPlayers) - -function getCachedPlayer(id) - cachePlayer(tonumber(id)) - return CachedPlayers[tonumber(id)] -end -exports('getCachedPlayer', getCachedPlayer) - -AddEventHandler('playerDropped', function (reason) - if CachedPlayers[source] then - CachedPlayers[source].droppedTime = os.time() - CachedPlayers[source].dropped = true - end -end) \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/server/reports.lua b/server-data/resources/[esx]/EasyAdmin/server/reports.lua deleted file mode 100644 index 787c0a18f..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/reports.lua +++ /dev/null @@ -1,248 +0,0 @@ ------------------------------------- ------------------------------------- ----- DONT TOUCH ANY OF THIS IF YOU DON'T KNOW WHAT YOU ARE DOING ----- THESE ARE **NOT** CONFIG VALUES, USE THE CONVARS IF YOU WANT TO CHANGE SOMETHING ----- ----- ----- If you are a developer and want to change something, consider writing a plugin instead: ----- https://easyadmin.readthedocs.io/en/latest/plugins/ ----- ------------------------------------- ------------------------------------- - -AddEventHandler('playerDropped', function (reason) - for i, report in pairs(reports) do - if report.reporter == source or (report.reported and report.reported == source) then - removeReport(report.id) - end - end - if cooldowns[source] then - cooldowns[source] = nil - end -end) - -cooldowns = {} -- DO NOT TOUCH THIS - -Citizen.CreateThread(function() - - PlayerReports = {} - - if GetConvar("ea_enableCallAdminCommand", "true") == "true" then - RegisterCommand(GetConvar("ea_callAdminCommandName", "calladmin"), function(source, args, rawCommand) - if args[1] then - local time = os.time() - local cooldowntime = GetConvarInt("ea_callAdminCooldown", 60) - local source=source - if cooldowns[source] and cooldowns[source] > (time - cooldowntime) then - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("waitbeforeusingagain")) - return - end - - local reason = string.gsub(rawCommand, GetConvar("ea_callAdminCommandName", "calladmin").." ", "") - local reportid = addNewReport(0, source, _,reason) - for i,_ in pairs(OnlineAdmins) do - local notificationText = string.format(string.gsub(GetLocalisedText("playercalledforadmin"), "```", ""), getName(source,true,false), reason, reportid) - TriggerClientEvent("EasyAdmin:showNotification", i, notificationText) - end - - - local preferredWebhook = (reportNotification ~= "false") and reportNotification or moderationNotification - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText("playercalledforadmin"), getName(source, true, true), reason, reportid), "calladmin", 16776960) - --TriggerClientEvent('chatMessage', source, "^3EasyAdmin^7", {255,255,255}, GetLocalisedText("admincalled")) - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("admincalled")) - - time = os.time() - cooldowns[source] = time - else - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("invalidreport")) - end - end, false) - end - if GetConvar("ea_enableReportCommand", "true") == "true" then - RegisterCommand(GetConvar("ea_reportCommandName", "report"), function(source, args, rawCommand) - if args[2] then - local source = source - local id = args[1] - local valid = false - local minimumreports = GetConvarInt("ea_defaultMinReports", 3) - if GetConvar("ea_MinReportModifierEnabled", "true") == "true" then - if #GetPlayers() > GetConvarInt("ea_MinReportPlayers", 12) then - minimumreports = math.round(#GetPlayers()/GetConvarInt("ea_MinReportModifier", 4),0) - end - end - if id and not GetPlayerIdentifier(id, 1) then - for i, player in pairs(GetPlayers()) do - if string.find(string.lower(getName(player, true)), string.lower(id)) then - id = player - valid = true - break - end - end - else - valid = true - end - - - if id and valid then - local reason = string.gsub(rawCommand, GetConvar("ea_reportCommandName", "report").." " ..args[1].." ", "") - if not PlayerReports[id] then - PlayerReports[id] = { } - end - local addReport = true - for i, report in pairs(PlayerReports[id]) do - if report.source == source or report.sourceName == getName(source, true) then - addReport = false - end - end - if addReport then - table.insert(PlayerReports[id], {source = source, sourceName = getName(source, true), reason = reason, time = os.time()}) - local reportid = addNewReport(1, source, id, reason) - local preferredWebhook = (reportNotification ~= "false") and reportNotification or moderationNotification - SendWebhookMessage(preferredWebhook,string.format(GetLocalisedText("playerreportedplayer"), getName(source, false, true), getName(id, true, true), reason, #PlayerReports[id], minimumreports, reportid), "report", 16776960) - if GetConvar("ea_enableReportScreenshots", "true") == "true" then - TriggerEvent("EasyAdmin:TakeScreenshot", id) - end - - - for i,_ in pairs(OnlineAdmins) do - local notificationText = string.format(string.gsub(GetLocalisedText("playerreportedplayer"), "```", ""), getName(source, false, false), getName(id, true, false), reason, #PlayerReports[id], minimumreports, reportid) - TriggerClientEvent('chat:addMessage', i, { - template = '
{0}
', - args = { "^3EasyAdmin Report^7\n"..notificationText }, color = { 255, 255, 255 } - }) - TriggerClientEvent("EasyAdmin:showNotification", i, notificationText) - end - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("successfullyreported")) - - if #PlayerReports[id] >= minimumreports then - TriggerEvent("EasyAdmin:addBan", id, string.format(GetLocalisedText("reportbantext"), minimumreports), os.time()+GetConvarInt("ea_ReportBanTime", 86400)) - end - else - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("alreadyreported")) - end - else - TriggerClientEvent('chat:addMessage', source, { - template = '
{0}:
{1}
', - args = { "^3EasyAdmin^7", GetLocalisedText("reportedusageerror") }, color = { 255, 255, 255 } - }) - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("reportedusageerror")) - end - else - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("invalidreport")) - end - end, false) - end - - - function addNewReport(type, reporter, reported, reason) - local t = nil - if type == 1 then - t = {type=type, reporter=reporter, reporterName=getName(reporter, true), reported=reported, reportedName=getName(reported, true),reason=reason} - else - t = {type=type, reporter=reporter, reporterName=getName(reporter, true), reason=reason} - end - t.id = #reports+1 - reports[t.id] = t - for i,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:NewReport", i, 10000, t) - end - TriggerEvent("EasyAdmin:reportAdded", t) - return t.id - end - - RegisterServerEvent("EasyAdmin:ClaimReport", function(reportId) - if DoesPlayerHavePermission(source, "player.reports.claim") then - if not reports[reportId].claimed then - reports[reportId].claimed = source - reports[reportId].claimedName = getName(source,true) - for admin,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:ClaimedReport", admin, 10000, reports[reportId]) - end - TriggerEvent("EasyAdmin:reportClaimed", reports[reportId]) - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminclaimedreport"), getName(source, false, true), reportId), "reports", 16777214) - else - TriggerClientEvent("EasyAdmin:showNotification", source, GetLocalisedText("reportalreadyclaimed")) - end - end - end) - - function removeReport(index,reporter,reported,reason) - for i, report in pairs(reports) do - if (index and i == index) then - for admin,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:RemoveReport", admin, 10000, report) - end - TriggerEvent("EasyAdmin:reportRemoved", report) - reports[i] = nil - elseif (reporter and reporter == report.reporter) then - for admin,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:RemoveReport", admin, 10000, report) - end - TriggerEvent("EasyAdmin:reportRemoved", report) - reports[i] = nil - elseif (reported and reported == report.reported) then - for admin,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:RemoveReport", admin, 10000, report) - end - TriggerEvent("EasyAdmin:reportRemoved", report) - reports[i] = nil - end - end - end - - function removeSimilarReports(report) - for i, r in pairs(reports) do - if (report.reporter and report.reported) and (report.reporter == r.reporter and report.reported == r.reported) then - for admin,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:RemoveReport", admin, 10000, r) - end - TriggerEvent("EasyAdmin:reportRemoved", r) - reports[i] = nil - end - if (report.reason and report.reporter) and (report.reason == r.reason and report.reporter == r.reporter) then - for admin,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:RemoveReport", admin, 10000, r) - end - TriggerEvent("EasyAdmin:reportRemoved", r) - reports[i] = nil - end - if (report.reported) and (report.reported == r.reported) then - for admin,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:RemoveReport", admin, 10000, r) - end - TriggerEvent("EasyAdmin:reportRemoved", r) - reports[i] = nil - end - if (report.reporter) and (report.reporter == r.reporter) then - for admin,_ in pairs(OnlineAdmins) do - TriggerLatentClientEvent("EasyAdmin:RemoveReport", admin, 10000, r) - end - TriggerEvent("EasyAdmin:reportRemoved", r) - reports[i] = nil - end - end - end - - - function getAllReports() - return reports - end - exports('getAllReports', getAllReports) - - - - RegisterServerEvent("EasyAdmin:RemoveReport", function(report) - if DoesPlayerHavePermission(source, "player.reports.process") then - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminclosedreport"), getName(source, false, true), report.id), "reports", 16777214) - removeReport(report.id) - end - end) - - RegisterServerEvent("EasyAdmin:RemoveSimilarReports", function(report) - if DoesPlayerHavePermission(source, "player.reports.process") then - SendWebhookMessage(moderationNotification,string.format(GetLocalisedText("adminclosedreport"), getName(source, false, true), report.id), "reports", 16777214) - removeSimilarReports(report) - end - end) - -end) \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/server/webhook.lua b/server-data/resources/[esx]/EasyAdmin/server/webhook.lua deleted file mode 100644 index c8f3714a2..000000000 --- a/server-data/resources/[esx]/EasyAdmin/server/webhook.lua +++ /dev/null @@ -1,63 +0,0 @@ ------------------------------------- ------------------------------------- ----- DONT TOUCH ANY OF THIS IF YOU DON'T KNOW WHAT YOU ARE DOING ----- THESE ARE **NOT** CONFIG VALUES, USE THE CONVARS IF YOU WANT TO CHANGE SOMETHING ----- ----- ----- If you are a developer and want to change something, consider writing a plugin instead: ----- https://easyadmin.readthedocs.io/en/latest/plugins/ ----- ------------------------------------- ------------------------------------- - -ExcludedWebhookFeatures = {} -RegisterCommand("ea_testWebhook", function(source, args, rawCommand) - if DoesPlayerHavePermission(source, "server") then - SendWebhookMessage(moderationNotification, "**Testing Webhook for moderationNotification**", false, 65280) - SendWebhookMessage(detailNotification, "**Testing Webhook for detailNotification**", false, 65280) - SendWebhookMessage(reportNotification, "**Testing Webhook for reportNotification**", false, 65280) - PrintDebugMessage("Webhook Message Sent") - end -end, false) - -RegisterCommand("ea_excludeWebhookFeature", function(source, args, rawCommand) - if DoesPlayerHavePermission(source, "server") then - ExcludedWebhookFeatures = Set(args) - PrintDebugMessage("Webhook excludes set", 3) - end -end, false) - - -function isWebhookFeatureExcluded(feature) - return ExcludedWebhookFeatures[feature] -end -exports('isWebhookFeatureExcluded', isWebhookFeatureExcluded) - -function SendWebhookMessage(webhook,message,feature,colour,title,image) - moderationNotification = GetConvar("ea_moderationNotification", "false") - reportNotification = GetConvar("ea_reportNotification", "false") - detailNotification = GetConvar("ea_detailNotification", "false") - - local embed = { - { - ["color"] = (colour or 16777214), - ["title"] = "**"..(title or "EasyAdmin").."**", - ["description"] = message, - ["footer"] = { - ["text"] = "EasyAdmin on "..formatDateString(os.time()), - }, - } - } - if image then - embed[1]["image"] = { ["url"] = image } - end - - if GetConvar("ea_botLogChannel", "") ~= "" then - exports[GetCurrentResourceName()]:LogDiscordMessage(message, feature, colour) - return - end - - if webhook ~= "false" and ExcludedWebhookFeatures[feature] ~= true then - PerformHttpRequest(webhook, function(err, text, headers) end, 'POST', json.encode({embeds = embed}), { ['Content-Type'] = 'application/json' }) - end -end \ No newline at end of file diff --git a/server-data/resources/[esx]/EasyAdmin/shared/util_shared.lua b/server-data/resources/[esx]/EasyAdmin/shared/util_shared.lua deleted file mode 100644 index 5948bb4cf..000000000 --- a/server-data/resources/[esx]/EasyAdmin/shared/util_shared.lua +++ /dev/null @@ -1,352 +0,0 @@ -permissions = { - ["player.ban.temporary"] = false, - ["player.ban.permanent"] = false, - ["player.ban.view"] = false, - ["player.ban.edit"] = false, - ["player.ban.remove"] = false, - ["player.kick"] = false, - ["player.spectate"] = false, - ["player.teleport.single"] = false, - ["player.slap"] = false, - ["player.freeze"] = false, - ["player.screenshot"] = false, - ["player.mute"] = false, - ["player.warn"] = false, - ["player.teleport.everyone"] = false, - ["player.reports.view"] = false, - ["player.reports.claim"] = false, - ["player.reports.process"] = false, - ["server.cleanup.cars"] = false, - ["server.cleanup.props"] = false, - ["server.cleanup.peds"] = false, - ["server.permissions.read"] = false, - ["server.permissions.write"] = false, - ["server.shortcut.add"] = false, - ["server.reminder.add"] = false, - ["server.announce"] = false, - ["server.convars"] = false, - ["server.resources.start"] = false, - ["server.resources.stop"] = false, - ["server.chat"] = false, - ["immune"] = false, - ["anon"] = false, -} - - -function PrintDebugMessage(msg,level) - loglevel = (GetConvarInt("ea_logLevel", 1)) - if not level or not tonumber(level) then level = 3 end - - if level == 1 and loglevel >= level then -- ERROR Loglevel - Citizen.Trace("^1"..GetCurrentResourceName().."^7: "..msg.."^7\n") - - if IsDuplicityVersion() then - for i,k in pairs(GetOnlineAdmins()) do - TriggerClientEvent("EasyAdmin:showNotification", i, string.gsub(msg, "%^%d", "")) - end - else - TriggerEvent("EasyAdmin:showNotification", string.gsub(msg, "%^%d", "")) - end - elseif level == 2 and loglevel >= level then -- WARN Loglevel - Citizen.Trace("^3"..GetCurrentResourceName().."^7: "..msg.."^7\n") - elseif level == 3 and loglevel >= level then -- INFO Loglevel - Citizen.Trace("^0"..GetCurrentResourceName().."^7: "..msg.."^7\n") - elseif level == 4 and loglevel >= level then -- DEV Loglevel - Citizen.Trace("^7"..GetCurrentResourceName().."^7: "..msg.."^7\n") - elseif level > 4 and loglevel >= level then -- anything above 4 shouldn't exist, but kept just in case - Citizen.Trace("^5"..GetCurrentResourceName().."^7: "..msg.."^7\n") - end -end - -if IsDuplicityVersion() then - if GetConvar("ea_enableDebugging", "false") ~= "false" or GetConvarInt("ea_logLevel", 1) ~= 1 then - SetConvar("ea_enableDebugging", "false") - if GetConvarInt("ea_logLevel", 1) == 1 then - SetConvar("ea_logLevel", 3) - end - if GetConvarInt("ea_logLevel", 1) > 1 then - PrintDebugMessage("Debug Messages Enabled, Verbosity is ^2"..GetConvarInt("ea_logLevel", 1).."^7.", 2) - end - else - enableDebugging = false - end -end - -if not IsDuplicityVersion() then - RegisterNUICallback("keyboardFinished", function(data, cb) - keyboardResult = data.result - keyboardState = data.state - cb('ok') - end) - - function ttsSpeechItem(item) - local ttsText = "" - if not item or GetResourceKvpInt('ea_tts') == 0 then return end - if type(item.Text) == "table" then - if item.Text._Text then - ttsText = item.Text._Text - if item.Label then - ttsText = ttsText .. ", " .. item.Label.Text._Text - end - end - elseif type(item.Text) == "function" then - ttsText = item.Base.Text._Text - if item.Checked == true then - ttsText = ttsText .. ", Checked" - elseif item.Checked == false then - ttsText = ttsText .. ", Unchecked" - end - if item.ItemText then - ttsText = ttsText .. ", " .. item.ItemText._Text - end - end - SendNUIMessage({action= "speak", text=ttsText}) - end - - function ttsSpeechText(text) - if not text or GetResourceKvpInt('ea_tts') == 0 then return end - SendNUIMessage({action= "speak", text=text}) - end -end - - -function displayKeyboardInput(title,default,maxLength) - if alreadyTyping then return nil end - keyboardResult, keyboardState = nil - local label = GetLabelText(title) - - SetNuiFocus(true, true) - SendNUIMessage({action= "open", title=label, default=default, maxLength=maxLength, resource=GetCurrentResourceName()}) - - alreadyTyping = true - - while not keyboardState do --While typing is not aborted and not finished, this loop waits - Citizen.Wait(0) - end - - alreadyTyping = false - SetNuiFocus(false,false) - if keyboardState == 0 then - return keyboardResult - else - return nil - end -end - -function copyToClipboard(text) - SendNUIMessage({action= "clip", text=text}) - TriggerEvent("EasyAdmin:showNotification", GetLocalisedText("copiedtoclipboard")) -end - -function DoesPlayerHavePermission(player, object) - if IsDuplicityVersion() then - local haspermission = false - if (player == 0 or player == "") then - return true - end-- Console. It's assumed this will be an admin with access. - - if not string.find(object, "easyadmin.") then -- compatability with outdated plugins - object = "easyadmin."..object - end - - if IsPlayerAceAllowed(player,object) then -- check if the player has access to this permission - haspermission = true - PrintDebugMessage(getName(player, true).." has Permissions for "..object..".", 4) - else - haspermission = false - PrintDebugMessage(getName(player, true).." does not have Permissions for "..object..".", 4) - end - return haspermission - else - return (permissions[object] or false) - end -end -exports('DoesPlayerHavePermission', DoesPlayerHavePermission) - -function DoesPlayerHavePermissionForCategory(player, object) - for perm in pairs(permissions) do - if string.startswith(perm, object) then - if DoesPlayerHavePermission(player, perm) then - return true - end - end - end - return false -end -exports('DoesPlayerHavePermissionForCategory', DoesPlayerHavePermissionForCategory) - - -function GetVersion() - local resourceName = GetCurrentResourceName() - local version = GetResourceMetadata(resourceName, 'version', 0) - local is_master = GetResourceMetadata(resourceName, 'is_master', 0) == "yes" or false - return version, is_master -end -exports('GetVersion', GetVersion) - - -function loadLanguageStrings() - local strfile = LoadResourceFile(GetCurrentResourceName(), "language/"..GetConvar("ea_LanguageName", "en")..".json") - if strfile then - strings = json.decode(strfile)[1] - else - strings = {language=GetConvar("ea_LanguageName", "en")} - end -end - -function GetLocalisedText(string) - if not strings then return "Strings not Loaded yet!" end - if not string then return "No String!" end - if strings[string] then - return strings[string] - else - return "String "..string.." not found in "..strings.language - end -end -exports('GetLocalisedText', GetLocalisedText) - -function formatDateString(string) - local dateFormat = GetConvar("ea_dateFormat", '%d/%m/%Y %H:%M:%S') - return os.date(dateFormat, string) -end -exports('formatDateString', formatDateString) - -function formatShortcuts(thisstring) - if not thisstring then return thisstring end - local cleanString = string.gsub(string.lower(thisstring), " ", "") - for shortcut,value in pairs(MessageShortcuts) do - if string.lower(shortcut) == cleanString then - thisstring = value - end - end - return thisstring -end -exports('formatShortcuts', formatShortcuts) - -function formatRightString(thisstring, customWidth) - if not thisstring then return thisstring end -- in case string is nil, just yeet it back. - local width = (customWidth or maxRightTextWidth) - if string.len(thisstring) > width then - thisstring = string.sub(thisstring, 1, width)..".." - end - - return thisstring -end - --- some util funcs so i dont have to mess with NativeUI Source Code. -function getMenuItemTitle(item) - if (item.Base and type(item.Base.Text) == "table" and item.Base.Text._Text) then - return item.Base.Text._Text - elseif (item.Text and type(item.Text) == "table" and item.Text._Text) then - return item.Text._Text - end -end - -function setMenuItemTitle(item,text) - if (item.Base and type(item.Base.Text) == "table" and item.Base.Text._Text) then - item.Base.Text._Text = text - elseif (item.Text and type(item.Text) == "table" and item.Text._Text) then - item.Text._Text = text - end -end - -function getCachedPlayer(playerId) - if CachedPlayers[playerId] then - return CachedPlayers[playerId] - else - return false - end -end -exports('getCachedPlayer', getCachedPlayer) - -function math.round(num, numDecimalPlaces) - if numDecimalPlaces and numDecimalPlaces>0 then - local mult = 10^numDecimalPlaces - return math.floor(num * mult + 0.5) / mult - end - return math.floor(num + 0.5) -end - -function string.split(inputstr, sep) - if sep == nil then - sep = "%s" - end - local t={} ; i=1 - for str in string.gmatch(inputstr, "([^"..sep.."]+)") do - t[i] = str - i = i + 1 - end - return t -end - -function string.reverse(s) - local r = "" - for p,c in utf8.codes(s) do - r = utf8.char(c)..r - end - return r -end - -function string.startswith(string,start) - return string:sub(1,string.len(start))==start -end - ---- http://www.lua.org/pil/11.5.html -function Set (list) - local set = {} - for _, l in ipairs(list) do set[l] = true end - return set -end - --- Convert a lua table into a lua syntactically correct string -function table_to_string(tbl) - return json.encode(tbl) -end - -function mergeTables(t1, t2) - local t = t1 - for i,v in pairs(t2) do - table.insert(t, v) - end - return t -end - - --- terrible function to look for URLs in a string -function matchURL(text_with_URLs) - - local domains = [[.ac.ad.ae.aero.af.ag.ai.al.am.an.ao.aq.ar.arpa.as.asia.at.au.aw.ax.az.ba.bb.bd.be.bf.bg.bh.bi.biz.bj.bm.bn.bo.br.bs.bt.bv.bw.by.bz.ca.cat.cc.cd.cf.cg.ch.ci.ck.cl.cm.cn.co.com.coop.cr.cs.cu.cv.cx.cy.cz.dd.de.dj.dk.dm.do.dz.ec.edu.ee.eg.eh.er.es.et.eu.fi.firm.fj.fk.fm.fo.fr.fx.ga.gb.gd.ge.gf.gh.gi.gl.gm.gn.gov.gp.gq.gr.gs.gt.gu.gw.gy.hk.hm.hn.hr.ht.hu.id.ie.il.im.in.info.int.io.iq.ir.is.it.je.jm.jo.jobs.jp.ke.kg.kh.ki.km.kn.kp.kr.kw.ky.kz.la.lb.lc.li.lk.lr.ls.lt.lu.lv.ly.ma.mc.md.me.mg.mh.mil.mk.ml.mm.mn.mo.mobi.mp.mq.mr.ms.mt.mu.museum.mv.mw.mx.my.mz.na.name.nato.nc.ne.net.nf.ng.ni.nl.no.nom.np.nr.nt.nu.nz.om.org.pa.pe.pf.pg.ph.pk.pl.pm.pn.post.pr.pro.ps.pt.pw.py.qa.re.ro.ru.rw.sa.sb.sc.sd.se.sg.sh.si.sj.sk.sl.sm.sn.so.sr.ss.st.store.su.sv.sy.sz.tc.td.tel.tf.tg.th.tj.tk.tl.tm.tn.to.tp.tr.travel.tt.tv.tw.tz.ua.ug.uk.um.us.uy.va.vc.ve.vg.vi.vn.vu.web.wf.ws.xxx.ye.yt.yu.za.zm.zr.zw]] - - local tlds = {} - for tld in domains:gmatch'%w+' do - tlds[tld] = true - end - local function max4(a,b,c,d) return math.max(a+0, b+0, c+0, d+0) end - local protocols = {[''] = 0, ['http://'] = 0, ['https://'] = 0, ['ftp://'] = 0} - local finished = {} - - for pos_start, url, prot, subd, tld, colon, port, slash, path in - text_with_URLs:gmatch'()(([%w_.~!*:@&+$/?%%#-]-)(%w[-.%w]*%.)(%w+)(:?)(%d*)(/?)([%w_.~!*:@&+$/?%%#=-]*))' - do - if protocols[prot:lower()] == (1 - #slash) * #path and not subd:find'%W%W' - and (colon == '' or port ~= '' and port + 0 < 65536) - and (tlds[tld:lower()] or tld:find'^%d+$' and subd:find'^%d+%.%d+%.%d+%.$' - and max4(tld, subd:match'^(%d+)%.(%d+)%.(%d+)%.$') < 256) - then - finished[pos_start] = true - return url - end - end - - for pos_start, url, prot, dom, colon, port, slash, path in - text_with_URLs:gmatch'()((%f[%w]%a+://)(%w[-.%w]*)(:?)(%d*)(/?)([%w_.~!*:@&+$/?%%#=-]*))' - do - if not finished[pos_start] and not (dom..'.'):find'%W%W' - and protocols[prot:lower()] == (1 - #slash) * #path - and (colon == '' or port ~= '' and port + 0 < 65536) - then - return url - end - end -end -exports('matchURL', matchURL) \ No newline at end of file