From e8a42be368aa2a15c623a3e877ec39fca33edd8e Mon Sep 17 00:00:00 2001 From: Ritabrata Das Date: Sat, 15 Feb 2025 19:17:52 +0530 Subject: Initial Commit for docs --- .gitignore | 6 - LICENSE | 674 --------------------- README.md | 106 ---- config.py | 80 --- lib/Aircraft.py | 103 ---- lib/DiscordClient.py | 42 -- lib/PacketManager/PacketManager.py | 14 - lib/PacketManager/__init__.py | 0 lib/PacketManager/packets/FSNETCMD_ADDOBJECT.py | 67 -- lib/PacketManager/packets/FSNETCMD_AIRCMD.py | 80 --- .../packets/FSNETCMD_AIRPLANESTATE.py | 313 ---------- lib/PacketManager/packets/FSNETCMD_EMPTYPACKET.py | 19 - lib/PacketManager/packets/FSNETCMD_ENVIRONMENT.py | 76 --- lib/PacketManager/packets/FSNETCMD_ERROR.py | 22 - lib/PacketManager/packets/FSNETCMD_FOGCOLOR.py | 21 - lib/PacketManager/packets/FSNETCMD_GETDAMAGE.py | 48 -- lib/PacketManager/packets/FSNETCMD_JOINAPPROVAL.py | 22 - lib/PacketManager/packets/FSNETCMD_JOINREQUEST.py | 29 - lib/PacketManager/packets/FSNETCMD_KILLSERVER.py | 14 - lib/PacketManager/packets/FSNETCMD_LIST.py | 70 --- lib/PacketManager/packets/FSNETCMD_LOADFIELD.py | 30 - lib/PacketManager/packets/FSNETCMD_LOCKON.py | 31 - lib/PacketManager/packets/FSNETCMD_LOGOFF.py | 19 - lib/PacketManager/packets/FSNETCMD_LOGON.py | 58 -- .../packets/FSNETCMD_MISSILELAUNCH.py | 97 --- lib/PacketManager/packets/FSNETCMD_NULL.py | 16 - .../packets/FSNETCMD_PREPARESIMULATION.py | 14 - lib/PacketManager/packets/FSNETCMD_READBACK.py | 39 -- .../packets/FSNETCMD_REJECTJOINREQ.py | 21 - .../packets/FSNETCMD_REMOVEAIRPLANE.py | 13 - lib/PacketManager/packets/FSNETCMD_REMOVEGROUND.py | 13 - lib/PacketManager/packets/FSNETCMD_REPORTSCORE.py | 50 -- .../packets/FSNETCMD_REQUESTTESTAIRPLANE.py | 14 - .../packets/FSNETCMD_SERVER_FORCE_JOIN.py | 14 - lib/PacketManager/packets/FSNETCMD_SKYCOLOR.py | 21 - lib/PacketManager/packets/FSNETCMD_SMOKECOLOR.py | 25 - lib/PacketManager/packets/FSNETCMD_TESTPACKET.py | 14 - lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py | 24 - lib/PacketManager/packets/FSNETCMD_UNJOIN.py | 26 - lib/PacketManager/packets/FSNETCMD_WEAPONCONFIG.py | 55 -- lib/PacketManager/packets/__init__.py | 67 -- lib/PacketManager/packets/constants.py | 472 --------------- lib/Player.py | 40 -- lib/YSchat.py | 20 - lib/YSendFlight.py | 6 - lib/YSplayer.py | 47 -- lib/YSundead.py | 13 - lib/YSviaversion.py | 11 - lib/__init__.py | 0 lib/discordSync.py | 100 --- lib/parseFlightData.py | 67 -- lib/plugin_manager.py | 74 --- lib/triggerCommand.py | 13 - lib/triggerRespectiveHook.py | 127 ---- plugins/allcaps.py | 23 - plugins/chat_weather_setter.py | 100 --- plugins/command_test.py | 26 - plugins/custom_aircraft_list/Plugin.py | 42 -- plugins/custom_aircraft_list/__init__.py | 2 - plugins/custom_aircraft_list/custom_list.json | 14 - plugins/discolights.py | 22 - plugins/over_g_damage.py | 31 - plugins/smoke_on_damage/Plugin.py | 48 -- plugins/smoke_on_damage/__init__.py | 2 - proxy.py | 254 -------- requirements.txt | 9 - tests/__init__.py | 0 tests/packet01_logon_test.py | 46 -- tests/packet04_loadfield_test.py | 38 -- tests/packet05_addobject_test.py | 39 -- tests/packet08_joinrequest_test.py | 31 - tests/packet09_joinapproval_test.py | 26 - 72 files changed, 4210 deletions(-) delete mode 100644 .gitignore delete mode 100644 LICENSE delete mode 100644 README.md delete mode 100644 config.py delete mode 100644 lib/Aircraft.py delete mode 100644 lib/DiscordClient.py delete mode 100644 lib/PacketManager/PacketManager.py delete mode 100644 lib/PacketManager/__init__.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_ADDOBJECT.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_AIRCMD.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_EMPTYPACKET.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_ENVIRONMENT.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_ERROR.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_FOGCOLOR.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_GETDAMAGE.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_JOINAPPROVAL.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_JOINREQUEST.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_KILLSERVER.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_LIST.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_LOADFIELD.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_LOCKON.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_LOGOFF.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_LOGON.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_MISSILELAUNCH.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_NULL.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_PREPARESIMULATION.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_READBACK.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_REJECTJOINREQ.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_REMOVEAIRPLANE.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_REMOVEGROUND.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_REPORTSCORE.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_REQUESTTESTAIRPLANE.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_SERVER_FORCE_JOIN.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_SKYCOLOR.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_SMOKECOLOR.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_TESTPACKET.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_UNJOIN.py delete mode 100644 lib/PacketManager/packets/FSNETCMD_WEAPONCONFIG.py delete mode 100644 lib/PacketManager/packets/__init__.py delete mode 100644 lib/PacketManager/packets/constants.py delete mode 100644 lib/Player.py delete mode 100644 lib/YSchat.py delete mode 100644 lib/YSendFlight.py delete mode 100644 lib/YSplayer.py delete mode 100644 lib/YSundead.py delete mode 100644 lib/YSviaversion.py delete mode 100644 lib/__init__.py delete mode 100644 lib/discordSync.py delete mode 100644 lib/parseFlightData.py delete mode 100644 lib/plugin_manager.py delete mode 100644 lib/triggerCommand.py delete mode 100644 lib/triggerRespectiveHook.py delete mode 100644 plugins/allcaps.py delete mode 100644 plugins/chat_weather_setter.py delete mode 100644 plugins/command_test.py delete mode 100644 plugins/custom_aircraft_list/Plugin.py delete mode 100644 plugins/custom_aircraft_list/__init__.py delete mode 100644 plugins/custom_aircraft_list/custom_list.json delete mode 100644 plugins/discolights.py delete mode 100644 plugins/over_g_damage.py delete mode 100644 plugins/smoke_on_damage/Plugin.py delete mode 100644 plugins/smoke_on_damage/__init__.py delete mode 100644 proxy.py delete mode 100644 requirements.txt delete mode 100644 tests/__init__.py delete mode 100644 tests/packet01_logon_test.py delete mode 100644 tests/packet04_loadfield_test.py delete mode 100644 tests/packet05_addobject_test.py delete mode 100644 tests/packet08_joinrequest_test.py delete mode 100644 tests/packet09_joinapproval_test.py diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 509d35b..0000000 --- a/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.ipynb_checkpoints/ -__pycache__/ -lib/__pycache__/ -venv/ -flightPacketParser.ipynb -config.py diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 64c8d22..0000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ -GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - Ritabrata Das (https://theindiandev.in) - Copyright (C) 2025 Ritabrata Das - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Sakuya AC Copyright (C) 2025 Ritabrata Das - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/README.md b/README.md deleted file mode 100644 index d035475..0000000 --- a/README.md +++ /dev/null @@ -1,106 +0,0 @@ -# **Sakuya AC** -
- sakuya walking gif -
- -### Perfect and Elegant Anti Cheat for your YSFlight server ---- -Well it started as an anti cheat... and now aims to add more features to make YSFlight more realstic server side -for vanilla clients. - -## Test Server - -I have a server running at ``9m.theindiandev.in`` and port ``7915`` -with [2ch map](https://w.atwiki.jp/ysflight/pages/26.html) and latest version of -Sakuya AC and G Limiter at 20. It also has all the experimental options turned on. - ---- - -## Contributors - -- Skipper -- Biry (Emotional Support) - ---- - -## **Features** -- Intercepts and parses network packets to monitor gameplay. -- Adds features like G Limiter and Smoke Emission on Death. -- All features are server side, vanilla client can join -- Supports clients post 20150425 version to join the server (Experimental) -- Easy configuration via `config.py`. -- Plugin Support - ---- - -## **Getting Started** - -### **Prerequisites** -- Python 3.9+ - -### **Installation** -1. Clone the repository: - ```bash - git clone https://github.com/the-indian-dev/sakuya-ac.git - cd sakuya-ac - ``` - -2. Edit `config.py` to match your server and client setup. -> **Warning** -> Please ensure that you have put the correct YSFlight version in YSF_VERSION variable in `config.py`. This is important for the proxy to work correctly. - -3. Run the proxy server: - ```bash - python proxy.py - ``` ---- - -## **Configuration** -All configuration is done via the `config.py` file. Example: - -```python -# config.py -SERVER_HOST = "127.0.0.1" # YSFlight server IP -SERVER_PORT = 7915 # YSFlight server port -PROXY_PORT = 9000 # Port where the proxy listens -``` - ---- - -## **Usage** -1. Point your YSFlight client to the proxy server (e.g., `127.0.0.1:9000`). -2. Monitor logs to view real-time parsing and activity tracking. - ---- -## **TODO :memo:** -1. Add more detection rules. -2. Radar. -3. More documentation. ---- - -## **Contact** -- If you have questions, feedback, or suggestions, feel free to reach out to me on Discord: **@theindiandev** -- You can email me at **theindiandev@theindiandev.in** -- Join our discord server [here](https://discord.gg/CgEdmBQQMr) ---- - -## **License** -This project is licensed under the GNU General Public License v3.0. See the [LICENSE](LICENSE) file for details. - ---- - -## **Reporting Issues** -1. Use Github issues tab to open an issue. -2. Please provide detailed information about the issue you are facing. -3. Give us all the log from console, it would be better if logging level was set to ``DEBUG`` -4. Please also give us the replay .yfs file while reporting issue -5. If you have a feature request, please open an issue with the label `enhancement`. ---- - -## **Acknowledgments** -- Thanks to Vincet A's work on YS Protocol -- Thanks to my friends at 9th Matrix for helping me out -- Pixel art GIF credit: [Tenor](https://tenor.com/view/sakuemon-pixel-art-touhou-sakuya-maid-gif-27137533). - ---- -:star: Consider giving a star to this repo if you like this project diff --git a/config.py b/config.py deleted file mode 100644 index 8071653..0000000 --- a/config.py +++ /dev/null @@ -1,80 +0,0 @@ -from logging import DEBUG, WARN, INFO, CRITICAL - -# Configuration -# Logging Level : Most of the times having INFO level is enough -# But while submitting issues, please consider sending the logs with DEBUG level -LOGGING_LEVEL = INFO - -# Server Configuration -# Replace with the YSFlight server address -SERVER_HOST = "127.0.0.1" -SERVER_PORT = 7915 # Please put where the normal YSFlight server is running -# Port for the proxy server -PROXY_PORT = 9000 - -# Welcome Message to the playe -# For formatting use {username} -# eg. "Welcome {username} to the server!" -# > Welcome Sakuya to the server! - -WELCOME_MESSAGE = "Welcome {username} to the server!" - -# Command Prefix for the server -# When commands are entered in chat, this will be treated -# as command when it starts with the prefix -# eg. if PREFIX = "/" -# /help will be treated as command - -PREFIX = "/" - -# Native YSFlight Server -# Please select the YSFlight server version for the -# local ysflight server -# Tested only with 20150425 version - -YSF_VERSION = 20150425 - -# Enable ViaVersion? This allows you clients post-20150425 versions -# to join your YSFlight server, this may however raise some issues -# Currently experimental - -VIA_VERSION = True - -# G Limit (abs(g) >= limit) and the player gets killed -# If you wish to turn off G Limiter, consider using some -# aribitary value like 100 -G_LIM = 4 - -# Will appear as message + player name -# eg. Detected health hack by -HEALTH_HACK_MESSAGE = "Detected for health hack" - -# Enable planes smoking on low life -# If true, planes on life < SMOKE_LIFE will emit black smoke -# They will also have an engine breakdown, not being able to turn -# on afterburner. Also they won't be able to fire missiles - -SMOKE_PLANE = True - -# Planes smoking minimum life - -SMOKE_LIFE = 5 - - -# Discord chat integration -# ```bash -# pip install -r requirements.txt -# ``` -# to install dependencies required to run the discord chat integration -# -# On Modern Linux distros you may need to create a virtual environment to install -# the dependencies - -DISCORD_ENABLED = False - -# Make sure to enable read message intent for the bot. - -DISCORD_TOKEN = "DISCORD_BOT_TOKEN" - -# Channel ID for the chat -CHANNEL_ID = 0 # Channel ID, as an integer diff --git a/lib/Aircraft.py b/lib/Aircraft.py deleted file mode 100644 index 5e6e24d..0000000 --- a/lib/Aircraft.py +++ /dev/null @@ -1,103 +0,0 @@ -from lib.PacketManager.packets import FSNETCMD_AIRPLANESTATE -from lib.PacketManager.packets.FSNETCMD_AIRCMD import FSNETCMD_AIRCMD -from logging import debug - -class Aircraft: - """ - An aircraft class - this will hold the info from the Airplane state, weapons etc packets.""" - def __init__(self, parent=None): - self.parent = parent - self.name = "" - self.position = [0,0,0] - self.attitude = [0,0,0] - self.initial_config = {} - self.custom_config = {} - self.life = -1 - self.prev_life = -1 - self.id = -1 - self.last_packet = None - self.damage_engine_warn_sent = False - self.last_over_g_message = 0 - self.just_repaired = False - - def reset(self): - """Resets the aircraft""" - self.name = "" - self.position = [0,0,0] - self.attitude = [0,0,0] - self.initial_config = {} - self.custom_config = {} - self.life = -1 - self.prev_life = -1 - self.id = -1 - self.last_packet = None - self.damage_engine_warn_sent = False - self.just_repaired = False - - def set_position(self, position:list): - """Sets the position of the aircraft from the Airplane state packet""" - self.position = position - - def set_attitude(self, attitude:list): - """Sets the attitude of the aircraft from the Airplane state packet""" - self.attitude = attitude - - def get_position(self): - """Returns the position of the aircraft""" - return self.position - - def get_altitude(self): - """Returns the altitude in m""" - return self.position[2] - - def get_attitude(self): - """Returns the attitude of the aircraft""" - return self.attitude - - def set_initial_config(self, config:dict): - """Sets the initial config of the aircraft""" - for key in config: - self.initial_config[key] = config[key] - - def get_initial_config_value(self, key:str): - """Returns the value of the initial config""" - if key in self.initial_config: - return self.initial_config[key] - - return None - - def set_custom_config_value(self, key:str, value): - """Sets a custom config value""" - self.custom_config[key] = value - #Send this to the client. - - def add_state(self, packet:FSNETCMD_AIRPLANESTATE): - """Adds the state of the aircraft""" - - if packet.player_id != self.id: - return None - if self.life == -1: - self.life=packet.life - - self.prev_life = self.life - - self.life = packet.life - self.set_position(packet.position) - self.set_attitude(packet.atti) - self.last_packet = packet - return packet - - def check_command(self,command:FSNETCMD_AIRCMD): - """Checks the command, and adds it to the aircraft""" - if command.aircraft_id != self.id: - return - if command.command: - self.initial_config[command.command[0]] = command.command[1] - debug(f"Command: {command.command}") - - def set_afterburner(self, enabled:bool): - """If the afterburner is avaialble on the aircraft, will send a command - to toggle it.""" - if self.get_initial_config_value("AFTBURNR") == "TRUE": - return FSNETCMD_AIRCMD.set_afterburner(self.id,enabled, True) - return None diff --git a/lib/DiscordClient.py b/lib/DiscordClient.py deleted file mode 100644 index 431a1d1..0000000 --- a/lib/DiscordClient.py +++ /dev/null @@ -1,42 +0,0 @@ -import discord -import asyncio -from lib.PacketManager.packets.FSNETCMD_TEXTMESSAGE import FSNETCMD_TEXTMESSAGE -from config import DISCORD_TOKEN, CHANNEL_ID - -class DiscordClient(discord.Client): - - def __init__(self, intents, parent=None): - super().__init__(intents=intents) - self.parent = parent - - async def on_ready(self): - await self.check_messages() - - async def on_message(self, message): - if message.channel.id == CHANNEL_ID: - if message.author.id == self.user.id: - return - author = message.author.name - content = message.content - messageToSendToClients = FSNETCMD_TEXTMESSAGE.encode(author, content) - if self.parent: - self.parent.send_to_all(messageToSendToClients) - - async def send_message(self, message): - channel = self.get_channel(CHANNEL_ID) - if channel: - message = await channel.send(message) - - async def check_messages(self): - while True: - if self.parent: - for message in self.parent.chatLog: - await self.send_message(message) - self.parent.chatLog.remove(message) - await asyncio.sleep(1) - - def start_bot(self): - loop = asyncio.get_event_loop() - loop.create_task(self.check_messages()) - self.run(DISCORD_TOKEN) - diff --git a/lib/PacketManager/PacketManager.py b/lib/PacketManager/PacketManager.py deleted file mode 100644 index 489b46a..0000000 --- a/lib/PacketManager/PacketManager.py +++ /dev/null @@ -1,14 +0,0 @@ -from struct import unpack, pack -from lib.PacketManager.packets.constants import MESSAGE_TYPES, FSWEAPON_DICT, GUIDEDWEAPONS - - -class PacketManager: - - def __init__(self): - pass - - def get_packet_type(self, data: bytes): - #Returns the message type of that packet. - if len(data) < 4: - return None - return MESSAGE_TYPES[unpack("=120 and should_decode: - self.decode() - - def decode(self): - self.object_type, self.net_type = unpack("HH", self.buffer[4:8]) - #If object_type = 0, then it's an aircraft, and client will send - # FSNETREADBACK_ADDAIRPLANE - #If object_types = 1, then it's a ground object, and client will send - # FSNETREADBACK_ADDGROUND - self.object_id = unpack("I", self.buffer[8:12])[0] - self.iff, _ = unpack("hh", self.buffer[12:16]) - self.pos = list(unpack("fff", self.buffer[16:28])) - self.atti = list(unpack("fff", self.buffer[28:40])) - self.identifier = unpack("32s", self.buffer[40:72])[0].decode().strip('\x00') - self.substrname = unpack("32s", self.buffer[72:104])[0].decode().strip('\x00') - self.ysfid = unpack("I", self.buffer[104:108])[0] - self.flags, self.flags0 = unpack("II", self.buffer[108:116]) - self.outsideRadius = unpack("f", self.buffer[116:120])[0] - - if len(self.buffer)>=128: - self.aircraft_class, self.aircraft_category = unpack("hh", self.buffer[120:124]) - #There is an extra short, but it's just set to 0 - if len(self.buffer) >= 176: - self.pilot = unpack("32s", self.buffer[124:156])[0].decode().strip('\x00') - - @staticmethod - def encode(object_type, net_type, object_id, iff, pos, atti, identifier, substrname, ysfid, - flags, flags0, outside_radius, aircraft_class=None, aircraft_category=None, - pilot=None, with_size:bool=False): - - buffer = pack('IHH', 5, object_type, net_type) - buffer += pack('IHHffffff', object_id, iff, 0, pos[0], pos[1], pos[2], atti[0], atti[1], atti[2]) - buffer += pack('32s32sI', identifier.encode(), substrname.encode(), ysfid) - buffer += pack('II', flags, flags0) - buffer += pack('f', outside_radius) - - if aircraft_class and aircraft_category: - buffer += pack("hhh", aircraft_class, aircraft_category, 0) - if pilot: - buffer += pack("32s", pilot.encode()) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_AIRCMD.py b/lib/PacketManager/packets/FSNETCMD_AIRCMD.py deleted file mode 100644 index beaade8..0000000 --- a/lib/PacketManager/packets/FSNETCMD_AIRCMD.py +++ /dev/null @@ -1,80 +0,0 @@ -from struct import pack, unpack -from .constants import AIRCMD_KEYWORDS -from typing import Union # Make it backwards compatible for python 3.9 - -class FSNETCMD_AIRCMD: #30 - - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.aircraft_id = None - self.message = None - self.command = None - if should_decode: - self.decode() - - def decode(self): - self.aircraft_id = unpack("I", self.buffer[4:8])[0] - self.message = self.buffer[8:].decode("utf-8").strip("\x00") - if self.message.startswith('*'): - self.command = self.get_command_from_message(self.message) - - def get_command_from_message(self, message:str): - """ - If the messages are prefixed with a *, then it is usually an engine/.dat - command, such as WEIGFUEL being the weight of the fuel. - Command would be something like *43 1000 - """ - message = message[1:] - engine_code = message.split(" ")[0] - try: - command = int(engine_code) - command = AIRCMD_KEYWORDS[command] - except ValueError: - return None - value = message.split(" ")[1] - return command, value - - @staticmethod - def encode(aircraft_id:int, message:str, with_size:bool=False): - buffer = pack("I",30)+pack("I",aircraft_id)+message.encode("utf-8") - buffer = buffer + b"\x00" #Last padding - if with_size: - return pack("I",len(buffer))+buffer - return buffer - - @staticmethod - def set_payload(aircraft_id:int, payload:int, units:str='kg', with_size:bool=False): - """ - This will set the payload of the aircraft, useful if you want to - load or unload passengers/cargo - for YSRP I use this to load and unload - on mission start and end. - """ - payload = str(payload) - message = f"INITLOAD {payload} {units}" - return FSNETCMD_AIRCMD.encode(aircraft_id, message, with_size) - - @staticmethod - def set_command(aircraft_id:int, command:str, value: Union[str, int], with_size:bool=False): - """ - This will set the command of the aircraft, useful if you want to - set the engine power, fuel, etc. - """ - if command in AIRCMD_KEYWORDS: - command = AIRCMD_KEYWORDS.index(command) - - message = f"*{command} {value}" - return FSNETCMD_AIRCMD.encode(aircraft_id, message, with_size) - - @staticmethod - def set_afterburner(aircarft_id:int, enabled:int, with_size:bool=False): - """ - This will set the afterburner of the aircraft, useful if you want to - enable or disable the afterburner. - """ - - command = "AFTBURNR" - value = str(enabled).upper() - return FSNETCMD_AIRCMD.set_command(aircarft_id, command, value, with_size) - - def __str__(self): - return f"Aircraft ID : {self.aircraft_id}; Message : {self.message}; Command : {self.command}" diff --git a/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py b/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py deleted file mode 100644 index 3ebf8d6..0000000 --- a/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py +++ /dev/null @@ -1,313 +0,0 @@ -from struct import pack, unpack -from math import pi -import math -from logging import debug - -class FSNETCMD_AIRPLANESTATE: #11 - """ - This packet is sent by the client to the server to update the state of the aircraft. - The server sends this to the client to update the state of the aircraft. - - Versions: - Version 0: vh, vp and vr are 16bit shorts - >= 1: vh, vp and vr are 32bit integer appended at the end. Because ...why? - >=2: includes thrust vector, reverser and bombbay - >=3: idOnServer is 32bit int - 4 and 5: Short version of vh, vp and vr - 4: thrust vector and bombbay - 5: no thrust vector or bombbay - """ - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.remote_time = None - self.player_id = None - self.packet_version = None - self.position = [0,0,0] - self.atti = [0,0,0] - self.velocity = [0,0,0] - self.atti_velocity = [0,0,0] - self.smoke_oil = None - self.fuel = None - self.payload = None - self.flight_state = None - self.vgw = None - self.spoiler = None - self.landing_gear = None - self.flap = None - self.brake = None - self.flags = { - "ab": None, - "firing": None, - "smoke": None, - "nav_lights": False, - "beacon": False, - "strobe": False, - "landing_lights": False, - } - self.gun_ammo = None - self.rocket_ammo = None - self.aam = None - self.agm = None - self.bomb = None - self.life = None - self.g_value = None - self.throttle = None - self.elev = None - self.ail = None - self.rud = None - self.trim = None - self.thrust_vector = { - "vector": None, - "reverser": None - } - self.bomb_bay_info = None - if should_decode: - self.decode() - - def decode(self): - self.remote_time, self.player_id = unpack("fI", self.buffer[4:12]) - self.packet_version = unpack("h", self.buffer[12:14])[0] - - if self.packet_version == 4 or self.packet_version == 5: - - self.position = list(unpack("fff", self.buffer[14:26])) - # self.atti = list(unpack("HHH", self.buffer[26:32])) - self.atti = list(map(lambda x: x * (pi / 32768.0), - unpack("HHH", self.buffer[26:32]))) - debug(self.atti) - - self.velocity = list(map(lambda x: x/10, - unpack("HHH", self.buffer[32:38]))) - self.atti_velocity = list(map(lambda x: x * (pi / 32768.0), - unpack("HHH", self.buffer[38:44]))) - self.smoke_oil = unpack("h", self.buffer[44:46])[0] - - self.fuel = unpack("I", self.buffer[46:50])[0] - - self.payload = unpack("h", self.buffer[50:52])[0] - - self.flight_state, self.vgw = unpack("BB", self.buffer[52:54]) - self.vgw = self.vgw / 255.0 - - c = unpack("B", self.buffer[54:55])[0] - self.spoiler = (c >> 4 & 15) / 15.0 #Bitshift 4 to the right, then mask with 15 - self.landing_gear = (c & 15) / 15.0 #Mask with 15 - - c = unpack("B", self.buffer[55:56])[0] - self.flap = (c >> 4 & 15) / 15.0 - self.brake = (c & 15) / 15.0 - - flags = unpack("h", self.buffer[56:58])[0] - self.flags["ab"] = bool(flags & 1) # Last bit - self.flags["firing"] = bool(flags &8) - self.flags["smoke"] = 0 - if flags & 2: - self.flags["smoke"] = (flags >> 8) & 255 # bitshift 8 to the right, - #then mask with 255 - if self.flags["smoke"] == 0: - self.flags["smoke"] = 255 # Need to review what this actuall does! - - if flags & 16: - self.flags["beacon"] = True - if flags & 32: - self.flags["nav_lights"] = True - if flags & 64: - self.flags["strobe"] = True - if flags & 128: - self.flags["landing_lights"] = True - - self.gun_ammo, self.rocket_ammo, self.aam, self.agm, self.bomb = unpack("HHBBB", self.buffer[58:65]) - self.life = unpack("B", self.buffer[65:66])[0] - - self.g_value = unpack("b", self.buffer[66:67])[0]/10.0 - - self.throttle = unpack("B", self.buffer[67:68])[0]/99.0 - self.elev = unpack("b", self.buffer[68:69])[0]/99.0 - self.ail = unpack("b", self.buffer[69:70])[0]/99.0 - self.rud = unpack("b", self.buffer[70:71])[0]/99.0 - self.trim = unpack("b", self.buffer[71:72])[0]/99.0 - - if self.packet_version == 4: - c = unpack("B", self.buffer[71:72])[0] - self.thrust_vector["vector"] = (c >> 4 & 15) / 15.0 - self.thrust_vector["reverser"] = (c & 15) / 15.0 - c = unpack("B", self.buffer[72:73])[0] - self.bomb_bay_info = (c >> 4 & 15) / 15.0 - - else: - - self.position = list(unpack("fff", self.buffer[16:28])) - self.atti = list(map(lambda x: x * (pi / 32768.0), - unpack("HHH", self.buffer[28:34]))) - - - self.velocity = list(map(lambda x: x/10, - unpack("HHH", self.buffer[34:40]))) - - self.atti_velocity = list(map(lambda x: x / (pi / 32768.0), - unpack("HHH", self.buffer[40:46]))) - self.g_value = unpack("h", self.buffer[46:48])[0]/100.0 - - self.gun_ammo, self.aam, self.agm, self.bomb, self.smoke_oil = unpack("hhhhh", self.buffer[48:58]) - self.fuel = unpack("f", self.buffer[58:62])[0] - self.payload = unpack("f", self.buffer[62:66])[0] - - self.life = unpack("h", self.buffer[66:68])[0] - - self.flight_state, self.vgw = unpack("BB", self.buffer[68:70]) - self.vgw = self.vgw / 255.0 - self.spoiler = unpack("B", self.buffer[70:71])[0]/255.0 - self.landing_gear = unpack("B", self.buffer[71:72])[0]/255.0 - self.flap = unpack("B", self.buffer[72:73])[0]/255.0 - self.brake = unpack("B", self.buffer[73:74])[0]/255.0 - - flags = unpack("H", self.buffer[74:76])[0] - self.flags["ab"] = bool(flags & 1) - self.flags["firing"] = bool(flags & 8) - self.flags["smoke"] = 0 - if flags & 2: - self.flags["smoke"] = (flags >> 8) & 255 - if self.flags["smoke"] == 0: - self.flags["smoke"] = 255 - - self.throttle = unpack("B", self.buffer[76:77])[0]/99.0 - self.elev = unpack("b", self.buffer[77:78])[0]/99.0 - self.ail = unpack("b", self.buffer[78:79])[0]/99.0 - self.rud = unpack("b", self.buffer[79:80])[0]/99.0 - self.trim = unpack("b", self.buffer[80:81])[0]/99.0 - - self.rocket_ammo = unpack("H", self.buffer[81:83])[0] - - if self.packet_version >= 1: - - self.atti_velocity = list(map(lambda x: x / (pi / 32768.0), - unpack("fff", self.buffer[83:95]))) - - if self.packet_version >= 2: - self.thrust_vector["vector"] = unpack("B", self.buffer[95:96])[0]/255.0 - self.thrust_vector["reverser"] = unpack("B", self.buffer[96:97])[0]/255.0 - self.bomb_bay_info = unpack("B", self.buffer[97:98])[0]/255.0 - - def smoke(self): - if self.packet_version == 4 or self.packet_version == 5: - flag = unpack('h',self.buffer[56:58])[0] - flag &= ~((1<<8)|2) - flag |= (1<<8) |2 - flag |= (1<<9) - flag |= (1<<10) - packet = self.buffer[:56] + pack('h',flag) + self.buffer[58:] - return pack('I',len(packet)) + packet - else: - flag = unpack('h',self.buffer[74:75])[0] - - flag &= ~((255<<8)|2) - flag |= (255<<8) | 2 - debug(flag) - packet = self.buffer[:74] + pack('h',flag) + self.buffer[76:] - return pack('I',len(packet)) + packet - - def stop_firing(self): - if self.packet_version == 4 or self.packet_version == 5: - flag = unpack('h',self.buffer[56:58])[0] - flag &= ~(8) - packet = self.buffer[:56] + pack('h',flag) + self.buffer[58:] - return pack('I',len(packet)) + packet - else: - flag = unpack('h',self.buffer[74:75])[0] - flag &= ~(8) - packet = self.buffer[:74] + pack('h',flag) + self.buffer[76:] - return pack('I',len(packet)) + packet - - @staticmethod - def get_life(buffer:bytes): - version = unpack("h", buffer[12:14])[0] - if version == 5 or version == 4: - return unpack("B", buffer[65:66])[0] - else: - return unpack("H", buffer[66:68])[0] - - - @staticmethod - def encode(remote_time, player_id, packet_version, position, atti, velocity, atti_velocity, - smoke_oil, fuel, payload, flight_state, vgw, spoiler, landing_gear, flap, brake, - flags, gun_ammo, rocket_ammo, aam, agm, bomb, life, g_value, throttle, elev, ail, rud, - trim, thrust_vector, bomb_bay_info, with_size:bool=False): - buffer = pack("IfI", 11, remote_time, player_id) - buffer += pack("H", packet_version) - if packet_version == 4 or packet_version == 5: - buffer += pack("fffhhhhhhhhh", *position, *atti, *velocity, *atti_velocity) - buffer += pack("hhhh", smoke_oil, fuel, payload, 0) - buffer += pack("BB", flight_state, int(vgw*255)) - buffer += pack("BB", int(spoiler*15)<<4 | int(landing_gear*15), int(flap*15)<<4 | int(brake*15)) - flagschar = 0 - if flags["ab"]: - flagschar |= 1 - if flags["firing"]: - flagschar |= 8 - if flags["smoke"]: - flagschar |= flags["smoke"] << 8 - if flags["beacon"]: - flagschar |= 16 - if flags["nav_lights"]: - flagschar |= 32 - if flags["strobe"]: - flagschar |= 64 - if flags["landing_lights"]: - flagschar |= 128 - buffer += pack("h", flagschar) - buffer += pack("HHBBB", gun_ammo, rocket_ammo, aam, agm, bomb) - buffer += pack("B", life) - buffer += pack("b", int(g_value*10)) - buffer += pack("B", int(throttle*99)) - buffer += pack("b", int(elev*99)) - buffer += pack("b", int(ail*99)) - buffer += pack("b", int(rud*99)) - buffer += pack("b", int(trim*99)) - - if packet_version == 4: - buffer += pack("BB", int(thrust_vector["vector"]*15)<<4 | int(thrust_vector["reverser"]*15), - int(bomb_bay_info*15)) - - else: - buffer += pack("fffhhhfff", *position, *atti, *velocity, *atti_velocity) - buffer += pack("HHHHH", gun_ammo, aam, agm, bomb, smoke_oil) - buffer += pack("f", payload) - buffer += pack("H", life) - buffer += pack("BB", flight_state, int(vgw*255)) - buffer += pack("BBBB", int(spoiler*15), int(landing_gear*15), - int(flap*15), int(brake*15)) - flagschar = 0 - if flags["ab"]: - flagschar |= 1 - if flags["firing"]: - flagschar |= 8 - if flags["smoke"]: - flagschar |= flags["smoke"] << 8 - buffer += pack("H", flagschar) - buffer += pack("B", int(throttle*99)) - buffer += pack("b", int(elev*99)) - buffer += pack("b", int(ail*99)) - buffer += pack("b", int(rud*99)) - buffer += pack("b", int(trim*99)) - buffer += pack("H", rocket_ammo) - if packet_version >= 1: - buffer += pack("fff", *atti_velocity) - if packet_version >= 2: - buffer += pack("BBB", int(thrust_vector["vector"]*255), int(thrust_vector["reverser"]*255), - int(bomb_bay_info*255)) - - if with_size: - return pack("I",len(buffer))+buffer - return buffer - - def __str__(self): - return f"Player ID : {self.player_id}; Remote Time : {self.remote_time}; \ - Position : {self.position}; Attitude : {self.atti}; Velocity : {self.velocity}; \ - Attitude Velocity : {self.atti_velocity}; Smoke Oil : {self.smoke_oil}; Fuel : {self.fuel}; \ - Payload : {self.payload}; Flight State : {self.flight_state}; VGW : {self.vgw}; \ - Spoiler : {self.spoiler}; Landing Gear : {self.landing_gear}; Flap : {self.flap}; \ - Brake : {self.brake}; Flags : {self.flags}; Gun Ammo : {self.gun_ammo}; \ - Rocket Ammo : {self.rocket_ammo}; AAM : {self.aam}; AGM : {self.agm}; Bomb : {self.bomb}; \ - Life : {self.life}; G Value : {self.g_value}; Throttle : {self.throttle}; Elev : {self.elev}; \ - Ail : {self.ail}; Rud : {self.rud}; Trim : {self.trim}; Thrust Vector : {self.thrust_vector}; \ - Bomb Bay Info : {self.bomb_bay_info}" diff --git a/lib/PacketManager/packets/FSNETCMD_EMPTYPACKET.py b/lib/PacketManager/packets/FSNETCMD_EMPTYPACKET.py deleted file mode 100644 index cfb35d6..0000000 --- a/lib/PacketManager/packets/FSNETCMD_EMPTYPACKET.py +++ /dev/null @@ -1,19 +0,0 @@ -from struct import pack - -class FSNETCMD_EMPTYPACKET: - """ - A template function for empty packets""" - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - if should_decode: - self.decode() - - def decode(self): - pass # There are no messages in this packet! - - @staticmethod - def encode(with_size:bool=False): #This will be extended by each func. - buffer = pack("I",14) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_ENVIRONMENT.py b/lib/PacketManager/packets/FSNETCMD_ENVIRONMENT.py deleted file mode 100644 index 3ede2ec..0000000 --- a/lib/PacketManager/packets/FSNETCMD_ENVIRONMENT.py +++ /dev/null @@ -1,76 +0,0 @@ -from struct import pack, unpack - -class FSNETCMD_ENVIRONMENT: #33 - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.day_night = -1 # 0 is day, 1 is night - self.flags = { - "fog":False, - "blackout":False, - "midair":False, - "can_land_anywhere":False - } - self.wind = [0,0,0] - self.visibility = None - if should_decode: - self.decode() - - def decode(self): - variables = unpack("IHHIffff", self.buffer[0:28]) - #0 is the packet type, 1 is just padding. - self.day_night = variables[2] - flags = variables[3] - self.wind = list(variables[4:7]) - self.visibility = variables[7] - self.flags["fog"] = bool(flags & 1) - if flags&8 == 1: #Server controls blackout: - self.flags["blackout"] = bool(flags & 4) - if flags&32 == 1: #Server controls midair: - self.flags["midair"] = bool(flags & 16) - if flags&128 == 1: #Server controls can_land_anywhere: - self.flags["can_land_anywhere"] = bool(flags & 64) - - @staticmethod - def encode(day_night, fog, blackout, midair, can_land_anywhere, wind, visibility, with_size:bool=False): - flags = 0 - if fog: - flags |= 1 - if blackout: - flags |= 4 - flags |=8 - if midair: - flags |= 16 - flags |= 32 - if can_land_anywhere: - flags |= 64 - flags |= 128 - buffer = pack("IHHIffff", 33, 0, day_night, flags, *wind, visibility) - if with_size: - return pack("I", len(buffer))+buffer - return buffer - - @staticmethod - def set_time(buffer:bytes, night:bool, with_size:bool = True): - if len(buffer)>28: - values = list(unpack("IHHIffff", buffer[4:])) - else: - values = list(unpack("IHHIffff", buffer)) - if night: values[2] = 1 - elif not night: values[2] = 0 - packet = pack("IHHIffff", *values) - if with_size: - return pack("I", len(packet)) + packet - return packet - - @staticmethod - def set_visibility(buffer:bytes, visibility:int, with_size:bool = True): - if len(buffer)>28: #Full data packet + the size - environment = FSNETCMD_ENVIRONMENT(buffer[4:]) - else: - environment = FSNETCMD_ENVIRONMENT(buffer) - environment.visibility = visibility - packet = FSNETCMD_ENVIRONMENT.encode(environment.day_night, True, - environment.flags['blackout'], environment.flags['midair'], - environment.flags['can_land_anywhere'], - environment.wind, visibility, with_size) - return packet \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_ERROR.py b/lib/PacketManager/packets/FSNETCMD_ERROR.py deleted file mode 100644 index 327d38c..0000000 --- a/lib/PacketManager/packets/FSNETCMD_ERROR.py +++ /dev/null @@ -1,22 +0,0 @@ -from struct import pack, unpack -from .constants import ERROR_CODES - -class FSNETCMD_ERROR: #3 - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.error_code = None - self.error_message = None - if should_decode: - self.decode() - - def decode(self): - errorCode = unpack("I",self.buffer[4:8])[0] - if errorCode < len(ERROR_CODES): - self.error_message = ERROR_CODES[errorCode] - - @staticmethod - def encode(error_code, with_size:bool=False): - buffer = pack("I",3)+pack("I",error_code) - if with_size: - return pack("I",len(buffer))+buffer - return buffer diff --git a/lib/PacketManager/packets/FSNETCMD_FOGCOLOR.py b/lib/PacketManager/packets/FSNETCMD_FOGCOLOR.py deleted file mode 100644 index fd195d4..0000000 --- a/lib/PacketManager/packets/FSNETCMD_FOGCOLOR.py +++ /dev/null @@ -1,21 +0,0 @@ -from struct import pack, unpack - -class FSNETCMD_FOGCOLOR: - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.redValye = 0 - self.greenValue = 0 - self.blueValue = 0 - if should_decode: - self.decode() - - def decode(self): - self.redValue = self.buffer[4] - self.greenValue = self.buffer[5] - self.blueValue = self.buffer[6] - - @staticmethod - def encode(redValue:int, greenValue:int, blueValue:int, with_size:bool=False): - buffer = pack("IBBB", 48, redValue, greenValue, blueValue) - if with_size: buffer = (pack("I", len(buffer))) + buffer - return buffer diff --git a/lib/PacketManager/packets/FSNETCMD_GETDAMAGE.py b/lib/PacketManager/packets/FSNETCMD_GETDAMAGE.py deleted file mode 100644 index 165da4d..0000000 --- a/lib/PacketManager/packets/FSNETCMD_GETDAMAGE.py +++ /dev/null @@ -1,48 +0,0 @@ -from struct import pack, unpack -from .constants import FSWEAPON_DICT - -class FSNETCMD_GETDAMAGE: #22 - """ - Sent when an aircraft or ground target has taken damage - """ - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.victim_id = None - self.victim_type = None - self.attacker_type = None - self.attacker_id = None - self.damage = None - self.died_of = None - self.weapon_type = None - if should_decode: - self.decode() - - def decode(self): - variables = unpack("IIIIIHHH", self.buffer[0:26]) - self.victim_type = variables[1] - self.victim_id = variables[2] - self.attacker_type = variables[3] - self.attacker_id = variables[4] - self.damage = variables[5] - self.died_of = variables[6] - self.weapon_type = variables[7] - if self.weapon_type in FSWEAPON_DICT: - self.weapon_type = FSWEAPON_DICT[self.weapon_type] - - - @staticmethod - def encode(victim_id, victim_type, attacker_type, attacker_id, damage, died_of, - weapon_type, with_size:bool=False): - if weapon_type in FSWEAPON_DICT and not isinstance(weapon_type,int): - weapon_type = list(FSWEAPON_DICT.keys())[list(FSWEAPON_DICT.values()).index(weapon_type)] - - buffer = pack("I",22)+pack("4I3H", victim_type, victim_id, attacker_type,attacker_id, - damage, died_of, weapon_type) - if with_size: - return pack("I", len(buffer))+buffer - return buffer - - def __str__(self): - return f"Victim ID : {self.victim_id}; Victim Type : {self.victim_type}; \ - Attacker Type : {self.attacker_type}; Attacker ID : {self.attacker_id} \ - Damage : {self.damage}; Died Of : {self.died_of}; weapon : {self.weapon_type}" diff --git a/lib/PacketManager/packets/FSNETCMD_JOINAPPROVAL.py b/lib/PacketManager/packets/FSNETCMD_JOINAPPROVAL.py deleted file mode 100644 index beb6ab9..0000000 --- a/lib/PacketManager/packets/FSNETCMD_JOINAPPROVAL.py +++ /dev/null @@ -1,22 +0,0 @@ -from struct import pack - -class FSNETCMD_JOINAPPROVAL: #9 - """ - When the server sends the "add aircraft" command, and - receves the readback from the client, they'll send this - It's an empty packet, but can be useful to know the client is about to join. - """ - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - if should_decode: - self.decode() - - def decode(self): - pass - - @staticmethod - def encode(with_size:bool=False): - buffer = pack("I",9) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_JOINREQUEST.py b/lib/PacketManager/packets/FSNETCMD_JOINREQUEST.py deleted file mode 100644 index 7796599..0000000 --- a/lib/PacketManager/packets/FSNETCMD_JOINREQUEST.py +++ /dev/null @@ -1,29 +0,0 @@ -from struct import pack, unpack - -class FSNETCMD_JOINREQUEST: #8 - """ - The client sends a join request to the server with their iff, aircraft, start position, fuel and smoke - The server replies with the join request readback,The server replies with the join request readback - """ - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.iff = None - self.aircraft = None - self.start_pos = None #It's the STP name - self.fuel = None - self.smoke = None - if should_decode: - self.decode() - - def decode(self): - self.iff, _, self.aircraft, self.start_pos, _, self.fuel, self.smoke = unpack("HH32s32sHHH", self.buffer[4:78]) - self.start_pos = self.start_pos.decode().strip('\x00') - self.aircraft = self.aircraft.decode().strip('\x00') - - @staticmethod - def encode(iff, aircraft, start_pos, fuel, smoke, with_size:bool=False): - buffer = pack("IHH32s32sHHH", 8, iff, 0, aircraft.encode(), - start_pos.encode(), 1, fuel, smoke) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_KILLSERVER.py b/lib/PacketManager/packets/FSNETCMD_KILLSERVER.py deleted file mode 100644 index 3e1b4ec..0000000 --- a/lib/PacketManager/packets/FSNETCMD_KILLSERVER.py +++ /dev/null @@ -1,14 +0,0 @@ -from struct import pack -from .FSNETCMD_EMPTYPACKET import FSNETCMD_EMPTYPACKET - -class FSNETCMD_KILLSERVER(FSNETCMD_EMPTYPACKET): #15 - """ - This is unimplemented in YS, but it would shutdown the server - The actual server functionality is disabled. - """ - @staticmethod - def encode(with_size:bool=False): - buffer = pack("I",15) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_LIST.py b/lib/PacketManager/packets/FSNETCMD_LIST.py deleted file mode 100644 index d6cb83c..0000000 --- a/lib/PacketManager/packets/FSNETCMD_LIST.py +++ /dev/null @@ -1,70 +0,0 @@ -from struct import unpack, pack -class FSNETCMD_LIST: #44 - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.list_type = None - self.num_of_items = 0 - self.list = [] - if should_decode: - self.decode() - - def decode(self): - packet_type = unpack('I', self.buffer[:4])[0] - self.list_type = unpack('B', self.buffer[4:5])[0] - self.num_of_items = unpack('B', self.buffer[5:6])[0] - #Then there is a spacer. - _ = unpack('BB', self.buffer[6:8]) - self.list = self.buffer[8:].split(b'\x00')[:-1] - - @staticmethod - def encode(list_type:int=1, list_buffer:bytes=b'', num_of_items:int=0, with_size:bool=False): - #Max length of the packet is 1024 bytes. - # 8+1 bytes for the header, leaving 1015 bytes for the list. - buffer = pack('IBBBB', 44, list_type, num_of_items, 0, 0) - buffer += list_buffer - if with_size: - return pack("I", len(buffer)) + buffer - return buffer - - -class List_Constructor: - """Takes a list of aircraft, and constructes a list of FSNETCMD_LIST packets for sending. - If sending custom lists to clients, the client FSNETCMD_LIST reply must be blocked from the server - and the server FSNETCMD_LIST command must also be blocked. - """ - def __init__(self, aircraftList:list, with_size:bool=True): - self.aircraftList = aircraftList - self.packet_list = [] - self.num_of_packets = 0 - self.with_size = with_size - self.construct_packets() - - def construct_packets(self): - packet = b'' - packet_length = 0 - for aircraft in self.aircraftList: - aircraft = aircraft.replace(' ', '_') - aircraft = aircraft.encode() + b'\x00' - if self.check_fit(packet, aircraft) and packet_length<32: - packet += aircraft - packet_length += 1 - else: - packet = FSNETCMD_LIST.encode(1,packet, packet_length,self.with_size) - self.packet_list.append(packet) - packet = b'' - packet += aircraft - self.num_of_packets += 1 - packet_length = 1 - #Append whatever is left over. - if len(packet) > 0: - packet = FSNETCMD_LIST.encode(1,packet, packet_length,self.with_size) - self.packet_list.append(packet) - self.num_of_packets += 1 - - def check_fit(self, packet, aircraft): - if len(packet) + len(aircraft) + 1 > 1015: - return False - return True - - def get_packets(self): - return self.packet_list diff --git a/lib/PacketManager/packets/FSNETCMD_LOADFIELD.py b/lib/PacketManager/packets/FSNETCMD_LOADFIELD.py deleted file mode 100644 index 2184f7d..0000000 --- a/lib/PacketManager/packets/FSNETCMD_LOADFIELD.py +++ /dev/null @@ -1,30 +0,0 @@ -from struct import pack, unpack - -class FSNETCMD_LOADFIELD: #4 - """ - This packet is sent by the server along with the field info. When received, - the client replies with the same packet. - """ - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.field = None - self.fieldShortName = None - self.flags = None - self.pos = [0,0,0] - self.atti = [0,0,0] - if len(buffer) == 64 and should_decode: - self.decode() - - def decode(self): - self.field, self.flags, self.pos[0], self.pos[1], self.pos[2], self.atti[0], self.atti[1], self.atti[2] = unpack("32sIffffff", self.buffer[4:]) - self.fieldShortName = self.field.split(b'\x00')[0].decode() - - @staticmethod - def encode(field, flags, pos, atti, with_size:bool=False): - if isinstance(field, str): - field = field.encode() - buffer = pack("I32sIffffff", 4, field, flags, pos[0], pos[1], - pos[2], atti[0], atti[1], atti[2]) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_LOCKON.py b/lib/PacketManager/packets/FSNETCMD_LOCKON.py deleted file mode 100644 index 2b3d01a..0000000 --- a/lib/PacketManager/packets/FSNETCMD_LOCKON.py +++ /dev/null @@ -1,31 +0,0 @@ -from struct import pack, unpack - -class FSNETCMD_LOCKON: #18 - """ - Sent from server to client, and client to server - when someone locks onto someone else - """ - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.locker_id = None - self.locker_is_air = False - self.lockee_id = None - self.lockee_is_air = False - if should_decode: - self.decode() - - def decode(self): - self.locker_id, self.locker_is_air, self.lockee_id, self.lockee_is_air = unpack("IIII", self.buffer[4:20]) - self.locker_is_air = bool(self.locker_is_air) - self.lockee_is_air = bool(self.lockee_is_air) - - @staticmethod - def encode(locker_id, locker_is_air, lockee_id, lockee_is_air, with_size:bool=False): - if isinstance(locker_is_air, bool): - locker_is_air = int(locker_is_air) - if isinstance(lockee_is_air, bool): - lockee_is_air = int(lockee_is_air) - buffer = pack("I",18)+pack("IIII", locker_id, locker_is_air, lockee_id, lockee_is_air) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_LOGOFF.py b/lib/PacketManager/packets/FSNETCMD_LOGOFF.py deleted file mode 100644 index bc03a0b..0000000 --- a/lib/PacketManager/packets/FSNETCMD_LOGOFF.py +++ /dev/null @@ -1,19 +0,0 @@ -from struct import pack - -class FSNETCMD_LOGOFF: #2 - """ - This is a logoff packet, used to logoff from the server. - It appeasr to be un-used by YS. Including it for completeness. - """ - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - - def decode(self): - pass - - @staticmethod - def encode( with_size:bool=False): - buffer = pack("I",2) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_LOGON.py b/lib/PacketManager/packets/FSNETCMD_LOGON.py deleted file mode 100644 index 9848590..0000000 --- a/lib/PacketManager/packets/FSNETCMD_LOGON.py +++ /dev/null @@ -1,58 +0,0 @@ -from struct import pack, unpack - -class FSNETCMD_LOGON: #1 - """ - This is a logon packet, used to logon to the server. - The client sends this to the server on login, and the server replies to acknowledge. - """ - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.version = None - self.username = None - self.alias = None #Alias is the longer form of the username, if they're longer than 16 chars - - #If the YS version is 2018 (or YSCE) then the server will reply with an - # empty packet on login-complete. - if len(self.buffer)>5 and should_decode: - #We can decode the packet. - self.decode() - - def decode(self): - self.username, self.version = unpack("16sI",self.buffer[4:24]) - if len(self.buffer)>24: - self.alias = self.buffer[24:].decode().strip('\x00') - else: - self.alias = self.username - if isinstance(self.username,bytes): - self.username = self.username.decode().strip('\x00') - if isinstance(self.alias,bytes): - self.alias = self.alias.decode().strip('\x00') - - - @staticmethod #Method to create a logon packet, if required. - def encode(username, version, with_size:bool=False): - if len(username)>15: - shortform = username[:15] - alias = username - else: - shortform = username - alias = None - if isinstance(shortform,str): - shortform = shortform.encode() - buffer = pack("I16sI", 1, shortform, version) - if alias: - if isinstance(alias,str): - alias = alias.encode() - if len(alias)<200: - alias = alias.ljust(200,b'\x00') - alias += b'\x00\x00\x00\x00' - buffer += alias - - if with_size: - return pack("I",len(buffer))+buffer - - return buffer - - @staticmethod - def alter_version(buffer:bytes, new_version:int): - return buffer[:20]+pack("I",new_version)+buffer[24:] \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_MISSILELAUNCH.py b/lib/PacketManager/packets/FSNETCMD_MISSILELAUNCH.py deleted file mode 100644 index ad03128..0000000 --- a/lib/PacketManager/packets/FSNETCMD_MISSILELAUNCH.py +++ /dev/null @@ -1,97 +0,0 @@ -from struct import pack, unpack -from .constants import FSWEAPON_DICT, GUIDEDWEAPONS -from lib.Aircraft import Aircraft -from math import pi -import random - -class FSNETCMD_MISSILELAUNCH: #20 - """ - Sent when a missile has been launched - """ - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.weapon_type = None - self.position = [0,0,0] - self.atti = [0,0,0] - self.velocity = None - self.life_remaining = None - self.power = None - self.fired_by_aircraft = None - self.fired_by = None - self.v_max = None - self.mobility = None - self.radar = None - self.fired_at_aircraft = None - self.fired_at = None - if should_decode: - self.decode() - - def decode(self): - print(self.buffer) - # _ = unpack("I", self.buffer[:4])[0] #Packet type - # IH # 6 - # fff # 12 - # fff # 12 - # ffH #10 - # II # 8 - self.weapon_type = unpack("H", self.buffer[4:6])[0] - self.position = list(unpack("fff", self.buffer[6:18])) - self.atti = list(unpack("fff", self.buffer[18:30])) - self.velocity, self.life_remaining, self.power = unpack("ffH", self.buffer[30:40]) - self.fired_by_aircraft = unpack("I", self.buffer[40:44])[0] - self.fired_by = unpack("I", self.buffer[44:48])[0] - if self.weapon_type in FSWEAPON_DICT: - self.weapon_type = FSWEAPON_DICT[self.weapon_type] - - if self.weapon_type in GUIDEDWEAPONS: - self.v_max, self.mobility, self.radar = unpack("fff", self.buffer[48:60]) - self.fired_at_aircraft = bool(unpack("I", self.buffer[60:64])[0]) - self.fired_at = unpack("I", self.buffer[64:68])[0] - elif self.weapon_type == "FSWEAPON_FLARE": - self.v_max = unpack("f", self.buffer[48:52])[0] - - - - @staticmethod - def encode(weapon_type, position, atti, velocity, life_remaining, power, - fired_by_aircraft, fired_by, v_max=1000, mobility=0, - radar=0, fired_at_aircraft=False, fired_at=0, with_size:bool=False): - if weapon_type in FSWEAPON_DICT and isinstance(weapon_type,int): - weapon_type_name = FSWEAPON_DICT[weapon_type] - else: - weapon_type_name = weapon_type - weapon_type = list(FSWEAPON_DICT.keys())[list(FSWEAPON_DICT.values()).index(weapon_type)] - buffer = pack("I",20) #Packet type 0:4 - - buffer += pack("H", weapon_type) #Weapon type 4:6 - buffer += pack("f", position[0]) #6:10 - buffer += pack("f", position[1]) #10:14 - buffer += pack("f", position[2]) #Position #14:18 - buffer += pack("f", atti[0]) #18:22 - buffer += pack("f", atti[1]) #22:26 - buffer += pack("f", atti[2]) #Attitude #26:30 - buffer += pack("ffH", velocity, life_remaining, power) #Velocity, life remaining, power #30:40 - buffer += pack("II",fired_by_aircraft,fired_by) #Fired by aircraft, fired by #40:48 - print(buffer) - if weapon_type_name in GUIDEDWEAPONS: - buffer += pack("fff", v_max, mobility, radar) - if isinstance(fired_at_aircraft, bool): - fired_at_aircraft = int(fired_at_aircraft) - buffer += pack("II", fired_at_aircraft, fired_at) - if weapon_type_name == "FSWEAPON_FLARE": - buffer += pack("f", v_max) - - if with_size: - return pack("I",len(buffer))+buffer - return buffer - - @staticmethod - def drop_bombs(aircraft:Aircraft): - position = aircraft.position - atti = aircraft.attitude - # atti = [(value*(32768/ pi)) for value in atti] - atti[2] =0 - weapon_type = random.randint(0,13) - packet = FSNETCMD_MISSILELAUNCH.encode(weapon_type, position=position, atti=atti, velocity=20, life_remaining=30000, power=999, fired_by_aircraft=0, fired_by=aircraft.id, v_max=1000, with_size=True) - print(packet) - return packet \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_NULL.py b/lib/PacketManager/packets/FSNETCMD_NULL.py deleted file mode 100644 index 5e35777..0000000 --- a/lib/PacketManager/packets/FSNETCMD_NULL.py +++ /dev/null @@ -1,16 +0,0 @@ -from struct import pack - -class FSNETCMD_NULL: #0 - """ - This is a 'null' packet, there is nothing to process. - """ - def __init__(self,buffer:bytes, should_decode:bool=True): - pass - - def decode(self): - return None - - def encode(self, with_size:bool=False): - if with_size: - return pack("II",4,0) - return pack("I", 0) diff --git a/lib/PacketManager/packets/FSNETCMD_PREPARESIMULATION.py b/lib/PacketManager/packets/FSNETCMD_PREPARESIMULATION.py deleted file mode 100644 index 4cfef8f..0000000 --- a/lib/PacketManager/packets/FSNETCMD_PREPARESIMULATION.py +++ /dev/null @@ -1,14 +0,0 @@ -from struct import pack -from .FSNETCMD_EMPTYPACKET import FSNETCMD_EMPTYPACKET - -class FSNETCMD_PREPARESIMULATION(FSNETCMD_EMPTYPACKET): #16 - """ - This is sent from server to client when they've almost finished - logging in. - """ - @staticmethod - def encode(with_size:bool=False): - buffer = pack("I",16) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_READBACK.py b/lib/PacketManager/packets/FSNETCMD_READBACK.py deleted file mode 100644 index 0fd4ead..0000000 --- a/lib/PacketManager/packets/FSNETCMD_READBACK.py +++ /dev/null @@ -1,39 +0,0 @@ -from struct import pack, unpack - -class FSNETCMD_READBACK: #6 - """ - Sent from client to server and back to acknowledge various packets. - - * Client sends FSNETREADBACK_ADDAIRPLAN or FSNETREADBACK_ADDGROUND to - acknowledge FSNETCMD_ADDOBJECT - * Client sends FSNETREADBACK_REMOVEAIRPLANE or FSNETREADBACK_REMOVEGROUND - to acknowledge FSNETCMD_REMOVEAIRPLANE or FSNETCMD_REMOVEGROUND - * Client sends FSNETREADBACK_ENVIRONMENT to acknowledge FSNETCMD_ENVIRONMENT - * Client sends FSNETREADBACK_JOINREQUEST to acknowledge FSNETCMD_JOINREQUEST - * Client sends FSNETREADBACK_PREPARE to acknowledge FSNETCMD_PREPARESIMULATION - * Client sends FSNETREADBACK_USEMISSILE to acknowledge FSNETCMD_USEMISSILE - * Client sends FSNETREADBACK_USEUNGUIDEDWEAPON to acknowledge FSNETCMD_USEUNGUIDEDWEAPON - * Client sends FSNETREADBACK_CTRLSHOWUSERNAME to acknowledge FSNETCMD_CTRLSHOWUSERNAME - - * Server sends FSNETREADBACK_JOINREQUEST to acknowledge FSNETCMD_JOINREQUEST - - Will punt the user if the server receives this from them - * There are probably more, but I've not gone into much detail here yet. - - """ - - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.read_back_type = None - self.read_back_param = None - if should_decode: - self.decode() - - def decode(self): - self.read_back_type, _, self.read_back_param = unpack("HHI", self.buffer[4:12]) - - @staticmethod - def encode(read_back_type, read_back_param, with_size:bool=False): - buffer = pack("IhhI", 6, read_back_type, 0, read_back_param) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_REJECTJOINREQ.py b/lib/PacketManager/packets/FSNETCMD_REJECTJOINREQ.py deleted file mode 100644 index e19a007..0000000 --- a/lib/PacketManager/packets/FSNETCMD_REJECTJOINREQ.py +++ /dev/null @@ -1,21 +0,0 @@ -from struct import pack - -class FSNETCMD_REJECTJOINREQ: #10 - """ - If the server rejects the join request, they'll send this. - It's usually followed by a chat message saying why. - """ - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - if should_decode: - self.decode() - - def decode(self): - pass - - @staticmethod - def encode(with_size:bool=False): - buffer = pack("I",10) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_REMOVEAIRPLANE.py b/lib/PacketManager/packets/FSNETCMD_REMOVEAIRPLANE.py deleted file mode 100644 index b880a3e..0000000 --- a/lib/PacketManager/packets/FSNETCMD_REMOVEAIRPLANE.py +++ /dev/null @@ -1,13 +0,0 @@ -from .FSNETCMD_UNJOIN import FSNETCMD_UNJOIN -from struct import pack - -class FSNETCMD_REMOVEAIRPLANE(FSNETCMD_UNJOIN): #13 - """ - Seems to just be the same as 12. No idea why Soji made 2. - We'll just extend UNJOIN.""" - @staticmethod - def encode(object_id, explosion, with_size:bool=False): - buffer = pack("I", 12)+pack("IIhh", 13, object_id, explosion) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_REMOVEGROUND.py b/lib/PacketManager/packets/FSNETCMD_REMOVEGROUND.py deleted file mode 100644 index 9861add..0000000 --- a/lib/PacketManager/packets/FSNETCMD_REMOVEGROUND.py +++ /dev/null @@ -1,13 +0,0 @@ -from struct import pack -from .FSNETCMD_UNJOIN import FSNETCMD_UNJOIN - -class FSNETCMD_REMOVEGROUND(FSNETCMD_UNJOIN): #19 - """ - This is the same as FSNETCMD_UNJOIN/Remove aircraft, but for ground objects. - """ - @staticmethod - def encode(object_id, explosion, with_size:bool=False): - buffer =pack("I",19)+pack("IIhh", 19, object_id, explosion) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_REPORTSCORE.py b/lib/PacketManager/packets/FSNETCMD_REPORTSCORE.py deleted file mode 100644 index 96dfe68..0000000 --- a/lib/PacketManager/packets/FSNETCMD_REPORTSCORE.py +++ /dev/null @@ -1,50 +0,0 @@ -from struct import pack, unpack -from . import FSWEAPON_DICT -""" -This is the score card for when an aircraft/ground object is destroyed. -""" -class FSNETCMD_REPORTSCORE: - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.scored = None - self.weapon_type = None - self.position = [0,0,0] - self.score_time = None - self.killer_id = None - self.killer_name = None - self.killer_plane = None - self.victim_id = None - self.victim_name = None - self.victim_plane = None - - if should_decode: - self.decode() - - def decode(self): - self.scored = bool(unpack("H", self.buffer[4:6])[0]) - self.weapon_type = unpack("H", self.buffer[6:8])[0] - if self.weapon_type in FSWEAPON_DICT: - self.weapon_type = FSWEAPON_DICT[self.weapon_type] - self.position = list(unpack("fff", self.buffer[8:20])) - self.score_time = unpack("f", self.buffer[20:24])[0] - self.killer_id = unpack("I", self.buffer[28:32])[0] - self.killer_name = self.buffer[32:64].decode("utf-8").rstrip("\x00") - self.killer_plane = self.buffer[64:96].decode("utf-8").rstrip("\x00") - self.victim_id = unpack("I", self.buffer[100:104])[0] - self.victim_name = self.buffer[104:136].decode("utf-8").rstrip("\x00") - self.victim_plane = self.buffer[136:168].decode("utf-8").rstrip("\x00") - - @staticmethod - def encode(scored, weapon_type, position, score_time, killer_id, killer_name, - killer_plane, victim_id, victim_name, victim_plane, with_size:bool=False): - if weapon_type in FSWEAPON_DICT and not isinstance(weapon_type,int): - weapon_type = list(FSWEAPON_DICT.keys())[list(FSWEAPON_DICT.values()).index(weapon_type)] - - buffer = pack("IHHffffII32s32sII32s32s", 46, - int(scored), weapon_type, *position, score_time, 0, killer_id, - killer_name.encode("utf-8"), killer_plane.encode("utf-8"),0, - victim_id, victim_name.encode("utf-8"), victim_plane.encode("utf-8")) - if with_size: - return pack("I", len(buffer))+buffer - - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_REQUESTTESTAIRPLANE.py b/lib/PacketManager/packets/FSNETCMD_REQUESTTESTAIRPLANE.py deleted file mode 100644 index f92667b..0000000 --- a/lib/PacketManager/packets/FSNETCMD_REQUESTTESTAIRPLANE.py +++ /dev/null @@ -1,14 +0,0 @@ -from struct import pack -from .FSNETCMD_EMPTYPACKET import FSNETCMD_EMPTYPACKET - -class FSNETCMD_REQUESTTESTAIRPLANE(FSNETCMD_EMPTYPACKET): #14 - """ - Spawns an F-15C at NORTH1000_01 in dogfight mode - There is no way of calling this from YS. - """ - @staticmethod - def encode(with_size:bool=False): - buffer = pack("I",14) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_SERVER_FORCE_JOIN.py b/lib/PacketManager/packets/FSNETCMD_SERVER_FORCE_JOIN.py deleted file mode 100644 index a94aa17..0000000 --- a/lib/PacketManager/packets/FSNETCMD_SERVER_FORCE_JOIN.py +++ /dev/null @@ -1,14 +0,0 @@ -from struct import pack, unpack -from .FSNETCMD_NULL import FSNETCMD_NULL - -class FSNETCMD_SERVER_FORCE_JOIN(FSNETCMD_NULL): - """ - Sent by the server to force the player to join - This literally just presses J. Wild. - """ - @staticmethod - def encode(player_id, with_size:bool=False): - buffer = pack("I", 47) - if with_size: - return pack("I", len(buffer)) + buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_SKYCOLOR.py b/lib/PacketManager/packets/FSNETCMD_SKYCOLOR.py deleted file mode 100644 index 2149bc5..0000000 --- a/lib/PacketManager/packets/FSNETCMD_SKYCOLOR.py +++ /dev/null @@ -1,21 +0,0 @@ -from struct import pack, unpack - -class FSNETCMD_SKYCOLOR: - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.redValye = 0 - self.greenValue = 0 - self.blueValue = 0 - if should_decode: - self.decode() - - def decode(self): - self.redValue = self.buffer[4] - self.greenValue = self.buffer[5] - self.blueValue = self.buffer[6] - - @staticmethod - def encode(redValue:int, greenValue:int, blueValue:int, with_size:bool=False): - buffer = pack("IBBB", 49, redValue, greenValue, blueValue) - if with_size: buffer = (pack("I", len(buffer))) + buffer - return buffer diff --git a/lib/PacketManager/packets/FSNETCMD_SMOKECOLOR.py b/lib/PacketManager/packets/FSNETCMD_SMOKECOLOR.py deleted file mode 100644 index 76e254d..0000000 --- a/lib/PacketManager/packets/FSNETCMD_SMOKECOLOR.py +++ /dev/null @@ -1,25 +0,0 @@ -from struct import unpack, pack - -class FSNETCMD_SMOKECOLOR: #7 - """The server sends this to the client when another aircraft - joins with smoke, and the client sends it to the server if - they're joining with smoke. - """ - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.aircraft_id = None - self.smoke_quantity = None - self.color = None - if should_decode: - self.decode() - - def decode(self): - self.aircraft_id, self.smoke_quantity, r, g, b = unpack("IBBBB", self.buffer[4:9]) - self.color = (r,g,b) - - @staticmethod - def encode(aircraft_id, smoke_quantity, color, with_size:bool=False): - buffer = pack("IIBBBB", 7, aircraft_id, smoke_quantity, color[0], color[1], color[2]) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_TESTPACKET.py b/lib/PacketManager/packets/FSNETCMD_TESTPACKET.py deleted file mode 100644 index 58c9bfc..0000000 --- a/lib/PacketManager/packets/FSNETCMD_TESTPACKET.py +++ /dev/null @@ -1,14 +0,0 @@ -from struct import pack -from .FSNETCMD_EMPTYPACKET import FSNETCMD_EMPTYPACKET - -class FSNETCMD_TESTPACKET(FSNETCMD_EMPTYPACKET): #17 - """ - This is just an empty packet. - Just overwrite the encode. - """ - @staticmethod - def encode(with_size:bool=False): - buffer = pack("I",17) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py b/lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py deleted file mode 100644 index 4cd0f42..0000000 --- a/lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py +++ /dev/null @@ -1,24 +0,0 @@ -from struct import pack -import re - -class FSNETCMD_TEXTMESSAGE: #32 - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.raw_message = None - self.user = None - self.message = "" - if should_decode: - self.decode() - - def decode(self): - self.raw_message = self.buffer[12:].decode("utf-8").strip("\x00") - match = re.match(r"^\(([^)]+)\)(.+)", self.raw_message) - if match: - self.user, self.message = match.groups() - - @staticmethod - def encode(message:str, with_size:bool=False): - buffer = pack("III",32,0,0)+message.encode("utf-8")+b"\x00" - if with_size: - return pack("I",len(buffer))+buffer - return buffer diff --git a/lib/PacketManager/packets/FSNETCMD_UNJOIN.py b/lib/PacketManager/packets/FSNETCMD_UNJOIN.py deleted file mode 100644 index 1f991ae..0000000 --- a/lib/PacketManager/packets/FSNETCMD_UNJOIN.py +++ /dev/null @@ -1,26 +0,0 @@ -from struct import pack, unpack - -class FSNETCMD_UNJOIN: #12 - """ - This is sent client to server when the client leaves. - The explosion doesn't seem to actually do anything in YS. - There is a comment saying "add explosion here"... Not helpful. - """ - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.object_id = None - self.explosion = None - if should_decode: - self.decode() - - def decode(self): - variables = unpack("IIhh", self.buffer[0:12]) - self.object_id = variables[1] - self.explosion = bool(variables[2]) - - @staticmethod - def encode(object_id, explosion, with_size:bool=False): - buffer = pack("I", 12)+pack("IIhh", 12, object_id, explosion) - if with_size: - return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_WEAPONCONFIG.py b/lib/PacketManager/packets/FSNETCMD_WEAPONCONFIG.py deleted file mode 100644 index aa4876b..0000000 --- a/lib/PacketManager/packets/FSNETCMD_WEAPONCONFIG.py +++ /dev/null @@ -1,55 +0,0 @@ -from struct import pack, unpack -from .constants import FSWEAPON_DICT - -class FSNETCMD_WEAPONCONFIG: - def __init__(self, buffer:bytes, should_decode:bool=True): - self.buffer = buffer - self.aircraft_id = None - self.number = None - self.weapon_config = {} - - - if should_decode: - self.decode() - - def decode(self): - self.aircraft_id, self.number = unpack("Ih",self.buffer[4:10]) - self.weapon_config = {} - self.number = self.number & (~1) - - for i in range(self.number // 2): - typ, count = unpack("hh",self.buffer[10+i*4:14+i*4]) - if typ in FSWEAPON_DICT: - typ = FSWEAPON_DICT[typ] - if "SMOKE" in typ: - #the count is actually the RGB value, formatted like a ballbag. - r = (count >>10)&31 - g = (count >>5)&31 - b = count&31 - r = (r>>2)+(r<<3) - g = (g>>2)+(g<<3) - b = (b>>2)+(b<<3) - count = [r,g,b] - self.weapon_config[typ] = count - print(self.weapon_config) - - @staticmethod - def encode(aircraft_id:int, weapon_config:dict, with_size:bool=False): - buffer = pack("IIh", 36, aircraft_id, len(weapon_config)*2) - for typ, count in weapon_config.items(): - if typ in FSWEAPON_DICT.values() and isinstance(typ, str): - typ = [k for k,v in FSWEAPON_DICT.items() if v == typ][0] - if typ >=32 and typ <=39 and isinstance(count,list): #Smoke - r,g,b = count - r = (r*31)/255 - g = (g*31)/255 - b = (b*31)/255 - count = (int(r)<<10)+(int(g)<<5)+int(b) - buffer += pack("hh", typ, count) - if with_size: - return pack("I",len(buffer))+buffer - return buffer - - @staticmethod - def addSmoke(aircraft_id:int): - return FSNETCMD_WEAPONCONFIG.encode(aircraft_id, {32:[66,66,66],33:[66,66,66],34:[66,66,66]}, True) diff --git a/lib/PacketManager/packets/__init__.py b/lib/PacketManager/packets/__init__.py deleted file mode 100644 index 1139ab5..0000000 --- a/lib/PacketManager/packets/__init__.py +++ /dev/null @@ -1,67 +0,0 @@ -from .FSNETCMD_LOGON import FSNETCMD_LOGON -from .FSNETCMD_LOGOFF import FSNETCMD_LOGOFF -from .FSNETCMD_ERROR import FSNETCMD_ERROR -from .FSNETCMD_LOADFIELD import FSNETCMD_LOADFIELD -from .FSNETCMD_ADDOBJECT import FSNETCMD_ADDOBJECT -from .FSNETCMD_READBACK import FSNETCMD_READBACK -from .FSNETCMD_SMOKECOLOR import FSNETCMD_SMOKECOLOR -from .FSNETCMD_JOINREQUEST import FSNETCMD_JOINREQUEST -from .FSNETCMD_JOINAPPROVAL import FSNETCMD_JOINAPPROVAL -from .FSNETCMD_REJECTJOINREQ import FSNETCMD_REJECTJOINREQ -from .FSNETCMD_AIRPLANESTATE import FSNETCMD_AIRPLANESTATE -from .FSNETCMD_UNJOIN import FSNETCMD_UNJOIN -from .FSNETCMD_REMOVEAIRPLANE import FSNETCMD_REMOVEAIRPLANE -from .FSNETCMD_REQUESTTESTAIRPLANE import FSNETCMD_REQUESTTESTAIRPLANE -from .FSNETCMD_KILLSERVER import FSNETCMD_KILLSERVER -from .FSNETCMD_PREPARESIMULATION import FSNETCMD_PREPARESIMULATION -from .FSNETCMD_TESTPACKET import FSNETCMD_TESTPACKET -from .FSNETCMD_LOCKON import FSNETCMD_LOCKON -from .FSNETCMD_REMOVEGROUND import FSNETCMD_REMOVEGROUND -from .FSNETCMD_MISSILELAUNCH import FSNETCMD_MISSILELAUNCH -#from .FSNETCMD_GROUNDSTATE import FSNETCMD_GROUNDSTATE -from .FSNETCMD_GETDAMAGE import FSNETCMD_GETDAMAGE -#from .FSNETCMD_GNDTURRETSTATE import FSNETCMD_GNDTURRETSTATE -#from .FSNETCMD_SETTESTAUTOPILOT import FSNETCMD_SETTESTAUTOPILOT -#from .FSNETCMD_REQTOBESIDEWINDOWOFSVR import FSNETCMD_REQTOBESIDEWINDOWOFSVR -#from .FSNETCMD_ASSIGNSIDEWINDOW import FSNETCMD_ASSIGNSIDEWINDOW -#from .FSNETCMD_RESENDAIRREQUEST import FSNETCMD_RESENDAIRREQUEST -#from .FSNETCMD_RESENDGNDREQUEST import FSNETCMD_RESENDGNDREQUEST -#from .FSNETCMD_VERSIONNOTIFY import FSNETCMD_VERSIONNOTIFY -from .FSNETCMD_AIRCMD import FSNETCMD_AIRCMD -#from .FSNETCMD_USEMISSILE import FSNETCMD_USEMISSILE -from .FSNETCMD_TEXTMESSAGE import FSNETCMD_TEXTMESSAGE -from .FSNETCMD_ENVIRONMENT import FSNETCMD_ENVIRONMENT -#from .FSNETCMD_NEEDRESENDJOINAPPROVAL import FSNETCMD_NEEDRESENDJOINAPPROVAL -#from .FSNETCMD_REVIVEGROUND import FSNETCMD_REVIVEGROUND -from .FSNETCMD_WEAPONCONFIG import FSNETCMD_WEAPONCONFIG -#from .FSNETCMD_LISTUSER import FSNETCMD_LISTUSER -#from .FSNETCMD_QUERYAIRSTATE import FSNETCMD_QUERYAIRSTATE -#from .FSNETCMD_USEUNGUIDEDWEAPON import FSNETCMD_USEUNGUIDEDWEAPON -#from .FSNETCMD_AIRTURRETSTATE import FSNETCMD_AIRTURRETSTATE -#from .FSNETCMD_CTRLSHOWUSERNAME import FSNETCMD_CTRLSHOWUSERNAME -#from .FSNETCMD_CONFIRMEXISTENCE import FSNETCMD_CONFIRMEXISTENCE -#from .FSNETCMD_CONFIGSTRING import FSNETCMD_CONFIGSTRING -from .FSNETCMD_LIST import FSNETCMD_LIST, List_Constructor -#from .FSNETCMD_GNDCMD import FSNETCMD_GNDCMD -#from .FSNETCMD_REPORTSCORE import FSNETCMD_REPORTSCORE -#from .FSNETCMD_SERVER_FORCE_JOIN import FSNETCMD_SERVER_FORCE_JOIN -from .FSNETCMD_FOGCOLOR import FSNETCMD_FOGCOLOR -from .FSNETCMD_SKYCOLOR import FSNETCMD_SKYCOLOR -#from .FSNETCMD_GNDCOLOR import FSNETCMD_GNDCOLOR -#from .FSNETCMD_RESERVED_FOR_LIGHTCOLOR import FSNETCMD_RESERVED_FOR_LIGHTCOLOR -#from .FSNETCMD_GENERATEATTACKER import FSNETCMD_GENERATEATTACKER - - -__all__ = ["FSNETCMD_LOGON", "FSNETCMD_LOGOFF", "FSNETCMD_ERROR", - "FSNETCMD_LOADFIELD", "FSNETCMD_ADDOBJECT", - "FSNETCMD_READBACK", "FSNETCMD_SMOKECOLOR", - "FSNETCMD_JOINREQUEST", "FSNETCMD_JOINAPPROVAL", - "FSNETCMD_REJECTJOINREQ", "FSNETCMD_AIRPLANESTATE", - "FSNETCMD_UNJOIN", "FSNETCMD_REMOVEAIRPLANE", - "FSNETCMD_REQUESTTESTAIRPLANE", "FSNETCMD_KILLSERVER", - "FSNETCMD_PREPARESIMULATION", "FSNETCMD_TESTPACKET", - "FSNETCMD_LOCKON", "FSNETCMD_REMOVEGROUND", - "FSNETCMD_MISSILELAUNCH", "FSNETCMD_GETDAMAGE", - "FSNETCMD_WEAPONCONFIG", "FSNETCMD_AIRCMD", - "FSNETCMD_TEXTMESSAGE", "FSNETCMD_ENVIRONMENT", - "FSNETCMD_SKYCOLOR", "FSNETCMD_FOGCOLOR", "FSNETCMD_LIST", "List_Constructor"] diff --git a/lib/PacketManager/packets/constants.py b/lib/PacketManager/packets/constants.py deleted file mode 100644 index 7a32e22..0000000 --- a/lib/PacketManager/packets/constants.py +++ /dev/null @@ -1,472 +0,0 @@ - - -MESSAGE_TYPES = [ - "FSNETCMD_NULL", # 0 - "FSNETCMD_LOGON", # 1 Cli ->Svr", (Svr->Cli for log-on complete acknowledgement.) - "FSNETCMD_LOGOFF", # 2 - "FSNETCMD_ERROR", # 3 - "FSNETCMD_LOADFIELD", # 4 Svr ->Cli", Cli->Svr for read back - "FSNETCMD_ADDOBJECT", # 5 Svr ->Cli - "FSNETCMD_READBACK", # 6 Svr<->Cli - "FSNETCMD_SMOKECOLOR", # 7 Svr<->Cli - "FSNETCMD_JOINREQUEST", # 8 Svr<- Cli - "FSNETCMD_JOINAPPROVAL", # 9 Svr ->Cli - "FSNETCMD_REJECTJOINREQ", # 10 - "FSNETCMD_AIRPLANESTATE", # 11 Svr<->Cli # Be careful in FsDeleteOldStatePacket when modify - "FSNETCMD_UNJOIN", # 12 Svr<- Cli - "FSNETCMD_REMOVEAIRPLANE", # 13 Svr<->Cli - "FSNETCMD_REQUESTTESTAIRPLANE", # 14 - "FSNETCMD_KILLSERVER", # 15 Svr<- Cli - "FSNETCMD_PREPARESIMULATION", # 16 Svr ->Cli - "FSNETCMD_TESTPACKET", # 17 - "FSNETCMD_LOCKON", # 18 Svr<->Cli - "FSNETCMD_REMOVEGROUND", # 19 Svr<->Cli - "FSNETCMD_MISSILELAUNCH", # 20 Svr<->Cli # fsweapon.cpp is responsible for encoding/decoding - "FSNETCMD_GROUNDSTATE", # 21 Svr<->Cli # Be careful in FsDeleteOldStatePacket when modify - "FSNETCMD_GETDAMAGE", # 22 Svr<->Cli - "FSNETCMD_GNDTURRETSTATE", # 23 Svr<->Cli - "FSNETCMD_SETTESTAUTOPILOT", # 24 Svr ->Cli - "FSNETCMD_REQTOBESIDEWINDOWOFSVR", # 25 Svr<- Cli - "FSNETCMD_ASSIGNSIDEWINDOW", # 26 Svr ->Cli - "FSNETCMD_RESENDAIRREQUEST", # 27 Svr<- Cli - "FSNETCMD_RESENDGNDREQUEST", # 28 Svr<- Cli - "FSNETCMD_VERSIONNOTIFY", # 29 Svr ->Cli - "FSNETCMD_AIRCMD", # 30 Svr<->Cli # After 2001/06/24 - "FSNETCMD_USEMISSILE", # 31 Svr ->Cli # After 2001/06/24 - "FSNETCMD_TEXTMESSAGE", # 32 Svr<->Cli - "FSNETCMD_ENVIRONMENT", # 33 Svr<->Cli (*1) - "FSNETCMD_NEEDRESENDJOINAPPROVAL", # 34 Svr<- Cli - "FSNETCMD_REVIVEGROUND", # 35 Svr ->Cli # After 2004 - "FSNETCMD_WEAPONCONFIG", # 36 Svr<->Cli # After 20040618 - "FSNETCMD_LISTUSER", # 37 Svr<->Cli # After 20040726 - "FSNETCMD_QUERYAIRSTATE", # 38 Cli ->Svr # After 20050207 - "FSNETCMD_USEUNGUIDEDWEAPON", # 39 Svr ->Cli # After 20050323 - "FSNETCMD_AIRTURRETSTATE", # 40 Svr<->Cli # After 20050701 - "FSNETCMD_CTRLSHOWUSERNAME", # 41 Svr ->Cli # After 20050914 - "FSNETCMD_CONFIRMEXISTENCE", # 42 Not Used - "FSNETCMD_CONFIGSTRING", # 43 Svr ->Cli # After 20060514 Cli->Svr for read back - "FSNETCMD_LIST", # 44 Svr ->Cli # After 20060514 Cli->Svr for read back - "FSNETCMD_GNDCMD", # 45 Svr<->Cli - "FSNETCMD_REPORTSCORE", # 46 Svr -> Cli # After 20100630 (Older version will ignore) - "FSNETCMD_SERVER_FORCE_JOIN", # 47 Svr -> Cli - "FSNETCMD_FOGCOLOR", # 48 Svr -> Cli - "FSNETCMD_SKYCOLOR", # 49 Svr -> Cli - "FSNETCMD_GNDCOLOR", # 50 Svr -> Cli - "FSNETCMD_RESERVED_FOR_LIGHTCOLOR",# 51 Svr -> Cli - "FSNETCMD_GENERATEATTACKER", # 52 - "FSNETCMD_RESERVED22", # 53 - "FSNETCMD_RESERVED23", # 54 - "FSNETCMD_RESERVED24", # 55 - "FSNETCMD_RESERVED25", # 56 - "FSNETCMD_RESERVED26", # 57 - "FSNETCMD_RESERVED27", # 58 - "FSNETCMD_RESERVED28", # 59 - "FSNETCMD_RESERVED29", # 60 - "FSNETCMD_RESERVED30", # 61 - "FSNETCMD_RESERVED31", # 62 - "FSNETCMD_RESERVED32", # 63 - "FSNETCMD_OPENYSF_RESERVED33", # 64 Reserved for OpenYSF - "FSNETCMD_OPENYSF_RESERVED34", # 65 Reserved for OpenYSF - "FSNETCMD_OPENYSF_RESERVED35", # 66 Reserved for OpenYSF - "FSNETCMD_OPENYSF_RESERVED36", # 67 Reserved for OpenYSF - "FSNETCMD_OPENYSF_RESERVED37", # 68 Reserved for OpenYSF - "FSNETCMD_OPENYSF_RESERVED38", # 69 Reserved for OpenYSF - "FSNETCMD_OPENYSF_RESERVED39", # 70 Reserved for OpenYSF - "FSNETCMD_OPENYSF_RESERVED40", # 71 Reserved for OpenYSF - "FSNETCMD_OPENYSF_RESERVED41", # 72 Reserved for OpenYSF - "FSNETCMD_OPENYSF_RESERVED42", # 73 Reserved for OpenYSF - "FSNETCMD_RESERVED43", # 74 - "FSNETCMD_RESERVED44", # 75 - "FSNETCMD_RESERVED45", # 76 - "FSNETCMD_RESERVED46", # 77 - "FSNETCMD_RESERVED47", # 78 - "FSNETCMD_RESERVED48", # 79 - "FSNETCMD_RESERVED49", # 80 - "FSNETCMD_NOP" -] - -READBACKS = ["FSNETREADBACK_ADDAIRPLANE", - "FSNETREADBACK_ADDGROUND", - "FSNETREADBACK_REMOVEAIRPLANE", - "FSNETREADBACK_REMOVEGROUND", - "FSNETREADBACK_ENVIRONMENT", - "FSNETREADBACK_JOINREQUEST", - "FSNETREADBACK_JOINAPPROVAL", - "FSNETREADBACK_PREPARE", - "FSNETREADBACK____UNUSED____", - "FSNETREADBACK_USEMISSILE", - "FSNETREADBACK_USEUNGUIDEDWEAPON", - "FSNETREADBACK_CTRLSHOWUSERNAME"] - -FSWEAPON_DICT = { - 0: "FSWEAPON_GUN", - 1: "FSWEAPON_AIM9", - 2: "FSWEAPON_AGM65", - 3: "FSWEAPON_BOMB", - 4: "FSWEAPON_ROCKET", - 5: "FSWEAPON_FLARE", - 6: "FSWEAPON_AIM120", - 7: "FSWEAPON_BOMB250", - 8: "FSWEAPON_SMOKE", - 9: "FSWEAPON_BOMB500HD", - 10: "FSWEAPON_AIM9X", - 11: "FSWEAPON_FLAREPOD", - 12: "FSWEAPON_FUELTANK", - 13: "FSWEAPON_RESERVED13", - 14: "FSWEAPON_RESERVED14", - 15: "FSWEAPON_RESERVED15", - 16: "FSWEAPON_RESERVED16", - 17: "FSWEAPON_RESERVED17", - 18: "FSWEAPON_RESERVED18", - 19: "FSWEAPON_RESERVED19", - 20: "FSWEAPON_RESERVED20", - 21: "FSWEAPON_RESERVED21", - 22: "FSWEAPON_RESERVED22", - 23: "FSWEAPON_RESERVED23", - 24: "FSWEAPON_RESERVED24", - 25: "FSWEAPON_RESERVED25", - 26: "FSWEAPON_RESERVED26", - 27: "FSWEAPON_RESERVED27", - 28: "FSWEAPON_RESERVED28", - 29: "FSWEAPON_RESERVED29", - 30: "FSWEAPON_RESERVED30", - 31: "FSWEAPON_RESERVED31", - 32: "FSWEAPON_SMOKE0", - 33: "FSWEAPON_SMOKE1", - 34: "FSWEAPON_SMOKE2", - 35: "FSWEAPON_SMOKE3", - 36: "FSWEAPON_SMOKE4", - 37: "FSWEAPON_SMOKE5", - 38: "FSWEAPON_SMOKE6", - 39: "FSWEAPON_SMOKE7", - 40: "FSWEAPON_RESERVED40", - 41: "FSWEAPON_RESERVED41", - 42: "FSWEAPON_RESERVED42", - 43: "FSWEAPON_RESERVED43", - 44: "FSWEAPON_RESERVED44", - 45: "FSWEAPON_RESERVED45", - 46: "FSWEAPON_RESERVED46", - 47: "FSWEAPON_RESERVED47", - 48: "FSWEAPON_NUMWEAPONTYPE", - 127: "FSWEAPON_NULL", - 128: "FSWEAPON_DEBRIS", - 200: "FSWEAPON_FLARE_INTERNAL" -} - -GUIDEDWEAPONS = missiles = ["FSWEAPON_AGM65", "FSWEAPON_AIM9", "FSWEAPON_AIM120", - "FSWEAPON_AIM9X", "FSWEAPON_ROCKET"] - -ERROR_CODES = ["FSNETERR_NOERR", - "FSNETERR_VERSIONCONFLICT", - "FSNETERR_CANNOTADDOBJECT", - "FSNETERR_REJECT", - "FSNETERR_CANNOTSUSTAIN"] - -AIRCMD_KEYWORDS = [ - "AFTBURNR", #TRUE/FALSE HAS AFTERBURNER - "THRAFTBN", ###[N][KG][LB] AFTERBURNER POWER - "THRMILIT", ###[N][KG][LB] MILITARY POWER - "WEIGHCLN", ###[KG][LB] CLEAN WEIGHT - "WEIGFUEL", ###[KG][LB] MAX WEIGHT OF FUEL - "WEIGLOAD", ###[KG][LB] MAX WEIGHT OF PAYLOAD - "FUELABRN", ###[KG][LB] FUEL CONSUMPTION/SEC WHEN BURNER ON - "FUELMILI", ###[KG][LB] FUEL CONSUMPTION/SEC WHEN MIL POWER - - "LEFTGEAR", #X Y Z [M][IN] LEFT MAIN GEAR POSITION - "RIGHGEAR", #X Y Z [M][IN] RIGHT MAIN GEAR POSITION - "WHELGEAR", #X Y Z [M][IN] WHEEL POSITION - - "CRITAOAP", ###[RAD][DEG] CRITICAL AOA (PLUS) - "CRITAOAM", ###[RAD][DEG] CRITICAL AOA (MINUS - - "CRITSPED", ###[KT][KM/H][M/S][MACH]CRITICAL AIRSPEED - "MAXSPEED", ###[KT][KM/H][M/S][MACH]MAXIMUM AIRSPEED - - "HASSPOIL", #TRUE/FALSE HAS SPOILER - "RETRGEAR", #TRUE/FALSE LANDING GEAR IS RETRACTABLE - "VARGEOMW", #TRUE/FALSE HAS VARIABLE GEOMETRY WING - - "CLVARGEO", ###(DIMENSIONLESS) INCREASE OF CL WHEN VGW IS EXTENDED - "CDVARGEO", ###(DIMENSIONLESS) INCREASE OF CD WHEN VGW IS EXTENDED - "CLBYFLAP", ###(DIMENSIONLESS) INCREASE OF CL WHEN FLAP FULL DOWN - "CDBYFLAP", ###(DIMENSIONLESS) INCREASE OF CD WHEN FLAP FULL DOWN - "CDBYGEAR", ###(DIMENSIONLESS) INCREASE OF CD WHEN GEAR DOWN - "CDSPOILR", ###(DIMENSIONLESS) INCREASE OF CD WHEN SPOILER IS DEPLOYED - - "WINGAREA", ###[M^2][IN^2] AREA OF WING - - "MXIPTAOA", ###[RAD][DEG] MAX INPUT AOA - "MXIPTSSA", ###[RAD][DEG] MAX INPUT YAW - "MXIPTROL", ###[RAD][DEG] MAX INPUT ROLL RATIO - - "CPITMANE", ###(DIMENSIONLESS) PITCH MANEUVABILITY CONSTANT - "CPITSTAB", ###(DIMENSIONLESS) PITCH STABILITY CONSTANT - "CYAWMANE", ###(DIMENSIONLESS) YAW MANEUVABILITY CONSTANT - "CYAWSTAB", ###(DIMENSIONLESS) YAW STABILITY CONSTANT - "CROLLMAN", ###(DIMENSIONLESS) ROLL MANEUVABILITY CONSTANT - - - "CTLLDGEA", #TRUE/FALSE INITIAL GEAR - "CTLBRAKE", #TRUE/FALSE INITIAL BRAKE - "CTLSPOIL", #0.0-1.0 INITIAL SPOILER - "CTLABRNR", #TRUE/FALSE INITIAL AFTERBURNER - "CTLTHROT", #0.0-1.0 INITIAL THROTTLE - "CTLIFLAP", #0.0-1.0 INITIAL FLAP - "CTLINVGW", #0.0-1.0 INITIAL VGW - "CTLATVGW", #TRUE/FALSE INITIAL AUTO VGW - - "POSITION", #X Y Z [M][IN] - "ATTITUDE", #H P B [DEG][RAD] - "INITFUEL", ###[KG][LB] - "INITLOAD", ###[KG][LB] - "INITSPED", ###[M/S][KT][MACH] - - - - "REFVCRUS", ###[M/S][KM/H][KT] CRUISING SPEED - "REFACRUS", ###[M][FT] CRUISING ALTITUDE - "REFVLAND", ###[M/S][KM/H][KT] LANDING SPEED - "REFAOALD", ###[DEG][RAD] AOA WHILE APPROACHING - "REFLNRWY", ###[M][FT][KM] RUNWAY LENGTH REQUIRED TO LAND - - "REM", - - "COCKPITP", - "REFTHRLD", - "REFTCRUS", - - "AUTOCALC", - - "IDENTIFY", - - "MANESPD1", - "MANESPD2", - - "MACHNGUN", - "SMOKEGEN", - "HTRADIUS", - "TRIGGER1", - "TRIGGER2", - "TRIGGER3", - "TRIGGER4", - - "STRENGTH", - - "PROPELLR", - - "VAPORPO0", - "VAPORPO1", - - "INITIGUN", - "INITIAAM", - "INITIAGM", - - "MANESPD3", - - "RADARCRS", - - "MACHNGN2", - - "SMOKEOIL", - "WEAPONCH", - "INITBOMB", - - "MONTRILS", - - "GUNPOWER", - - "CATEGORY", # Normal,Utility or Aerobatic (+fighter, attacker) - - "VGWSPED1", # Auto Vgw Reference Speed (Slower Speed) - "VGWSPED2", # Auto Vgw Reference Speed (Faster Speed) - - "GUNDIREC", # GUN direction - - # 2001/05/06 >> - "INITRCKT", # Initial number of rockets - "MAXNMGUN", # chMaxNumGunBullet - "MAXNMAAM", # chMaxNumAAM Deprecated 2010/08/04 - "MAXNMAGM", # chMaxNumAGM Deprecated 2010/08/04 - "MAXNMRKT", # chMaxNumRocket Deprecated 2010/08/04 - - # 2001/06/05 >> - "AAMSLOT_", # chAAMSlot[chNumAAMSlot++] - "AGMSLOT_", # chAGMSlot[chNumAGMSlot++] - "RKTSLOT_", # chRocketSlot[chNumRocketSlot++] - "BOMBSLOT", # chBombSlot[chNumBombSlot++] - "AAMVISIB", # chAAMVisible; - "AGMVISIB", # chAGMVisible; - "BOMVISIB", # chBombVisible; - "RKTVISIB", # chRocketVisible - "MAXNBOMB", # chMaxNumBomb Deprecated 2010/08/04 - - # 2002/12/11 >> - "ARRESTER", # chArrestingHook - - # 2003/02/02 >> - "TRSTVCTR", # chHasThrustVector - "TRSTDIR0", # chThrVec0 - "TRSTDIR1", # chThrVec1 - "PSTMPTCH", # Post-Stall VPitch - "PSTMYAW_", # Post-Stall VYaw - "PSTMROLL", # Post-Stall VRoll - - # 2003/02/12 - "AIRCLASS", # Aircraft class - - # 2003#02/15 - "PROPEFCY", # Propeller efficiency - "PROPVMIN", # Minimum speed that T=P/v becomes valid - - # 2003/09/19 - "VRGMNOSE", # Variable Geometry Nose : Concorde only - - - # 2003/11/25 - "THRSTREV", # Effectiveness of the Thrust Reverser - - - # 2004/05/22 - "GUNSIGHT", # Lead Gun Sight - - - # 2004/06/14 - "HRDPOINT", # Defining a hardpoint - "LOADWEPN", # Load weapons - "LMTBYHDP", # Limit weapons by hardpoint definition. - "UNLOADWP", # Unload All Weapons (Missiles, Bombs, Rockets. Excluding Guns, Smokes, and Flare) - - # 2005/01/03 - "INSTPANL", # Draw an instrument panel instead of a hud. (av[1] for inst panel definition file.) - - # 2005/01/05 - "MACHNGN3", - "MACHNGN4", - "MACHNGN5", - "MACHNGN6", - "MACHNGN7", - "MACHNGN8", - - # 2005/01/11 - "BOMINBAY", - "BMBAYRCS", - - # 2005/01/23 - "INITAAMM", # Mid-Range AAM - "MAXNAAMM", # Max # Mid-Range AAM - "INITB250", # 250lb Bomb - "MAXNB250", # Max # 250lb Bomb - - # 2005/03/08 - "GUNINTVL", # Gun Interval - - # 2005/06/26 - "NMTURRET", # Number of turret - "TURRETPO", # 0 0m -0.8m 2.7m 0deg 0deg 0deg # Number x y z h p b - "TURRETPT", # 0 -40deg 0deg 0deg # Number MinPitch MaxPitch NeutralPitch - "TURRETHD", # 0 -120deg 120deg 0deg # Number MinHdg MaxHdg NeutralHdg - "TURRETAM", # 0 0 # Ammo(zero -> staGunBullet will be used) - "TURRETIV", # 0 0.5sec # Number ShootingInterval - "TURRETNM", # 0 GUN # DNM Node Name - "TURRETAR", # 0 FALSE # TRUE -> Anti Air Capable - "TURRETGD", # 0 TRUE # TRUE -> Anti Ground Capable - "TURRETCT", # "PILOT" or "GUNNER" - "TURRETRG", # Range - # 2005/09/28 - "TURRETNH", # DNM Node Name (Heading Rotation) - "TURRETNP", # DNM Node Name (Pitch Rotation) - - # 2006/04/25 - "SETCNTRL", # Set Control eg. ILS TRIM:0.3 etc. - - # 2006/07/19 - "EXCAMERA", # Extra Camera - - # 2006/08/05 - "NMACHNGN", # Number of machine guns. - - # 2007/04/06 - "SMOKECOL", # Smoke Color #dmy# R G B - - # 2007/09/16 - "SUBSTNAM", # Substitute airplane (In case the airplane was not installed) - - # 2010/06/26 - "ISPNLPOS", # Instrument Panel Position - "ISPNLSCL", # Instrument Panel Scaling - - # 2010/06/29 - "ISPNLHUD", # Use both inst panel and HUD - "COCKPITA", # Neutral Head Direction - - # 2010/06/30 - "SCRNCNTR", # Screen center (Relative. (-1.0,-1.0)-(1.0,1.0) - "ISPNLATT", # Instrument Panel Orientation - "MAXNMFLR", # Maximum number of flare - - # 2010/07/01 - "FLAPPOSI", # Flap position - "FLAREPOS", # Flare Dispenser Position and Direction - - # 2010/12/11 - "INITAAAM", # Initialize AIM9X - "INITHDBM", # Initialize High-Drag bomb - "ULOADAAM", # Unload all AAMs - "ULOADAGM", # Unload all AGMs - "ULOADBOM", # Unload all Bombs - "ULOADFLR", # Unload all Flare - "ULOADGUN", # Unload all Gun - "ULOADRKT", # Unload all Rocket - - # 2011/12/25 - "LOOKOFST", # Look-at Offset - - # 2012/02/02 - "WPNSHAPE", # Weapon-shape override - - # 2012/02/21 - "GEARHORN", # Landing-gear warning horn - "STALHORN", # Stall-warning horn - - # 2013/04/14 - "CKPITIST", # To Make inst panel available in only one of EXCAMERAs, it can be hidden in the default cockpit view. - "CKPITHUD", # To Make HUD available in only one of EXCAMERAs, it can be hidden in the default cockpit view. - - # 2013/04/25 - "MALFUNCT", # Malfunction - "REPAIRAL", # Repair all - - # 2013/04/25 - "REPAIRFN", # Repair functionality - - # 2013/06/02 - "NOLDGFLR", # No landing flare - - # 2014/06/05 - "NREALPRP", # Number of (real) propeller engines - "REALPROP", # Support for realistic propeller engine - - # 2014/06/13 - "TIREFRIC", # Tire friction coefficient - - # 2014/06/24 - "PSTMSPD1", # Maximum speed that the direct attitude control is fully effective. - "PSTMSPD2", # Speed at which the direct attitude control becomes ineffective. - "PSTMPWR1", # Minimum required power setting for direct attitude control - "PSTMPWR2", # Power setting at which the direct attitude control is fully effective - - # 2014/07/11 - "MAXCDAOA", - "FLATCLR1", - "FLATCLR2", - "CLDECAY1", - "CLDECAY2", - - # 2014/10/17 - "AIRSTATE", # I'm shocked that I didn't have it yet. - - # 2018/10/07 - "INITZOOM", # Initial zoom factor - - None -] diff --git a/lib/Player.py b/lib/Player.py deleted file mode 100644 index 7f54914..0000000 --- a/lib/Player.py +++ /dev/null @@ -1,40 +0,0 @@ -from lib.Aircraft import Aircraft -from lib.PacketManager.packets import FSNETCMD_LOGON, FSNETCMD_ADDOBJECT -class Player: - """ - A player class, this will hold info about the client, including which aircraft they're flying""" - def __init__(self, server_messages, client_messages, streamWriterObject): - - self.username = "" - self.alias = "" - self.aircraft = Aircraft() - self.version = 0 - self.ip = "" - self.streamWriterObject = streamWriterObject - self.is_a_bot = True # We check if they are still present after LOGIN packet, then they're not a bot - - def set_aircraft(self, aircraft:Aircraft): - self.aircraft = aircraft - - def login(self, packet:FSNETCMD_LOGON): - self.username = packet.username - self.alias = packet.alias - self.version = packet.version - - def set_ip(self, ip): - self.ip = ip - - def check_add_object(self, packet:FSNETCMD_ADDOBJECT): - if packet.pilot == self.username: - self.aircraft = Aircraft() - self.aircraft.name = packet.identifier - self.aircraft.id = packet.object_id - self.aircraft.set_position(packet.pos) - self.aircraft.set_initial_config({ - "IFF": packet.iff - }) - return True - return False - - def __str__(self): - return f"Player {self.username} flying {self.aircraft.name} at {self.aircraft.position}" diff --git a/lib/YSchat.py b/lib/YSchat.py deleted file mode 100644 index 980a11b..0000000 --- a/lib/YSchat.py +++ /dev/null @@ -1,20 +0,0 @@ -from struct import pack, unpack -from lib.PacketManager.packets import FSNETCMD_TEXTMESSAGE - -def send(buffer: bytes): - """ - Add to a packet the 'size' information - """ - return pack("I", len(buffer)) + buffer - -def reply(type, buffer:bytes): - """ - Generate packets to send - """ - return send(pack("I", type) + buffer) - -def message(msg: str): - """ - Generate packets for sending messages - """ - return FSNETCMD_TEXTMESSAGE.encode(msg,True) diff --git a/lib/YSendFlight.py b/lib/YSendFlight.py deleted file mode 100644 index c8456cf..0000000 --- a/lib/YSendFlight.py +++ /dev/null @@ -1,6 +0,0 @@ -from struct import pack -from lib.YSchat import reply - -def endFlight(id: int): - buffer = pack("Ih", id, 0) - return reply(12, buffer) diff --git a/lib/YSplayer.py b/lib/YSplayer.py deleted file mode 100644 index e953aa0..0000000 --- a/lib/YSplayer.py +++ /dev/null @@ -1,47 +0,0 @@ -class Player: - def __init__(self,username, playerId, x, y, z, throttle, aam, agm, - gunAmmo, rktAmmo, fuel, ipAddr, life, vx, vy, vz, gValue, - streamWriterObject=None, warningSent=False, smokedAdded=False): - self.username = username - self.ip = ipAddr - self.playerId = playerId - self.position = [x, y, z] - self.throttle = throttle - self.aam = aam - self.agm = agm - self.gunAmmo = gunAmmo - self.rktAmmo = rktAmmo - self.fuel = fuel - self.life = life - self.velocity = [vx, vy, vz] - self.gValue = gValue - self.streamWriterObject = streamWriterObject - self.warningSent = warningSent - self.smokeAdded = smokedAdded - - def __str__(self): - return f"Username: {self.username}, IP: {self.ip}, " \ - f"Player ID: {self.playerId}, X: {self.getX()}, Y: {self.getY()}, Z: {self.getZ()}, " \ - f"Throttle: {self.throttle}, AAM: {self.aam}, AGM: {self.agm}, " \ - f"Gun Ammo: {self.gunAmmo}, Rocket Ammo: {self.rktAmmo}, Fuel: {self.fuel}" \ - f"Life: {self.life}, gValue: {self.gValue}" - - def getX(self): - return self.position[0] - - def getY(self): - return self.position[1] - - def getZ(self): - return self.position[2] - - def setX(self, x): - self.position[0] = x - - def setY(self, y): - self.position[1] = y - - def setZ(self, z): - self.position[2] = z - - diff --git a/lib/YSundead.py b/lib/YSundead.py deleted file mode 100644 index 57e6648..0000000 --- a/lib/YSundead.py +++ /dev/null @@ -1,13 +0,0 @@ -# Black smoke, 50 fuel, no load extra -# Comptaible with every type of plane -# just before their death -# -from struct import pack - -def undeadPatch(id:int, data:bytes): - buffer = data[0:8] + pack("I", id) + data[12:] - return buffer - -def smokedPlane(id:int): - data = b'"\x00\x00\x00$\x00\x00\x00*\x03\x01\x00\x0c\x00\xc8\x00\x14\x00 \x00\x08!!\x00\x08!"\x00\x08!\x00\x00\xb8\x0b\xc8\x00\x14\x00' - return undeadPatch(id, data) diff --git a/lib/YSviaversion.py b/lib/YSviaversion.py deleted file mode 100644 index 70b4554..0000000 --- a/lib/YSviaversion.py +++ /dev/null @@ -1,11 +0,0 @@ -from struct import pack - -def genViaVersion(username: str, finalVersion: int): - """ - Generates Packets for porting the version - """ - padding = 16-len(username) - byteUserame = [] - for char in username: - byteUserame.append(char.encode('ascii')) - return pack("II16cI", 24, 1, *byteUserame+(padding*[b"\x00"]), finalVersion) diff --git a/lib/__init__.py b/lib/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/lib/discordSync.py b/lib/discordSync.py deleted file mode 100644 index 0a8e8be..0000000 --- a/lib/discordSync.py +++ /dev/null @@ -1,100 +0,0 @@ -import aiohttp -import asyncio -from config import * -from lib.PacketManager.packets.FSNETCMD_TEXTMESSAGE import FSNETCMD_TEXTMESSAGE as txtMsgr -from logging import debug, warning -import re - -BOT_TOKEN = DISCORD_TOKEN - -# API Base URL -BASE_URL = 'https://discord.com/api/v10' - -# Headers for making API requests -HEADERS = { - 'Authorization': f'Bot {BOT_TOKEN}', - 'Content-Type': 'application/json' -} - -# Function to send a message to a specific Discord channel -async def discord_send_message(channel_id:int, message:str, santize_message:bool = True): - """ - Santizes the message of @everyone and @here pings - and then sends the message to given channel id - """ - if santize_message : message = re.sub(r'@(?:everyone|here)', '', message) - url = f'{BASE_URL}/channels/{channel_id}/messages' - payload = { - 'content': message - } - - async with aiohttp.ClientSession() as session: - async with session.post(url, json=payload, headers=HEADERS) as response: - if response.status in [200, 201]: - pass - else: - warning(f'Failed to send message. Status Code: {response.status} | {await response.text()}') - -# Function to fetch messages from a specific Discord channel - -async def discord_fetch_messages(channel_id, last_message_id=None): - url = f'{BASE_URL}/channels/{channel_id}/messages' - params = {'limit': 1} - if last_message_id: - params['after'] = last_message_id - - try: - async with aiohttp.ClientSession() as session: - async with session.get(url, headers=HEADERS, params=params) as response: - if response.status == 200: - return await response.json() - else: - warning(f"Failed to fetch messages. Status Code: {response.status} | {await response.text()}") - return [] - except (aiohttp.ClientError, asyncio.TimeoutError) as e: - warning(f"Network error while fetching messages: {e}") - return [] # Return empty list to avoid crashing - - -# Callback function when a new message is detected -def on_new_message(message): - author = message['author'] - # Skip messages from bots (including this bot itself) - if author.get('bot'): # Safely get the 'bot' key (returns None if key does not exist) - return - - username = author['username'] - content = message['content'] - debug(f'New Discord message from {username}: {content}') - -# Asynchronous function to monitor a Discord channel for new messages -async def monitor_channel(channel_id, playerList:list): - last_message_id = None - while True: - # Fetch new messages - messages = await discord_fetch_messages(channel_id, last_message_id) - if messages: - # Process only the latest message - message = messages[0] - if messages: - message = messages[0] - if last_message_id is None or message['id'] > last_message_id: # Ensure only newer messages are processed - last_message_id = message['id'] - if not message['author'].get('bot'): # Skip messages from bot - encoded_msg = txtMsgr.encode(f"[Discord] {message['author']['username']}: {message['content']}", True) - for player in playerList: - if player.streamWriterObject.is_closing(): - if not player.is_a_bot: - asyncio.create_task(discord_send_message(channel_id, f"{player.username} has left the server!")) - playerList.remove(player) # Remove disconnected players - continue - player.streamWriterObject.write(encoded_msg) - try: - await player.streamWriterObject.drain() - except Exception as e: - warning(f"Error while sending message to {player.username}: {e}") - if not player.is_a_bot: - asyncio.create_task(discord_send_message(channel_id, f"{player.username} has left the server!")) - playerList.remove(player) - on_new_message(message) - await asyncio.sleep(1) # Poll every second (adjust as needed) diff --git a/lib/parseFlightData.py b/lib/parseFlightData.py deleted file mode 100644 index 35aa3b3..0000000 --- a/lib/parseFlightData.py +++ /dev/null @@ -1,67 +0,0 @@ -from math import pi -from struct import unpack as up - -# Authored by https://theindiandev.in -# Date : Jan 26 2025 -# Not more than 80 characters per line - -def parseFlightData(data: bytes): - """ - Input : Bytecode, Type 11 datapackets from ysflight server, - do NOT strip the heading(first 8 octets) - Output : tuple - - Tested only on 20150425 version of ysflight - """ - # Assuming version(info1) = 5,4 when speed < 400kts - # version(info1) = 3 when speed > 400kts OR just spawning in the server - version = up("h", data[16:18])[0] - if version == 5 or version == 4: - tRemote = up("f", data[8:12])[0] # Remote Timer from client - playerId = up("I", data[12:16])[0] - x,y,z = up("fff", data[18:30]) - # Heading, Pitch and Bank values are correct but cannot be interepeted - # correctly - # FIXME - h, p, b = up("hhh", data[30:36]) - heading = (h*pi/32768.0) - aoa = (p*pi/32768.0) - bank = (b*pi/32760.0) - vx, vy, vz = up("hhh", data[36:42]) - # FIXME : Unkown padding of 2 bytes, it seems to be from the fuel as a - # integer however correct values only with a short - smokeOil, fuel, payload, _ = up("hhhh", data[48:56]) - flightState, vgw = up("BB", data[56:58]) - gunAmmo, rktAmmo = up("hh", data[62:66]) - # FIXME : aam count incorrect - aam, agm, bomb, life = up("BBBB", data[66:70]) # aam, agm, bomb, life - gValue = (up("B", data[70:71])[0])/10 - throttle, elev, ail, rud, trim, bombBayInfo = up("BBBBBB", data[71:77]) - elif version == 3: - tRemote = up("f", data[8:12])[0] - playerId = up("I", data[12:16])[0] - x,y,z = up("fff", data[20:32]) - h, p, b = up("hhh", data[32:38]) - heading = (h*pi/32768.0) - aoa = (p*pi/32768.0) - bank = (b*pi/32760.0) - vx, vy, vz = up("hhh", data[38:44]) - gValue = (up("h", data[50:52])[0])/100 - gunAmmo, aam, agm, bomb, smokeOil = up("5h", data[52:62]) - fuel, payload = up("2f", data[62:70]) - life = up("h", data[70:72])[0] - flightState, vgw = up("BB", data[72:74]) - throttle, elev, ail, rud, trim = up("B4c", data[80:85]) - rktAmmo = up("h", data[85:87])[0] - bombBayInfo = up("B", data[89:90])[0] - else: - print(f"Unkown version {version}") - print("Payload Dump:") - print(data) - raise ValueError("Unknown version of ysflight") - - - return (tRemote, playerId, x, y, z, heading, aoa, bank, vx, vy, vz, - smokeOil, fuel, payload, flightState, vgw, gunAmmo, rktAmmo, - aam, agm, bomb, life, throttle, elev, ail, rud, trim, - bombBayInfo, gValue) diff --git a/lib/plugin_manager.py b/lib/plugin_manager.py deleted file mode 100644 index ae4cf0b..0000000 --- a/lib/plugin_manager.py +++ /dev/null @@ -1,74 +0,0 @@ -import importlib -import os -import sys -from logging import info, warning - -PLUGIN_DIR = os.path.join(os.path.dirname(__file__), '../plugins') -sys.path.append(PLUGIN_DIR) - -class PluginManager: - def __init__(self): - self.plugins = {} - self.hooks= {} - self.commands = {} - self.help_message = "List of Available Commands:\n" - self.load_plugins() - - def load_plugins(self): - for plugin in os.listdir(PLUGIN_DIR): - plugin_path = os.path.join(PLUGIN_DIR, plugin) - if plugin.endswith('.py') and not plugin.startswith('__'): - plugin_name = plugin[:-3] - plugin_module = importlib.import_module(plugin_name) - if hasattr(plugin_module, 'ENABLED') and plugin_module.ENABLED: - if hasattr(plugin_module, 'Plugin'): - plugin_instance = plugin_module.Plugin() - self.register_plugin(plugin_instance) - info(f"Loaded plugin {plugin_name}") - self.plugins[plugin_name] = plugin_instance - elif os.path.isdir(plugin_path) and os.path.exists(os.path.join(plugin_path, '__init__.py')): - plugin_module = importlib.import_module(plugin) - if hasattr(plugin_module, 'ENABLED') and plugin_module.ENABLED: - if hasattr(plugin_module, 'Plugin'): - plugin_instance = plugin_module.Plugin() - self.register_plugin(plugin_instance) - info(f"Loaded plugin {plugin}") - self.plugins[plugin] = plugin_instance - - def register_plugin(self, plugin): - """Registers the plugin with the plugin manager""" - plugin.register(self) - - def register_hook(self, hook_name, callback): - """Registers the hook with the plugin manager""" - if hook_name not in self.hooks: - self.hooks[hook_name] = [] - self.hooks[hook_name].append(callback) - - def register_command(self, command_name, callback): - """Registers the command with the plugin manager""" - if command_name in self.commands: - warning(f"Command {command_name} already registered, Ignoring this registration") - else: - self.commands[command_name] = callback - self.help_message = self.help_message + f"/{command_name}\n" - - def triggar_hook(self, hook_name, data, *args, **kwargs): - """Triggars the callbacks for the hook. - If a callback returns False, then the original data is set to None - and not forwarded to the destination. This is useful for modifying - packets.""" - keep_orignal = True - if hook_name in self.hooks: - for callback in self.hooks[hook_name]: - keep = callback(data, *args, **kwargs) - if keep == False: - keep_orignal = False - return keep_orignal - - def trigger_command(self, command:str, player, full_message:str, message_to_client:list, message_to_server:list): - """Triggers the command""" - if command in self.commands: - self.commands[command](full_message, player, message_to_client, message_to_server) - return True - return False diff --git a/lib/triggerCommand.py b/lib/triggerCommand.py deleted file mode 100644 index d6a6116..0000000 --- a/lib/triggerCommand.py +++ /dev/null @@ -1,13 +0,0 @@ -from config import * -from lib import YSchat -from logging import debug - -async def triggerCommand(command, full_message, player, message_to_client, message_to_server, plugin_manager): - debug(f"{player.username} triggered command {command}") - if command == "help": - message_to_client.append(YSchat.message(plugin_manager.help_message)) - return 0 - - h = plugin_manager.trigger_command(command, player, full_message , message_to_client, message_to_server) - if not h: - message_to_client.append(YSchat.message(f"Command not found, Type {PREFIX}help for all commands.")) diff --git a/lib/triggerRespectiveHook.py b/lib/triggerRespectiveHook.py deleted file mode 100644 index 25801a0..0000000 --- a/lib/triggerRespectiveHook.py +++ /dev/null @@ -1,127 +0,0 @@ -from logging import debug - -def triggerRespectiveHook(packet_type, packet, player, message_to_client, message_to_server, plugin_manager): - if packet_type == "FSNETCMD_LOGON": - keep_message = plugin_manager.triggar_hook('on_login', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_LOGOFF": - keep_message = plugin_manager.triggar_hook('on_logout', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_ERROR": - keep_message = plugin_manager.triggar_hook('on_error', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_LOADFIELD": - keep_message = plugin_manager.triggar_hook('on_load_field', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_ADDOBJECT": - keep_message = plugin_manager.triggar_hook('on_add_object', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_READBACK": - keep_message = plugin_manager.triggar_hook('on_readback', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_SMOKECOLOR": - keep_message = plugin_manager.triggar_hook('on_smoke_color', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_JOINREQUEST": - keep_message = plugin_manager.triggar_hook('on_join_request', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_JOINAPPROVAL": - keep_message = plugin_manager.triggar_hook('on_join_approval', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_REJECTJOINREQ": - keep_message = plugin_manager.triggar_hook('on_reject_join_request', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_AIRPLANESTATE": - keep_message = plugin_manager.triggar_hook('on_flight_data', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_UNJOIN": - keep_message = plugin_manager.triggar_hook('on_unjoin', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_REMOVEAIRPLANE": - keep_message = plugin_manager.triggar_hook('on_remove_airplane', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_REQUESTTESTAIRPLANE": - keep_message = plugin_manager.triggar_hook('on_request_test_airplane', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_KILLSERVER": - keep_message = plugin_manager.triggar_hook('on_kill_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_PREPARESIMULATION": - keep_message = plugin_manager.triggar_hook('on_prepare_simulation', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_TESTPACKET": - keep_message = plugin_manager.triggar_hook('on_test_packet', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_LOCKON": - keep_message = plugin_manager.triggar_hook('on_lockon', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_REMOVEGROUND": - keep_message = plugin_manager.triggar_hook('on_remove_ground', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_MISSILELAUNCH": - keep_message = plugin_manager.triggar_hook('on_missile_launch', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_GETDAMAGE": - keep_message = plugin_manager.triggar_hook('on_get_damage', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_WEAPONCONFIG": - keep_message = plugin_manager.triggar_hook('on_weapon_config', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_AIRCMD": - keep_message = plugin_manager.triggar_hook('on_air_cmd', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_TEXTMESSAGE": - keep_message = plugin_manager.triggar_hook('on_chat', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_ENVIRONMENT": - keep_message = plugin_manager.triggar_hook('on_environment', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_SKYCOLOR": - keep_message = plugin_manager.triggar_hook('on_sky_color', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_FOGCOLOR": - keep_message = plugin_manager.triggar_hook('on_fog_color', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_LIST": - keep_message = plugin_manager.triggar_hook('on_list', packet, player, message_to_client, message_to_server) - else: - keep_message = True - debug(f"Unknown packet type {packet_type}, C2S") - - return keep_message - -def triggerRespectiveHookServer(packet_type, packet, player, message_to_client, message_to_server, plugin_manager): - if packet_type == "FSNETCMD_LOGON": - keep_message = plugin_manager.triggar_hook('on_login_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_LOGOFF": - keep_message = plugin_manager.triggar_hook('on_logout_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_ERROR": - keep_message = plugin_manager.triggar_hook('on_error_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_LOADFIELD": - keep_message = plugin_manager.triggar_hook('on_load_field_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_ADDOBJECT": - keep_message = plugin_manager.triggar_hook('on_add_object_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_READBACK": - keep_message = plugin_manager.triggar_hook('on_readback_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_SMOKECOLOR": - keep_message = plugin_manager.triggar_hook('on_smoke_color_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_JOINREQUEST": - keep_message = plugin_manager.triggar_hook('on_join_request_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_JOINAPPROVAL": - keep_message = plugin_manager.triggar_hook('on_join_approval_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_REJECTJOINREQ": - keep_message = plugin_manager.triggar_hook('on_reject_join_request_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_AIRPLANESTATE": - keep_message = plugin_manager.triggar_hook('on_flight_data_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_UNJOIN": - keep_message = plugin_manager.triggar_hook('on_unjoin_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_REMOVEAIRPLANE": - keep_message = plugin_manager.triggar_hook('on_remove_airplane_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_REQUESTTESTAIRPLANE": - keep_message = plugin_manager.triggar_hook('on_request_test_airplane_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_KILLSERVER": - keep_message = plugin_manager.triggar_hook('on_kill_server_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_PREPARESIMULATION": - keep_message = plugin_manager.triggar_hook('on_prepare_simulation_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_TESTPACKET": - keep_message = plugin_manager.triggar_hook('on_test_packet_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_LOCKON": - keep_message = plugin_manager.triggar_hook('on_lockon_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_REMOVEGROUND": - keep_message = plugin_manager.triggar_hook('on_remove_ground_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_MISSILELAUNCH": - keep_message = plugin_manager.triggar_hook('on_missile_launch_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_GETDAMAGE": - keep_message = plugin_manager.triggar_hook('on_get_damage_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_WEAPONCONFIG": - keep_message = plugin_manager.triggar_hook('on_weapon_config_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_AIRCMD": - keep_message = plugin_manager.triggar_hook('on_air_cmd_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_TEXTMESSAGE": - keep_message = plugin_manager.triggar_hook('on_chat_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_ENVIRONMENT": - keep_message = plugin_manager.triggar_hook('on_environment_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_SKYCOLOR": - keep_message = plugin_manager.triggar_hook('on_sky_color_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_FOGCOLOR": - keep_message = plugin_manager.triggar_hook('on_fog_color_server', packet, player, message_to_client, message_to_server) - elif packet_type == "FSNETCMD_LIST": - keep_message = plugin_manager.triggar_hook('on_list_server', packet, player, message_to_client, message_to_server) - else: - keep_message = True - debug(f"Unknown packet type {packet_type}, S2C") - - return keep_message diff --git a/plugins/allcaps.py b/plugins/allcaps.py deleted file mode 100644 index 83b5aec..0000000 --- a/plugins/allcaps.py +++ /dev/null @@ -1,23 +0,0 @@ -"""This plugin will convert all chat messages to all caps. -It can be enabled here by changing the value of ENABLED to True.""" -from lib.PacketManager.packets import FSNETCMD_TEXTMESSAGE -from logging import info -ENABLED = False - -class Plugin: - def __init__(self): - self.plugin_manager = None - - def register(self, plugin_manager): - self.plugin_manager = plugin_manager - self.plugin_manager.register_hook('on_chat', self.on_chat) - - def on_chat(self, data, player,message_to_client, message_to_server): - if ENABLED: - message = FSNETCMD_TEXTMESSAGE(data, should_decode=True) - message.message = message.message.upper() - message = FSNETCMD_TEXTMESSAGE.encode(f"({message.user}){message.message}", with_size=True) - message_to_server.append(message) - - - return False diff --git a/plugins/chat_weather_setter.py b/plugins/chat_weather_setter.py deleted file mode 100644 index 5b31a38..0000000 --- a/plugins/chat_weather_setter.py +++ /dev/null @@ -1,100 +0,0 @@ -"""This plugin will set the weather based on a chat message. -""" -from lib.PacketManager.packets import FSNETCMD_SKYCOLOR, FSNETCMD_FOGCOLOR, FSNETCMD_TEXTMESSAGE, FSNETCMD_ENVIRONMENT -from random import randint -ENABLED = True - -class Plugin: - def __init__(self): - self.initialWeather = None - self.plugin_manager = None - - def register(self, plugin_manager): - self.plugin_manager = plugin_manager - #self.plugin_manager.register_hook('on_chat', self.on_chat) - self.plugin_manager.register_hook('on_environment_server', self.on_environment) - self.plugin_manager.register_command('fog', self.fog) - self.plugin_manager.register_command('sky', self.sky) - self.plugin_manager.register_command('time', self.time) - self.plugin_manager.register_command('vis', self.visibility) - - def fog(self, full_message, player, message_to_client, message_to_server): - try: - args = list(map(int, full_message[4:].split(','))) - except: - message_to_client.append(FSNETCMD_TEXTMESSAGE.encode("Invalid fog argument, usage /fog r,g,b", True)) - return - fog_colour_packet = FSNETCMD_FOGCOLOR.encode(args[0], args[1], args[2], True) - message_to_client.append(fog_colour_packet) - - def sky(self, full_message, player, message_to_client, message_to_server): - try: - args = list(map(int, full_message[4:].split(','))) - except Exception as e: - message_to_client.append(FSNETCMD_TEXTMESSAGE.encode("Invalid sky argument, usage /sky r,g,b", True)) - return True - sky_colour_packet = FSNETCMD_SKYCOLOR.encode(args[0], args[1], args[2], True) - message_to_client.append(sky_colour_packet) - return True - - def time(self, full_message, player, message_to_client, message_to_server): - requested = full_message[6:].lower() - if requested == 'day' and self.initialWeather: - packet = FSNETCMD_ENVIRONMENT.set_time(self.initialWeather.buffer, False, True) - self.initialWeather = FSNETCMD_ENVIRONMENT(packet[4:]) - message_to_client.append(packet) - - elif requested == 'night' and self.initialWeather: - packet = FSNETCMD_ENVIRONMENT.set_time(self.initialWeather.buffer, True, True) - self.initialWeather = FSNETCMD_ENVIRONMENT(packet[4:]) - message_to_client.append(packet) - - else: - message_to_client.append(FSNETCMD_TEXTMESSAGE.encode("Invalid time argument, usage /time night or /time day", True)) - return True - - def visibility(self, full_message, player, message_to_client, message_to_server): - visibility = int(full_message[4:]) - returnpacket = FSNETCMD_ENVIRONMENT.set_visibility(self.initialWeather.buffer, visibility, True) - self.initialWeather = FSNETCMD_ENVIRONMENT(returnpacket[4:]) - message_to_client.append(returnpacket) - return True - - """ - def on_chat(self, data, player, messages_to_client, *args): - if ENABLED: - message = FSNETCMD_TEXTMESSAGE(data).message - if message[:3].lower() == 'fog': - #We'll split the fog r,g,b message into a list of 3 integers - fog = list(map(int, message[4:].split(','))) - fog_colour_packet = FSNETCMD_FOGCOLOR.encode(fog[0], fog[1], fog[2], True) - messages_to_client.append(fog_colour_packet) - - if message[:3].lower() == 'sky': - sky = list(map(int, message[4:].split(','))) - sky_colour_packet = FSNETCMD_SKYCOLOR.encode(sky[0], sky[1], sky[2], True) - messages_to_client.append(sky_colour_packet) - - if message[:3].lower() == 'day' and self.initialWeather: - packet = FSNETCMD_ENVIRONMENT.set_time(self.initialWeather.buffer, False, True) - self.initialWeather = FSNETCMD_ENVIRONMENT(packet[4:]) - messages_to_client.append(packet) - - if message[:5].lower() == 'night' and self.initialWeather: - packet = FSNETCMD_ENVIRONMENT.set_time(self.initialWeather.buffer, True, True) - self.initialWeather = FSNETCMD_ENVIRONMENT(packet[4:]) - messages_to_client.append(packet) - - if message[:3].lower() == 'vis': - visibility = int(message[4:]) - returnpacket = FSNETCMD_ENVIRONMENT.set_visibility(self.initialWeather.buffer, visibility, True) - self.initialWeather = FSNETCMD_ENVIRONMENT(returnpacket[4:]) - messages_to_client.append(returnpacket) - return False - """ - - - def on_environment(self, data, *args): - """Store the initial weather packet for the server.""" - self.initialWeather = FSNETCMD_ENVIRONMENT(data) - return True diff --git a/plugins/command_test.py b/plugins/command_test.py deleted file mode 100644 index 6d8e8af..0000000 --- a/plugins/command_test.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -This is an example test command! -""" - -from lib import YSchat -from time import sleep - -ENABLED = False - -class Plugin: - def __init__(self): - self.plugin_manager = None - - def register(self, plugin_manager): - self.plugin_manager = plugin_manager - self.plugin_manager.register_command('test', self.test) - self.plugin_manager.register_command('timer', self.timer) - - def test(self, full_message, player, message_to_client, message_to_server): - message_to_client.append(YSchat.message("Test command received")) - return True - - def timer(self, full_message, player, message_to_client, message_to_server): - sleep(5) - message_to_client.append(YSchat.message("Timer ended")) - return True diff --git a/plugins/custom_aircraft_list/Plugin.py b/plugins/custom_aircraft_list/Plugin.py deleted file mode 100644 index 0fc1bd0..0000000 --- a/plugins/custom_aircraft_list/Plugin.py +++ /dev/null @@ -1,42 +0,0 @@ -"""TThis plugin will cause the aircraft to emit smoke if it's health is below a certain threshold. -It is also an example of a plugin as a folder/module. -This can be used as a basis for more complex plugins that may need multiple files.""" -from lib.PacketManager.packets import List_Constructor -from json import load -from struct import pack -from logging import error -ENABLED = False -custom_list_file = "plugins\\custom_aircraft_list\\custom_list.json" - -class Plugin: - def __init__(self): - self.plugin_manager = None - self.aircraft_list = [] - - def register(self, plugin_manager): - self.plugin_manager = plugin_manager - with open(custom_list_file, 'r', encoding='utf-8') as f: - json_file = load(f) - if isinstance(json_file,list): - self.aircraft_list = json_file - else: - error(f"Invalid JSON file {custom_list_file}. Must be a list of aircraft.") - self.plugin_manager.register_hook('on_list', self.on_list) - self.plugin_manager.register_hook('on_list_server', self.on_list_server) - - def on_list(self, packet, player, message_to_client, message_to_server): - if ENABLED: - return False - - def on_list_server(self, packet, player, message_to_client, message_to_server): - if ENABLED: - #Send the packet straight back to the server, and prevent it being passed to the client. - packet = pack("I",len(packet)) + packet - message_to_server.append(packet) - if not hasattr(player, 'custom_packet_sent'): - player.custom_packet_sent=True - #Send the custom list packets. - lc = List_Constructor(self.aircraft_list).get_packets() - for packet in lc: - message_to_client.append(packet) - return False diff --git a/plugins/custom_aircraft_list/__init__.py b/plugins/custom_aircraft_list/__init__.py deleted file mode 100644 index 425d2ad..0000000 --- a/plugins/custom_aircraft_list/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .Plugin import Plugin -from .Plugin import ENABLED \ No newline at end of file diff --git a/plugins/custom_aircraft_list/custom_list.json b/plugins/custom_aircraft_list/custom_list.json deleted file mode 100644 index 987350d..0000000 --- a/plugins/custom_aircraft_list/custom_list.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - "AIRBUS300", - "AIRBUS320", - "B737", - "B747", - "B767", - "B777", - "CONCORDE", - "DIAMOND_ECLIPSE", - "PIPER_ARCHER(WASHIN-AIR_MARKING)", - "T-400", - "U-125", - "U-125A" -] diff --git a/plugins/discolights.py b/plugins/discolights.py deleted file mode 100644 index db441e7..0000000 --- a/plugins/discolights.py +++ /dev/null @@ -1,22 +0,0 @@ -"""This plugin will flash the lights/fog colour whenever a flight status update -is sent -It can be enabled here by changing the value of ENABLED to True.""" -from lib.PacketManager.packets import FSNETCMD_SKYCOLOR, FSNETCMD_FOGCOLOR -from random import randint -ENABLED = False - -class Plugin: - def __init__(self): - self.plugin_manager = None - - def register(self, plugin_manager): - self.plugin_manager = plugin_manager - self.plugin_manager.register_hook('on_flight_data', self.on_receive) - - def on_receive(self, data, player, messages_to_client, *args): - if ENABLED: - sky_colour_packet = FSNETCMD_SKYCOLOR.encode(randint(0, 255), randint(0, 255), randint(0, 255), True) - fog_colour_packet = FSNETCMD_FOGCOLOR.encode(randint(0, 255), randint(0, 255), randint(0, 255), True) - messages_to_client.append(sky_colour_packet) - messages_to_client.append(fog_colour_packet) - return True diff --git a/plugins/over_g_damage.py b/plugins/over_g_damage.py deleted file mode 100644 index 50c1b21..0000000 --- a/plugins/over_g_damage.py +++ /dev/null @@ -1,31 +0,0 @@ -"""This plugin will cause damage to the aircraft if -it exceeds the g-force limit set in the config file.""" -from lib.PacketManager.packets import FSNETCMD_GETDAMAGE, FSNETCMD_TEXTMESSAGE -from config import G_LIM -import time - -# CONFIG -ENABLED = True # Enable or disable the plugin -INTERVAL = 0.3 # Interval of second before G Limit check is enforced - -class Plugin: - def __init__(self): - self.plugin_manager = None - - def register(self, plugin_manager): - self.plugin_manager = plugin_manager - self.plugin_manager.register_hook('on_flight_data', self.on_receive) - - def on_receive(self, data, player, messages_to_client, *args): - if ENABLED: - if abs(player.aircraft.last_packet.g_value)> G_LIM: - if time.time() - player.aircraft.last_over_g_message > INTERVAL: - player.aircraft.last_over_g_message = time.time() - damage_packet = FSNETCMD_GETDAMAGE.encode(player.aircraft.id, - 1, 1, - player.aircraft.id, - 1, 11,0, True) - warning_message = FSNETCMD_TEXTMESSAGE.encode(f"You are exceeding the G Limit for the aircraft!, gValue = {player.aircraft.last_packet.g_value}!",True) - messages_to_client.append(damage_packet) - messages_to_client.append(warning_message) - return True diff --git a/plugins/smoke_on_damage/Plugin.py b/plugins/smoke_on_damage/Plugin.py deleted file mode 100644 index 08c184b..0000000 --- a/plugins/smoke_on_damage/Plugin.py +++ /dev/null @@ -1,48 +0,0 @@ -"""TThis plugin will cause the aircraft to emit smoke if it's health is below a certain threshold. -It is also an example of a plugin as a folder/module. -This can be used as a basis for more complex plugins that may need multiple files.""" -from lib.PacketManager.packets import FSNETCMD_AIRCMD, FSNETCMD_AIRPLANESTATE, FSNETCMD_TEXTMESSAGE -from logging import debug -from config import SMOKE_LIFE, SMOKE_PLANE -ENABLED = True - -class Plugin: - def __init__(self): - self.plugin_manager = None - - def register(self, plugin_manager): - self.plugin_manager = plugin_manager - self.plugin_manager.register_hook('on_flight_data', self.on_flight_data) - self.plugin_manager.register_hook('on_weapon_config', self.on_weapon_config) - - def on_flight_data(self, data, player,message_to_client, message_to_server): - """After the initial incoming flight packet, check whether - the health is below the threshold, if so add smoke""" - if SMOKE_PLANE and player.aircraft.life 0: - client_writer.write(message_to_client.pop(0)) - await client_writer.drain() - if len(message_to_server) > 0: - server_writer.write(message_to_server.pop(0)) - await server_writer.drain() - - if not reader.at_eof(): # Connection closed - try: - header = await reader.readexactly(4) # Ensures we always get 4 bytes - except asyncio.IncompleteReadError: - break - except ConnectionResetError: - break - except Exception as e: - critical(f"Error reading header: {e}") - break - - if not header: - break # Connection closed - - length = unpack("I", header)[0] - - packet = await reader.read(length) - - if not packet: - break - - data = header + packet - packet_type = PacketManager().get_packet_type(packet) - if direction == "client_to_server": - debug("C2S" + str(packet_type)) - debug(data) - - try: - - - if packet_type == "FSNETCMD_LOGON": - # keep_message = plugin_manager.triggar_hook('on_login', packet, player, message_to_client, message_to_server) - # if not keep_message: - # data = None - player.login(FSNETCMD_LOGON(packet)) - if player.version != YSF_VERSION and VIA_VERSION: - info(f"ViaVersion enabled : Porting {player.username} from {player.version} to {YSF_VERSION}") - message_to_client.append(YSchat.message(f"Porting you to YSFlight {YSF_VERSION}, This is currently Experimental")) - message_to_client.append(YSchat.message(f"Please report any bugs to the server admin or join with the correct version")) - data = YSviaversion.genViaVersion(player.username, YSF_VERSION) #TODO: Refactor using the FSNETCMD packet. - writer.write(data) - continue - - elif packet_type == "FSNETCMD_AIRPLANESTATE": - player.aircraft.add_state(FSNETCMD_AIRPLANESTATE(packet)) #TODO: Do we want to convert all this to plugins? Probably not, but there is duplicated functionality - # keep_message = plugin_manager.triggar_hook('on_flight_data', packet, player, message_to_client, message_to_server) - # if not keep_message: - # data = None - - if player.aircraft.prev_life < player.aircraft.life and player.aircraft.prev_life != -1 and not player.aircraft.just_repaired: - cheatingMsg = YSchat.message(f"{HEALTH_HACK_MESSAGE} by {player.username}") - warning(f"Health hack detected for {player.username}, Connected from {player.ip}") - message_to_server.append(cheatingMsg) - - player.aircraft.just_repaired = False - - elif packet_type == "FSNETCMD_UNJOIN": - player.aircraft.reset() - - elif packet_type == "FSNETCMD_WEAPONCONFIG": - #keep_message = plugin_manager.triggar_hook('on_weapon_config', packet, player, message_to_client, message_to_server) - #if not keep_message: - # data = None - pass - - elif packet_type == "FSNETCMD_TEXTMESSAGE": - msg = FSNETCMD_TEXTMESSAGE(packet) - # keep_message = plugin_manager.triggar_hook('on_chat', packet, player, message_to_client, message_to_server) - # if not keep_message: - # data = None - - finalMsg = (f"{player.username} : {msg.message}") - if msg.message.startswith(PREFIX): - data = None - command = msg.message.split(" ")[0][1:] - asyncio.create_task(triggerCommand.triggerCommand(command, msg.message, player, message_to_client, message_to_server, plugin_manager)) - - if DISCORD_ENABLED: - # Make it non blocking! - asyncio.create_task(discord_send_message(CHANNEL_ID, finalMsg)) - - elif packet_type == "FSNETCMD_LIST": - # keep_message = plugin_manager.triggar_hook('on_list', packet, player, message_to_client, message_to_server) - # if not keep_message: - # data = None - pass - - keep_message = triggerRespectiveHook(packet_type, packet, player, message_to_client, message_to_server, plugin_manager) - if not keep_message: data = None - - except Exception as e: - warning(f"Error parsing flight data: {e}", exc_info=True) - traceback.print_exc() # This will display the full traceback - - else : - debug("S2C" + str(packet_type)) - debug(data) - - keep_message = triggerRespectiveHookServer(packet_type, packet, player, message_to_client, message_to_server, plugin_manager) - if not keep_message: data = None - - #Coming from the server to the client - if packet_type == "FSNETCMD_ADDOBJECT": - if player.check_add_object(FSNETCMD_ADDOBJECT(packet)): - info(f"{player.username} has spawned an aircraft") - addSmoke = FSNETCMD_WEAPONCONFIG.addSmoke(player.aircraft.id) - message_to_server.append(addSmoke) - - elif packet_type == "FSNETCMD_AIRCMD": - #Check the configs against the current aircraft - #These come server to client, not the other way around. - command = FSNETCMD_AIRCMD(packet) - player.aircraft.check_command(command) - - elif packet_type == "FSNETCMD_PREPARESIMULATION": - welcomeMsg = YSchat.message(WELCOME_MESSAGE.format(username=player.username)) - message_to_server.append(welcomeMsg) - player.is_a_bot = False - if DISCORD_ENABLED: - asyncio.create_task(discord_send_message(CHANNEL_ID, f"{player.username} has joined the server!")) - - # Forward the packet to the other endpoint if the data packet still exists. - if data: - writer.write(data) - await writer.drain() - except (asyncio.CancelledError, ConnectionResetError, BrokenPipeError) as e: - if e == BrokenPipeError or ConnectionResetError or asyncio.CancelledError: - info(f"Connection closed by {player.username} : {player.ip}") - else: - warning(f"Connection error during packet forwarding: {e}") - break - - # Start forwarding data between client and server - await asyncio.gather( - forward(client_reader, server_writer, "client_to_server"), - forward(server_reader, client_writer, "server_to_client"), - ) - except (asyncio.CancelledError, ConnectionResetError, BrokenPipeError) as e: - if not isinstance(e, BrokenPipeError): - critical(f"Connection error: {e}") - finally: - try: - client_writer.close() - await client_writer.wait_closed() - except Exception as e: - if not isinstance(e, BrokenPipeError): - critical(f"Error closing client connection: {e}") - - -# Start the proxy server -async def start_proxy(): - server = await asyncio.start_server(handle_client, "0.0.0.0", PROXY_PORT) - info(f"Proxy server listening on port {PROXY_PORT}") - if DISCORD_ENABLED: - await asyncio.create_task(monitor_channel(CHANNEL_ID, CONNECTED_PLAYERS)) - async with server: - await server.serve_forever() - - -if __name__ == "__main__": - try: - asyncio.run(start_proxy()) - except KeyboardInterrupt: - info("Goodbye!") diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 859a08f..0000000 --- a/requirements.txt +++ /dev/null @@ -1,9 +0,0 @@ -aiohappyeyeballs==2.4.6 -aiohttp==3.11.12 -aiosignal==1.3.2 -attrs==25.1.0 -frozenlist==1.5.0 -idna==3.10 -multidict==6.1.0 -propcache==0.2.1 -yarl==1.18.3 diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/packet01_logon_test.py b/tests/packet01_logon_test.py deleted file mode 100644 index 9650585..0000000 --- a/tests/packet01_logon_test.py +++ /dev/null @@ -1,46 +0,0 @@ -import unittest -import sys -import os - -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) -from lib.PacketManager.packets.FSNETCMD_LOGON import FSNETCMD_LOGON - -class TestFSNETCMD_LOGON(unittest.TestCase): - - def test_decode(self): - buffer = b'\x01\x00\x00\x00User1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99x3\x01' - packet = FSNETCMD_LOGON(buffer) - self.assertEqual(packet.username, 'User1') - self.assertEqual(packet.version, 20150425) - self.assertEqual(packet.alias, 'User1') - - def test_decode_with_alias(self): - buffer = b'\x01\x00\x00\x00ExtraLongUserna\x00\x99x3\x01ExtraLongUsernameThatIsTooLongForYS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' - packet = FSNETCMD_LOGON(buffer) - self.assertEqual(packet.username, 'ExtraLongUserna') - self.assertEqual(packet.version, 20150425) - self.assertEqual(packet.alias, 'ExtraLongUsernameThatIsTooLongForYS') - - def test_encode(self): - username = "User1" - version = 20150425 - buffer = FSNETCMD_LOGON.encode(username, version) - expected_buffer = b'\x01\x00\x00\x00User1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99x3\x01' - self.assertEqual(buffer, expected_buffer) - - def test_encode_with_alias(self): - username = "ExtraLongUsernameThatIsTooLongForYS" - version = 20150425 - buffer = FSNETCMD_LOGON.encode(username, version) - expected_buffer = b'\x01\x00\x00\x00ExtraLongUserna\x00\x99x3\x01ExtraLongUsernameThatIsTooLongForYS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' - self.assertEqual(buffer, expected_buffer) - - def test_encode_with_size(self): - username = "User1" - version = 20150425 - buffer = FSNETCMD_LOGON.encode(username, version, with_size=True) - expected_buffer = b'\x18\x00\x00\x00\x01\x00\x00\x00User1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99x3\x01' - self.assertEqual(buffer, expected_buffer) - -if __name__ == '__main__': - unittest.main() \ No newline at end of file diff --git a/tests/packet04_loadfield_test.py b/tests/packet04_loadfield_test.py deleted file mode 100644 index a9004be..0000000 --- a/tests/packet04_loadfield_test.py +++ /dev/null @@ -1,38 +0,0 @@ -import unittest -import sys -import os - -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) -from lib.PacketManager.packets.FSNETCMD_LOADFIELD import FSNETCMD_LOADFIELD -from struct import pack - -class TestFSNETCMD_LOADFIELD(unittest.TestCase): - - def test_decode(self): - buffer = b'\x04\x00\x00\x00ISLAND_GOURD\x00\xc39\x00\xe0\x1ff\x00\r\x00\x00\x00\r\x00\x00\x00\x10\xc49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' - packet = FSNETCMD_LOADFIELD(buffer) - self.assertEqual(packet.fieldShortName, 'ISLAND_GOURD') - self.assertEqual(packet.flags, 0) - self.assertEqual(packet.pos, [0, 0, 0]) - self.assertEqual(packet.atti, [0, 0,0]) - - def test_encode(self): - field = b'ISLAND_GOURD\x00\xc39\x00\xe0\x1ff\x00\r\x00\x00\x00\r\x00\x00\x00\x10\xc49\x00' - flags = 0 - pos = [0, 0, 0] - atti = [0, 0, 0] - buffer = FSNETCMD_LOADFIELD.encode(field, flags, pos, atti) - expected_buffer = b'\x04\x00\x00\x00ISLAND_GOURD\x00\xc39\x00\xe0\x1ff\x00\r\x00\x00\x00\r\x00\x00\x00\x10\xc49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' - self.assertEqual(buffer, expected_buffer) - - def test_encode_with_size(self): - field = b'ISLAND_GOURD\x00\xc39\x00\xe0\x1ff\x00\r\x00\x00\x00\r\x00\x00\x00\x10\xc49\x00' - flags = 0 - pos = [0, 0, 0] - atti = [0, 0, 0] - buffer = FSNETCMD_LOADFIELD.encode(field, flags, pos, atti, with_size=True) - expected_buffer = b'@\x00\x00\x00\x04\x00\x00\x00ISLAND_GOURD\x00\xc39\x00\xe0\x1ff\x00\r\x00\x00\x00\r\x00\x00\x00\x10\xc49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' - self.assertEqual(buffer, expected_buffer) - -if __name__ == '__main__': - unittest.main() \ No newline at end of file diff --git a/tests/packet05_addobject_test.py b/tests/packet05_addobject_test.py deleted file mode 100644 index 6378858..0000000 --- a/tests/packet05_addobject_test.py +++ /dev/null @@ -1,39 +0,0 @@ -import unittest -import sys -import os - -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) -from lib.PacketManager.packets.FSNETCMD_ADDOBJECT import FSNETCMD_ADDOBJECT - -class TestFSNETCMD_ADDOBJECT(unittest.TestCase): - - def test_decode(self): - buffer = b'\x05\x00\x00\x00\x01\x00\x01\x00\x02\x00\x01\x00\x00\x00\x00\x00R\x0c^E\x00\x00\x00\x00H\x85%E\x1d\x96\xcb\xbf\x00\x00\x00\x00\x00\x00\x00\x80HANGER\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\xd7\xa3dB' - - packet = FSNETCMD_ADDOBJECT(buffer) - self.assertEqual(packet.object_type, 1) - self.assertEqual(packet.net_type, 1) - self.assertEqual(packet.object_id, 65538) - self.assertEqual(packet.iff, 0) - self.assertEqual(packet.pos, [3552.77001953125, 0.0, 2648.330078125]) - self.assertEqual(packet.atti, [-1.590518593788147, 0.0, -0.0]) - self.assertEqual(packet.identifier, 'HANGER') - self.assertEqual(packet.substrname, '') - self.assertEqual(packet.ysfid, 0) - self.assertEqual(packet.flags, 0) - self.assertEqual(packet.flags0, 32768) - self.assertEqual(packet.outsideRadius, 57.15999984741211) - - def test_encode(self): - buffer = FSNETCMD_ADDOBJECT.encode( - object_type=1, net_type=1, object_id=65538, iff=0, pos=[3552.77001953125, 0.0, 2648.330078125], - atti=[-1.590518593788147, 0.0, -0.0], identifier='HANGER', substrname='', ysfid=0, - flags=0, flags0=32768, outside_radius=57.15999984741211 - ) - expected_buffer = b'\x05\x00\x00\x00\x01\x00\x01\x00\x02\x00\x01\x00\x00\x00\x00\x00R\x0c^E\x00\x00\x00\x00H\x85%E\x1d\x96\xcb\xbf\x00\x00\x00\x00\x00\x00\x00\x80HANGER\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\xd7\xa3dB' - self.assertEqual(buffer, expected_buffer) - - - -if __name__ == '__main__': - unittest.main() \ No newline at end of file diff --git a/tests/packet08_joinrequest_test.py b/tests/packet08_joinrequest_test.py deleted file mode 100644 index e712989..0000000 --- a/tests/packet08_joinrequest_test.py +++ /dev/null @@ -1,31 +0,0 @@ -import unittest -import sys -import os - -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) -from lib.PacketManager.packets.FSNETCMD_JOINREQUEST import FSNETCMD_JOINREQUEST - -class TestFSNETCMD_JOINREQUEST(unittest.TestCase): - - def test_decode(self): - buffer = b'\x08\x00\x00\x00\x02\x00\x00\x00EUROFIGHTER_TYPHOON\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00RW36_01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00K\x00\x00\x00' - packet = FSNETCMD_JOINREQUEST(buffer) - self.assertEqual(packet.iff,2) - self.assertEqual(packet.aircraft, 'EUROFIGHTER_TYPHOON') - self.assertEqual(packet.start_pos, 'RW36_01') - self.assertEqual(packet.fuel, 75) - self.assertEqual(packet.smoke,0) - - def test_encode(self): - iff = 2 - aircraft = 'EUROFIGHTER_TYPHOON' - start_pos = 'NORTH10000_01' - fuel = 75 - smoke = 0 - buffer = FSNETCMD_JOINREQUEST.encode(iff, aircraft, start_pos, fuel, smoke) - expected_buffer = b'\x08\x00\x00\x00\x02\x00\x00\x00EUROFIGHTER_TYPHOON\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00NORTH10000_01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00K\x00\x00\x00' - self.assertEqual(buffer, expected_buffer) - - -if __name__ == '__main__': - unittest.main() \ No newline at end of file diff --git a/tests/packet09_joinapproval_test.py b/tests/packet09_joinapproval_test.py deleted file mode 100644 index 6334f78..0000000 --- a/tests/packet09_joinapproval_test.py +++ /dev/null @@ -1,26 +0,0 @@ -import unittest -import sys -import os - -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) -from lib.PacketManager.packets.FSNETCMD_JOINAPPROVAL import FSNETCMD_JOINAPPROVAL - -class TestFSNETCMD_JOINAPPROVAL(unittest.TestCase): - - def test_decode(self): - buffer = b'\t\x00\x00\x00' - packet = FSNETCMD_JOINAPPROVAL(buffer) - self.assertEqual(packet.buffer, buffer) - - def test_encode(self): - buffer = FSNETCMD_JOINAPPROVAL.encode() - expected_buffer = b'\t\x00\x00\x00' - self.assertEqual(buffer, expected_buffer) - - def test_encode_with_size(self): - buffer = FSNETCMD_JOINAPPROVAL.encode(with_size=True) - expected_buffer = b'\x04\x00\x00\x00\t\x00\x00\x00' - self.assertEqual(buffer, expected_buffer) - -if __name__ == '__main__': - unittest.main() \ No newline at end of file -- cgit v1.2.3